18 |
18 |
19 import scala.swing.{BorderPanel, Button, CheckBox, Action, FileChooser, Panel, ScrollPane} |
19 import scala.swing.{BorderPanel, Button, CheckBox, Action, FileChooser, Panel, ScrollPane} |
20 import scala.swing.event.{Event, Key, MousePressed, MouseDragged, MouseClicked, MouseEvent} |
20 import scala.swing.event.{Event, Key, MousePressed, MouseDragged, MouseClicked, MouseEvent} |
21 |
21 |
22 |
22 |
23 class Graph_Panel(val graphview: Graphview) extends BorderPanel |
23 class Graph_Panel(val graphview: Graphview) extends BorderPanel { |
24 { |
|
25 graph_panel => |
24 graph_panel => |
26 |
25 |
27 |
26 |
28 |
27 |
29 /** graph **/ |
28 /** graph **/ |
30 |
29 |
31 /* painter */ |
30 /* painter */ |
32 |
31 |
33 private val painter = new Panel |
32 private val painter = new Panel { |
34 { |
33 override def paint(gfx: Graphics2D): Unit = { |
35 override def paint(gfx: Graphics2D): Unit = |
|
36 { |
|
37 super.paintComponent(gfx) |
34 super.paintComponent(gfx) |
38 |
35 |
39 gfx.setColor(graphview.background_color) |
36 gfx.setColor(graphview.background_color) |
40 gfx.fillRect(0, 0, peer.getWidth, peer.getHeight) |
37 gfx.fillRect(0, 0, peer.getWidth, peer.getHeight) |
41 |
38 |
42 gfx.transform(Transform()) |
39 gfx.transform(Transform()) |
43 graphview.paint(gfx) |
40 graphview.paint(gfx) |
44 } |
41 } |
45 } |
42 } |
46 |
43 |
47 def set_preferred_size(): Unit = |
44 def set_preferred_size(): Unit = { |
48 { |
|
49 val box = graphview.bounding_box() |
45 val box = graphview.bounding_box() |
50 val s = Transform.scale_discrete |
46 val s = Transform.scale_discrete |
51 painter.preferredSize = new Dimension((box.width * s).ceil.toInt, (box.height * s).ceil.toInt) |
47 painter.preferredSize = new Dimension((box.width * s).ceil.toInt, (box.height * s).ceil.toInt) |
52 painter.revalidate() |
48 painter.revalidate() |
53 } |
49 } |
54 |
50 |
55 def refresh(): Unit = |
51 def refresh(): Unit = { |
56 { |
|
57 if (painter != null) { |
52 if (painter != null) { |
58 set_preferred_size() |
53 set_preferred_size() |
59 painter.repaint() |
54 painter.repaint() |
60 } |
55 } |
61 } |
56 } |
62 |
57 |
63 def scroll_to_node(node: Graph_Display.Node): Unit = |
58 def scroll_to_node(node: Graph_Display.Node): Unit = { |
64 { |
|
65 val gap = graphview.metrics.gap |
59 val gap = graphview.metrics.gap |
66 val info = graphview.layout.get_node(node) |
60 val info = graphview.layout.get_node(node) |
67 |
61 |
68 val t = Transform() |
62 val t = Transform() |
69 val p = |
63 val p = |
99 verticalScrollBarPolicy = ScrollPane.BarPolicy.Always |
93 verticalScrollBarPolicy = ScrollPane.BarPolicy.Always |
100 |
94 |
101 listenTo(mouse.moves) |
95 listenTo(mouse.moves) |
102 listenTo(mouse.clicks) |
96 listenTo(mouse.clicks) |
103 reactions += |
97 reactions += |
104 { |
98 { |
105 case MousePressed(_, p, _, _, _) => |
99 case MousePressed(_, p, _, _, _) => |
106 Mouse_Interaction.pressed(p) |
100 Mouse_Interaction.pressed(p) |
107 painter.repaint() |
101 painter.repaint() |
108 case MouseDragged(_, to, _) => |
102 case MouseDragged(_, to, _) => |
109 Mouse_Interaction.dragged(to) |
103 Mouse_Interaction.dragged(to) |
110 painter.repaint() |
104 painter.repaint() |
111 case e @ MouseClicked(_, p, m, n, _) => |
105 case e @ MouseClicked(_, p, m, n, _) => |
112 Mouse_Interaction.clicked(p, m, n, SwingUtilities.isRightMouseButton(e.peer)) |
106 Mouse_Interaction.clicked(p, m, n, SwingUtilities.isRightMouseButton(e.peer)) |
113 painter.repaint() |
107 painter.repaint() |
114 } |
108 } |
115 |
109 |
116 contents = painter |
110 contents = painter |
117 } |
111 } |
118 graph_pane.peer.getVerticalScrollBar.setUnitIncrement(10) |
112 graph_pane.peer.getVerticalScrollBar.setUnitIncrement(10) |
119 |
113 |
120 |
114 |
121 /* transform */ |
115 /* transform */ |
122 |
116 |
123 def rescale(s: Double): Unit = |
117 def rescale(s: Double): Unit = { |
124 { |
|
125 Transform.scale = s |
118 Transform.scale = s |
126 if (zoom != null) zoom.set_item((Transform.scale_discrete * 100).floor.toInt) |
119 if (zoom != null) zoom.set_item((Transform.scale_discrete * 100).floor.toInt) |
127 refresh() |
120 refresh() |
128 } |
121 } |
129 |
122 |
130 def fit_to_window(): Unit = |
123 def fit_to_window(): Unit = { |
131 { |
|
132 Transform.fit_to_window() |
124 Transform.fit_to_window() |
133 refresh() |
125 refresh() |
134 } |
126 } |
135 |
127 |
136 private object Transform |
128 private object Transform { |
137 { |
|
138 private var _scale: Double = 1.0 |
129 private var _scale: Double = 1.0 |
139 def scale: Double = _scale |
130 def scale: Double = _scale |
140 def scale_=(s: Double): Unit = |
131 def scale_=(s: Double): Unit = { |
141 { |
|
142 _scale = (s min 10.0) max 0.1 |
132 _scale = (s min 10.0) max 0.1 |
143 } |
133 } |
144 |
134 |
145 def scale_discrete: Double = |
135 def scale_discrete: Double = { |
146 { |
|
147 val font_height = GUI.line_metrics(graphview.metrics.font).getHeight.toInt |
136 val font_height = GUI.line_metrics(graphview.metrics.font).getHeight.toInt |
148 (scale * font_height).floor / font_height |
137 (scale * font_height).floor / font_height |
149 } |
138 } |
150 |
139 |
151 def apply(): AffineTransform = |
140 def apply(): AffineTransform = { |
152 { |
|
153 val box = graphview.bounding_box() |
141 val box = graphview.bounding_box() |
154 val t = AffineTransform.getScaleInstance(scale_discrete, scale_discrete) |
142 val t = AffineTransform.getScaleInstance(scale_discrete, scale_discrete) |
155 t.translate(- box.x, - box.y) |
143 t.translate(- box.x, - box.y) |
156 t |
144 t |
157 } |
145 } |
158 |
146 |
159 def fit_to_window(): Unit = |
147 def fit_to_window(): Unit = { |
160 { |
|
161 if (graphview.visible_graph.is_empty) |
148 if (graphview.visible_graph.is_empty) |
162 rescale(1.0) |
149 rescale(1.0) |
163 else { |
150 else { |
164 val box = graphview.bounding_box() |
151 val box = graphview.bounding_box() |
165 rescale((size.width / box.width) min (size.height / box.height)) |
152 rescale((size.width / box.width) min (size.height / box.height)) |
166 } |
153 } |
167 } |
154 } |
168 |
155 |
169 def pane_to_graph_coordinates(at: Point2D): Point2D = |
156 def pane_to_graph_coordinates(at: Point2D): Point2D = { |
170 { |
|
171 val s = Transform.scale_discrete |
157 val s = Transform.scale_discrete |
172 val p = Transform().inverseTransform(graph_pane.peer.getViewport.getViewPosition, null) |
158 val p = Transform().inverseTransform(graph_pane.peer.getViewport.getViewPosition, null) |
173 |
159 |
174 p.setLocation(p.getX + at.getX / s, p.getY + at.getY / s) |
160 p.setLocation(p.getX + at.getX / s, p.getY + at.getY / s) |
175 p |
161 p |
180 /* interaction */ |
166 /* interaction */ |
181 |
167 |
182 graphview.model.Colors.events += { case _ => painter.repaint() } |
168 graphview.model.Colors.events += { case _ => painter.repaint() } |
183 graphview.model.Mutators.events += { case _ => painter.repaint() } |
169 graphview.model.Mutators.events += { case _ => painter.repaint() } |
184 |
170 |
185 private object Mouse_Interaction |
171 private object Mouse_Interaction { |
186 { |
|
187 private var draginfo: (Point, List[Graph_Display.Node], List[Layout.Dummy]) = |
172 private var draginfo: (Point, List[Graph_Display.Node], List[Layout.Dummy]) = |
188 (new Point(0, 0), Nil, Nil) |
173 (new Point(0, 0), Nil, Nil) |
189 |
174 |
190 def pressed(at: Point): Unit = |
175 def pressed(at: Point): Unit = { |
191 { |
|
192 val c = Transform.pane_to_graph_coordinates(at) |
176 val c = Transform.pane_to_graph_coordinates(at) |
193 val l = |
177 val l = |
194 graphview.find_node(c) match { |
178 graphview.find_node(c) match { |
195 case Some(node) => |
179 case Some(node) => |
196 if (graphview.Selection.contains(node)) graphview.Selection.get() |
180 if (graphview.Selection.contains(node)) graphview.Selection.get() |