[gedit] Bug 698434 - Show popup on right-click for history buttons in file browser
- From: Garrett Regier <gregier src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gedit] Bug 698434 - Show popup on right-click for history buttons in file browser
- Date: Sun, 16 Jun 2013 16:02:10 +0000 (UTC)
commit e7ca301dc721af6082846c8e03bd6c20c867c4b2
Author: Garrett Regier <garrettregier gmail com>
Date: Sun Jun 16 08:43:17 2013 -0700
Bug 698434 - Show popup on right-click for history buttons in file browser
This is partially a reversion of:
https://git.gnome.org/browse/gedit/commit/?id=b69de75046faf4844d45fa67b772a68335b2ff57
plugins/filebrowser/gedit-file-browser-widget.c | 300 +++++++++++++++++++++-
plugins/filebrowser/gedit-file-browser-widget.ui | 12 +-
2 files changed, 304 insertions(+), 8 deletions(-)
---
diff --git a/plugins/filebrowser/gedit-file-browser-widget.c b/plugins/filebrowser/gedit-file-browser-widget.c
index 7b87514..6e485d0 100644
--- a/plugins/filebrowser/gedit-file-browser-widget.c
+++ b/plugins/filebrowser/gedit-file-browser-widget.c
@@ -124,6 +124,9 @@ struct _GeditFileBrowserWidgetPrivate
GMenuModel *dir_menu;
GMenuModel *bookmarks_menu;
+ GtkWidget *previous_button;
+ GtkWidget *next_button;
+
GtkWidget *combo;
GtkTreeStore *combo_model;
@@ -144,6 +147,9 @@ struct _GeditFileBrowserWidgetPrivate
GList *locations;
GList *current_location;
gboolean changing_location;
+ GtkWidget *location_previous_menu;
+ GtkWidget *location_next_menu;
+ GtkWidget *current_location_menu_item;
gboolean enable_delete;
@@ -168,6 +174,9 @@ static void on_file_store_error (GeditFileBrowserStore *store,
static gboolean on_file_store_no_trash (GeditFileBrowserStore *store,
GList *files,
GeditFileBrowserWidget *obj);
+static gboolean on_location_button_press_event (GtkWidget *button,
+ GdkEventButton *event,
+ GeditFileBrowserWidget *obj);
static void on_combo_changed (GtkComboBox *combo,
GeditFileBrowserWidget *obj);
static void on_location_entry_activate (GtkEntry *entry,
@@ -196,6 +205,8 @@ static void on_virtual_root_changed (GeditFileBrowserStore *model,
GeditFileBrowserWidget *obj);
static gboolean on_entry_filter_activate (GeditFileBrowserWidget *obj);
+static void on_location_jump_activate (GtkMenuItem *item,
+ GeditFileBrowserWidget *obj);
static void on_bookmarks_row_changed (GtkTreeModel *model,
GtkTreePath *path,
GtkTreeIter *iter,
@@ -399,6 +410,7 @@ gedit_file_browser_widget_dispose (GObject *object)
cancel_async_operation (obj);
+ g_clear_object (&obj->priv->current_location_menu_item);
g_clear_object (&priv->busy_cursor);
g_clear_object (&priv->dir_menu);
g_clear_object (&priv->bookmarks_menu);
@@ -544,11 +556,15 @@ gedit_file_browser_widget_class_init (GeditFileBrowserWidgetClass *klass)
/* Bind class to template */
gtk_widget_class_set_template_from_resource (widget_class,
"/org/gnome/gedit/plugins/file-browser/ui/gedit-file-browser-widget.ui");
+ gtk_widget_class_bind_child (widget_class, GeditFileBrowserWidgetPrivate, previous_button);
+ gtk_widget_class_bind_child (widget_class, GeditFileBrowserWidgetPrivate, next_button);
gtk_widget_class_bind_child (widget_class, GeditFileBrowserWidgetPrivate, combo);
gtk_widget_class_bind_child (widget_class, GeditFileBrowserWidgetPrivate, combo_model);
gtk_widget_class_bind_child (widget_class, GeditFileBrowserWidgetPrivate, location_entry);
gtk_widget_class_bind_child (widget_class, GeditFileBrowserWidgetPrivate, treeview);
gtk_widget_class_bind_child (widget_class, GeditFileBrowserWidgetPrivate, filter_entry);
+ gtk_widget_class_bind_child (widget_class, GeditFileBrowserWidgetPrivate, location_previous_menu);
+ gtk_widget_class_bind_child (widget_class, GeditFileBrowserWidgetPrivate, location_next_menu);
g_type_class_add_private (object_class,
sizeof (GeditFileBrowserWidgetPrivate));
@@ -988,6 +1004,11 @@ gedit_file_browser_widget_init (GeditFileBrowserWidget *obj)
gtk_widget_init_template (GTK_WIDGET (obj));
+ g_signal_connect (obj->priv->previous_button, "button-press-event",
+ G_CALLBACK (on_location_button_press_event), obj);
+ g_signal_connect (obj->priv->next_button, "button-press-event",
+ G_CALLBACK (on_location_button_press_event), obj);
+
/* combo */
fill_combo_model (obj);
g_signal_connect (obj->priv->combo, "changed",
@@ -1364,6 +1385,54 @@ get_topmost_file (GFile *file)
return current;
}
+static GtkWidget *
+create_goto_menu_item (GeditFileBrowserWidget *obj,
+ GList *item,
+ GdkPixbuf *icon)
+{
+ GtkWidget *result;
+ GtkWidget *image;
+ gchar *unescape;
+ GdkPixbuf *pixbuf = NULL;
+ Location *loc;
+
+ loc = (Location *) (item->data);
+
+ if (!get_from_bookmark_file (obj, loc->virtual_root, &unescape, &pixbuf))
+ {
+ unescape = gedit_file_browser_utils_file_basename (loc->virtual_root);
+
+ if (icon)
+ pixbuf = g_object_ref (icon);
+ }
+
+ if (pixbuf)
+ {
+ image = gtk_image_new_from_pixbuf (pixbuf);
+ g_object_unref (pixbuf);
+
+ gtk_widget_show (image);
+
+ result = gtk_image_menu_item_new_with_label (unescape);
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (result),
+ image);
+ }
+ else
+ {
+ result = gtk_menu_item_new_with_label (unescape);
+ }
+
+ g_object_set_data (G_OBJECT (result), LOCATION_DATA_KEY, item);
+ g_signal_connect (result, "activate",
+ G_CALLBACK (on_location_jump_activate), obj);
+
+ gtk_widget_show (result);
+
+ g_free (unescape);
+
+ return result;
+}
+
static GList *
list_next_iterator (GList *list)
{
@@ -1388,7 +1457,12 @@ jump_to_location (GeditFileBrowserWidget *obj,
gboolean previous)
{
Location *loc;
+ GtkWidget *widget;
+ GList *children;
+ GList *child;
GList *(*iter_func) (GList *);
+ GtkWidget *menu_from;
+ GtkWidget *menu_to;
if (!obj->priv->locations)
return;
@@ -1396,24 +1470,62 @@ jump_to_location (GeditFileBrowserWidget *obj,
if (previous)
{
iter_func = list_next_iterator;
+ menu_from = obj->priv->location_previous_menu;
+ menu_to = obj->priv->location_next_menu;
}
else
{
iter_func = list_prev_iterator;
+ menu_from = obj->priv->location_next_menu;
+ menu_to = obj->priv->location_previous_menu;
}
- obj->priv->changing_location = TRUE;
+ children = gtk_container_get_children (GTK_CONTAINER (menu_from));
+ child = children;
+
+ /* This is the menuitem for the current location, which is the first
+ to be added to the menu */
+ widget = obj->priv->current_location_menu_item;
- if (obj->priv->current_location != item)
+ while (obj->priv->current_location != item)
{
- obj->priv->current_location = iter_func (obj->priv->current_location);
+ if (widget)
+ {
+ /* Prepend the menu item to the menu */
+ gtk_menu_shell_prepend (GTK_MENU_SHELL (menu_to),
+ widget);
+
+ g_object_unref (widget);
+ }
+
+ widget = GTK_WIDGET (child->data);
+
+ /* Make sure the widget isn't destroyed when removed */
+ g_object_ref (widget);
+ gtk_container_remove (GTK_CONTAINER (menu_from), widget);
+
+ obj->priv->current_location_menu_item = widget;
if (obj->priv->current_location == NULL)
{
obj->priv->current_location = obj->priv->locations;
+
+ if (obj->priv->current_location == item)
+ break;
+ }
+ else
+ {
+ obj->priv->current_location =
+ iter_func (obj->priv->current_location);
}
+
+ child = child->next;
}
+ g_list_free (children);
+
+ obj->priv->changing_location = TRUE;
+
loc = (Location *) (obj->priv->current_location->data);
/* Set the new root + virtual root */
@@ -1428,6 +1540,8 @@ static void
clear_next_locations (GeditFileBrowserWidget *obj)
{
GAction *action;
+ GList *children;
+ GList *item;
if (obj->priv->current_location == NULL)
return;
@@ -1435,10 +1549,23 @@ clear_next_locations (GeditFileBrowserWidget *obj)
while (obj->priv->current_location->prev)
{
location_free ((Location *) (obj->priv->current_location->prev->data));
- obj->priv->locations = g_list_remove_link (obj->priv->locations,
- obj->priv->current_location->prev);
+ obj->priv->locations =
+ g_list_remove_link (obj->priv->locations,
+ obj->priv->current_location->prev);
}
+ children = gtk_container_get_children (GTK_CONTAINER
+ (obj->priv->location_next_menu));
+
+ for (item = children; item; item = item->next)
+ {
+ gtk_container_remove (GTK_CONTAINER
+ (obj->priv->location_next_menu),
+ GTK_WIDGET (item->data));
+ }
+
+ g_list_free (children);
+
action = g_simple_action_group_lookup (obj->priv->action_group,
"next_location");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE);
@@ -2316,6 +2443,16 @@ on_virtual_root_changed (GeditFileBrowserStore *model,
loc->root = gedit_file_browser_store_get_root (model);
loc->virtual_root = g_object_ref (location);
+ if (obj->priv->current_location)
+ {
+ /* Add current location to the menu so we can go back
+ to it later */
+ gtk_menu_shell_prepend
+ (GTK_MENU_SHELL
+ (obj->priv->location_previous_menu),
+ obj->priv->current_location_menu_item);
+ }
+
obj->priv->locations =
g_list_prepend (obj->priv->locations,
loc);
@@ -2325,7 +2462,14 @@ on_virtual_root_changed (GeditFileBrowserStore *model,
GEDIT_FILE_BROWSER_STORE_COLUMN_ICON,
&pixbuf, -1);
- obj->priv->current_location = obj->priv->locations;
+ obj->priv->current_location =
+ obj->priv->locations;
+ obj->priv->current_location_menu_item =
+ create_goto_menu_item (obj,
+ obj->priv->current_location,
+ pixbuf);
+
+ g_object_ref_sink (obj->priv->current_location_menu_item);
if (pixbuf)
{
@@ -2381,7 +2525,12 @@ on_model_set (GObject *gobject, GParamSpec *arg1,
{
GAction *action;
+ gtk_menu_shell_prepend (GTK_MENU_SHELL (obj->priv->location_previous_menu),
+ obj->priv->current_location_menu_item);
+
+ g_object_unref (obj->priv->current_location_menu_item);
obj->priv->current_location = NULL;
+ obj->priv->current_location_menu_item = NULL;
action = g_simple_action_group_lookup (obj->priv->action_group,
"previous_location");
@@ -2434,6 +2583,123 @@ on_treeview_error (GeditFileBrowserView *tree_view,
g_signal_emit (obj, signals[ERROR], 0, code, message);
}
+/* Copied from GTK+'s gtkmenubutton.c and modified */
+static void
+menu_position_func (GtkMenu *menu,
+ gint *x,
+ gint *y,
+ gboolean *push_in,
+ GtkWidget *widget)
+{
+ GtkWidget *popup = GTK_WIDGET (menu);
+ GtkWidget *toplevel;
+ GtkRequisition menu_req;
+ GtkTextDirection direction;
+ GdkRectangle monitor;
+ gint monitor_num;
+ GdkScreen *screen;
+ GdkWindow *window;
+ GtkAllocation allocation, arrow_allocation;
+ GtkAlign align;
+
+ /* Set the corresponding type hint on the toplevel,
+ * so the WM can omit the top side of the shadows.
+ */
+ toplevel = gtk_widget_get_toplevel (popup);
+ gtk_window_set_type_hint (GTK_WINDOW (toplevel),
+ GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU);
+
+ gtk_widget_get_preferred_size (popup, &menu_req, NULL);
+
+ align = gtk_widget_get_halign (popup);
+ direction = gtk_widget_get_direction (widget);
+ window = gtk_widget_get_window (widget);
+
+ screen = gtk_widget_get_screen (GTK_WIDGET (menu));
+ monitor_num = gdk_screen_get_monitor_at_window (screen, window);
+
+ if (monitor_num < 0)
+ {
+ monitor_num = 0;
+ }
+
+ gdk_screen_get_monitor_workarea (screen, monitor_num, &monitor);
+
+ gtk_widget_get_allocation (widget, &allocation);
+ gtk_widget_get_allocation (widget, &arrow_allocation);
+
+ gdk_window_get_origin (window, x, y);
+ *x += allocation.x;
+ *y += allocation.y;
+
+ /* treat the default align value like START */
+ if (align == GTK_ALIGN_FILL)
+ {
+ align = GTK_ALIGN_START;
+ }
+
+ if (align == GTK_ALIGN_CENTER)
+ {
+ *x -= (menu_req.width - allocation.width) / 2;
+ }
+ else if ((align == GTK_ALIGN_START && direction == GTK_TEXT_DIR_LTR) ||
+ (align == GTK_ALIGN_END && direction == GTK_TEXT_DIR_RTL))
+ {
+ *x += MAX (allocation.width - menu_req.width, 0);
+ }
+ else if (menu_req.width > allocation.width)
+ {
+ *x -= menu_req.width - allocation.width;
+ }
+
+ if ((*y + arrow_allocation.height + menu_req.height) <= monitor.y + monitor.height)
+ {
+ *y += arrow_allocation.height;
+ }
+ else if ((*y - menu_req.height) >= monitor.y)
+ {
+ *y -= menu_req.height;
+ }
+ else if (monitor.y + monitor.height - (*y + arrow_allocation.height) > *y)
+ {
+ *y += arrow_allocation.height;
+ }
+ else
+ {
+ *y -= menu_req.height;
+ }
+
+ *push_in = FALSE;
+}
+
+static gboolean
+on_location_button_press_event (GtkWidget *button,
+ GdkEventButton *event,
+ GeditFileBrowserWidget *obj)
+{
+ GtkWidget *menu;
+
+ if (event->button != GDK_BUTTON_SECONDARY)
+ {
+ return FALSE;
+ }
+
+ if (button == obj->priv->previous_button)
+ {
+ menu = obj->priv->location_previous_menu;
+ }
+ else
+ {
+ menu = obj->priv->location_next_menu;
+ }
+
+ gtk_menu_popup_for_device (GTK_MENU (menu), event->device, NULL, NULL,
+ (GtkMenuPositionFunc) menu_position_func,
+ button, NULL, event->button, event->time);
+
+ return TRUE;
+}
+
static void
on_combo_changed (GtkComboBox *combo,
GeditFileBrowserWidget *obj)
@@ -2760,6 +3026,28 @@ on_entry_filter_activate (GeditFileBrowserWidget *obj)
}
static void
+on_location_jump_activate (GtkMenuItem *item,
+ GeditFileBrowserWidget *obj)
+{
+ GList *location;
+
+ location = g_object_get_data (G_OBJECT (item), LOCATION_DATA_KEY);
+
+ if (obj->priv->current_location)
+ {
+ jump_to_location (obj, location,
+ g_list_position (obj->priv->locations,
+ location) >
+ g_list_position (obj->priv->locations,
+ obj->priv->current_location));
+ }
+ else
+ {
+ jump_to_location (obj, location, TRUE);
+ }
+}
+
+static void
on_bookmarks_row_changed (GtkTreeModel *model,
GtkTreePath *path,
GtkTreeIter *iter,
diff --git a/plugins/filebrowser/gedit-file-browser-widget.ui
b/plugins/filebrowser/gedit-file-browser-widget.ui
index b0acb0e..540580b 100644
--- a/plugins/filebrowser/gedit-file-browser-widget.ui
+++ b/plugins/filebrowser/gedit-file-browser-widget.ui
@@ -13,6 +13,14 @@
<column type="guint"/>
</columns>
</object>
+ <object class="GtkMenu" id="location_previous_menu">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <object class="GtkMenu" id="location_next_menu">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
<template class="GeditFileBrowserWidget" parent="GtkGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
@@ -40,7 +48,7 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
- <object class="GtkButton" id="button1">
+ <object class="GtkButton" id="previous_button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
@@ -61,7 +69,7 @@
</packing>
</child>
<child>
- <object class="GtkButton" id="button2">
+ <object class="GtkButton" id="next_button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]