source: trunk/src/org/apollo/ApolloGestureActions.java@ 1415

Last change on this file since 1415 was 1415, checked in by bln4, 5 years ago

Renamed Frame.getItems() to Frame.getSortedItems() to better represent its functionality.

-> org.apollo.ApolloGestureActions
-> org.apollo.ApolloSystem
-> org.expeditee.actions.Actions
-> org.expeditee.actions.Debug
-> org.expeditee.actions.ExploratorySearchActions
-> org.expeditee.actions.JfxBrowserActions
-> org.expeditee.actions.Misc
-> org.expeditee.actions.Navigation
-> org.expeditee.actions.ScriptBase
-> org.expeditee.actions.Simple
-> org.expeditee.agents.ComputeTree
-> org.expeditee.agents.CopyTree
-> org.expeditee.agents.DisplayComet
-> org.expeditee.agents.DisplayTree
-> org.expeditee.agents.DisplayTreeLeaves
-> org.expeditee.agents.GraphFramesetLinks
-> org.expeditee.agents.TreeProcessor
-> org.expeditee.gio.gesture.StandardGestureActions
-> org.expeditee.gui.DisplayController
-> org.expeditee.gui.FrameCreator
-> org.expeditee.gui.FrameIO
-> org.expeditee.io.DefaultTreeWriter
-> org.expeditee.io.JavaWriter
-> org.expeditee.io.PDF2Writer
-> org.expeditee.io.TXTWriter
-> org.expeditee.io.WebParser
-> org.expeditee.io.flowlayout.XGroupItem
-> org.expeditee.items.Dot
-> org.expeditee.items.Item
-> org.expeditee.items.ItemUtils
-> org.expeditee.network.FrameShare
-> org.expeditee.stats.TreeStats


Created ItemsList class to wrap ArrayList<Item>. Frames now use this new class to store its body list (used for display) as well as its primaryBody and surrogateBody.

-> org.expeditee.agents.Format
-> org.expeditee.agents.HFormat
-> org.expeditee.gio.gesture.StandardGestureActions
-> org.expeditee.gui.Frame
-> org.expeditee.gui.FrameUtils


Refactorted Frame.setResort(bool) to Frame.invalidateSorted() to better function how it is intended to with a more accurate name.

-> org.expeditee.agents.Sort


When writing out .exp files and getting attributes to respond to LEFT + RIGHT click, boolean items are by default true. This has always been the case. An ammendment to this is that defaults can now be established.
Also added 'EnterClick' functionality. If cursored over a item with this property and you press enter, it acts as if you have clicked on it instead.

-> org.expeditee.assets.resources-public.framesets.authentication.1.exp to 6.exp
-> org.expeditee.gio.gesture.StandardGestureActions
-> org.expeditee.gio.input.KBMInputEvent
-> org.expeditee.gio.javafx.JavaFXConversions
-> org.expeditee.gio.swing.SwingConversions
-> org.expeditee.gui.AttributeUtils
-> org.expeditee.io.Conversion
-> org.expeditee.io.DefaultFrameWriter
-> org.expeditee.items.Item


Fixed a bug caused by calling Math.abs on Integer.MIN_VALUE returning unexpected result. Due to zero being a thing, you cannot represent Math.abs(Integer.MIN_VALUE) in a Integer object. The solution is to use Integer.MIN_VALUE + 1 instead of Integer.MIN_VALUE.

-> org.expeditee.core.bounds.CombinationBounds
-> org.expeditee.io.flowlayout.DimensionExtent


Recoded the contains function in EllipticalBounds so that intersection tests containing circles work correctly.

-> org.expeditee.core.bounds.EllipticalBounds


Added toString() to PolygonBounds to allow for useful printing during debugging.

-> org.expeditee.core.bounds.PolygonBounds

Implemented Surrogate Mode!

-> org.expeditee.encryption.io.EncryptedExpReader
-> org.expeditee.encryption.io.EncryptedExpWriter
-> org.expeditee.encryption.items.surrogates.EncryptionDetail
-> org.expeditee.encryption.items.surrogates.Label
-> org.expeditee.gui.FrameUtils
-> org.expeditee.gui.ItemsList
-> org.expeditee.items.Item
-> org.expeditee.items.Text


???? Use Integer.MAX_VALUE cast to a float instead of Float.MAX_VALUE. This fixed some bug which I cannot remember.

-> org.expeditee.gio.TextLayoutManager
-> org.expeditee.gio.swing.SwingTextLayoutManager


Improved solution for dealing with the F10 key taking focus away from Expeditee due to it being a assessibility key.

-> org.expeditee.gio.swing.SwingInputManager


Renamed variable visibleItems in FrameGraphics.paintFrame to itemsToPaintCanditates to better represent functional intent.

-> org.expeditee.gui.FrameGraphics


Improved checking for if personal resources exist before recreating them

-> org.expeditee.gui.FrameIO


Repeated messages to message bay now have a visual feedback instead of just a beep. This visual feedback is in the form of a count of the amount of times it has repeated.

-> org.expeditee.gui.MessageBay


Updated comment on the Vector class to explain what vectors are.

-> org.expeditee.gui.Vector


Added constants to represent all of the property keys in DefaultFrameReader and DefaultFrameWriter.

-> org.expeditee.io.DefaultFrameReader
-> org.expeditee.io.DefaultFrameWriter


Updated the KeyList setting to be more heirarcial with how users will store their Secrets.

-> org.expeditee.settings.identity.secrets.KeyList

File size: 22.0 KB
Line 
1package org.apollo;
2
3import java.util.Collection;
4import java.util.HashMap;
5import java.util.LinkedHashSet;
6import java.util.LinkedList;
7import java.util.List;
8import java.util.Map;
9
10import org.apollo.gio.gesture.data.TrackAdjustmentGestureData;
11import org.apollo.util.Mutable;
12import org.apollo.widgets.LinkedTrack;
13import org.apollo.widgets.SampledTrack;
14import org.apollo.widgets.TrackWidgetCommons;
15import org.expeditee.core.Dimension;
16import org.expeditee.core.Point;
17import org.expeditee.gio.EcosystemManager;
18import org.expeditee.gio.gesture.Gesture;
19import org.expeditee.gio.gesture.Gesture.GestureType;
20import org.expeditee.gio.gesture.GestureAction;
21import org.expeditee.gio.gesture.GestureListener;
22import org.expeditee.gio.gesture.StandardGestureActions;
23import org.expeditee.gio.gesture.StandardGestureActions.StandardGestureType;
24import org.expeditee.gio.gesture.data.ItemSpecificGestureData;
25import org.expeditee.gio.gesture.data.PickUpGestureData;
26import org.expeditee.gio.input.KBMInputEvent.Key;
27import org.expeditee.gio.input.StandardInputEventListeners;
28import org.expeditee.gui.DisplayController;
29import org.expeditee.gui.Frame;
30import org.expeditee.gui.FrameIO;
31import org.expeditee.gui.FreeItems;
32import org.expeditee.items.Dot;
33import org.expeditee.items.Item;
34import org.expeditee.items.Item.HighlightMode;
35import org.expeditee.items.ItemUtils;
36import org.expeditee.items.Line;
37import org.expeditee.items.Text;
38import org.expeditee.items.UserAppliedPermission;
39import org.expeditee.items.widgets.InteractiveWidgetInitialisationFailedException;
40import org.expeditee.items.widgets.InteractiveWidgetNotAvailableException;
41import org.expeditee.items.widgets.Widget;
42import org.expeditee.items.widgets.WidgetCorner;
43import org.expeditee.items.widgets.WidgetEdge;
44
45public class ApolloGestureActions implements GestureListener {
46 //@formatter:off
47 public enum ApolloGestureType {
48 ADJUST_INITIATION_TIME,
49 ADJUST_VERTICAL_POSITION,
50 CREATE_LINKED_TRACKS,
51 MODULUS_POSITION, // TODO: Think of a better name. cts16
52 TOGGLE_QUALITY_GRAPHICS
53 }
54 //@formatter:on
55
56 private static ApolloGestureActions _instance = null;
57
58 public static ApolloGestureActions getInstance() {
59 if (_instance == null) {
60 _instance = new ApolloGestureActions();
61 }
62
63 return _instance;
64 }
65
66 private HashMap<ApolloGestureType, GestureType> _gestureTypes;
67
68 private HashMap<GestureType, GestureAction> _actions;
69
70 private ApolloGestureActions() {
71 _gestureTypes = new HashMap<ApolloGestureType, GestureType>();
72 initialiseGestureTypes();
73 _actions = new HashMap<GestureType, GestureAction>();
74 initialiseActions();
75 }
76
77 @Override
78 public void preGesture(final Gesture gesture) {
79 final GestureAction action = getGestureAction(gesture.getType());
80 if (action == null) {
81 return;
82 }
83 action.prepare(gesture);
84 }
85
86 @Override
87 public void onGesture(final Gesture gesture) {
88 final GestureAction action = getGestureAction(gesture.getType());
89 if (action == null) {
90 return;
91 }
92 action.exec(gesture);
93 }
94
95 @Override
96 public void postGesture(final Gesture gesture) {
97 final GestureAction action = getGestureAction(gesture.getType());
98 if (action == null) {
99 return;
100 }
101 action.finalise(gesture);
102 }
103
104 private void setGestureAction(GestureType type, GestureAction action) {
105 if (type == null) {
106 return;
107 }
108
109 _actions.put(type, action);
110 }
111
112 private GestureAction getGestureAction(GestureType type) {
113 if (type == null) {
114 return null;
115 }
116
117 return _actions.get(type);
118 }
119
120 private void initialiseActions() {
121 // Set the ADJUST_INITIATION_TIME action
122 setGestureAction(gestureType(ApolloGestureType.ADJUST_INITIATION_TIME), new GestureAction() {
123 @Override
124 public void exec(Gesture gesture) {
125 TrackAdjustmentGestureData data = (TrackAdjustmentGestureData) gesture.getData();
126
127 Widget selectedIW = null;
128
129 if (data.getCurrentItem() != null) {
130 if (data.getCurrentItem() instanceof WidgetEdge) {
131 selectedIW = ((WidgetEdge) data.getCurrentItem()).getWidgetSource();
132 } else if (data.getCurrentItem() instanceof WidgetCorner) {
133 selectedIW = ((WidgetCorner) data.getCurrentItem()).getWidgetSource();
134 }
135 }
136
137 if (selectedIW != null) {
138 adjustInitiationTime(selectedIW, data.getAdjustment());
139 }
140 }
141 });
142
143 // Set the ADJUST_VERTICAL_POSITION action
144 setGestureAction(gestureType(ApolloGestureType.ADJUST_VERTICAL_POSITION), new GestureAction() {
145 @Override
146 public void exec(Gesture gesture) {
147 TrackAdjustmentGestureData data = (TrackAdjustmentGestureData) gesture.getData();
148
149 Widget selectedIW = null;
150
151 if (data.getCurrentItem() != null) {
152 if (data.getCurrentItem() instanceof WidgetEdge) {
153 selectedIW = ((WidgetEdge) data.getCurrentItem()).getWidgetSource();
154 } else if (data.getCurrentItem() instanceof WidgetCorner) {
155 selectedIW = ((WidgetCorner) data.getCurrentItem()).getWidgetSource();
156 }
157 }
158
159 if (selectedIW != null) {
160 adjustVerticalPosition(selectedIW, data.getAdjustment());
161 }
162 }
163 });
164
165 // Set the CREATE_LINKED_TRACKS action
166 setGestureAction(gestureType(ApolloGestureType.CREATE_LINKED_TRACKS), new GestureAction() {
167 @Override
168 public void exec(Gesture gesture) {
169 ItemSpecificGestureData data = (ItemSpecificGestureData) gesture.getData();
170
171 createLinkedTracks(data.getCurrentItem(), data.getCurrentItems());
172 }
173 });
174
175 // Set the MOD_POSITION action
176 setGestureAction(gestureType(ApolloGestureType.MODULUS_POSITION), new GestureAction() {
177 @Override
178 public void exec(Gesture gesture) {
179 Frame current = DisplayController.getCurrentFrame();
180 Dimension windowSize = EcosystemManager.getGraphicsManager().getWindowSize();
181
182 for (Item i : current.getSortedItems()) {
183 Point pos = i.getPosition();
184 pos.setX(pos.getX() % windowSize.width);
185 pos.setY(pos.getY() % windowSize.height);
186 i.setPosition(pos);
187 }
188 }
189 });
190
191 // Set the TOGGLE_QUALITY_GRAPHICS action
192 setGestureAction(gestureType(ApolloGestureType.TOGGLE_QUALITY_GRAPHICS), new GestureAction() {
193 @Override
194 public void exec(Gesture gesture) {
195 ApolloSystem.useQualityGraphics = !ApolloSystem.useQualityGraphics;
196 }
197 });
198
199 // Set the MOVE_CURSOR action
200 setGestureAction(StandardGestureActions.getInstance().gestureType(StandardGestureType.MOVE_CURSOR),
201 new GestureAction() {
202 @Override
203 public void exec(Gesture gesture) {
204 mouseMoved(gesture.getData().getPosition());
205 }
206 });
207
208 // Set the PLACE action
209 setGestureAction(StandardGestureActions.getInstance().gestureType(StandardGestureType.PLACE),
210 new GestureAction() {
211
212 final List<SampledTrack> sampledTracks = new LinkedList<SampledTrack>();
213
214 @Override
215 public void prepare(final Gesture gesture) {
216 final FreeItems freeItems = FreeItems.getInstance();
217 List<Widget> widgets = null;
218 if (freeItems != null && !freeItems.isEmpty()) {
219 widgets = ItemUtils.extractWidgets(freeItems);
220 }
221 widgets.forEach(w -> {
222 if (w instanceof SampledTrack) {
223 final SampledTrack st = (SampledTrack) w;
224 st.setIgnoreInjection(true);
225 sampledTracks.add(st);
226 }
227 });
228 }
229
230 @Override
231 public void exec(final Gesture gesture) {
232 final PickUpGestureData data = (PickUpGestureData) gesture.getData();
233 final List<Item> widgetPieces = new LinkedList<Item>();
234 if (data.getCopy()) {
235 sampledTracks.forEach(st -> {
236 st.getItems().forEach(i -> {
237 StandardGestureActions.anchor(i);
238 widgetPieces.add(i);
239 });
240 });
241 FreeItems.getInstance().clear();
242 anchorTracks(widgetPieces);
243 final List<Item> toPickup = new LinkedList<Item>();
244 sampledTracks.forEach(st -> {
245 try {
246 final Widget copy = st.copy();
247 toPickup.addAll(copy.getItems());
248 } catch (InteractiveWidgetNotAvailableException e) {
249 e.printStackTrace();
250 } catch (InteractiveWidgetInitialisationFailedException e) {
251 e.printStackTrace();
252 }
253 });
254 StandardGestureActions.pickup(toPickup);
255 } else {
256 anchorTracks(FreeItems.getInstance());
257 }
258 }
259
260 @Override
261 public void finalise(final Gesture gesture) {
262 sampledTracks.forEach(st -> st.setIgnoreInjection(false));
263 sampledTracks.clear();
264 }
265 });
266 }
267
268 /** Initialises the set of gesture types. */
269 private void initialiseGestureTypes() {
270 for (ApolloGestureType type : ApolloGestureType.values()) {
271 GestureType gestureType;
272 if ((gestureType = GestureType.register(type.toString())) == null) {
273 gestureType = GestureType.get(type.toString());
274 }
275 _gestureTypes.put(type, gestureType);
276 }
277 }
278
279 /** Gets the gesture type associated with the given standard type. */
280 public GestureType gestureType(ApolloGestureType type) {
281 if (type == null) {
282 return null;
283 }
284
285 return _gestureTypes.get(type);
286 }
287
288 /*
289 * TODO: EVERYTHING BELOW HERE IS ONLY TEMPORARILY SITUATED IN THIS CLASS
290 *
291 * The following methods were mostly copy-pasted here from the old
292 * ApolloFrameKeyboardActions and ApolloFrameMouseActions classes (to enable
293 * quick change-over to the new input system). Really they should be relocated
294 * to more suitable homes based on their function.
295 */
296
297 public static void adjustInitiationTime(Widget track, long adjustment) {
298 if (track instanceof SampledTrack) {
299 adjustInitiationTime((SampledTrack) track, adjustment);
300 } else if (track instanceof LinkedTrack) {
301 adjustInitiationTime((LinkedTrack) track, adjustment);
302 }
303 }
304
305 public static void adjustInitiationTime(SampledTrack track, long adjustment) {
306 Mutable.Long oldIt = track.getInitiationTimeFromMeta();
307 if (oldIt == null) {
308 oldIt = Mutable.createMutableLong(0);
309 }
310 track.setInitiationTime(oldIt.value + adjustment);
311 }
312
313 public static void adjustInitiationTime(LinkedTrack track, long adjustment) {
314 Mutable.Long oldIt = track.getInitiationTimeFromMeta();
315 if (oldIt == null) {
316 oldIt = Mutable.createMutableLong(0);
317 }
318 track.setInitiationTime(oldIt.value + adjustment);
319 }
320
321 public static void adjustVerticalPosition(Widget track, long adjustment) {
322 if (track instanceof SampledTrack) {
323 adjustVerticalPosition((SampledTrack) track, adjustment);
324 } else if (track instanceof LinkedTrack) {
325 adjustVerticalPosition((LinkedTrack) track, adjustment);
326 }
327 }
328
329 public static void adjustVerticalPosition(SampledTrack track, long adjustment) {
330 track.setYPosition(track.getY() + (int) adjustment);
331 }
332
333 public static void adjustVerticalPosition(LinkedTrack track, long adjustment) {
334 track.setYPosition(track.getY() + (int) adjustment);
335 }
336
337 public static void createLinkedTracks(Item currentItem, Collection<Item> enclosedItems) {
338 if (currentItem == null) {
339
340 if (enclosedItems != null) {
341
342 Frame current = DisplayController.getCurrentFrame();
343
344 Collection<Item> toRemove = new LinkedHashSet<Item>(enclosedItems.size());
345 LinkedList<LinkedTrack> enclosedLinkedTracks = new LinkedList<LinkedTrack>();
346 LinkedList<SampledTrack> enclosedTracks = new LinkedList<SampledTrack>();
347
348 // Get enclosing shape and enclosed tracks
349 for (Item ip : enclosedItems) {
350 if (ip.getParent() != current) {
351 continue;
352 }
353
354 if (ip.hasPermission(UserAppliedPermission.full)) {
355 // Only include lines if one of their enpoints are also being removed
356 if (ip instanceof Line) {
357 Line l = (Line) ip;
358 Item end = l.getEndItem();
359 Item start = l.getStartItem();
360
361 // If one end of a line is being delted, remove the
362 // other end if all its connecting lines are being
363 // delted
364 if (enclosedItems.contains(end)) {
365 if (!enclosedItems.contains(start) && enclosedItems.containsAll(start.getLines())) {
366 toRemove.add(start);
367 }
368 } else if (enclosedItems.contains(start)) {
369 if (enclosedItems.containsAll(end.getLines())) {
370 toRemove.add(end);
371 }
372 } else {
373 continue;
374 }
375 } else if (ip instanceof WidgetCorner) {
376 Widget iw = ((WidgetCorner) ip).getWidgetSource();
377 if (!enclosedTracks.contains(iw) && iw instanceof SampledTrack) {
378 enclosedTracks.add((SampledTrack) iw);
379 } else if (!enclosedLinkedTracks.contains(iw) && iw instanceof LinkedTrack) {
380 enclosedLinkedTracks.add((LinkedTrack) iw);
381 }
382 } else {
383 if ((ip instanceof Line || ip instanceof Dot)
384 && ip.getHighlightMode() == HighlightMode.Enclosed) {
385 toRemove.add(ip);
386 toRemove.addAll(ip.getConnected());
387 }
388 }
389
390 }
391 } // End searching enclosed items
392
393 // If there was some enclosed tracks
394 if (current != null && !toRemove.isEmpty()
395 && (!enclosedLinkedTracks.isEmpty() || !enclosedTracks.isEmpty())) {
396
397 // Remove enclosure
398 current.removeAllItems(toRemove);
399
400 // Determine initiation time of group
401 Mutable.Long initTime = null;
402 Point initiatePosition = null;
403
404 for (SampledTrack st : enclosedTracks) {
405
406 if (initTime == null) {
407 initTime = st.getInitiationTimeFromMeta();
408 initiatePosition = st.getPosition();
409 } else if (st.getInitiationTimeFromMeta() != null
410 && st.getInitiationTimeFromMeta().value < initTime.value) {
411 initTime = st.getInitiationTimeFromMeta();
412 initiatePosition = st.getPosition();
413 }
414 }
415 for (LinkedTrack lt : enclosedLinkedTracks) {
416
417 if (initTime == null) {
418 initTime = lt.getInitiationTimeFromMeta();
419 initiatePosition = lt.getPosition();
420 } else if (lt.getInitiationTimeFromMeta() != null
421 && lt.getInitiationTimeFromMeta().value < initTime.value) {
422 initTime = lt.getInitiationTimeFromMeta();
423 initiatePosition = lt.getPosition();
424 }
425 }
426
427 assert (initTime != null);
428 assert (initiatePosition != null);
429
430 // Creat the link to contain all tracks
431 String name = current.getTitle();
432 if (name == null) {
433 name = "Unnamed";
434 }
435 name += " group";
436
437 Text linkSource = new Text(current.getNextItemID());
438 linkSource.addToData(TrackWidgetCommons.META_NAME_TAG + name);
439 linkSource.addToData(TrackWidgetCommons.META_INITIATIONTIME_TAG + initTime);
440 linkSource.setPosition(initiatePosition);
441 linkSource.setParent(current);
442 LinkedTrack linkedVersion = new LinkedTrack(linkSource, null);
443
444 // Create a new frame to hold the track group
445 Frame newFrame = FrameIO.CreateNewFrame(linkedVersion.getItems().get(0));
446
447 for (SampledTrack st : enclosedTracks) {
448 st.saveAudio(); // Blocking
449 current.removeAllItems(st.getItems());
450 newFrame.addAllItems(st.getItems());
451 }
452
453 for (LinkedTrack lt : enclosedLinkedTracks) {
454 current.removeAllItems(lt.getItems());
455 newFrame.addAllItems(lt.getItems());
456 }
457
458 FrameIO.SaveFrame(newFrame);
459
460 // Link the linked tracks
461 linkedVersion.setLink(newFrame.getName(), null);
462
463 // Add the new link
464 current.addAllItems(linkedVersion.getItems());
465
466 // Ensure initiation time is retained to the exact frame... avoiding loss due to
467 // resolution
468 linkedVersion.setInitiationTime(initTime.value);
469 }
470 }
471 }
472 }
473
474 /**
475 * The minimum distance from a track widget to auto-align free space items to.
476 */
477 private static final int COARSE_X_PLACEMENT_TOLERANCE = 80;
478
479 private static final int COARSE_Y_PLACEMENT_TOLERANCE = 20;
480
481 public void mouseMoved(Point to) {
482 boolean forwareToExpeditee = true;
483
484 if (isYAxisRestictionOn() && !FreeItems.getInstance().isEmpty()) {
485
486 // Restrict movement of free items to Y-Axis only
487 forwareToExpeditee = false;
488
489 int smallestY = FreeItems.getInstance().get(0).getY();
490
491 for (Item i : FreeItems.getInstance()) {
492 if (i.getY() < smallestY) {
493 smallestY = i.getY();
494 }
495 }
496
497 for (Item i : FreeItems.getInstance()) {
498 i.setY(to.getY() + (i.getY() - smallestY));
499 }
500
501 } else if (isSnapOn() && !FreeItems.getInstance().isEmpty()) {
502
503 // Couse movement of free items: Restraining left-most pixel in items
504 // to the closest anchored track widgets x position.
505
506 Frame currentFrame = DisplayController.getCurrentFrame();
507 if (currentFrame != null) {
508
509 // Search all anchored track x positions for the current frame
510 List<Widget> widgets = currentFrame.getInteractiveWidgets();
511
512 int closestXPosition = -1;
513 int closestYPosition = -1;
514 int closestXDistance = -1;
515 int closestYDistance = -1;
516
517 for (Widget iw : widgets) {
518
519 if (iw instanceof SampledTrack || iw instanceof LinkedTrack) {
520
521 // Determine TOP-LEFT Snapping
522 int xDistance = Math.abs(to.getX() - iw.getX());
523 if (closestXDistance < 0 || xDistance < closestXDistance) {
524 closestXDistance = xDistance;
525 closestXPosition = iw.getX();
526 }
527
528 int yDistance = Math.abs(to.getY() - iw.getY());
529 if (closestYDistance < 0 || yDistance < closestYDistance) {
530 closestYDistance = yDistance;
531 closestYPosition = iw.getY();
532 }
533
534 // Determine BOTTOM-RIGHT Snapping
535 xDistance = Math.abs(to.getX() - (iw.getX() + iw.getWidth()));
536 if (closestXDistance < 0 || xDistance < closestXDistance) {
537 closestXDistance = xDistance;
538 closestXPosition = iw.getX() + iw.getWidth();
539 }
540
541 yDistance = Math.abs(to.getY() - (iw.getY() + iw.getHeight()));
542 if (closestYDistance < 0 || yDistance < closestYDistance) {
543 closestYDistance = yDistance;
544 closestYPosition = iw.getY() + iw.getHeight();
545 }
546 }
547
548 }
549
550 // Determine top-left position of free items
551 int smallestX = FreeItems.getInstance().get(0).getX();
552 int smallestY = FreeItems.getInstance().get(0).getY();
553 for (Item i : FreeItems.getInstance()) {
554 if (i.getX() < smallestX) {
555 smallestX = i.getX();
556 }
557 if (i.getY() < smallestY) {
558 smallestY = i.getY();
559 }
560 }
561
562 for (Item i : FreeItems.getInstance()) {
563
564 int x;
565 int y;
566
567 if (closestXDistance > 0 && closestXDistance < COARSE_X_PLACEMENT_TOLERANCE) {
568 x = closestXPosition + (i.getX() - smallestX);
569 } else {
570 x = to.getX() + (i.getX() - smallestX);
571 }
572
573 if (closestYDistance > 0 && closestYDistance < COARSE_Y_PLACEMENT_TOLERANCE) {
574 y = closestYPosition + (i.getY() - smallestY);
575 } else {
576 y = to.getY() + (i.getY() - smallestY);
577 }
578
579 i.setPosition(x, y);
580
581 }
582
583 forwareToExpeditee = false;
584
585 }
586
587 }
588
589 // Expeditees frame mouse actions uses an offset and fights over free-item
590 // movement if it listens to the mouse event router... therefore add an extra
591 // layer to avoid this... otherwise auto-aligned items jitter like crazy while
592 // moving the cursus
593 // if (forwareToExpeditee) {
594 // FrameMouseActions.getInstance().mouseMoved(e);
595 // } else {
596 // FrameGraphics.refresh(true);
597 // }
598 }
599
600 /**
601 * @return True if the user is restricting movement on the y-axis only
602 */
603 public static boolean isYAxisRestictionOn() {
604 return StandardInputEventListeners.kbmStateListener.isKeyDown(Key.CTRL)
605 && !StandardInputEventListeners.kbmStateListener.isKeyDown(Key.SHIFT);
606 }
607
608 public static boolean isSnapOn() {
609 return StandardInputEventListeners.kbmStateListener.isKeyDown(Key.SHIFT)
610 && !StandardInputEventListeners.kbmStateListener.isKeyDown(Key.CTRL);
611 }
612
613 private void anchorTracks(final List<Item> widgetPieces) {
614
615 // Widget -> delta IT time
616 Map<LinkedTrack, Mutable.Long> anchoredLinkedTracks = null;
617 Map<SampledTrack, Mutable.Long> anchoredTracks = null;
618
619// if (FreeItems.getInstance().size() > 1) {
620 if (widgetPieces.size() > 1) {
621// List<Widget> anchoringWidgets = ItemUtils.extractWidgets(FreeItems.getInstance());
622 List<Widget> anchoringWidgets = ItemUtils.extractWidgets(widgetPieces);
623
624 Mutable.Long firstInitTime = null;
625 anchoredLinkedTracks = new HashMap<LinkedTrack, Mutable.Long>();
626 anchoredTracks = new HashMap<SampledTrack, Mutable.Long>();
627
628 for (Widget iw : anchoringWidgets) {
629
630 Mutable.Long it = null;
631
632 if (iw instanceof LinkedTrack) {
633
634 LinkedTrack lt = (LinkedTrack) iw;
635 it = lt.getInitiationTimeFromMeta();
636 if (it == null) {
637 it = Mutable.createMutableLong(0);
638 }
639
640 anchoredLinkedTracks.put(lt, it);
641
642 } else if (iw instanceof SampledTrack) {
643
644 SampledTrack st = (SampledTrack) iw;
645 it = st.getInitiationTimeFromMeta();
646 if (it == null) {
647 it = Mutable.createMutableLong(0);
648 }
649
650 anchoredTracks.put(st, it);
651
652 } else {
653 continue;
654 }
655
656 if (firstInitTime == null) {
657 firstInitTime = Mutable.createMutableLong(it.value); // Important to create new instance
658 } else if (it.value < firstInitTime.value) {
659 firstInitTime = Mutable.createMutableLong(it.value); // Important to create new instance
660 }
661 }
662
663 // Should do a accurate anchor with init times properly aligned?
664 if ((anchoredLinkedTracks.size() + anchoredTracks.size()) > 1) {
665
666 assert (firstInitTime != null);
667
668 // Then calc all the deltas
669 for (LinkedTrack lt : anchoredLinkedTracks.keySet()) {
670 Mutable.Long it = anchoredLinkedTracks.get(lt);
671 it.value -= firstInitTime.value;
672 }
673
674 for (SampledTrack st : anchoredTracks.keySet()) {
675 Mutable.Long it = anchoredTracks.get(st);
676 it.value -= firstInitTime.value;
677 }
678
679 } else {
680 anchoredLinkedTracks = null;
681 anchoredTracks = null;
682 }
683
684 }
685
686 // If anchored a group of tracks .. adjust initiation times to
687 if (anchoredLinkedTracks != null) {
688
689 Mutable.Long firstInitTime = null;
690
691 for (LinkedTrack lt : anchoredLinkedTracks.keySet()) {
692 Mutable.Long it = anchoredLinkedTracks.get(lt);
693 if (it.value == 0) {
694 firstInitTime = lt.getInitiationTimeFromMeta();
695 break;
696 }
697 }
698 if (firstInitTime == null) {
699 for (SampledTrack st : anchoredTracks.keySet()) {
700 Mutable.Long it = anchoredTracks.get(st);
701 if (it.value == 0) {
702 firstInitTime = st.getInitiationTimeFromMeta();
703 break;
704 }
705 }
706 }
707 assert (firstInitTime != null);
708
709 for (LinkedTrack lt : anchoredLinkedTracks.keySet()) {
710 Mutable.Long it = anchoredLinkedTracks.get(lt);
711 if (it.value == 0) {
712 continue;
713 }
714 lt.setInitiationTime(firstInitTime.value + it.value);
715 }
716
717 for (SampledTrack st : anchoredTracks.keySet()) {
718 Mutable.Long it = anchoredTracks.get(st);
719 if (it.value == 0) {
720 continue;
721 }
722 st.setInitiationTime(firstInitTime.value + it.value);
723 }
724
725 }
726 }
727}
Note: See TracBrowser for help on using the repository browser.