/* * Copyright (c) 2011 Red Hat, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser 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 Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Cosimo Cecchi * */ #include "gd-main-toolbar.h" #include #include G_DEFINE_TYPE (GdMainToolbar, gd_main_toolbar, GTK_TYPE_TOOLBAR) struct _GdMainToolbarPrivate { GtkSizeGroup *size_group; GtkSizeGroup *vertical_size_group; GtkToolItem *left_group; GtkToolItem *center_group; GtkToolItem *right_group; GtkWidget *left_grid; GtkWidget *back; GtkWidget *title_label; GtkWidget *detail_label; GtkWidget *right_grid; GdMainToolbarMode mode; }; enum { SELECTION_MODE_REQUEST = 1, GO_BACK_REQUEST, CLEAR_REQUEST, NUM_SIGNALS }; static guint signals[NUM_SIGNALS] = { 0, }; static void gd_main_toolbar_dispose (GObject *obj) { GdMainToolbar *self = GD_MAIN_TOOLBAR (obj); g_clear_object (&self->priv->size_group); g_clear_object (&self->priv->vertical_size_group); G_OBJECT_CLASS (gd_main_toolbar_parent_class)->dispose (obj); } static gint get_icon_margin (void) { gint toolbar_size, menu_size; gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &menu_size, NULL); gtk_icon_size_lookup (GTK_ICON_SIZE_LARGE_TOOLBAR, &toolbar_size, NULL); return (gint) floor ((toolbar_size - menu_size) / 2.0); } static GtkSizeGroup * get_vertical_size_group (void) { GtkSizeGroup *retval; GtkWidget *w, *dummy; gint icon_margin; icon_margin = get_icon_margin (); dummy = gtk_toggle_button_new (); w = gtk_image_new_from_stock (GTK_STOCK_OPEN, GTK_ICON_SIZE_MENU); g_object_set (w, "margin", icon_margin, NULL); gtk_container_add (GTK_CONTAINER (dummy), w); gtk_widget_show_all (dummy); retval = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL); gtk_size_group_add_widget (retval, dummy); return retval; } static GtkWidget * get_symbolic_button (const gchar *icon_name) { GtkWidget *button, *w; button = gtk_button_new (); gtk_style_context_add_class (gtk_widget_get_style_context (button), "raised"); w = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_MENU); g_object_set (w, "margin", get_icon_margin (), NULL); gtk_widget_show (w); gtk_container_add (GTK_CONTAINER (button), w); return button; } static GtkWidget * get_text_button (const gchar *label) { GtkWidget *w; w = gtk_button_new_with_label (label); gtk_widget_set_vexpand (w, TRUE); gtk_style_context_add_class (gtk_widget_get_style_context (w), "raised"); return w; } static void on_back_button_clicked (GtkButton *b, gpointer user_data) { GdMainToolbar *self = user_data; g_signal_emit (self, signals[GO_BACK_REQUEST], 0); } static void gd_main_toolbar_constructed (GObject *obj) { GdMainToolbar *self = GD_MAIN_TOOLBAR (obj); GtkToolbar *tb = GTK_TOOLBAR (obj); GtkWidget *grid; G_OBJECT_CLASS (gd_main_toolbar_parent_class)->constructed (obj); self->priv->vertical_size_group = get_vertical_size_group (); /* left section */ self->priv->left_group = gtk_tool_item_new (); gtk_widget_set_margin_right (GTK_WIDGET (self->priv->left_group), 12); gtk_toolbar_insert (tb, self->priv->left_group, -1); gtk_size_group_add_widget (self->priv->vertical_size_group, GTK_WIDGET (self->priv->left_group)); /* left button group */ self->priv->left_grid = gtk_grid_new (); gtk_grid_set_column_spacing (GTK_GRID (self->priv->left_grid), 12); gtk_container_add (GTK_CONTAINER (self->priv->left_group), self->priv->left_grid); self->priv->back = get_symbolic_button ("go-previous-symbolic"); gtk_widget_set_no_show_all (self->priv->back, TRUE); gtk_container_add (GTK_CONTAINER (self->priv->left_grid), self->priv->back); g_signal_connect (self->priv->back, "clicked", G_CALLBACK (on_back_button_clicked), self); /* center section */ self->priv->center_group = gtk_tool_item_new (); gtk_tool_item_set_expand (self->priv->center_group, TRUE); gtk_toolbar_insert (tb, self->priv->center_group, -1); gtk_size_group_add_widget (self->priv->vertical_size_group, GTK_WIDGET (self->priv->center_group)); /* centered label group */ grid = gtk_grid_new (); gtk_widget_set_halign (grid, GTK_ALIGN_CENTER); gtk_widget_set_valign (grid, GTK_ALIGN_CENTER); gtk_container_add (GTK_CONTAINER (self->priv->center_group), grid); self->priv->title_label = gtk_label_new (NULL); gtk_label_set_ellipsize (GTK_LABEL (self->priv->title_label), PANGO_ELLIPSIZE_END); gtk_container_add (GTK_CONTAINER (grid), self->priv->title_label); self->priv->detail_label = gtk_label_new (NULL); gtk_widget_set_no_show_all (self->priv->detail_label, TRUE); gtk_widget_set_margin_left (self->priv->detail_label, 12); gtk_style_context_add_class (gtk_widget_get_style_context (self->priv->detail_label), "dim-label"); gtk_container_add (GTK_CONTAINER (grid), self->priv->detail_label); /* right section */ self->priv->right_group = gtk_tool_item_new (); gtk_widget_set_margin_left (GTK_WIDGET (self->priv->right_group), 12); gtk_toolbar_insert (tb, self->priv->right_group, -1); gtk_size_group_add_widget (self->priv->vertical_size_group, GTK_WIDGET (self->priv->right_group)); self->priv->right_grid = gtk_grid_new (); gtk_grid_set_column_spacing (GTK_GRID (self->priv->right_grid), 12); gtk_container_add (GTK_CONTAINER (self->priv->right_group), self->priv->right_grid); self->priv->size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); gtk_size_group_add_widget (self->priv->size_group, GTK_WIDGET (self->priv->left_group)); gtk_size_group_add_widget (self->priv->size_group, GTK_WIDGET (self->priv->right_group)); } static void gd_main_toolbar_init (GdMainToolbar *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GD_TYPE_MAIN_TOOLBAR, GdMainToolbarPrivate); self->priv->mode = GD_MAIN_TOOLBAR_MODE_INVALID; } static void gd_main_toolbar_class_init (GdMainToolbarClass *klass) { GObjectClass *oclass; oclass = G_OBJECT_CLASS (klass); oclass->constructed = gd_main_toolbar_constructed; oclass->dispose = gd_main_toolbar_dispose; signals[SELECTION_MODE_REQUEST] = g_signal_new ("selection-mode-request", GD_TYPE_MAIN_TOOLBAR, G_SIGNAL_RUN_FIRST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_BOOLEAN); signals[GO_BACK_REQUEST] = g_signal_new ("go-back-request", GD_TYPE_MAIN_TOOLBAR, G_SIGNAL_RUN_FIRST, 0, NULL, NULL, NULL, G_TYPE_NONE, 0); signals[CLEAR_REQUEST] = g_signal_new ("clear-request", GD_TYPE_MAIN_TOOLBAR, G_SIGNAL_RUN_FIRST, 0, NULL, NULL, NULL, G_TYPE_NONE, 0); g_type_class_add_private (klass, sizeof (GdMainToolbarPrivate)); } static void on_selection_mode_button_clicked (GtkButton *b, gpointer user_data) { GdMainToolbar *self = user_data; g_signal_emit (self, signals[SELECTION_MODE_REQUEST], 0, TRUE); } static void on_selection_mode_done_button_clicked (GtkButton *b, gpointer user_data) { GdMainToolbar *self = user_data; g_signal_emit (self, signals[SELECTION_MODE_REQUEST], 0, FALSE); } static void gd_main_toolbar_populate_for_selection (GdMainToolbar *self) { GtkWidget *w; gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (self)), "documents-selection-mode"); gtk_widget_reset_style (GTK_WIDGET (self)); /* right section */ w = get_text_button (_("Done")); gtk_container_add (GTK_CONTAINER (self->priv->right_grid), w); g_signal_connect (w, "clicked", G_CALLBACK (on_selection_mode_done_button_clicked), self); gtk_widget_show_all (GTK_WIDGET (self)); } static void gd_main_toolbar_populate_for_overview (GdMainToolbar *self) { GtkWidget *button; /* right section */ button = get_symbolic_button ("emblem-default-symbolic"); gtk_container_add (GTK_CONTAINER (self->priv->right_grid), button); g_signal_connect (button, "clicked", G_CALLBACK (on_selection_mode_button_clicked), self); gtk_widget_show_all (GTK_WIDGET (self)); } static void gd_main_toolbar_populate_for_preview (GdMainToolbar *self) { gtk_widget_show (self->priv->back); gtk_widget_show_all (GTK_WIDGET (self)); } static void on_left_grid_clear (GtkWidget *w, gpointer user_data) { GdMainToolbar *self = user_data; if (w != self->priv->back) gtk_widget_destroy (w); } static void gd_main_toolbar_clear (GdMainToolbar *self) { GtkStyleContext *context; /* reset labels */ gtk_label_set_text (GTK_LABEL (self->priv->title_label), ""); gtk_label_set_text (GTK_LABEL (self->priv->detail_label), ""); /* clear all on the left, except the back button */ gtk_widget_hide (self->priv->back); gtk_container_foreach (GTK_CONTAINER (self->priv->left_grid), on_left_grid_clear, self); /* clear all on the right */ gtk_container_foreach (GTK_CONTAINER (self->priv->right_grid), (GtkCallback) gtk_widget_destroy, self); context = gtk_widget_get_style_context (GTK_WIDGET (self)); if (gtk_style_context_has_class (context, "documents-selection-mode")) { gtk_style_context_remove_class (context, "documents-selection-mode"); gtk_widget_reset_style (GTK_WIDGET (self)); } g_signal_emit (self, signals[CLEAR_REQUEST], 0); } /** * gd_main_toolbar_set_mode: * @mode: * */ void gd_main_toolbar_set_mode (GdMainToolbar *self, GdMainToolbarMode mode) { if (mode == self->priv->mode) return; gd_main_toolbar_clear (self); self->priv->mode = mode; switch (mode) { case GD_MAIN_TOOLBAR_MODE_OVERVIEW: gd_main_toolbar_populate_for_overview (self); break; case GD_MAIN_TOOLBAR_MODE_SELECTION: gd_main_toolbar_populate_for_selection (self); break; case GD_MAIN_TOOLBAR_MODE_PREVIEW: gd_main_toolbar_populate_for_preview (self); break; default: g_assert_not_reached (); break; } } GdMainToolbarMode gd_main_toolbar_get_mode (GdMainToolbar *self) { return self->priv->mode; } /** * gd_main_toolbar_set_labels: * @self: * @primary: (allow-none): * @detail: (allow-none): * */ void gd_main_toolbar_set_labels (GdMainToolbar *self, const gchar *primary, const gchar *detail) { gchar *real_primary = NULL; if (primary != NULL) real_primary = g_markup_printf_escaped ("%s", primary); if (real_primary == NULL) { gtk_label_set_markup (GTK_LABEL (self->priv->title_label), ""); gtk_widget_hide (self->priv->title_label); } else { gtk_label_set_markup (GTK_LABEL (self->priv->title_label), real_primary); gtk_widget_show (self->priv->title_label); } if (detail == NULL) { gtk_label_set_text (GTK_LABEL (self->priv->detail_label), ""); gtk_widget_hide (self->priv->detail_label); } else { gtk_label_set_text (GTK_LABEL (self->priv->detail_label), detail); gtk_widget_show (self->priv->detail_label); } g_free (real_primary); } /** * gd_main_toolbar_set_back_visible: * @self: * @visible: * */ void gd_main_toolbar_set_back_visible (GdMainToolbar *self, gboolean visible) { if (visible != gtk_widget_get_visible (self->priv->back)) gtk_widget_set_visible (self->priv->back, visible); } GtkWidget * gd_main_toolbar_new (void) { return g_object_new (GD_TYPE_MAIN_TOOLBAR, NULL); } GtkWidget * gd_main_toolbar_add_button (GdMainToolbar *self, const gchar *icon_name, const gchar *label, gboolean pack_start) { GtkWidget *button; if (icon_name != NULL) { button = get_symbolic_button (icon_name); if (label != NULL) gtk_widget_set_tooltip_text (button, label); } else if (label != NULL) { button = get_text_button (label); } if (pack_start) gtk_container_add (GTK_CONTAINER (self->priv->left_grid), button); else gtk_container_add (GTK_CONTAINER (self->priv->right_grid), button); gtk_widget_show_all (button); return button; }