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