From 449775aa430a42a6c68df260046d9110c8bda580 Mon Sep 17 00:00:00 2001 From: Gergely Polonkai Date: Mon, 6 Oct 2014 01:32:41 +0200 Subject: [PATCH] Add AgHeaderBar class It extends GtkHeaderBar, adding Astrognome specific buttons. --- src/Makefile.am | 3 +- src/ag-header-bar.c | 267 ++++++++++++++++++++++++++++++ src/ag-header-bar.h | 54 ++++++ src/ag.gresource.xml | 1 + src/resources/ui/ag-header-bar.ui | 151 +++++++++++++++++ 5 files changed, 475 insertions(+), 1 deletion(-) create mode 100644 src/ag-header-bar.c create mode 100644 src/ag-header-bar.h create mode 100644 src/resources/ui/ag-header-bar.ui diff --git a/src/Makefile.am b/src/Makefile.am index b194dd5..ba37b0b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,7 +1,7 @@ RESOURCE_DIR = $(srcdir)/resources resource_files = $(shell glib-compile-resources --sourcedir=$(RESOURCE_DIR) --generate-dependencies $(srcdir)/ag.gresource.xml) -ag_enum_headers = ag-icon-view.h +ag_enum_headers = ag-icon-view.h ag-header-bar.h ag-resources.c: ag.gresource.xml $(resource_files) glib-compile-resources --target=$@ --sourcedir=$(RESOURCE_DIR) --generate-source --c-name ag $(srcdir)/ag.gresource.xml @@ -35,6 +35,7 @@ astrognome_source_files = \ ag-icon-view.c \ ag-chart-renderer.c \ ag-chart-edit.c \ + ag-header-bar.c \ astrognome.c \ $(NULL) diff --git a/src/ag-header-bar.c b/src/ag-header-bar.c new file mode 100644 index 0000000..5807d13 --- /dev/null +++ b/src/ag-header-bar.c @@ -0,0 +1,267 @@ +#include "ag-header-bar.h" +#include "ag-enumtypes.h" + +#define DEFAULT_MODE AG_HEADER_BAR_MODE_LIST + +typedef struct { + GtkWidget *selection_cancel_button; + GtkWidget *left_stack; + GtkWidget *right_stack; + + AgHeaderBarMode mode; +} AgHeaderBarPrivate; + +enum { + PROP_0, + PROP_MODE, + PROP_COUNT +}; + +static void ag_header_bar_dispose(GObject *gobject); +static void ag_header_bar_finalize(GObject *gobject); + +G_DEFINE_TYPE_WITH_PRIVATE(AgHeaderBar, ag_header_bar, GTK_TYPE_HEADER_BAR); + +#define GET_PRIV(v, o) AgHeaderBarPrivate *v = ag_header_bar_get_instance_private(o); + +static GParamSpec *properties[PROP_COUNT]; + +static void +ag_header_bar_selection_mode_cb(GtkButton *button, + AgHeaderBar *header_bar) +{ + GET_PRIV(priv, header_bar); + + switch (priv->mode) { + case AG_HEADER_BAR_MODE_LIST: + ag_header_bar_set_mode(header_bar, AG_HEADER_BAR_MODE_SELECTION); + + break; + + case AG_HEADER_BAR_MODE_SELECTION: + ag_header_bar_set_mode(header_bar, AG_HEADER_BAR_MODE_LIST); + + break; + + default: + g_warning("Invalid header bar mode transition!"); + + break; + } +} + +static void +ag_header_bar_set_selection_mode(AgHeaderBar *header_bar, gboolean state) +{ + GtkStyleContext *style; + GET_PRIV(priv, header_bar); + + style = gtk_widget_get_style_context(GTK_WIDGET(header_bar)); + + if (state) { + // Enabling selection mode + gtk_stack_set_visible_child_name( + GTK_STACK(priv->right_stack), + "selection" + ); + gtk_widget_hide(priv->left_stack); + gtk_style_context_add_class(style, "selection-mode"); + } else { + // Disabling selection mode + gtk_widget_show(priv->left_stack); + gtk_style_context_remove_class(style, "selection-mode"); + } + + gtk_header_bar_set_show_close_button( + GTK_HEADER_BAR(header_bar), + !state + ); +} + +static void +ag_header_bar_set_mode_internal(AgHeaderBar *header_bar, + AgHeaderBarMode mode, + gboolean force) +{ + GET_PRIV(priv, header_bar); + + if (!force && (priv->mode == mode)) { + return; + } + + priv->mode = mode; + + switch (mode) { + case AG_HEADER_BAR_MODE_LIST: + gtk_stack_set_visible_child_name( + GTK_STACK(priv->left_stack), + "list" + ); + gtk_stack_set_visible_child_name( + GTK_STACK(priv->right_stack), + "list" + ); + ag_header_bar_set_selection_mode(header_bar, FALSE); + + break; + + case AG_HEADER_BAR_MODE_CHART: + gtk_stack_set_visible_child_name( + GTK_STACK(priv->left_stack), + "chart" + ); + gtk_stack_set_visible_child_name( + GTK_STACK(priv->right_stack), + "chart" + ); + ag_header_bar_set_selection_mode(header_bar, FALSE); + + break; + + case AG_HEADER_BAR_MODE_SELECTION: + ag_header_bar_set_selection_mode(header_bar, TRUE); + + break; + + default: + g_warning("Invalid header bar mode!"); + + break; + } + + g_object_notify_by_pspec(G_OBJECT(header_bar), properties[PROP_MODE]); +} + +void +ag_header_bar_set_mode(AgHeaderBar *header_bar, + AgHeaderBarMode mode) +{ + ag_header_bar_set_mode_internal(header_bar, mode, FALSE); +} + +AgHeaderBarMode +ag_header_bar_get_mode(AgHeaderBar *header_bar) +{ + GET_PRIV(priv, header_bar); + + return priv->mode; +} + +static void +ag_header_bar_set_property(GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (prop_id) { + case PROP_MODE: + ag_header_bar_set_mode( + AG_HEADER_BAR(gobject), + g_value_get_enum(value) + ); + + return; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, pspec); + + return; + } +} + +static void +ag_header_bar_get_property(GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GET_PRIV(priv, AG_HEADER_BAR(gobject)); + + switch (prop_id) { + case PROP_MODE: + g_value_set_enum(value, priv->mode); + + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, pspec); + + break; + } +} + +static void +ag_header_bar_dispose(GObject *gobject) +{ + G_OBJECT_CLASS(ag_header_bar_parent_class)->dispose(gobject); +} + +static void +ag_header_bar_finalize(GObject *gobject) +{ + g_signal_handlers_destroy(gobject); + G_OBJECT_CLASS(ag_header_bar_parent_class)->finalize(gobject); +} + +static void +ag_header_bar_class_init(AgHeaderBarClass *klass) +{ + GObjectClass *gobject_class = (GObjectClass *)klass; + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass); + + gobject_class->dispose = ag_header_bar_dispose; + gobject_class->finalize = ag_header_bar_finalize; + gobject_class->set_property = ag_header_bar_set_property; + gobject_class->get_property = ag_header_bar_get_property; + + properties[PROP_MODE] = g_param_spec_enum( + "mode", + "Mode", + "Header bar mode", + AG_TYPE_HEADER_BAR_MODE, + AG_HEADER_BAR_MODE_LIST, + G_PARAM_STATIC_STRINGS + | G_PARAM_READWRITE + ); + g_object_class_install_property( + gobject_class, + PROP_MODE, + properties[PROP_MODE] + ); + + gtk_widget_class_set_template_from_resource( + widget_class, + "/eu/polonkai/gergely/Astrognome/ui/ag-header-bar.ui" + ); + + gtk_widget_class_bind_template_child_private( + widget_class, + AgHeaderBar, + selection_cancel_button + ); + gtk_widget_class_bind_template_child_private( + widget_class, + AgHeaderBar, + left_stack + ); + gtk_widget_class_bind_template_child_private( + widget_class, + AgHeaderBar, + right_stack + ); + + gtk_widget_class_bind_template_callback( + widget_class, + ag_header_bar_selection_mode_cb + ); +} + +static void +ag_header_bar_init(AgHeaderBar *header_bar) +{ + GET_PRIV(priv, header_bar); + + gtk_widget_init_template(GTK_WIDGET(header_bar)); + + ag_header_bar_set_mode_internal(header_bar, DEFAULT_MODE, TRUE); +} diff --git a/src/ag-header-bar.h b/src/ag-header-bar.h new file mode 100644 index 0000000..7d0ed54 --- /dev/null +++ b/src/ag-header-bar.h @@ -0,0 +1,54 @@ +#ifndef __AG_HEADER_BAR_H__ +#define __AG_HEADER_BAR_H__ + +#include + +G_BEGIN_DECLS + +#define AG_TYPE_HEADER_BAR \ + (ag_header_bar_get_type()) +#define AG_HEADER_BAR(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), \ + AG_TYPE_HEADER_BAR, \ + AgHeaderBar)) +#define AG_HEADER_BAR_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), \ + AG_TYPE_HEADER_BAR, \ + AgHeaderBarClass)) +#define IS_AG_HEADER_BAR(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), \ + AG_TYPE_HEADER_BAR)) +#define IS_AG_HEADER_BAR_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), \ + AG_TYPE_HEADER_BAR)) +#define AG_HEADER_BAR_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), \ + AG_TYPE_HEADER_BAR, \ + AgHeaderBarClass)) + +typedef struct _AgHeaderBar AgHeaderBar; +typedef struct _AgHeaderBarClass AgHeaderBarClass; + +struct _AgHeaderBarClass { + GtkHeaderBarClass parent_class; +}; + +struct _AgHeaderBar{ + GtkHeaderBar parent; +}; + +typedef enum { + AG_HEADER_BAR_MODE_LIST, + AG_HEADER_BAR_MODE_CHART, + AG_HEADER_BAR_MODE_SELECTION +} AgHeaderBarMode; + +GType ag_header_bar_get_type(void) G_GNUC_CONST; + +void ag_header_bar_set_mode(AgHeaderBar *header_bar, AgHeaderBarMode mode); + +AgHeaderBarMode ag_header_bar_get_mode(AgHeaderBar *header_bar); + +G_END_DECLS + +#endif /* __AG_HEADER_BAR_H__ */ diff --git a/src/ag.gresource.xml b/src/ag.gresource.xml index e9aba42..2a795b4 100644 --- a/src/ag.gresource.xml +++ b/src/ag.gresource.xml @@ -5,6 +5,7 @@ ui/ag-window.ui ui/ag-preferences.ui ui/ag-chart-edit.ui + ui/ag-header-bar.ui ui/chart-default.css ui/chart-default.xsl diff --git a/src/resources/ui/ag-header-bar.ui b/src/resources/ui/ag-header-bar.ui new file mode 100644 index 0000000..dd9dc03 --- /dev/null +++ b/src/resources/ui/ag-header-bar.ui @@ -0,0 +1,151 @@ + + + + +