[goffice] GOActionComboStack: reimplement using GtkComboBox
- From: Morten Welinder <mortenw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [goffice] GOActionComboStack: reimplement using GtkComboBox
- Date: Fri, 21 Jan 2022 20:26:44 +0000 (UTC)
commit 710d1e2a75b8662922dc47a102f66496b491e525
Author: Morten Welinder <terra gnome org>
Date: Fri Jan 21 15:25:52 2022 -0500
GOActionComboStack: reimplement using GtkComboBox
This makes the widget fix better in visually.
ChangeLog | 5 +
NEWS | 1 +
goffice/gtk/go-action-combo-stack.c | 317 +++++++++---------------------------
goffice/gtk/go-action-combo-text.c | 2 +-
4 files changed, 81 insertions(+), 244 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 74925ef9..a673c5f6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2022-01-21 Morten Welinder <terra gnome org>
+
+ * goffice/gtk/go-action-combo-stack.c: Reimplement based on
+ GtkComboBox.
+
2022-01-20 Morten Welinder <terra gnome org>
* configure.ac: Post-release bump.
diff --git a/NEWS b/NEWS
index c23908d3..23fe50ac 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,7 @@ goffice 0.10.52:
Morten:
* Improve GOComboBox css styling.
+ * Reimplement GOActionComboStack using GtkComboBox.
--------------------------------------------------------------------------
goffice 0.10.51:
diff --git a/goffice/gtk/go-action-combo-stack.c b/goffice/gtk/go-action-combo-stack.c
index 63239d96..956864d1 100644
--- a/goffice/gtk/go-action-combo-stack.c
+++ b/goffice/gtk/go-action-combo-stack.c
@@ -29,198 +29,16 @@
/**************************************************************************/
-typedef struct {
- GOComboBox base;
-
- GtkWidget *button;
- GtkTreeView *list;
- GtkWidget *scrolled;
-
- gpointer last_key;
-} GOComboStack;
-
-typedef struct {
- GOComboBoxClass base;
- void (*pop) (GOComboStack *cbox, gpointer key);
-} GOComboStackClass;
-
-enum {
- POP,
- LAST_SIGNAL
-};
enum {
LABEL_COL,
- INDEX_COL,
KEY_COL
};
-#define GO_TYPE_COMBO_STACK (go_combo_stack_get_type ())
-#define GO_COMBO_STACK(o) G_TYPE_CHECK_INSTANCE_CAST (o, GO_TYPE_COMBO_STACK, GOComboStack)
-#define GO_IS_COMBO_STACK(o) G_TYPE_CHECK_INSTANCE_TYPE (o, GO_TYPE_COMBO_STACK)
-
-static GType go_combo_stack_get_type (void);
-static guint go_combo_stack_signals [LAST_SIGNAL] = { 0, };
-
-static void
-cb_screen_changed (GOComboStack *cs, GdkScreen *previous_screen)
-{
- GtkWidget *w = GTK_WIDGET (cs);
- GdkScreen *screen = gtk_widget_has_screen (w)
- ? gtk_widget_get_screen (w)
- : NULL;
-
- if (screen) {
- GtkWidget *toplevel = gtk_widget_get_toplevel (cs->scrolled
- ? cs->scrolled : GTK_WIDGET (cs->list));
- gtk_window_set_screen (GTK_WINDOW (toplevel), screen);
- }
-}
-
-static gpointer
-get_key_at_path (GtkTreeView *view, GtkTreePath *pos)
-{
- gpointer res = NULL;
- GtkTreeIter iter;
- GtkTreeModel *model = gtk_tree_view_get_model (view);
- if (gtk_tree_model_get_iter (model, &iter, pos))
- gtk_tree_model_get (model, &iter, KEY_COL, &res, -1);
- return res;
-}
-
-static void
-cb_button_clicked (GOComboStack *stack)
-{
- if (!_go_combo_is_updating (GO_COMBO_BOX (stack))) {
- GtkTreePath *pos = gtk_tree_path_new_first ();
- gpointer top = get_key_at_path (stack->list, pos);
- gtk_tree_path_free (pos);
- g_signal_emit (stack, go_combo_stack_signals [POP], 0, top);
- go_combo_box_popup_hide (GO_COMBO_BOX (stack));
- }
-}
-
-static gboolean
-cb_button_release_event (GtkWidget *list, GdkEventButton *e, gpointer data)
-{
- GOComboStack *stack = GO_COMBO_STACK (data);
-
- go_combo_box_popup_hide (GO_COMBO_BOX (stack));
-
- if (stack->last_key != NULL) {
- gint dummy, w, h;
- gdk_window_get_geometry (e->window, &dummy, &dummy, &w, &h);
- if (0 <= e->x && e->x < w && 0 <= e->y && e->y < h)
- g_signal_emit (stack, go_combo_stack_signals [POP], 0,
- stack->last_key);
- }
-
- return TRUE;
-}
-
-static gboolean
-cb_motion_notify_event (GtkWidget *widget, GdkEventMotion *event,
- GOComboStack *stack)
-{
- GtkTreePath *start, *pos;
- GtkTreeSelection *sel;
- GtkTreeModel *model = gtk_tree_view_get_model (stack->list);
-
- stack->last_key = NULL;
- sel = gtk_tree_view_get_selection (stack->list);
- gtk_tree_selection_unselect_all (sel);
-
- if (!gtk_tree_view_get_path_at_pos
- (stack->list, event->x, event->y, &pos, NULL, NULL, NULL)) {
- int n = gtk_tree_model_iter_n_children (model, NULL);
- if (n == 0)
- return TRUE;
- pos = gtk_tree_path_new_from_indices (n - 1, -1);
- }
-
- stack->last_key = get_key_at_path (stack->list, pos);
- start = gtk_tree_path_new_first ();
- gtk_tree_selection_select_range (sel, start, pos);
- gtk_tree_path_free (start);
- gtk_tree_path_free (pos);
-
- return TRUE;
-}
-
-static gboolean
-cb_leave_notify_event (GOComboStack *stack)
-{
- stack->last_key = NULL;
- gtk_tree_selection_unselect_all (gtk_tree_view_get_selection (stack->list));
- return FALSE;
-}
-
-static void
-go_combo_stack_init (GOComboStack *stack)
-{
- GtkScrolledWindow *scrolled;
- GtkTreeSelection *selection;
-
- stack->button = gtk_toggle_button_new ();
- gtk_button_set_relief (GTK_BUTTON (stack->button), GTK_RELIEF_NONE);
- gtk_widget_set_can_focus (stack->button, FALSE);
-
- stack->list = (GtkTreeView *)gtk_tree_view_new ();
- selection = gtk_tree_view_get_selection (stack->list);
- gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
-
- stack->scrolled = gtk_scrolled_window_new (
- gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (stack->list)),
- gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (stack->list)));
- scrolled = GTK_SCROLLED_WINDOW (stack->scrolled);
- gtk_scrolled_window_set_policy (scrolled,
- GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
- gtk_scrolled_window_add_with_viewport (scrolled, GTK_WIDGET (stack->list));
- gtk_widget_set_size_request (stack->scrolled, -1, 200); /* MAGIC NUMBER */
-
- /* Set up the dropdown list */
- g_signal_connect (G_OBJECT (stack), "screen-changed", G_CALLBACK (cb_screen_changed), NULL);
- g_signal_connect (G_OBJECT (stack->list),
- "button_release_event",
- G_CALLBACK (cb_button_release_event), stack);
- g_signal_connect (G_OBJECT (stack->list),
- "motion_notify_event",
- G_CALLBACK (cb_motion_notify_event), stack);
- g_signal_connect_swapped (G_OBJECT (stack->list),
- "leave_notify_event",
- G_CALLBACK (cb_leave_notify_event), stack);
- g_signal_connect_swapped (stack->button, "clicked",
- G_CALLBACK (cb_button_clicked),
- (gpointer) stack);
-
- gtk_widget_show (GTK_WIDGET (stack->list));
- gtk_widget_show (stack->scrolled);
- gtk_widget_show (stack->button);
- go_combo_box_construct (GO_COMBO_BOX (stack),
- stack->button, stack->scrolled, GTK_WIDGET (stack->list));
-}
-
-static void
-go_combo_stack_class_init (GObjectClass *klass)
-{
- go_combo_stack_signals [POP] = g_signal_new ("pop",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GOComboStackClass, pop),
- NULL, NULL,
- g_cclosure_marshal_VOID__POINTER,
- G_TYPE_NONE,
- 1, G_TYPE_POINTER);
-}
-
-GSF_CLASS (GOComboStack, go_combo_stack,
- go_combo_stack_class_init, go_combo_stack_init,
- GO_TYPE_COMBO_BOX)
-
/**************************************************************************/
typedef struct {
- GtkToolItem base;
- GOComboStack *combo; /* container has a ref, not us */
+ GtkToolItem base;
+ GtkWidget *combo; /* container has a ref, not us */
} GOToolComboStack;
typedef GtkToolItemClass GOToolComboStackClass;
@@ -239,67 +57,79 @@ static GSF_CLASS (GOToolComboStack, go_tool_combo_stack,
struct _GOActionComboStack {
GtkAction base;
GtkTreeModel *model;
-
- gpointer last_selection;
+ int last_selection;
};
typedef GtkActionClass GOActionComboStackClass;
static GObjectClass *combo_stack_parent;
+static int
+goacs_count (GOActionComboStack *action)
+{
+ return gtk_tree_model_iter_n_children (action->model, NULL);
+}
+
static void
-cb_tool_popped (GOToolComboStack *tool, gpointer key, GOActionComboStack *a)
+cb_combo_changed (GtkComboBoxText *combo, GOActionComboStack *action)
{
/* YUCK
* YUCK
* YUCK
- * We really need to return the key in "activate" but can not for now.
+ * We really need to return the key in "activate" but cannot for now.
* as a result people had better call
* go_action_combo_stack_selection
* from with the handler or they will lose the selection from toolitems.
- * We can not tell whether the activation was a menu or accelerator
+ * We cannot tell whether the activation was a menu or accelerator
* which just use the top. */
- a->last_selection = key;
- gtk_action_activate (GTK_ACTION (a));
- a->last_selection = NULL;
+
+ action->last_selection = gtk_combo_box_get_active (GTK_COMBO_BOX (combo));
+ if (action->last_selection >= 0) {
+ g_printerr ("Activate\n");
+ gtk_action_activate (GTK_ACTION (action));
+ }
+}
+
+static void
+cb_button_clicked (GtkButton *button, GOActionComboStack *action)
+{
+ int n = goacs_count (action);
+ if (n > 0) {
+ action->last_selection = 0;
+ gtk_action_activate (GTK_ACTION (action));
+ } else
+ action->last_selection = -1;
}
static void
cb_reconfig (GOToolComboStack *tool, GtkAction *a)
{
GtkIconSize size = gtk_tool_item_get_icon_size (GTK_TOOL_ITEM (tool));
- GtkReliefStyle relief = gtk_tool_item_get_relief_style (GTK_TOOL_ITEM (tool));
- GtkWidget *image;
+ GtkWidget *image, *button;
GtkWidget *child;
- child = gtk_bin_get_child (GTK_BIN (tool->combo->button));
+ child = gtk_bin_get_child (GTK_BIN (tool->combo));
if (child)
- gtk_container_remove (GTK_CONTAINER (tool->combo->button), child);
+ gtk_container_remove (GTK_CONTAINER (tool->combo), child);
image = gtk_action_create_icon (a, size);
- gtk_widget_show (image);
- gtk_container_add (GTK_CONTAINER (tool->combo->button), image);
+ button = g_object_new (GTK_TYPE_BUTTON, "image", image, NULL);
+ gtk_widget_show_all (button);
+ gtk_container_add (GTK_CONTAINER (tool->combo), button);
- go_combo_box_set_relief (GO_COMBO_BOX (tool->combo), relief);
+ g_signal_connect (button, "clicked", G_CALLBACK (cb_button_clicked), a);
}
-
static GtkWidget *
go_action_combo_stack_create_tool_item (GtkAction *a)
{
GOActionComboStack *saction = (GOActionComboStack *)a;
- GtkTreeView *tree_view;
GOToolComboStack *tool = g_object_new (GO_TYPE_TOOL_COMBO_STACK, NULL);
- gboolean is_sensitive = gtk_tree_model_iter_n_children (saction->model, NULL) > 0;
-
- tool->combo = g_object_new (GO_TYPE_COMBO_STACK, NULL);
- tree_view = GTK_TREE_VIEW (tool->combo->list);
- gtk_tree_view_set_model (tree_view, saction->model);
- gtk_tree_view_set_headers_visible (tree_view, FALSE);
- gtk_tree_view_append_column (tree_view,
- gtk_tree_view_column_new_with_attributes (NULL,
- gtk_cell_renderer_text_new (),
- "text", 0,
- NULL));
+ gboolean is_sensitive = goacs_count (saction) > 0;
+ GtkCellRenderer *renderer = gtk_cell_renderer_text_new();
+
+ tool->combo = gtk_combo_box_new_with_model (saction->model);
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (tool->combo), renderer, FALSE);
+ gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (tool->combo), renderer, "text", 0);
g_signal_connect (tool, "toolbar-reconfigured",
G_CALLBACK (cb_reconfig), a);
@@ -307,14 +137,14 @@ go_action_combo_stack_create_tool_item (GtkAction *a)
gtk_widget_set_sensitive (GTK_WIDGET (tool), is_sensitive);
- go_gtk_widget_disable_focus (GTK_WIDGET (tool->combo));
- gtk_container_add (GTK_CONTAINER (tool), GTK_WIDGET (tool->combo));
- gtk_widget_show (GTK_WIDGET (tool->combo));
+ go_gtk_widget_disable_focus (tool->combo);
+ gtk_container_add (GTK_CONTAINER (tool), tool->combo);
+ gtk_widget_show (tool->combo);
gtk_widget_show (GTK_WIDGET (tool));
- g_signal_connect (G_OBJECT (tool->combo),
- "pop",
- G_CALLBACK (cb_tool_popped), saction);
+ g_signal_connect_object (tool->combo,
+ "changed",
+ G_CALLBACK (cb_combo_changed), a, 0);
return GTK_WIDGET (tool);
}
@@ -323,8 +153,8 @@ static GtkWidget *
go_action_combo_stack_create_menu_item (GtkAction *a)
{
GOActionComboStack *saction = (GOActionComboStack *)a;
- GtkWidget *item = gtk_image_menu_item_new ();
- gboolean is_sensitive = gtk_tree_model_iter_n_children (saction->model, NULL) > 0;
+ GtkWidget *item = gtk_menu_item_new ();
+ gboolean is_sensitive = goacs_count (saction) > 0;
gtk_widget_set_sensitive (GTK_WIDGET (item), is_sensitive);
return item;
}
@@ -354,8 +184,8 @@ static void
go_action_combo_stack_init (GOActionComboStack *saction)
{
saction->model = (GtkTreeModel *)
- gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_INT, G_TYPE_POINTER);
- saction->last_selection = NULL;
+ gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_POINTER);
+ saction->last_selection = -1;
}
GSF_CLASS (GOActionComboStack, go_action_combo_stack,
@@ -365,7 +195,7 @@ GSF_CLASS (GOActionComboStack, go_action_combo_stack,
static void
check_sensitivity (GOActionComboStack *saction, unsigned old_count)
{
- unsigned new_count = gtk_tree_model_iter_n_children (saction->model, NULL);
+ unsigned new_count = goacs_count (saction);
if ((old_count > 0) ^ (new_count > 0)) {
GSList *ptr = gtk_action_get_proxies (GTK_ACTION (saction));
@@ -379,7 +209,7 @@ check_sensitivity (GOActionComboStack *saction, unsigned old_count)
* go_action_combo_stack_push :
* @act: #GOActionComboStack
* @str: The label to push
- * @key: a key value to id the pushe item
+ * @key: a key value to id the pushed item
**/
void
go_action_combo_stack_push (GOActionComboStack *act,
@@ -387,7 +217,7 @@ go_action_combo_stack_push (GOActionComboStack *act,
{
GOActionComboStack *saction = GO_ACTION_COMBO_STACK (act);
GtkTreeIter iter;
- unsigned old_count = gtk_tree_model_iter_n_children (saction->model, NULL);
+ unsigned old_count = goacs_count (saction);
g_return_if_fail (saction != NULL);
@@ -412,7 +242,7 @@ go_action_combo_stack_pop (GOActionComboStack *act, unsigned n)
{
GOActionComboStack *saction = GO_ACTION_COMBO_STACK (act);
GtkTreeIter iter;
- unsigned old_count = gtk_tree_model_iter_n_children (saction->model, NULL);
+ unsigned old_count = goacs_count (saction);
g_return_if_fail (saction != NULL);
@@ -435,40 +265,41 @@ void
go_action_combo_stack_truncate (GOActionComboStack *act, unsigned n)
{
GOActionComboStack *saction = GO_ACTION_COMBO_STACK (act);
- GtkTreeIter iter;
unsigned old_count;
g_return_if_fail (saction != NULL);
- old_count = gtk_tree_model_iter_n_children (saction->model, NULL);
-
- if (gtk_tree_model_iter_nth_child (saction->model, &iter, NULL, n))
- while (gtk_list_store_remove (GTK_LIST_STORE (saction->model), &iter))
- ;
- check_sensitivity (saction, old_count);
+ old_count = goacs_count (saction);
+ if (old_count > n) {
+ GtkTreeIter iter;
+ if (gtk_tree_model_iter_nth_child (saction->model, &iter, NULL, n))
+ while (gtk_list_store_remove (GTK_LIST_STORE (saction->model), &iter))
+ ;
+ check_sensitivity (saction, old_count);
+ }
}
/**
* go_action_combo_stack_selection:
* @a: #GOActionComboStack
*
- * Returns: (transfer full): the key of the item last selected in one of the proxies.
+ * Returns: (transfer none): the key of the item last selected in one of the proxies.
* Yes this interface is terrible, but we can't return the key in the
* activate signal.
*
- * NOTE : see writeup in cb_tool_popped.
+ * NOTE : see writeup in cb_combo_changed.
**/
gpointer
go_action_combo_stack_selection (GOActionComboStack const *a)
{
- gpointer res = NULL;
GtkTreeIter iter;
+ int i = MAX (0, a->last_selection);
+
+ if (gtk_tree_model_iter_nth_child (a->model, &iter, NULL, i)) {
+ gpointer key;
+ gtk_tree_model_get (a->model, &iter, KEY_COL, &key, -1);
+ return key;
+ }
- if (a->last_selection != NULL)
- return a->last_selection;
- if (gtk_tree_model_get_iter_first (a->model, &iter))
- gtk_tree_model_get (a->model, &iter,
- KEY_COL, &res,
- -1);
- return res;
+ return NULL;
}
diff --git a/goffice/gtk/go-action-combo-text.c b/goffice/gtk/go-action-combo-text.c
index 977eaed4..5a87217e 100644
--- a/goffice/gtk/go-action-combo-text.c
+++ b/goffice/gtk/go-action-combo-text.c
@@ -142,7 +142,7 @@ go_action_combo_text_create_menu_item (GtkAction *act)
{
GOActionComboText *taction = GO_ACTION_COMBO_TEXT (act);
GtkWidget *menu = gtk_menu_new ();
- GtkWidget *item = gtk_image_menu_item_new ();
+ GtkWidget *item = gtk_menu_item_new ();
GSList *ptr;
for (ptr = taction->elements; ptr != NULL ; ptr = ptr->next) {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]