# PyDia DOT Renderer
# Copyright (c) 2005 Hans Breuer <hans@breuer.org>

# A Dia export filter based on the object export interface.
# Generating output in the DOT language. That can be processed
# with the dot tool from http://www.graphviz.org

#    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., 675 Mass Ave, Cambridge, MA 02139, USA.

import sys, dia

class DotRenderer :
	def __init__ (self) :
		self.nodes = {}
		self.edges = {}
	def GetName (self, o) :
		"A small helper to turn a dia object into a name"
		s = ""
		if o.properties.has_key("name") :
			s = o.properties["name"].value
		elif o.properties.has_key("text") :
			s = o.properties["text"].value.text
		if s is None or s == "" :
			s = str(o)
		return s
	def GetColor (self, o) :
		if o.properties.has_key("fill_colour") :
			rgb = o.properties["fill_colour"].value
			return "#%02x%02x%02x" % (rgb.red * 255, rgb.green * 255, rgb.blue * 255)
		return None
	def begin_render (self, data, filename) :
		self.f = open(filename, "w")
		self.f.write ("# %s\n" % (filename,))
		self.f.write ("# generated by (dia)dot.py\n")
		self.f.write ("digraph test {\n")
		# preserve the ratio as given by the bounding box
		rect = data.extents
		ratio = (rect.bottom - rect.top) / (rect.right - rect.left)
		self.f.write ("ratio=%.3f\n" % (ratio,))
		# extract some attributes as well as grouping
		self.f.write("node [style=filled]\n") # otherwise fillcolor is ignored
		for layer in data.layers :
			for o in layer.objects :
				if len(o.connections) < 1 :
					continue # no node
				if o.type.name == "Group" :
					continue # FIXME : iterate these, but we seem them below, too
				sColor = self.GetColor (o)
				if sColor and sColor != "#ffffff" : # dont write the default
					self.f.write('"%s" [fillcolor="%s"];\n' % (self.GetName(o), self.GetColor (o)))
		for layer in data.layers :
			for o in layer.objects :
				for c in o.connections :
					# these are the connection points of the objects. We will have e.g. "UML - Dependency"
					for n in c.connected :
						# we see the connecting lines multiple times, just process once
						if self.edges.has_key(str(n)) :
							continue
						self.edges[str(n)] = 1
						if not (n.handles[0].connected_to and n.handles[1].connected_to) :
							continue
						# the right handles give us the direction 
						a = n.handles[0].connected_to.object
						b = n.handles[1].connected_to.object
						try :
							self.f.write('"%s" -> "%s"\n' % (self.GetName(a), self.GetName(b)))
							#self.f.write('"%s" -> "%s"\n' % (str(a.properties["text"].value.text), str(b.properties["text"].value.text)))
						except :
							print a, b, " writing connection failed."
				else :
					pass
		self.f.write('}\n')
	def end_render (self) :
		self.f.close()
	
# dia-python keeps a reference to the renderer class and uses it on demand
dia.register_export ("PyDia DOT Export", "dot", DotRenderer())
