1   /****************************************************************************
2    **
3    ** This file is part of yFiles-2.6. 
4    ** 
5    ** yWorks proprietary/confidential. Use is subject to license terms.
6    **
7    ** Redistribution of this file or of an unauthorized byte-code version
8    ** of this file is strictly forbidden.
9    **
10   ** Copyright (c) 2000-2008 by yWorks GmbH, Vor dem Kreuzberg 28, 
11   ** 72070 Tuebingen, Germany. All rights reserved.
12   **
13   ***************************************************************************/
14  package demo.view.ports;
15  
16  import demo.view.DemoBase;
17  import demo.view.advanced.DragAndDropDemo;
18  import y.base.Edge;
19  import y.base.YList;
20  import y.io.GMLIOHandler;
21  import y.io.YGFIOHandler;
22  import y.util.D;
23  import y.view.CreateEdgeMode;
24  import y.view.EdgeRealizer;
25  import y.view.EditMode;
26  import y.view.Graph2D;
27  import y.view.Graph2DView;
28  import y.view.ImageNodeRealizer;
29  import y.view.NodeRealizer;
30  import y.view.Port;
31  
32  import javax.swing.AbstractAction;
33  import javax.swing.Action;
34  import javax.swing.JComponent;
35  import javax.swing.JFileChooser;
36  import javax.swing.JList;
37  import javax.swing.JScrollPane;
38  import javax.swing.ListCellRenderer;
39  import javax.swing.event.ListSelectionEvent;
40  import javax.swing.event.ListSelectionListener;
41  import java.awt.BorderLayout;
42  import java.awt.Color;
43  import java.awt.Component;
44  import java.awt.Dimension;
45  import java.awt.Graphics;
46  import java.awt.Image;
47  import java.awt.event.ActionEvent;
48  import java.io.IOException;
49  import java.util.ArrayList;
50  import java.util.List;
51  
52  /**
53   *  Demonstrates how CreateEdgeMode and ImageNodeRealizer can be customized 
54   *  in order to create an application that makes use of a set of 
55   *  fixed port coordinates for each node.
56   *  Additionally this application demonstrates the customization of the GML 
57   *  parser and encoder. For this scenario, the GML format is customized in order
58   *  to serialize and deserialize possible port coordinate for each node.
59   */
60  public class PortsDemo extends DemoBase{
61    private ImageNodeRealizer[] images;
62  
63    /**
64     * This method is called before the view modes and actions are registered and the menu and toolbar is build.
65     */
66    protected void initialize() {
67      GMLIOHandler.setEncoderFactory(new EncoderFactory());
68      GMLIOHandler.setParserFactory(new ParserFactory());
69  
70      List imageNRList = new ArrayList();
71  
72      FixedPortsNodeRealizer nr = new FixedPortsNodeRealizer();
73      nr.setPaintingPorts(false);
74      nr.setImageURL(this.getClass().getResource("resource/4pkt.gif"));
75      nr.setToImageSize();
76      imageNRList.add(nr);
77      YList ports = nr.getPortCandidates();
78      ports.clear();
79      double w = nr.getWidth();
80      double h = nr.getHeight();
81      double r = 6;
82      ports.add(new Port(-w/2 + r, -h/2 + r));
83      ports.add(new Port(-w/2 + r, 0));
84      ports.add(new Port(w/2 - r, 0));
85      ports.add(new Port(-w/2+ r, h/2 -r));
86  
87      nr = new FixedPortsNodeRealizer();
88      nr.setPaintingPorts(false);
89      nr.setImageURL(this.getClass().getResource("resource/4pktleft.gif"));
90      nr.setToImageSize();
91      imageNRList.add(nr);
92      ports = nr.getPortCandidates();
93      ports.clear();
94      w = nr.getWidth();
95      h = nr.getHeight();
96      r = 6;
97      ports.add(new Port(w/2 - r, -h/2 + r));
98      ports.add(new Port(w/2 - r, 0));
99      ports.add(new Port(-w/2 + r, 0));
100     ports.add(new Port(w/2 - r, h/2 - r));
101 
102     nr = new FixedPortsNodeRealizer();
103     nr.setPaintingPorts(false);
104     nr.setImageURL(this.getClass().getResource("resource/2pkt.gif"));
105     imageNRList.add(nr);
106     nr.setToImageSize();
107     ports = nr.getPortCandidates();
108     ports.clear();
109     w = nr.getWidth();
110     h = nr.getHeight();
111     r = 6;
112     ports.add(new Port(w/2 - r, 0));
113     ports.add(new Port(-w/2+ r, 0));
114 
115     final Graph2D graph = this.view.getGraph2D();
116 
117     images = new ImageNodeRealizer[imageNRList.size()];
118     images = (ImageNodeRealizer[]) imageNRList.toArray(images);
119 
120     graph.setDefaultNodeRealizer(images[0]);
121 
122     //Scroll
123     DragAndDropDemo.DragAndDropSupport dragAndDropSupport = new MyDragAndDropSupport( images );
124 
125     final JList list = dragAndDropSupport.getList();
126     list.addListSelectionListener( new ListSelectionListener() {
127       public void valueChanged( ListSelectionEvent e ) {
128         graph.setDefaultNodeRealizer( images[ list.getSelectedIndex() ] );
129       }
130     } );
131     list.setSelectedIndex( 0 );
132     JScrollPane scrollPane = new JScrollPane( list );
133 
134     list.setBackground( Color.LIGHT_GRAY );
135     list.setCellRenderer( new Renderer() );
136 
137     contentPane.add( scrollPane, BorderLayout.WEST );
138 
139     loadGraph(  "resource/viewport.gml" );
140 
141     view.setGridMode( true );            //snap to grid
142     view.setGridResolution( 29 );        //grid distance (should correspond to actual port candidates)
143     view.setGridType( Graph2DView.GRID_CROSS ); //grid type
144     view.setGridVisible( true );         //show grid
145   }
146 
147   protected void registerViewModes() {
148     EditMode editMode = new EditMode( );
149     editMode.setCreateEdgeMode(new PortCreateEdgeMode());
150     view.addViewMode( editMode );
151   }
152 
153   public void dispose() {
154     super.dispose();
155     // reset to old state
156     GMLIOHandler.setEncoderFactory(null);
157     GMLIOHandler.setParserFactory(null);
158   }
159 
160   /**
161    * modified version of CreateEdgeMode, that assigns port coordinates
162    * according to the ones offered by FixedPortsNodeRealizer's candidates
163    */
164   private static final class PortCreateEdgeMode extends CreateEdgeMode {
165     private Edge edge; // need this for the hook
166 
167     /**
168      * If a node was hit at the given coordinates, that node
169      * will be used as target node for the newly created edge.
170      *
171      */
172     public void mouseReleasedLeft( double x, double y ) {
173       // simulate a pressed shift...
174       // this will trigger CreateEdgeMode, to preassign offset
175       // to source and target ports
176       super.mouseShiftReleasedLeft( x, y );
177 
178       if ( edge != null ) { // the edge has just been created
179         Graph2D graph = ( Graph2D ) edge.getGraph();
180         EdgeRealizer er = graph.getRealizer( edge );
181 
182         NodeRealizer nr = graph.getRealizer( edge.target() );
183         if ( nr instanceof FixedPortsNodeRealizer ) {
184           FixedPortsNodeRealizer fpnr = ( FixedPortsNodeRealizer ) nr;
185           Port p = er.getTargetPort();
186           p = fpnr.snapCandidate( graph, er, false, p.getOffsetX(), p.getOffsetY() );
187           er.setTargetPort( p );
188         }
189 
190         nr = graph.getRealizer( edge.source() );
191         if ( nr instanceof FixedPortsNodeRealizer ) {
192           FixedPortsNodeRealizer fpnr = ( FixedPortsNodeRealizer ) nr;
193           Port p = er.getSourcePort();
194           p = fpnr.snapCandidate( graph, er, true, p.getOffsetX(), p.getOffsetY() );
195           er.setSourcePort( p );
196         }
197 
198         // do some clean up
199         edge = null;
200         graph.updateViews();
201       }
202 
203     }
204 
205     /**
206      * Initiates the creation of an edge.
207      * 
208      */
209     public void mousePressedLeft( double x, double y ) {
210       // simulate a pressed shift...
211       // this will trigger CreateEdgeMode, to preassign offset
212       // to source and target ports
213       super.mouseShiftPressedLeft( x, y );
214     }
215 
216 
217     public void edgeCreated( Edge e ) {
218       //remember the edge...
219       this.edge = e;
220     }
221   }
222 
223   /*
224    * overwritten here to install gml io handling
225    */
226   protected Action createLoadAction() {
227     return new LoadAction();
228   }
229 
230   /*
231    * overwritten here to install gml io handling
232    */
233   protected Action createSaveAction() {
234     return new SaveAction();
235   }
236 
237   /**
238    * Action that saves the current graph to a file in YGF or GML format.
239    */
240   private final class SaveAction extends AbstractAction {
241     SaveAction() {
242       super( "Save..." );
243     }
244 
245     public void actionPerformed( ActionEvent e ) {
246       JFileChooser chooser = new JFileChooser();
247       if ( chooser.showSaveDialog( contentPane ) == JFileChooser.APPROVE_OPTION ) {
248         String name = chooser.getSelectedFile().toString();
249         if ( name.endsWith( ".gml" ) ) {
250           GMLIOHandler ioh = new GMLIOHandler();
251           try {
252             ioh.write( view.getGraph2D(), name );
253           } catch ( IOException ioe ) {
254             D.show( ioe );
255           }
256         } else {
257           if ( !name.endsWith( ".ygf" ) ) name = name + ".ygf";
258           YGFIOHandler ioh = new YGFIOHandler();
259           try {
260             ioh.write( view.getGraph2D(), name );
261           } catch ( IOException ioe ) {
262             D.show( ioe );
263           }
264         }
265       }
266     }
267   }
268 
269   /**
270    * Action that loads the current graph from a file in YGF or GML format.
271    */
272   private final class LoadAction extends AbstractAction {
273     LoadAction() {
274       super( "Load..." );
275     }
276 
277     public void actionPerformed( ActionEvent e ) {
278       JFileChooser chooser = new JFileChooser();
279       if ( chooser.showOpenDialog( contentPane ) == JFileChooser.APPROVE_OPTION ) {
280         String name = chooser.getSelectedFile().toString();
281         if ( name.endsWith( ".gml" ) ) {
282           GMLIOHandler ioh = new GMLIOHandler();
283           try {
284             view.getGraph2D().clear();
285             ioh.read( view.getGraph2D(), name );
286           } catch ( IOException ioe ) {
287             D.show( ioe );
288           }
289         } else {
290           if ( !name.endsWith( ".ygf" ) ) name = name + ".ygf";
291           YGFIOHandler ioh = new YGFIOHandler();
292           try {
293             view.getGraph2D().clear();
294             ioh.read( view.getGraph2D(), name );
295           } catch ( IOException ioe ) {
296             D.show( ioe );
297           }
298         }
299         //force redisplay of view contents
300         view.updateView();
301       }
302     }
303   }
304 
305   /**
306    * helper class for displaying ImageNodeRealizers in a JComboBox
307    */
308   private static final class Renderer extends JComponent implements ListCellRenderer {
309     private Image image;
310     private int width, height;
311     private Color bg;
312 
313     public void paintComponent( Graphics gfx ) {
314       gfx.setColor( bg );
315       gfx.fillRect( 0, 0, getWidth(), getHeight() );
316       gfx.drawImage( image, 5, ( getHeight() - height ) / 2, width, height, this );
317     }
318 
319     public Component getListCellRendererComponent(
320       JList list, Object value, int index, boolean isSelected, boolean cellHasFocus ) {
321       bg = isSelected ? list.getSelectionBackground() : list.getBackground();
322       image = ( ( ImageNodeRealizer ) value ).getImage();
323       width = image.getWidth( this );
324       height = image.getHeight( this );
325       setPreferredSize( new Dimension( width + 10, height + 10 ) );
326       return this;
327     }
328   }
329 
330   /**
331    * launches the demo
332    */
333   public static void main( String[] args ) {
334     initLnF();
335     PortsDemo demo = new PortsDemo();
336     demo.start("Port Demo");
337   }
338 
339   private class MyDragAndDropSupport extends DragAndDropDemo.DragAndDropSupport {
340     MyDragAndDropSupport( ImageNodeRealizer[] images ) {
341       super( images, view );
342     }
343 
344     protected String getTextValue( NodeRealizer selected ) {
345       return ( ( ImageNodeRealizer ) selected ).getImageURL().getFile();
346     }
347 
348     protected NodeRealizer createNodeRealizerFromTextValue( String s ) {
349       for ( int i = 0; i < images.length; i++ ) {
350         ImageNodeRealizer image = images[ i ];
351         if ( image.getImageURL().getPath().equals( s ) ) {
352           return image;
353         }
354       }
355       return images[ 0 ];
356     }
357   }
358 }
359 
360 
361       
362