31 #include "gnc-combott.h"
50 #define GNC_COMBOTT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GNC_TYPE_COMBOTT, GncCombottPrivate))
52 static guint combott_signals[LAST_SIGNAL] = {0,};
60 GtkTreeIter active_iter;
81 static void gctt_set_property (GObject *
object,
86 static void gctt_get_property (GObject *
object,
91 static void gctt_finalize (GObject *
object);
93 static void gctt_combott_menu_position (GtkMenu *menu,
99 static void gctt_changed (
GncCombott *combott);
100 static void gctt_set_model (
GncCombott *combott, GtkTreeModel *model);
101 static void gctt_refresh_menu (
GncCombott *combott, GtkTreeModel *model);
102 static void gctt_rebuild_menu (
GncCombott *combott, GtkTreeModel *model);
104 static gboolean which_tooltip_cb (GtkWidget *widget, gint x, gint y,
105 gboolean keyboard_mode, GtkTooltip *tooltip, gpointer user_data);
106 static gboolean button_press_cb (GtkWidget *widget, GdkEvent *event, gpointer *user_data );
107 static void button_getsize_cb (GtkWidget *widget, GtkAllocation *allocation, gpointer *user_data);
108 static void menu_getsize_cb (GtkWidget *widget, GtkAllocation *allocation, gpointer *user_data);
109 static void menuitem_response_cb (GtkMenuItem *item, gpointer *user_data);
115 static GObjectClass *parent_class = NULL;
118 gnc_combott_get_type (
void)
120 static GType combott_type = 0;
124 static const GTypeInfo combott_info =
129 (GClassInitFunc) gctt_class_init,
134 (GInstanceInitFunc) gctt_init,
137 combott_type = g_type_register_static (GTK_TYPE_HBOX,
148 GObjectClass *gobject_class;
150 parent_class = g_type_class_peek_parent (klass);
151 gobject_class = G_OBJECT_CLASS (klass);
153 gobject_class->set_property = gctt_set_property;
154 gobject_class->get_property = gctt_get_property;
155 gobject_class->finalize = gctt_finalize;
157 klass->changed = gctt_changed;
159 combott_signals[CHANGED] =
160 g_signal_new (
"changed",
161 G_OBJECT_CLASS_TYPE (klass),
165 g_cclosure_marshal_VOID__VOID,
168 g_object_class_install_property (
171 g_param_spec_object (
"model",
173 "The model for the combo tooltip",
177 g_object_class_install_property (
180 g_param_spec_int (
"text-col",
182 "Column for the text",
188 g_object_class_install_property (
191 g_param_spec_int (
"tip-col",
193 "Column for the tip",
218 hbox = gtk_hbox_new(FALSE, 0);
220 arrow = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_OUT);
221 gtk_box_pack_end (GTK_BOX (hbox), arrow, FALSE, FALSE, 0);
223 sep = gtk_vseparator_new();
224 gtk_box_pack_end (GTK_BOX (hbox), sep, FALSE, FALSE, 0);
226 label = gtk_label_new(NULL);
227 gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
230 button = gtk_button_new();
231 gtk_container_add(GTK_CONTAINER(button), GTK_WIDGET(hbox));
232 priv->button = button;
234 gtk_container_add(GTK_CONTAINER(combott), GTK_WIDGET(button));
236 g_signal_connect (button,
"event",
237 G_CALLBACK (button_press_cb), combott);
239 gtk_widget_set_has_tooltip (GTK_WIDGET(combott), TRUE);
241 g_signal_connect(G_OBJECT(combott),
"query-tooltip",
242 G_CALLBACK(which_tooltip_cb), combott);
244 g_signal_connect(G_OBJECT(combott),
"size-allocate",
245 G_CALLBACK(button_getsize_cb), combott);
247 gtk_widget_show(GTK_WIDGET(priv->button));
252 gctt_set_property (GObject *
object,
263 gctt_set_model (combott, g_value_get_object (value));
267 gnc_combott_set_active (combott, g_value_get_int (value));
271 priv->text_col = g_value_get_int (value);
275 priv->tip_col = g_value_get_int (value);
276 gctt_refresh_menu(combott, priv->model);
280 G_OBJECT_WARN_INVALID_PROPERTY_ID (
object, param_id, pspec);
292 gctt_get_property (GObject *
object,
303 g_value_take_object (value, priv->model);
307 g_value_set_int (value, gnc_combott_get_active (combott));
311 g_value_set_int (value, priv->text_col);
315 g_value_set_int (value, priv->tip_col);
319 G_OBJECT_WARN_INVALID_PROPERTY_ID (
object, param_id, pspec);
326 gctt_finalize (GObject *
object)
331 g_return_if_fail (
object != NULL);
332 g_return_if_fail (GNC_IS_COMBOTT (
object));
334 combott = GNC_COMBOTT (
object);
335 priv = GNC_COMBOTT_GET_PRIVATE (combott);
347 G_OBJECT_CLASS (parent_class)->finalize (
object);
352 gctt_set_model (
GncCombott *combott, GtkTreeModel *model)
356 g_return_if_fail (GNC_IS_COMBOTT (combott));
357 g_return_if_fail (model == NULL || GTK_IS_TREE_MODEL (model));
359 priv = GNC_COMBOTT_GET_PRIVATE (combott);
361 gctt_rebuild_menu(combott, model);
364 g_object_ref (priv->model);
369 gctt_rebuild_menu (
GncCombott *combott, GtkTreeModel *model)
373 GtkWidget *menu_items;
378 g_return_if_fail (GNC_IS_COMBOTT (combott));
379 g_return_if_fail (model == NULL || GTK_IS_TREE_MODEL (model));
381 priv = GNC_COMBOTT_GET_PRIVATE (combott);
385 priv->menu = gtk_menu_new();
387 valid = gtk_tree_model_get_iter_first (model, &iter);
395 gtk_tree_model_get (model, &iter,
396 priv->text_col, &str_data,
397 priv->tip_col, &tip_data,
401 menu_items = gtk_menu_item_new_with_label (str_data);
404 if(strlen(str_data) > num)
405 num = strlen(str_data);
408 label = gtk_bin_get_child(GTK_BIN(menu_items));
409 gtk_widget_set_tooltip_text (label, tip_data);
410 gtk_misc_set_alignment (GTK_MISC(label), 0, 0.5);
413 gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu), menu_items);
414 g_signal_connect (menu_items,
"activate",
415 G_CALLBACK (menuitem_response_cb),
419 gtk_widget_show (menu_items);
424 valid = gtk_tree_model_iter_next (model, &iter);
427 g_signal_connect(G_OBJECT(priv->menu),
"size-allocate", G_CALLBACK(menu_getsize_cb), combott);
430 priv->max_number_char = num;
431 gtk_label_set_width_chars(GTK_LABEL(priv->label), priv->max_number_char);
433 priv->num_items = items;
438 gctt_refresh_menu (
GncCombott *combott, GtkTreeModel *model)
442 g_return_if_fail (GNC_IS_COMBOTT (combott));
443 g_return_if_fail (model == NULL || GTK_IS_TREE_MODEL (model));
445 priv = GNC_COMBOTT_GET_PRIVATE (combott);
447 gctt_rebuild_menu(combott, model);
461 gctt_combott_menu_position (GtkMenu *menu,
467 GncCombott *combott = GNC_COMBOTT (user_data);
473 child = GTK_BIN (priv->button)->child;
477 if (!gtk_widget_get_has_window (child))
479 sx += child->allocation.x;
480 sy += child->allocation.y;
483 gdk_window_get_root_coords (child->window, sx, sy, &sx, &sy);
485 sx -= GTK_WIDGET (priv->button)->style->xthickness;
487 gtk_widget_size_request (GTK_WIDGET (menu), &req);
489 if (gtk_widget_get_direction (GTK_WIDGET (priv->button)) == GTK_TEXT_DIR_LTR)
492 *x = sx + child->allocation.width - req.width;
494 if(priv->active == -1 || priv->active == 0)
497 *y = sy - ((req.height / priv->num_items) * (priv->active - 1));
504 button_getsize_cb (GtkWidget *widget, GtkAllocation *allocation, gpointer *user_data)
506 GncCombott *combott = GNC_COMBOTT (user_data);
509 priv->width = allocation->width;
510 priv->height = allocation->height;
511 priv->x = allocation->x;
512 priv->y = allocation->y;
517 menu_getsize_cb (GtkWidget *widget, GtkAllocation *allocation, gpointer *user_data)
519 GncCombott *combott = GNC_COMBOTT (user_data);
523 gtk_widget_set_size_request (widget, priv->width - 6, allocation->height);
528 which_tooltip_cb (GtkWidget *widget, gint x, gint y, gboolean keyboard_mode, GtkTooltip *tooltip, gpointer user_data)
532 GncCombott *combott = GNC_COMBOTT (user_data);
535 if(!priv->active == 0)
537 gtk_tree_model_get( priv->model, &priv->active_iter, priv->tip_col, &text, -1 );
538 if(g_strcmp0(text,
"") && (text != NULL))
541 gtk_tooltip_set_text (tooltip, text);
556 button_press_cb (GtkWidget *widget, GdkEvent *event, gpointer *user_data )
558 GncCombott *combott = GNC_COMBOTT (user_data);
561 if(priv->model != NULL)
563 if (event->type == GDK_BUTTON_PRESS)
565 GdkEventButton *bevent = (GdkEventButton *) event;
567 gtk_menu_popup (GTK_MENU (priv->menu),
569 gctt_combott_menu_position, combott,
570 bevent->button, bevent->time);
583 menuitem_response_cb (GtkMenuItem *item, gpointer *user_data )
585 const gchar *label_text;
586 GtkTreeIter iter, iter_now = {0, NULL, NULL, NULL};
591 GncCombott *combott = GNC_COMBOTT (user_data);
594 label_text = gtk_menu_item_get_label (item);
597 gtk_label_set_text(GTK_LABEL(priv->label), label_text);
598 gtk_misc_set_alignment (GTK_MISC(priv->label), 0, 0.5);
601 valid = gtk_tree_model_get_iter_first (priv->model, &iter);
607 gtk_tree_model_get (priv->model, &iter,
608 priv->text_col, &str_data,
609 priv->tip_col, &tip_data,
611 if(!g_strcmp0(str_data, label_text))
620 valid = gtk_tree_model_iter_next (priv->model, &iter);
624 if(priv->active != active_now)
626 priv->active = active_now;
627 priv->active_iter = iter_now;
629 g_signal_emit (combott, combott_signals[CHANGED], 0);
635 gnc_combott_new (
void)
638 hbox = g_object_new (GNC_TYPE_COMBOTT, NULL);
639 return GNC_COMBOTT (hbox);
649 g_return_val_if_fail (GNC_IS_COMBOTT (combott), 0);
651 priv = GNC_COMBOTT_GET_PRIVATE (combott);
653 result = priv->active - 1;
660 gnc_combott_set_active (
GncCombott *combott, gint index)
664 gboolean valid = TRUE;
668 g_return_if_fail (GNC_IS_COMBOTT (combott));
669 g_return_if_fail (index >= -1);
671 priv = GNC_COMBOTT_GET_PRIVATE (combott);
674 if (priv->model != NULL)
677 if(index + 1 != priv->active)
683 gtk_label_set_text(GTK_LABEL(priv->label),
"");
684 g_signal_emit (combott, combott_signals[CHANGED], 0);
689 valid = gtk_tree_model_get_iter_first (priv->model, &iter);
697 gtk_tree_model_get (priv->model, &iter,
698 priv->text_col, &str_data,
699 priv->tip_col, &tip_data,
702 if(index + 1 == active)
704 priv->active = index + 1;
705 priv->active_iter = iter;
706 gtk_label_set_text(GTK_LABEL(priv->label), str_data);
707 gtk_misc_set_alignment (GTK_MISC(priv->label), 0, 0.5);
708 g_signal_emit (combott, combott_signals[CHANGED], 0);
714 valid = gtk_tree_model_iter_next (priv->model, &iter);