source: trunk/src_apollo/org/apollo/AudioFrameMouseActions.java@ 366

Last change on this file since 366 was 366, checked in by bjn8, 16 years ago

Improved mix settings... Also fix widget anchoring bug in Apollo

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