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 demo.view.DemoDefaults;
32  
33  import y.view.AbstractMouseInputEditor;
34  import y.view.Drawable;
35  import y.view.EditMode;
36  import y.view.Graph2DView;
37  import y.view.HitInfo;
38  import y.view.Mouse2DEvent;
39  import y.view.MouseInputEditor;
40  import y.view.MouseInputEditorProvider;
41  
42  import javax.swing.Timer;
43  import java.awt.Color;
44  import java.awt.Graphics2D;
45  import java.awt.Rectangle;
46  import java.awt.Shape;
47  import java.awt.EventQueue;
48  import java.awt.event.ActionEvent;
49  import java.awt.event.ActionListener;
50  import java.awt.geom.AffineTransform;
51  import java.awt.geom.GeneralPath;
52  import java.awt.geom.Point2D;
53  import java.util.Locale;
54  
55  /**
56   * This class demonstrates how to add a custom drawable to the view that interacts
57   * with {@link y.view.EditMode}'s {@link y.view.MouseInputMode}.
58   * @see <a href="http://docs.yworks.com/yfiles/doc/api/index.html#/dguide/mvc_controller#intf_MouseInputEditor" target="_blank">Section User Interaction</a> in the yFiles for Java Developer's Guide
59   */
60  public class MouseInputDemo extends DemoBase {
61  
62    public MouseInputDemo() {
63      {
64        AffineTransform transform = AffineTransform.getTranslateInstance( 45, 45 );
65        transform.translate( 0, -40 );
66        new ArrowButton( view,
67                         ArrowButton.ARROW.createTransformedShape( transform ),
68                         new ScrollActionListener( 0, -10 ) );
69      }
70      {
71        AffineTransform transform = AffineTransform.getTranslateInstance( 45, 45 );
72        transform.rotate( Math.toRadians( -90 ) );
73        transform.translate( 0, -40 );
74        new ArrowButton( view,
75                         ArrowButton.ARROW.createTransformedShape( transform ),
76                         new ScrollActionListener( -10, 0 ) );
77      }
78      {
79        AffineTransform transform = AffineTransform.getTranslateInstance( 45, 45 );
80        transform.rotate( Math.toRadians( -180 ) );
81        transform.translate( 0, -40 );
82        new ArrowButton( view,
83                         ArrowButton.ARROW.createTransformedShape( transform ),
84                         new ScrollActionListener( 0, 10 ) );
85      }
86      {
87        AffineTransform transform = AffineTransform.getTranslateInstance( 45, 45 );
88        transform.rotate( Math.toRadians( 90 ) );
89        transform.translate( 0, -40 );
90        new ArrowButton( view,
91                         ArrowButton.ARROW.createTransformedShape( transform ),
92                         new ScrollActionListener( 10, 0 ) );
93      }
94  
95      loadGraph( "resource/5.graphml" );
96      DemoDefaults.applyRealizerDefaults(view.getGraph2D(), true, true);
97    }
98  
99    protected void registerViewModes() {
100     EditMode editMode = new EditMode();
101     editMode.getMouseInputMode().setDrawableSearchingEnabled( true );
102     editMode.allowMouseInput( true );
103     view.addViewMode( editMode );
104   }
105 
106   static final class ArrowButton implements Drawable, MouseInputEditorProvider {
107     private final Graph2DView view;
108     private final Shape arrow;
109     private final ActionListener action;
110     private boolean highlight;
111 
112     public static final GeneralPath ARROW;
113 
114     static {
115       GeneralPath path;
116       path = new GeneralPath( GeneralPath.WIND_EVEN_ODD, 8 );
117       path.moveTo( 0, 0 );
118       path.lineTo( 15, 15 );
119       path.lineTo( 5, 15 );
120       path.lineTo( 5, 25 );
121       path.lineTo( -5, 25 );
122       path.lineTo( -5, 15 );
123       path.lineTo( -15, 15 );
124       path.closePath();
125       ARROW = path;
126     }
127 
128 
129     public ArrowButton( Graph2DView view, Shape arrow, ActionListener action ) {
130       this.view = view;
131       this.arrow = arrow;
132       this.action = action;
133       view.addDrawable( this );
134     }
135 
136     public void paint( Graphics2D g ) {
137       double x = view.toWorldCoordX( 0 );
138       double y = view.toWorldCoordY( 0 );
139       g = ( Graphics2D ) g.create();
140       g.translate( x, y );
141       double z2 = 1 / view.getZoom();
142       g.scale( z2, z2 );
143       g.setColor( new Color( 0, 0, 0, 64 ) );
144       g.translate( 4, 4 );
145       g.fill( arrow );
146       g.translate( -4, -4 );
147       g.setColor( highlight ? Color.yellow : DemoDefaults.DEFAULT_CONTRAST_COLOR );
148       g.fill( arrow );
149       g.setColor( Color.black );
150       g.draw( arrow );
151       g.dispose();
152     }
153 
154     public Rectangle getBounds() {
155       Rectangle bounds = arrow.getBounds();
156       double x = view.toWorldCoordX( ( int ) bounds.getCenterX() );
157       double y = view.toWorldCoordY( ( int ) bounds.getCenterY() );
158       double w2 = ( int ) ( 0.5d * bounds.getWidth() / view.getZoom() );
159       double h2 = ( int ) ( 0.5d * bounds.getHeight() / view.getZoom() );
160       return new Rectangle( ( int ) ( x - w2 ), ( int ) ( y - h2 ), ( int ) ( 2 * w2 ), ( int ) ( 2 * h2 ) );
161     }
162 
163     public MouseInputEditor findMouseInputEditor( double x, double y ) {
164       int vx = view.toViewCoordX( x );
165       int vy = view.toViewCoordY( y );
166       if ( arrow.contains( vx, vy ) ) {
167         return new AbstractMouseInputEditor() {
168           Timer timer;
169 
170           {
171             timer = new Timer( 30, action );
172             timer.setRepeats( true );
173             timer.setInitialDelay( 200 );
174           }
175 
176           public boolean startsEditing( Mouse2DEvent event ) {
177             int vx = view.toViewCoordX( event.getX() );
178             int vy = view.toViewCoordY( event.getY() );
179             return arrow.contains( vx, vy );
180           }
181 
182           public void mouse2DEventHappened( Mouse2DEvent event ) {
183             int vx = view.toViewCoordX( event.getX() );
184             int vy = view.toViewCoordY( event.getY() );
185             boolean contains = arrow.contains( vx, vy );
186             switch ( event.getId() ) {
187               case Mouse2DEvent.MOUSE_DRAGGED:
188                 break;
189               case Mouse2DEvent.MOUSE_PRESSED:
190                 timer.start();
191                 break;
192               case Mouse2DEvent.MOUSE_CLICKED:
193                 action.actionPerformed( new ActionEvent( ArrowButton.this, ActionEvent.ACTION_PERFORMED, null ) );
194                 view.updateView();
195                 // fall through
196               case Mouse2DEvent.MOUSE_RELEASED:
197                 timer.stop();
198                 // fall through
199               case Mouse2DEvent.MOUSE_MOVED:
200                 if ( highlight != contains ) {
201                   highlight = contains;
202                   view.updateView();
203                 }
204                 if ( !contains ) {
205                   stopEditing();
206                 }
207             }
208           }
209         };
210       } else {
211         return null;
212       }
213     }
214 
215     public MouseInputEditor findMouseInputEditor( Graph2DView view, double x, double y, HitInfo hitInfo ) {
216       return findMouseInputEditor( x, y );
217     }
218   }
219 
220   private class ScrollActionListener implements ActionListener {
221     private final double dx;
222     private final double dy;
223 
224     public ScrollActionListener( double dx, double dy ) {
225       this.dx = dx;
226       this.dy = dy;
227     }
228 
229     public void actionPerformed( ActionEvent e ) {
230       Point2D viewPoint2D = view.getViewPoint2D();
231       view.setViewPoint2D( viewPoint2D.getX() + dx, viewPoint2D.getY() + dy );
232       view.updateView();
233     }
234   }
235 
236   public static void main(String[] args) {
237     EventQueue.invokeLater(new Runnable() {
238       public void run() {
239         Locale.setDefault(Locale.ENGLISH);
240         initLnF();
241         (new MouseInputDemo()).start("MouseInputDemo");
242       }
243     });
244   }
245 }
246