[gedit] Add a fake notebook stack switcher
- From: Paolo Borelli <pborelli src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gedit] Add a fake notebook stack switcher
- Date: Thu, 1 May 2014 17:55:29 +0000 (UTC)
commit 09a7f9f3eba48f0d0ba58772921f70fa290c2e0a
Author: Paolo Borelli <pborelli gnome org>
Date: Thu May 1 16:22:04 2014 +0200
Add a fake notebook stack switcher
Add a stack switcher that it is actually implemented with a notebook
and empty pages. This is needed to make the bottom pane switcher look
like a real notebook but expose GtkStack in the API.
Hopefully this will be replaced by a real tabs stack switcher in Gtk.
gedit/Makefile.am | 2 +
gedit/gedit-notebook-stack-switcher.c | 345 +++++++++++++++++++++++++++++++++
gedit/gedit-notebook-stack-switcher.h | 71 +++++++
gedit/gedit-window.ui | 2 +-
4 files changed, 419 insertions(+), 1 deletions(-)
---
diff --git a/gedit/Makefile.am b/gedit/Makefile.am
index 71e19f2..23152c5 100644
--- a/gedit/Makefile.am
+++ b/gedit/Makefile.am
@@ -114,6 +114,7 @@ gedit_NOINST_H_FILES = \
gedit/gedit-multi-notebook.h \
gedit/gedit-notebook.h \
gedit/gedit-notebook-popup-menu.h \
+ gedit/gedit-notebook-stack-switcher.h \
gedit/gedit-plugins-engine.h \
gedit/gedit-preferences-dialog.h \
gedit/gedit-print-job.h \
@@ -191,6 +192,7 @@ gedit_libgedit_c_files = \
gedit/gedit-multi-notebook.c \
gedit/gedit-notebook.c \
gedit/gedit-notebook-popup-menu.c \
+ gedit/gedit-notebook-stack-switcher.c \
gedit/gedit-plugins-engine.c \
gedit/gedit-preferences-dialog.c \
gedit/gedit-print-job.c \
diff --git a/gedit/gedit-notebook-stack-switcher.c b/gedit/gedit-notebook-stack-switcher.c
new file mode 100644
index 0000000..a0cc449
--- /dev/null
+++ b/gedit/gedit-notebook-stack-switcher.c
@@ -0,0 +1,345 @@
+/*
+ * gedit-notebook-stack-switcher.h
+ * This file is part of gedit
+ *
+ * Copyright (C) 2014 - Paolo Borelli
+ *
+ * This program 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.
+ *
+ * This program 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include "gedit-notebook-stack-switcher.h"
+
+/*
+ * This widget is a rather ugly kludge: it uses a GtkNotebook full of empty
+ * pages to create a stack switcher for the bottom pane. This is needed
+ * because we want to expose GtkStack in the API but we want the tabs styled
+ * as notebook tabs. Hopefully Gtk itself will grow a "tabs" stack switcher...
+ */
+
+struct _GeditNotebookStackSwitcherPrivate
+{
+ GtkWidget *notebook;
+ GtkStack *stack;
+};
+
+enum {
+ PROP_0,
+ PROP_STACK
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (GeditNotebookStackSwitcher, gedit_notebook_stack_switcher, GTK_TYPE_BIN)
+
+static void
+gedit_notebook_stack_switcher_init (GeditNotebookStackSwitcher *switcher)
+{
+ GeditNotebookStackSwitcherPrivate *priv;
+
+ priv = gedit_notebook_stack_switcher_get_instance_private (switcher);
+ switcher->priv = priv;
+
+ priv->notebook = gtk_notebook_new ();
+
+ gtk_notebook_set_tab_pos (GTK_NOTEBOOK (priv->notebook), GTK_POS_BOTTOM);
+ gtk_notebook_set_scrollable (GTK_NOTEBOOK (priv->notebook), TRUE);
+ gtk_notebook_set_show_border (GTK_NOTEBOOK (priv->notebook), FALSE);
+ gtk_container_set_border_width (GTK_CONTAINER (priv->notebook), 0);
+
+ gtk_widget_show (priv->notebook);
+ gtk_container_add (GTK_CONTAINER (switcher), priv->notebook);
+}
+
+static GtkWidget *
+find_notebook_child (GeditNotebookStackSwitcher *switcher,
+ GtkWidget *stack_child)
+{
+ GeditNotebookStackSwitcherPrivate *priv = switcher->priv;
+ GList *pages;
+ GList *p;
+ GtkWidget *ret = NULL;
+
+ if (stack_child == NULL)
+ {
+ return NULL;
+ }
+
+ pages = gtk_container_get_children (GTK_CONTAINER (priv->notebook));
+ for (p = pages; p != NULL; p = p->next)
+ {
+ GtkWidget *child;
+
+ child = g_object_get_data (p->data, "stack-child");
+ if (stack_child == child)
+ {
+ ret = p->data;
+ break;
+ }
+ }
+
+ g_list_free (pages);
+
+ return ret;
+}
+
+static void
+sync_label (GeditNotebookStackSwitcher *switcher,
+ GtkWidget *stack_child,
+ GtkWidget *notebook_child)
+{
+ GeditNotebookStackSwitcherPrivate *priv = switcher->priv;
+
+ if (stack_child != NULL && notebook_child != NULL)
+ {
+ gchar *title;
+
+ gtk_widget_set_visible (notebook_child,
+ gtk_widget_get_visible (stack_child));
+
+ gtk_container_child_get (GTK_CONTAINER (priv->stack), stack_child,
+ "title", &title,
+ NULL);
+
+ gtk_notebook_set_tab_label_text (GTK_NOTEBOOK (priv->notebook),
+ notebook_child,
+ title);
+
+ g_free (title);
+ }
+}
+
+static void
+on_child_prop_changed (GtkWidget *widget,
+ GParamSpec *pspec,
+ GeditNotebookStackSwitcher *switcher)
+{
+ GtkWidget *nb_child;
+
+ nb_child = find_notebook_child (switcher, widget);
+ sync_label (switcher, widget, nb_child);
+}
+
+static void
+on_child_changed (GtkWidget *widget,
+ GParamSpec *pspec,
+ GeditNotebookStackSwitcher *switcher)
+{
+ GtkWidget *child;
+ GtkWidget *nb_child;
+
+ child = gtk_stack_get_visible_child (GTK_STACK (widget));
+ nb_child = find_notebook_child (switcher, child);
+ sync_label (switcher, child, nb_child);
+}
+
+static void
+on_stack_child_added (GtkStack *stack,
+ GtkWidget *widget,
+ GeditNotebookStackSwitcher *switcher)
+{
+ GeditNotebookStackSwitcherPrivate *priv = switcher->priv;
+ GtkWidget *dummy;
+
+ dummy = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+ g_object_set_data (G_OBJECT (dummy), "stack-child", widget);
+ gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook),
+ dummy,
+ NULL);
+
+ g_signal_connect (widget, "notify::visible",
+ G_CALLBACK (on_child_prop_changed), switcher);
+ g_signal_connect (widget, "child-notify::title",
+ G_CALLBACK (on_child_prop_changed), switcher);
+
+ sync_label (switcher, widget, dummy);
+}
+
+static void
+on_stack_child_removed (GtkStack *stack,
+ GtkWidget *widget,
+ GeditNotebookStackSwitcher *switcher)
+{
+ GeditNotebookStackSwitcherPrivate *priv = switcher->priv;
+ GtkWidget *nb_child;
+
+ g_signal_handlers_disconnect_by_func (widget, on_child_prop_changed, switcher);
+
+ nb_child = find_notebook_child (switcher, widget);
+ gtk_container_remove (GTK_CONTAINER (priv->notebook), nb_child);
+}
+
+static void
+on_notebook_switch_page (GtkNotebook *notebook,
+ GtkWidget *page,
+ guint page_num,
+ GeditNotebookStackSwitcher *switcher)
+{
+ GeditNotebookStackSwitcherPrivate *priv = switcher->priv;
+ GtkWidget *child;
+
+ child = g_object_get_data (G_OBJECT (page), "stack-child");
+ if (child != NULL)
+ {
+ gtk_stack_set_visible_child (priv->stack, child);
+ }
+}
+
+static void
+disconnect_signals (GeditNotebookStackSwitcher *switcher)
+{
+ GeditNotebookStackSwitcherPrivate *priv = switcher->priv;
+
+ g_signal_handlers_disconnect_by_func (priv->stack, on_stack_child_added, switcher);
+ g_signal_handlers_disconnect_by_func (priv->stack, on_stack_child_removed, switcher);
+ g_signal_handlers_disconnect_by_func (priv->stack, on_child_changed, switcher);
+ g_signal_handlers_disconnect_by_func (priv->stack, disconnect_signals, switcher);
+ g_signal_handlers_disconnect_by_func (priv->notebook, on_notebook_switch_page, switcher);
+}
+
+static void
+connect_signals (GeditNotebookStackSwitcher *switcher)
+{
+ GeditNotebookStackSwitcherPrivate *priv = switcher->priv;
+
+ g_signal_connect (priv->stack, "add",
+ G_CALLBACK (on_stack_child_added), switcher);
+ g_signal_connect (priv->stack, "remove",
+ G_CALLBACK (on_stack_child_removed), switcher);
+ g_signal_connect (priv->stack, "notify::visible-child",
+ G_CALLBACK (on_child_changed), switcher);
+ g_signal_connect_swapped (priv->stack, "destroy",
+ G_CALLBACK (disconnect_signals), switcher);
+ g_signal_connect (priv->notebook, "switch-page",
+ G_CALLBACK (on_notebook_switch_page), switcher);
+}
+
+void
+gedit_notebook_stack_switcher_set_stack (GeditNotebookStackSwitcher *switcher,
+ GtkStack *stack)
+{
+ GeditNotebookStackSwitcherPrivate *priv;
+
+ g_return_if_fail (GEDIT_IS_NOTEBOOK_STACK_SWITCHER (switcher));
+ g_return_if_fail (stack == NULL || GTK_IS_STACK (stack));
+
+ priv = switcher->priv;
+
+ if (priv->stack == stack)
+ return;
+
+ if (priv->stack)
+ {
+ disconnect_signals (switcher);
+ g_clear_object (&priv->stack);
+ }
+
+ if (stack)
+ {
+ priv->stack = g_object_ref (stack);
+ connect_signals (switcher);
+ }
+
+ g_object_notify (G_OBJECT (switcher), "stack");
+}
+
+GtkStack *
+gedit_notebook_stack_switcher_get_stack (GeditNotebookStackSwitcher *switcher)
+{
+ g_return_val_if_fail (GEDIT_IS_NOTEBOOK_STACK_SWITCHER (switcher), NULL);
+
+ return switcher->priv->stack;
+}
+
+static void
+gedit_notebook_stack_switcher_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GeditNotebookStackSwitcher *switcher = GEDIT_NOTEBOOK_STACK_SWITCHER (object);
+ GeditNotebookStackSwitcherPrivate *priv = switcher->priv;
+
+ switch (prop_id)
+ {
+ case PROP_STACK:
+ g_value_set_object (value, priv->stack);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gedit_notebook_stack_switcher_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GeditNotebookStackSwitcher *switcher = GEDIT_NOTEBOOK_STACK_SWITCHER (object);
+
+ switch (prop_id)
+ {
+ case PROP_STACK:
+ gedit_notebook_stack_switcher_set_stack (switcher, g_value_get_object (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gedit_notebook_stack_switcher_dispose (GObject *object)
+{
+ GeditNotebookStackSwitcher *switcher = GEDIT_NOTEBOOK_STACK_SWITCHER (object);
+
+ gedit_notebook_stack_switcher_set_stack (switcher, NULL);
+
+ G_OBJECT_CLASS (gedit_notebook_stack_switcher_parent_class)->dispose (object);
+}
+
+static void
+gedit_notebook_stack_switcher_class_init (GeditNotebookStackSwitcherClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = gedit_notebook_stack_switcher_get_property;
+ object_class->set_property = gedit_notebook_stack_switcher_set_property;
+ object_class->dispose = gedit_notebook_stack_switcher_dispose;
+
+ g_object_class_install_property (object_class,
+ PROP_STACK,
+ g_param_spec_object ("stack",
+ "Stack",
+ "Stack",
+ GTK_TYPE_STACK,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+}
+
+GtkWidget *
+gedit_notebook_stack_switcher_new (void)
+{
+ return g_object_new (GEDIT_TYPE_NOTEBOOK_STACK_SWITCHER, NULL);
+}
+
+/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-notebook-stack-switcher.h b/gedit/gedit-notebook-stack-switcher.h
new file mode 100644
index 0000000..96cca0d
--- /dev/null
+++ b/gedit/gedit-notebook-stack-switcher.h
@@ -0,0 +1,71 @@
+/*
+ * gedit-notebook-stack-switcher.h
+ * This file is part of gedit
+ *
+ * Copyright (C) 2014 - Paolo Borelli
+ *
+ * This program 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.
+ *
+ * This program 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GEDIT_NOTEBOOK_STACK_SWITCHER_H__
+#define __GEDIT_NOTEBOOK_STACK_SWITCHER_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GEDIT_TYPE_NOTEBOOK_STACK_SWITCHER (gedit_notebook_stack_switcher_get_type())
+#define GEDIT_NOTEBOOK_STACK_SWITCHER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),
GEDIT_TYPE_NOTEBOOK_STACK_SWITCHER, GeditNotebookStackSwitcher))
+#define GEDIT_NOTEBOOK_STACK_SWITCHER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),
GEDIT_TYPE_NOTEBOOK_STACK_SWITCHER, GeditNotebookStackSwitcherClass))
+#define GEDIT_IS_NOTEBOOK_STACK_SWITCHER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),
GEDIT_TYPE_NOTEBOOK_STACK_SWITCHER))
+#define GEDIT_IS_NOTEBOOK_STACK_SWITCHER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),
GEDIT_TYPE_NOTEBOOK_STACK_SWITCHER))
+#define GEDIT_NOTEBOOK_STACK_SWITCHER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),
GEDIT_TYPE_NOTEBOOK_STACK_SWITCHER, GeditNotebookStackSwitcherClass))
+
+typedef struct _GeditNotebookStackSwitcher GeditNotebookStackSwitcher;
+typedef struct _GeditNotebookStackSwitcherClass GeditNotebookStackSwitcherClass;
+typedef struct _GeditNotebookStackSwitcherPrivate GeditNotebookStackSwitcherPrivate;
+
+struct _GeditNotebookStackSwitcher
+{
+ GtkBin parent;
+
+ /*< private >*/
+ GeditNotebookStackSwitcherPrivate *priv;
+};
+
+struct _GeditNotebookStackSwitcherClass
+{
+ GtkBinClass parent_class;
+
+ /* Padding for future expansion */
+ void (*_gedit_reserved1) (void);
+ void (*_gedit_reserved2) (void);
+ void (*_gedit_reserved3) (void);
+ void (*_gedit_reserved4) (void);
+};
+
+GType gedit_notebook_stack_switcher_get_type (void) G_GNUC_CONST;
+
+GtkWidget *gedit_notebook_stack_switcher_new (void);
+
+void gedit_notebook_stack_switcher_set_stack (GeditNotebookStackSwitcher *switcher,
+ GtkStack *stack);
+
+GtkStack *gedit_notebook_stack_switcher_get_stack (GeditNotebookStackSwitcher *switcher);
+
+G_END_DECLS
+
+#endif /* __GEDIT_NOTEBOOK_STACK_SWITCHER_H__ */
+
+/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-window.ui b/gedit/gedit-window.ui
index ee7dc73..6e19771 100644
--- a/gedit/gedit-window.ui
+++ b/gedit/gedit-window.ui
@@ -226,7 +226,7 @@
</packing>
</child>
<child>
- <object class="GtkStackSwitcher" id="bottom_panel_stack_switcher">
+ <object class="GeditNotebookStackSwitcher"
id="bottom_panel_stack_switcher">
<property name="visible">True</property>
<property name="stack">bottom_panel</property>
<style>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]