1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
3 * Copyright (C) 2006 Armin Burgmeier
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Library General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 #include "combo-flags.h"
22 #include <gtk/gtktreeview.h>
23 #include <gtk/gtktreeselection.h>
24 #include <gtk/gtkcelllayout.h>
25 #include <gtk/gtkcellrenderer.h>
26 #include <gtk/gtkscrolledwindow.h>
27 #include <gtk/gtkframe.h>
28 #include <gtk/gtkwindow.h>
29 #include <gtk/gtkmain.h>
31 #include <gdk/gdkkeysyms.h>
33 #include <libanjuta/anjuta-marshal.h>
35 typedef struct _CgComboFlagsCellInfo CgComboFlagsCellInfo
;
36 struct _CgComboFlagsCellInfo
38 GtkCellRenderer
*cell
;
41 GtkCellLayoutDataFunc func
;
43 GDestroyNotify destroy
;
49 typedef struct _CgComboFlagsPrivate CgComboFlagsPrivate
;
50 struct _CgComboFlagsPrivate
56 GtkTreeViewColumn
* column
;
60 gboolean editing_started
;
61 gboolean editing_canceled
;
64 #define CG_COMBO_FLAGS_PRIVATE(o) \
65 (G_TYPE_INSTANCE_GET_PRIVATE( \
67 CG_TYPE_COMBO_FLAGS, \
81 static GtkHBoxClass
* parent_class
= NULL
;
82 static guint combo_flags_signals
[LAST_SIGNAL
];
84 static CgComboFlagsCellInfo
*
85 cg_combo_flags_get_cell_info (CgComboFlags
*combo
,
86 GtkCellRenderer
*cell
)
88 CgComboFlagsPrivate
*priv
;
91 priv
= CG_COMBO_FLAGS_PRIVATE (combo
);
92 for (i
= priv
->cells
; i
!= NULL
; i
= i
->next
)
94 CgComboFlagsCellInfo
*info
= (CgComboFlagsCellInfo
*) i
->data
;
96 if (info
!= NULL
&& info
->cell
== cell
)
104 cg_combo_flags_cell_layout_pack_start (GtkCellLayout
*layout
,
105 GtkCellRenderer
*cell
,
109 CgComboFlagsPrivate
*priv
;
110 CgComboFlagsCellInfo
*info
;
112 combo
= CG_COMBO_FLAGS (layout
);
113 priv
= CG_COMBO_FLAGS_PRIVATE (combo
);
116 gtk_object_sink (GTK_OBJECT (cell
));
118 info
= g_new0 (CgComboFlagsCellInfo
, 1);
120 info
->expand
= expand
;
121 info
->pack
= GTK_PACK_START
;
123 priv
->cells
= g_slist_append (priv
->cells
, info
);
125 if (priv
->column
!= NULL
)
126 gtk_tree_view_column_pack_start (priv
->column
, cell
, expand
);
130 cg_combo_flags_cell_layout_pack_end (GtkCellLayout
*layout
,
131 GtkCellRenderer
*cell
,
135 CgComboFlagsPrivate
*priv
;
136 CgComboFlagsCellInfo
*info
;
138 combo
= CG_COMBO_FLAGS (layout
);
139 priv
= CG_COMBO_FLAGS_PRIVATE (combo
);
142 gtk_object_sink (GTK_OBJECT (cell
));
144 info
= g_new0 (CgComboFlagsCellInfo
, 1);
146 info
->expand
= expand
;
147 info
->pack
= GTK_PACK_END
;
149 priv
->cells
= g_slist_append (priv
->cells
, info
);
151 if (priv
->column
!= NULL
)
152 gtk_tree_view_column_pack_end (priv
->column
, cell
, expand
);
156 cg_combo_flags_cell_layout_clear_attributes (GtkCellLayout
*layout
,
157 GtkCellRenderer
*cell
)
160 CgComboFlagsPrivate
*priv
;
161 CgComboFlagsCellInfo
*info
;
164 combo
= CG_COMBO_FLAGS (layout
);
165 priv
= CG_COMBO_FLAGS_PRIVATE (combo
);
167 info
= cg_combo_flags_get_cell_info (combo
, cell
);
168 g_return_if_fail (info
!= NULL
);
170 list
= info
->attributes
;
171 while (list
&& list
->next
)
174 list
= list
->next
->next
;
177 g_slist_free (info
->attributes
);
178 info
->attributes
= NULL
;
180 if (priv
->column
!= NULL
)
182 gtk_cell_layout_clear_attributes (GTK_CELL_LAYOUT (priv
->column
),
186 gtk_widget_queue_resize (GTK_WIDGET (combo
));
190 cg_combo_flags_cell_layout_clear (GtkCellLayout
*layout
)
193 CgComboFlagsPrivate
*priv
;
196 combo
= CG_COMBO_FLAGS (layout
);
197 priv
= CG_COMBO_FLAGS_PRIVATE (combo
);
199 if (priv
->column
!= NULL
)
200 gtk_tree_view_column_clear (priv
->column
);
202 for (i
= priv
->cells
; i
; i
= i
->next
)
204 CgComboFlagsCellInfo
* info
= (CgComboFlagsCellInfo
*)i
->data
;
206 cg_combo_flags_cell_layout_clear_attributes (layout
, info
->cell
);
207 g_object_unref (info
->cell
);
212 g_slist_free (priv
->cells
);
217 cg_combo_flags_cell_layout_add_attribute (GtkCellLayout
*layout
,
218 GtkCellRenderer
*cell
,
219 const gchar
*attribute
,
223 CgComboFlagsPrivate
*priv
;
224 CgComboFlagsCellInfo
*info
;
226 combo
= CG_COMBO_FLAGS (layout
);
227 priv
= CG_COMBO_FLAGS_PRIVATE(combo
);
228 info
= cg_combo_flags_get_cell_info (combo
, cell
);
230 info
->attributes
= g_slist_prepend (info
->attributes
,
231 GINT_TO_POINTER (column
));
232 info
->attributes
= g_slist_prepend (info
->attributes
,
233 g_strdup (attribute
));
235 if (priv
->column
!= NULL
)
237 gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (priv
->column
),
238 cell
, attribute
, column
);
241 gtk_widget_queue_resize (GTK_WIDGET (combo
));
245 cg_combo_flags_cell_data_func (GtkCellLayout
*cell_layout
,
246 GtkCellRenderer
*cell
,
247 GtkTreeModel
*tree_model
,
251 CgComboFlagsCellInfo
*info
;
252 info
= (CgComboFlagsCellInfo
*) data
;
254 if (info
->func
== NULL
)
257 (*info
->func
) (cell_layout
, cell
, tree_model
, iter
, info
->func_data
);
261 cg_combo_flags_cell_layout_set_cell_data_func (GtkCellLayout
*layout
,
262 GtkCellRenderer
*cell
,
263 GtkCellLayoutDataFunc func
,
265 GDestroyNotify destroy
)
268 CgComboFlagsPrivate
*priv
;
269 CgComboFlagsCellInfo
*info
;
270 GDestroyNotify old_destroy
;
272 combo
= CG_COMBO_FLAGS (layout
);
273 priv
= CG_COMBO_FLAGS_PRIVATE (combo
);
274 info
= cg_combo_flags_get_cell_info (combo
, cell
);
275 g_return_if_fail (info
!= NULL
);
279 old_destroy
= info
->destroy
;
281 info
->destroy
= NULL
;
282 old_destroy (info
->func_data
);
286 info
->func_data
= func_data
;
287 info
->destroy
= destroy
;
289 if (priv
->column
!= NULL
)
291 gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (priv
->column
),
292 cell
, func
, func_data
, NULL
);
295 gtk_widget_queue_resize (GTK_WIDGET (combo
));
299 cg_combo_flags_cell_layout_reorder (GtkCellLayout
*layout
,
300 GtkCellRenderer
*cell
,
304 CgComboFlagsPrivate
*priv
;
305 CgComboFlagsCellInfo
*info
;
308 combo
= CG_COMBO_FLAGS (layout
);
309 priv
= CG_COMBO_FLAGS_PRIVATE (combo
);
311 info
= cg_combo_flags_get_cell_info (combo
, cell
);
312 g_return_if_fail (info
!= NULL
);
314 link
= g_slist_find (priv
->cells
, info
);
315 g_return_if_fail (link
!= NULL
);
317 priv
->cells
= g_slist_remove_link (priv
->cells
, link
);
318 priv
->cells
= g_slist_insert (priv
->cells
, info
, position
);
320 if (priv
->column
!= NULL
)
321 gtk_cell_layout_reorder (GTK_CELL_LAYOUT (priv
->column
), cell
, position
);
323 gtk_widget_queue_draw (GTK_WIDGET (combo
));
327 cg_combo_flags_cell_editable_start_editing (GtkCellEditable
*cell_editable
,
328 G_GNUC_UNUSED GdkEvent
*event
)
331 CgComboFlagsPrivate
*priv
;
333 combo
= CG_COMBO_FLAGS (cell_editable
);
334 priv
= CG_COMBO_FLAGS_PRIVATE (combo
);
336 priv
->editing_started
= TRUE
;
337 gtk_widget_grab_focus (GTK_WIDGET (combo
));
338 cg_combo_flags_popup (combo
);
342 cg_combo_flags_sync_cells (CgComboFlags
*combo
,
343 GtkCellLayout
*cell_layout
)
345 CgComboFlagsPrivate
*priv
;
346 CgComboFlagsCellInfo
*info
;
350 priv
= CG_COMBO_FLAGS_PRIVATE (combo
);
351 for (k
= priv
->cells
; k
!= NULL
; k
= k
->next
)
353 info
= (CgComboFlagsCellInfo
*) k
->data
;
355 if (info
->pack
== GTK_PACK_START
)
356 gtk_cell_layout_pack_start (cell_layout
, info
->cell
, info
->expand
);
357 else if (info
->pack
== GTK_PACK_END
)
358 gtk_cell_layout_pack_end (cell_layout
, info
->cell
, info
->expand
);
360 gtk_cell_layout_set_cell_data_func (cell_layout
, info
->cell
,
361 cg_combo_flags_cell_data_func
,
364 for (j
= info
->attributes
; j
!= NULL
; j
= j
->next
->next
)
366 gtk_cell_layout_add_attribute (cell_layout
, info
->cell
, j
->data
,
367 GPOINTER_TO_INT (j
->next
->data
));
373 cg_combo_flags_get_position (CgComboFlags
*combo
,
379 CgComboFlagsPrivate
*priv
;
382 GdkRectangle monitor
;
383 GtkRequisition popup_req
;
385 priv
= CG_COMBO_FLAGS_PRIVATE (combo
);
387 g_assert (priv
->window
!= NULL
);
389 gdk_window_get_origin (GTK_WIDGET (combo
)->window
, x
, y
);
391 if (GTK_WIDGET_NO_WINDOW (GTK_WIDGET (combo
)))
393 *x
+= GTK_WIDGET (combo
)->allocation
.x
;
394 *y
+= GTK_WIDGET (combo
)->allocation
.y
;
397 gtk_widget_size_request (priv
->window
, &popup_req
);
399 *width
= GTK_WIDGET (combo
)->allocation
.width
;
400 if (popup_req
.width
> *width
) *width
= popup_req
.width
;
401 *height
= popup_req
.height
;
403 screen
= gtk_widget_get_screen (GTK_WIDGET(combo
));
405 gdk_screen_get_monitor_at_window (screen
, GTK_WIDGET (combo
)->window
);
407 gdk_screen_get_monitor_geometry (screen
, monitor_num
, &monitor
);
413 else if (*x
+ *width
> monitor
.x
+ monitor
.width
)
415 *x
= monitor
.x
+ monitor
.width
- *width
;
418 if (*y
+ GTK_WIDGET (combo
)->allocation
.height
+ *height
<=
419 monitor
.y
+ monitor
.height
)
421 *y
+= GTK_WIDGET (combo
)->allocation
.height
;
423 else if (*y
- *height
>= monitor
.y
)
427 else if (monitor
.y
+ monitor
.height
-
428 (*y
+ GTK_WIDGET (combo
)->allocation
.height
) > *y
- monitor
.y
)
430 *y
+= GTK_WIDGET (combo
)->allocation
.height
;
431 *height
= monitor
.y
+ monitor
.height
- *y
;
435 *height
= *y
- monitor
.y
;
441 cg_combo_flags_treeview_button_press_cb (G_GNUC_UNUSED GtkWidget
*widget
,
442 GdkEventButton
*event
,
446 CgComboFlagsPrivate
*priv
;
447 GtkTreeSelection
*selection
;
450 combo
= CG_COMBO_FLAGS(data
);
451 priv
= CG_COMBO_FLAGS_PRIVATE(combo
);
453 switch (event
->button
)
457 gtk_tree_view_get_selection (GTK_TREE_VIEW (priv
->treeview
));
459 if(gtk_tree_selection_get_selected (selection
, NULL
, &iter
) == TRUE
)
461 g_signal_emit (G_OBJECT (combo
), combo_flags_signals
[SELECTED
],
462 0, &iter
, CG_COMBO_FLAGS_SELECTION_TOGGLE
);
470 priv
->editing_canceled
= FALSE
;
471 cg_combo_flags_popdown (combo
);
481 cg_combo_flags_treeview_key_press_cb (G_GNUC_UNUSED GtkWidget
*widget
,
486 CgComboFlagsPrivate
*priv
;
487 GtkTreeSelection
*selection
;
490 combo
= CG_COMBO_FLAGS (data
);
491 priv
= CG_COMBO_FLAGS_PRIVATE (combo
);
493 switch (event
->keyval
)
498 gtk_tree_view_get_selection (GTK_TREE_VIEW (priv
->treeview
));
500 if(gtk_tree_selection_get_selected (selection
, NULL
, &iter
) == TRUE
)
502 g_signal_emit (G_OBJECT (combo
), combo_flags_signals
[SELECTED
],
503 0, &iter
, CG_COMBO_FLAGS_SELECTION_TOGGLE
);
513 gtk_tree_view_get_selection (GTK_TREE_VIEW (priv
->treeview
));
515 if(gtk_tree_selection_get_selected (selection
, NULL
, &iter
) == TRUE
)
517 g_signal_emit (G_OBJECT (combo
), combo_flags_signals
[SELECTED
],
518 0, &iter
, CG_COMBO_FLAGS_SELECTION_SELECT
);
521 priv
->editing_canceled
= FALSE
;
522 cg_combo_flags_popdown (combo
);
532 cg_combo_flags_window_button_press_cb (G_GNUC_UNUSED GtkWidget
*widget
,
533 G_GNUC_UNUSED GdkEventButton
*event
,
536 /* Probably the mouse clicked somewhere else but not into the window,
537 * otherwise the treeview would have received the event. */
539 CgComboFlagsPrivate
*priv
;
541 combo
= CG_COMBO_FLAGS (data
);
542 priv
= CG_COMBO_FLAGS_PRIVATE (combo
);
544 priv
->editing_canceled
= FALSE
;
545 cg_combo_flags_popdown (combo
);
551 cg_combo_flags_window_key_press_cb (G_GNUC_UNUSED GtkWidget
*widget
,
556 CgComboFlagsPrivate
*priv
;
558 combo
= CG_COMBO_FLAGS (data
);
559 priv
= CG_COMBO_FLAGS_PRIVATE (combo
);
561 switch (event
->keyval
)
564 priv
->editing_canceled
= TRUE
;
565 cg_combo_flags_popdown (combo
);
575 cg_combo_flags_init (CgComboFlags
*combo_flags
)
577 CgComboFlagsPrivate
*priv
;
578 priv
= CG_COMBO_FLAGS_PRIVATE (combo_flags
);
582 priv
->treeview
= NULL
;
586 priv
->editing_started
= FALSE
;
587 priv
->editing_canceled
= FALSE
;
591 cg_combo_flags_finalize (GObject
*object
)
593 CgComboFlags
*combo_flags
;
594 CgComboFlagsPrivate
*priv
;
596 combo_flags
= CG_COMBO_FLAGS (object
);
597 priv
= CG_COMBO_FLAGS_PRIVATE (combo_flags
);
599 if (priv
->window
!= NULL
)
600 cg_combo_flags_popdown (combo_flags
);
602 G_OBJECT_CLASS (parent_class
)->finalize (object
);
606 cg_combo_flags_set_property (GObject
*object
,
611 CgComboFlags
*combo_flags
;
612 CgComboFlagsPrivate
*priv
;
614 g_return_if_fail(CG_IS_COMBO_FLAGS (object
));
616 combo_flags
= CG_COMBO_FLAGS (object
);
617 priv
= CG_COMBO_FLAGS_PRIVATE (combo_flags
);
622 if (priv
->model
!= NULL
) g_object_unref (G_OBJECT (priv
->model
));
623 priv
->model
= GTK_TREE_MODEL (g_value_dup_object (value
));
625 if (priv
->treeview
!= NULL
)
627 gtk_tree_view_set_model (GTK_TREE_VIEW (priv
->treeview
),
633 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
639 cg_combo_flags_get_property (GObject
*object
,
644 CgComboFlags
*combo_flags
;
645 CgComboFlagsPrivate
*priv
;
647 g_return_if_fail (CG_IS_COMBO_FLAGS (object
));
649 combo_flags
= CG_COMBO_FLAGS (object
);
650 priv
= CG_COMBO_FLAGS_PRIVATE (combo_flags
);
655 g_value_set_object (value
, G_OBJECT (priv
->model
));
658 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
664 cg_combo_flags_class_init (CgComboFlagsClass
*klass
)
666 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
667 parent_class
= g_type_class_peek_parent (klass
);
669 g_type_class_add_private (klass
, sizeof (CgComboFlagsPrivate
));
671 object_class
->finalize
= cg_combo_flags_finalize
;
672 object_class
->set_property
= cg_combo_flags_set_property
;
673 object_class
->get_property
= cg_combo_flags_get_property
;
675 g_object_class_install_property(object_class
,
677 g_param_spec_object("model",
679 "The model used by the CgComboFlags widget",
683 combo_flags_signals
[SELECTED
] =
684 g_signal_new("selected",
685 G_OBJECT_CLASS_TYPE(object_class
),
687 0, /* no default handler */
689 anjuta_cclosure_marshal_VOID__BOXED_ENUM
,
693 CG_TYPE_COMBO_FLAGS_SELECTION_TYPE
);
697 cg_combo_flags_cell_layout_init (GtkCellLayoutIface
*iface
)
699 iface
->pack_start
= cg_combo_flags_cell_layout_pack_start
;
700 iface
->pack_end
= cg_combo_flags_cell_layout_pack_end
;
701 iface
->reorder
= cg_combo_flags_cell_layout_reorder
;
702 iface
->clear
= cg_combo_flags_cell_layout_clear
;
703 iface
->add_attribute
= cg_combo_flags_cell_layout_add_attribute
;
704 iface
->set_cell_data_func
= cg_combo_flags_cell_layout_set_cell_data_func
;
705 iface
->clear_attributes
= cg_combo_flags_cell_layout_clear_attributes
;
709 cg_combo_flags_cell_editable_init (GtkCellEditableIface
*iface
)
711 iface
->start_editing
= cg_combo_flags_cell_editable_start_editing
;
715 cg_combo_flags_popup_idle (gpointer data
)
718 CgComboFlagsPrivate
*priv
;
719 GtkTreeSelection
* selection
;
722 gint height
, width
, x
, y
;
724 combo
= CG_COMBO_FLAGS (data
);
725 priv
= CG_COMBO_FLAGS_PRIVATE (combo
);
727 g_assert (priv
->window
== NULL
);
728 priv
->window
= gtk_window_new (GTK_WINDOW_POPUP
);
730 g_object_ref (G_OBJECT (priv
->window
));
731 gtk_window_set_resizable (GTK_WINDOW (priv
->window
), FALSE
);
733 g_signal_connect (G_OBJECT (priv
->window
), "key_press_event",
734 G_CALLBACK (cg_combo_flags_window_key_press_cb
),
737 g_signal_connect (G_OBJECT (priv
->window
), "button_press_event",
738 G_CALLBACK (cg_combo_flags_window_button_press_cb
),
741 scrolled
= gtk_scrolled_window_new (NULL
, NULL
);
742 gtk_container_add (GTK_CONTAINER (priv
->window
), scrolled
);
744 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled
),
745 GTK_SHADOW_ETCHED_IN
);
747 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled
),
748 GTK_POLICY_NEVER
, GTK_POLICY_NEVER
);
750 gtk_widget_show (scrolled
);
752 priv
->treeview
= gtk_tree_view_new_with_model (priv
->model
);
753 gtk_widget_show (priv
->treeview
);
754 gtk_container_add (GTK_CONTAINER (scrolled
), priv
->treeview
);
756 g_signal_connect (G_OBJECT (priv
->treeview
), "key_press_event",
757 G_CALLBACK (cg_combo_flags_treeview_key_press_cb
),
760 g_signal_connect (G_OBJECT (priv
->treeview
), "button_press_event",
761 G_CALLBACK (cg_combo_flags_treeview_button_press_cb
),
764 priv
->column
= gtk_tree_view_column_new ();
765 g_object_ref (G_OBJECT (priv
->column
));
766 cg_combo_flags_sync_cells (combo
, GTK_CELL_LAYOUT (priv
->column
));
767 gtk_tree_view_append_column (GTK_TREE_VIEW (priv
->treeview
), priv
->column
);
769 selection
= gtk_tree_view_get_selection (GTK_TREE_VIEW (priv
->treeview
));
770 gtk_tree_selection_set_mode (selection
, GTK_SELECTION_BROWSE
);
772 gtk_tree_view_set_enable_search (GTK_TREE_VIEW (priv
->treeview
), FALSE
);
773 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (priv
->treeview
), FALSE
);
774 gtk_tree_view_set_hover_selection (GTK_TREE_VIEW (priv
->treeview
), TRUE
);
776 toplevel
= gtk_widget_get_toplevel (GTK_WIDGET (combo
));
777 if (GTK_IS_WINDOW (toplevel
))
779 gtk_window_group_add_window (gtk_window_get_group (
780 GTK_WINDOW (toplevel
)),
781 GTK_WINDOW (priv
->window
));
783 gtk_window_set_transient_for (GTK_WINDOW (priv
->window
),
784 GTK_WINDOW (toplevel
));
788 gtk_window_set_screen (GTK_WINDOW (priv
->window
),
789 gtk_widget_get_screen (GTK_WIDGET (combo
)));
791 cg_combo_flags_get_position (combo
, &x
, &y
, &width
, &height
);
792 gtk_widget_set_size_request (priv
->window
, width
, height
);
793 gtk_window_move (GTK_WINDOW(priv
->window
), x
, y
);
794 gtk_widget_show (priv
->window
);
796 gtk_widget_grab_focus (priv
->window
);
797 if (!GTK_WIDGET_HAS_FOCUS (priv
->treeview
))
798 gtk_widget_grab_focus (priv
->treeview
);
800 gdk_pointer_grab (priv
->window
->window
, TRUE
,
801 GDK_BUTTON_PRESS_MASK
| GDK_BUTTON_RELEASE_MASK
|
802 GDK_POINTER_MOTION_MASK
,
803 NULL
, NULL
, GDK_CURRENT_TIME
);
805 gtk_grab_add (priv
->window
);
807 gdk_keyboard_grab (priv
->window
->window
, TRUE
, GDK_CURRENT_TIME
);
812 cg_combo_flags_popdown_idle (gpointer data
)
814 gtk_widget_destroy (GTK_WIDGET (data
));
819 cg_combo_flags_selection_type_get_type (void)
821 static GType our_type
= 0;
825 static const GEnumValue values
[] =
827 { CG_COMBO_FLAGS_SELECTION_NONE
, "CG_COMBO_FLAGS_SELECTION_NONE", "none" },
828 { CG_COMBO_FLAGS_SELECTION_UNSELECT
, "CG_COMBO_FLAGS_SELECTION_UNSELECT", "unselect" },
829 { CG_COMBO_FLAGS_SELECTION_SELECT
, "CG_COMBO_FLAGS_SELECTION_SELECT", "select" },
830 { CG_COMBO_FLAGS_SELECTION_TOGGLE
, "CG_COMBO_FLAGS_SELECTION_TOGGLE", "toggle" },
834 our_type
= g_enum_register_static("CgComboFlagsSelectionType", values
);
841 cg_combo_flags_get_type (void)
843 static GType our_type
= 0;
847 static const GTypeInfo our_info
=
849 sizeof (CgComboFlagsClass
),
850 (GBaseInitFunc
) NULL
,
851 (GBaseFinalizeFunc
) NULL
,
852 (GClassInitFunc
) cg_combo_flags_class_init
,
855 sizeof (CgComboFlags
),
857 (GInstanceInitFunc
) cg_combo_flags_init
,
861 static const GInterfaceInfo cell_layout_info
=
863 (GInterfaceInitFunc
) cg_combo_flags_cell_layout_init
,
868 static const GInterfaceInfo cell_editable_info
=
870 (GInterfaceInitFunc
) cg_combo_flags_cell_editable_init
,
875 our_type
= g_type_register_static(GTK_TYPE_HBOX
, "CgComboFlags",
878 g_type_add_interface_static (our_type
, GTK_TYPE_CELL_LAYOUT
,
881 g_type_add_interface_static (our_type
, GTK_TYPE_CELL_EDITABLE
,
882 &cell_editable_info
);
889 cg_combo_flags_new (void)
892 object
= g_object_new (CG_TYPE_COMBO_FLAGS
, NULL
);
893 return GTK_WIDGET (object
);
897 cg_combo_flags_new_with_model (GtkTreeModel
*model
)
900 object
= g_object_new (CG_TYPE_COMBO_FLAGS
, "model", model
, NULL
);
901 return GTK_WIDGET (object
);
905 cg_combo_flags_popup(CgComboFlags
*combo
)
907 g_idle_add(cg_combo_flags_popup_idle
, combo
);
911 cg_combo_flags_popdown(CgComboFlags
*combo
)
913 CgComboFlagsPrivate
*priv
;
914 priv
= CG_COMBO_FLAGS_PRIVATE (combo
);
916 if (priv
->window
!= NULL
)
918 gtk_grab_remove (priv
->window
);
919 gdk_pointer_ungrab (GDK_CURRENT_TIME
);
920 gdk_keyboard_ungrab (GDK_CURRENT_TIME
);
921 gtk_widget_hide (priv
->window
);
923 g_object_unref (priv
->column
);
924 g_idle_add (cg_combo_flags_popdown_idle
, priv
->window
);
927 priv
->treeview
= NULL
;
930 if (priv
->editing_started
)
932 priv
->editing_started
= FALSE
;
933 gtk_cell_editable_editing_done (GTK_CELL_EDITABLE (combo
));
935 /* Seems like someone already calls _remove_widget when the
936 * cell renderer emits its edited signal (which we rely on if
937 * the editing was not canceled). */
938 if (priv
->editing_canceled
)
939 gtk_cell_editable_remove_widget (GTK_CELL_EDITABLE (combo
));
945 cg_combo_flags_editing_canceled (CgComboFlags
*combo
)
947 return CG_COMBO_FLAGS_PRIVATE (combo
)->editing_canceled
;