source: trunk/src_apollo/org/apollo/widgets/MetronomePlayer.java@ 333

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

Improved recording interactions for faster idea capturing.
Various fixes for interactive widgets

File size: 6.0 KB
Line 
1package org.apollo.widgets;
2
3import java.awt.Dimension;
4import java.awt.event.ActionEvent;
5import java.awt.event.ActionListener;
6
7import javax.sound.midi.MidiUnavailableException;
8import javax.swing.JButton;
9import javax.swing.JCheckBox;
10import javax.swing.JComboBox;
11import javax.swing.JLabel;
12import javax.swing.JPanel;
13import javax.swing.JSlider;
14import javax.swing.event.ChangeEvent;
15import javax.swing.event.ChangeListener;
16
17import org.apollo.audio.ApolloSubjectChangedEvent;
18import org.apollo.audio.Metronome;
19import org.apollo.io.IconRepository;
20import org.apollo.mvc.Observer;
21import org.apollo.mvc.Subject;
22import org.apollo.mvc.SubjectChangedEvent;
23import org.expeditee.items.ItemParentStateChangedEvent;
24import org.expeditee.items.Text;
25import org.expeditee.items.widgets.InteractiveWidget;
26
27/**
28 * A widget to provide an interface for the simple Metronome facility in Apollo
29 *
30 * MVC Design pattern
31 *
32 * @author Brook Novak
33 *
34 */
35public class MetronomePlayer extends InteractiveWidget implements Observer {
36
37 private JLabel tempoLabel;
38 private JSlider bpmSlider;
39 private JButton startStopButton;
40 private JComboBox beatsPerMeasureCombo;
41 private JCheckBox enabledCheckbox;
42 private boolean interfaceIsUpdating = false;
43
44 private static final int MAX_BPM = 300;
45
46 public MetronomePlayer(Text source, String[] args) {
47 super(source, new JPanel(), 130, 130, 175, 175);
48
49 tempoLabel = new JLabel();
50 bpmSlider = new JSlider();
51 bpmSlider.setMinimum(1);
52 bpmSlider.setMaximum(MAX_BPM);
53 bpmSlider.setMajorTickSpacing(20);
54 bpmSlider.setValue(100);
55 bpmSlider.setPreferredSize(new Dimension(120, 20));
56 bpmSlider.addChangeListener(new ChangeListener() {
57 public void stateChanged(ChangeEvent e) {
58
59 if (!interfaceIsUpdating) {
60 try {
61 Metronome.getInstance().setTempo(bpmSlider.getValue());
62 } catch (MidiUnavailableException e1) {
63 e1.printStackTrace();
64 }
65 }
66
67 }
68 });
69
70 startStopButton = new JButton();
71 startStopButton.setPreferredSize(new Dimension(40, 40));
72 startStopButton.addActionListener(new ActionListener() {
73 public void actionPerformed(ActionEvent e) {
74 if (Metronome.getInstance().isPlaying()) {
75 Metronome.getInstance().stop();
76 } else {
77 try {
78 Metronome.getInstance().start();
79 } catch (MidiUnavailableException e1) {
80 e1.printStackTrace();
81 }
82 }
83 }
84 });
85
86 beatsPerMeasureCombo = new JComboBox(new String[]{"1", "2", "3", "4", "5", "6", "7", "8"});
87 beatsPerMeasureCombo.setPreferredSize(new Dimension(60, 25));
88 beatsPerMeasureCombo.setEditable(false);
89 beatsPerMeasureCombo.addActionListener(new ActionListener() {
90
91 public void actionPerformed(ActionEvent e) {
92
93 if (!interfaceIsUpdating) {
94 Metronome.getInstance().setBeatsPerMeasure(beatsPerMeasureCombo.getSelectedIndex() + 1);
95 }
96
97 }
98
99 });
100
101 enabledCheckbox = new JCheckBox("Auto-start");
102 enabledCheckbox.addActionListener(new ActionListener() {
103
104 public void actionPerformed(ActionEvent e) {
105 if (!interfaceIsUpdating) {
106 Metronome.getInstance().setEnabled(enabledCheckbox.isSelected());
107 }
108 }
109
110 });
111
112 updateInterface();
113
114 _swingComponent.add(tempoLabel);
115 _swingComponent.add(bpmSlider);
116 _swingComponent.add(startStopButton);
117 _swingComponent.add(new JLabel("Beats per measure:"));
118 _swingComponent.add(beatsPerMeasureCombo);
119 _swingComponent.add(enabledCheckbox);
120
121 setWidgetEdgeThickness(TrackWidgetCommons.PLAYING_TRACK_EDGE_THICKNESS); // TODO: Fix this work around
122 setWidgetEdgeThickness(TrackWidgetCommons.STOPPED_TRACK_EDGE_THICKNESS);
123
124 }
125
126 private void updateInterface() {
127
128 interfaceIsUpdating = true;
129
130 try {
131
132 tempoLabel.setText("Tempo: " + Metronome.getInstance().getTempo());
133 bpmSlider.setValue(Math.min(Metronome.getInstance().getTempo(), MAX_BPM));
134
135 if (Metronome.getInstance().isPlaying()) {
136 startStopButton.setIcon(IconRepository.getIcon("metrostop.png"));
137 setWidgetEdgeThickness(TrackWidgetCommons.PLAYING_TRACK_EDGE_THICKNESS);
138
139 } else {
140 startStopButton.setIcon(IconRepository.getIcon("metroplay.png"));
141 setWidgetEdgeThickness(TrackWidgetCommons.STOPPED_TRACK_EDGE_THICKNESS);
142 }
143
144 int index = Math.min(beatsPerMeasureCombo.getItemCount(), Metronome.getInstance().getBeatsPerMeasure()) - 1;
145 beatsPerMeasureCombo.setSelectedIndex(index);
146
147 enabledCheckbox.setSelected(Metronome.getInstance().isEnabled());
148 if (Metronome.getInstance().isEnabled()) {
149 enabledCheckbox.setText("Auto-start on");
150 } else {
151 enabledCheckbox.setText("Auto-start off");
152 }
153
154 } finally {
155 interfaceIsUpdating = false;
156 }
157
158 }
159
160 @Override
161 protected String[] getArgs() {
162 return null;
163 }
164
165 public Subject getObservedSubject() {
166 return Metronome.getInstance();
167 }
168
169 public void setObservedSubject(Subject parent) {
170 // Ignore
171 }
172
173 public void modelChanged(Subject source, SubjectChangedEvent event) {
174
175 if (source != Metronome.getInstance()) return;
176
177 switch (event.getID()) {
178 case ApolloSubjectChangedEvent.METRONOME_BEATS_PER_MEASURE_CHANGED:
179 case ApolloSubjectChangedEvent.METRONOME_STARTED:
180 case ApolloSubjectChangedEvent.METRONOME_STOPPED:
181 case ApolloSubjectChangedEvent.METRONOME_TEMPO_CHANGED:
182 case ApolloSubjectChangedEvent.METRONOME_ENABLED_CHANGED:
183 updateInterface();
184 break;
185 }
186
187 }
188
189 @Override
190 protected void onParentStateChanged(int eventType) {
191 super.onParentStateChanged(eventType);
192
193 // Be sure to remove self when removed from view .. so the widget does not hang
194 // around in memory forever
195 switch (eventType) {
196
197 case ItemParentStateChangedEvent.EVENT_TYPE_REMOVED:
198 case ItemParentStateChangedEvent.EVENT_TYPE_REMOVED_VIA_OVERLAY:
199 case ItemParentStateChangedEvent.EVENT_TYPE_HIDDEN:
200 Metronome.getInstance().removeObserver(this);
201 break;
202
203 case ItemParentStateChangedEvent.EVENT_TYPE_ADDED:
204 case ItemParentStateChangedEvent.EVENT_TYPE_ADDED_VIA_OVERLAY:
205 case ItemParentStateChangedEvent.EVENT_TYPE_SHOWN:
206 case ItemParentStateChangedEvent.EVENT_TYPE_SHOWN_VIA_OVERLAY:
207 Metronome.getInstance().addObserver(this);
208 break;
209
210 }
211 }
212
213
214}
Note: See TracBrowser for help on using the repository browser.