1   /****************************************************************************
2    * This demo file is part of yFiles for Java 2.14.
3    * Copyright (c) 2000-2017 by yWorks GmbH, Vor dem Kreuzberg 28,
4    * 72070 Tuebingen, Germany. All rights reserved.
5    * 
6    * yFiles demo files exhibit yFiles for Java functionalities. Any redistribution
7    * of demo files in source code or binary form, with or without
8    * modification, is not permitted.
9    * 
10   * Owners of a valid software license for a yFiles for Java version that this
11   * demo is shipped with are allowed to use the demo source code as basis
12   * for their own yFiles for Java powered applications. Use of such programs is
13   * governed by the rights and conditions as set out in the yFiles for Java
14   * license agreement.
15   * 
16   * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESS OR IMPLIED
17   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18   * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
19   * NO EVENT SHALL yWorks BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
21   * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22   * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23   * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24   * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26   *
27   ***************************************************************************/
28  package demo.view.advanced.ports;
29  
30  import y.base.Node;
31  import y.geom.YPoint;
32  import y.option.RealizerCellRenderer;
33  import y.view.DropSupport;
34  import y.view.Graph2D;
35  import y.view.Graph2DView;
36  import y.view.NodePort;
37  import y.view.NodeRealizer;
38  import y.view.NodeScaledPortLocationModel;
39  
40  import java.awt.Color;
41  import java.awt.GridLayout;
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.geom.Rectangle2D;
47  import java.util.Enumeration;
48  import javax.swing.DefaultListModel;
49  import javax.swing.JList;
50  import javax.swing.JPanel;
51  import javax.swing.JScrollPane;
52  import javax.swing.ListSelectionModel;
53  import javax.swing.event.ListSelectionEvent;
54  import javax.swing.event.ListSelectionListener;
55  
56  /**
57   * A palette that provides templates for nodes with node ports.
58   *
59   */
60  class Palette extends JPanel {
61    /**
62     * Initializes a new <code>Palette</code> instance for the specified graph
63     * view.
64     * @param view the {@link y.view.Graph2DView} holding the graph in which
65     * nodes can be created using this palette's templates.
66     */
67    Palette( final Graph2DView view ) {
68      super(new GridLayout(1, 1));
69  
70      // begin create templates
71      final NodeRealizer nr = view.getGraph2D().getDefaultNodeRealizer();
72      final NodeRealizer prototype = nr.createCopy();
73      prototype.setSize(90, 60);
74      prototype.setFillColor(Color.LIGHT_GRAY);
75  
76      final DefaultListModel model = new DefaultListModel();
77      model.addElement(addDynamicPorts(prototype.createCopy()));
78      model.addElement(addEllipsePorts(prototype.createCopy()));
79      model.addElement(addRectanglePort(prototype.createCopy()));
80      // end create templates
81  
82      // begin create control to choose between templates
83      final Rectangle2D.Double r = new Rectangle2D.Double(0, 0, -1, -1);
84      for (Enumeration en = model.elements(); en.hasMoreElements();) {
85        ((NodeRealizer) en.nextElement()).calcUnionRect(r);
86      }
87  
88      final JList jl = new JList(model);
89      jl.setCellRenderer(new RealizerCellRenderer(
90              (int) Math.ceil(r.getWidth()) + 10,
91              (int) Math.ceil(r.getHeight()) + 10));
92      jl.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
93        public void valueChanged( final ListSelectionEvent e ) {
94          final Object value = jl.getSelectedValue();
95          if (value instanceof NodeRealizer) {
96            view.getGraph2D().setDefaultNodeRealizer((NodeRealizer) value);
97          }
98        }
99      });
100     jl.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
101     jl.setSelectedIndex(0);
102 
103     add(new JScrollPane(jl));
104     // end create control to choose between templates
105 
106     // begin setup drag and drop support
107     //   nodes can be created by dragging this palette's templates to the
108     //   associated graph view
109     final DropSupport dropSupport = new DropSupport(view) {
110       protected Node createNode(
111               final Graph2DView view,
112               final NodeRealizer nr,
113               final double x,
114               final double y
115       ) {
116         final Graph2D graph = view.getGraph2D();
117         final Node node = super.createNode(view, nr, x, y);
118         graph.getRealizer(node).setLabelText(Integer.toString(graph.nodeCount()));
119         return node;
120       }
121     };
122     dropSupport.setPreviewEnabled(true);
123 
124     final DragSource dragSource = new DragSource();
125     dragSource.createDefaultDragGestureRecognizer(jl, DnDConstants.ACTION_MOVE,
126         new DragGestureListener() {
127           public void dragGestureRecognized( final DragGestureEvent e ) {
128             final Object value = jl.getSelectedValue();
129             if (value instanceof NodeRealizer) {
130               dropSupport.startDrag(dragSource, (NodeRealizer) value, e, DragSource.DefaultMoveDrop);
131             }
132           }
133         });
134     // end setup drag and drop support
135   }
136 
137   /**
138    * Adds dynamic, rectangular node ports to the specified realizer.
139    * @param nr the {@link y.view.NodeRealizer} to which node ports are added.
140    * @return the specified realizer instance.
141    */
142   private NodeRealizer addDynamicPorts( final NodeRealizer nr ) {
143     return addPorts(
144             nr,
145             PortConfigurations.INSTANCE.portConfigDynamic,
146             NodeScaledPortLocationModel.POLICY_BOUNDARY,
147             new YPoint[]{
148                     new YPoint(nr.getCenterX(), nr.getY()),
149                     new YPoint(nr.getX(), nr.getCenterY()),
150                     new YPoint(nr.getCenterX(), nr.getY() + nr.getHeight()),
151                     new YPoint(nr.getX() + nr.getWidth(), nr.getCenterY()),
152             }
153     );
154   }
155 
156   /**
157    * Adds rectangular node ports to the specified realizer.
158    * @param nr the {@link y.view.NodeRealizer} to which node ports are added.
159    * @return the specified realizer instance.
160    */
161   private NodeRealizer addRectanglePort( final NodeRealizer nr ) {
162     final double x = nr.getX();
163     final double y = nr.getY();
164     final double w = nr.getWidth();
165     final double h = nr.getHeight();
166     return addPorts(
167             nr,
168             PortConfigurations.INSTANCE.portConfigRectangle,
169             NodeScaledPortLocationModel.POLICY_BOUNDARY,
170             new YPoint[] {
171                     new YPoint(x, y + h * 0.25),
172                     new YPoint(x, y + h * 0.75),
173                     new YPoint(x + w, y + h * 0.25),
174                     new YPoint(x + w, y + h * 0.75),
175             }
176     );
177   }
178 
179   /**
180    * Adds elliptical node ports to the specified realizer.
181    * @param nr the {@link y.view.NodeRealizer} to which node ports are added.
182    * @return the specified realizer instance.
183    */
184   private NodeRealizer addEllipsePorts( final NodeRealizer nr ) {
185     final double x = nr.getX();
186     final double y = nr.getY();
187     final double w = nr.getWidth();
188     final double h = nr.getHeight();
189     return addPorts(
190             nr,
191             PortConfigurations.INSTANCE.portConfigEllipse,
192             NodeScaledPortLocationModel.POLICY_BOUNDARY_CENTER,
193             new YPoint[]{
194                     new YPoint(x, y + h * 0.25),
195                     new YPoint(x, y + h * 0.75),
196                     new YPoint(x + w * 0.25, y + h),
197                     new YPoint(x + w * 0.5, y + h),
198                     new YPoint(x + w * 0.75, y + h),
199                     new YPoint(x + w, y + h * 0.75),
200                     new YPoint(x + w, y + h * 0.25),
201                     new YPoint(x + w * 0.75, y),
202                     new YPoint(x + w * 0.5, y),
203                     new YPoint(x + w * 0.25, y),
204             }
205     );
206   }
207 
208   /**
209    * Adds a node port to the specified realizer for each of the specified
210    * port positions.
211    * @param nr the {@link y.view.NodeRealizer} to which node ports are added.
212    * @param configuration the name of the node port configuration for the
213    * added node ports.
214    * @param policy the location policy of the {@link y.view.PortLocationModel}
215    * used for the added node ports.
216    * @param positions the positions of the added node ports.
217    * @return the specified realizer instance.
218    */
219   private NodeRealizer addPorts(
220           final NodeRealizer nr,
221           final String configuration,
222           final byte policy,
223           final YPoint[] positions
224   ) {
225     for (int i = 0; i < positions.length; ++i) {
226       final NodePort port = new NodePort();
227       port.setConfiguration(configuration);
228       nr.addPort(port);
229       final NodeScaledPortLocationModel model = new NodeScaledPortLocationModel();
230       model.setPortLocationPolicy(policy);
231       port.setModelParameter(model.createParameter(nr, positions[i]));
232     }
233 
234     return nr;
235   }
236 }
237