source: trunk/src_apollo/org/apollo/gui/VolumeControlButton.java@ 343

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

GUI Improvements

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