[gnumeric] GUI: Improve sheet tabs.



commit 62417256f65ba1379b309546ca536aea9d0e8714
Author: Morten Welinder <terra gnome org>
Date:   Wed Apr 3 13:52:13 2013 -0400

    GUI: Improve sheet tabs.

 ChangeLog                           |    8 +
 NEWS                                |    2 +
 src/gnumeric.css                    |    7 +
 src/sheet-control-gui.c             |   24 ++-
 src/wbc-gtk.c                       |   34 ++--
 src/widgets/ChangeLog               |    7 +
 src/widgets/Makefile.am             |   14 +-
 src/widgets/gnm-notebook.c          |  321 +++++++++++++++++++++++++
 src/widgets/gnm-notebook.h          |    7 +
 src/widgets/widget-editable-label.c |  438 -----------------------------------
 src/widgets/widget-editable-label.h |   26 --
 11 files changed, 392 insertions(+), 496 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index d8a7b08..b822ffd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2013-04-03  Morten Welinder  <terra gnome org>
+
+       * src/wbc-gtk.c (cb_sheet_tab_change): Use g_object_set to set
+       attributes of the tab.
+
+       * src/sheet-control-gui.c (sheet_control_gui_new): Create a
+       GnmNotebookButton, not an EditableLabel.
+
 2013-04-02  Morten Welinder  <terra gnome org>
 
        * src/wbc-gtk.c (cb_wbcg_drag_motion): Fix test for notebook tab
diff --git a/NEWS b/NEWS
index a42c1f0..1f9ebf3 100644
--- a/NEWS
+++ b/NEWS
@@ -17,6 +17,8 @@ Morten:
        * Style most of Gnumeric using css.
        * Fix focus problem in cell comment dialog.  [#696826]
        * Move sheet renaming into a dialog.
+       * Make it easier to see what sheet is selected.  [#659317]
+
 
 --------------------------------------------------------------------------
 Gnumeric 1.12.1
diff --git a/src/gnumeric.css b/src/gnumeric.css
index 0d1d75c..bd72f92 100644
--- a/src/gnumeric.css
+++ b/src/gnumeric.css
@@ -194,3 +194,10 @@ GtkArrow.auto-filter:active {
 }
 
 /* ------------------------------------------------------------------------- */
+/* GnmNotebookButton is the sheet name buttons used to select sheets.  */
+
+GnmNotebookButton:active {
+  font-weight: bold;
+}
+
+/* ------------------------------------------------------------------------- */
diff --git a/src/sheet-control-gui.c b/src/sheet-control-gui.c
index c3d1636..ce5fed3 100644
--- a/src/sheet-control-gui.c
+++ b/src/sheet-control-gui.c
@@ -62,7 +62,6 @@
 #include "item-bar.h"
 #include "item-cursor.h"
 #include "widgets/gnumeric-expr-entry.h"
-#include "widgets/widget-editable-label.h"
 #include "gnm-sheet-slicer.h"
 
 #include <go-data-slicer-field.h>
@@ -1711,14 +1710,21 @@ sheet_control_gui_new (SheetView *sv, WBCGtk *wbcg)
                }
        }
 
-       scg->label = editable_label_new
-               (sheet->name_unquoted,
-                sheet->tab_color
-                ? go_color_to_gdk_rgba (sheet->tab_color->go_color, &cback)
-                : NULL,
-                sheet->tab_text_color
-                ? go_color_to_gdk_rgba (sheet->tab_text_color->go_color, &cfore)
-                : NULL);
+       scg->label = g_object_new
+               (GNM_NOTEBOOK_BUTTON_TYPE,
+                "label", sheet->name_unquoted,
+                //"valign", GTK_ALIGN_START,
+                "background-color",
+                (sheet->tab_color
+                 ? go_color_to_gdk_rgba (sheet->tab_color->go_color,
+                                         &cback)
+                 : NULL),
+                "text-color",
+                (sheet->tab_text_color
+                 ? go_color_to_gdk_rgba (sheet->tab_text_color->go_color,
+                                         &cfore)
+                 : NULL),
+                NULL);
        g_object_ref (scg->label);
 
        return scg;
diff --git a/src/wbc-gtk.c b/src/wbc-gtk.c
index 707a8b6..50ebeff 100644
--- a/src/wbc-gtk.c
+++ b/src/wbc-gtk.c
@@ -49,7 +49,6 @@
 #include "style-border.h"
 #include "gnumeric-conf.h"
 #include "dialogs/dialogs.h"
-#include "widgets/widget-editable-label.h"
 #include "widgets/gnm-fontbutton.h"
 #include "gui-clipboard.h"
 #include "libgnumeric.h"
@@ -382,8 +381,8 @@ wbcg_update_action_sensitivity (WorkbookControl *wbc)
                for (i = 0; i < N; i++) {
                        GtkWidget *label =
                                gnm_notebook_get_nth_label (wbcg->bnotebook, i);
-                       editable_label_set_editable (EDITABLE_LABEL (label),
-                                                    enable_actions);
+                       g_object_set_data (G_OBJECT (label), "editable",
+                                          GINT_TO_POINTER (enable_actions));
                }
        }
 
@@ -569,7 +568,7 @@ sheet_menu_label_run (SheetControlGUI *scg, GdkEventButton *event)
 /**
  * cb_sheet_label_button_press:
  *
- * Invoked when the user has clicked on the EditableLabel widget.
+ * Invoked when the user has clicked on the sheet name widget.
  * This takes care of switching to the notebook that contains the label
  */
 static gboolean
@@ -592,7 +591,7 @@ cb_sheet_label_button_press (GtkWidget *widget, GdkEventButton *event,
        if (event->button == 3) {
                if ((scg_wbcg (scg))->edit_line.guru == NULL)
                        scg_object_unselect (scg, NULL);
-               if (editable_label_get_editable (EDITABLE_LABEL (widget))) {
+               if (g_object_get_data (G_OBJECT (widget), "editable")) {
                        sheet_menu_label_run (scg, event);
                        scg_take_focus (scg);
                        return TRUE;
@@ -978,22 +977,27 @@ wbcg_menu_state_sheet_count (WBCGtk *wbcg)
 static void
 cb_sheet_tab_change (Sheet *sheet,
                     G_GNUC_UNUSED GParamSpec *pspec,
-                    EditableLabel *el)
+                    GtkWidget *widget)
 {
        GdkRGBA cfore, cback;
-       SheetControlGUI *scg = get_scg (GTK_WIDGET (el));
+       SheetControlGUI *scg = get_scg (widget);
 
        g_return_if_fail (IS_SHEET_CONTROL_GUI (scg));
 
        /* We're lazy and just set all relevant attributes.  */
-       editable_label_set_text (el, sheet->name_unquoted);
-       editable_label_set_color (el,
-                                 sheet->tab_color
-                                 ? go_color_to_gdk_rgba (sheet->tab_color->go_color, &cback)
-                                 : NULL,
-                                 sheet->tab_text_color
-                                 ? go_color_to_gdk_rgba (sheet->tab_text_color->go_color, &cfore)
-                                 : NULL);
+       g_object_set (widget,
+                     "label", sheet->name_unquoted,
+                     "background-color",
+                     (sheet->tab_color
+                      ? go_color_to_gdk_rgba (sheet->tab_color->go_color,
+                                              &cback)
+                      : NULL),
+                     "text-color",
+                     (sheet->tab_text_color
+                      ? go_color_to_gdk_rgba (sheet->tab_text_color->go_color,
+                                              &cfore)
+                      : NULL),
+                     NULL);
 }
 
 static void
diff --git a/src/widgets/ChangeLog b/src/widgets/ChangeLog
index 7008fc4..a47ce10 100644
--- a/src/widgets/ChangeLog
+++ b/src/widgets/ChangeLog
@@ -1,3 +1,10 @@
+2013-04-03  Morten Welinder  <terra gnome org>
+
+       * gnm-notebook.c (GnmNoteBookButton): New widget for use as
+       notebook tab.
+
+       * Makefile.am: Remove editable-widget.
+
 2013-04-02  Morten Welinder  <terra gnome org>
 
        * gnumeric-text-view.c (gtv_grab_focus): Bounce focus to textview.
diff --git a/src/widgets/Makefile.am b/src/widgets/Makefile.am
index 6315b91..b10b823 100644
--- a/src/widgets/Makefile.am
+++ b/src/widgets/Makefile.am
@@ -18,17 +18,15 @@ libwidgets_la_SOURCES =                             \
        gnm-notebook.c                          \
        gnm-radiobutton.c                       \
        gnm-radiobutton.h                       \
-       widget-editable-label.c                 \
-       widget-editable-label.h                 \
-       gnm-cell-combo-view.c           \
-       gnm-cell-combo-view.h           \
+       gnm-cell-combo-view.c                   \
+       gnm-cell-combo-view.h                   \
        gnm-cell-combo-view-impl.h              \
-       gnm-filter-combo-view.c         \
-       gnm-filter-combo-view.h         \
+       gnm-filter-combo-view.c                 \
+       gnm-filter-combo-view.h                 \
        gnm-validation-combo-view.c             \
        gnm-validation-combo-view.h             \
-       gnm-sheet-slicer-combo-view.c   \
-       gnm-sheet-slicer-combo-view.h   \
+       gnm-sheet-slicer-combo-view.c           \
+       gnm-sheet-slicer-combo-view.h           \
        gnumeric-cell-renderer-text.c           \
        gnumeric-cell-renderer-text.h           \
        gnumeric-cell-renderer-expr-entry.c     \
diff --git a/src/widgets/gnm-notebook.c b/src/widgets/gnm-notebook.c
index 9765285..7da07b8 100644
--- a/src/widgets/gnm-notebook.c
+++ b/src/widgets/gnm-notebook.c
@@ -21,8 +21,273 @@
 
 #include <gnumeric-config.h>
 #include "gnm-notebook.h"
+#include <goffice/goffice.h>
+#include "gnm-i18n.h"
 #include <gsf/gsf-impl-utils.h>
 
+/* ------------------------------------------------------------------------- */
+
+struct GnmNotebookButton_ {
+       /*
+        * We need to derive from GtkLabel mostly for theming reasons,
+        * but GtkLabel is also special for clipping.
+        */
+       GtkLabel base;
+
+       PangoLayout *layout;
+       PangoLayout *layout_active;
+
+       int x_offset, x_offset_active;
+
+       GdkRGBA *fg, *bg;
+};
+
+typedef struct {
+       GtkLabelClass parent_class;
+} GnmNotebookButtonClass;
+
+static GObjectClass *gnm_notebook_button_parent_class;
+
+enum {
+       NBB_PROP_0,
+       NBB_PROP_BACKGROUND_COLOR,
+       NBB_PROP_TEXT_COLOR
+};
+
+static void
+gnm_notebook_button_finalize (GObject *obj)
+{
+       GnmNotebookButton *nbb = GNM_NOTEBOOK_BUTTON (obj);
+       g_clear_object (&nbb->layout);
+       g_clear_object (&nbb->layout_active);
+       gdk_rgba_free (nbb->fg);
+       gdk_rgba_free (nbb->bg);
+       gnm_notebook_button_parent_class->finalize (obj);
+}
+
+static void
+gnm_notebook_button_set_property (GObject      *obj,
+                                 guint         prop_id,
+                                 const GValue *value,
+                                 GParamSpec   *pspec)
+{
+       GnmNotebookButton *nbb = GNM_NOTEBOOK_BUTTON (obj);
+
+       switch (prop_id) {
+       case NBB_PROP_BACKGROUND_COLOR:
+               gdk_rgba_free (nbb->bg);
+               nbb->bg = g_value_dup_boxed (value);
+               gtk_widget_queue_draw (GTK_WIDGET (obj));
+               break;
+       case NBB_PROP_TEXT_COLOR:
+               gdk_rgba_free (nbb->fg);
+               nbb->fg = g_value_dup_boxed (value);
+               gtk_widget_queue_draw (GTK_WIDGET (obj));
+               gtk_widget_override_color (GTK_WIDGET (obj),
+                                          GTK_STATE_FLAG_NORMAL,
+                                          nbb->fg);
+               gtk_widget_override_color (GTK_WIDGET (obj),
+                                          GTK_STATE_FLAG_ACTIVE,
+                                          nbb->fg);
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+               break;
+       }
+}
+
+static void
+gnm_notebook_button_ensure_layout (GnmNotebookButton *nbb)
+{
+       const char *text = gtk_label_get_text (GTK_LABEL (nbb));
+
+       if (nbb->layout) {
+               /* Optimize?  */
+               pango_layout_set_text (nbb->layout, text, -1);
+               pango_layout_set_text (nbb->layout_active, text, -1);
+       } else {
+               PangoAttrList *attrs, *attrs_active;
+               PangoAttribute *attr;
+               PangoFontDescription *desc;
+               GtkStyleContext *context = gtk_widget_get_style_context (GTK_WIDGET (nbb));
+
+               nbb->layout = gtk_widget_create_pango_layout (GTK_WIDGET (nbb), text);
+               nbb->layout_active = gtk_widget_create_pango_layout (GTK_WIDGET (nbb), text);
+
+               /* Common */
+               attrs = pango_attr_list_new ();
+               if (nbb->bg) {
+                       attr = go_color_to_pango
+                               (go_color_from_gdk_rgba (nbb->bg, NULL),
+                                FALSE);
+                       attr->start_index = 0;
+                       attr->end_index = -1;
+                       pango_attr_list_insert (attrs, attr);
+               }                       
+               attrs_active = pango_attr_list_copy (attrs);
+
+               /* Normal */
+               gtk_style_context_get (context, GTK_STATE_FLAG_NORMAL,
+                                      "font", &desc, NULL);
+               attr = pango_attr_font_desc_new (desc);
+               attr->start_index = 0;
+               attr->end_index = -1;
+               pango_attr_list_insert (attrs, attr);
+               pango_font_description_free (desc);
+               pango_layout_set_attributes (nbb->layout, attrs);
+               pango_attr_list_unref (attrs);
+
+               /* Active */
+               gtk_style_context_get (context, GTK_STATE_FLAG_ACTIVE,
+                                      "font", &desc, NULL);
+               attr = pango_attr_font_desc_new (desc);
+               attr->start_index = 0;
+               attr->end_index = -1;
+               pango_attr_list_insert (attrs_active, attr);
+               pango_font_description_free (desc);
+               pango_layout_set_attributes (nbb->layout_active, attrs_active);
+               pango_attr_list_unref (attrs_active);
+       }
+}
+
+static void
+gnm_notebook_button_screen_changed (GtkWidget *widget, G_GNUC_UNUSED GdkScreen *prev)
+{
+       GnmNotebookButton *nbb = GNM_NOTEBOOK_BUTTON (widget);
+       g_clear_object (&nbb->layout);
+}
+
+static gboolean
+gnm_notebook_button_draw (GtkWidget *widget, cairo_t *cr)
+{
+       GnmNotebookButton *nbb = GNM_NOTEBOOK_BUTTON (widget);
+       GnmNotebook *nb = GNM_NOTEBOOK (gtk_widget_get_parent (widget));
+       GtkStyleContext *context = gtk_widget_get_style_context (widget);
+       gboolean is_active = (widget == gnm_notebook_get_current_label (nb));
+       GtkStateFlags state =
+               is_active ? GTK_STATE_FLAG_ACTIVE : GTK_STATE_FLAG_NORMAL;
+       GtkBorder padding;
+
+       gtk_style_context_save (context);
+       gtk_style_context_set_state (context, state);
+
+       gtk_style_context_get_padding (context, state, &padding);
+
+       gnm_notebook_button_ensure_layout (nbb);
+
+       gtk_render_layout (context, cr,
+                          padding.left + (is_active ? nbb->x_offset_active : nbb->x_offset),
+                          0,
+                          is_active ? nbb->layout_active : nbb->layout);
+
+       gtk_style_context_restore (context);
+       return FALSE;
+}
+
+static GtkSizeRequestMode 
+gnm_notebook_button_get_request_mode (GtkWidget *widget)
+{ 
+       return GTK_SIZE_REQUEST_CONSTANT_SIZE;
+}
+
+static void
+gnm_notebook_button_get_preferred_height (GtkWidget *widget,
+                                         gint      *minimum,
+                                         gint      *natural)
+{
+       GnmNotebookButton *nbb = GNM_NOTEBOOK_BUTTON (widget);
+       PangoRectangle logical, logical_active;
+       GtkBorder padding;
+
+       gtk_style_context_get_padding (gtk_widget_get_style_context (widget),
+                                      GTK_STATE_FLAG_NORMAL,
+                                      &padding);
+
+       gnm_notebook_button_ensure_layout (nbb);
+       pango_layout_get_extents (nbb->layout, NULL, &logical);
+       pango_layout_get_extents (nbb->layout_active, NULL, &logical_active);
+
+       *minimum = *natural =
+               (padding.top +
+                PANGO_PIXELS_CEIL (MAX (logical.height, logical_active.height)) +
+                padding.bottom);
+}
+
+static void
+gnm_notebook_button_get_preferred_width (GtkWidget *widget,
+                                        gint      *minimum,
+                                        gint      *natural)
+{
+       GnmNotebookButton *nbb = GNM_NOTEBOOK_BUTTON (widget);
+       PangoRectangle logical, logical_active;
+       GtkBorder padding;
+       int dx;
+
+       gtk_style_context_get_padding (gtk_widget_get_style_context (widget),
+                                      GTK_STATE_FLAG_NORMAL,
+                                      &padding);
+
+       gnm_notebook_button_ensure_layout (nbb);
+       pango_layout_get_extents (nbb->layout, NULL, &logical);
+       pango_layout_get_extents (nbb->layout_active, NULL, &logical_active);
+
+       dx = logical_active.width - logical.width;
+       nbb->x_offset = PANGO_PIXELS (MAX (0, dx / 2));
+       nbb->x_offset_active = PANGO_PIXELS (MAX (0, -dx / 2));
+
+       *minimum = *natural =
+               (padding.left +
+                PANGO_PIXELS_CEIL (MAX (logical.width, logical_active.width)) +
+                padding.right);
+}
+
+static void
+gnm_notebook_button_class_init (GObjectClass *klass)
+{
+       GtkWidgetClass *wclass = (GtkWidgetClass *)klass;
+
+       gnm_notebook_button_parent_class = g_type_class_peek_parent (klass);
+       klass->finalize = gnm_notebook_button_finalize;
+       klass->set_property = gnm_notebook_button_set_property;
+
+       g_object_class_install_property
+               (klass,
+                NBB_PROP_BACKGROUND_COLOR,
+                g_param_spec_boxed ("background-color",
+                                    P_("Background Color"),
+                                    P_("Override color to use for background"),
+                                    GDK_TYPE_RGBA,
+                                    G_PARAM_WRITABLE));
+       g_object_class_install_property
+               (klass,
+                NBB_PROP_TEXT_COLOR,
+                g_param_spec_boxed ("text-color",
+                                    P_("Text Color"),
+                                    P_("Override color to use for label"),
+                                    GDK_TYPE_RGBA,
+                                    G_PARAM_WRITABLE));
+
+       wclass->draw = gnm_notebook_button_draw;
+       wclass->screen_changed = gnm_notebook_button_screen_changed;
+       wclass->get_request_mode = gnm_notebook_button_get_request_mode;
+       wclass->get_preferred_width = gnm_notebook_button_get_preferred_width;
+       wclass->get_preferred_height = gnm_notebook_button_get_preferred_height;
+}
+
+static void
+gnm_notebook_button_init (GnmNotebookButton *nbb)
+{
+}
+
+GSF_CLASS (GnmNotebookButton, gnm_notebook_button,
+          gnm_notebook_button_class_init,
+          gnm_notebook_button_init, GTK_TYPE_LABEL)
+#if 0
+       ;
+#endif
+
+/* ------------------------------------------------------------------------- */
+
 struct _GnmNotebook {
        GtkNotebook parent;
 
@@ -68,11 +333,56 @@ gnm_notebook_size_allocate (GtkWidget     *widget,
                (widget, &alc);
 }
 
+static gboolean
+gnm_notebook_button_press (GtkWidget      *widget,
+                          GdkEventButton *event)
+{
+       GnmNotebook *nb = GNM_NOTEBOOK (widget);
+       unsigned ui;
+
+       for (ui = 0; /* Nothing */; ui++) {
+               GtkWidget *child = gnm_notebook_get_nth_label (nb, ui);
+               GtkAllocation child_allocation;
+
+               if (!child)
+                       break;
+
+               if (!gtk_widget_get_child_visible (child))
+                       continue;
+
+               gtk_widget_get_allocation (child, &child_allocation);
+
+               if (event->x >= child_allocation.x &&
+                   event->x <  child_allocation.x + child_allocation.width &&
+                   event->y >= child_allocation.y &&
+                   event->y <  child_allocation.y + child_allocation.height) {
+                       if (0)
+                               g_printerr ("Button %d pressed\n", ui);
+                       return gtk_widget_event (child, (GdkEvent*)event);
+               }
+       }
+
+       return TRUE;
+}
+
+static GType
+gnm_notebook_child_type (G_GNUC_UNUSED GtkContainer *container)
+{
+       return GNM_NOTEBOOK_BUTTON_TYPE;
+}
+
 static void
 gnm_notebook_class_init (GtkWidgetClass *klass)
 {
+       GtkWidgetClass *wclass = (GtkWidgetClass *)klass;
+       GtkContainerClass *cclass = (GtkContainerClass *)klass;
+
        gnm_notebook_parent_class = g_type_class_peek (GTK_TYPE_NOTEBOOK);
        klass->size_allocate = gnm_notebook_size_allocate;
+
+       cclass->child_type = gnm_notebook_child_type;
+
+       wclass->button_press_event = gnm_notebook_button_press;
 }
 
 static void
@@ -117,6 +427,17 @@ gnm_notebook_get_nth_label (GnmNotebook *nb, int n)
        return gtk_notebook_get_tab_label (GTK_NOTEBOOK (nb), page);
 }
 
+GtkWidget *
+gnm_notebook_get_current_label (GnmNotebook *nb)
+{
+       int i;
+
+       g_return_val_if_fail (GNM_IS_NOTEBOOK (nb), NULL);
+
+       i = gtk_notebook_get_current_page (GTK_NOTEBOOK (nb));
+       return i == -1 ? NULL : gnm_notebook_get_nth_label (nb, i);
+}
+
 static void
 cb_label_destroyed (G_GNUC_UNUSED GtkWidget *label, GtkWidget *dummy)
 {
diff --git a/src/widgets/gnm-notebook.h b/src/widgets/gnm-notebook.h
index e880c8c..82b3f8d 100644
--- a/src/widgets/gnm-notebook.h
+++ b/src/widgets/gnm-notebook.h
@@ -23,6 +23,12 @@
 
 #include <gtk/gtk.h>
 
+GType          gnm_notebook_button_get_type    (void);
+typedef struct GnmNotebookButton_ GnmNotebookButton;
+#define GNM_NOTEBOOK_BUTTON_TYPE        (gnm_notebook_button_get_type ())
+#define GNM_NOTEBOOK_BUTTON(obj)        (G_TYPE_CHECK_INSTANCE_CAST((obj), GNM_NOTEBOOK_BUTTON_TYPE, 
GnmNotebookButton))
+#define GNM_IS_NOTEBOOK_BUTTON(obj)     (G_TYPE_CHECK_INSTANCE_TYPE((obj), GNM_NOTEBOOK_BUTTON_TYPE))
+
 #define GNM_NOTEBOOK_TYPE        (gnm_notebook_get_type ())
 #define GNM_NOTEBOOK(obj)        (G_TYPE_CHECK_INSTANCE_CAST((obj), GNM_NOTEBOOK_TYPE, GnmNotebook))
 #define GNM_IS_NOTEBOOK(obj)     (G_TYPE_CHECK_INSTANCE_TYPE((obj), GNM_NOTEBOOK_TYPE))
@@ -33,6 +39,7 @@ GType         gnm_notebook_get_type   (void);
 
 int             gnm_notebook_get_n_visible (GnmNotebook *nb);
 GtkWidget *     gnm_notebook_get_nth_label (GnmNotebook *nb, int n);
+GtkWidget *     gnm_notebook_get_current_label (GnmNotebook *nb);
 void            gnm_notebook_insert_tab (GnmNotebook *nb, GtkWidget *label,
                                         int pos);
 void            gnm_notebook_move_tab (GnmNotebook *nb, GtkWidget *label, int newpos);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]