/* 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. */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include "intl.h" #include "object.h" #include "element.h" #include "diarenderer.h" #include "attributes.h" #include "text.h" #include "properties.h" #include "uml.h" #include "stereotype.h" #include "pixmaps/largepackage.xpm" typedef struct _LargePackage LargePackage; #define NUM_CONNECTIONS 9 struct _LargePackage { Element element; ConnectionPoint connections[NUM_CONNECTIONS]; char *name; char *stereotype; /* Can be NULL, including << and >> */ char *st_stereotype; DiaFont *font; Color text_color; Color line_color; Color fill_color; real topwidth; real topheight; }; #define LARGEPACKAGE_BORDERWIDTH 0.1 #define LARGEPACKAGE_FONTHEIGHT 0.8 static real largepackage_distance_from(LargePackage *pkg, Point *point); static void largepackage_select(LargePackage *pkg, Point *clicked_point, DiaRenderer *interactive_renderer); static ObjectChange* largepackage_move_handle(LargePackage *pkg, Handle *handle, Point *to, ConnectionPoint *cp, HandleMoveReason reason, ModifierKeys modifiers); static ObjectChange* largepackage_move(LargePackage *pkg, Point *to); static void largepackage_draw(LargePackage *pkg, DiaRenderer *renderer); static DiaObject *largepackage_create(Point *startpoint, void *user_data, Handle **handle1, Handle **handle2); static void largepackage_destroy(LargePackage *pkg); static void largepackage_update_data(LargePackage *pkg); static PropDescription *largepackage_describe_props(LargePackage *largepackage); static void largepackage_get_props(LargePackage *largepackage, GPtrArray *props); static void largepackage_set_props(LargePackage *largepackage, GPtrArray *props); static DiaObject *largepackage_load(ObjectNode obj_node, int version, const char *filename); static ObjectTypeOps largepackage_type_ops = { (CreateFunc) largepackage_create, (LoadFunc) largepackage_load,/*using_properties*/ /* load */ (SaveFunc) object_save_using_properties, /* save */ (GetDefaultsFunc) NULL, (ApplyDefaultsFunc) NULL }; DiaObjectType largepackage_type = { "UML - LargePackage", /* name */ 0, /* version */ (char **) largepackage_xpm, /* pixmap */ &largepackage_type_ops /* ops */ }; static ObjectOps largepackage_ops = { (DestroyFunc) largepackage_destroy, (DrawFunc) largepackage_draw, (DistanceFunc) largepackage_distance_from, (SelectFunc) largepackage_select, (CopyFunc) object_copy_using_properties, (MoveFunc) largepackage_move, (MoveHandleFunc) largepackage_move_handle, (GetPropertiesFunc) object_create_props_dialog, (ApplyPropertiesFunc) object_apply_props_from_dialog, (ObjectMenuFunc) NULL, (DescribePropsFunc) largepackage_describe_props, (GetPropsFunc) largepackage_get_props, (SetPropsFunc) largepackage_set_props }; static PropDescription largepackage_props[] = { ELEMENT_COMMON_PROPERTIES, PROP_STD_LINE_COLOUR_OPTIONAL, PROP_STD_FILL_COLOUR_OPTIONAL, /* can't use PROP_STD_TEXT_COLOUR_OPTIONAL cause it has PROP_FLAG_DONT_SAVE. It is designed to fill the Text object - not some subset */ PROP_STD_TEXT_COLOUR_OPTIONS(PROP_FLAG_VISIBLE|PROP_FLAG_STANDARD|PROP_FLAG_OPTIONAL), { "stereotype", PROP_TYPE_STRING, PROP_FLAG_VISIBLE, N_("Stereotype"), NULL, NULL }, { "name", PROP_TYPE_STRING, PROP_FLAG_VISIBLE, N_("Name"), NULL, NULL }, PROP_DESC_END }; static PropDescription * largepackage_describe_props(LargePackage *largepackage) { if (largepackage_props[0].quark == 0) { prop_desc_list_calculate_quarks(largepackage_props); } return largepackage_props; } static PropOffset largepackage_offsets[] = { ELEMENT_COMMON_PROPERTIES_OFFSETS, {"line_colour",PROP_TYPE_COLOUR,offsetof(LargePackage,line_color)}, {"fill_colour",PROP_TYPE_COLOUR,offsetof(LargePackage,fill_color)}, {"text_colour",PROP_TYPE_COLOUR,offsetof(LargePackage,text_color)}, {"stereotype", PROP_TYPE_STRING, offsetof(LargePackage , stereotype) }, {"name", PROP_TYPE_STRING, offsetof(LargePackage , name) }, { NULL, 0, 0 }, }; static void largepackage_get_props(LargePackage * largepackage, GPtrArray *props) { object_get_props_from_offsets(&largepackage->element.object, largepackage_offsets, props); } static void largepackage_set_props(LargePackage *largepackage, GPtrArray *props) { object_set_props_from_offsets(&largepackage->element.object, largepackage_offsets, props); g_free(largepackage->st_stereotype); largepackage->st_stereotype = NULL; largepackage_update_data(largepackage); } static real largepackage_distance_from(LargePackage *pkg, Point *point) { DiaObject *obj = &pkg->element.object; return distance_rectangle_point(&obj->bounding_box, point); } static void largepackage_select(LargePackage *pkg, Point *clicked_point, DiaRenderer *interactive_renderer) { element_update_handles(&pkg->element); } static ObjectChange* largepackage_move_handle(LargePackage *pkg, Handle *handle, Point *to, ConnectionPoint *cp, HandleMoveReason reason, ModifierKeys modifiers) { assert(pkg!=NULL); assert(handle!=NULL); assert(to!=NULL); assert(handle->id < 8); element_move_handle(&pkg->element, handle->id, to, cp, reason, modifiers); largepackage_update_data(pkg); return NULL; } static ObjectChange* largepackage_move(LargePackage *pkg, Point *to) { pkg->element.corner = *to; largepackage_update_data(pkg); return NULL; } static void largepackage_draw(LargePackage *pkg, DiaRenderer *renderer) { DiaRendererClass *renderer_ops = DIA_RENDERER_GET_CLASS (renderer); Element *elem; real x, y, w, h; Point p1, p2; assert(pkg != NULL); assert(renderer != NULL); elem = &pkg->element; x = elem->corner.x; y = elem->corner.y; w = elem->width; h = elem->height; renderer_ops->set_fillstyle(renderer, FILLSTYLE_SOLID); renderer_ops->set_linewidth(renderer, LARGEPACKAGE_BORDERWIDTH); renderer_ops->set_linestyle(renderer, LINESTYLE_SOLID); p1.x = x; p1.y = y; p2.x = x+w; p2.y = y+h; renderer_ops->fill_rect(renderer, &p1, &p2, &pkg->fill_color); renderer_ops->draw_rect(renderer, &p1, &p2, &pkg->line_color); p1.x= x; p1.y = y - pkg->topheight; p2.x = x + pkg->topwidth; p2.y = y; renderer_ops->fill_rect(renderer, &p1, &p2, &pkg->fill_color); renderer_ops->draw_rect(renderer, &p1, &p2, &pkg->line_color); renderer_ops->set_font(renderer, pkg->font, LARGEPACKAGE_FONTHEIGHT); p1.x = x + 0.1; p1.y = y - LARGEPACKAGE_FONTHEIGHT - dia_font_descent(pkg->st_stereotype, pkg->font, LARGEPACKAGE_FONTHEIGHT) - 0.1; if (pkg->st_stereotype && pkg->st_stereotype[0] != '\0') { renderer_ops->draw_string(renderer, pkg->st_stereotype, &p1, ALIGN_LEFT, &pkg->text_color); } p1.y += LARGEPACKAGE_FONTHEIGHT; if (pkg->name) renderer_ops->draw_string(renderer, pkg->name, &p1, ALIGN_LEFT, &pkg->text_color); } static void largepackage_update_data(LargePackage *pkg) { Element *elem = &pkg->element; DiaObject *obj = &elem->object; pkg->stereotype = remove_stereotype_from_string(pkg->stereotype); if (!pkg->st_stereotype) { pkg->st_stereotype = string_to_stereotype(pkg->stereotype); } pkg->topheight = LARGEPACKAGE_FONTHEIGHT + 0.1*2; pkg->topwidth = 2.0; if (pkg->name != NULL) pkg->topwidth = MAX(pkg->topwidth, dia_font_string_width(pkg->name, pkg->font, LARGEPACKAGE_FONTHEIGHT)+2*0.1); if (pkg->st_stereotype != NULL && pkg->st_stereotype[0] != '\0') { pkg->topwidth = MAX(pkg->topwidth, dia_font_string_width(pkg->st_stereotype, pkg->font, LARGEPACKAGE_FONTHEIGHT)+2*0.1); pkg->topheight += LARGEPACKAGE_FONTHEIGHT; } if (elem->width < (pkg->topwidth + 0.2)) elem->width = pkg->topwidth + 0.2; if (elem->height < 1.0) elem->height = 1.0; /* Update connections: */ element_update_connections_rectangle(elem, pkg->connections); element_update_boundingbox(elem); /* fix boundingbox for top rectangle: */ obj->bounding_box.top -= pkg->topheight; obj->position = elem->corner; element_update_handles(elem); } static DiaObject * largepackage_create(Point *startpoint, void *user_data, Handle **handle1, Handle **handle2) { LargePackage *pkg; Element *elem; DiaObject *obj; int i; pkg = g_malloc0(sizeof(LargePackage)); elem = &pkg->element; obj = &elem->object; obj->type = &largepackage_type; obj->ops = &largepackage_ops; obj->flags |= DIA_OBJECT_CAN_PARENT; elem->corner = *startpoint; element_init(elem, 8, NUM_CONNECTIONS); elem->width = 4.0; elem->height = 4.0; pkg->text_color = color_black; pkg->line_color = attributes_get_foreground(); pkg->fill_color = attributes_get_background(); pkg->font = dia_font_new_from_style(DIA_FONT_MONOSPACE, LARGEPACKAGE_FONTHEIGHT); pkg->stereotype = NULL; pkg->st_stereotype = NULL; pkg->name = g_strdup(""); pkg->topwidth = 2.0; pkg->topheight = LARGEPACKAGE_FONTHEIGHT*2 + 0.1*2; for (i=0;iconnections[i] = &pkg->connections[i]; pkg->connections[i].object = obj; pkg->connections[i].connected = NULL; } pkg->connections[8].flags = CP_FLAGS_MAIN; pkg->element.extra_spacing.border_trans = LARGEPACKAGE_BORDERWIDTH/2.0; largepackage_update_data(pkg); *handle1 = NULL; *handle2 = obj->handles[7]; return &pkg->element.object; } static void largepackage_destroy(LargePackage *pkg) { dia_font_unref(pkg->font); g_free(pkg->stereotype); g_free(pkg->st_stereotype); g_free(pkg->name); element_destroy(&pkg->element); } static DiaObject * largepackage_load(ObjectNode obj_node, int version, const char *filename) { return object_load_using_properties(&largepackage_type, obj_node,version,filename); }