gschem
|
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 }