[dia/zbrown/test-build: 2/6] canvas: move core parts of canvas to a new DiaCanvas type




commit eac8ee8df138a2532b3723a528d60266aa4fc968
Author: Zander Brown <zbrown gnome org>
Date:   Thu Sep 23 22:07:08 2021 +0100

    canvas: move core parts of canvas to a new DiaCanvas type
    
    Override the vfuncs directly instead of connecting to signals
    
    Add a gtk3 stub

 app/dia-canvas.c  | 327 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 app/dia-canvas.h  |  35 ++++++
 app/interface.c   | 177 +----------------------------
 app/interface.h   |  17 ++-
 app/meson.build   |   2 +
 lib/dia-autoptr.h |   1 +
 6 files changed, 383 insertions(+), 176 deletions(-)
---
diff --git a/app/dia-canvas.c b/app/dia-canvas.c
new file mode 100644
index 000000000..306d0b403
--- /dev/null
+++ b/app/dia-canvas.c
@@ -0,0 +1,327 @@
+/* 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
+ */
+
+#include "config.h"
+
+#include <glib/gi18n-lib.h>
+#include <gtk/gtk.h>
+
+#include "dia-canvas.h"
+#include "disp_callbacks.h"
+#include "toolbox.h"
+#include "diainteractiverenderer.h"
+#include "interface.h"
+#include "object.h"
+
+struct _DiaCanvas {
+  GtkDrawingArea parent;
+
+  DDisplay *display;
+};
+
+G_DEFINE_TYPE (DiaCanvas, dia_canvas, GTK_TYPE_DRAWING_AREA)
+
+
+enum {
+  PROP_0,
+  PROP_DISPLAY,
+  LAST_PROP
+};
+static GParamSpec *pspecs[LAST_PROP] = { NULL, };
+
+
+static void
+dia_canvas_set_property (GObject      *object,
+                         guint         property_id,
+                         const GValue *value,
+                         GParamSpec   *pspec)
+{
+  DiaCanvas *self = DIA_CANVAS (object);
+
+  switch (property_id) {
+    case PROP_DISPLAY:
+      self->display = g_value_get_pointer (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+  }
+}
+
+
+static void
+dia_canvas_get_property (GObject    *object,
+                         guint       property_id,
+                         GValue     *value,
+                         GParamSpec *pspec)
+{
+  DiaCanvas *self = DIA_CANVAS (object);
+
+  switch (property_id) {
+    case PROP_DISPLAY:
+      g_value_set_pointer (value, self->display);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+  }
+}
+
+
+/*!
+ * Called when the widget's window "size, position or stacking"
+ * changes. Needs GDK_STRUCTURE_MASK set.
+ */
+static gboolean
+dia_canvas_configure_event (GtkWidget *widget, GdkEventConfigure *cevent)
+{
+  DiaCanvas *self = DIA_CANVAS (widget);
+  gboolean new_size = FALSE;
+  int width, height;
+  DiaRenderer *renderer;
+
+  g_return_val_if_fail (self->display, FALSE);
+  g_return_val_if_fail (widget == self->display->canvas, FALSE);
+
+  renderer = self->display->renderer;
+
+  if (renderer) {
+    width = dia_interactive_renderer_get_width_pixels (DIA_INTERACTIVE_RENDERER (renderer));
+    height = dia_interactive_renderer_get_height_pixels (DIA_INTERACTIVE_RENDERER (renderer));
+  } else {
+    /* We can continue even without a renderer here because
+     * ddisplay_resize_canvas () does the setup for us.
+     */
+    width = height = 0;
+  }
+
+  /* Only do this when size is really changing */
+  if (width != cevent->width || height != cevent->height) {
+    g_debug ("%s: Canvas size change...", G_STRLOC);
+    ddisplay_resize_canvas (self->display, cevent->width, cevent->height);
+    ddisplay_update_scrollbars (self->display);
+    /* on resize stop further propagation - does not help */
+    new_size = TRUE;
+  }
+
+  /* If the UI is not integrated, resizing should set the resized
+   * window as active.  With integrated UI, there is only one window.
+   */
+  if (is_integrated_ui () == 0) {
+    display_set_active (self->display);
+  }
+
+  /* continue propagation with FALSE */
+  return new_size;
+}
+
+
+static gboolean
+dia_canvas_draw (GtkWidget *widget, cairo_t *ctx)
+{
+  DiaCanvas *self = DIA_CANVAS (widget);
+  GSList *l;
+  DiaRectangle *r, totrect;
+  GtkAllocation alloc;
+  DiaRenderer *renderer;
+
+  g_return_val_if_fail (self->display, FALSE);
+  g_return_val_if_fail (self->display->renderer != NULL, FALSE);
+
+  renderer = self->display->renderer;
+
+  /* Only update if update_areas exist */
+  l = self->display->update_areas;
+  if (l != NULL) {
+    totrect = *(DiaRectangle *) l->data;
+
+    dia_interactive_renderer_clip_region_clear (DIA_INTERACTIVE_RENDERER (renderer));
+
+    while ( l!= NULL) {
+      r = (DiaRectangle *) l->data;
+
+      rectangle_union (&totrect, r);
+      dia_interactive_renderer_clip_region_add_rect (DIA_INTERACTIVE_RENDERER (renderer), r);
+
+      l = g_slist_next (l);
+    }
+    /* Free update_areas list: */
+    g_slist_free_full (self->display->update_areas, g_free);
+    self->display->update_areas = NULL;
+
+    totrect.left -= 0.1;
+    totrect.right += 0.1;
+    totrect.top -= 0.1;
+    totrect.bottom += 0.1;
+
+    ddisplay_render_pixmap (self->display, &totrect);
+  }
+
+  gtk_widget_get_allocation (widget, &alloc);
+
+  dia_interactive_renderer_paint (DIA_INTERACTIVE_RENDERER (renderer),
+                                  ctx,
+                                  alloc.width,
+                                  alloc.height);
+
+  return FALSE;
+}
+
+
+#if !GTK_CHECK_VERSION (3, 0, 0)
+static gboolean
+dia_canvas_expose_event (GtkWidget *widget, GdkEventExpose *event)
+{
+  cairo_t *ctx;
+  gboolean res;
+
+  ctx = gdk_cairo_create (GDK_DRAWABLE (gtk_widget_get_window (widget)));
+
+  res = dia_canvas_draw (widget, ctx);
+
+  cairo_destroy (ctx);
+
+  return res;
+}
+#endif
+
+
+static gboolean
+dia_canvas_event (GtkWidget *widget, GdkEvent *event)
+{
+  DiaCanvas *self = DIA_CANVAS (widget);
+
+  return ddisplay_canvas_events (widget, event, self->display);
+}
+
+
+static gboolean
+dia_canvas_drag_drop (GtkWidget      *widget,
+                      GdkDragContext *context,
+                      int             x,
+                      int             y,
+                      guint           time)
+{
+  if (gtk_drag_get_source_widget (context) != NULL) {
+    /* we only accept drops from the same instance of the application,
+     * as the drag data is a pointer in our address space */
+    return TRUE;
+  }
+
+  gtk_drag_finish (context, FALSE, FALSE, time);
+
+  return FALSE;
+}
+
+
+static void
+dia_canvas_drag_data_received (GtkWidget        *widget,
+                               GdkDragContext   *context,
+                               int               x,
+                               int               y,
+                               GtkSelectionData *data,
+                               guint             info,
+                               guint             time)
+{
+  DiaCanvas *self = DIA_CANVAS (widget);
+
+  if (gtk_selection_data_get_format (data) == 8 &&
+      gtk_selection_data_get_length (data) == sizeof (ToolButtonData *) &&
+      gtk_drag_get_source_widget(context) != NULL) {
+    ToolButtonData *tooldata = *(ToolButtonData **) gtk_selection_data_get_data (data);
+
+    ddisplay_drop_object (self->display,
+                          x,
+                          y,
+                          object_get_type ((char *) tooldata->extra_data),
+                          tooldata->user_data);
+
+    gtk_drag_finish (context, TRUE, FALSE, time);
+  } else {
+    dia_dnd_file_drag_data_received (widget,
+                                     context,
+                                     x,
+                                     y,
+                                     data,
+                                     info,
+                                     time,
+                                     self->display);
+  }
+
+  /* ensure the right window has the focus for text editing */
+  gtk_window_present (GTK_WINDOW (self->display->shell));
+}
+
+
+static void
+dia_canvas_class_init (DiaCanvasClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  object_class->set_property = dia_canvas_set_property;
+  object_class->get_property = dia_canvas_get_property;
+
+  widget_class->configure_event = dia_canvas_configure_event;
+#if GTK_CHECK_VERSION (3, 0, 0)
+  widget_class->draw = dia_canvas_draw;
+#else
+  widget_class->expose_event = dia_canvas_expose_event;
+#endif
+  widget_class->event = dia_canvas_event;
+  widget_class->drag_drop = dia_canvas_drag_drop;
+  widget_class->drag_data_received = dia_canvas_drag_data_received;
+
+  pspecs[PROP_DISPLAY] =
+    g_param_spec_pointer ("display",
+                          "Display",
+                          "The DDisplay",
+                          G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
+
+  g_object_class_install_properties (object_class, LAST_PROP, pspecs);
+}
+
+
+static void
+dia_canvas_init (DiaCanvas *self)
+{
+  gtk_widget_set_events (GTK_WIDGET (self),
+                         GDK_EXPOSURE_MASK |
+                         GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK |
+                         GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
+                         GDK_STRUCTURE_MASK | GDK_ENTER_NOTIFY_MASK |
+                         GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK);
+
+  gtk_widget_set_can_focus (GTK_WIDGET (self), TRUE);
+
+}
+
+
+GtkWidget *
+dia_canvas_new (DDisplay *ddisp)
+{
+  GtkWidget *self = g_object_new (DIA_TYPE_CANVAS,
+                                  "display", ddisp,
+                                  NULL);
+
+  g_object_set_data (G_OBJECT (self), "user_data", (gpointer) ddisp);
+
+  return self;
+}
diff --git a/app/dia-canvas.h b/app/dia-canvas.h
new file mode 100644
index 000000000..30c216927
--- /dev/null
+++ b/app/dia-canvas.h
@@ -0,0 +1,35 @@
+/* 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
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "dia-autoptr.h"
+#include "display.h"
+
+G_BEGIN_DECLS
+
+#define DIA_TYPE_CANVAS dia_canvas_get_type ()
+G_DECLARE_FINAL_TYPE (DiaCanvas, dia_canvas, DIA, CANVAS, GtkDrawingArea)
+
+GtkWidget *dia_canvas_new                   (DDisplay               *ddisp);
+
+G_END_DECLS
diff --git a/app/interface.c b/app/interface.c
index 2dcdd2554..79eab1831 100644
--- a/app/interface.c
+++ b/app/interface.c
@@ -30,6 +30,7 @@
 #include <stdio.h>
 #include <string.h>
 
+#include "dia-canvas.h"
 #include "diagram.h"
 #include "object.h"
 #include "layer-editor/layer_dialog.h"
@@ -80,7 +81,7 @@ static gboolean _ddisplay_vruler_motion_notify (GtkWidget *widget,
         DDisplay *ddisp);
 
 
-static void
+void
 dia_dnd_file_drag_data_received (GtkWidget        *widget,
                                  GdkDragContext   *context,
                                  int               x,
@@ -335,51 +336,6 @@ create_zoom_widget(DDisplay *ddisp) {
 }
 
 
-static gboolean
-display_drop_callback (GtkWidget      *widget,
-                       GdkDragContext *context,
-                       int             x,
-                       int             y,
-                       guint           time)
-{
-  if (gtk_drag_get_source_widget(context) != NULL) {
-    /* we only accept drops from the same instance of the application,
-     * as the drag data is a pointer in our address space */
-    return TRUE;
-  }
-  gtk_drag_finish (context, FALSE, FALSE, time);
-  return FALSE;
-}
-
-
-static void
-display_data_received_callback (GtkWidget        *widget,
-                                GdkDragContext   *context,
-                                int               x,
-                                int               y,
-                                GtkSelectionData *data,
-                                guint             info,
-                                guint             time,
-                                DDisplay         *ddisp)
-{
-  if (gtk_selection_data_get_format(data) == 8 &&
-      gtk_selection_data_get_length(data) == sizeof(ToolButtonData *) &&
-      gtk_drag_get_source_widget(context) != NULL) {
-    ToolButtonData *tooldata = *(ToolButtonData **)gtk_selection_data_get_data(data);
-    /* g_message("Tool drop %s at (%d, %d)", (gchar *)tooldata->extra_data, x, y);*/
-    ddisplay_drop_object(ddisp, x, y,
-                        object_get_type((gchar *)tooldata->extra_data),
-                        tooldata->user_data);
-
-    gtk_drag_finish (context, TRUE, FALSE, time);
-  } else {
-    dia_dnd_file_drag_data_received (widget, context, x, y, data, info, time, ddisp);
-  }
-  /* ensure the right window has the focus for text editing */
-  gtk_window_present(GTK_WINDOW(ddisp->shell));
-}
-
-
 /**
  * close_notebook_page_callback:
  * @button: The notebook close button.
@@ -414,131 +370,6 @@ notebook_switch_page (GtkNotebook *notebook,
   gtk_widget_grab_focus (ddisp->canvas);
 }
 
-/*!
- * Called when the widget's window "size, position or stacking"
- * changes. Needs GDK_STRUCTURE_MASK set.
- */
-static gboolean
-canvas_configure_event (GtkWidget         *widget,
-                        GdkEventConfigure *cevent,
-                        DDisplay          *ddisp)
-{
-  gboolean new_size = FALSE;
-  int width, height;
-
-  g_return_val_if_fail (widget == ddisp->canvas, FALSE);
-
-  if (ddisp->renderer) {
-    width = dia_interactive_renderer_get_width_pixels (DIA_INTERACTIVE_RENDERER (ddisp->renderer));
-    height = dia_interactive_renderer_get_height_pixels (DIA_INTERACTIVE_RENDERER (ddisp->renderer));
-  } else {
-    /* We can continue even without a renderer here because
-     * ddisplay_resize_canvas () does the setup for us.
-     */
-    width = height = 0;
-  }
-
-  /* Only do this when size is really changing */
-  if (width != cevent->width || height != cevent->height) {
-    g_debug ("%s: Canvas size change...", G_STRLOC);
-    ddisplay_resize_canvas (ddisp, cevent->width, cevent->height);
-    ddisplay_update_scrollbars (ddisp);
-    /* on resize stop further propagation - does not help */
-    new_size = TRUE;
-  }
-
-  /* If the UI is not integrated, resizing should set the resized
-   * window as active.  With integrated UI, there is only one window.
-   */
-  if (is_integrated_ui () == 0) {
-    display_set_active (ddisp);
-  }
-
-  /* continue propagation with FALSE */
-  return new_size;
-}
-
-static gboolean
-canvas_expose_event (GtkWidget      *widget,
-                     GdkEventExpose *event,
-                     DDisplay       *ddisp)
-{
-  GSList *l;
-  DiaRectangle *r, totrect;
-  GtkAllocation alloc;
-  cairo_t *ctx;
-
-  ctx = gdk_cairo_create (gtk_widget_get_window (widget));
-
-  g_return_val_if_fail (ddisp->renderer != NULL, FALSE);
-
-  /* Only update if update_areas exist */
-  l = ddisp->update_areas;
-  if (l != NULL) {
-    totrect = *(DiaRectangle *) l->data;
-
-    dia_interactive_renderer_clip_region_clear (DIA_INTERACTIVE_RENDERER (ddisp->renderer));
-
-    while ( l!= NULL) {
-      r = (DiaRectangle *) l->data;
-
-      rectangle_union (&totrect, r);
-      dia_interactive_renderer_clip_region_add_rect (DIA_INTERACTIVE_RENDERER (ddisp->renderer), r);
-
-      l = g_slist_next (l);
-    }
-    /* Free update_areas list: */
-    g_slist_free_full (ddisp->update_areas, g_free);
-    ddisp->update_areas = NULL;
-
-    totrect.left -= 0.1;
-    totrect.right += 0.1;
-    totrect.top -= 0.1;
-    totrect.bottom += 0.1;
-
-    ddisplay_render_pixmap (ddisp, &totrect);
-  }
-
-  gtk_widget_get_allocation (widget, &alloc);
-
-  dia_interactive_renderer_paint (DIA_INTERACTIVE_RENDERER (ddisp->renderer),
-                                  ctx,
-                                  alloc.width,
-                                  alloc.height);
-
-  return FALSE;
-}
-
-static GtkWidget *
-create_canvas (DDisplay *ddisp)
-{
-  GtkWidget *canvas = gtk_drawing_area_new();
-
-  gtk_widget_set_can_focus (canvas, TRUE);
-
-  gtk_widget_set_events (canvas,
-                         GDK_EXPOSURE_MASK |
-                         GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK |
-                         GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
-                         GDK_STRUCTURE_MASK | GDK_ENTER_NOTIFY_MASK |
-                         GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK);
-  g_signal_connect (G_OBJECT (canvas), "configure-event",
-                    G_CALLBACK (canvas_configure_event), ddisp);
-  g_signal_connect (G_OBJECT (canvas), "expose-event",
-                    G_CALLBACK (canvas_expose_event), ddisp);
-  gtk_widget_set_can_focus (canvas, TRUE);
-  g_signal_connect (G_OBJECT (canvas), "event",
-                    G_CALLBACK (ddisplay_canvas_events), ddisp);
-
-  canvas_setup_drag_dest (canvas);
-  g_signal_connect (G_OBJECT (canvas), "drag_drop",
-                    G_CALLBACK (display_drop_callback), NULL);
-  g_signal_connect (G_OBJECT (canvas), "drag_data_received",
-                    G_CALLBACK (display_data_received_callback), ddisp);
-  g_object_set_data (G_OBJECT (canvas), "user_data", (gpointer) ddisp);
-
-  return canvas;
-}
 
 /* Shared helper functions for both UI cases
  */
@@ -740,7 +571,7 @@ use_integrated_ui_for_display_shell (DDisplay *ddisp, char *title)
   _ddisplay_setup_scrollbars (ddisp, table, width, height);
   _ddisplay_setup_navigation (ddisp, table, TRUE);
 
-  ddisp->canvas = create_canvas (ddisp);
+  ddisp->canvas = dia_canvas_new (ddisp);
 
   /*  place all remaining widgets (no 'origin' anymore, since navigation is top-left */
   gtk_table_attach (GTK_TABLE (table), ddisp->canvas, 1, 2, 1, 2,
@@ -871,7 +702,7 @@ create_display_shell (DDisplay *ddisp,
   _ddisplay_setup_scrollbars (ddisp, table, width, height);
   _ddisplay_setup_navigation (ddisp, table, FALSE);
 
-  ddisp->canvas = create_canvas (ddisp);
+  ddisp->canvas = dia_canvas_new (ddisp);
 
   /*  pack all remaining widgets  */
   gtk_table_attach (GTK_TABLE (table), ddisp->origin, 0, 1, 0, 1,
diff --git a/app/interface.h b/app/interface.h
index 9396efc85..1d6593607 100644
--- a/app/interface.h
+++ b/app/interface.h
@@ -15,13 +15,15 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
-#ifndef INTERFACE_H
-#define INTERFACE_H
+
+#pragma once
 
 #include "display.h"
 
 #include "app_procs.h"
 
+G_BEGIN_DECLS
+
 /* Integrated UI Constants */
 #define  DIA_MAIN_WINDOW   "dia-main-window"
 #define  DIA_MAIN_NOTEBOOK "dia-main-notebook"
@@ -59,4 +61,13 @@ void close_notebook_page_callback (GtkButton *button, gpointer user_data);
 
 double parse_zoom (const char *zoom);
 
-#endif /* INTERFACE_H */
+void   dia_dnd_file_drag_data_received (GtkWidget        *widget,
+                                        GdkDragContext   *context,
+                                        int               x,
+                                        int               y,
+                                        GtkSelectionData *data,
+                                        guint             info,
+                                        guint             time,
+                                        DDisplay         *ddisp);
+
+G_END_DECLS
diff --git a/app/meson.build b/app/meson.build
index 694bc6425..2b09b964d 100644
--- a/app/meson.build
+++ b/app/meson.build
@@ -11,6 +11,8 @@ dia_sources = [
 
     'dia-builder.c',
     'dia-builder.h',
+    'dia-canvas.c',
+    'dia-canvas.h',
 
     'layer-editor/dia-layer-list.c',
     'layer-editor/dia-layer-list.h',
diff --git a/lib/dia-autoptr.h b/lib/dia-autoptr.h
index 5508030c5..d47c0306f 100644
--- a/lib/dia-autoptr.h
+++ b/lib/dia-autoptr.h
@@ -32,6 +32,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (GtkSpinButton, g_object_unref)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC (GtkComboBox, g_object_unref)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC (GtkHBox, g_object_unref)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC (GtkTreeView, g_object_unref)
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (GtkDrawingArea, g_object_unref)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC (GtkCellRenderer, g_object_unref)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC (GtkCellRendererText, g_object_unref)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC (GtkBin, g_object_unref)


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