[gnome-builder/wip/chergert/326redesign: 16/21] import recent panel-gtk updates
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/wip/chergert/326redesign: 16/21] import recent panel-gtk updates
- Date: Tue, 9 May 2017 21:27:53 +0000 (UTC)
commit f5f83458855dd2fcbe93e31c696335f6b30b46b1
Author: Christian Hergert <chergert redhat com>
Date: Fri May 5 00:40:12 2017 -0700
import recent panel-gtk updates
contrib/pnl/Makefile.am | 38 +-
contrib/pnl/pnl-bin.c | 190 ++++
contrib/pnl/{pnl-dock-tab-strip.c => pnl-bin.h} | 40 +-
contrib/pnl/pnl-child-property-action.c | 558 ++++++++++++
...ock-tab-strip.h => pnl-child-property-action.h} | 22 +-
contrib/pnl/pnl-dock-bin-edge-private.h | 8 +-
contrib/pnl/pnl-dock-bin-edge.c | 34 +-
contrib/pnl/pnl-dock-bin-edge.h | 10 +-
contrib/pnl/pnl-dock-bin.c | 741 +++++++++++-----
contrib/pnl/pnl-dock-bin.h | 24 +-
contrib/pnl/pnl-dock-item.c | 231 +++++-
contrib/pnl/pnl-dock-item.h | 85 ++-
contrib/pnl/pnl-dock-manager.h | 16 +-
contrib/pnl/pnl-dock-overlay-edge.c | 25 +-
contrib/pnl/pnl-dock-overlay-edge.h | 10 +-
contrib/pnl/pnl-dock-overlay.c | 2 +-
contrib/pnl/pnl-dock-overlay.h | 16 +-
contrib/pnl/pnl-dock-paned-private.h | 4 +
contrib/pnl/pnl-dock-paned.c | 2 +-
contrib/pnl/pnl-dock-paned.h | 16 +-
contrib/pnl/pnl-dock-revealer.c | 175 +++-
contrib/pnl/pnl-dock-revealer.h | 25 +-
contrib/pnl/pnl-dock-stack.c | 170 ++++-
contrib/pnl/pnl-dock-stack.h | 19 +-
contrib/pnl/pnl-dock-transient-grab.h | 4 +
contrib/pnl/pnl-dock-types.h | 63 +-
contrib/pnl/pnl-dock-widget.c | 135 +++-
contrib/pnl/pnl-dock-widget.h | 29 +-
contrib/pnl/pnl-dock-window.c | 2 +-
contrib/pnl/pnl-dock-window.h | 9 +
contrib/pnl/pnl-multi-paned.c | 188 +++--
contrib/pnl/pnl-multi-paned.h | 16 +-
.../{pnl-dock-tab-strip.h => pnl-tab-private.h} | 18 +-
contrib/pnl/pnl-tab-strip.c | 188 ++++-
contrib/pnl/pnl-tab-strip.h | 20 +-
contrib/pnl/pnl-tab.c | 944 +++++++++++++++++++-
contrib/pnl/pnl-tab.h | 36 +-
contrib/pnl/pnl-util-private.h | 20 +-
contrib/pnl/pnl-util.c | 281 +++++--
contrib/pnl/pnl-version.h.in | 2 +-
contrib/pnl/pnl.h | 10 +-
data/theme/Adwaita-panels.css | 90 ++-
data/theme/Adwaita.css | 13 -
43 files changed, 3826 insertions(+), 703 deletions(-)
---
diff --git a/contrib/pnl/Makefile.am b/contrib/pnl/Makefile.am
index a31bb5c..a82e056 100644
--- a/contrib/pnl/Makefile.am
+++ b/contrib/pnl/Makefile.am
@@ -8,7 +8,7 @@ pkglib_LTLIBRARIES = libpanel-gtk.la
headersdir = $(includedir)/gnome-builder-@VERSION@/pnl
headers_DATA = \
- pnl-animation.h \
+ pnl-bin.h \
pnl-dock-bin.h \
pnl-dock-bin-edge.h \
pnl-dock-item.h \
@@ -22,7 +22,6 @@ headers_DATA = \
pnl-dock-widget.h \
pnl-dock-window.h \
pnl-dock.h \
- pnl-frame-source.h \
pnl-multi-paned.h \
pnl-tab-strip.h \
pnl-tab.h \
@@ -30,31 +29,39 @@ headers_DATA = \
pnl.h \
$(NULL)
-libpanel_gtk_la_SOURCES = \
- $(headers_DATA) \
- pnl-animation.c \
+public_sources = \
+ pnl-bin.c \
pnl-dock-bin-edge.c \
- pnl-dock-bin-edge-private.h \
pnl-dock-bin.c \
pnl-dock-item.c \
pnl-dock-manager.c \
- pnl-dock-overlay-edge.c \
pnl-dock-overlay.c \
- pnl-dock-paned-private.h \
+ pnl-dock-overlay-edge.c \
pnl-dock-paned.c \
pnl-dock-revealer.c \
pnl-dock-stack.c \
- pnl-dock-tab-strip.c \
- pnl-dock-tab-strip.h \
- pnl-dock-transient-grab.c \
- pnl-dock-transient-grab.h \
pnl-dock-widget.c \
pnl-dock-window.c \
pnl-dock.c \
- pnl-frame-source.c \
pnl-multi-paned.c \
pnl-tab-strip.c \
pnl-tab.c \
+ $(NULL)
+
+libpanel_gtk_la_SOURCES = \
+ $(headers_DATA) \
+ $(public_sources) \
+ pnl-animation.c \
+ pnl-animation.h \
+ pnl-child-property-action.c \
+ pnl-child-property-action.h \
+ pnl-dock-bin-edge-private.h \
+ pnl-dock-paned-private.h \
+ pnl-dock-transient-grab.c \
+ pnl-dock-transient-grab.h \
+ pnl-frame-source.c \
+ pnl-frame-source.h \
+ pnl-tab-private.h \
pnl-util-private.h \
pnl-util.c \
$(NULL)
@@ -93,7 +100,10 @@ Pnl-1.0.gir: libpanel-gtk.la
Pnl_1_0_gir_INCLUDES = Gio-2.0 Gdk-3.0 Gtk-3.0
Pnl_1_0_gir_CFLAGS = $(libpanel_gtk_la_CFLAGS) -DPNL_COMPILATION
Pnl_1_0_gir_LIBS = libpanel-gtk.la
-Pnl_1_0_gir_FILES = $(libpanel_gtk_la_SOURCES)
+Pnl_1_0_gir_FILES = \
+ $(public_sources) \
+ $(headers_DATA) \
+ $(NULL)
Pnl_1_0_gir_SCANNERFLAGS = \
--c-include="pnl.h" \
-n Pnl \
diff --git a/contrib/pnl/pnl-bin.c b/contrib/pnl/pnl-bin.c
new file mode 100644
index 0000000..82421d4
--- /dev/null
+++ b/contrib/pnl/pnl-bin.c
@@ -0,0 +1,190 @@
+/* pnl-bin.c
+ *
+ * Copyright (C) 2017 Christian Hergert <chergert redhat com>
+ *
+ * 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 3 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/>.
+ */
+
+#define G_LOG_DOMAIN "pnl-bin"
+
+/**
+ * SECTION:pnl-bin
+ * @title: PnlBin
+ *
+ * This is just a #GtkBin class that also allows for various styling with
+ * CSS over what can be done in GtkBin directly.
+ */
+
+#include <string.h>
+
+#include "pnl-bin.h"
+#include "pnl-util-private.h"
+
+G_DEFINE_TYPE (PnlBin, pnl_bin, GTK_TYPE_BIN)
+
+static gboolean
+pnl_bin_draw (GtkWidget *widget,
+ cairo_t *cr)
+{
+ GtkStyleContext *style_context;
+ GtkWidget *child;
+ GtkAllocation alloc;
+ GtkStateFlags state;
+ GtkBorder margin;
+
+ g_assert (PNL_IS_BIN (widget));
+
+ gtk_widget_get_allocation (widget, &alloc);
+ alloc.x = 0;
+ alloc.y = 0;
+
+ style_context = gtk_widget_get_style_context (widget);
+ state = gtk_widget_get_state_flags (widget);
+
+ gtk_style_context_get_margin (style_context, state, &margin);
+ pnl_gtk_allocation_subtract_border (&alloc, &margin);
+
+ gtk_render_background (style_context, cr, alloc.x, alloc.y, alloc.width, alloc.height);
+
+ child = gtk_bin_get_child (GTK_BIN (widget));
+ if (child != NULL)
+ gtk_container_propagate_draw (GTK_CONTAINER (widget), child, cr);
+
+ gtk_render_frame (style_context, cr, alloc.x, alloc.y, alloc.width, alloc.height);
+
+ return FALSE;
+}
+
+static inline void
+add_border (GtkBorder *lsv,
+ const GtkBorder *rsv)
+{
+ lsv->left += rsv->left;
+ lsv->right += rsv->right;
+ lsv->top += rsv->top;
+ lsv->bottom += rsv->bottom;
+}
+
+static void
+pnl_bin_size_allocate (GtkWidget *widget,
+ GtkAllocation *alloc)
+{
+ PnlBin *self = (PnlBin *)widget;
+ GtkAllocation child_alloc = { 0 };
+ GtkWidget *child;
+
+ g_assert (PNL_IS_BIN (self));
+ g_assert (alloc != NULL);
+
+ child = gtk_bin_get_child (GTK_BIN (self));
+
+ if (child != NULL)
+ {
+ GtkStyleContext *style_context;
+ GtkBorder borders;
+
+ style_context = gtk_widget_get_style_context (widget);
+ child_alloc = *alloc;
+
+ if (gtk_widget_get_has_window (widget))
+ {
+ child_alloc.x = 0;
+ child_alloc.y = 0;
+ }
+
+ pnl_gtk_style_context_get_borders (style_context, &borders);
+ pnl_gtk_allocation_subtract_border (&child_alloc, &borders);
+ }
+
+ GTK_WIDGET_CLASS (pnl_bin_parent_class)->size_allocate (widget, alloc);
+
+ if (child != NULL)
+ gtk_widget_size_allocate (child, &child_alloc);
+}
+
+static void
+pnl_bin_get_preferred_width (GtkWidget *widget,
+ gint *min_width,
+ gint *nat_width)
+{
+ PnlBin *self = (PnlBin *)widget;
+ GtkStyleContext *style_context;
+ GtkWidget *child;
+ GtkBorder borders;
+
+ g_assert (PNL_IS_BIN (widget));
+
+ *min_width = 0;
+ *nat_width = 0;
+
+ child = gtk_bin_get_child (GTK_BIN (self));
+ if (child != NULL)
+ gtk_widget_get_preferred_width (child, min_width, nat_width);
+
+ style_context = gtk_widget_get_style_context (widget);
+ pnl_gtk_style_context_get_borders (style_context, &borders);
+
+ *min_width += (borders.left + borders.right);
+ *nat_width += (borders.left + borders.right);
+}
+
+static void
+pnl_bin_get_preferred_height (GtkWidget *widget,
+ gint *min_height,
+ gint *nat_height)
+{
+ PnlBin *self = (PnlBin *)widget;
+ GtkStyleContext *style_context;
+ GtkWidget *child;
+ GtkBorder borders;
+
+ g_assert (PNL_IS_BIN (widget));
+
+ *min_height = 0;
+ *nat_height = 0;
+
+ child = gtk_bin_get_child (GTK_BIN (self));
+ if (child != NULL)
+ gtk_widget_get_preferred_height (child, min_height, nat_height);
+
+ style_context = gtk_widget_get_style_context (widget);
+ pnl_gtk_style_context_get_borders (style_context, &borders);
+
+ *min_height += (borders.top + borders.bottom);
+ *nat_height += (borders.top + borders.bottom);
+}
+
+static void
+pnl_bin_class_init (PnlBinClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ widget_class->draw = pnl_bin_draw;
+ widget_class->get_preferred_width = pnl_bin_get_preferred_width;
+ widget_class->get_preferred_height = pnl_bin_get_preferred_height;
+ widget_class->size_allocate = pnl_bin_size_allocate;
+
+ gtk_widget_class_set_css_name (widget_class, "pnlbin");
+}
+
+static void
+pnl_bin_init (PnlBin *self)
+{
+}
+
+GtkWidget *
+pnl_bin_new (void)
+{
+ return g_object_new (PNL_TYPE_BIN, NULL);
+}
diff --git a/contrib/pnl/pnl-dock-tab-strip.c b/contrib/pnl/pnl-bin.h
similarity index 58%
rename from contrib/pnl/pnl-dock-tab-strip.c
rename to contrib/pnl/pnl-bin.h
index 3f0b9a6..125ea09 100644
--- a/contrib/pnl/pnl-dock-tab-strip.c
+++ b/contrib/pnl/pnl-bin.h
@@ -1,6 +1,6 @@
-/* pnl-dock-tab-strip.c
+/* pnl-bin.h
*
- * Copyright (C) 2016 Christian Hergert <christian hergert me>
+ * Copyright (C) 2017 Christian Hergert <chergert redhat com>
*
* 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
@@ -16,26 +16,28 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "pnl-dock-tab-strip.h"
+#if !defined(PNL_INSIDE) && !defined(PNL_COMPILATION)
+# error "Only <pnl.h> can be included directly."
+#endif
-struct _PnlDockTabStrip
-{
- PnlTabStrip parent;
-};
+#ifndef PNL_BIN_H
+#define PNL_BIN_H
-enum {
- PROP_0,
- N_PROPS
-};
+#include <gtk/gtk.h>
-G_DEFINE_TYPE (PnlDockTabStrip, pnl_dock_tab_strip, PNL_TYPE_TAB_STRIP)
+G_BEGIN_DECLS
-static void
-pnl_dock_tab_strip_class_init (PnlDockTabStripClass *klass)
-{
-}
+#define PNL_TYPE_BIN (pnl_bin_get_type())
+
+G_DECLARE_DERIVABLE_TYPE (PnlBin, pnl_bin, PNL, BIN, GtkBin)
-static void
-pnl_dock_tab_strip_init (PnlDockTabStrip *strip)
+struct _PnlBinClass
{
-}
+ GtkBinClass parent_class;
+};
+
+GtkWidget *pnl_bin_new (void);
+
+G_END_DECLS
+
+#endif /* PNL_BIN_H */
diff --git a/contrib/pnl/pnl-child-property-action.c b/contrib/pnl/pnl-child-property-action.c
new file mode 100644
index 0000000..e276099
--- /dev/null
+++ b/contrib/pnl/pnl-child-property-action.c
@@ -0,0 +1,558 @@
+/* pnl-child-property-action.c
+ *
+ * Copyright (C) 2017 Christian Hergert <chergert redhat com>
+ *
+ * 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 3 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/>.
+ */
+
+#define G_LOG_DOMAIN "pnl-child-property-action"
+
+#include "pnl-child-property-action.h"
+#include "pnl-util-private.h"
+
+struct _PnlChildPropertyAction
+{
+ GObject parent_instance;
+
+ GtkContainer *container;
+ GtkWidget *child;
+
+ const gchar *child_property_name;
+ const gchar *name;
+
+ guint enabled : 1;
+};
+
+enum {
+ PROP_0,
+ PROP_CHILD,
+ PROP_CHILD_PROPERTY_NAME,
+ PROP_CONTAINER,
+ PROP_ENABLED,
+ PROP_NAME,
+ PROP_PARAMETER_TYPE,
+ PROP_STATE,
+ PROP_STATE_TYPE,
+ N_PROPS
+};
+
+static void action_iface_init (GActionInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (PnlChildPropertyAction, pnl_child_property_action, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (G_TYPE_ACTION, action_iface_init))
+
+static GParamSpec *properties [N_PROPS];
+
+static const gchar *
+pnl_child_property_action_get_name (GAction *action)
+{
+ return PNL_CHILD_PROPERTY_ACTION (action)->name;
+}
+
+static const GVariantType *
+pnl_child_property_action_get_state_type (GAction *action)
+{
+ PnlChildPropertyAction *self = PNL_CHILD_PROPERTY_ACTION (action);
+
+ if (self->container != NULL &&
+ self->child != NULL &&
+ self->child_property_name != NULL)
+ {
+ GParamSpec *pspec;
+
+ pspec = gtk_container_class_find_child_property (G_OBJECT_GET_CLASS (self->container),
+ self->child_property_name);
+
+ if (pspec != NULL)
+ {
+ if (G_IS_PARAM_SPEC_BOOLEAN (pspec))
+ return G_VARIANT_TYPE ("b");
+ else if (G_IS_PARAM_SPEC_INT (pspec))
+ return G_VARIANT_TYPE ("i");
+ else if (G_IS_PARAM_SPEC_UINT (pspec))
+ return G_VARIANT_TYPE ("u");
+ else if (G_IS_PARAM_SPEC_STRING (pspec))
+ return G_VARIANT_TYPE ("s");
+ else if (G_IS_PARAM_SPEC_DOUBLE (pspec))
+ return G_VARIANT_TYPE ("d");
+ else if (G_IS_PARAM_SPEC_FLOAT (pspec))
+ return G_VARIANT_TYPE ("d");
+ }
+ }
+
+ g_warning ("Failed to discover state type for child property %s",
+ self->child_property_name);
+
+ return NULL;
+}
+
+static const GVariantType *
+pnl_child_property_action_get_parameter_type (GAction *action)
+{
+ const GVariantType *state_type = g_action_get_state_type (action);
+
+ if (g_variant_type_equal (state_type, G_VARIANT_TYPE ("b")))
+ return NULL;
+
+ return state_type;
+}
+
+
+static GVariant *
+pnl_child_property_action_get_state_hint (GAction *action)
+{
+ return NULL;
+}
+
+static gboolean
+pnl_child_property_action_get_enabled (GAction *action)
+{
+ return PNL_CHILD_PROPERTY_ACTION (action)->enabled;
+}
+
+static GVariant *
+pnl_child_property_action_get_state (GAction *action)
+{
+ PnlChildPropertyAction *self = PNL_CHILD_PROPERTY_ACTION (action);
+
+ g_assert (PNL_IS_CHILD_PROPERTY_ACTION (self));
+
+ if (self->container != NULL &&
+ self->child != NULL &&
+ self->child_property_name != NULL)
+ {
+ GParamSpec *pspec;
+
+ pspec = gtk_container_class_find_child_property (G_OBJECT_GET_CLASS (self->container),
+ self->child_property_name);
+
+ if (pspec != NULL)
+ {
+ g_auto(GValue) value = G_VALUE_INIT;
+ GVariant *ret = NULL;
+
+ g_value_init (&value, pspec->value_type);
+ gtk_container_child_get_property (self->container,
+ self->child,
+ self->child_property_name,
+ &value);
+
+ if (G_IS_PARAM_SPEC_BOOLEAN (pspec))
+ ret = g_variant_new_boolean (g_value_get_boolean (&value));
+ else if (G_IS_PARAM_SPEC_INT (pspec))
+ ret = g_variant_new_int32 (g_value_get_int (&value));
+ else if (G_IS_PARAM_SPEC_UINT (pspec))
+ ret = g_variant_new_uint32 (g_value_get_uint (&value));
+ else if (G_IS_PARAM_SPEC_STRING (pspec))
+ ret = g_variant_new_string (g_value_get_string (&value));
+ else if (G_IS_PARAM_SPEC_DOUBLE (pspec))
+ ret = g_variant_new_double (g_value_get_double (&value));
+ else if (G_IS_PARAM_SPEC_FLOAT (pspec))
+ ret = g_variant_new_double (g_value_get_double (&value));
+
+ if (ret)
+ return g_variant_ref_sink (ret);
+ }
+ }
+
+ g_warning ("Failed to determine default state");
+
+ return NULL;
+}
+
+static void
+pnl_child_property_action_change_state (GAction *action,
+ GVariant *state)
+{
+ PnlChildPropertyAction *self = PNL_CHILD_PROPERTY_ACTION (action);
+
+ if (self->container != NULL &&
+ self->child != NULL &&
+ self->child_property_name != NULL)
+ {
+ GParamSpec *pspec;
+
+ pspec = gtk_container_class_find_child_property (G_OBJECT_GET_CLASS (self->container),
+ self->child_property_name);
+
+ if (pspec != NULL)
+ {
+ g_auto(GValue) value = G_VALUE_INIT;
+
+ g_value_init (&value, pspec->value_type);
+
+ if (G_IS_PARAM_SPEC_BOOLEAN (pspec))
+ {
+ if (!g_variant_is_of_type (state, G_VARIANT_TYPE_BOOLEAN))
+ {
+ g_warning ("Expected 'b', got %s", g_variant_get_type_string (state));
+ return;
+ }
+
+ g_value_set_boolean (&value, g_variant_get_boolean (state));
+ }
+ else if (G_IS_PARAM_SPEC_INT (pspec))
+ {
+ if (!g_variant_is_of_type (state, G_VARIANT_TYPE_INT32))
+ {
+ g_warning ("Expected 'i', got %s", g_variant_get_type_string (state));
+ return;
+ }
+
+ g_value_set_int (&value, g_variant_get_int32 (state));
+ }
+ else if (G_IS_PARAM_SPEC_UINT (pspec))
+ {
+ if (!g_variant_is_of_type (state, G_VARIANT_TYPE_UINT32))
+ {
+ g_warning ("Expected 'u', got %s", g_variant_get_type_string (state));
+ return;
+ }
+
+ g_value_set_uint (&value, g_variant_get_uint32 (state));
+ }
+ else if (G_IS_PARAM_SPEC_STRING (pspec))
+ {
+ if (!g_variant_is_of_type (state, G_VARIANT_TYPE_STRING))
+ {
+ g_warning ("Expected 's', got %s", g_variant_get_type_string (state));
+ return;
+ }
+
+ g_value_set_string (&value, g_variant_get_string (state, NULL));
+ }
+ else if (G_IS_PARAM_SPEC_DOUBLE (pspec) || G_IS_PARAM_SPEC_FLOAT (pspec))
+ {
+ if (!g_variant_is_of_type (state, G_VARIANT_TYPE_STRING))
+ {
+ g_warning ("Expected 'd', got %s", g_variant_get_type_string (state));
+ return;
+ }
+
+ if (G_IS_PARAM_SPEC_DOUBLE (pspec))
+ g_value_set_double (&value, g_variant_get_double (state));
+ else
+ g_value_set_float (&value, g_variant_get_double (state));
+ }
+ else
+ {
+ g_warning ("I don't know how to handle %s property types.",
+ g_type_name (pspec->value_type));
+ return;
+ }
+
+ gtk_container_child_set_property (self->container,
+ self->child,
+ self->child_property_name,
+ &value);
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_STATE]);
+
+ return;
+ }
+ }
+
+ g_warning ("Attempt to change state on incapable child property action");
+}
+
+static void
+pnl_child_property_action_activate (GAction *action,
+ GVariant *parameter)
+{
+ PnlChildPropertyAction *self = (PnlChildPropertyAction *)action;
+
+ g_assert (PNL_IS_CHILD_PROPERTY_ACTION (self));
+
+ if (parameter == NULL &&
+ self->container != NULL &&
+ self->child != NULL &&
+ self->child_property_name != NULL)
+ {
+ GParamSpec *pspec;
+
+ pspec = gtk_container_class_find_child_property (G_OBJECT_GET_CLASS (self->container),
+ self->child_property_name);
+
+ if (pspec != NULL)
+ {
+ g_auto(GValue) value = G_VALUE_INIT;
+
+ if (G_IS_PARAM_SPEC_BOOLEAN (pspec))
+ {
+ g_value_init (&value, G_TYPE_BOOLEAN);
+
+ if (parameter != NULL)
+ g_value_set_boolean (&value, g_variant_get_boolean (parameter));
+ else
+ {
+ g_auto(GValue) previous = G_VALUE_INIT;
+
+ g_value_init (&previous, G_TYPE_BOOLEAN);
+ gtk_container_child_get_property (self->container,
+ self->child,
+ self->child_property_name,
+ &previous);
+ g_value_set_boolean (&value, !g_value_get_boolean (&previous));
+ }
+ }
+ else if (G_IS_PARAM_SPEC_INT (pspec))
+ {
+ g_value_init (&value, G_TYPE_INT);
+ g_value_set_int (&value, g_variant_get_int32 (parameter));
+ }
+ else if (G_IS_PARAM_SPEC_UINT (pspec))
+ {
+ g_value_init (&value, G_TYPE_UINT);
+ g_value_set_uint (&value, g_variant_get_uint32 (parameter));
+ }
+ else if (G_IS_PARAM_SPEC_STRING (pspec))
+ {
+ g_value_init (&value, G_TYPE_STRING);
+ g_value_set_string (&value, g_variant_get_string (parameter, NULL));
+ }
+ else if (G_IS_PARAM_SPEC_DOUBLE (pspec) || G_IS_PARAM_SPEC_FLOAT (pspec))
+ {
+ g_value_init (&value, G_TYPE_DOUBLE);
+ g_value_set_double (&value, g_variant_get_double (parameter));
+ }
+ else
+ {
+ g_warning ("Failed to transform state type");
+ return;
+ }
+
+ gtk_container_child_set_property (self->container, self->child, pspec->name, &value);
+
+ return;
+ }
+ }
+
+ g_warning ("I don't know how to activate %s", self->name);
+}
+
+static void
+action_iface_init (GActionInterface *iface)
+{
+ iface->get_name = pnl_child_property_action_get_name;
+ iface->get_parameter_type = pnl_child_property_action_get_parameter_type;
+ iface->get_state_type = pnl_child_property_action_get_state_type;
+ iface->get_state_hint = pnl_child_property_action_get_state_hint;
+ iface->get_enabled = pnl_child_property_action_get_enabled;
+ iface->get_state = pnl_child_property_action_get_state;
+ iface->change_state = pnl_child_property_action_change_state;
+ iface->activate = pnl_child_property_action_activate;
+}
+
+static void
+child_notify_cb (PnlChildPropertyAction *self,
+ GParamSpec *pspec,
+ GtkWidget *child)
+{
+ g_assert (PNL_IS_CHILD_PROPERTY_ACTION (self));
+ g_assert (pspec != NULL);
+ g_assert (GTK_IS_WIDGET (child));
+
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_STATE]);
+}
+
+static void
+pnl_child_property_action_constructed (GObject *object)
+{
+ PnlChildPropertyAction *self = (PnlChildPropertyAction *)object;
+ g_autofree gchar *signal_detail = NULL;
+
+ G_OBJECT_CLASS (pnl_child_property_action_parent_class)->constructed (object);
+
+ if (!self->child || !self->container || !self->child_property_name)
+ {
+ g_warning ("Child property action not setup correctly.");
+ return;
+ }
+
+ signal_detail = g_strdup_printf ("child-notify::%s", self->child_property_name);
+
+ g_signal_connect_object (self->child,
+ signal_detail,
+ G_CALLBACK (child_notify_cb),
+ self,
+ G_CONNECT_SWAPPED);
+}
+
+static void
+pnl_child_property_action_dispose (GObject *object)
+{
+ PnlChildPropertyAction *self = (PnlChildPropertyAction *)object;
+
+ pnl_clear_weak_pointer (&self->container);
+ pnl_clear_weak_pointer (&self->child);
+
+ G_OBJECT_CLASS (pnl_child_property_action_parent_class)->dispose (object);
+}
+
+static void
+pnl_child_property_action_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ PnlChildPropertyAction *self = PNL_CHILD_PROPERTY_ACTION (object);
+
+ switch (prop_id)
+ {
+ case PROP_CONTAINER:
+ g_value_set_object (value, self->container);
+ break;
+
+ case PROP_CHILD:
+ g_value_set_object (value, self->child);
+ break;
+
+ case PROP_CHILD_PROPERTY_NAME:
+ g_value_set_static_string (value, self->child_property_name);
+ break;
+
+ case PROP_ENABLED:
+ g_value_set_boolean (value, self->enabled);
+ break;
+
+ case PROP_PARAMETER_TYPE:
+ g_value_set_boxed (value, pnl_child_property_action_get_parameter_type (G_ACTION (self)));
+ break;
+
+ case PROP_STATE:
+ g_value_take_variant (value, pnl_child_property_action_get_state (G_ACTION (self)));
+ break;
+
+ case PROP_STATE_TYPE:
+ g_value_set_boxed (value, pnl_child_property_action_get_state_type (G_ACTION (self)));
+ break;
+
+ case PROP_NAME:
+ g_value_set_static_string (value, self->name);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+pnl_child_property_action_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ PnlChildPropertyAction *self = PNL_CHILD_PROPERTY_ACTION (object);
+
+ switch (prop_id)
+ {
+ case PROP_CONTAINER:
+ pnl_set_weak_pointer (&self->container, g_value_get_object (value));
+ break;
+
+ case PROP_CHILD:
+ pnl_set_weak_pointer (&self->child, g_value_get_object (value));
+ break;
+
+ case PROP_CHILD_PROPERTY_NAME:
+ self->child_property_name = g_intern_string (g_value_get_string (value));
+ break;
+
+ case PROP_ENABLED:
+ self->enabled = g_value_get_boolean (value);
+ break;
+
+ case PROP_NAME:
+ self->name = g_intern_string (g_value_get_string (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+pnl_child_property_action_class_init (PnlChildPropertyActionClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = pnl_child_property_action_dispose;
+ object_class->get_property = pnl_child_property_action_get_property;
+ object_class->set_property = pnl_child_property_action_set_property;
+ object_class->constructed = pnl_child_property_action_constructed;
+
+ properties [PROP_CHILD] =
+ g_param_spec_object ("child",
+ "Child",
+ "The child widget",
+ GTK_TYPE_WIDGET,
+ (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_CHILD_PROPERTY_NAME] =
+ g_param_spec_string ("child-property-name",
+ "Child Property Name",
+ "The name of the child property",
+ NULL,
+ (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_CONTAINER] =
+ g_param_spec_object ("container",
+ "Container",
+ "The container widget",
+ GTK_TYPE_CONTAINER,
+ (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_ENABLED] =
+ g_param_spec_boolean ("enabled",
+ "Enabled",
+ "Enabled",
+ TRUE,
+ (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_PARAMETER_TYPE] =
+ g_param_spec_boxed ("parameter-type",
+ "Parameter Type",
+ "The parameter type",
+ G_TYPE_VARIANT_TYPE,
+ (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_STATE] =
+ g_param_spec_variant ("state",
+ "State",
+ "State for the action",
+ G_VARIANT_TYPE_ANY,
+ NULL,
+ (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_STATE_TYPE] =
+ g_param_spec_boxed ("state-type",
+ "State Type",
+ "The state type",
+ G_TYPE_VARIANT_TYPE,
+ (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_NAME] =
+ g_param_spec_string ("name",
+ "Action Name",
+ "The name of the action",
+ NULL,
+ (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+pnl_child_property_action_init (PnlChildPropertyAction *self)
+{
+ self->enabled = TRUE;
+}
diff --git a/contrib/pnl/pnl-dock-tab-strip.h b/contrib/pnl/pnl-child-property-action.h
similarity index 56%
copy from contrib/pnl/pnl-dock-tab-strip.h
copy to contrib/pnl/pnl-child-property-action.h
index 6cf04d6..f8319de 100644
--- a/contrib/pnl/pnl-dock-tab-strip.h
+++ b/contrib/pnl/pnl-child-property-action.h
@@ -1,6 +1,6 @@
-/* pnl-dock-tab-strip.h
+/* pnl-child-property-action.h
*
- * Copyright (C) 2016 Christian Hergert <christian hergert me>
+ * Copyright (C) 2017 Christian Hergert <chergert redhat com>
*
* 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
@@ -16,19 +16,21 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef PNL_DOCK_TAB_STRIP_H
-#define PNL_DOCK_TAB_STRIP_H
+#if !defined(PNL_INSIDE) && !defined(PNL_COMPILATION)
+# error "Only <pnl.h> can be included directly."
+#endif
-#include "pnl-tab-strip.h"
+#ifndef PNL_CHILD_PROPERTY_ACTION_H
+#define PNL_CHILD_PROPERTY_ACTION_H
-G_BEGIN_DECLS
+#include "pnl-dock-types.h"
-#define PNL_TYPE_DOCK_TAB_STRIP (pnl_dock_tab_strip_get_type())
+G_BEGIN_DECLS
-G_DECLARE_FINAL_TYPE (PnlDockTabStrip, pnl_dock_tab_strip, PNL, DOCK_TAB_STRIP, PnlTabStrip)
+#define PNL_TYPE_CHILD_PROPERTY_ACTION (pnl_child_property_action_get_type())
-GtkWidget *pnl_dock_tab_strip_new (void);
+G_DECLARE_FINAL_TYPE (PnlChildPropertyAction, pnl_child_property_action, PNL, CHILD_PROPERTY_ACTION,
GObject)
G_END_DECLS
-#endif /* PNL_DOCK_TAB_STRIP_H */
+#endif /* PNL_CHILD_PROPERTY_ACTION_H */
diff --git a/contrib/pnl/pnl-dock-bin-edge-private.h b/contrib/pnl/pnl-dock-bin-edge-private.h
index e45e4e2..ea3956d 100644
--- a/contrib/pnl/pnl-dock-bin-edge-private.h
+++ b/contrib/pnl/pnl-dock-bin-edge-private.h
@@ -16,6 +16,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#if !defined(PNL_INSIDE) && !defined(PNL_COMPILATION)
+# error "Only <pnl.h> can be included directly."
+#endif
+
#ifndef PNL_DOCK_BIN_EDGE_PRIVATE_H
#define PNL_DOCK_BIN_EDGE_PRIVATE_H
@@ -23,8 +27,8 @@
G_BEGIN_DECLS
-void pnl_dock_bin_edge_set_edge (PnlDockBinEdge *self,
- GtkPositionType bin_edge);
+void pnl_dock_bin_edge_set_edge (PnlDockBinEdge *self,
+ GtkPositionType bin_edge);
G_END_DECLS
diff --git a/contrib/pnl/pnl-dock-bin-edge.c b/contrib/pnl/pnl-dock-bin-edge.c
index 408ceb2..d4f0b6e 100644
--- a/contrib/pnl/pnl-dock-bin-edge.c
+++ b/contrib/pnl/pnl-dock-bin-edge.c
@@ -19,6 +19,7 @@
#include "pnl-dock-bin.h"
#include "pnl-dock-bin-edge.h"
#include "pnl-dock-bin-edge-private.h"
+#include "pnl-dock-item.h"
#include "pnl-dock-revealer.h"
typedef struct
@@ -26,9 +27,11 @@ typedef struct
GtkPositionType edge : 3;
} PnlDockBinEdgePrivate;
+static void dock_item_iface_init (PnlDockItemInterface *iface);
+
G_DEFINE_TYPE_EXTENDED (PnlDockBinEdge, pnl_dock_bin_edge, PNL_TYPE_DOCK_REVEALER, 0,
G_ADD_PRIVATE (PnlDockBinEdge)
- G_IMPLEMENT_INTERFACE (PNL_TYPE_DOCK_ITEM, NULL))
+ G_IMPLEMENT_INTERFACE (PNL_TYPE_DOCK_ITEM, dock_item_iface_init))
enum {
PROP_0,
@@ -139,6 +142,11 @@ pnl_dock_bin_edge_add (GtkContainer *container,
child = gtk_bin_get_child (GTK_BIN (container));
gtk_container_add (GTK_CONTAINER (child), widget);
+
+ if (PNL_IS_DOCK_ITEM (child))
+ pnl_dock_item_adopt (PNL_DOCK_ITEM (container), PNL_DOCK_ITEM (child));
+
+ gtk_widget_show (child);
}
static void
@@ -238,7 +246,7 @@ pnl_dock_bin_edge_class_init (PnlDockBinEdgeClass *klass)
binding_set = gtk_binding_set_by_class (klass);
gtk_binding_entry_add_signal (binding_set, GDK_KEY_Escape, 0, "move-to-bin-child", 0);
- gtk_widget_class_set_css_name (widget_class, "dockbinedge");
+ gtk_widget_class_set_css_name (widget_class, "pnldockbinedge");
}
static void
@@ -250,6 +258,26 @@ pnl_dock_bin_edge_init (PnlDockBinEdge *self)
"visible", TRUE,
NULL);
GTK_CONTAINER_CLASS (pnl_dock_bin_edge_parent_class)->add (GTK_CONTAINER (self), child);
+}
- pnl_dock_bin_edge_update_edge (self);
+static void
+pnl_dock_bin_edge_update_visibility (PnlDockItem *item)
+{
+ PnlDockBinEdge *self = (PnlDockBinEdge *)item;
+ GtkWidget *child;
+ gboolean visible = FALSE;
+
+ g_assert (PNL_IS_DOCK_BIN_EDGE (self));
+
+ if (NULL != (child = gtk_bin_get_child (GTK_BIN (self))))
+ visible = pnl_dock_item_has_widgets (PNL_DOCK_ITEM (child));
+
+ if (visible != pnl_dock_revealer_get_reveal_child (PNL_DOCK_REVEALER (self)))
+ pnl_dock_revealer_set_reveal_child (PNL_DOCK_REVEALER (self), visible);
+}
+
+static void
+dock_item_iface_init (PnlDockItemInterface *iface)
+{
+ iface->update_visibility = pnl_dock_bin_edge_update_visibility;
}
diff --git a/contrib/pnl/pnl-dock-bin-edge.h b/contrib/pnl/pnl-dock-bin-edge.h
index c5496fa..3c2421d 100644
--- a/contrib/pnl/pnl-dock-bin-edge.h
+++ b/contrib/pnl/pnl-dock-bin-edge.h
@@ -16,17 +16,17 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#if !defined(PNL_INSIDE) && !defined(PNL_COMPILATION)
+# error "Only <pnl.h> can be included directly."
+#endif
+
#ifndef PNL_DOCK_BIN_EDGE_H
#define PNL_DOCK_BIN_EDGE_H
-#include "pnl-dock-revealer.h"
+#include "pnl-dock-types.h"
G_BEGIN_DECLS
-#define PNL_TYPE_DOCK_BIN_EDGE (pnl_dock_bin_edge_get_type())
-
-G_DECLARE_DERIVABLE_TYPE (PnlDockBinEdge, pnl_dock_bin_edge, PNL, DOCK_BIN_EDGE, PnlDockRevealer)
-
struct _PnlDockBinEdgeClass
{
PnlDockRevealerClass parent;
diff --git a/contrib/pnl/pnl-dock-bin.c b/contrib/pnl/pnl-dock-bin.c
index c3fb51d..91e8945 100644
--- a/contrib/pnl/pnl-dock-bin.c
+++ b/contrib/pnl/pnl-dock-bin.c
@@ -18,12 +18,13 @@
#include <stdlib.h>
+#include "pnl-child-property-action.h"
#include "pnl-dock-bin.h"
#include "pnl-dock-bin-edge-private.h"
#include "pnl-dock-item.h"
-#define HANDLE_WIDTH 10
-#define HANDLE_HEIGHT 10
+#define HANDLE_WIDTH 3
+#define HANDLE_HEIGHT 3
typedef enum
{
@@ -83,6 +84,13 @@ typedef struct
* the last child, and our sort function ensures that.
*/
PnlDockBinChildType type : 3;
+
+ /*
+ * If the panel is pinned, this will be set to TRUE. A pinned panel
+ * means that it is displayed juxtapose the center child, where as
+ * an unpinned child is floating above teh center child.
+ */
+ guint pinned : 1;
} PnlDockBinChild;
typedef struct
@@ -122,34 +130,184 @@ static void pnl_dock_bin_init_dock_item_iface (PnlDockItemInterface *iface);
G_DEFINE_TYPE_EXTENDED (PnlDockBin, pnl_dock_bin, GTK_TYPE_CONTAINER, 0,
G_ADD_PRIVATE (PnlDockBin)
- G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
- pnl_dock_bin_init_buildable_iface)
- G_IMPLEMENT_INTERFACE (PNL_TYPE_DOCK_ITEM,
- pnl_dock_bin_init_dock_item_iface)
- G_IMPLEMENT_INTERFACE (PNL_TYPE_DOCK,
- pnl_dock_bin_init_dock_iface))
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, pnl_dock_bin_init_buildable_iface)
+ G_IMPLEMENT_INTERFACE (PNL_TYPE_DOCK_ITEM, pnl_dock_bin_init_dock_item_iface)
+ G_IMPLEMENT_INTERFACE (PNL_TYPE_DOCK, pnl_dock_bin_init_dock_iface))
enum {
PROP_0,
+ PROP_LEFT_VISIBLE,
+ PROP_RIGHT_VISIBLE,
+ PROP_TOP_VISIBLE,
+ PROP_BOTTOM_VISIBLE,
+ N_PROPS,
+
PROP_MANAGER,
- N_PROPS
};
enum {
CHILD_PROP_0,
+ CHILD_PROP_PINNED,
CHILD_PROP_POSITION,
CHILD_PROP_PRIORITY,
N_CHILD_PROPS
};
-enum {
- STYLE_PROP_0,
- STYLE_PROP_HANDLE_SIZE,
- N_STYLE_PROPS
-};
-
+static GParamSpec *properties [N_PROPS];
static GParamSpec *child_properties [N_CHILD_PROPS];
-static GParamSpec *style_properties [N_STYLE_PROPS];
+
+static gint
+pnl_dock_bin_child_compare (gconstpointer a,
+ gconstpointer b)
+{
+ const PnlDockBinChild *child_a = a;
+ const PnlDockBinChild *child_b = b;
+
+ if (child_a->type == PNL_DOCK_BIN_CHILD_CENTER)
+ return 1;
+ else if (child_b->type == PNL_DOCK_BIN_CHILD_CENTER)
+ return -1;
+
+ if ((child_a->pinned ^ child_b->pinned) != 0)
+ return child_a->pinned - child_b->pinned;
+
+ return child_a->priority - child_b->priority;
+}
+
+static void
+pnl_dock_bin_resort_children (PnlDockBin *self)
+{
+ PnlDockBinPrivate *priv = pnl_dock_bin_get_instance_private (self);
+
+ g_assert (PNL_IS_DOCK_BIN (self));
+
+ /*
+ * Sort the children by priority/pinned status, but do not change
+ * the position of the PNL_DOCK_BIN_CHILD_CENTER child. It should
+ * always be at the last position.
+ */
+
+ g_qsort_with_data (&priv->children[0],
+ PNL_DOCK_BIN_CHILD_CENTER,
+ sizeof (PnlDockBinChild),
+ (GCompareDataFunc)pnl_dock_bin_child_compare,
+ NULL);
+
+ gtk_widget_queue_allocate (GTK_WIDGET (self));
+}
+
+static GAction *
+pnl_dock_bin_get_visible_action_for_type (PnlDockBin *self,
+ PnlDockBinChildType type)
+{
+ PnlDockBinPrivate *priv = pnl_dock_bin_get_instance_private (self);
+ const gchar *name = NULL;
+
+ g_assert (PNL_IS_DOCK_BIN (self));
+
+ switch (type)
+ {
+ case PNL_DOCK_BIN_CHILD_LEFT:
+ name = "left-visible";
+ break;
+
+ case PNL_DOCK_BIN_CHILD_RIGHT:
+ name = "right-visible";
+ break;
+
+ case PNL_DOCK_BIN_CHILD_TOP:
+ name = "top-visible";
+ break;
+
+ case PNL_DOCK_BIN_CHILD_BOTTOM:
+ name = "bottom-visible";
+ break;
+
+ case PNL_DOCK_BIN_CHILD_CENTER:
+ case LAST_PNL_DOCK_BIN_CHILD:
+ default:
+ g_assert_not_reached ();
+ }
+
+ return g_action_map_lookup_action (G_ACTION_MAP (priv->actions), name);
+}
+
+static gboolean
+get_visible (PnlDockBin *self,
+ const gchar *action_name)
+{
+ PnlDockBinPrivate *priv = pnl_dock_bin_get_instance_private (self);
+ GAction *action;
+
+ g_assert (PNL_IS_DOCK_BIN (self));
+ g_assert (action_name != NULL);
+
+ action = g_action_map_lookup_action (G_ACTION_MAP (priv->actions), action_name);
+
+ if (action != NULL)
+ {
+ GVariant *v = g_action_get_state (action);
+ gboolean ret = v ? g_variant_get_boolean (v) : FALSE;
+
+ g_clear_pointer (&v, g_variant_unref);
+
+ return ret;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+set_visible (PnlDockBin *self,
+ const gchar *action_name,
+ gboolean value)
+{
+ PnlDockBinPrivate *priv = pnl_dock_bin_get_instance_private (self);
+ GAction *action;
+
+ g_assert (PNL_IS_DOCK_BIN (self));
+ g_assert (action_name != NULL);
+
+ action = g_action_map_lookup_action (G_ACTION_MAP (priv->actions), action_name);
+
+ if (action != NULL)
+ g_simple_action_set_state (G_SIMPLE_ACTION (action), g_variant_new_boolean (value));
+
+ return FALSE;
+}
+
+static void
+pnl_dock_bin_update_actions (PnlDockBin *self)
+{
+ PnlDockBinPrivate *priv = pnl_dock_bin_get_instance_private (self);
+ guint i;
+
+ g_assert (PNL_IS_DOCK_BIN (self));
+
+ /*
+ * We need to walk each of the children edges looking for widgets
+ * that are visible. If so, we need to keep the edge action enabled.
+ * Otherwise disable it, so any buttons representing the action get
+ * properly desensitized.
+ */
+
+ for (i = 0; i < G_N_ELEMENTS (priv->children); i++)
+ {
+ PnlDockBinChild *child = &priv->children [i];
+ GAction *action;
+ gboolean enabled = FALSE;
+
+ if (child->type == PNL_DOCK_BIN_CHILD_CENTER)
+ continue;
+
+ action = pnl_dock_bin_get_visible_action_for_type (self, child->type);
+
+ if (child->widget != NULL)
+ enabled = pnl_dock_item_has_widgets (PNL_DOCK_ITEM (child->widget));
+
+ g_simple_action_set_enabled (G_SIMPLE_ACTION (action), enabled);
+ }
+}
static gboolean
map_boolean_to_variant (GBinding *binding,
@@ -245,29 +403,6 @@ pnl_dock_bin_update_focus_chain (PnlDockBin *self)
}
}
-static GAction *
-pnl_dock_bin_get_action_for_type (PnlDockBin *self,
- PnlDockBinChildType type)
-{
- PnlDockBinPrivate *priv = pnl_dock_bin_get_instance_private (self);
- const gchar *name = NULL;
-
- g_assert (PNL_IS_DOCK_BIN (self));
-
- if (type == PNL_DOCK_BIN_CHILD_LEFT)
- name = "left-visible";
- else if (type == PNL_DOCK_BIN_CHILD_RIGHT)
- name = "right-visible";
- else if (type == PNL_DOCK_BIN_CHILD_TOP)
- name = "top-visible";
- else if (type == PNL_DOCK_BIN_CHILD_BOTTOM)
- name = "bottom-visible";
- else
- g_assert_not_reached ();
-
- return g_action_map_lookup_action (G_ACTION_MAP (priv->actions), name);
-}
-
static void
pnl_dock_bin_add (GtkContainer *container,
GtkWidget *widget)
@@ -330,14 +465,33 @@ pnl_dock_bin_forall (GtkContainer *container,
{
PnlDockBin *self = (PnlDockBin *)container;
PnlDockBinPrivate *priv = pnl_dock_bin_get_instance_private (self);
+ PnlDockBinChild *child;
guint i;
g_assert (PNL_IS_DOCK_BIN (self));
g_assert (callback != NULL);
- for (i = G_N_ELEMENTS (priv->children); i > 0; i--)
+ /*
+ * Always call the "center" child callback first. This helps ensure that
+ * it is the first child to be rendered. We need that to ensure that panels
+ * are drawn *above* the center, even when floating. Note that the center
+ * child is always the last child in the array.
+ */
+ child = &priv->children [G_N_ELEMENTS (priv->children) - 1];
+ if (child->widget != NULL)
+ callback (child->widget, user_data);
+
+ /*
+ * Normally, we would iterate the array backwards so that we can ensure that
+ * the list is safe against widget destruction. However, since we have a
+ * fixed size array, we can walk forwards safely. This helps ensure we
+ * preserve draw ordering for the various panels when we chain up to the
+ * container draw vfunc.
+ */
+
+ for (i = 0; i < G_N_ELEMENTS (priv->children) - 1; i++)
{
- PnlDockBinChild *child = &priv->children [i - 1];
+ child = &priv->children[i];
if (child->widget != NULL)
callback (GTK_WIDGET (child->widget), user_data);
@@ -357,7 +511,6 @@ pnl_dock_bin_get_children_preferred_width (PnlDockBin *self,
gint child_nat_width = 0;
gint neighbor_min_width = 0;
gint neighbor_nat_width = 0;
- gint handle_size = 0;
g_assert (PNL_IS_DOCK_BIN (self));
g_assert (children != NULL);
@@ -368,10 +521,6 @@ pnl_dock_bin_get_children_preferred_width (PnlDockBin *self,
*min_width = 0;
*nat_width = 0;
- gtk_widget_style_get (GTK_WIDGET (self),
- "handle-size", &handle_size,
- NULL);
-
/*
* We have a fairly simple rule for deducing the size request of
* the children layout. Since children edges can have any priority,
@@ -432,14 +581,22 @@ pnl_dock_bin_get_children_preferred_width (PnlDockBin *self,
{
case PNL_DOCK_BIN_CHILD_LEFT:
case PNL_DOCK_BIN_CHILD_RIGHT:
- *min_width = (child_min_width + neighbor_min_width + handle_size);
- *nat_width = (child_nat_width + neighbor_nat_width + handle_size);
+ if (child->pinned)
+ {
+ *min_width = (child_min_width + neighbor_min_width);
+ *nat_width = (child_nat_width + neighbor_nat_width);
+ }
+ else
+ {
+ *min_width = MAX (child_min_width, neighbor_min_width);
+ *nat_width = MAX (child_nat_width, neighbor_nat_width);
+ }
break;
case PNL_DOCK_BIN_CHILD_TOP:
case PNL_DOCK_BIN_CHILD_BOTTOM:
- *min_width = MAX (child_min_width, neighbor_min_width + handle_size);
- *nat_width = MAX (child_nat_width, neighbor_nat_width + handle_size);
+ *min_width = MAX (child_min_width, neighbor_min_width);
+ *nat_width = MAX (child_nat_width, neighbor_nat_width);
break;
case PNL_DOCK_BIN_CHILD_CENTER:
@@ -488,7 +645,6 @@ pnl_dock_bin_get_children_preferred_height (PnlDockBin *self,
gint child_nat_height = 0;
gint neighbor_min_height = 0;
gint neighbor_nat_height = 0;
- gint handle_size = 0;
g_assert (PNL_IS_DOCK_BIN (self));
g_assert (children != NULL);
@@ -499,10 +655,6 @@ pnl_dock_bin_get_children_preferred_height (PnlDockBin *self,
*min_height = 0;
*nat_height = 0;
- gtk_widget_style_get (GTK_WIDGET (self),
- "handle-size", &handle_size,
- NULL);
-
/*
* See pnl_dock_bin_get_children_preferred_width() for more information on
* how this works. This works just like that but the negotiated/additive
@@ -527,14 +679,22 @@ pnl_dock_bin_get_children_preferred_height (PnlDockBin *self,
{
case PNL_DOCK_BIN_CHILD_LEFT:
case PNL_DOCK_BIN_CHILD_RIGHT:
- *min_height = MAX (child_min_height, neighbor_min_height + handle_size);
- *nat_height = MAX (child_nat_height, neighbor_nat_height + handle_size);
+ *min_height = MAX (child_min_height, neighbor_min_height);
+ *nat_height = MAX (child_nat_height, neighbor_nat_height);
break;
case PNL_DOCK_BIN_CHILD_TOP:
case PNL_DOCK_BIN_CHILD_BOTTOM:
- *min_height = (child_min_height + neighbor_min_height + handle_size);
- *nat_height = (child_nat_height + neighbor_nat_height + handle_size);
+ if (child->pinned)
+ {
+ *min_height = (child_min_height + neighbor_min_height);
+ *nat_height = (child_nat_height + neighbor_nat_height);
+ }
+ else
+ {
+ *min_height = MAX (child_min_height, neighbor_min_height);
+ *nat_height = MAX (child_nat_height, neighbor_nat_height);
+ }
break;
case PNL_DOCK_BIN_CHILD_CENTER:
@@ -605,7 +765,6 @@ pnl_dock_bin_child_size_allocate (PnlDockBin *self,
GtkAllocation *allocation)
{
PnlDockBinChild *child = children;
- gint handle_size = 0;
g_assert (PNL_IS_DOCK_BIN (self));
g_assert (children != NULL);
@@ -622,10 +781,6 @@ pnl_dock_bin_child_size_allocate (PnlDockBin *self,
return;
}
- gtk_widget_style_get (GTK_WIDGET (self),
- "handle-size", &handle_size,
- NULL);
-
if (child->widget != NULL &&
gtk_widget_get_visible (child->widget) &&
gtk_widget_get_child_visible (child->widget))
@@ -634,6 +789,11 @@ pnl_dock_bin_child_size_allocate (PnlDockBin *self,
GtkAllocation handle_alloc = { 0 };
GtkRequisition neighbor_min = { 0 };
GtkRequisition neighbor_nat = { 0 };
+ GtkStyleContext *style_context = gtk_widget_get_style_context (child->widget);
+ GtkStateType state = gtk_style_context_get_state (style_context);
+ GtkBorder margin;
+
+ gtk_style_context_get_margin (style_context, state, &margin);
pnl_dock_bin_get_children_preferred_height (self, child, 1,
&child->min_req.height,
@@ -643,17 +803,20 @@ pnl_dock_bin_child_size_allocate (PnlDockBin *self,
&child->min_req.width,
&child->nat_req.width);
- pnl_dock_bin_get_children_preferred_height (self,
- &children [1],
- n_children - 1,
- &neighbor_min.height,
- &neighbor_nat.height);
-
- pnl_dock_bin_get_children_preferred_width (self,
- &children [1],
- n_children - 1,
- &neighbor_min.width,
- &neighbor_nat.width);
+ if (child->pinned)
+ {
+ pnl_dock_bin_get_children_preferred_height (self,
+ &children [1],
+ n_children - 1,
+ &neighbor_min.height,
+ &neighbor_nat.height);
+
+ pnl_dock_bin_get_children_preferred_width (self,
+ &children [1],
+ n_children - 1,
+ &neighbor_min.width,
+ &neighbor_nat.width);
+ }
pnl_dock_bin_negotiate_size (self,
allocation,
@@ -669,36 +832,52 @@ pnl_dock_bin_child_size_allocate (PnlDockBin *self,
child_alloc.x = allocation->x;
child_alloc.y = allocation->y;
child_alloc.height = allocation->height;
- child_alloc.width -= handle_size;
- allocation->x += child_alloc.width + handle_size;
- allocation->width -= child_alloc.width + handle_size;
+
+ if (child->pinned)
+ {
+ allocation->x += child_alloc.width;
+ allocation->width -= child_alloc.width;
+ }
+
break;
+
case PNL_DOCK_BIN_CHILD_RIGHT:
- child_alloc.width -= handle_size;
child_alloc.x = allocation->x + allocation->width - child_alloc.width;
child_alloc.y = allocation->y;
child_alloc.height = allocation->height;
- allocation->width -= child_alloc.width + handle_size;
+
+ if (child->pinned)
+ allocation->width -= child_alloc.width;
+
break;
+
case PNL_DOCK_BIN_CHILD_TOP:
child_alloc.x = allocation->x;
child_alloc.y = allocation->y;
child_alloc.width = allocation->width;
- child_alloc.height -= handle_size;
- allocation->y += child_alloc.height + handle_size;
- allocation->height -= child_alloc.height + handle_size;
+
+ if (child->pinned)
+ {
+ allocation->y += child_alloc.height;
+ allocation->height -= child_alloc.height;
+ }
+
break;
+
case PNL_DOCK_BIN_CHILD_BOTTOM:
- child_alloc.height -= handle_size;
child_alloc.x = allocation->x;
child_alloc.y = allocation->y + allocation->height - child_alloc.height;
child_alloc.width = allocation->width;
- allocation->height -= child_alloc.height + handle_size;
+
+ if (child->pinned)
+ allocation->height -= child_alloc.height;
+
break;
+
case PNL_DOCK_BIN_CHILD_CENTER:
case LAST_PNL_DOCK_BIN_CHILD:
default:
@@ -711,6 +890,7 @@ pnl_dock_bin_child_size_allocate (PnlDockBin *self,
switch (child->type)
{
case PNL_DOCK_BIN_CHILD_LEFT:
+
/*
* When left-to-right, we often have a scrollbar to deal
* with right here. So fudge the allocation position a bit
@@ -727,20 +907,29 @@ pnl_dock_bin_child_size_allocate (PnlDockBin *self,
handle_alloc.x += handle_alloc.width - HANDLE_WIDTH;
handle_alloc.width = HANDLE_WIDTH;
}
+
+ handle_alloc.x -= margin.right;
+
break;
case PNL_DOCK_BIN_CHILD_RIGHT:
handle_alloc.width = HANDLE_WIDTH;
+
if (gtk_widget_get_direction (child->widget) == GTK_TEXT_DIR_RTL)
handle_alloc.x -= (HANDLE_WIDTH / 2);
+
+ handle_alloc.x += margin.left;
+
break;
case PNL_DOCK_BIN_CHILD_BOTTOM:
handle_alloc.height = HANDLE_HEIGHT;
+ handle_alloc.y += margin.top;
break;
case PNL_DOCK_BIN_CHILD_TOP:
handle_alloc.y += handle_alloc.height - HANDLE_HEIGHT;
+ handle_alloc.y -= margin.bottom;
handle_alloc.height = HANDLE_HEIGHT;
break;
@@ -799,15 +988,20 @@ pnl_dock_bin_size_allocate (GtkWidget *widget,
* because the child has an empty allocation.
*/
- for (i = 0; i < PNL_DOCK_BIN_CHILD_CENTER; i++)
+ for (i = PNL_DOCK_BIN_CHILD_CENTER; i > 0; i--)
{
- PnlDockBinChild *child = &priv->children [i];
+ PnlDockBinChild *child = &priv->children [i - 1];
if (child->handle != NULL)
{
- if (PNL_IS_DOCK_BIN_EDGE (child->widget) &&
- pnl_dock_revealer_get_reveal_child (PNL_DOCK_REVEALER (child->widget)))
- gdk_window_show (child->handle);
+ if (PNL_IS_DOCK_BIN_EDGE (child->widget))
+ {
+ if (gtk_widget_get_realized (child->widget))
+ gdk_window_raise (gtk_widget_get_window (child->widget));
+
+ if (pnl_dock_revealer_get_reveal_child (PNL_DOCK_REVEALER (child->widget)))
+ gdk_window_show (child->handle);
+ }
else
gdk_window_hide (child->handle);
}
@@ -815,9 +1009,9 @@ pnl_dock_bin_size_allocate (GtkWidget *widget,
}
static void
-pnl_dock_bin_visible_action (GSimpleAction *action,
- GVariant *state,
- gpointer user_data)
+pnl_dock_bin_visible_change_state (GSimpleAction *action,
+ GVariant *state,
+ gpointer user_data)
{
PnlDockBin *self = user_data;
PnlDockBinChild *child;
@@ -849,19 +1043,38 @@ pnl_dock_bin_visible_action (GSimpleAction *action,
pnl_dock_revealer_set_reveal_child (PNL_DOCK_REVEALER (child->widget), reveal_child);
}
-static gint
-pnl_dock_bin_child_compare (gconstpointer a,
- gconstpointer b)
+static void
+pnl_dock_bin_set_child_pinned (PnlDockBin *self,
+ GtkWidget *widget,
+ gboolean pinned)
{
- const PnlDockBinChild *child_a = a;
- const PnlDockBinChild *child_b = b;
+ PnlDockBinChild *child;
+ GtkStyleContext *style_context;
- if (child_a->type == PNL_DOCK_BIN_CHILD_CENTER)
- return 1;
- else if (child_b->type == PNL_DOCK_BIN_CHILD_CENTER)
- return -1;
+ g_assert (PNL_IS_DOCK_BIN (self));
+ g_assert (GTK_IS_WIDGET (widget));
- return child_a->priority - child_b->priority;
+ child = pnl_dock_bin_get_child (self, widget);
+
+ if (child->type == PNL_DOCK_BIN_CHILD_CENTER)
+ return;
+
+ child->pinned = !!pinned;
+
+ style_context = gtk_widget_get_style_context (widget);
+
+ if (child->pinned)
+ gtk_style_context_add_class (style_context, PNL_DOCK_BIN_STYLE_CLASS_PINNED);
+ else
+ gtk_style_context_remove_class (style_context, PNL_DOCK_BIN_STYLE_CLASS_PINNED);
+
+ pnl_dock_bin_resort_children (self);
+
+ gtk_widget_queue_resize (GTK_WIDGET (self));
+
+ if (child->widget != NULL)
+ gtk_container_child_notify_by_pspec (GTK_CONTAINER (self), child->widget,
+ child_properties [CHILD_PROP_PINNED]);
}
static void
@@ -870,7 +1083,6 @@ pnl_dock_bin_set_child_priority (PnlDockBin *self,
gint priority)
{
PnlDockBinChild *child;
- PnlDockBinPrivate *priv = pnl_dock_bin_get_instance_private (self);
g_assert (PNL_IS_DOCK_BIN (self));
g_assert (GTK_IS_WIDGET (widget));
@@ -878,13 +1090,13 @@ pnl_dock_bin_set_child_priority (PnlDockBin *self,
child = pnl_dock_bin_get_child (self, widget);
child->priority = priority;
- g_qsort_with_data (&priv->children[0],
- PNL_DOCK_BIN_CHILD_CENTER,
- sizeof (PnlDockBinChild),
- (GCompareDataFunc)pnl_dock_bin_child_compare,
- NULL);
+ pnl_dock_bin_resort_children (self);
gtk_widget_queue_resize (GTK_WIDGET (self));
+
+ if (child->widget != NULL)
+ gtk_container_child_notify_by_pspec (GTK_CONTAINER (self), child->widget,
+ child_properties [CHILD_PROP_PRIORITY]);
}
static void
@@ -1335,7 +1547,12 @@ pnl_dock_bin_create_edge (PnlDockBin *self,
PnlDockBinChild *child,
PnlDockBinChildType type)
{
+ PnlDockBinPrivate *priv = pnl_dock_bin_get_instance_private (self);
+ g_autoptr(GSimpleActionGroup) map = NULL;
+ g_autoptr(GAction) pinned = NULL;
+ const gchar *name = NULL;
GAction *action;
+ gboolean reveal_child = FALSE;
g_assert (PNL_IS_DOCK_BIN (self));
g_assert (child != NULL);
@@ -1358,101 +1575,73 @@ pnl_dock_bin_create_edge (PnlDockBin *self,
return;
}
- g_object_set (child->widget, "edge", (GtkPositionType)type, NULL);
+ /*
+ * If the user set the initial state for the edge before we created the
+ * edge, the value for it will be the state to the action. We need to
+ * grab that and apply it for our initial state.
+ */
+ switch (type)
+ {
+ case PNL_DOCK_BIN_CHILD_LEFT: reveal_child = get_visible (self, "left-visible"); break;
+ case PNL_DOCK_BIN_CHILD_RIGHT: reveal_child = get_visible (self, "right-visible"); break;
+ case PNL_DOCK_BIN_CHILD_TOP: reveal_child = get_visible (self, "top-visible"); break;
+ case PNL_DOCK_BIN_CHILD_BOTTOM: reveal_child = get_visible (self, "bottom-visible"); break;
+ case PNL_DOCK_BIN_CHILD_CENTER:
+ case LAST_PNL_DOCK_BIN_CHILD:
+ default:
+ break;
+ }
+
+ g_object_set (child->widget,
+ "edge", (GtkPositionType)type,
+ "reveal-child", reveal_child,
+ NULL);
+
gtk_widget_set_parent (g_object_ref_sink (child->widget), GTK_WIDGET (self));
- action = pnl_dock_bin_get_action_for_type (self, type);
+ action = pnl_dock_bin_get_visible_action_for_type (self, type);
g_object_bind_property_full (child->widget, "reveal-child",
action, "state",
G_BINDING_SYNC_CREATE,
map_boolean_to_variant,
NULL, NULL, NULL);
-}
-
-static gboolean
-pnl_dock_bin_draw (GtkWidget *widget,
- cairo_t *cr)
-{
- PnlDockBin *self = (PnlDockBin *)widget;
- PnlDockBinPrivate *priv = pnl_dock_bin_get_instance_private (self);
- GtkStyleContext *style_context;
- gboolean ret;
- guint i;
- gint handle_size = 0;
- g_assert (PNL_IS_DOCK_BIN (self));
- g_assert (cr != NULL);
-
- ret = GTK_WIDGET_CLASS (pnl_dock_bin_parent_class)->draw (widget, cr);
-
- if (ret == GDK_EVENT_STOP)
- return ret;
-
- gtk_widget_style_get (widget,
- "handle-size", &handle_size,
- NULL);
-
- if (handle_size == 0)
- return ret;
-
- style_context = gtk_widget_get_style_context (widget);
-
- for (i = 0; i < PNL_DOCK_BIN_CHILD_CENTER; i++)
- {
- PnlDockBinChild *child = &priv->children [i];
-
- if ((child->widget != NULL) &&
- gtk_widget_get_visible (child->widget) &&
- gtk_widget_get_child_visible (child->widget))
- {
- GtkAllocation handle;
-
- gtk_widget_get_allocation (child->widget, &handle);
-
- if (((child->type == PNL_DOCK_BIN_CHILD_LEFT) ||
- (child->type == PNL_DOCK_BIN_CHILD_RIGHT)) &&
- (handle.width <= handle_size))
- continue;
-
- if (((child->type == PNL_DOCK_BIN_CHILD_TOP) ||
- (child->type == PNL_DOCK_BIN_CHILD_BOTTOM)) &&
- (handle.height <= handle_size))
- continue;
-
- switch (child->type)
- {
- case PNL_DOCK_BIN_CHILD_LEFT:
- handle.x += handle.width;
- handle.width = handle_size;
- break;
-
- case PNL_DOCK_BIN_CHILD_RIGHT:
- handle.x -= handle_size;
- handle.width = handle_size;
- break;
-
- case PNL_DOCK_BIN_CHILD_TOP:
- handle.y += handle.height;
- handle.height = handle_size;
- break;
-
- case PNL_DOCK_BIN_CHILD_BOTTOM:
- handle.y -= handle_size;
- handle.height = handle_size;
- break;
-
- case PNL_DOCK_BIN_CHILD_CENTER:
- case LAST_PNL_DOCK_BIN_CHILD:
- default:
- g_assert_not_reached ();
- break;
- }
-
- gtk_render_handle (style_context, cr, handle.x, handle.y, handle.width, handle.height);
- }
- }
-
- return ret;
+ pnl_dock_item_adopt (PNL_DOCK_ITEM (self), PNL_DOCK_ITEM (child->widget));
+
+ /* Action for panel children to easily activate */
+ map = g_simple_action_group_new ();
+ pinned = g_object_new (PNL_TYPE_CHILD_PROPERTY_ACTION,
+ "enabled", TRUE,
+ "container", self,
+ "child", child->widget,
+ "child-property-name", "pinned",
+ "name", "pinned",
+ NULL);
+ g_action_map_add_action (G_ACTION_MAP (map), pinned);
+ gtk_widget_insert_action_group (child->widget, "panel", G_ACTION_GROUP (map));
+ g_clear_object (&pinned);
+
+ /* Action for global widgetry to activate */
+ if (child->type == PNL_DOCK_BIN_CHILD_LEFT)
+ name = "left-pinned";
+ else if (child->type == PNL_DOCK_BIN_CHILD_RIGHT)
+ name = "right-pinned";
+ else if (child->type == PNL_DOCK_BIN_CHILD_TOP)
+ name = "top-pinned";
+ else if (child->type == PNL_DOCK_BIN_CHILD_BOTTOM)
+ name = "bottom-pinned";
+ pinned = g_object_new (PNL_TYPE_CHILD_PROPERTY_ACTION,
+ "enabled", TRUE,
+ "container", self,
+ "child", child->widget,
+ "child-property-name", "pinned",
+ "name", name,
+ NULL);
+ g_action_map_add_action (G_ACTION_MAP (priv->actions), pinned);
+
+ if (child->pinned)
+ gtk_style_context_add_class (gtk_widget_get_style_context (child->widget),
+ PNL_DOCK_BIN_STYLE_CLASS_PINNED);
}
static void
@@ -1467,6 +1656,7 @@ pnl_dock_bin_init_child (PnlDockBin *self,
child->type = type;
child->priority = (int)type * 100;
+ child->pinned = TRUE;
}
static void
@@ -1501,6 +1691,10 @@ pnl_dock_bin_get_child_property (GtkContainer *container,
g_value_set_enum (value, (GtkPositionType)child->type);
break;
+ case CHILD_PROP_PINNED:
+ g_value_set_boolean (value, child->pinned);
+ break;
+
default:
GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, prop_id, pspec);
}
@@ -1517,6 +1711,10 @@ pnl_dock_bin_set_child_property (GtkContainer *container,
switch (prop_id)
{
+ case CHILD_PROP_PINNED:
+ pnl_dock_bin_set_child_pinned (self, widget, g_value_get_boolean (value));
+ break;
+
case CHILD_PROP_PRIORITY:
pnl_dock_bin_set_child_priority (self, widget, g_value_get_int (value));
break;
@@ -1536,6 +1734,22 @@ pnl_dock_bin_get_property (GObject *object,
switch (prop_id)
{
+ case PROP_LEFT_VISIBLE:
+ g_value_set_boolean (value, get_visible (self, "left-visible"));
+ break;
+
+ case PROP_RIGHT_VISIBLE:
+ g_value_set_boolean (value, get_visible (self, "right-visible"));
+ break;
+
+ case PROP_TOP_VISIBLE:
+ g_value_set_boolean (value, get_visible (self, "top-visible"));
+ break;
+
+ case PROP_BOTTOM_VISIBLE:
+ g_value_set_boolean (value, get_visible (self, "bottom-visible"));
+ break;
+
case PROP_MANAGER:
g_value_set_object (value, pnl_dock_item_get_manager (PNL_DOCK_ITEM (self)));
break;
@@ -1555,6 +1769,22 @@ pnl_dock_bin_set_property (GObject *object,
switch (prop_id)
{
+ case PROP_LEFT_VISIBLE:
+ set_visible (self, "left-visible", g_value_get_boolean (value));
+ break;
+
+ case PROP_RIGHT_VISIBLE:
+ set_visible (self, "right-visible", g_value_get_boolean (value));
+ break;
+
+ case PROP_TOP_VISIBLE:
+ set_visible (self, "top-visible", g_value_get_boolean (value));
+ break;
+
+ case PROP_BOTTOM_VISIBLE:
+ set_visible (self, "bottom-visible", g_value_get_boolean (value));
+ break;
+
case PROP_MANAGER:
pnl_dock_item_set_manager (PNL_DOCK_ITEM (self), g_value_get_object (value));
break;
@@ -1574,7 +1804,6 @@ pnl_dock_bin_class_init (PnlDockBinClass *klass)
object_class->get_property = pnl_dock_bin_get_property;
object_class->set_property = pnl_dock_bin_set_property;
- widget_class->draw = pnl_dock_bin_draw;
widget_class->destroy = pnl_dock_bin_destroy;
widget_class->drag_leave = pnl_dock_bin_drag_leave;
widget_class->drag_motion = pnl_dock_bin_drag_motion;
@@ -1597,6 +1826,43 @@ pnl_dock_bin_class_init (PnlDockBinClass *klass)
g_object_class_override_property (object_class, PROP_MANAGER, "manager");
+ properties [PROP_LEFT_VISIBLE] =
+ g_param_spec_boolean ("left-visible",
+ "Left Visible",
+ "If the left panel is visible.",
+ FALSE,
+ (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_RIGHT_VISIBLE] =
+ g_param_spec_boolean ("right-visible",
+ "Right Visible",
+ "If the right panel is visible.",
+ FALSE,
+ (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_TOP_VISIBLE] =
+ g_param_spec_boolean ("top-visible",
+ "Top Visible",
+ "If the top panel is visible.",
+ FALSE,
+ (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_BOTTOM_VISIBLE] =
+ g_param_spec_boolean ("bottom-visible",
+ "Bottom Visible",
+ "If the bottom panel is visible.",
+ FALSE,
+ (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+
+ child_properties [CHILD_PROP_PINNED] =
+ g_param_spec_boolean ("pinned",
+ "Pinned",
+ "If the child panel is pinned",
+ FALSE,
+ (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
child_properties [CHILD_PROP_POSITION] =
g_param_spec_enum ("position",
"Position",
@@ -1616,17 +1882,7 @@ pnl_dock_bin_class_init (PnlDockBinClass *klass)
gtk_container_class_install_child_properties (container_class, N_CHILD_PROPS, child_properties);
- style_properties [STYLE_PROP_HANDLE_SIZE] =
- g_param_spec_int ("handle-size",
- "Handle Size",
- "Width of the resize handle",
- 0,
- G_MAXINT,
- 1,
- (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
- gtk_widget_class_install_style_property (widget_class, style_properties [STYLE_PROP_HANDLE_SIZE]);
-
- gtk_widget_class_set_css_name (widget_class, "dockbin");
+ gtk_widget_class_set_css_name (widget_class, "pnldockbin");
}
static void
@@ -1637,10 +1893,10 @@ pnl_dock_bin_init (PnlDockBin *self)
{ (gchar *)"PNL_DOCK_BIN_WIDGET", GTK_TARGET_SAME_APP, 0 },
};
static const GActionEntry entries[] = {
- { "left-visible", NULL, NULL, "false", pnl_dock_bin_visible_action },
- { "right-visible", NULL, NULL, "false", pnl_dock_bin_visible_action },
- { "top-visible", NULL, NULL, "false", pnl_dock_bin_visible_action },
- { "bottom-visible", NULL, NULL, "false", pnl_dock_bin_visible_action },
+ { "left-visible", NULL, NULL, "false", pnl_dock_bin_visible_change_state },
+ { "right-visible", NULL, NULL, "false", pnl_dock_bin_visible_change_state },
+ { "top-visible", NULL, NULL, "false", pnl_dock_bin_visible_change_state },
+ { "bottom-visible", NULL, NULL, "false", pnl_dock_bin_visible_change_state },
};
gtk_widget_set_has_window (GTK_WIDGET (self), TRUE);
@@ -1898,7 +2154,7 @@ pnl_dock_bin_get_child_visible (PnlDockItem *item,
(ancestor == priv->children [1].widget) ||
(ancestor == priv->children [2].widget) ||
(ancestor == priv->children [3].widget))
- return pnl_dock_revealer_get_reveal_child (PNL_DOCK_REVEALER (ancestor));
+ return pnl_dock_revealer_get_child_revealed (PNL_DOCK_REVEALER (ancestor));
return FALSE;
}
@@ -1920,10 +2176,69 @@ pnl_dock_bin_set_child_visible (PnlDockItem *item,
pnl_dock_revealer_set_reveal_child (PNL_DOCK_REVEALER (ancestor), child_visible);
}
+static gboolean
+pnl_dock_bin_minimize (PnlDockItem *item,
+ PnlDockItem *child,
+ GtkPositionType *position)
+{
+ PnlDockBin *self = (PnlDockBin *)item;
+ PnlDockBinPrivate *priv = pnl_dock_bin_get_instance_private (self);
+
+ g_assert (PNL_IS_DOCK_BIN (self));
+ g_assert (PNL_IS_DOCK_ITEM (child));
+ g_assert (position != NULL);
+
+ for (guint i = 0; i < LAST_PNL_DOCK_BIN_CHILD; i++)
+ {
+ const PnlDockBinChild *info = &priv->children [i];
+
+ if (info->widget != NULL && gtk_widget_is_ancestor (GTK_WIDGET (child), info->widget))
+ {
+ switch (info->type)
+ {
+ case PNL_DOCK_BIN_CHILD_LEFT:
+ case PNL_DOCK_BIN_CHILD_CENTER:
+ case LAST_PNL_DOCK_BIN_CHILD:
+ default:
+ *position = GTK_POS_LEFT;
+ break;
+
+ case PNL_DOCK_BIN_CHILD_RIGHT:
+ *position = GTK_POS_RIGHT;
+ break;
+
+ case PNL_DOCK_BIN_CHILD_TOP:
+ *position = GTK_POS_TOP;
+ break;
+
+ case PNL_DOCK_BIN_CHILD_BOTTOM:
+ *position = GTK_POS_BOTTOM;
+ break;
+ }
+
+ break;
+ }
+ }
+
+ return FALSE;
+}
+
+static void
+pnl_dock_bin_update_visibility (PnlDockItem *item)
+{
+ PnlDockBin *self = (PnlDockBin *)item;
+
+ g_assert (PNL_IS_DOCK_BIN (self));
+
+ pnl_dock_bin_update_actions (self);
+}
+
static void
pnl_dock_bin_init_dock_item_iface (PnlDockItemInterface *iface)
{
iface->present_child = pnl_dock_bin_present_child;
iface->get_child_visible = pnl_dock_bin_get_child_visible;
iface->set_child_visible = pnl_dock_bin_set_child_visible;
+ iface->minimize = pnl_dock_bin_minimize;
+ iface->update_visibility = pnl_dock_bin_update_visibility;
}
diff --git a/contrib/pnl/pnl-dock-bin.h b/contrib/pnl/pnl-dock-bin.h
index 9ba8ec8..08d3d7f 100644
--- a/contrib/pnl/pnl-dock-bin.h
+++ b/contrib/pnl/pnl-dock-bin.h
@@ -20,27 +20,29 @@
# error "Only <pnl.h> can be included directly."
#endif
-#ifndef PNL_DOCK_BIN_BIN_H
-#define PNL_DOCK_BIN_BIN_H
+#ifndef PNL_DOCK_BIN_H
+#define PNL_DOCK_BIN_H
#include "pnl-dock-types.h"
G_BEGIN_DECLS
+#define PNL_DOCK_BIN_STYLE_CLASS_PINNED "pinned"
+
struct _PnlDockBinClass
{
GtkContainerClass parent;
GtkWidget *(*create_edge) (PnlDockBin *self);
- void (*padding1) (void);
- void (*padding2) (void);
- void (*padding3) (void);
- void (*padding4) (void);
- void (*padding5) (void);
- void (*padding6) (void);
- void (*padding7) (void);
- void (*padding8) (void);
+ gpointer _reserved1;
+ gpointer _reserved2;
+ gpointer _reserved3;
+ gpointer _reserved4;
+ gpointer _reserved5;
+ gpointer _reserved6;
+ gpointer _reserved7;
+ gpointer _reserved8;
};
GtkWidget *pnl_dock_bin_new (void);
@@ -52,4 +54,4 @@ GtkWidget *pnl_dock_bin_get_right_edge (PnlDockBin *self);
G_END_DECLS
-#endif /* PNL_DOCK_BIN_BIN_H */
+#endif /* PNL_DOCK_BIN_H */
diff --git a/contrib/pnl/pnl-dock-item.c b/contrib/pnl/pnl-dock-item.c
index 60e335e..cdca76b 100644
--- a/contrib/pnl/pnl-dock-item.c
+++ b/contrib/pnl/pnl-dock-item.c
@@ -76,20 +76,6 @@ pnl_dock_item_real_get_manager (PnlDockItem *self)
static void
pnl_dock_item_real_update_visibility (PnlDockItem *self)
{
- GtkWidget *parent;
-
- g_assert (PNL_IS_DOCK_ITEM (self));
-
- for (parent = gtk_widget_get_parent (GTK_WIDGET (self));
- parent != NULL;
- parent = gtk_widget_get_parent (parent))
- {
- if (PNL_IS_DOCK_ITEM (parent))
- {
- pnl_dock_item_update_visibility (PNL_DOCK_ITEM (parent));
- break;
- }
- }
}
static void
@@ -129,12 +115,40 @@ pnl_dock_item_real_manager_set (PnlDockItem *self,
}
static void
+pnl_dock_item_real_release (PnlDockItem *self,
+ PnlDockItem *child)
+{
+ g_assert (PNL_IS_DOCK_ITEM (self));
+ g_assert (PNL_IS_DOCK_ITEM (child));
+
+ g_warning ("%s does not know how to release child %s",
+ G_OBJECT_TYPE_NAME (self),
+ G_OBJECT_TYPE_NAME (child));
+}
+
+static gboolean
+pnl_dock_item_real_can_minimize (PnlDockItem *self,
+ PnlDockItem *descendant)
+{
+ return FALSE;
+}
+
+static gboolean
+pnl_dock_item_real_get_can_close (PnlDockItem *self)
+{
+ return FALSE;
+}
+
+static void
pnl_dock_item_default_init (PnlDockItemInterface *iface)
{
iface->get_manager = pnl_dock_item_real_get_manager;
iface->set_manager = pnl_dock_item_real_set_manager;
iface->manager_set = pnl_dock_item_real_manager_set;
iface->update_visibility = pnl_dock_item_real_update_visibility;
+ iface->release = pnl_dock_item_real_release;
+ iface->get_can_close = pnl_dock_item_real_get_can_close;
+ iface->can_minimize = pnl_dock_item_real_can_minimize;
signals [MANAGER_SET] =
g_signal_new ("manager-set",
@@ -181,9 +195,19 @@ pnl_dock_item_set_manager (PnlDockItem *self,
void
pnl_dock_item_update_visibility (PnlDockItem *self)
{
+ GtkWidget *parent;
+
g_return_if_fail (PNL_IS_DOCK_ITEM (self));
PNL_DOCK_ITEM_GET_IFACE (self)->update_visibility (self);
+
+ for (parent = gtk_widget_get_parent (GTK_WIDGET (self));
+ parent != NULL;
+ parent = gtk_widget_get_parent (parent))
+ {
+ if (PNL_IS_DOCK_ITEM (parent))
+ PNL_DOCK_ITEM_GET_IFACE (parent)->update_visibility (PNL_DOCK_ITEM (parent));
+ }
}
static void
@@ -454,3 +478,182 @@ pnl_dock_item_set_child_visible (PnlDockItem *self,
if (PNL_DOCK_ITEM_GET_IFACE (self)->set_child_visible)
PNL_DOCK_ITEM_GET_IFACE (self)->set_child_visible (self, child, child_visible);
}
+
+/**
+ * pnl_dock_item_get_can_close:
+ * @self: a #PnlDockItem
+ *
+ * If this dock item can be closed by the user, this virtual function should be
+ * implemented by the panel and return %TRUE.
+ *
+ * Returns: %TRUE if the dock item can be closed by the user, otherwise %FALSE.
+ */
+gboolean
+pnl_dock_item_get_can_close (PnlDockItem *self)
+{
+ g_return_val_if_fail (PNL_IS_DOCK_ITEM (self), FALSE);
+
+ if (PNL_DOCK_ITEM_GET_IFACE (self)->get_can_close)
+ return PNL_DOCK_ITEM_GET_IFACE (self)->get_can_close (self);
+
+ return FALSE;
+}
+
+/**
+ * pnl_dock_item_close:
+ * @self: a #PnlDockItem
+ *
+ * This function will request that the dock item close itself.
+ *
+ * Returns: %TRUE if the dock item was closed
+ */
+gboolean
+pnl_dock_item_close (PnlDockItem *self)
+{
+ g_return_val_if_fail (PNL_IS_DOCK_ITEM (self), FALSE);
+
+ if (pnl_dock_item_get_can_close (self))
+ {
+ if (PNL_DOCK_ITEM_GET_IFACE (self)->close)
+ return PNL_DOCK_ITEM_GET_IFACE (self)->close (self);
+
+ gtk_widget_destroy (GTK_WIDGET (self));
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ * pnl_dock_item_minimize:
+ * @self: a #PnlDockItem
+ * @child: A #PnlDockItem that is a child of @self
+ * @position: (inout): A location for a #GtkPositionType
+ *
+ * This requests that @self minimize @child if it knows how.
+ *
+ * If not, it should suggest the gravity for @child if it knows how to
+ * determine that. For example, a #PnlDockBin might know if the widget was part
+ * of the right panel and therefore may set @position to %GTK_POS_RIGHT.
+ *
+ * Returns: %TRUE if @child was minimized. Otherwise %FALSE and @position
+ * may be updated to a suggested position.
+ */
+gboolean
+pnl_dock_item_minimize (PnlDockItem *self,
+ PnlDockItem *child,
+ GtkPositionType *position)
+{
+ GtkPositionType unused = GTK_POS_LEFT;
+
+ g_return_val_if_fail (PNL_IS_DOCK_ITEM (self), FALSE);
+ g_return_val_if_fail (PNL_IS_DOCK_ITEM (child), FALSE);
+ g_return_val_if_fail (self != child, FALSE);
+
+ if (position == NULL)
+ position = &unused;
+
+ if (PNL_DOCK_ITEM_GET_IFACE (self)->minimize)
+ return PNL_DOCK_ITEM_GET_IFACE (self)->minimize (self, child, position);
+
+ return FALSE;
+}
+
+/**
+ * pnl_dock_item_get_title:
+ * @self: A #PnlDockItem
+ *
+ * Gets the title for the #PnlDockItem.
+ *
+ * Generally, you want to use a #PnlDockWidget which has a "title" property you
+ * can set. But this can be helpful for integration of various container
+ * widgets.
+ *
+ * Returns: (transfer full) (nullable): A newly allocated string or %NULL.
+ */
+gchar *
+pnl_dock_item_get_title (PnlDockItem *self)
+{
+ g_return_val_if_fail (PNL_IS_DOCK_ITEM (self), NULL);
+
+ if (PNL_DOCK_ITEM_GET_IFACE (self)->get_title)
+ return PNL_DOCK_ITEM_GET_IFACE (self)->get_title (self);
+
+ return NULL;
+}
+
+/**
+ * pnl_dock_item_get_icon_name:
+ * @self: A #PnlDockItem
+ *
+ * Gets the icon_name for the #PnlDockItem.
+ *
+ * Generally, you want to use a #PnlDockWidget which has a "icon-name" property
+ * you can set. But this can be helpful for integration of various container
+ * widgets.
+ *
+ * Returns: (transfer full) (nullable): A newly allocated string or %NULL.
+ */
+gchar *
+pnl_dock_item_get_icon_name (PnlDockItem *self)
+{
+ g_return_val_if_fail (PNL_IS_DOCK_ITEM (self), NULL);
+
+ if (PNL_DOCK_ITEM_GET_IFACE (self)->get_icon_name)
+ return PNL_DOCK_ITEM_GET_IFACE (self)->get_icon_name (self);
+
+ return NULL;
+}
+
+/**
+ * pnl_dock_item_release:
+ * @self: A #PnlDockItem
+ *
+ * This virtual method should remove @child from @self if the
+ * dock item knows how to do so. For example, the #PnlDockStack
+ * will remove @child from it's internal #GtkStack.
+ *
+ * After the virtual function has been executed, child tracking
+ * will be removed so that #PnlDockItem implementations do not
+ * need to implement themselves.
+ */
+void
+pnl_dock_item_release (PnlDockItem *self,
+ PnlDockItem *child)
+{
+ g_return_if_fail (PNL_IS_DOCK_ITEM (self));
+ g_return_if_fail (self == pnl_dock_item_get_parent (child));
+
+ PNL_DOCK_ITEM_GET_IFACE (self)->release (self, child);
+
+ g_object_weak_unref (G_OBJECT (child),
+ pnl_dock_item_child_weak_notify,
+ self);
+ pnl_dock_item_child_weak_notify (self, (GObject *)child);
+}
+
+/**
+ * pnl_dock_item_get_can_minimize: (virtual can_minimize)
+ * @self: a #PnlDockItem
+ *
+ * Returns: %TRUE if the widget can be minimized.
+ */
+gboolean
+pnl_dock_item_get_can_minimize (PnlDockItem *self)
+{
+ PnlDockItem *parent;
+
+ g_return_val_if_fail (PNL_IS_DOCK_ITEM (self), FALSE);
+
+ parent = pnl_dock_item_get_parent (self);
+
+ while (parent != NULL)
+ {
+ if (PNL_DOCK_ITEM_GET_IFACE (parent)->can_minimize (parent, self))
+ return TRUE;
+ parent = pnl_dock_item_get_parent (parent);
+ }
+
+ return FALSE;
+}
diff --git a/contrib/pnl/pnl-dock-item.h b/contrib/pnl/pnl-dock-item.h
index 2a067e1..86d24ce 100644
--- a/contrib/pnl/pnl-dock-item.h
+++ b/contrib/pnl/pnl-dock-item.h
@@ -16,6 +16,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#if !defined(PNL_INSIDE) && !defined(PNL_COMPILATION)
+# error "Only <pnl.h> can be included directly."
+#endif
+
#ifndef PNL_DOCK_ITEM_H
#define PNL_DOCK_ITEM_H
@@ -27,38 +31,59 @@ struct _PnlDockItemInterface
{
GTypeInterface parent;
- void (*set_manager) (PnlDockItem *self,
- PnlDockManager *manager);
- PnlDockManager *(*get_manager) (PnlDockItem *self);
- void (*manager_set) (PnlDockItem *self,
- PnlDockManager *old_manager);
- void (*present_child) (PnlDockItem *self,
- PnlDockItem *child);
- void (*update_visibility) (PnlDockItem *self);
- gboolean (*get_child_visible) (PnlDockItem *self,
- PnlDockItem *child);
- void (*set_child_visible) (PnlDockItem *self,
- PnlDockItem *child,
- gboolean child_visible);
+ void (*set_manager) (PnlDockItem *self,
+ PnlDockManager *manager);
+ PnlDockManager *(*get_manager) (PnlDockItem *self);
+ void (*manager_set) (PnlDockItem *self,
+ PnlDockManager *old_manager);
+ void (*present_child) (PnlDockItem *self,
+ PnlDockItem *child);
+ void (*update_visibility) (PnlDockItem *self);
+ gboolean (*get_child_visible) (PnlDockItem *self,
+ PnlDockItem *child);
+ void (*set_child_visible) (PnlDockItem *self,
+ PnlDockItem *child,
+ gboolean child_visible);
+ gchar *(*get_title) (PnlDockItem *self);
+ gchar *(*get_icon_name) (PnlDockItem *self);
+ gboolean (*get_can_close) (PnlDockItem *self);
+ gboolean (*can_minimize) (PnlDockItem *self,
+ PnlDockItem *descendant);
+ gboolean (*close) (PnlDockItem *self);
+ gboolean (*minimize) (PnlDockItem *self,
+ PnlDockItem *child,
+ GtkPositionType *position);
+ void (*release) (PnlDockItem *self,
+ PnlDockItem *child);
};
-PnlDockManager *pnl_dock_item_get_manager (PnlDockItem *self);
-void pnl_dock_item_set_manager (PnlDockItem *self,
- PnlDockManager *manager);
-gboolean pnl_dock_item_adopt (PnlDockItem *self,
- PnlDockItem *child);
-void pnl_dock_item_present (PnlDockItem *self);
-void pnl_dock_item_present_child (PnlDockItem *self,
- PnlDockItem *child);
-void pnl_dock_item_update_visibility (PnlDockItem *self);
-gboolean pnl_dock_item_has_widgets (PnlDockItem *self);
-gboolean pnl_dock_item_get_child_visible (PnlDockItem *self,
- PnlDockItem *child);
-void pnl_dock_item_set_child_visible (PnlDockItem *self,
- PnlDockItem *child,
- gboolean child_visible);
-PnlDockItem *pnl_dock_item_get_parent (PnlDockItem *self);
-void _pnl_dock_item_printf (PnlDockItem *self);
+PnlDockManager *pnl_dock_item_get_manager (PnlDockItem *self);
+void pnl_dock_item_set_manager (PnlDockItem *self,
+ PnlDockManager *manager);
+gboolean pnl_dock_item_adopt (PnlDockItem *self,
+ PnlDockItem *child);
+void pnl_dock_item_present (PnlDockItem *self);
+void pnl_dock_item_present_child (PnlDockItem *self,
+ PnlDockItem *child);
+void pnl_dock_item_update_visibility (PnlDockItem *self);
+gboolean pnl_dock_item_has_widgets (PnlDockItem *self);
+gboolean pnl_dock_item_get_child_visible (PnlDockItem *self,
+ PnlDockItem *child);
+void pnl_dock_item_set_child_visible (PnlDockItem *self,
+ PnlDockItem *child,
+ gboolean child_visible);
+PnlDockItem *pnl_dock_item_get_parent (PnlDockItem *self);
+gchar *pnl_dock_item_get_title (PnlDockItem *self);
+gchar *pnl_dock_item_get_icon_name (PnlDockItem *self);
+gboolean pnl_dock_item_get_can_close (PnlDockItem *self);
+gboolean pnl_dock_item_get_can_minimize (PnlDockItem *self);
+gboolean pnl_dock_item_close (PnlDockItem *self);
+gboolean pnl_dock_item_minimize (PnlDockItem *self,
+ PnlDockItem *child,
+ GtkPositionType *position);
+void pnl_dock_item_release (PnlDockItem *self,
+ PnlDockItem *child);
+void _pnl_dock_item_printf (PnlDockItem *self);
G_END_DECLS
diff --git a/contrib/pnl/pnl-dock-manager.h b/contrib/pnl/pnl-dock-manager.h
index a6d022d..1690b70 100644
--- a/contrib/pnl/pnl-dock-manager.h
+++ b/contrib/pnl/pnl-dock-manager.h
@@ -36,14 +36,14 @@ struct _PnlDockManagerClass
void (*unregister_dock) (PnlDockManager *self,
PnlDock *dock);
- void (*padding1) (void);
- void (*padding2) (void);
- void (*padding3) (void);
- void (*padding4) (void);
- void (*padding5) (void);
- void (*padding6) (void);
- void (*padding7) (void);
- void (*padding8) (void);
+ gpointer _reserved1;
+ gpointer _reserved2;
+ gpointer _reserved3;
+ gpointer _reserved4;
+ gpointer _reserved5;
+ gpointer _reserved6;
+ gpointer _reserved7;
+ gpointer _reserved8;
};
PnlDockManager *pnl_dock_manager_new (void);
diff --git a/contrib/pnl/pnl-dock-overlay-edge.c b/contrib/pnl/pnl-dock-overlay-edge.c
index 6a07fc1..aa22dc0 100644
--- a/contrib/pnl/pnl-dock-overlay-edge.c
+++ b/contrib/pnl/pnl-dock-overlay-edge.c
@@ -25,12 +25,12 @@
struct _PnlDockOverlayEdge
{
- GtkBin parent;
+ PnlBin parent;
GtkPositionType edge : 2;
gint position;
};
-G_DEFINE_TYPE_EXTENDED (PnlDockOverlayEdge, pnl_dock_overlay_edge, GTK_TYPE_BIN, 0,
+G_DEFINE_TYPE_EXTENDED (PnlDockOverlayEdge, pnl_dock_overlay_edge, PNL_TYPE_BIN, 0,
G_IMPLEMENT_INTERFACE (PNL_TYPE_DOCK_ITEM, NULL))
enum {
@@ -63,35 +63,35 @@ pnl_dock_overlay_edge_update_edge (PnlDockOverlayEdge *self)
style_context = gtk_widget_get_style_context (GTK_WIDGET (self));
- gtk_style_context_remove_class (style_context, "left-edge");
- gtk_style_context_remove_class (style_context, "right-edge");
- gtk_style_context_remove_class (style_context, "top-edge");
- gtk_style_context_remove_class (style_context, "bottom-edge");
+ gtk_style_context_remove_class (style_context, "left");
+ gtk_style_context_remove_class (style_context, "right");
+ gtk_style_context_remove_class (style_context, "top");
+ gtk_style_context_remove_class (style_context, "bottom");
switch (self->edge)
{
case GTK_POS_TOP:
edge = GTK_POS_BOTTOM;
orientation = GTK_ORIENTATION_HORIZONTAL;
- style_class = "top-edge";
+ style_class = "top";
break;
case GTK_POS_BOTTOM:
edge = GTK_POS_TOP;
orientation = GTK_ORIENTATION_HORIZONTAL;
- style_class = "bottom-edge";
+ style_class = "bottom";
break;
case GTK_POS_LEFT:
edge = GTK_POS_RIGHT;
orientation = GTK_ORIENTATION_VERTICAL;
- style_class = "left-edge";
+ style_class = "left";
break;
case GTK_POS_RIGHT:
edge = GTK_POS_LEFT;
orientation = GTK_ORIENTATION_VERTICAL;
- style_class = "right-edge";
+ style_class = "right";
break;
default:
@@ -189,9 +189,6 @@ pnl_dock_overlay_edge_class_init (PnlDockOverlayEdgeClass *klass)
container_class->add = pnl_dock_overlay_edge_add;
- widget_class->draw = pnl_gtk_bin_draw;
- widget_class->size_allocate = pnl_gtk_bin_size_allocate;
-
properties [PROP_EDGE] =
g_param_spec_enum ("edge",
"Edge",
@@ -235,7 +232,7 @@ pnl_dock_overlay_edge_class_init (PnlDockOverlayEdgeClass *klass)
gtk_widget_class_install_style_property (widget_class,
style_properties [STYLE_PROP_OVERLAP_SIZE]);
- gtk_widget_class_set_css_name (widget_class, "dockoverlayedge");
+ gtk_widget_class_set_css_name (widget_class, "pnldockoverlayedge");
}
static void
diff --git a/contrib/pnl/pnl-dock-overlay-edge.h b/contrib/pnl/pnl-dock-overlay-edge.h
index 1a0d521..e9e4ede 100644
--- a/contrib/pnl/pnl-dock-overlay-edge.h
+++ b/contrib/pnl/pnl-dock-overlay-edge.h
@@ -16,17 +16,17 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#if !defined(PNL_INSIDE) && !defined(PNL_COMPILATION)
+# error "Only <pnl.h> can be included directly."
+#endif
+
#ifndef PNL_DOCK_OVERLAY_EDGE_H
#define PNL_DOCK_OVERLAY_EDGE_H
-#include <gtk/gtk.h>
+#include "pnl-dock-types.h"
G_BEGIN_DECLS
-#define PNL_TYPE_DOCK_OVERLAY_EDGE (pnl_dock_overlay_edge_get_type())
-
-G_DECLARE_FINAL_TYPE (PnlDockOverlayEdge, pnl_dock_overlay_edge, PNL, DOCK_OVERLAY_EDGE, GtkBin)
-
GtkPositionType pnl_dock_overlay_edge_get_edge (PnlDockOverlayEdge *self);
void pnl_dock_overlay_edge_set_edge (PnlDockOverlayEdge *self,
GtkPositionType edge);
diff --git a/contrib/pnl/pnl-dock-overlay.c b/contrib/pnl/pnl-dock-overlay.c
index 88ea7b7..e9520b9 100644
--- a/contrib/pnl/pnl-dock-overlay.c
+++ b/contrib/pnl/pnl-dock-overlay.c
@@ -900,7 +900,7 @@ pnl_dock_overlay_class_init (PnlDockOverlayClass *klass)
gtk_container_class_install_child_properties (container_class, N_CHILD_PROPS, child_properties);
- gtk_widget_class_set_css_name (widget_class, "dockoverlay");
+ gtk_widget_class_set_css_name (widget_class, "pnldockoverlay");
signals [HIDE_EDGES] =
g_signal_new ("hide-edges",
diff --git a/contrib/pnl/pnl-dock-overlay.h b/contrib/pnl/pnl-dock-overlay.h
index e5c69b0..3e5c69f 100644
--- a/contrib/pnl/pnl-dock-overlay.h
+++ b/contrib/pnl/pnl-dock-overlay.h
@@ -34,14 +34,14 @@ struct _PnlDockOverlayClass
void (*hide_edges) (PnlDockOverlay *self);
- void (*padding1) (void);
- void (*padding2) (void);
- void (*padding3) (void);
- void (*padding4) (void);
- void (*padding5) (void);
- void (*padding6) (void);
- void (*padding7) (void);
- void (*padding8) (void);
+ gpointer _reserved1;
+ gpointer _reserved2;
+ gpointer _reserved3;
+ gpointer _reserved4;
+ gpointer _reserved5;
+ gpointer _reserved6;
+ gpointer _reserved7;
+ gpointer _reserved8;
};
GtkWidget *pnl_dock_overlay_new (void);
diff --git a/contrib/pnl/pnl-dock-paned-private.h b/contrib/pnl/pnl-dock-paned-private.h
index a120a0a..9f73223 100644
--- a/contrib/pnl/pnl-dock-paned-private.h
+++ b/contrib/pnl/pnl-dock-paned-private.h
@@ -16,6 +16,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#if !defined(PNL_INSIDE) && !defined(PNL_COMPILATION)
+# error "Only <pnl.h> can be included directly."
+#endif
+
#ifndef PNL_DOCK_PANED_PRIVATE_H
#define PNL_DOCK_PANED_PRIVATE_H
diff --git a/contrib/pnl/pnl-dock-paned.c b/contrib/pnl/pnl-dock-paned.c
index 36cd6ba..2536a1f 100644
--- a/contrib/pnl/pnl-dock-paned.c
+++ b/contrib/pnl/pnl-dock-paned.c
@@ -86,7 +86,7 @@ pnl_dock_paned_class_init (PnlDockPanedClass *klass)
container_class->add = pnl_dock_paned_add;
- gtk_widget_class_set_css_name (widget_class, "dockpaned");
+ gtk_widget_class_set_css_name (widget_class, "pnldockpaned");
}
static void
diff --git a/contrib/pnl/pnl-dock-paned.h b/contrib/pnl/pnl-dock-paned.h
index 4889e00..f345d42 100644
--- a/contrib/pnl/pnl-dock-paned.h
+++ b/contrib/pnl/pnl-dock-paned.h
@@ -31,14 +31,14 @@ struct _PnlDockPanedClass
{
PnlMultiPanedClass parent;
- void (*padding1) (void);
- void (*padding2) (void);
- void (*padding3) (void);
- void (*padding4) (void);
- void (*padding5) (void);
- void (*padding6) (void);
- void (*padding7) (void);
- void (*padding8) (void);
+ gpointer _reserved1;
+ gpointer _reserved2;
+ gpointer _reserved3;
+ gpointer _reserved4;
+ gpointer _reserved5;
+ gpointer _reserved6;
+ gpointer _reserved7;
+ gpointer _reserved8;
};
GtkWidget *pnl_dock_paned_new (void);
diff --git a/contrib/pnl/pnl-dock-revealer.c b/contrib/pnl/pnl-dock-revealer.c
index ee994b0..3f176ff 100644
--- a/contrib/pnl/pnl-dock-revealer.c
+++ b/contrib/pnl/pnl-dock-revealer.c
@@ -54,9 +54,10 @@ typedef struct
guint position_set : 1;
guint reveal_child : 1;
guint child_revealed : 1;
+ GtkRequisition nat_req;
} PnlDockRevealerPrivate;
-G_DEFINE_TYPE_WITH_PRIVATE (PnlDockRevealer, pnl_dock_revealer, GTK_TYPE_BIN)
+G_DEFINE_TYPE_WITH_PRIVATE (PnlDockRevealer, pnl_dock_revealer, PNL_TYPE_BIN)
enum {
PROP_0,
@@ -202,6 +203,9 @@ pnl_dock_revealer_calculate_duration (PnlDockRevealer *self)
g_assert (PNL_IS_DOCK_REVEALER (self));
+ if (!gtk_widget_get_realized (GTK_WIDGET (self)))
+ return 0;
+
child = gtk_bin_get_child (GTK_BIN (self));
if (child == NULL)
@@ -285,7 +289,6 @@ pnl_dock_revealer_set_reveal_child (PnlDockRevealer *self,
g_object_ref (self),
"value", reveal_child ? 1.0 : 0.0,
NULL);
-
pnl_set_weak_pointer (&priv->animation, animation);
}
@@ -394,25 +397,50 @@ pnl_dock_revealer_get_preferred_width (GtkWidget *widget,
{
PnlDockRevealer *self = (PnlDockRevealer *)widget;
PnlDockRevealerPrivate *priv = pnl_dock_revealer_get_instance_private (self);
+ GtkStyleContext *style_context;
+ GtkWidget *child;
+ GtkBorder borders;
g_assert (PNL_IS_DOCK_REVEALER (self));
g_assert (min_width != NULL);
g_assert (nat_width != NULL);
+ style_context = gtk_widget_get_style_context (widget);
+ pnl_gtk_style_context_get_borders (style_context, &borders);
+
+ child = gtk_bin_get_child (GTK_BIN (self));
+
pnl_dock_revealer_get_child_preferred_width (self, min_width, nat_width);
- if (IS_HORIZONTAL (priv->transition_type) && priv->animation != NULL)
- {
- /*
- * We allow going smaller than the minimum size during animations
- * and rely on clipping to hide the child.
- */
- *min_width = 0;
+ *min_width += borders.left + borders.right;
+ *nat_width += borders.left + borders.right;
- /*
- * Our natural width is adjusted for the in-progress animation.
- */
- *nat_width *= gtk_adjustment_get_value (priv->adjustment);
+ priv->nat_req.width = *nat_width;
+
+ if (IS_HORIZONTAL (priv->transition_type))
+ {
+ if (priv->animation != NULL)
+ {
+ /*
+ * We allow going smaller than the minimum size during animations
+ * and rely on clipping to hide the child.
+ */
+ *min_width = 0;
+
+ /*
+ * Our natural width is adjusted for the in-progress animation.
+ */
+ *nat_width *= gtk_adjustment_get_value (priv->adjustment);
+ }
+ else if (child != NULL && !gtk_widget_get_child_visible (child))
+ {
+ /*
+ * Make sure we are completely hidden if the child is not currently
+ * visible.
+ */
+ *min_width = 0;
+ *nat_width = 0;
+ }
}
}
@@ -455,25 +483,50 @@ pnl_dock_revealer_get_preferred_height (GtkWidget *widget,
{
PnlDockRevealer *self = (PnlDockRevealer *)widget;
PnlDockRevealerPrivate *priv = pnl_dock_revealer_get_instance_private (self);
+ GtkStyleContext *style_context;
+ GtkWidget *child;
+ GtkBorder borders;
g_assert (PNL_IS_DOCK_REVEALER (self));
g_assert (min_height != NULL);
g_assert (nat_height != NULL);
+ style_context = gtk_widget_get_style_context (widget);
+ pnl_gtk_style_context_get_borders (style_context, &borders);
+
+ child = gtk_bin_get_child (GTK_BIN (self));
+
pnl_dock_revealer_get_child_preferred_height (self, min_height, nat_height);
- if (IS_VERTICAL (priv->transition_type) && priv->animation != NULL)
- {
- /*
- * We allow going smaller than the minimum size during animations
- * and rely on clipping to hide the child.
- */
- *min_height = 0;
+ *min_height += borders.top + borders.bottom;
+ *nat_height += borders.top + borders.bottom;
- /*
- * Our natural height is adjusted for the in-progress animation.
- */
- *nat_height *= gtk_adjustment_get_value (priv->adjustment);
+ priv->nat_req.height = *nat_height;
+
+ if (IS_VERTICAL (priv->transition_type))
+ {
+ if (priv->animation != NULL)
+ {
+ /*
+ * We allow going smaller than the minimum size during animations
+ * and rely on clipping to hide the child.
+ */
+ *min_height = 0;
+
+ /*
+ * Our natural height is adjusted for the in-progress animation.
+ */
+ *nat_height *= gtk_adjustment_get_value (priv->adjustment);
+ }
+ else if (child != NULL && !gtk_widget_get_child_visible (child))
+ {
+ /*
+ * Make sure we are completely hidden if the child is not currently
+ * visible.
+ */
+ *min_height = 0;
+ *nat_height = 0;
+ }
}
}
@@ -486,7 +539,9 @@ pnl_dock_revealer_size_allocate (GtkWidget *widget,
GtkAllocation child_allocation;
GtkRequisition min_req;
GtkRequisition nat_req;
+ GtkStyleContext *style_context;
GtkWidget *child;
+ GtkBorder borders;
g_assert (PNL_IS_DOCK_REVEALER (self));
@@ -505,10 +560,13 @@ pnl_dock_revealer_size_allocate (GtkWidget *widget,
if (!gtk_widget_get_child_visible (child))
return;
+ child_allocation = *allocation;
child_allocation.x = 0;
child_allocation.y = 0;
- child_allocation.width = allocation->width;
- child_allocation.height = allocation->height;
+
+ style_context = gtk_widget_get_style_context (widget);
+ pnl_gtk_style_context_get_borders (style_context, &borders);
+ pnl_gtk_allocation_subtract_border (&child_allocation, &borders);
if (IS_HORIZONTAL (priv->transition_type))
{
@@ -516,7 +574,7 @@ pnl_dock_revealer_size_allocate (GtkWidget *widget,
child_allocation.width = nat_req.width;
if (priv->transition_type == PNL_DOCK_REVEALER_TRANSITION_TYPE_SLIDE_RIGHT)
- child_allocation.x = allocation->width - child_allocation.width;
+ child_allocation.x = allocation->width - borders.right - child_allocation.width;
}
else if (IS_VERTICAL (priv->transition_type))
{
@@ -524,7 +582,7 @@ pnl_dock_revealer_size_allocate (GtkWidget *widget,
child_allocation.height = nat_req.height;
if (priv->transition_type == PNL_DOCK_REVEALER_TRANSITION_TYPE_SLIDE_DOWN)
- child_allocation.y = allocation->height - child_allocation.height;
+ child_allocation.y = allocation->height - borders.bottom - child_allocation.height;
}
gtk_widget_size_allocate (child, &child_allocation);
@@ -545,6 +603,66 @@ pnl_dock_revealer_add (GtkContainer *container,
gtk_widget_set_child_visible (widget, priv->reveal_child);
}
+static gboolean
+pnl_dock_revealer_draw (GtkWidget *widget,
+ cairo_t *cr)
+{
+ PnlDockRevealer *self = (PnlDockRevealer *)widget;
+ PnlDockRevealerPrivate *priv = pnl_dock_revealer_get_instance_private (self);
+ GtkAllocation alloc;
+ GtkStyleContext *style_context;
+ GtkWidget *child;
+ GtkBorder margin;
+ GtkStateFlags state;
+
+ g_assert (PNL_IS_DOCK_REVEALER (self));
+
+ gtk_widget_get_allocation (widget, &alloc);
+
+ if (gtk_widget_get_has_window (widget))
+ {
+ alloc.x = 0;
+ alloc.y = 0;
+ }
+
+ if (priv->animation != NULL)
+ {
+ /*
+ * If we are currently animating, we want to ensure that our background
+ * is drawn at the size of the natural allocation. Otherwise borders
+ * will be shown in improper locations.
+ */
+ if (IS_HORIZONTAL (priv->transition_type))
+ {
+ if (priv->transition_type == PNL_DOCK_REVEALER_TRANSITION_TYPE_SLIDE_RIGHT)
+ alloc.x -= (priv->nat_req.width - alloc.width);
+ alloc.width = priv->nat_req.width;
+ }
+ else
+ {
+ if (priv->transition_type == PNL_DOCK_REVEALER_TRANSITION_TYPE_SLIDE_DOWN)
+ alloc.y -= (priv->nat_req.height - alloc.height);
+ alloc.height = priv->nat_req.height;
+ }
+ }
+
+ style_context = gtk_widget_get_style_context (widget);
+ state = gtk_style_context_get_state (style_context);
+
+ gtk_style_context_get_margin (style_context, state, &margin);
+ pnl_gtk_allocation_subtract_border (&alloc, &margin);
+
+ gtk_render_background (style_context, cr, alloc.x, alloc.y, alloc.width, alloc.height);
+
+ child = gtk_bin_get_child (GTK_BIN (widget));
+ if (child != NULL)
+ gtk_container_propagate_draw (GTK_CONTAINER (widget), child, cr);
+
+ gtk_render_frame (style_context, cr, alloc.x, alloc.y, alloc.width, alloc.height);
+
+ return FALSE;
+}
+
static void
pnl_dock_revealer_realize (GtkWidget *widget)
{
@@ -680,6 +798,7 @@ pnl_dock_revealer_class_init (PnlDockRevealerClass *klass)
widget_class->get_preferred_height = pnl_dock_revealer_get_preferred_height;
widget_class->realize = pnl_dock_revealer_realize;
widget_class->size_allocate = pnl_dock_revealer_size_allocate;
+ widget_class->draw = pnl_dock_revealer_draw;
container_class->add = pnl_dock_revealer_add;
diff --git a/contrib/pnl/pnl-dock-revealer.h b/contrib/pnl/pnl-dock-revealer.h
index 7865e1b..7bbcdb3 100644
--- a/contrib/pnl/pnl-dock-revealer.h
+++ b/contrib/pnl/pnl-dock-revealer.h
@@ -23,11 +23,14 @@
#ifndef PNL_DOCK_REVEALER_H
#define PNL_DOCK_REVEALER_H
-#include "pnl-dock-types.h"
+#include "pnl-bin.h"
G_BEGIN_DECLS
#define PNL_TYPE_DOCK_REVEALER_TRANSITION_TYPE (pnl_dock_revealer_transition_type_get_type())
+#define PNL_TYPE_DOCK_REVEALER (pnl_dock_revealer_get_type())
+
+G_DECLARE_DERIVABLE_TYPE (PnlDockRevealer, pnl_dock_revealer, PNL, DOCK_REVEALER, PnlBin)
typedef enum
{
@@ -40,16 +43,16 @@ typedef enum
struct _PnlDockRevealerClass
{
- GtkBinClass parent;
+ PnlBinClass parent;
- void (*padding1) (void);
- void (*padding2) (void);
- void (*padding3) (void);
- void (*padding4) (void);
- void (*padding5) (void);
- void (*padding6) (void);
- void (*padding7) (void);
- void (*padding8) (void);
+ gpointer _reserved1;
+ gpointer _reserved2;
+ gpointer _reserved3;
+ gpointer _reserved4;
+ gpointer _reserved5;
+ gpointer _reserved6;
+ gpointer _reserved7;
+ gpointer _reserved8;
};
GType pnl_dock_revealer_transition_type_get_type (void);
diff --git a/contrib/pnl/pnl-dock-stack.c b/contrib/pnl/pnl-dock-stack.c
index 6f9f64b..9cdf82f 100644
--- a/contrib/pnl/pnl-dock-stack.c
+++ b/contrib/pnl/pnl-dock-stack.c
@@ -16,16 +16,22 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#define G_LOG_DOMAIN "pnl-dock-stack"
+
#include "pnl-dock-item.h"
#include "pnl-dock-stack.h"
#include "pnl-dock-widget.h"
-#include "pnl-dock-tab-strip.h"
+#include "pnl-tab-private.h"
+#include "pnl-tab-strip.h"
+#include "pnl-util-private.h"
typedef struct
{
GtkStack *stack;
PnlTabStrip *tab_strip;
+ GtkButton *pinned_button;
GtkPositionType edge : 2;
+ PnlTabStyle style : 2;
} PnlDockStackPrivate;
static void pnl_dock_stack_init_dock_item_iface (PnlDockItemInterface *iface);
@@ -38,6 +44,8 @@ G_DEFINE_TYPE_EXTENDED (PnlDockStack, pnl_dock_stack, GTK_TYPE_BOX, 0,
enum {
PROP_0,
PROP_EDGE,
+ PROP_SHOW_PINNED_BUTTON,
+ PROP_STYLE,
N_PROPS
};
@@ -49,14 +57,19 @@ pnl_dock_stack_add (GtkContainer *container,
{
PnlDockStack *self = (PnlDockStack *)container;
PnlDockStackPrivate *priv = pnl_dock_stack_get_instance_private (self);
- const gchar *title = NULL;
+ g_autofree gchar *icon_name = NULL;
+ g_autofree gchar *title = NULL;
g_assert (PNL_IS_DOCK_STACK (self));
- if (PNL_IS_DOCK_WIDGET (widget))
- title = pnl_dock_widget_get_title (PNL_DOCK_WIDGET (widget));
+ if (PNL_IS_DOCK_ITEM (widget))
+ {
+ title = pnl_dock_item_get_title (PNL_DOCK_ITEM (widget));
+ icon_name = pnl_dock_item_get_icon_name (PNL_DOCK_ITEM (widget));
+ }
gtk_container_add_with_properties (GTK_CONTAINER (priv->stack), widget,
+ "icon-name", icon_name,
"title", title,
NULL);
@@ -95,6 +108,14 @@ pnl_dock_stack_get_property (GObject *object,
g_value_set_enum (value, pnl_dock_stack_get_edge (self));
break;
+ case PROP_SHOW_PINNED_BUTTON:
+ g_value_set_boolean (value, pnl_dock_stack_get_show_pinned_button (self));
+ break;
+
+ case PROP_STYLE:
+ g_value_set_flags (value, pnl_dock_stack_get_style (self));
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
@@ -114,6 +135,14 @@ pnl_dock_stack_set_property (GObject *object,
pnl_dock_stack_set_edge (self, g_value_get_enum (value));
break;
+ case PROP_SHOW_PINNED_BUTTON:
+ pnl_dock_stack_set_show_pinned_button (self, g_value_get_boolean (value));
+ break;
+
+ case PROP_STYLE:
+ pnl_dock_stack_set_style (self, g_value_get_flags (value));
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
@@ -141,9 +170,24 @@ pnl_dock_stack_class_init (PnlDockStackClass *klass)
GTK_POS_TOP,
(G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
+ properties [PROP_SHOW_PINNED_BUTTON] =
+ g_param_spec_boolean ("show-pinned-button",
+ "Show Pinned Button",
+ "Show the pinned button to pin the dock edge",
+ FALSE,
+ (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_STYLE] =
+ g_param_spec_flags ("style",
+ "Style",
+ "Style",
+ PNL_TYPE_TAB_STYLE,
+ PNL_TAB_BOTH,
+ (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
+
g_object_class_install_properties (object_class, N_PROPS, properties);
- gtk_widget_class_set_css_name (widget_class, "dockstack");
+ gtk_widget_class_set_css_name (widget_class, "pnldockstack");
}
static void
@@ -153,23 +197,41 @@ pnl_dock_stack_init (PnlDockStack *self)
gtk_orientable_set_orientation (GTK_ORIENTABLE (self), GTK_ORIENTATION_VERTICAL);
+ priv->style = PNL_TAB_BOTH;
priv->edge = GTK_POS_TOP;
+ /*
+ * NOTE: setting a transition for the stack seems to muck up
+ * focus, causing the old-tab to get refocused. So we can't
+ * switch to CROSSFADE just yet.
+ */
+
priv->stack = g_object_new (GTK_TYPE_STACK,
"homogeneous", TRUE,
"visible", TRUE,
NULL);
- priv->tab_strip = g_object_new (PNL_TYPE_DOCK_TAB_STRIP,
+ priv->tab_strip = g_object_new (PNL_TYPE_TAB_STRIP,
"edge", GTK_POS_TOP,
"stack", priv->stack,
"visible", TRUE,
NULL);
+ priv->pinned_button = g_object_new (GTK_TYPE_BUTTON,
+ "action-name", "panel.pinned",
+ "child", g_object_new (GTK_TYPE_IMAGE,
+ "icon-name", "window-maximize-symbolic",
+ "visible", TRUE,
+ NULL),
+ "visible", FALSE,
+ NULL);
+
GTK_CONTAINER_CLASS (pnl_dock_stack_parent_class)->add (GTK_CONTAINER (self),
GTK_WIDGET (priv->tab_strip));
GTK_CONTAINER_CLASS (pnl_dock_stack_parent_class)->add (GTK_CONTAINER (self),
GTK_WIDGET (priv->stack));
+
+ pnl_tab_strip_add_control (priv->tab_strip, GTK_WIDGET (priv->pinned_button));
}
GtkWidget *
@@ -312,9 +374,105 @@ pnl_dock_stack_set_child_visible (PnlDockItem *item,
}
static void
+update_tab_controls (GtkWidget *widget,
+ gpointer unused)
+{
+ g_assert (GTK_IS_WIDGET (widget));
+
+ if (PNL_IS_TAB (widget))
+ _pnl_tab_update_controls (PNL_TAB (widget));
+}
+
+static void
+pnl_dock_stack_update_visibility (PnlDockItem *item)
+{
+ PnlDockStack *self = (PnlDockStack *)item;
+ PnlDockStackPrivate *priv = pnl_dock_stack_get_instance_private (self);
+
+ g_assert (PNL_IS_DOCK_STACK (self));
+
+ gtk_container_foreach (GTK_CONTAINER (priv->tab_strip),
+ update_tab_controls,
+ NULL);
+
+ if (!pnl_dock_item_has_widgets (item))
+ gtk_widget_hide (GTK_WIDGET (item));
+ else
+ gtk_widget_show (GTK_WIDGET (item));
+}
+
+static void
+pnl_dock_stack_release (PnlDockItem *item,
+ PnlDockItem *child)
+{
+ PnlDockStack *self = (PnlDockStack *)item;
+ PnlDockStackPrivate *priv = pnl_dock_stack_get_instance_private (self);
+
+ g_assert (PNL_IS_DOCK_STACK (self));
+ g_assert (PNL_IS_DOCK_ITEM (child));
+
+ gtk_container_remove (GTK_CONTAINER (priv->stack), GTK_WIDGET (child));
+}
+
+static void
pnl_dock_stack_init_dock_item_iface (PnlDockItemInterface *iface)
{
iface->present_child = pnl_dock_stack_present_child;
iface->get_child_visible = pnl_dock_stack_get_child_visible;
iface->set_child_visible = pnl_dock_stack_set_child_visible;
+ iface->update_visibility = pnl_dock_stack_update_visibility;
+ iface->release = pnl_dock_stack_release;
+}
+
+gboolean
+pnl_dock_stack_get_show_pinned_button (PnlDockStack *self)
+{
+ PnlDockStackPrivate *priv = pnl_dock_stack_get_instance_private (self);
+
+ g_return_val_if_fail (PNL_IS_DOCK_STACK (self), FALSE);
+
+ return gtk_widget_get_visible (GTK_WIDGET (priv->pinned_button));
+}
+
+void
+pnl_dock_stack_set_show_pinned_button (PnlDockStack *self,
+ gboolean show_pinned_button)
+{
+ PnlDockStackPrivate *priv = pnl_dock_stack_get_instance_private (self);
+
+ g_return_if_fail (PNL_IS_DOCK_STACK (self));
+
+ show_pinned_button = !!show_pinned_button;
+
+ if (show_pinned_button != gtk_widget_get_visible (GTK_WIDGET (priv->pinned_button)))
+ {
+ gtk_widget_set_visible (GTK_WIDGET (priv->pinned_button), show_pinned_button);
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_SHOW_PINNED_BUTTON]);
+ }
+}
+
+PnlTabStyle
+pnl_dock_stack_get_style (PnlDockStack *self)
+{
+ PnlDockStackPrivate *priv = pnl_dock_stack_get_instance_private (self);
+
+ g_return_val_if_fail (PNL_IS_DOCK_STACK (self), 0);
+
+ return priv->style;
+}
+
+void
+pnl_dock_stack_set_style (PnlDockStack *self,
+ PnlTabStyle style)
+{
+ PnlDockStackPrivate *priv = pnl_dock_stack_get_instance_private (self);
+
+ g_return_if_fail (PNL_IS_DOCK_STACK (self));
+
+ if (priv->style != style)
+ {
+ priv->style = style;
+ pnl_tab_strip_set_style (priv->tab_strip, style);
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_STYLE]);
+ }
}
diff --git a/contrib/pnl/pnl-dock-stack.h b/contrib/pnl/pnl-dock-stack.h
index fb19286..edbb646 100644
--- a/contrib/pnl/pnl-dock-stack.h
+++ b/contrib/pnl/pnl-dock-stack.h
@@ -30,12 +30,23 @@ G_BEGIN_DECLS
struct _PnlDockStackClass
{
GtkBoxClass parent;
+
+ gpointer _reserved1;
+ gpointer _reserved2;
+ gpointer _reserved3;
+ gpointer _reserved4;
};
-GtkWidget *pnl_dock_stack_new (void);
-GtkPositionType pnl_dock_stack_get_edge (PnlDockStack *self);
-void pnl_dock_stack_set_edge (PnlDockStack *self,
- GtkPositionType edge);
+GtkWidget *pnl_dock_stack_new (void);
+GtkPositionType pnl_dock_stack_get_edge (PnlDockStack *self);
+void pnl_dock_stack_set_edge (PnlDockStack *self,
+ GtkPositionType edge);
+PnlTabStyle pnl_dock_stack_get_style (PnlDockStack *self);
+void pnl_dock_stack_set_style (PnlDockStack *self,
+ PnlTabStyle style);
+gboolean pnl_dock_stack_get_show_pinned_button (PnlDockStack *self);
+void pnl_dock_stack_set_show_pinned_button (PnlDockStack *self,
+ gboolean show_pinned_button);
G_END_DECLS
diff --git a/contrib/pnl/pnl-dock-transient-grab.h b/contrib/pnl/pnl-dock-transient-grab.h
index 1c603d1..3125a4b 100644
--- a/contrib/pnl/pnl-dock-transient-grab.h
+++ b/contrib/pnl/pnl-dock-transient-grab.h
@@ -16,6 +16,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#if !defined(PNL_INSIDE) && !defined(PNL_COMPILATION)
+# error "Only <pnl.h> can be included directly."
+#endif
+
#ifndef PNL_DOCK_TRANSIENT_GRAB_H
#define PNL_DOCK_TRANSIENT_GRAB_H
diff --git a/contrib/pnl/pnl-dock-types.h b/contrib/pnl/pnl-dock-types.h
index 33f9c7b..66803df 100644
--- a/contrib/pnl/pnl-dock-types.h
+++ b/contrib/pnl/pnl-dock-types.h
@@ -25,31 +25,52 @@
#include <gtk/gtk.h>
+#include "pnl-bin.h"
+#include "pnl-dock-revealer.h"
#include "pnl-multi-paned.h"
G_BEGIN_DECLS
-#define PNL_TYPE_DOCK (pnl_dock_get_type ())
-#define PNL_TYPE_DOCK_BIN (pnl_dock_bin_get_type())
-#define PNL_TYPE_DOCK_ITEM (pnl_dock_item_get_type())
-#define PNL_TYPE_DOCK_MANAGER (pnl_dock_manager_get_type())
-#define PNL_TYPE_DOCK_OVERLAY (pnl_dock_overlay_get_type())
-#define PNL_TYPE_DOCK_PANED (pnl_dock_paned_get_type())
-#define PNL_TYPE_DOCK_REVEALER (pnl_dock_revealer_get_type())
-#define PNL_TYPE_DOCK_STACK (pnl_dock_stack_get_type())
-#define PNL_TYPE_DOCK_WIDGET (pnl_dock_widget_get_type())
-#define PNL_TYPE_DOCK_WINDOW (pnl_dock_window_get_type())
-
-G_DECLARE_INTERFACE (PnlDock, pnl_dock, PNL, DOCK, GtkContainer)
-G_DECLARE_DERIVABLE_TYPE (PnlDockBin, pnl_dock_bin, PNL, DOCK_BIN, GtkContainer)
-G_DECLARE_INTERFACE (PnlDockItem, pnl_dock_item, PNL, DOCK_ITEM, GtkWidget)
-G_DECLARE_DERIVABLE_TYPE (PnlDockManager, pnl_dock_manager, PNL, DOCK_MANAGER, GObject)
-G_DECLARE_DERIVABLE_TYPE (PnlDockOverlay, pnl_dock_overlay, PNL, DOCK_OVERLAY, GtkEventBox)
-G_DECLARE_DERIVABLE_TYPE (PnlDockPaned, pnl_dock_paned, PNL, DOCK_PANED, PnlMultiPaned)
-G_DECLARE_DERIVABLE_TYPE (PnlDockRevealer, pnl_dock_revealer, PNL, DOCK_REVEALER, GtkBin)
-G_DECLARE_DERIVABLE_TYPE (PnlDockStack, pnl_dock_stack, PNL, DOCK_STACK, GtkBox)
-G_DECLARE_DERIVABLE_TYPE (PnlDockWidget, pnl_dock_widget, PNL, DOCK_WIDGET, GtkBin)
-G_DECLARE_DERIVABLE_TYPE (PnlDockWindow, pnl_dock_window, PNL, DOCK_WINDOW, GtkWindow)
+#define PNL_TYPE_DOCK (pnl_dock_get_type ())
+#define PNL_TYPE_DOCK_BIN (pnl_dock_bin_get_type())
+#define PNL_TYPE_DOCK_BIN_EDGE (pnl_dock_bin_edge_get_type())
+#define PNL_TYPE_DOCK_ITEM (pnl_dock_item_get_type())
+#define PNL_TYPE_DOCK_MANAGER (pnl_dock_manager_get_type())
+#define PNL_TYPE_DOCK_OVERLAY (pnl_dock_overlay_get_type())
+#define PNL_TYPE_DOCK_OVERLAY_EDGE (pnl_dock_overlay_edge_get_type())
+#define PNL_TYPE_DOCK_PANED (pnl_dock_paned_get_type())
+#define PNL_TYPE_DOCK_STACK (pnl_dock_stack_get_type())
+#define PNL_TYPE_DOCK_TAB_STRIP (pnl_dock_tab_strip_get_type())
+#define PNL_TYPE_DOCK_WIDGET (pnl_dock_widget_get_type())
+#define PNL_TYPE_DOCK_WINDOW (pnl_dock_window_get_type())
+#define PNL_TYPE_TAB (pnl_tab_get_type())
+#define PNL_TYPE_TAB_STRIP (pnl_tab_strip_get_type())
+#define PNL_TYPE_TAB_STYLE (pnl_tab_style_get_type())
+
+G_DECLARE_DERIVABLE_TYPE (PnlDockBin, pnl_dock_bin, PNL, DOCK_BIN,
GtkContainer)
+G_DECLARE_DERIVABLE_TYPE (PnlDockBinEdge, pnl_dock_bin_edge, PNL, DOCK_BIN_EDGE,
PnlDockRevealer)
+G_DECLARE_DERIVABLE_TYPE (PnlDockManager, pnl_dock_manager, PNL, DOCK_MANAGER,
GObject)
+G_DECLARE_DERIVABLE_TYPE (PnlDockOverlay, pnl_dock_overlay, PNL, DOCK_OVERLAY,
GtkEventBox)
+G_DECLARE_DERIVABLE_TYPE (PnlDockPaned, pnl_dock_paned, PNL, DOCK_PANED,
PnlMultiPaned)
+G_DECLARE_DERIVABLE_TYPE (PnlDockStack, pnl_dock_stack, PNL, DOCK_STACK,
GtkBox)
+G_DECLARE_DERIVABLE_TYPE (PnlDockWidget, pnl_dock_widget, PNL, DOCK_WIDGET,
PnlBin)
+G_DECLARE_DERIVABLE_TYPE (PnlDockWindow, pnl_dock_window, PNL, DOCK_WINDOW,
GtkWindow)
+G_DECLARE_DERIVABLE_TYPE (PnlTabStrip, pnl_tab_strip, PNL, TAB_STRIP,
GtkBox)
+
+G_DECLARE_FINAL_TYPE (PnlTab, pnl_tab, PNL, TAB,
PnlBin)
+G_DECLARE_FINAL_TYPE (PnlDockOverlayEdge, pnl_dock_overlay_edge, PNL, DOCK_OVERLAY_EDGE,
PnlBin)
+
+G_DECLARE_INTERFACE (PnlDock, pnl_dock, PNL, DOCK,
GtkContainer)
+G_DECLARE_INTERFACE (PnlDockItem, pnl_dock_item, PNL, DOCK_ITEM,
GtkWidget)
+
+typedef enum
+{
+ PNL_TAB_TEXT = 1 << 0,
+ PNL_TAB_ICONS = 1 << 1,
+ PNL_TAB_BOTH = (PNL_TAB_TEXT | PNL_TAB_ICONS),
+} PnlTabStyle;
+
+GType pnl_tab_style_get_type (void);
G_END_DECLS
diff --git a/contrib/pnl/pnl-dock-widget.c b/contrib/pnl/pnl-dock-widget.c
index 0b54845..f115b29 100644
--- a/contrib/pnl/pnl-dock-widget.c
+++ b/contrib/pnl/pnl-dock-widget.c
@@ -23,14 +23,20 @@
typedef struct
{
gchar *title;
+ gchar *icon_name;
+ guint can_close : 1;
} PnlDockWidgetPrivate;
-G_DEFINE_TYPE_EXTENDED (PnlDockWidget, pnl_dock_widget, GTK_TYPE_BIN, 0,
+static void dock_item_iface_init (PnlDockItemInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (PnlDockWidget, pnl_dock_widget, PNL_TYPE_BIN, 0,
G_ADD_PRIVATE (PnlDockWidget)
- G_IMPLEMENT_INTERFACE (PNL_TYPE_DOCK_ITEM, NULL))
+ G_IMPLEMENT_INTERFACE (PNL_TYPE_DOCK_ITEM, dock_item_iface_init))
enum {
PROP_0,
+ PROP_CAN_CLOSE,
+ PROP_ICON_NAME,
PROP_MANAGER,
PROP_TITLE,
N_PROPS
@@ -38,6 +44,56 @@ enum {
static GParamSpec *properties [N_PROPS];
+static gchar *
+pnl_dock_widget_item_get_title (PnlDockItem *item)
+{
+ PnlDockWidget *self = (PnlDockWidget *)item;
+ PnlDockWidgetPrivate *priv = pnl_dock_widget_get_instance_private (self);
+
+ g_return_val_if_fail (PNL_IS_DOCK_WIDGET (self), NULL);
+
+ return g_strdup (priv->title);
+}
+
+static gchar *
+pnl_dock_widget_item_get_icon_name (PnlDockItem *item)
+{
+ PnlDockWidget *self = (PnlDockWidget *)item;
+ PnlDockWidgetPrivate *priv = pnl_dock_widget_get_instance_private (self);
+
+ g_return_val_if_fail (PNL_IS_DOCK_WIDGET (self), NULL);
+
+ return g_strdup (priv->icon_name);
+}
+
+static gboolean
+pnl_dock_widget_get_can_close (PnlDockItem *item)
+{
+ PnlDockWidget *self = (PnlDockWidget *)item;
+ PnlDockWidgetPrivate *priv = pnl_dock_widget_get_instance_private (self);
+
+ g_return_val_if_fail (PNL_IS_DOCK_WIDGET (self), FALSE);
+
+ return priv->can_close;
+}
+
+static void
+pnl_dock_widget_set_can_close (PnlDockWidget *self,
+ gboolean can_close)
+{
+ PnlDockWidgetPrivate *priv = pnl_dock_widget_get_instance_private (self);
+
+ g_return_if_fail (PNL_IS_DOCK_WIDGET (self));
+
+ can_close = !!can_close;
+
+ if (can_close != priv->can_close)
+ {
+ priv->can_close = can_close;
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_CAN_CLOSE]);
+ }
+}
+
static void
pnl_dock_widget_grab_focus (GtkWidget *widget)
{
@@ -61,6 +117,7 @@ pnl_dock_widget_finalize (GObject *object)
PnlDockWidgetPrivate *priv = pnl_dock_widget_get_instance_private (self);
g_clear_pointer (&priv->title, g_free);
+ g_clear_pointer (&priv->icon_name, g_free);
G_OBJECT_CLASS (pnl_dock_widget_parent_class)->finalize (object);
}
@@ -75,12 +132,20 @@ pnl_dock_widget_get_property (GObject *object,
switch (prop_id)
{
+ case PROP_CAN_CLOSE:
+ g_value_set_boolean (value, pnl_dock_widget_get_can_close (PNL_DOCK_ITEM (self)));
+ break;
+
+ case PROP_ICON_NAME:
+ g_value_set_string (value, pnl_dock_widget_item_get_icon_name (PNL_DOCK_ITEM (self)));
+ break;
+
case PROP_MANAGER:
g_value_set_object (value, pnl_dock_item_get_manager (PNL_DOCK_ITEM (self)));
break;
case PROP_TITLE:
- g_value_set_string (value, pnl_dock_widget_get_title (self));
+ g_value_set_string (value, pnl_dock_widget_item_get_title (PNL_DOCK_ITEM (self)));
break;
default:
@@ -98,6 +163,14 @@ pnl_dock_widget_set_property (GObject *object,
switch (prop_id)
{
+ case PROP_CAN_CLOSE:
+ pnl_dock_widget_set_can_close (self, g_value_get_boolean (value));
+ break;
+
+ case PROP_ICON_NAME:
+ pnl_dock_widget_set_icon_name (self, g_value_get_string (value));
+ break;
+
case PROP_MANAGER:
pnl_dock_item_set_manager (PNL_DOCK_ITEM (self), g_value_get_object (value));
break;
@@ -121,27 +194,39 @@ pnl_dock_widget_class_init (PnlDockWidgetClass *klass)
object_class->get_property = pnl_dock_widget_get_property;
object_class->set_property = pnl_dock_widget_set_property;
- widget_class->draw = pnl_gtk_bin_draw;
widget_class->grab_focus = pnl_dock_widget_grab_focus;
- widget_class->size_allocate = pnl_gtk_bin_size_allocate;
+
+ properties [PROP_CAN_CLOSE] =
+ g_param_spec_boolean ("can-close",
+ "Can Close",
+ "If the dock widget can be closed by the user",
+ FALSE,
+ (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_ICON_NAME] =
+ g_param_spec_string ("icon-name",
+ "Icon Name",
+ "Icon Name",
+ NULL,
+ (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
properties [PROP_MANAGER] =
g_param_spec_object ("manager",
"Manager",
"The panel manager",
PNL_TYPE_DOCK_MANAGER,
- (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
properties [PROP_TITLE] =
g_param_spec_string ("title",
"Title",
"Title",
NULL,
- (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
g_object_class_install_properties (object_class, N_PROPS, properties);
- gtk_widget_class_set_css_name (widget_class, "dockwidget");
+ gtk_widget_class_set_css_name (widget_class, "pnldockwidget");
}
static void
@@ -157,16 +242,6 @@ pnl_dock_widget_new (void)
return g_object_new (PNL_TYPE_DOCK_WIDGET, NULL);
}
-const gchar *
-pnl_dock_widget_get_title (PnlDockWidget *self)
-{
- PnlDockWidgetPrivate *priv = pnl_dock_widget_get_instance_private (self);
-
- g_return_val_if_fail (PNL_IS_DOCK_WIDGET (self), NULL);
-
- return priv->title;
-}
-
void
pnl_dock_widget_set_title (PnlDockWidget *self,
const gchar *title)
@@ -182,3 +257,27 @@ pnl_dock_widget_set_title (PnlDockWidget *self,
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_TITLE]);
}
}
+
+void
+pnl_dock_widget_set_icon_name (PnlDockWidget *self,
+ const gchar *icon_name)
+{
+ PnlDockWidgetPrivate *priv = pnl_dock_widget_get_instance_private (self);
+
+ g_return_if_fail (PNL_IS_DOCK_WIDGET (self));
+
+ if (g_strcmp0 (icon_name, priv->icon_name) != 0)
+ {
+ g_free (priv->icon_name);
+ priv->icon_name = g_strdup (icon_name);
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_ICON_NAME]);
+ }
+}
+
+static void
+dock_item_iface_init (PnlDockItemInterface *iface)
+{
+ iface->get_can_close = pnl_dock_widget_get_can_close;
+ iface->get_title = pnl_dock_widget_item_get_title;
+ iface->get_icon_name = pnl_dock_widget_item_get_icon_name;
+}
diff --git a/contrib/pnl/pnl-dock-widget.h b/contrib/pnl/pnl-dock-widget.h
index 7141ad4..d97daf2 100644
--- a/contrib/pnl/pnl-dock-widget.h
+++ b/contrib/pnl/pnl-dock-widget.h
@@ -29,22 +29,23 @@ G_BEGIN_DECLS
struct _PnlDockWidgetClass
{
- GtkBinClass parent;
-
- void (*padding1) (void);
- void (*padding2) (void);
- void (*padding3) (void);
- void (*padding4) (void);
- void (*padding5) (void);
- void (*padding6) (void);
- void (*padding7) (void);
- void (*padding8) (void);
+ PnlBinClass parent;
+
+ gpointer _reserved1;
+ gpointer _reserved2;
+ gpointer _reserved3;
+ gpointer _reserved4;
+ gpointer _reserved5;
+ gpointer _reserved6;
+ gpointer _reserved7;
+ gpointer _reserved8;
};
-GtkWidget *pnl_dock_widget_new (void);
-const gchar *pnl_dock_widget_get_title (PnlDockWidget *self);
-void pnl_dock_widget_set_title (PnlDockWidget *self,
- const gchar *title);
+GtkWidget *pnl_dock_widget_new (void);
+void pnl_dock_widget_set_title (PnlDockWidget *self,
+ const gchar *title);
+void pnl_dock_widget_set_icon_name (PnlDockWidget *self,
+ const gchar *icon_name);
G_END_DECLS
diff --git a/contrib/pnl/pnl-dock-window.c b/contrib/pnl/pnl-dock-window.c
index 4aa7d85..afaaefd 100644
--- a/contrib/pnl/pnl-dock-window.c
+++ b/contrib/pnl/pnl-dock-window.c
@@ -93,7 +93,7 @@ pnl_dock_window_class_init (PnlDockWindowClass *klass)
g_object_class_override_property (object_class, PROP_MANAGER, "manager");
- gtk_widget_class_set_css_name (widget_class, "dockwindow");
+ gtk_widget_class_set_css_name (widget_class, "pnldockwindow");
}
static void
diff --git a/contrib/pnl/pnl-dock-window.h b/contrib/pnl/pnl-dock-window.h
index b45fb2d..ae8ff43 100644
--- a/contrib/pnl/pnl-dock-window.h
+++ b/contrib/pnl/pnl-dock-window.h
@@ -30,6 +30,15 @@ G_BEGIN_DECLS
struct _PnlDockWindowClass
{
GtkWindowClass parent;
+
+ gpointer _reserved1;
+ gpointer _reserved2;
+ gpointer _reserved3;
+ gpointer _reserved4;
+ gpointer _reserved5;
+ gpointer _reserved6;
+ gpointer _reserved7;
+ gpointer _reserved8;
};
GtkWidget *pnl_dock_window_new (void);
diff --git a/contrib/pnl/pnl-multi-paned.c b/contrib/pnl/pnl-multi-paned.c
index 0217136..7b0d5d2 100644
--- a/contrib/pnl/pnl-multi-paned.c
+++ b/contrib/pnl/pnl-multi-paned.c
@@ -17,7 +17,10 @@
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#define G_LOG_DOMAIN "pnl-multi-paned"
+
#include "pnl-multi-paned.h"
+#include "pnl-util-private.h"
#define HANDLE_WIDTH 10
#define HANDLE_HEIGHT 10
@@ -573,6 +576,8 @@ pnl_multi_paned_get_preferred_height (GtkWidget *widget,
{
PnlMultiPaned *self = (PnlMultiPaned *)widget;
PnlMultiPanedPrivate *priv = pnl_multi_paned_get_instance_private (self);
+ GtkStyleContext *style_context;
+ GtkBorder borders;
guint i;
gint real_min_height = 0;
gint real_nat_height = 0;
@@ -614,6 +619,12 @@ pnl_multi_paned_get_preferred_height (GtkWidget *widget,
*min_height = real_min_height;
*nat_height = real_nat_height;
+
+ style_context = gtk_widget_get_style_context (widget);
+ pnl_gtk_style_context_get_borders (style_context, &borders);
+
+ *min_height += borders.top + borders.bottom;
+ *nat_height += borders.top + borders.bottom;
}
static void
@@ -675,6 +686,8 @@ pnl_multi_paned_get_preferred_height_for_width (GtkWidget *widget,
{
PnlMultiPaned *self = (PnlMultiPaned *)widget;
PnlMultiPanedPrivate *priv = pnl_multi_paned_get_instance_private (self);
+ GtkStyleContext *style_context;
+ GtkBorder borders;
g_assert (PNL_IS_MULTI_PANED (self));
g_assert (min_height != NULL);
@@ -697,6 +710,12 @@ pnl_multi_paned_get_preferred_height_for_width (GtkWidget *widget,
*min_height += handle_size;
*nat_height += handle_size;
}
+
+ style_context = gtk_widget_get_style_context (widget);
+ pnl_gtk_style_context_get_borders (style_context, &borders);
+
+ *min_height += borders.top + borders.bottom;
+ *nat_height += borders.top + borders.bottom;
}
static void
@@ -706,6 +725,8 @@ pnl_multi_paned_get_preferred_width (GtkWidget *widget,
{
PnlMultiPaned *self = (PnlMultiPaned *)widget;
PnlMultiPanedPrivate *priv = pnl_multi_paned_get_instance_private (self);
+ GtkStyleContext *style_context;
+ GtkBorder borders;
guint i;
gint real_min_width = 0;
gint real_nat_width = 0;
@@ -747,6 +768,12 @@ pnl_multi_paned_get_preferred_width (GtkWidget *widget,
*min_width = real_min_width;
*nat_width = real_nat_width;
+
+ style_context = gtk_widget_get_style_context (widget);
+ pnl_gtk_style_context_get_borders (style_context, &borders);
+
+ *min_width += borders.left + borders.right;
+ *nat_width += borders.left + borders.right;
}
static void
@@ -808,6 +835,8 @@ pnl_multi_paned_get_preferred_width_for_height (GtkWidget *widget,
{
PnlMultiPaned *self = (PnlMultiPaned *)widget;
PnlMultiPanedPrivate *priv = pnl_multi_paned_get_instance_private (self);
+ GtkStyleContext *style_context;
+ GtkBorder borders;
g_assert (PNL_IS_MULTI_PANED (self));
g_assert (min_width != NULL);
@@ -827,6 +856,12 @@ pnl_multi_paned_get_preferred_width_for_height (GtkWidget *widget,
*min_width += handle_size;
*nat_width += handle_size;
}
+
+ style_context = gtk_widget_get_style_context (widget);
+ pnl_gtk_style_context_get_borders (style_context, &borders);
+
+ *min_width += borders.left + borders.right;
+ *nat_width += borders.left + borders.right;
}
static void
@@ -958,19 +993,26 @@ static void
allocation_stage_borders (PnlMultiPaned *self,
AllocationState *state)
{
- gint border_width;
+ GtkStyleContext *style_context;
+ GtkBorder borders;
g_assert (PNL_IS_MULTI_PANED (self));
g_assert (state != NULL);
g_assert (state->children != NULL);
g_assert (state->n_children > 0);
- border_width = gtk_container_get_border_width (GTK_CONTAINER (self));
+ /*
+ * This subtracts the border+padding from the allocation area so the
+ * children are guaranteed to fall within that area.
+ */
+
+ style_context = gtk_widget_get_style_context (GTK_WIDGET (self));
+ pnl_gtk_style_context_get_borders (style_context, &borders);
- state->top_alloc.x += border_width;
- state->top_alloc.y += border_width;
- state->top_alloc.width -= border_width * 2;
- state->top_alloc.height -= border_width * 2;
+ state->top_alloc.x += borders.left;
+ state->top_alloc.y += borders.right;
+ state->top_alloc.width -= (borders.left + borders.right);
+ state->top_alloc.height -= (borders.top + borders.bottom);
if (state->top_alloc.width < 0)
state->top_alloc.width = 0;
@@ -1212,7 +1254,7 @@ allocation_stage_expand (PnlMultiPaned *self,
}
if (n_expand == 0)
- return;
+ goto fill_last;
if (IS_HORIZONTAL (state->orientation))
adjust = state->avail_width / n_expand;
@@ -1249,6 +1291,8 @@ allocation_stage_expand (PnlMultiPaned *self,
}
}
+fill_last:
+
if (IS_HORIZONTAL (state->orientation))
{
if (state->avail_width > 0)
@@ -1284,26 +1328,33 @@ allocation_stage_allocate (PnlMultiPaned *self,
gtk_widget_size_allocate (child->widget, &child->alloc);
- if ((child->handle != NULL) && (state->n_children != (i + 1)))
+ if (child->handle != NULL)
{
- if (state->orientation == GTK_ORIENTATION_HORIZONTAL)
+ if (state->n_children != (i + 1))
{
- gdk_window_move_resize (child->handle,
- child->alloc.x + child->alloc.width - (HANDLE_WIDTH / 2),
- child->alloc.y,
- HANDLE_WIDTH,
- child->alloc.height);
+ if (state->orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ gdk_window_move_resize (child->handle,
+ child->alloc.x + child->alloc.width - (HANDLE_WIDTH / 2),
+ child->alloc.y,
+ HANDLE_WIDTH,
+ child->alloc.height);
+ }
+ else
+ {
+ gdk_window_move_resize (child->handle,
+ child->alloc.x,
+ child->alloc.y + child->alloc.height - (HANDLE_HEIGHT / 2),
+ child->alloc.width,
+ HANDLE_HEIGHT);
+ }
+
+ gdk_window_show (child->handle);
}
else
{
- gdk_window_move_resize (child->handle,
- child->alloc.x,
- child->alloc.y + child->alloc.height - (HANDLE_HEIGHT / 2),
- child->alloc.width,
- HANDLE_HEIGHT);
+ gdk_window_hide (child->handle);
}
-
- gdk_window_show (child->handle);
}
}
}
@@ -1451,55 +1502,88 @@ pnl_multi_paned_draw (GtkWidget *widget,
{
PnlMultiPaned *self = (PnlMultiPaned *)widget;
PnlMultiPanedPrivate *priv = pnl_multi_paned_get_instance_private (self);
- gboolean ret;
+ GtkStyleContext *style_context;
+ GtkAllocation alloc;
+ GtkBorder margin;
+ GtkBorder borders;
+ GtkStateFlags state;
+ gint handle_size = 1;
+ guint i;
g_assert (PNL_IS_MULTI_PANED (self));
g_assert (cr != NULL);
- ret = GTK_WIDGET_CLASS (pnl_multi_paned_parent_class)->draw (widget, cr);
+ gtk_widget_get_allocation (widget, &alloc);
+
+ alloc.x = 0;
+ alloc.y = 0;
+
+ style_context = gtk_widget_get_style_context (widget);
+ state = gtk_style_context_get_state (style_context);
+
+ pnl_gtk_style_context_get_borders (style_context, &borders);
+
+ gtk_style_context_get_margin (style_context, state, &margin);
+ pnl_gtk_allocation_subtract_border (&alloc, &margin);
- if (ret != GDK_EVENT_STOP)
+ gtk_render_background (style_context, cr, alloc.x, alloc.y, alloc.width, alloc.height);
+
+ gtk_widget_style_get (widget, "handle-size", &handle_size, NULL);
+
+ for (i = 0; i < priv->children->len; i++)
{
- GtkStyleContext *style_context;
- gint handle_size = 1;
- guint i;
+ PnlMultiPanedChild *child = &g_array_index (priv->children, PnlMultiPanedChild, i);
- style_context = gtk_widget_get_style_context (GTK_WIDGET (self));
+ if (!gtk_widget_get_realized (child->widget) ||
+ !gtk_widget_get_visible (child->widget))
+ continue;
- gtk_widget_style_get (widget, "handle-size", &handle_size, NULL);
+ gtk_container_propagate_draw (GTK_CONTAINER (self), child->widget, cr);
+ }
+
+ if (priv->children->len > 0)
+ {
+ gtk_style_context_save (style_context);
+ gtk_style_context_add_class (style_context, "handle");
for (i = 0; i < priv->children->len; i++)
{
PnlMultiPanedChild *child = &g_array_index (priv->children, PnlMultiPanedChild, i);
- GtkAllocation alloc;
+ GtkAllocation child_alloc;
- if (!gtk_widget_get_realized (child->widget) ||
- !gtk_widget_get_visible (child->widget))
+ if (!gtk_widget_get_visible (child->widget) ||
+ !gtk_widget_get_child_visible (child->widget))
continue;
- gtk_widget_get_allocation (child->widget, &alloc);
+ if (pnl_multi_paned_is_last_visible_child (self, child))
+ break;
+
+ gtk_widget_get_allocation (child->widget, &child_alloc);
+ gtk_widget_translate_coordinates (child->widget, widget, 0, 0, &child_alloc.x, &child_alloc.y);
+
+ if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
+ gtk_render_handle (style_context,
+ cr,
+ child_alloc.x + child_alloc.width,
+ borders.top,
+ handle_size,
+ child_alloc.height);
+ else
+ gtk_render_handle (style_context,
+ cr,
+ borders.left,
+ child_alloc.y + child_alloc.height,
+ child_alloc.width,
+ handle_size);
- if (!pnl_multi_paned_is_last_visible_child (self, child))
- {
- if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
- gtk_render_handle (style_context,
- cr,
- alloc.x + alloc.width,
- 0,
- handle_size,
- alloc.height);
- else
- gtk_render_handle (style_context,
- cr,
- 0,
- alloc.y + alloc.height,
- alloc.width,
- handle_size);
- }
}
+
+ gtk_style_context_restore (style_context);
}
- return ret;
+ gtk_render_frame (style_context, cr, alloc.x, alloc.y, alloc.width, alloc.height);
+
+ return FALSE;
}
static void
@@ -1834,7 +1918,7 @@ pnl_multi_paned_class_init (PnlMultiPanedClass *klass)
klass->resize_drag_begin = pnl_multi_paned_resize_drag_begin;
klass->resize_drag_end = pnl_multi_paned_resize_drag_end;
- gtk_widget_class_set_css_name (widget_class, "multipaned");
+ gtk_widget_class_set_css_name (widget_class, "pnlmultipaned");
properties [PROP_ORIENTATION] =
g_param_spec_enum ("orientation",
diff --git a/contrib/pnl/pnl-multi-paned.h b/contrib/pnl/pnl-multi-paned.h
index 2dae9cd..9b6854c 100644
--- a/contrib/pnl/pnl-multi-paned.h
+++ b/contrib/pnl/pnl-multi-paned.h
@@ -41,14 +41,14 @@ struct _PnlMultiPanedClass
void (*resize_drag_end) (PnlMultiPaned *self,
GtkWidget *child);
- void (*padding1) (void);
- void (*padding2) (void);
- void (*padding3) (void);
- void (*padding4) (void);
- void (*padding5) (void);
- void (*padding6) (void);
- void (*padding7) (void);
- void (*padding8) (void);
+ gpointer _reserved1;
+ gpointer _reserved2;
+ gpointer _reserved3;
+ gpointer _reserved4;
+ gpointer _reserved5;
+ gpointer _reserved6;
+ gpointer _reserved7;
+ gpointer _reserved8;
};
GtkWidget *pnl_multi_paned_new (void);
diff --git a/contrib/pnl/pnl-dock-tab-strip.h b/contrib/pnl/pnl-tab-private.h
similarity index 62%
rename from contrib/pnl/pnl-dock-tab-strip.h
rename to contrib/pnl/pnl-tab-private.h
index 6cf04d6..bbca3b5 100644
--- a/contrib/pnl/pnl-dock-tab-strip.h
+++ b/contrib/pnl/pnl-tab-private.h
@@ -1,6 +1,6 @@
-/* pnl-dock-tab-strip.h
+/* pnl-tab-private.h
*
- * Copyright (C) 2016 Christian Hergert <christian hergert me>
+ * Copyright (C) 2017 Christian Hergert <chergert redhat com>
*
* 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
@@ -16,19 +16,15 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef PNL_DOCK_TAB_STRIP_H
-#define PNL_DOCK_TAB_STRIP_H
+#ifndef PNL_TAB_PRIVATE_H
+#define PNL_TAB_PRIVATE_H
-#include "pnl-tab-strip.h"
+#include "pnl-tab.h"
G_BEGIN_DECLS
-#define PNL_TYPE_DOCK_TAB_STRIP (pnl_dock_tab_strip_get_type())
-
-G_DECLARE_FINAL_TYPE (PnlDockTabStrip, pnl_dock_tab_strip, PNL, DOCK_TAB_STRIP, PnlTabStrip)
-
-GtkWidget *pnl_dock_tab_strip_new (void);
+void _pnl_tab_update_controls (PnlTab *self);
G_END_DECLS
-#endif /* PNL_DOCK_TAB_STRIP_H */
+#endif /* PNL_TAB_PRIVATE_H */
diff --git a/contrib/pnl/pnl-tab-strip.c b/contrib/pnl/pnl-tab-strip.c
index e50b1c4..d78d9b9 100644
--- a/contrib/pnl/pnl-tab-strip.c
+++ b/contrib/pnl/pnl-tab-strip.c
@@ -17,6 +17,10 @@
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#define G_LOG_DOMAIN "pnl-tab-strip"
+
+#include "pnl-dock-item.h"
+#include "pnl-dock-widget.h"
#include "pnl-tab.h"
#include "pnl-tab-strip.h"
@@ -25,14 +29,20 @@ typedef struct
GAction *action;
GtkStack *stack;
GtkPositionType edge : 2;
+ PnlTabStyle style : 2;
} PnlTabStripPrivate;
-G_DEFINE_TYPE_WITH_PRIVATE (PnlTabStrip, pnl_tab_strip, GTK_TYPE_BOX)
+static void buildable_iface_init (GtkBuildableIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (PnlTabStrip, pnl_tab_strip, GTK_TYPE_BOX,
+ G_ADD_PRIVATE (PnlTabStrip)
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, buildable_iface_init))
enum {
PROP_0,
PROP_EDGE,
PROP_STACK,
+ PROP_STYLE,
N_PROPS
};
@@ -73,7 +83,7 @@ set_tab_state (GSimpleAction *action,
* manually setting the state.
*/
if (PNL_IS_TAB (tab))
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (tab), TRUE);
+ pnl_tab_set_active (PNL_TAB (tab), TRUE);
}
}
@@ -90,8 +100,11 @@ pnl_tab_strip_update_action_targets (PnlTabStrip *self)
for (i = 0, iter = list; iter != NULL; iter = iter->next, i++)
{
- PnlTab *tab = iter->data;
- gtk_actionable_set_action_target (GTK_ACTIONABLE (tab), "i", i);
+ GtkWidget *widget = iter->data;
+
+ /* Ignore controls, and just update tabs */
+ if (PNL_IS_TAB (widget))
+ gtk_actionable_set_action_target (GTK_ACTIONABLE (widget), "i", i);
}
g_list_free (list);
@@ -165,6 +178,10 @@ pnl_tab_strip_get_property (GObject *object,
g_value_set_object (value, pnl_tab_strip_get_stack (self));
break;
+ case PROP_STYLE:
+ g_value_set_flags (value, pnl_tab_strip_get_style (self));
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
@@ -188,6 +205,10 @@ pnl_tab_strip_set_property (GObject *object,
pnl_tab_strip_set_stack (self, g_value_get_object (value));
break;
+ case PROP_STYLE:
+ pnl_tab_strip_set_style (self, g_value_get_flags (value));
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
@@ -216,6 +237,14 @@ pnl_tab_strip_class_init (PnlTabStripClass *klass)
GTK_POS_TOP,
(G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
+ properties [PROP_STYLE] =
+ g_param_spec_flags ("style",
+ "Style",
+ "The tab style",
+ PNL_TYPE_TAB_STYLE,
+ PNL_TAB_BOTH,
+ (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
+
properties [PROP_STACK] =
g_param_spec_object ("stack",
"Stack",
@@ -225,7 +254,7 @@ pnl_tab_strip_class_init (PnlTabStripClass *klass)
g_object_class_install_properties (object_class, N_PROPS, properties);
- gtk_widget_class_set_css_name (widget_class, "docktabstrip");
+ gtk_widget_class_set_css_name (widget_class, "pnltabstrip");
}
static void
@@ -237,6 +266,8 @@ pnl_tab_strip_init (PnlTabStrip *self)
{ "tab", NULL, "i", "0", set_tab_state },
};
+ priv->style = PNL_TAB_BOTH;
+
gtk_orientable_set_orientation (GTK_ORIENTABLE (self), GTK_ORIENTATION_HORIZONTAL);
group = g_simple_action_group_new ();
@@ -299,7 +330,7 @@ pnl_tab_strip_child_title_changed (PnlTabStrip *self,
GParamSpec *pspec,
GtkWidget *child)
{
- g_autofree gchar *title = NULL;
+ gchar *title = NULL;
GtkWidget *parent;
PnlTab *tab;
@@ -320,6 +351,38 @@ pnl_tab_strip_child_title_changed (PnlTabStrip *self,
NULL);
pnl_tab_set_title (tab, title);
+
+ g_free (title);
+}
+
+static void
+pnl_tab_strip_child_icon_name_changed (PnlTabStrip *self,
+ GParamSpec *pspec,
+ GtkWidget *child)
+{
+ gchar *icon_name = NULL;
+ GtkWidget *parent;
+ PnlTab *tab;
+
+ g_assert (PNL_IS_TAB_STRIP (self));
+ g_assert (GTK_IS_WIDGET (child));
+
+ tab = g_object_get_data (G_OBJECT (child), "PNL_TAB");
+
+ if (!PNL_IS_TAB (tab))
+ return;
+
+ parent = gtk_widget_get_parent (child);
+
+ g_assert (GTK_IS_STACK (parent));
+
+ gtk_container_child_get (GTK_CONTAINER (parent), child,
+ "icon-name", &icon_name,
+ NULL);
+
+ pnl_tab_set_icon_name (tab, icon_name);
+
+ g_free (icon_name);
}
static void
@@ -339,7 +402,7 @@ pnl_tab_strip_stack_notify_visible_child (PnlTabStrip *self,
PnlTab *tab = g_object_get_data (G_OBJECT (visible), "PNL_TAB");
if (PNL_IS_TAB (tab))
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (tab), TRUE);
+ pnl_tab_set_active (PNL_TAB (tab), TRUE);
}
}
@@ -354,7 +417,7 @@ pnl_tab_strip_tab_clicked (PnlTabStrip *self,
if (NULL != (widget = pnl_tab_get_widget (tab)))
{
- if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (tab)))
+ if (pnl_tab_get_active (tab))
gtk_widget_grab_focus (widget);
}
}
@@ -367,15 +430,21 @@ pnl_tab_strip_stack_add (PnlTabStrip *self,
PnlTabStripPrivate *priv = pnl_tab_strip_get_instance_private (self);
g_autoptr(GVariant) target = g_variant_ref_sink (g_variant_new_int32 (0));
PnlTab *tab;
+ gboolean can_close = FALSE;
g_assert (PNL_IS_TAB_STRIP (self));
g_assert (GTK_IS_WIDGET (widget));
g_assert (GTK_IS_STACK (stack));
+ if (PNL_IS_DOCK_ITEM (widget))
+ can_close = pnl_dock_item_get_can_close (PNL_DOCK_ITEM (widget));
+
tab = g_object_new (PNL_TYPE_TAB,
"action-name", "tab-strip.tab",
"action-target", target,
+ "can-close", can_close,
"edge", priv->edge,
+ "style", priv->style,
"widget", widget,
NULL);
@@ -399,11 +468,25 @@ pnl_tab_strip_stack_add (PnlTabStrip *self,
self,
G_CONNECT_SWAPPED);
- gtk_container_add (GTK_CONTAINER (self), GTK_WIDGET (tab));
+ g_signal_connect_object (widget,
+ "child-notify::icon-name",
+ G_CALLBACK (pnl_tab_strip_child_icon_name_changed),
+ self,
+ G_CONNECT_SWAPPED);
+
+ gtk_container_add_with_properties (GTK_CONTAINER (self), GTK_WIDGET (tab),
+ "pack-type", GTK_PACK_START,
+ "expand", TRUE,
+ "fill", TRUE,
+ NULL);
g_object_bind_property (widget, "visible", tab, "visible", G_BINDING_SYNC_CREATE);
+ if (PNL_IS_DOCK_WIDGET (widget))
+ g_object_bind_property (widget, "can-close", tab, "can-close", 0);
+
pnl_tab_strip_child_title_changed (self, NULL, widget);
+ pnl_tab_strip_child_icon_name_changed (self, NULL, widget);
pnl_tab_strip_stack_notify_visible_child (self, NULL, stack);
}
@@ -565,10 +648,10 @@ pnl_tab_strip_set_edge (PnlTabStrip *self,
style_context = gtk_widget_get_style_context (GTK_WIDGET (self));
- gtk_style_context_remove_class (style_context, "left-edge");
- gtk_style_context_remove_class (style_context, "top-edge");
- gtk_style_context_remove_class (style_context, "right-edge");
- gtk_style_context_remove_class (style_context, "bottom-edge");
+ gtk_style_context_remove_class (style_context, "left");
+ gtk_style_context_remove_class (style_context, "top");
+ gtk_style_context_remove_class (style_context, "right");
+ gtk_style_context_remove_class (style_context, "bottom");
switch (edge)
{
@@ -597,3 +680,82 @@ pnl_tab_strip_set_edge (PnlTabStrip *self,
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_EDGE]);
}
}
+
+static void
+apply_style (GtkWidget *widget,
+ gpointer user_data)
+{
+ PnlTabStyle style = GPOINTER_TO_UINT (user_data);
+
+ g_assert (GTK_IS_WIDGET (widget));
+
+ if (PNL_IS_TAB (widget))
+ pnl_tab_set_style (PNL_TAB (widget), style);
+}
+
+guint
+pnl_tab_strip_get_style (PnlTabStrip *self)
+{
+ PnlTabStripPrivate *priv = pnl_tab_strip_get_instance_private (self);
+
+ g_return_val_if_fail (PNL_IS_TAB_STRIP (self), 0);
+
+ return priv->style;
+}
+
+void
+pnl_tab_strip_set_style (PnlTabStrip *self,
+ PnlTabStyle style)
+{
+ PnlTabStripPrivate *priv = pnl_tab_strip_get_instance_private (self);
+
+ g_return_if_fail (PNL_IS_TAB_STRIP (self));
+
+ if (style != priv->style)
+ {
+ priv->style = style;
+ gtk_container_foreach (GTK_CONTAINER (self), apply_style, GUINT_TO_POINTER (style));
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_STYLE]);
+ }
+}
+
+void
+pnl_tab_strip_add_control (PnlTabStrip *self,
+ GtkWidget *widget)
+{
+ g_return_if_fail (PNL_IS_TAB_STRIP (self));
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ gtk_container_add_with_properties (GTK_CONTAINER (self), widget,
+ "pack-type", GTK_PACK_END,
+ "expand", FALSE,
+ "fill", FALSE,
+ NULL);
+
+ gtk_style_context_add_class (gtk_widget_get_style_context (widget), "control");
+}
+
+static void
+pnl_tab_strip_add_child (GtkBuildable *buildable,
+ GtkBuilder *builder,
+ GObject *child,
+ const gchar *child_type)
+{
+ PnlTabStrip *self = (PnlTabStrip *)buildable;
+
+ g_assert (PNL_IS_TAB_STRIP (self));
+ g_assert (GTK_IS_BUILDER (builder));
+ g_assert (G_IS_OBJECT (child));
+
+ if (g_strcmp0 (child_type, "control") == 0 && GTK_IS_WIDGET (child))
+ pnl_tab_strip_add_control (self, GTK_WIDGET (child));
+ else
+ g_warning ("I do not know how to add %s of type %s",
+ G_OBJECT_TYPE_NAME (child), child_type ? child_type : "NULL");
+}
+
+static void
+buildable_iface_init (GtkBuildableIface *iface)
+{
+ iface->add_child = pnl_tab_strip_add_child;
+}
diff --git a/contrib/pnl/pnl-tab-strip.h b/contrib/pnl/pnl-tab-strip.h
index 1aba919..81b1138 100644
--- a/contrib/pnl/pnl-tab-strip.h
+++ b/contrib/pnl/pnl-tab-strip.h
@@ -24,17 +24,22 @@
#ifndef PNL_TAB_STRIP_H
#define PNL_TAB_STRIP_H
-#include <gtk/gtk.h>
+#include "pnl-dock-types.h"
G_BEGIN_DECLS
-#define PNL_TYPE_TAB_STRIP (pnl_tab_strip_get_type())
-
-G_DECLARE_DERIVABLE_TYPE (PnlTabStrip, pnl_tab_strip, PNL, TAB_STRIP, GtkBox)
-
struct _PnlTabStripClass
{
GtkBoxClass parent;
+
+ gpointer _reserved1;
+ gpointer _reserved2;
+ gpointer _reserved3;
+ gpointer _reserved4;
+ gpointer _reserved5;
+ gpointer _reserved6;
+ gpointer _reserved7;
+ gpointer _reserved8;
};
GtkWidget *pnl_tab_strip_new (void);
@@ -47,6 +52,11 @@ void pnl_tab_strip_set_edge (PnlTabStrip *self,
gboolean pnl_tab_strip_get_show_labels (PnlTabStrip *self);
void pnl_tab_strip_set_show_labels (PnlTabStrip *self,
gboolean show_labels);
+PnlTabStyle pnl_tab_strip_get_style (PnlTabStrip *self);
+void pnl_tab_strip_set_style (PnlTabStrip *self,
+ PnlTabStyle style);
+void pnl_tab_strip_add_control (PnlTabStrip *self,
+ GtkWidget *widget);
G_END_DECLS
diff --git a/contrib/pnl/pnl-tab.c b/contrib/pnl/pnl-tab.c
index 5199cf0..0b1c3a4 100644
--- a/contrib/pnl/pnl-tab.c
+++ b/contrib/pnl/pnl-tab.c
@@ -19,35 +19,187 @@
#define G_LOG_DOMAIN "pnl-tab"
+#include "pnl-dock-item.h"
#include "pnl-tab.h"
+#include "pnl-tab-private.h"
#include "pnl-util-private.h"
-struct _PnlTab
+struct _PnlTab { GtkEventBox parent; };
+
+typedef struct
{
- GtkToggleButton parent;
- GtkPositionType edge : 2;
- GtkLabel *title;
- GtkWidget *widget;
-};
+ /*
+ * The edge the tab is being displayed upon. We use this to rotate
+ * text or alter box orientation.
+ */
+ GtkPositionType edge : 2;
+
+ /* Can we be closed by the user */
+ guint can_close : 1;
+
+ /* Are we the active tab */
+ guint active : 1;
+
+ /* If we are currently pressed */
+ guint pressed : 1;
+
+ /* If the pointer is over the widget (prelight) */
+ guint pointer_in_widget : 1;
+
+ /* If we are currently activating */
+ guint in_activate : 1;
+
+ /* Our icon/text style */
+ PnlTabStyle style : 2;
+
+ /* The action name to change the current tab */
+ gchar *action_name;
+
+ /* The value for the current tab */
+ GVariant *action_target_value;
+
+ /*
+ * Because we don't have access to GtkActionMuxer or GtkActionHelper
+ * from inside of Gtk, we need to manually track the state of the
+ * action we are monitoring.
+ *
+ * We hold a pointer to the group so we can disconnect as necessary.
+ */
+ GActionGroup *action_group;
+ gulong action_state_changed_handler;
-G_DEFINE_TYPE (PnlTab, pnl_tab, GTK_TYPE_TOGGLE_BUTTON)
+ /*
+ * These are our control widgets. The box contains the title in the
+ * center with the minimize/close buttons to a side, depending on the
+ * orientation/edge of the tabs.
+ */
+ GtkBox *box;
+ GtkImage *image;
+ GtkLabel *title;
+ GtkWidget *close;
+ GtkWidget *minimize;
+
+ /*
+ * This is a weak pointer to the widget this tab represents.
+ * It's used by the stack to translate between the tab/widget
+ * as necessary.
+ */
+ GtkWidget *widget;
+} PnlTabPrivate;
+
+static void actionable_iface_init (GtkActionableInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (PnlTab, pnl_tab, PNL_TYPE_BIN,
+ G_ADD_PRIVATE (PnlTab)
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIONABLE, actionable_iface_init))
enum {
PROP_0,
+ PROP_ACTIVE,
+ PROP_CAN_CLOSE,
PROP_EDGE,
+ PROP_STYLE,
PROP_TITLE,
PROP_WIDGET,
- N_PROPS
+ N_PROPS,
+
+ PROP_ACTION_NAME,
+ PROP_ACTION_TARGET,
+};
+
+enum {
+ CLICKED,
+ N_SIGNALS
};
static GParamSpec *properties [N_PROPS];
+static guint signals [N_SIGNALS];
+
+static void
+pnl_tab_get_inner_allocation (PnlTab *self,
+ GtkAllocation *alloc)
+{
+ GtkBorder margin;
+ GtkBorder border;
+ GtkStyleContext *style_context;
+ GtkStateFlags flags;
+
+ g_assert (PNL_IS_TAB (self));
+ g_assert (alloc != NULL);
+
+ gtk_widget_get_allocation (GTK_WIDGET (self), alloc);
+
+ style_context = gtk_widget_get_style_context (GTK_WIDGET (self));
+ flags = gtk_widget_get_state_flags (GTK_WIDGET (self));
+
+ gtk_style_context_get_border (style_context, flags, &margin);
+ gtk_style_context_get_border (style_context, flags, &border);
+
+ alloc->x += border.left;
+ alloc->x += margin.left;
+
+ alloc->y += border.top;
+ alloc->y += margin.top;
+
+ alloc->width -= (border.right + border.left);
+ alloc->width -= (margin.right + margin.left);
+
+ alloc->height -= (border.bottom + border.top);
+ alloc->height -= (margin.bottom + margin.top);
+}
+
+static void
+pnl_tab_apply_state (PnlTab *self)
+{
+ PnlTabPrivate *priv = pnl_tab_get_instance_private (self);
+
+ g_assert (PNL_IS_TAB (self));
+
+ if (priv->active)
+ gtk_widget_set_state_flags (GTK_WIDGET (self), GTK_STATE_FLAG_CHECKED, FALSE);
+ else
+ gtk_widget_unset_state_flags (GTK_WIDGET (self), GTK_STATE_FLAG_CHECKED);
+}
+
+static void
+pnl_tab_activate (PnlTab *self)
+{
+ PnlTabPrivate *priv = pnl_tab_get_instance_private (self);
+ g_autoptr(GVariant) value = NULL;
+
+ g_assert (PNL_IS_TAB (self));
+
+ if (priv->in_activate ||
+ priv->action_name == NULL ||
+ priv->action_target_value == NULL)
+ return;
+
+ priv->in_activate = TRUE;
+
+ value = pnl_gtk_widget_get_action_state (GTK_WIDGET (self), priv->action_name);
+ if (value != NULL && !g_variant_equal (value, priv->action_target_value))
+ pnl_gtk_widget_activate_action (GTK_WIDGET (self), priv->action_name, priv->action_target_value);
+
+ priv->in_activate = FALSE;
+}
static void
pnl_tab_destroy (GtkWidget *widget)
{
PnlTab *self = (PnlTab *)widget;
+ PnlTabPrivate *priv = pnl_tab_get_instance_private (self);
- pnl_clear_weak_pointer (&self->widget);
+ if (priv->action_group != NULL)
+ {
+ g_signal_handler_disconnect (priv->action_group,
+ priv->action_state_changed_handler);
+ priv->action_state_changed_handler = 0;
+ pnl_clear_weak_pointer (&priv->action_group);
+ }
+
+ pnl_clear_weak_pointer (&priv->widget);
+ g_clear_pointer (&priv->action_name, g_free);
+ g_clear_pointer (&priv->action_target_value, g_variant_unref);
GTK_WIDGET_CLASS (pnl_tab_parent_class)->destroy (widget);
}
@@ -55,30 +207,44 @@ pnl_tab_destroy (GtkWidget *widget)
static void
pnl_tab_update_edge (PnlTab *self)
{
+ PnlTabPrivate *priv = pnl_tab_get_instance_private (self);
+
g_assert (PNL_IS_TAB (self));
- switch (self->edge)
+ switch (priv->edge)
{
case GTK_POS_TOP:
- gtk_label_set_angle (self->title, 0.0);
+ gtk_label_set_angle (priv->title, 0.0);
+ gtk_orientable_set_orientation (GTK_ORIENTABLE (priv->box), GTK_ORIENTATION_HORIZONTAL);
+ gtk_box_set_child_packing (priv->box, GTK_WIDGET (priv->close), FALSE, FALSE, 0, GTK_PACK_END);
+ gtk_box_set_child_packing (priv->box, GTK_WIDGET (priv->minimize), FALSE, FALSE, 0, GTK_PACK_END);
gtk_widget_set_hexpand (GTK_WIDGET (self), TRUE);
gtk_widget_set_vexpand (GTK_WIDGET (self), FALSE);
break;
case GTK_POS_BOTTOM:
- gtk_label_set_angle (self->title, 0.0);
+ gtk_label_set_angle (priv->title, 0.0);
+ gtk_orientable_set_orientation (GTK_ORIENTABLE (priv->box), GTK_ORIENTATION_HORIZONTAL);
+ gtk_box_set_child_packing (priv->box, GTK_WIDGET (priv->close), FALSE, FALSE, 0, GTK_PACK_END);
+ gtk_box_set_child_packing (priv->box, GTK_WIDGET (priv->minimize), FALSE, FALSE, 0, GTK_PACK_END);
gtk_widget_set_hexpand (GTK_WIDGET (self), TRUE);
gtk_widget_set_vexpand (GTK_WIDGET (self), FALSE);
break;
case GTK_POS_LEFT:
- gtk_label_set_angle (self->title, -90.0);
+ gtk_label_set_angle (priv->title, -90.0);
+ gtk_orientable_set_orientation (GTK_ORIENTABLE (priv->box), GTK_ORIENTATION_VERTICAL);
+ gtk_box_set_child_packing (priv->box, GTK_WIDGET (priv->close), FALSE, FALSE, 0, GTK_PACK_END);
+ gtk_box_set_child_packing (priv->box, GTK_WIDGET (priv->minimize), FALSE, FALSE, 0, GTK_PACK_END);
gtk_widget_set_hexpand (GTK_WIDGET (self), FALSE);
gtk_widget_set_vexpand (GTK_WIDGET (self), TRUE);
break;
case GTK_POS_RIGHT:
- gtk_label_set_angle (self->title, 90.0);
+ gtk_label_set_angle (priv->title, 90.0);
+ gtk_orientable_set_orientation (GTK_ORIENTABLE (priv->box), GTK_ORIENTATION_VERTICAL);
+ gtk_box_set_child_packing (priv->box, GTK_WIDGET (priv->close), FALSE, FALSE, 0, GTK_PACK_START);
+ gtk_box_set_child_packing (priv->box, GTK_WIDGET (priv->minimize), FALSE, FALSE, 0, GTK_PACK_START);
gtk_widget_set_hexpand (GTK_WIDGET (self), FALSE);
gtk_widget_set_vexpand (GTK_WIDGET (self), TRUE);
break;
@@ -88,6 +254,356 @@ pnl_tab_update_edge (PnlTab *self)
}
}
+static gboolean
+get_widget_coordinates (GtkWidget *widget,
+ GdkEvent *event,
+ gdouble *x,
+ gdouble *y)
+{
+ GdkWindow *window = ((GdkEventAny *)event)->window;
+ GdkWindow *target = gtk_widget_get_window (widget);
+ gdouble tx, ty;
+
+ if (!gdk_event_get_coords (event, &tx, &ty))
+ return FALSE;
+
+ while (window && window != target)
+ {
+ gint window_x, window_y;
+
+ gdk_window_get_position (window, &window_x, &window_y);
+ tx += window_x;
+ ty += window_y;
+
+ window = gdk_window_get_parent (window);
+ }
+
+ if (window)
+ {
+ *x = tx;
+ *y = ty;
+
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+static void
+pnl_tab_update_prelight (PnlTab *self,
+ GdkEvent *event)
+{
+ PnlTabPrivate *priv = pnl_tab_get_instance_private (self);
+ gdouble x, y;
+
+ g_assert (PNL_IS_TAB (self));
+ g_assert (event != NULL);
+
+ if (get_widget_coordinates (GTK_WIDGET (self), (GdkEvent *)event, &x, &y))
+ {
+ GtkAllocation alloc;
+
+ pnl_tab_get_inner_allocation (self, &alloc);
+
+ /*
+ * We've translated our x,y coords to be relative to the widget, so we
+ * can discard the x,y of the allocation.
+ */
+ alloc.x = 0;
+ alloc.y = 0;
+
+ if (x >= alloc.x &&
+ x <= (alloc.x + alloc.width) &&
+ y >= alloc.y &&
+ y <= (alloc.y + alloc.height))
+ {
+ priv->pointer_in_widget = TRUE;
+ gtk_widget_set_state_flags (GTK_WIDGET (self), GTK_STATE_FLAG_PRELIGHT, FALSE);
+ return;
+ }
+ }
+
+ priv->pointer_in_widget = FALSE;
+ gtk_widget_unset_state_flags (GTK_WIDGET (self), GTK_STATE_FLAG_PRELIGHT);
+}
+
+static gboolean
+pnl_tab_motion_notify_event (GtkWidget *widget,
+ GdkEventMotion *event)
+{
+ PnlTab *self = (PnlTab *)widget;
+
+ g_assert (PNL_IS_TAB (self));
+ g_assert (event != NULL);
+
+ pnl_tab_update_prelight (self, (GdkEvent *)event);
+
+ return GDK_EVENT_PROPAGATE;
+}
+
+static gboolean
+pnl_tab_enter_notify_event (GtkWidget *widget,
+ GdkEventCrossing *event)
+{
+ PnlTab *self = (PnlTab *)widget;
+
+ g_assert (PNL_IS_TAB (self));
+ g_assert (event != NULL);
+
+ pnl_tab_update_prelight (self, (GdkEvent *)event);
+
+ return GDK_EVENT_PROPAGATE;
+}
+
+static gboolean
+pnl_tab_leave_notify_event (GtkWidget *widget,
+ GdkEventCrossing *event)
+{
+ PnlTab *self = (PnlTab *)widget;
+
+ g_return_val_if_fail (PNL_IS_TAB (self), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ pnl_tab_update_prelight (self, (GdkEvent *)event);
+
+ return GDK_EVENT_PROPAGATE;
+}
+
+static gboolean
+pnl_tab_button_press_event (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ PnlTab *self = (PnlTab *)widget;
+ PnlTabPrivate *priv = pnl_tab_get_instance_private (self);
+
+ g_return_val_if_fail (PNL_IS_TAB (self), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (event->button == GDK_BUTTON_PRIMARY)
+ {
+ priv->pressed = TRUE;
+ gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_ACTIVE, FALSE);
+ gtk_widget_grab_focus (GTK_WIDGET (self));
+ return GDK_EVENT_STOP;
+ }
+
+ return GDK_EVENT_PROPAGATE;
+}
+
+static gboolean
+pnl_tab_button_release_event (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ PnlTab *self = (PnlTab *)widget;
+ PnlTabPrivate *priv = pnl_tab_get_instance_private (self);
+
+ g_return_val_if_fail (PNL_IS_TAB (self), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (event->button == GDK_BUTTON_PRIMARY)
+ {
+ priv->pressed = FALSE;
+ gtk_widget_unset_state_flags (widget, GTK_STATE_FLAG_ACTIVE);
+
+ if (priv->pointer_in_widget)
+ g_signal_emit (self, signals [CLICKED], 0);
+
+ return GDK_EVENT_STOP;
+ }
+
+ return GDK_EVENT_PROPAGATE;
+}
+
+static void
+pnl_tab_realize (GtkWidget *widget)
+{
+ PnlTab *self = (PnlTab *)widget;
+ GdkWindowAttr attributes = { 0 };
+ GdkWindow *parent;
+ GdkWindow *window;
+ GtkAllocation alloc;
+ gint attributes_mask = 0;
+
+ g_assert (PNL_IS_TAB (widget));
+
+ gtk_widget_get_allocation (GTK_WIDGET (self), &alloc);
+
+ gtk_widget_set_realized (GTK_WIDGET (self), TRUE);
+
+ parent = gtk_widget_get_parent_window (GTK_WIDGET (self));
+
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.x = alloc.x;
+ attributes.y = alloc.y;
+ attributes.width = alloc.width;
+ attributes.height = alloc.height;
+ attributes.visual = gtk_widget_get_visual (widget);
+ attributes.event_mask = gtk_widget_get_events (widget);
+ attributes.event_mask |= (GDK_BUTTON_PRESS_MASK |
+ GDK_BUTTON_RELEASE_MASK |
+ GDK_TOUCH_MASK |
+ GDK_EXPOSURE_MASK |
+ GDK_ENTER_NOTIFY_MASK |
+ GDK_LEAVE_NOTIFY_MASK);
+
+ attributes_mask = (GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL);
+
+ window = gdk_window_new (parent, &attributes, attributes_mask);
+ gtk_widget_register_window (GTK_WIDGET (self), window);
+ gtk_widget_set_window (GTK_WIDGET (self), window);
+}
+
+static void
+pnl_tab_action_state_changed (PnlTab *self,
+ const gchar *action_name,
+ GVariant *value,
+ GActionGroup *group)
+{
+ PnlTabPrivate *priv = pnl_tab_get_instance_private (self);
+ gboolean active;
+
+ g_assert (PNL_IS_TAB (self));
+ g_assert (action_name != NULL);
+ g_assert (G_IS_ACTION_GROUP (group));
+
+ active = (value != NULL &&
+ priv->action_target_value != NULL &&
+ g_variant_equal (value, priv->action_target_value));
+
+ if (active != priv->active)
+ {
+ priv->active = active;
+ pnl_tab_apply_state (self);
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ACTIVE]);
+ }
+}
+
+static void
+pnl_tab_monitor_action_group (PnlTab *self,
+ GActionGroup *group)
+{
+ PnlTabPrivate *priv = pnl_tab_get_instance_private (self);
+
+ g_return_if_fail (PNL_IS_TAB (self));
+ g_return_if_fail (!group || G_IS_ACTION_GROUP (group));
+
+ if (group != priv->action_group)
+ {
+ if (priv->action_group != NULL)
+ {
+ g_signal_handler_disconnect (priv->action_group,
+ priv->action_state_changed_handler);
+ priv->action_state_changed_handler = 0;
+ pnl_clear_weak_pointer (&priv->action_group);
+ }
+
+ if (group != NULL)
+ {
+ gchar *prefix = NULL;
+ gchar *name = NULL;
+
+ pnl_g_action_name_parse (priv->action_name, &prefix, &name);
+
+ if (name != NULL)
+ {
+ gchar *detailed;
+
+ detailed = g_strdup_printf ("action-state-changed::%s", name);
+ pnl_set_weak_pointer (&priv->action_group, group);
+ priv->action_state_changed_handler =
+ g_signal_connect_object (priv->action_group,
+ detailed,
+ G_CALLBACK (pnl_tab_action_state_changed),
+ self,
+ G_CONNECT_SWAPPED);
+
+ g_free (detailed);
+ }
+
+ g_free (prefix);
+ g_free (name);
+ }
+ }
+}
+
+static void
+pnl_tab_hierarchy_changed (GtkWidget *widget,
+ GtkWidget *old_toplevel)
+{
+ PnlTab *self = (PnlTab *)widget;
+ PnlTabPrivate *priv = pnl_tab_get_instance_private (self);
+ GActionGroup *group;
+
+ g_assert (GTK_IS_WIDGET (widget));
+ g_assert (!old_toplevel || GTK_IS_WIDGET (old_toplevel));
+
+ group = pnl_gtk_widget_find_group_for_action (widget, priv->action_name);
+ pnl_tab_monitor_action_group (self, group);
+}
+
+static void
+pnl_tab_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ g_assert (PNL_IS_TAB (widget));
+
+ GTK_WIDGET_CLASS (pnl_tab_parent_class)->size_allocate (widget, allocation);
+
+ if (gtk_widget_get_realized (widget))
+ gdk_window_move_resize (gtk_widget_get_window (widget),
+ allocation->x,
+ allocation->y,
+ allocation->width,
+ allocation->height);
+}
+
+static void
+pnl_tab_close_clicked (PnlTab *self,
+ GtkWidget *button)
+{
+ PnlTabPrivate *priv = pnl_tab_get_instance_private (self);
+
+ g_assert (PNL_IS_TAB (self));
+ g_assert (GTK_IS_BUTTON (button));
+
+ g_object_ref (self);
+
+ if (PNL_IS_DOCK_ITEM (priv->widget) &&
+ pnl_dock_item_get_can_close (PNL_DOCK_ITEM (priv->widget)))
+ pnl_dock_item_close (PNL_DOCK_ITEM (priv->widget));
+
+ g_object_unref (self);
+}
+
+static void
+pnl_tab_minimize_clicked (PnlTab *self,
+ GtkWidget *button)
+{
+ PnlTabPrivate *priv = pnl_tab_get_instance_private (self);
+ GtkPositionType position = GTK_POS_LEFT;
+
+ g_assert (PNL_IS_TAB (self));
+ g_assert (GTK_IS_BUTTON (button));
+
+ g_object_ref (self);
+
+ if (PNL_IS_DOCK_ITEM (priv->widget))
+ {
+ PnlDockItem *item = PNL_DOCK_ITEM (priv->widget);
+
+ for (PnlDockItem *parent = pnl_dock_item_get_parent (item);
+ parent != NULL;
+ parent = pnl_dock_item_get_parent (parent))
+ {
+ if (pnl_dock_item_minimize (parent, item, &position))
+ break;
+ }
+ }
+
+ g_object_unref (self);
+}
+
static void
pnl_tab_get_property (GObject *object,
guint prop_id,
@@ -95,13 +611,34 @@ pnl_tab_get_property (GObject *object,
GParamSpec *pspec)
{
PnlTab *self = PNL_TAB (object);
+ PnlTabPrivate *priv = pnl_tab_get_instance_private (self);
switch (prop_id)
{
+ case PROP_ACTIVE:
+ g_value_set_boolean (value, pnl_tab_get_active (self));
+ break;
+
+ case PROP_ACTION_NAME:
+ g_value_set_string (value, priv->action_name);
+ break;
+
+ case PROP_ACTION_TARGET:
+ g_value_set_boxed (value, priv->action_target_value);
+ break;
+
+ case PROP_CAN_CLOSE:
+ g_value_set_boolean (value, pnl_tab_get_can_close (self));
+ break;
+
case PROP_EDGE:
g_value_set_enum (value, pnl_tab_get_edge (self));
break;
+ case PROP_STYLE:
+ g_value_set_flags (value, pnl_tab_get_style (self));
+ break;
+
case PROP_TITLE:
g_value_set_string (value, pnl_tab_get_title (self));
break;
@@ -122,13 +659,38 @@ pnl_tab_set_property (GObject *object,
GParamSpec *pspec)
{
PnlTab *self = PNL_TAB (object);
+ PnlTabPrivate *priv = pnl_tab_get_instance_private (self);
switch (prop_id)
{
+ case PROP_ACTIVE:
+ pnl_tab_set_active (self, g_value_get_boolean (value));
+ break;
+
+ case PROP_ACTION_NAME:
+ g_free (priv->action_name);
+ priv->action_name = g_value_dup_string (value);
+ break;
+
+ case PROP_ACTION_TARGET:
+ g_clear_pointer (&priv->action_target_value, g_variant_unref);
+ priv->action_target_value = g_value_get_variant (value);
+ if (priv->action_target_value != NULL)
+ g_variant_ref_sink (priv->action_target_value);
+ break;
+
+ case PROP_CAN_CLOSE:
+ pnl_tab_set_can_close (self, g_value_get_boolean (value));
+ break;
+
case PROP_EDGE:
pnl_tab_set_edge (self, g_value_get_enum (value));
break;
+ case PROP_STYLE:
+ pnl_tab_set_style (self, g_value_get_flags (value));
+ break;
+
case PROP_TITLE:
pnl_tab_set_title (self, g_value_get_string (value));
break;
@@ -152,8 +714,33 @@ pnl_tab_class_init (PnlTabClass *klass)
object_class->set_property = pnl_tab_set_property;
widget_class->destroy = pnl_tab_destroy;
+ widget_class->button_press_event = pnl_tab_button_press_event;
+ widget_class->button_release_event = pnl_tab_button_release_event;
+ widget_class->motion_notify_event = pnl_tab_motion_notify_event;
+ widget_class->enter_notify_event = pnl_tab_enter_notify_event;
+ widget_class->leave_notify_event = pnl_tab_leave_notify_event;
+ widget_class->realize = pnl_tab_realize;
+ widget_class->size_allocate = pnl_tab_size_allocate;
+ widget_class->hierarchy_changed = pnl_tab_hierarchy_changed;
+
+ gtk_widget_class_set_css_name (widget_class, "pnltab");
+
+ g_object_class_override_property (object_class, PROP_ACTION_NAME, "action-name");
+ g_object_class_override_property (object_class, PROP_ACTION_TARGET, "action-target");
- gtk_widget_class_set_css_name (widget_class, "docktab");
+ properties [PROP_ACTIVE] =
+ g_param_spec_boolean ("active",
+ "Active",
+ "If the tab is currently active",
+ FALSE,
+ (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_CAN_CLOSE] =
+ g_param_spec_boolean ("can-close",
+ "Can Close",
+ "If the tab widget can be closed",
+ FALSE,
+ (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
properties [PROP_EDGE] =
g_param_spec_enum ("edge",
@@ -163,6 +750,14 @@ pnl_tab_class_init (PnlTabClass *klass)
GTK_POS_TOP,
(G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
+ properties [PROP_STYLE] =
+ g_param_spec_flags ("style",
+ "Style",
+ "The style for the tab",
+ PNL_TYPE_TAB_STYLE,
+ PNL_TAB_BOTH,
+ (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
+
properties [PROP_TITLE] =
g_param_spec_string ("title",
"Title",
@@ -178,61 +773,164 @@ pnl_tab_class_init (PnlTabClass *klass)
(G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
g_object_class_install_properties (object_class, N_PROPS, properties);
+
+ signals [CLICKED] =
+ g_signal_new_class_handler ("clicked",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_CALLBACK (pnl_tab_activate),
+ NULL, NULL, NULL, G_TYPE_NONE, 0);
}
static void
pnl_tab_init (PnlTab *self)
{
- self->edge = GTK_POS_TOP;
+ PnlTabPrivate *priv = pnl_tab_get_instance_private (self);
+ GtkBox *center;
+
+ priv->style = PNL_TAB_BOTH;
+ priv->edge = GTK_POS_TOP;
+
+ gtk_widget_set_has_window (GTK_WIDGET (self), TRUE);
+ gtk_widget_add_events (GTK_WIDGET (self),
+ GDK_BUTTON_PRESS_MASK |
+ GDK_BUTTON_RELEASE_MASK |
+ GDK_POINTER_MOTION_MASK |
+ GDK_ENTER_NOTIFY_MASK|
+ GDK_LEAVE_NOTIFY_MASK);
gtk_widget_set_hexpand (GTK_WIDGET (self), TRUE);
gtk_widget_set_vexpand (GTK_WIDGET (self), FALSE);
- self->title = g_object_new (GTK_TYPE_LABEL,
+ priv->box = g_object_new (GTK_TYPE_BOX,
+ "orientation", GTK_ORIENTATION_HORIZONTAL,
+ "visible", TRUE,
+ NULL);
+ g_signal_connect (priv->box, "destroy", G_CALLBACK (gtk_widget_destroyed), &priv->box);
+ gtk_container_add (GTK_CONTAINER (self), GTK_WIDGET (priv->box));
+
+ center = g_object_new (GTK_TYPE_BOX,
+ "spacing", 6,
+ "visible", TRUE,
+ NULL);
+ gtk_box_set_center_widget (priv->box, GTK_WIDGET (center));
+
+ priv->image = g_object_new (GTK_TYPE_IMAGE,
+ "visible", TRUE,
+ NULL);
+ g_signal_connect (priv->image, "destroy", G_CALLBACK (gtk_widget_destroyed), &priv->image);
+ gtk_box_pack_start (center, GTK_WIDGET (priv->image), FALSE, FALSE, 0);
+
+ priv->title = g_object_new (GTK_TYPE_LABEL,
"ellipsize", PANGO_ELLIPSIZE_END,
"use-underline", TRUE,
"visible", TRUE,
NULL);
+ g_signal_connect (priv->title, "destroy", G_CALLBACK (gtk_widget_destroyed), &priv->title);
+ gtk_box_pack_start (center, GTK_WIDGET (priv->title), FALSE, FALSE, 0);
+
+ priv->close = g_object_new (GTK_TYPE_BUTTON,
+ "halign", GTK_ALIGN_END,
+ "child", g_object_new (GTK_TYPE_IMAGE,
+ "icon-name", "window-close-symbolic",
+ "visible", TRUE,
+ NULL),
+ "visible", TRUE,
+ NULL);
+ g_signal_connect_object (priv->close,
+ "clicked",
+ G_CALLBACK (pnl_tab_close_clicked),
+ self,
+ G_CONNECT_SWAPPED);
+ gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (priv->close)), "close");
+ gtk_box_pack_end (priv->box, GTK_WIDGET (priv->close), FALSE, FALSE, 0);
+ g_object_bind_property (self, "can-close", priv->close, "visible", G_BINDING_SYNC_CREATE);
- gtk_container_add (GTK_CONTAINER (self), GTK_WIDGET (self->title));
+ priv->minimize = g_object_new (GTK_TYPE_BUTTON,
+ "halign", GTK_ALIGN_END,
+ "child", g_object_new (GTK_TYPE_IMAGE,
+ "icon-name", "window-minimize-symbolic",
+ "visible", TRUE,
+ NULL),
+ "visible", TRUE,
+ NULL);
+ g_signal_connect_object (priv->minimize,
+ "clicked",
+ G_CALLBACK (pnl_tab_minimize_clicked),
+ self,
+ G_CONNECT_SWAPPED);
+ gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (priv->minimize)), "minimize");
+ gtk_box_pack_end (priv->box, GTK_WIDGET (priv->minimize), FALSE, FALSE, 0);
}
const gchar *
pnl_tab_get_title (PnlTab *self)
{
+ PnlTabPrivate *priv = pnl_tab_get_instance_private (self);
+
g_return_val_if_fail (PNL_IS_TAB (self), NULL);
- return gtk_label_get_label (self->title);
+ return gtk_label_get_label (priv->title);
}
void
pnl_tab_set_title (PnlTab *self,
const gchar *title)
{
+ PnlTabPrivate *priv = pnl_tab_get_instance_private (self);
+
g_return_if_fail (PNL_IS_TAB (self));
- gtk_label_set_label (self->title, title);
+ gtk_label_set_label (priv->title, title);
+}
+
+const gchar *
+pnl_tab_get_icon_name (PnlTab *self)
+{
+ PnlTabPrivate *priv = pnl_tab_get_instance_private (self);
+ const gchar *ret = NULL;
+
+ g_return_val_if_fail (PNL_IS_TAB (self), NULL);
+
+ gtk_image_get_icon_name (priv->image, &ret, NULL);
+
+ return ret;
+}
+
+void
+pnl_tab_set_icon_name (PnlTab *self,
+ const gchar *icon_name)
+{
+ PnlTabPrivate *priv = pnl_tab_get_instance_private (self);
+
+ g_return_if_fail (PNL_IS_TAB (self));
+
+ g_object_set (priv->image, "icon-name", icon_name, NULL);
}
GtkPositionType
pnl_tab_get_edge (PnlTab *self)
{
+ PnlTabPrivate *priv = pnl_tab_get_instance_private (self);
+
g_return_val_if_fail (PNL_IS_TAB (self), 0);
- return self->edge;
+ return priv->edge;
}
void
pnl_tab_set_edge (PnlTab *self,
GtkPositionType edge)
{
+ PnlTabPrivate *priv = pnl_tab_get_instance_private (self);
+
g_return_if_fail (PNL_IS_TAB (self));
g_return_if_fail (edge >= 0);
g_return_if_fail (edge <= 3);
- if (self->edge != edge)
+ if (priv->edge != edge)
{
- self->edge = edge;
+ priv->edge = edge;
pnl_tab_update_edge (self);
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_EDGE]);
}
@@ -246,20 +944,214 @@ pnl_tab_set_edge (PnlTab *self,
GtkWidget *
pnl_tab_get_widget (PnlTab *self)
{
+ PnlTabPrivate *priv = pnl_tab_get_instance_private (self);
+
g_return_val_if_fail (PNL_IS_TAB (self), NULL);
- return self->widget;
+ return priv->widget;
}
void
pnl_tab_set_widget (PnlTab *self,
GtkWidget *widget)
{
+ PnlTabPrivate *priv = pnl_tab_get_instance_private (self);
+
g_return_if_fail (PNL_IS_TAB (self));
- if (pnl_set_weak_pointer (&self->widget, widget))
+ if (pnl_set_weak_pointer (&priv->widget, widget))
{
- gtk_label_set_mnemonic_widget (self->title, widget);
+ gtk_label_set_mnemonic_widget (priv->title, widget);
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_WIDGET]);
}
}
+
+gboolean
+pnl_tab_get_can_close (PnlTab *self)
+{
+ PnlTabPrivate *priv = pnl_tab_get_instance_private (self);
+
+ g_return_val_if_fail (PNL_IS_TAB (self), FALSE);
+
+ return priv->can_close;
+}
+
+void
+pnl_tab_set_can_close (PnlTab *self,
+ gboolean can_close)
+{
+ PnlTabPrivate *priv = pnl_tab_get_instance_private (self);
+
+ g_return_if_fail (PNL_IS_TAB (self));
+
+ can_close = !!can_close;
+
+ if (can_close != priv->can_close)
+ {
+ priv->can_close = can_close;
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_CAN_CLOSE]);
+ }
+}
+
+gboolean
+pnl_tab_get_active (PnlTab *self)
+{
+ PnlTabPrivate *priv = pnl_tab_get_instance_private (self);
+
+ g_return_val_if_fail (PNL_IS_TAB (self), FALSE);
+
+ return priv->active;
+}
+
+void
+pnl_tab_set_active (PnlTab *self,
+ gboolean active)
+{
+ PnlTabPrivate *priv = pnl_tab_get_instance_private (self);
+
+ g_return_if_fail (PNL_IS_TAB (self));
+
+ active = !!active;
+
+ if (priv->active != active)
+ {
+ priv->active = active;
+ pnl_tab_activate (self);
+ pnl_tab_apply_state (self);
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_ACTIVE]);
+ }
+}
+
+static const gchar *
+pnl_tab_get_action_name (GtkActionable *actionable)
+{
+ PnlTab *self = (PnlTab *)actionable;
+ PnlTabPrivate *priv = pnl_tab_get_instance_private (self);
+
+ g_return_val_if_fail (PNL_IS_TAB (self), NULL);
+
+ return priv->action_name;
+}
+
+static void
+pnl_tab_set_action_name (GtkActionable *actionable,
+ const gchar *action_name)
+{
+ PnlTab *self = (PnlTab *)actionable;
+ PnlTabPrivate *priv = pnl_tab_get_instance_private (self);
+
+ g_return_if_fail (PNL_IS_TAB (self));
+
+ if (g_strcmp0 (priv->action_name, action_name) != 0)
+ {
+ g_free (priv->action_name);
+ priv->action_name = g_strdup (action_name);
+ g_object_notify (G_OBJECT (self), "action-name");
+ }
+}
+
+static GVariant *
+pnl_tab_get_action_target_value (GtkActionable *actionable)
+{
+ PnlTab *self = (PnlTab *)actionable;
+ PnlTabPrivate *priv = pnl_tab_get_instance_private (self);
+
+ g_return_val_if_fail (PNL_IS_TAB (self), NULL);
+
+ return priv->action_target_value;
+}
+
+static void
+pnl_tab_set_action_target_value (GtkActionable *actionable,
+ GVariant *variant)
+{
+ PnlTab *self = (PnlTab *)actionable;
+ PnlTabPrivate *priv = pnl_tab_get_instance_private (self);
+
+ g_return_if_fail (PNL_IS_TAB (self));
+
+ if (priv->action_target_value != variant)
+ {
+ g_clear_pointer (&priv->action_target_value, g_variant_unref);
+ if (variant)
+ priv->action_target_value = g_variant_ref (variant);
+ g_object_notify (G_OBJECT (self), "action-target");
+ }
+}
+
+static void
+actionable_iface_init (GtkActionableInterface *iface)
+{
+ iface->get_action_name = pnl_tab_get_action_name;
+ iface->set_action_name = pnl_tab_set_action_name;
+ iface->get_action_target_value = pnl_tab_get_action_target_value;
+ iface->set_action_target_value = pnl_tab_set_action_target_value;
+}
+
+PnlTabStyle
+pnl_tab_get_style (PnlTab *self)
+{
+ PnlTabPrivate *priv = pnl_tab_get_instance_private (self);
+
+ g_return_val_if_fail (PNL_IS_TAB (self), 0);
+
+ return priv->style;
+}
+
+void
+pnl_tab_set_style (PnlTab *self,
+ PnlTabStyle style)
+{
+ PnlTabPrivate *priv = pnl_tab_get_instance_private (self);
+
+ g_return_if_fail (PNL_IS_TAB (self));
+
+ if (style != priv->style)
+ {
+ priv->style = style;
+ gtk_widget_set_visible (GTK_WIDGET (priv->image), !!(priv->style & PNL_TAB_ICONS));
+ gtk_widget_set_visible (GTK_WIDGET (priv->title), !!(priv->style & PNL_TAB_TEXT));
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_STYLE]);
+ }
+}
+
+void
+_pnl_tab_update_controls (PnlTab *self)
+{
+ PnlTabPrivate *priv = pnl_tab_get_instance_private (self);
+ gboolean can_close = FALSE;
+ gboolean can_minimize = FALSE;
+
+ g_return_if_fail (PNL_IS_TAB (self));
+
+ if (PNL_IS_DOCK_ITEM (priv->widget))
+ {
+ can_close = pnl_dock_item_get_can_close (PNL_DOCK_ITEM (priv->widget));
+ can_minimize = pnl_dock_item_get_can_minimize (PNL_DOCK_ITEM (priv->widget));
+ }
+
+ gtk_widget_set_visible (GTK_WIDGET (priv->close), can_close);
+ gtk_widget_set_visible (GTK_WIDGET (priv->minimize), can_minimize);
+}
+
+GType
+pnl_tab_style_get_type (void)
+{
+ static GType type_id;
+
+ if (g_once_init_enter (&type_id))
+ {
+ GType _type_id;
+ static const GFlagsValue values[] = {
+ { PNL_TAB_ICONS, "PNL_TAB_ICONS", "icons" },
+ { PNL_TAB_TEXT, "PNL_TAB_TEXT", "text" },
+ { PNL_TAB_BOTH, "PNL_TAB_BOTH", "both" },
+ { 0 }
+ };
+
+ _type_id = g_flags_register_static ("PnlTabStyle", values);
+ g_once_init_leave (&type_id, _type_id);
+ }
+
+ return type_id;
+}
diff --git a/contrib/pnl/pnl-tab.h b/contrib/pnl/pnl-tab.h
index a59bfd5..c1e2188 100644
--- a/contrib/pnl/pnl-tab.h
+++ b/contrib/pnl/pnl-tab.h
@@ -24,23 +24,31 @@
#ifndef PNL_TAB_H
#define PNL_TAB_H
-#include <gtk/gtk.h>
+#include "pnl-dock-types.h"
G_BEGIN_DECLS
-#define PNL_TYPE_TAB (pnl_tab_get_type())
-
-G_DECLARE_FINAL_TYPE (PnlTab, pnl_tab, PNL, TAB, GtkToggleButton)
-
-const gchar *pnl_tab_get_title (PnlTab *self);
-void pnl_tab_set_title (PnlTab *self,
- const gchar *title);
-GtkPositionType pnl_tab_get_edge (PnlTab *self);
-void pnl_tab_set_edge (PnlTab *self,
- GtkPositionType edge);
-GtkWidget *pnl_tab_get_widget (PnlTab *self);
-void pnl_tab_set_widget (PnlTab *self,
- GtkWidget *widget);
+const gchar *pnl_tab_get_icon_name (PnlTab *self);
+void pnl_tab_set_icon_name (PnlTab *self,
+ const gchar *icon_name);
+const gchar *pnl_tab_get_title (PnlTab *self);
+void pnl_tab_set_title (PnlTab *self,
+ const gchar *title);
+GtkPositionType pnl_tab_get_edge (PnlTab *self);
+void pnl_tab_set_edge (PnlTab *self,
+ GtkPositionType edge);
+GtkWidget *pnl_tab_get_widget (PnlTab *self);
+void pnl_tab_set_widget (PnlTab *self,
+ GtkWidget *widget);
+gboolean pnl_tab_get_active (PnlTab *self);
+void pnl_tab_set_active (PnlTab *self,
+ gboolean active);
+gboolean pnl_tab_get_can_close (PnlTab *self);
+void pnl_tab_set_can_close (PnlTab *self,
+ gboolean can_close);
+PnlTabStyle pnl_tab_get_style (PnlTab *self);
+void pnl_tab_set_style (PnlTab *self,
+ PnlTabStyle style);
G_END_DECLS
diff --git a/contrib/pnl/pnl-util-private.h b/contrib/pnl/pnl-util-private.h
index 36e6845..8d1f1a9 100644
--- a/contrib/pnl/pnl-util-private.h
+++ b/contrib/pnl/pnl-util-private.h
@@ -29,10 +29,22 @@ G_BEGIN_DECLS
#define pnl_set_weak_pointer(ptr,obj) \
((obj!=*(ptr))?(pnl_clear_weak_pointer(ptr),*(ptr)=obj,((obj)?g_object_add_weak_pointer((GObject*)obj,(gpointer*)ptr),NULL:NULL),1):0)
-gboolean pnl_gtk_bin_draw (GtkWidget *widget,
- cairo_t *cr);
-void pnl_gtk_bin_size_allocate (GtkWidget *widget,
- GtkAllocation *allocation);
+void pnl_gtk_widget_add_class (GtkWidget *widget,
+ const gchar *class_name);
+gboolean pnl_gtk_widget_activate_action (GtkWidget *widget,
+ const gchar *full_action_name,
+ GVariant *variant);
+GVariant *pnl_gtk_widget_get_action_state (GtkWidget *widget,
+ const gchar *action_name);
+GActionGroup *pnl_gtk_widget_find_group_for_action (GtkWidget *widget,
+ const gchar *action_name);
+void pnl_g_action_name_parse (const gchar *action_name,
+ gchar **prefix,
+ gchar **name);
+void pnl_gtk_style_context_get_borders (GtkStyleContext *style_context,
+ GtkBorder *borders);
+void pnl_gtk_allocation_subtract_border (GtkAllocation *alloc,
+ GtkBorder *border);
G_END_DECLS
diff --git a/contrib/pnl/pnl-util.c b/contrib/pnl/pnl-util.c
index 5105be3..4f35d4a 100644
--- a/contrib/pnl/pnl-util.c
+++ b/contrib/pnl/pnl-util.c
@@ -16,6 +16,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#define G_LOG_DOMAIN "pnl-util"
+
+#include <string.h>
+
#include "pnl-util-private.h"
static void
@@ -28,82 +32,255 @@ pnl_gtk_border_sum (GtkBorder *one,
one->left += two->left;
}
-gboolean
-pnl_gtk_bin_draw (GtkWidget *widget,
- cairo_t *cr)
+void
+pnl_gtk_style_context_get_borders (GtkStyleContext *style_context,
+ GtkBorder *borders)
{
- GtkStyleContext *style_context;
+ GtkBorder border = { 0 };
+ GtkBorder padding = { 0 };
+ GtkBorder margin = { 0 };
GtkStateFlags state;
- GtkAllocation alloc;
- GtkBorder border;
- GtkBorder padding;
- GtkWidget *child;
- g_assert (GTK_IS_WIDGET (widget));
- g_assert (cr != NULL);
+ g_return_if_fail (GTK_IS_STYLE_CONTEXT (style_context));
+ g_return_if_fail (borders != NULL);
- gtk_widget_get_allocation (widget, &alloc);
+ memset (borders, 0, sizeof *borders);
- style_context = gtk_widget_get_style_context (widget);
state = gtk_style_context_get_state (style_context);
+
gtk_style_context_get_border (style_context, state, &border);
gtk_style_context_get_padding (style_context, state, &padding);
+ gtk_style_context_get_margin (style_context, state, &margin);
- pnl_gtk_border_sum (&border, &padding);
+ pnl_gtk_border_sum (borders, &padding);
+ pnl_gtk_border_sum (borders, &border);
+ pnl_gtk_border_sum (borders, &margin);
+}
- gtk_render_background (gtk_widget_get_style_context (widget), cr,
- border.left,
- border.top,
- alloc.width - border.left - border.right,
- alloc.height - border.top - border.bottom);
+static void
+split_action_name (const gchar *action_name,
+ gchar **prefix,
+ gchar **name)
+{
+ const gchar *dot;
- child = gtk_bin_get_child (GTK_BIN (widget));
+ g_assert (prefix != NULL);
+ g_assert (name != NULL);
- if (child != NULL)
- gtk_container_propagate_draw (GTK_CONTAINER (widget), child, cr);
+ *prefix = NULL;
+ *name = NULL;
- return GDK_EVENT_PROPAGATE;
+ if (action_name == NULL)
+ return;
+
+ dot = strchr (action_name, '.');
+
+ if (dot == NULL)
+ *name = g_strdup (action_name);
+ else
+ {
+ *prefix = g_strndup (action_name, dot - action_name);
+ *name = g_strdup (dot + 1);
+ }
}
-void
-pnl_gtk_bin_size_allocate (GtkWidget *widget,
- GtkAllocation *allocation)
+gboolean
+pnl_gtk_widget_activate_action (GtkWidget *widget,
+ const gchar *full_action_name,
+ GVariant *parameter)
{
- GtkStyleContext *style_context;
- GtkStateFlags state;
- GtkBorder border;
- GtkBorder padding;
- gint border_width;
- GtkWidget *child;
+ GtkWidget *toplevel;
+ GApplication *app;
+ GActionGroup *group = NULL;
+ gchar *prefix = NULL;
+ gchar *action_name = NULL;
+ const gchar *dot;
+ gboolean ret = FALSE;
- g_return_if_fail (GTK_IS_BIN (widget));
- g_return_if_fail (allocation != NULL);
+ g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+ g_return_val_if_fail (full_action_name, FALSE);
- gtk_widget_set_allocation (widget, allocation);
+ dot = strchr (full_action_name, '.');
- child = gtk_bin_get_child (GTK_BIN (widget));
+ if (dot == NULL)
+ {
+ prefix = NULL;
+ action_name = g_strdup (full_action_name);
+ }
+ else
+ {
+ prefix = g_strndup (full_action_name, dot - full_action_name);
+ action_name = g_strdup (dot + 1);
+ }
- if (child == NULL)
- return;
+ /*
+ * TODO: Support non-grouped names. We need to walk
+ * through all the groups at each level to do this.
+ */
+ if (prefix == NULL)
+ prefix = g_strdup ("win");
- style_context = gtk_widget_get_style_context (widget);
- state = gtk_style_context_get_state (style_context);
- gtk_style_context_get_border (style_context, state, &border);
- gtk_style_context_get_padding (style_context, state, &padding);
+ app = g_application_get_default ();
+ toplevel = gtk_widget_get_toplevel (widget);
+
+ while ((group == NULL) && (widget != NULL))
+ {
+ group = gtk_widget_get_action_group (widget, prefix);
+
+ if G_UNLIKELY (GTK_IS_POPOVER (widget))
+ {
+ GtkWidget *relative_to;
+
+ relative_to = gtk_popover_get_relative_to (GTK_POPOVER (widget));
+
+ if (relative_to != NULL)
+ widget = relative_to;
+ else
+ widget = gtk_widget_get_parent (widget);
+ }
+ else
+ {
+ widget = gtk_widget_get_parent (widget);
+ }
+ }
+
+ if (!group && g_str_equal (prefix, "win") && G_IS_ACTION_GROUP (toplevel))
+ group = G_ACTION_GROUP (toplevel);
+
+ if (!group && g_str_equal (prefix, "app") && G_IS_ACTION_GROUP (app))
+ group = G_ACTION_GROUP (app);
+
+ if (group && g_action_group_has_action (group, action_name))
+ {
+ g_action_group_activate_action (group, action_name, parameter);
+ ret = TRUE;
+ goto cleanup;
+ }
+
+ if (parameter && g_variant_is_floating (parameter))
+ {
+ parameter = g_variant_ref_sink (parameter);
+ g_variant_unref (parameter);
+ }
+
+ g_warning ("Failed to locate action %s.%s", prefix, action_name);
+
+cleanup:
+ g_free (prefix);
+ g_free (action_name);
+
+ return ret;
+}
+
+static GActionGroup *
+find_group_with_action (GtkWidget *widget,
+ const gchar *prefix,
+ const gchar *name)
+{
+ GActionGroup *group;
- pnl_gtk_border_sum (&border, &padding);
+ g_assert (GTK_IS_WIDGET (widget));
+ g_assert (name != NULL);
+
+ /*
+ * GtkWidget does not provide a way to get group names,
+ * so there is nothing more we can do if prefix is NULL.
+ */
+ if (prefix == NULL)
+ return NULL;
+
+ if (g_str_equal (prefix, "app"))
+ group = G_ACTION_GROUP (g_application_get_default ());
+ else
+ group = gtk_widget_get_action_group (widget, prefix);
+
+ if (group != NULL && g_action_group_has_action (group, name))
+ return group;
+
+ widget = gtk_widget_get_parent (widget);
- allocation->x += border.left;
- allocation->y += border.top;
- allocation->width -= border.left + border.right;
- allocation->height -= border.top + border.bottom;
+ if (widget != NULL)
+ return find_group_with_action (widget, prefix, name);
+
+ return NULL;
+}
+
+GVariant *
+pnl_gtk_widget_get_action_state (GtkWidget *widget,
+ const gchar *action_name)
+{
+ GActionGroup *group;
+ gchar *prefix = NULL;
+ gchar *name = NULL;
+ GVariant *ret = NULL;
+
+ split_action_name (action_name, &prefix, &name);
+ if (name == NULL || prefix == NULL)
+ goto cleanup;
+
+ group = find_group_with_action (widget, prefix, name);
+ if (group == NULL)
+ goto cleanup;
+
+ ret = g_action_group_get_action_state (group, name);
+
+cleanup:
+ g_free (name);
+ g_free (prefix);
+
+ return ret;
+}
+
+GActionGroup *
+pnl_gtk_widget_find_group_for_action (GtkWidget *widget,
+ const gchar *action_name)
+{
+ GActionGroup *group;
+ gchar *prefix = NULL;
+ gchar *name = NULL;
- border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
+ g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
- allocation->x += border_width;
- allocation->y += border_width;
- allocation->width -= border_width * 2;
- allocation->height -= border_width * 2;
+ if (action_name == NULL)
+ return NULL;
- gtk_widget_size_allocate (child, allocation);
+ split_action_name (action_name, &prefix, &name);
+ if (name == NULL || prefix == NULL)
+ goto cleanup;
+
+ group = find_group_with_action (widget, prefix, name);
+
+cleanup:
+ g_free (name);
+ g_free (prefix);
+
+ return group;
+}
+
+void
+pnl_g_action_name_parse (const gchar *action_name,
+ gchar **prefix,
+ gchar **name)
+{
+ split_action_name (action_name, prefix, name);
+}
+
+void
+pnl_gtk_allocation_subtract_border (GtkAllocation *alloc,
+ GtkBorder *border)
+{
+ g_return_if_fail (alloc != NULL);
+ g_return_if_fail (border != NULL);
+
+ alloc->x += border->left;
+ alloc->y += border->top;
+ alloc->width -= (border->left + border->right);
+ alloc->height -= (border->top + border->bottom);
+}
+
+void
+pnl_gtk_widget_add_class (GtkWidget *widget,
+ const gchar *class_name)
+{
+ gtk_style_context_add_class (gtk_widget_get_style_context (widget), class_name);
}
diff --git a/contrib/pnl/pnl-version.h.in b/contrib/pnl/pnl-version.h.in
index 54a637b..a11acaa 100644
--- a/contrib/pnl/pnl-version.h.in
+++ b/contrib/pnl/pnl-version.h.in
@@ -24,7 +24,7 @@
#endif
/**
- * SECTION:pnlversion
+ * SECTION:pnl-version
* @short_description: pnl version checking
*
* pnl provides macros to check the version of the library
diff --git a/contrib/pnl/pnl.h b/contrib/pnl/pnl.h
index 500e654..87867e2 100644
--- a/contrib/pnl/pnl.h
+++ b/contrib/pnl/pnl.h
@@ -28,24 +28,24 @@ G_BEGIN_DECLS
#include "pnl-dock.h"
#include "pnl-dock-bin.h"
#include "pnl-dock-bin-edge.h"
-#include "pnl-dock-item.h"
-#include "pnl-dock-manager.h"
#include "pnl-dock-overlay.h"
#include "pnl-dock-overlay-edge.h"
+#include "pnl-dock-item.h"
+#include "pnl-dock-manager.h"
#include "pnl-dock-paned.h"
#include "pnl-dock-revealer.h"
#include "pnl-dock-stack.h"
-#include "pnl-dock-tab-strip.h"
#include "pnl-dock-types.h"
#include "pnl-dock-widget.h"
#include "pnl-dock-window.h"
-#include "pnl-version.h"
-
+#include "pnl-bin.h"
#include "pnl-tab.h"
#include "pnl-tab-strip.h"
#include "pnl-multi-paned.h"
+#include "pnl-version.h"
+
#undef PNL_INSIDE
G_END_DECLS
diff --git a/data/theme/Adwaita-panels.css b/data/theme/Adwaita-panels.css
index 34d6907..d630d65 100644
--- a/data/theme/Adwaita-panels.css
+++ b/data/theme/Adwaita-panels.css
@@ -1,50 +1,80 @@
-dockbin {
- border: 1px solid alpha(@borders, 0.75);
- -PnlDockBin-handle-size: 1;
+pnldockbinedge {
+ background-color: @content_view_bg;
+ border-color: @borders;
+ border-style: solid;
}
-dockpaned {
- border: 1px solid @borders;
+pnldockbinedge.right {
+ border-left-width: 1px;
}
-docktabstrip {
- padding: 0 6px 0 6px;
+pnldockbinedge.left {
+ border-right-width: 1px;
}
-docktab {
- background-image: none;
- background-color: transparent;
- border-color: transparent;
- border-style: solid;
- color: @theme_fg_color;
- min-height: 39px;
- outline-offset: -6px;
- transition-duration: 200ms;
- transition-timing-function: ease;
+pnldockbinedge.bottom {
+ border-top-width: 1px;
+}
+
+pnldockpaned .handle {
+ border: 1px solid @borders;
}
-docktab > label {
- font-size: 0.9em;
+pnldockstack pnltabstrip {
+ padding-top: 2px;
+ background-color: @content_view_bg;
+ color: @theme_fg_color;
+ border-bottom: 1px solid mix(@theme_bg_color, @borders, 0.25);
}
-docktab > * {
- padding: 0 6px 0 6px;
+pnldockstack pnltabstrip button.control,
+pnldockstack pnltabstrip pnltab {
+ background: transparent;
+ box-shadow: none;
+ border: none;
+ padding: 0;
+ margin: 0;
+
+ border-bottom: 3px;
+ border-bottom-style: solid;
+ border-bottom-color: transparent;
+
+ margin-left: 6px;
+ margin-right: 6px;
+
+ color: @theme_fg_color;
}
-dockoverlayedge {
- background-color: @theme_bg_color;
+pnldockstack pnltabstrip button.control,
+pnldockstack pnltabstrip pnltab button,
+pnldockstack pnltabstrip pnltab {
+ transition-duration: 200ms;
}
-dockoverlayedge docktabstrip {
+pnldockstack pnltabstrip pnltab button {
padding: 0;
+ margin: 0;
border: none;
+ background: none;
+ box-shadow: none;
}
-dockoverlayedge.left-edge docktab:checked {
- border-right-color: @theme_selected_bg_color;
- border-bottom-color: transparent;
+pnldockstack pnltabstrip pnltab:active {
+ border-bottom-color: @theme_selected_bg_color;
}
-dockoverlayedge.right-edge docktab:checked {
- border-left-color: @theme_selected_bg_color;
- border-bottom-color: transparent;
+
+pnldockstack pnltabstrip button.control:last-child {
+ margin-right: 16px;
+}
+
+pnldockstack pnltabstrip button.control:hover,
+pnldockstack pnltabstrip pnltab:hover {
+ border-bottom-color: mix(@borders, @theme_bg_color, 0.25);
+}
+
+pnldockstack pnltabstrip button.control:hover:checked,
+pnldockstack pnltabstrip button.control:checked,
+pnldockstack pnltabstrip pnltab:hover:checked,
+pnldockstack pnltabstrip pnltab:checked {
+ border-bottom-color: @theme_selected_bg_color;
}
diff --git a/data/theme/Adwaita.css b/data/theme/Adwaita.css
index 8b62802..168333c 100644
--- a/data/theme/Adwaita.css
+++ b/data/theme/Adwaita.css
@@ -34,19 +34,6 @@ layouttab:backdrop {
}
-docktabstrip {
- background-color: #d6d6d6;
- box-shadow: 0 4px 3px -5px #aaa inset,
- 0 -1px 0 #a1a1a1 inset;
-}
-docktabstrip:backdrop {
- box-shadow: 0 -1px 0 #a1a1a1 inset;
-}
-docktabstrip docktab:checked {
- box-shadow: 0 -2px 0 #4a90d9 inset;
-}
-
-
entry.search-missing {
border-color: #aa0000;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]