https://github.com/jrfonseca/xdot.py/pull/68
1 | 1 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,14 @@ |
1 |
+digraph draworder { |
|
2 |
+ outputorder=nodesfirst; |
|
3 |
+ size ="8.5, 11"; |
|
4 |
+ 0 [shape = circle, style = filled, color = lightgrey ]; |
|
5 |
+ 2 [ shape = trapezium, style = filled, color = lightgrey, label = < |
|
6 |
+ <table border='0' cellborder='0'> |
|
7 |
+ <tr><td port='a'>A</td><td port='b'>B</td></tr> |
|
8 |
+ <tr><td colspan='2'>Some label goes here</td></tr> |
|
9 |
+ </table> |
|
10 |
+ >]; |
|
11 |
+ |
|
12 |
+ 0 -> 2:a [ label = "a" ]; |
|
13 |
+ 0 -> 2:b [ label = "b" ]; |
|
14 |
+} |
... | ... |
@@ -437,6 +437,7 @@ class XDotParser(DotParser): |
437 | 437 |
self.top_graph = True |
438 | 438 |
self.width = 0 |
439 | 439 |
self.height = 0 |
440 |
+ self.outputorder = 'breadthfirst' |
|
440 | 441 |
|
441 | 442 |
def handle_graph(self, attrs): |
442 | 443 |
if self.top_graph: |
... | ... |
@@ -450,6 +451,12 @@ class XDotParser(DotParser): |
450 | 451 |
sys.stderr.write('warning: xdot version %s, but supported is %s\n' % |
451 | 452 |
(xdotversion, self.XDOTVERSION)) |
452 | 453 |
|
454 |
+ # Parse output order |
|
455 |
+ try: |
|
456 |
+ self.outputorder = attrs['outputorder'].decode('utf-8') |
|
457 |
+ except KeyError: |
|
458 |
+ pass |
|
459 |
+ |
|
453 | 460 |
# Parse bounding box |
454 | 461 |
try: |
455 | 462 |
bb = attrs['bb'] |
... | ... |
@@ -526,7 +533,7 @@ class XDotParser(DotParser): |
526 | 533 |
def parse(self): |
527 | 534 |
DotParser.parse(self) |
528 | 535 |
return elements.Graph(self.width, self.height, self.shapes, |
529 |
- self.nodes, self.edges) |
|
536 |
+ self.nodes, self.edges, self.outputorder) |
|
530 | 537 |
|
531 | 538 |
def parse_node_pos(self, pos): |
532 | 539 |
x, y = pos.split(b",") |
... | ... |
@@ -544,7 +544,7 @@ class Edge(Element): |
544 | 544 |
|
545 | 545 |
class Graph(Shape): |
546 | 546 |
|
547 |
- def __init__(self, width=1, height=1, shapes=(), nodes=(), edges=()): |
|
547 |
+ def __init__(self, width=1, height=1, shapes=(), nodes=(), edges=(), outputorder='breadthfirst'): |
|
548 | 548 |
Shape.__init__(self) |
549 | 549 |
|
550 | 550 |
self.width = width |
... | ... |
@@ -552,6 +552,7 @@ class Graph(Shape): |
552 | 552 |
self.shapes = shapes |
553 | 553 |
self.nodes = nodes |
554 | 554 |
self.edges = edges |
555 |
+ self.outputorder = outputorder |
|
555 | 556 |
|
556 | 557 |
self.bounding = Shape._envelope_bounds( |
557 | 558 |
map(_get_bounding, self.shapes), |
... | ... |
@@ -561,6 +562,23 @@ class Graph(Shape): |
561 | 562 |
def get_size(self): |
562 | 563 |
return self.width, self.height |
563 | 564 |
|
565 |
+ def _draw_shapes(self, cr, bounding): |
|
566 |
+ for shape in self.shapes: |
|
567 |
+ if bounding is None or shape._intersects(bounding): |
|
568 |
+ shape._draw(cr, highlight=False, bounding=bounding) |
|
569 |
+ |
|
570 |
+ def _draw_nodes(self, cr, bounding, highlight_items): |
|
571 |
+ for node in self.nodes: |
|
572 |
+ if bounding is None or node._intersects(bounding): |
|
573 |
+ node._draw(cr, highlight=(node in highlight_items), bounding=bounding) |
|
574 |
+ |
|
575 |
+ def _draw_edges(self, cr, bounding, highlight_items): |
|
576 |
+ for edge in self.edges: |
|
577 |
+ if bounding is None or edge._intersects(bounding): |
|
578 |
+ should_highlight = any(e in highlight_items |
|
579 |
+ for e in (edge, edge.src, edge.dst)) |
|
580 |
+ edge._draw(cr, highlight=should_highlight, bounding=bounding) |
|
581 |
+ |
|
564 | 582 |
def draw(self, cr, highlight_items=None, bounding=None): |
565 | 583 |
if bounding is not None: |
566 | 584 |
if not self._intersects(bounding): |
... | ... |
@@ -575,17 +593,13 @@ class Graph(Shape): |
575 | 593 |
cr.set_line_cap(cairo.LINE_CAP_BUTT) |
576 | 594 |
cr.set_line_join(cairo.LINE_JOIN_MITER) |
577 | 595 |
|
578 |
- for shape in self.shapes: |
|
579 |
- if bounding is None or shape._intersects(bounding): |
|
580 |
- shape._draw(cr, highlight=False, bounding=bounding) |
|
581 |
- for edge in self.edges: |
|
582 |
- if bounding is None or edge._intersects(bounding): |
|
583 |
- should_highlight = any(e in highlight_items |
|
584 |
- for e in (edge, edge.src, edge.dst)) |
|
585 |
- edge._draw(cr, highlight=should_highlight, bounding=bounding) |
|
586 |
- for node in self.nodes: |
|
587 |
- if bounding is None or node._intersects(bounding): |
|
588 |
- node._draw(cr, highlight=(node in highlight_items), bounding=bounding) |
|
596 |
+ self._draw_shapes(cr, bounding) |
|
597 |
+ if self.outputorder == 'edgesfirst': |
|
598 |
+ self._draw_edges(cr, bounding, highlight_items) |
|
599 |
+ self._draw_nodes(cr, bounding, highlight_items) |
|
600 |
+ else: |
|
601 |
+ self._draw_nodes(cr, bounding, highlight_items) |
|
602 |
+ self._draw_edges(cr, bounding, highlight_items) |
|
589 | 603 |
|
590 | 604 |
def get_element(self, x, y): |
591 | 605 |
for node in self.nodes: |