source: trunk/src/org/apollo/widgets/MetronomePlayer.java@ 1102

Last change on this file since 1102 was 1102, checked in by davidb, 6 years ago

Reworking of the code-base to separate logic from graphics. This version of Expeditee now supports a JFX graphics as an alternative to SWING

File size: 6.1 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.gio.swing.SwingMiscManager;
24import org.expeditee.items.ItemParentStateChangedEvent;
25import org.expeditee.items.Text;
26import org.expeditee.items.widgets.SwingWidget;
27
28/**
29 * A widget to provide an interface for the simple Metronome facility in Apollo
30 *
31 * MVC Design pattern
32 *
33 * @author Brook Novak
34 *
35 */
36public class MetronomePlayer extends SwingWidget implements Observer {
37
38 private JLabel tempoLabel;
39 private JSlider bpmSlider;
40 private JButton startStopButton;
41 private JComboBox<String> beatsPerMeasureCombo;
42 private JCheckBox enabledCheckbox;
43 private boolean interfaceIsUpdating = false;
44
45 private static final int MAX_BPM = 300;
46
47 public MetronomePlayer(Text source, String[] args) {
48 super(source, new JPanel(), 130, 130, 175, 175);
49
50 tempoLabel = new JLabel();
51 bpmSlider = new JSlider();
52 bpmSlider.setMinimum(1);
53 bpmSlider.setMaximum(MAX_BPM);
54 bpmSlider.setMajorTickSpacing(20);
55 bpmSlider.setValue(100);
56 bpmSlider.setPreferredSize(new Dimension(120, 20));
57 bpmSlider.addChangeListener(new ChangeListener() {
58 public void stateChanged(ChangeEvent e) {
59
60 if (!interfaceIsUpdating) {
61 try {
62 Metronome.getInstance().setTempo(bpmSlider.getValue());
63 } catch (MidiUnavailableException e1) {
64 e1.printStackTrace();
65 }
66 }
67
68 }
69 });
70
71 startStopButton = new JButton();
72 startStopButton.setPreferredSize(new Dimension(40, 40));
73 startStopButton.addActionListener(new ActionListener() {
74 public void actionPerformed(ActionEvent e) {
75 if (Metronome.getInstance().isPlaying()) {
76 Metronome.getInstance().stop();
77 } else {
78 try {
79 Metronome.getInstance().start();
80 } catch (MidiUnavailableException e1) {
81 e1.printStackTrace();
82 }
83 }
84 }
85 });
86
87 beatsPerMeasureCombo = new JComboBox<String>(new String[]{"1", "2", "3", "4", "5", "6", "7", "8"});
88 beatsPerMeasureCombo.setPreferredSize(new Dimension(60, 25));
89 beatsPerMeasureCombo.setEditable(false);
90 beatsPerMeasureCombo.addActionListener(new ActionListener() {
91
92 public void actionPerformed(ActionEvent e) {
93
94 if (!interfaceIsUpdating) {
95 Metronome.getInstance().setBeatsPerMeasure(beatsPerMeasureCombo.getSelectedIndex() + 1);
96 }
97
98 }
99
100 });
101
102 enabledCheckbox = new JCheckBox("Auto-start");
103 enabledCheckbox.addActionListener(new ActionListener() {
104
105 public void actionPerformed(ActionEvent e) {
106 if (!interfaceIsUpdating) {
107 Metronome.getInstance().setEnabled(enabledCheckbox.isSelected());
108 }
109 }
110
111 });
112
113 updateInterface();
114
115 _swingComponent.add(tempoLabel);
116 _swingComponent.add(bpmSlider);
117 _swingComponent.add(startStopButton);
118 _swingComponent.add(new JLabel("Beats per measure:"));
119 _swingComponent.add(beatsPerMeasureCombo);
120 _swingComponent.add(enabledCheckbox);
121
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 SwingMiscManager.setJButtonIcon(startStopButton, IconRepository.getIcon("metrostop.png"));
137 setWidgetEdgeThickness(TrackWidgetCommons.PLAYING_TRACK_EDGE_THICKNESS);
138
139 } else {
140 SwingMiscManager.setJButtonIcon(startStopButton, 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 @Override
214 public boolean isWidgetEdgeThicknessAdjustable() {
215 return false;
216 }
217
218}
Note: See TracBrowser for help on using the repository browser.