[dia] Bug 576548 - Refactoring of highlighting in interactive rendering



commit ec0943877ba6b4adbe975f625380b983ec861ff9
Author: Hans Breuer <hans breuer org>
Date:   Sun Oct 4 19:12:23 2009 +0200

    Bug 576548 - Refactoring of highlighting in interactive rendering
    
    The previous implementation was keeping the state in every object
    (DiaObject::highlight_color) and in the renderer to support it: e.g.
    DiaGdkRenderer::highlight_color. But the real highlighting state is managed by
    the diagram (where it needs to be).
    We got rid of the object knowing about highlight state;  provide methods in
    the InteractiveRenderer interface to perform highlighted rendering and have
    something like a "highlighting selection" (similar to standard selection)
    to manage which object should be rendered highlighted.
    
    From: Heikki Paajanen <hepaajan iki fi>
    Date: Thu, 28 May 2009 18:37:49 +0300
    Subject: Refactoring of highlighting in interactive rendering
    
    https://bugzilla.gnome.org/attachment.cgi?id=135703
    
    From: Hans Breuer <hans breuer org>
    Date: Sat, 30 May 2009 14:07:08 +0200
    Subject: Bug 576548 - Highlighting cleanup second iteration
    
    https://bugzilla.gnome.org/attachment.cgi?id=135704
    
    * app/display.c : don't crash if the renderer does not support highligthing
    * lib/diagramdata.[ch] : renamed some functions and more consistent format
    * app/highlight.c app/object_ops.c : reflect renaming
    * lib/libdia.def : export highlight accessors
    * lib/plug-ins.h : increment API_VERSION, object size changed

 app/create_object.c                 |    2 +-
 app/display.c                       |   10 ++++++-
 app/highlight.c                     |   16 ++--------
 app/highlight.h                     |    2 +-
 app/modify_tool.c                   |   13 ++------
 app/object_ops.c                    |    2 +-
 app/render_gdk.c                    |   43 +++++++++++++++++++++++++++
 app/textedit.c                      |    4 +--
 lib/diagdkrenderer.c                |    9 +----
 lib/diagramdata.c                   |   54 +++++++++++++++++++++++++++++++++++
 lib/diagramdata.h                   |   14 +++++++++
 lib/diainteractiverenderer.c        |    1 +
 lib/diarenderer.h                   |    6 ++++
 lib/libdia.def                      |    3 ++
 lib/object.h                        |    3 --
 lib/plug-ins.h                      |    2 +-
 plug-ins/libart/dialibartrenderer.c |    7 ----
 plug-ins/libart/render_libart.c     |   42 +++++++++++++++++++++++++++
 18 files changed, 187 insertions(+), 46 deletions(-)
---
diff --git a/app/create_object.c b/app/create_object.c
index 4ba1117..f2bf369 100644
--- a/app/create_object.c
+++ b/app/create_object.c
@@ -233,7 +233,7 @@ create_object_motion(CreateObjectTool *tool, GdkEventMotion *event,
     
     if (connectionpoint != NULL) {
       to = connectionpoint->pos;
-      highlight_object(connectionpoint->object, NULL, ddisp->diagram);
+      highlight_object(connectionpoint->object, DIA_HIGHLIGHT_CONNECTIONPOINT, ddisp->diagram);
       ddisplay_set_all_cursor(get_cursor(CURSOR_CONNECT));
     }
   }
diff --git a/app/display.c b/app/display.c
index 343eafd..661d364 100644
--- a/app/display.c
+++ b/app/display.c
@@ -618,7 +618,15 @@ ddisplay_obj_render(DiaObject *obj, DiaRenderer *renderer,
   DDisplay *ddisp = (DDisplay *)data;
   int i;
 
-  DIA_RENDERER_GET_CLASS(renderer)->draw_object(renderer, obj);
+  DiaInteractiveRendererInterface *irenderer =
+    DIA_GET_INTERACTIVE_RENDERER_INTERFACE (renderer);
+  DiaHighlightType hltype = data_object_get_highlight(DIA_DIAGRAM_DATA(ddisp->diagram), obj);
+
+  if (hltype != DIA_HIGHLIGHT_NONE && irenderer->draw_object_highlighted != NULL)
+    irenderer->draw_object_highlighted(renderer, obj, hltype);
+  else /* maybe the renderer does not support highlighting */
+    DIA_RENDERER_GET_CLASS(renderer)->draw_object(renderer, obj);
+
   if (ddisp->show_cx_pts && 
       obj->parent_layer != NULL && obj->parent_layer->connectable) {
     for (i=0;i<obj->num_connections;i++) {
diff --git a/app/highlight.c b/app/highlight.c
index 8100369..61d56b1 100644
--- a/app/highlight.c
+++ b/app/highlight.c
@@ -40,15 +40,10 @@
  * as it knows about the conversion.
  */
 
-static Color red = { 1.0, 0.0, 0.0 };
-
 void
-highlight_object(DiaObject *obj, Color *col, Diagram *dia)
+highlight_object(DiaObject *obj, DiaHighlightType type, Diagram *dia)
 {
-  if (col) 
-    obj->highlight_color = col;
-  else
-    obj->highlight_color = &red;
+  data_highlight_add(dia->data, obj, type);
 
   object_add_updates(obj, dia);
 }
@@ -56,11 +51,8 @@ highlight_object(DiaObject *obj, Color *col, Diagram *dia)
 void
 highlight_object_off(DiaObject *obj, Diagram *dia)
 {
-  if (obj->highlight_color != NULL) {
-    /* Must add updates first, so we get the border erased. */
-    object_add_updates(obj, dia);
-    obj->highlight_color = NULL;
-  }
+  object_add_updates(obj, dia);
+  data_highlight_remove(dia->data, obj);
 }
 
 /** Resets all highlighting in this layer.  Helper function for 
diff --git a/app/highlight.h b/app/highlight.h
index 005bf06..8913de6 100644
--- a/app/highlight.h
+++ b/app/highlight.h
@@ -31,7 +31,7 @@
  * If color is NULL, a standard #FF0000 color (red) is used.
  * The exact method used for highlighting depends on the renderer.
  */
-void highlight_object(DiaObject *obj, Color *col, Diagram *dia);
+void highlight_object(DiaObject *obj, DiaHighlightType type, Diagram *dia);
 /** Remove highlighting from an object.
  */
 void highlight_object_off(DiaObject *obj, Diagram *dia);
diff --git a/app/modify_tool.c b/app/modify_tool.c
index 75525da..6c9af24 100644
--- a/app/modify_tool.c
+++ b/app/modify_tool.c
@@ -414,11 +414,6 @@ modify_move_already(ModifyTool *tool, DDisplay *ddisp, Point *to)
   }
 }
 
-/** Used for highlighting mainpoint connections. */
-static Color mainpoint_color = { 1.0, 0.8, 0.0 };
-/** Used for highlighting normal connections. */
-static Color cp_color = { 1.0, 0.0, 0.0 };
-
 static void
 modify_motion(ModifyTool *tool, GdkEventMotion *event,
 	      DDisplay *ddisp)
@@ -535,14 +530,14 @@ modify_motion(ModifyTool *tool, GdkEventMotion *event,
       connectionpoint =
 	object_find_connectpoint_display(ddisp, &to, tool->object, TRUE);
       if (connectionpoint != NULL) {
-	Color *hi_color;
+        DiaHighlightType type;
 	to = connectionpoint->pos;
 	if (connectionpoint->flags & CP_FLAGS_MAIN) {
-	  hi_color = &mainpoint_color;
+          type = DIA_HIGHLIGHT_CONNECTIONPOINT_MAIN;
 	} else {
-	  hi_color = &cp_color;
+          type = DIA_HIGHLIGHT_CONNECTIONPOINT;
 	}
-	highlight_object(connectionpoint->object, hi_color, ddisp->diagram);
+	highlight_object(connectionpoint->object, type, ddisp->diagram);
 	ddisplay_set_all_cursor(get_cursor(CURSOR_CONNECT));
       }
     }
diff --git a/app/object_ops.c b/app/object_ops.c
index 7daddc1..0096408 100644
--- a/app/object_ops.c
+++ b/app/object_ops.c
@@ -35,7 +35,7 @@ object_add_updates(DiaObject *obj, Diagram *dia)
   int i;
 
   /* Bounding box */
-  if (obj->highlight_color != NULL) {
+  if (data_object_get_highlight(dia->data,obj) != DIA_HIGHLIGHT_NONE) {
     diagram_add_update_with_border(dia, &obj->bounding_box, 5);
   } else {
     diagram_add_update(dia, dia_object_get_enclosing_box (obj));
diff --git a/app/render_gdk.c b/app/render_gdk.c
index 26d1d84..50c7393 100644
--- a/app/render_gdk.c
+++ b/app/render_gdk.c
@@ -23,10 +23,20 @@
 #include <string.h>
 #include <gdk/gdk.h>
 
+#include "object.h"
 #include "message.h"
 #include "render_gdk.h"
 #include "diagdkrenderer.h"
 
+
+/** Used for highlighting mainpoint connections. */
+static Color cp_main_color = { 1.0, 0.8, 0.0 };
+/** Used for highlighting normal connections. */
+static Color cp_color = { 1.0, 0.0, 0.0 };
+
+static Color text_edit_color = {1.0, 1.0, 0.0 };
+
+
 static void clip_region_clear(DiaRenderer *renderer);
 static void clip_region_add_rect(DiaRenderer *renderer,
                                  Rectangle *rect);
@@ -49,6 +59,9 @@ static void set_size (DiaRenderer *renderer,
 static void copy_to_window (DiaRenderer *renderer, 
                 gpointer window,
                 int x, int y, int width, int height);
+static void draw_object_highlighted (DiaRenderer *renderer,
+                                     DiaObject *object,
+                                     DiaHighlightType type);
 
 static void dia_gdk_renderer_iface_init (DiaInteractiveRendererInterface* iface)
 {
@@ -59,6 +72,7 @@ static void dia_gdk_renderer_iface_init (DiaInteractiveRendererInterface* iface)
   iface->fill_pixel_rect = fill_pixel_rect;
   iface->copy_to_window = copy_to_window;
   iface->set_size = set_size;
+  iface->draw_object_highlighted = draw_object_highlighted;
 }
 
 DiaRenderer *
@@ -246,3 +260,32 @@ fill_pixel_rect(DiaRenderer *object,
   gdk_draw_rectangle (renderer->pixmap, gc, TRUE,
 		      x, y,  width, height);
 }
+
+static void
+draw_object_highlighted (DiaRenderer *renderer, DiaObject *object, DiaHighlightType type)
+{
+  DiaGdkRenderer *gdk_rend = DIA_GDK_RENDERER(renderer);
+  Color *color = NULL;
+  switch (type) {
+  case DIA_HIGHLIGHT_CONNECTIONPOINT:
+    color = &cp_color;
+    break;
+  case DIA_HIGHLIGHT_CONNECTIONPOINT_MAIN:
+    color = &cp_main_color;
+    break;
+  case DIA_HIGHLIGHT_TEXT_EDIT:
+    color = &text_edit_color;
+    break;
+  case DIA_HIGHLIGHT_NONE:
+    color = NULL;
+    break;
+  }
+  if( color ) {
+    gdk_rend->highlight_color = color;
+    object->ops->draw(object, renderer);
+    gdk_rend->highlight_color = NULL;
+  }
+
+  object->ops->draw(object, renderer);
+}
+
diff --git a/app/textedit.c b/app/textedit.c
index 64ac322..2df962f 100644
--- a/app/textedit.c
+++ b/app/textedit.c
@@ -124,14 +124,12 @@ textedit_exit(DDisplay *ddisp)
 static void
 textedit_begin_edit(DDisplay *ddisp, Focus *focus)
 {
-  Color *focus_col = color_new_rgb(1.0, 1.0, 0.0);
-  
   g_assert(dia_object_is_selected(focus_get_object(focus)));
   if (!textedit_mode(ddisp)) {
     textedit_enter(ddisp);
   }
   ddisplay_set_active_focus(ddisp, focus);
-  highlight_object(focus->obj, focus_col, ddisp->diagram);
+  highlight_object(focus->obj, DIA_HIGHLIGHT_TEXT_EDIT, ddisp->diagram);
   object_add_updates(focus->obj, ddisp->diagram);
 /* Undo not quite ready yet.
   undo_push_change(ddisp->diagram->undo, text_edit_create_change(focus->text));
diff --git a/lib/diagdkrenderer.c b/lib/diagdkrenderer.c
index 6ccf42f..1e15dde 100644
--- a/lib/diagdkrenderer.c
+++ b/lib/diagdkrenderer.c
@@ -46,6 +46,7 @@
 #include <pango/pangoft2.h>
 #endif
 
+
 static int get_width_pixels (DiaRenderer *);
 static int get_height_pixels (DiaRenderer *);
 
@@ -1056,16 +1057,10 @@ fill_rounded_rect (DiaRenderer *self,
     fill_rect (self, ul_corner, lr_corner, color);
 }
 
+
 static void
 draw_object (DiaRenderer *renderer, DiaObject *object)
 {
-  if (renderer->is_interactive &&
-      object->highlight_color != NULL) {
-    DiaGdkRenderer *gdk_rend = DIA_GDK_RENDERER(renderer);
-    gdk_rend->highlight_color = object->highlight_color;
-    object->ops->draw(object, renderer);
-    gdk_rend->highlight_color = NULL;
-  }
   object->ops->draw(object, renderer);
 }
 
diff --git a/lib/diagramdata.c b/lib/diagramdata.c
index 43f10aa..062bc70 100644
--- a/lib/diagramdata.c
+++ b/lib/diagramdata.c
@@ -45,6 +45,11 @@ enum {
   LAST_SIGNAL
 };
 
+typedef struct {
+  DiaObject *obj;
+  DiaHighlightType type;
+} ObjectHighlight;
+
 static guint diagram_data_signals[LAST_SIGNAL] = { 0, };
 
 static gpointer parent_class = NULL;
@@ -117,6 +122,8 @@ diagram_data_init(DiagramData *data)
 
   data->selected_count_private = 0;
   data->selected = NULL;
+
+  data->highlighted = NULL;
   
   data->is_compressed = compress; /* Overridden by doc */
 
@@ -327,6 +334,53 @@ data_delete_layer(DiagramData *data, Layer *layer)
   }
 }
 
+static ObjectHighlight *
+find_object_highlight(GList *list, DiaObject *obj)
+{
+  ObjectHighlight *oh=NULL;
+  while(list) {
+    oh = (ObjectHighlight*)list->data;
+    if (oh && oh->obj == obj) {
+      return oh;
+    }
+    list = g_list_next(list);
+  }
+  return NULL;
+}
+
+void 
+data_highlight_add(DiagramData *data, DiaObject *obj, DiaHighlightType type)
+{
+  ObjectHighlight *oh;
+  if (find_object_highlight (data->highlighted, obj))
+    return; /* should this be an error?`*/
+  oh = g_malloc(sizeof(ObjectHighlight));
+  oh->obj = obj;
+  oh->type = type;
+  data->highlighted = g_list_prepend(data->highlighted, oh);
+}
+
+void 
+data_highlight_remove(DiagramData *data, DiaObject *obj)
+{
+  ObjectHighlight *oh;
+  if (!(oh = find_object_highlight (data->highlighted, obj)))
+    return; /* should this be an error?`*/
+  data->highlighted = g_list_remove(data->highlighted, oh);
+  g_free(oh);
+}
+
+DiaHighlightType 
+data_object_get_highlight(DiagramData *data, DiaObject *obj)
+{
+  ObjectHighlight *oh;
+  DiaHighlightType type = DIA_HIGHLIGHT_NONE;
+  if (oh = find_object_highlight (data->highlighted, obj)) {
+    type = oh->type;
+  }
+  return type;
+}
+
 /** Select an object in a diagram.  Note that this does not unselect other
  *  objects currently selected in the diagram.
  * @param data The diagram to select in.
diff --git a/lib/diagramdata.h b/lib/diagramdata.h
index eb37f8b..3e3c296 100644
--- a/lib/diagramdata.h
+++ b/lib/diagramdata.h
@@ -82,6 +82,9 @@ struct _DiagramData {
   /** The focus (from text_edits) that's currently being edited, if any.
    *  Updated by focus.c */
   Focus *active_text_edit;
+
+  GList *highlighted;        /*!< List of objects that are highlighted */
+
 };
 
 /**
@@ -120,6 +123,13 @@ struct _Layer {
 				  layer_get_parent_diagram() */
 };
 
+typedef enum {
+  DIA_HIGHLIGHT_NONE,
+  DIA_HIGHLIGHT_CONNECTIONPOINT,
+  DIA_HIGHLIGHT_CONNECTIONPOINT_MAIN,
+  DIA_HIGHLIGHT_TEXT_EDIT
+} DiaHighlightType;
+
 Layer *new_layer (char *name, DiagramData *parent);
 void layer_destroy(Layer *layer);
 
@@ -134,6 +144,10 @@ int  data_layer_get_index (const DiagramData *data, const Layer *layer);
 int data_layer_count(const DiagramData *data);
 Layer *data_layer_get_nth (const DiagramData *data, guint index);
 
+void data_highlight_add(DiagramData *data, DiaObject *obj, DiaHighlightType type);
+void data_highlight_remove(DiagramData *data, DiaObject *obj);
+DiaHighlightType data_object_get_highlight(DiagramData *data, DiaObject *obj);
+
 void data_select(DiagramData *data, DiaObject *obj);
 void data_unselect(DiagramData *data, DiaObject *obj);
 void data_remove_all_selected(DiagramData *data);
diff --git a/lib/diainteractiverenderer.c b/lib/diainteractiverenderer.c
index 7d13209..0419797 100644
--- a/lib/diainteractiverenderer.c
+++ b/lib/diainteractiverenderer.c
@@ -33,6 +33,7 @@ dia_interactive_renderer_iface_init (DiaInteractiveRendererInterface *iface)
   iface->fill_pixel_rect = NULL;
   iface->copy_to_window = NULL;
   iface->set_size = NULL;
+  iface->draw_object_highlighted = NULL;
 }
 
 GType
diff --git a/lib/diarenderer.h b/lib/diarenderer.h
index a903bfd..22fda68 100644
--- a/lib/diarenderer.h
+++ b/lib/diarenderer.h
@@ -27,6 +27,8 @@
 #include "geometry.h"
 #include "font.h" /* not strictly needed by this header, but needed in almost any plug-in/ */
 
+#include "diagramdata.h"
+
 G_BEGIN_DECLS
 
 /*! GObject boiler plate, create runtime information */
@@ -289,6 +291,10 @@ struct _DiaInteractiveRendererInterface
   void (*copy_to_window)      (DiaRenderer *renderer,
                                gpointer     window, 
                                int x, int y, int width, int height);
+
+  void (*draw_object_highlighted) (DiaRenderer *renderer,
+				   DiaObject *object,
+				   DiaHighlightType type);
 };
 
 GType dia_interactive_renderer_interface_get_type (void) G_GNUC_CONST;
diff --git a/lib/libdia.def b/lib/libdia.def
index b6b9db8..e417c8b 100644
--- a/lib/libdia.def
+++ b/lib/libdia.def
@@ -150,6 +150,9 @@ EXPORTS
  data_foreach_object
  data_get_sorted_selected
  data_get_sorted_selected_remove
+ data_highlight_add
+ data_highlight_remove
+ data_object_get_highlight 
  data_int
  data_layer_count
  data_layer_get_index
diff --git a/lib/object.h b/lib/object.h
index 0ad570b..1fbdb4c 100644
--- a/lib/object.h
+++ b/lib/object.h
@@ -489,9 +489,6 @@ struct _DiaObject {
   GList *children; /*!< In case this object is a parent of other object the children are listed here */
   gint flags; /*!< Various flags that can be set for this object, see defines above */
 
-  Color *highlight_color; /*!< The color that this object is currently
-			       highlighted with, or NULL if it is not 
-			       highlighted. */
   /** The area that contains all parts rendered interactively, so includes
    *  handles, bezier controllers etc.  Despite historical difference, this
    *  should not be accessed directly, but through dia_object_get_bounding_box().
diff --git a/lib/plug-ins.h b/lib/plug-ins.h
index a2ec0ce..902901f 100644
--- a/lib/plug-ins.h
+++ b/lib/plug-ins.h
@@ -48,7 +48,7 @@ G_BEGIN_DECLS
  * The list is by no means complete. If in doubt about your change
  * please ask on dia-list or alternative increment ;-)      --hb
  */
-#define DIA_PLUGIN_API_VERSION 13
+#define DIA_PLUGIN_API_VERSION 14
 
 typedef enum {
   DIA_PLUGIN_INIT_OK,
diff --git a/plug-ins/libart/dialibartrenderer.c b/plug-ins/libart/dialibartrenderer.c
index 5f30962..5f12d46 100644
--- a/plug-ins/libart/dialibartrenderer.c
+++ b/plug-ins/libart/dialibartrenderer.c
@@ -1329,13 +1329,6 @@ draw_image(DiaRenderer *self,
 static void
 draw_object (DiaRenderer *renderer, DiaObject *object)
 {
-  if (renderer->is_interactive &&
-      object->highlight_color != NULL) {
-    DiaLibartRenderer *libart_rend = DIA_LIBART_RENDERER(renderer);
-    libart_rend->highlight_color = object->highlight_color;
-    object->ops->draw(object, renderer);
-    libart_rend->highlight_color = NULL;
-  }
   object->ops->draw(object, renderer);
 }
 
diff --git a/plug-ins/libart/render_libart.c b/plug-ins/libart/render_libart.c
index e34a2f5..bcf7c3c 100644
--- a/plug-ins/libart/render_libart.c
+++ b/plug-ins/libart/render_libart.c
@@ -26,11 +26,20 @@
 
 #ifdef HAVE_LIBART
 
+#include "object.h"
 #include "dialibartrenderer.h"
 #include <libart_lgpl/art_rgb.h>
 #include "font.h"
 #include "color.h"
 
+/** Used for highlighting mainpoint connections. */
+static Color cp_main_color = { 1.0, 0.8, 0.0 };
+/** Used for highlighting normal connections. */
+static Color cp_color = { 1.0, 0.0, 0.0 };
+
+static Color text_edit_color = {1.0, 1.0, 0.0 };
+
+
 static void clip_region_clear(DiaRenderer *self);
 static void clip_region_add_rect(DiaRenderer *self,
 				 Rectangle *rect);
@@ -51,6 +60,9 @@ static void set_size(DiaRenderer *self, gpointer window,
                      int width, int height);
 static void copy_to_window (DiaRenderer *self, gpointer window,
                             int x, int y, int width, int height);
+static void draw_object_highlighted (DiaRenderer *renderer,
+                                     DiaObject *object,
+                                     DiaHighlightType type);
 
 
 void 
@@ -63,6 +75,7 @@ dia_libart_renderer_iface_init (DiaInteractiveRendererInterface* iface)
   iface->fill_pixel_rect = fill_pixel_rect;
   iface->copy_to_window = copy_to_window;
   iface->set_size = set_size;
+  iface->draw_object_highlighted = draw_object_highlighted;
 }
 
 
@@ -460,6 +473,35 @@ fill_pixel_rect(DiaRenderer *self,
   }
 }
 
+
+static void
+draw_object_highlighted (DiaRenderer *renderer, DiaObject *object, DiaHighlightType type)
+{
+  DiaLibartRenderer *libart_rend = DIA_LIBART_RENDERER(renderer);
+  Color *color = NULL;
+  switch (type) {
+  case DIA_HIGHLIGHT_CONNECTIONPOINT:
+    color = &cp_color;
+    break;
+  case DIA_HIGHLIGHT_CONNECTIONPOINT_MAIN:
+    color = &cp_main_color;
+    break;
+  case DIA_HIGHLIGHT_TEXT_EDIT:
+    color = &text_edit_color;
+    break;
+  case DIA_HIGHLIGHT_NONE:
+    color = NULL;
+    break;
+  }
+  if( color ) {
+    libart_rend->highlight_color = color;
+    object->ops->draw(object, renderer);
+    libart_rend->highlight_color = NULL;
+  }
+
+  object->ops->draw(object, renderer);
+}
+
 #else
 
 DiaRenderer *



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