f778dc4c292c376408ef2dc0e74119c9ffa5dd4c
[scilab.git] / scilab / modules / graph / src / java / org / scilab / modules / graph / event / ArrowKeyListener.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2009 - DIGITEO - Clement DAVID
4  * Copyright (C) 2012 - Scilab Enterprises - Clement DAVID
5  *
6  * Copyright (C) 2012 - 2016 - Scilab Enterprises
7  *
8  * This file is hereby licensed under the terms of the GNU GPL v2.0,
9  * pursuant to article 5.3.4 of the CeCILL v.2.1.
10  * This file was originally licensed under the terms of the CeCILL v2.1,
11  * and continues to be available under such terms.
12  * For more information, see the COPYING file which you should have received
13  * along with this program.
14  *
15  */
16
17 package org.scilab.modules.graph.event;
18
19 import java.awt.Toolkit;
20 import java.awt.event.ActionEvent;
21 import java.awt.event.ActionListener;
22 import java.awt.event.KeyEvent;
23 import java.awt.event.KeyListener;
24 import java.util.List;
25
26 import javax.swing.Timer;
27
28 import com.mxgraph.model.mxGeometry;
29 import com.mxgraph.model.mxIGraphModel;
30 import com.mxgraph.swing.mxGraphComponent;
31 import com.mxgraph.util.mxPoint;
32 import com.mxgraph.view.mxGraph;
33
34 /**
35  * Move cells with the arrow keys.
36  */
37 public final class ArrowKeyListener implements KeyListener {
38
39     private static final int DEFAULT_PIXEL_MOVE = 1;
40     private static final int MODIFIER_FACTOR = 5;
41     private static final int DEFAULT_DELAY = 800; // milliseconds
42
43     /* Configuration variables */
44     private final int pixelMove = DEFAULT_PIXEL_MOVE;
45     private int delay = DEFAULT_DELAY;
46
47     /* Runtime variables */
48     private double xIncrement;
49     private double yIncrement;
50     private mxGraph graph;
51
52     private final Timer repetitionTimer;
53     private final ActionListener doMove = new ActionListener() {
54         @Override
55         public void actionPerformed(ActionEvent arg0) {
56             if (graph != null) {
57
58                 final mxIGraphModel model = graph.getModel();
59                 model.beginUpdate();
60                 try {
61                     for (Object cell : graph.getSelectionCells()) {
62                         // first increment
63                         graph.translateCell(cell, xIncrement, yIncrement);
64
65                         // then align
66                         final mxGeometry geom = model.getGeometry(cell);
67                         model.setGeometry(cell, snap(graph, geom));
68                     }
69                 } finally {
70                     model.endUpdate();
71                 }
72
73             }
74         }
75     };
76
77     private static final mxGeometry snap(final mxGraph graph, final mxGeometry rect) {
78         final double x = graph.snap(rect.getX());
79         final double y = graph.snap(rect.getY());
80
81         final double width = graph.snap(rect.getWidth() - x + rect.getX());
82         final double height = graph.snap(rect.getHeight() - y + rect.getY());
83
84         final List<mxPoint> points = rect.getPoints();
85         if (points != null) {
86             for (final mxPoint p : points) {
87                 p.setX(graph.snap(p.getX()));
88                 p.setY(graph.snap(p.getY()));
89             }
90         }
91
92         final mxGeometry snappedGeom = new mxGeometry(x, y, width, height);
93         snappedGeom.setPoints(points);
94
95         return snappedGeom;
96     }
97
98     /**
99      * Constructor
100      */
101     public ArrowKeyListener() {
102         repetitionTimer = new Timer(delay, doMove);
103         repetitionTimer.setInitialDelay(0);
104     }
105
106     /**
107      * @param delay
108      *            the delay to set
109      */
110     public void setDelay(int delay) {
111         this.delay = delay;
112         repetitionTimer.setDelay(delay);
113     }
114
115     /**
116      * @return the delay
117      */
118     public int getDelay() {
119         return delay;
120     }
121
122     /**
123      * Get the action parameters and start the action timer.
124      *
125      * @param e
126      *            key event
127      */
128     @Override
129     public void keyPressed(KeyEvent e) {
130         if (e.isConsumed()) {
131             return;
132         }
133
134         int realMove;
135         boolean mustMove = true;
136
137         mxGraphComponent sourceDiagram = (mxGraphComponent) e.getSource();
138         graph = sourceDiagram.getGraph();
139
140         if (graph.isGridEnabled()) {
141             realMove = graph.getGridSize();
142         } else {
143             realMove = pixelMove;
144         }
145
146         if (e.getModifiers() == Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()) {
147             realMove *= MODIFIER_FACTOR;
148         }
149
150         switch (e.getKeyCode()) {
151             case KeyEvent.VK_UP:
152                 yIncrement = -realMove;
153                 break;
154
155             case KeyEvent.VK_DOWN:
156                 yIncrement = realMove;
157                 break;
158
159             case KeyEvent.VK_RIGHT:
160                 xIncrement = realMove;
161                 break;
162
163             case KeyEvent.VK_LEFT:
164                 xIncrement = -realMove;
165                 break;
166
167             default:
168                 mustMove = false;
169                 break;
170         }
171
172         if (!mustMove) {
173             return;
174         }
175
176         if (!graph.isGridEnabled()) {
177             xIncrement *= sourceDiagram.getZoomFactor();
178             yIncrement *= sourceDiagram.getZoomFactor();
179         }
180
181         repetitionTimer.start();
182
183         e.consume();
184     }
185
186     /**
187      * Stop the action timer and clear parameters
188      *
189      * @param e
190      *            key event
191      */
192     @Override
193     public void keyReleased(KeyEvent e) {
194         if (e.isConsumed()) {
195             return;
196         }
197
198         repetitionTimer.stop();
199         yIncrement = 0;
200         xIncrement = 0;
201         graph = null;
202
203         e.consume();
204     }
205
206     /**
207      * Not used there
208      *
209      * @param e
210      *            Not used
211      */
212     @Override
213     public void keyTyped(KeyEvent e) {
214     }
215 }