[dia] [gtk-deprecated] reimplementation of a Dia's own ruler



commit 55b9b8d26eaca996af7d0f95c6f4dd5e317099db
Author: Hans Breuer <hans breuer org>
Date:   Sun Aug 12 15:18:05 2012 +0200

    [gtk-deprecated] reimplementation of a Dia's own ruler
    
    With gtk+-3.0 GtkRuler will be gone. From gtk+-2.24 on the
    new implementation is used. There are still small rendering
    glitches, but it basically works.

 app/Makefile.am  |    1 -
 app/grid.c       |   34 ++++++++-
 app/grid.h       |    3 +
 app/interface.c  |    8 ++-
 app/makefile.msc |    2 +-
 app/ruler.c      |  215 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
 app/ruler.h      |    9 ++-
 7 files changed, 259 insertions(+), 13 deletions(-)
---
diff --git a/app/Makefile.am b/app/Makefile.am
index f4e9afb..45c2900 100644
--- a/app/Makefile.am
+++ b/app/Makefile.am
@@ -247,7 +247,6 @@ EXTRA_DIST = \
 	pixmaps/portrait.xpm \
 	pixmaps/landscape.xpm \
 	\
-	\
 	pixmaps/missing.xpm \
 	pixmaps/n_a.xpm \
 	pixmaps/line_break.xpm \
diff --git a/app/grid.c b/app/grid.c
index df78d96..bbb862a 100644
--- a/app/grid.c
+++ b/app/grid.c
@@ -50,6 +50,38 @@ calculate_dynamic_grid(DDisplay *ddisp, real *width_x, real *width_y)
   *width_y = ret;
 }
 
+gboolean
+grid_step (DDisplay *ddisp, GtkOrientation orientation,
+	   real *start, int *ipos, gboolean *is_major)
+{
+  real  length;
+  real  pos, tmp;
+  guint major_lines = ddisp->diagram->grid.major_lines;
+  int   x, y;
+  int   major_count = 1;
+
+  /* length from the diagram settings - but always dynamic */
+  calculate_dynamic_grid (ddisp, &length, &length);
+  pos = ceil(*start / length) * length;
+
+  pos += length;
+  if (major_lines) {
+    major_count = ROUND (pos/length);
+    if(major_count < 0) major_count -= major_lines * major_count;
+    major_count %= major_lines;
+  }
+  ddisplay_transform_coords(ddisp,
+			    orientation == GTK_ORIENTATION_HORIZONTAL ? pos : 0,
+			    orientation == GTK_ORIENTATION_VERTICAL ? pos : 0,
+			    &x, &y);
+
+  *start = pos;
+  *ipos = (orientation == GTK_ORIENTATION_HORIZONTAL ? x : y);
+  *is_major = (major_count == 0);
+
+  return TRUE;
+}
+
 static void
 grid_draw_horizontal_lines(DDisplay *ddisp, Rectangle *update, real length) 
 {
@@ -223,7 +255,7 @@ grid_draw_hex(DDisplay *ddisp, Rectangle *update, real length)
 				 &ddisp->diagram->grid.colour);
       horiz_pos += 3 * length;
     }
-	
+
     vert_pos += sqrt(3) * length;
   }
 
diff --git a/app/grid.h b/app/grid.h
index 91eec07..13a6c71 100644
--- a/app/grid.h
+++ b/app/grid.h
@@ -34,4 +34,7 @@ void grid_draw(DDisplay *ddisp, Rectangle *update);
 void pagebreak_draw(DDisplay *ddisp, Rectangle *update);
 void snap_to_grid(DDisplay *ddisp, coord *x, coord *y);
 
+gboolean grid_step (DDisplay *ddisp, GtkOrientation orientation,
+		    real *start, int *ipos, gboolean *is_major);
+
 #endif /* GRID_H */
diff --git a/app/interface.c b/app/interface.c
index de2c2df..f65445d 100644
--- a/app/interface.c
+++ b/app/interface.c
@@ -58,7 +58,11 @@ dia_dnd_file_drag_data_received (GtkWidget        *widget,
                                  guint             time,
 				 DDisplay         *ddisp)
 {
+#if GTK_CHECK_VERSION(2,22,0)
+  switch (gdk_drag_context_get_selected_action(context))
+#else
   switch (context->action)
+#endif
     {
     case GDK_ACTION_DEFAULT:
     case GDK_ACTION_COPY:
@@ -376,8 +380,8 @@ create_canvas (DDisplay *ddisp)
 static void
 _ddisplay_setup_rulers (DDisplay *ddisp, GtkWidget *shell, GtkWidget *table)
 {
-  ddisp->hrule = dia_ruler_new (GTK_ORIENTATION_HORIZONTAL, shell);
-  ddisp->vrule = dia_ruler_new (GTK_ORIENTATION_VERTICAL, shell);
+  ddisp->hrule = dia_ruler_new (GTK_ORIENTATION_HORIZONTAL, shell, ddisp);
+  ddisp->vrule = dia_ruler_new (GTK_ORIENTATION_VERTICAL, shell, ddisp);
 
   /* harder to change position in the table, but we did not do it for years ;) */
   gtk_table_attach (GTK_TABLE (table), ddisp->hrule, 1, 2, 0, 1,
diff --git a/app/makefile.msc b/app/makefile.msc
index 3e3a076..84f5281 100644
--- a/app/makefile.msc
+++ b/app/makefile.msc
@@ -15,7 +15,7 @@ DEFINES = \
 	-DWIN32 \
 	-DG_DISABLE_DEPRECATED -DGTK_DISABLE_DEPRECATED \
 
-PKG_LINK = $(GTK2_LIBS) $(GLIB_LIBS) $(GTHREAD_LIBS) $(PANGOWIN32_LIBS) \
+PKG_LINK = $(GTK2_LIBS) $(GLIB_LIBS) $(GTHREAD_LIBS) $(PANGOWIN32_LIBS) $(PANGOCAIRO_LIBS) \
 	$(LIBXML2_LIBS) \
 	$(PRJ_TOP)\lib\libdia.lib $(CAIRO_LIBS) \
 	$(GDK_PIXBUF_LIBS) $(INTL_LIBS) \
diff --git a/app/ruler.c b/app/ruler.c
index 5491198..5b0c25d 100644
--- a/app/ruler.c
+++ b/app/ruler.c
@@ -1,6 +1,8 @@
 /* Dia -- an diagram creation/manipulation program
  * Copyright (C) 1998 Alexander Larsson
  *
+ * ruler.c - Dia specific reimplementation (C) 2012 Hans Breuer
+ *
  * 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
@@ -18,20 +20,208 @@
 
 #include <config.h>
 
-#undef GTK_DISABLE_DEPRECATED /* GtkRuler */
 /* GtkRuler is deprecated by gtk-2-24, gone with gtk-3-0 because it is 
  * deemed to be too specialized for maintenance in Gtk. Maybe Dia is 
  * too specialized to be ported?
+ *
+ * Or maybe not - at least the ruler part can be reimplemented quite
+ * easily with already exisiting application specific logic.
  */
-#include <gtk/gtk.h>
 
 #include "ruler.h"
+#if GTK_CHECK_VERSION(2,24,0)
+#include "grid.h"
+#include "display.h"
+
+typedef struct _DiaRulerClass
+{
+  GtkDrawingAreaClass parent_class;
+} DiaRulerClass;
+
+typedef struct _DiaRuler
+{
+  GtkDrawingArea parent;
+
+  DDisplay *ddisp;
+
+  GtkOrientation orientation;
+  gdouble lower;
+  gdouble upper;
+  gdouble position;
+  gdouble max_size;
+} DiaRuler;
+
+GType dia_ruler_get_type (void);
+#define DIA_TYPE_RULER (dia_ruler_get_type ())
+#define DIA_RULER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DIA_TYPE_RULER, DiaRuler))
+
+G_DEFINE_TYPE (DiaRuler, dia_ruler, GTK_TYPE_DRAWING_AREA)
+
+static gboolean
+dia_ruler_draw (GtkWidget *widget,
+		cairo_t   *cr)
+{
+  DiaRuler *ruler = DIA_RULER(widget);
+
+  if (gtk_widget_is_drawable (widget))
+    {
+      GtkStyle *style = gtk_widget_get_style (widget);
+      PangoLayout *layout;
+      int x = 0, y = 0, dx, dy, width, height;
+      real pos;
+
+      layout = gtk_widget_create_pango_layout (widget, "012456789");
+
+      width = gtk_widget_get_allocated_width (widget);
+      height = gtk_widget_get_allocated_height (widget);
+      dx = (ruler->orientation == GTK_ORIENTATION_VERTICAL) ? width/3 : 0;
+      dy = (ruler->orientation == GTK_ORIENTATION_HORIZONTAL) ? height/3 : 0;
+
+      gdk_cairo_set_source_color (cr, &style->text[gtk_widget_get_state(widget)]);
+      cairo_set_line_width (cr, 1);
+
+      pos = ruler->lower;
+      for (x = 0, y = 0; x < width && y < height;)
+        {
+	  gboolean is_major;
+	  int n;
+
+	  if (!grid_step (ruler->ddisp, ruler->orientation, &pos,
+	                  (ruler->orientation == GTK_ORIENTATION_HORIZONTAL) ? &x : &y,
+			  &is_major))
+	    break;
+
+	  /* ticks */
+	  n = (is_major ? 1 : 2);
+	  /* + .5 for pixel aligned lines */
+	  cairo_move_to (cr, x + 3*dx + .5, y + 3*dy + .5);
+	  cairo_line_to (cr, x + n*dx + .5, y + n*dy + .5);
+	  cairo_stroke (cr);
+
+	  /* label */
+	  if (is_major)
+	    {
+	      gchar text[G_ASCII_DTOSTR_BUF_SIZE];
+
+	      g_snprintf (text, sizeof(text)-1, "%g", pos);
+	      pango_layout_set_text (layout, text, -1);
+	      pango_layout_context_changed (layout);
+	      cairo_save (cr);
+	      if (ruler->orientation == GTK_ORIENTATION_VERTICAL)
+	        {
+		  cairo_translate (cr, x, y);
+		  cairo_rotate (cr, -G_PI/2.0);
+		  cairo_move_to (cr, 2, 0);
+		}
+	      else
+		{
+		  cairo_move_to (cr, x+2, y);
+		}
+	      pango_cairo_show_layout (cr, layout);
+	      cairo_restore (cr);
+	    }
+	}
+      /* arrow */
+      if (ruler->position > ruler->lower && ruler->position < ruler->upper)
+	{
+	  real pos = ruler->position;
+	  if (ruler->orientation == GTK_ORIENTATION_VERTICAL)
+	    {
+	      ddisplay_transform_coords (ruler->ddisp, 0, pos, &x, &y);
+	      cairo_move_to (cr, 3*dx, y);
+	      cairo_line_to (cr,   dx, y - dx);
+	      cairo_line_to (cr,   dx, y + dx);
+	      cairo_fill (cr);
+	    }
+	  else
+	    {
+	      ddisplay_transform_coords (ruler->ddisp, pos, 0, &x, &y);
+	      cairo_move_to (cr, x, 3*dy);
+	      cairo_line_to (cr, x + dy, dy);
+	      cairo_line_to (cr, x - dy, dy);
+	      cairo_fill (cr);
+	    }
+	}
+    }
+  return FALSE;
+}
+
+/* Wrapper can go with Gtk+-3.0 */
+static gboolean
+dia_ruler_expose_event (GtkWidget      *widget,
+                        GdkEventExpose *event)
+{
+  if (gtk_widget_is_drawable (widget))
+    {
+      GdkWindow *window = gtk_widget_get_window(widget);
+      cairo_t *cr = gdk_cairo_create (window);
+
+      dia_ruler_draw (widget, cr);
+
+      cairo_destroy (cr);
+    }
+  return FALSE;
+}
+
+static gboolean
+dia_ruler_motion_notify (GtkWidget      *widget,
+                         GdkEventMotion *event)
+{
+  DiaRuler *ruler = DIA_RULER (widget);
+  gint x;
+  gint y;
+  real tmp;
+
+  gdk_event_request_motions (event);
+  x = event->x;
+  y = event->y;
+
+  if (ruler->orientation == GTK_ORIENTATION_HORIZONTAL)
+    ddisplay_untransform_coords (ruler->ddisp, x, y, &ruler->position, &tmp);
+  else
+    ddisplay_untransform_coords (ruler->ddisp, x, y, &tmp, &ruler->position);
+  /* FIXME: might be a bit too expensive */
+  if (gtk_widget_is_drawable (GTK_WIDGET (ruler)))
+    gtk_widget_queue_draw (GTK_WIDGET (ruler));
+
+  return FALSE;
+}
+
+static void
+dia_ruler_class_init (DiaRulerClass *klass)
+{
+  GtkWidgetClass *widget_class  = GTK_WIDGET_CLASS (klass);
+
+#if GTK_CHECK_VERSION(2,24,0)
+  widget_class->expose_event = dia_ruler_expose_event;
+#endif
+}
+
+static void
+dia_ruler_init (DiaRuler *rule)
+{
+}
+#endif /* GTK_CHECK_VERSION(2.24.0) */
 
 GtkWidget *
-dia_ruler_new (GtkOrientation orientation, GtkWidget *shell)
+dia_ruler_new (GtkOrientation orientation, GtkWidget *shell, DDisplay *ddisp)
 {
-  GtkWidget *rule;
+  GtkWidget *rule = NULL;
+
+#if GTK_CHECK_VERSION(2,24,0)
+  rule = g_object_new (DIA_TYPE_RULER, NULL);
+  /* FIXME: calculate from style settings  */
+  gtk_widget_set_size_request (rule, 15, 15);
+
+  DIA_RULER(rule)->orientation = orientation;
+  DIA_RULER(rule)->ddisp = ddisp;
 
+  gtk_widget_set_events (rule, GDK_EXPOSURE_MASK);
+
+  g_signal_connect_swapped (G_OBJECT (shell), "motion_notify_event",
+                            G_CALLBACK (dia_ruler_motion_notify),
+                            G_OBJECT (rule));
+#else
   if (orientation == GTK_ORIENTATION_HORIZONTAL)
     rule = gtk_hruler_new ();
   else if (orientation == GTK_ORIENTATION_VERTICAL)
@@ -40,15 +230,28 @@ dia_ruler_new (GtkOrientation orientation, GtkWidget *shell)
   g_signal_connect_swapped (G_OBJECT (shell), "motion_notify_event",
                             G_CALLBACK(GTK_WIDGET_GET_CLASS (rule)->motion_notify_event),
                             G_OBJECT (rule));
+#endif
   return rule;
 }
 
 void 
-dia_ruler_set_range (GtkWidget *ruler,
+dia_ruler_set_range (GtkWidget *self,
                      gdouble    lower,
                      gdouble    upper,
                      gdouble    position,
                      gdouble    max_size)
 {
-  gtk_ruler_set_range (GTK_RULER (ruler), lower, upper, position, max_size);
+#if GTK_CHECK_VERSION(2,24,0)
+  DiaRuler *ruler = DIA_RULER(self);
+
+  ruler->lower = lower;
+  ruler->upper = upper;
+  ruler->position = position;
+  ruler->max_size = max_size;
+
+  if (gtk_widget_is_drawable (GTK_WIDGET (ruler)))
+    gtk_widget_queue_draw (GTK_WIDGET (ruler));
+#else
+  gtk_ruler_set_range (GTK_RULER (self), lower, upper, position, max_size);
+#endif
 }
diff --git a/app/ruler.h b/app/ruler.h
index 75c074a..8dc758b 100644
--- a/app/ruler.h
+++ b/app/ruler.h
@@ -1,11 +1,16 @@
 /* prepare deprecation of GtkRuler */
-#include <gtk/gtk.h>
+#ifndef DIA_RULER_H
+#define DIA_RULER_H
+
+#include "display.h"
 
 GtkWidget *dia_ruler_new (GtkOrientation  orientation,
-			  GtkWidget      *shell);
+			  GtkWidget      *shell,
+			  DDisplay       *ddisp);
 
 void dia_ruler_set_range (GtkWidget      *ruler,
                           gdouble         lower,
                           gdouble         upper,
                           gdouble         position,
                           gdouble         max_size);
+#endif



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