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

Last change on this file since 335 was 335, checked in by bjn8, 16 years ago
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.STOPPED_TRACK_EDGE_THICKNESS);
122
123 }
124
125 private void updateInterface() {
126
127 interfaceIsUpdating = true;
128
129 try {
130
131 tempoLabel.setText("Tempo: " + Metronome.getInstance().getTempo());
132 bpmSlider.setValue(Math.min(Metronome.getInstance().getTempo(), MAX_BPM));
133
134 if (Metronome.getInstance().isPlaying()) {
135 startStopButton.setIcon(IconRepository.getIcon("metrostop.png"));
136 setWidgetEdgeThickness(TrackWidgetCommons.PLAYING_TRACK_EDGE_THICKNESS);
137
138 } else {
139 startStopButton.setIcon(IconRepository.getIcon("metroplay.png"));
140 setWidgetEdgeThickness(TrackWidgetCommons.STOPPED_TRACK_EDGE_THICKNESS);
141 }
142
143 int index = Math.min(beatsPerMeasureCombo.getItemCount(), Metronome.getInstance().getBeatsPerMeasure()) - 1;
144 beatsPerMeasureCombo.setSelectedIndex(index);
145
146 enabledCheckbox.setSelected(Metronome.getInstance().isEnabled());
147 if (Metronome.getInstance().isEnabled()) {
148 enabledCheckbox.setText("Auto-start on");
149 } else {
150 enabledCheckbox.setText("Auto-start off");
151 }
152
153 } finally {
154 interfaceIsUpdating = false;
155 }
156
157 }
158
159 @Override
160 protected String[] getArgs() {
161 return null;
162 }
163
164 public Subject getObservedSubject() {
165 return Metronome.getInstance();
166 }
167
168 public void setObservedSubject(Subject parent) {
169 // Ignore
170 }
171
172 public void modelChanged(Subject source, SubjectChangedEvent event) {
173
174 if (source != Metronome.getInstance()) return;
175
176 switch (event.getID()) {
177 case ApolloSubjectChangedEvent.METRONOME_BEATS_PER_MEASURE_CHANGED:
178 case ApolloSubjectChangedEvent.METRONOME_STARTED:
179 case ApolloSubjectChangedEvent.METRONOME_STOPPED:
180 case ApolloSubjectChangedEvent.METRONOME_TEMPO_CHANGED:
181 case ApolloSubjectChangedEvent.METRONOME_ENABLED_CHANGED:
182 updateInterface();
183 break;
184 }
185
186 }
187
188 @Override
189 protected void onParentStateChanged(int eventType) {
190 super.onParentStateChanged(eventType);
191
192 // Be sure to remove self when removed from view .. so the widget does not hang
193 // around in memory forever
194 switch (eventType) {
195
196 case ItemParentStateChangedEvent.EVENT_TYPE_REMOVED:
197 case ItemParentStateChangedEvent.EVENT_TYPE_REMOVED_VIA_OVERLAY:
198 case ItemParentStateChangedEvent.EVENT_TYPE_HIDDEN:
199 Metronome.getInstance().removeObserver(this);
200 break;
201
202 case ItemParentStateChangedEvent.EVENT_TYPE_ADDED:
203 case ItemParentStateChangedEvent.EVENT_TYPE_ADDED_VIA_OVERLAY:
204 case ItemParentStateChangedEvent.EVENT_TYPE_SHOWN:
205 case ItemParentStateChangedEvent.EVENT_TYPE_SHOWN_VIA_OVERLAY:
206 Metronome.getInstance().addObserver(this);
207 break;
208
209 }
210 }
211
212 @Override
213 public boolean isWidgetEdgeThicknessAdjustable() {
214 return false;
215 }
216
217}
Note: See TracBrowser for help on using the repository browser.