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