1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
3 /* egg-combo-action widget
5 * Copyright (C) Naba Kumar <naba@gnome.org>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of the
10 * License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public
18 * License along with this program; if not, write to the
19 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
22 #include <gtk/gtkwidget.h>
23 #include <libegg/menu/eggcomboselect.h>
24 #include "egg-combo-action.h"
30 struct _EggComboActionPriv
33 GtkTreeIter
*active_iter
;
44 static void egg_combo_action_init (EggComboAction
*action
);
45 static void egg_combo_action_class_init (EggComboActionClass
*class);
47 static GtkWidget
* create_tool_item (GtkAction
*action
);
48 static void connect_proxy (GtkAction
*action
,
50 static void disconnect_proxy (GtkAction
*action
,
52 static void egg_combo_action_finalize (GObject
*object
);
53 static void egg_combo_action_dispose (GObject
*object
);
54 static void egg_combo_action_update (EggComboAction
*combo
);
55 static void egg_combo_action_set_property (GObject
*object
,
59 static void egg_combo_action_get_property (GObject
*object
,
63 static void on_change (EggComboSelect
*combo
, EggComboAction
*action
);
65 static GObjectClass
*parent_class
= NULL
;
68 egg_combo_action_get_type (void)
70 static GtkType type
= 0;
74 static const GTypeInfo type_info
=
76 sizeof (EggComboActionClass
),
78 (GBaseFinalizeFunc
) NULL
,
79 (GClassInitFunc
) egg_combo_action_class_init
,
80 (GClassFinalizeFunc
) NULL
,
83 sizeof (EggComboAction
),
85 (GInstanceInitFunc
) egg_combo_action_init
,
88 type
= g_type_register_static (GTK_TYPE_ACTION
,
96 egg_combo_action_class_init (EggComboActionClass
*class)
98 GtkActionClass
*action_class
;
99 GObjectClass
*object_class
;
101 parent_class
= g_type_class_peek_parent (class);
102 action_class
= GTK_ACTION_CLASS (class);
103 object_class
= G_OBJECT_CLASS (class);
105 object_class
->finalize
= egg_combo_action_finalize
;
106 object_class
->dispose
= egg_combo_action_dispose
;
107 object_class
->set_property
= egg_combo_action_set_property
;
108 object_class
->get_property
= egg_combo_action_get_property
;
110 action_class
->connect_proxy
= connect_proxy
;
111 action_class
->disconnect_proxy
= disconnect_proxy
;
112 action_class
->menu_item_type
= GTK_TYPE_CHECK_MENU_ITEM
;
113 action_class
->toolbar_item_type
= GTK_TYPE_TOOL_ITEM
;
114 action_class
->create_tool_item
= create_tool_item
;
116 g_object_class_install_property (object_class
,
118 g_param_spec_pointer ("model",
120 _("Model for the combo box"),
123 g_object_class_install_property (object_class
,
125 g_param_spec_int ("width",
127 _("Width of the entry."),
133 egg_combo_action_init (EggComboAction
*action
)
135 action
->priv
= g_new0 (EggComboActionPriv
, 1);
136 action
->priv
->model
= NULL
;
137 action
->priv
->active_iter
= NULL
;
138 action
->priv
->width
= 100;
142 egg_combo_action_set_property (GObject
*object
,
147 EggComboAction
*action
;
149 action
= EGG_COMBO_ACTION (object
);
154 egg_combo_action_set_model (action
,
155 GTK_TREE_MODEL (g_value_get_pointer (value
)));
158 action
->priv
->width
= g_value_get_int (value
);
161 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
167 egg_combo_action_get_property (GObject
*object
,
172 EggComboAction
*action
;
174 action
= EGG_COMBO_ACTION (object
);
179 g_value_set_pointer (value
, action
->priv
->model
);
182 g_value_set_int (value
, action
->priv
->width
);
185 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
191 egg_combo_action_update (EggComboAction
*action
)
195 for (slist
= gtk_action_get_proxies (GTK_ACTION (action
));
196 slist
; slist
= slist
->next
)
198 GtkWidget
*proxy
= slist
->data
;
200 gtk_action_block_activate_from (GTK_ACTION (action
), proxy
);
201 if (GTK_IS_TOOL_ITEM (proxy
))
204 combo
= gtk_bin_get_child (GTK_BIN (proxy
));
205 if (EGG_IS_COMBO_SELECT (combo
))
207 g_signal_handlers_block_by_func (combo
,
208 G_CALLBACK (on_change
),
210 egg_combo_select_set_active (EGG_COMBO_SELECT (combo
),
211 action
->priv
->active_index
);
212 g_signal_handlers_unblock_by_func (combo
,
213 G_CALLBACK (on_change
),
218 g_warning ("Don't know how to change `%s' widgets",
219 G_OBJECT_TYPE_NAME (proxy
));
224 g_warning ("Don't know how to change `%s' widgets",
225 G_OBJECT_TYPE_NAME (proxy
));
227 gtk_action_unblock_activate_from (GTK_ACTION (action
), proxy
);
232 egg_combo_action_finalize (GObject
*object
)
234 if (EGG_COMBO_ACTION (object
)->priv
->active_iter
)
235 gtk_tree_iter_free (EGG_COMBO_ACTION (object
)->priv
->active_iter
);
236 g_free (EGG_COMBO_ACTION (object
)->priv
);
237 if (parent_class
->finalize
)
238 (* parent_class
->finalize
) (object
);
242 egg_combo_action_dispose (GObject
*object
)
244 EggComboActionPriv
*priv
;
246 priv
= EGG_COMBO_ACTION (object
)->priv
;
248 g_object_unref (priv
->model
);
250 if (parent_class
->dispose
)
251 (* parent_class
->dispose
) (object
);
255 on_change (EggComboSelect
*combo
, EggComboAction
*action
)
258 if (action
->priv
->active_iter
)
259 gtk_tree_iter_free (action
->priv
->active_iter
);
260 egg_combo_select_get_active_iter (combo
, &iter
);
261 action
->priv
->active_iter
= gtk_tree_iter_copy (&iter
);
262 action
->priv
->active_index
= egg_combo_select_get_active (combo
);
263 egg_combo_action_update (action
);
264 gtk_action_activate (GTK_ACTION (action
));
267 static GtkTreeModel
*
268 create_dummy_model ()
270 GtkTreeIter iter
, *parent
;
274 store
= gtk_tree_store_new (3, GDK_TYPE_PIXBUF
,
275 G_TYPE_STRING
, G_TYPE_INT
);
276 gtk_tree_store_append (store
, &iter
, NULL
);
277 gtk_tree_store_set (store
, &iter
,
278 1, "----------------------------",
280 return GTK_TREE_MODEL (store
);
284 create_tool_item (GtkAction
*action
)
288 GtkCellRenderer
*renderer
;
290 g_return_val_if_fail (EGG_IS_COMBO_ACTION (action
), NULL
);
291 /* g_message ("Creating combo toolitem"); */
292 item
= gtk_tool_item_new ();
293 combo
= egg_combo_select_new ();
294 egg_combo_select_set_title (EGG_COMBO_SELECT (combo
), _("Symbol"));
295 gtk_widget_set_name (combo
, "egg-combo-action-toolitem");
296 gtk_widget_show (combo
);
297 if (EGG_COMBO_ACTION (action
)->priv
->model
)
299 egg_combo_select_set_model (EGG_COMBO_SELECT (combo
),
300 EGG_COMBO_ACTION (action
)->priv
->model
);
301 egg_combo_select_set_active (EGG_COMBO_SELECT (combo
), 0);
305 /* Create a dummy model */
306 GtkTreeModel
*dummy_model
;
307 dummy_model
= create_dummy_model ();
308 egg_combo_select_set_model (EGG_COMBO_SELECT (combo
), dummy_model
);
309 g_object_unref (dummy_model
);
311 renderer
= gtk_cell_renderer_pixbuf_new ();
312 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo
),
314 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo
),
318 renderer
= gtk_cell_renderer_text_new ();
319 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo
),
321 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo
),
326 gtk_container_add (GTK_CONTAINER (item
), combo
);
327 // gtk_widget_set_size_request (combo, 80, -1);
328 gtk_widget_show(GTK_WIDGET (item
));
329 return GTK_WIDGET (item
);
333 connect_proxy (GtkAction
*action
, GtkWidget
*proxy
)
335 EggComboAction
*combo_action
;
337 combo_action
= EGG_COMBO_ACTION (action
);
339 /* do this before hand, so that we don't call the "activate" handler */
340 if (GTK_IS_MENU_ITEM (proxy
))
341 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (proxy
),
343 else if (GTK_IS_TOOL_ITEM (proxy
))
346 combo
= gtk_bin_get_child (GTK_BIN (proxy
));
347 if (EGG_IS_COMBO_SELECT (combo
))
349 if (EGG_COMBO_ACTION (action
)->priv
->model
)
351 egg_combo_select_set_active (EGG_COMBO_SELECT (combo
), -1);
352 egg_combo_select_set_model (EGG_COMBO_SELECT (combo
),
353 EGG_COMBO_ACTION (action
)->priv
->model
);
354 egg_combo_select_set_active (EGG_COMBO_SELECT (combo
), 0);
356 g_signal_connect (G_OBJECT (combo
), "changed",
357 G_CALLBACK (on_change
), action
);
360 (* GTK_ACTION_CLASS (parent_class
)->connect_proxy
) (action
, proxy
);
364 disconnect_proxy (GtkAction
*action
, GtkWidget
*proxy
)
366 EggComboAction
*combo_action
;
368 combo_action
= EGG_COMBO_ACTION (action
);
370 if (GTK_IS_TOOL_ITEM (proxy
))
373 combo
= gtk_bin_get_child (GTK_BIN (proxy
));
374 if (GTK_IS_COMBO (combo
))
376 g_signal_connect (combo
, "changed",
377 G_CALLBACK (on_change
), action
);
380 (* GTK_ACTION_CLASS (parent_class
)->connect_proxy
) (action
, proxy
);
384 * egg_combo_action_set_model:
385 * @action: the action object
386 * @model: a GtkTreeModel
388 * Sets a model in the action.
391 egg_combo_action_set_model (EggComboAction
*action
, GtkTreeModel
*model
)
395 g_return_if_fail (EGG_IS_COMBO_ACTION (action
));
396 g_return_if_fail (GTK_IS_TREE_MODEL (model
));
398 g_object_ref (model
);
399 if (action
->priv
->model
) {
400 g_object_unref (action
->priv
->model
);
402 action
->priv
->model
= model
;
404 for (slist
= gtk_action_get_proxies (GTK_ACTION(action
));
405 slist
; slist
= slist
->next
)
407 GtkWidget
*proxy
= slist
->data
;
409 gtk_action_block_activate_from (GTK_ACTION (action
), proxy
);
410 if (GTK_IS_CHECK_MENU_ITEM (proxy
))
412 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (proxy
),
415 else if (GTK_IS_TOOL_ITEM (proxy
))
418 combo
= gtk_bin_get_child (GTK_BIN (proxy
));
419 if (EGG_IS_COMBO_SELECT (combo
))
421 g_signal_handlers_block_by_func (combo
,
422 G_CALLBACK (on_change
),
424 egg_combo_select_set_active (EGG_COMBO_SELECT (combo
), -1);
425 egg_combo_select_set_model (EGG_COMBO_SELECT (combo
), model
);
426 egg_combo_select_set_active (EGG_COMBO_SELECT (combo
), 0);
427 g_signal_handlers_unblock_by_func (combo
,
428 G_CALLBACK (on_change
),
433 g_warning ("Don't know how to set popdown for `%s' widgets",
434 G_OBJECT_TYPE_NAME (proxy
));
439 g_warning ("Don't know how to set popdown for `%s' widgets",
440 G_OBJECT_TYPE_NAME (proxy
));
442 gtk_action_unblock_activate_from (GTK_ACTION (action
), proxy
);
447 egg_combo_action_get_model (EggComboAction
*action
)
449 return action
->priv
->model
;
453 egg_combo_action_get_active_iter (EggComboAction
*action
, GtkTreeIter
*iter
)
455 if (action
->priv
->active_iter
)
457 *iter
= *(action
->priv
->active_iter
);
464 egg_combo_action_set_active_iter (EggComboAction
*action
,
469 for (slist
= gtk_action_get_proxies (GTK_ACTION (action
));
470 slist
; slist
= slist
->next
)
472 GtkWidget
*proxy
= slist
->data
;
474 gtk_action_block_activate_from (GTK_ACTION (action
), proxy
);
475 if (GTK_IS_TOOL_ITEM (proxy
))
478 combo
= gtk_bin_get_child (GTK_BIN (proxy
));
479 if (EGG_IS_COMBO_SELECT (combo
))
481 if (action
->priv
->active_iter
)
482 gtk_tree_iter_free(action
->priv
->active_iter
);
483 action
->priv
->active_iter
= gtk_tree_iter_copy(iter
);
484 g_signal_handlers_block_by_func (combo
,
485 G_CALLBACK (on_change
),
487 egg_combo_select_set_active_iter (EGG_COMBO_SELECT (combo
),
488 action
->priv
->active_iter
);
489 action
->priv
->active_index
= egg_combo_select_get_active(EGG_COMBO_SELECT(combo
));
490 g_signal_handlers_unblock_by_func (combo
,
491 G_CALLBACK (on_change
),
496 g_warning ("Don't know how to change `%s' widgets",
497 G_OBJECT_TYPE_NAME (proxy
));
502 g_warning ("Don't know how to change `%s' widgets",
503 G_OBJECT_TYPE_NAME (proxy
));
505 gtk_action_unblock_activate_from (GTK_ACTION (action
), proxy
);