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

Last change on this file since 1555 was 1555, checked in by davidb, 3 years ago

Merging in minor tweaks from the mozart's laptop branch of the code

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