Add AgHeaderBar class

It extends GtkHeaderBar, adding Astrognome specific buttons.
This commit is contained in:
Gergely Polonkai 2014-10-06 01:32:41 +02:00
parent f88d43972a
commit 449775aa43
5 changed files with 475 additions and 1 deletions

View File

@ -1,7 +1,7 @@
RESOURCE_DIR = $(srcdir)/resources RESOURCE_DIR = $(srcdir)/resources
resource_files = $(shell glib-compile-resources --sourcedir=$(RESOURCE_DIR) --generate-dependencies $(srcdir)/ag.gresource.xml) 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) ag-resources.c: ag.gresource.xml $(resource_files)
glib-compile-resources --target=$@ --sourcedir=$(RESOURCE_DIR) --generate-source --c-name ag $(srcdir)/ag.gresource.xml 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-icon-view.c \
ag-chart-renderer.c \ ag-chart-renderer.c \
ag-chart-edit.c \ ag-chart-edit.c \
ag-header-bar.c \
astrognome.c \ astrognome.c \
$(NULL) $(NULL)

267
src/ag-header-bar.c Normal file
View File

@ -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);
}

54
src/ag-header-bar.h Normal file
View File

@ -0,0 +1,54 @@
#ifndef __AG_HEADER_BAR_H__
#define __AG_HEADER_BAR_H__
#include <gtk/gtk.h>
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__ */

View File

@ -5,6 +5,7 @@
<file>ui/ag-window.ui</file> <file>ui/ag-window.ui</file>
<file>ui/ag-preferences.ui</file> <file>ui/ag-preferences.ui</file>
<file>ui/ag-chart-edit.ui</file> <file>ui/ag-chart-edit.ui</file>
<file>ui/ag-header-bar.ui</file>
<file>ui/chart-default.css</file> <file>ui/chart-default.css</file>
<file>ui/chart-default.xsl</file> <file>ui/chart-default.xsl</file>

View File

@ -0,0 +1,151 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk+" version="3.0"/>
<template class="AgHeaderBar" parent="GtkHeaderBar">
<property name="visible">True</property>
<property name="show_close_button">True</property>
<property name="title" translatable="yes">Astrognome</property>
<property name="vexpand">False</property>
<child>
<object class="GtkStack" id="left_stack">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<child>
<object class="GtkGrid">
<property name="visible">True</property>
<child>
<object class="GtkButton" id="new_button">
<property name="visible">True</property>
<property name="action_name">win.new-chart</property>
<style>
<class name="image-button"/>
</style>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="icon_name">document-new-symbolic</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkButton" id="refresh_button">
<property name="visible">True</property>
<property name="action_name">win.refresh</property>
<style>
<class name="image-button"/>
</style>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="icon_name">view-refresh-symbolic</property>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="name">list</property>
</packing>
</child><!-- list mode left side buttons -->
<child>
<object class="GtkGrid">
<property name="visible">True</property>
<child>
<object class="GtkButton" id="back_button">
<property name="visible">True</property>
<property name="action_name">win.back</property>
<style>
<class name="image-button"/>
</style>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="icon_name">go-previous-symbolic</property>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="name">chart</property>
</packing>
</child><!-- chart mode left side buttons -->
</object>
</child>
<child>
<object class="GtkStack" id="right_stack">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<child>
<object class="GtkButton">
<property name="visible">True</property>
<signal name="clicked" handler="ag_header_bar_selection_mode_cb" object="AgHeaderBar" swapped="no"/>
<style>
<class name="image-button"/>
</style>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="icon_name">object-select-symbolic</property>
</object>
</child>
</object>
<packing>
<property name="name">list</property>
</packing>
</child><!-- list mode right side buttons -->
<child>
<object class="GtkButton" id="selection_cancel_button">
<property name="visible">True</property>
<property name="label" translatable="yes">Cancel</property>
<signal name="clicked" handler="ag_header_bar_selection_mode_cb" object="AgHeaderBar" swapped="no"/>
</object>
<packing>
<property name="name">selection</property>
</packing>
</child><!-- selection mode right side buttons -->
<child>
<object class="GtkGrid">
<property name="visible">True</property>
<child>
<object class="GtkMenuButton" id="view_menu">
<property name="action_name">win.view-menu</property>
<style>
<class name="image-button"/>
</style>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="icon_name">document-properties-symbolic</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkMenuButton" id="gear_menu">
<property name="visible">True</property>
<property name="action_name">win.gear-menu</property>
<style>
<class name="image-button"/>
</style>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="icon_name">open-menu-symbolic</property>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="name">chart</property>
</packing>
</child><!-- chart mode right side buttons -->
</object>
<packing>
<property name="pack_type">end</property>
</packing>
</child>
</template>
</interface>