Expand the child of GtkHeaderBar

Yosef Or Boczko <[email protected]>
Newsgroups gmane.comp.gnome.gtk+.devel.general,gmane.comp.gnome.nautilus
Message-ID <[email protected]>
Good afternoon!

I am port the GtkToolbar to GtkHeaderBar in Nautilus (attached patch).

I could not to expand the patch-bar (child of header_bar).

The relevant code from patch (src/nautilus-header-bar.c):
...
GtkWidget *box, *hbox, *header_bar;
...
header_bar = gtk_header_bar_new ();
self->priv->header_bar = header_bar;
...
/* regular path bar */
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_widget_show (hbox);

self->priv->path_bar = g_object_new (NAUTILUS_TYPE_PATH_BAR, NULL);
gtk_widget_set_hexpand (self->priv->path_bar, TRUE);
gtk_box_pack_start (GTK_BOX (hbox), self->priv->path_bar, TRUE, TRUE, 
0);

/* entry-like location bar */
self->priv->location_entry = nautilus_location_entry_new ();
gtk_widget_set_hexpand (self->priv->location_entry, TRUE);
gtk_box_pack_start (GTK_BOX (hbox), self->priv->location_entry, TRUE, 
TRUE, 0);

gtk_widget_set_hexpand (hbox, TRUE);
gtk_header_bar_pack_start (GTK_HEADER_BAR (self->priv->header_bar), 
hbox);
gtk_widget_show (GTK_WIDGET (hbox));
...

The gtk_widget_set_hexpand function it does not affect.

Screenshost:
patch-bar:
https://bitbucket.org/yoseforb/expand-header-bar/raw/e95d5c963051d781c7c029751c8e1fbebbabd49b/patch-bar.png
location-bar:
https://bitbucket.org/yoseforb/expand-header-bar/raw/e95d5c963051d781c7c029751c8e1fbebbabd49b/location-bar.png

Regards,
‏Yosef Or Boczko

_______________________________________________
gtk-devel-list mailing list
[email protected]
https://mail.gnome.org/mailman/listinfo/gtk-devel-list
0002-Port-GtkToolbar-to-GtkHeaderBar.patch (text/x-patch, 13.5 KB)
From 9b0ed3f2e6d1c4e65f2706de4cd338515aa1de02 Mon Sep 17 00:00:00 2001
From: Yosef Or Boczko <[email protected]>
Date: Sun, 30 Jun 2013 13:48:44 +0300
Subject: Port GtkToolbar to GtkHeaderBar

---
 src/Makefile.am               |   4 +-
 src/nautilus-header-bar.c     | 628 +++++++++++++++++++++++++++++++++++++++++
 src/nautilus-header-bar.h     |  75 +++++
 src/nautilus-toolbar.c        | 642 ------------------------------------------
 src/nautilus-toolbar.h        |  77 -----
 src/nautilus-window-private.h |   2 +-
 src/nautilus-window-slot.c    |   2 +-
 src/nautilus-window.c         |  40 +--
 8 files changed, 727 insertions(+), 743 deletions(-)
 create mode 100644 src/nautilus-header-bar.c
 create mode 100644 src/nautilus-header-bar.h
 delete mode 100644 src/nautilus-toolbar.c
 delete mode 100644 src/nautilus-toolbar.h

diff --git a/src/Makefile.am b/src/Makefile.am
index 651fccc..61909e5 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -185,8 +185,8 @@ nautilus_SOURCES = \
 	nautilus-shell-search-provider.c	\
 	nautilus-special-location-bar.c		\
 	nautilus-special-location-bar.h		\
-	nautilus-toolbar.c			\
-	nautilus-toolbar.h			\
+	nautilus-header-bar.c			\
+	nautilus-header-bar.h			\
 	nautilus-trash-bar.c			\
 	nautilus-trash-bar.h			\
 	nautilus-view.c				\
diff --git a/src/nautilus-header-bar.c b/src/nautilus-header-bar.c
new file mode 100644
index 0000000..2eadbd7
--- /dev/null
+++ b/src/nautilus-header-bar.c
@@ -0,0 +1,628 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+
+/*
+ * Nautilus
+ *
+ * Copyright (C) 2011, Red Hat, Inc.
+ *
+ * Nautilus is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * Nautilus 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Author: Cosimo Cecchi <[email protected]>
+ *
+ */
+
+#include <config.h>
+
+#include "nautilus-header-bar.h"
+
+#include "nautilus-location-entry.h"
+#include "nautilus-pathbar.h"
+#include "nautilus-actions.h"
+
+#include <libnautilus-private/nautilus-global-preferences.h>
+#include <libnautilus-private/nautilus-ui-utilities.h>
+
+#include <glib/gi18n.h>
+#include <math.h>
+
+typedef enum {
+	NAUTILUS_NAVIGATION_DIRECTION_NONE,
+	NAUTILUS_NAVIGATION_DIRECTION_BACK,
+	NAUTILUS_NAVIGATION_DIRECTION_FORWARD
+} NautilusNavigationDirection;
+
+struct _NautilusHeaderBarPriv {
+	GtkWidget *header_bar;
+	NautilusWindow *window;
+
+	GtkWidget *path_bar;
+	GtkWidget *location_entry;
+
+	GtkToolItem *back_forward;
+
+	gboolean show_location_entry;
+
+	guint popup_timeout_id;
+};
+
+enum {
+	PROP_WINDOW = 1,
+	PROP_SHOW_LOCATION_ENTRY,
+	NUM_PROPERTIES
+};
+
+static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
+
+G_DEFINE_TYPE (NautilusHeaderBar, nautilus_header_bar, GTK_TYPE_BOX);
+
+static void unschedule_menu_popup_timeout (NautilusHeaderBar *self);
+
+static void
+header_bar_update_appearance (NautilusHeaderBar *self)
+{
+	gboolean show_location_entry;
+
+	show_location_entry = self->priv->show_location_entry ||
+		g_settings_get_boolean (nautilus_preferences, NAUTILUS_PREFERENCES_ALWAYS_USE_LOCATION_ENTRY);
+
+	gtk_widget_set_visible (self->priv->location_entry,
+				show_location_entry);
+	gtk_widget_set_visible (self->priv->path_bar,
+				!show_location_entry);
+}
+
+static gint
+get_icon_margin (NautilusHeaderBar *self)
+{
+	GtkIconSize toolbar_size;
+	gint toolbar_size_px, menu_size_px;
+
+	g_object_get (gtk_settings_get_default (), "gtk-toolbar-icon-size", &toolbar_size, NULL);
+	/* toolbar_size = GTK_ICON_SIZE_SMALL_TOOLBAR; */
+
+	gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &menu_size_px, NULL);
+	gtk_icon_size_lookup (toolbar_size, &toolbar_size_px, NULL);
+
+	return (gint) floor ((toolbar_size_px - menu_size_px) / 2.0);
+}
+
+static GtkWidget *
+header_bar_create_toolbutton (NautilusHeaderBar *self,
+			      gboolean create_menu,
+			      gboolean create_toggle,
+			      const gchar *name,
+			      const gchar *tooltip)
+{
+	GtkWidget *button, *image;
+	GtkActionGroup *action_group;
+	GtkAction *action;
+
+	action_group = nautilus_window_get_main_action_group (self->priv->window);
+
+	if (create_menu) {
+		button = gtk_menu_button_new ();
+	} else if (create_toggle) {
+		button = gtk_toggle_button_new ();
+	} else {
+		button = gtk_button_new ();
+	}
+
+	image = gtk_image_new ();
+	g_object_set (image, "margin", get_icon_margin (self), NULL);
+
+	gtk_button_set_image (GTK_BUTTON (button), image);
+
+	if (create_menu) {
+		gtk_image_set_from_icon_name (GTK_IMAGE (image), name,
+					      GTK_ICON_SIZE_MENU);
+		gtk_widget_set_tooltip_text (button, tooltip);
+	} else {
+		action = gtk_action_group_get_action (action_group, name);
+		gtk_activatable_set_related_action (GTK_ACTIVATABLE (button), action);
+		gtk_button_set_label (GTK_BUTTON (button), NULL);
+		gtk_widget_set_tooltip_text (button, gtk_action_get_tooltip (action));
+	}
+
+	return button;
+}
+
+static void
+activate_back_or_forward_menu_item (GtkMenuItem *menu_item, 
+				    NautilusWindow *window,
+				    gboolean back)
+{
+	int index;
+	
+	g_assert (GTK_IS_MENU_ITEM (menu_item));
+
+	index = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (menu_item), "user_data"));
+
+	nautilus_window_back_or_forward (window, back, index, nautilus_event_get_window_open_flags ());
+}
+
+static void
+activate_back_menu_item_callback (GtkMenuItem *menu_item,
+                                  NautilusWindow *window)
+{
+	activate_back_or_forward_menu_item (menu_item, window, TRUE);
+}
+
+static void
+activate_forward_menu_item_callback (GtkMenuItem *menu_item, NautilusWindow *window)
+{
+	activate_back_or_forward_menu_item (menu_item, window, FALSE);
+}
+
+static void
+fill_menu (NautilusWindow *window,
+	   GtkWidget *menu,
+	   gboolean back)
+{
+	NautilusWindowSlot *slot;
+	GtkWidget *menu_item;
+	int index;
+	GList *list;
+
+	slot = nautilus_window_get_active_slot (window);
+	list = back ? nautilus_window_slot_get_back_history (slot) :
+		nautilus_window_slot_get_forward_history (slot);
+
+	index = 0;
+	while (list != NULL) {
+		menu_item = nautilus_bookmark_menu_item_new (NAUTILUS_BOOKMARK (list->data));
+		g_object_set_data (G_OBJECT (menu_item), "user_data", GINT_TO_POINTER (index));
+		gtk_widget_show (GTK_WIDGET (menu_item));
+  		g_signal_connect_object (menu_item, "activate",
+					 back
+					 ? G_CALLBACK (activate_back_menu_item_callback)
+					 : G_CALLBACK (activate_forward_menu_item_callback),
+					 window, 0);
+
+		gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
+		list = g_list_next (list);
+		++index;
+	}
+}
+
+/* adapted from gtk/gtkmenubutton.c */
+static void
+menu_position_func (GtkMenu       *menu,
+		    gint          *x,
+		    gint          *y,
+		    gboolean      *push_in,
+		    GtkWidget     *widget)
+{
+	GtkWidget *toplevel;
+	GtkRequisition menu_req;
+	GdkRectangle monitor;
+	gint monitor_num;
+	GdkScreen *screen;
+	GdkWindow *window;
+	GtkAllocation allocation;
+
+	/* Set the dropdown menu hint on the toplevel, so the WM can omit the top side
+	 * of the shadows.
+	 */
+	toplevel = gtk_widget_get_toplevel (GTK_WIDGET (menu));
+	gtk_window_set_type_hint (GTK_WINDOW (toplevel), GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU);
+
+	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_preferred_size (GTK_WIDGET (menu), &menu_req, NULL);
+	gtk_widget_get_allocation (widget, &allocation);
+	gdk_window_get_origin (window, x, y);
+
+	*x += allocation.x;
+	*y += allocation.y;
+
+	if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) {
+		*x -= MAX (menu_req.width - allocation.width, 0);
+	} else {
+		*x += MAX (allocation.width - menu_req.width, 0);
+	}
+
+	if ((*y + allocation.height + menu_req.height) <= monitor.y + monitor.height) {
+		*y += allocation.height;
+	} else if ((*y - menu_req.height) >= monitor.y) {
+		*y -= menu_req.height;
+	} else if (monitor.y + monitor.height - (*y + allocation.height) > *y) {
+		*y += allocation.height;
+	} else {
+		*y -= menu_req.height;
+	}
+
+	*push_in = FALSE;
+}
+
+static void
+show_menu (NautilusHeaderBar *self,
+	   GtkWidget *widget,
+           guint button,
+           guint32 event_time)
+{
+	NautilusWindow *window;
+	GtkWidget *menu;
+	NautilusNavigationDirection direction;
+
+	window = self->priv->window;
+	menu = gtk_menu_new ();
+
+	direction = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (widget),
+							 "nav-direction"));
+
+	switch (direction) {
+	case NAUTILUS_NAVIGATION_DIRECTION_FORWARD:
+		fill_menu (window, menu, FALSE);
+		break;
+	case NAUTILUS_NAVIGATION_DIRECTION_BACK:
+		fill_menu (window, menu, TRUE);
+		break;
+	default:
+		g_assert_not_reached ();
+		break;
+	}
+
+        gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
+			(GtkMenuPositionFunc) menu_position_func, widget,
+                        button, event_time);
+}
+
+#define MENU_POPUP_TIMEOUT 1200
+
+typedef struct {
+	NautilusHeaderBar *self;
+	GtkWidget *widget;
+} ScheduleMenuData;
+
+static void
+schedule_menu_data_free (ScheduleMenuData *data)
+{
+	g_slice_free (ScheduleMenuData, data);
+}
+
+static gboolean
+popup_menu_timeout_cb (gpointer user_data)
+{
+	ScheduleMenuData *data = user_data;
+
+        show_menu (data->self, data->widget,
+		   1, gtk_get_current_event_time ());
+
+        return FALSE;
+}
+
+static void
+unschedule_menu_popup_timeout (NautilusHeaderBar *self)
+{
+        if (self->priv->popup_timeout_id != 0) {
+                g_source_remove (self->priv->popup_timeout_id);
+                self->priv->popup_timeout_id = 0;
+        }
+}
+
+static void
+schedule_menu_popup_timeout (NautilusHeaderBar *self,
+			     GtkWidget *widget)
+{
+	ScheduleMenuData *data;
+
+        /* unschedule any previous timeouts */
+        unschedule_menu_popup_timeout (self);
+
+	data = g_slice_new0 (ScheduleMenuData);
+	data->self = self;
+	data->widget = widget;
+
+        self->priv->popup_timeout_id =
+                g_timeout_add_full (G_PRIORITY_DEFAULT, MENU_POPUP_TIMEOUT,
+				    popup_menu_timeout_cb, data,
+				    (GDestroyNotify) schedule_menu_data_free);
+}
+
+static gboolean
+tool_button_press_cb (GtkButton *button,
+                      GdkEventButton *event,
+                      gpointer user_data)
+{
+        NautilusHeaderBar *self = user_data;
+
+        if (event->button == 3) {
+                /* right click */
+                show_menu (self, GTK_WIDGET (button), event->button, event->time);
+                return TRUE;
+        }
+
+        if (event->button == 1) {
+                schedule_menu_popup_timeout (self, GTK_WIDGET (button));
+        }
+
+	return FALSE;
+}
+
+static gboolean
+tool_button_release_cb (GtkButton *button,
+                        GdkEventButton *event,
+                        gpointer user_data)
+{
+        NautilusHeaderBar *self = user_data;
+
+        unschedule_menu_popup_timeout (self);
+
+        return FALSE;
+}
+
+static void
+navigation_button_setup_menu (NautilusHeaderBar *self,
+			      GtkWidget *button,
+			      NautilusNavigationDirection direction)
+{
+	g_object_set_data (G_OBJECT (button), "nav-direction", GUINT_TO_POINTER (direction));
+
+	g_signal_connect (button, "button-press-event",
+			  G_CALLBACK (tool_button_press_cb), self);
+	g_signal_connect (button, "button-release-event",
+			  G_CALLBACK (tool_button_release_cb), self);
+}
+
+static gboolean
+gear_menu_key_press (GtkWidget *widget,
+                     GdkEventKey *event,
+                     gpointer user_data)
+{
+        GdkModifierType mask = gtk_accelerator_get_default_mod_mask ();
+
+        if ((event->state & mask) == 0 && (event->keyval == GDK_KEY_F10)) {
+            gtk_menu_shell_deactivate (GTK_MENU_SHELL (widget));
+            return TRUE;
+        }
+
+        return FALSE;
+}
+
+static void
+nautilus_header_bar_constructed (GObject *obj)
+{
+	NautilusHeaderBar *self = NAUTILUS_HEADER_BAR (obj);
+	GtkWidget *box, *hbox, *header_bar;
+	GtkWidget *tool_button;
+	GtkWidget *menu;
+	GtkWidget *back_forward;
+	GtkUIManager *ui_manager;
+
+	G_OBJECT_CLASS (nautilus_header_bar_parent_class)->constructed (obj);
+
+	ui_manager = nautilus_window_get_ui_manager (self->priv->window);
+
+	gtk_style_context_set_junction_sides (gtk_widget_get_style_context (GTK_WIDGET (self)),
+					      GTK_JUNCTION_BOTTOM);
+
+	header_bar = gtk_header_bar_new ();
+	self->priv->header_bar = header_bar;
+
+	gtk_box_pack_start (GTK_BOX (self), self->priv->header_bar, TRUE, TRUE, 0);
+	//~ gtk_window_set_titlebar (GTK_WINDOW (self->priv->window), self->priv->header_bar);
+	gtk_widget_show_all (self->priv->header_bar);
+
+	/* Back and Forward */
+	back_forward = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+	/* Back */
+	tool_button = header_bar_create_toolbutton (self, FALSE, FALSE, NAUTILUS_ACTION_BACK, NULL);
+	navigation_button_setup_menu (self, tool_button, NAUTILUS_NAVIGATION_DIRECTION_BACK);
+	gtk_container_add (GTK_CONTAINER (back_forward), GTK_WIDGET (tool_button));
+
+	/* Forward */
+	tool_button = header_bar_create_toolbutton (self, FALSE, FALSE, NAUTILUS_ACTION_FORWARD, NULL);
+	navigation_button_setup_menu (self, tool_button, NAUTILUS_NAVI
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.