001: /*
002: * Javu WingS - Lightweight Java Component Set
003: * Copyright (c) 2005-2007 Krzysztof A. Sadlocha
004: * e-mail: ksadlocha@programics.com
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2.1 of the License, or (at your option) any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: */
020:
021: package com.javujavu.javux.wings;
022:
023: import java.awt.Dimension;
024: import java.awt.event.ActionEvent;
025: import java.awt.event.FocusEvent;
026: import java.awt.event.KeyEvent;
027: import java.awt.event.MouseEvent;
028: import java.awt.event.MouseListener;
029: import java.util.Vector;
030:
031: /**
032: * This class allows a user to choose from a range of numeric values
033: * by 'spinning' through the values by clicking the up or down
034: * arrows on the spinner or by typing a value into the spinner box
035: * <br>
036: * <br>
037: * <b>This class is thread safe.</b>
038: **/
039: public class WingSpinner extends WingComponent implements MouseListener {
040: protected static class Range {
041: Range(int min, int max, int step, String text) {
042: if ((max - min) % step != 0) {
043: max = max - ((max - min) % step);
044: }
045: this .min = min;
046: this .max = max;
047: this .step = step;
048: this .text = text;
049: }
050:
051: int min;
052: int max;
053: int step;
054: String text;
055: }
056:
057: protected/*final*/Vector ranges;
058: private/*final*/WingButton inc;
059: private/*final*/WingButton dec;
060: private/*final*/WingTextField edit;
061:
062: private int value;
063: private String stringValue;
064:
065: public WingSpinner() {
066: ranges = new Vector();
067: edit = new WingTextField(stringValue = "0", 8);
068: this .add(edit);
069: inc = new WingButton();
070: dec = new WingButton();
071: this .add(inc);
072: this .add(dec);
073: edit.addMouseListener(this );
074: inc.setRepeat(true);
075: inc.setShortcut(KeyEvent.VK_UP, 0);
076: dec.setRepeat(true);
077: dec.setShortcut(KeyEvent.VK_DOWN, 0);
078: setWingFocusable(true);
079: edit.setWingFocusable(false);
080: inc.setWingFocusable(false);
081: dec.setWingFocusable(false);
082:
083: WingToolkit.the().addWheelListener(this , this );
084:
085: enableEvents(FocusEvent.FOCUS_EVENT_MASK);
086:
087: setStyleId(null);
088: }
089:
090: public void setStyleId(String styleId) {
091: super .setStyleId(styleId);
092: edit.setStyleId(WingSkin.catKeys(styleId, "spin"));
093: inc.setStyleId(WingSkin.catKeys(styleId, "inc.spin"));
094: dec.setStyleId(WingSkin.catKeys(styleId, "dec.spin"));
095: }
096:
097: public void setEnabled(boolean b) {
098: super .setEnabled(b);
099: edit.setEnabled(b);
100: dec.setEnabled(b);
101: inc.setEnabled(b);
102: }
103:
104: public void setTooltip(Object tooltip) {
105: edit.setTooltip(tooltip);
106: dec.setTooltip(tooltip);
107: inc.setTooltip(tooltip);
108: }
109:
110: public void setHorizontalAlignment(int alignment) {
111: edit.setHorizontalAlignment(alignment);
112: }
113:
114: public Dimension getPreferredSize() {
115: Dimension prefSize = wingPrefSize;
116: if (prefSize == null) {
117: prefSize = new Dimension(edit.getPreferredSize());
118: Dimension d2 = dec.getPreferredSize();
119: prefSize.width += d2.width;
120: wingPrefSize = prefSize;
121: }
122: return prefSize;
123: }
124:
125: public void doLayout() {
126: Dimension d = getSize();
127: Dimension d2 = dec.getPreferredSize();
128: edit.setBounds(0, 0, d.width - d2.width, d.height);
129: inc.setBounds(d.width - d2.width, 0, d2.width, d.height / 2);
130: dec.setBounds(d.width - d2.width, d.height / 2, d2.width,
131: d.height - (d.height / 2));
132: }
133:
134: public synchronized void setRange(int min, int max) {
135: removeAllRanges();
136: addRange(new Range(min, max, 1, null));
137: }
138:
139: public void addRange(int min, int max, int step) {
140: addRange(new Range(min, max, step, null));
141: }
142:
143: public void addEnum(int value, String text) {
144: addRange(new Range(value, value, 1, text));
145: }
146:
147: public synchronized void removeAllRanges() {
148: ranges.removeAllElements();
149: }
150:
151: private synchronized void addRange(Range r) {
152: ranges.addElement(r);
153:
154: int cols = 4;
155: for (int i = 0; i < ranges.size(); i++) {
156: Range r2 = (Range) ranges.elementAt(i);
157: int k, c;
158: if (r2.text != null)
159: c = r2.text.length();
160: else {
161: for (k = r2.max, c = 1; k > 0; k = k / 10)
162: c++;
163: }
164: if (cols < c)
165: cols = c;
166: }
167: edit.setColumns(cols);
168:
169: revalidateAndRepaint();
170: }
171:
172: public synchronized void setValue(int value) {
173: Range r;
174: int i;
175: this .value = value;
176: for (i = 0; i < ranges.size(); i++) {
177: r = (Range) ranges.elementAt(i);
178: if (r.min <= value && r.max >= value && r.text != null) {
179: edit.setText(stringValue = r.text);
180: return;
181: }
182: }
183: edit.setText(stringValue = String.valueOf(value));
184: }
185:
186: public int getValue() {
187: editToValue();
188: return value;
189: }
190:
191: protected void spinAdjust(boolean inc) {
192: String postText = null;
193: synchronized (this ) {
194: Range r = null;
195: int i, v = value, lastRange;
196: if (ranges.size() == 0)
197: v = v + ((inc) ? 1 : -1);
198: else {
199: lastRange = ranges.size() - 1;
200: if (inc) {
201: for (i = 0; i <= lastRange; i++) {
202: r = (Range) ranges.elementAt(i);
203: if (v < r.min) {
204: v = r.min;
205: } else if (v < r.max) {
206: v += r.step;
207: } else if (i == lastRange) {
208: r = (Range) ranges.firstElement();
209: v = r.min;
210: } else
211: continue;
212: break;
213: }
214: } else {
215: for (i = lastRange; i >= 0; i--) {
216: r = (Range) ranges.elementAt(i);
217: if (v > r.max) {
218: v = r.max;
219: } else if (v > r.min) {
220: v -= r.step;
221: } else if (i == 0) {
222: r = (Range) ranges.lastElement();
223: v = r.max;
224: } else
225: continue;
226: break;
227: }
228: }
229: }
230: if (v != value) {
231: if (r != null && r.text != null)
232: stringValue = r.text;
233: else
234: stringValue = String.valueOf(v);
235: value = v;
236: edit.setText(stringValue);
237: postText = stringValue;
238: }
239: }
240: if (postText != null) {
241: wingProcessActionEvent(new ActionEvent(this ,
242: ActionEvent.ACTION_PERFORMED, postText));
243: }
244: }
245:
246: protected void processFocusEvent(FocusEvent e) {
247: edit.processFocusEvent(e);
248: super .processFocusEvent(e);
249: }
250:
251: protected void wingProcessKeyEvent(KeyEvent e,
252: WingComponent redirecting) {
253: if (redirecting == this )
254: return;
255:
256: int key = e.getKeyCode();
257: if (key == KeyEvent.VK_UP) {
258: inc.processShortcut(e);
259: } else if (key == KeyEvent.VK_DOWN) {
260: dec.processShortcut(e);
261: }
262: if (!e.isConsumed()) {
263: edit.wingProcessKeyEvent(e, this );
264: }
265: super .wingProcessKeyEvent(e, redirecting);
266: }
267:
268: public void mouseWheelMoved(Object src, int rotation) {
269: if (isEnabled())
270: spinAdjust(rotation < 0);
271: }
272:
273: private synchronized String editToValue() {
274: String postText = null;
275: int i, v, v2 = value;
276: String text = edit.getText();
277: if (stringValue.equals(text))
278: return null;
279: Range r = null;
280: try {
281: v = Integer.parseInt(text);
282: for (i = 0; i < ranges.size(); i++) {
283: r = (Range) ranges.elementAt(i);
284: if (v >= r.min && v <= r.max
285: && (v - r.min) % r.step == 0) {
286: v2 = v;
287: break;
288: }
289: }
290: if (ranges.size() == 0)
291: v2 = v;
292: } catch (NumberFormatException e2) {
293: for (i = 0; i < ranges.size(); i++) {
294: r = (Range) ranges.elementAt(i);
295: if (r.text != null && r.text.equalsIgnoreCase(text)) {
296: v2 = r.min;
297: break;
298: }
299: }
300: }
301: if (v2 != value) {
302: value = v2;
303: if (r != null && r.text != null)
304: stringValue = r.text;
305: else
306: stringValue = String.valueOf(v2);
307: postText = stringValue;
308: }
309: edit.setText(stringValue);
310: return postText;
311: }
312:
313: public void wingProcessActionEvent(ActionEvent e) {
314: Object src = e.getSource();
315: if (src == inc || src == dec) {
316: if (isEnabled() && wingFocusable && !edit.focused)
317: requestFocus(); //wingRequestFocusInWindow();
318: spinAdjust(src == inc);
319: } else if (src == edit) {
320: String postText = editToValue();
321: if (postText != null) {
322: wingProcessActionEvent(new ActionEvent(this ,
323: ActionEvent.ACTION_PERFORMED, postText));
324: }
325: } else
326: super .wingProcessActionEvent(e);
327: }
328:
329: public void mouseClicked(MouseEvent e) {
330: }
331:
332: public void mouseEntered(MouseEvent e) {
333: }
334:
335: public void mouseExited(MouseEvent e) {
336: }
337:
338: public void mousePressed(MouseEvent e) {
339: if (wingFocusable && !edit.focused)
340: requestFocus(); //wingRequestFocusInWindow();
341: }
342:
343: public void mouseReleased(MouseEvent e) {
344: }
345:
346: }
|