Commit | Line | Data |
---|---|---|
739b9fec AM |
1 | package org.eclipse.tracecompass.internal.provisional.tmf.ui.views.timegraph2.swtjfx.examples; |
2 | ||
3 | import java.util.Arrays; | |
4 | import java.util.HashSet; | |
5 | import java.util.Random; | |
6 | import java.util.Set; | |
7 | ||
8 | import org.eclipse.jdt.annotation.Nullable; | |
9 | ||
10 | import javafx.application.Application; | |
11 | import javafx.event.EventHandler; | |
12 | import javafx.scene.Node; | |
13 | import javafx.scene.Scene; | |
14 | import javafx.scene.control.Label; | |
15 | import javafx.scene.image.Image; | |
16 | import javafx.scene.image.ImageView; | |
17 | import javafx.scene.input.MouseEvent; | |
18 | import javafx.scene.layout.Pane; | |
19 | import javafx.scene.layout.Region; | |
20 | import javafx.scene.paint.Color; | |
21 | import javafx.scene.shape.Rectangle; | |
22 | import javafx.scene.shape.StrokeLineCap; | |
23 | import javafx.stage.Stage; | |
24 | ||
25 | public class ExampleMouseDrag2 extends Application { | |
26 | ||
27 | // public static Image image = new Image("http://upload.wikimedia.org/wikipedia/commons/thumb/4/41/Siberischer_tiger_de_edit02.jpg/320px-Siberischer_tiger_de_edit02.jpg"); | |
28 | public Image image = new Image("file:///home/alexandre/Desktop/tiger.jpg"); | |
29 | // public Image image = new Image( getClass().getResource( "/home/alexandre/Desktop/tiger.jpg").toExternalForm()); | |
30 | ||
31 | SelectionModel selectionModel = new SelectionModel(); | |
32 | ||
33 | DragMouseGestures dragMouseGestures = new DragMouseGestures(); | |
34 | ||
35 | static Random rnd = new Random(); | |
36 | ||
37 | @Override | |
38 | public void start(@Nullable Stage primaryStage) { | |
39 | if (primaryStage == null) { | |
40 | return; | |
41 | } | |
42 | ||
43 | Pane pane = new Pane(); | |
44 | pane.setStyle("-fx-background-color:white"); | |
45 | ||
46 | new RubberBandSelection( pane); | |
47 | ||
48 | double width = 200; | |
49 | double height = 160; | |
50 | ||
51 | double padding = 20; | |
52 | for( int row=0; row < 4; row++) { | |
53 | for( int col=0; col < 4; col++) { | |
54 | ||
55 | Selectable selectable = new Selectable( width, height); | |
56 | selectable.relocate( padding * (col+1) + width * col, padding * (row + 1) + height * row); | |
57 | ||
58 | pane.getChildren().add(selectable); | |
59 | ||
60 | dragMouseGestures.makeDraggable(selectable); | |
61 | ||
62 | } | |
63 | } | |
64 | ||
65 | Label infoLabel = new Label( "Drag on scene for Rubberband Selection. Shift+Click to add to selection, CTRL+Click to toggle selection. Drag selected nodes for multi-dragging."); | |
66 | pane.getChildren().add( infoLabel); | |
67 | ||
68 | Scene scene = new Scene( pane, 1600, 900); | |
69 | scene.getStylesheets().add( getClass().getResource("application.css").toExternalForm()); | |
70 | ||
71 | primaryStage.setScene( scene); | |
72 | primaryStage.show(); | |
73 | ||
74 | ||
75 | ||
76 | } | |
77 | ||
78 | private class Selectable extends Region { | |
79 | ||
80 | ImageView view; | |
81 | ||
82 | public Selectable( double width, double height) { | |
83 | ||
84 | view = new ImageView( image); | |
85 | view.setFitWidth(width); | |
86 | view.setFitHeight(height); | |
87 | ||
88 | getChildren().add( view); | |
89 | ||
90 | this.setPrefSize(width, height); | |
91 | } | |
92 | ||
93 | } | |
94 | ||
95 | private class SelectionModel { | |
96 | ||
97 | Set<Node> selection = new HashSet<>(); | |
98 | ||
99 | public void add( Node node) { | |
100 | ||
101 | if( !node.getStyleClass().contains("highlight")) { | |
102 | node.getStyleClass().add( "highlight"); | |
103 | } | |
104 | ||
105 | selection.add( node); | |
106 | } | |
107 | ||
108 | public void remove( Node node) { | |
109 | node.getStyleClass().remove( "highlight"); | |
110 | selection.remove( node); | |
111 | } | |
112 | ||
113 | public void clear() { | |
114 | ||
115 | while( !selection.isEmpty()) { | |
116 | remove( selection.iterator().next()); | |
117 | } | |
118 | ||
119 | } | |
120 | ||
121 | public boolean contains( Node node) { | |
122 | return selection.contains(node); | |
123 | } | |
124 | ||
125 | // public int size() { | |
126 | // return selection.size(); | |
127 | // } | |
128 | ||
129 | public void log() { | |
130 | System.out.println( "Items in model: " + Arrays.asList( selection.toArray())); | |
131 | } | |
132 | ||
133 | } | |
134 | ||
135 | private class DragMouseGestures { | |
136 | ||
137 | final DragContext dragContext = new DragContext(); | |
138 | ||
139 | private boolean enabled = false; | |
140 | ||
141 | public void makeDraggable(final Node node) { | |
142 | ||
143 | node.setOnMousePressed(onMousePressedEventHandler); | |
144 | node.setOnMouseDragged(onMouseDraggedEventHandler); | |
145 | node.setOnMouseReleased(onMouseReleasedEventHandler); | |
146 | ||
147 | } | |
148 | ||
149 | EventHandler<MouseEvent> onMousePressedEventHandler = new EventHandler<MouseEvent>() { | |
150 | ||
151 | @Override | |
152 | public void handle(MouseEvent event) { | |
153 | ||
154 | // don't do anything if the user is in the process of adding to the selection model | |
155 | if( event.isControlDown() || event.isShiftDown()) { | |
156 | return; | |
157 | } | |
158 | ||
159 | Node node = (Node) event.getSource(); | |
160 | ||
161 | dragContext.x = node.getTranslateX() - event.getSceneX(); | |
162 | dragContext.y = node.getTranslateY() - event.getSceneY(); | |
163 | ||
164 | // clear the model if the current node isn't in the selection => new selection | |
165 | if( !selectionModel.contains(node)) { | |
166 | selectionModel.clear(); | |
167 | selectionModel.add( node); | |
168 | } | |
169 | ||
170 | // flag that the mouse released handler should consume the event, so it won't bubble up to the pane which has a rubberband selection mouse released handler | |
171 | enabled = true; | |
172 | ||
173 | // prevent rubberband selection handler | |
174 | event.consume(); | |
175 | } | |
176 | }; | |
177 | ||
178 | EventHandler<MouseEvent> onMouseDraggedEventHandler = new EventHandler<MouseEvent>() { | |
179 | ||
180 | @Override | |
181 | public void handle(MouseEvent event) { | |
182 | ||
183 | if( !enabled) { | |
184 | return; | |
185 | } | |
186 | ||
187 | // all in selection | |
188 | for( Node node: selectionModel.selection) { | |
189 | node.setTranslateX( dragContext.x + event.getSceneX()); | |
190 | node.setTranslateY( dragContext.y + event.getSceneY()); | |
191 | } | |
192 | ||
193 | } | |
194 | }; | |
195 | ||
196 | EventHandler<MouseEvent> onMouseReleasedEventHandler = new EventHandler<MouseEvent>() { | |
197 | ||
198 | @Override | |
199 | public void handle(MouseEvent event) { | |
200 | ||
201 | // prevent rubberband selection handler | |
202 | if( enabled) { | |
203 | ||
204 | // set node's layout position to current position,remove translate coordinates | |
205 | for( Node node: selectionModel.selection) { | |
206 | fixPosition(node); | |
207 | } | |
208 | ||
209 | enabled = false; | |
210 | ||
211 | event.consume(); | |
212 | } | |
213 | } | |
214 | }; | |
215 | ||
216 | /** | |
217 | * Set node's layout position to current position, remove translate coordinates. | |
218 | * @param node | |
219 | */ | |
220 | private void fixPosition( Node node) { | |
221 | ||
222 | double x = node.getTranslateX(); | |
223 | double y = node.getTranslateY(); | |
224 | ||
225 | node.relocate(node.getLayoutX() + x, node.getLayoutY() + y); | |
226 | ||
227 | node.setTranslateX(0); | |
228 | node.setTranslateY(0); | |
229 | ||
230 | } | |
231 | ||
232 | class DragContext { | |
233 | ||
234 | double x; | |
235 | double y; | |
236 | ||
237 | } | |
238 | ||
239 | } | |
240 | ||
241 | private class RubberBandSelection { | |
242 | ||
243 | final DragContext dragContext = new DragContext(); | |
244 | final Rectangle rect; | |
245 | ||
246 | Pane group; | |
247 | boolean enabled = false; | |
248 | ||
249 | public RubberBandSelection( Pane group) { | |
250 | ||
251 | this.group = group; | |
252 | ||
253 | rect = new Rectangle( 0,0,0,0); | |
254 | rect.setStroke(Color.BLUE); | |
255 | rect.setStrokeWidth(1); | |
256 | rect.setStrokeLineCap(StrokeLineCap.ROUND); | |
257 | rect.setFill(Color.LIGHTBLUE.deriveColor(0, 1.2, 1, 0.6)); | |
258 | ||
259 | group.addEventHandler(MouseEvent.MOUSE_PRESSED, onMousePressedEventHandler); | |
260 | group.addEventHandler(MouseEvent.MOUSE_DRAGGED, onMouseDraggedEventHandler); | |
261 | group.addEventHandler(MouseEvent.MOUSE_RELEASED, onMouseReleasedEventHandler); | |
262 | ||
263 | } | |
264 | ||
265 | EventHandler<MouseEvent> onMousePressedEventHandler = new EventHandler<MouseEvent>() { | |
266 | ||
267 | @Override | |
268 | public void handle(MouseEvent event) { | |
269 | ||
270 | // simple flag to prevent multiple handling of this event or we'd get an exception because rect is already on the scene | |
271 | // eg if you drag with left mouse button and while doing that click the right mouse button | |
272 | if( enabled) { | |
273 | return; | |
274 | } | |
275 | ||
276 | dragContext.mouseAnchorX = event.getSceneX(); | |
277 | dragContext.mouseAnchorY = event.getSceneY(); | |
278 | ||
279 | rect.setX(dragContext.mouseAnchorX); | |
280 | rect.setY(dragContext.mouseAnchorY); | |
281 | rect.setWidth(0); | |
282 | rect.setHeight(0); | |
283 | ||
284 | group.getChildren().add( rect); | |
285 | ||
286 | event.consume(); | |
287 | ||
288 | enabled = true; | |
289 | } | |
290 | }; | |
291 | ||
292 | EventHandler<MouseEvent> onMouseReleasedEventHandler = new EventHandler<MouseEvent>() { | |
293 | ||
294 | @Override | |
295 | public void handle(MouseEvent event) { | |
296 | ||
297 | if( !event.isShiftDown() && !event.isControlDown()) { | |
298 | selectionModel.clear(); | |
299 | } | |
300 | ||
301 | for( Node node: group.getChildren()) { | |
302 | ||
303 | if( node instanceof Selectable) { | |
304 | if( node.getBoundsInParent().intersects( rect.getBoundsInParent())) { | |
305 | ||
306 | if( event.isShiftDown()) { | |
307 | ||
308 | selectionModel.add( node); | |
309 | ||
310 | } else if( event.isControlDown()) { | |
311 | ||
312 | if( selectionModel.contains( node)) { | |
313 | selectionModel.remove( node); | |
314 | } else { | |
315 | selectionModel.add( node); | |
316 | } | |
317 | } else { | |
318 | selectionModel.add( node); | |
319 | } | |
320 | ||
321 | } | |
322 | } | |
323 | ||
324 | } | |
325 | ||
326 | selectionModel.log(); | |
327 | ||
328 | rect.setX(0); | |
329 | rect.setY(0); | |
330 | rect.setWidth(0); | |
331 | rect.setHeight(0); | |
332 | ||
333 | group.getChildren().remove( rect); | |
334 | ||
335 | event.consume(); | |
336 | ||
337 | enabled = false; | |
338 | } | |
339 | }; | |
340 | ||
341 | EventHandler<MouseEvent> onMouseDraggedEventHandler = new EventHandler<MouseEvent>() { | |
342 | ||
343 | @Override | |
344 | public void handle(MouseEvent event) { | |
345 | ||
346 | double offsetX = event.getSceneX() - dragContext.mouseAnchorX; | |
347 | double offsetY = event.getSceneY() - dragContext.mouseAnchorY; | |
348 | ||
349 | if( offsetX > 0) { | |
350 | rect.setWidth( offsetX); | |
351 | } else { | |
352 | rect.setX(event.getSceneX()); | |
353 | rect.setWidth(dragContext.mouseAnchorX - rect.getX()); | |
354 | } | |
355 | ||
356 | if( offsetY > 0) { | |
357 | rect.setHeight( offsetY); | |
358 | } else { | |
359 | rect.setY(event.getSceneY()); | |
360 | rect.setHeight(dragContext.mouseAnchorY - rect.getY()); | |
361 | } | |
362 | ||
363 | event.consume(); | |
364 | ||
365 | } | |
366 | }; | |
367 | ||
368 | private final class DragContext { | |
369 | ||
370 | public double mouseAnchorX; | |
371 | public double mouseAnchorY; | |
372 | ||
373 | ||
374 | } | |
375 | } | |
376 | ||
377 | ||
378 | public static void main(String[] args) { | |
379 | launch(args); | |
380 | } | |
381 | ||
382 | } |