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

Last change on this file was 1523, checked in by bnemhaus, 4 years ago

Reimplementing snapping of SampledTracks and LinkedTracks so that it does not interfere with StandardGestureActions.

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