1
14 package demo.yext.svg;
15
16 import yext.svg.view.SVGNodeRealizer;
17
18 import y.base.Edge;
19 import y.base.Node;
20 import y.base.NodeCursor;
21 import y.geom.YRectangle;
22 import y.layout.EdgeLabelModel;
23 import y.util.D;
24 import y.view.EdgeLabel;
25 import y.view.EdgeRealizer;
26 import y.view.Graph2D;
27 import y.view.Graph2DView;
28 import y.view.NodeRealizer;
29
30 import java.awt.BorderLayout;
31 import java.awt.Component;
32 import java.awt.Dimension;
33 import java.awt.EventQueue;
34 import java.awt.Graphics;
35 import java.awt.Graphics2D;
36 import java.awt.Point;
37 import java.awt.RenderingHints;
38 import java.awt.datatransfer.DataFlavor;
39 import java.awt.datatransfer.StringSelection;
40 import java.awt.datatransfer.Transferable;
41 import java.awt.datatransfer.UnsupportedFlavorException;
42 import java.awt.dnd.DnDConstants;
43 import java.awt.dnd.DragGestureEvent;
44 import java.awt.dnd.DragGestureListener;
45 import java.awt.dnd.DragSource;
46 import java.awt.dnd.DropTarget;
47 import java.awt.dnd.DropTargetDragEvent;
48 import java.awt.dnd.DropTargetDropEvent;
49 import java.awt.dnd.DropTargetEvent;
50 import java.awt.dnd.DropTargetListener;
51 import java.io.IOException;
52 import java.net.URL;
53 import java.util.Collection;
54 import java.util.HashMap;
55 import java.util.Map;
56 import javax.swing.DefaultListCellRenderer;
57 import javax.swing.Icon;
58 import javax.swing.JLabel;
59 import javax.swing.JList;
60 import javax.swing.JOptionPane;
61 import javax.swing.JScrollPane;
62 import javax.swing.JSplitPane;
63 import javax.swing.ListCellRenderer;
64 import javax.swing.ListSelectionModel;
65 import javax.swing.event.ListSelectionEvent;
66 import javax.swing.event.ListSelectionListener;
67
68
69
73 public class SVGNodeRealizerDemo extends SVGExportDemo {
74
79 public SVGNodeRealizerDemo() {
80 createGraph();
82
83 view.fitContent();
85 view.updateView();
86
87 createContent();
89 }
90
91
94 private void createContent() {
95 final String[] tmp = {
96 "camera.svg",
97 "cdrom.svg",
98 "computer.svg",
99 "floppy.svg",
100 "harddisk.svg",
101 "ipod.svg",
102 "network.svg",
103 "printer.svg",
104 "scanner.svg",
105 "zipdisk.svg"
106 };
107 double maxW = 90.0;
108 final Map stringToRealizerMap = new HashMap();
109 final Map inverse = new HashMap();
110 for (int i = 0; i < tmp.length; ++i) {
111 final SVGNodeRealizer snr = createSvgRealizer(tmp[i]);
112 if (maxW < snr.getWidth()) {
113 maxW = snr.getWidth();
114 }
115 final URL url = snr.getSVGURL();
116 if (url != null) {
117 final String s = url.toString();
118 stringToRealizerMap.put(s, snr);
119 inverse.put(snr, s);
120 }
121 }
122
123 if (inverse.isEmpty()) {
124 JOptionPane.showMessageDialog(
125 this,
126 "Could not find SVG resources.",
127 "Warning",
128 JOptionPane.WARNING_MESSAGE);
129 System.err.println("Could not find SVG resources.");
130 return;
131 }
132
133 final DragAndDropSupport templates =
134 new DragAndDropSupport(inverse.keySet(), view) {
135 protected String getTextValue( final NodeRealizer selected ) {
136 return (String) inverse.get(selected);
137 }
138
139 protected NodeRealizer createNodeRealizerFromTextValue( final String s ) {
140 return (NodeRealizer) stringToRealizerMap.get(s);
141 }
142 };
143
144 int prefW = (int) (1.5 * maxW);
145 prefW += 10 - (prefW % 10);
146 final JScrollPane templatesScroll = new JScrollPane(templates.getList());
147 templatesScroll.setPreferredSize(
148 new Dimension(prefW, view.getPreferredSize().height));
149 remove(view);
150 add(new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, templatesScroll, view),
151 BorderLayout.CENTER);
152 }
153
154
157 private void createGraph() {
158 final Graph2D graph = view.getGraph2D();
159 final Node computer = graph.createNode(createSvgRealizer("computer.svg"));
160 final Node cdrom = graph.createNode(createSvgRealizer("cdrom.svg"));
161 final Node hd = graph.createNode(createSvgRealizer("harddisk.svg"));
162 final Node printer = graph.createNode(createSvgRealizer("printer.svg"));
163 final Node scanner = graph.createNode(createSvgRealizer("scanner.svg"));
164 final Node ipod = graph.createNode(createSvgRealizer("ipod.svg"));
165
166 final Edge hasCdrom = graph.createEdge(computer, cdrom);
168 final Edge hasHd = graph.createEdge(computer, hd);
169 final Edge hasPrinter = graph.createEdge(computer, printer);
170 final Edge hasScanner = graph.createEdge(computer, scanner);
171 graph.createEdge(computer, ipod);
172
173 double maxW = 0;
175 double maxH = 0;
176
177 NodeRealizer nr;
178 for (NodeCursor nc = graph.nodes(); nc.ok(); nc.next()) {
179 nr = graph.getRealizer(nc.node());
180 if (maxW < nr.getWidth()) {
181 maxW = nr.getWidth();
182 }
183 if (maxH < nr.getHeight()) {
184 maxH = nr.getHeight();
185 }
186 }
187
188 nr = graph.getRealizer(computer);
189 nr.setCenter(0.0, 0.0);
190
191 nr = graph.getRealizer(cdrom);
192 nr.setCenter(maxW, 3 * maxH);
193 nr = graph.getRealizer(hd);
194 nr.setCenter(-maxW, 3 * maxH);
195
196 nr = graph.getRealizer(printer);
197 nr.setCenter(3 * maxW, maxH);
198 nr = graph.getRealizer(scanner);
199 nr.setCenter(3 * maxW, -maxH);
200
201 nr = graph.getRealizer(ipod);
202 nr.setCenter(-3 * maxW, 0.0);
203
204 EdgeRealizer er;
205 er = graph.getRealizer(hasCdrom);
206 er.appendBend(0.0, 2 * maxH);
207 er.appendBend(maxW, 2 * maxH);
208
209 er = graph.getRealizer(hasHd);
210 er.appendBend(0.0, 2 * maxH);
211 er.appendBend(-maxW, 2 * maxH);
212 er.setLabelText("Storage Devices");
213 double[] size;
214 size = getLabelSize(er);
215 setLabelPosition(er, -size[0] * 0.5, 2 * maxH + 5);
216
217 er = graph.getRealizer(hasPrinter);
218 er.appendBend(2 * maxW, 0.0);
219 er.appendBend(2 * maxW, maxH);
220
221 er = graph.getRealizer(hasScanner);
222 er.appendBend(2 * maxW, 0.0);
223 er.appendBend(2 * maxW, -maxH);
224 er.setLabelText("Periphery");
225 size = getLabelSize(er);
226 setLabelPosition(er, 2 * maxW - size[0] - 5, -size[1] - 5);
227 }
228
229
234 private static double[] getLabelSize( final EdgeRealizer er ) {
235 final EdgeLabel label = er.getLabel();
236 final YRectangle bounds = label.getBox();
237 final double w = bounds.getWidth();
238 final double h = bounds.getHeight();
239 return new double[]{w, h};
240 }
241
242
246 private static void setLabelPosition(
247 final EdgeRealizer er, final double x, final double y
248 ) {
249 final Edge edge = er.getEdge();
250 final Graph2D graph = (Graph2D) edge.getGraph();
251 final EdgeLabel label = er.getLabel();
252
253 final YRectangle oldBounds = label.getBox();
254 final YRectangle newBounds =
255 new YRectangle(x, y, oldBounds.getWidth(), oldBounds.getHeight());
256
257 label.setModel(EdgeLabel.FREE);
258 final EdgeLabelModel model = label.getLabelModel();
259 final Object param =
260 model.createModelParameter(newBounds, er,
261 graph.getRealizer(edge.source()),
262 graph.getRealizer(edge.target()));
263 label.setModelParameter(param);
264 }
265
266
270 private static SVGNodeRealizer createSvgRealizer( final String icon ) {
271 URL url = null;
272 try {
273 url = SVGNodeRealizerDemo.class.getResource("resource/svg/" + icon);
274 } catch (Exception ex) {
275 System.err.println("Can't find SVG resource resource/svg/" + icon);
276 ex.printStackTrace(System.err);
277 url = null;
278 }
279
280 if (url != null) {
281 return new SVGNodeRealizer(url);
282 } else {
283 final SVGNodeRealizer nr = new SVGNodeRealizer();
284 nr.setLabelText(icon);
285 return nr;
286 }
287 }
288
289
290
294 public static void main( final String[] args ) {
295 EventQueue.invokeLater(new Runnable() {
296 public void run() {
297 initLnF();
298 (new SVGNodeRealizerDemo()).start();
299 }
300 });
301 }
302
303
304
309
310
314 public abstract static class DragAndDropSupport {
315 private final JList realizerList;
316
317 public DragAndDropSupport( Collection nodeRealizerList, final Graph2DView view ) {
318 this(nodeRealizerList.toArray(), view);
319 }
320
321 public DragAndDropSupport( Object[] nodeRealizers, final Graph2DView view ) {
322 realizerList = new JList(nodeRealizers);
324 realizerList.setCellRenderer(new NodeRealizerCellRenderer());
325
326 realizerList.addListSelectionListener(new ListSelectionListener() {
328 public void valueChanged( ListSelectionEvent e ) {
329 if (realizerList.getSelectedValue() instanceof NodeRealizer) {
330 nodeRealizerSelected(view);
331 }
332 }
333 });
334
335 realizerList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
336 realizerList.setSelectedIndex(0);
337
338 final DragSource dragSource = new DragSource();
341 dragSource.createDefaultDragGestureRecognizer(realizerList, DnDConstants.ACTION_MOVE,
342 new DragGestureListener() {
343 public void dragGestureRecognized( DragGestureEvent event ) {
344 Object selected = realizerList.getSelectedValue();
345 final String textValue = getTextValue((NodeRealizer) selected);
346 if (textValue != null) {
347 StringSelection text = new StringSelection(textValue);
348 dragSource.startDrag(event, DragSource.DefaultMoveDrop, text, null);
350 }
351 }
352 });
353
354 DropTarget dropTarget = new DropTarget(view.getCanvasComponent(),
357 new DropTargetListener() {
358
359 public void dragEnter( DropTargetDragEvent event ) {
361 if (checkStringFlavor(event)) {
362 event.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE);
363 } else {
364 event.rejectDrag();
365 }
366 }
367
368 private boolean checkStringFlavor( DropTargetDragEvent event ) {
370 DataFlavor[] flavors = event.getCurrentDataFlavors();
372 for (int i = 0; i < flavors.length; i++) {
373 if (flavors[i] == DataFlavor.stringFlavor) {
374 return true;
375 }
376 }
377 return false;
378 }
379
380 public void drop( DropTargetDropEvent event ) {
382 try {
383 boolean foundStringFlavor = false;
385 DataFlavor[] flavors = event.getCurrentDataFlavors();
386 for (int i = 0; i < flavors.length; i++) {
387 if (flavors[i] == DataFlavor.stringFlavor) {
388 foundStringFlavor = true;
389 break;
390 }
391 }
392 if (foundStringFlavor) {
393 event.acceptDrop(event.getDropAction());
394 } else {
395 event.rejectDrop();
396 return;
397 }
398 } catch (RuntimeException rex) {
399 event.rejectDrop();
400 D.show(rex);
401 }
402 try {
403 Transferable transferable = event.getTransferable();
404 String s = (String) transferable.getTransferData(DataFlavor.stringFlavor);
405 Point p = event.getLocation();
406 NodeRealizer r = createNodeRealizerFromTextValue(s);
407 if (r != null) {
408 final double worldCoordX = view.toWorldCoordX(p.x);
410 final double worldCoordY = view.toWorldCoordY(p.y);
411 event.dropComplete(dropRealizer(view, r, worldCoordX, worldCoordY));
412 } else {
413 event.dropComplete(false);
415 }
416 } catch (IOException ioe) {
417 event.dropComplete(false);
419 D.show(ioe);
420 } catch (UnsupportedFlavorException ufe) {
421 event.dropComplete(false);
423 D.show(ufe);
424 } catch (RuntimeException x) {
425 event.dropComplete(false);
426 throw x;
427 }
428 }
429
430 public void dragExit( DropTargetEvent dte ) {
432 }
433
434 public void dropActionChanged( DropTargetDragEvent dtde ) {
436 dragEnter(dtde);
437 }
438
439 public void dragOver( DropTargetDragEvent dtde ) {
441 dragEnter(dtde);
442 }
443 });
444 }
445
446
453 protected abstract String getTextValue( NodeRealizer selected );
454
455
462 protected abstract NodeRealizer createNodeRealizerFromTextValue( String s );
463
464
470 protected boolean dropRealizer( Graph2DView view, NodeRealizer r, double worldCoordX, double worldCoordY ) {
471 final Graph2D graph = view.getGraph2D();
472 r = r.createCopy();
473
474 if (view.getGridMode()) {
475 double gridSize = view.getGridResolution();
476 double x = Math.floor(worldCoordX / gridSize + 0.5) * gridSize;
477 double y = Math.floor(worldCoordY / gridSize + 0.5) * gridSize;
478
479 r.setCenter(x, y);
480 } else {
481 r.setCenter(worldCoordX, worldCoordY);
482 }
483 graph.createNode(r);
484 view.updateView();
485 return true;
486 }
487
488
492 protected void nodeRealizerSelected( Graph2DView view ) {
493 view.getGraph2D().setDefaultNodeRealizer((NodeRealizer) realizerList.getSelectedValue());
494 }
495
496
499 public JList getList() {
500 return realizerList;
501 }
502 }
503
504
505
509 public static final class NodeRealizerCellRenderer
510 implements ListCellRenderer {
511
512 private DefaultListCellRenderer renderer = new DefaultListCellRenderer();
513 private NodeRealizerIcon icon = new NodeRealizerIcon();
514
515 public Component getListCellRendererComponent( JList list, Object value, int index, boolean isSelected, boolean cellHasFocus ) {
516 JLabel label = (JLabel) renderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
517 icon.setRealizer((NodeRealizer) value);
518 label.setText("");
519 label.setIcon(icon);
520 return label;
521 }
522
523
526 public static final class NodeRealizerIcon implements Icon {
527 private static final int inset = 10;
528 private NodeRealizer realizer;
529
530 public void setRealizer( NodeRealizer realizer ) {
531 this.realizer = realizer;
532 }
533
534 public int getIconWidth() {
535 return (int) (realizer.getWidth() + inset);
536 }
537
538 public int getIconHeight() {
539 return (int) (realizer.getHeight() + inset);
540 }
541
542 public void paintIcon( Component c, Graphics g, int x, int y ) {
543 realizer.setLocation(x + inset * 0.5d, y + inset * 0.5d);
544 g = g.create();
545 try {
546 final Graphics2D gfx = (Graphics2D) g;
547 gfx.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
548 realizer.paint(gfx);
549 } finally {
550 g.dispose();
551 }
552 }
553 }
554 }
555 }
556