Hi folks,

the enclosed patch (against 0.80) demonstrates the feasibility of
"implementation snarfing". It is not intended for inclusion in its current
state.
Basically, this patch adds a new object type derived from zigzagline,
which features corners with a 1.0 radius ; otherwise, the object is
identical to zigzagline.
This follows my previous post, where I describe a project intended to
minimise the amount of boilerplate code and duplication.

The next steps would be to add a property manager 'layer', in order to
make persistency and most of dialogbox work automatic, and a way to
encapsulate the binary-defined objects into XML-defined ones (including
various fun stuff on properties) (see my previous message)

Comments ?

        -- Cyrille

------------------------------------------------------------------
Oh, my god ! I'm trapped into a V90 modem !  GPG ID: A879BEF8

diff -urN -x dia.pot -x Makefile.in -x cat-id-tbl.c dia-0.80/app/Makefile.am 
dia-mine/app/Makefile.am
--- dia-0.80/app/Makefile.am    Sun Oct 17 13:01:02 1999
+++ dia-mine/app/Makefile.am    Sat Oct 30 21:13:38 1999
@@ -120,6 +120,7 @@
         echo DIA_LIB_PATH=\$$DIA_LIB_PATH:`pwd`/../objects/FS/.libs >> run_dia.sh
         echo DIA_LIB_PATH=\$$DIA_LIB_PATH:`pwd`/../objects/sybase/.libs >> run_dia.sh
         echo DIA_LIB_PATH=\$$DIA_LIB_PATH:`pwd`/../objects/flowchart/.libs >> 
run_dia.sh
+        echo DIA_LIB_PATH=\$$DIA_LIB_PATH:`pwd`/../objects/snarf/.libs >> run_dia.sh
         echo DIA_SHAPE_PATH=`pwd`/../shapes >> run_dia.sh
         echo >> run_dia.sh
         echo "`pwd`/dia \$$*" >> run_dia.sh
diff -urN -x dia.pot -x Makefile.in -x cat-id-tbl.c dia-0.80/configure 
dia-mine/configure
--- dia-0.80/configure  Sun Oct 17 14:31:01 1999
+++ dia-mine/configure  Sat Oct 30 22:20:05 1999
@@ -5109,6 +5109,7 @@
 objects/sybase/Makefile
 objects/flowchart/Makefile
 objects/custom/Makefile
+objects/snarf/Makefile
 shapes/Makefile
 shapes/Circuit/Makefile
 app/Makefile
@@ -5268,6 +5269,7 @@
 objects/sybase/Makefile
 objects/flowchart/Makefile
 objects/custom/Makefile
+objects/snarf/Makefile
 shapes/Makefile
 shapes/Circuit/Makefile
 app/Makefile
diff -urN -x dia.pot -x Makefile.in -x cat-id-tbl.c dia-0.80/configure.in 
dia-mine/configure.in
--- dia-0.80/configure.in       Sat Oct 16 17:11:25 1999
+++ dia-mine/configure.in       Sat Oct 30 20:06:09 1999
@@ -150,6 +150,7 @@
 objects/sybase/Makefile
 objects/flowchart/Makefile
 objects/custom/Makefile
+objects/snarf/Makefile
 shapes/Makefile
 shapes/Circuit/Makefile
 app/Makefile
Binary files dia-0.80/core and dia-mine/core differ
diff -urN -x dia.pot -x Makefile.in -x cat-id-tbl.c dia-0.80/objects/Makefile.am 
dia-mine/objects/Makefile.am
--- dia-0.80/objects/Makefile.am        Sun Aug 22 18:31:53 1999
+++ dia-mine/objects/Makefile.am        Sat Oct 30 20:03:55 1999
@@ -1,3 +1,3 @@
 ## Process this file with automake to produce Makefile.in
 
-SUBDIRS = standard network UML ER FS sybase flowchart custom
+SUBDIRS = standard network UML ER FS snarf sybase flowchart custom 
diff -urN -x dia.pot -x Makefile.in -x cat-id-tbl.c dia-0.80/objects/snarf/Makefile.am 
dia-mine/objects/snarf/Makefile.am
--- dia-0.80/objects/snarf/Makefile.am  Thu Jan  1 01:00:00 1970
+++ dia-mine/objects/snarf/Makefile.am  Sat Oct 30 22:19:28 1999
@@ -0,0 +1,15 @@
+## Process this file with automake to produce Makefile.in
+
+pkglib_LTLIBRARIES =   libsnarf_objects.la
+libsnarf_objects_la_SOURCES = \
+                             snarf.h \
+                             sadt_data.c \
+                             snarf.c
+
+libsnarf_objects_la_LDFLAGS = -export-dynamic -module -avoid-version
+
+INCLUDES = -I$(top_srcdir)/intl -I$(srcdir)/../../lib @CFLAGS@ @GTK_CFLAGS@ 
+@GNOME_CFLAGS@
+
+EXTRA_DIST = \
+       pixmaps/data.xpm
+
diff -urN -x dia.pot -x Makefile.in -x cat-id-tbl.c 
dia-0.80/objects/snarf/pixmaps/data.xpm dia-mine/objects/snarf/pixmaps/data.xpm
--- dia-0.80/objects/snarf/pixmaps/data.xpm     Thu Jan  1 01:00:00 1970
+++ dia-mine/objects/snarf/pixmaps/data.xpm     Sat Oct 30 20:55:23 1999
@@ -0,0 +1,29 @@
+/* XPM */
+static char * sadt_data_xpm[] = {
+"22 22 4 1",
+"      c None",
+".     c #00FC00",
+"+     c #000000",
+"@     c #F88010",
+"                      ",
+"                      ",
+"   ..                 ",
+"   ..                 ",
+"   ++                 ",
+"   ++                 ",
+"   ++                 ",
+"   ++                 ",
+"   ++                 ",
+"   +++                ",
+"    +++++@@++++       ",
+"     ++++@@+++++      ",
+"              +++     ",
+"               ++     ",
+"               ++     ",
+"               ++     ",
+"               ..     ",
+"               ..     ",
+"                      ",
+"                      ",
+"                      ",
+"                      "};
diff -urN -x dia.pot -x Makefile.in -x cat-id-tbl.c dia-0.80/objects/snarf/sadt_data.c 
dia-mine/objects/snarf/sadt_data.c
--- dia-0.80/objects/snarf/sadt_data.c  Thu Jan  1 01:00:00 1970
+++ dia-mine/objects/snarf/sadt_data.c  Sat Oct 30 22:17:50 1999
@@ -0,0 +1,308 @@
+/* Dia -- an diagram creation/manipulation program
+ * Copyright (C) 1998 Alexander Larsson
+ *
+ * Zigzagline plundered and turned into SADT data flow
+ * This is only a demonstrator.
+ * Copyright (C) 1999 Cyrille Chepelov
+ *
+ * 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 <assert.h>
+#include <gtk/gtk.h>
+#include <math.h>
+#include <string.h>
+
+#include "config.h"
+#include "intl.h"
+#include "object.h"
+#include "orth_conn.h"
+#include "connectionpoint.h"
+#include "render.h"
+#include "attributes.h"
+#include "widgets.h"
+#include "message.h"
+#include "sheet.h"
+
+#include "pixmaps/data.xpm"
+#define DEFAULT_CORNER_RADIUS 1.0
+
+#define corner_radius DEFAULT_CORNER_RADIUS /* temporary */
+
+
+/* This is indeed Zigzagline verbatim. I'm not happy about this, dynamic
+   properties will help getting rid of this crud. */
+
+typedef struct _Sadt_Data {
+  OrthConn orth;
+
+  Color line_color;
+  LineStyle line_style;
+  real dashlength;
+  real line_width;
+  Arrow start_arrow, end_arrow;
+} Sadt_Data;
+
+
+static void sadt_data_draw(Sadt_Data *sadt_data, Renderer *renderer);
+
+static CreateFunc *zigzagline_create;
+static Object *sadt_data_create(Point *startpoint,
+                                void *user_data,
+                                Handle **handle1,
+                                Handle **handle2);
+static LoadFunc *zigzagline_load;
+static Object *sadt_data_load(ObjectNode obj_node, 
+                              int version, 
+                              const char *filename);
+
+
+static ObjectTypeOps sadt_data_type_ops =
+{ /* will be filled from zigzagline_type_ops */
+  (CreateFunc) NULL,  
+  (LoadFunc)  NULL,    
+  (SaveFunc)  NULL,      
+  (GetDefaultsFunc)   NULL,
+  (ApplyDefaultsFunc) NULL
+};
+
+static ObjectType sadt_data_type =
+{
+  "Snarf - Sadt_Data",   /* name */
+  0,                         /* version */
+  (char **) sadt_data_xpm,      /* pixmap */ 
+  &sadt_data_type_ops       /* ops */
+};
+
+ObjectType *_sadt_data_type = (ObjectType *) &sadt_data_type;
+
+
+static ObjectOps sadt_data_ops = {
+  (DestroyFunc)         NULL,
+  (DrawFunc)            NULL,
+  (DistanceFunc)        NULL,
+  (SelectFunc)          NULL,
+  (CopyFunc)            NULL,
+  (MoveFunc)            NULL,
+  (MoveHandleFunc)      NULL,
+  (GetPropertiesFunc)   NULL,
+  (ApplyPropertiesFunc) NULL,
+  (ObjectMenuFunc)      NULL
+};
+
+
+/* This should be gotten rid of by using index.sheet for everything */
+SheetObject sadt_data_sheetobj =
+{
+  "Snarf - Sadt_Data",             /* type */
+  N_("SADT Data flow (sort of)."),  /* description */
+  (char **) sadt_data_xpm,     /* pixmap */
+
+  NULL                    /* user_data */
+};
+
+
+
+
+static void 
+sadt_data_draw(Sadt_Data *sadt_data, Renderer *renderer)
+{
+  OrthConn *orth = &((Sadt_Data *)sadt_data)->orth;
+  Point *points;
+  int n;
+  
+  points = &orth->points[0];
+  n = orth->numpoints;
+
+  renderer->ops->set_linewidth(renderer, sadt_data->line_width);
+  renderer->ops->set_linestyle(renderer, sadt_data->line_style);
+  renderer->ops->set_dashlength(renderer, sadt_data->dashlength);
+  renderer->ops->set_linejoin(renderer, LINEJOIN_MITER);
+  renderer->ops->set_linecaps(renderer, LINECAPS_BUTT);
+
+  if (corner_radius == 0.0) {
+    renderer->ops->draw_polyline(renderer, points, n, &sadt_data->line_color);
+  } else {
+    int i;
+    Point *p;
+    real rr;
+    real zzr;
+    p = points;
+    zzr = corner_radius;
+
+    for (i=0; i<(n-2); i++,p++) 
+      {
+       real len1,len2;
+       real rr,cosa,sina,cosb,sinb,cosg,sing,alpha,beta,gamma,ca,cb;
+       Point v1,v2,vca,vcb;
+       Point X,Y,m1,m2,M,C,A,B;
+      
+       rr = zzr;
+
+       len1 = distance_point_point(p,p+1);
+       if ((len1/2) < rr) rr = len1/2;
+       len2 = distance_point_point(p+1,p+2);
+       if ((len2/2) < rr) rr = len2/2;
+
+       M.x = (*(p+1)).x; X.x = p->x; Y.x = (*(p+2)).x;
+       M.y = (*(p+1)).y; X.y = p->y; Y.y = (*(p+2)).y;
+       m1.x = (i==0)?(p->x):((p->x + M.x) / 2);
+       m1.y = (i==0)?(p->y):((p->y + M.y) / 2);
+       m2.x = (i==(n-3))?(Y.x):((M.x + Y.x) / 2);
+       m2.y = (i==(n-3))?(Y.y):((M.y + Y.y) / 2);
+      
+       if (rr < .01) {
+         /* too small corner : we do it a bit faster */
+         renderer->ops->draw_line(renderer,&m1,&M,&sadt_data->line_color);
+         renderer->ops->draw_line(renderer,&M,&m2,&sadt_data->line_color);
+       } else {
+         /* full rendering. We know len1 and len2 are nonzero. */
+         v1.x = (M.x - X.x) / len1;
+         v1.y = (M.y - X.y) / len1;
+         v2.x = (Y.x - M.x) / len2;
+         v2.y = (Y.y - M.y) / len2;
+       
+         A.x = M.x - (v1.x * rr);
+         A.y = M.y - (v1.y * rr);
+         renderer->ops->draw_line(renderer,&m1,&A,&sadt_data->line_color);
+         B.x = M.x + (v2.x * rr);
+         B.y = M.y + (v2.y * rr);
+         renderer->ops->draw_line(renderer,&B,&m2,&sadt_data->line_color);
+         C.x = A.x + (v2.x * rr); /* (or B.x - v1.x*rr) */
+         C.y = A.y + (v2.y * rr);
+         
+         vca.x = A.x - C.x;
+         vca.y = -(A.y - C.y); /* @#$! coordinate system */
+         vcb.x = B.x - C.x;
+         vcb.y = -(B.y - C.y);
+         
+         ca = distance_point_point(&C,&A);
+         cosa = vca.x / ca; sina = vca.y / ca;
+         
+         cb = distance_point_point(&C,&B);
+         cosb = vcb.x / cb; sinb = vcb.y / cb;
+
+         /*cosg = ((M.x-X.x)*(Y.x-M.x) + (M.y-X.y)*(Y.y-M.y)) / (len1*len2);*/
+         sing = (-(M.x-X.x)*(Y.y-M.y) + (Y.x-M.x)*(M.y-X.y)) / (len1*len2);
+
+         alpha = acos(cosa) * 180.0 / M_PI;
+         if (sina < 0.0) alpha = -alpha;
+         beta = acos(cosb) * 180.0 / M_PI ; 
+         if (sinb < 0.0) beta = -beta;
+         
+         /* we'll keep gamma in radians, since we're only interested in its
+            sign */
+         /* after all, we don't even need to compute cos(gamma), and
+          we can use sin(gamma) to extract the sign of gamma itself. */
+         
+         if (alpha < 0.0) alpha += 360.0;
+         if (beta < 0.0) beta += 360.0;
+         if (sing /* gamma*/ < 0) {
+           /* if this happens, we swap alpha and beta, in order to draw
+              the other portion of circle */
+           real tau;
+           tau = beta;
+           beta=alpha;
+           alpha = tau;
+         }
+         
+         
+renderer->ops->draw_arc(renderer,&C,rr*2,rr*2,alpha,beta,&sadt_data->line_color);
+
+       }
+      }
+  }
+         
+
+  if (sadt_data->start_arrow.type != ARROW_NONE) {
+    arrow_draw(renderer, sadt_data->start_arrow.type,
+              &points[0], &points[1],
+              sadt_data->start_arrow.length, sadt_data->start_arrow.width, 
+              sadt_data->line_width,
+              &sadt_data->line_color, &color_white);
+  }
+  if (sadt_data->end_arrow.type != ARROW_NONE) {
+    arrow_draw(renderer, sadt_data->end_arrow.type,
+              &points[n-1], &points[n-2],
+              sadt_data->end_arrow.length, sadt_data->end_arrow.width, 
+              sadt_data->line_width,
+              &sadt_data->line_color, &color_white);
+  }
+}
+
+
+
+static void fix_sadt_data_ops(Object *obj) {
+  if (!sadt_data_ops.draw) {
+    memcpy(&sadt_data_ops,obj->ops,sizeof(sadt_data_ops));
+    sadt_data_ops.draw = (DrawFunc)sadt_data_draw;
+    sadt_data_type.ops = &sadt_data_type_ops;
+  }
+  obj->type = &sadt_data_type;
+  obj->ops = &sadt_data_ops;
+}
+
+static Object *
+sadt_data_load(ObjectNode obj_node, 
+              int version, 
+              const char *filename) 
+{
+  Object *obj;
+  
+  obj = (*zigzagline_load)(obj_node,version,filename);
+  fix_sadt_data_ops(obj);
+  
+  return obj;
+}
+
+static Object *
+sadt_data_create(Point *startpoint,
+                 void *user_data,
+                 Handle **handle1,
+                 Handle **handle2)
+{
+  Object *obj;
+
+  obj = (*zigzagline_create)(startpoint,user_data,handle1,handle2);
+  fix_sadt_data_ops(obj);
+
+  return obj;
+}
+
+int snarf_sadt_data_type(void) {
+  static int sadt_data_registered = 0;
+  ObjectType *zigzagline_type;
+
+  if (sadt_data_registered) return 0;
+
+  zigzagline_type = object_get_type("Standard - ZigZagLine");
+  if (!zigzagline_type) return;
+
+  memcpy(&sadt_data_type_ops,zigzagline_type->ops,sizeof(sadt_data_type_ops));
+
+  
+  zigzagline_create = &(zigzagline_type->ops->create);
+  sadt_data_type_ops.create = (CreateFunc)sadt_data_create;
+
+  zigzagline_load = &(zigzagline_type->ops->load);
+  sadt_data_type_ops.load = (LoadFunc)sadt_data_load;
+
+  object_register_type(&sadt_data_type);
+  sadt_data_registered = 1;
+  return sadt_data_registered;
+}
+
+  
+
+
diff -urN -x dia.pot -x Makefile.in -x cat-id-tbl.c dia-0.80/objects/snarf/snarf.c 
dia-mine/objects/snarf/snarf.c
--- dia-0.80/objects/snarf/snarf.c      Thu Jan  1 01:00:00 1970
+++ dia-mine/objects/snarf/snarf.c      Sat Oct 30 20:57:32 1999
@@ -0,0 +1,53 @@
+/* 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.
+ */
+#include "object.h"
+#include "sheet.h"
+
+#include "config.h"
+#include "intl.h"
+
+int get_version(void) {
+  return 0;
+}
+
+void register_objects(void) {
+  /* we don't actually register here, because we might have been loaded
+     before the standard objects.
+     
+     As a temporary measure, we'll register in register_sheets (baaad),
+     but we really ought to improve the library loading mechanism instead.
+  */
+}
+
+extern SheetObject sadt_data_sheetobj;
+
+void register_sheets(void) {
+  Sheet *sheet;
+
+  /* XXX see above ! */
+  snarf_sadt_data_type();
+
+  sheet = new_sheet(_("Snarf"),
+                   _("Object implementation snarfing proof of concept"));
+  
+  sheet_append_sheet_obj(sheet, &sadt_data_sheetobj);
+  
+  register_sheet(sheet);
+
+}
+

Reply via email to