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);
+
+}
+