source: trunk/src/org/apollo/AudioFrameMouseActions.java@ 1102

Last change on this file since 1102 was 1102, checked in by davidb, 6 years ago

Reworking of the code-base to separate logic from graphics. This version of Expeditee now supports a JFX graphics as an alternative to SWING

File size: 9.5 KB
Line 
1package org.apollo;
2
3import java.awt.event.MouseEvent;
4import java.awt.event.MouseListener;
5import java.awt.event.MouseMotionListener;
6import java.util.HashMap;
7import java.util.LinkedList;
8import java.util.List;
9import java.util.Map;
10
11import org.apollo.util.Mutable;
12import org.apollo.widgets.LinkedTrack;
13import org.apollo.widgets.SampledTrack;
14import org.expeditee.gui.DisplayIO;
15import org.expeditee.gui.Frame;
16import org.expeditee.gui.FrameGraphics;
17import org.expeditee.gui.FrameMouseActions;
18import org.expeditee.gui.FreeItems;
19import org.expeditee.items.Item;
20import org.expeditee.items.ItemUtils;
21import org.expeditee.items.widgets.InteractiveWidget;
22
23/**
24 * Apollos mouse actions extensions. Overrides expeditees frame mouse actions and
25 * forwards them onto expeditee (filtering out certain non-conflicting key-sequences).
26 *
27 * @author Brook Novak
28 *
29 */
30public class AudioFrameMouseActions implements MouseMotionListener, MouseListener {
31
32 private static final int COARSE_X_PLACEMENT_TOLERANCE = 80; // The minium distance from a track widet to auto-align free space items to
33
34 private static final int COARSE_Y_PLACEMENT_TOLERANCE = 20;
35
36 private static boolean isAnchoring = false;
37 private static boolean isStamping = false;
38
39 private static List<Item> anchoringItems = new LinkedList<Item>();
40
41 public void mouseDragged(MouseEvent e) {
42 FrameMouseActions.getInstance().mouseDragged(e);
43 }
44
45 public void mouseMoved(MouseEvent e) {
46
47 boolean forwareToExpeditee = true;
48
49 if (AudioFrameKeyboardActions.isControlDown != e.isControlDown()) {
50 AudioFrameKeyboardActions.isControlDown = e.isControlDown();
51 FrameGraphics.refresh(false); // For special post effects
52 }
53
54 AudioFrameKeyboardActions.isShiftDown = e.isShiftDown();
55
56 if (isYAxisRestictionOn() && !FreeItems.getInstance().isEmpty()) {
57
58 // Restrict movement of free items to Y-Axis only
59 forwareToExpeditee = false;
60
61 int smallestY = FreeItems.getInstance().get(0).getY();
62
63 for (Item i : FreeItems.getInstance()) {
64 if (i.getY() < smallestY) smallestY = i.getY();
65 }
66
67 for (Item i : FreeItems.getInstance()) {
68 i.setY(e.getY() + (i.getY() - smallestY));
69 }
70
71 // Avoids no-op suppression in expeditee once anchored free items
72 FrameMouseActions.MouseX = e.getX();
73 FrameMouseActions.MouseY = e.getY();
74
75 } else if (isSnapOn() && !FreeItems.getInstance().isEmpty()) {
76
77 // Couse movement of free items: Restraining left-most pixel in items
78 // to the closest anchored track widgets x position.
79
80 Frame currentFrame = DisplayIO.getCurrentFrame();
81 if (currentFrame != null) {
82
83 // Search all anchored track x positions for the current frame
84 List<InteractiveWidget> widgets = currentFrame.getInteractiveWidgets();
85
86 int closestXPosition = -1;
87 int closestYPosition = -1;
88 int closestXDistance = -1;
89 int closestYDistance = -1;
90
91 for (InteractiveWidget iw : widgets) {
92
93 if (iw instanceof SampledTrack || iw instanceof LinkedTrack) {
94
95 // Determine TOP-LEFT Snapping
96 int xDistance = Math.abs(e.getX() - iw.getX());
97 if (closestXDistance < 0 || xDistance < closestXDistance) {
98 closestXDistance = xDistance;
99 closestXPosition = iw.getX();
100 }
101
102 int yDistance = Math.abs(e.getY() - iw.getY());
103 if (closestYDistance < 0 || yDistance < closestYDistance) {
104 closestYDistance = yDistance;
105 closestYPosition = iw.getY();
106 }
107
108 // Determine BOTTOM-RIGHT Snapping
109 xDistance = Math.abs(e.getX() - (iw.getX() + iw.getWidth()));
110 if (closestXDistance < 0 || xDistance < closestXDistance) {
111 closestXDistance = xDistance;
112 closestXPosition = iw.getX() + iw.getWidth();
113 }
114
115 yDistance = Math.abs(e.getY() - (iw.getY() + iw.getHeight()));
116 if (closestYDistance < 0 || yDistance < closestYDistance) {
117 closestYDistance = yDistance;
118 closestYPosition = iw.getY() + iw.getHeight();
119 }
120 }
121
122 }
123
124 //Determine top-left positoin of free items
125 int smallestX = FreeItems.getInstance().get(0).getX();
126 int smallestY = FreeItems.getInstance().get(0).getY();
127 for (Item i : FreeItems.getInstance()) {
128 if (i.getX() < smallestX) smallestX = i.getX();
129 if (i.getY() < smallestY) smallestY = i.getY();
130 }
131
132 for (Item i : FreeItems.getInstance()) {
133
134 int x;
135 int y;
136
137 if (closestXDistance > 0 && closestXDistance < COARSE_X_PLACEMENT_TOLERANCE)
138 x = closestXPosition + (i.getX() - smallestX);
139 else
140 x = e.getX() + (i.getX() - smallestX);
141
142 if (closestYDistance > 0 && closestYDistance < COARSE_Y_PLACEMENT_TOLERANCE)
143 y = closestYPosition + (i.getY() - smallestY);
144 else
145 y = e.getY() + (i.getY() - smallestY);
146
147 i.setPosition(x, y);
148
149 }
150
151 forwareToExpeditee = false;
152
153 }
154
155 }
156
157 // Expeditees frame mouse actions uses an offset and fights over free-item
158 // movement if it listens to the mouse event router... therefore add an extra
159 // layer to avoid this... otherwise auto-aligned items jitter like crazy while
160 // moving the cursus
161 if (forwareToExpeditee) {
162 FrameMouseActions.getInstance().mouseMoved(e);
163 } else {
164 FrameGraphics.refresh(true);
165 }
166 }
167
168 public void mouseClicked(MouseEvent e) {
169 FrameMouseActions.getInstance().mouseClicked(e);
170 }
171
172 public void mouseEntered(MouseEvent e) {
173 FrameMouseActions.getInstance().mouseEntered(e);
174 }
175
176 public void mouseExited(MouseEvent e) {
177 FrameMouseActions.getInstance().mouseExited(e);
178 }
179
180 public void mousePressed(MouseEvent e) {
181 isAnchoring = (e.getModifiersEx() & MouseEvent.BUTTON2_DOWN_MASK) != 0;
182 isStamping = (e.getModifiersEx() & MouseEvent.BUTTON3_DOWN_MASK) != 0;
183 FrameMouseActions.getInstance().mousePressed(e);
184 }
185
186 public void mouseReleased(MouseEvent e) {
187
188 // Widget -> delta IT time
189 Map<LinkedTrack, Mutable.Long> anchoredLinkedTracks = null;
190 Map<SampledTrack, Mutable.Long> anchoredTracks = null;
191
192 if (isAnchoring) {
193 if (FreeItems.getInstance().size() > 1) {
194 List<InteractiveWidget> anchoringWidgets = ItemUtils.extractWidgets(FreeItems.getInstance());
195
196 Mutable.Long firstInitTime = null;
197 anchoredLinkedTracks = new HashMap<LinkedTrack, Mutable.Long>();
198 anchoredTracks = new HashMap<SampledTrack, Mutable.Long>();
199
200 for (InteractiveWidget iw : anchoringWidgets) {
201
202 Mutable.Long it = null;
203
204 if (iw instanceof LinkedTrack) {
205
206 LinkedTrack lt = (LinkedTrack)iw;
207 it = lt.getInitiationTimeFromMeta();
208 if (it == null) it = Mutable.createMutableLong(0);
209
210 anchoredLinkedTracks.put(lt, it);
211
212 } else if (iw instanceof SampledTrack) {
213
214 SampledTrack st = (SampledTrack)iw;
215 it = st.getInitiationTimeFromMeta();
216 if (it == null) it = Mutable.createMutableLong(0);
217
218 anchoredTracks.put(st, it);
219
220 } else continue;
221
222 if (firstInitTime == null) {
223 firstInitTime = Mutable.createMutableLong(it.value); // Important to create new instance
224 } else if (it.value < firstInitTime.value) {
225 firstInitTime = Mutable.createMutableLong(it.value); // Important to create new instance
226 }
227 }
228
229 // Should do a accurate anchor with init times properly aligned?
230 if ((anchoredLinkedTracks.size() + anchoredTracks.size()) > 1) {
231
232 assert(firstInitTime != null);
233
234 // Then calc all the deltas
235 for (LinkedTrack lt : anchoredLinkedTracks.keySet()) {
236 Mutable.Long it = anchoredLinkedTracks.get(lt);
237 it.value -= firstInitTime.value;
238 }
239
240 for (SampledTrack st : anchoredTracks.keySet()) {
241 Mutable.Long it = anchoredTracks.get(st);
242 it.value -= firstInitTime.value;
243 }
244
245 } else {
246 anchoredLinkedTracks = null;
247 anchoredTracks = null;
248 }
249
250 }
251 anchoringItems.clear();
252 anchoringItems.addAll(FreeItems.getInstance());
253 }
254
255
256 FrameMouseActions.getInstance().mouseReleased(e);
257
258 // If anchored a group of tracks .. adjust initiation times to
259 if (anchoredLinkedTracks != null && FreeItems.getInstance().isEmpty()) {
260
261 Mutable.Long firstInitTime = null;
262
263 for (LinkedTrack lt : anchoredLinkedTracks.keySet()) {
264 Mutable.Long it = anchoredLinkedTracks.get(lt);
265 if (it.value == 0) {
266 firstInitTime = lt.getInitiationTimeFromMeta();
267 break;
268 }
269 }
270 if (firstInitTime == null) {
271 for (SampledTrack st : anchoredTracks.keySet()) {
272 Mutable.Long it = anchoredTracks.get(st);
273 if (it.value == 0) {
274 firstInitTime = st.getInitiationTimeFromMeta();
275 break;
276 }
277 }
278 }
279 assert(firstInitTime != null);
280
281 for (LinkedTrack lt : anchoredLinkedTracks.keySet()) {
282 Mutable.Long it = anchoredLinkedTracks.get(lt);
283 if (it.value == 0) continue;
284 lt.setInitiationTime(firstInitTime.value + it.value);
285 }
286
287 for (SampledTrack st : anchoredTracks.keySet()) {
288 Mutable.Long it = anchoredTracks.get(st);
289 if (it.value == 0) continue;
290 st.setInitiationTime(firstInitTime.value + it.value);
291 }
292
293 }
294
295 isAnchoring = false;
296 isStamping = false;
297 anchoringItems.clear();
298 }
299
300 /**
301 * @return
302 * True if the user is restricting movement on the y-axis only
303 */
304 public static boolean isYAxisRestictionOn() {
305 return AudioFrameKeyboardActions.isControlDown && !AudioFrameKeyboardActions.isShiftDown;
306 }
307
308 public static boolean isSnapOn() {
309 return AudioFrameKeyboardActions.isShiftDown && !AudioFrameKeyboardActions.isControlDown;
310 }
311
312 public static boolean isMouseAnchoring() {
313 return isAnchoring;
314 }
315
316 public static boolean isMouseStamping() {
317 return isStamping;
318 }
319
320 public static List<Item> getAnchoringItems() {
321 return anchoringItems;
322 }
323
324}
Note: See TracBrowser for help on using the repository browser.