gschem

x_compselect.c

Go to the documentation of this file.
00001 /* gEDA - GPL Electronic Design Automation
00002  * gschem - gEDA Schematic Capture
00003  * Copyright (C) 1998-2010 Ales Hvezda
00004  * Copyright (C) 1998-2010 gEDA Contributors (see ChangeLog for details)
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00019  */
00020 #include <config.h>
00021 
00022 #include <stdio.h>
00023 #include <stdlib.h>
00024 #include <sys/types.h>
00025 #ifdef HAVE_SYS_PARAM_H
00026 #include <sys/param.h>
00027 #endif
00028 #include <sys/stat.h>
00029 #ifdef HAVE_UNISTD_H
00030 #include <unistd.h>
00031 #endif
00032 #ifdef HAVE_STRING_H
00033 #include <string.h>
00034 #endif
00035 
00036 #include "gschem.h"
00037 #include <gdk/gdkkeysyms.h>
00038 
00039 #ifdef HAVE_LIBDMALLOC
00040 #include <dmalloc.h>
00041 #endif
00042 
00043 #include "../include/gschem_dialog.h"
00044 #include "../include/x_preview.h"
00045 #include "../include/x_compselect.h"
00046 
00057 #define COMPSELECT_FILTER_INTERVAL 200
00058 
00059 
00060 enum compselect_view {
00061   VIEW_INUSE=0,
00062   VIEW_CLIB
00063 };
00064 
00065 
00079 static enum compselect_view
00080 compselect_get_view (Compselect *compselect)
00081 {
00082   switch (gtk_notebook_get_current_page (compselect->viewtabs)) {
00083     case 0: return VIEW_INUSE;  /* In use page */
00084     case 1: return VIEW_CLIB;   /* Component library page */
00085     default:
00086       g_critical ("compselect_get_view: Unknown tab position\n");
00087       return 0;
00088   }
00089 }
00090 
00091 
00104 static void
00105 x_compselect_callback_response (GtkDialog *dialog,
00106                                 gint arg1,
00107                                 gpointer user_data)
00108 {
00109   Compselect *compselect = (Compselect*)dialog;
00110   GSCHEM_TOPLEVEL *w_current = (GSCHEM_TOPLEVEL *)user_data;
00111   TOPLEVEL *toplevel = w_current->toplevel;
00112 
00113   switch (arg1) {
00114       case COMPSELECT_RESPONSE_PLACE: {
00115         CLibSymbol *symbol = NULL;
00116         CompselectBehavior behavior;
00117 
00118         g_object_get (compselect,
00119                       "symbol", &symbol,
00120                       "behavior", &behavior,
00121                       NULL);
00122 
00123         w_current->include_complex = w_current->embed_complex = 0;
00124         switch (behavior) {
00125             case COMPSELECT_BEHAVIOR_REFERENCE:
00126               break;
00127             case COMPSELECT_BEHAVIOR_EMBED:
00128               w_current->embed_complex   = 1;
00129               break;
00130             case COMPSELECT_BEHAVIOR_INCLUDE:
00131               w_current->include_complex = 1;
00132               break;
00133             default:
00134               g_assert_not_reached ();
00135         }
00136 
00137         if (w_current->event_state == ENDCOMP) {
00138           /* Delete the component which was being placed */
00139           if (w_current->rubber_visible)
00140             o_place_invalidate_rubber (w_current, FALSE);
00141           w_current->rubber_visible = 0;
00142           s_delete_object_glist (toplevel,
00143                                  toplevel->page_current->place_list);
00144           toplevel->page_current->place_list = NULL;
00145         } else {
00146           /* Cancel whatever other action is currently in progress */
00147           o_redraw_cleanstates (w_current);
00148         }
00149 
00150         if (symbol == NULL) {
00151           /* If there is no symbol selected, switch to SELECT mode */
00152           w_current->event_state = SELECT;
00153         } else {
00154           /* Otherwise set the new symbol to place */
00155           o_complex_prepare_place (w_current, symbol);
00156         }
00157         break;
00158       }
00159 
00160       case COMPSELECT_RESPONSE_HIDE:
00161         /* Response when clicking on the "hide" button */
00162 
00163         /* If there is no component in the complex place list, set the current one */
00164         if (toplevel->page_current->place_list == NULL) {
00165           gtk_dialog_response (GTK_DIALOG (compselect),
00166                                COMPSELECT_RESPONSE_PLACE);
00167         }
00168 
00169         /* Hide the component selector */
00170         g_object_set (G_OBJECT (compselect), "hidden", TRUE, NULL);
00171         break;
00172 
00173       case GTK_RESPONSE_CLOSE:
00174       case GTK_RESPONSE_DELETE_EVENT:
00175         g_assert (GTK_WIDGET (dialog) == w_current->cswindow);
00176         gtk_widget_destroy (GTK_WIDGET (dialog));
00177         w_current->cswindow = NULL;
00178 
00179         if (w_current->event_state == ENDCOMP) {
00180 
00181           /* Cancel the place operation currently in progress */
00182           o_redraw_cleanstates (w_current);
00183 
00184           /* return to the default state */
00185           i_set_state (w_current, SELECT);
00186           i_update_toolbar (w_current);
00187         }
00188         break;
00189 
00190       default:
00191         /* Do nothing, in case there's another handler function which
00192            can handle the response ID received. */
00193         break;
00194   }
00195 
00196 }
00197 
00206 void
00207 x_compselect_open (GSCHEM_TOPLEVEL *w_current)
00208 {
00209   GtkWidget *current_tab, *entry_filter;
00210   GtkNotebook *compselect_notebook;
00211 
00212   if (w_current->cswindow == NULL) {
00213     w_current->cswindow = GTK_WIDGET (
00214       g_object_new (TYPE_COMPSELECT,
00215                     /* GschemDialog */
00216                     "settings-name", "compselect",
00217                     "gschem-toplevel", w_current,
00218                     NULL));
00219 
00220     g_signal_connect (w_current->cswindow,
00221                       "response",
00222                       G_CALLBACK (x_compselect_callback_response),
00223                       w_current);
00224 
00225     gtk_window_set_transient_for (GTK_WINDOW (w_current->cswindow),
00226                                   GTK_WINDOW (w_current->main_window));
00227 
00228     gtk_widget_show (w_current->cswindow);
00229 
00230   } else {
00231     gtk_window_present (GTK_WINDOW (w_current->cswindow));
00232   }
00233   gtk_editable_select_region (GTK_EDITABLE (COMPSELECT (w_current->cswindow)->entry_filter), 0, -1);
00234 
00235   /* Set the focus to the filter entry only if it is in the current
00236      displayed tab */
00237   compselect_notebook = GTK_NOTEBOOK (COMPSELECT (w_current->cswindow)->viewtabs);
00238   current_tab = gtk_notebook_get_nth_page (compselect_notebook,
00239                                            gtk_notebook_get_current_page (compselect_notebook));
00240   entry_filter = GTK_WIDGET (COMPSELECT (w_current->cswindow)->entry_filter);
00241   if (gtk_widget_is_ancestor (entry_filter, current_tab)) {
00242     gtk_widget_grab_focus (entry_filter);
00243   }
00244 }
00245 
00253 void
00254 x_compselect_close (GSCHEM_TOPLEVEL *w_current)
00255 {
00256   if (w_current->cswindow) {
00257     g_assert (IS_COMPSELECT (w_current->cswindow));
00258     gtk_widget_destroy (w_current->cswindow);
00259     w_current->cswindow = NULL;
00260   }
00261 }
00262 
00263 
00264 void
00265 x_compselect_deselect (GSCHEM_TOPLEVEL *w_current)
00266 {
00267   Compselect *compselect = COMPSELECT (w_current->cswindow);
00268 
00269   if (compselect == NULL)
00270     return;
00271 
00272   switch (compselect_get_view (compselect)) {
00273   case VIEW_INUSE:
00274     gtk_tree_selection_unselect_all (
00275       gtk_tree_view_get_selection (compselect->inusetreeview));
00276     break;
00277   case VIEW_CLIB:
00278     gtk_tree_selection_unselect_all (
00279       gtk_tree_view_get_selection (compselect->libtreeview));
00280     break;
00281   default:
00282     g_assert_not_reached ();
00283   }
00284 }
00285 
00286 
00287 enum {
00288   PROP_SYMBOL=1,
00289   PROP_BEHAVIOR,
00290   PROP_HIDDEN
00291 };
00292 
00293 static GObjectClass *compselect_parent_class = NULL;
00294 
00295 
00296 static void compselect_class_init      (CompselectClass *class);
00297 static GObject *compselect_constructor (GType type,
00298                                         guint n_construct_properties,
00299                                         GObjectConstructParam *construct_params);
00300 static void compselect_finalize        (GObject *object);
00301 static void compselect_set_property    (GObject *object,
00302                                         guint property_id,
00303                                         const GValue *value,
00304                                         GParamSpec *pspec);
00305 static void compselect_get_property    (GObject *object,
00306                                         guint property_id,
00307                                         GValue *value,
00308                                         GParamSpec *pspec);
00309 
00310 
00311 
00320 static void
00321 inuse_treeview_set_cell_data (GtkTreeViewColumn *tree_column,
00322                             GtkCellRenderer   *cell,
00323                             GtkTreeModel      *tree_model,
00324                             GtkTreeIter       *iter,
00325                             gpointer           data)
00326 {
00327   CLibSymbol *symbol;
00328 
00329   gtk_tree_model_get (tree_model, iter, 0, &symbol, -1);
00330   g_object_set ((GObject*)cell, "text", s_clib_symbol_get_name (symbol), NULL);
00331 }
00332 
00342 static void
00343 lib_treeview_set_cell_data (GtkTreeViewColumn *tree_column,
00344                             GtkCellRenderer   *cell,
00345                             GtkTreeModel      *tree_model,
00346                             GtkTreeIter       *iter,
00347                             gpointer           data)
00348 {
00349   GtkTreeIter parent;
00350   CLibSource *source;
00351   CLibSymbol *symbol;
00352   const char *text;
00353 
00354   if (!gtk_tree_model_iter_parent (tree_model, &parent, iter)) {
00355     /* If top level, must be a source. */
00356     gtk_tree_model_get (tree_model, iter, 0, &source, -1);
00357     text = s_clib_source_get_name (source);
00358   } else {
00359     /* Otherwise, must be a symbol */
00360     gtk_tree_model_get (tree_model, iter, 0, &symbol, -1);
00361     text = s_clib_symbol_get_name (symbol);
00362   }
00363   g_object_set ((GObject*)cell, "text", text, NULL);
00364 }
00365 
00376 static gboolean
00377 lib_model_filter_visible_func (GtkTreeModel *model,
00378                                       GtkTreeIter  *iter,
00379                                       gpointer      data)
00380 {
00381   Compselect *compselect = (Compselect*)data;
00382   CLibSymbol *sym;
00383   const gchar *compname;
00384   gchar *compname_upper, *text_upper, *pattern;
00385   const gchar *text;
00386   gboolean ret;
00387 
00388   g_assert (IS_COMPSELECT (data));
00389 
00390   text = gtk_entry_get_text (compselect->entry_filter);
00391   if (g_ascii_strcasecmp (text, "") == 0) {
00392     return TRUE;
00393   }
00394 
00395   /* If this is a source, only display it if it has children that
00396    * match */
00397   if (gtk_tree_model_iter_has_child (model, iter)) {
00398     GtkTreeIter iter2;
00399 
00400     gtk_tree_model_iter_children (model, &iter2, iter);
00401     ret = FALSE;
00402     do {
00403       if (lib_model_filter_visible_func (model, &iter2, data)) {
00404         ret = TRUE;
00405         break;
00406       }
00407     } while (gtk_tree_model_iter_next (model, &iter2));
00408   } else {
00409     gtk_tree_model_get (model, iter,
00410                         0, &sym,
00411                         -1);
00412     compname = s_clib_symbol_get_name (sym);
00413     /* Do a case insensitive comparison, converting the strings
00414        to uppercase */
00415     compname_upper = g_ascii_strup (compname, -1);
00416     text_upper = g_ascii_strup (text, -1);
00417     pattern = g_strconcat ("*", text_upper, "*", NULL);
00418     ret = g_pattern_match_simple (pattern, compname_upper);
00419     g_free (compname_upper);
00420     g_free (text_upper);
00421     g_free (pattern);
00422   }
00423 
00424   return ret;
00425 }
00426 
00427 
00438 static void
00439 tree_row_activated (GtkTreeView       *tree_view,
00440                     GtkTreePath       *path,
00441                     GtkTreeViewColumn *column,
00442                     gpointer           user_data)
00443 {
00444   GtkTreeModel *model;
00445   GtkTreeIter iter;
00446   Compselect *compselect = (Compselect*)user_data;
00447 
00448   model = gtk_tree_view_get_model (tree_view);
00449   gtk_tree_model_get_iter (model, &iter, path);
00450 
00451   if (!gtk_tree_model_iter_has_child (model, &iter)) {
00452     gtk_dialog_response (GTK_DIALOG (compselect),
00453                          COMPSELECT_RESPONSE_HIDE);
00454     return;
00455   }
00456 
00457   if (gtk_tree_view_row_expanded (tree_view, path))
00458     gtk_tree_view_collapse_row (tree_view, path);
00459   else
00460     gtk_tree_view_expand_row (tree_view, path, FALSE);
00461 }
00462 
00465 static gint
00466 sort_object_text (OBJECT *a, OBJECT *b)
00467 {
00468   return strcmp (a->text->string, b->text->string);
00469 }
00470 
00471 enum {
00472   ATTRIBUTE_COLUMN_NAME = 0,
00473   ATTRIBUTE_COLUMN_VALUE,
00474   NUM_ATTRIBUTE_COLUMNS
00475 };
00476 
00484 void
00485 update_attributes_model (Compselect *compselect, TOPLEVEL *preview_toplevel)
00486 {
00487   GtkListStore *model;
00488   GtkTreeIter iter;
00489   GtkTreeViewColumn *column;
00490   GList *listiter, *o_iter, *o_attrlist, *filter_list;
00491   gchar *name, *value;
00492   OBJECT *o_current;
00493 
00494   model = (GtkListStore*) gtk_tree_view_get_model (compselect->attrtreeview);
00495   gtk_list_store_clear (model);
00496 
00497   /* Invalidate the column width for the attribute value column, so
00498    * the column is re-sized based on the new data being shown. Symbols
00499    * with long values are common, and we don't want having viewed those
00500    * forcing a h-scroll-bar on symbols with short valued attributes.
00501    *
00502    * We might also consider invalidating the attribute name columns,
00503    * however that gives an inconsistent column division when swithing
00504    * between symbols, which doesn't look nice. For now, assume that
00505    * the name column can keep the max width gained whilst previewing.
00506    */
00507   column = gtk_tree_view_get_column (compselect->attrtreeview,
00508                                      ATTRIBUTE_COLUMN_VALUE);
00509   gtk_tree_view_column_queue_resize (column);
00510 
00511   if (preview_toplevel->page_current == NULL) {
00512     return;
00513   }
00514 
00515   o_attrlist = o_attrib_find_floating_attribs (
00516                               s_page_objects (preview_toplevel->page_current));
00517 
00518   filter_list = GSCHEM_DIALOG (compselect)->w_current->component_select_attrlist;
00519 
00520   if (filter_list != NULL
00521       && strcmp (filter_list->data, "*") == 0) {
00522     /* display all attributes in alphabetical order */
00523     o_attrlist = g_list_sort (o_attrlist, (GCompareFunc) sort_object_text);
00524     for (o_iter = o_attrlist; o_iter != NULL; o_iter = g_list_next (o_iter)) {
00525       o_current = o_iter->data;
00526       o_attrib_get_name_value (o_current, &name, &value);
00527       gtk_list_store_append (model, &iter);
00528       gtk_list_store_set (model, &iter, 0, name, 1, value, -1);
00529       g_free (name);
00530       g_free (value);
00531     }
00532   } else {
00533     /* display only attribute that are in the filter list */
00534     for (listiter = filter_list;
00535          listiter != NULL;
00536          listiter = g_list_next (listiter)) {
00537       for (o_iter = o_attrlist; o_iter != NULL; o_iter = g_list_next (o_iter)) {
00538         o_current = o_iter->data;
00539         if (o_attrib_get_name_value (o_current, &name, &value)) {
00540           if (strcmp (name, listiter->data) == 0) {
00541             gtk_list_store_append (model, &iter);
00542             gtk_list_store_set (model, &iter, 0, name, 1, value, -1);
00543           }
00544           g_free (name);
00545           g_free (value);
00546         }
00547       }
00548     }
00549   }
00550   g_list_free (o_attrlist);
00551 }
00552 
00568 static void
00569 compselect_callback_tree_selection_changed (GtkTreeSelection *selection,
00570                                             gpointer          user_data)
00571 {
00572   GtkTreeView *view;
00573   GtkTreeModel *model;
00574   GtkTreeIter iter, parent;
00575   Compselect *compselect = (Compselect*)user_data;
00576   const CLibSymbol *sym = NULL;
00577   gchar *buffer = NULL;
00578 
00579   if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
00580 
00581     view = gtk_tree_selection_get_tree_view (selection);
00582     if (view == compselect->inusetreeview ||
00583         /* No special handling required */
00584         (view == compselect->libtreeview &&
00585          gtk_tree_model_iter_parent (model, &parent, &iter))) {
00586          /* Tree view needs to check that we're at a leaf node */
00587 
00588       gtk_tree_model_get (model, &iter, 0, &sym, -1);
00589       buffer = s_clib_symbol_get_data (sym);
00590     }
00591   }
00592 
00593   /* update the preview with new symbol data */
00594   g_object_set (compselect->preview,
00595                 "buffer", buffer,
00596                 "active", (buffer != NULL),
00597                 NULL);
00598 
00599   /* update the attributes with the toplevel of the preview widget*/
00600   if (compselect->attrtreeview != NULL)
00601     update_attributes_model (compselect,
00602                              compselect->preview->preview_w_current->toplevel);
00603 
00604   /* signal a component has been selected to parent of dialog */
00605   g_signal_emit_by_name (compselect,
00606                          "response",
00607                          COMPSELECT_RESPONSE_PLACE,
00608                          NULL);
00609 
00610   g_free (buffer);
00611 }
00612 
00624 static gboolean
00625 compselect_filter_timeout (gpointer data)
00626 {
00627   Compselect *compselect = COMPSELECT (data);
00628   GtkTreeModel *model;
00629 
00630   /* resets the source id in compselect */
00631   compselect->filter_timeout = 0;
00632 
00633   model = gtk_tree_view_get_model (compselect->libtreeview);
00634 
00635   if (model != NULL) {
00636     const gchar *text = gtk_entry_get_text (compselect->entry_filter);
00637     gtk_tree_model_filter_refilter ((GtkTreeModelFilter*)model);
00638     if (strcmp (text, "") != 0) {
00639       /* filter text not-empty */
00640       gtk_tree_view_expand_all (compselect->libtreeview);
00641     } else {
00642       /* filter text is empty, collapse expanded tree */
00643       gtk_tree_view_collapse_all (compselect->libtreeview);
00644     }
00645   }
00646 
00647   /* return FALSE to remove the source */
00648   return FALSE;
00649 }
00650 
00662 static void
00663 compselect_callback_filter_entry_changed (GtkEditable *editable,
00664                                           gpointer  user_data)
00665 {
00666   Compselect *compselect = COMPSELECT (user_data);
00667   GtkWidget *button;
00668   gboolean sensitive;
00669 
00670   /* turns button off if filter entry is empty */
00671   /* turns it on otherwise */
00672   button    = GTK_WIDGET (compselect->button_clear);
00673   sensitive =
00674     (g_ascii_strcasecmp (gtk_entry_get_text (compselect->entry_filter),
00675                          "") != 0);
00676   if (GTK_WIDGET_IS_SENSITIVE (button) != sensitive) {
00677     gtk_widget_set_sensitive (button, sensitive);
00678   }
00679 
00680   /* Cancel any pending update of the component list filter */
00681   if (compselect->filter_timeout != 0)
00682     g_source_remove (compselect->filter_timeout);
00683 
00684   /* Schedule an update of the component list filter in
00685    * COMPSELECT_FILTER_INTERVAL milliseconds */
00686   compselect->filter_timeout = g_timeout_add (COMPSELECT_FILTER_INTERVAL,
00687                                               compselect_filter_timeout,
00688                                               compselect);
00689 
00690 }
00691 
00703 static void
00704 compselect_callback_filter_button_clicked (GtkButton *button,
00705                                            gpointer   user_data)
00706 {
00707   Compselect *compselect = COMPSELECT (user_data);
00708 
00709   /* clears text in text entry for filter */
00710   gtk_entry_set_text (compselect->entry_filter, "");
00711 
00712 }
00713 
00726 static void
00727 compselect_callback_behavior_changed (GtkOptionMenu *optionmenu,
00728                                       gpointer user_data)
00729 {
00730   Compselect *compselect = (Compselect*)user_data;
00731 
00732   g_signal_emit_by_name (compselect,
00733                          "response",
00734                          COMPSELECT_RESPONSE_PLACE,
00735                          NULL);
00736 }
00737 
00738 /* \brief Create the tree model for the "In Use" view.
00739  * \par Function Description
00740  * Creates a straightforward list of symbols which are currently in
00741  * use, using s_toplevel_get_symbols().
00742  */
00743 static GtkTreeModel*
00744 create_inuse_tree_model (Compselect *compselect)
00745 {
00746   GtkListStore *store;
00747   GList *symhead, *symlist;
00748   GtkTreeIter iter;
00749 
00750   store = (GtkListStore *) gtk_list_store_new (1, G_TYPE_POINTER);
00751 
00752   symhead = s_toplevel_get_symbols (GSCHEM_DIALOG (compselect)->w_current->toplevel);
00753 
00754   for (symlist = symhead;
00755        symlist != NULL;
00756        symlist = g_list_next (symlist)) {
00757 
00758     gtk_list_store_append (store, &iter);
00759 
00760     gtk_list_store_set (store, &iter,
00761                         0, symlist->data,
00762                         -1);
00763   }
00764 
00765   g_list_free (symhead);
00766 
00767   return (GtkTreeModel*)store;
00768 }
00769 
00770 /* \brief Create the tree model for the "Library" view.
00771  * \par Function Description
00772  * Creates a tree where the branches are the available component
00773  * sources and the leaves are the symbols.
00774  */
00775 static GtkTreeModel*
00776 create_lib_tree_model (Compselect *compselect)
00777 {
00778   GtkTreeStore *store;
00779   GList *srchead, *srclist;
00780   GList *symhead, *symlist;
00781 
00782   store = (GtkTreeStore*)gtk_tree_store_new (1, G_TYPE_POINTER);
00783 
00784   /* populate component store */
00785   srchead = s_clib_get_sources (GSCHEM_DIALOG (compselect)->w_current->sort_component_library != 0);
00786   for (srclist = srchead;
00787        srclist != NULL;
00788        srclist = g_list_next (srclist)) {
00789 
00790     GtkTreeIter iter, iter2;
00791 
00792     gtk_tree_store_append (store, &iter, NULL);
00793     gtk_tree_store_set (store, &iter,
00794                         0, srclist->data,
00795                         -1);
00796 
00797     symhead = s_clib_source_get_symbols ((CLibSource *)srclist->data);
00798     for (symlist = symhead;
00799          symlist != NULL;
00800          symlist = g_list_next (symlist)) {
00801 
00802       gtk_tree_store_append (store, &iter2, &iter);
00803       gtk_tree_store_set (store, &iter2,
00804                           0, symlist->data,
00805                           -1);
00806     }
00807 
00808     g_list_free (symhead);
00809   }
00810   g_list_free (srchead);
00811 
00812   return (GtkTreeModel*)store;
00813 }
00814 
00815 /* \brief On-demand refresh of the component library.
00816  * \par Function Description
00817  * Requests a rescan of the component library in order to pick up any
00818  * new signals, and then updates the component selector.
00819  */
00820 static void
00821 compselect_callback_refresh_library (GtkButton *button, gpointer user_data)
00822 {
00823   Compselect *compselect = COMPSELECT (user_data);
00824   GtkTreeModel *model;
00825   GtkTreeSelection *selection;
00826 
00827   /* Rescan the libraries for symbols */
00828   s_clib_refresh ();
00829 
00830   /* Refresh the "Library" view */
00831   g_object_unref (gtk_tree_view_get_model (compselect->libtreeview));
00832   model = (GtkTreeModel *)
00833     g_object_new (GTK_TYPE_TREE_MODEL_FILTER,
00834                   "child-model", create_lib_tree_model (compselect),
00835                   "virtual-root", NULL,
00836                   NULL);
00837 
00838   gtk_tree_model_filter_set_visible_func ((GtkTreeModelFilter*)model,
00839                                           lib_model_filter_visible_func,
00840                                           compselect,
00841                                           NULL);
00842 
00843   /* Block handling selection updated for duration of model changes */
00844   selection = gtk_tree_view_get_selection (compselect->libtreeview);
00845   g_signal_handlers_block_by_func (selection,
00846                                    compselect_callback_tree_selection_changed,
00847                                    compselect);
00848 
00849   /* Update the view model with signals blocked */
00850   gtk_tree_view_set_model (compselect->libtreeview, model);
00851 
00852   /* Refresh the "In Use" view */
00853   g_object_unref (gtk_tree_view_get_model (compselect->inusetreeview));
00854   model = create_inuse_tree_model (compselect);
00855 
00856   /* Here we can update the model without blocking signals
00857    * as this is the second (final) tree view we are updating */
00858   gtk_tree_view_set_model (compselect->inusetreeview, model);
00859 
00860   /* Unblock & fire handler for libtreeview selection */
00861   g_signal_handlers_unblock_by_func (selection,
00862                                      compselect_callback_tree_selection_changed,
00863                                      compselect);
00864 }
00865 
00867 static GtkWidget*
00868 create_inuse_treeview (Compselect *compselect)
00869 {
00870   GtkWidget *scrolled_win, *treeview, *vbox, *hbox, *button;
00871   GtkTreeModel *model;
00872   GtkTreeSelection *selection;
00873   GtkCellRenderer *renderer;
00874   GtkTreeViewColumn *column;
00875 
00876   model = create_inuse_tree_model (compselect);
00877 
00878   vbox = GTK_WIDGET (g_object_new (GTK_TYPE_VBOX,
00879                                    /* GtkContainer */
00880                                    "border-width", 5,
00881                                    /* GtkBox */
00882                                    "homogeneous",  FALSE,
00883                                    "spacing",      5,
00884                                    NULL));
00885 
00886   /* Create a scrolled window to accomodate the treeview */
00887   scrolled_win = GTK_WIDGET (
00888     g_object_new (GTK_TYPE_SCROLLED_WINDOW,
00889                   /* GtkContainer */
00890                   "border-width", 5,
00891                   /* GtkScrolledWindow */
00892                   "hscrollbar-policy", GTK_POLICY_AUTOMATIC,
00893                   "vscrollbar-policy", GTK_POLICY_ALWAYS,
00894                   "shadow-type",       GTK_SHADOW_ETCHED_IN,
00895                   NULL));
00896 
00897   /* Create the treeview */
00898   treeview = GTK_WIDGET (g_object_new (GTK_TYPE_TREE_VIEW,
00899                                        /* GtkTreeView */
00900                                        "model",      model,
00901                                        "rules-hint", TRUE,
00902                                        "headers-visible", FALSE,
00903                                        NULL));
00904 
00905   /* Connect callback to selection */
00906   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
00907   gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
00908   g_signal_connect (selection,
00909                     "changed",
00910                     G_CALLBACK (compselect_callback_tree_selection_changed),
00911                     compselect);
00912 
00913   /* Insert a column for symbol name */
00914   renderer = GTK_CELL_RENDERER (
00915     g_object_new (GTK_TYPE_CELL_RENDERER_TEXT,
00916                   /* GtkCellRendererText */
00917                   "editable", FALSE,
00918                   NULL));
00919   column = GTK_TREE_VIEW_COLUMN (
00920     g_object_new (GTK_TYPE_TREE_VIEW_COLUMN,
00921                   /* GtkTreeViewColumn */
00922                   "title", _("Components"),
00923                   NULL));
00924   gtk_tree_view_column_pack_start (column, renderer, TRUE);
00925   gtk_tree_view_column_set_cell_data_func (column, renderer,
00926                                            inuse_treeview_set_cell_data,
00927                                            NULL, NULL);
00928   gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
00929 
00930   /* Add the treeview to the scrolled window */
00931   gtk_container_add (GTK_CONTAINER (scrolled_win), treeview);
00932   /* set the inuse treeview of compselect */
00933   compselect->inusetreeview = GTK_TREE_VIEW (treeview);
00934 
00935   /* add the scrolled window for directories to the vertical box */
00936   gtk_box_pack_start (GTK_BOX (vbox), scrolled_win,
00937                       TRUE, TRUE, 0);
00938 
00939   /* -- refresh button area -- */
00940   hbox = GTK_WIDGET (g_object_new (GTK_TYPE_HBOX,
00941                                           /* GtkBox */
00942                                           "homogeneous", FALSE,
00943                                           "spacing",     3,
00944                                           NULL));
00945   /* create the refresh button */
00946   button = GTK_WIDGET (g_object_new (GTK_TYPE_BUTTON,
00947                                      /* GtkWidget */
00948                                      "sensitive", TRUE,
00949                                      /* GtkButton */
00950                                      "relief",    GTK_RELIEF_NONE,
00951                                      NULL));
00952   gtk_container_add (GTK_CONTAINER (button),
00953                      gtk_image_new_from_stock (GTK_STOCK_REFRESH,
00954                                             GTK_ICON_SIZE_SMALL_TOOLBAR));
00955   /* add the refresh button to the horizontal box at the end */
00956   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
00957   g_signal_connect (button,
00958                     "clicked",
00959                     G_CALLBACK (compselect_callback_refresh_library),
00960                     compselect);
00961 
00962   /* add the refresh button area to the vertical box */
00963   gtk_box_pack_start (GTK_BOX (vbox), hbox,
00964                       FALSE, FALSE, 0);
00965 
00966   return vbox;
00967 }
00968 
00970 static GtkWidget *
00971 create_lib_treeview (Compselect *compselect)
00972 {
00973   GtkWidget *libtreeview, *vbox, *scrolled_win, *label,
00974     *hbox, *entry, *button;
00975   GtkTreeModel *child_model, *model;
00976   GtkTreeSelection *selection;
00977   GtkCellRenderer *renderer;
00978   GtkTreeViewColumn *column;
00979 
00980   /* -- library selection view -- */
00981 
00982   /* vertical box for component selection and search entry */
00983   vbox = GTK_WIDGET (g_object_new (GTK_TYPE_VBOX,
00984                                    /* GtkContainer */
00985                                    "border-width", 5,
00986                                    /* GtkBox */
00987                                    "homogeneous",  FALSE,
00988                                    "spacing",      5,
00989                                    NULL));
00990 
00991   child_model  = create_lib_tree_model (compselect);
00992   model = (GtkTreeModel*)g_object_new (GTK_TYPE_TREE_MODEL_FILTER,
00993                                        "child-model",  child_model,
00994                                        "virtual-root", NULL,
00995                                        NULL);
00996 
00997   scrolled_win = GTK_WIDGET (
00998     g_object_new (GTK_TYPE_SCROLLED_WINDOW,
00999                   /* GtkContainer */
01000                   "border-width", 5,
01001                   /* GtkScrolledWindow */
01002                   "hscrollbar-policy", GTK_POLICY_AUTOMATIC,
01003                   "vscrollbar-policy", GTK_POLICY_ALWAYS,
01004                   "shadow-type",       GTK_SHADOW_ETCHED_IN,
01005                   NULL));
01006   /* create the treeview */
01007   libtreeview = GTK_WIDGET (g_object_new (GTK_TYPE_TREE_VIEW,
01008                                           /* GtkTreeView */
01009                                           "model",      model,
01010                                           "rules-hint", TRUE,
01011                                           "headers-visible", FALSE,
01012                                           NULL));
01013 
01014   g_signal_connect (libtreeview,
01015                     "row-activated",
01016                     G_CALLBACK (tree_row_activated),
01017                     compselect);
01018 
01019   /* connect callback to selection */
01020   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (libtreeview));
01021   gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
01022   g_signal_connect (selection,
01023                     "changed",
01024                     G_CALLBACK (compselect_callback_tree_selection_changed),
01025                     compselect);
01026 
01027   /* insert a column to treeview for library/symbol name */
01028   renderer = GTK_CELL_RENDERER (
01029     g_object_new (GTK_TYPE_CELL_RENDERER_TEXT,
01030                   /* GtkCellRendererText */
01031                   "editable", FALSE,
01032                   NULL));
01033   column = GTK_TREE_VIEW_COLUMN (
01034     g_object_new (GTK_TYPE_TREE_VIEW_COLUMN,
01035                   /* GtkTreeViewColumn */
01036                   "title", _("Components"),
01037                   NULL));
01038   gtk_tree_view_column_pack_start (column, renderer, TRUE);
01039   gtk_tree_view_column_set_cell_data_func (column, renderer,
01040                                            lib_treeview_set_cell_data,
01041                                            NULL, NULL);
01042   gtk_tree_view_append_column (GTK_TREE_VIEW (libtreeview), column);
01043 
01044   /* add the treeview to the scrolled window */
01045   gtk_container_add (GTK_CONTAINER (scrolled_win), libtreeview);
01046   /* set directory/component treeview of compselect */
01047   compselect->libtreeview = GTK_TREE_VIEW (libtreeview);
01048 
01049   /* add the scrolled window for directories to the vertical box */
01050   gtk_box_pack_start (GTK_BOX (vbox), scrolled_win,
01051                       TRUE, TRUE, 0);
01052 
01053 
01054   /* -- filter area -- */
01055   hbox = GTK_WIDGET (g_object_new (GTK_TYPE_HBOX,
01056                                           /* GtkBox */
01057                                           "homogeneous", FALSE,
01058                                           "spacing",     3,
01059                                           NULL));
01060 
01061   /* create the entry label */
01062   label = GTK_WIDGET (g_object_new (GTK_TYPE_LABEL,
01063                                     /* GtkMisc */
01064                                     "xalign", 0.0,
01065                                     /* GtkLabel */
01066                                     "label",  _("Filter:"),
01067                                     NULL));
01068   /* add the search label to the filter area */
01069   gtk_box_pack_start (GTK_BOX (hbox), label,
01070                       FALSE, FALSE, 0);
01071 
01072   /* create the text entry for filter in components */
01073   entry = GTK_WIDGET (g_object_new (GTK_TYPE_ENTRY,
01074                                     /* GtkEntry */
01075                                     "text", "",
01076                                     NULL));
01077   g_signal_connect (entry,
01078                     "changed",
01079                     G_CALLBACK (compselect_callback_filter_entry_changed),
01080                     compselect);
01081 
01082   /* now that that we have an entry, set the filter func of model */
01083   gtk_tree_model_filter_set_visible_func ((GtkTreeModelFilter*)model,
01084                                           lib_model_filter_visible_func,
01085                                           compselect,
01086                                           NULL);
01087 
01088   /* add the filter entry to the filter area */
01089   gtk_box_pack_start (GTK_BOX (hbox), entry,
01090                       TRUE, TRUE, 0);
01091   /* set filter entry of compselect */
01092   compselect->entry_filter = GTK_ENTRY (entry);
01093   /* and init the event source for component filter */
01094   compselect->filter_timeout = 0;
01095 
01096   /* create the erase button for filter entry */
01097   button = GTK_WIDGET (g_object_new (GTK_TYPE_BUTTON,
01098                                      /* GtkWidget */
01099                                      "sensitive", FALSE,
01100                                      /* GtkButton */
01101                                      "relief",    GTK_RELIEF_NONE,
01102                                      NULL));
01103 
01104   gtk_container_add (GTK_CONTAINER (button),
01105                      gtk_image_new_from_stock (GTK_STOCK_CLEAR,
01106                                                GTK_ICON_SIZE_SMALL_TOOLBAR));
01107   g_signal_connect (button,
01108                     "clicked",
01109                     G_CALLBACK (compselect_callback_filter_button_clicked),
01110                     compselect);
01111   /* add the clear button to the filter area */
01112   gtk_box_pack_start (GTK_BOX (hbox), button,
01113                       FALSE, FALSE, 0);
01114   /* set clear button of compselect */
01115   compselect->button_clear = GTK_BUTTON (button);
01116 
01117   /* create the refresh button */
01118   button = GTK_WIDGET (g_object_new (GTK_TYPE_BUTTON,
01119                                      /* GtkWidget */
01120                                      "sensitive", TRUE,
01121                                      /* GtkButton */
01122                                      "relief",    GTK_RELIEF_NONE,
01123                                      NULL));
01124   gtk_container_add (GTK_CONTAINER (button),
01125                      gtk_image_new_from_stock (GTK_STOCK_REFRESH,
01126                                             GTK_ICON_SIZE_SMALL_TOOLBAR));
01127   /* add the refresh button to the filter area */
01128   gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
01129   g_signal_connect (button,
01130                     "clicked",
01131                     G_CALLBACK (compselect_callback_refresh_library),
01132                     compselect);
01133 
01134   /* add the filter area to the vertical box */
01135   gtk_box_pack_start (GTK_BOX (vbox), hbox,
01136                       FALSE, FALSE, 0);
01137 
01138   compselect->libtreeview = GTK_TREE_VIEW (libtreeview);
01139 
01140   return vbox;
01141 }
01142 
01145 static GtkWidget*
01146 create_attributes_treeview (Compselect *compselect)
01147 {
01148   GtkWidget *attrtreeview, *scrolled_win;
01149   GtkListStore *model;
01150   GtkCellRenderer *renderer;
01151   GtkTreeViewColumn *column;
01152 
01153   model = gtk_list_store_new (NUM_ATTRIBUTE_COLUMNS,
01154                               G_TYPE_STRING, G_TYPE_STRING);
01155 
01156   attrtreeview = GTK_WIDGET (g_object_new (GTK_TYPE_TREE_VIEW,
01157                                            /* GtkTreeView */
01158                                            "model",      model,
01159                                            "headers-visible", FALSE,
01160                                            "rules-hint", TRUE,
01161                                            NULL));
01162 
01163   /* two columns for name and value of the attributes */
01164   renderer = GTK_CELL_RENDERER (g_object_new (GTK_TYPE_CELL_RENDERER_TEXT,
01165                                               "editable", FALSE,
01166                                               NULL));
01167 
01168   column = GTK_TREE_VIEW_COLUMN (g_object_new (GTK_TYPE_TREE_VIEW_COLUMN,
01169                                                "title", _("Name"),
01170                                                "resizable", TRUE,
01171                                                NULL));
01172   gtk_tree_view_column_pack_start (column, renderer, TRUE);
01173   gtk_tree_view_column_add_attribute (column, renderer, "text",
01174                                       ATTRIBUTE_COLUMN_NAME);
01175   gtk_tree_view_append_column (GTK_TREE_VIEW (attrtreeview), column);
01176 
01177   column = GTK_TREE_VIEW_COLUMN (g_object_new (GTK_TYPE_TREE_VIEW_COLUMN,
01178                                                "title", _("Value"),
01179                                                "resizable", TRUE,
01180                                                NULL));
01181   gtk_tree_view_column_pack_start (column, renderer, TRUE);
01182   gtk_tree_view_column_add_attribute (column, renderer, "text",
01183                                       ATTRIBUTE_COLUMN_VALUE);
01184   gtk_tree_view_append_column (GTK_TREE_VIEW (attrtreeview), column);
01185 
01186   scrolled_win = GTK_WIDGET (g_object_new (GTK_TYPE_SCROLLED_WINDOW,
01187                                            /* GtkContainer */
01188                                            "border-width", 5,
01189                                            /* GtkScrolledWindow */
01190                                            "hscrollbar-policy", GTK_POLICY_AUTOMATIC,
01191                                            "vscrollbar-policy", GTK_POLICY_AUTOMATIC,
01192                                            "shadow-type",       GTK_SHADOW_ETCHED_IN,
01193                                            NULL));
01194 
01195   gtk_container_add (GTK_CONTAINER (scrolled_win), attrtreeview);
01196 
01197   compselect->attrtreeview = GTK_TREE_VIEW (attrtreeview);
01198 
01199   return scrolled_win;
01200 }
01201 
01207 static GtkWidget*
01208 create_behaviors_combo_box (void)
01209 {
01210   GtkWidget *combobox;
01211 
01212   combobox = gtk_combo_box_new_text ();
01213 
01214   /* Note: order of items in menu is important */
01215   /* COMPSEL_BEHAVIOR_REFERENCE */
01216   gtk_combo_box_append_text (GTK_COMBO_BOX (combobox),
01217                              _("Default behavior - reference component"));
01218   /* COMPSEL_BEHAVIOR_EMBED */
01219   gtk_combo_box_append_text (GTK_COMBO_BOX (combobox),
01220                              _("Embed component in schematic"));
01221   /* COMPSEL_BEHAVIOR_INCLUDE */
01222   gtk_combo_box_append_text (GTK_COMBO_BOX (combobox),
01223                              _("Include component as individual objects"));
01224 
01225   gtk_combo_box_set_active (GTK_COMBO_BOX (combobox), 0);
01226 
01227   return combobox;
01228 }
01229 
01230 GType
01231 compselect_get_type ()
01232 {
01233   static GType compselect_type = 0;
01234 
01235   if (!compselect_type) {
01236     static const GTypeInfo compselect_info = {
01237       sizeof (CompselectClass),
01238       NULL, /* base_init */
01239       NULL, /* base_finalize */
01240       (GClassInitFunc) compselect_class_init,
01241       NULL, /* class_finalize */
01242       NULL, /* class_data */
01243       sizeof (Compselect),
01244       0,    /* n_preallocs */
01245       NULL  /* instance_init */
01246     };
01247 
01248     compselect_type = g_type_register_static (GSCHEM_TYPE_DIALOG,
01249                                               "Compselect",
01250                                               &compselect_info, 0);
01251   }
01252 
01253   return compselect_type;
01254 }
01255 
01256 
01267 static void
01268 compselect_geometry_save (GschemDialog *dialog, GKeyFile *key_file, gchar *group_name)
01269 {
01270   int position;
01271 
01272   /* Call the parent's geometry_save method */
01273   GSCHEM_DIALOG_CLASS (compselect_parent_class)->
01274     geometry_save (dialog, key_file, group_name);
01275 
01276   position = gtk_paned_get_position (GTK_PANED (COMPSELECT (dialog)->hpaned));
01277   g_key_file_set_integer (key_file, group_name, "hpaned", position);
01278 
01279   position = gtk_paned_get_position (GTK_PANED (COMPSELECT (dialog)->vpaned));
01280   g_key_file_set_integer (key_file, group_name, "vpaned", position);
01281 
01282   position = gtk_notebook_get_current_page (COMPSELECT (dialog)->viewtabs);
01283   g_key_file_set_integer (key_file, group_name, "source-tab", position);
01284 }
01285 
01286 
01297 static void
01298 compselect_geometry_restore (GschemDialog *dialog, GKeyFile *key_file, gchar *group_name)
01299 {
01300   int position;
01301 
01302   /* Call the parent's geometry_restore method */
01303   GSCHEM_DIALOG_CLASS (compselect_parent_class)->
01304     geometry_restore (dialog, key_file, group_name);
01305 
01306   position = g_key_file_get_integer (key_file, group_name, "hpaned", NULL);
01307   if (position != 0)
01308     gtk_paned_set_position (GTK_PANED (COMPSELECT (dialog)->hpaned), position);
01309 
01310   position = g_key_file_get_integer (key_file, group_name, "vpaned", NULL);
01311   if (position != 0)
01312     gtk_paned_set_position (GTK_PANED (COMPSELECT (dialog)->vpaned), position);
01313 
01314   position = g_key_file_get_integer (key_file, group_name, "source-tab", NULL);
01315   gtk_notebook_set_current_page (COMPSELECT (dialog)->viewtabs, position);
01316 }
01317 
01318 
01319 static void
01320 compselect_class_init (CompselectClass *klass)
01321 {
01322   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
01323   GschemDialogClass *gschem_dialog_class = GSCHEM_DIALOG_CLASS (klass);
01324 
01325   gschem_dialog_class->geometry_save    = compselect_geometry_save;
01326   gschem_dialog_class->geometry_restore = compselect_geometry_restore;
01327 
01328   gobject_class->constructor  = compselect_constructor;
01329   gobject_class->finalize     = compselect_finalize;
01330   gobject_class->set_property = compselect_set_property;
01331   gobject_class->get_property = compselect_get_property;
01332 
01333   compselect_parent_class = g_type_class_peek_parent (klass);
01334 
01335   g_object_class_install_property (
01336     gobject_class, PROP_SYMBOL,
01337     g_param_spec_pointer ("symbol",
01338                           "",
01339                           "",
01340                           G_PARAM_READABLE));
01341   g_object_class_install_property (
01342     gobject_class, PROP_BEHAVIOR,
01343     g_param_spec_enum ("behavior",
01344                        "",
01345                        "",
01346                        COMPSELECT_TYPE_BEHAVIOR,
01347                        COMPSELECT_BEHAVIOR_REFERENCE,
01348                        G_PARAM_READWRITE));
01349   g_object_class_install_property (
01350     gobject_class, PROP_HIDDEN,
01351     g_param_spec_boolean ("hidden",
01352                           "",
01353                           "",
01354                           FALSE,
01355                           G_PARAM_READWRITE));
01356 
01357 }
01358 
01359 static GObject*
01360 compselect_constructor (GType type,
01361                         guint n_construct_properties,
01362                         GObjectConstructParam *construct_params)
01363 {
01364   GObject *object;
01365   Compselect *compselect;
01366 
01367   GtkWidget *hpaned, *vpaned, *notebook, *attributes;
01368   GtkWidget *libview, *inuseview;
01369   GtkWidget *preview, *combobox;
01370   GtkWidget *alignment, *frame;
01371 
01372   /* chain up to constructor of parent class */
01373   object = G_OBJECT_CLASS (compselect_parent_class)->
01374     constructor (type, n_construct_properties, construct_params);
01375   compselect = COMPSELECT (object);
01376 
01377   /* dialog initialization */
01378   g_object_set (object,
01379                 /* GtkWindow */
01380                 "title",           _("Select Component..."),
01381                 "default-height",  300,
01382                 "default-width",   400,
01383                 NULL);
01384 
01385   /* vertical pane containing preview and attributes */
01386   vpaned = GTK_WIDGET (g_object_new (GTK_TYPE_VPANED, NULL));
01387   compselect->vpaned = vpaned;
01388 
01389   /* horizontal pane containing selection and preview */
01390   hpaned = GTK_WIDGET (g_object_new (GTK_TYPE_HPANED,
01391                                     /* GtkContainer */
01392                                     "border-width", 5,
01393                                      NULL));
01394   compselect->hpaned = hpaned;
01395 
01396   /* notebook for library and inuse views */
01397   notebook = GTK_WIDGET (g_object_new (GTK_TYPE_NOTEBOOK,
01398                                        NULL));
01399   compselect->viewtabs = GTK_NOTEBOOK (notebook);
01400 
01401   inuseview = create_inuse_treeview (compselect);
01402   gtk_notebook_append_page (GTK_NOTEBOOK (notebook), inuseview,
01403                             gtk_label_new (_("In Use")));
01404 
01405   libview = create_lib_treeview (compselect);
01406   gtk_notebook_append_page (GTK_NOTEBOOK (notebook), libview,
01407                             gtk_label_new (_("Libraries")));
01408 
01409   /* include the vertical box in horizontal box */
01410   gtk_paned_pack1 (GTK_PANED (hpaned), notebook, TRUE, FALSE);
01411 
01412 
01413   /* -- preview area -- */
01414   frame = GTK_WIDGET (g_object_new (GTK_TYPE_FRAME,
01415                                     /* GtkFrame */
01416                                     "label", _("Preview"),
01417                                     NULL));
01418   alignment = GTK_WIDGET (g_object_new (GTK_TYPE_ALIGNMENT,
01419                                         /* GtkAlignment */
01420                                         "border-width", 5,
01421                                         "xscale",         1.0,
01422                                         "yscale",         1.0,
01423                                         "xalign",         0.5,
01424                                         "yalign",         0.5,
01425                                         NULL));
01426   preview = GTK_WIDGET (g_object_new (TYPE_PREVIEW,
01427                                       /* Preview */
01428                                       "active", FALSE,
01429                                       NULL));
01430   gtk_container_add (GTK_CONTAINER (alignment), preview);
01431   gtk_container_add (GTK_CONTAINER (frame), alignment);
01432   /* set preview of compselect */
01433   compselect->preview = PREVIEW (preview);
01434 
01435   gtk_paned_pack1 (GTK_PANED (vpaned), frame, FALSE, FALSE);
01436 
01437   /* only create the attribute treeview if there are elements in the
01438      component_select_attrlist */
01439   if (GSCHEM_DIALOG (compselect)->w_current->component_select_attrlist == NULL) {
01440     compselect->attrtreeview = NULL;
01441   } else {
01442     frame = GTK_WIDGET (g_object_new (GTK_TYPE_FRAME,
01443                                       /* GtkFrame */
01444                                       "label", _("Attributes"),
01445                                       NULL));
01446     attributes = create_attributes_treeview (compselect);
01447     gtk_paned_pack2 (GTK_PANED (vpaned), frame, FALSE, FALSE);
01448     gtk_container_add (GTK_CONTAINER (frame), attributes);
01449   }
01450 
01451   gtk_paned_pack2 (GTK_PANED (hpaned), vpaned, FALSE, FALSE);
01452 
01453   /* add the hpaned to the dialog vbox */
01454   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (compselect)->vbox), hpaned,
01455                       TRUE, TRUE, 0);
01456   gtk_widget_show_all (hpaned);
01457 
01458 
01459   /* -- behavior combo box -- */
01460   combobox = create_behaviors_combo_box ();
01461   g_signal_connect (combobox,
01462                     "changed",
01463                     G_CALLBACK (compselect_callback_behavior_changed),
01464                     compselect);
01465   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (compselect)->vbox), combobox,
01466                       FALSE, FALSE, 10);
01467   gtk_widget_show_all (combobox);
01468   /* set behavior combo box of compselect */
01469   compselect->combobox_behaviors = GTK_COMBO_BOX (combobox);
01470 
01471   /* now add buttons in the action area */
01472   gtk_dialog_add_buttons (GTK_DIALOG (compselect),
01473                           /*  - close button */
01474                           GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
01475                           GTK_STOCK_OK, COMPSELECT_RESPONSE_HIDE,
01476                           NULL);
01477 
01478   /* Set the alternative button order (ok, cancel, help) for other systems */
01479   gtk_dialog_set_alternative_button_order (GTK_DIALOG (compselect),
01480                                           COMPSELECT_RESPONSE_HIDE,
01481                                           GTK_RESPONSE_CLOSE,
01482                                           -1);
01483 
01484   /* Initialize the hidden property */
01485   compselect->hidden = FALSE;
01486 
01487   return object;
01488 }
01489 
01490 static void
01491 compselect_finalize (GObject *object)
01492 {
01493   Compselect *compselect = COMPSELECT (object);
01494 
01495   if (compselect->filter_timeout != 0) {
01496     g_source_remove (compselect->filter_timeout);
01497     compselect->filter_timeout = 0;
01498   }
01499 
01500   G_OBJECT_CLASS (compselect_parent_class)->finalize (object);
01501 }
01502 
01503 static void
01504 compselect_set_property (GObject *object,
01505                          guint property_id,
01506                          const GValue *value,
01507                          GParamSpec *pspec)
01508 {
01509   Compselect *compselect = COMPSELECT (object);
01510 
01511   switch (property_id) {
01512     case PROP_BEHAVIOR:
01513       gtk_combo_box_set_active (compselect->combobox_behaviors,
01514                                 g_value_get_enum (value));
01515       break;
01516     case PROP_HIDDEN:
01517       compselect->hidden = g_value_get_boolean (value);
01518       if (compselect->hidden)
01519         gtk_widget_hide (GTK_WIDGET (compselect));
01520       else
01521         gtk_window_present (GTK_WINDOW (compselect));
01522       break;
01523     default:
01524       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
01525   }
01526 
01527 }
01528 
01529 static void
01530 compselect_get_property (GObject *object,
01531                          guint property_id,
01532                          GValue *value,
01533                          GParamSpec *pspec)
01534 {
01535   Compselect *compselect = COMPSELECT (object);
01536 
01537   switch (property_id) {
01538       case PROP_SYMBOL:
01539         {
01540           GtkTreeModel *model;
01541           GtkTreeIter iter, parent;
01542           CLibSymbol *symbol = NULL;
01543 
01544           switch (compselect_get_view (compselect)) {
01545           case VIEW_INUSE:
01546             if (gtk_tree_selection_get_selected (
01547                   gtk_tree_view_get_selection (compselect->inusetreeview),
01548                   &model,
01549                   &iter)) {
01550               gtk_tree_model_get (model, &iter, 0, &symbol, -1);
01551             }
01552             break;
01553           case VIEW_CLIB:
01554             if (gtk_tree_selection_get_selected (
01555                   gtk_tree_view_get_selection (compselect->libtreeview),
01556                   &model,
01557                   &iter)
01558                 && gtk_tree_model_iter_parent (model, &parent, &iter)) {
01559               gtk_tree_model_get (model, &iter, 0, &symbol, -1);
01560             }
01561             break;
01562           default:
01563             g_assert_not_reached ();
01564           }
01565 
01566           g_value_set_pointer (value, symbol);
01567           break;
01568         }
01569       case PROP_BEHAVIOR:
01570         g_value_set_enum (value,
01571                           gtk_combo_box_get_active (
01572                             compselect->combobox_behaviors));
01573         break;
01574       case PROP_HIDDEN:
01575         g_value_set_boolean (value, compselect->hidden);
01576         break;
01577       default:
01578         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
01579   }
01580 
01581 }
01582 
01583 
01584 
01585 GType
01586 compselect_behavior_get_type (void)
01587 {
01588   static GType etype = 0;
01589 
01590   if (etype == 0) {
01591     static const GEnumValue values[] = {
01592       { COMPSELECT_BEHAVIOR_REFERENCE, "COMPSELECT_BEHAVIOR_REFERENCE", "reference" },
01593       { COMPSELECT_BEHAVIOR_EMBED,     "COMPSELECT_BEHAVIOR_EMBED",     "embed" },
01594       { COMPSELECT_BEHAVIOR_INCLUDE,   "COMPSELECT_BEHAVIOR_INCLUDE",   "include" },
01595       { 0, NULL, NULL }
01596     };
01597 
01598     etype = g_enum_register_static ("CompselectBehavior", values);
01599   }
01600 
01601   return etype;
01602 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines