diff options
author | P. F. Chimento <philip.chimento@gmail.com> | 2013-07-24 10:17:19 -0700 |
---|---|---|
committer | P. F. Chimento <philip.chimento@gmail.com> | 2013-07-24 10:17:19 -0700 |
commit | 3bbf1c4223d4b05a790b22e24c74ec144ce48c34 (patch) | |
tree | 94b1329b4a7ec8ce999183e027040b11e3023f2a | |
parent | 1ff95e823772b048a5c966235a7f3a7b5ab3681a (diff) | |
parent | b6d8e1da288e7b1dab3cc792f8b7dd449f6db6cd (diff) |
Merge pull request #170 from endlessm/issues/146
#146 Layout of `EosActionMenu`
-rw-r--r-- | endless/eosactionmenu-private.h | 6 | ||||
-rw-r--r-- | endless/eosactionmenu.c | 94 | ||||
-rw-r--r-- | test/smoke-tests/action-buttons.js | 25 | ||||
-rw-r--r-- | test/smoke-tests/eosactionbutton.css | 1 | ||||
-rw-r--r-- | test/test-action-menu.c | 52 |
5 files changed, 150 insertions, 28 deletions
diff --git a/endless/eosactionmenu-private.h b/endless/eosactionmenu-private.h index 8b3755e..4393fdc 100644 --- a/endless/eosactionmenu-private.h +++ b/endless/eosactionmenu-private.h @@ -37,21 +37,21 @@ typedef struct _EosActionMenuPrivate EosActionMenuPrivate; struct _EosActionMenu { - GtkGrid parent; + GtkFrame parent; EosActionMenuPrivate *priv; }; struct _EosActionMenuClass { - GtkGridClass parent_class; + GtkFrameClass parent_class; }; GType eos_action_menu_get_type (void) G_GNUC_CONST; GtkWidget *eos_action_menu_new (); -void eos_action_menu_add_action (EosActionMenu *menu, +void eos_action_menu_add_action (EosActionMenu *menu, GtkAction *action); GtkAction *eos_action_menu_get_action (EosActionMenu *menu, diff --git a/endless/eosactionmenu.c b/endless/eosactionmenu.c index e3466e2..0f45305 100644 --- a/endless/eosactionmenu.c +++ b/endless/eosactionmenu.c @@ -17,13 +17,17 @@ */ -G_DEFINE_TYPE (EosActionMenu, eos_action_menu, GTK_TYPE_GRID) +G_DEFINE_TYPE (EosActionMenu, eos_action_menu, GTK_TYPE_FRAME) #define EOS_ACTION_MENU_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), EOS_TYPE_ACTION_MENU, EosActionMenuPrivate)) struct _EosActionMenuPrivate { + GtkWidget *overlay; + GtkWidget *center_grid; + GtkWidget *bottom_grid; + GtkActionGroup *action_group; }; @@ -58,13 +62,44 @@ eos_action_menu_init (EosActionMenu *self) context = gtk_widget_get_style_context (GTK_WIDGET (self)); gtk_style_context_add_class (context, _EOS_STYLE_CLASS_ACTION_MENU); + priv->overlay = gtk_overlay_new (); + g_object_set (G_OBJECT (priv->overlay), + "halign", GTK_ALIGN_FILL, + "valign", GTK_ALIGN_FILL, + "hexpand", TRUE, + "vexpand", TRUE, + NULL); + + priv->center_grid = gtk_grid_new (); + g_object_set (G_OBJECT (priv->center_grid), + "orientation", GTK_ORIENTATION_VERTICAL, + "halign", GTK_ALIGN_CENTER, + "valign", GTK_ALIGN_CENTER, + NULL); + + priv->bottom_grid = gtk_grid_new (); + g_object_set (G_OBJECT (priv->bottom_grid), + "orientation", GTK_ORIENTATION_VERTICAL, + "halign", GTK_ALIGN_CENTER, + "valign", GTK_ALIGN_END, + NULL); + + // this is ugly, but needed so the overlay takes all the available space + GtkWidget* placeholder = gtk_event_box_new(); + gtk_widget_set_hexpand (placeholder, TRUE); + gtk_widget_set_vexpand (placeholder, TRUE); + gtk_container_add (GTK_CONTAINER (priv->overlay), placeholder); + + gtk_overlay_add_overlay (GTK_OVERLAY (priv->overlay), priv->center_grid); + gtk_overlay_add_overlay (GTK_OVERLAY (priv->overlay), priv->bottom_grid); + + gtk_container_add (GTK_CONTAINER (self), priv->overlay); + // TODO : name? priv->action_group = gtk_action_group_new ("EosActionMenu"); gtk_widget_set_hexpand (GTK_WIDGET (self), TRUE); gtk_widget_set_vexpand (GTK_WIDGET (self), TRUE); - gtk_widget_set_halign (GTK_WIDGET (self), GTK_ALIGN_CENTER); - gtk_widget_set_valign (GTK_WIDGET (self), GTK_ALIGN_CENTER); } /* ******* LIFECYCLE ******* */ @@ -99,8 +134,15 @@ eos_action_menu_finalize (GObject *object) * @menu: a #EosActionMenu * @action: a #GtkAction: name, label, icon-name, is-important. * - * Adds an action to the #EosActionMenu, using its name, label, icon-name and - * is-important properties. + * Adds an action to the #EosActionMenu, using its #GtkAction:name, + * #GtkAction:label, #GtkAction:icon-name, #GtkAction:is-important and + * #GtkAction:stock-id properties. + * + * Cancel, close and delete actions are placed at the bottom of the menu. To + * indicate this, set the #GtkAction:stock-id property to one of + * #GTK_STOCK_CANCEL, #GTK_STOCK_CLOSE or #GTK_STOCK_DELETE. All other values of + * this property will be ignored. + * */ void eos_action_menu_add_action (EosActionMenu *menu, @@ -125,9 +167,16 @@ eos_action_menu_add_action (EosActionMenu *menu, gtk_activatable_set_related_action (GTK_ACTIVATABLE (action_button), action); - // TODO : maybe we need a finer control, taking is-important into account? - gtk_grid_attach_next_to (GTK_GRID (menu), action_button, NULL, - GTK_POS_BOTTOM, 1, 1); + if (g_strcmp0 (gtk_action_get_stock_id (action), GTK_STOCK_CANCEL) == 0 || + g_strcmp0 (gtk_action_get_stock_id (action), GTK_STOCK_CLOSE) == 0 || + g_strcmp0 (gtk_action_get_stock_id (action), GTK_STOCK_DELETE) == 0) + { + gtk_container_add (GTK_CONTAINER (priv->bottom_grid), action_button); + } + else + { + gtk_container_add (GTK_CONTAINER (priv->center_grid), action_button); + } } } @@ -179,10 +228,37 @@ eos_action_menu_remove_action (EosActionMenu *menu, GtkAction *action) { EosActionMenuPrivate *priv; + GList *children, *i; + GtkWidget *target_child = NULL; + g_return_if_fail (EOS_IS_ACTION_MENU (menu)); + g_return_if_fail (GTK_IS_ACTION (action)); priv = menu->priv; gtk_action_group_remove_action(priv->action_group, action); + + children = gtk_container_get_children (GTK_CONTAINER (priv->center_grid)); + + children = g_list_concat (children, + gtk_container_get_children (GTK_CONTAINER (priv->bottom_grid))); + + for (i = children; i != NULL; i = i->next) + { + GtkWidget *child = i->data; + GtkAction *childs_action = gtk_activatable_get_related_action (GTK_ACTIVATABLE (child)); + + if (childs_action != NULL && + g_strcmp0 (gtk_action_get_name (childs_action), gtk_action_get_name (action)) == 0) + { + target_child = child; + break; + } + } + + if (target_child != NULL) + { + gtk_widget_destroy (target_child); + } } /* @@ -205,7 +281,7 @@ eos_action_menu_remove_action_by_name (EosActionMenu *menu, action = gtk_action_group_get_action (priv->action_group, name); if (action) { - gtk_action_group_remove_action (priv->action_group, action); + eos_action_menu_remove_action (menu, action); } } diff --git a/test/smoke-tests/action-buttons.js b/test/smoke-tests/action-buttons.js index 7997793..476912a 100644 --- a/test/smoke-tests/action-buttons.js +++ b/test/smoke-tests/action-buttons.js @@ -24,9 +24,9 @@ const TestApplication = new Lang.Class ({ this._darkSwitch = new Gtk.Switch ({active: false}); this._darkSwitch.connect ('notify::active', Lang.bind (this, function (active) { if (this._darkSwitch.get_active()) { - this._menu_panel.get_style_context().add_class('dark'); + this._menu.get_style_context().add_class('dark'); } else { - this._menu_panel.get_style_context().remove_class('dark'); + this._menu.get_style_context().remove_class('dark'); } })); this._content.attach(new Gtk.Label ({label: 'Dark action menu'}), 0, 0, 1, 1); @@ -57,23 +57,17 @@ const TestApplication = new Lang.Class ({ 'label-position': Gtk.PositionType.RIGHT }), 1, 2, 1, 1); - this._menu = new Endless.ActionMenu (); + this._menu = new Endless.ActionMenu ({name: 'menu'}); - // put the ActionMenu in a panel, as GtkGrid doesn't expand if none of its children want to - this._menu_panel = new Gtk.Frame ({name: 'menu'}); - this._menu_panel.add (this._menu); - this._menu_panel.set_hexpand (true); - this._menu_panel.set_vexpand (true); - // the ActionMenu takes 1/6 of the width this._page.set_column_homogeneous (true); this._page.attach (this._content, 0, 0, 5, 1); - this._page.attach (this._menu_panel, 5, 0, 1, 1); + this._page.attach (this._menu, 5, 0, 1, 1); this._menu.add_action ({ name: 'select', 'icon-name': 'object-select-symbolic', - label: 'select stuff', + label: 'SELECT', 'is-important': true }, Lang.bind(this, function () { var md = new Gtk.MessageDialog({modal:true, title:"Information", @@ -86,19 +80,20 @@ const TestApplication = new Lang.Class ({ this._menu.add_action ({ name: 'delete', 'icon-name': 'edit-delete-symbolic', - label: 'delete stuff', - 'is-important': false }); + label: 'DELETE', + 'is-important': false, + 'stock-id': Gtk.STOCK_DELETE }); this._menu.add_action ({ name: 'smile', 'icon-name': 'face-smile-symbolic', - label: 'smile', + label: 'SMILE', 'is-important': false }); this._menu.add_action ({ name: 'sadface', 'icon-name': 'face-sad-symbolic', - label: 'sadface', + label: 'SAD FACE', 'is-important': false }); this._pm = new Endless.PageManager(); diff --git a/test/smoke-tests/eosactionbutton.css b/test/smoke-tests/eosactionbutton.css index b01e3cf..189a15a 100644 --- a/test/smoke-tests/eosactionbutton.css +++ b/test/smoke-tests/eosactionbutton.css @@ -8,6 +8,7 @@ GtkWindow { background-color: mix(white, black, 0.2); border-color: mix(white, black, 0.5); border-width: 0 0 0 6px; + padding: 30px; } .dark#menu { diff --git a/test/test-action-menu.c b/test/test-action-menu.c index b12ff8d..e066b70 100644 --- a/test/test-action-menu.c +++ b/test/test-action-menu.c @@ -5,6 +5,8 @@ #include "run-tests.h" +#include "endless/eosactionmenu.c" + #define ADD_ACTION_MENU_TEST(path, test_func) \ g_test_add ((path), ActionMenuFixture, NULL, \ am_fixture_setup, (test_func), am_fixture_teardown) @@ -55,7 +57,7 @@ test_am_add_action (ActionMenuFixture *fixture, eos_action_menu_add_action (fixture->action_menu, fixture->action1); - GtkWidget *button = gtk_grid_get_child_at (GTK_GRID (fixture->action_menu), 0, 0); + GtkWidget *button = gtk_grid_get_child_at (GTK_GRID (fixture->action_menu->priv->center_grid), 0, 0); g_assert (EOS_IS_ACTION_BUTTON (button)); @@ -103,6 +105,35 @@ test_am_list_actions (ActionMenuFixture *fixture, g_assert (g_list_find (list, fixture->action3) == NULL); } +static gboolean +menu_contains_button_with_label (EosActionMenu *menu, const gchar* button_label) +{ + GList* children; + gboolean found = FALSE; + + children = gtk_container_get_children (GTK_CONTAINER (menu->priv->center_grid)); + + children = g_list_concat (children, + gtk_container_get_children (GTK_CONTAINER (menu->priv->bottom_grid))); + + for (GList *i = children; i != NULL ; i = i->next) + { + if (EOS_IS_ACTION_BUTTON (i->data)) + { + if (g_strcmp0 (eos_action_button_get_label (EOS_ACTION_BUTTON (i->data)), + button_label) == 0) + { + found = TRUE; + break; + } + } + } + + g_list_free (children); + + return found; +} + static void test_am_remove_action (ActionMenuFixture *fixture, gconstpointer unused) @@ -121,6 +152,14 @@ test_am_remove_action (ActionMenuFixture *fixture, g_assert (g_list_find (list, fixture->action2) == NULL); g_assert (g_list_find (list, fixture->action3) != NULL); + // the buttons have been removed as well + g_assert (menu_contains_button_with_label (fixture->action_menu, + gtk_action_get_label (fixture->action1))); + g_assert (!menu_contains_button_with_label (fixture->action_menu, + gtk_action_get_label (fixture->action2))); + g_assert (menu_contains_button_with_label (fixture->action_menu, + gtk_action_get_label (fixture->action3))); + eos_action_menu_remove_action (fixture->action_menu, fixture->action1); eos_action_menu_remove_action (fixture->action_menu, fixture->action3); @@ -129,6 +168,10 @@ test_am_remove_action (ActionMenuFixture *fixture, g_assert (g_list_find (list, fixture->action1) == NULL); g_assert (g_list_find (list, fixture->action2) == NULL); g_assert (g_list_find (list, fixture->action3) == NULL); + + // the container is empty + g_assert (gtk_container_get_children (GTK_CONTAINER (fixture->action_menu->priv->center_grid)) == NULL); + g_assert (gtk_container_get_children (GTK_CONTAINER (fixture->action_menu->priv->bottom_grid)) == NULL); } static void @@ -146,6 +189,13 @@ test_am_remove_action_by_name (ActionMenuFixture *fixture, g_assert (g_list_find (list, fixture->action1) != NULL); g_assert (g_list_find (list, fixture->action2) == NULL); g_assert (g_list_find (list, fixture->action3) != NULL); + + g_assert (menu_contains_button_with_label (fixture->action_menu, + gtk_action_get_label (fixture->action1))); + g_assert (!menu_contains_button_with_label (fixture->action_menu, + gtk_action_get_label (fixture->action2))); + g_assert (menu_contains_button_with_label (fixture->action_menu, + gtk_action_get_label (fixture->action3))); } void |