001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: /**
018: * @author Dennis Ushakov
019: * @version $Revision$
020: */package javax.swing.plaf.basic;
021:
022: import java.awt.Component;
023: import java.awt.Container;
024: import java.awt.Dimension;
025: import java.awt.Insets;
026: import java.awt.LayoutManager;
027: import java.awt.event.ActionEvent;
028: import java.awt.event.ActionListener;
029: import java.awt.event.FocusEvent;
030: import java.awt.event.FocusListener;
031: import java.awt.event.MouseEvent;
032: import java.awt.event.MouseListener;
033: import java.beans.PropertyChangeEvent;
034: import java.beans.PropertyChangeListener;
035:
036: import javax.swing.JButton;
037: import javax.swing.JComponent;
038: import javax.swing.JSpinner;
039: import javax.swing.LookAndFeel;
040: import javax.swing.Timer;
041: import javax.swing.UIManager;
042: import javax.swing.JSpinner.DefaultEditor;
043: import javax.swing.plaf.ComponentUI;
044: import javax.swing.plaf.SpinnerUI;
045:
046: import org.apache.harmony.x.swing.StringConstants;
047: import org.apache.harmony.x.swing.Utilities;
048:
049: public class BasicSpinnerUI extends SpinnerUI {
050:
051: private class PropertyChangeHandler implements
052: PropertyChangeListener {
053: public void propertyChange(final PropertyChangeEvent event) {
054: String changedProperty = event.getPropertyName();
055:
056: if (StringConstants.EDITOR_PROPERTY_CHANGED
057: .equals(changedProperty)) {
058: replaceEditor((JComponent) event.getOldValue(),
059: (JComponent) event.getNewValue());
060: }
061: }
062: }
063:
064: private class ArrowButtonHandler implements ActionListener,
065: FocusListener, MouseListener {
066: private int dir;
067: private Timer scrollTimer;
068: private static final int SCROLL_DELAY = 50;
069: private static final int PRE_SCROLL_DELAY = 300;
070: private static final int NEXT = 0;
071: private static final int PREVIOUS = 1;
072:
073: public void actionPerformed(final ActionEvent e) {
074: e.setSource(spinner);
075: if (dir == NEXT) {
076: BasicSpinnerKeyboardActions.incrementAction
077: .actionPerformed(e);
078: }
079: if (dir == PREVIOUS) {
080: BasicSpinnerKeyboardActions.decrementAction
081: .actionPerformed(e);
082: }
083: }
084:
085: public void focusGained(final FocusEvent e) {
086: editor.requestFocus();
087: }
088:
089: public void focusLost(final FocusEvent e) {
090: }
091:
092: public void mousePressed(final MouseEvent e) {
093: if (e.getSource() == nextButton) {
094: dir = NEXT;
095: } else if (e.getSource() == previousButton) {
096: dir = PREVIOUS;
097: }
098: if (scrollTimer == null) {
099: scrollTimer = new Timer(SCROLL_DELAY, this );
100: scrollTimer.setInitialDelay(PRE_SCROLL_DELAY);
101: }
102: scrollTimer.restart();
103: }
104:
105: public void mouseReleased(final MouseEvent e) {
106: if (scrollTimer != null) {
107: scrollTimer.stop();
108: }
109: }
110:
111: public void mouseClicked(final MouseEvent e) {
112: }
113:
114: public void mouseEntered(final MouseEvent e) {
115: }
116:
117: public void mouseExited(final MouseEvent e) {
118: }
119: }
120:
121: private class SpinnerLayout implements LayoutManager {
122:
123: public void addLayoutComponent(final String name,
124: final Component comp) {
125: }
126:
127: public void layoutContainer(final Container parent) {
128: int left = parent.getInsets().left;
129: int top = parent.getInsets().top;
130: int right = parent.getInsets().right;
131: int bottom = parent.getInsets().bottom;
132:
133: Dimension parentSize = parent.getSize();
134: int width = parentSize.width;
135: int height = parentSize.height;
136: int nextWidth = 0;
137: int previousWidth = 0;
138:
139: if (nextButton != null) {
140: nextButton.setSize(buttonSize);
141: nextWidth = nextButton.getWidth();
142: }
143: if (previousButton != null) {
144: previousButton.setSize(buttonSize);
145: previousWidth = previousButton.getWidth();
146: }
147:
148: int rightMargin = Math.max(nextWidth, previousWidth);
149: int leftMargin = 0;
150:
151: if (spinner.getComponentOrientation().isLeftToRight()) {
152: if (editor != null) {
153: leftMargin = width - rightMargin;
154: editor.setBounds(left, top, leftMargin - left,
155: height - bottom - top);
156: }
157: if (nextButton != null) {
158: nextButton.setBounds(leftMargin, buttonInsets.top,
159: nextButton.getWidth() - buttonInsets.right,
160: height / 2 - buttonInsets.top);
161: }
162: if (previousButton != null) {
163: previousButton.setBounds(leftMargin, height / 2,
164: previousButton.getWidth()
165: - buttonInsets.right, height / 2
166: - buttonInsets.bottom);
167: }
168: } else {
169: if (editor != null) {
170: leftMargin = width - rightMargin;
171: editor.setBounds(rightMargin, top, leftMargin
172: - right, height - bottom - top);
173: }
174: if (nextButton != null) {
175: nextButton.setBounds(buttonInsets.left,
176: buttonInsets.top, nextButton.getWidth()
177: - buttonInsets.left, height / 2
178: - buttonInsets.top);
179: }
180: if (previousButton != null) {
181: previousButton.setBounds(buttonInsets.left,
182: height / 2, previousButton.getWidth()
183: - buttonInsets.left, height / 2
184: - buttonInsets.bottom);
185: }
186: }
187: }
188:
189: public Dimension minimumLayoutSize(final Container parent) {
190: Dimension editorSize = editor != null ? editor
191: .getMinimumSize() : new Dimension();
192: Dimension result = new Dimension(editorSize.width
193: + buttonSize.width, Math.max(editorSize.height,
194: 2 * buttonSize.height));
195: return Utilities.addInsets(result, parent.getInsets());
196: }
197:
198: public Dimension preferredLayoutSize(final Container parent) {
199: Dimension editorSize = editor != null ? editor
200: .getPreferredSize() : new Dimension();
201: Dimension result = new Dimension(editorSize.width
202: + buttonSize.width, Math.max(editorSize.height,
203: 2 * buttonSize.height));
204: return Utilities.addInsets(result, parent.getInsets());
205: }
206:
207: public void removeLayoutComponent(final Component comp) {
208: }
209: }
210:
211: private static final String EDITOR_FIELD = "Editor";
212: private static final String NEXT_FIELD = "Next";
213: private static final String PREVIOUS_FIELD = "Previous";
214:
215: private Component editor;
216: private Component nextButton;
217: private Component previousButton;
218:
219: protected JSpinner spinner;
220: private PropertyChangeListener changeListener;
221: private ArrowButtonHandler buttonHandler = new ArrowButtonHandler();
222: private Dimension buttonSize;
223: private Insets buttonInsets;
224: private boolean paintEditorBorder;
225:
226: public static ComponentUI createUI(final JComponent c) {
227: return new BasicSpinnerUI();
228: }
229:
230: public void installUI(final JComponent c) {
231: spinner = (JSpinner) c;
232: installDefaults();
233: installListeners();
234: installKeyboardActions();
235:
236: spinner.setLayout(createLayout());
237:
238: replaceEditor(null, createEditor());
239:
240: nextButton = createNextButton();
241: // nextButton.setMinimumSize(buttonSize);
242: spinner.add(NEXT_FIELD, nextButton);
243:
244: previousButton = createPreviousButton();
245: // previousButton.setMinimumSize(buttonSize);
246: spinner.add(PREVIOUS_FIELD, previousButton);
247: }
248:
249: public void uninstallUI(final JComponent c) {
250: uninstallKeyboardActions();
251: uninstallListeners();
252: uninstallDefaults();
253: spinner.remove(editor);
254: spinner.remove(nextButton);
255: spinner.remove(previousButton);
256: spinner = null;
257: }
258:
259: protected void installListeners() {
260: changeListener = createPropertyChangeListener();
261: spinner.addPropertyChangeListener(changeListener);
262: }
263:
264: protected void uninstallListeners() {
265: spinner.removePropertyChangeListener(changeListener);
266: }
267:
268: protected void installDefaults() {
269: LookAndFeel.installBorder(spinner, "Spinner.border");
270: LookAndFeel.installColorsAndFont(spinner, "Spinner.background",
271: "Spinner.foreground", "Spinner.font");
272: LookAndFeel.installProperty(spinner, "opaque", Boolean.TRUE);
273:
274: paintEditorBorder = UIManager
275: .getBoolean("Spinner.editorBorderPainted");
276: buttonSize = UIManager.getDimension("Spinner.arrowButtonSize");
277: buttonInsets = UIManager.getInsets("Spinner.arrowButtonInsets");
278: }
279:
280: protected void uninstallDefaults() {
281: LookAndFeel.uninstallBorder(spinner);
282: Utilities.uninstallColorsAndFont(spinner);
283: }
284:
285: protected void installNextButtonListeners(final Component c) {
286: if (!(c instanceof JButton)) {
287: return;
288: }
289: JButton next = (JButton) c;
290: next.addMouseListener(buttonHandler);
291: next.addActionListener(buttonHandler);
292: next.addFocusListener(buttonHandler);
293: }
294:
295: protected void installPreviousButtonListeners(final Component c) {
296: if (!(c instanceof JButton)) {
297: return;
298: }
299: JButton previous = (JButton) c;
300: previous.addMouseListener(buttonHandler);
301: previous.addActionListener(buttonHandler);
302: previous.addFocusListener(buttonHandler);
303: }
304:
305: protected LayoutManager createLayout() {
306: return new SpinnerLayout();
307: }
308:
309: protected PropertyChangeListener createPropertyChangeListener() {
310: return new PropertyChangeHandler();
311: }
312:
313: protected Component createPreviousButton() {
314: BasicArrowButton previous = new BasicArrowButton(
315: BasicArrowButton.SOUTH);
316: installPreviousButtonListeners(previous);
317: return previous;
318: }
319:
320: protected Component createNextButton() {
321: BasicArrowButton next = new BasicArrowButton(
322: BasicArrowButton.NORTH);
323: installNextButtonListeners(next);
324: return next;
325: }
326:
327: protected JComponent createEditor() {
328: return spinner.getEditor();
329: }
330:
331: protected void replaceEditor(final JComponent oldEditor,
332: final JComponent newEditor) {
333: if (oldEditor != null) {
334: spinner.remove(oldEditor);
335: }
336:
337: editor = newEditor;
338:
339: if (!paintEditorBorder && editor instanceof DefaultEditor) {
340: ((DefaultEditor) editor).getTextField().setBorder(null);
341: }
342: spinner.add(newEditor, EDITOR_FIELD);
343: }
344:
345: protected void installKeyboardActions() {
346: BasicSpinnerKeyboardActions.installKeyboardActions(spinner);
347: }
348:
349: private void uninstallKeyboardActions() {
350: BasicSpinnerKeyboardActions.uninstallKeyboardActions(spinner);
351: }
352: }
|