Updated copyright text/header in most source files.
[geda-gaf.git] / gschem / src / x_multiattrib.c
blob498e3ffffe4fcd9d3a2762e284ebe026c4281627
1 /* gEDA - GPL Electronic Design Automation
2 * gschem - gEDA Schematic Capture
3 * Copyright (C) 1998-2007 Ales Hvezda
4 * Copyright (C) 1998-2007 gEDA Contributors (see ChangeLog for details)
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
20 #include <config.h>
22 #include <stdio.h>
23 #ifdef HAVE_STDLIB_H
24 #include <stdlib.h>
25 #endif
26 #ifdef HAVE_STRING_H
27 #include <string.h>
28 #endif
30 #include <libgeda/libgeda.h>
32 #include "../include/i_vars.h"
33 #include "../include/globals.h"
34 #include "../include/prototype.h"
36 #ifdef HAVE_LIBDMALLOC
37 #include <dmalloc.h>
38 #endif
40 #include <gdk/gdkkeysyms.h>
41 #include "../include/gschem_dialog.h"
42 #include "../include/x_multiattrib.h"
44 /*! \brief Open multiple attribute editor dialog.
45 * \par Function Description
46 * Opens the multiple attribute editor dialog for <B>object</B> in the
47 * context of <B>toplevel</B>.
49 * The dialog is modal and this function does not return until the user
50 * closes the dialog.
52 * \param [in] toplevel The TOPLEVEL object.
53 * \param [in] object OBJECT to edit attributes on.
55 void x_multiattrib_open (TOPLEVEL *toplevel, OBJECT *object)
57 GtkWidget *dialog;
59 dialog = GTK_WIDGET (g_object_new (TYPE_MULTIATTRIB,
60 "object", object,
61 /* GschemDialog */
62 "settings-name", "multiattrib",
63 "toplevel", toplevel,
64 NULL));
66 gtk_window_set_transient_for(GTK_WINDOW(dialog),
67 GTK_WINDOW(toplevel->main_window));
69 multiattrib_update (MULTIATTRIB(dialog));
70 gtk_widget_show (dialog);
71 switch (gtk_dialog_run ((GtkDialog*)dialog)) {
72 case GTK_RESPONSE_CLOSE:
73 case GTK_RESPONSE_DELETE_EVENT:
74 /* reset state and update message in toolbar */
75 i_set_state (toplevel, SELECT);
76 i_update_toolbar (toplevel);
77 break;
78 default:
79 g_assert_not_reached ();
81 gtk_widget_destroy (dialog);
85 /*! \section celltextview-widget Cell TextView Widget Code.
86 * This widget makes a 'GtkTextView' widget implements the 'GtkCellEditable'
87 * interface. It can then be used to renderer multi-line texts inside
88 * tree views ('GtkTreeView').
90 static void celltextview_class_init (CellTextViewClass *klass);
91 static void celltextview_init (CellTextView *self);
92 static void celltextview_cell_editable_init (GtkCellEditableIface *iface);
94 /*! \todo Finish function documentation
95 * \brief
96 * \par Function Description
99 static gboolean celltextview_key_press_event (GtkWidget *widget,
100 GdkEventKey *event,
101 gpointer data)
103 CellTextView *celltextview = (CellTextView*)widget;
105 /* ends editing of cell if one of these keys are pressed */
106 if (
107 /* the Escape key */
108 event->keyval == GDK_Escape ||
109 /* the Enter key without the Control modifier */
110 (!(event->state & GDK_CONTROL_MASK) &&
111 (event->keyval == GDK_Return ||
112 event->keyval == GDK_KP_Enter))) {
113 gtk_cell_editable_editing_done (GTK_CELL_EDITABLE (celltextview));
114 gtk_cell_editable_remove_widget (GTK_CELL_EDITABLE (celltextview));
115 return TRUE;
118 return FALSE;
121 /*! \todo Finish function documentation
122 * \brief
123 * \par Function Description
126 static void celltextview_start_editing (GtkCellEditable *cell_editable,
127 GdkEvent *event)
129 g_signal_connect (cell_editable,
130 "key_press_event",
131 G_CALLBACK (celltextview_key_press_event),
132 NULL);
136 /*! \todo Finish function documentation
137 * \brief
138 * \par Function Description
141 GType celltextview_get_type()
143 static GType celltextview_type = 0;
145 if (!celltextview_type) {
146 static const GTypeInfo celltextview_info = {
147 sizeof(CellTextViewClass),
148 NULL, /* base_init */
149 NULL, /* base_finalize */
150 (GClassInitFunc) celltextview_class_init,
151 NULL, /* class_finalize */
152 NULL, /* class_data */
153 sizeof(CellTextView),
154 0, /* n_preallocs */
155 (GInstanceInitFunc) celltextview_init,
158 static const GInterfaceInfo cell_editable_info = {
159 (GInterfaceInitFunc) celltextview_cell_editable_init,
160 NULL, /* interface_finalize */
161 NULL /* interface_data */
164 celltextview_type = g_type_register_static(GTK_TYPE_TEXT_VIEW,
165 "CellTextView",
166 &celltextview_info, 0);
167 g_type_add_interface_static(celltextview_type,
168 GTK_TYPE_CELL_EDITABLE,
169 &cell_editable_info);
172 return celltextview_type;
175 /*! \todo Finish function documentation
176 * \brief
177 * \par Function Description
180 static void celltextview_class_init(CellTextViewClass *klass)
182 /* GObjectClass *gobject_class = G_OBJECT_CLASS (klass); */
185 /*! \todo Finish function documentation
186 * \brief
187 * \par Function Description
190 static void celltextview_init(CellTextView *self)
194 /*! \todo Finish function documentation
195 * \brief
196 * \par Function Description
199 static void celltextview_cell_editable_init(GtkCellEditableIface *iface)
201 iface->start_editing = celltextview_start_editing;
204 /*! \section multi-line-text-cell-renderer Multi-line Text Cell Renderer
205 * GTK has no multi-line text cell renderer. This code adds one to be used
206 * in gschem code. It is inspired by the 'GtkCellRendererCombo' renderer
207 * of GTK 2.4 (LGPL).
209 static void cellrenderermultilinetext_class_init(CellRendererMultiLineTextClass *klass);
210 static void cellrenderermultilinetext_init (CellRendererMultiLineText *self);
212 static void cellrenderermultilinetext_editing_done (GtkCellEditable *cell_editable,
213 gpointer user_data);
214 static gboolean cellrenderermultilinetext_focus_out_event (GtkWidget *widget,
215 GdkEvent *event,
216 gpointer user_data);
219 #define CELL_RENDERER_MULTI_LINE_TEXT_PATH "cell-renderer-multi-line-text-path"
222 /*! \todo Finish function documentation
223 * \brief
224 * \par Function Description
227 static GtkCellEditable* cellrenderermultilinetext_start_editing(GtkCellRenderer *cell,
228 GdkEvent *event,
229 GtkWidget *widget,
230 const gchar *path,
231 GdkRectangle *background_area,
232 GdkRectangle *cell_area,
233 GtkCellRendererState flags)
235 GtkCellRendererText *cell_text;
236 CellRendererMultiLineText *cell_mlt;
237 GtkWidget *textview;
238 GtkTextBuffer *textbuffer;
240 cell_text = GTK_CELL_RENDERER_TEXT (cell);
241 if (cell_text->editable == FALSE) {
242 return NULL;
245 cell_mlt = CELL_RENDERER_MULTI_LINE_TEXT (cell);
247 textbuffer = GTK_TEXT_BUFFER (g_object_new (GTK_TYPE_TEXT_BUFFER,
248 NULL));
249 gtk_text_buffer_set_text (textbuffer,
250 cell_text->text,
251 strlen (cell_text->text));
253 textview = GTK_WIDGET (g_object_new (TYPE_CELL_TEXT_VIEW,
254 /* GtkTextView */
255 /* unknown property in GTK 2.2, use
256 * gtk_text_view_set_buffer() instead */
257 /* "buffer", textbuffer, */
258 "editable", TRUE,
259 /* GtkWidget */
260 "height-request", cell_area->height,
261 NULL));
262 gtk_text_view_set_buffer (GTK_TEXT_VIEW (textview), textbuffer);
263 g_object_set_data_full (G_OBJECT (textview),
264 CELL_RENDERER_MULTI_LINE_TEXT_PATH,
265 g_strdup (path), g_free);
267 gtk_widget_show (textview);
269 g_signal_connect (GTK_CELL_EDITABLE (textview),
270 "editing_done",
271 G_CALLBACK (cellrenderermultilinetext_editing_done),
272 cell_mlt);
273 cell_mlt->focus_out_id =
274 g_signal_connect (textview,
275 "focus_out_event",
276 G_CALLBACK (cellrenderermultilinetext_focus_out_event),
277 cell_mlt);
279 return GTK_CELL_EDITABLE (textview);
282 /*! \todo Finish function documentation
283 * \brief
284 * \par Function Description
287 static void cellrenderermultilinetext_editing_done(GtkCellEditable *cell_editable,
288 gpointer user_data)
290 CellRendererMultiLineText *cell = CELL_RENDERER_MULTI_LINE_TEXT (user_data);
291 GtkTextBuffer *buffer;
292 GtkTextIter start, end;
293 gchar *new_text;
294 const gchar *path;
296 if (cell->focus_out_id > 0) {
297 g_signal_handler_disconnect (cell_editable,
298 cell->focus_out_id);
299 cell->focus_out_id = 0;
302 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (cell_editable));
303 gtk_text_buffer_get_start_iter (buffer, &start);
304 gtk_text_buffer_get_end_iter (buffer, &end);
305 new_text = gtk_text_buffer_get_text (buffer, &start, &end, TRUE);
307 path = g_object_get_data (G_OBJECT (cell_editable),
308 CELL_RENDERER_MULTI_LINE_TEXT_PATH);
309 g_signal_emit_by_name (cell, "edited", path, new_text);
311 g_free (new_text);
315 /*! \todo Finish function documentation
316 * \brief
317 * \par Function Description
320 static gboolean cellrenderermultilinetext_focus_out_event(GtkWidget *widget,
321 GdkEvent *event,
322 gpointer user_data)
324 cellrenderermultilinetext_editing_done (GTK_CELL_EDITABLE (widget),
325 user_data);
327 return FALSE;
330 /*! \todo Finish function documentation
331 * \brief
332 * \par Function Description
335 GType cellrenderermultilinetext_get_type()
337 static GType cellrenderermultilinetext_type = 0;
339 if (!cellrenderermultilinetext_type) {
340 static const GTypeInfo cellrenderermultilinetext_info = {
341 sizeof(CellRendererMultiLineTextClass),
342 NULL, /* base_init */
343 NULL, /* base_finalize */
344 (GClassInitFunc) cellrenderermultilinetext_class_init,
345 NULL, /* class_finalize */
346 NULL, /* class_data */
347 sizeof(CellRendererMultiLineText),
348 0, /* n_preallocs */
349 (GInstanceInitFunc) cellrenderermultilinetext_init,
352 cellrenderermultilinetext_type = g_type_register_static (
353 GTK_TYPE_CELL_RENDERER_TEXT,
354 "CellRendererMultiLineText",
355 &cellrenderermultilinetext_info, 0);
358 return cellrenderermultilinetext_type;
361 /*! \todo Finish function documentation
362 * \brief
363 * \par Function Description
366 static void cellrenderermultilinetext_class_init(CellRendererMultiLineTextClass *klass)
368 /* GObjectClass *gobject_class = G_OBJECT_CLASS (klass); */
369 GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (klass);
371 cell_class->start_editing = cellrenderermultilinetext_start_editing;
375 /*! \todo Finish function documentation
376 * \brief
377 * \par Function Description
380 static void cellrenderermultilinetext_init(CellRendererMultiLineText *self)
385 enum {
386 PROP_OBJECT = 1
389 enum {
390 COLUMN_ATTRIBUTE,
391 NUM_COLUMNS
395 static void multiattrib_class_init (MultiattribClass *class);
396 static void multiattrib_init (Multiattrib *multiattrib);
397 static void multiattrib_set_property (GObject *object,
398 guint property_id,
399 const GValue *value,
400 GParamSpec *pspec);
401 static void multiattrib_get_property (GObject *object,
402 guint property_id,
403 GValue *value,
404 GParamSpec *pspec);
406 static void multiattrib_popup_menu (Multiattrib *multiattrib,
407 GdkEventButton *event);
410 /*! \todo Finish function documentation
411 * \brief
412 * \par Function Description
415 static void multiattrib_action_add_attribute(TOPLEVEL *toplevel,
416 OBJECT *object,
417 const gchar *name,
418 const gchar *value,
419 gint visible,
420 gint show_name_value)
422 OBJECT *o_attrib;
423 gchar *newtext;
425 newtext = g_strdup_printf ("%s=%s", name, value);
427 /* create a new attribute and link it */
428 o_attrib = o_attrib_add_attrib (toplevel, newtext,
429 visible, show_name_value, object);
431 toplevel->page_current->CHANGED = 1;
432 o_undo_savestate (toplevel, UNDO_ALL);
434 g_free (newtext);
438 /*! \todo Finish function documentation
439 * \brief
440 * \par Function Description
443 static void multiattrib_action_duplicate_attribute(TOPLEVEL *toplevel,
444 OBJECT *object,
445 OBJECT *o_attrib)
447 OBJECT *o_new;
449 o_new = o_attrib_add_attrib (toplevel,
450 o_attrib->text->string,
451 o_attrib->visibility,
452 o_attrib->show_name_value,
453 object);
454 toplevel->page_current->CHANGED = 1;
455 o_undo_savestate (toplevel, UNDO_ALL);
459 /*! \todo Finish function documentation
460 * \brief
461 * \par Function Description
464 static void multiattrib_action_delete_attribute(TOPLEVEL *toplevel,
465 OBJECT *o_attrib)
467 /* actually deletes the attribute */
468 o_selection_remove (&(toplevel->page_current->selection_list), o_attrib);
469 o_delete_text (toplevel, o_attrib);
470 toplevel->page_current->CHANGED=1;
471 o_undo_savestate (toplevel, UNDO_ALL);
475 /*! \todo Finish function documentation
476 * \brief
477 * \par Function Description
480 static void multiattrib_column_set_data_name(GtkTreeViewColumn *tree_column,
481 GtkCellRenderer *cell,
482 GtkTreeModel *tree_model,
483 GtkTreeIter *iter,
484 gpointer data)
486 OBJECT *o_attrib;
487 gchar *name, *value;
489 gtk_tree_model_get (tree_model, iter,
490 COLUMN_ATTRIBUTE, &o_attrib,
491 -1);
492 g_assert (o_attrib->type == OBJ_TEXT);
494 o_attrib_get_name_value (o_attrib->text->string, &name, &value);
495 g_object_set (cell,
496 "text", name,
497 NULL);
498 g_free (name);
499 g_free (value);
503 /*! \todo Finish function documentation
504 * \brief
505 * \par Function Description
508 static void multiattrib_column_set_data_value(GtkTreeViewColumn *tree_column,
509 GtkCellRenderer *cell,
510 GtkTreeModel *tree_model,
511 GtkTreeIter *iter,
512 gpointer data)
514 OBJECT *o_attrib;
515 gchar *name, *value;
517 gtk_tree_model_get (tree_model, iter,
518 COLUMN_ATTRIBUTE, &o_attrib,
519 -1);
520 g_assert (o_attrib->type == OBJ_TEXT);
522 o_attrib_get_name_value (o_attrib->text->string, &name, &value);
523 g_object_set (cell,
524 "text", value,
525 NULL);
526 g_free (name);
527 g_free (value);
531 /*! \todo Finish function documentation
532 * \brief
533 * \par Function Description
536 static void multiattrib_column_set_data_visible(GtkTreeViewColumn *tree_column,
537 GtkCellRenderer *cell,
538 GtkTreeModel *tree_model,
539 GtkTreeIter *iter,
540 gpointer data)
542 OBJECT *o_attrib;
544 gtk_tree_model_get (tree_model, iter,
545 COLUMN_ATTRIBUTE, &o_attrib,
546 -1);
547 g_assert (o_attrib->type == OBJ_TEXT);
549 g_object_set (cell,
550 "active", (o_attrib->visibility == VISIBLE),
551 NULL);
555 /*! \todo Finish function documentation
556 * \brief
557 * \par Function Description
560 static void multiattrib_column_set_data_show_name(GtkTreeViewColumn *tree_column,
561 GtkCellRenderer *cell,
562 GtkTreeModel *tree_model,
563 GtkTreeIter *iter,
564 gpointer data)
566 OBJECT *o_attrib;
568 gtk_tree_model_get (tree_model, iter,
569 COLUMN_ATTRIBUTE, &o_attrib,
570 -1);
571 g_assert (o_attrib->type == OBJ_TEXT);
573 g_object_set (cell,
574 "active", (o_attrib->show_name_value == SHOW_NAME_VALUE ||
575 o_attrib->show_name_value == SHOW_NAME),
576 NULL);
580 /*! \todo Finish function documentation
581 * \brief
582 * \par Function Description
585 static void multiattrib_column_set_data_show_value(GtkTreeViewColumn *tree_column,
586 GtkCellRenderer *cell,
587 GtkTreeModel *tree_model,
588 GtkTreeIter *iter,
589 gpointer data)
591 OBJECT *o_attrib;
593 gtk_tree_model_get (tree_model, iter,
594 COLUMN_ATTRIBUTE, &o_attrib,
595 -1);
596 g_assert (o_attrib->type == OBJ_TEXT);
598 g_object_set (cell,
599 "active", (o_attrib->show_name_value == SHOW_NAME_VALUE ||
600 o_attrib->show_name_value == SHOW_VALUE),
601 NULL);
605 /*! \brief Requests an update of the display of a row.
606 * \par Function Description
607 * This is an helper function to update the display of a row when
608 * data for this row have been modified in the model.
610 * It emits the 'row_changed' signal on the pointed row.
612 * \param [in] model A GtkTreeModel.
613 * \param [in] iter A valid GtkTreeIter pointing to the changed row.
615 static void
616 update_row_display (GtkTreeModel *model, GtkTreeIter *iter)
618 GtkTreePath *path;
620 path = gtk_tree_model_get_path (model, iter);
621 gtk_tree_model_row_changed (model, path, iter);
622 gtk_tree_path_free (path);
626 /*! \todo Finish function documentation
627 * \brief
628 * \par Function Description
631 static void multiattrib_callback_edited_name(GtkCellRendererText *cellrenderertext,
632 gchar *arg1,
633 gchar *arg2,
634 gpointer user_data)
636 Multiattrib *multiattrib = (Multiattrib*)user_data;
637 GtkTreeModel *model;
638 GtkTreeIter iter;
639 OBJECT *o_attrib;
640 TOPLEVEL *toplevel;
641 gchar *name, *value, *newtext;
643 model = gtk_tree_view_get_model (multiattrib->treeview);
644 toplevel = GSCHEM_DIALOG (multiattrib)->toplevel;
646 if (!gtk_tree_model_get_iter_from_string (model, &iter, arg1)) {
647 return;
650 if (g_ascii_strcasecmp (arg2, "") == 0) {
651 GtkWidget *dialog = gtk_message_dialog_new (
652 GTK_WINDOW (multiattrib),
653 GTK_DIALOG_MODAL,
654 GTK_MESSAGE_ERROR,
655 GTK_BUTTONS_OK,
656 _("Attributes with empty name are not allowed. Please set a name."));
658 gtk_dialog_run (GTK_DIALOG (dialog));
659 gtk_widget_destroy (dialog);
660 return;
663 gtk_tree_model_get (model, &iter,
664 COLUMN_ATTRIBUTE, &o_attrib,
665 -1);
666 g_assert (o_attrib->type == OBJ_TEXT);
668 o_attrib_get_name_value (o_attrib->text->string, &name, &value);
669 newtext = g_strdup_printf ("%s=%s", arg2, value);
671 /* actually modifies the attribute */
672 o_text_change (toplevel, o_attrib,
673 newtext, o_attrib->visibility, o_attrib->show_name_value);
675 g_free (name);
676 g_free (value);
677 g_free (newtext);
681 /*! \todo Finish function documentation
682 * \brief
683 * \par Function Description
686 static void multiattrib_callback_edited_value(GtkCellRendererText *cell_renderer,
687 gchar *arg1,
688 gchar *arg2,
689 gpointer user_data)
691 Multiattrib *multiattrib = (Multiattrib*)user_data;
692 GtkTreeModel *model;
693 GtkTreeIter iter;
694 OBJECT *o_attrib;
695 TOPLEVEL *toplevel;
696 gchar *name, *value, *newtext;
698 model = gtk_tree_view_get_model (multiattrib->treeview);
699 toplevel = GSCHEM_DIALOG (multiattrib)->toplevel;
701 if (!gtk_tree_model_get_iter_from_string (model, &iter, arg1)) {
702 return;
705 gtk_tree_model_get (model, &iter,
706 COLUMN_ATTRIBUTE, &o_attrib,
707 -1);
708 g_assert (o_attrib->type == OBJ_TEXT);
710 o_attrib_get_name_value (o_attrib->text->string, &name, &value);
711 newtext = g_strdup_printf ("%s=%s", name, arg2);
713 /* actually modifies the attribute */
714 o_text_change (toplevel, o_attrib,
715 newtext, o_attrib->visibility, o_attrib->show_name_value);
717 /* request an update of display for this row */
718 update_row_display (model, &iter);
720 g_free (name);
721 g_free (value);
722 g_free (newtext);
726 /*! \todo Finish function documentation
727 * \brief
728 * \par Function Description
731 static void multiattrib_callback_toggled_visible(GtkCellRendererToggle *cell_renderer,
732 gchar *path,
733 gpointer user_data)
735 Multiattrib *multiattrib = (Multiattrib*)user_data;
736 GtkTreeModel *model;
737 GtkTreeIter iter;
738 OBJECT *o_attrib;
739 TOPLEVEL *toplevel;
740 gint visibility;
742 model = gtk_tree_view_get_model (multiattrib->treeview);
743 toplevel = GSCHEM_DIALOG (multiattrib)->toplevel;
745 if (!gtk_tree_model_get_iter_from_string (model, &iter, path)) {
746 return;
749 gtk_tree_model_get (model, &iter,
750 COLUMN_ATTRIBUTE, &o_attrib,
751 -1);
752 g_assert (o_attrib->type == OBJ_TEXT);
753 o_text_erase (toplevel, o_attrib);
755 visibility = o_attrib->visibility == VISIBLE ? INVISIBLE : VISIBLE;
757 /* actually modifies the attribute */
758 o_attrib->visibility = visibility;
759 o_text_recreate (toplevel, o_attrib);
760 o_text_draw (toplevel, o_attrib);
761 o_undo_savestate (toplevel, UNDO_ALL);
763 /* request an update of display for this row */
764 update_row_display (model, &iter);
768 /*! \todo Finish function documentation
769 * \brief
770 * \par Function Description
773 static void multiattrib_callback_toggled_show_name(GtkCellRendererToggle *cell_renderer,
774 gchar *path,
775 gpointer user_data)
777 Multiattrib *multiattrib = (Multiattrib*)user_data;
778 GtkTreeModel *model;
779 GtkTreeIter iter;
780 OBJECT *o_attrib;
781 TOPLEVEL *toplevel;
782 gint new_snv;
784 model = gtk_tree_view_get_model (multiattrib->treeview);
785 toplevel = GSCHEM_DIALOG (multiattrib)->toplevel;
787 if (!gtk_tree_model_get_iter_from_string (model, &iter, path)) {
788 return;
791 gtk_tree_model_get (model, &iter,
792 COLUMN_ATTRIBUTE, &o_attrib,
793 -1);
794 g_assert (o_attrib->type == OBJ_TEXT);
795 o_text_erase (toplevel, o_attrib);
797 switch (o_attrib->show_name_value) {
798 case SHOW_NAME_VALUE: new_snv = SHOW_VALUE; break;
799 case SHOW_NAME: new_snv = SHOW_VALUE; break;
800 case SHOW_VALUE: new_snv = SHOW_NAME_VALUE; break;
801 default:
802 g_assert_not_reached ();
803 new_snv = SHOW_NAME_VALUE;
806 /* actually modifies the attribute */
807 o_attrib->show_name_value = new_snv;
808 o_text_recreate (toplevel, o_attrib);
809 o_text_draw (toplevel, o_attrib);
810 o_undo_savestate (toplevel, UNDO_ALL);
812 /* request an update of display for this row */
813 update_row_display (model, &iter);
817 /*! \todo Finish function documentation
818 * \brief
819 * \par Function Description
822 static void multiattrib_callback_toggled_show_value(GtkCellRendererToggle *cell_renderer,
823 gchar *path,
824 gpointer user_data)
826 Multiattrib *multiattrib = (Multiattrib*)user_data;
827 GtkTreeModel *model;
828 GtkTreeIter iter;
829 OBJECT *o_attrib;
830 TOPLEVEL *toplevel;
831 gint new_snv;
833 model = gtk_tree_view_get_model (multiattrib->treeview);
834 toplevel = GSCHEM_DIALOG (multiattrib)->toplevel;
836 if (!gtk_tree_model_get_iter_from_string (model, &iter, path)) {
837 return;
840 gtk_tree_model_get (model, &iter,
841 COLUMN_ATTRIBUTE, &o_attrib,
842 -1);
843 g_assert (o_attrib->type == OBJ_TEXT);
844 o_text_erase (toplevel, o_attrib);
846 switch (o_attrib->show_name_value) {
847 case SHOW_NAME_VALUE: new_snv = SHOW_NAME; break;
848 case SHOW_NAME: new_snv = SHOW_NAME_VALUE; break;
849 case SHOW_VALUE: new_snv = SHOW_NAME; break;
850 default:
851 g_assert_not_reached ();
852 new_snv = SHOW_NAME_VALUE;
855 /* actually modifies the attribute */
856 o_attrib->show_name_value = new_snv;
857 o_text_recreate (toplevel, o_attrib);
858 o_text_draw (toplevel, o_attrib);
859 o_undo_savestate (toplevel, UNDO_ALL);
861 /* request an update of display for this row */
862 update_row_display (model, &iter);
866 /*! \todo Finish function documentation
867 * \brief
868 * \par Function Description
871 static gboolean multiattrib_callback_key_pressed(GtkWidget *widget,
872 GdkEventKey *event,
873 gpointer user_data)
875 Multiattrib *multiattrib = (Multiattrib*)user_data;
877 if (event->state == 0 &&
878 (event->keyval == GDK_Delete || event->keyval == GDK_KP_Delete)) {
879 GtkTreeModel *model;
880 GtkTreeIter iter;
881 OBJECT *o_attrib;
882 /* delete the currently selected attribute */
884 if (!gtk_tree_selection_get_selected (
885 gtk_tree_view_get_selection (multiattrib->treeview),
886 &model, &iter)) {
887 /* nothing selected, nothing to do */
888 return FALSE;
891 gtk_tree_model_get (model, &iter,
892 COLUMN_ATTRIBUTE, &o_attrib,
893 -1);
894 g_assert (o_attrib->type == OBJ_TEXT);
896 multiattrib_action_delete_attribute (GSCHEM_DIALOG (multiattrib)->toplevel,
897 o_attrib);
899 /* update the treeview contents */
900 multiattrib_update (multiattrib);
903 return FALSE;
906 /*! \todo Finish function documentation
907 * \brief
908 * \par Function Description
911 static gboolean multiattrib_callback_button_pressed(GtkWidget *widget,
912 GdkEventButton *event,
913 gpointer user_data)
915 Multiattrib *multiattrib = (Multiattrib*)user_data;
916 gboolean ret = FALSE;
918 if (event->type == GDK_BUTTON_PRESS && event->button == 3) {
919 multiattrib_popup_menu (multiattrib, event);
920 ret = TRUE;
923 return ret;
926 /*! \todo Finish function documentation
927 * \brief
928 * \par Function Description
931 static gboolean multiattrib_callback_popup_menu(GtkWidget *widget,
932 gpointer user_data)
934 Multiattrib *multiattrib = (Multiattrib*)user_data;
936 multiattrib_popup_menu (multiattrib, NULL);
938 return TRUE;
941 /*! \todo Finish function documentation
942 * \brief
943 * \par Function Description
946 static void multiattrib_callback_popup_duplicate(GtkMenuItem *menuitem,
947 gpointer user_data)
949 Multiattrib *multiattrib = (Multiattrib*)user_data;
950 GtkTreeModel *model;
951 GtkTreeIter iter;
952 TOPLEVEL *toplevel;
953 OBJECT *object, *o_attrib;
955 if (!gtk_tree_selection_get_selected (
956 gtk_tree_view_get_selection (multiattrib->treeview),
957 &model, &iter)) {
958 /* nothing selected, nothing to do */
959 return;
962 toplevel = GSCHEM_DIALOG (multiattrib)->toplevel;
963 object = multiattrib->object;
965 gtk_tree_model_get (model, &iter,
966 COLUMN_ATTRIBUTE, &o_attrib,
967 -1);
968 g_assert (o_attrib->type == OBJ_TEXT);
970 multiattrib_action_duplicate_attribute (toplevel, object, o_attrib);
972 /* update the treeview contents */
973 multiattrib_update (multiattrib);
977 /*! \todo Finish function documentation
978 * \brief
979 * \par Function Description
982 static void multiattrib_callback_popup_delete(GtkMenuItem *menuitem,
983 gpointer user_data)
985 Multiattrib *multiattrib = (Multiattrib*)user_data;
986 GtkTreeModel *model;
987 GtkTreeIter iter;
988 TOPLEVEL *toplevel;
989 OBJECT *o_attrib;
991 if (!gtk_tree_selection_get_selected (
992 gtk_tree_view_get_selection (multiattrib->treeview),
993 &model, &iter)) {
994 /* nothing selected, nothing to do */
995 return;
998 toplevel = GSCHEM_DIALOG (multiattrib)->toplevel;
1000 gtk_tree_model_get (model, &iter,
1001 COLUMN_ATTRIBUTE, &o_attrib,
1002 -1);
1003 g_assert (o_attrib->type == OBJ_TEXT);
1005 multiattrib_action_delete_attribute (toplevel, o_attrib);
1007 /* update the treeview contents */
1008 multiattrib_update (multiattrib);
1012 /*! \todo Finish function documentation
1013 * \brief
1014 * \par Function Description
1017 static gboolean multiattrib_callback_value_key_pressed(GtkWidget *widget,
1018 GdkEventKey *event,
1019 gpointer user_data)
1021 Multiattrib *multiattrib = (Multiattrib*)widget;
1022 gboolean retval = FALSE;
1024 /* ends editing of cell if one of these keys are pressed: */
1025 /* - the Return key without the Control modifier */
1026 /* - the Tab key without the Control modifier */
1027 if ((event->keyval == GDK_Return || event->keyval == GDK_KP_Enter) ||
1028 (event->keyval == GDK_Tab || event->keyval == GDK_KP_Tab)) {
1029 /* Control modifier activated? */
1030 if (event->state & GDK_CONTROL_MASK) {
1031 /* yes the modifier in event structure and let event propagate */
1032 event->state ^= GDK_CONTROL_MASK;
1033 retval = FALSE;
1034 } else {
1035 /* change focus and stop propagation */
1036 g_signal_emit_by_name (multiattrib,
1037 "move_focus",
1038 (event->state & GDK_SHIFT_MASK) ?
1039 GTK_DIR_TAB_BACKWARD : GTK_DIR_TAB_FORWARD);
1040 retval = TRUE;
1044 return retval;
1047 /*! \todo Finish function documentation
1048 * \brief
1049 * \par Function Description
1052 static void multiattrib_callback_button_add(GtkButton *button,
1053 gpointer user_data)
1055 Multiattrib *multiattrib = (Multiattrib*)user_data;
1056 GtkTextBuffer *buffer;
1057 GtkTextIter start, end;
1058 const gchar *name;
1059 gchar *value;
1060 TOPLEVEL *toplevel;
1061 OBJECT *object;
1062 gboolean visible;
1063 gint shownv;
1065 toplevel = GSCHEM_DIALOG (multiattrib)->toplevel;
1066 object = multiattrib->object;
1067 buffer = gtk_text_view_get_buffer (multiattrib->textview_value);
1069 /* retrieve information from the Add/Edit frame */
1070 /* - attribute's name */
1071 name = gtk_entry_get_text (
1072 GTK_ENTRY (GTK_COMBO (multiattrib->combo_name)->entry));
1073 /* - attribute's value */
1074 gtk_text_buffer_get_bounds (buffer, &start, &end);
1075 value = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
1076 /* - attribute's visibility status */
1077 visible = gtk_toggle_button_get_active (
1078 (GtkToggleButton*)multiattrib->button_visible);
1079 /* - visibility type */
1080 shownv = (gint)gtk_option_menu_get_history (multiattrib->optionmenu_shownv);
1082 if (name[0] == '\0' || name[0] == ' ') {
1083 /* name not allowed for an attribute */
1084 g_free (value);
1085 return;
1088 multiattrib_action_add_attribute (toplevel, object,
1089 name, value,
1090 visible, shownv);
1091 g_free (value);
1093 /* clear fields of lower frame */
1094 /* - resets entry for name */
1095 gtk_list_select_item (GTK_LIST (multiattrib->combo_name->list), 0);
1096 /* - resets entry for value */
1097 gtk_text_buffer_set_text (buffer, "", 0);
1098 /* - resets entry for visibility */
1099 g_object_set (multiattrib->button_visible,
1100 "active", TRUE,
1101 NULL);
1102 /* - resets entry for show name/value */
1103 gtk_option_menu_set_history (multiattrib->optionmenu_shownv,
1106 multiattrib_update (multiattrib);
1110 /*! \todo Finish function documentation
1111 * \brief
1112 * \par Function Description
1115 static void multiattrib_init_attrib_names(GtkCombo *combo)
1117 GList *items = NULL;
1118 const gchar *string;
1119 gint i;
1121 for (i = 0, string = s_attrib_get (i);
1122 string != NULL;
1123 i++, string = s_attrib_get (i)) {
1124 items = g_list_append (items, (gpointer)string);
1127 gtk_combo_set_popdown_strings (GTK_COMBO (combo), items);
1129 g_list_free (items);
1133 /*! \todo Finish function documentation
1134 * \brief
1135 * \par Function Description
1138 static void multiattrib_init_visible_types(GtkOptionMenu *optionmenu)
1140 GtkWidget *menu, *item;
1142 menu = gtk_menu_new ();
1143 item = gtk_menu_item_new_with_label (_("Show Name & Value"));
1144 gtk_menu_append (menu, item);
1145 item = gtk_menu_item_new_with_label (_("Show Value only"));
1146 gtk_menu_append (menu, item);
1147 item = gtk_menu_item_new_with_label (_("Show Name only"));
1148 gtk_menu_append (menu, item);
1150 gtk_option_menu_set_menu (optionmenu, menu);
1154 /*! \brief Popup a context-sensitive menu.
1155 * \par Function Description
1156 * Pops up a context-sensitive menu.
1157 * <B>event</B> can be NULL if the popup is triggered by a key binding
1158 * instead of a mouse click.
1160 * \param [in] multiattrib The Multiattrib object.
1161 * \param [in] event Mouse event.
1163 static void multiattrib_popup_menu(Multiattrib *multiattrib,
1164 GdkEventButton *event)
1166 GtkTreePath *path;
1167 GtkWidget *menu;
1168 struct menuitem_t {
1169 gchar *label;
1170 GCallback callback;
1172 struct menuitem_t menuitems[] = {
1173 { N_("Duplicate"), G_CALLBACK (multiattrib_callback_popup_duplicate) },
1174 { N_("Delete"), G_CALLBACK (multiattrib_callback_popup_delete) },
1175 { NULL, NULL } };
1176 struct menuitem_t *tmp;
1178 if (event != NULL &&
1179 gtk_tree_view_get_path_at_pos (multiattrib->treeview,
1180 (gint)event->x,
1181 (gint)event->y,
1182 &path, NULL, NULL, NULL)) {
1183 GtkTreeSelection *selection;
1184 selection = gtk_tree_view_get_selection (multiattrib->treeview);
1185 gtk_tree_selection_unselect_all (selection);
1186 gtk_tree_selection_select_path (selection, path);
1187 gtk_tree_path_free (path);
1190 /* create the context menu */
1191 menu = gtk_menu_new();
1192 for (tmp = menuitems; tmp->label != NULL; tmp++) {
1193 GtkWidget *menuitem;
1194 if (g_strcasecmp (tmp->label, "-") == 0) {
1195 menuitem = gtk_separator_menu_item_new ();
1196 } else {
1197 menuitem = gtk_menu_item_new_with_label (_(tmp->label));
1198 g_signal_connect (menuitem,
1199 "activate",
1200 tmp->callback,
1201 multiattrib);
1203 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
1205 gtk_widget_show_all (menu);
1206 /* make menu a popup menu */
1207 gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL,
1208 (event != NULL) ? event->button : 0,
1209 gdk_event_get_time ((GdkEvent*)event));
1213 /*! \todo Finish function documentation
1214 * \brief
1215 * \par Function Description
1218 GType multiattrib_get_type()
1220 static GType multiattrib_type = 0;
1222 if (!multiattrib_type) {
1223 static const GTypeInfo multiattrib_info = {
1224 sizeof(MultiattribClass),
1225 NULL, /* base_init */
1226 NULL, /* base_finalize */
1227 (GClassInitFunc) multiattrib_class_init,
1228 NULL, /* class_finalize */
1229 NULL, /* class_data */
1230 sizeof(Multiattrib),
1231 0, /* n_preallocs */
1232 (GInstanceInitFunc) multiattrib_init,
1235 multiattrib_type = g_type_register_static (GSCHEM_TYPE_DIALOG,
1236 "Multiattrib",
1237 &multiattrib_info, 0);
1240 return multiattrib_type;
1243 /*! \todo Finish function documentation
1244 * \brief
1245 * \par Function Description
1248 static void multiattrib_class_init(MultiattribClass *klass)
1250 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
1252 gobject_class->set_property = multiattrib_set_property;
1253 gobject_class->get_property = multiattrib_get_property;
1255 g_object_class_install_property (
1256 gobject_class, PROP_OBJECT,
1257 g_param_spec_pointer ("object",
1260 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
1264 /*! \todo Finish function documentation
1265 * \brief
1266 * \par Function Description
1269 static void multiattrib_init(Multiattrib *multiattrib)
1271 GtkWidget *frame, *label, *scrolled_win, *treeview;
1272 GtkWidget *table, *textview, *combo, *optionm, *button;
1273 GtkTreeModel *store;
1274 GtkCellRenderer *renderer;
1275 GtkTreeViewColumn *column;
1276 GtkTreeSelection *selection;
1278 /* dialog initialization */
1279 g_object_set (G_OBJECT (multiattrib),
1280 /* GtkContainer */
1281 "border-width", 0,
1282 /* GtkWindow */
1283 "type", GTK_WINDOW_TOPLEVEL,
1284 "title", _("Edit Attributes"),
1285 "default-width", 320,
1286 "default-height", 350,
1287 "modal", TRUE,
1288 "window-position", GTK_WIN_POS_MOUSE,
1289 "allow-grow", TRUE,
1290 "allow-shrink", FALSE,
1291 /* GtkDialog */
1292 "has-separator", TRUE,
1293 NULL);
1295 multiattrib->object = NULL;
1297 /* create the attribute list frame */
1298 frame = GTK_WIDGET (g_object_new (GTK_TYPE_FRAME,
1299 /* GtkFrame */
1300 "label", _("Attributes"),
1301 NULL));
1302 /* - create the model for the treeview */
1303 store = (GtkTreeModel*)gtk_list_store_new (NUM_COLUMNS,
1304 G_TYPE_POINTER); /* attribute */
1305 /* - create a scrolled window for the treeview */
1306 scrolled_win = GTK_WIDGET (
1307 g_object_new (GTK_TYPE_SCROLLED_WINDOW,
1308 /* GtkContainer */
1309 "border-width", 3,
1310 /* GtkScrolledWindow */
1311 "hscrollbar-policy",
1312 GTK_POLICY_AUTOMATIC,
1313 "vscrollbar-policy",
1314 GTK_POLICY_AUTOMATIC,
1315 "shadow-type",
1316 GTK_SHADOW_ETCHED_IN,
1317 NULL));
1318 /* - create the treeview */
1319 treeview = GTK_WIDGET (g_object_new (GTK_TYPE_TREE_VIEW,
1320 /* GtkTreeView */
1321 "model", store,
1322 "rules-hint", TRUE,
1323 NULL));
1324 g_signal_connect (treeview,
1325 "key-press-event",
1326 G_CALLBACK (multiattrib_callback_key_pressed),
1327 multiattrib);
1328 g_signal_connect (treeview,
1329 "button-press-event",
1330 G_CALLBACK (multiattrib_callback_button_pressed),
1331 multiattrib);
1332 g_signal_connect (treeview,
1333 "popup-menu",
1334 G_CALLBACK (multiattrib_callback_popup_menu),
1335 multiattrib);
1336 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
1337 gtk_tree_selection_set_mode (selection,
1338 GTK_SELECTION_SINGLE);
1340 /* - and now the columns of the treeview */
1341 /* - column 1: attribute name */
1342 renderer = GTK_CELL_RENDERER (
1343 g_object_new (GTK_TYPE_CELL_RENDERER_TEXT,
1344 /* GtkCellRendererText */
1345 "editable", TRUE,
1346 /* unknown in GTK 2.4 */
1347 /* "ellipsize",
1348 * PANGO_ELLIPSIZE_END, */
1349 NULL));
1350 g_signal_connect (renderer,
1351 "edited",
1352 G_CALLBACK (multiattrib_callback_edited_name),
1353 multiattrib);
1354 column = GTK_TREE_VIEW_COLUMN (
1355 g_object_new (GTK_TYPE_TREE_VIEW_COLUMN,
1356 /* GtkTreeViewColumn */
1357 "title", _("Name"),
1358 "min-width", 100,
1359 "resizable", TRUE,
1360 NULL));
1361 gtk_tree_view_column_pack_start (column, renderer, TRUE);
1362 gtk_tree_view_column_set_cell_data_func (column, renderer,
1363 multiattrib_column_set_data_name,
1364 NULL, NULL);
1365 gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
1366 /* - column 2: attribute value */
1367 renderer = GTK_CELL_RENDERER (
1368 g_object_new (TYPE_CELL_RENDERER_MULTI_LINE_TEXT,
1369 /* GtkCellRendererText */
1370 "editable", TRUE,
1371 /* unknown in GTK 2.4 */
1372 /* "ellipsize",
1373 PANGO_ELLIPSIZE_END, */
1374 NULL));
1375 g_signal_connect (renderer,
1376 "edited",
1377 G_CALLBACK (multiattrib_callback_edited_value),
1378 multiattrib);
1379 column = GTK_TREE_VIEW_COLUMN (
1380 g_object_new (GTK_TYPE_TREE_VIEW_COLUMN,
1381 /* GtkTreeViewColumn */
1382 "title", _("Value"),
1383 "min-width", 140,
1384 "resizable", TRUE,
1385 NULL));
1386 gtk_tree_view_column_pack_start (column, renderer, TRUE);
1387 gtk_tree_view_column_set_cell_data_func (column, renderer,
1388 multiattrib_column_set_data_value,
1389 NULL, NULL);
1390 gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
1391 /* - column 3: visibility */
1392 renderer = GTK_CELL_RENDERER (
1393 g_object_new (GTK_TYPE_CELL_RENDERER_TOGGLE,
1394 /* GtkCellRendererToggle */
1395 "activatable", TRUE,
1396 NULL));
1397 g_signal_connect (renderer,
1398 "toggled",
1399 G_CALLBACK (multiattrib_callback_toggled_visible),
1400 multiattrib);
1401 column = GTK_TREE_VIEW_COLUMN (
1402 g_object_new (GTK_TYPE_TREE_VIEW_COLUMN,
1403 /* GtkTreeViewColumn */
1404 "title", _("Vis?"),
1405 NULL));
1406 gtk_tree_view_column_pack_start (column, renderer, TRUE);
1407 gtk_tree_view_column_set_cell_data_func (column, renderer,
1408 multiattrib_column_set_data_visible,
1409 NULL, NULL);
1410 gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
1411 /* - column 4: show name */
1412 renderer = GTK_CELL_RENDERER (
1413 g_object_new (GTK_TYPE_CELL_RENDERER_TOGGLE,
1414 /* GtkCellRendererToggle */
1415 "activatable", TRUE,
1416 NULL));
1417 g_signal_connect (renderer,
1418 "toggled",
1419 G_CALLBACK (multiattrib_callback_toggled_show_name),
1420 multiattrib);
1421 column = GTK_TREE_VIEW_COLUMN (
1422 g_object_new (GTK_TYPE_TREE_VIEW_COLUMN,
1423 /* GtkTreeViewColumn */
1424 "title", _("N"),
1425 NULL));
1426 gtk_tree_view_column_pack_start (column, renderer, TRUE);
1427 gtk_tree_view_column_set_cell_data_func (column, renderer,
1428 multiattrib_column_set_data_show_name,
1429 NULL, NULL);
1430 gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
1431 /* - column 5: show value */
1432 renderer = GTK_CELL_RENDERER (
1433 g_object_new (GTK_TYPE_CELL_RENDERER_TOGGLE,
1434 /* GtkCellRendererToggle */
1435 "activatable", TRUE,
1436 NULL));
1437 g_signal_connect (renderer,
1438 "toggled",
1439 G_CALLBACK (multiattrib_callback_toggled_show_value),
1440 multiattrib);
1441 column = GTK_TREE_VIEW_COLUMN (
1442 g_object_new (GTK_TYPE_TREE_VIEW_COLUMN,
1443 /* GtkTreeViewColumn */
1444 "title", _("V"),
1445 NULL));
1446 gtk_tree_view_column_pack_start (column, renderer, TRUE);
1447 gtk_tree_view_column_set_cell_data_func (column, renderer,
1448 multiattrib_column_set_data_show_value,
1449 NULL, NULL);
1450 gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
1452 /* add the treeview to the scrolled window */
1453 gtk_container_add (GTK_CONTAINER (scrolled_win), treeview);
1454 /* set treeview of multiattrib */
1455 multiattrib->treeview = GTK_TREE_VIEW (treeview);
1456 /* add the scrolled window to frame */
1457 gtk_container_add (GTK_CONTAINER (frame), scrolled_win);
1458 /* pack the frame */
1459 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (multiattrib)->vbox), frame,
1460 TRUE, TRUE, 1);
1461 gtk_widget_show_all (frame);
1463 /* create the add/edit frame */
1464 frame = GTK_WIDGET (g_object_new (GTK_TYPE_FRAME,
1465 "label", _("Add Attribute"),
1466 NULL));
1467 table = GTK_WIDGET (g_object_new (GTK_TYPE_TABLE,
1468 /* GtkTable */
1469 "n-rows", 4,
1470 "n-columns", 2,
1471 "homogeneous", FALSE,
1472 NULL));
1474 /* - the name entry: a GtkComboBoxEntry */
1475 label = GTK_WIDGET (g_object_new (GTK_TYPE_LABEL,
1476 /* GtkMisc */
1477 "xalign", 0.0,
1478 "yalign", 0.5,
1479 /* GtkLabel */
1480 "label", _("Name:"),
1481 NULL));
1482 combo = GTK_WIDGET (g_object_new (GTK_TYPE_COMBO,
1483 /* GtkCombo */
1484 "value-in-list", FALSE,
1485 NULL));
1486 multiattrib_init_attrib_names (GTK_COMBO (combo));
1487 multiattrib->combo_name = GTK_COMBO (combo);
1488 gtk_table_attach (GTK_TABLE (table), label,
1489 0, 1, 0, 1, 0, 0, 0, 0);
1490 gtk_table_attach (GTK_TABLE (table), combo,
1491 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, 0, 6, 3);
1493 /* - the value entry: a GtkEntry */
1494 label = GTK_WIDGET (g_object_new (GTK_TYPE_LABEL,
1495 /* GtkMisc */
1496 "xalign", 0.0,
1497 "yalign", 0.5,
1498 /* GtkLabel */
1499 "label", _("Value:"),
1500 NULL));
1501 scrolled_win = GTK_WIDGET (
1502 g_object_new (GTK_TYPE_SCROLLED_WINDOW,
1503 /* GtkScrolledWindow */
1504 "hscrollbar-policy",
1505 GTK_POLICY_NEVER,
1506 "vscrollbar-policy",
1507 GTK_POLICY_AUTOMATIC,
1508 "shadow-type",
1509 GTK_SHADOW_IN,
1510 NULL));
1511 textview = GTK_WIDGET (g_object_new (GTK_TYPE_TEXT_VIEW,
1512 NULL));
1513 g_signal_connect (textview,
1514 "key_press_event",
1515 G_CALLBACK (multiattrib_callback_value_key_pressed),
1516 multiattrib);
1517 gtk_container_add (GTK_CONTAINER (scrolled_win), textview);
1518 multiattrib->textview_value = GTK_TEXT_VIEW (textview);
1519 gtk_table_attach (GTK_TABLE (table), label,
1520 0, 1, 1, 2, 0, 0, 0, 0);
1521 gtk_table_attach (GTK_TABLE (table), scrolled_win,
1522 1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 6, 3);
1524 /* - the visible status */
1525 button = GTK_WIDGET (g_object_new (GTK_TYPE_CHECK_BUTTON,
1526 /* GtkButton */
1527 "label", _("Visible"),
1528 "active", TRUE,
1529 NULL));
1530 multiattrib->button_visible = GTK_CHECK_BUTTON (button);
1531 gtk_table_attach (GTK_TABLE (table), button,
1532 0, 1, 2, 3, GTK_FILL, 0, 3, 0);
1534 /* - the visibility type */
1535 optionm = GTK_WIDGET (g_object_new (GTK_TYPE_OPTION_MENU,
1536 NULL));
1537 multiattrib_init_visible_types (GTK_OPTION_MENU (optionm));
1538 multiattrib->optionmenu_shownv = GTK_OPTION_MENU (optionm);
1539 gtk_table_attach (GTK_TABLE (table), optionm,
1540 1, 2, 2, 3, GTK_EXPAND | GTK_FILL, 0, 6, 3);
1541 gtk_widget_show_all (table);
1543 /* create the add button */
1544 button = gtk_button_new_from_stock (GTK_STOCK_ADD);
1545 g_signal_connect (button,
1546 "clicked",
1547 G_CALLBACK (multiattrib_callback_button_add),
1548 multiattrib);
1549 gtk_table_attach (GTK_TABLE (table), button,
1550 2, 3, 0, 3, 0, 0, 6, 3);
1552 /* add the table to the frame */
1553 gtk_container_add (GTK_CONTAINER (frame), table);
1554 /* pack the frame in the dialog */
1555 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (multiattrib)->vbox), frame,
1556 FALSE, TRUE, 4);
1557 gtk_widget_show_all (frame);
1560 /* now add the close button to the action area */
1561 gtk_dialog_add_button (GTK_DIALOG (multiattrib),
1562 GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE);
1566 /*! \todo Finish function documentation
1567 * \brief
1568 * \par Function Description
1571 static void multiattrib_set_property (GObject *object,
1572 guint property_id,
1573 const GValue *value,
1574 GParamSpec *pspec)
1576 Multiattrib *multiattrib = MULTIATTRIB (object);
1578 switch(property_id) {
1579 case PROP_OBJECT:
1580 multiattrib->object = (OBJECT*)g_value_get_pointer (value);
1581 multiattrib_update (multiattrib);
1582 break;
1583 default:
1584 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1589 /*! \todo Finish function documentation
1590 * \brief
1591 * \par Function Description
1594 static void multiattrib_get_property (GObject *object,
1595 guint property_id,
1596 GValue *value,
1597 GParamSpec *pspec)
1599 Multiattrib *multiattrib = MULTIATTRIB (object);
1601 switch(property_id) {
1602 case PROP_OBJECT:
1603 g_value_set_pointer (value, (gpointer)multiattrib->object);
1604 break;
1605 default:
1606 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1611 /*! \todo Finish function documentation
1612 * \brief
1613 * \par Function Description
1616 void multiattrib_update (Multiattrib *multiattrib)
1618 GtkListStore *liststore;
1619 GtkTreeIter iter;
1620 OBJECT **object_attribs, *o_current;
1621 gint i;
1623 if (GSCHEM_DIALOG (multiattrib)->toplevel == NULL ||
1624 multiattrib->object == NULL) {
1625 /* we can not do anything until both toplevel and object are set */
1626 return;
1629 liststore = (GtkListStore*)gtk_tree_view_get_model (multiattrib->treeview);
1631 /* clear the list of attributes */
1632 gtk_list_store_clear (liststore);
1634 /* get list of attributes */
1635 object_attribs = o_attrib_return_attribs (
1636 GSCHEM_DIALOG (multiattrib)->toplevel->page_current->object_head,
1637 multiattrib->object);
1638 /* populate the store with attributes */
1639 if (object_attribs) {
1640 for (i = 0, o_current = object_attribs[i];
1641 o_current != NULL;
1642 i++, o_current = object_attribs[i]) {
1643 gtk_list_store_append (liststore, &iter);
1644 gtk_list_store_set (liststore, &iter,
1645 COLUMN_ATTRIBUTE, o_current,
1646 -1);
1649 /* delete the list of attribute objects */
1650 o_attrib_free_returned (object_attribs);