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