1
14 package demo.view.realizer;
15
16 import y.view.AbstractMouseInputEditor;
17 import y.view.EditMode;
18 import y.view.Graph2DView;
19 import y.view.HitInfo;
20 import y.view.Mouse2DEvent;
21 import y.view.MouseInputEditor;
22 import y.view.NodeRealizer;
23 import y.view.MouseInputEditorProvider;
24
25 import javax.swing.JFrame;
26 import javax.swing.JRootPane;
27 import java.awt.Color;
28 import java.awt.Graphics2D;
29 import java.awt.geom.GeneralPath;
30 import java.awt.geom.Rectangle2D;
31
32
35 public class ScrollingNodeRealizer extends NodeRealizer implements MouseInputEditorProvider {
36
37 private double viewWidth = 300;
38 private double viewHeight = 300;
39 private ScrollBar verticalScrollBar;
40 private ScrollBar horizontalScrollBar;
41
42 public ScrollingNodeRealizer() {
43 super();
44 init();
45 }
46
47 public ScrollingNodeRealizer(NodeRealizer nr) {
48 super(nr);
49 init();
50 }
51
52 private void init() {
53 this.verticalScrollBar = new ScrollBar(true, 100, this);
54 this.horizontalScrollBar = new ScrollBar(false, 100, this);
55 boundsChanged();
56 }
57
58 protected void boundsChanged() {
59 super.boundsChanged();
60 this.horizontalScrollBar.setBounds(
61 new Rectangle2D.Double(0, getViewPortHeight(), getViewPortWidth(), getHeight() - getViewPortHeight() - 1));
62 this.verticalScrollBar.setBounds(
63 new Rectangle2D.Double(getViewPortWidth(), 0, getWidth() - getViewPortWidth() - 1, getViewPortHeight()));
64 this.horizontalScrollBar.setMaxPosition(Math.max(0, getViewWidth() - getViewPortWidth()));
65 this.horizontalScrollBar.setExtent(Math.max(10, getViewPortWidth() * getViewPortWidth() / getViewWidth()));
66 this.verticalScrollBar.setMaxPosition(Math.max(0, getViewHeight() - getViewPortHeight()));
67 this.verticalScrollBar.setExtent(Math.max(10, getViewPortHeight() * getViewPortHeight() / getViewHeight()));
68 }
69
70 public NodeRealizer createCopy(NodeRealizer nr) {
71 return new ScrollingNodeRealizer(nr);
72 }
73
74 public Rectangle2D getViewPortBounds() {
75 return new Rectangle2D.Double(0, 0, getViewPortWidth(), getViewPortHeight());
76 }
77
78 public double getViewPortWidth() {
79 return getWidth() - 10;
80 }
81
82 public double getViewPortHeight() {
83 return getHeight() - 10;
84 }
85
86 public double getViewWidth() {
87 return viewWidth;
88 }
89
90 public double getViewHeight() {
91 return viewHeight;
92 }
93
94 protected void paintNode(Graphics2D g) {
95 Rectangle2D.Double rect = new Rectangle2D.Double(x, y, width, height);
96 g.setColor(getFillColor());
97 g.fill(rect);
98 if (isSelected()) {
99 paintHotSpots(g);
100 }
101 g = (Graphics2D) g.create();
102 g.translate(x, y);
103 horizontalScrollBar.paint(g);
104 verticalScrollBar.paint(g);
105 rect.setFrame(getViewPortBounds());
106 g.clip(rect);
107 g.translate(rect.x - horizontalScrollBar.getPosition(), rect.y - verticalScrollBar.getPosition());
108 g.setColor(Color.black);
109 renderContent(g);
110 g.dispose();
111 }
112
113 private void renderContent(Graphics2D g) {
114 g.setColor(getLineColor());
115 for (int i = 0; i < 10; i ++) {
116 g.drawString("Test" + i, i, 10 * i);
117 }
118 }
119
120
131 public MouseInputEditorProvider getMouseInputEditorProvider() {
132 return this;
133 }
134
135 public MouseInputEditor findMouseInputEditor(Graph2DView view, double x, double y, HitInfo hitInfo) {
136 x -= getX();
137 y -= getY();
138 MouseInputEditor editor = verticalScrollBar.findEditor(x, y);
139 if (editor != null) {
140 return editor;
141 }
142 editor = horizontalScrollBar.findEditor(x, y);
143 return editor;
144 }
145
146 static final class ScrollBar {
147 private double x;
148 private double y;
149 private double w;
150 private double h;
151 private double position;
152 private double extent;
153 private double maxPosition;
154 private boolean vertical;
155 private NodeRealizer context;
156 private ScrollBarInputEditor currentEditor;
157
158 public ScrollBar(boolean vertical, double maxPosition, NodeRealizer context) {
159 this.maxPosition = maxPosition;
160 this.vertical = vertical;
161 this.context = context;
162 }
163
164 public Rectangle2D getBounds(Rectangle2D rect) {
165 rect.setFrame(x, y, w, h);
166 return rect;
167 }
168
169 public boolean contains(double x, double y) {
170 return x >= this.x && y >= this.y && x < this.x + this.w && y < this.y + this.h;
171 }
172
173 public double getExtent() {
174 return extent;
175 }
176
177 public void setExtent(double extent) {
178 this.extent = extent;
179 }
180
181 public void setBounds(Rectangle2D bounds) {
182 this.x = bounds.getX();
183 this.y = bounds.getY();
184 this.w = bounds.getWidth();
185 this.h = bounds.getHeight();
186 }
187
188 public double getPosition() {
189 return position;
190 }
191
192 public void setPosition(double position) {
193 double oldPosition = this.position;
194 this.position = Math.max(0, Math.min(position, maxPosition));
195 if (oldPosition != this.position) {
196 repaint();
197 }
198 }
199
200 public void setMaxPosition(double maxPosition) {
201 if (this.maxPosition != maxPosition) {
202 this.maxPosition = maxPosition;
203 this.position = Math.min(this.position, maxPosition);
204 repaint();
205 }
206 }
207
208 public double getMaxPosition() {
209 return maxPosition;
210 }
211
212 public void repaint() {
213 context.repaint();
214 }
215
216 public void paint(Graphics2D g) {
217 if (maxPosition == 0) {
218 return;
219 }
220 Rectangle2D.Double bounds = new Rectangle2D.Double();
221 getBounds(bounds);
222 g = (Graphics2D) g.create();
223 g.setColor(isHighlighted() ? context.getFillColor().brighter() : context.getFillColor());
224 g.fill(bounds);
225 g.setColor(context.getLineColor());
226 g.draw(bounds);
227 GeneralPath p = new GeneralPath(GeneralPath.WIND_EVEN_ODD, 5);
228 if (vertical) {
229 p.moveTo((float) (bounds.getCenterX()), (float) (bounds.getY() + 4));
230 p.lineTo((float) (bounds.getCenterX() + 3), (float) (bounds.getY() + 10));
231 p.lineTo((float) (bounds.getCenterX() - 3), (float) (bounds.getY() + 10));
232 p.closePath();
233 g.fill(p);
234
235 p.reset();
236 p.moveTo((float) (bounds.getCenterX()), (float) (bounds.getMaxY() - 4));
237 p.lineTo((float) (bounds.getCenterX() + 3), (float) (bounds.getMaxY() - 10));
238 p.lineTo((float) (bounds.getCenterX() - 3), (float) (bounds.getMaxY() - 10));
239 p.closePath();
240 g.fill(p);
241
242 getThumbBounds(bounds);
243 g.fill(bounds);
244
245 g.dispose();
246 } else {
247 p.moveTo((float) (bounds.getX() + 4), (float) (bounds.getCenterY()));
248 p.lineTo((float) (bounds.getX() + 10), (float) (bounds.getCenterY() + 3));
249 p.lineTo((float) (bounds.getX() + 10), (float) (bounds.getCenterY() - 3));
250 p.closePath();
251 g.fill(p);
252
253 p.reset();
254 p.moveTo((float) (bounds.getMaxX() - 4), (float) (bounds.getCenterY()));
255 p.lineTo((float) (bounds.getMaxX() - 10), (float) (bounds.getCenterY() + 3));
256 p.lineTo((float) (bounds.getMaxX() - 10), (float) (bounds.getCenterY() - 3));
257 p.closePath();
258 g.fill(p);
259 getThumbBounds(bounds);
260 g.fill(bounds);
261 g.dispose();
262 }
263 }
264
265 private void getThumbBounds(Rectangle2D bounds) {
266 getBounds(bounds);
267 if (vertical) {
268 bounds.setFrame(bounds.getX() + 1, bounds.getY() + 12, bounds.getWidth() - 2, bounds.getHeight() - 24);
269 double p = getPosition() / getMaxPosition();
270 bounds.setFrame(bounds.getX(), bounds.getY() + (bounds.getHeight() - getExtent()) * p, bounds.getWidth(),
271 getExtent());
272 } else {
273 bounds.setFrame(bounds.getX() + 12, bounds.getY() + 1, bounds.getWidth() - 24, bounds.getHeight() - 2);
274 double p = getPosition() / getMaxPosition();
275 bounds.setFrame(bounds.getX() + (bounds.getWidth() - getExtent()) * p, bounds.getY(), getExtent(),
276 bounds.getHeight());
277 }
278 }
279
280 private boolean isHighlighted() {
281 return currentEditor != null && currentEditor.isHighlighted();
282 }
283
284 public MouseInputEditor findEditor(double x, double y) {
285 if (maxPosition == 0) {
286 return null;
287 }
288 Rectangle2D.Double bounds = new Rectangle2D.Double();
289 getBounds(bounds);
290
291 if (contains(x, y)) {
292 this.currentEditor = new ScrollBarInputEditor();
293 return currentEditor;
294 }
295 return null;
296 }
297
298 class ScrollBarInputEditor extends AbstractMouseInputEditor {
299
300 private boolean down;
301 private double initialX;
302 private double initialY;
303 private double initialPos;
304 private boolean highlighted;
305
306 public boolean startsEditing(Mouse2DEvent event) {
307 double x = event.getX() - context.getX();
308 double y = event.getY() - context.getY();
309 if (contains(x, y)) {
310 highlighted = true;
311 repaint();
312 return true;
313 }
314 return false;
315 }
316
317 public void mouse2DEventHappened(Mouse2DEvent event) {
318 if (context != null) {
319 if (event.getId() == Mouse2DEvent.MOUSE_MOVED ||
320 event.getId() == Mouse2DEvent.MOUSE_RELEASED) {
321 double x = event.getX() - context.getX();
322 double y = event.getY() - context.getY();
323 if (!contains(x, y)) {
324 highlighted = false;
325 ScrollBar.this.currentEditor = null;
326 repaint();
327 stopEditing();
328 }
329 } else {
330 double x = event.getX() - context.getX();
331 double y = event.getY() - context.getY();
332 switch (event.getId()) {
333 case Mouse2DEvent.MOUSE_CLICKED:
334 if (vertical) {
335 setPosition(getPosition() + (y > (ScrollBar.this.y + ScrollBar.this.h * 0.5d) ? 10 : -10));
336 } else {
337 setPosition(getPosition() + (x > (ScrollBar.this.x + ScrollBar.this.w * 0.5d) ? 10 : -10));
338 }
339 break;
340 case Mouse2DEvent.MOUSE_PRESSED:
341 initialX = x;
342 initialY = y;
343 initialPos = getPosition();
344 down = true;
345 break;
346 case Mouse2DEvent.MOUSE_RELEASED:
347 if (down) {
348 double dx = x - initialX;
349 double dy = y - initialY;
350 setPosition(initialPos + (vertical ? dy : dx));
351 down = false;
352 }
353 break;
354 case Mouse2DEvent.MOUSE_DRAGGED:
355 if (down) {
356 double dx = x - initialX;
357 double dy = y - initialY;
358 setPosition(initialPos + (vertical ? dy : dx));
359 }
360 break;
361 }
362 }
363 } else {
364 ScrollBar.this.currentEditor = null;
365 stopEditing();
366 }
367 }
368
369 public boolean isHighlighted() {
370 return highlighted;
371 }
372 }
373 }
374
375
376
377 public static void addContentTo( final JRootPane rootPane )
378 {
379 final ScrollingNodeRealizer r = new ScrollingNodeRealizer();
380 r.setSize(100, 40);
381
382 final EditMode editMode = new EditMode();
383 editMode.getMouseInputMode().setNodeSearchingEnabled(true);
384 editMode.allowMouseInput(true);
385
386 final Graph2DView view = new Graph2DView();
387 view.getGraph2D().setDefaultNodeRealizer(r.createCopy());
388 view.setAntialiasedPainting(true);
389 view.getGraph2D().createNode();
390 view.addViewMode(editMode);
391 view.fitContent();
392
393 rootPane.setContentPane(view);
394 }
395
396
400 public static void main(String[] args)
401 {
402 final JFrame frame = new JFrame();
403 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
404 addContentTo(frame.getRootPane());
405 frame.pack();
406 frame.setLocationRelativeTo(null);
407 frame.setVisible(true);
408 }
409 }
410