Refactor header bar mode changing

Fixes #101
This commit is contained in:
Gergely Polonkai 2014-10-14 00:22:29 +02:00
parent a9ab84d8b1
commit 7c01382e81
5 changed files with 149 additions and 107 deletions

View File

@ -17,6 +17,11 @@ enum {
PROP_COUNT PROP_COUNT
}; };
enum {
SIGNAL_MODE_CHANGED,
SIGNAL_COUNT
};
static void ag_header_bar_dispose(GObject *gobject); static void ag_header_bar_dispose(GObject *gobject);
static void ag_header_bar_finalize(GObject *gobject); static void ag_header_bar_finalize(GObject *gobject);
@ -25,6 +30,7 @@ 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); #define GET_PRIV(v, o) AgHeaderBarPrivate *v = ag_header_bar_get_instance_private(o);
static GParamSpec *properties[PROP_COUNT]; static GParamSpec *properties[PROP_COUNT];
static guint signals[SIGNAL_COUNT] = { 0 };
static void static void
ag_header_bar_selection_mode_cb(GtkButton *button, ag_header_bar_selection_mode_cb(GtkButton *button,
@ -32,22 +38,58 @@ ag_header_bar_selection_mode_cb(GtkButton *button,
{ {
GET_PRIV(priv, header_bar); GET_PRIV(priv, header_bar);
switch (priv->mode) { /* If we are not in list mode, this transition is invalid */
case AG_HEADER_BAR_MODE_LIST: if (priv->mode != 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!"); g_warning("Invalid header bar mode transition!");
break; return;
} }
g_signal_emit(
header_bar,
signals[SIGNAL_MODE_CHANGED], 0,
AG_HEADER_BAR_MODE_SELECTION
);
}
static void
ag_header_bar_selection_cancel_cb(GtkButton *button,
AgHeaderBar *header_bar)
{
GET_PRIV(priv, header_bar);
/* If we are not in selection mode, this transition is invalid */
if (priv->mode != AG_HEADER_BAR_MODE_SELECTION) {
g_warning("Invalid header bar mode transition!");
return;
}
g_signal_emit(
header_bar,
signals[SIGNAL_MODE_CHANGED], 0,
AG_HEADER_BAR_MODE_LIST
);
}
static void
ag_header_bar_back_cb(GtkButton *button,
AgHeaderBar *header_bar)
{
GET_PRIV(priv, header_bar);
/* If we are not in chart mode, this transition is invalid */
if (priv->mode != AG_HEADER_BAR_MODE_CHART) {
g_warning("Invalid header bar mode transition!");
return;
}
g_signal_emit(
header_bar,
signals[SIGNAL_MODE_CHANGED], 0,
AG_HEADER_BAR_MODE_LIST
);
} }
static void static void
@ -56,6 +98,10 @@ ag_header_bar_set_selection_mode(AgHeaderBar *header_bar, gboolean state)
GtkStyleContext *style; GtkStyleContext *style;
GET_PRIV(priv, header_bar); GET_PRIV(priv, header_bar);
if (state == (priv->mode == AG_HEADER_BAR_MODE_SELECTION)) {
return;
}
style = gtk_widget_get_style_context(GTK_WIDGET(header_bar)); style = gtk_widget_get_style_context(GTK_WIDGET(header_bar));
if (state) { if (state) {
@ -83,13 +129,15 @@ ag_header_bar_set_mode_internal(AgHeaderBar *header_bar,
AgHeaderBarMode mode, AgHeaderBarMode mode,
gboolean force) gboolean force)
{ {
gboolean invalid = FALSE;
AgHeaderBarMode old_mode;
GET_PRIV(priv, header_bar); GET_PRIV(priv, header_bar);
if (!force && (priv->mode == mode)) { if (!force && (priv->mode == mode)) {
return; return;
} }
priv->mode = mode; old_mode = priv->mode;
switch (mode) { switch (mode) {
case AG_HEADER_BAR_MODE_LIST: case AG_HEADER_BAR_MODE_LIST:
@ -124,13 +172,19 @@ ag_header_bar_set_mode_internal(AgHeaderBar *header_bar,
break; break;
default: default:
invalid = TRUE;
g_warning("Invalid header bar mode!"); g_warning("Invalid header bar mode!");
break; break;
} }
if (invalid) {
priv->mode = old_mode;
} else {
priv->mode = mode;
g_object_notify_by_pspec(G_OBJECT(header_bar), properties[PROP_MODE]); g_object_notify_by_pspec(G_OBJECT(header_bar), properties[PROP_MODE]);
} }
}
void void
ag_header_bar_set_mode(AgHeaderBar *header_bar, ag_header_bar_set_mode(AgHeaderBar *header_bar,
@ -229,6 +283,18 @@ ag_header_bar_class_init(AgHeaderBarClass *klass)
properties[PROP_MODE] properties[PROP_MODE]
); );
signals[SIGNAL_MODE_CHANGED] = g_signal_new(
"mode-changed",
AG_TYPE_HEADER_BAR,
G_SIGNAL_RUN_FIRST,
0,
NULL, NULL,
NULL,
G_TYPE_NONE,
1,
AG_TYPE_HEADER_BAR_MODE
);
gtk_widget_class_set_template_from_resource( gtk_widget_class_set_template_from_resource(
widget_class, widget_class,
"/eu/polonkai/gergely/Astrognome/ui/ag-header-bar.ui" "/eu/polonkai/gergely/Astrognome/ui/ag-header-bar.ui"
@ -254,6 +320,14 @@ ag_header_bar_class_init(AgHeaderBarClass *klass)
widget_class, widget_class,
ag_header_bar_selection_mode_cb ag_header_bar_selection_mode_cb
); );
gtk_widget_class_bind_template_callback(
widget_class,
ag_header_bar_selection_cancel_cb
);
gtk_widget_class_bind_template_callback(
widget_class,
ag_header_bar_back_cb
);
} }
static void static void

View File

@ -36,7 +36,10 @@ ag_icon_view_set_mode(AgIconView *icon_view, AgIconViewMode mode)
{ {
AgIconViewPrivate *priv = ag_icon_view_get_instance_private(icon_view); AgIconViewPrivate *priv = ag_icon_view_get_instance_private(icon_view);
if (priv->mode != mode) { if (priv->mode == mode) {
return;
}
priv->mode = mode; priv->mode = mode;
if (mode != AG_ICON_VIEW_MODE_SELECTION) { if (mode != AG_ICON_VIEW_MODE_SELECTION) {
@ -55,7 +58,6 @@ ag_icon_view_set_mode(AgIconView *icon_view, AgIconViewMode mode)
properties[PROP_MODE] properties[PROP_MODE]
); );
} }
}
AgIconViewMode AgIconViewMode
ag_icon_view_get_mode(AgIconView *icon_view) ag_icon_view_get_mode(AgIconView *icon_view)

View File

@ -1299,20 +1299,19 @@ ag_window_set_theme(AgWindow *window, AgDisplayTheme *theme)
static void static void
ag_window_tab_changed_cb(GtkStack *tabs, GParamSpec *pspec, AgWindow *window) ag_window_tab_changed_cb(GtkStack *tabs, GParamSpec *pspec, AgWindow *window)
{ {
GtkWidget *active_tab;
const gchar *active_tab_name = gtk_stack_get_visible_child_name(tabs);
GET_PRIV(window); GET_PRIV(window);
GtkWidget *old_tab = priv->current_tab;
GtkWidget *new_tab = gtk_stack_get_visible_child(tabs);
const gchar *active_tab_name = gtk_stack_get_visible_child_name(tabs);
g_debug("Active tab changed: %s", active_tab_name); if (old_tab == new_tab) {
if (active_tab_name == NULL) {
return; return;
} }
active_tab = gtk_stack_get_visible_child(tabs); g_debug("Active tab changed: %s", active_tab_name);
if (strcmp("chart", active_tab_name) == 0) { if (strcmp("chart", active_tab_name) == 0) {
gtk_widget_set_size_request(active_tab, 600, 600); gtk_widget_set_size_request(new_tab, 600, 600);
if (priv->theme == NULL) { if (priv->theme == NULL) {
AgSettings *settings; AgSettings *settings;
GSettings *main_settings; GSettings *main_settings;
@ -1335,6 +1334,8 @@ ag_window_tab_changed_cb(GtkStack *tabs, GParamSpec *pspec, AgWindow *window)
if (strcmp("list", active_tab_name) == 0) { if (strcmp("list", active_tab_name) == 0) {
ag_header_bar_set_mode(priv->header_bar, AG_HEADER_BAR_MODE_LIST); ag_header_bar_set_mode(priv->header_bar, AG_HEADER_BAR_MODE_LIST);
} else { } else {
g_debug("Switching header bar to chart mode");
ag_header_bar_set_mode(priv->header_bar, AG_HEADER_BAR_MODE_CHART); ag_header_bar_set_mode(priv->header_bar, AG_HEADER_BAR_MODE_CHART);
// Note that priv->current_tab is actually the previously selected tab, // Note that priv->current_tab is actually the previously selected tab,
@ -1345,7 +1346,7 @@ ag_window_tab_changed_cb(GtkStack *tabs, GParamSpec *pspec, AgWindow *window)
} }
} }
priv->current_tab = active_tab; priv->current_tab = new_tab;
} }
static void static void
@ -1492,46 +1493,29 @@ ag_window_refresh_action(GSimpleAction *action,
} }
static void static void
ag_window_set_selection_mode(AgWindow *window, gboolean state) ag_window_header_bar_mode_change_cb(AgHeaderBar *header_bar,
AgHeaderBarMode mode,
AgWindow *window)
{ {
GET_PRIV(window); GET_PRIV(window);
if (priv->current_tab != priv->tab_list) { switch (mode) {
g_warning("You can activate selection mode only in the list view!"); case AG_HEADER_BAR_MODE_LIST:
ag_window_change_tab(window, "list");
ag_header_bar_set_mode(header_bar, mode);
ag_icon_view_set_mode(priv->chart_list, AG_ICON_VIEW_MODE_NORMAL);
return; break;
case AG_HEADER_BAR_MODE_SELECTION:
ag_header_bar_set_mode(header_bar, mode);
ag_icon_view_set_mode(priv->chart_list, AG_ICON_VIEW_MODE_SELECTION);
break;
default:
break;
} }
g_debug("Set selection mode: %d", state);
if (state) {
ag_header_bar_set_mode(priv->header_bar, AG_HEADER_BAR_MODE_SELECTION);
ag_icon_view_set_mode(
priv->chart_list,
AG_ICON_VIEW_MODE_SELECTION
);
} else {
ag_header_bar_set_mode(priv->header_bar, AG_HEADER_BAR_MODE_LIST);
ag_icon_view_set_mode(
priv->chart_list,
AG_ICON_VIEW_MODE_NORMAL
);
}
}
static void
ag_window_header_bar_mode_change_cb(AgHeaderBar *header_bar,
GParamSpec *pspec,
AgWindow *window)
{
AgHeaderBarMode mode;
mode = ag_header_bar_get_mode(header_bar);
ag_window_set_selection_mode(
window,
(mode == AG_HEADER_BAR_MODE_SELECTION)
);
} }
static void static void
@ -1543,29 +1527,21 @@ ag_window_icon_view_mode_cb(AgIconView *icon_view,
GVariant *state_var = g_variant_new_boolean( GVariant *state_var = g_variant_new_boolean(
(mode == AG_ICON_VIEW_MODE_SELECTION) (mode == AG_ICON_VIEW_MODE_SELECTION)
); );
GET_PRIV(window);
g_debug("IV mode change: %d", (mode == AG_ICON_VIEW_MODE_SELECTION));
g_action_group_activate_action( g_action_group_activate_action(
G_ACTION_GROUP(window), G_ACTION_GROUP(window),
"selection", "selection",
state_var state_var
); );
} ag_header_bar_set_mode(
priv->header_bar,
static void (mode == AG_ICON_VIEW_MODE_SELECTION)
ag_window_selection_mode_action(GSimpleAction *action, ? AG_HEADER_BAR_MODE_SELECTION
GVariant *parameter, : AG_HEADER_BAR_MODE_LIST
gpointer user_data) );
{
GVariant *state;
gboolean new_state;
AgWindow *window = AG_WINDOW(user_data);
state = g_action_get_state(G_ACTION(action));
new_state = !g_variant_get_boolean(state);
g_action_change_state(G_ACTION(action), g_variant_new_boolean(new_state));
g_variant_unref(state);
ag_window_set_selection_mode(window, new_state);
} }
static void static void
@ -1680,7 +1656,6 @@ static GActionEntry win_entries[] = {
{ "new-chart", ag_window_new_chart_action, NULL, NULL, NULL }, { "new-chart", ag_window_new_chart_action, NULL, NULL, NULL },
{ "back", ag_window_back_action, NULL, NULL, NULL }, { "back", ag_window_back_action, NULL, NULL, NULL },
{ "refresh", ag_window_refresh_action, NULL, NULL, NULL }, { "refresh", ag_window_refresh_action, NULL, NULL, NULL },
{ "selection", ag_window_selection_mode_action, "b", "false", NULL },
{ "delete", ag_window_delete_action, NULL, NULL, NULL }, { "delete", ag_window_delete_action, NULL, NULL, NULL },
{ "connection", ag_window_connection_action, "s", "'aspects'", NULL }, { "connection", ag_window_connection_action, "s", "'aspects'", NULL },
}; };
@ -2012,12 +1987,6 @@ ag_window_destroy(GtkWidget *widget)
GTK_WIDGET_CLASS(ag_window_parent_class)->destroy(widget); GTK_WIDGET_CLASS(ag_window_parent_class)->destroy(widget);
} }
static void
ag_window_selection_mode_cancel_cb(GtkButton *button, AgWindow *window)
{
ag_window_set_selection_mode(window, FALSE);
}
static void static void
ag_window_set_property(GObject *gobject, ag_window_set_property(GObject *gobject,
guint prop_id, guint prop_id,
@ -2207,10 +2176,6 @@ ag_window_class_init(AgWindowClass *klass)
widget_class, widget_class,
ag_window_icon_view_mode_cb ag_window_icon_view_mode_cb
); );
gtk_widget_class_bind_template_callback(
widget_class,
ag_window_selection_mode_cancel_cb
);
gtk_widget_class_bind_template_callback( gtk_widget_class_bind_template_callback(
widget_class, widget_class,
ag_window_house_system_changed_cb ag_window_house_system_changed_cb

View File

@ -55,6 +55,7 @@
<object class="GtkButton" id="back_button"> <object class="GtkButton" id="back_button">
<property name="visible">True</property> <property name="visible">True</property>
<property name="action_name">win.back</property> <property name="action_name">win.back</property>
<signal name="clicked" handler="ag_header_bar_back_cb" swapped="no" object="AgHeaderBar"/>
<style> <style>
<class name="image-button"/> <class name="image-button"/>
</style> </style>
@ -99,7 +100,7 @@
<object class="GtkButton" id="selection_cancel_button"> <object class="GtkButton" id="selection_cancel_button">
<property name="visible">True</property> <property name="visible">True</property>
<property name="label" translatable="yes">Cancel</property> <property name="label" translatable="yes">Cancel</property>
<signal name="clicked" handler="ag_header_bar_selection_mode_cb" object="AgHeaderBar" swapped="no"/> <signal name="clicked" handler="ag_header_bar_selection_cancel_cb" object="AgHeaderBar" swapped="no"/>
</object> </object>
<packing> <packing>
<property name="name">selection</property> <property name="name">selection</property>

View File

@ -83,7 +83,7 @@
<signal name="delete-event" handler="ag_window_delete_event_callback" swapped="no"/> <signal name="delete-event" handler="ag_window_delete_event_callback" swapped="no"/>
<child type="titlebar"> <child type="titlebar">
<object class="AgHeaderBar" id="header_bar"> <object class="AgHeaderBar" id="header_bar">
<signal name="notify::mode" handler="ag_window_header_bar_mode_change_cb" swapped="no"/> <signal name="mode-changed" handler="ag_window_header_bar_mode_change_cb" swapped="no"/>
</object> </object>
</child> </child>
<child> <child>