pcb 4.1.1
An interactive printed circuit board layout editor.
|
00001 /* 00002 * COPYRIGHT 00003 * 00004 * PCB, interactive printed circuit board design 00005 * Copyright (C) 1994,1995,1996 Thomas Nau 00006 * 00007 * This program is free software; you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License as published by 00009 * the Free Software Foundation; either version 2 of the License, or 00010 * (at your option) any later version. 00011 * 00012 * This program is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License along 00018 * with this program; if not, write to the Free Software Foundation, Inc., 00019 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00020 * 00021 * Contact addresses for paper mail and Email: 00022 * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany 00023 * Thomas.Nau@rz.uni-ulm.de 00024 * 00025 */ 00026 00027 /* This file originally from the PCB Gtk port by Bill Wilson. It has 00028 * since been combined with modified code from the gEDA project: 00029 * 00030 * gschem/src/ghid_library_window.c, checked out by Peter Clifton 00031 * from gEDA/gaf commit 72581a91da08c9d69593c24756144fc18940992e 00032 * on 3rd Jan, 2008. 00033 * 00034 * gEDA - GPL Electronic Design Automation 00035 * gschem - gEDA Schematic Capture 00036 * Copyright (C) 1998-2007 Ales Hvezda 00037 * Copyright (C) 1998-2007 gEDA Contributors (see ChangeLog for details) 00038 * 00039 * This program is free software; you can redistribute it and/or modify 00040 * it under the terms of the GNU General Public License as published by 00041 * the Free Software Foundation; either version 2 of the License, or 00042 * (at your option) any later version. 00043 * 00044 * This program is distributed in the hope that it will be useful, 00045 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00046 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00047 * GNU General Public License for more details. 00048 * 00049 * You should have received a copy of the GNU General Public License 00050 * along with this program; if not, write to the Free Software 00051 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA 00052 */ 00053 00054 #ifdef HAVE_CONFIG_H 00055 #include "config.h" 00056 #endif 00057 00058 #include "gui.h" 00059 #include "global.h" 00060 #include "buffer.h" 00061 #include "data.h" 00062 #include "set.h" 00063 00064 #include <gdk/gdkkeysyms.h> 00065 00066 #ifdef HAVE_LIBDMALLOC 00067 #include <dmalloc.h> 00068 #endif 00069 00070 static GtkWidget *library_window; 00071 00072 #include "gui-pinout-preview.h" 00073 #include "gui-library-window.h" 00074 00085 #define LIBRARY_FILTER_INTERVAL 200 00086 00087 00088 static gint 00089 library_window_configure_event_cb (GtkWidget * widget, GdkEventConfigure * ev, 00090 gpointer data) 00091 { 00092 GtkAllocation allocation; 00093 00094 gtk_widget_get_allocation (widget, &allocation); 00095 ghidgui->library_window_width = allocation.width; 00096 ghidgui->library_window_height = allocation.height; 00097 ghidgui->config_modified = TRUE; 00098 return FALSE; 00099 } 00100 00101 00102 enum 00103 { 00104 MENU_TOPPATH_COLUMN, /* Top path of the library */ 00105 MENU_SUBPATH_COLUMN, /* Relative path to the top */ 00106 MENU_NAME_COLUMN, /* Text to display in the tree */ 00107 MENU_LIBRARY_COLUMN, /* Pointer to the LibraryMenuType */ 00108 MENU_ENTRY_COLUMN, /* Pointer to the LibraryEntryType */ 00109 N_MENU_COLUMNS 00110 }; 00111 00112 00125 static void 00126 library_window_callback_response (GtkDialog * dialog, 00127 gint arg1, gpointer user_data) 00128 { 00129 switch (arg1) 00130 { 00131 case GTK_RESPONSE_CLOSE: 00132 case GTK_RESPONSE_DELETE_EVENT: 00133 gtk_widget_destroy (GTK_WIDGET (library_window)); 00134 library_window = NULL; 00135 break; 00136 00137 default: 00138 /* Do nothing, in case there's another handler function which 00139 can handle the response ID received. */ 00140 break; 00141 } 00142 } 00143 00144 00151 void 00152 ghid_library_window_create (GHidPort * out) 00153 { 00154 GtkWidget *current_tab, *entry_filter; 00155 GtkNotebook *notebook; 00156 00157 if (library_window) 00158 return; 00159 00160 library_window = (GtkWidget *)g_object_new (GHID_TYPE_LIBRARY_WINDOW, NULL); 00161 00162 g_signal_connect (library_window, 00163 "response", 00164 G_CALLBACK (library_window_callback_response), NULL); 00165 g_signal_connect (G_OBJECT (library_window), "configure_event", 00166 G_CALLBACK (library_window_configure_event_cb), NULL); 00167 gtk_window_resize (GTK_WINDOW (library_window), 00168 ghidgui->library_window_width, 00169 ghidgui->library_window_height); 00170 00171 gtk_window_set_title (GTK_WINDOW (library_window), _("PCB Library")); 00172 gtk_window_set_wmclass (GTK_WINDOW (library_window), "PCB_Library", 00173 "PCB"); 00174 00175 gtk_widget_realize (library_window); 00176 if (Settings.AutoPlace) 00177 gtk_window_move (GTK_WINDOW (library_window), 10, 10); 00178 00179 gtk_editable_select_region (GTK_EDITABLE 00180 (GHID_LIBRARY_WINDOW (library_window)-> 00181 entry_filter), 0, -1); 00182 00183 /* Set the focus to the filter entry only if it is in the current 00184 displayed tab */ 00185 notebook = GTK_NOTEBOOK (GHID_LIBRARY_WINDOW (library_window)->viewtabs); 00186 current_tab = gtk_notebook_get_nth_page (notebook, 00187 gtk_notebook_get_current_page 00188 (notebook)); 00189 entry_filter = 00190 GTK_WIDGET (GHID_LIBRARY_WINDOW (library_window)->entry_filter); 00191 if (gtk_widget_is_ancestor (entry_filter, current_tab)) 00192 { 00193 gtk_widget_grab_focus (entry_filter); 00194 } 00195 } 00196 00203 void 00204 ghid_library_window_show (GHidPort * out, gboolean raise) 00205 { 00206 ghid_library_window_create (out); 00207 gtk_widget_show_all (library_window); 00208 if (raise) 00209 gtk_window_present (GTK_WINDOW(library_window)); 00210 } 00211 00212 static GObjectClass *library_window_parent_class = NULL; 00213 00214 00225 static gboolean 00226 lib_model_filter_visible_func (GtkTreeModel * model, 00227 GtkTreeIter * iter, gpointer data) 00228 { 00229 GhidLibraryWindow *library_window = (GhidLibraryWindow *) data; 00230 const gchar *compname; 00231 gchar *compname_upper, *text_upper, *pattern; 00232 const gchar *text; 00233 gboolean ret; 00234 00235 g_assert (GHID_IS_LIBRARY_WINDOW (data)); 00236 00237 text = gtk_entry_get_text (library_window->entry_filter); 00238 if (g_ascii_strcasecmp (text, "") == 0) 00239 { 00240 return TRUE; 00241 } 00242 00243 /* If this is a source, only display it if it has children that 00244 * match */ 00245 if (gtk_tree_model_iter_has_child (model, iter)) 00246 { 00247 GtkTreeIter iter2; 00248 00249 gtk_tree_model_iter_children (model, &iter2, iter); 00250 ret = FALSE; 00251 do 00252 { 00253 if (lib_model_filter_visible_func (model, &iter2, data)) 00254 { 00255 ret = TRUE; 00256 break; 00257 } 00258 } 00259 while (gtk_tree_model_iter_next (model, &iter2)); 00260 } 00261 else 00262 { 00263 gtk_tree_model_get (model, iter, MENU_NAME_COLUMN, &compname, -1); 00264 /* Do a case insensitive comparison, converting the strings 00265 to uppercase */ 00266 compname_upper = g_ascii_strup (compname, -1); 00267 text_upper = g_ascii_strup (text, -1); 00268 pattern = g_strconcat ("*", text_upper, "*", NULL); 00269 ret = g_pattern_match_simple (pattern, compname_upper); 00270 g_free (compname_upper); 00271 g_free (text_upper); 00272 g_free (pattern); 00273 } 00274 00275 return ret; 00276 } 00277 00278 00289 static void 00290 tree_row_activated (GtkTreeView *tree_view, 00291 GtkTreePath *path, 00292 GtkTreeViewColumn *column, 00293 gpointer user_data) 00294 { 00295 GtkTreeModel *model; 00296 GtkTreeIter iter; 00297 00298 model = gtk_tree_view_get_model (tree_view); 00299 gtk_tree_model_get_iter (model, &iter, path); 00300 00301 if (!gtk_tree_model_iter_has_child (model, &iter)) 00302 return; 00303 00304 if (gtk_tree_view_row_expanded (tree_view, path)) 00305 gtk_tree_view_collapse_row (tree_view, path); 00306 else 00307 gtk_tree_view_expand_row (tree_view, path, FALSE); 00308 } 00309 00320 static gboolean 00321 tree_row_key_pressed (GtkTreeView *tree_view, 00322 GdkEventKey *event, 00323 gpointer user_data) 00324 { 00325 GtkTreeSelection *selection; 00326 GtkTreeModel *model; 00327 GtkTreeIter iter; 00328 GtkClipboard *clipboard; 00329 const gchar *compname; 00330 guint default_mod_mask = gtk_accelerator_get_default_mod_mask(); 00331 00332 /* Handle both lower- and uppercase `c' */ 00333 if (((event->state & default_mod_mask) != GDK_CONTROL_MASK) 00334 || ((event->keyval != GDK_c) && (event->keyval != GDK_C))) 00335 return FALSE; 00336 00337 selection = gtk_tree_view_get_selection (tree_view); 00338 g_return_val_if_fail (selection != NULL, TRUE); 00339 00340 if (!gtk_tree_selection_get_selected (selection, &model, &iter)) 00341 return TRUE; 00342 00343 gtk_tree_model_get (model, &iter, MENU_NAME_COLUMN, &compname, -1); 00344 00345 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD); 00346 g_return_val_if_fail (clipboard != NULL, TRUE); 00347 00348 gtk_clipboard_set_text (clipboard, compname, -1); 00349 00350 return TRUE; 00351 } 00352 00364 static void 00365 library_window_callback_tree_selection_changed (GtkTreeSelection * selection, 00366 gpointer user_data) 00367 { 00368 GtkTreeModel *model; 00369 GtkTreeIter iter; 00370 GhidLibraryWindow *library_window = (GhidLibraryWindow *) user_data; 00371 LibraryEntryType *entry = NULL; 00372 gchar *m4_args; 00373 00374 if (!gtk_tree_selection_get_selected (selection, &model, &iter)) 00375 return; 00376 00377 gtk_tree_model_get (model, &iter, MENU_ENTRY_COLUMN, &entry, -1); 00378 00379 if (entry == NULL) 00380 return; 00381 00382 /* -1 flags this is an element file part and the file path is in 00383 | entry->AllocateMemory. 00384 */ 00385 if (entry->Template == (char *) -1) 00386 { 00387 if (LoadElementToBuffer (PASTEBUFFER, entry->AllocatedMemory, true)) 00388 { 00389 SetMode (PASTEBUFFER_MODE); 00390 goto out; 00391 } 00392 return; 00393 } 00394 00395 /* Otherwise, it's a m4 element and we need to create a string of 00396 | macro arguments to be passed to the library command in 00397 | LoadElementToBuffer() 00398 */ 00399 m4_args = g_strdup_printf ("'%s' '%s' '%s'", EMPTY (entry->Template), 00400 EMPTY (entry->Value), EMPTY (entry->Package)); 00401 00402 if (LoadElementToBuffer (PASTEBUFFER, m4_args, false)) 00403 { 00404 SetMode (PASTEBUFFER_MODE); 00405 g_free (m4_args); 00406 goto out; 00407 } 00408 00409 g_free (m4_args); 00410 return; 00411 00412 out: 00413 00414 /* update the preview with new symbol data */ 00415 g_object_set (library_window->preview, 00416 "element-data", PASTEBUFFER->Data->Element->data, NULL); 00417 } 00418 00421 static void 00422 maybe_expand_toplevel_node (GtkTreeView *tree_view) 00423 { 00424 GtkTreeModel *model = gtk_tree_view_get_model (tree_view); 00425 if (gtk_tree_model_iter_n_children (model, NULL) == 1) 00426 { 00427 GtkTreePath *path = gtk_tree_path_new_first (); 00428 if (path != NULL) 00429 { 00430 gtk_tree_view_expand_row (tree_view, path, FALSE); 00431 gtk_tree_path_free(path); 00432 } 00433 } 00434 } 00435 00447 static gboolean 00448 library_window_filter_timeout (gpointer data) 00449 { 00450 GhidLibraryWindow *library_window = GHID_LIBRARY_WINDOW (data); 00451 GtkTreeModel *model; 00452 00453 /* resets the source id in library_window */ 00454 library_window->filter_timeout = 0; 00455 00456 model = gtk_tree_view_get_model (library_window->libtreeview); 00457 00458 if (model != NULL) 00459 { 00460 const gchar *text = gtk_entry_get_text (library_window->entry_filter); 00461 gtk_tree_model_filter_refilter ((GtkTreeModelFilter *) model); 00462 if (strcmp (text, "") != 0) 00463 { 00464 /* filter text not-empty */ 00465 gtk_tree_view_expand_all (library_window->libtreeview); 00466 } else { 00467 /* filter text is empty, collapse expanded tree */ 00468 gtk_tree_view_collapse_all (library_window->libtreeview); 00469 maybe_expand_toplevel_node (library_window->libtreeview); 00470 } 00471 } 00472 00473 /* return FALSE to remove the source */ 00474 return FALSE; 00475 } 00476 00488 static void 00489 library_window_callback_filter_entry_changed (GtkEditable * editable, 00490 gpointer user_data) 00491 { 00492 GhidLibraryWindow *library_window = GHID_LIBRARY_WINDOW (user_data); 00493 GtkWidget *button; 00494 gboolean sensitive; 00495 00496 /* turns button off if filter entry is empty */ 00497 /* turns it on otherwise */ 00498 button = GTK_WIDGET (library_window->button_clear); 00499 sensitive = 00500 (g_ascii_strcasecmp (gtk_entry_get_text (library_window->entry_filter), 00501 "") != 0); 00502 gtk_widget_set_sensitive (button, sensitive); 00503 00504 /* Cancel any pending update of the footprint list filter */ 00505 if (library_window->filter_timeout != 0) 00506 g_source_remove (library_window->filter_timeout); 00507 00508 /* Schedule an update of the footprint list filter in 00509 * LIBRARY_FILTER_INTERVAL milliseconds */ 00510 library_window->filter_timeout = g_timeout_add (LIBRARY_FILTER_INTERVAL, 00511 library_window_filter_timeout, 00512 library_window); 00513 00514 } 00515 00527 static void 00528 library_window_callback_filter_button_clicked (GtkButton * button, 00529 gpointer user_data) 00530 { 00531 GhidLibraryWindow *library_window = GHID_LIBRARY_WINDOW (user_data); 00532 00533 /* clears text in text entry for filter */ 00534 gtk_entry_set_text (library_window->entry_filter, ""); 00535 00536 } 00537 00538 /* \brief Create the tree model for the "Library" view. 00539 * \par Function Description 00540 * Creates a tree where the branches are the available library 00541 * sources and the leaves are the footprints. 00542 */ 00543 static GtkTreeModel * 00544 create_lib_tree_model (GhidLibraryWindow * library_window) 00545 { 00546 GtkTreeStore *tree; 00547 char *rel_path, empty_string[] = ""; /* writable */ 00548 GtkTreeIter *iter, p_iter, e_iter, c_iter; 00549 char *tok_start, *tok_end; 00550 gchar *name; 00551 gboolean exists; 00552 00553 tree = gtk_tree_store_new (N_MENU_COLUMNS, 00554 G_TYPE_STRING, G_TYPE_STRING, 00555 G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_POINTER); 00556 00557 MENU_LOOP (&Library); 00558 { 00559 /* Watch for directory changes of library parts and create new 00560 | parent iter at each change. 00561 */ 00562 if (!menu->directory) /* Shouldn't happen */ 00563 menu->directory = g_strdup ("???"); 00564 00565 rel_path = menu->Name; 00566 00567 if (strncmp(rel_path, menu->directory, strlen(menu->directory)) == 0) 00568 { 00569 if (rel_path[strlen(menu->directory)] == '\0') 00570 rel_path = empty_string; 00571 else if (rel_path[strlen(menu->directory)] == PCB_DIR_SEPARATOR_C) 00572 rel_path += strlen(menu->directory) + 1; 00573 } 00574 00575 iter = NULL; 00576 tok_start = tok_end = rel_path; 00577 00578 do 00579 { 00580 char saved_ch = *tok_end; 00581 *tok_end = '\0'; 00582 00583 exists = FALSE; 00584 if (gtk_tree_model_iter_children (GTK_TREE_MODEL (tree), &e_iter, iter)) 00585 do 00586 { 00587 gtk_tree_model_get (GTK_TREE_MODEL (tree), &e_iter, 00588 MENU_TOPPATH_COLUMN, &name, -1); 00589 if (strcmp (name, menu->directory) != 0) 00590 continue; 00591 00592 gtk_tree_model_get (GTK_TREE_MODEL (tree), &e_iter, 00593 MENU_SUBPATH_COLUMN, &name, -1); 00594 if (strcmp (name, rel_path) != 0) 00595 continue; 00596 00597 exists = TRUE; 00598 break; 00599 } 00600 while (gtk_tree_model_iter_next (GTK_TREE_MODEL (tree), &e_iter)); 00601 00602 if (exists) 00603 p_iter = e_iter; 00604 else 00605 { 00606 gtk_tree_store_append (tree, &p_iter, iter); 00607 gtk_tree_store_set (tree, &p_iter, 00608 MENU_TOPPATH_COLUMN, menu->directory, 00609 MENU_SUBPATH_COLUMN, rel_path, 00610 MENU_NAME_COLUMN, 00611 tok_end == rel_path ? 00612 g_path_get_basename(menu->directory) : tok_start, 00613 MENU_LIBRARY_COLUMN, 00614 saved_ch == '\0' ? menu : NULL, 00615 MENU_ENTRY_COLUMN, NULL, -1); 00616 } 00617 iter = &p_iter; 00618 00619 *tok_end = saved_ch; 00620 00621 tok_start = tok_end; 00622 if (*tok_start == PCB_DIR_SEPARATOR_C) 00623 tok_start++; 00624 tok_end = strchr(tok_start, PCB_DIR_SEPARATOR_C); 00625 if (!tok_end) tok_end = tok_start + strlen(tok_start); 00626 } 00627 while (*tok_start != '\0'); 00628 00629 ENTRY_LOOP (menu); 00630 { 00631 gtk_tree_store_append (tree, &c_iter, iter); 00632 gtk_tree_store_set (tree, &c_iter, 00633 MENU_TOPPATH_COLUMN, menu->directory, 00634 MENU_SUBPATH_COLUMN, rel_path, 00635 MENU_NAME_COLUMN, entry->ListEntry, 00636 MENU_LIBRARY_COLUMN, menu, 00637 MENU_ENTRY_COLUMN, entry, -1); 00638 } 00639 END_LOOP; 00640 00641 } 00642 END_LOOP; 00643 00644 return (GtkTreeModel *) tree; 00645 } 00646 00647 00648 #if 0 00649 /* \brief On-demand refresh of the footprint library. 00650 * \par Function Description 00651 * Requests a rescan of the footprint library in order to pick up any 00652 * new signals, and then updates the library window. 00653 */ 00654 static void 00655 library_window_callback_refresh_library (GtkButton * button, 00656 gpointer user_data) 00657 { 00658 GhidLibraryWindow *library_window = GHID_LIBRARY_WINDOW (user_data); 00659 GtkTreeModel *model; 00660 00661 /* Rescan the libraries for symbols */ 00662 /* TODO: How do we do this in PCB? */ 00663 00664 /* Refresh the "Library" view */ 00665 model = (GtkTreeModel *) 00666 g_object_new (GTK_TYPE_TREE_MODEL_FILTER, 00667 "child-model", create_lib_tree_model (library_window), 00668 "virtual-root", NULL, NULL); 00669 00670 gtk_tree_model_filter_set_visible_func ((GtkTreeModelFilter *) model, 00671 lib_model_filter_visible_func, 00672 library_window, NULL); 00673 00674 gtk_tree_view_set_model (library_window->libtreeview, model); 00675 maybe_expand_toplevel_node (library_window->libtreeview); 00676 } 00677 #endif 00678 00679 00681 static GtkWidget * 00682 create_lib_treeview (GhidLibraryWindow * library_window) 00683 { 00684 GtkWidget *libtreeview, *vbox, *scrolled_win, *label, 00685 *hbox, *entry, *button; 00686 GtkTreeModel *child_model, *model; 00687 GtkTreeSelection *selection; 00688 GtkCellRenderer *renderer; 00689 GtkTreeViewColumn *column; 00690 00691 /* -- library selection view -- */ 00692 00693 /* vertical box for footprint selection and search entry */ 00694 vbox = GTK_WIDGET (g_object_new (GTK_TYPE_VBOX, 00695 /* GtkContainer */ 00696 "border-width", 5, 00697 /* GtkBox */ 00698 "homogeneous", FALSE, "spacing", 5, NULL)); 00699 00700 child_model = create_lib_tree_model (library_window); 00701 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (child_model), 00702 MENU_NAME_COLUMN, GTK_SORT_ASCENDING); 00703 model = (GtkTreeModel *) g_object_new (GTK_TYPE_TREE_MODEL_FILTER, 00704 "child-model", child_model, 00705 "virtual-root", NULL, NULL); 00706 00707 scrolled_win = GTK_WIDGET (g_object_new (GTK_TYPE_SCROLLED_WINDOW, 00708 /* GtkScrolledWindow */ 00709 "hscrollbar-policy", 00710 GTK_POLICY_AUTOMATIC, 00711 "vscrollbar-policy", 00712 GTK_POLICY_ALWAYS, "shadow-type", 00713 GTK_SHADOW_ETCHED_IN, NULL)); 00714 /* create the treeview */ 00715 libtreeview = GTK_WIDGET (g_object_new (GTK_TYPE_TREE_VIEW, 00716 /* GtkTreeView */ 00717 "model", model, 00718 "rules-hint", TRUE, 00719 "headers-visible", FALSE, NULL)); 00720 00721 g_signal_connect (libtreeview, 00722 "row-activated", 00723 G_CALLBACK (tree_row_activated), 00724 NULL); 00725 00726 g_signal_connect (libtreeview, 00727 "key-press-event", 00728 G_CALLBACK (tree_row_key_pressed), 00729 NULL); 00730 00731 maybe_expand_toplevel_node (GTK_TREE_VIEW (libtreeview)); 00732 00733 /* connect callback to selection */ 00734 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (libtreeview)); 00735 gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE); 00736 g_signal_connect (selection, 00737 "changed", 00738 G_CALLBACK 00739 (library_window_callback_tree_selection_changed), 00740 library_window); 00741 00742 /* insert a column to treeview for library/symbol name */ 00743 renderer = GTK_CELL_RENDERER (g_object_new (GTK_TYPE_CELL_RENDERER_TEXT, 00744 /* GtkCellRendererText */ 00745 "editable", FALSE, NULL)); 00746 column = GTK_TREE_VIEW_COLUMN (g_object_new (GTK_TYPE_TREE_VIEW_COLUMN, 00747 /* GtkTreeViewColumn */ 00748 "title", _("Components"), 00749 NULL)); 00750 gtk_tree_view_column_pack_start (column, renderer, TRUE); 00751 gtk_tree_view_column_set_attributes (column, renderer, 00752 "text", MENU_NAME_COLUMN, NULL); 00753 gtk_tree_view_append_column (GTK_TREE_VIEW (libtreeview), column); 00754 00755 /* add the treeview to the scrolled window */ 00756 gtk_container_add (GTK_CONTAINER (scrolled_win), libtreeview); 00757 00758 /* add the scrolled window for directories to the vertical box */ 00759 gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0); 00760 00761 00762 /* -- filter area -- */ 00763 hbox = GTK_WIDGET (g_object_new (GTK_TYPE_HBOX, 00764 /* GtkBox */ 00765 "homogeneous", FALSE, "spacing", 3, NULL)); 00766 00767 /* create the entry label */ 00768 label = GTK_WIDGET (g_object_new (GTK_TYPE_LABEL, 00769 /* GtkMisc */ 00770 "xalign", 0.0, 00771 /* GtkLabel */ 00772 "label", _("Filter:"), NULL)); 00773 /* add the search label to the filter area */ 00774 gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); 00775 00776 /* create the text entry for filter in footprints */ 00777 entry = GTK_WIDGET (g_object_new (GTK_TYPE_ENTRY, 00778 /* GtkEntry */ 00779 "text", "", NULL)); 00780 g_signal_connect (entry, 00781 "changed", 00782 G_CALLBACK (library_window_callback_filter_entry_changed), 00783 library_window); 00784 00785 /* now that that we have an entry, set the filter func of model */ 00786 gtk_tree_model_filter_set_visible_func ((GtkTreeModelFilter *) model, 00787 lib_model_filter_visible_func, 00788 library_window, NULL); 00789 00790 /* add the filter entry to the filter area */ 00791 gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0); 00792 /* set filter entry of library_window */ 00793 library_window->entry_filter = GTK_ENTRY (entry); 00794 /* and init the event source for footprint filter */ 00795 library_window->filter_timeout = 0; 00796 00797 /* create the erase button for filter entry */ 00798 button = GTK_WIDGET (g_object_new (GTK_TYPE_BUTTON, 00799 /* GtkWidget */ 00800 "sensitive", FALSE, 00801 /* GtkButton */ 00802 "relief", GTK_RELIEF_NONE, NULL)); 00803 00804 gtk_container_add (GTK_CONTAINER (button), 00805 gtk_image_new_from_stock (GTK_STOCK_CLEAR, 00806 GTK_ICON_SIZE_SMALL_TOOLBAR)); 00807 g_signal_connect (button, 00808 "clicked", 00809 G_CALLBACK 00810 (library_window_callback_filter_button_clicked), 00811 library_window); 00812 /* add the clear button to the filter area */ 00813 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0); 00814 /* set clear button of library_window */ 00815 library_window->button_clear = GTK_BUTTON (button); 00816 00817 #if 0 00818 /* create the refresh button */ 00819 button = GTK_WIDGET (g_object_new (GTK_TYPE_BUTTON, 00820 /* GtkWidget */ 00821 "sensitive", TRUE, 00822 /* GtkButton */ 00823 "relief", GTK_RELIEF_NONE, NULL)); 00824 gtk_container_add (GTK_CONTAINER (button), 00825 gtk_image_new_from_stock (GTK_STOCK_REFRESH, 00826 GTK_ICON_SIZE_SMALL_TOOLBAR)); 00827 /* add the refresh button to the filter area */ 00828 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0); 00829 g_signal_connect (button, 00830 "clicked", 00831 G_CALLBACK (library_window_callback_refresh_library), 00832 library_window); 00833 #endif 00834 00835 /* add the filter area to the vertical box */ 00836 gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); 00837 00838 /* save pointer to libtreeview in library_window */ 00839 library_window->libtreeview = GTK_TREE_VIEW (libtreeview); 00840 00841 return vbox; 00842 } 00843 00844 00845 static GObject * 00846 library_window_constructor (GType type, 00847 guint n_construct_properties, 00848 GObjectConstructParam * construct_params) 00849 { 00850 GObject *object; 00851 GhidLibraryWindow *library_window; 00852 GtkWidget *content_area; 00853 GtkWidget *hpaned, *notebook; 00854 GtkWidget *libview; 00855 GtkWidget *preview; 00856 GtkWidget *alignment, *frame; 00857 00858 /* chain up to constructor of parent class */ 00859 object = G_OBJECT_CLASS (library_window_parent_class)-> 00860 constructor (type, n_construct_properties, construct_params); 00861 library_window = GHID_LIBRARY_WINDOW (object); 00862 00863 /* dialog initialization */ 00864 g_object_set (object, 00865 /* GtkWindow */ 00866 "type", GTK_WINDOW_TOPLEVEL, 00867 "title", _("Select Footprint..."), 00868 "default-height", 300, 00869 "default-width", 400, 00870 "modal", FALSE, "window-position", GTK_WIN_POS_NONE, 00871 /* GtkDialog */ 00872 "has-separator", TRUE, NULL); 00873 g_object_set (gtk_dialog_get_content_area (GTK_DIALOG (library_window)), 00874 "homogeneous", FALSE, NULL); 00875 00876 /* horizontal pane containing selection and preview */ 00877 hpaned = GTK_WIDGET (g_object_new (GTK_TYPE_HPANED, 00878 /* GtkContainer */ 00879 "border-width", 5, NULL)); 00880 library_window->hpaned = hpaned; 00881 00882 /* notebook for library views */ 00883 notebook = GTK_WIDGET (g_object_new (GTK_TYPE_NOTEBOOK, 00884 "show-tabs", FALSE, NULL)); 00885 library_window->viewtabs = GTK_NOTEBOOK (notebook); 00886 00887 libview = create_lib_treeview (library_window); 00888 gtk_notebook_append_page (GTK_NOTEBOOK (notebook), libview, 00889 gtk_label_new (_("Libraries"))); 00890 00891 /* include the vertical box in horizontal box */ 00892 gtk_paned_pack1 (GTK_PANED (hpaned), notebook, TRUE, FALSE); 00893 00894 00895 /* -- preview area -- */ 00896 frame = GTK_WIDGET (g_object_new (GTK_TYPE_FRAME, 00897 /* GtkFrame */ 00898 "label", _("Preview"), NULL)); 00899 alignment = GTK_WIDGET (g_object_new (GTK_TYPE_ALIGNMENT, 00900 /* GtkAlignment */ 00901 "left-padding", 5, 00902 "right-padding", 5, 00903 "top-padding", 5, 00904 "bottom-padding", 5, 00905 "xscale", 1.0, 00906 "yscale", 1.0, 00907 "xalign", 0.5, "yalign", 0.5, NULL)); 00908 preview = (GtkWidget *)g_object_new (GHID_TYPE_PINOUT_PREVIEW, 00909 /* GhidPinoutPreview */ 00910 "element-data", NULL, 00911 /* GtkWidget */ 00912 "width-request", 150, "height-request", 150, NULL); 00913 gtk_container_add (GTK_CONTAINER (alignment), preview); 00914 gtk_container_add (GTK_CONTAINER (frame), alignment); 00915 /* set preview of library_window */ 00916 library_window->preview = preview; 00917 00918 gtk_paned_pack2 (GTK_PANED (hpaned), frame, FALSE, FALSE); 00919 00920 /* add the hpaned to the dialog content area */ 00921 content_area = gtk_dialog_get_content_area (GTK_DIALOG (library_window)); 00922 gtk_box_pack_start (GTK_BOX (content_area), hpaned, TRUE, TRUE, 0); 00923 gtk_widget_show_all (hpaned); 00924 00925 00926 /* now add buttons in the action area */ 00927 gtk_dialog_add_buttons (GTK_DIALOG (library_window), 00928 /* - close button */ 00929 GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, NULL); 00930 00931 return object; 00932 } 00933 00934 static void 00935 library_window_finalize (GObject * object) 00936 { 00937 GhidLibraryWindow *library_window = GHID_LIBRARY_WINDOW (object); 00938 00939 if (library_window->filter_timeout != 0) 00940 { 00941 g_source_remove (library_window->filter_timeout); 00942 library_window->filter_timeout = 0; 00943 } 00944 00945 G_OBJECT_CLASS (library_window_parent_class)->finalize (object); 00946 } 00947 00948 00949 static void 00950 library_window_class_init (GhidLibraryWindowClass * klass) 00951 { 00952 GObjectClass *gobject_class = G_OBJECT_CLASS (klass); 00953 00954 gobject_class->constructor = library_window_constructor; 00955 gobject_class->finalize = library_window_finalize; 00956 00957 library_window_parent_class = (GObjectClass *)g_type_class_peek_parent (klass); 00958 } 00959 00960 00961 GType 00962 ghid_library_window_get_type () 00963 { 00964 static GType library_window_type = 0; 00965 00966 if (!library_window_type) 00967 { 00968 static const GTypeInfo library_window_info = { 00969 sizeof (GhidLibraryWindowClass), 00970 NULL, /* base_init */ 00971 NULL, /* base_finalize */ 00972 (GClassInitFunc) library_window_class_init, 00973 NULL, /* class_finalize */ 00974 NULL, /* class_data */ 00975 sizeof (GhidLibraryWindow), 00976 0, /* n_preallocs */ 00977 NULL /* instance_init */ 00978 }; 00979 00980 library_window_type = g_type_register_static (GTK_TYPE_DIALOG, 00981 "GhidLibraryWindow", 00982 &library_window_info, (GTypeFlags)0); 00983 } 00984 00985 return library_window_type; 00986 }