summaryrefslogtreecommitdiffstats
path: root/gedit/gedit-multi-notebook.c
diff options
context:
space:
mode:
Diffstat (limited to 'gedit/gedit-multi-notebook.c')
-rw-r--r--gedit/gedit-multi-notebook.c1125
1 files changed, 1125 insertions, 0 deletions
diff --git a/gedit/gedit-multi-notebook.c b/gedit/gedit-multi-notebook.c
new file mode 100644
index 0000000..46d75ed
--- /dev/null
+++ b/gedit/gedit-multi-notebook.c
@@ -0,0 +1,1125 @@
+/*
+ * gedit-multi-notebook.c
+ * This file is part of gedit
+ *
+ * Copyright (C) 2010 - Ignacio Casal Quinteiro
+ *
+ * gedit 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.
+ *
+ * gedit 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 gedit; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#include "gedit-multi-notebook.h"
+
+#include "gedit-enum-types-private.h"
+#include "gedit-settings.h"
+#include "gedit-tab-private.h"
+#include "gedit-tab.h"
+
+struct _GeditMultiNotebookPrivate
+{
+ GtkWidget *active_notebook;
+ GList *notebooks;
+ gint total_tabs;
+
+ GeditTab *active_tab;
+
+ GeditNotebookShowTabsModeType show_tabs_mode;
+ GSettings *ui_settings;
+
+ guint show_tabs : 1;
+ guint removing_notebook : 1;
+};
+
+enum
+{
+ PROP_0,
+ PROP_ACTIVE_NOTEBOOK,
+ PROP_ACTIVE_TAB,
+ PROP_SHOW_TABS_MODE,
+ LAST_PROP
+};
+
+static GParamSpec *properties[LAST_PROP];
+
+enum
+{
+ NOTEBOOK_ADDED,
+ NOTEBOOK_REMOVED,
+ TAB_ADDED,
+ TAB_REMOVED,
+ SWITCH_TAB,
+ TAB_CLOSE_REQUEST,
+ CREATE_WINDOW,
+ PAGE_REORDERED,
+ SHOW_POPUP_MENU,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL];
+
+G_DEFINE_TYPE_WITH_PRIVATE (GeditMultiNotebook, gedit_multi_notebook, GTK_TYPE_GRID)
+
+static void remove_notebook (GeditMultiNotebook *mnb,
+ GtkWidget *notebook);
+
+static void update_tabs_visibility (GeditMultiNotebook *mnb);
+
+static void
+gedit_multi_notebook_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GeditMultiNotebook *mnb = GEDIT_MULTI_NOTEBOOK (object);
+
+ switch (prop_id)
+ {
+ case PROP_ACTIVE_NOTEBOOK:
+ g_value_set_object (value,
+ mnb->priv->active_notebook);
+ break;
+ case PROP_ACTIVE_TAB:
+ g_value_set_object (value,
+ mnb->priv->active_tab);
+ break;
+ case PROP_SHOW_TABS_MODE:
+ g_value_set_enum (value,
+ mnb->priv->show_tabs_mode);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gedit_multi_notebook_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GeditMultiNotebook *mnb = GEDIT_MULTI_NOTEBOOK (object);
+
+ switch (prop_id)
+ {
+ case PROP_SHOW_TABS_MODE:
+ mnb->priv->show_tabs_mode = g_value_get_enum (value);
+ update_tabs_visibility (mnb);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gedit_multi_notebook_dispose (GObject *object)
+{
+ GeditMultiNotebook *mnb = GEDIT_MULTI_NOTEBOOK (object);
+
+ g_clear_object (&mnb->priv->ui_settings);
+
+ G_OBJECT_CLASS (gedit_multi_notebook_parent_class)->dispose (object);
+}
+
+static void
+gedit_multi_notebook_finalize (GObject *object)
+{
+ GeditMultiNotebook *mnb = GEDIT_MULTI_NOTEBOOK (object);
+
+ g_list_free (mnb->priv->notebooks);
+
+ G_OBJECT_CLASS (gedit_multi_notebook_parent_class)->finalize (object);
+}
+
+static void
+gedit_multi_notebook_class_init (GeditMultiNotebookClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = gedit_multi_notebook_dispose;
+ object_class->finalize = gedit_multi_notebook_finalize;
+ object_class->get_property = gedit_multi_notebook_get_property;
+ object_class->set_property = gedit_multi_notebook_set_property;
+
+ properties[PROP_ACTIVE_NOTEBOOK] =
+ g_param_spec_object ("active-notebook",
+ "Active Notebook",
+ "The Active Notebook",
+ GEDIT_TYPE_NOTEBOOK,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ properties[PROP_ACTIVE_TAB] =
+ g_param_spec_object ("active-tab",
+ "Active Tab",
+ "The Active Tab",
+ GEDIT_TYPE_TAB,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ properties[PROP_SHOW_TABS_MODE] =
+ g_param_spec_enum ("show-tabs-mode",
+ "Show Tabs Mode",
+ "When tabs should be shown",
+ GEDIT_TYPE_NOTEBOOK_SHOW_TABS_MODE_TYPE,
+ GEDIT_NOTEBOOK_SHOW_TABS_ALWAYS,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (object_class, LAST_PROP, properties);
+
+ signals[NOTEBOOK_ADDED] =
+ g_signal_new ("notebook-added",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GeditMultiNotebookClass, notebook_added),
+ NULL, NULL, NULL,
+ G_TYPE_NONE,
+ 1,
+ GEDIT_TYPE_NOTEBOOK);
+ signals[NOTEBOOK_REMOVED] =
+ g_signal_new ("notebook-removed",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GeditMultiNotebookClass, notebook_removed),
+ NULL, NULL, NULL,
+ G_TYPE_NONE,
+ 1,
+ GEDIT_TYPE_NOTEBOOK);
+ signals[TAB_ADDED] =
+ g_signal_new ("tab-added",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GeditMultiNotebookClass, tab_added),
+ NULL, NULL, NULL,
+ G_TYPE_NONE,
+ 2,
+ GEDIT_TYPE_NOTEBOOK,
+ GEDIT_TYPE_TAB);
+ signals[TAB_REMOVED] =
+ g_signal_new ("tab-removed",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GeditMultiNotebookClass, tab_removed),
+ NULL, NULL, NULL,
+ G_TYPE_NONE,
+ 2,
+ GEDIT_TYPE_NOTEBOOK,
+ GEDIT_TYPE_TAB);
+ signals[SWITCH_TAB] =
+ g_signal_new ("switch-tab",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GeditMultiNotebookClass, switch_tab),
+ NULL, NULL, NULL,
+ G_TYPE_NONE,
+ 4,
+ GEDIT_TYPE_NOTEBOOK,
+ GEDIT_TYPE_TAB,
+ GEDIT_TYPE_NOTEBOOK,
+ GEDIT_TYPE_TAB);
+ signals[TAB_CLOSE_REQUEST] =
+ g_signal_new ("tab-close-request",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GeditMultiNotebookClass, tab_close_request),
+ NULL, NULL, NULL,
+ G_TYPE_NONE,
+ 2,
+ GEDIT_TYPE_NOTEBOOK,
+ GEDIT_TYPE_TAB);
+ signals[CREATE_WINDOW] =
+ g_signal_new ("create-window",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GeditMultiNotebookClass, create_window),
+ NULL, NULL, NULL,
+ GTK_TYPE_NOTEBOOK, 4,
+ GEDIT_TYPE_NOTEBOOK, GTK_TYPE_WIDGET,
+ G_TYPE_INT, G_TYPE_INT);
+ signals[PAGE_REORDERED] =
+ g_signal_new ("page-reordered",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GeditMultiNotebookClass, page_reordered),
+ NULL, NULL, NULL,
+ G_TYPE_NONE,
+ 3,
+ GEDIT_TYPE_NOTEBOOK, GTK_TYPE_WIDGET,
+ G_TYPE_INT);
+ signals[SHOW_POPUP_MENU] =
+ g_signal_new ("show-popup-menu",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GeditMultiNotebookClass, show_popup_menu),
+ NULL, NULL, NULL,
+ G_TYPE_NONE,
+ 2,
+ GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE,
+ GEDIT_TYPE_TAB);
+}
+
+static void
+notebook_show_popup_menu (GtkNotebook *notebook,
+ GdkEvent *event,
+ GeditTab *tab,
+ GeditMultiNotebook *mnb)
+{
+ g_signal_emit (G_OBJECT (mnb), signals[SHOW_POPUP_MENU], 0, event, tab);
+}
+
+static void
+notebook_tab_close_request (GeditNotebook *notebook,
+ GeditTab *tab,
+ GeditMultiNotebook *mnb)
+{
+ g_signal_emit (G_OBJECT (mnb), signals[TAB_CLOSE_REQUEST], 0,
+ notebook, tab);
+}
+
+static GtkNotebook *
+notebook_create_window (GeditNotebook *notebook,
+ GtkWidget *child,
+ gint x,
+ gint y,
+ GeditMultiNotebook *mnb)
+{
+ GtkNotebook *dest_notebook;
+
+ g_signal_emit (G_OBJECT (mnb), signals[CREATE_WINDOW], 0,
+ notebook, child, x, y, &dest_notebook);
+
+ return dest_notebook;
+}
+
+static void
+notebook_page_reordered (GeditNotebook *notebook,
+ GtkWidget *child,
+ guint page_num,
+ GeditMultiNotebook *mnb)
+{
+ g_signal_emit (G_OBJECT (mnb), signals[PAGE_REORDERED], 0, notebook,
+ child, page_num);
+}
+
+static void
+set_active_tab (GeditMultiNotebook *mnb,
+ GeditTab *tab)
+{
+ mnb->priv->active_tab = tab;
+ g_object_notify_by_pspec (G_OBJECT (mnb), properties[PROP_ACTIVE_TAB]);
+}
+
+static void
+notebook_page_removed (GtkNotebook *notebook,
+ GtkWidget *child,
+ guint page_num,
+ GeditMultiNotebook *mnb)
+{
+ GeditTab *tab = GEDIT_TAB (child);
+ guint num_tabs;
+ gboolean last_notebook;
+
+ --mnb->priv->total_tabs;
+ num_tabs = gtk_notebook_get_n_pages (notebook);
+ last_notebook = (mnb->priv->notebooks->next == NULL);
+
+ if (mnb->priv->total_tabs == 0)
+ {
+ set_active_tab (mnb, NULL);
+ }
+
+ g_signal_emit (G_OBJECT (mnb), signals[TAB_REMOVED], 0, notebook, tab);
+
+ /* Not last notebook but last tab of the notebook, this means we have
+ to remove the current notebook */
+ if (num_tabs == 0 && !mnb->priv->removing_notebook &&
+ !last_notebook)
+ {
+ remove_notebook (mnb, GTK_WIDGET (notebook));
+ }
+
+ update_tabs_visibility (mnb);
+}
+
+static void
+notebook_page_added (GtkNotebook *notebook,
+ GtkWidget *child,
+ guint page_num,
+ GeditMultiNotebook *mnb)
+{
+ GeditTab *tab = GEDIT_TAB (child);
+
+ ++mnb->priv->total_tabs;
+
+ update_tabs_visibility (mnb);
+
+ g_signal_emit (G_OBJECT (mnb), signals[TAB_ADDED], 0, notebook, tab);
+}
+
+static void
+notebook_switch_page (GtkNotebook *book,
+ GtkWidget *pg,
+ gint page_num,
+ GeditMultiNotebook *mnb)
+{
+ GeditTab *tab;
+
+ /* When we switch a tab from a notebook that it is not the active one
+ the switch page is emitted before the set focus, so we do this check
+ and we avoid to call switch page twice */
+ if (GTK_WIDGET (book) != mnb->priv->active_notebook)
+ return;
+
+ /* CHECK: I don't know why but it seems notebook_switch_page is called
+ two times every time the user change the active tab */
+ tab = GEDIT_TAB (gtk_notebook_get_nth_page (book, page_num));
+ if (tab != mnb->priv->active_tab)
+ {
+ GeditTab *old_tab;
+
+ old_tab = mnb->priv->active_tab;
+ set_active_tab (mnb, tab);
+ g_signal_emit (G_OBJECT (mnb), signals[SWITCH_TAB], 0,
+ mnb->priv->active_notebook, old_tab,
+ book, tab);
+ }
+}
+
+/* We need to figure out if the any of the internal widget of the notebook
+ has got the focus to set the active notebook */
+static void
+notebook_set_focus (GtkContainer *container,
+ GtkWidget *widget,
+ GeditMultiNotebook *mnb)
+{
+ if (GEDIT_IS_NOTEBOOK (container) &&
+ GTK_WIDGET (container) != mnb->priv->active_notebook)
+ {
+ gint page_num;
+
+ mnb->priv->active_notebook = GTK_WIDGET (container);
+
+ page_num = gtk_notebook_get_current_page (GTK_NOTEBOOK (container));
+ notebook_switch_page (GTK_NOTEBOOK (container), NULL,
+ page_num, mnb);
+
+ g_object_notify_by_pspec (G_OBJECT (mnb), properties[PROP_ACTIVE_NOTEBOOK]);
+ }
+}
+
+static void
+show_tabs_changed (GObject *object,
+ GParamSpec *pspec,
+ gpointer *data)
+{
+ update_tabs_visibility (GEDIT_MULTI_NOTEBOOK (data));
+}
+
+static void
+update_tabs_visibility (GeditMultiNotebook *mnb)
+{
+ gboolean show_tabs;
+ GList *l;
+
+ if (mnb->priv->notebooks == NULL)
+ return;
+
+ if (!mnb->priv->show_tabs)
+ {
+ show_tabs = FALSE;
+ }
+ else if (mnb->priv->notebooks->next == NULL) /* only one notebook */
+ {
+ switch (mnb->priv->show_tabs_mode)
+ {
+ case GEDIT_NOTEBOOK_SHOW_TABS_NEVER:
+ show_tabs = FALSE;
+ break;
+ case GEDIT_NOTEBOOK_SHOW_TABS_AUTO:
+ show_tabs = gtk_notebook_get_n_pages (GTK_NOTEBOOK (mnb->priv->notebooks->data)) > 1;
+ break;
+ case GEDIT_NOTEBOOK_SHOW_TABS_ALWAYS:
+ default:
+ show_tabs = TRUE;
+ break;
+ }
+ }
+ else
+ {
+ show_tabs = (mnb->priv->show_tabs_mode != GEDIT_NOTEBOOK_SHOW_TABS_NEVER);
+ }
+
+ g_signal_handlers_block_by_func (mnb, show_tabs_changed, NULL);
+
+ for (l = mnb->priv->notebooks; l != NULL; l = l->next)
+ {
+ gtk_notebook_set_show_tabs (GTK_NOTEBOOK (l->data), show_tabs);
+ }
+
+ g_signal_handlers_unblock_by_func (mnb, show_tabs_changed, NULL);
+}
+
+static void
+connect_notebook_signals (GeditMultiNotebook *mnb,
+ GtkWidget *notebook)
+{
+ g_signal_connect (notebook,
+ "set-focus-child",
+ G_CALLBACK (notebook_set_focus),
+ mnb);
+ g_signal_connect (notebook,
+ "page-added",
+ G_CALLBACK (notebook_page_added),
+ mnb);
+ g_signal_connect (notebook,
+ "page-removed",
+ G_CALLBACK (notebook_page_removed),
+ mnb);
+ g_signal_connect (notebook,
+ "switch-page",
+ G_CALLBACK (notebook_switch_page),
+ mnb);
+ g_signal_connect (notebook,
+ "page-reordered",
+ G_CALLBACK (notebook_page_reordered),
+ mnb);
+ g_signal_connect (notebook,
+ "create-window",
+ G_CALLBACK (notebook_create_window),
+ mnb);
+ g_signal_connect (notebook,
+ "tab-close-request",
+ G_CALLBACK (notebook_tab_close_request),
+ mnb);
+ g_signal_connect (notebook,
+ "show-popup-menu",
+ G_CALLBACK (notebook_show_popup_menu),
+ mnb);
+ g_signal_connect (notebook,
+ "notify::show-tabs",
+ G_CALLBACK (show_tabs_changed),
+ mnb);
+}
+
+static void
+disconnect_notebook_signals (GeditMultiNotebook *mnb,
+ GtkWidget *notebook)
+{
+ g_signal_handlers_disconnect_by_func (notebook, notebook_set_focus,
+ mnb);
+ g_signal_handlers_disconnect_by_func (notebook, notebook_switch_page,
+ mnb);
+ g_signal_handlers_disconnect_by_func (notebook, notebook_page_added,
+ mnb);
+ g_signal_handlers_disconnect_by_func (notebook, notebook_page_removed,
+ mnb);
+ g_signal_handlers_disconnect_by_func (notebook, notebook_page_reordered,
+ mnb);
+ g_signal_handlers_disconnect_by_func (notebook, notebook_create_window,
+ mnb);
+ g_signal_handlers_disconnect_by_func (notebook, notebook_tab_close_request,
+ mnb);
+ g_signal_handlers_disconnect_by_func (notebook, notebook_show_popup_menu,
+ mnb);
+ g_signal_handlers_disconnect_by_func (notebook, show_tabs_changed,
+ mnb);
+}
+
+static void
+add_notebook (GeditMultiNotebook *mnb,
+ GtkWidget *notebook,
+ gboolean main_container)
+{
+ gtk_widget_set_hexpand (notebook, TRUE);
+ gtk_widget_set_vexpand (notebook, TRUE);
+
+ if (main_container)
+ {
+ gtk_container_add (GTK_CONTAINER (mnb), notebook);
+
+ mnb->priv->notebooks = g_list_append (mnb->priv->notebooks,
+ notebook);
+ }
+ else
+ {
+ GtkWidget *paned;
+ GtkWidget *parent;
+ GtkAllocation allocation;
+ GtkWidget *active_notebook = mnb->priv->active_notebook;
+ gint active_nb_pos;
+
+ paned = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
+ gtk_widget_show (paned);
+
+ /* First we remove the active container from its parent to make
+ this we add a ref to it*/
+ g_object_ref (active_notebook);
+ parent = gtk_widget_get_parent (active_notebook);
+ gtk_widget_get_allocation (active_notebook, &allocation);
+
+ gtk_container_remove (GTK_CONTAINER (parent), active_notebook);
+ gtk_container_add (GTK_CONTAINER (parent), paned);
+
+ gtk_paned_pack1 (GTK_PANED (paned), active_notebook, TRUE, FALSE);
+ g_object_unref (active_notebook);
+
+ gtk_paned_pack2 (GTK_PANED (paned), notebook, FALSE, FALSE);
+
+ /* We need to set the new paned in the right place */
+ gtk_paned_set_position (GTK_PANED (paned),
+ allocation.width / 2);
+
+ active_nb_pos = g_list_index (mnb->priv->notebooks,
+ active_notebook);
+ mnb->priv->notebooks = g_list_insert (mnb->priv->notebooks,
+ notebook,
+ active_nb_pos + 1);
+ }
+
+ gtk_widget_show (notebook);
+
+ connect_notebook_signals (mnb, notebook);
+
+ g_signal_emit (G_OBJECT (mnb), signals[NOTEBOOK_ADDED], 0, notebook);
+}
+
+static void
+remove_notebook (GeditMultiNotebook *mnb,
+ GtkWidget *notebook)
+{
+ GtkWidget *parent;
+ GtkWidget *grandpa;
+ GList *children;
+ GtkWidget *new_notebook;
+ GList *current;
+
+ if (mnb->priv->notebooks->next == NULL)
+ {
+ g_warning ("You are trying to remove the main notebook");
+ return;
+ }
+
+ current = g_list_find (mnb->priv->notebooks,
+ notebook);
+
+ if (current->next != NULL)
+ {
+ new_notebook = GTK_WIDGET (current->next->data);
+ }
+ else
+ {
+ new_notebook = GTK_WIDGET (mnb->priv->notebooks->data);
+ }
+
+ parent = gtk_widget_get_parent (notebook);
+
+ /* Now we destroy the widget, we get the children of parent and we destroy
+ parent too as the parent is an useless paned. Finally we add the child
+ into the grand parent */
+ g_object_ref (notebook);
+ mnb->priv->removing_notebook = TRUE;
+
+ gtk_widget_destroy (notebook);
+
+ mnb->priv->notebooks = g_list_remove (mnb->priv->notebooks,
+ notebook);
+
+ mnb->priv->removing_notebook = FALSE;
+
+ children = gtk_container_get_children (GTK_CONTAINER (parent));
+ if (children->next != NULL)
+ {
+ g_warning ("The parent is not a paned");
+ return;
+ }
+ grandpa = gtk_widget_get_parent (parent);
+
+ g_object_ref (children->data);
+ gtk_container_remove (GTK_CONTAINER (parent),
+ GTK_WIDGET (children->data));
+ gtk_widget_destroy (parent);
+ gtk_container_add (GTK_CONTAINER (grandpa),
+ GTK_WIDGET (children->data));
+ g_object_unref (children->data);
+ g_list_free (children);
+
+ disconnect_notebook_signals (mnb, notebook);
+
+ g_signal_emit (G_OBJECT (mnb), signals[NOTEBOOK_REMOVED], 0, notebook);
+ g_object_unref (notebook);
+
+ /* Let's make the active notebook grab the focus */
+ gtk_widget_grab_focus (new_notebook);
+}
+
+static void
+gedit_multi_notebook_init (GeditMultiNotebook *mnb)
+{
+ GeditMultiNotebookPrivate *priv;
+
+ mnb->priv = gedit_multi_notebook_get_instance_private (mnb);
+ priv = mnb->priv;
+
+ priv->removing_notebook = FALSE;
+
+ gtk_orientable_set_orientation (GTK_ORIENTABLE (mnb),
+ GTK_ORIENTATION_VERTICAL);
+
+ priv->show_tabs_mode = GEDIT_NOTEBOOK_SHOW_TABS_ALWAYS;
+ priv->show_tabs = TRUE;
+
+ priv->ui_settings = g_settings_new ("org.gnome.gedit.preferences.ui");
+ g_settings_bind (priv->ui_settings,
+ GEDIT_SETTINGS_SHOW_TABS_MODE,
+ mnb,
+ "show-tabs-mode",
+ G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
+
+ priv->active_notebook = gedit_notebook_new ();
+ add_notebook (mnb, priv->active_notebook, TRUE);
+}
+
+GeditMultiNotebook *
+gedit_multi_notebook_new ()
+{
+ return g_object_new (GEDIT_TYPE_MULTI_NOTEBOOK, NULL);
+}
+
+GeditNotebook *
+gedit_multi_notebook_get_active_notebook (GeditMultiNotebook *mnb)
+{
+ g_return_val_if_fail (GEDIT_IS_MULTI_NOTEBOOK (mnb), NULL);
+
+ return GEDIT_NOTEBOOK (mnb->priv->active_notebook);
+}
+
+gint
+gedit_multi_notebook_get_n_notebooks (GeditMultiNotebook *mnb)
+{
+ g_return_val_if_fail (GEDIT_IS_MULTI_NOTEBOOK (mnb), 0);
+
+ return g_list_length (mnb->priv->notebooks);
+}
+
+GeditNotebook *
+gedit_multi_notebook_get_nth_notebook (GeditMultiNotebook *mnb,
+ gint notebook_num)
+{
+ g_return_val_if_fail (GEDIT_IS_MULTI_NOTEBOOK (mnb), NULL);
+
+ return g_list_nth_data (mnb->priv->notebooks, notebook_num);
+}
+
+GeditNotebook *
+gedit_multi_notebook_get_notebook_for_tab (GeditMultiNotebook *mnb,
+ GeditTab *tab)
+{
+ GList *l;
+ gint page_num;
+
+ g_return_val_if_fail (GEDIT_IS_MULTI_NOTEBOOK (mnb), NULL);
+ g_return_val_if_fail (GEDIT_IS_TAB (tab), NULL);
+
+ l = mnb->priv->notebooks;
+
+ do
+ {
+ page_num = gtk_notebook_page_num (GTK_NOTEBOOK (l->data),
+ GTK_WIDGET (tab));
+ if (page_num != -1)
+ break;
+
+ l = g_list_next (l);
+ } while (l != NULL && page_num == -1);
+
+ g_return_val_if_fail (page_num != -1, NULL);
+
+ return GEDIT_NOTEBOOK (l->data);
+}
+
+gint
+gedit_multi_notebook_get_notebook_num (GeditMultiNotebook *mnb,
+ GeditNotebook *notebook)
+{
+ g_return_val_if_fail (GEDIT_IS_MULTI_NOTEBOOK (mnb), -1);
+ g_return_val_if_fail (GEDIT_IS_NOTEBOOK (notebook), -1);
+
+ return g_list_index (mnb->priv->notebooks, notebook);
+}
+
+gint
+gedit_multi_notebook_get_n_tabs (GeditMultiNotebook *mnb)
+{
+ g_return_val_if_fail (GEDIT_IS_MULTI_NOTEBOOK (mnb), 0);
+
+ return mnb->priv->total_tabs;
+}
+
+gint
+gedit_multi_notebook_get_page_num (GeditMultiNotebook *mnb,
+ GeditTab *tab)
+{
+ GList *l;
+ gint real_page_num = 0;
+
+ for (l = mnb->priv->notebooks; l != NULL; l = g_list_next (l))
+ {
+ gint page_num;
+
+ page_num = gtk_notebook_page_num (GTK_NOTEBOOK (l->data),
+ GTK_WIDGET (tab));
+
+ if (page_num != -1)
+ {
+ real_page_num += page_num;
+ break;
+ }
+
+ real_page_num += gtk_notebook_get_n_pages (GTK_NOTEBOOK (l->data));
+ }
+
+ return real_page_num;
+}
+
+GeditTab *
+gedit_multi_notebook_get_active_tab (GeditMultiNotebook *mnb)
+{
+ g_return_val_if_fail (GEDIT_IS_MULTI_NOTEBOOK (mnb), NULL);
+
+ return (mnb->priv->active_tab == NULL) ?
+ NULL : GEDIT_TAB (mnb->priv->active_tab);
+}
+
+void
+gedit_multi_notebook_set_active_tab (GeditMultiNotebook *mnb,
+ GeditTab *tab)
+{
+ GList *l;
+ gint page_num;
+
+ g_return_if_fail (GEDIT_IS_MULTI_NOTEBOOK (mnb));
+ g_return_if_fail (GEDIT_IS_TAB (tab) || tab == NULL);
+
+ /* use plain C cast since the active tab can be null */
+ if (tab == (GeditTab *) mnb->priv->active_tab)
+ {
+ return;
+ }
+
+ if (tab == NULL)
+ {
+ set_active_tab (mnb, NULL);
+ return;
+ }
+
+ l = mnb->priv->notebooks;
+
+ do
+ {
+ page_num = gtk_notebook_page_num (GTK_NOTEBOOK (l->data),
+ GTK_WIDGET (tab));
+ if (page_num != -1)
+ break;
+
+ l = g_list_next (l);
+ } while (l != NULL && page_num == -1);
+
+ g_return_if_fail (page_num != -1);
+
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (l->data), page_num);
+
+ if (GTK_WIDGET (l->data) != mnb->priv->active_notebook)
+ {
+ gtk_widget_grab_focus (GTK_WIDGET (l->data));
+ }
+}
+
+void
+gedit_multi_notebook_set_current_page (GeditMultiNotebook *mnb,
+ gint page_num)
+{
+ GList *l;
+ gint pages = 0;
+ gint single_num = page_num;
+
+ g_return_if_fail (GEDIT_IS_MULTI_NOTEBOOK (mnb));
+
+ for (l = mnb->priv->notebooks; l != NULL; l = g_list_next (l))
+ {
+ gint p;
+
+ p = gtk_notebook_get_n_pages (GTK_NOTEBOOK (l->data));
+ pages += p;
+
+ if ((pages - 1) >= page_num)
+ break;
+
+ single_num -= p;
+ }
+
+ if (l == NULL)
+ return;
+
+ if (GTK_WIDGET (l->data) != mnb->priv->active_notebook)
+ {
+ gtk_widget_grab_focus (GTK_WIDGET (l->data));
+ }
+
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (l->data), single_num);
+}
+
+GList *
+gedit_multi_notebook_get_all_tabs (GeditMultiNotebook *mnb)
+{
+ GList *nbs;
+ GList *ret = NULL;
+
+ g_return_val_if_fail (GEDIT_IS_MULTI_NOTEBOOK (mnb), NULL);
+
+ for (nbs = mnb->priv->notebooks; nbs != NULL; nbs = g_list_next (nbs))
+ {
+ GList *l, *children;
+
+ children = gtk_container_get_children (GTK_CONTAINER (nbs->data));
+
+ for (l = children; l != NULL; l = g_list_next (l))
+ {
+ ret = g_list_prepend (ret, l->data);
+ }
+
+ g_list_free (children);
+ }
+
+ ret = g_list_reverse (ret);
+
+ return ret;
+}
+
+void
+gedit_multi_notebook_close_tabs (GeditMultiNotebook *mnb,
+ const GList *tabs)
+{
+ GList *l;
+
+ g_return_if_fail (GEDIT_IS_MULTI_NOTEBOOK (mnb));
+
+ for (l = (GList *)tabs; l != NULL; l = g_list_next (l))
+ {
+ GList *nbs;
+
+ for (nbs = mnb->priv->notebooks; nbs != NULL; nbs = g_list_next (nbs))
+ {
+ gint n;
+
+ n = gtk_notebook_page_num (GTK_NOTEBOOK (nbs->data),
+ GTK_WIDGET (l->data));
+
+ if (n != -1)
+ {
+ gtk_container_remove (GTK_CONTAINER (nbs->data),
+ GTK_WIDGET (l->data));
+ break;
+ }
+ }
+ }
+}
+
+/**
+ * gedit_multi_notebook_close_all_tabs:
+ * @mnb: a #GeditMultiNotebook
+ *
+ * Closes all opened tabs.
+ */
+void
+gedit_multi_notebook_close_all_tabs (GeditMultiNotebook *mnb)
+{
+ GList *nbs, *l;
+
+ g_return_if_fail (GEDIT_MULTI_NOTEBOOK (mnb));
+
+ /* We copy the list because the main one is going to have the items
+ removed */
+ nbs = g_list_copy (mnb->priv->notebooks);
+
+ for (l = nbs; l != NULL; l = g_list_next (l))
+ {
+ gedit_notebook_remove_all_tabs (GEDIT_NOTEBOOK (l->data));
+ }
+
+ g_list_free (nbs);
+}
+
+void
+gedit_multi_notebook_add_new_notebook (GeditMultiNotebook *mnb)
+{
+ GtkWidget *notebook;
+ GeditTab *tab;
+
+ g_return_if_fail (GEDIT_IS_MULTI_NOTEBOOK (mnb));
+
+ notebook = gedit_notebook_new ();
+ add_notebook (mnb, notebook, FALSE);
+
+ tab = _gedit_tab_new ();
+ gtk_widget_show (GTK_WIDGET (tab));
+
+ /* When gtk_notebook_insert_page is called the focus is set in
+ the notebook, we don't want this to happen until the page is added.
+ Also we don't want to call switch_page when we add the tab
+ but when we switch the notebook. */
+ g_signal_handlers_block_by_func (notebook, notebook_set_focus, mnb);
+ g_signal_handlers_block_by_func (notebook, notebook_switch_page, mnb);
+
+ gedit_notebook_add_tab (GEDIT_NOTEBOOK (notebook),
+ tab,
+ -1,
+ TRUE);
+
+ g_signal_handlers_unblock_by_func (notebook, notebook_switch_page, mnb);
+ g_signal_handlers_unblock_by_func (notebook, notebook_set_focus, mnb);
+
+ notebook_set_focus (GTK_CONTAINER (notebook), NULL, mnb);
+}
+
+void
+gedit_multi_notebook_add_new_notebook_with_tab (GeditMultiNotebook *mnb,
+ GeditTab *tab)
+{
+ GtkWidget *notebook;
+ GeditNotebook *old_notebook;
+
+ g_return_if_fail (GEDIT_IS_MULTI_NOTEBOOK (mnb));
+ g_return_if_fail (GEDIT_IS_TAB (tab));
+
+ notebook = gedit_notebook_new ();
+ add_notebook (mnb, notebook, FALSE);
+
+ old_notebook = gedit_multi_notebook_get_notebook_for_tab (mnb, tab);
+
+ /* When gtk_notebook_insert_page is called the focus is set in
+ the notebook, we don't want this to happen until the page is added.
+ Also we don't want to call switch_page when we add the tab
+ but when we switch the notebook. */
+ g_signal_handlers_block_by_func (old_notebook, notebook_set_focus, mnb);
+ g_signal_handlers_block_by_func (old_notebook, notebook_switch_page, mnb);
+
+ gedit_notebook_move_tab (old_notebook,
+ GEDIT_NOTEBOOK (notebook),
+ tab,
+ -1);
+
+ g_signal_handlers_unblock_by_func (old_notebook, notebook_switch_page, mnb);
+ g_signal_handlers_unblock_by_func (old_notebook, notebook_set_focus, mnb);
+
+ notebook_set_focus (GTK_CONTAINER (notebook), NULL, mnb);
+}
+
+void
+gedit_multi_notebook_remove_active_notebook (GeditMultiNotebook *mnb)
+{
+ g_return_if_fail (GEDIT_IS_MULTI_NOTEBOOK (mnb));
+
+ gedit_notebook_remove_all_tabs (GEDIT_NOTEBOOK (mnb->priv->active_notebook));
+}
+
+void
+gedit_multi_notebook_previous_notebook (GeditMultiNotebook *mnb)
+{
+ GList *current;
+ GtkWidget *notebook;
+
+ g_return_if_fail (GEDIT_IS_MULTI_NOTEBOOK (mnb));
+
+ current = g_list_find (mnb->priv->notebooks,
+ mnb->priv->active_notebook);
+
+ if (current->prev != NULL)
+ notebook = GTK_WIDGET (current->prev->data);
+ else
+ notebook = GTK_WIDGET (g_list_last (mnb->priv->notebooks)->data);
+
+ gtk_widget_grab_focus (notebook);
+}
+
+void
+gedit_multi_notebook_next_notebook (GeditMultiNotebook *mnb)
+{
+ GList *current;
+ GtkWidget *notebook;
+
+ g_return_if_fail (GEDIT_IS_MULTI_NOTEBOOK (mnb));
+
+ current = g_list_find (mnb->priv->notebooks,
+ mnb->priv->active_notebook);
+
+ if (current->next != NULL)
+ notebook = GTK_WIDGET (current->next->data);
+ else
+ notebook = GTK_WIDGET (mnb->priv->notebooks->data);
+
+ gtk_widget_grab_focus (notebook);
+}
+
+void
+gedit_multi_notebook_foreach_notebook (GeditMultiNotebook *mnb,
+ GtkCallback callback,
+ gpointer callback_data)
+{
+ GList *l;
+
+ g_return_if_fail (GEDIT_IS_MULTI_NOTEBOOK (mnb));
+
+ for (l = mnb->priv->notebooks; l != NULL; l = g_list_next (l))
+ {
+ callback (GTK_WIDGET (l->data), callback_data);
+ }
+}
+
+void
+gedit_multi_notebook_foreach_tab (GeditMultiNotebook *mnb,
+ GtkCallback callback,
+ gpointer callback_data)
+{
+ GList *nb;
+
+ g_return_if_fail (GEDIT_IS_MULTI_NOTEBOOK (mnb));
+
+ for (nb = mnb->priv->notebooks; nb != NULL; nb = g_list_next (nb))
+ {
+ GList *l, *children;
+
+ children = gtk_container_get_children (GTK_CONTAINER (nb->data));
+
+ for (l = children; l != NULL; l = g_list_next (l))
+ {
+ callback (GTK_WIDGET (l->data), callback_data);
+ }
+
+ g_list_free (children);
+ }
+}
+
+/* We only use this to hide tabs in fullscreen mode so for now
+ * we do not have a real property etc.
+ */
+void
+_gedit_multi_notebook_set_show_tabs (GeditMultiNotebook *mnb,
+ gboolean show)
+{
+ g_return_if_fail (GEDIT_IS_MULTI_NOTEBOOK (mnb));
+
+ mnb->priv->show_tabs = show != FALSE;
+
+ update_tabs_visibility (mnb);
+}
+
+/* ex:set ts=8 noet: */