from flash.text.engine import (TextElement, ElementFormat, FontDescription, TextBlock) from graph import Colors @package('graph') class Drawer: def __init__(self, graph, sprite): self.graph = graph self.sprite = sprite self.canvas = sprite.graphics def color(self, value): if not value: return 0 if value.charAt(0) == '#': return int('0x' + value.substring(1)) else: return Colors.x11[value.toLowerCase()] def draw(self): for node in values(self.graph.nodes): self['node_' + node.shape](node) self.label_node(node) for edge in values(self.graph.edges): self.draw_edge(edge) def node_ellipse(self, node): if node.style == 'filled': self.canvas.beginFill(self.color(node.color)) else: self.canvas.lineStyle(1, self.color(node.color)) self.canvas.drawEllipse(node.x-node.width*36, node.y-node.height*36, node.width*72, node.height*72) if node.style == 'filled': self.canvas.endFill() def node_circle(self, node): if node.style == 'filled': self.canvas.beginFill(self.color(node.fillcolor)) else: self.canvas.lineStyle(1, self.color(node.color)) self.canvas.drawCircle(node.x, node.y, node.width*36) if node.style == 'filled': self.canvas.endFill() def node_doublecircle(self, node): self.canvas.lineStyle(1, self.color(node.color)) self.canvas.drawCircle(node.x, node.y, node.width*36) if node.style == 'filled': self.canvas.beginFill(self.color(node.fillcolor)) self.canvas.drawCircle(node.x, node.y, node.width*36 - 4) if node.style == 'filled': self.canvas.endFill() def draw_edge(self, edge): self.canvas.lineStyle(1, self.color(edge.color)) if self.startpoint: self.canvas.moveTo(edge.startpoint.x, edge.startpoint.y) self.canvas.lineTo(edge.path[0].x, edge.path[0].y) else: self.canvas.moveTo(edge.path[0].x, edge.path[0].y) for i in range(1, edge.path.length, 3): self.canvas.curveTo(edge.path[i].x, edge.path[i].y, (edge.path[i].x+edge.path[i+1].x)*0.5, (edge.path[i].y+edge.path[i+1].y)*0.5) self.canvas.curveTo(edge.path[i+1].x, edge.path[i+1].y, edge.path[i+2].x, edge.path[i+2].y) self['arrow_' + edge.arrowhead](self.color(edge.color), edge.path[edge.path.length-1], edge.endpoint) def arrow_normal(self, color, center, end): dx = center.x - end.x dy = center.y - end.y s = 0.259 # sin 15 c = 0.966 # cos 15 ax = (dx*c - dy*s)*1.5 ay = (dx*s + dy*c)*1.5 s = -0.259 # sin -15 c = 0.966 # cos -15 bx = (dx*c - dy*s)*1.5 by = (dx*s + dy*c)*1.5 self.canvas.beginFill(color) self.canvas.moveTo(end.x, end.y) self.canvas.lineTo(end.x+ax, end.y+ay) self.canvas.lineTo(center.x, center.y) self.canvas.lineTo(end.x+bx, end.y+by) self.canvas.endFill() def label_node(self, node): font = FontDescription("Arial") format = ElementFormat(font) format.fontSize = 14 el = TextElement(node.label or node.name, format) block = TextBlock() block.content = el tl = block.createTextLine(None, node.width*36) pos = node.label_pos if not pos: pos = node tl.x = int(pos.x-tl.width/2) tl.y = int(pos.y+tl.height/2) self.sprite.addChild(tl)