source: trunk/src/org/apollo/gui/VolumeControlButton.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: 9.0 KB
Line 
1package org.apollo.gui;
2
3import java.awt.Dimension;
4import java.awt.GridBagConstraints;
5import java.awt.GridBagLayout;
6import java.awt.Insets;
7import java.awt.event.ActionEvent;
8import java.awt.event.ActionListener;
9import java.util.LinkedList;
10import java.util.List;
11
12import javax.swing.JButton;
13import javax.swing.JPanel;
14import javax.swing.JSlider;
15import javax.swing.event.ChangeEvent;
16import javax.swing.event.ChangeListener;
17
18import org.apollo.io.IconRepository;
19import org.expeditee.core.Colour;
20import org.expeditee.core.Image;
21import org.expeditee.core.bounds.AxisAlignedBoxBounds;
22import org.expeditee.gio.swing.SwingConversions;
23import org.expeditee.gio.swing.SwingMiscManager;
24import org.expeditee.gui.Popup;
25import org.expeditee.gui.PopupManager;
26import org.expeditee.gui.PopupManager.ExpandShrinkAnimator;
27
28/**
29 * A volume control button which can be reused in multiple situations... Follows swings MVC pattern.
30 *
31 * @author Brook Novak
32 */
33public class VolumeControlButton extends JButton {
34
35 private static final long serialVersionUID = 1L;
36
37 private VolumeControlPopup vcPopup;
38
39 private int volumeValue = 0;
40 private boolean muted = false;
41
42 private List<ChangeListener> changeListeners = new LinkedList<ChangeListener>();
43
44 private String volumeTag;
45
46 private Colour SELECTED_BACKCOLOR = Colour.GRAY;
47 private Colour UNSELECTED_BACKCOLOR = null;
48
49 private static final int VOL_ADJUSTMENT = 10;
50 private static final int VOL_HEIGHT = 150;
51
52 /**
53 * @param volumeTag
54 * The tag line to appear before the volume value in the tip tool text.
55 * Null = no tag line.
56 * E.G. "Master Volume".
57 */
58 public VolumeControlButton(String volumeTag)
59 {
60 super();
61 UNSELECTED_BACKCOLOR = SwingConversions.fromSwingColor(getBackground());
62 vcPopup = new VolumeControlPopup();
63 PopupManager.getInstance().add(vcPopup);
64 this.volumeTag = volumeTag;
65 toggleSelectionState(false);
66 updateButtonGUI();
67 }
68
69 /**
70 * Adds a change listener which will be notified whenever the volume value
71 * changes via the GUI.
72 *
73 * @param listener
74 */
75 public void addVolumeChangeListener(ChangeListener listener)
76 {
77 assert(listener != null);
78 changeListeners.add(listener);
79 }
80
81 private void fireVolumeChanged()
82 {
83 for (ChangeListener a : changeListeners) {
84 a.stateChanged(new ChangeEvent(this));
85 }
86 }
87
88 private void toggleSelectionState(boolean selected)
89 {
90 if (selected) {
91 setBackground(SwingConversions.toSwingColor(SELECTED_BACKCOLOR));
92 } else {
93 setBackground(SwingConversions.toSwingColor(UNSELECTED_BACKCOLOR));
94 }
95 }
96
97 /**
98 * {@inheritDoc}
99 * Displays the volume control popup when the button is pressed
100 */
101 @Override
102 protected void fireActionPerformed(ActionEvent event)
103 {
104 super.fireActionPerformed(event);
105
106 if (!vcPopup.isShowing()) { // show popup
107 vcPopup.showPopup();
108 } else { // hide popup
109 vcPopup.hide();
110 }
111 }
112
113 /**
114 * Sets the volume GUI. This will not fire any event - it will just update the gui.
115 * @param n
116 * return true if changed
117 */
118 public boolean setVolumeValue(int n) {
119
120 // Clamp
121 if (n > 100) n = 100;
122 else if (n < 0) n = 0;
123
124 if (n != volumeValue) {
125 volumeValue = n;
126 updateButtonGUI();
127 vcPopup.updatePopupGUI();
128 return true;
129 }
130
131 return false;
132 }
133
134 /**
135 * Sets the volume GUI. This will not fire any event - it will just update the gui.
136 *
137 * @param mute
138 *
139 * @return
140 */
141 public void setMuted(boolean mute)
142 {
143 muted = mute;
144 updateButtonGUI();
145 }
146
147
148 private void updateButtonGUI()
149 {
150 Image newIcon;
151 if(muted)
152 newIcon = IconRepository.getIcon("volmute.png");
153 else if (volumeValue <= 25)
154 newIcon = IconRepository.getIcon("vol25.png");
155 else if (volumeValue <= 50)
156 newIcon = IconRepository.getIcon("vol50.png");
157 else if (volumeValue <= 75)
158 newIcon = IconRepository.getIcon("vol75.png");
159 else // maxing
160 newIcon = IconRepository.getIcon("vol100.png");
161
162 if (newIcon != getIcon()) SwingMiscManager.setJButtonIcon(this, newIcon);
163
164 if (muted) {
165 if (volumeTag != null) {
166 setToolTipText(volumeTag + ": Muted");
167 } else {
168 setToolTipText("Muted");
169 }
170 } else {
171 if (volumeTag != null) {
172 setToolTipText(volumeTag + ": " + volumeValue + "%");
173 } else {
174 setToolTipText(volumeValue + "%");
175 }
176 }
177 }
178
179 /**
180 *
181 * @return The volume value of the gui
182 */
183 public int getVolumeValue()
184 {
185 return volumeValue;
186 }
187
188
189 /**
190 *
191 * @return The mute value of the gui
192 */
193 public boolean getMuteValue()
194 {
195 return muted;
196 }
197
198 private class VolumeControlPopup extends Popup
199 {
200 private JPanel panel;
201 private JSlider volumeSlider;
202 private JButton increaseButton;
203 private JButton decreaseButton;
204
205 /**
206 * Constructor.
207 */
208 public VolumeControlPopup()
209 {
210 super(new ExpandShrinkAnimator());
211
212 panel = new JPanel();
213
214 volumeSlider = new JSlider(JSlider.VERTICAL);
215 volumeSlider.setMinimum(0);
216 volumeSlider.setMaximum(100);
217 volumeSlider.addChangeListener(new ChangeListener() {
218 public void stateChanged(ChangeEvent e) {
219 onVolumeSliderChanged();
220 }
221 });
222
223 increaseButton = new JButton();
224 //increaseButton.setIcon(IconRepository.getIcon("incvol.ico"));
225 increaseButton.setText("+");
226 increaseButton.addActionListener( new ActionListener() {
227 public void actionPerformed(ActionEvent e) {
228 onIncrementVolume();
229 }
230 });
231
232 decreaseButton = new JButton();
233 //decreaseButton.setIcon(IconRepository.getIcon("decvol.ico"));
234 decreaseButton.setText("-");
235 decreaseButton.addActionListener( new ActionListener() {
236 public void actionPerformed(ActionEvent e) {
237 onDeincrementVolume();
238 }
239 });
240
241 updatePopupGUI();
242 }
243
244 private void onIncrementVolume()
245 {
246 if (setVolumeValue(volumeValue + VOL_ADJUSTMENT)) {
247 fireVolumeChanged();
248 }
249 }
250
251 private void onDeincrementVolume()
252 {
253 if (setVolumeValue(volumeValue - VOL_ADJUSTMENT)) {
254 fireVolumeChanged();
255 }
256 }
257
258 private void onVolumeSliderChanged()
259 {
260 if (setVolumeValue(volumeSlider.getValue())) {
261 fireVolumeChanged();
262 }
263 }
264
265 private void updatePopupGUI()
266 {
267 volumeSlider.setValue(volumeValue);
268 increaseButton.setEnabled(volumeValue < 100);
269 decreaseButton.setEnabled(volumeValue > 0);
270 }
271
272 private void prepLayout()
273 {
274 if (panel.getComponents().length == 0) {
275
276 final int INNER_SPACING = 0;
277 final int OUTER_SPACING = 0;
278 final int YPAD = 0;
279 final int BUTTON_MARGIN = 0;
280
281 int targetWidth = VolumeControlButton.this.getWidth();
282 Dimension buttonSizes = new Dimension(targetWidth, targetWidth);
283
284 decreaseButton.setPreferredSize(buttonSizes);
285 increaseButton.setPreferredSize(buttonSizes);
286 volumeSlider.setPreferredSize(new Dimension(volumeSlider.getWidth(), VOL_HEIGHT));
287 decreaseButton.setSize(buttonSizes);
288 increaseButton.setSize(buttonSizes);
289 volumeSlider.setSize(new Dimension(volumeSlider.getWidth(), VOL_HEIGHT));
290
291 increaseButton.setMargin(new Insets(BUTTON_MARGIN,BUTTON_MARGIN,BUTTON_MARGIN,BUTTON_MARGIN));
292 decreaseButton.setMargin(increaseButton.getMargin());
293
294 GridBagLayout layout = new GridBagLayout();
295
296 layout.rowHeights = new int[] {
297 increaseButton.getHeight(), volumeSlider.getHeight(), decreaseButton.getHeight()
298 };
299
300 setLayout(layout);
301
302 GridBagConstraints c = new GridBagConstraints();
303 c.gridx = 0;
304 c.gridy = 0;
305 c.fill = GridBagConstraints.BOTH;
306 c.insets = new Insets(OUTER_SPACING,OUTER_SPACING,INNER_SPACING,OUTER_SPACING);
307 c.ipady = YPAD;
308 panel.add(increaseButton, c);
309
310 c = new GridBagConstraints();
311 c.gridx = 0;
312 c.gridy = 1;
313 c.fill = GridBagConstraints.BOTH;
314 c.insets = new Insets(INNER_SPACING,OUTER_SPACING,INNER_SPACING,OUTER_SPACING);
315 c.ipady = YPAD;
316 panel.add(volumeSlider, c);
317
318 c = new GridBagConstraints();
319 c.gridx = 0;
320 c.gridy = 2;
321 c.fill = GridBagConstraints.BOTH;
322 c.insets = new Insets(INNER_SPACING,OUTER_SPACING,OUTER_SPACING,OUTER_SPACING);
323 c.ipady = YPAD;
324 panel.add(decreaseButton, c);
325
326 setSize(targetWidth, volumeSlider.getHeight() + (2 * buttonSizes.height) + (2 * OUTER_SPACING));
327 panel.doLayout();
328 }
329
330 }
331
332 private void showPopup()
333 {
334 prepLayout();
335 show();
336 }
337
338 @Override
339 public void onHide() {
340 // Toggle state = volume popup showing
341 toggleSelectionState(false);
342 }
343
344 @Override
345 public void onShow() {
346 // Toggle state = volume popup showing
347 toggleSelectionState(true);
348 }
349
350 @Override
351 public boolean shouldConsumeBackClick()
352 {
353 return true;
354 }
355
356 @Override
357 protected void paintInternal()
358 {
359 // TODO Auto-generated method stub
360
361 }
362
363 @Override
364 public AxisAlignedBoxBounds getFullBounds()
365 {
366 // Determine where popup should show
367 int x = VolumeControlButton.this.getX();
368 int y = VolumeControlButton.this.getY() - getHeight() - 2; // by default show above
369
370 if (y < 0) {
371 y = VolumeControlButton.this.getY() + VolumeControlButton.this.getHeight() + 2;
372 }
373
374 return new AxisAlignedBoxBounds(x, y, VolumeControlButton.this.getBounds().width, VolumeControlButton.this.getBounds().height);
375 }
376 }
377}
Note: See TracBrowser for help on using the repository browser.