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.viewmode;
29  
30  import demo.view.DemoBase;
31  import y.base.Node;
32  import y.geom.YPoint;
33  import y.view.CreateEdgeMode;
34  import y.view.Drawable;
35  import y.view.EditMode;
36  import y.view.MoveSelectionMode;
37  import y.view.SnapLine;
38  import y.view.Graph2DView;
39  import y.view.MoveSnapContext;
40  
41  import javax.swing.BorderFactory;
42  import javax.swing.JSlider;
43  import javax.swing.JToggleButton;
44  import javax.swing.JToolBar;
45  import javax.swing.SwingConstants;
46  import javax.swing.event.ChangeEvent;
47  import javax.swing.event.ChangeListener;
48  import java.awt.Color;
49  import java.awt.Dimension;
50  import java.awt.Graphics2D;
51  import java.awt.Rectangle;
52  import java.awt.EventQueue;
53  import java.util.Locale;
54  
55  /**
56   * Demonstrates {@link EditMode}'s snapping feature in conjunction with orthogonal edges. <br>
57   * This demo can be used to toggle the snapping feature on and off. It shows how a custom {@link SnapLine}
58   * (the red vertical line) can be used to snap nodes and edges to other entities.
59   * Toggling the "Snapping" button in the toolbar toggles snapping on and off, the sliders can be used to adjust the
60   * preferred distance between nodes and edges. This will influence the "preferred distance snap lines."<br>
61   * Toggling the "Grid" button in the toolbar toggles the grid on and off. Note that
62   * {@link Graph2DView#setGridMode(boolean) enabling the grid on the view} has the effect that nodes can only
63   * be placed on grid positions, thus it prevents the other snapping rules from being applied. The grid in this
64   * demo uses the {@link MoveSnapContext#setUsingGridSnapping(boolean) newer grid snapping feature} instead, which
65   * coexists nicely with other snapping rules.
66   * @see <a href="http://docs.yworks.com/yfiles/doc/api/index.html#/dguide/mvc_controller#snapping" target="_blank">Section User Interaction</a> in the yFiles for Java Developer's Guide
67   */
68  public class SnapLineDemo extends DemoBase {
69  
70    private EditMode editMode;
71    private JToggleButton snapLineButton;
72    private JToggleButton showGridButton;
73    private SnappingConfiguration snappingConfiguration;
74  
75    /**
76     * A custom single snap line that will displayed in the view and used by the {@link MoveSelectionMode}'s
77     * {@link MoveSnapContext}.
78     */
79    private SnapLine snapLine;
80  
81    public SnapLineDemo() {
82      // Initialize snapping.
83      snappingConfiguration = createDefaultSnappingConfiguration();
84      snappingConfiguration.configureView(view);
85      snappingConfiguration.configureEditMode(editMode);
86  
87      setUsingSnapping(true);
88  
89      final Node n1 = view.getGraph2D().createNode(40, 30, "1");
90      final Node n2 = view.getGraph2D().createNode(40, 90, "2");
91      final Node n3 = view.getGraph2D().createNode(40, 210,"3");
92      view.getGraph2D().createEdge(n1, n2);
93      view.getGraph2D().createEdge(n2, n3);
94      view.updateWorldRect();
95    }
96  
97    protected void initialize() {
98      super.initialize();
99  
100     snapLine = new SnapLine(SnapLine.VERTICAL, SnapLine.CENTER, new YPoint(200, 200), 0, 400, null, 1.0d);
101     view.getGraph2D().addDrawable(new Drawable() {
102       public void paint(Graphics2D g) {
103         g.setColor(Color.red);
104         snapLine.paint(g);
105       }
106 
107       public Rectangle getBounds() {
108         return snapLine.getBounds();
109       }
110     });
111   }
112 
113 
114   protected JToolBar createToolBar() {
115     JToolBar toolBar = super.createToolBar();
116     toolBar.addSeparator(TOOLBAR_SMALL_SEPARATOR);
117 
118     snapLineButton = new JToggleButton("Snapping");
119     snapLineButton.setIcon(getIconResource("resource/mode_snapping.png"));
120     toolBar.add(snapLineButton);
121     toolBar.addSeparator(TOOLBAR_SMALL_SEPARATOR);
122 
123     showGridButton = new JToggleButton("Grid");
124     showGridButton.setIcon(getIconResource("resource/mode_grid.png"));
125     toolBar.add(showGridButton);
126 
127     final JSlider s1 = new JSlider(SwingConstants.HORIZONTAL, 0, 80, 30);
128     s1.setBorder(BorderFactory.createTitledBorder("Node To Node"));
129     s1.setMaximumSize(new Dimension(200, 100));
130     toolBar.add(s1);
131     final JSlider s2 = new JSlider(SwingConstants.HORIZONTAL, 0, 80, 20);
132     s2.setBorder(BorderFactory.createTitledBorder("Node To Edge"));
133     s2.setMaximumSize(new Dimension(200, 100));
134     toolBar.add(s2);
135     final JSlider s3 = new JSlider(SwingConstants.HORIZONTAL, 0, 80, 20);
136     s3.setBorder(BorderFactory.createTitledBorder("Edge To Edge"));
137     s3.setMaximumSize(new Dimension(200, 100));
138     toolBar.add(s3);
139     final ChangeListener listener = new ChangeListener() {
140       public void stateChanged(ChangeEvent e) {
141         snappingConfiguration.setSnappingEnabled(snapLineButton.isSelected());
142         snappingConfiguration.setRemovingInnerBends(snapLineButton.isSelected());
143         snappingConfiguration.setNodeToNodeDistance(s1.getValue());
144         snappingConfiguration.setNodeToEdgeDistance(s2.getValue());
145         snappingConfiguration.setEdgeToEdgeDistance(s3.getValue());
146         snappingConfiguration.setGridSnappingEnabled(showGridButton.isSelected());
147 
148         snappingConfiguration.configureView(view);
149         snappingConfiguration.configureEditMode(editMode);
150       }
151     };
152     s1.addChangeListener(listener);
153     s2.addChangeListener(listener);
154     s3.addChangeListener(listener);
155     snapLineButton.addChangeListener(listener);
156     showGridButton.addChangeListener(listener);
157 
158     return toolBar;
159   }
160 
161   protected EditMode createEditMode() {
162     editMode = super.createEditMode();
163     ((MoveSelectionMode) editMode.getMoveSelectionMode()).getSnapContext().addSnapLine(snapLine);
164 
165     // Edges are always orthogonal in this demo.
166     editMode.setOrthogonalEdgeRouting(true);
167     ((CreateEdgeMode)editMode.getCreateEdgeMode()).setOrthogonalEdgeCreation(true);
168 
169     return editMode;
170   }
171 
172   public boolean isUsingSnapping() {
173     return snapLineButton.isSelected();
174   }
175 
176   public void setUsingSnapping(boolean usingSnapping) {
177     this.snapLineButton.setSelected(usingSnapping);
178   }
179 
180   public static void main(String[] args) {
181     EventQueue.invokeLater(new Runnable() {
182       public void run() {
183         Locale.setDefault(Locale.ENGLISH);
184         initLnF();
185         (new SnapLineDemo()).start("SnapLine Demo");
186       }
187     });
188   }
189 }
190