2 Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package javax
.swing
.plaf
.basic
;
41 import java
.awt
.Component
;
42 import java
.awt
.Container
;
43 import java
.awt
.Dimension
;
44 import java
.awt
.Insets
;
45 import java
.awt
.LayoutManager
;
46 import java
.awt
.event
.ActionEvent
;
47 import java
.awt
.event
.ActionListener
;
48 import java
.awt
.event
.MouseAdapter
;
49 import java
.awt
.event
.MouseEvent
;
50 import java
.beans
.PropertyChangeEvent
;
51 import java
.beans
.PropertyChangeListener
;
53 import javax
.swing
.JButton
;
54 import javax
.swing
.JComponent
;
55 import javax
.swing
.JSpinner
;
56 import javax
.swing
.LookAndFeel
;
57 import javax
.swing
.Timer
;
58 import javax
.swing
.plaf
.ComponentUI
;
59 import javax
.swing
.plaf
.SpinnerUI
;
64 * @author Ka-Hing Cheung
66 * @see javax.swing.JSpinner
69 public class BasicSpinnerUI
extends SpinnerUI
72 * Creates a new <code>ComponentUI</code> for the specified
73 * <code>JComponent</code>
75 * @param c DOCUMENT ME!
77 * @return a ComponentUI
79 public static ComponentUI
createUI(JComponent c
)
81 return new BasicSpinnerUI();
85 * Creates an editor component. Really, it just returns
86 * <code>JSpinner.getEditor()</code>
88 * @return a JComponent as an editor
90 * @see javax.swing.JSpinner#getEditor
92 protected JComponent
createEditor()
94 return spinner
.getEditor();
98 * Creates a <code>LayoutManager</code> that layouts the sub components. The
99 * subcomponents are identifies by the constraint "Next", "Previous" and
102 * @return a LayoutManager
104 * @see java.awt.LayoutManager
106 protected LayoutManager
createLayout()
108 return new DefaultLayoutManager();
112 * Creates the "Next" button
114 * @return the next button component
116 protected Component
createNextButton()
118 JButton button
= new BasicArrowButton(BasicArrowButton
.NORTH
);
123 * Creates the "Previous" button
125 * @return the previous button component
127 protected Component
createPreviousButton()
129 JButton button
= new BasicArrowButton(BasicArrowButton
.SOUTH
);
134 * Creates the <code>PropertyChangeListener</code> that will be attached by
135 * <code>installListeners</code>. It should watch for the "editor"
136 * property, when it's changed, replace the old editor with the new one,
137 * probably by calling <code>replaceEditor</code>
139 * @return a PropertyChangeListener
141 * @see #replaceEditor
143 protected PropertyChangeListener
createPropertyChangeListener()
145 return new PropertyChangeListener()
147 public void propertyChange(PropertyChangeEvent evt
)
149 // FIXME: Add check for enabled property change. Need to
150 // disable the buttons.
151 if ("editor".equals(evt
.getPropertyName()))
152 BasicSpinnerUI
.this.replaceEditor((JComponent
) evt
.getOldValue(),
153 (JComponent
) evt
.getNewValue());
159 * Called by <code>installUI</code>. This should set various defaults
160 * obtained from <code>UIManager.getLookAndFeelDefaults</code>, as well as
161 * set the layout obtained from <code>createLayout</code>
163 * @see javax.swing.UIManager#getLookAndFeelDefaults
167 protected void installDefaults()
169 LookAndFeel
.installColorsAndFont(spinner
, "Spinner.background",
170 "Spinner.foreground", "Spinner.font");
171 LookAndFeel
.installBorder(spinner
, "Spinner.border");
172 spinner
.setLayout(createLayout());
173 spinner
.setOpaque(true);
177 * Called by <code>installUI</code>, which basically adds the
178 * <code>PropertyChangeListener</code> created by
179 * <code>createPropertyChangeListener</code>
181 * @see #createPropertyChangeListener
184 protected void installListeners()
186 spinner
.addPropertyChangeListener(listener
);
190 * Install listeners to the next button so that it increments the model
192 protected void installNextButtonListeners(Component c
)
194 c
.addMouseListener(new MouseAdapter()
196 public void mousePressed(MouseEvent evt
)
198 if (! spinner
.isEnabled())
201 timer
.setInitialDelay(500);
205 public void mouseReleased(MouseEvent evt
)
212 Object next
= BasicSpinnerUI
.this.spinner
.getNextValue();
214 BasicSpinnerUI
.this.spinner
.getModel().setValue(next
);
217 volatile boolean mouseDown
= false;
218 Timer timer
= new Timer(50,
221 public void actionPerformed(ActionEvent event
)
230 * Install listeners to the previous button so that it decrements the model
232 protected void installPreviousButtonListeners(Component c
)
234 c
.addMouseListener(new MouseAdapter()
236 public void mousePressed(MouseEvent evt
)
238 if (! spinner
.isEnabled())
241 timer
.setInitialDelay(500);
245 public void mouseReleased(MouseEvent evt
)
252 Object prev
= BasicSpinnerUI
.this.spinner
.getPreviousValue();
254 BasicSpinnerUI
.this.spinner
.getModel().setValue(prev
);
257 volatile boolean mouseDown
= false;
258 Timer timer
= new Timer(50,
261 public void actionPerformed(ActionEvent event
)
270 * Install this UI to the <code>JComponent</code>, which in reality, is a
271 * <code>JSpinner</code>. Calls <code>installDefaults</code>,
272 * <code>installListeners</code>, and also adds the buttons and editor.
274 * @param c DOCUMENT ME!
276 * @see #installDefaults
277 * @see #installListeners
278 * @see #createNextButton
279 * @see #createPreviousButton
282 public void installUI(JComponent c
)
286 spinner
= (JSpinner
) c
;
291 Component next
= createNextButton();
292 Component previous
= createPreviousButton();
294 installNextButtonListeners(next
);
295 installPreviousButtonListeners(previous
);
297 c
.add(createEditor(), "Editor");
299 c
.add(previous
, "Previous");
303 * Replace the old editor with the new one
305 * @param oldEditor the old editor
306 * @param newEditor the new one to replace with
308 protected void replaceEditor(JComponent oldEditor
, JComponent newEditor
)
310 spinner
.remove(oldEditor
);
311 spinner
.add(newEditor
);
315 * The reverse of <code>installDefaults</code>. Called by
316 * <code>uninstallUI</code>
318 protected void uninstallDefaults()
320 spinner
.setLayout(null);
324 * The reverse of <code>installListeners</code>, called by
325 * <code>uninstallUI</code>
327 protected void uninstallListeners()
329 spinner
.removePropertyChangeListener(listener
);
333 * Called when the current L&F is replaced with another one, should call
334 * <code>uninstallDefaults</code> and <code>uninstallListeners</code> as
335 * well as remove the next/previous buttons and the editor
337 * @param c DOCUMENT ME!
339 public void uninstallUI(JComponent c
)
341 super.uninstallUI(c
);
344 uninstallListeners();
348 /** The spinner for this UI */
349 protected JSpinner spinner
;
352 private PropertyChangeListener listener
= createPropertyChangeListener();
357 private class DefaultLayoutManager
implements LayoutManager
362 * @param parent DOCUMENT ME!
364 public void layoutContainer(Container parent
)
366 synchronized (parent
.getTreeLock())
368 Insets i
= parent
.getInsets();
369 boolean l2r
= parent
.getComponentOrientation().isLeftToRight();
371 -------------- --------------
373 | e | - | or | - | e |
375 -------------- --------------
377 Dimension e
= minSize(editor
);
378 Dimension n
= minSize(next
);
379 Dimension p
= minSize(previous
);
380 Dimension s
= spinner
.getPreferredSize();
382 int x
= l2r ? i
.left
: i
.right
;
384 int w
= Math
.max(p
.width
, n
.width
);
385 int h
= Math
.max(p
.height
, n
.height
);
386 h
= Math
.max(h
, e
.height
/ 2);
387 int e_width
= s
.width
- w
;
391 setBounds(editor
, x
, y
+ (s
.height
- e
.height
) / 2, e_width
,
395 setBounds(next
, x
, y
, w
, h
);
398 setBounds(previous
, x
, y
, w
, h
);
402 setBounds(next
, x
, y
+ (s
.height
- e
.height
) / 2, w
, h
);
405 setBounds(previous
, x
, y
, w
, h
);
409 setBounds(editor
, x
, y
, e_width
, e
.height
);
417 * @param parent DOCUMENT ME!
419 * @return DOCUMENT ME!
421 public Dimension
minimumLayoutSize(Container parent
)
423 Dimension d
= new Dimension();
427 Dimension tmp
= editor
.getMinimumSize();
428 d
.width
+= tmp
.width
;
429 d
.height
= tmp
.height
;
433 int previousWidth
= 0;
438 Dimension tmp
= next
.getMinimumSize();
439 nextWidth
= tmp
.width
;
440 otherHeight
+= tmp
.height
;
442 if (previous
!= null)
444 Dimension tmp
= previous
.getMinimumSize();
445 previousWidth
= tmp
.width
;
446 otherHeight
+= tmp
.height
;
449 d
.height
= Math
.max(d
.height
, otherHeight
);
450 d
.width
+= Math
.max(nextWidth
, previousWidth
);
458 * @param parent DOCUMENT ME!
460 * @return DOCUMENT ME!
462 public Dimension
preferredLayoutSize(Container parent
)
464 Dimension d
= new Dimension();
468 Dimension tmp
= editor
.getPreferredSize();
469 d
.width
+= Math
.max(tmp
.width
, 40);
470 d
.height
= tmp
.height
;
474 int previousWidth
= 0;
479 Dimension tmp
= next
.getPreferredSize();
480 nextWidth
= tmp
.width
;
481 otherHeight
+= tmp
.height
;
483 if (previous
!= null)
485 Dimension tmp
= previous
.getPreferredSize();
486 previousWidth
= tmp
.width
;
487 otherHeight
+= tmp
.height
;
490 d
.height
= Math
.max(d
.height
, otherHeight
);
491 d
.width
+= Math
.max(nextWidth
, previousWidth
);
499 * @param child DOCUMENT ME!
501 public void removeLayoutComponent(Component child
)
505 else if (child
== next
)
507 else if (previous
== child
)
514 * @param name DOCUMENT ME!
515 * @param child DOCUMENT ME!
517 public void addLayoutComponent(String name
, Component child
)
519 if ("Editor".equals(name
))
521 else if ("Next".equals(name
))
523 else if ("Previous".equals(name
))
530 * @param c DOCUMENT ME!
532 * @return DOCUMENT ME!
534 private Dimension
minSize(Component c
)
537 return new Dimension();
539 return c
.getMinimumSize();
545 * @param c DOCUMENT ME!
546 * @param x DOCUMENT ME!
547 * @param y DOCUMENT ME!
548 * @param w DOCUMENT ME!
549 * @param h DOCUMENT ME!
551 private void setBounds(Component c
, int x
, int y
, int w
, int h
)
554 c
.setBounds(x
, y
, w
, h
);
558 private Component editor
;
561 private Component next
;
564 private Component previous
;