[dia] Initial implementation of diagram-as-element (embedding diagrams)



commit fbe3937bb67c0cb450f54f44ed176e8a90bfcd27
Author: Hans Breuer <hans breuer org>
Date:   Sat Oct 3 15:58:13 2009 +0200

    Initial implementation of diagram-as-element (embedding diagrams)
    
    TODO:
     - extend the renderer interface to get rid of the extra DiaImage,
       at least for some renderers (DiaRenderer::set_matrix?)
     - the image gets updated too often, something wrong with mtime check?
     - make diagrams directly selecteable in the properties dialog file entry
     - allow to open the diagram stand-alone by context menu
     - make new object available in the Misc sheet

 objects/Misc/Makefile.am                    |    2 +
 objects/Misc/diagram_as_object.c            |  319 +++++++++++++++++++++++++++
 objects/Misc/libmisc.c                      |    2 +
 objects/Misc/pixmaps/diagram_as_element.xpm |  231 +++++++++++++++++++
 objects/makefile.msc                        |    1 +
 5 files changed, 555 insertions(+), 0 deletions(-)
---
diff --git a/objects/Misc/Makefile.am b/objects/Misc/Makefile.am
index f09b34f..0dd48ff 100644
--- a/objects/Misc/Makefile.am
+++ b/objects/Misc/Makefile.am
@@ -4,6 +4,7 @@ pkglib_LTLIBRARIES = 	libmisc_objects.la
 libmisc_objects_la_SOURCES = \
 			libmisc.c \
 			analog_clock.c \
+			diagram_as_object.c \
 			grid_object.c \
 			measure.c \
 			tree.c
@@ -16,6 +17,7 @@ INCLUDES = -I$(top_srcdir)/intl -I$(srcdir)/../../lib \
 
 EXTRA_DIST = \
 	pixmaps/analog_clock.xpm \
+	pixmaps/diagram_as_element.xpm \
 	pixmaps/grid_object.xpm \
 	pixmaps/measure.xpm \
 	pixmaps/newgroup.xpm \
diff --git a/objects/Misc/diagram_as_object.c b/objects/Misc/diagram_as_object.c
new file mode 100644
index 0000000..0dd5ada
--- /dev/null
+++ b/objects/Misc/diagram_as_object.c
@@ -0,0 +1,319 @@
+/* Dia -- an diagram creation/manipulation program
+ * Copyright (C) 1998 Alexander Larsson
+ *
+ * diagram_as_object.c -- embedding diagrams
+ * Copyright (C) 2009  Hans Breuer, <Hans Breuer Org>
+ *
+ * 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.
+ */
+#include <config.h>
+
+#include <time.h>
+#ifdef HAVE_UTIME_H
+#  include <utime.h>
+#else
+#  include <sys/utime.h>
+#endif
+#include <glib.h>
+#ifdef G_OS_WIN32
+#include <io.h> /* close */
+#endif
+#include <glib/gstdio.h>
+
+#include "object.h"
+#include "diarenderer.h"
+#include "attributes.h"
+#include "properties.h"
+#include "boundingbox.h"
+#include "element.h"
+#include "diagramdata.h"
+#include "filter.h"
+#include "intl.h"
+
+#include "filter.h"
+#include "dia_image.h"
+
+#include "pixmaps/diagram_as_element.xpm"
+
+#define DEFAULT_WIDTH 2.0
+#define DEFAULT_HEIGHT 2.0
+#define NUM_CONNECTIONS 9
+/* Object definition */
+typedef struct _DiagramAsElement {
+  Element element;
+
+  ConnectionPoint connections[NUM_CONNECTIONS];
+
+  Color border_color;
+  real border_line_width;
+  Color inner_color;
+  gboolean show_background;
+
+  gchar *filename;
+  time_t mtime;
+  DiagramData *data;
+
+  /* for indirect rendering*/
+  DiaImage *image;
+  
+  real scale;
+} DiagramAsElement;
+
+static DiaObject *
+_dae_create (Point *startpoint,
+	     void *user_data,
+	     Handle **handle1,
+	     Handle **handle2);
+
+static ObjectTypeOps _dae_type_ops =
+{
+  (CreateFunc) _dae_create,
+  (LoadFunc)   object_load_using_properties,
+  (SaveFunc)   object_save_using_properties,
+  (GetDefaultsFunc)   NULL,
+  (ApplyDefaultsFunc) NULL
+};
+
+DiaObjectType diagram_as_element_type =
+{
+  "Misc - Diagram",  /* name */
+  0,                 /* version */
+  (char **) diagram_as_element_xpm, /* pixmap */
+  
+  &_dae_type_ops      /* ops */
+};
+
+static void _dae_update_data (DiagramAsElement *dae);
+
+static PropDescription _dae_props[] = {
+  ELEMENT_COMMON_PROPERTIES,
+  PROP_STD_LINE_WIDTH,
+  PROP_STD_LINE_COLOUR,
+  PROP_STD_FILL_COLOUR,
+  PROP_STD_SHOW_BACKGROUND,
+  { "diagram_file", PROP_TYPE_FILE, PROP_FLAG_VISIBLE,
+    N_("Diagram file"), NULL, NULL},
+  PROP_DESC_END
+};
+static PropDescription *
+_dae_describe_props(DiagramAsElement *dae)
+{
+  if (_dae_props[0].quark == 0)
+    prop_desc_list_calculate_quarks(_dae_props);
+  return _dae_props;
+}
+static PropOffset _dae_offsets[] = {
+  ELEMENT_COMMON_PROPERTIES_OFFSETS,
+  { PROP_STDNAME_LINE_WIDTH, PROP_STDTYPE_LINE_WIDTH, offsetof(DiagramAsElement, border_line_width) },
+  { "line_colour", PROP_TYPE_COLOUR, offsetof(DiagramAsElement, border_color) },
+  { "fill_colour", PROP_TYPE_COLOUR, offsetof(DiagramAsElement, inner_color) },
+  { "show_background", PROP_TYPE_BOOL,offsetof(DiagramAsElement, show_background) },
+  { "diagram_file", PROP_TYPE_FILE, offsetof(DiagramAsElement, filename) },
+  { NULL }
+};
+static void
+_dae_get_props(DiagramAsElement *dae, GPtrArray *props)
+{  
+  object_get_props_from_offsets(&dae->element.object, _dae_offsets, props);
+}
+static void
+_dae_set_props(DiagramAsElement *dae, GPtrArray *props)
+{
+  object_set_props_from_offsets(&dae->element.object, _dae_offsets, props);
+  _dae_update_data(dae);
+}
+static real
+_dae_distance_from(DiagramAsElement *dae, Point *point)
+{
+  DiaObject *obj = &dae->element.object;
+  return distance_rectangle_point(&obj->bounding_box, point);
+}
+static void
+_dae_select(DiagramAsElement *dae, Point *clicked_point, DiaRenderer *interactive_renderer)
+{
+  element_update_handles(&dae->element);
+}
+static ObjectChange*
+_dae_move_handle(DiagramAsElement *dae, Handle *handle,
+		 Point *to, ConnectionPoint *cp, 
+		 HandleMoveReason reason, ModifierKeys modifiers)
+{
+  Element *elem = &dae->element;
+  real aspect = elem->width / elem->height;
+
+  g_assert(handle!=NULL);
+  g_assert(to!=NULL);
+
+  element_move_handle_aspect(&dae->element, handle->id, to, /*cp, reason, modifiers,*/ aspect);
+  _dae_update_data(dae);
+
+  return NULL;
+}
+static ObjectChange*
+_dae_move(DiagramAsElement *dae, Point *to)
+{
+  dae->element.corner = *to;
+  _dae_update_data(dae);
+
+  return NULL;
+}
+_dae_draw(DiagramAsElement *dae, DiaRenderer *renderer)
+{
+  DiaRendererClass *renderer_ops = DIA_RENDERER_GET_CLASS (renderer);
+  Element *elem = &dae->element;
+
+  if (!dae->data) {
+    /* just draw the box */
+    Point lower_right = {
+      elem->corner.x + elem->width,
+      elem->corner.y + elem->height 
+    };
+
+    renderer_ops->draw_rect(renderer,&elem->corner, &lower_right, 
+                            &dae->border_color);
+
+  } else {
+    if (FALSE) {
+      /* if the renderer supports transformations ... */
+      /* temporary messing with it (not enough) */
+      dae->data->paper.scaling *= dae->scale;
+      data_render (dae->data, DIA_RENDERER (renderer), NULL, NULL, NULL);
+      dae->data->paper.scaling /= dae->scale;
+    } else {
+      /* we have to render to an image and draw that */
+      if (!dae->image) { /* lazy creation */
+	gchar *imgfname = NULL;
+	gint fd = g_file_open_tmp ("diagram-as-elementXXXXXX.png", &imgfname, NULL);
+	if (fd != -1) {
+          DiaExportFilter *ef = filter_guess_export_filter (imgfname);
+	  
+	  close(fd);
+	  if (ef) {
+	    ef->export_func (dae->data, imgfname, dae->filename, ef->user_data);
+	    /* TODO: change export_func to return success or GError* */
+	    dae->image = dia_image_load (imgfname);
+	  }
+	  g_free (imgfname);
+	}
+      }
+      if (dae->image)
+	renderer_ops->draw_image (renderer, &elem->corner, elem->width, elem->height, dae->image);
+    }
+  }
+}
+static void
+_dae_update_data(DiagramAsElement *dae)
+{
+  struct utimbuf utbuf;
+  Element *elem = &dae->element;
+  
+  if (   strlen(dae->filename)
+      && g_utime(dae->filename, &utbuf) == 0
+      && dae->mtime != utbuf.modtime) {
+    DiaImportFilter *inf;
+
+    if (dae->data)
+      g_object_unref(dae->data);
+    dae->data = g_object_new (DIA_TYPE_DIAGRAM_DATA, NULL);
+
+    inf = filter_guess_import_filter(dae->filename);
+    if (inf && inf->import_func(dae->filename, dae->data, inf->user_data)) {
+      dae->scale = dae->element.width / (dae->data->extents.right - dae->data->extents.left);
+      dae->element.height = (dae->data->extents.bottom - dae->data->extents.top) * dae->scale;
+      dae->mtime = utbuf.modtime;
+    }
+    /* invalidate possibly cached image */
+    if (dae->image) {
+      g_object_unref (dae->image);
+      dae->image = NULL;
+    }
+  }
+  /* fixme - fit the scale to draw the diagram in elements size ?*/
+  if (dae->scale)
+    dae->scale = dae->element.width / (dae->data->extents.right - dae->data->extents.left);
+
+  elem->extra_spacing.border_trans = dae->border_line_width/2.0;
+  element_update_boundingbox(elem);
+  element_update_handles(elem);
+}
+static void 
+_dae_destroy(DiagramAsElement *dae) 
+{
+  if (dae->data)
+    g_object_unref(dae->data);
+
+  g_free(dae->filename);
+
+  element_destroy(&dae->element);
+}
+
+static ObjectOps _dae_ops = {
+  (DestroyFunc)         _dae_destroy,
+  (DrawFunc)            _dae_draw,
+  (DistanceFunc)        _dae_distance_from,
+  (SelectFunc)          _dae_select,
+  (CopyFunc)            object_copy_using_properties,
+  (MoveFunc)            _dae_move,
+  (MoveHandleFunc)      _dae_move_handle,
+  (GetPropertiesFunc)   object_create_props_dialog,
+  (ApplyPropertiesDialogFunc) object_apply_props_from_dialog,
+  (ObjectMenuFunc)      NULL,
+  (DescribePropsFunc)   _dae_describe_props,
+  (GetPropsFunc)        _dae_get_props,
+  (SetPropsFunc)        _dae_set_props,
+  (TextEditFunc) 0,
+  (ApplyPropertiesListFunc) object_apply_props,
+};
+
+/*! factory function */
+static DiaObject *
+_dae_create (Point *startpoint,
+	     void *user_data,
+	     Handle **handle1,
+	     Handle **handle2)
+{
+  DiagramAsElement *dae;
+  Element *elem;
+  DiaObject *obj;
+  int i;
+
+  dae = g_new0(DiagramAsElement, 1);
+
+  obj = &dae->element.object;
+  obj->type = &diagram_as_element_type;
+  obj->ops = &_dae_ops;
+
+  elem = &dae->element;
+  elem->corner = *startpoint;
+  elem->width = DEFAULT_WIDTH;
+  elem->height = DEFAULT_HEIGHT;
+  
+  element_init(elem, 8, NUM_CONNECTIONS);
+
+  for (i=0; i<NUM_CONNECTIONS; i++) {
+    obj->connections[i] = &dae->connections[i];
+    dae->connections[i].object = obj;
+    dae->connections[i].connected = NULL;
+  }
+  dae->connections[8].flags = CP_FLAGS_MAIN;
+
+  dae->filename = g_strdup("");
+
+  _dae_update_data(dae);
+
+  *handle1 = NULL;
+  *handle2 = obj->handles[7];  
+  return &dae->element.object;
+}
diff --git a/objects/Misc/libmisc.c b/objects/Misc/libmisc.c
index 981f52c..e72ea9a 100644
--- a/objects/Misc/libmisc.c
+++ b/objects/Misc/libmisc.c
@@ -32,6 +32,7 @@ extern DiaObjectType analog_clock_type;
 extern DiaObjectType grid_object_type;
 extern DiaObjectType tree_type;
 extern DiaObjectType measure_type;
+extern DiaObjectType diagram_as_element_type;
 
 DIA_PLUGIN_CHECK_INIT
 
@@ -46,6 +47,7 @@ dia_plugin_init(PluginInfo *info)
   object_register_type(&grid_object_type);  
   object_register_type(&tree_type);
   object_register_type(&measure_type);
+  object_register_type(&diagram_as_element_type);
 
   return DIA_PLUGIN_INIT_OK;
 }
diff --git a/objects/Misc/pixmaps/diagram_as_element.xpm b/objects/Misc/pixmaps/diagram_as_element.xpm
new file mode 100644
index 0000000..11a8545
--- /dev/null
+++ b/objects/Misc/pixmaps/diagram_as_element.xpm
@@ -0,0 +1,231 @@
+/* XPM */
+static char * diagram_as_element_xpm[] = {
+"22 22 206 2",
+"  	c None",
+". 	c #4E4E4E",
+"+ 	c #5B5B5B",
+"@ 	c #2D2D2D",
+"# 	c #3D3D3D",
+"$ 	c #5D5D5D",
+"% 	c #7E7E7E",
+"& 	c #9C9C9B",
+"* 	c #8D8D8D",
+"= 	c #3C3C3B",
+"- 	c #474747",
+"; 	c #555555",
+"> 	c #6B6B6B",
+", 	c #898988",
+"' 	c #969696",
+") 	c #A5A5A5",
+"! 	c #B0B0AF",
+"~ 	c #A5A5A4",
+"{ 	c #5D5D5C",
+"] 	c #717171",
+"^ 	c #878787",
+"/ 	c #8E8E8E",
+"( 	c #A2A2A1",
+"_ 	c #AEAEAD",
+": 	c #B3B3B3",
+"< 	c #B1B1B1",
+"[ 	c #ADADAC",
+"} 	c #838383",
+"| 	c #606060",
+"1 	c #B5B5B5",
+"2 	c #A2A2A2",
+"3 	c #737373",
+"4 	c #5C6C5C",
+"5 	c #60755F",
+"6 	c #969796",
+"7 	c #AFAFAF",
+"8 	c #AEAEAE",
+"9 	c #ADADAD",
+"0 	c #9D9D9D",
+"a 	c #565656",
+"b 	c #888888",
+"c 	c #BBBBBB",
+"d 	c #5E615E",
+"e 	c #1D751D",
+"f 	c #1A8E1A",
+"g 	c #7B847B",
+"h 	c #ABABAB",
+"i 	c #ACACAC",
+"j 	c #ABABAA",
+"k 	c #272727",
+"l 	c #727272",
+"m 	c #7A7A79",
+"n 	c #6A6A6A",
+"o 	c #636563",
+"p 	c #296629",
+"q 	c #267726",
+"r 	c #7B827A",
+"s 	c #A8A8A8",
+"t 	c #9E9E9E",
+"u 	c #515151",
+"v 	c #5C5C5C",
+"w 	c #7F7F7E",
+"x 	c #7C7C7C",
+"y 	c #646463",
+"z 	c #393F38",
+"A 	c #3B433B",
+"B 	c #5F605E",
+"C 	c #706F6E",
+"D 	c #727171",
+"E 	c #747474",
+"F 	c #8A8A8A",
+"G 	c #A8A8A7",
+"H 	c #AFAFAE",
+"I 	c #808080",
+"J 	c #686868",
+"K 	c #858585",
+"L 	c #595959",
+"M 	c #606160",
+"N 	c #7C7979",
+"O 	c #8A5F5F",
+"P 	c #875E5E",
+"Q 	c #7A7878",
+"R 	c #5F5F5F",
+"S 	c #6E6E6E",
+"T 	c #A7A7A7",
+"U 	c #B9B9B8",
+"V 	c #B8B8B8",
+"W 	c #8D8E8D",
+"X 	c #B9A8A7",
+"Y 	c #D15A57",
+"Z 	c #C95656",
+"` 	c #AB9D9D",
+" .	c #3F3F3F",
+"..	c #7B7B7B",
+"+.	c #B7B7B7",
+"@.	c #898989",
+"#.	c #5E5E5E",
+"$.	c #BEBEBE",
+"%.	c #CACACA",
+"&.	c #C5C5C4",
+"*.	c #8C8C8C",
+"=.	c #6D6B6B",
+"-.	c #896665",
+";.	c #884746",
+">.	c #864645",
+",.	c #7F5C5C",
+"'.	c #747171",
+").	c #3E3E3E",
+"!.	c #5A5A5A",
+"~.	c #BCBCBC",
+"{.	c #B3B3B2",
+"].	c #666666",
+"^.	c #444444",
+"/.	c #BABABA",
+"(.	c #DADADA",
+"_.	c #D6D6D6",
+":.	c #999999",
+"<.	c #7F6363",
+"[.	c #A03736",
+"}.	c #934C4B",
+"|.	c #984E4B",
+"1.	c #992F2E",
+"2.	c #775D5C",
+"3.	c #383837",
+"4.	c #656565",
+"5.	c #C2C2C2",
+"6.	c #C5C5C5",
+"7.	c #9A9A9A",
+"8.	c #434341",
+"9.	c #373737",
+"0.	c #E7E7E7",
+"a.	c #E1E1E1",
+"b.	c #AA8B8B",
+"c.	c #D47878",
+"d.	c #D07778",
+"e.	c #D07777",
+"f.	c #C86B6A",
+"g.	c #8D6D6D",
+"h.	c #474646",
+"i.	c #CBCBCB",
+"j.	c #CBCBCA",
+"k.	c #797978",
+"l.	c #959595",
+"m.	c #E9E9E9",
+"n.	c #BFBFBF",
+"o.	c #777777",
+"p.	c #777676",
+"q.	c #94908F",
+"r.	c #969292",
+"s.	c #8F8B8B",
+"t.	c #6F6D6D",
+"u.	c #868685",
+"v.	c #D1D1D0",
+"w.	c #CFCFCE",
+"x.	c #C6C6C6",
+"y.	c #9B9B9A",
+"z.	c #3C3C3C",
+"A.	c #E5E5E5",
+"B.	c #929292",
+"C.	c #989898",
+"D.	c #D5D5D5",
+"E.	c #D4D4D4",
+"F.	c #C3C3C3",
+"G.	c #919191",
+"H.	c #535353",
+"I.	c #D7D7D7",
+"J.	c #E4E4E4",
+"K.	c #949494",
+"L.	c #DCDCDC",
+"M.	c #E3E3E2",
+"N.	c #E0E0E0",
+"O.	c #E1E1E0",
+"P.	c #DEDEDD",
+"Q.	c #CCCCCC",
+"R.	c #222222",
+"S.	c #070707",
+"T.	c #FAFAFA",
+"U.	c #E6E6E6",
+"V.	c #F4F4F4",
+"W.	c #F3F3F3",
+"X.	c #EFEFEF",
+"Y.	c #D2D2D2",
+"Z.	c #636363",
+"`.	c #262626",
+" +	c #080808",
+".+	c #000000",
+"++	c #FFFFFF",
+"@+	c #FEFEFE",
+"#+	c #F9F9F9",
+"$+	c #EDEDED",
+"%+	c #CFCFCF",
+"&+	c #575756",
+"*+	c #616161",
+"=+	c #DFDFDF",
+"-+	c #E8E8E8",
+";+	c #C0C0C0",
+">+	c #868686",
+",+	c #484848",
+"'+	c #181818",
+")+	c #050505",
+"!+	c #313131",
+"~+	c #0F0F0F",
+"{+	c #040404",
+"]+	c #141414",
+"^+	c #121212",
+"/+	c #0B0B0B",
+"                                            ",
+"                        . +                 ",
+"                @ # $ % & * =               ",
+"          - ; > , ' ) ! ! ~ {               ",
+"        ] ^ / ( _ : : < ! [ }               ",
+"      | 1 2 3 4 5 6 ! 7 8 9 0 a             ",
+"      b c ' d e f g h 8 [ i j %             ",
+"    k l m n o p q r s i h i 8 t u           ",
+"      v w x y z A B C D E F G H I           ",
+"      J 2 0 K L M N O P Q R S T ) a         ",
+"      S U V : K W X Y Z ` }     +           ",
+"      #.$.%.&.*.=.-.;.>.,.'.).!.~.{.].      ",
+"      ^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.    ",
+"      9.< 0.a.) b.c.d.e.f.g.h./ i.j.c k.    ",
+"        l.m.n.o.p.q.q.r.s.t.u.c v.w.x.y.z.  ",
+"        E A./.].J B.' C.0 7 %.D.E.F.G.H.    ",
+"        R I.J.K.0 L.A.M.N.O.P.Q.( R R.S.    ",
+"          +.T.U.0.V.W.X.A.Y.T Z.`. +.+.+    ",
+"          * V ++ +#+$+%+' &+`. +.+.+.+.+    ",
+"          *+=+#+-+;+>+,+'+)+.+.+.+.+        ",
+"            * t > !+~+{+.+.+                ",
+"            ]+^+/+                          "};
diff --git a/objects/makefile.msc b/objects/makefile.msc
index 719368b..cf64853 100644
--- a/objects/makefile.msc
+++ b/objects/makefile.msc
@@ -202,6 +202,7 @@ OBJECTS = \
 	grid_object.obj \
 	measure.obj \
 	tree.obj \
+	diagram_as_object.obj \
 	libmisc.obj
 !ENDIF
 



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