GNOME Bugzilla – Bug 428696
[patch] New Misc object : tree
Last modified: 2007-10-20 11:00:35 UTC
Add several objects belonging to Misc sheet: - one object - tree. A core tree, eg to represents filesystem. Hacked from ethernet bus. - two shapes: - exanded node: simple square with minus sign - expansible node: simple square with + sign
Created attachment 86185 [details] [review] patch => "tree" object and "+ an -" shapes mainly tree object, plus necessary stuff (pixmap, additiontion to misc makefile...)
Created attachment 86186 [details] "+ and -" png thumbs
Comment on attachment 86185 [details] [review] patch => "tree" object and "+ an -" shapes >Index: objects/Misc/tree.c >=================================================================== >--- objects/Misc/tree.c (revision 0) >+++ objects/Misc/tree.c (revision 0) >@@ -0,0 +1,765 @@ >+/* Dia -- an diagram creation/manipulation program >+ * Copyright (C) 1998 Alexander Larsson >+ * Hacked (c) 2007 Thomas Harding for tree object >+ * 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. >+ */ >+ >+#ifdef HAVE_CONFIG_H >+#include <config.h> >+#endif >+ >+#include <assert.h> >+#include <math.h> >+ >+#include "intl.h" >+#include "object.h" >+#include "connection.h" >+#include "connectionpoint.h" >+#include "diarenderer.h" >+#include "attributes.h" >+#include "diamenu.h" >+ >+#include "pixmaps/tree.xpm" >+ >+#define LINE_WIDTH 0.1 >+ >+#define DEFAULT_NUMHANDLES 6 >+#define HANDLE_BUS (HANDLE_CUSTOM1) >+ >+ >+typedef struct _Tree { >+ Connection connection; >+ >+ int num_handles; >+ Handle **handles; >+ Point *parallel_points; >+ Point real_ends[2]; >+ Color line_color; >+} Tree; >+ >+enum change_type { >+ TYPE_ADD_POINT, >+ TYPE_REMOVE_POINT >+}; >+ >+struct PointChange { >+ ObjectChange obj_change; >+ >+ enum change_type type; >+ int applied; >+ >+ Point point; >+ Handle *handle; /* owning ref when not applied for ADD_POINT >+ owning ref when applied for REMOVE_POINT */ >+ ConnectionPoint *connected_to; /* NULL if not connected */ >+}; >+ >+static ObjectChange* tree_move_handle(Tree *tree, Handle *handle, >+ Point *to, ConnectionPoint *cp, >+ HandleMoveReason reason, ModifierKeys modifiers); >+static ObjectChange* tree_move(Tree *tree, Point *to); >+static void tree_select(Tree *tree, Point *clicked_point, >+ DiaRenderer *interactive_renderer); >+static void tree_draw(Tree *tree, DiaRenderer *renderer); >+static DiaObject *tree_create(Point *startpoint, >+ void *user_data, >+ Handle **handle1, >+ Handle **handle2); >+static real tree_distance_from(Tree *tree, Point *point); >+static void tree_update_data(Tree *tree); >+static void tree_destroy(Tree *tree); >+static DiaObject *tree_copy(Tree *tree); >+ >+static PropDescription *tree_describe_props(Tree *tree); >+static void tree_get_props(Tree *tree, GPtrArray *props); >+static void tree_set_props(Tree *tree, GPtrArray *props); >+static void tree_save(Tree *tree, ObjectNode obj_node, const char *filename); >+static DiaObject *tree_load(ObjectNode obj_node, int version, >+ const char *filename); >+static DiaMenu *tree_get_object_menu(Tree *tree, Point *clickedpoint); >+ >+static ObjectChange * >+tree_create_change(Tree *tree, enum change_type type, >+ Point *point, Handle *handle, >+ ConnectionPoint *connected_to); >+ >+ >+static ObjectTypeOps tree_type_ops = >+{ >+ (CreateFunc) tree_create, >+ (LoadFunc) tree_load, >+ (SaveFunc) tree_save, >+ (GetDefaultsFunc) NULL, >+ (ApplyDefaultsFunc) NULL >+}; >+ >+DiaObjectType tree_type = >+{ >+ "Misc - Tree", /* name */ >+ 0, /* version */ >+ (char **) tree_xpm, /* pixmap */ >+ &tree_type_ops /* ops */ >+}; >+ >+static ObjectOps tree_ops = { >+ (DestroyFunc) tree_destroy, >+ (DrawFunc) tree_draw, >+ (DistanceFunc) tree_distance_from, >+ (SelectFunc) tree_select, >+ (CopyFunc) tree_copy, >+ (MoveFunc) tree_move, >+ (MoveHandleFunc) tree_move_handle, >+ (GetPropertiesFunc) object_create_props_dialog, >+ (ApplyPropertiesFunc) object_apply_props_from_dialog, >+ (ObjectMenuFunc) tree_get_object_menu, >+ (DescribePropsFunc) tree_describe_props, >+ (GetPropsFunc) tree_get_props, >+ (SetPropsFunc) tree_set_props, >+}; >+ >+static PropDescription tree_props[] = { >+ OBJECT_COMMON_PROPERTIES, >+ PROP_STD_LINE_COLOUR, >+ PROP_DESC_END >+}; >+ >+static PropDescription * >+tree_describe_props(Tree *tree) >+{ >+ if (tree_props[0].quark == 0) >+ prop_desc_list_calculate_quarks(tree_props); >+ return tree_props; >+} >+ >+static PropOffset tree_offsets[] = { >+ OBJECT_COMMON_PROPERTIES_OFFSETS, >+ { "line_colour", PROP_TYPE_COLOUR, offsetof(Tree, line_color) }, >+ { NULL, 0, 0 } >+}; >+ >+static void >+tree_get_props(Tree *tree, GPtrArray *props) >+{ >+ object_get_props_from_offsets(&tree->connection.object, tree_offsets, >+ props); >+} >+ >+static void >+tree_set_props(Tree *tree, GPtrArray *props) >+{ >+ object_set_props_from_offsets(&tree->connection.object, tree_offsets, >+ props); >+ tree_update_data(tree); >+} >+ >+static real >+tree_distance_from(Tree *tree, Point *point) >+{ >+ Point *endpoints; >+ real min_dist; >+ int i; >+ >+ endpoints = &tree->real_ends[0]; >+ min_dist = distance_line_point( &endpoints[0], &endpoints[1], >+ LINE_WIDTH, point); >+ for (i=0;i<tree->num_handles;i++) { >+ min_dist = MIN(min_dist, >+ distance_line_point( &tree->handles[i]->pos, >+ &tree->parallel_points[i], >+ LINE_WIDTH, point)); >+ } >+ return min_dist; >+} >+ >+static void >+tree_select(Tree *tree, Point *clicked_point, >+ DiaRenderer *interactive_renderer) >+{ >+ connection_update_handles(&tree->connection); >+} >+ >+static ObjectChange* >+tree_move_handle(Tree *tree, Handle *handle, >+ Point *to, ConnectionPoint *cp, >+ HandleMoveReason reason, ModifierKeys modifiers) >+{ >+ Connection *conn = &tree->connection; >+ Point *endpoints; >+ static real *parallel=NULL; >+ static real *perp=NULL; >+ static int max_num=0; >+ Point vhat, vhatperp; >+ Point u; >+ real vlen, vlen2; >+ real len_scale; >+ int i; >+ >+ if (tree->num_handles>max_num) { >+ if (parallel!=NULL) { >+ g_free(parallel); >+ g_free(perp); >+ } >+ parallel = g_malloc(sizeof(real)*tree->num_handles); >+ perp = g_malloc(sizeof(real)*tree->num_handles); >+ max_num = tree->num_handles; >+ } >+ >+ if (handle->id == HANDLE_BUS) { >+ handle->pos = *to; >+ } else { >+ endpoints = &conn->endpoints[0]; >+ vhat = endpoints[1]; >+ point_sub(&vhat, &endpoints[0]); >+ if ((fabs(vhat.x) == 0.0) && (fabs(vhat.y)==0.0)) { >+ vhat.y += 0.01; >+ } >+ vlen = sqrt(point_dot(&vhat, &vhat)); >+ point_scale(&vhat, 1.0/vlen); >+ >+ vhatperp.y = -vhat.x; >+ vhatperp.x = vhat.y; >+ for (i=0;i<tree->num_handles;i++) { >+ u = tree->handles[i]->pos; >+ point_sub(&u, &endpoints[0]); >+ parallel[i] = point_dot(&vhat, &u); >+ perp[i] = point_dot(&vhatperp, &u); >+ } >+ >+ connection_move_handle(&tree->connection, handle->id, to, cp, >+ reason, modifiers); >+ >+ vhat = endpoints[1]; >+ point_sub(&vhat, &endpoints[0]); >+ if ((fabs(vhat.x) == 0.0) && (fabs(vhat.y)==0.0)) { >+ vhat.y += 0.01; >+ } >+ vlen2 = sqrt(point_dot(&vhat, &vhat)); >+ len_scale = vlen2 / vlen; >+ point_normalize(&vhat); >+ vhatperp.y = -vhat.x; >+ vhatperp.x = vhat.y; >+ for (i=0;i<tree->num_handles;i++) { >+ if (tree->handles[i]->connected_to == NULL) { >+ u = vhat; >+ point_scale(&u, parallel[i]*len_scale); >+ point_add(&u, &endpoints[0]); >+ tree->parallel_points[i] = u; >+ u = vhatperp; >+ point_scale(&u, perp[i]); >+ point_add(&u, &tree->parallel_points[i]); >+ tree->handles[i]->pos = u; >+ } >+ } >+ } >+ >+ tree_update_data(tree); >+ >+ return NULL; >+} >+ >+static ObjectChange* >+tree_move(Tree *tree, Point *to) >+{ >+ Point delta; >+ Point *endpoints = &tree->connection.endpoints[0]; >+ DiaObject *obj = &tree->connection.object; >+ int i; >+ >+ delta = *to; >+ point_sub(&delta, &obj->position); >+ >+ for (i=0;i<2;i++) { >+ point_add(&endpoints[i], &delta); >+ point_add(&tree->real_ends[i], &delta); >+ } >+ >+ for (i=0;i<tree->num_handles;i++) { >+ if (tree->handles[i]->connected_to == NULL) { >+ point_add(&tree->handles[i]->pos, &delta); >+ } >+ } >+ >+ tree_update_data(tree); >+ >+ return NULL; >+} >+ >+static void >+tree_draw(Tree *tree, DiaRenderer *renderer) >+{ >+ DiaRendererClass *renderer_ops = DIA_RENDERER_GET_CLASS (renderer); >+ Point *endpoints; >+ int i; >+ >+ assert(tree != NULL); >+ assert(renderer != NULL); >+ >+ endpoints = &tree->real_ends[0]; >+ >+ renderer_ops->set_linewidth(renderer, LINE_WIDTH); >+ renderer_ops->set_linestyle(renderer, LINESTYLE_SOLID); >+ renderer_ops->set_linecaps(renderer, LINECAPS_BUTT); >+ >+ renderer_ops->draw_line(renderer, >+ &endpoints[0], &endpoints[1], >+ &tree->line_color); >+ >+ for (i=0;i<tree->num_handles;i++) { >+ renderer_ops->draw_line(renderer, >+ &tree->parallel_points[i], >+ &tree->handles[i]->pos, >+ &tree->line_color); >+ } >+} >+ >+static DiaObject * >+tree_create(Point *startpoint, >+ void *user_data, >+ Handle **handle1, >+ Handle **handle2) >+{ >+ Tree *tree; >+ Connection *conn; >+ LineBBExtras *extra; >+ DiaObject *obj; >+ Point defaultlen = { 0.0, 20.0 }; >+ int i; >+ >+ tree = g_malloc0(sizeof(Tree)); >+ >+ conn = &tree->connection; >+ conn->endpoints[0] = *startpoint; >+ conn->endpoints[1] = *startpoint; >+ point_add(&conn->endpoints[1], &defaultlen); >+ >+ obj = &conn->object; >+ extra = &conn->extra_spacing; >+ >+ obj->type = &tree_type; >+ obj->ops = &tree_ops; >+ >+ tree->num_handles = DEFAULT_NUMHANDLES; >+ >+ connection_init(conn, 2+tree->num_handles, 0); >+ tree->line_color = attributes_get_foreground(); >+ tree->handles = g_malloc(sizeof(Handle *)*tree->num_handles); >+ tree->parallel_points = g_malloc(sizeof(Point)*tree->num_handles); >+ for (i=0;i<tree->num_handles;i++) { >+ tree->handles[i] = g_new0(Handle,1); >+ tree->handles[i]->id = HANDLE_BUS; >+ tree->handles[i]->type = HANDLE_MINOR_CONTROL; >+ tree->handles[i]->connect_type = HANDLE_CONNECTABLE_NOBREAK; >+ tree->handles[i]->connected_to = NULL; >+ tree->handles[i]->pos = *startpoint; >+ tree->handles[i]->pos.y += 20*((real)i+1)/(tree->num_handles+1); >+ tree->handles[i]->pos.x += 1.0; /* (i%2==0)?1.0:-1.0; */ >+ obj->handles[2+i] = tree->handles[i]; >+ } >+ >+ extra->start_trans = >+ extra->end_trans = >+ extra->start_long = >+ extra->end_long = LINE_WIDTH/2.0; >+ tree_update_data(tree); >+ >+ *handle1 = obj->handles[0]; >+ *handle2 = obj->handles[1]; >+ return &tree->connection.object; >+} >+ >+static void >+tree_destroy(Tree *tree) >+{ >+ int i; >+ connection_destroy(&tree->connection); >+ for (i=0;i<tree->num_handles;i++) >+ g_free(tree->handles[i]); >+ g_free(tree->handles); >+ g_free(tree->parallel_points); >+} >+ >+static DiaObject * >+tree_copy(Tree *tree) >+{ >+ Tree *newtree; >+ Connection *conn, *newconn; >+ DiaObject *newobj; >+ int i; >+ >+ conn = &tree->connection; >+ >+ newtree = g_malloc0(sizeof(Tree)); >+ newconn = &newtree->connection; >+ newobj = &newconn->object; >+ >+ connection_copy(conn, newconn); >+ >+ newtree->num_handles = tree->num_handles; >+ newtree->line_color = tree->line_color; >+ >+ newtree->handles = g_malloc(sizeof(Handle *)*newtree->num_handles); >+ newtree->parallel_points = g_malloc(sizeof(Point)*newtree->num_handles); >+ >+ for (i=0;i<newtree->num_handles;i++) { >+ newtree->handles[i] = g_new0(Handle,1); >+ *newtree->handles[i] = *tree->handles[i]; >+ newtree->handles[i]->connected_to = NULL; >+ newobj->handles[2+i] = newtree->handles[i]; >+ newtree->parallel_points[i] = tree->parallel_points[i]; >+ } >+ >+ newtree->real_ends[0] = tree->real_ends[0]; >+ newtree->real_ends[1] = tree->real_ends[1]; >+ >+ return &newtree->connection.object; >+} >+ >+ >+static void >+tree_update_data(Tree *tree) >+{ >+ Connection *conn = &tree->connection; >+ DiaObject *obj = &conn->object; >+ int i; >+ Point u, v, vhat; >+ Point *endpoints; >+ real ulen; >+ real min_par, max_par; >+ >+/* >+ * This seems to break stuff wildly. >+ */ >+/* >+ if (connpoint_is_autogap(conn->endpoint_handles[0].connected_to) || >+ connpoint_is_autogap(conn->endpoint_handles[1].connected_to)) { >+ connection_adjust_for_autogap(conn); >+ } >+*/ >+ endpoints = &conn->endpoints[0]; >+ obj->position = endpoints[0]; >+ >+ v = endpoints[1]; >+ point_sub(&v, &endpoints[0]); >+ if ((fabs(v.x) == 0.0) && (fabs(v.y)==0.0)) { >+ v.y += 0.01; >+ } >+ vhat = v; >+ point_normalize(&vhat); >+ min_par = 0.0; >+ max_par = point_dot(&vhat, &v); >+ for (i=0;i<tree->num_handles;i++) { >+ u = tree->handles[i]->pos; >+ point_sub(&u, &endpoints[0]); >+ ulen = point_dot(&u, &vhat); >+ min_par = MIN(min_par, ulen); >+ max_par = MAX(max_par, ulen); >+ tree->parallel_points[i] = vhat; >+ point_scale(&tree->parallel_points[i], ulen); >+ point_add(&tree->parallel_points[i], &endpoints[0]); >+ } >+ >+ min_par -= LINE_WIDTH/2.0; >+ max_par += LINE_WIDTH/2.0; >+ >+ tree->real_ends[0] = vhat; >+ point_scale(&tree->real_ends[0], min_par); >+ point_add(&tree->real_ends[0], &endpoints[0]); >+ tree->real_ends[1] = vhat; >+ point_scale(&tree->real_ends[1], max_par); >+ point_add(&tree->real_ends[1], &endpoints[0]); >+ >+ connection_update_boundingbox(conn); >+ rectangle_add_point(&obj->bounding_box, &tree->real_ends[0]); >+ rectangle_add_point(&obj->bounding_box, &tree->real_ends[1]); >+ for (i=0;i<tree->num_handles;i++) { >+ rectangle_add_point(&obj->bounding_box, &tree->handles[i]->pos); >+ } >+ >+ connection_update_handles(conn); >+} >+ >+static void >+tree_add_handle(Tree *tree, Point *p, Handle *handle) >+{ >+ int i; >+ >+ tree->num_handles++; >+ >+ /* Allocate more handles */ >+ tree->handles = g_realloc(tree->handles, >+ sizeof(Handle *)*tree->num_handles); >+ tree->parallel_points = g_realloc(tree->parallel_points, >+ sizeof(Point)*tree->num_handles); >+ >+ i = tree->num_handles - 1; >+ >+ tree->handles[i] = handle; >+ tree->handles[i]->id = HANDLE_BUS; >+ tree->handles[i]->type = HANDLE_MINOR_CONTROL; >+ tree->handles[i]->connect_type = HANDLE_CONNECTABLE_NOBREAK; >+ tree->handles[i]->connected_to = NULL; >+ tree->handles[i]->pos = *p; >+ object_add_handle(&tree->connection.object, tree->handles[i]); >+} >+ >+static void >+tree_remove_handle(Tree *tree, Handle *handle) >+{ >+ int i, j; >+ >+ for (i=0;i<tree->num_handles;i++) { >+ if (tree->handles[i] == handle) { >+ object_remove_handle(&tree->connection.object, handle); >+ >+ for (j=i;j<tree->num_handles-1;j++) { >+ tree->handles[j] = tree->handles[j+1]; >+ tree->parallel_points[j] = tree->parallel_points[j+1]; >+ } >+ >+ tree->num_handles--; >+ tree->handles = g_realloc(tree->handles, >+ sizeof(Handle *)*tree->num_handles); >+ tree->parallel_points = g_realloc(tree->parallel_points, >+ sizeof(Point)*tree->num_handles); >+ >+ break; >+ } >+ } >+} >+ >+static ObjectChange * >+tree_add_handle_callback (DiaObject *obj, Point *clicked, gpointer data) >+{ >+ Tree *tree = (Tree *) obj; >+ Handle *handle; >+ >+ handle = g_new0(Handle,1); >+ tree_add_handle(tree, clicked, handle); >+ tree_update_data(tree); >+ >+ return tree_create_change(tree, TYPE_ADD_POINT, clicked, handle, NULL); >+} >+ >+static int >+tree_point_near_handle(Tree *tree, Point *p) >+{ >+ int i, min; >+ real dist = 1000.0; >+ real d; >+ >+ min = -1; >+ for (i=0;i<tree->num_handles;i++) { >+ d = distance_line_point(&tree->parallel_points[i], >+ &tree->handles[i]->pos, 0.0, p); >+ >+ if (d < dist) { >+ dist = d; >+ min = i; >+ } >+ } >+ >+ if (dist < 0.5) >+ return min; >+ else >+ return -1; >+} >+ >+static ObjectChange * >+tree_delete_handle_callback (DiaObject *obj, Point *clicked, gpointer data) >+{ >+ Tree *tree = (Tree *) obj; >+ Handle *handle; >+ int handle_num; >+ ConnectionPoint *connectionpoint; >+ Point p; >+ >+ handle_num = tree_point_near_handle(tree, clicked); >+ >+ handle = tree->handles[handle_num]; >+ p = handle->pos; >+ connectionpoint = handle->connected_to; >+ >+ object_unconnect(obj, handle); >+ tree_remove_handle(tree, handle ); >+ tree_update_data(tree); >+ >+ return tree_create_change(tree, TYPE_REMOVE_POINT, &p, handle, >+ connectionpoint); >+} >+ >+static DiaMenuItem tree_menu_items[] = { >+ { N_("Add Handle"), tree_add_handle_callback, NULL, 1 }, >+ { N_("Delete Handle"), tree_delete_handle_callback, NULL, 1 }, >+}; >+ >+static DiaMenu tree_menu = { >+ "Tree", >+ sizeof(tree_menu_items)/sizeof(DiaMenuItem), >+ tree_menu_items, >+ NULL >+}; >+ >+static DiaMenu * >+tree_get_object_menu(Tree *tree, Point *clickedpoint) >+{ >+ /* Set entries sensitive/selected etc here */ >+ tree_menu_items[0].active = 1; >+ tree_menu_items[1].active = (tree_point_near_handle(tree, clickedpoint) >= 0); >+ return &tree_menu; >+} >+ >+static void >+tree_save(Tree *tree, ObjectNode obj_node, const char *filename) >+{ >+ int i; >+ AttributeNode attr; >+ >+ connection_save(&tree->connection, obj_node); >+ >+ data_add_color( new_attribute(obj_node, "line_color"), &tree->line_color); >+ >+ attr = new_attribute(obj_node, "tree_handles"); >+ >+ for (i=0;i<tree->num_handles;i++) { >+ data_add_point(attr, &tree->handles[i]->pos); >+ } >+} >+ >+static DiaObject * >+tree_load(ObjectNode obj_node, int version, const char *filename) >+{ >+ Tree *tree; >+ Connection *conn; >+ LineBBExtras *extra; >+ DiaObject *obj; >+ AttributeNode attr; >+ DataNode data; >+ int i; >+ >+ tree = g_malloc0(sizeof(Tree)); >+ >+ conn = &tree->connection; >+ obj = &conn->object; >+ extra = &conn->extra_spacing; >+ >+ obj->type = &tree_type; >+ obj->ops = &tree_ops; >+ >+ connection_load(conn, obj_node); >+ >+ attr = object_find_attribute(obj_node, "tree_handles"); >+ >+ tree->num_handles = 0; >+ if (attr != NULL) >+ tree->num_handles = attribute_num_data(attr); >+ >+ connection_init(conn, 2 + tree->num_handles, 0); >+ >+ data = attribute_first_data(attr); >+ tree->handles = g_malloc(sizeof(Handle *)*tree->num_handles); >+ tree->parallel_points = g_malloc(sizeof(Point)*tree->num_handles); >+ for (i=0;i<tree->num_handles;i++) { >+ tree->handles[i] = g_new0(Handle,1); >+ tree->handles[i]->id = HANDLE_BUS; >+ tree->handles[i]->type = HANDLE_MINOR_CONTROL; >+ tree->handles[i]->connect_type = HANDLE_CONNECTABLE_NOBREAK; >+ tree->handles[i]->connected_to = NULL; >+ data_point(data, &tree->handles[i]->pos); >+ obj->handles[2+i] = tree->handles[i]; >+ >+ data = data_next(data); >+ } >+ >+ tree->line_color = color_black; >+ attr = object_find_attribute(obj_node, "line_color"); >+ if (attr != NULL) >+ data_color(attribute_first_data(attr), &tree->line_color); >+ >+ extra->start_trans = >+ extra->end_trans = >+ extra->start_long = >+ extra->end_long = LINE_WIDTH/2.0; >+ tree_update_data(tree); >+ >+ return &tree->connection.object; >+} >+ >+static void >+tree_change_free(struct PointChange *change) >+{ >+ if ( (change->type==TYPE_ADD_POINT && !change->applied) || >+ (change->type==TYPE_REMOVE_POINT && change->applied) ){ >+ if (change->handle) >+ g_free(change->handle); >+ change->handle = NULL; >+ } >+} >+ >+static void >+tree_change_apply(struct PointChange *change, DiaObject *obj) >+{ >+ change->applied = 1; >+ switch (change->type) { >+ case TYPE_ADD_POINT: >+ tree_add_handle((Tree *)obj, &change->point, change->handle); >+ break; >+ case TYPE_REMOVE_POINT: >+ object_unconnect(obj, change->handle); >+ tree_remove_handle((Tree *)obj, change->handle); >+ break; >+ } >+ tree_update_data((Tree *)obj); >+} >+ >+static void >+tree_change_revert(struct PointChange *change, DiaObject *obj) >+{ >+ switch (change->type) { >+ case TYPE_ADD_POINT: >+ tree_remove_handle((Tree *)obj, change->handle); >+ break; >+ case TYPE_REMOVE_POINT: >+ tree_add_handle((Tree *)obj, &change->point, change->handle); >+ if (change->connected_to) { >+ object_connect(obj, change->handle, change->connected_to); >+ } >+ break; >+ } >+ tree_update_data((Tree *)obj); >+ change->applied = 0; >+} >+ >+static ObjectChange * >+tree_create_change(Tree *tree, enum change_type type, >+ Point *point, Handle *handle, >+ ConnectionPoint *connected_to) >+{ >+ struct PointChange *change; >+ >+ change = g_new0(struct PointChange, 1); >+ >+ change->obj_change.apply = (ObjectChangeApplyFunc) tree_change_apply; >+ change->obj_change.revert = (ObjectChangeRevertFunc) tree_change_revert; >+ change->obj_change.free = (ObjectChangeFreeFunc) tree_change_free; >+ >+ change->type = type; >+ change->applied = 1; >+ change->point = *point; >+ change->handle = handle; >+ change->connected_to = connected_to; >+ >+ return (ObjectChange *)change; >+} >+ >Index: objects/Misc/pixmaps/tree.xpm >=================================================================== >--- objects/Misc/pixmaps/tree.xpm (revision 0) >+++ objects/Misc/pixmaps/tree.xpm (revision 0) >@@ -0,0 +1,87 @@ >+/* XPM */ >+static char * tree_xpm[] = { >+/* >+# >+# (c)2007, Thomas Harding <thomas.harding@laposte.net> >+# >+# 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 >+# >+*/ >+/* columns rows colors chars-per-pixel */ >+"30 60 2 1", >+" c black", >+". c None", >+/* pixels */ >+"..............................", >+"..............................", >+"..............................", >+"..............................", >+"..............................", >+"..............................", >+"..............................", >+"........ ...................", >+"........ ...................", >+"........ ...................", >+"........ ...................", >+"........ ...................", >+"........ ...................", >+"........ ......", >+"........ ......", >+"........ ......", >+"........ ...................", >+"........ ...................", >+"........ ...................", >+"........ ...................", >+"........ ...................", >+"........ ...................", >+"........ ...................", >+"........ ...................", >+"........ ...................", >+"........ ...................", >+"........ ...................", >+"........ ......", >+"........ ......", >+"........ ......", >+"........ ...................", >+"........ ...................", >+"........ ...................", >+"........ ...................", >+"........ ...................", >+"........ ...................", >+"........ ...................", >+"........ ...................", >+"........ ...................", >+"........ ......", >+"........ ......", >+"........ ......", >+"........ ...................", >+"........ ...................", >+"........ ...................", >+"........ ...................", >+"........ ...................", >+"........ ...................", >+"........ ...................", >+"........ ...................", >+"........ ...................", >+"........ ...................", >+"........ ...................", >+"..............................", >+"..............................", >+"..............................", >+"..............................", >+"..............................", >+"..............................", >+".............................." >+}; >Index: objects/Misc/libmisc.c >=================================================================== >--- objects/Misc/libmisc.c (revision 3659) >+++ objects/Misc/libmisc.c (working copy) >@@ -29,6 +29,7 @@ > #include "plug-ins.h" > > extern DiaObjectType analog_clock_type; >+extern DiaObjectType tree_type; > #ifndef _MSC_VER > /** Taken from app, but here while testing. */ > extern DiaObjectType newgroup_type; >@@ -44,6 +45,7 @@ > return DIA_PLUGIN_INIT_ERROR; > > object_register_type(&analog_clock_type); >+ object_register_type(&tree_type); > #ifndef _MSC_VER > object_register_type(&newgroup_type); > #endif >Index: objects/Misc/Makefile.am >=================================================================== >--- objects/Misc/Makefile.am (revision 3659) >+++ objects/Misc/Makefile.am (working copy) >@@ -3,7 +3,8 @@ > pkglib_LTLIBRARIES = libmisc_objects.la > libmisc_objects_la_SOURCES = \ > libmisc.c \ >- analog_clock.c >+ analog_clock.c \ >+ tree.c > > > libmisc_objects_la_LDFLAGS = -export-dynamic -module -avoid-version >@@ -12,6 +13,7 @@ > > EXTRA_DIST = \ > pixmaps/analog_clock.xpm \ >- pixmaps/newgroup.xpm >+ pixmaps/newgroup.xpm \ >+ pixmaps/tree.xpm > > >Index: sheets/Misc.sheet.in >=================================================================== >--- sheets/Misc.sheet.in (revision 3659) >+++ sheets/Misc.sheet.in (working copy) >@@ -3,12 +3,21 @@ > <_name>Misc</_name> > <_description>Miscellaneous Shapes</_description> > <contents> >+ <object name="Misc - Tree"> >+ <_description>Tree</_description> >+ </object> > <object name="Filesystem - Folder"> > <_description>Folder</_description> > </object> > <object name="Filesystem - File"> > <_description>File</_description> > </object> >+ <object name="Misc - expensible node"> >+ <_description>expensible node</_description> >+ </object> >+ <object name="Misc - expended node"> >+ <_description>expended node</_description> >+ </object> > <object name="Misc - Analog Clock"> > <_description>Traditional clock</_description> > </object> >Index: shapes/Misc/expensible-node.svg >=================================================================== >--- shapes/Misc/expensible-node.svg (revision 0) >+++ shapes/Misc/expensible-node.svg (revision 0) >@@ -0,0 +1,26 @@ >+<?xml version="1.0"?> >+<!-- >+ (c)2007, Thomas Harding <thomas.harding@laposte.net> >+ >+ 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 >+ >+ >+--> >+<svg width="2cm" height="2cm" viewBox="0 0 20 20" >+ xmlns="http://www.w3.org/2000/svg"> >+ <rect style="fill: #ffffff ; stroke: #0000ff ; stroke-width: 1" x="0" y="0" width="20" height="20"/> >+ <line style="stroke-width: 1; stroke: #000000" x1="10" y1="3" x2="10" y2="17"/> >+ <line style="stroke-width: 1; stroke: #000000" y1="10" x1="3" y2="10" x2="17"/> >+ </svg> >Index: shapes/Misc/expensible-node.shape >=================================================================== >--- shapes/Misc/expensible-node.shape (revision 0) >+++ shapes/Misc/expensible-node.shape (revision 0) >@@ -0,0 +1,38 @@ >+<?xml version="1.0"?> >+<!-- >+ (c)2007, Thomas Harding <thomas.harding@laposte.net> >+ >+ 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 >+ >+ >+--> >+<shape xmlns="http://www.daa.com.au/~james/dia-shape-ns" >+ xmlns:svg="http://www.w3.org/2000/svg"> >+ <name>Misc - expensible node</name> >+ <icon>expensible-node.png</icon> >+ <connections> >+ <point x="5" y="5" main="yes"/> >+ <point x="5" y="0"/> >+ <point x="0" y="5"/> >+ <point x="10" y="5"/> >+ <point x="5" y="10"/> >+ </connections> >+ <aspectratio type="fixed"/> >+ <svg:svg width="2cm" height="2cm" viewBox="0 0 10 10"> >+ <svg:rect style="fill: background ; stroke: foreground ; stroke-width: 1" x="0" y="0" width="10" height="10"/> >+ <svg:line style="stroke-width: 1; stroke: foreground" x1="5" y1="1.5" x2="5" y2="8.5"/> >+ <svg:line style="stroke-width: 1; stroke: foreground" y1="5" x1="1.5" y2="5" x2="8.5"/> >+ </svg:svg> >+</shape> >Index: shapes/Misc/Makefile.am >=================================================================== >--- shapes/Misc/Makefile.am (revision 3659) >+++ shapes/Misc/Makefile.am (working copy) >@@ -7,7 +7,11 @@ > file.shape \ > file.png \ > folder.shape \ >- folder.png >+ folder.png \ >+ expended-node.shape \ >+ expended-node.png \ >+ expensible-node.shape \ >+ expensible-node.png > > EXTRA_DIST = $(SHAPES) > >Index: shapes/Misc/expended-node.svg >=================================================================== >--- shapes/Misc/expended-node.svg (revision 0) >+++ shapes/Misc/expended-node.svg (revision 0) >@@ -0,0 +1,25 @@ >+<?xml version="1.0"?> >+<!-- >+ (c)2007, Thomas Harding <thomas.harding@laposte.net> >+ >+ 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 >+ >+ >+--> >+<svg width="2cm" height="2cm" viewBox="0 0 20 20" >+ xmlns="http://www.w3.org/2000/svg"> >+ <rect style="fill: #ffffff ; stroke: #0000ff ; stroke-width: 1" x="0" y="0" width="20" height="20"/> >+ <line style="stroke-width: 1; stroke: #000000" x1="3" y1="10" x2="17" y2="10"/> >+ </svg> >Index: shapes/Misc/expended-node.shape >=================================================================== >--- shapes/Misc/expended-node.shape (revision 0) >+++ shapes/Misc/expended-node.shape (revision 0) >@@ -0,0 +1,37 @@ >+<?xml version="1.0"?> >+<!-- >+ (c)2007, Thomas Harding <thomas.harding@laposte.net> >+ >+ 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 >+ >+ >+--> >+<shape xmlns="http://www.daa.com.au/~james/dia-shape-ns" >+ xmlns:svg="http://www.w3.org/2000/svg"> >+ <name>Misc - expended node</name> >+ <icon>expended-node.png</icon> >+ <connections> >+ <point x="5" y="5" main="yes"/> >+ <point x="5" y="0"/> >+ <point x="0" y="5"/> >+ <point x="10" y="5"/> >+ <point x="5" y="10"/> >+ </connections> >+ <aspectratio type="fixed"/> >+ <svg:svg width="2cm" height="2cm" viewBox="0 0 10 10"> >+ <svg:rect style="fill: background ; stroke: foreground ; stroke-width: 1" x="0" y="0" width="10" height="10"/> >+ <svg:line style="stroke-width: 1; stroke: foreground" y1="5" x1="1.5" y2="5" x2="8.5"/> >+ </svg:svg> >+</shape>
Created attachment 86189 [details] [review] patch => add "tree" object and "+ & -" shapes to Misc sheet
Thank you for your contribution. Is this different from the Network - Bus object in any other way than that the branches point the same way at start? What kind of tree is this expected to be used for? It might belong in a different sheet, depending on the type of tree it's meant for.
The tree is vertical with all branches pointing to the right, and space between branches is convenient to add nodes or files objets without retouch them, but, as bus, they have not magnetic behaviour in this way (you can connect handles to objects, but not objects to handles). apart these points, the tree object is as bus object is (you can add/move handles to the left of the tree, resize tree length, etc). The tree object is just unhassle to use compared to bus when you want a tree :)
2007-10-20 Hans Breuer <hans@breuer.org> * objects/Misc/libmisc.c objects/Misc/tree.c objects/Misc/Makefile.am objects/Misc/pixmaps/tree.xpm shapes/Misc/expended-node.shape shapes/Misc/expensible-node.shape shapes/Misc/Makefile.am sheets/Misc.sheet.in : patch from Thomas Harding adding the shapes to simplify construction of explorer like trees, bug #428696 * shapes/Misc/expended-node.png shapes/Misc/expensible-node.png objects/Misc/pixmaps/tree.xpm : ... adapted to follow the default icons size and format, i.e. not adding SVG * objects/makefile.msc : build on win32