32 def translate_vertex(v: Layout.Vertex, dx: Double, dy: Double): Unit = |
32 def translate_vertex(v: Layout.Vertex, dx: Double, dy: Double): Unit = |
33 _layout = _layout.translate_vertex(v, dx, dy) |
33 _layout = _layout.translate_vertex(v, dx, dy) |
34 |
34 |
35 def find_node(at: Point2D): Option[Graph_Display.Node] = |
35 def find_node(at: Point2D): Option[Graph_Display.Node] = |
36 layout.output_graph.iterator.collectFirst({ |
36 layout.output_graph.iterator.collectFirst({ |
37 case (Layout.Node(node), _) if Shapes.Node.shape(visualizer, node).contains(at) => node |
37 case (Layout.Node(node), (info, _)) if Shapes.shape(info).contains(at) => node |
38 }) |
38 }) |
39 |
39 |
40 def find_dummy(at: Point2D): Option[Layout.Dummy] = |
40 def find_dummy(at: Point2D): Option[Layout.Dummy] = |
41 layout.output_graph.iterator.collectFirst({ |
41 layout.output_graph.iterator.collectFirst({ |
42 case (dummy: Layout.Dummy, (d, _)) if Shapes.Dummy.shape(visualizer, d).contains(at) => dummy |
42 case (dummy: Layout.Dummy, (info, _)) if Shapes.shape(info).contains(at) => dummy |
43 }) |
43 }) |
44 |
44 |
45 def bounding_box(): Rectangle2D.Double = |
45 def bounding_box(): Rectangle2D.Double = |
46 { |
46 { |
47 var x0 = 0.0 |
47 var x0 = 0.0 |
48 var y0 = 0.0 |
48 var y0 = 0.0 |
49 var x1 = 0.0 |
49 var x1 = 0.0 |
50 var y1 = 0.0 |
50 var y1 = 0.0 |
51 ((for (node <- visible_graph.keys_iterator) yield Shapes.Node.shape(visualizer, node)) ++ |
51 for ((_, (info, _)) <- layout.output_graph.iterator) { |
52 (for (d <- layout.dummies_iterator) yield Shapes.Dummy.shape(visualizer, d))). |
52 val rect = Shapes.shape(info) |
53 foreach(rect => { |
53 x0 = x0 min rect.getMinX |
54 x0 = x0 min rect.getMinX |
54 y0 = y0 min rect.getMinY |
55 y0 = y0 min rect.getMinY |
55 x1 = x1 max rect.getMaxX |
56 x1 = x1 max rect.getMaxX |
56 y1 = y1 max rect.getMaxY |
57 y1 = y1 max rect.getMaxY |
57 } |
58 }) |
58 x0 = (x0 - metrics.gap).floor |
59 val gap = metrics.gap |
59 y0 = (y0 - metrics.gap).floor |
60 x0 = (x0 - gap).floor |
60 x1 = (x1 + metrics.gap).ceil |
61 y0 = (y0 - gap).floor |
61 y1 = (y1 + metrics.gap).ceil |
62 x1 = (x1 + gap).ceil |
|
63 y1 = (y1 + gap).ceil |
|
64 new Rectangle2D.Double(x0, y0, x1 - x0, y1 - y0) |
62 new Rectangle2D.Double(x0, y0, x1 - x0, y1 - y0) |
65 } |
63 } |
66 |
64 |
67 def update_layout() |
65 def update_layout() |
68 { |
66 { |
69 val metrics = Metrics(make_font()) |
67 val metrics = Metrics(make_font()) |
70 val visible_graph = model.make_visible_graph() |
68 val visible_graph = model.make_visible_graph() |
71 |
69 |
|
70 def node_text(node: Graph_Display.Node, content: XML.Body): String = |
|
71 if (show_content) { |
|
72 val s = |
|
73 XML.content(Pretty.formatted( |
|
74 content, options.int("graphview_content_margin").toDouble, metrics.Pretty_Metric)) |
|
75 if (s.nonEmpty) s else node.toString |
|
76 } |
|
77 else node.toString |
|
78 |
72 // FIXME avoid expensive operation on GUI thread |
79 // FIXME avoid expensive operation on GUI thread |
73 _layout = Layout.make(options, metrics, visible_graph) |
80 _layout = Layout.make(options, metrics, node_text _, visible_graph) |
74 } |
81 } |
75 |
82 |
76 |
83 |
77 /* tooltips */ |
84 /* tooltips */ |
78 |
85 |
128 { |
136 { |
129 gfx.setRenderingHints(Metrics.rendering_hints) |
137 gfx.setRenderingHints(Metrics.rendering_hints) |
130 for (edge <- visible_graph.edges_iterator) |
138 for (edge <- visible_graph.edges_iterator) |
131 Shapes.Cardinal_Spline_Edge.paint(gfx, visualizer, edge) |
139 Shapes.Cardinal_Spline_Edge.paint(gfx, visualizer, edge) |
132 for (node <- visible_graph.keys_iterator) |
140 for (node <- visible_graph.keys_iterator) |
133 Shapes.Node.paint(gfx, visualizer, node) |
141 Shapes.paint_node(gfx, visualizer, node) |
134 } |
142 } |
135 |
143 |
136 object Selection |
144 object Selection |
137 { |
145 { |
138 // owned by GUI thread |
146 // owned by GUI thread |