Blob Blame History Raw
From fb97b62aad23bb44820713c8084785bbc147bfd7 Mon Sep 17 00:00:00 2001
From: Michael Webster <miketwebster@gmail.com>
Date: Sun, 27 Dec 2015 11:31:57 -0500
Subject: [PATCH] improve context menu toggle: - shows separate distinct
 regions of the menu item now - tooltip manifests as right-justified text next
 to the toggle icon

---
 data/icons/Makefile.am                             |   2 +
 ...tions_scalable_collapse-menu-hover-symbolic.svg |  62 +++
 ...lor_actions_scalable_collapse-menu-symbolic.svg |   4 +-
 ...actions_scalable_expand-menu-hover-symbolic.svg |  62 +++
 ...color_actions_scalable_expand-menu-symbolic.svg |   8 +-
 libnemo-private/Makefile.am                        |   2 +
 libnemo-private/nemo-context-menu-menu-item.c      | 452 +++++++++++++++++++++
 libnemo-private/nemo-context-menu-menu-item.h      |  71 ++++
 libnemo-private/nemo-widget-action.c               |  58 ++-
 libnemo-private/nemo-widget-action.h               |   5 +
 src/nemo-actions.h                                 |   1 +
 src/nemo-directory-view-ui.xml                     |   2 +-
 src/nemo-view.c                                    | 273 +++----------
 13 files changed, 765 insertions(+), 237 deletions(-)
 create mode 100644 data/icons/hicolor_actions_scalable_collapse-menu-hover-symbolic.svg
 create mode 100644 data/icons/hicolor_actions_scalable_expand-menu-hover-symbolic.svg
 create mode 100644 libnemo-private/nemo-context-menu-menu-item.c
 create mode 100644 libnemo-private/nemo-context-menu-menu-item.h

diff --git a/data/icons/Makefile.am b/data/icons/Makefile.am
index b590ed9..b573ec2 100644
--- a/data/icons/Makefile.am
+++ b/data/icons/Makefile.am
@@ -19,7 +19,9 @@ public_icons = \
 	hicolor_actions_scalable_sidebar-tree-symbolic.svg \
 	hicolor_actions_scalable_sidebar-places-symbolic.svg \
 	hicolor_actions_scalable_expand-menu-symbolic.svg \
+	hicolor_actions_scalable_expand-menu-hover-symbolic.svg \
 	hicolor_actions_scalable_collapse-menu-symbolic.svg \
+	hicolor_actions_scalable_collapse-menu-hover-symbolic.svg \
 	hicolor_status_48x48_progress-0.png \
 	hicolor_status_48x48_progress-10.png \
 	hicolor_status_48x48_progress-20.png \
diff --git a/data/icons/hicolor_actions_scalable_collapse-menu-hover-symbolic.svg b/data/icons/hicolor_actions_scalable_collapse-menu-hover-symbolic.svg
new file mode 100644
index 0000000..dce477a
--- /dev/null
+++ b/data/icons/hicolor_actions_scalable_collapse-menu-hover-symbolic.svg
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   id="svg7384"
+   height="16"
+   width="16"
+   version="1.1"
+   inkscape:version="0.91 r"
+   sodipodi:docname="hicolor_actions_scalable_collapse-menu-hover-symbolic.svg">
+  <defs
+     id="defs9" />
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1920"
+     inkscape:window-height="1003"
+     id="namedview7"
+     showgrid="false"
+     inkscape:zoom="14.75"
+     inkscape:cx="-15.050847"
+     inkscape:cy="8"
+     inkscape:window-x="0"
+     inkscape:window-y="25"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="svg7384" />
+  <metadata
+     id="metadata90">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title>Gnome Symbolic Icon Theme</dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <title
+     id="title9167">Gnome Symbolic Icon Theme</title>
+  <path
+     style="fill:#bebebe;fill-opacity:1"
+     d="M 9.5,1.5 A 6.5,6.5 0 0 0 3,8 6.5,6.5 0 0 0 9.5,14.5 6.5,6.5 0 0 0 16,8 6.5,6.5 0 0 0 9.5,1.5 Z M 6,7 13,7 13,9 6,9 6,7 Z"
+     id="path4223"
+     inkscape:connector-curvature="0" />
+  <g
+     id="layer12"
+     transform="matrix(0.70002797,0,0,1,-25.601203,-726.0002)" />
+</svg>
diff --git a/data/icons/hicolor_actions_scalable_collapse-menu-symbolic.svg b/data/icons/hicolor_actions_scalable_collapse-menu-symbolic.svg
index 6080b8e..940a236 100644
--- a/data/icons/hicolor_actions_scalable_collapse-menu-symbolic.svg
+++ b/data/icons/hicolor_actions_scalable_collapse-menu-symbolic.svg
@@ -31,7 +31,7 @@
      id="namedview7"
      showgrid="false"
      inkscape:zoom="14.75"
-     inkscape:cx="-3.4237288"
+     inkscape:cx="-15.050847"
      inkscape:cy="8"
      inkscape:window-x="0"
      inkscape:window-y="25"
@@ -53,7 +53,7 @@
      id="title9167">Gnome Symbolic Icon Theme</title>
   <g
      id="layer12"
-     transform="matrix(0.70002797,0,0,1,-23.601203,-726)">
+     transform="matrix(0.70002797,0,0,1,-24.101203,-726.0002)">
     <rect
        id="rect31984"
        style="color:#bebebe;fill:#bebebe"
diff --git a/data/icons/hicolor_actions_scalable_expand-menu-hover-symbolic.svg b/data/icons/hicolor_actions_scalable_expand-menu-hover-symbolic.svg
new file mode 100644
index 0000000..41821f9
--- /dev/null
+++ b/data/icons/hicolor_actions_scalable_expand-menu-hover-symbolic.svg
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   id="svg7384"
+   height="16"
+   width="16"
+   version="1.1"
+   inkscape:version="0.91 r"
+   sodipodi:docname="hicolor_actions_scalable_expand-menu-hover-symbolic.svg">
+  <defs
+     id="defs9" />
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1920"
+     inkscape:window-height="1003"
+     id="namedview7"
+     showgrid="false"
+     inkscape:zoom="14.75"
+     inkscape:cx="-13.305229"
+     inkscape:cy="10.71689"
+     inkscape:window-x="0"
+     inkscape:window-y="25"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="svg7384" />
+  <metadata
+     id="metadata90">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title>Gnome Symbolic Icon Theme</dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <title
+     id="title9167">Gnome Symbolic Icon Theme</title>
+  <path
+     id="path4223"
+     style="fill:#bebebe;fill-opacity:1"
+     d="M 9.5,2.4999998 A 5.5,5.5 0 0 0 4,8 5.5,5.5 0 0 0 9.5,13.5 5.5,5.5 0 0 0 15,8 5.5,5.5 0 0 0 9.5,2.4999998 Z m -1,2 2,0 L 10.5,7 13,7 l 0,2 -2.5,0 0,2.5 -2,0 L 8.5,9 6,9 6,7 8.5,7 8.5,4.4999998 Z M 9.5,1.5 A 6.5,6.5 0 0 0 3,8 6.5,6.5 0 0 0 9.5,14.5 6.5,6.5 0 0 0 16,8 6.5,6.5 0 0 0 9.5,1.5 Z m 0,1.5 a 5,5 0 0 1 5,5 5,5 0 0 1 -5,5 5,5 0 0 1 -5,-5 5,5 0 0 1 5,-5 z"
+     inkscape:connector-curvature="0" />
+  <g
+     id="layer12-7"
+     transform="matrix(0,-0.70002797,1,0,-726,41.601203)" />
+</svg>
diff --git a/data/icons/hicolor_actions_scalable_expand-menu-symbolic.svg b/data/icons/hicolor_actions_scalable_expand-menu-symbolic.svg
index 494886f..faaea15 100644
--- a/data/icons/hicolor_actions_scalable_expand-menu-symbolic.svg
+++ b/data/icons/hicolor_actions_scalable_expand-menu-symbolic.svg
@@ -31,8 +31,8 @@
      id="namedview7"
      showgrid="false"
      inkscape:zoom="14.75"
-     inkscape:cx="-14.983051"
-     inkscape:cy="8"
+     inkscape:cx="-22.187982"
+     inkscape:cy="8.2033898"
      inkscape:window-x="0"
      inkscape:window-y="25"
      inkscape:window-maximized="1"
@@ -53,7 +53,7 @@
      id="title9167">Gnome Symbolic Icon Theme</title>
   <g
      id="layer12"
-     transform="matrix(0.70002797,0,0,1,-23.601203,-726)">
+     transform="matrix(0.70002797,0,0,1,-24.101203,-726)">
     <rect
        id="rect31984"
        style="color:#bebebe;fill:#bebebe"
@@ -64,7 +64,7 @@
   </g>
   <g
      id="layer12-7"
-     transform="matrix(0,-0.70002797,1,0,-724,41.601203)">
+     transform="matrix(0,-0.70002797,1,0,-724.5,41.601203)">
     <rect
        id="rect31984-6"
        style="color:#bebebe;fill:#bebebe"
diff --git a/libnemo-private/Makefile.am b/libnemo-private/Makefile.am
index 0a8ab6c..9a28a7b 100644
--- a/libnemo-private/Makefile.am
+++ b/libnemo-private/Makefile.am
@@ -75,6 +75,8 @@ libnemo_private_la_SOURCES = \
 	nemo-column-chooser.h \
 	nemo-column-utilities.c \
 	nemo-column-utilities.h \
+	nemo-context-menu-menu-item.c \
+	nemo-context-menu-menu-item.h \
 	nemo-dbus-manager.c \
 	nemo-dbus-manager.h \
 	nemo-debug.c \
diff --git a/libnemo-private/nemo-context-menu-menu-item.c b/libnemo-private/nemo-context-menu-menu-item.c
new file mode 100644
index 0000000..7491610
--- /dev/null
+++ b/libnemo-private/nemo-context-menu-menu-item.c
@@ -0,0 +1,452 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <config.h>
+
+#include "nemo-global-preferences.h"
+#include "nemo-context-menu-menu-item.h"
+#include "nemo-widget-action.h"
+
+#include <glib/gi18n.h>
+
+static GtkActivatableIface *parent_activatable_iface;
+
+static void nemo_context_menu_menu_item_dispose              (GObject *object);
+
+static gboolean nemo_context_menu_menu_item_enter      (GtkWidget        *widget,
+                                          GdkEventCrossing *event);
+static gboolean nemo_context_menu_menu_item_leave      (GtkWidget        *widget,
+                                          GdkEventCrossing *event);
+static gboolean nemo_context_menu_menu_item_motion     (GtkWidget        *widget,
+                                          GdkEventMotion   *event);
+
+static gboolean nemo_context_menu_menu_item_button_press (GtkWidget      *widget,
+                                                          GdkEventButton *event);
+
+static gboolean nemo_context_menu_menu_item_button_release (GtkWidget      *widget,
+                                                            GdkEventButton *event);
+
+static void nemo_context_menu_menu_item_set_label (GtkMenuItem      *menu_item,
+                                                   const gchar      *label);
+
+static void nemo_context_menu_menu_item_activatable_interface_init (GtkActivatableIface  *iface);
+
+G_DEFINE_TYPE_WITH_CODE (NemoContextMenuMenuItem, nemo_context_menu_menu_item, GTK_TYPE_IMAGE_MENU_ITEM,
+                         G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE,
+                                                nemo_context_menu_menu_item_activatable_interface_init));
+
+static void
+set_action_image_temporary_visibility (NemoContextMenuMenuItem *item,
+                                       gboolean                 visible)
+{
+    GtkWidget *image = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (item));
+
+    if (!visible) {
+        gtk_widget_set_visible (image, FALSE);
+    } else {
+        if (gtk_image_menu_item_get_always_show_image (GTK_IMAGE_MENU_ITEM (item))) {
+            gtk_widget_set_visible (image, TRUE);
+        }
+    }
+}
+
+static void
+update_toggle_state (NemoContextMenuMenuItem *item,
+                     gboolean                 from_event,
+                     gboolean                 on_item)
+{
+    gboolean complex_mode = g_settings_get_boolean (nemo_preferences, NEMO_PREFERENCES_CONTEXT_MENUS_SHOW_ALL_ACTIONS);
+
+    /* const */ gchar *tip_text = complex_mode ? _("Show less actions") :
+                                                 _("Show more actions");
+
+    gchar *markup = g_strdup_printf ("<small><i>%s</i></small>", tip_text);
+
+    gtk_label_set_markup (GTK_LABEL (item->toggle_label_widget), markup);
+
+    g_free (markup);
+
+    if (item->on_toggle) {
+        set_action_image_temporary_visibility (item, FALSE);
+        gtk_stack_set_visible_child_name (GTK_STACK (item->stack), "toggle");
+    } else {
+        set_action_image_temporary_visibility (item, TRUE);
+        gtk_stack_set_visible_child_name (GTK_STACK (item->stack), "action");
+    }
+
+    GtkStyleContext *context = gtk_widget_get_style_context (GTK_WIDGET (item));
+
+    if (on_item) {
+        gtk_image_set_from_icon_name (GTK_IMAGE (item->toggle_widget),
+                                      complex_mode ? "collapse-menu-hover-symbolic" : "expand-menu-hover-symbolic",
+                                      GTK_ICON_SIZE_MENU);
+    } else {
+        gtk_image_set_from_icon_name (GTK_IMAGE (item->toggle_widget),
+                                      complex_mode ? "collapse-menu-symbolic" : "expand-menu-symbolic",
+                                      GTK_ICON_SIZE_MENU);
+    }
+
+    GtkStateFlags default_item_state = from_event ? GTK_STATE_FLAG_PRELIGHT : gtk_style_context_get_state (context);
+
+    gtk_style_context_set_state (context, item->on_toggle ? GTK_STATE_FLAG_NORMAL : default_item_state);
+
+    gtk_widget_queue_draw (GTK_WIDGET (item));
+}
+
+static void
+update_toggle_appearance_from_event (GtkWidget *widget,
+                                     gint       x,
+                                     gint       y,
+                                     gboolean   on_item)
+{
+    NemoContextMenuMenuItem *item = NEMO_CONTEXT_MENU_MENU_ITEM (widget);
+    GtkAllocation alloc;
+
+    gtk_widget_get_allocation (item->toggle_widget, &alloc);
+
+    item->on_toggle = ((x >= alloc.x) &&
+                       (x <= alloc.x + alloc.width) &&
+                       (y >= alloc.y) &&
+                       (y <= alloc.y + alloc.height));
+
+    update_toggle_state (item, TRUE, on_item);
+}
+
+static void
+nemo_context_menu_menu_item_class_init (NemoContextMenuMenuItemClass *klass)
+{
+    GObjectClass *gobject_class = (GObjectClass*) klass;
+    GtkMenuItemClass *menu_item_class = (GtkMenuItemClass*) klass;
+    GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+    gobject_class->dispose = nemo_context_menu_menu_item_dispose;
+
+    menu_item_class->set_label = nemo_context_menu_menu_item_set_label;
+
+    widget_class->enter_notify_event = nemo_context_menu_menu_item_enter;
+    widget_class->leave_notify_event = nemo_context_menu_menu_item_leave;
+    widget_class->motion_notify_event = nemo_context_menu_menu_item_motion;
+    widget_class->button_press_event = nemo_context_menu_menu_item_button_press;
+    widget_class->button_release_event = nemo_context_menu_menu_item_button_release;
+}
+
+static void 
+nemo_context_menu_menu_item_init (NemoContextMenuMenuItem *item)
+{
+    item->on_toggle = FALSE;
+    GtkWidget *box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+    GtkWidget *stack = gtk_stack_new ();
+
+    item->stack = stack;
+
+    GtkWidget *label = gtk_label_new (NULL);
+    gtk_misc_set_alignment (GTK_MISC (label), 0.98, 0.5);
+    gtk_stack_add_named (GTK_STACK (stack), label, "toggle");
+    item->toggle_label_widget = label;
+
+    label = gtk_label_new (NULL);
+    gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+    gtk_stack_add_named (GTK_STACK (stack), label, "action");
+    item->label_widget = label;
+
+    gtk_box_pack_start (GTK_BOX (box), stack, TRUE, TRUE, 0);
+
+    GtkWidget *toggle = gtk_image_new ();
+    gtk_box_pack_end (GTK_BOX (box), toggle, FALSE, FALSE, 0);
+    item->toggle_widget = toggle;
+
+    gtk_widget_show_all (box);
+
+    gtk_container_add (GTK_CONTAINER (item), box);
+
+    update_toggle_state (item, FALSE, FALSE);
+
+    item->settings_monitor_id = g_signal_connect_swapped (nemo_preferences, 
+                                                          "changed::" NEMO_PREFERENCES_CONTEXT_MENUS_SHOW_ALL_ACTIONS,
+                                                          G_CALLBACK (update_toggle_state),
+                                                          item);
+}
+
+static void
+nemo_context_menu_menu_item_dispose (GObject *object)
+{
+    NemoContextMenuMenuItem *item = NEMO_CONTEXT_MENU_MENU_ITEM (object);
+
+    if (item->settings_monitor_id > 0) {
+        g_signal_handler_disconnect (nemo_preferences, item->settings_monitor_id);
+        item->settings_monitor_id = 0;
+    }
+
+    G_OBJECT_CLASS (nemo_context_menu_menu_item_parent_class)->dispose (object);
+}
+
+static gboolean
+nemo_context_menu_menu_item_enter (GtkWidget        *widget,
+                                   GdkEventCrossing *event)
+{
+    g_return_val_if_fail (event != NULL, FALSE);
+
+    update_toggle_appearance_from_event (widget, event->x, event->y, TRUE);
+
+    return gtk_widget_event (gtk_widget_get_parent (widget), (GdkEvent *) event);
+}
+
+static gboolean
+nemo_context_menu_menu_item_leave (GtkWidget        *widget,
+                                   GdkEventCrossing *event)
+{
+    g_return_val_if_fail (event != NULL, FALSE);
+
+    update_toggle_appearance_from_event (widget, event->x, event->y, FALSE);
+
+    return gtk_widget_event (gtk_widget_get_parent (widget), (GdkEvent *) event);
+}
+
+static gboolean
+nemo_context_menu_menu_item_motion (GtkWidget        *widget,
+                                    GdkEventMotion   *event)
+{
+    g_return_val_if_fail (event != NULL, FALSE);
+
+    update_toggle_appearance_from_event (widget, event->x, event->y, TRUE);
+
+    return gtk_widget_event (gtk_widget_get_parent (widget), (GdkEvent *) event);
+}
+
+static gboolean
+nemo_context_menu_menu_item_button_press (GtkWidget      *widget,
+                                          GdkEventButton *event)
+{
+    NemoContextMenuMenuItem *item = NEMO_CONTEXT_MENU_MENU_ITEM (widget);
+
+    if (event->button != GDK_BUTTON_PRIMARY)
+        return GDK_EVENT_PROPAGATE;
+
+    update_toggle_appearance_from_event (widget, event->x, event->y, TRUE);
+
+    if (item->on_toggle) {
+        g_settings_set_boolean (nemo_preferences,
+                                NEMO_PREFERENCES_CONTEXT_MENUS_SHOW_ALL_ACTIONS,
+                                !g_settings_get_boolean (nemo_preferences,
+                                                         NEMO_PREFERENCES_CONTEXT_MENUS_SHOW_ALL_ACTIONS));
+        return GDK_EVENT_STOP;
+    }
+
+    return GDK_EVENT_PROPAGATE;
+}
+
+static gboolean
+nemo_context_menu_menu_item_button_release (GtkWidget      *widget,
+                                            GdkEventButton *event)
+{
+    NemoContextMenuMenuItem *item = NEMO_CONTEXT_MENU_MENU_ITEM (widget);
+
+    if (event->button != GDK_BUTTON_PRIMARY &&
+        event->button != GDK_BUTTON_SECONDARY)
+        return GDK_EVENT_PROPAGATE;
+
+    update_toggle_appearance_from_event (widget, event->x, event->y, TRUE);
+
+    if (item->on_toggle) {
+        return GDK_EVENT_STOP;
+    }
+
+    return GDK_EVENT_PROPAGATE;
+}
+
+static void
+nemo_context_menu_menu_item_set_label (GtkMenuItem      *menu_item,
+                                       const gchar      *label)
+{
+    NemoContextMenuMenuItem *item = NEMO_CONTEXT_MENU_MENU_ITEM (menu_item);
+
+    if (item->label != label)
+    {
+        g_free (item->label);
+        item->label = g_strdup (label);
+
+        gtk_label_set_text_with_mnemonic (GTK_LABEL (item->label_widget), label);
+
+        g_object_notify (G_OBJECT (menu_item), "label");
+    }
+}
+
+static gboolean
+activatable_update_stock_id (GtkImageMenuItem *image_menu_item,
+                             GtkAction        *action)
+{
+    GtkWidget   *image;
+    const gchar *stock_id  = gtk_action_get_stock_id (action);
+
+    image = gtk_image_menu_item_get_image (image_menu_item);
+
+    if (GTK_IS_IMAGE (image) &&
+        stock_id && gtk_icon_factory_lookup_default (stock_id)) {
+        gtk_image_set_from_stock (GTK_IMAGE (image), stock_id, GTK_ICON_SIZE_MENU);
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
+static gboolean
+activatable_update_gicon (GtkImageMenuItem *image_menu_item,
+                          GtkAction        *action)
+{
+    GtkWidget   *image;
+    GIcon       *icon = gtk_action_get_gicon (action);
+    const gchar *stock_id;
+    gboolean     ret = FALSE;
+
+    stock_id = gtk_action_get_stock_id (action);
+
+    image = gtk_image_menu_item_get_image (image_menu_item);
+
+    if (icon && GTK_IS_IMAGE (image) &&
+        !(stock_id && gtk_icon_factory_lookup_default (stock_id))) {
+        gtk_image_set_from_gicon (GTK_IMAGE (image), icon, GTK_ICON_SIZE_MENU);
+        ret = TRUE;
+    }
+
+    return ret;
+}
+
+static void
+activatable_update_icon_name (GtkImageMenuItem *image_menu_item,
+                              GtkAction        *action)
+{
+    GtkWidget   *image;
+    const gchar *icon_name = gtk_action_get_icon_name (action);
+
+    image = gtk_image_menu_item_get_image (image_menu_item);
+
+    if (GTK_IS_IMAGE (image) &&
+        (gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_EMPTY ||
+         gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_ICON_NAME)) {
+        gtk_image_set_from_icon_name (GTK_IMAGE (image), icon_name, GTK_ICON_SIZE_MENU);
+    }
+}
+
+static void
+activatable_update_label (GtkMenuItem *menu_item, GtkAction *action)
+{
+    const gchar *label;
+    label = gtk_action_get_label (action);
+    nemo_context_menu_menu_item_set_label (menu_item, label);
+}
+
+static void
+nemo_context_menu_menu_item_update (GtkActivatable *activatable,
+                                    GtkAction      *action,
+                                    const gchar    *property_name)
+{
+    if (!gtk_activatable_get_use_action_appearance (activatable))
+        return;
+    if (strcmp (property_name, "label") == 0)
+        activatable_update_label (GTK_MENU_ITEM (activatable), action);
+    else if (strcmp (property_name, "stock-id") == 0)
+        activatable_update_stock_id (GTK_IMAGE_MENU_ITEM (activatable), action);
+    else if (strcmp (property_name, "gicon") == 0)
+        activatable_update_gicon (GTK_IMAGE_MENU_ITEM (activatable), action);
+    else if (strcmp (property_name, "icon-name") == 0)
+        activatable_update_icon_name (GTK_IMAGE_MENU_ITEM (activatable), action);
+}
+
+static void
+menu_item_sync_action_properties (NemoContextMenuMenuItem *menu_item,
+                                  GtkAction               *action)
+{
+    GtkImageMenuItem *image_menu_item;
+    GtkActivatable *activatable;
+    GtkWidget *image;
+    gboolean   use_appearance;
+
+    image_menu_item = GTK_IMAGE_MENU_ITEM (menu_item);
+
+    activatable = GTK_ACTIVATABLE (image_menu_item);
+
+    if (!action)
+        return;
+
+    use_appearance = gtk_activatable_get_use_action_appearance (activatable);
+    if (!use_appearance)
+        return;
+
+    image = gtk_image_menu_item_get_image (image_menu_item);
+    if (image && !GTK_IS_IMAGE (image)) {
+        gtk_image_menu_item_set_image (image_menu_item, NULL);
+        image = NULL;
+    }
+
+    if (!image) {
+        image = gtk_image_new ();
+        gtk_widget_show (image);
+        gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (activatable),
+                                       image);
+    }
+
+    if (!activatable_update_stock_id (image_menu_item, action) &&
+        !activatable_update_gicon (image_menu_item, action))
+        activatable_update_icon_name (image_menu_item, action);
+
+    gtk_image_menu_item_set_always_show_image (image_menu_item,
+                                               gtk_action_get_always_show_image (action));
+
+    activatable_update_label (GTK_MENU_ITEM (menu_item), action);
+}
+
+static void
+nemo_context_menu_menu_item_sync_action_properties (GtkActivatable *activatable,
+                                                    GtkAction      *action)
+{
+    NemoContextMenuMenuItem *context_menu_menu_item;
+
+    context_menu_menu_item = NEMO_CONTEXT_MENU_MENU_ITEM (activatable);
+
+    if (!action)
+        return;
+
+    if (!gtk_activatable_get_use_action_appearance (activatable))
+        return;
+
+    menu_item_sync_action_properties (context_menu_menu_item, action);
+
+    gtk_widget_show (GTK_WIDGET (context_menu_menu_item));
+}
+
+static void
+nemo_context_menu_menu_item_activatable_interface_init (GtkActivatableIface  *iface)
+{
+    parent_activatable_iface = g_type_interface_peek_parent (iface);
+    iface->update = nemo_context_menu_menu_item_update;
+    iface->sync_action_properties = nemo_context_menu_menu_item_sync_action_properties;
+}
+
+/**
+ * nemo_context_menu_menu_item_new:
+ * @widget: The custom widget to use
+ *
+ * Creates a new #NemoContextMenuMenuItem.
+ *
+ * Returns: a new #NemoContextMenuMenuItem.
+ */
+GtkWidget *
+nemo_context_menu_menu_item_new (GtkWidget *widget)
+{
+    return g_object_new (NEMO_TYPE_CONTEXT_MENU_MENU_ITEM,
+                         NULL);
+}
diff --git a/libnemo-private/nemo-context-menu-menu-item.h b/libnemo-private/nemo-context-menu-menu-item.h
new file mode 100644
index 0000000..bb032e9
--- /dev/null
+++ b/libnemo-private/nemo-context-menu-menu-item.h
@@ -0,0 +1,71 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
+ */
+
+#ifndef __NEMO_CONTEXT_MENU_MENU_ITEM_H__
+#define __NEMO_CONTEXT_MENU_MENU_ITEM_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define NEMO_TYPE_CONTEXT_MENU_MENU_ITEM            (nemo_context_menu_menu_item_get_type ())
+#define NEMO_CONTEXT_MENU_MENU_ITEM(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NEMO_TYPE_CONTEXT_MENU_MENU_ITEM, NemoContextMenuMenuItem))
+#define NEMO_CONTEXT_MENU_MENU_ITEM_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NEMO_TYPE_CONTEXT_MENU_MENU_ITEM, NemoContextMenuMenuItemClass))
+#define NEMO_IS_CONTEXT_MENU_MENU_ITEM(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NEMO_TYPE_CONTEXT_MENU_MENU_ITEM))
+#define NEMO_IS_CONTEXT_MENU_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NEMO_TYPE_CONTEXT_MENU_MENU_ITEM))
+#define NEMO_CONTEXT_MENU_MENU_ITEM_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NEMO_TYPE_CONTEXT_MENU_MENU_ITEM, NemoContextMenuMenuItemClass))
+
+
+typedef struct _NemoContextMenuMenuItem       NemoContextMenuMenuItem;
+typedef struct _NemoContextMenuMenuItemClass  NemoContextMenuMenuItemClass;
+
+struct _NemoContextMenuMenuItem
+{
+  GtkImageMenuItem menu_item;
+
+  gchar *label;
+  GtkWidget *stack;
+  GtkWidget *label_widget;
+  GtkWidget *toggle_label_widget;
+  GtkWidget *toggle_widget;
+
+  gulong settings_monitor_id;
+  gboolean on_toggle;
+};
+
+/**
+ * NemoContextMenuMenuItemClass:
+ * @parent_class: The parent class.
+ */
+struct _NemoContextMenuMenuItemClass
+{
+  GtkImageMenuItemClass parent_class;
+};
+
+GType      nemo_context_menu_menu_item_get_type    (void) G_GNUC_CONST;
+GtkWidget *nemo_context_menu_menu_item_new             (GtkWidget *widget);
+
+G_END_DECLS
+
+#endif /* __NEMO_CONTEXT_MENU_MENU_ITEM_H__ */
diff --git a/libnemo-private/nemo-widget-action.c b/libnemo-private/nemo-widget-action.c
index 5ca13de..ceafb2a 100644
--- a/libnemo-private/nemo-widget-action.c
+++ b/libnemo-private/nemo-widget-action.c
@@ -19,6 +19,7 @@
 
 #include "nemo-widget-action.h"
 #include "nemo-widget-menu-item.h"
+#include "nemo-context-menu-menu-item.h"
 
 G_DEFINE_TYPE (NemoWidgetAction, nemo_widget_action,
 	       GTK_TYPE_ACTION);
@@ -62,6 +63,7 @@ nemo_widget_action_init (NemoWidgetAction *action)
     action->widget_b = NULL;
     action->a_used = FALSE;
     action->b_used = FALSE;
+    action->is_menu_toggle = FALSE;
 }
 
 static void
@@ -118,6 +120,22 @@ nemo_widget_action_new (const gchar *name,
                          NULL);
 }
 
+GtkAction *
+nemo_widget_action_new_for_menu_toggle (const gchar *name,
+                                        const gchar *label,
+                                        const gchar *tooltip)
+{
+    GtkAction *ret = g_object_new (NEMO_TYPE_WIDGET_ACTION,
+                                   "name", name,
+                                   "label", label,
+                                   "tooltip", tooltip,
+                                   NULL);
+
+    NEMO_WIDGET_ACTION (ret)->is_menu_toggle = TRUE;
+
+    return ret;
+}
+
 static void
 nemo_widget_action_finalize (GObject *object)
 {
@@ -198,29 +216,35 @@ create_menu_item (GtkAction *action)
 {
   NemoWidgetAction *widget_action;
   GType menu_item_type;
-  GtkWidget *w, *ret;
-  gint slot;
+  GtkWidget *w;
+  GtkWidget *ret = NULL;
+  gint slot = -1;
 
   widget_action = NEMO_WIDGET_ACTION (action);
   menu_item_type = GTK_ACTION_GET_CLASS (action)->menu_item_type;
 
-  if (!widget_action->a_used) {
-    w = widget_action->widget_a;
-    widget_action->a_used = TRUE;
-    slot = ACTION_SLOT_A;
-  } else if (!widget_action->b_used) {
-    w = widget_action->widget_b;
-    widget_action->b_used = TRUE;
-    slot = ACTION_SLOT_B;
-  } else
-    return NULL;
+  if (widget_action->is_menu_toggle) {
+    ret = g_object_new (NEMO_TYPE_CONTEXT_MENU_MENU_ITEM, NULL);
+  } else {
+    if (!widget_action->a_used) {
+      w = widget_action->widget_a;
+      widget_action->a_used = TRUE;
+      slot = ACTION_SLOT_A;
+    } else if (!widget_action->b_used) {
+      w = widget_action->widget_b;
+      widget_action->b_used = TRUE;
+      slot = ACTION_SLOT_B;
+    }
 
-  ret = g_object_new (menu_item_type,
-                      "child-widget", w,
-                      "action-slot", slot,
-                      NULL);
+    if (slot != -1)
+      ret = g_object_new (menu_item_type,
+                          "child-widget", w,
+                          "action-slot", slot,
+                          NULL);
+  }
 
-  gtk_activatable_set_related_action (GTK_ACTIVATABLE (ret), action);
+  if (ret)
+    gtk_activatable_set_related_action (GTK_ACTIVATABLE (ret), action);
 
   return ret;
 }
diff --git a/libnemo-private/nemo-widget-action.h b/libnemo-private/nemo-widget-action.h
index 9674ce8..a55c17f 100644
--- a/libnemo-private/nemo-widget-action.h
+++ b/libnemo-private/nemo-widget-action.h
@@ -44,6 +44,7 @@ struct _NemoWidgetAction {
     GtkWidget *widget_b;
     gboolean a_used;
     gboolean b_used;
+    gboolean is_menu_toggle;
 };
 
 struct _NemoWidgetActionClass {
@@ -59,6 +60,10 @@ GType         nemo_widget_action_get_type             (void);
 GtkAction    *nemo_widget_action_new                  (const gchar *name,
                                                        GtkWidget *widget_a,
                                                        GtkWidget *widget_b);
+GtkAction    *nemo_widget_action_new_for_menu_toggle (const gchar *name,
+                                                      const gchar *label,
+                                                      const gchar *tooltip);
+
 void          nemo_widget_action_activate             (NemoWidgetAction *action);
 GtkWidget *   nemo_widget_action_get_widget_a (NemoWidgetAction *action);
 void          nemo_widget_action_set_widget_a (NemoWidgetAction *action, GtkWidget *widget);
diff --git a/src/nemo-actions.h b/src/nemo-actions.h
index 22998a3..adbbc73 100644
--- a/src/nemo-actions.h
+++ b/src/nemo-actions.h
@@ -60,6 +60,7 @@
 #define NEMO_ACTION_NEW_TAB "New Tab"
 
 #define NEMO_ACTION_OPEN "Open"
+#define NEMO_ACTION_OPEN_TOGGLE "OpenToggle"
 #define NEMO_ACTION_OPEN_ALTERNATE "OpenAlternate"
 #define NEMO_ACTION_OPEN_IN_NEW_TAB "OpenInNewTab"
 #define NEMO_ACTION_LOCATION_OPEN_ALTERNATE "LocationOpenAlternate"
diff --git a/src/nemo-directory-view-ui.xml b/src/nemo-directory-view-ui.xml
index d136eb3..e30a3f6 100644
--- a/src/nemo-directory-view-ui.xml
+++ b/src/nemo-directory-view-ui.xml
@@ -147,7 +147,7 @@
 </popup>
 <popup name="selection">
 	<placeholder name="Open Placeholder">
-		<menuitem name="Open" action="Open"/>
+		<menuitem name="OpenToggle" action="OpenToggle"/>
 		<menuitem name="OpenInNewTab" action="OpenInNewTab"/>
 		<menuitem name="OpenAlternate" action="OpenAlternate"/>
 		<separator name="applications separator"/>
diff --git a/src/nemo-view.c b/src/nemo-view.c
index 19de9bd..eb44927 100644
--- a/src/nemo-view.c
+++ b/src/nemo-view.c
@@ -127,7 +127,7 @@
 #define NEMO_VIEW_POPUP_PATH_SCRIPTS_PLACEHOLDER    	  "/selection/Open Placeholder/Scripts/Scripts Placeholder"
 #define NEMO_VIEW_POPUP_PATH_ACTIONS_PLACEHOLDER           "/selection/Open Placeholder/ActionsPlaceholder"
 #define NEMO_VIEW_POPUP_PATH_EXTENSION_ACTIONS		  "/selection/Extension Actions"
-#define NEMO_VIEW_POPUP_PATH_OPEN				  "/selection/Open Placeholder/Open"
+#define NEMO_VIEW_POPUP_PATH_OPEN				  "/selection/Open Placeholder/OpenToggle"
 
 #define NEMO_VIEW_POPUP_PATH_BACKGROUND			  "/background"
 #define NEMO_VIEW_POPUP_PATH_BACKGROUND_SCRIPTS_PLACEHOLDER	  "/background/Before Zoom Items/New Object Items/Scripts/Scripts Placeholder"
@@ -193,12 +193,6 @@ struct NemoViewDetails
 	GtkActionGroup *dir_action_group;
 	guint dir_merge_id;
 
-    GtkWidget *expander_menu_widget;
-    GtkWidget *menu_widget_ref;
-    GtkWidget *expander_label_widget;
-    guint menu_expander_click_handler_id;
-    gchar *expander_tooltip_text;
-
 	gboolean supports_zooming;
 
 	GList *scripts_directory_list;
@@ -2686,12 +2680,6 @@ nemo_view_init (NemoView *view)
 	/* Default to true; desktop-icon-view sets to false */
 	view->details->show_foreign_files = TRUE;
 
-    view->details->expander_menu_widget = NULL;
-    view->details->menu_widget_ref = NULL;
-    view->details->expander_label_widget = NULL;
-    view->details->menu_expander_click_handler_id = 0;
-    view->details->expander_tooltip_text = NULL;
-
 	view->details->non_ready_files =
 		g_hash_table_new_full (file_and_directory_hash,
 				       file_and_directory_equal,
@@ -2779,6 +2767,10 @@ nemo_view_init (NemoView *view)
 
     nemo_to_menu_preferences_changed_callback (view);
 
+    g_signal_connect_swapped (nemo_preferences,
+                              "changed::" NEMO_PREFERENCES_CONTEXT_MENUS_SHOW_ALL_ACTIONS,
+                              G_CALLBACK (schedule_update_menus), view);
+
 	manager = nemo_file_undo_manager_get ();
 	g_signal_connect_object (manager, "undo-changed",
 				 G_CALLBACK (undo_manager_changed_cb), view, 0);				  
@@ -2871,15 +2863,6 @@ nemo_view_destroy (GtkWidget *object)
 
 	view = NEMO_VIEW (object);
 
-    if (view->details->expander_menu_widget != NULL) {
-        gtk_widget_destroy (view->details->expander_menu_widget);
-    }
-
-    if (view->details->menu_expander_click_handler_id > 0) {
-        g_signal_handler_disconnect (view->details->menu_widget_ref, view->details->menu_expander_click_handler_id);
-        view->details->menu_expander_click_handler_id = 0;
-    }
-
 	disconnect_model_handlers (view);
 
     if (view->details->bookmarks_changed_id != 0) {
@@ -2975,6 +2958,9 @@ nemo_view_finalize (GObject *object)
     g_signal_handlers_disconnect_by_func (nemo_preferences,
                           nemo_to_menu_preferences_changed_callback, view);
 
+    g_signal_handlers_disconnect_by_func (nemo_preferences,
+                          schedule_update_menus, view);
+
 	unschedule_pop_up_location_context_menu (view);
 	if (view->details->location_popup_event != NULL) {
 		gdk_event_free ((GdkEvent *) view->details->location_popup_event);
@@ -6639,163 +6625,6 @@ update_templates_menu (NemoView *view)
 	g_free (templates_directory_uri);
 }
 
-static void ensure_expander_attached (NemoView *view, GtkWidget *menu_item);
-
-static void
-on_expander_destroyed (GtkWidget *widget, NemoView *view)
-{
-    view->details->expander_menu_widget = NULL;
-}
-
-static void
-on_menu_destroyed (GtkWidget *widget, NemoView *view)
-{
-    view->details->menu_widget_ref = NULL;
-    view->details->expander_label_widget = NULL;
-}
-
-static gboolean
-pointer_in_expander_widget (GtkWidget *widget, gint x, gint y)
-{
-    GtkAllocation alloc;
-
-    gtk_widget_get_allocation (widget, &alloc);
-
-    return ((x >= alloc.x) &&
-            (x <= alloc.x + alloc.width) &&
-            (y >= alloc.y) &&
-            (y <= alloc.y + alloc.height));
-}
-
-static gboolean
-on_query_menu_tooltip (GtkWidget  *widget,
-                       gint        x,
-                       gint        y,
-                       gboolean    keyboard_mode,
-                       GtkTooltip *tooltip,
-                       gpointer    user_data)
-{
-    NemoView *view = NEMO_VIEW (user_data);
-
-    if (view->details->expander_menu_widget != NULL &&
-        pointer_in_expander_widget (view->details->expander_menu_widget, x, y)) {
-        gtk_tooltip_set_text (tooltip, view->details->expander_tooltip_text);
-        return TRUE;
-    }
-
-    gtk_tooltip_set_text (tooltip, NULL);
-    return FALSE;
-}
-
-static GtkWidget *
-get_expander_widget_and_tooltip (NemoView *view, gchar **tooltip)
-{
-    if (view->details->expander_menu_widget != NULL)
-        gtk_widget_destroy (view->details->expander_menu_widget);
-
-    gboolean complex_mode = g_settings_get_boolean (nemo_preferences,
-                                                    NEMO_PREFERENCES_CONTEXT_MENUS_SHOW_ALL_ACTIONS);
-
-    GtkWidget *widget = gtk_image_new_from_icon_name (complex_mode ? "collapse-menu-symbolic" : "expand-menu-symbolic",
-                                                      GTK_ICON_SIZE_MENU);
-
-    *tooltip = complex_mode ? _("Show less actions") : _("Show more actions");
-
-    g_signal_connect (widget, "destroy", G_CALLBACK (on_expander_destroyed), view);
-
-    return widget;
-}
-
-static void
-attach_expander (NemoView *view, GtkWidget *widget, GtkWidget *expander)
-{
-    GtkWidget *parent = gtk_widget_get_parent (widget);
-    GtkWidget *hbox = NULL;
-
-    if (!GTK_IS_LABEL (widget) && !GTK_IS_BOX (widget))
-        return;
-
-    if (GTK_IS_LABEL (widget)) {
-        g_object_ref (widget);
-
-        hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
-
-        gtk_container_remove (GTK_CONTAINER (parent), widget);
-        gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 0);
-        gtk_container_add (GTK_CONTAINER (parent), hbox);
-
-        view->details->expander_label_widget = widget;
-
-        g_object_unref (widget);
-    }
-
-    if (GTK_IS_BOX (widget)) {
-        hbox = widget;
-    }
-
-    gtk_box_pack_end (GTK_BOX (hbox), expander, FALSE, FALSE, 0);
-}
-
-static gboolean
-on_menu_button_released (GtkWidget *widget, GdkEvent *event, NemoView *view)
-{
-    if (event->button.button != GDK_BUTTON_PRIMARY)
-        return FALSE;
-
-    gint ev_x = (gint) event->button.x;
-    gint ev_y = (gint) event->button.y;
-
-    if (pointer_in_expander_widget (view->details->expander_menu_widget, ev_x, ev_y)) {
-        g_settings_set_boolean (nemo_preferences,
-                                NEMO_PREFERENCES_CONTEXT_MENUS_SHOW_ALL_ACTIONS,
-                                !g_settings_get_boolean (nemo_preferences,
-                                                         NEMO_PREFERENCES_CONTEXT_MENUS_SHOW_ALL_ACTIONS));
-        ensure_expander_attached (view, widget);
-        schedule_update_menus (view);
-        return TRUE;
-    }
-
-    return FALSE;
-}
-
-static void
-ensure_expander_attached (NemoView *view, GtkWidget *menu_item)
-{
-    gchar *tooltip = NULL;
-
-    GtkWidget *expander = get_expander_widget_and_tooltip (view, &tooltip);
-
-    view->details->expander_menu_widget = expander;
-
-    g_clear_pointer (&view->details->expander_tooltip_text, g_free);
-    view->details->expander_tooltip_text = g_strdup (tooltip);
-
-    GtkWidget *child = gtk_bin_get_child (GTK_BIN (menu_item));
-
-    attach_expander (view, child, expander);
-
-    gtk_widget_show_all (menu_item);
-
-    if (view->details->menu_expander_click_handler_id == 0) {
-        view->details->menu_expander_click_handler_id = g_signal_connect (menu_item,
-                                                                          "button-release-event",
-                                                                          G_CALLBACK (on_menu_button_released),
-                                                                          view);
-    }
-
-    if (view->details->menu_widget_ref == NULL) {
-        view->details->menu_widget_ref = menu_item;
-        g_signal_connect (menu_item, "destroy", G_CALLBACK (on_menu_destroyed), view);
-    }
-
-    gtk_widget_set_has_tooltip (menu_item, TRUE);
-
-    g_signal_handlers_disconnect_matched (menu_item, G_SIGNAL_MATCH_FUNC,
-                                          0, 0, NULL, on_query_menu_tooltip, NULL);
-
-    g_signal_connect (menu_item, "query-tooltip", G_CALLBACK (on_query_menu_tooltip), view);
-}
-
 static GtkMenu *
 create_popup_menu (NemoView *view, const char *popup_path)
 {
@@ -8268,7 +8097,7 @@ static const GtkActionEntry directory_view_entries[] = {
   /* name, stock id */         { "Open", NULL,
   /* label, accelerator */       N_("_Open"), "<control>o",
   /* tooltip */                  N_("Open the selected item in this window"),
-				 G_CALLBACK (action_open_callback) },
+                 G_CALLBACK (action_open_callback) },
   /* name, stock id */         { "OpenAccel", NULL,
   /* label, accelerator */       "OpenAccel", "<alt>Down",
   /* tooltip */                  NULL,
@@ -8603,6 +8432,17 @@ pre_activate (NemoView *view,
 	}
 }
 
+static GtkAction *
+get_expander_action (NemoView *view)
+{
+    GtkAction *action = nemo_widget_action_new_for_menu_toggle ("OpenToggle", N_("_Open"),
+                                                                N_("Open the selected item in this window"));
+
+    g_signal_connect (action, "activate", G_CALLBACK (action_open_callback), view);
+
+    return action;
+}
+
 static void
 real_merge_menus (NemoView *view)
 {
@@ -8620,6 +8460,9 @@ real_merge_menus (NemoView *view)
 				      directory_view_entries, G_N_ELEMENTS (directory_view_entries),
 				      view);
 
+    /* Add the special Open action with built-in menu toggle*/
+    gtk_action_group_add_action (action_group, get_expander_action (view));
+
 	tooltip = g_strdup_printf (_("Run scripts"));
 	/* Create a script action here specially because its tooltip is dynamic */
 	action = gtk_action_new ("Scripts", _("_Scripts"), tooltip, NULL);
@@ -9630,6 +9473,7 @@ update_complex_popup_items (NemoView *view)
 static void
 real_update_menus (NemoView *view)
 {
+    GtkWidget *menuitem;
 	GList *selection, *l;
 	gint selection_count;
 	const char *tip, *label;
@@ -9656,7 +9500,7 @@ real_update_menus (NemoView *view)
 	GtkAction *action;
 	GAppInfo *app;
 	GIcon *app_icon;
-	GtkWidget *menuitem;
+	// GtkWidget *menuitem;
 	gboolean next_pane_is_writable;
 	gboolean show_properties;
 
@@ -9711,10 +9555,6 @@ real_update_menus (NemoView *view)
 	gtk_action_set_sensitive (action, can_create_files);
     gtk_action_set_visible (action, !selection_contains_recent);
 
-	action = gtk_action_group_get_action (view->details->dir_action_group,
-					      NEMO_ACTION_OPEN);
-	gtk_action_set_sensitive (action, selection_count != 0);
-	
 	can_open = show_app = selection_count != 0;
 
 	for (l = selection; l != NULL; l = l->next) {
@@ -9756,43 +9596,50 @@ real_update_menus (NemoView *view)
 		g_object_unref (app);
 	}
 
-	g_object_set (action, "label", 
-		      label_with_underscore ? label_with_underscore : _("_Open"),
-		      NULL);
+	if (app_icon == NULL) {
+		app_icon = g_themed_icon_new (GTK_STOCK_OPEN);
+	}
 
-    if (view->details->expander_label_widget) {
-        gtk_label_set_text_with_mnemonic (GTK_LABEL (view->details->expander_label_widget),
-                                          label_with_underscore ? label_with_underscore : _("_Open"));
-    }
+    action = gtk_action_group_get_action (view->details->dir_action_group,
+                          NEMO_ACTION_OPEN);
+    gtk_action_set_sensitive (action, selection_count != 0);
 
-	menuitem = gtk_ui_manager_get_widget (
-					      nemo_window_get_ui_manager (view->details->window),
-					      NEMO_VIEW_MENU_PATH_OPEN);
+    g_object_set (action, "label", 
+              label_with_underscore ? label_with_underscore : _("_Open"),
+              NULL);
 
-	/* Only force displaying the icon if it is an application icon */
-	gtk_image_menu_item_set_always_show_image (
-						   GTK_IMAGE_MENU_ITEM (menuitem), app_icon != NULL);
+    gtk_action_set_gicon (action, app_icon);
+    gtk_action_set_visible (action, can_open);
 
-	menuitem = gtk_ui_manager_get_widget (
-					      nemo_window_get_ui_manager (view->details->window),
-					      NEMO_VIEW_POPUP_PATH_OPEN);
+    action = gtk_action_group_get_action (view->details->dir_action_group,
+                          NEMO_ACTION_OPEN_TOGGLE);
+    gtk_action_set_sensitive (action, selection_count != 0);
 
-    ensure_expander_attached (view, menuitem);
+    g_object_set (action, "label", 
+              label_with_underscore ? label_with_underscore : _("_Open"),
+              NULL);
 
-	/* Only force displaying the icon if it is an application icon */
-	gtk_image_menu_item_set_always_show_image (
-						   GTK_IMAGE_MENU_ITEM (menuitem), app_icon != NULL);
+    gtk_action_set_gicon (action, app_icon);
+    gtk_action_set_visible (action, can_open);
 
-	if (app_icon == NULL) {
-		app_icon = g_themed_icon_new (GTK_STOCK_OPEN);
-	}
+    g_object_unref (app_icon);
+    g_free (label_with_underscore);
 
-	gtk_action_set_gicon (action, app_icon);
-	g_object_unref (app_icon);
+    menuitem = gtk_ui_manager_get_widget (
+                          nemo_window_get_ui_manager (view->details->window),
+                          NEMO_VIEW_MENU_PATH_OPEN);
 
-	gtk_action_set_visible (action, can_open);
-	
-	g_free (label_with_underscore);
+    /* Only force displaying the icon if it is an application icon */
+    gtk_image_menu_item_set_always_show_image (
+                           GTK_IMAGE_MENU_ITEM (menuitem), app_icon != NULL);
+
+    menuitem = gtk_ui_manager_get_widget (
+                          nemo_window_get_ui_manager (view->details->window),
+                          NEMO_VIEW_POPUP_PATH_OPEN);
+
+    /* Only force displaying the icon if it is an application icon */
+    gtk_image_menu_item_set_always_show_image (
+                           GTK_IMAGE_MENU_ITEM (menuitem), app_icon != NULL);
 
 	show_open_alternate = file_list_all_are_folders (selection) &&
 		selection_count > 0 &&
-- 
2.5.0