[1098] | 1 | package org.apollo;
|
---|
| 2 |
|
---|
| 3 | import java.util.Collection;
|
---|
| 4 | import java.util.HashMap;
|
---|
| 5 | import java.util.LinkedHashSet;
|
---|
| 6 | import java.util.LinkedList;
|
---|
| 7 | import java.util.List;
|
---|
| 8 | import java.util.Map;
|
---|
| 9 |
|
---|
| 10 | import org.apollo.gio.gesture.data.TrackAdjustmentGestureData;
|
---|
| 11 | import org.apollo.util.Mutable;
|
---|
| 12 | import org.apollo.widgets.LinkedTrack;
|
---|
| 13 | import org.apollo.widgets.SampledTrack;
|
---|
| 14 | import org.apollo.widgets.TrackWidgetCommons;
|
---|
| 15 | import org.expeditee.core.Dimension;
|
---|
| 16 | import org.expeditee.core.Point;
|
---|
| 17 | import org.expeditee.gio.EcosystemManager;
|
---|
| 18 | import org.expeditee.gio.gesture.Gesture;
|
---|
[1155] | 19 | import org.expeditee.gio.gesture.Gesture.GestureType;
|
---|
[1098] | 20 | import org.expeditee.gio.gesture.GestureAction;
|
---|
| 21 | import org.expeditee.gio.gesture.GestureListener;
|
---|
| 22 | import org.expeditee.gio.gesture.StandardGestureActions;
|
---|
| 23 | import org.expeditee.gio.gesture.StandardGestureActions.StandardGestureType;
|
---|
| 24 | import org.expeditee.gio.gesture.data.ItemSpecificGestureData;
|
---|
[1155] | 25 | import org.expeditee.gio.gesture.data.PickUpGestureData;
|
---|
| 26 | import org.expeditee.gio.input.KBMInputEvent.Key;
|
---|
[1098] | 27 | import org.expeditee.gio.input.StandardInputEventListeners;
|
---|
| 28 | import org.expeditee.gui.DisplayController;
|
---|
| 29 | import org.expeditee.gui.Frame;
|
---|
| 30 | import org.expeditee.gui.FrameIO;
|
---|
| 31 | import org.expeditee.gui.FreeItems;
|
---|
| 32 | import org.expeditee.items.Dot;
|
---|
| 33 | import org.expeditee.items.Item;
|
---|
[1155] | 34 | import org.expeditee.items.Item.HighlightMode;
|
---|
[1098] | 35 | import org.expeditee.items.ItemUtils;
|
---|
| 36 | import org.expeditee.items.Line;
|
---|
| 37 | import org.expeditee.items.Text;
|
---|
| 38 | import org.expeditee.items.UserAppliedPermission;
|
---|
[1179] | 39 | import org.expeditee.items.widgets.InteractiveWidgetInitialisationFailedException;
|
---|
| 40 | import org.expeditee.items.widgets.InteractiveWidgetNotAvailableException;
|
---|
[1098] | 41 | import org.expeditee.items.widgets.Widget;
|
---|
| 42 | import org.expeditee.items.widgets.WidgetCorner;
|
---|
| 43 | import org.expeditee.items.widgets.WidgetEdge;
|
---|
| 44 |
|
---|
[1155] | 45 | public class ApolloGestureActions implements GestureListener {
|
---|
[1158] | 46 | //@formatter:off
|
---|
[1155] | 47 | public enum ApolloGestureType {
|
---|
[1158] | 48 | ADJUST_INITIATION_TIME,
|
---|
| 49 | ADJUST_VERTICAL_POSITION,
|
---|
| 50 | CREATE_LINKED_TRACKS,
|
---|
| 51 | MODULUS_POSITION, // TODO: Think of a better name. cts16
|
---|
[1098] | 52 | TOGGLE_QUALITY_GRAPHICS
|
---|
| 53 | }
|
---|
[1158] | 54 | //@formatter:on
|
---|
[1155] | 55 |
|
---|
[1098] | 56 | private static ApolloGestureActions _instance = null;
|
---|
[1155] | 57 |
|
---|
| 58 | public static ApolloGestureActions getInstance() {
|
---|
[1098] | 59 | if (_instance == null) {
|
---|
| 60 | _instance = new ApolloGestureActions();
|
---|
| 61 | }
|
---|
[1155] | 62 |
|
---|
[1098] | 63 | return _instance;
|
---|
| 64 | }
|
---|
[1155] | 65 |
|
---|
[1098] | 66 | private HashMap<ApolloGestureType, GestureType> _gestureTypes;
|
---|
| 67 |
|
---|
| 68 | private HashMap<GestureType, GestureAction> _actions;
|
---|
[1155] | 69 |
|
---|
| 70 | private ApolloGestureActions() {
|
---|
[1098] | 71 | _gestureTypes = new HashMap<ApolloGestureType, GestureType>();
|
---|
| 72 | initialiseGestureTypes();
|
---|
| 73 | _actions = new HashMap<GestureType, GestureAction>();
|
---|
| 74 | initialiseActions();
|
---|
| 75 | }
|
---|
[1155] | 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 | }
|
---|
[1098] | 94 |
|
---|
| 95 | @Override
|
---|
[1155] | 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);
|
---|
[1098] | 102 | }
|
---|
[1155] | 103 |
|
---|
| 104 | private void setGestureAction(GestureType type, GestureAction action) {
|
---|
[1179] | 105 | if (type == null) {
|
---|
[1155] | 106 | return;
|
---|
[1179] | 107 | }
|
---|
[1155] | 108 |
|
---|
[1098] | 109 | _actions.put(type, action);
|
---|
| 110 | }
|
---|
[1155] | 111 |
|
---|
| 112 | private GestureAction getGestureAction(GestureType type) {
|
---|
[1179] | 113 | if (type == null) {
|
---|
[1155] | 114 | return null;
|
---|
[1179] | 115 | }
|
---|
[1155] | 116 |
|
---|
[1098] | 117 | return _actions.get(type);
|
---|
| 118 | }
|
---|
[1155] | 119 |
|
---|
| 120 | private void initialiseActions() {
|
---|
[1098] | 121 | // Set the ADJUST_INITIATION_TIME action
|
---|
[1155] | 122 | setGestureAction(gestureType(ApolloGestureType.ADJUST_INITIATION_TIME), new GestureAction() {
|
---|
[1098] | 123 | @Override
|
---|
[1155] | 124 | public void exec(Gesture gesture) {
|
---|
[1098] | 125 | TrackAdjustmentGestureData data = (TrackAdjustmentGestureData) gesture.getData();
|
---|
[1155] | 126 |
|
---|
[1098] | 127 | Widget selectedIW = null;
|
---|
[1155] | 128 |
|
---|
[1098] | 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 | }
|
---|
[1155] | 136 |
|
---|
[1179] | 137 | if (selectedIW != null) {
|
---|
[1155] | 138 | adjustInitiationTime(selectedIW, data.getAdjustment());
|
---|
[1179] | 139 | }
|
---|
[1098] | 140 | }
|
---|
| 141 | });
|
---|
[1155] | 142 |
|
---|
[1098] | 143 | // Set the ADJUST_VERTICAL_POSITION action
|
---|
[1155] | 144 | setGestureAction(gestureType(ApolloGestureType.ADJUST_VERTICAL_POSITION), new GestureAction() {
|
---|
[1098] | 145 | @Override
|
---|
[1155] | 146 | public void exec(Gesture gesture) {
|
---|
[1098] | 147 | TrackAdjustmentGestureData data = (TrackAdjustmentGestureData) gesture.getData();
|
---|
[1155] | 148 |
|
---|
[1098] | 149 | Widget selectedIW = null;
|
---|
[1155] | 150 |
|
---|
[1098] | 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 | }
|
---|
[1155] | 158 |
|
---|
[1179] | 159 | if (selectedIW != null) {
|
---|
[1155] | 160 | adjustVerticalPosition(selectedIW, data.getAdjustment());
|
---|
[1179] | 161 | }
|
---|
[1098] | 162 | }
|
---|
| 163 | });
|
---|
[1155] | 164 |
|
---|
[1098] | 165 | // Set the CREATE_LINKED_TRACKS action
|
---|
[1155] | 166 | setGestureAction(gestureType(ApolloGestureType.CREATE_LINKED_TRACKS), new GestureAction() {
|
---|
[1098] | 167 | @Override
|
---|
[1155] | 168 | public void exec(Gesture gesture) {
|
---|
[1098] | 169 | ItemSpecificGestureData data = (ItemSpecificGestureData) gesture.getData();
|
---|
[1155] | 170 |
|
---|
[1098] | 171 | createLinkedTracks(data.getCurrentItem(), data.getCurrentItems());
|
---|
| 172 | }
|
---|
| 173 | });
|
---|
[1155] | 174 |
|
---|
[1098] | 175 | // Set the MOD_POSITION action
|
---|
[1155] | 176 | setGestureAction(gestureType(ApolloGestureType.MODULUS_POSITION), new GestureAction() {
|
---|
[1098] | 177 | @Override
|
---|
[1155] | 178 | public void exec(Gesture gesture) {
|
---|
[1098] | 179 | Frame current = DisplayController.getCurrentFrame();
|
---|
| 180 | Dimension windowSize = EcosystemManager.getGraphicsManager().getWindowSize();
|
---|
[1155] | 181 |
|
---|
[1415] | 182 | for (Item i : current.getSortedItems()) {
|
---|
[1098] | 183 | Point pos = i.getPosition();
|
---|
[1142] | 184 | pos.setX(pos.getX() % windowSize.width);
|
---|
| 185 | pos.setY(pos.getY() % windowSize.height);
|
---|
[1098] | 186 | i.setPosition(pos);
|
---|
| 187 | }
|
---|
| 188 | }
|
---|
| 189 | });
|
---|
[1155] | 190 |
|
---|
[1098] | 191 | // Set the TOGGLE_QUALITY_GRAPHICS action
|
---|
[1155] | 192 | setGestureAction(gestureType(ApolloGestureType.TOGGLE_QUALITY_GRAPHICS), new GestureAction() {
|
---|
[1098] | 193 | @Override
|
---|
[1155] | 194 | public void exec(Gesture gesture) {
|
---|
[1098] | 195 | ApolloSystem.useQualityGraphics = !ApolloSystem.useQualityGraphics;
|
---|
| 196 | }
|
---|
| 197 | });
|
---|
[1155] | 198 |
|
---|
[1098] | 199 | // Set the MOVE_CURSOR action
|
---|
[1155] | 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 |
|
---|
[1098] | 208 | // Set the PLACE action
|
---|
[1155] | 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();
|
---|
[1179] | 233 | final List<Item> widgetPieces = new LinkedList<Item>();
|
---|
[1155] | 234 | if (data.getCopy()) {
|
---|
[1179] | 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());
|
---|
[1155] | 257 | }
|
---|
| 258 | }
|
---|
| 259 |
|
---|
| 260 | @Override
|
---|
| 261 | public void finalise(final Gesture gesture) {
|
---|
| 262 | sampledTracks.forEach(st -> st.setIgnoreInjection(false));
|
---|
| 263 | sampledTracks.clear();
|
---|
| 264 | }
|
---|
| 265 | });
|
---|
[1098] | 266 | }
|
---|
[1155] | 267 |
|
---|
[1098] | 268 | /** Initialises the set of gesture types. */
|
---|
[1155] | 269 | private void initialiseGestureTypes() {
|
---|
[1098] | 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 | }
|
---|
[1155] | 278 |
|
---|
[1098] | 279 | /** Gets the gesture type associated with the given standard type. */
|
---|
[1155] | 280 | public GestureType gestureType(ApolloGestureType type) {
|
---|
[1179] | 281 | if (type == null) {
|
---|
[1155] | 282 | return null;
|
---|
[1179] | 283 | }
|
---|
[1155] | 284 |
|
---|
[1098] | 285 | return _gestureTypes.get(type);
|
---|
| 286 | }
|
---|
| 287 |
|
---|
[1155] | 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.
|
---|
[1098] | 295 | */
|
---|
[1155] | 296 |
|
---|
| 297 | public static void adjustInitiationTime(Widget track, long adjustment) {
|
---|
[1098] | 298 | if (track instanceof SampledTrack) {
|
---|
| 299 | adjustInitiationTime((SampledTrack) track, adjustment);
|
---|
| 300 | } else if (track instanceof LinkedTrack) {
|
---|
| 301 | adjustInitiationTime((LinkedTrack) track, adjustment);
|
---|
| 302 | }
|
---|
| 303 | }
|
---|
[1155] | 304 |
|
---|
| 305 | public static void adjustInitiationTime(SampledTrack track, long adjustment) {
|
---|
[1098] | 306 | Mutable.Long oldIt = track.getInitiationTimeFromMeta();
|
---|
[1179] | 307 | if (oldIt == null) {
|
---|
[1155] | 308 | oldIt = Mutable.createMutableLong(0);
|
---|
[1179] | 309 | }
|
---|
[1098] | 310 | track.setInitiationTime(oldIt.value + adjustment);
|
---|
| 311 | }
|
---|
[1155] | 312 |
|
---|
| 313 | public static void adjustInitiationTime(LinkedTrack track, long adjustment) {
|
---|
[1098] | 314 | Mutable.Long oldIt = track.getInitiationTimeFromMeta();
|
---|
[1179] | 315 | if (oldIt == null) {
|
---|
[1155] | 316 | oldIt = Mutable.createMutableLong(0);
|
---|
[1179] | 317 | }
|
---|
[1098] | 318 | track.setInitiationTime(oldIt.value + adjustment);
|
---|
| 319 | }
|
---|
[1155] | 320 |
|
---|
| 321 | public static void adjustVerticalPosition(Widget track, long adjustment) {
|
---|
[1098] | 322 | if (track instanceof SampledTrack) {
|
---|
| 323 | adjustVerticalPosition((SampledTrack) track, adjustment);
|
---|
| 324 | } else if (track instanceof LinkedTrack) {
|
---|
| 325 | adjustVerticalPosition((LinkedTrack) track, adjustment);
|
---|
| 326 | }
|
---|
| 327 | }
|
---|
[1155] | 328 |
|
---|
| 329 | public static void adjustVerticalPosition(SampledTrack track, long adjustment) {
|
---|
[1098] | 330 | track.setYPosition(track.getY() + (int) adjustment);
|
---|
| 331 | }
|
---|
[1155] | 332 |
|
---|
| 333 | public static void adjustVerticalPosition(LinkedTrack track, long adjustment) {
|
---|
[1098] | 334 | track.setYPosition(track.getY() + (int) adjustment);
|
---|
| 335 | }
|
---|
| 336 |
|
---|
[1155] | 337 | public static void createLinkedTracks(Item currentItem, Collection<Item> enclosedItems) {
|
---|
[1098] | 338 | if (currentItem == null) {
|
---|
| 339 |
|
---|
| 340 | if (enclosedItems != null) {
|
---|
[1155] | 341 |
|
---|
[1098] | 342 | Frame current = DisplayController.getCurrentFrame();
|
---|
[1155] | 343 |
|
---|
[1098] | 344 | Collection<Item> toRemove = new LinkedHashSet<Item>(enclosedItems.size());
|
---|
| 345 | LinkedList<LinkedTrack> enclosedLinkedTracks = new LinkedList<LinkedTrack>();
|
---|
| 346 | LinkedList<SampledTrack> enclosedTracks = new LinkedList<SampledTrack>();
|
---|
[1155] | 347 |
|
---|
[1098] | 348 | // Get enclosing shape and enclosed tracks
|
---|
| 349 | for (Item ip : enclosedItems) {
|
---|
[1179] | 350 | if (ip.getParent() != current) {
|
---|
[1155] | 351 | continue;
|
---|
[1179] | 352 | }
|
---|
[1155] | 353 |
|
---|
[1098] | 354 | if (ip.hasPermission(UserAppliedPermission.full)) {
|
---|
[1155] | 355 | // Only include lines if one of their enpoints are also being removed
|
---|
[1098] | 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)) {
|
---|
[1155] | 365 | if (!enclosedItems.contains(start) && enclosedItems.containsAll(start.getLines())) {
|
---|
[1098] | 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 | }
|
---|
[1155] | 375 | } else if (ip instanceof WidgetCorner) {
|
---|
| 376 | Widget iw = ((WidgetCorner) ip).getWidgetSource();
|
---|
[1098] | 377 | if (!enclosedTracks.contains(iw) && iw instanceof SampledTrack) {
|
---|
[1155] | 378 | enclosedTracks.add((SampledTrack) iw);
|
---|
[1098] | 379 | } else if (!enclosedLinkedTracks.contains(iw) && iw instanceof LinkedTrack) {
|
---|
[1155] | 380 | enclosedLinkedTracks.add((LinkedTrack) iw);
|
---|
[1098] | 381 | }
|
---|
| 382 | } else {
|
---|
[1155] | 383 | if ((ip instanceof Line || ip instanceof Dot)
|
---|
| 384 | && ip.getHighlightMode() == HighlightMode.Enclosed) {
|
---|
[1098] | 385 | toRemove.add(ip);
|
---|
| 386 | toRemove.addAll(ip.getConnected());
|
---|
| 387 | }
|
---|
| 388 | }
|
---|
[1155] | 389 |
|
---|
[1098] | 390 | }
|
---|
| 391 | } // End searching enclosed items
|
---|
[1155] | 392 |
|
---|
[1098] | 393 | // If there was some enclosed tracks
|
---|
[1155] | 394 | if (current != null && !toRemove.isEmpty()
|
---|
| 395 | && (!enclosedLinkedTracks.isEmpty() || !enclosedTracks.isEmpty())) {
|
---|
[1098] | 396 |
|
---|
| 397 | // Remove enclosure
|
---|
| 398 | current.removeAllItems(toRemove);
|
---|
[1155] | 399 |
|
---|
[1098] | 400 | // Determine initiation time of group
|
---|
| 401 | Mutable.Long initTime = null;
|
---|
| 402 | Point initiatePosition = null;
|
---|
[1155] | 403 |
|
---|
[1098] | 404 | for (SampledTrack st : enclosedTracks) {
|
---|
[1155] | 405 |
|
---|
[1098] | 406 | if (initTime == null) {
|
---|
| 407 | initTime = st.getInitiationTimeFromMeta();
|
---|
| 408 | initiatePosition = st.getPosition();
|
---|
[1155] | 409 | } else if (st.getInitiationTimeFromMeta() != null
|
---|
| 410 | && st.getInitiationTimeFromMeta().value < initTime.value) {
|
---|
[1098] | 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();
|
---|
[1155] | 420 | } else if (lt.getInitiationTimeFromMeta() != null
|
---|
| 421 | && lt.getInitiationTimeFromMeta().value < initTime.value) {
|
---|
[1098] | 422 | initTime = lt.getInitiationTimeFromMeta();
|
---|
| 423 | initiatePosition = lt.getPosition();
|
---|
| 424 | }
|
---|
| 425 | }
|
---|
[1155] | 426 |
|
---|
| 427 | assert (initTime != null);
|
---|
| 428 | assert (initiatePosition != null);
|
---|
| 429 |
|
---|
[1098] | 430 | // Creat the link to contain all tracks
|
---|
| 431 | String name = current.getTitle();
|
---|
[1179] | 432 | if (name == null) {
|
---|
[1155] | 433 | name = "Unnamed";
|
---|
[1179] | 434 | }
|
---|
[1098] | 435 | name += " group";
|
---|
[1155] | 436 |
|
---|
[1098] | 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);
|
---|
[1155] | 443 |
|
---|
[1098] | 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 | }
|
---|
[1155] | 452 |
|
---|
[1098] | 453 | for (LinkedTrack lt : enclosedLinkedTracks) {
|
---|
| 454 | current.removeAllItems(lt.getItems());
|
---|
| 455 | newFrame.addAllItems(lt.getItems());
|
---|
| 456 | }
|
---|
[1155] | 457 |
|
---|
[1098] | 458 | FrameIO.SaveFrame(newFrame);
|
---|
[1155] | 459 |
|
---|
[1098] | 460 | // Link the linked tracks
|
---|
| 461 | linkedVersion.setLink(newFrame.getName(), null);
|
---|
[1155] | 462 |
|
---|
[1098] | 463 | // Add the new link
|
---|
| 464 | current.addAllItems(linkedVersion.getItems());
|
---|
[1155] | 465 |
|
---|
| 466 | // Ensure initiation time is retained to the exact frame... avoiding loss due to
|
---|
| 467 | // resolution
|
---|
[1098] | 468 | linkedVersion.setInitiationTime(initTime.value);
|
---|
| 469 | }
|
---|
| 470 | }
|
---|
| 471 | }
|
---|
| 472 | }
|
---|
[1155] | 473 |
|
---|
| 474 | /**
|
---|
| 475 | * The minimum distance from a track widget to auto-align free space items to.
|
---|
| 476 | */
|
---|
[1098] | 477 | private static final int COARSE_X_PLACEMENT_TOLERANCE = 80;
|
---|
| 478 |
|
---|
[1155] | 479 | private static final int COARSE_Y_PLACEMENT_TOLERANCE = 20;
|
---|
| 480 |
|
---|
| 481 | public void mouseMoved(Point to) {
|
---|
[1098] | 482 | boolean forwareToExpeditee = true;
|
---|
| 483 |
|
---|
[1155] | 484 | if (isYAxisRestictionOn() && !FreeItems.getInstance().isEmpty()) {
|
---|
| 485 |
|
---|
[1098] | 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()) {
|
---|
[1179] | 492 | if (i.getY() < smallestY) {
|
---|
[1155] | 493 | smallestY = i.getY();
|
---|
[1179] | 494 | }
|
---|
[1098] | 495 | }
|
---|
| 496 |
|
---|
| 497 | for (Item i : FreeItems.getInstance()) {
|
---|
| 498 | i.setY(to.getY() + (i.getY() - smallestY));
|
---|
| 499 | }
|
---|
[1155] | 500 |
|
---|
| 501 | } else if (isSnapOn() && !FreeItems.getInstance().isEmpty()) {
|
---|
| 502 |
|
---|
[1098] | 503 | // Couse movement of free items: Restraining left-most pixel in items
|
---|
| 504 | // to the closest anchored track widgets x position.
|
---|
[1155] | 505 |
|
---|
[1098] | 506 | Frame currentFrame = DisplayController.getCurrentFrame();
|
---|
| 507 | if (currentFrame != null) {
|
---|
[1155] | 508 |
|
---|
[1098] | 509 | // Search all anchored track x positions for the current frame
|
---|
| 510 | List<Widget> widgets = currentFrame.getInteractiveWidgets();
|
---|
[1155] | 511 |
|
---|
[1098] | 512 | int closestXPosition = -1;
|
---|
| 513 | int closestYPosition = -1;
|
---|
| 514 | int closestXDistance = -1;
|
---|
| 515 | int closestYDistance = -1;
|
---|
[1155] | 516 |
|
---|
[1098] | 517 | for (Widget iw : widgets) {
|
---|
[1155] | 518 |
|
---|
[1098] | 519 | if (iw instanceof SampledTrack || iw instanceof LinkedTrack) {
|
---|
[1155] | 520 |
|
---|
[1098] | 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 | }
|
---|
[1155] | 527 |
|
---|
[1098] | 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 | }
|
---|
[1155] | 540 |
|
---|
[1098] | 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 | }
|
---|
[1155] | 547 |
|
---|
[1098] | 548 | }
|
---|
[1155] | 549 |
|
---|
| 550 | // Determine top-left position of free items
|
---|
[1098] | 551 | int smallestX = FreeItems.getInstance().get(0).getX();
|
---|
| 552 | int smallestY = FreeItems.getInstance().get(0).getY();
|
---|
| 553 | for (Item i : FreeItems.getInstance()) {
|
---|
[1179] | 554 | if (i.getX() < smallestX) {
|
---|
[1155] | 555 | smallestX = i.getX();
|
---|
[1179] | 556 | }
|
---|
| 557 | if (i.getY() < smallestY) {
|
---|
[1155] | 558 | smallestY = i.getY();
|
---|
[1179] | 559 | }
|
---|
[1098] | 560 | }
|
---|
| 561 |
|
---|
| 562 | for (Item i : FreeItems.getInstance()) {
|
---|
[1155] | 563 |
|
---|
[1098] | 564 | int x;
|
---|
| 565 | int y;
|
---|
[1155] | 566 |
|
---|
[1179] | 567 | if (closestXDistance > 0 && closestXDistance < COARSE_X_PLACEMENT_TOLERANCE) {
|
---|
[1098] | 568 | x = closestXPosition + (i.getX() - smallestX);
|
---|
[1179] | 569 | } else {
|
---|
[1098] | 570 | x = to.getX() + (i.getX() - smallestX);
|
---|
[1179] | 571 | }
|
---|
[1155] | 572 |
|
---|
[1179] | 573 | if (closestYDistance > 0 && closestYDistance < COARSE_Y_PLACEMENT_TOLERANCE) {
|
---|
[1098] | 574 | y = closestYPosition + (i.getY() - smallestY);
|
---|
[1179] | 575 | } else {
|
---|
[1098] | 576 | y = to.getY() + (i.getY() - smallestY);
|
---|
[1179] | 577 | }
|
---|
[1155] | 578 |
|
---|
[1098] | 579 | i.setPosition(x, y);
|
---|
[1155] | 580 |
|
---|
[1098] | 581 | }
|
---|
| 582 |
|
---|
| 583 | forwareToExpeditee = false;
|
---|
| 584 |
|
---|
| 585 | }
|
---|
[1155] | 586 |
|
---|
[1158] | 587 | }
|
---|
[1155] | 588 |
|
---|
[1098] | 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
|
---|
[1155] | 593 | // if (forwareToExpeditee) {
|
---|
| 594 | // FrameMouseActions.getInstance().mouseMoved(e);
|
---|
| 595 | // } else {
|
---|
| 596 | // FrameGraphics.refresh(true);
|
---|
| 597 | // }
|
---|
[1098] | 598 | }
|
---|
| 599 |
|
---|
| 600 | /**
|
---|
[1155] | 601 | * @return True if the user is restricting movement on the y-axis only
|
---|
[1098] | 602 | */
|
---|
[1155] | 603 | public static boolean isYAxisRestictionOn() {
|
---|
| 604 | return StandardInputEventListeners.kbmStateListener.isKeyDown(Key.CTRL)
|
---|
| 605 | && !StandardInputEventListeners.kbmStateListener.isKeyDown(Key.SHIFT);
|
---|
[1098] | 606 | }
|
---|
[1155] | 607 |
|
---|
| 608 | public static boolean isSnapOn() {
|
---|
| 609 | return StandardInputEventListeners.kbmStateListener.isKeyDown(Key.SHIFT)
|
---|
| 610 | && !StandardInputEventListeners.kbmStateListener.isKeyDown(Key.CTRL);
|
---|
[1098] | 611 | }
|
---|
[1155] | 612 |
|
---|
[1179] | 613 | private void anchorTracks(final List<Item> widgetPieces) {
|
---|
[1155] | 614 |
|
---|
[1098] | 615 | // Widget -> delta IT time
|
---|
| 616 | Map<LinkedTrack, Mutable.Long> anchoredLinkedTracks = null;
|
---|
| 617 | Map<SampledTrack, Mutable.Long> anchoredTracks = null;
|
---|
[1155] | 618 |
|
---|
[1179] | 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);
|
---|
[1098] | 623 |
|
---|
| 624 | Mutable.Long firstInitTime = null;
|
---|
| 625 | anchoredLinkedTracks = new HashMap<LinkedTrack, Mutable.Long>();
|
---|
| 626 | anchoredTracks = new HashMap<SampledTrack, Mutable.Long>();
|
---|
[1155] | 627 |
|
---|
[1098] | 628 | for (Widget iw : anchoringWidgets) {
|
---|
[1155] | 629 |
|
---|
[1098] | 630 | Mutable.Long it = null;
|
---|
[1155] | 631 |
|
---|
[1098] | 632 | if (iw instanceof LinkedTrack) {
|
---|
[1155] | 633 |
|
---|
| 634 | LinkedTrack lt = (LinkedTrack) iw;
|
---|
[1098] | 635 | it = lt.getInitiationTimeFromMeta();
|
---|
[1179] | 636 | if (it == null) {
|
---|
[1155] | 637 | it = Mutable.createMutableLong(0);
|
---|
[1179] | 638 | }
|
---|
[1155] | 639 |
|
---|
[1098] | 640 | anchoredLinkedTracks.put(lt, it);
|
---|
[1155] | 641 |
|
---|
[1098] | 642 | } else if (iw instanceof SampledTrack) {
|
---|
[1155] | 643 |
|
---|
| 644 | SampledTrack st = (SampledTrack) iw;
|
---|
[1098] | 645 | it = st.getInitiationTimeFromMeta();
|
---|
[1179] | 646 | if (it == null) {
|
---|
[1155] | 647 | it = Mutable.createMutableLong(0);
|
---|
[1179] | 648 | }
|
---|
[1155] | 649 |
|
---|
[1098] | 650 | anchoredTracks.put(st, it);
|
---|
[1155] | 651 |
|
---|
[1179] | 652 | } else {
|
---|
[1155] | 653 | continue;
|
---|
[1179] | 654 | }
|
---|
[1155] | 655 |
|
---|
[1098] | 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 | }
|
---|
[1155] | 662 |
|
---|
[1098] | 663 | // Should do a accurate anchor with init times properly aligned?
|
---|
| 664 | if ((anchoredLinkedTracks.size() + anchoredTracks.size()) > 1) {
|
---|
[1155] | 665 |
|
---|
| 666 | assert (firstInitTime != null);
|
---|
| 667 |
|
---|
[1098] | 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 | }
|
---|
[1155] | 673 |
|
---|
[1098] | 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 | }
|
---|
[1155] | 683 |
|
---|
[1098] | 684 | }
|
---|
[1179] | 685 |
|
---|
[1098] | 686 | // If anchored a group of tracks .. adjust initiation times to
|
---|
| 687 | if (anchoredLinkedTracks != null) {
|
---|
[1155] | 688 |
|
---|
[1098] | 689 | Mutable.Long firstInitTime = null;
|
---|
[1155] | 690 |
|
---|
[1098] | 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 | }
|
---|
[1155] | 707 | assert (firstInitTime != null);
|
---|
| 708 |
|
---|
[1098] | 709 | for (LinkedTrack lt : anchoredLinkedTracks.keySet()) {
|
---|
| 710 | Mutable.Long it = anchoredLinkedTracks.get(lt);
|
---|
[1179] | 711 | if (it.value == 0) {
|
---|
[1155] | 712 | continue;
|
---|
[1179] | 713 | }
|
---|
[1098] | 714 | lt.setInitiationTime(firstInitTime.value + it.value);
|
---|
| 715 | }
|
---|
[1155] | 716 |
|
---|
[1098] | 717 | for (SampledTrack st : anchoredTracks.keySet()) {
|
---|
| 718 | Mutable.Long it = anchoredTracks.get(st);
|
---|
[1179] | 719 | if (it.value == 0) {
|
---|
[1155] | 720 | continue;
|
---|
[1179] | 721 | }
|
---|
[1098] | 722 | st.setInitiationTime(firstInitTime.value + it.value);
|
---|
| 723 | }
|
---|
[1155] | 724 |
|
---|
[1098] | 725 | }
|
---|
| 726 | }
|
---|
| 727 | }
|
---|