source: trunk/src/org/apollo/gui/PlaybackControlPopup.java@ 1561

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

A set of changes that spans three things: beat detection, time stretching; and a debug class motivated by the need to look at a canvas redraw issue most notable when a waveform widget is playing

File size: 9.6 KB
Line 
1package org.apollo.gui;
2
3import java.awt.Dimension;
4import java.awt.Graphics2D;
5import java.awt.GridBagConstraints;
6import java.awt.GridBagLayout;
7import java.awt.Insets;
8import java.awt.event.ActionEvent;
9import java.awt.event.ActionListener;
10
11import javax.swing.JButton;
12import javax.swing.JPanel;
13import javax.swing.JSlider;
14import javax.swing.JToggleButton;
15import javax.swing.event.ChangeEvent;
16import javax.swing.event.ChangeListener;
17
18import org.apollo.io.IconRepository;
19import org.expeditee.core.Image;
20import org.expeditee.core.bounds.AxisAlignedBoxBounds;
21import org.expeditee.gio.swing.SwingConversions;
22import org.expeditee.gio.swing.SwingMiscManager;
23import org.expeditee.gui.Popup;
24import org.expeditee.gui.PopupManager.ExpandShrinkAnimator;
25
26/**
27 * A pure GUI for playback and mixing popup used for tracks and linked tracks.
28 * Does not implement beahviour - just the gui.
29 *
30 * @author Brook Novak
31 *
32 */
33public abstract class PlaybackControlPopup extends Popup implements ActionListener
34{
35 public JPanel panel;
36 public JButton playPauseButton;
37 public JButton stopButton;
38 public JButton rewindButton;
39 public JToggleButton muteButton;
40 public JToggleButton soloButton;
41 public JToggleButton beatDetectButton;
42 public JButton miscButton;
43 public JSlider volumeSlider;
44
45 private boolean isUpdatingGUI = false;
46
47 private static final int BUTTON_SIZE = 40;
48
49 protected PlaybackControlPopup()
50 {
51 super(new ExpandShrinkAnimator());
52
53 panel = new JPanel(new GridBagLayout());
54
55 playPauseButton = new JButton();
56 playPauseButton.setActionCommand("playpause");
57 playPauseButton.addActionListener(this);
58 SwingMiscManager.setJButtonIcon(playPauseButton, IconRepository.getIcon("play.png"));
59 playPauseButton.setPreferredSize(new Dimension(BUTTON_SIZE, BUTTON_SIZE));
60 playPauseButton.setToolTipText("Play selection / Pause");
61
62 stopButton = new JButton();
63 stopButton.setEnabled(false);
64 stopButton.addActionListener(this);
65 stopButton.setActionCommand("stop");
66 SwingMiscManager.setJButtonIcon(stopButton, IconRepository.getIcon("stop.png"));
67 stopButton.setPreferredSize(new Dimension(BUTTON_SIZE, BUTTON_SIZE));
68 stopButton.setToolTipText("Stop playback");
69
70 rewindButton = new JButton();
71 rewindButton.addActionListener(this);
72 rewindButton.setActionCommand("rewind");
73 SwingMiscManager.setJButtonIcon(rewindButton, IconRepository.getIcon("rewind.png"));
74 rewindButton.setPreferredSize(new Dimension(BUTTON_SIZE, BUTTON_SIZE));
75 rewindButton.setToolTipText("Rewind to start");
76
77 // Icon changes
78 muteButton = new JToggleButton();
79 SwingMiscManager.setJButtonSelectedIcon(muteButton, IconRepository.getIcon("volmute.png"));
80 muteButton.setPreferredSize(new Dimension(BUTTON_SIZE, BUTTON_SIZE));
81 muteButton.setToolTipText("Toggle mute");
82 muteButton.addChangeListener(new ChangeListener() {
83 public void stateChanged(ChangeEvent e) {
84 if (!PlaybackControlPopup.this.isUpdatingGUI) {
85 muteChanged();
86 }
87 }
88 });
89
90 soloButton = new JToggleButton();
91 SwingMiscManager.setJButtonIcon(soloButton, IconRepository.getIcon("solo.png"));
92 SwingMiscManager.setJButtonSelectedIcon(soloButton, IconRepository.getIcon("soloon.png"));
93 soloButton.setPreferredSize(new Dimension(BUTTON_SIZE, BUTTON_SIZE));
94 soloButton.setToolTipText("Toggle solo");
95 soloButton.addChangeListener(new ChangeListener() {
96 public void stateChanged(ChangeEvent e) {
97 if (!PlaybackControlPopup.this.isUpdatingGUI) {
98 soloChanged();
99 }
100 }
101 });
102
103 beatDetectButton = new JToggleButton();
104 SwingMiscManager.setJButtonIcon(beatDetectButton,IconRepository.getIcon("beatDetect.png"));
105 SwingMiscManager.setJButtonSelectedIcon(beatDetectButton,IconRepository.getIcon("beatDetect-no-sticks.png"));
106 beatDetectButton.setPreferredSize(new Dimension(BUTTON_SIZE, BUTTON_SIZE));
107 beatDetectButton.setToolTipText("Toggle beat detection in track");
108
109 beatDetectButton.addChangeListener(new ChangeListener() {
110 public void stateChanged(ChangeEvent e) {
111 if (!PlaybackControlPopup.this.isUpdatingGUI) {
112 beatDetectChanged();
113 }
114 }
115 });
116
117 miscButton = new JButton();
118 miscButton.addActionListener(this);
119 miscButton.setPreferredSize(new Dimension(BUTTON_SIZE, BUTTON_SIZE));
120
121 final int VOLUME_SPACING = 6;
122 volumeSlider = new JSlider(JSlider.HORIZONTAL);
123 volumeSlider.setPreferredSize(new Dimension(2 * (BUTTON_SIZE - VOLUME_SPACING), BUTTON_SIZE));
124 volumeSlider.setMinimum(0);
125 volumeSlider.setMaximum(100);
126 volumeSlider.addChangeListener(new ChangeListener() {
127 public void stateChanged(ChangeEvent e) {
128 if (!PlaybackControlPopup.this.isUpdatingGUI) {
129 volumeChanged();
130 }
131 // Update the icons
132 updateButtonGUI();
133 }
134 });
135
136
137 // Create the toolbar
138 GridBagConstraints c = new GridBagConstraints();
139 c.gridx = 0;
140 c.gridy = 0;
141 c.fill = GridBagConstraints.BOTH;
142 panel.add(playPauseButton, c);
143
144 c = new GridBagConstraints();
145 c.gridx = 1;
146 c.gridy = 0;
147 c.fill = GridBagConstraints.BOTH;
148 panel.add(stopButton, c);
149
150 c = new GridBagConstraints();
151 c.gridx = 2;
152 c.gridy = 0;
153 c.fill = GridBagConstraints.BOTH;
154 panel.add(rewindButton, c);
155
156 c = new GridBagConstraints();
157 c.gridx = 3;
158 c.gridy = 0;
159 c.fill = GridBagConstraints.BOTH;
160 panel.add(soloButton, c);
161
162 c = new GridBagConstraints();
163 c.gridx = 4;
164 c.gridy = 0;
165 c.fill = GridBagConstraints.BOTH;
166 panel.add(muteButton, c);
167
168 c = new GridBagConstraints();
169 c.gridx = 5;
170 c.gridy = 0;
171 c.fill = GridBagConstraints.BOTH;
172 panel.add(beatDetectButton, c);
173
174 c = new GridBagConstraints();
175 c.gridx = 6;
176 c.gridy = 0;
177 c.fill = GridBagConstraints.BOTH;
178 c.insets = new Insets(0,VOLUME_SPACING,0,VOLUME_SPACING);
179 panel.add(volumeSlider, c);
180
181 c = new GridBagConstraints();
182 c.gridx = 8;
183 c.gridy = 0;
184 c.fill = GridBagConstraints.BOTH;
185 panel.add(miscButton, c);
186
187//
188// GridBagConstraints c = new GridBagConstraints();
189// c.gridx = 0;
190// c.gridy = 0;
191// c.fill = GridBagConstraints.BOTH;
192// this.add(soloButton, c);
193//
194// c = new GridBagConstraints();
195// c.gridx = 1;
196// c.gridy = 0;
197// c.fill = GridBagConstraints.BOTH;
198// this.add(muteButton, c);
199//
200// c = new GridBagConstraints();
201// c.gridx = 2;
202// c.gridy = 0;
203// c.gridwidth = 2;
204// c.insets = new Insets(0,VOLUME_SPACING,0,VOLUME_SPACING);
205// c.fill = GridBagConstraints.BOTH;
206// this.add(volumeSlider, c);
207//
208// c = new GridBagConstraints();
209// c.gridx = 0;
210// c.gridy = 1;
211// c.fill = GridBagConstraints.BOTH;
212// this.add(playPauseButton, c);
213//
214// c = new GridBagConstraints();
215// c.gridx = 1;
216// c.gridy = 1;
217// c.fill = GridBagConstraints.BOTH;
218// this.add(stopButton, c);
219//
220// c = new GridBagConstraints();
221// c.gridx = 2;
222// c.gridy = 1;
223// c.fill = GridBagConstraints.BOTH;
224// this.add(rewindButton, c);
225//
226// c = new GridBagConstraints();
227// c.gridx = 3;
228// c.gridy = 1;
229// c.fill = GridBagConstraints.BOTH;
230// this.add(miscButton, c);
231//
232// this.setSize(BUTTON_SIZE * 4, BUTTON_SIZE * 2);
233
234 panel.setSize(BUTTON_SIZE * 9, BUTTON_SIZE);
235
236 panel.doLayout();
237
238 }
239
240 /**
241 * Sets the mute icon to represent the current volume value in the slider.
242 * Note: this is not the icon if mute is on.
243 */
244 private void updateButtonGUI() {
245
246 Image newIcon = null;
247 if (volumeSlider.getValue() <= 25)
248 newIcon = IconRepository.getIcon("vol25.png");
249 else if (volumeSlider.getValue() <= 50)
250 newIcon = IconRepository.getIcon("vol50.png");
251 else if (volumeSlider.getValue() <= 75)
252 newIcon = IconRepository.getIcon("vol75.png");
253 else // maxing
254 newIcon = IconRepository.getIcon("vol100.png");
255
256 SwingMiscManager.setJButtonIcon(muteButton, newIcon);
257 }
258
259 @Override
260 protected void paintInternal()
261 {
262 Graphics2D g = SwingMiscManager.getIfUsingSwingGraphicsManager().getCurrentSurface();
263 AxisAlignedBoxBounds bounds = getBounds();
264
265 g.translate(bounds.getMinX(), bounds.getMinY());
266 panel.paint(g);
267 g.translate(-bounds.getMinX(), -bounds.getMinY());
268 }
269
270 @Override
271 public AxisAlignedBoxBounds getFullBounds()
272 {
273 return SwingConversions.fromSwingRectangle(panel.getBounds());
274 }
275
276 public abstract void actionPerformed(ActionEvent e);
277
278 /**
279 * Invoke when the slider changes via the user (i.e. not from a model-changed to event)
280 */
281 protected abstract void volumeChanged();
282
283 /**
284 * Invoke when mute button toggles via the user (i.e. not from a model-changed to event)
285 */
286 protected abstract void muteChanged();
287
288 /**
289 * Invoke when solo button toggles via the user (i.e. not from a model-changed to event)
290 */
291 protected abstract void soloChanged();
292
293 protected abstract void beatDetectChanged();
294
295
296 /**
297 * Updates the volume GUI.
298 * {@link #volumeChanged()} is not raised as a result of this call.
299 *
300 * @param vol
301 * The volume ranging from 0 - 100. Clamped.
302 */
303 public void updateVolume(int vol) {
304
305 if (volumeSlider.getValue() == vol) return;
306
307 // Clamp
308 if(vol < 0) vol = 0;
309 else if (vol > 100) vol = 100;
310
311 isUpdatingGUI = true;
312
313 volumeSlider.setValue(vol);
314
315 isUpdatingGUI = false;
316 }
317
318
319 /**
320 * Updates the mute button GUI.
321 * {@link #muteChanged()} is not raised as a result of this call.
322 *
323 * @param isMuted
324 * True if set gui to muted.
325 */
326 public void updateMute(boolean isMuted) {
327
328 if (muteButton.isSelected() == isMuted) return;
329
330 isUpdatingGUI = true;
331
332 muteButton.setSelected(isMuted);
333
334 isUpdatingGUI = false;
335 }
336
337
338 /**
339 * Updates the solo button GUI.
340 * {@link #muteChanged()} is not raised as a result of this call.
341 *
342 * @param isSolo
343 * True if set gui to solo on.
344 */
345 public void updateSolo(boolean isSolo) {
346
347 if (soloButton.isSelected() == isSolo) return;
348
349 isUpdatingGUI = true;
350
351 soloButton.setSelected(isSolo);
352
353 isUpdatingGUI = false;
354 }
355
356
357}
Note: See TracBrowser for help on using the repository browser.