[dia] line-selector: use GtkComboBox



commit 4ef327f8b061194f75e7e199fd610fcce018cb63
Author: Zander Brown <zbrown gnome org>
Date:   Mon Nov 25 02:15:22 2019 +0000

    line-selector: use GtkComboBox
    
    CellRenderer for lines
    
    LineStyle is passed as int, ideally it would be a GEnum

 lib/dia-line-cell-renderer.c | 258 +++++++++++++++++++++++++++++++++++++++++++
 lib/dia-line-cell-renderer.h |  42 +++++++
 lib/dialinestyleselector.c   | 212 +++++++++++++++++++----------------
 lib/meson.build              |   2 +
 4 files changed, 416 insertions(+), 98 deletions(-)
---
diff --git a/lib/dia-line-cell-renderer.c b/lib/dia-line-cell-renderer.c
new file mode 100644
index 00000000..0b6a2914
--- /dev/null
+++ b/lib/dia-line-cell-renderer.c
@@ -0,0 +1,258 @@
+/* Dia -- an diagram creation/manipulation program
+ * Copyright (C) 1998 Alexander Larsson
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * Copyright © 2019 Zander Brown <zbrown gnome org>
+ */
+
+#include <config.h>
+#include "intl.h"
+#include <gtk/gtk.h>
+#include "dia-line-cell-renderer.h"
+#include "renderer/diacairo.h"
+#include "diarenderer.h"
+
+
+#define LINEWIDTH 2
+
+typedef struct _DiaLineCellRendererPrivate DiaLineCellRendererPrivate;
+struct _DiaLineCellRendererPrivate {
+  DiaRenderer *renderer;
+  LineStyle    line;
+};
+
+
+G_DEFINE_TYPE_WITH_PRIVATE (DiaLineCellRenderer, dia_line_cell_renderer, GTK_TYPE_CELL_RENDERER)
+
+
+enum {
+  PROP_0,
+  PROP_LINE,
+  PROP_RENDERER,
+  LAST_PROP
+};
+static GParamSpec *pspecs[LAST_PROP] = { NULL, };
+
+
+static void
+dia_line_cell_renderer_get_property (GObject    *object,
+                                     guint       param_id,
+                                     GValue     *value,
+                                     GParamSpec *pspec)
+{
+  DiaLineCellRenderer *self = DIA_LINE_CELL_RENDERER (object);
+  DiaLineCellRendererPrivate *priv = dia_line_cell_renderer_get_instance_private (self);
+
+  switch (param_id) {
+    case PROP_RENDERER:
+      g_value_set_object (value, priv->renderer);
+      break;
+
+    case PROP_LINE:
+      g_value_set_int (value, priv->line);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+      break;
+  }
+}
+
+
+static void
+dia_line_cell_renderer_set_property (GObject      *object,
+                                     guint         param_id,
+                                     const GValue *value,
+                                     GParamSpec   *pspec)
+{
+  DiaLineCellRenderer *self = DIA_LINE_CELL_RENDERER (object);
+  DiaLineCellRendererPrivate *priv = dia_line_cell_renderer_get_instance_private (self);
+
+  switch (param_id) {
+    case PROP_RENDERER:
+      g_clear_object (&priv->renderer);
+      priv->renderer = g_value_dup_object (value);
+      break;
+
+    case PROP_LINE:
+      priv->line = g_value_get_int (value);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+      break;
+    }
+}
+
+
+static void
+dia_line_cell_renderer_finalize (GObject *object)
+{
+  DiaLineCellRenderer *self = DIA_LINE_CELL_RENDERER (object);
+  DiaLineCellRendererPrivate *priv = dia_line_cell_renderer_get_instance_private (self);
+
+  g_clear_object (&priv->renderer);
+
+  G_OBJECT_CLASS (dia_line_cell_renderer_parent_class)->finalize (object);
+}
+
+
+static void
+dia_line_cell_renderer_get_size (GtkCellRenderer *cell,
+                                 GtkWidget       *widget,
+                                 GdkRectangle    *cell_area,
+                                 gint            *x_offset,
+                                 gint            *y_offset,
+                                 gint            *width,
+                                 gint            *height)
+{
+  gint calc_width;
+  gint calc_height;
+  int  xpad;
+  int  ypad;
+
+  gtk_cell_renderer_get_padding (cell, &xpad, &ypad);
+
+  calc_width  = (gint) xpad * 2 + 40;
+  calc_height = (gint) ypad * 2 + 20;
+
+  if (x_offset) *x_offset = 0;
+  if (y_offset) *y_offset = 0;
+
+  if (width)  *width  = calc_width;
+  if (height) *height = calc_height;
+}
+
+
+static void
+dia_line_cell_renderer_render (GtkCellRenderer      *cell,
+                               GdkWindow            *window,
+                               GtkWidget            *widget,
+                               GdkRectangle         *background_area,
+                               GdkRectangle         *cell_area,
+                               GdkRectangle         *expose_area,
+                               GtkCellRendererState  flags)
+{
+  DiaLineCellRenderer *self = DIA_LINE_CELL_RENDERER (cell);
+  DiaLineCellRendererPrivate *priv = dia_line_cell_renderer_get_instance_private (self);
+  Point from, to;
+  gint width, height;
+  gint x, y;
+  cairo_t *ctx;
+  int xpad, ypad;
+  Color colour_fg;
+  GtkStyle *style = gtk_widget_get_style (widget);
+  GdkColor fg = style->text[gtk_widget_get_state(widget)];
+
+  GDK_COLOR_TO_DIA (fg, colour_fg);
+
+  gtk_cell_renderer_get_padding (cell, &xpad, &ypad);
+
+  ctx = gdk_cairo_create (GDK_DRAWABLE (window));
+
+  g_return_if_fail (DIA_CAIRO_IS_RENDERER (priv->renderer));
+
+  width = cell_area->width - xpad * 2;
+  height = cell_area->height - ypad * 2;
+  x = (cell_area->x + xpad);
+  y = (cell_area->y + ypad);
+
+  to.y = from.y = height / 2;
+  from.x = 0;
+  to.x = width - LINEWIDTH;
+
+  dia_renderer_begin_render (DIA_RENDERER (priv->renderer), NULL);
+  dia_renderer_set_linewidth (DIA_RENDERER (priv->renderer),
+                              LINEWIDTH);
+  dia_renderer_set_linestyle (DIA_RENDERER (priv->renderer),
+                              priv->line,
+                              20.0);
+
+  dia_renderer_draw_line (DIA_RENDERER (priv->renderer),
+                          &from,
+                          &to,
+                          &colour_fg);
+
+  dia_renderer_end_render (DIA_RENDERER (priv->renderer));
+
+  cairo_set_source_surface (ctx, DIA_CAIRO_RENDERER (priv->renderer)->surface, x, y);
+  cairo_paint (ctx);
+}
+
+
+static void
+dia_line_cell_renderer_class_init (DiaLineCellRendererClass *klass)
+{
+  GObjectClass         *object_class = G_OBJECT_CLASS (klass);
+  GtkCellRendererClass *cell_class   = GTK_CELL_RENDERER_CLASS (klass);
+
+  object_class->set_property = dia_line_cell_renderer_set_property;
+  object_class->get_property = dia_line_cell_renderer_get_property;
+  object_class->finalize = dia_line_cell_renderer_finalize;
+
+  cell_class->get_size = dia_line_cell_renderer_get_size;
+  cell_class->render = dia_line_cell_renderer_render;
+
+  /**
+   * DiaLineCellRenderer:renderer:
+   *
+   * Since: 0.98
+   */
+  pspecs[PROP_RENDERER] =
+    g_param_spec_object ("renderer",
+                         "Renderer",
+                         "Renderer to draw lines",
+                         DIA_TYPE_RENDERER,
+                         G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE);
+
+  /**
+   * DiaLineCellRenderer:line:
+   *
+   * Since: 0.98
+   */
+  // TODO: Make LineStyle a GEnum
+  pspecs[PROP_LINE] =
+    g_param_spec_int ("line",
+                      "Line",
+                      "Line style",
+                       LINESTYLE_DEFAULT,
+                       LINESTYLE_DOTTED, // KEEP IN SYNC
+                       LINESTYLE_SOLID,
+                       G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE);
+
+  g_object_class_install_properties (object_class, LAST_PROP, pspecs);
+}
+
+
+static void
+dia_line_cell_renderer_init (DiaLineCellRenderer *self)
+{
+  DiaLineCellRendererPrivate *priv = dia_line_cell_renderer_get_instance_private (self);
+
+  priv->renderer = g_object_new (DIA_CAIRO_TYPE_RENDERER, NULL);
+
+  DIA_CAIRO_RENDERER (priv->renderer)->surface = cairo_recording_surface_create (CAIRO_CONTENT_COLOR_ALPHA, 
NULL);
+  DIA_CAIRO_RENDERER (priv->renderer)->with_alpha = TRUE;
+}
+
+
+GtkCellRenderer *
+dia_line_cell_renderer_new (void)
+{
+  return g_object_new (DIA_TYPE_LINE_CELL_RENDERER, NULL);
+}
diff --git a/lib/dia-line-cell-renderer.h b/lib/dia-line-cell-renderer.h
new file mode 100644
index 00000000..e903ea02
--- /dev/null
+++ b/lib/dia-line-cell-renderer.h
@@ -0,0 +1,42 @@
+/* Dia -- an diagram creation/manipulation program
+ * Copyright (C) 1998 Alexander Larsson
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * Copyright © 2019 Zander Brown <zbrown gnome org>
+ */
+
+#include <gtk/gtk.h>
+
+#pragma once
+
+G_BEGIN_DECLS
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (GtkCellRenderer, g_object_unref)
+
+#define DIA_TYPE_LINE_CELL_RENDERER dia_line_cell_renderer_get_type ()
+G_DECLARE_DERIVABLE_TYPE (DiaLineCellRenderer, dia_line_cell_renderer, DIA, LINE_CELL_RENDERER, 
GtkCellRenderer)
+
+struct _DiaLineCellRendererClass {
+  GtkCellRendererClass parent_class;
+};
+
+
+GtkCellRenderer *dia_line_cell_renderer_new (void);
+
+
+G_END_DECLS
diff --git a/lib/dialinestyleselector.c b/lib/dialinestyleselector.c
index 6c62e1d8..a314e1a4 100644
--- a/lib/dialinestyleselector.c
+++ b/lib/dialinestyleselector.c
@@ -18,23 +18,31 @@
 
 #include <config.h>
 
-#undef GTK_DISABLE_DEPRECATED /* GtkOptionMenu, ... */
 #include <gtk/gtk.h>
 
 #include "intl.h"
 #include "dialinechooser.h"
 #include "widgets.h"
+#include "dia-line-cell-renderer.h"
 
 /************* DiaLineStyleSelector: ***************/
+
+enum {
+  COL_LINE,
+  N_COL
+};
+
+
 struct _DiaLineStyleSelector
 {
   GtkVBox vbox;
 
-  GtkOptionMenu *omenu;
-  GtkMenu *linestyle_menu;
   GtkLabel *lengthlabel;
   GtkSpinButton *dashlength;
-    
+
+  GtkWidget    *combo;
+  GtkListStore *line_store;
+  LineStyle     looking_for;
 };
 
 struct _DiaLineStyleSelectorClass
@@ -49,6 +57,9 @@ enum {
 
 static guint dls_signals[DLS_LAST_SIGNAL] = { 0 };
 
+G_DEFINE_TYPE (DiaLineStyleSelector, dia_line_style_selector, GTK_TYPE_VBOX)
+
+
 static void
 dia_line_style_selector_class_init (DiaLineStyleSelectorClass *class)
 {
@@ -61,22 +72,31 @@ dia_line_style_selector_class_init (DiaLineStyleSelectorClass *class)
                     G_TYPE_NONE, 0);
 }
 
+
 static void
-set_linestyle_sensitivity(DiaLineStyleSelector *fs)
+set_linestyle_sensitivity (DiaLineStyleSelector *fs)
 {
-  int state;
-  GtkWidget *menuitem;
-  if (!fs->linestyle_menu) return;
-  menuitem = gtk_menu_get_active(fs->linestyle_menu);
-  state = (GPOINTER_TO_INT(g_object_get_data(G_OBJECT(menuitem), "user_data"))
-          != LINESTYLE_SOLID);
-
-  gtk_widget_set_sensitive(GTK_WIDGET(fs->lengthlabel), state);
-  gtk_widget_set_sensitive(GTK_WIDGET(fs->dashlength), state);
+  GtkTreeIter iter;
+
+  if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (fs->combo), &iter)) {
+    LineStyle line;
+
+    gtk_tree_model_get (GTK_TREE_MODEL (fs->line_store),
+                        &iter,
+                        COL_LINE, &line,
+                        -1);
+
+    gtk_widget_set_sensitive (GTK_WIDGET (fs->lengthlabel), line != LINESTYLE_SOLID);
+    gtk_widget_set_sensitive (GTK_WIDGET (fs->dashlength), line != LINESTYLE_SOLID);
+  } else {
+    gtk_widget_set_sensitive (GTK_WIDGET (fs->lengthlabel), FALSE);
+    gtk_widget_set_sensitive (GTK_WIDGET (fs->dashlength), FALSE);
+  }
 }
 
+
 static void
-linestyle_type_change_callback(GtkMenu *menu, gpointer data)
+linestyle_type_change_callback(GtkComboBox *menu, gpointer data)
 {
   set_linestyle_sensitivity(DIALINESTYLESELECTOR(data));
   g_signal_emit(DIALINESTYLESELECTOR(data),
@@ -90,52 +110,42 @@ linestyle_dashlength_change_callback(GtkSpinButton *sb, gpointer data)
                dls_signals[DLS_VALUE_CHANGED], 0);
 }
 
+
 static void
 dia_line_style_selector_init (DiaLineStyleSelector *fs)
 {
-  GtkWidget *menu;
-  GtkWidget *menuitem, *ln;
   GtkWidget *label;
   GtkWidget *length;
   GtkWidget *box;
   GtkAdjustment *adj;
-  gint i;
-  static const gchar *_line_style_names[LINESTYLE_DOTTED+1];
-  static gboolean once = FALSE;
-
-  if (!once) {
-    _line_style_names[LINESTYLE_SOLID]        = Q_("line|Solid");
-    _line_style_names[LINESTYLE_DASHED]       = Q_("line|Dashed");
-    _line_style_names[LINESTYLE_DASH_DOT]     = Q_("line|Dash-Dot");
-    _line_style_names[LINESTYLE_DASH_DOT_DOT] = Q_("line|Dash-Dot-Dot");
-    _line_style_names[LINESTYLE_DOTTED]       = Q_("line|Dotted");
-    once = TRUE;
-  }
+  GtkTreeIter iter;
+  GtkCellRenderer *renderer;
+
+  fs->line_store = gtk_list_store_new (N_COL, G_TYPE_INT);
 
-  menu = gtk_option_menu_new();
-  fs->omenu = GTK_OPTION_MENU(menu);
-
-  menu = gtk_menu_new ();
-  fs->linestyle_menu = GTK_MENU(menu);
-
-  for (i = 0; i <= LINESTYLE_DOTTED; i++) {
-    menuitem = gtk_menu_item_new();
-    gtk_widget_set_tooltip_text(menuitem, _line_style_names[i]);
-    g_object_set_data(G_OBJECT(menuitem), "user_data", GINT_TO_POINTER(i));
-    ln = dia_line_preview_new(i);
-    gtk_container_add(GTK_CONTAINER(menuitem), ln);
-    gtk_widget_show(ln);
-    gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
-    gtk_widget_show(menuitem);
+  for (int i = 0; i <= LINESTYLE_DOTTED; i++) {
+    gtk_list_store_append (fs->line_store, &iter);
+    gtk_list_store_set (fs->line_store,
+                        &iter,
+                        COL_LINE, i,
+                        -1);
   }
-  
-  gtk_menu_set_active(GTK_MENU (menu), DEFAULT_LINESTYLE);
-  gtk_option_menu_set_menu (GTK_OPTION_MENU (fs->omenu), menu);
-  g_signal_connect(G_OBJECT(menu), "selection-done", 
-                  G_CALLBACK(linestyle_type_change_callback), fs);
- 
-  gtk_box_pack_start(GTK_BOX(fs), GTK_WIDGET(fs->omenu), FALSE, TRUE, 0);
-  gtk_widget_show(GTK_WIDGET(fs->omenu));
+
+  fs->combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (fs->line_store));
+  g_signal_connect (fs->combo,
+                    "changed",
+                    G_CALLBACK (linestyle_type_change_callback),
+                    fs);
+
+  renderer = dia_line_cell_renderer_new ();
+  gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (fs->combo), renderer, TRUE);
+  gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (fs->combo),
+                                  renderer,
+                                  "line", COL_LINE,
+                                  NULL);
+
+  gtk_box_pack_start (GTK_BOX (fs), fs->combo, FALSE, TRUE, 0);
+  gtk_widget_show (fs->combo);
 
   box = gtk_hbox_new(FALSE,0);
   /*  fs->sizebox = GTK_HBOX(box); */
@@ -153,71 +163,77 @@ dia_line_style_selector_init (DiaLineStyleSelector *fs)
   gtk_box_pack_start(GTK_BOX (box), length, TRUE, TRUE, 0);
   gtk_widget_show (length);
 
-  g_signal_connect(G_OBJECT(length), "changed", 
+  g_signal_connect(G_OBJECT(length), "changed",
                   G_CALLBACK(linestyle_dashlength_change_callback), fs);
 
   set_linestyle_sensitivity(fs);
   gtk_box_pack_start(GTK_BOX(fs), box, TRUE, TRUE, 0);
   gtk_widget_show(box);
-  
+
 }
 
-GType
-dia_line_style_selector_get_type (void)
-{
-  static GType dfs_type = 0;
-
-  if (!dfs_type) {
-    static const GTypeInfo dfs_info = {
-      sizeof (DiaLineStyleSelectorClass),
-      (GBaseInitFunc) NULL,
-      (GBaseFinalizeFunc) NULL,
-      (GClassInitFunc) dia_line_style_selector_class_init,
-      NULL, /* class_finalize */
-      NULL, /* class_data */
-      sizeof (DiaLineStyleSelector),
-      0,    /* n_preallocs */
-      (GInstanceInitFunc) dia_line_style_selector_init,
-    };
-    
-    dfs_type = g_type_register_static (gtk_vbox_get_type (), 
-                                      "DiaLineStyleSelector",
-                                      &dfs_info, 0);
-  }
 
-  return dfs_type;
+GtkWidget *
+dia_line_style_selector_new (void)
+{
+  return g_object_new (dia_line_style_selector_get_type (), NULL);
 }
 
-GtkWidget *
-dia_line_style_selector_new ()
+
+void
+dia_line_style_selector_get_linestyle (DiaLineStyleSelector *fs,
+                                       LineStyle            *ls,
+                                       real                 *dl)
 {
-  return GTK_WIDGET ( g_object_new (dia_line_style_selector_get_type (), NULL));
+  GtkTreeIter iter;
+
+  if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (fs->combo), &iter)) {
+    gtk_tree_model_get (GTK_TREE_MODEL (fs->line_store),
+                        &iter,
+                        COL_LINE, ls,
+                        -1);
+  } else {
+    *ls = LINESTYLE_DEFAULT;
+  }
+
+  if (dl != NULL) {
+    *dl = gtk_spin_button_get_value (fs->dashlength);
+  }
 }
 
 
-void 
-dia_line_style_selector_get_linestyle(DiaLineStyleSelector *fs, 
-                                     LineStyle *ls, real *dl)
+static gboolean
+set_style (GtkTreeModel *model,
+           GtkTreePath  *path,
+           GtkTreeIter  *iter,
+           gpointer      data)
 {
-  GtkWidget *menuitem;
-  void *align;
-  
-  menuitem = gtk_menu_get_active(fs->linestyle_menu);
-  align = g_object_get_data(G_OBJECT(menuitem), "user_data");
-  *ls = GPOINTER_TO_INT(align);
-  if (dl!=NULL) {
-    *dl = gtk_spin_button_get_value(fs->dashlength);
+  DiaLineStyleSelector *self = DIALINESTYLESELECTOR (data);
+  LineStyle line;
+  gboolean res = FALSE;
+
+  gtk_tree_model_get (model,
+                      iter,
+                      COL_LINE, &line,
+                      -1);
+
+  res = line == self->looking_for;
+  if (res) {
+    gtk_combo_box_set_active_iter (GTK_COMBO_BOX (self->combo), iter);
   }
+
+  return res;
 }
 
+
 void
 dia_line_style_selector_set_linestyle (DiaLineStyleSelector *as,
-                                      LineStyle linestyle, real dashlength)
+                                       LineStyle             linestyle,
+                                       real                  dashlength)
 {
-  gtk_menu_set_active(GTK_MENU (as->linestyle_menu), linestyle);
-  gtk_option_menu_set_history (GTK_OPTION_MENU(as->omenu), linestyle);
-/* TODO restore this later */
-/*  gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM(gtk_menu_get_active(GTK_MENU(as->linestyle_menu))), 
TRUE);*/
-  set_linestyle_sensitivity(DIALINESTYLESELECTOR(as));
-  gtk_spin_button_set_value(GTK_SPIN_BUTTON(as->dashlength), dashlength);
+  as->looking_for = linestyle;
+  gtk_tree_model_foreach (GTK_TREE_MODEL (as->line_store), set_style, as);
+  as->looking_for = LINESTYLE_DEFAULT;
+
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON (as->dashlength), dashlength);
 }
diff --git a/lib/meson.build b/lib/meson.build
index d80c3295..35d2abe8 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -154,6 +154,8 @@ libdia_sources = stdprop_sources + [
     'diacellrendererenum.c',
     'dia-arrow-cell-renderer.c',
     'dia-arrow-cell-renderer.h',
+    'dia-line-cell-renderer.c',
+    'dia-line-cell-renderer.h',
 ]
 
 gnome = import('gnome')


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