1#    PyDia Self Documentation Series - Part II : Object Types
2#    Copyright (c) 2003, Hans Breuer <hans@breuer.org>
3#
4#        generates a new diagram which contains all the currently
5#    registered object types sorted by their containing package
6#
7
8#    This program is free software; you can redistribute it and/or modify
9#   it under the terms of the GNU General Public License as published by
10#   the Free Software Foundation; either version 2 of the License, or
11#   (at your option) any later version.
12#
13#   This program is distributed in the hope that it will be useful,
14#   but WITHOUT ANY WARRANTY; without even the implied warranty of
15#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16#   GNU General Public License for more details.
17#
18#   You should have received a copy of the GNU General Public License
19#   along with this program; if not, write to the Free Software
20#   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21
22import sys, dia, string
23
24def _log(s, append=1) :
25	pass
26	if append :
27		mode = "a"
28	else :
29		mode = "w"
30	f = open("c:\\temp\\otypes.log", mode)
31	f.write(s)
32
33def otypes_cb(data, flags) :
34
35	if data :
36		diagram = None # we may be running w/o GUI
37	else :
38		diagram = dia.new("Object Types.dia")
39		data = diagram.data
40	layer = data.active_layer
41
42	otypes = dia.registered_types()
43	keys = otypes.keys()
44	keys.sort()
45
46	# property keys w/o overlap
47	object_props = ["obj_pos", "obj_bb", "meta"]
48	element_props = ["elem_corner", "elem_width", "elem_height"]
49	orthconn_props = ["orth_points", "orth_orient", "orth_autoroute"]
50	shape_props = ["flip_horizontal", "flip_vertical"]
51	# the following are not exclusuve to any objects type
52	line_props = ["line_width", "line_style", "line_colour"]
53	fill_props = ["fill_colour", "show_background"]
54	text_props = ["text_colour", "text_font", "text_height", "text"] # "text_alignment", "text_pos"
55
56	packages = {}
57	for s in keys :
58		kt = string.split(s, " - ")
59		if len(kt) == 2 :
60			if len(kt[0]) == 0 :
61				sp = "<unnamed>"
62			else :
63				sp = kt[0]
64			st = kt[1]
65		else :
66			sp = "<broken>"
67			st = kt[0]
68		if packages.has_key(sp) :
69			packages[sp].append(st)
70		else :
71			packages[sp] = [st]
72
73	dtp = dia.get_object_type("UML - LargePackage")
74	dtc = dia.get_object_type("UML - Class")
75	cy = 0
76	maxy = 0
77	maxx = 0
78
79	for sp in packages.keys() :
80		pkg = packages[sp]
81		op, h1, h2 = dtp.create(0.0, cy + 1.0)
82		op.properties["name"] = sp
83		layer.add_object(op)
84		cx = 0
85		for st in pkg :
86			if st == "Group" :
87				continue # too special to handle
88			oc, h3, h4 = dtc.create(cx + 1.0, cy + 4.0)
89			oc.properties["name"] = st
90			attrs = []
91			# we detect inheritance by common props
92			n_object = 0
93			n_element = 0
94			n_orthconn = 0
95			n_shape = 0
96			n_line = 0
97			n_fill = 0
98			n_text = 0
99			if otypes.has_key(st) :
100				o_real, h5, h6 = dia.get_object_type(st).create(0,0)
101			elif otypes.has_key(sp + " - " + st) :
102				o_real, h5, h6 = dia.get_object_type(sp + " - " + st).create(0,0)
103			else :
104				o_real = None
105				print "Failed to create object", sp, st
106			formal_params = []
107			if not o_real is None :
108				for p in o_real.properties.keys() :
109					if p in object_props : n_object = n_object + 1
110					elif p in orthconn_props : n_orthconn = n_orthconn + 1
111					elif p in element_props : n_element = n_element + 1
112					elif p in shape_props : n_shape = n_shape + 1
113					elif p in line_props : n_line = n_line + 1
114					elif p in text_props : n_text = n_text + 1
115					elif p in fill_props : n_fill = n_fill + 1
116					else : # don't replicate common props
117						attrs.append((p, o_real.properties[p].type, '', '', 0, 0, 0))
118				if n_line == len(line_props) :
119					formal_params.append(('Line', ''))
120				else : # need to add the incomplete set
121					for pp in line_props :
122						if o_real.properties.has_key(pp) :
123							attrs.append((pp, o_real.properties[pp].type, '', '', 0, 0, 0))
124				if n_fill == len(fill_props) :
125					formal_params.append(('Fill', ''))
126				else :
127					for pp in fill_props :
128						if o_real.properties.has_key(pp) :
129							attrs.append((pp, o_real.properties[pp].type, '', '', 0, 0, 0))
130				if n_text == len(text_props) :
131					formal_params.append(('Text', ''))
132				else :
133					for pp in text_props :
134						if o_real.properties.has_key(pp) :
135							attrs.append((pp, o_real.properties[pp].type, '', '', 0, 0, 0))
136			if n_orthconn == len(orthconn_props) :
137				oc.properties["stereotype"] = "OrthConn"
138				oc.properties["fill_colour"] = "light blue"
139			elif n_shape == len(shape_props) :
140				oc.properties["stereotype"] = "Shape"
141				oc.properties["fill_colour"] = "light cyan"
142			elif n_element == len(element_props) :
143				oc.properties["stereotype"] = "Element"
144				oc.properties["fill_colour"] = "light yellow"
145			elif n_object == len(object_props) :
146				oc.properties["stereotype"] = "Object"
147			else :
148				print "Huh?", st
149				oc.properties["fill_colour"] = "red"
150			oc.properties["attributes"] = attrs
151			if len(formal_params) > 0 :
152				oc.properties["template"] = 1
153				oc.properties["templates"] = formal_params
154			layer.add_object(oc)
155			# XXX: there really should be a way to safely delete an object. This one will crash:
156			# - when the object got added somewhere
157			# - any object method gets called afterwards
158			if not o_real is None :
159				o_real.destroy()
160				del o_real
161			cx = oc.bounding_box.right
162			if maxy < oc.bounding_box.bottom :
163				maxy = oc.bounding_box.bottom
164			if maxx < cx :
165				maxx = cx
166			# wrapping too long lines
167			if cx > 300 :
168				cx = 0
169				cy = maxy
170		h = op.handles[7]
171		# adjust the package size to fit the objects
172		op.move_handle(h,(maxx + 1.0, maxy + 1.0), 0, 0)
173		cy = maxy + 2.0
174		maxx = 0 # every package a new size
175	data.update_extents()
176	if diagram :
177		diagram.display()
178		diagram.flush()
179	# make it work standalone
180	return data
181
182dia.register_action ("HelpOtypes", "Dia Object Types",
183                     "/ToolboxMenu/Help/HelpExtensionStart",
184                     otypes_cb)
185