2006-12-05 David Lodge <dave@cirt.net>
[dia.git] / objects / UML / umlattribute.c
blob946c92ab1252496f06fb6298ef226c280d762b74
1 /* Dia -- an diagram creation/manipulation program
2 * Copyright (C) 1998 Alexander Larsson
4 * umlattribute.c : refactored from uml.c, class.c to final use StdProps
5 * PROP_TYPE_DARRAY, a list where each element is a set
6 * of properies described by the same StdPropDesc
7 * Copyright (C) 2005 Hans Breuer
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
28 #include <string.h>
30 #include "uml.h"
31 #include "properties.h"
33 extern PropEnumData _uml_visibilities[];
35 static PropDescription umlattribute_props[] = {
36 { "name", PROP_TYPE_STRING, PROP_FLAG_VISIBLE | PROP_FLAG_OPTIONAL,
37 N_("Name"), NULL, NULL },
38 { "type", PROP_TYPE_STRING, PROP_FLAG_VISIBLE | PROP_FLAG_OPTIONAL,
39 N_("Type"), NULL, NULL },
40 { "value", PROP_TYPE_STRING, PROP_FLAG_VISIBLE | PROP_FLAG_OPTIONAL,
41 N_("Value"), NULL, NULL },
42 { "comment", PROP_TYPE_STRING, PROP_FLAG_VISIBLE | PROP_FLAG_OPTIONAL,
43 N_("Comment"), NULL, NULL },
44 { "visibility", PROP_TYPE_ENUM, PROP_FLAG_VISIBLE | PROP_FLAG_OPTIONAL,
45 N_("Visibility"), NULL, _uml_visibilities },
46 { "abstract", PROP_TYPE_BOOL, PROP_FLAG_VISIBLE | PROP_FLAG_OPTIONAL,
47 N_("Abstract (?)"), NULL, NULL },
48 { "class_scope", PROP_TYPE_BOOL, PROP_FLAG_VISIBLE | PROP_FLAG_OPTIONAL,
49 N_("Class scope (static)"), NULL, NULL },
51 PROP_DESC_END
54 static PropOffset umlattribute_offsets[] = {
55 { "name", PROP_TYPE_STRING, offsetof(UMLAttribute, name) },
56 { "type", PROP_TYPE_STRING, offsetof(UMLAttribute, type) },
57 { "value", PROP_TYPE_STRING, offsetof(UMLAttribute, value) },
58 { "comment", PROP_TYPE_STRING, offsetof(UMLAttribute, comment) },
59 { "visibility", PROP_TYPE_ENUM, offsetof(UMLAttribute, visibility) },
60 { "abstract", PROP_TYPE_BOOL, offsetof(UMLAttribute, abstract) },
61 { "class_scope", PROP_TYPE_BOOL, offsetof(UMLAttribute, class_scope) },
62 { NULL, 0, 0 },
66 PropDescDArrayExtra umlattribute_extra = {
67 { umlattribute_props, umlattribute_offsets, "umlattribute" },
68 (NewRecordFunc)uml_attribute_new,
69 (FreeRecordFunc)uml_attribute_destroy
73 UMLAttribute *
74 uml_attribute_new(void)
76 UMLAttribute *attr;
77 static gint next_id = 1;
79 attr = g_new0(UMLAttribute, 1);
80 attr->internal_id = next_id++;
81 attr->name = g_strdup("");
82 attr->type = g_strdup("");
83 attr->value = NULL;
84 attr->comment = g_strdup("");
85 attr->visibility = UML_PUBLIC;
86 attr->abstract = FALSE;
87 attr->class_scope = FALSE;
88 #if 0 /* setup elsewhere */
89 attr->left_connection = g_new0(ConnectionPoint, 1);
90 attr->right_connection = g_new0(ConnectionPoint, 1);
91 #endif
92 return attr;
95 /** Copy the data of an attribute into another, but not the connections.
96 * Frees up any strings in the attribute being copied into. */
97 void
98 uml_attribute_copy_into(UMLAttribute *attr, UMLAttribute *newattr)
100 newattr->internal_id = attr->internal_id;
101 if (newattr->name != NULL) {
102 g_free(newattr->name);
104 newattr->name = g_strdup(attr->name);
105 if (newattr->type != NULL) {
106 g_free(newattr->type);
108 newattr->type = g_strdup(attr->type);
110 if (newattr->value != NULL) {
111 g_free(newattr->value);
113 if (attr->value != NULL) {
114 newattr->value = g_strdup(attr->value);
115 } else {
116 newattr->value = NULL;
119 if (newattr->comment != NULL) {
120 g_free(newattr->comment);
122 if (attr->comment != NULL)
123 newattr->comment = g_strdup (attr->comment);
124 else
125 newattr->comment = NULL;
127 newattr->visibility = attr->visibility;
128 newattr->abstract = attr->abstract;
129 newattr->class_scope = attr->class_scope;
132 /** Copy an attribute's content.
134 UMLAttribute *
135 uml_attribute_copy(UMLAttribute *attr)
137 UMLAttribute *newattr;
139 newattr = g_new0(UMLAttribute, 1);
141 uml_attribute_copy_into(attr, newattr);
143 return newattr;
146 void
147 uml_attribute_destroy(UMLAttribute *attr)
149 g_free(attr->name);
150 g_free(attr->type);
151 if (attr->value != NULL)
152 g_free(attr->value);
153 if (attr->comment != NULL)
154 g_free(attr->comment);
155 #if 0 /* free'd elsewhere */
156 g_free(attr->left_connection);
157 g_free(attr->right_connection);
158 #endif
159 g_free(attr);
162 void
163 uml_attribute_write(AttributeNode attr_node, UMLAttribute *attr)
165 DataNode composite;
167 composite = data_add_composite(attr_node, "umlattribute");
169 data_add_string(composite_add_attribute(composite, "name"),
170 attr->name);
171 data_add_string(composite_add_attribute(composite, "type"),
172 attr->type);
173 data_add_string(composite_add_attribute(composite, "value"),
174 attr->value);
175 data_add_string(composite_add_attribute(composite, "comment"),
176 attr->comment);
177 data_add_enum(composite_add_attribute(composite, "visibility"),
178 attr->visibility);
179 data_add_boolean(composite_add_attribute(composite, "abstract"),
180 attr->abstract);
181 data_add_boolean(composite_add_attribute(composite, "class_scope"),
182 attr->class_scope);
185 /* Warning, the following *must* be strictly ASCII characters (or fix the
186 following code for UTF-8 cleanliness */
188 char visible_char[] = { '+', '-', '#', ' ' };
190 char *
191 uml_get_attribute_string (UMLAttribute *attribute)
193 int len;
194 char *str;
196 len = 1 + strlen (attribute->name) + strlen (attribute->type);
197 if (attribute->name[0] && attribute->type[0]) {
198 len += 2;
200 if (attribute->value != NULL && attribute->value[0] != '\0') {
201 len += 3 + strlen (attribute->value);
204 str = g_malloc (sizeof (char) * (len + 1));
206 str[0] = visible_char[(int) attribute->visibility];
207 str[1] = 0;
209 strcat (str, attribute->name);
210 if (attribute->name[0] && attribute->type[0]) {
211 strcat (str, ": ");
213 strcat (str, attribute->type);
214 if (attribute->value != NULL && attribute->value[0] != '\0') {
215 strcat (str, " = ");
216 strcat (str, attribute->value);
219 g_assert (strlen (str) == len);
221 return str;
225 * The ownership of these connection points is quite complicated. Instead of being part of the UMLAttribute as one may expect
226 * at first, they are somewhat in between the DiaObject (see: DiaObject::connections and the concrete user, here UMLClass)
227 * and the UMLAttribute.
228 * But with taking undo state mangement into account it gets even worse. Deleted (to be restored connection points) live inside
229 * the UMLClassChange until they get reverted back to the object *or* get free'd by umlclass_change_free()
230 * Since the implementation of attributes/operations being settable via StdProps there are more places to keep this stuff
231 * consitent. So here comes a tolerant helper.
233 * NOTE: Same function as uml_operation_ensure_connection_points(), with C++ it would be a template function ;)
235 void
236 uml_attribute_ensure_connection_points (UMLAttribute* attr, DiaObject* obj)
238 if (!attr->left_connection)
239 attr->left_connection = g_new0(ConnectionPoint,1);
240 attr->left_connection->object = obj;
241 if (!attr->right_connection)
242 attr->right_connection = g_new0(ConnectionPoint,1);
243 attr->right_connection->object = obj;