def build(cls, tree, config=None, layout=True): DiagramNode.clear() DiagramEdge.clear() NodeGroup.clear() Diagram.clear() return cls(tree, config, layout).run()
def compare_child_node_order(self, parent, node1, node2): def compare(x, y): x = x.duplicate() y = y.duplicate() while x.node1 == y.node1 and x.node1.group is not None: x.node1 = x.node1.group y.node1 = y.node1.group # cmp x.node1.order and y.node1.order if x.node1.order < y.node1.order: return -1 elif x.node1.order == y.node1.order: return 0 else: return 1 edges = (DiagramEdge.find(parent, node1) + DiagramEdge.find(parent, node2)) edges.sort(key=cmp_to_key(compare)) if len(edges) == 0: return 0 elif edges[0].node2 == node2: return 1 else: return -1
def run(self): for i, group in enumerate(self._groups): base = self.diagram.duplicate() base.level = group.level - 1 # bind edges on base diagram (outer the group) edges = (DiagramEdge.find(None, group) + DiagramEdge.find(group, None)) base.edges = self._filter_edges(edges, self.diagram, group.level) # bind edges on target group (inner the group) subgroups = group.traverse_groups() edges = sum([g.edges for g in subgroups], group.edges) group.edges = [] for e in self._filter_edges(edges, group, group.level): if isinstance(e.node1, NodeGroup) and e.node1 == e.node2: pass else: group.edges.append(e) # clear subgroups in the group for g in group.nodes: if isinstance(g, NodeGroup): g.nodes = [] g.edges = [] g.separated = True # pick up nodes to base diagram nodes1 = [e.node1 for e in DiagramEdge.find(None, group)] nodes1.sort(key=lambda x: x.order) nodes2 = [e.node2 for e in DiagramEdge.find(group, None)] nodes2.sort(key=lambda x: x.order) nodes = nodes1 + [group] + nodes2 for i, n in enumerate(nodes): n.order = i if n not in base.nodes: base.nodes.append(n) n.group = base if isinstance(group, Diagram): base = group DiagramLayoutManager(base).run() base.fixiate(True) EdgeLayoutManager(base).run() yield base
def run(self): if isinstance(self.diagram, Diagram): for group in self.diagram.traverse_groups(): self.__class__(group).run() self.edges = DiagramEdge.find_by_level(self.diagram.level) self.do_layout() self.diagram.fixiate() if self.diagram.orientation == 'portrait': self.rotate_diagram()
def instantiate(self, group, tree): for stmt in tree.stmts: # Translate Node having group attribute to Group if isinstance(stmt, parser.Node): group_attr = [a for a in stmt.attrs if a.name == 'group'] if group_attr: group_id = group_attr[-1] stmt.attrs.remove(group_id) if group_id.value != group.id: stmt = parser.Group(group_id.value, [stmt]) # Instantiate statements if isinstance(stmt, parser.Node): node = DiagramNode.get(stmt.id) node.set_attributes(stmt.attrs) self.belong_to(node, group) elif isinstance(stmt, parser.Edge): from_nodes = [DiagramNode.get(n) for n in stmt.from_nodes] to_nodes = [DiagramNode.get(n) for n in stmt.to_nodes] for node in from_nodes + to_nodes: self.belong_to(node, group) for node1 in from_nodes: for node2 in to_nodes: edge = DiagramEdge.get(node1, node2) edge.set_dir(stmt.edge_type) edge.set_attributes(stmt.attrs) elif isinstance(stmt, parser.Group): subgroup = NodeGroup.get(stmt.id) subgroup.level = group.level + 1 self.belong_to(subgroup, group) self.instantiate(subgroup, stmt) elif isinstance(stmt, parser.Attr): group.set_attribute(stmt) elif isinstance(stmt, parser.Extension): if stmt.type == 'class': name = unquote(stmt.name) Diagram.classes[name] = stmt elif stmt.type == 'plugin': self.diagram.set_plugin(stmt.name, stmt.attrs, config=self.config) elif isinstance(stmt, parser.Statements): self.instantiate(group, stmt) group.update_order() return group
def get_parent_node_ypos(self, parent, child): heights = [] for e in DiagramEdge.find(parent, child): y = parent.xy.y node = e.node1 while node != parent: y += node.xy.y node = node.group heights.append(y) if heights: return min(heights) else: return None
def _groups(self): # Store nodes and edges of subgroups nodes = {self.diagram: self.diagram.nodes} edges = {self.diagram: self.diagram.edges} levels = {self.diagram: self.diagram.level} for group in self.diagram.traverse_groups(): nodes[group] = group.nodes edges[group] = group.edges levels[group] = group.level groups = {} orders = {} for node in self.diagram.traverse_nodes(): groups[node] = node.group orders[node] = node.order for group in self.diagram.traverse_groups(): yield group # Restore nodes, groups and edges for g in nodes: g.nodes = nodes[g] g.edges = edges[g] g.level = levels[g] for n in groups: n.group = groups[n] n.order = orders[n] n.xy = XY(0, 0) n.colwidth = 1 n.colheight = 1 n.separated = False for edge in DiagramEdge.find_all(): edge.skipped = False edge.crosspoints = [] yield self.diagram
def bind_edges(self, group): for node in group.nodes: if isinstance(node, DiagramNode): group.edges += DiagramEdge.find(node) else: self.bind_edges(node)