1
28 package demo.view.mindmap;
29
30 import y.base.GraphEvent;
31 import y.base.GraphListener;
32 import y.base.Node;
33 import y.base.NodeCursor;
34 import y.base.NodeList;
35 import y.view.AbstractMouseInputEditor;
36 import y.view.Drawable;
37 import y.view.Graph2D;
38 import y.view.Graph2DView;
39 import y.view.HitInfo;
40 import y.view.Mouse2DEvent;
41 import y.view.MouseInputEditor;
42 import y.view.MouseInputEditorProvider;
43 import y.view.NodeRealizer;
44
45 import java.awt.Color;
46 import java.awt.Graphics2D;
47 import java.awt.Rectangle;
48 import java.awt.geom.GeneralPath;
49 import java.util.WeakHashMap;
50
51
54 class CollapseButton extends AbstractMouseInputEditor implements Drawable, MouseInputEditorProvider, MouseInputEditor {
55
58 private final Node node;
59
62 private final Graph2D graph;
63
64
67 CollapseButton( final Node node, Graph2D graph ) {
68 this.graph = graph;
69 this.node = node;
70 }
71
72
76 public Rectangle getBounds() {
77 Rectangle r = new Rectangle(-1,-1);
78 if (isVisible()) {
79 r = new Rectangle(16, 16);
80 final NodeRealizer realizer = graph.getRealizer(node);
81 if (ViewModel.instance.isRoot(node)) {
83 r.x = (int) realizer.getCenterX() - 8;
84 r.y = (int) (realizer.getY() + realizer.getHeight());
85 } else {
87 if (ViewModel.instance.isLeft(node)) {
88 r.x = (int) (realizer.getX() - 13);
89 } else {
90 r.x = (int) (realizer.getX() + realizer.getWidth());
91 }
92 r.y = (int) (realizer.getY() + realizer.getHeight()/2+3);
93 }
94 }
95 return r;
96 }
97
98
102 public void paint(Graphics2D g) {
103 final double x = this.getBounds().x;
104 final double y = this.getBounds().y;
105 if (isVisible()) {
106 g = (Graphics2D) g.create();
108 g.translate(x,y);
109 GeneralPath gp = new GeneralPath();
110 if (!ViewModel.instance.isCollapsed(node) == ViewModel.instance.isLeft(node)) {
112 gp.moveTo(4, 6);
113 gp.lineTo(4, 10);
114 gp.lineTo(8, 10);
115 gp.lineTo(8, 12);
116 gp.lineTo(13, 8);
117 gp.lineTo(8, 4);
118 gp.lineTo(8, 6);
119 } else {
121 gp.moveTo(12, 6);
122 gp.lineTo(12, 10);
123 gp.lineTo(8, 10);
124 gp.lineTo(8, 12);
125 gp.lineTo(3, 8);
126 gp.lineTo(8, 4);
127 gp.lineTo(8, 6);
128 }
129 final Color circleBlue = new Color(6, 164, 255);
130 g.setColor(circleBlue);
131 g.fillOval(0, 0, 16, 16);
132 g.setColor(Color.WHITE);
133 g.fill(gp);
134 g.dispose();
135 }
136 }
137
138
143 private boolean isVisible() {
144 return graph.contains(node) &&
145 (ViewModel.instance.isCollapsed(node) ||
146 !MindMapUtil.outEdges(node).isEmpty());
147 }
148
149
153 private void handleClick() {
154 if (isVisible()) {
155 MindMapUtil.toggleCollapseState(graph, node);
156 graph.updateViews();
157 }
158 }
159
160
166 public boolean startsEditing(final Mouse2DEvent event) {
167 return getBounds().contains(event.getX(), event.getY());
168 }
169
170
175 public void mouse2DEventHappened(final Mouse2DEvent event) {
176 if (getBounds().contains(event.getX(), event.getY())) {
177 if (event.getId() == Mouse2DEvent.MOUSE_CLICKED) {
178 handleClick();
179 stopEditing();
180 }
181 } else {
182 stopEditing();
183 }
184 }
185
186
195 public MouseInputEditor findMouseInputEditor(Graph2DView view, double x, double y, HitInfo hitInfo) {
196 return getBounds().contains(x, y) ? this : null;
197 }
198
199
200
204 static class Handler implements GraphListener {
205 private final Graph2DView view;
206 private final WeakHashMap node2button;
207
208
212 Handler( final Graph2DView view ) {
213 this.view = view;
214 this.node2button = new WeakHashMap();
215
216 view.getGraph2D().addGraphListener(this);
217 }
218
219
223 public void onGraphEvent( final GraphEvent e ) {
224 switch (e.getType()) {
225 case GraphEvent.NODE_CREATION:
226 case GraphEvent.NODE_REINSERTION:
227 onNodeCreated((Node) e.getData());
228 break;
229 case GraphEvent.PRE_NODE_REMOVAL:
230 onNodeDeleted((Node) e.getData());
231 break;
232 case GraphEvent.SUBGRAPH_INSERTION:
233 for (NodeCursor nc = ((NodeList) e.getData()).nodes(); nc.ok(); nc.next()) {
234 onNodeCreated(nc.node());
235 }
236 break;
237 case GraphEvent.SUBGRAPH_REMOVAL:
238 for (NodeCursor nc = ((NodeList) e.getData()).nodes(); nc.ok(); nc.next()) {
239 onNodeDeleted(nc.node());
240 }
241 break;
242 }
243 }
244
245
249 private void onNodeCreated( final Node node ) {
250 final CollapseButton button = new CollapseButton(node, view.getGraph2D());
251 node2button.put(node, button);
252 view.addDrawable(button);
253 }
254
255
259 private void onNodeDeleted( final Node node ) {
260 final Object button = node2button.get(node);
261 if (button instanceof CollapseButton) {
262 view.removeDrawable(((CollapseButton) button));
263 }
264 }
265 }
266 }
267