1
2 package hep.wired.interaction;
3
4 import java.awt.*;
5 import java.awt.event.*;
6 import java.awt.geom.*;
7 import javax.swing.*;
8
9 import org.freehep.application.Application;
10
11 import hep.wired.edit.WiredCompoundEdit;
12 import hep.wired.edit.Translate;
13 import hep.wired.edit.Scale;
14 import hep.wired.feature.Translateable;
15 import hep.wired.services.RecordPlot;
16 import hep.wired.services.GraphicsPanel;
17 import hep.wired.image.WiredBaseImage;
18
19 /***
20 * Drag/click to define a rectangle to scale and translate the plot.
21 *
22 * @author Mark Donszelmann
23 * @version $Id: DragRectangleToScale.java 1858 2005-06-08 00:11:23Z duns $
24 */
25 public class DragRectangleToScale extends DefaultInteractionHandler {
26
27 private static final String name = "Combined Translate-Scale";
28 private static final int cursorSize = 32;
29 private static final double fixedScale = Math.sqrt(2);
30
31 private boolean fixedRatio = true;
32 private int xp, yp;
33 private int xd, yd;
34 private Rectangle rectangle;
35
36 /***
37 * Create a rectangle handler to generate scale edits.
38 */
39 public DragRectangleToScale() {
40 super("Drag Rectangle to Scale");
41 }
42
43 public Icon getIcon(int size) {
44 return WiredBaseImage.getIcon("Rectangle%w", size);
45 }
46
47 public String getDescription() {
48 return "Click center-zoom-in, Alt-Click to zoom-out-displace, Drag rectangle to zoom.";
49 }
50
51 public boolean isSupportedBy(GraphicsPanel panel) {
52 return new Translate().isSupportedBy(panel) &&
53 new Scale().isSupportedBy(panel);
54 }
55
56 public void changeCursor(RecordPlot plot, InputEvent event) {
57 if (event.getID() == MouseEvent.MOUSE_DRAGGED) {
58 plot.setCursor(WiredBaseImage.getBestCursor("RectangleScaleCursor%w", cursorSize, cursorSize));
59 } else if (event.isAltDown()) {
60 plot.setCursor(WiredBaseImage.getBestCursor("RectangleScaleMinusCursor%w", cursorSize, cursorSize));
61 } else {
62 plot.setCursor(WiredBaseImage.getBestCursor("RectangleScalePlusCursor%w", cursorSize, cursorSize));
63 }
64 }
65
66 public void reset(RecordPlot plot, InputEvent event) {
67 rectangle = null;
68 plot.drawShape(null);
69 Application.getApplication().setStatusMessage(getDescription());
70 }
71
72 public void mouseEntered(RecordPlot plot, MouseEvent event) {
73 plot.requestFocusInWindow();
74 changeCursor(plot, event);
75 }
76
77 /***
78 * Store starting point of rectangle.
79 */
80 public void mouseButton1DragStarted(RecordPlot plot, MouseEvent event) {
81 xp = event.getX();
82 yp = event.getY();
83 changeCursor(plot, event);
84 Application.getApplication().setStatusMessage("Drag rectangle to zoom, Shift removes ratio constraint.");
85 }
86
87 /***
88 * Update moving point of rectangle and draw.
89 */
90 public void mouseButton1Dragged(RecordPlot plot, MouseEvent event) {
91 xd = event.getX();
92 yd = event.getY();
93 defineRectangle(plot, event);
94 }
95
96 /***
97 * Update end point of rectangle, translate and scale, and remove rectangle.
98 */
99 public void mouseButton1DragEnded(RecordPlot plot, MouseEvent event) {
100 translateAndScale(plot, rectangle, fixedRatio);
101 reset(plot, event);
102 }
103
104
105 public static void translateAndScale(RecordPlot plot, Rectangle2D rectangle, boolean fixedRatio) {
106 double du = rectangle.getX()+rectangle.getWidth()/2 -plot.getWidth()/2;
107 double dv = rectangle.getY()+rectangle.getHeight()/2-plot.getHeight()/2;
108
109 WiredCompoundEdit edit = new WiredCompoundEdit(name);
110
111
112 Translateable translateable = (Translateable)plot.getGraphicsPanel().getFeature(Translateable.class);
113 double t[] = translateable.getModelTranslation(new double[] { -du, dv, 0 }, plot.getGraphicsPanel().getViewPort());
114 Translate translate = new Translate(t[0], t[1], t[2], rectangle, 5);
115 Shape shape = translate.createTransformedShape((Component)plot, rectangle);
116 edit.addEdit(translate);
117
118
119 double sx = plot.getWidth() / (rectangle.getWidth()+1);
120 double sy = fixedRatio ? sx : plot.getHeight() / (rectangle.getHeight()+1);
121 double sz = fixedRatio ? sx : Math.min(sx, sy);
122 edit.addEdit(new Scale(sx, sy, sz, shape, 5));
123
124 edit.end();
125 plot.postEdit(edit);
126 }
127
128 public void mouseButton1Released(RecordPlot plot, MouseEvent event) {
129 changeCursor(plot, event);
130 }
131
132 public boolean shiftKeyPressed(RecordPlot plot, KeyEvent event) {
133 defineRectangle(plot, event);
134 return true;
135 }
136
137 public boolean shiftKeyReleased(RecordPlot plot, KeyEvent event) {
138 defineRectangle(plot, event);
139 return true;
140 }
141
142 public boolean altKeyPressed(RecordPlot plot, KeyEvent event) {
143 changeCursor(plot, event);
144 return true;
145 }
146
147 public boolean altKeyReleased(RecordPlot plot, KeyEvent event) {
148 changeCursor(plot, event);
149 return true;
150 }
151
152 private void defineRectangle(RecordPlot plot, InputEvent event) {
153
154 if ((event instanceof KeyEvent) && (rectangle == null)) return;
155
156 int dx = xd - xp;
157 int dy = yd - yp;
158
159
160 if (!event.isShiftDown()) {
161 double ratio = (double)plot.getHeight() / (double)plot.getWidth();
162 if (Math.abs(dy) < Math.abs(dx) * ratio) {
163 dy = (int)(Math.abs(dx)*((dy < 0) ? -1 : 1)*ratio);
164 } else {
165 dx = (int)(Math.abs(dy)*((dx < 0) ? -1 : 1)/ratio);
166 }
167 fixedRatio = true;
168 } else {
169 fixedRatio = false;
170 }
171 rectangle = new Rectangle(Math.min(xp, xp + dx),
172 Math.min(yp, yp + dy),
173 Math.abs(dx),
174 Math.abs(dy));
175 plot.drawShape(rectangle);
176 }
177
178 /***
179 * Translate point to center and zoom in (or out if alt key pressed).
180 */
181 public void mouseButton1Clicked(RecordPlot plot, MouseEvent event) {
182
183 int w2 = plot.getWidth()/2;
184 int h2 = plot.getHeight()/2;
185 int du = event.getX()-w2;
186 int dv = event.getY()-h2;
187
188 WiredCompoundEdit edit = new WiredCompoundEdit(name);
189
190 if (event.isAltDown()) {
191 Shape shape = new Rectangle(0, 0, 2*w2, 2*h2);
192
193
194 Scale scale = new Scale(1/fixedScale, 1/fixedScale, 1/fixedScale, shape, 5);
195 shape = scale.createTransformedShape((Component)plot, shape);
196 edit.addEdit(scale);
197
198
199 Translateable translateable = (Translateable)plot.getGraphicsPanel().getFeature(Translateable.class);
200 double t[] = translateable.getModelTranslation(new double[] { du*fixedScale, -dv*fixedScale, 0 }, plot.getGraphicsPanel().getViewPort());
201 edit.addEdit(new Translate(t[0], t[1], t[2], shape, 5));
202 } else {
203 int ws2 = (int)(w2/fixedScale);
204 int hs2 = (int)(h2/fixedScale);
205 Shape shape = new Rectangle(event.getX()-ws2, event.getY()-hs2, 2*ws2, 2*hs2);
206
207
208 Translateable translateable = (Translateable)plot.getGraphicsPanel().getFeature(Translateable.class);
209 double t[] = translateable.getModelTranslation(new double[] { -du, dv, 0 }, plot.getGraphicsPanel().getViewPort());
210 Translate translate = new Translate(t[0], t[1], t[2], shape, 5);
211 shape = translate.createTransformedShape((Component)plot, shape);
212 edit.addEdit(translate);
213
214
215 edit.addEdit(new Scale(fixedScale, fixedScale, fixedScale, shape, 5));
216 }
217 edit.end();
218 plot.postEdit(edit);
219 }
220
221 public String toString() {
222 return "Drag rectangle to Scale";
223 }
224 }