summaryrefslogtreecommitdiffstats
path: root/shell/cc-panel.c
diff options
context:
space:
mode:
Diffstat (limited to 'shell/cc-panel.c')
-rw-r--r--shell/cc-panel.c433
1 files changed, 433 insertions, 0 deletions
diff --git a/shell/cc-panel.c b/shell/cc-panel.c
new file mode 100644
index 0000000..cd3e0a8
--- /dev/null
+++ b/shell/cc-panel.c
@@ -0,0 +1,433 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2010 Red Hat, Inc.
+ * Copyright (C) 2010 Intel, Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: William Jon McCann <jmccann@redhat.com>
+ * Thomas Wood <thomas.wood@intel.com>
+ *
+ */
+
+/**
+ * SECTION:cc-panel
+ * @short_description: An abstract class for Control Center panels
+ *
+ * CcPanel is an abstract class used to implement panels for the shell. A
+ * panel contains a collection of related settings that are displayed within
+ * the shell window.
+ *
+ * # Buildable
+ *
+ * CcPanel implements the GtkBuildable interface, and allows having different
+ * types of children for convenience.
+ *
+ * It is possible to add widgets to the start and end of the panel titlebar
+ * using, respectively, the `titlebar-start` and `titlebar-end` child types.
+ * It is also possible to override the titlebar entirely with a custom titlebar
+ * using the `titlebar` child type.
+ *
+ * Most panels will use the `content` child type, which sets the panel content
+ * beneath the titlebar.
+ *
+ * At last, it is possible to override all custom CcPanel widgets by not setting
+ * any child type.
+ */
+
+#include "config.h"
+
+#include "cc-panel-private.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <gtk/gtk.h>
+#include <gio/gio.h>
+
+typedef struct
+{
+ AdwBin *content_bin;
+ GtkBox *main_box;
+ AdwBin *titlebar_bin;
+ AdwHeaderBar *titlebar;
+
+ CcShell *shell;
+ GCancellable *cancellable;
+ gboolean folded;
+ gchar *title;
+} CcPanelPrivate;
+
+static void cc_panel_buildable_init (GtkBuildableIface *iface);
+
+G_DEFINE_ABSTRACT_TYPE_WITH_CODE (CcPanel, cc_panel, ADW_TYPE_BIN,
+ G_ADD_PRIVATE (CcPanel)
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, cc_panel_buildable_init))
+
+static GtkBuildableIface *parent_buildable_iface;
+
+enum
+{
+ SIDEBAR_ACTIVATED,
+ LAST_SIGNAL
+};
+
+enum
+{
+ PROP_0,
+ PROP_SHELL,
+ PROP_PARAMETERS,
+ PROP_FOLDED,
+ PROP_TITLE,
+ N_PROPS
+};
+
+static GParamSpec *properties [N_PROPS];
+
+static guint signals [LAST_SIGNAL] = { 0 };
+
+/* GtkBuildable interface */
+
+static void
+cc_panel_buildable_add_child (GtkBuildable *buildable,
+ GtkBuilder *builder,
+ GObject *child,
+ const char *type)
+{
+ CcPanelPrivate *priv = cc_panel_get_instance_private (CC_PANEL (buildable));
+
+ if (GTK_IS_WIDGET (child) && !priv->main_box)
+ {
+ adw_bin_set_child (ADW_BIN (buildable), GTK_WIDGET (child));
+ return;
+ }
+
+ if (g_strcmp0 (type, "content") == 0)
+ adw_bin_set_child (priv->content_bin, GTK_WIDGET (child));
+ else if (g_strcmp0 (type, "titlebar-start") == 0)
+ adw_header_bar_pack_start (priv->titlebar, GTK_WIDGET (child));
+ else if (g_strcmp0 (type, "titlebar-end") == 0)
+ adw_header_bar_pack_end (priv->titlebar, GTK_WIDGET (child));
+ else if (g_strcmp0 (type, "titlebar") == 0)
+ adw_bin_set_child (priv->titlebar_bin, GTK_WIDGET (child));
+ else
+ parent_buildable_iface->add_child (buildable, builder, child, type);
+}
+
+static void
+cc_panel_buildable_init (GtkBuildableIface *iface)
+{
+ parent_buildable_iface = g_type_interface_peek_parent (iface);
+
+ iface->add_child = cc_panel_buildable_add_child;
+}
+
+/* GObject overrides */
+
+static void
+cc_panel_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CcPanelPrivate *priv = cc_panel_get_instance_private (CC_PANEL (object));
+
+ switch (prop_id)
+ {
+ case PROP_SHELL:
+ /* construct only property */
+ priv->shell = g_value_get_object (value);
+ break;
+
+ case PROP_PARAMETERS:
+ {
+ g_autoptr(GVariant) v = NULL;
+ GVariant *parameters;
+ gsize n_parameters;
+
+ parameters = g_value_get_variant (value);
+
+ if (parameters == NULL)
+ return;
+
+ n_parameters = g_variant_n_children (parameters);
+ if (n_parameters == 0)
+ return;
+
+ g_variant_get_child (parameters, 0, "v", &v);
+
+ if (!g_variant_is_of_type (v, G_VARIANT_TYPE_DICTIONARY))
+ g_warning ("Wrong type for the first argument GVariant, expected 'a{sv}' but got '%s'",
+ (gchar *)g_variant_get_type (v));
+ else if (g_variant_n_children (v) > 0)
+ g_warning ("Ignoring additional flags");
+
+ if (n_parameters > 1)
+ g_warning ("Ignoring additional parameters");
+
+ break;
+ }
+
+ case PROP_TITLE:
+ priv->title = g_value_dup_string (value);
+ break;
+
+ case PROP_FOLDED:
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+cc_panel_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ CcPanelPrivate *priv = cc_panel_get_instance_private (CC_PANEL (object));
+
+ switch (prop_id)
+ {
+ case PROP_SHELL:
+ g_value_set_object (value, priv->shell);
+ break;
+
+ case PROP_FOLDED:
+ g_value_set_boolean (value, priv->folded);
+ break;
+
+ case PROP_TITLE:
+ g_value_set_string (value, priv->title);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+cc_panel_finalize (GObject *object)
+{
+ CcPanelPrivate *priv = cc_panel_get_instance_private (CC_PANEL (object));
+
+ g_cancellable_cancel (priv->cancellable);
+ g_clear_object (&priv->cancellable);
+
+ g_clear_pointer (&priv->title, g_free);
+
+ G_OBJECT_CLASS (cc_panel_parent_class)->finalize (object);
+}
+
+static void
+cc_panel_class_init (CcPanelClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->get_property = cc_panel_get_property;
+ object_class->set_property = cc_panel_set_property;
+ object_class->finalize = cc_panel_finalize;
+
+ signals[SIDEBAR_ACTIVATED] = g_signal_new ("sidebar-activated",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ properties[PROP_SHELL] = g_param_spec_object ("shell",
+ "Shell",
+ "Shell the Panel resides in",
+ CC_TYPE_SHELL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+ properties[PROP_FOLDED] = g_param_spec_boolean ("folded", NULL, NULL,
+ FALSE,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+ properties[PROP_PARAMETERS] = g_param_spec_variant ("parameters",
+ "Structured parameters",
+ "Additional parameters passed externally (ie. command line, D-Bus activation)",
+ G_VARIANT_TYPE ("av"),
+ NULL,
+ G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS);
+
+ properties[PROP_TITLE] = g_param_spec_string ("title", NULL, NULL, NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Settings/gtk/cc-panel.ui");
+
+ gtk_widget_class_bind_template_child_private (widget_class, CcPanel, content_bin);
+ gtk_widget_class_bind_template_child_private (widget_class, CcPanel, main_box);
+ gtk_widget_class_bind_template_child_private (widget_class, CcPanel, titlebar_bin);
+ gtk_widget_class_bind_template_child_private (widget_class, CcPanel, titlebar);
+}
+
+static void
+cc_panel_init (CcPanel *panel)
+{
+ gtk_widget_init_template (GTK_WIDGET (panel));
+}
+
+/**
+ * cc_panel_get_shell:
+ * @panel: A #CcPanel
+ *
+ * Get the shell that the panel resides in
+ *
+ * Returns: a #CcShell
+ */
+CcShell *
+cc_panel_get_shell (CcPanel *panel)
+{
+ CcPanelPrivate *priv;
+
+ g_return_val_if_fail (CC_IS_PANEL (panel), NULL);
+
+ priv = cc_panel_get_instance_private (panel);
+
+ return priv->shell;
+}
+
+const gchar*
+cc_panel_get_help_uri (CcPanel *panel)
+{
+ CcPanelClass *class = CC_PANEL_GET_CLASS (panel);
+
+ if (class->get_help_uri)
+ return class->get_help_uri (panel);
+
+ return NULL;
+}
+
+GtkWidget*
+cc_panel_get_sidebar_widget (CcPanel *panel)
+{
+ CcPanelClass *class = CC_PANEL_GET_CLASS (panel);
+
+ if (class->get_sidebar_widget)
+ {
+ GtkWidget *sidebar_widget;
+
+ sidebar_widget = class->get_sidebar_widget (panel);
+ g_assert (sidebar_widget != NULL);
+
+ return sidebar_widget;
+ }
+
+ return NULL;
+}
+
+GCancellable *
+cc_panel_get_cancellable (CcPanel *panel)
+{
+ CcPanelPrivate *priv = cc_panel_get_instance_private (panel);
+
+ g_return_val_if_fail (CC_IS_PANEL (panel), NULL);
+
+ if (priv->cancellable == NULL)
+ priv->cancellable = g_cancellable_new ();
+
+ return priv->cancellable;
+}
+
+void
+cc_panel_set_folded (CcPanel *panel,
+ gboolean folded)
+{
+ CcPanelPrivate *priv;
+
+ g_return_if_fail (CC_IS_PANEL (panel));
+
+ priv = cc_panel_get_instance_private (panel);
+
+ if (priv->folded != folded)
+ {
+ g_debug ("Panel %s folded: %s",
+ G_OBJECT_TYPE_NAME (panel),
+ folded ? "yes" : "no");
+
+ priv->folded = folded;
+ g_object_notify_by_pspec (G_OBJECT (panel), properties[PROP_FOLDED]);
+ }
+}
+
+gboolean
+cc_panel_get_folded (CcPanel *panel)
+{
+ CcPanelPrivate *priv;
+
+ g_return_val_if_fail (CC_IS_PANEL (panel), FALSE);
+
+ priv = cc_panel_get_instance_private (panel);
+ return priv->folded;
+}
+
+GtkWidget*
+cc_panel_get_content (CcPanel *panel)
+{
+ CcPanelPrivate *priv;
+
+ g_return_val_if_fail (CC_IS_PANEL (panel), NULL);
+
+ priv = cc_panel_get_instance_private (panel);
+ return adw_bin_get_child (priv->content_bin);
+}
+
+void
+cc_panel_set_content (CcPanel *panel,
+ GtkWidget *content)
+{
+ CcPanelPrivate *priv;
+
+ g_return_if_fail (CC_IS_PANEL (panel));
+
+ priv = cc_panel_get_instance_private (panel);
+ adw_bin_set_child (priv->content_bin, content);
+}
+
+GtkWidget*
+cc_panel_get_titlebar (CcPanel *panel)
+{
+ CcPanelPrivate *priv;
+
+ g_return_val_if_fail (CC_IS_PANEL (panel), NULL);
+
+ priv = cc_panel_get_instance_private (panel);
+ return adw_bin_get_child (priv->titlebar_bin);
+}
+
+void
+cc_panel_set_titlebar (CcPanel *panel,
+ GtkWidget *titlebar)
+{
+ CcPanelPrivate *priv;
+
+ g_return_if_fail (CC_IS_PANEL (panel));
+
+ priv = cc_panel_get_instance_private (panel);
+ adw_bin_set_child (priv->titlebar_bin, titlebar);
+}
+
+void
+cc_panel_deactivate (CcPanel *panel)
+{
+ CcPanelPrivate *priv = cc_panel_get_instance_private (panel);
+
+ g_cancellable_cancel (priv->cancellable);
+}