/* * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package javax.swing.plaf.basic; import java.awt.*;import java.awt.event.*;import java.text.ParseException; import javax.swing.*;import javax.swing.border.*;import javax.swing.event.*;import javax.swing.plaf.*;import javax.swing.text.*; import java.beans.*;import java.text.*;import java.util.*;import sun.swing.DefaultLookup; /** * The default Spinner UI delegate. * * @author Hans Muller * @since 1.4 */public class BasicSpinnerUI extends SpinnerUI{ /** * The spinner that we're a UI delegate for. Initialized by * the <code>installUI</code> method, and reset to null * by <code>uninstallUI</code>. * * @see #installUI * @see #uninstallUI */ protected JSpinner spinner; private Handler handler; /** * The mouse/action listeners that are added to the spinner's * arrow buttons. These listeners are shared by all * spinner arrow buttons. * * @see #createNextButton * @see #createPreviousButton */ private static final ArrowButtonHandler nextButtonHandler = new ArrowButtonHandler("increment", true); private static final ArrowButtonHandler previousButtonHandler = new ArrowButtonHandler("decrement", false); private PropertyChangeListener propertyChangeListener; /** * Used by the default LayoutManager class - SpinnerLayout for * missing (null) editor/nextButton/previousButton children. */ private static final Dimension zeroSize = new Dimension(0, 0); /** * Returns a new instance of BasicSpinnerUI. SpinnerListUI * delegates are allocated one per JSpinner. * * @param c the JSpinner (not used) * @see ComponentUI#createUI * @return a new BasicSpinnerUI object */ public static ComponentUI createUI(JComponent c) { return new BasicSpinnerUI(); } private void maybeAdd(Component c, String s) { if (c != null) { spinner.add(c, s); } } /** * Calls <code>installDefaults</code>, <code>installListeners</code>, * and then adds the components returned by <code>createNextButton</code>, * <code>createPreviousButton</code>, and <code>createEditor</code>. * * @param c the JSpinner * @see #installDefaults * @see #installListeners * @see #createNextButton * @see #createPreviousButton * @see #createEditor */ public void installUI(JComponent c) { this.spinner = (JSpinner)c; installDefaults(); installListeners(); maybeAdd(createNextButton(), "Next"); maybeAdd(createPreviousButton(), "Previous"); maybeAdd(createEditor(), "Editor"); updateEnabledState(); installKeyboardActions(); } /** * Calls <code>uninstallDefaults</code>, <code>uninstallListeners</code>, * and then removes all of the spinners children. * * @param c the JSpinner (not used) */ public void uninstallUI(JComponent c) { uninstallDefaults(); uninstallListeners(); this.spinner = null; c.removeAll(); } /** * Initializes <code>PropertyChangeListener</code> with * a shared object that delegates interesting PropertyChangeEvents * to protected methods. * <p> * This method is called by <code>installUI</code>. * * @see #replaceEditor * @see #uninstallListeners */ protected void installListeners() { propertyChangeListener = createPropertyChangeListener(); spinner.addPropertyChangeListener(propertyChangeListener); if (DefaultLookup.getBoolean(spinner, this, "Spinner.disableOnBoundaryValues", false)) { spinner.addChangeListener(getHandler()); } JComponent editor = spinner.getEditor(); if (editor != null && editor instanceof JSpinner.DefaultEditor) { JTextField tf = ((JSpinner.DefaultEditor)editor).getTextField(); if (tf != null) { tf.addFocusListener(nextButtonHandler); tf.addFocusListener(previousButtonHandler); } } } /** * Removes the <code>PropertyChangeListener</code> added * by installListeners. * <p> * This method is called by <code>uninstallUI</code>. * * @see #installListeners */ protected void uninstallListeners() { spinner.removePropertyChangeListener(propertyChangeListener); spinner.removeChangeListener(handler); JComponent editor = spinner.getEditor(); removeEditorBorderListener(editor); if (editor instanceof JSpinner.DefaultEditor) { JTextField tf = ((JSpinner.DefaultEditor)editor).getTextField(); if (tf != null) { tf.removeFocusListener(nextButtonHandler); tf.removeFocusListener(previousButtonHandler); } } propertyChangeListener = null; handler = null; } /** * Initialize the <code>JSpinner</code> <code>border</code>, * <code>foreground</code>, and <code>background</code>, properties * based on the corresponding "Spinner.*" properties from defaults table. * The <code>JSpinners</code> layout is set to the value returned by * <code>createLayout</code>. This method is called by <code>installUI</code>. * * @see #uninstallDefaults * @see #installUI * @see #createLayout * @see LookAndFeel#installBorder * @see LookAndFeel#installColors */ protected void installDefaults() { spinner.setLayout(createLayout()); LookAndFeel.installBorder(spinner, "Spinner.border"); LookAndFeel.installColorsAndFont(spinner, "Spinner.background", "Spinner.foreground", "Spinner.font"); LookAndFeel.installProperty(spinner, "opaque", Boolean.TRUE); } /** * Sets the <code>JSpinner's</code> layout manager to null. This * method is called by <code>uninstallUI</code>. * * @see #installDefaults * @see #uninstallUI */ protected void uninstallDefaults() { spinner.setLayout(null); } private Handler getHandler() { if (handler == null) { handler = new Handler(); } return handler; } /** * Installs the necessary listeners on the next button, <code>c</code>, * to update the <code>JSpinner</code> in response to a user gesture. * * @param c Component to install the listeners on * @throws NullPointerException if <code>c</code> is null. * @see #createNextButton * @since 1.5 */ protected void installNextButtonListeners(Component c) { installButtonListeners(c, nextButtonHandler); } /** * Installs the necessary listeners on the previous button, <code>c</code>, * to update the <code>JSpinner</code> in response to a user gesture. * * @param c Component to install the listeners on. * @throws NullPointerException if <code>c</code> is null. * @see #createPreviousButton * @since 1.5 */ protected void installPreviousButtonListeners(Component c) { installButtonListeners(c, previousButtonHandler); } private void installButtonListeners(Component c, ArrowButtonHandler handler) { if (c instanceof JButton) { ((JButton)c).addActionListener(handler); } c.addMouseListener(handler); } /** * Creates a <code>LayoutManager</code> that manages the <code>editor</code>, * <code>nextButton</code>, and <code>previousButton</code> * children of the JSpinner. These three children must be * added with a constraint that identifies their role: * "Editor", "Next", and "Previous". The default layout manager * can handle the absence of any of these children. * * @return a LayoutManager for the editor, next button, and previous button. * @see #createNextButton * @see #createPreviousButton * @see #createEditor */ protected LayoutManager createLayout() { return getHandler(); } /** * Creates a <code>PropertyChangeListener</code> that can be * added to the JSpinner itself. Typically, this listener * will call replaceEditor when the "editor" property changes, * since it's the <code>SpinnerUI's</code> responsibility to * add the editor to the JSpinner (and remove the old one). * This method is called by <code>installListeners</code>. * * @return A PropertyChangeListener for the JSpinner itself * @see #installListeners */ protected PropertyChangeListener createPropertyChangeListener() { return getHandler(); } /** * Creates a decrement button, i.e. component that replaces the spinner * value with the object returned by <code>spinner.getPreviousValue</code>. * By default the <code>previousButton</code> is a {@code JButton}. If the * decrement button is not needed this method should return {@code null}. * * @return a component that will replace the spinner's value with the * previous value in the sequence, or {@code null} * @see #installUI * @see #createNextButton * @see #installPreviousButtonListeners */ protected Component createPreviousButton() { Component c = createArrowButton(SwingConstants.SOUTH); c.setName("Spinner.previousButton"); installPreviousButtonListeners(c); return c; } /** * Creates an increment button, i.e. component that replaces the spinner * value with the object returned by <code>spinner.getNextValue</code>. * By default the <code>nextButton</code> is a {@code JButton}. If the * increment button is not needed this method should return {@code null}. * * @return a component that will replace the spinner's value with the * next value in the sequence, or {@code null} * @see #installUI * @see #createPreviousButton * @see #installNextButtonListeners */ protected Component createNextButton() { Component c = createArrowButton(SwingConstants.NORTH); c.setName("Spinner.nextButton"); installNextButtonListeners(c); return c; } private Component createArrowButton(int direction) { JButton b = new BasicArrowButton(direction); Border buttonBorder = UIManager.getBorder("Spinner.arrowButtonBorder"); if (buttonBorder instanceof UIResource) { // Wrap the border to avoid having the UIResource be replaced by // the ButtonUI. This is the opposite of using BorderUIResource. b.setBorder(new CompoundBorder(buttonBorder, null)); } else { b.setBorder(buttonBorder); } b.setInheritsPopupMenu(true); return b; } /** * This method is called by installUI to get the editor component * of the <code>JSpinner</code>. By default it just returns * <code>JSpinner.getEditor()</code>. Subclasses can override * <code>createEditor</code> to return a component that contains * the spinner's editor or null, if they're going to handle adding * the editor to the <code>JSpinner</code> in an * <code>installUI</code> override. * <p> * Typically this method would be overridden to wrap the editor * with a container with a custom border, since one can't assume * that the editors border can be set directly. * <p> * The <code>replaceEditor</code> method is called when the spinners * editor is changed with <code>JSpinner.setEditor</code>. If you've * overriden this method, then you'll probably want to override * <code>replaceEditor</code> as well. * * @return the JSpinners editor JComponent, spinner.getEditor() by default * @see #installUI * @see #replaceEditor * @see JSpinner#getEditor */ protected JComponent createEditor() { JComponent editor = spinner.getEditor(); maybeRemoveEditorBorder(editor); installEditorBorderListener(editor); editor.setInheritsPopupMenu(true); updateEditorAlignment(editor); return editor; } /** * Called by the <code>PropertyChangeListener</code> when the * <code>JSpinner</code> editor property changes. It's the responsibility * of this method to remove the old editor and add the new one. By * default this operation is just: * <pre> * spinner.remove(oldEditor); * spinner.add(newEditor, "Editor"); * </pre> * The implementation of <code>replaceEditor</code> should be coordinated * with the <code>createEditor</code> method. * * @see #createEditor * @see #createPropertyChangeListener */ protected void replaceEditor(JComponent oldEditor, JComponent newEditor) { spinner.remove(oldEditor); maybeRemoveEditorBorder(newEditor); installEditorBorderListener(newEditor); newEditor.setInheritsPopupMenu(true); spinner.add(newEditor, "Editor"); } private void updateEditorAlignment(JComponent editor) { if (editor instanceof JSpinner.DefaultEditor) { // if editor alignment isn't set in LAF, we get 0 (CENTER) here int alignment = UIManager.getInt("Spinner.editorAlignment"); JTextField text = ((JSpinner.DefaultEditor)editor).getTextField(); text.setHorizontalAlignment(alignment); } } /** * Remove the border around the inner editor component for LaFs * that install an outside border around the spinner, */ private void maybeRemoveEditorBorder(JComponent editor) { if (!UIManager.getBoolean("Spinner.editorBorderPainted")) { if (editor instanceof JPanel && editor.getBorder() == null && editor.getComponentCount() > 0) { editor = (JComponent)editor.getComponent(0); } if (editor != null && editor.getBorder() instanceof UIResource) { editor.setBorder(null); } } } /** * Remove the border around the inner editor component for LaFs * that install an outside border around the spinner, */ private void installEditorBorderListener(JComponent editor) { if (!UIManager.getBoolean("Spinner.editorBorderPainted")) { if (editor instanceof JPanel && editor.getBorder() == null && editor.getComponentCount() > 0) { editor = (JComponent)editor.getComponent(0); } if (editor != null && (editor.getBorder() == null || editor.getBorder() instanceof UIResource)) { editor.addPropertyChangeListener(getHandler()); } } } private void removeEditorBorderListener(JComponent editor) { if (!UIManager.getBoolean("Spinner.editorBorderPainted")) { if (editor instanceof JPanel && editor.getComponentCount() > 0) { editor = (JComponent)editor.getComponent(0); } if (editor != null) { editor.removePropertyChangeListener(getHandler()); } } } /** * Updates the enabled state of the children Components based on the * enabled state of the <code>JSpinner</code>. */ private void updateEnabledState() { updateEnabledState(spinner, spinner.isEnabled()); } /** * Recursively updates the enabled state of the child * <code>Component</code>s of <code>c</code>. */ private void updateEnabledState(Container c, boolean enabled) { for (int counter = c.getComponentCount() - 1; counter >= 0;counter--) { Component child = c.getComponent(counter); if (DefaultLookup.getBoolean(spinner, this, "Spinner.disableOnBoundaryValues", false)) { SpinnerModel model = spinner.getModel(); if (child.getName() == "Spinner.nextButton" && model.getNextValue() == null) { child.setEnabled(false); } else if (child.getName() == "Spinner.previousButton" &&Lines 1–500 of 1062. Load more
/* * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package javax.swing.plaf.basic; import java.awt.*; import java.awt.event.*; import java.text.ParseException; import javax.swing.*; import javax.swing.border.*; import javax.swing.event.*; import javax.swing.plaf.*; import javax.swing.text.*; import java.beans.*; import java.text.*; import java.util.*; import sun.swing.DefaultLookup; /** * The default Spinner UI delegate. * * @author Hans Muller * @since 1.4 */ public class BasicSpinnerUI extends SpinnerUI { /** * The spinner that we're a UI delegate for. Initialized by * the <code>installUI</code> method, and reset to null * by <code>uninstallUI</code>. * * @see #installUI * @see #uninstallUI */ protected JSpinner spinner; private Handler handler; /** * The mouse/action listeners that are added to the spinner's * arrow buttons. These listeners are shared by all * spinner arrow buttons. * * @see #createNextButton * @see #createPreviousButton */ private static final ArrowButtonHandler nextButtonHandler = new ArrowButtonHandler("increment", true); private static final ArrowButtonHandler previousButtonHandler = new ArrowButtonHandler("decrement", false); private PropertyChangeListener propertyChangeListener; /** * Used by the default LayoutManager class - SpinnerLayout for * missing (null) editor/nextButton/previousButton children. */ private static final Dimension zeroSize = new Dimension(0, 0); /** * Returns a new instance of BasicSpinnerUI. SpinnerListUI * delegates are allocated one per JSpinner. * * @param c the JSpinner (not used) * @see ComponentUI#createUI * @return a new BasicSpinnerUI object */ public static ComponentUI createUI(JComponent c) { return new BasicSpinnerUI(); } private void maybeAdd(Component c, String s) { if (c != null) { spinner.add(c, s); } } /** * Calls <code>installDefaults</code>, <code>installListeners</code>, * and then adds the components returned by <code>createNextButton</code>, * <code>createPreviousButton</code>, and <code>createEditor</code>. * * @param c the JSpinner * @see #installDefaults * @see #installListeners * @see #createNextButton * @see #createPreviousButton * @see #createEditor */ public void installUI(JComponent c) { this.spinner = (JSpinner)c; installDefaults(); installListeners(); maybeAdd(createNextButton(), "Next"); maybeAdd(createPreviousButton(), "Previous"); maybeAdd(createEditor(), "Editor"); updateEnabledState(); installKeyboardActions(); } /** * Calls <code>uninstallDefaults</code>, <code>uninstallListeners</code>, * and then removes all of the spinners children. * * @param c the JSpinner (not used) */ public void uninstallUI(JComponent c) { uninstallDefaults(); uninstallListeners(); this.spinner = null; c.removeAll(); } /** * Initializes <code>PropertyChangeListener</code> with * a shared object that delegates interesting PropertyChangeEvents * to protected methods. * <p> * This method is called by <code>installUI</code>. * * @see #replaceEditor * @see #uninstallListeners */ protected void installListeners() { propertyChangeListener = createPropertyChangeListener(); spinner.addPropertyChangeListener(propertyChangeListener); if (DefaultLookup.getBoolean(spinner, this, "Spinner.disableOnBoundaryValues", false)) { spinner.addChangeListener(getHandler()); } JComponent editor = spinner.getEditor(); if (editor != null && editor instanceof JSpinner.DefaultEditor) { JTextField tf = ((JSpinner.DefaultEditor)editor).getTextField(); if (tf != null) { tf.addFocusListener(nextButtonHandler); tf.addFocusListener(previousButtonHandler); } } } /** * Removes the <code>PropertyChangeListener</code> added * by installListeners. * <p> * This method is called by <code>uninstallUI</code>. * * @see #installListeners */ protected void uninstallListeners() { spinner.removePropertyChangeListener(propertyChangeListener); spinner.removeChangeListener(handler); JComponent editor = spinner.getEditor(); removeEditorBorderListener(editor); if (editor instanceof JSpinner.DefaultEditor) { JTextField tf = ((JSpinner.DefaultEditor)editor).getTextField(); if (tf != null) { tf.removeFocusListener(nextButtonHandler); tf.removeFocusListener(previousButtonHandler); } } propertyChangeListener = null; handler = null; } /** * Initialize the <code>JSpinner</code> <code>border</code>, * <code>foreground</code>, and <code>background</code>, properties * based on the corresponding "Spinner.*" properties from defaults table. * The <code>JSpinners</code> layout is set to the value returned by * <code>createLayout</code>. This method is called by <code>installUI</code>. * * @see #uninstallDefaults * @see #installUI * @see #createLayout * @see LookAndFeel#installBorder * @see LookAndFeel#installColors */ protected void installDefaults() { spinner.setLayout(createLayout()); LookAndFeel.installBorder(spinner, "Spinner.border"); LookAndFeel.installColorsAndFont(spinner, "Spinner.background", "Spinner.foreground", "Spinner.font"); LookAndFeel.installProperty(spinner, "opaque", Boolean.TRUE); } /** * Sets the <code>JSpinner's</code> layout manager to null. This * method is called by <code>uninstallUI</code>. * * @see #installDefaults * @see #uninstallUI */ protected void uninstallDefaults() { spinner.setLayout(null); } private Handler getHandler() { if (handler == null) { handler = new Handler(); } return handler; } /** * Installs the necessary listeners on the next button, <code>c</code>, * to update the <code>JSpinner</code> in response to a user gesture. * * @param c Component to install the listeners on * @throws NullPointerException if <code>c</code> is null. * @see #createNextButton * @since 1.5 */ protected void installNextButtonListeners(Component c) { installButtonListeners(c, nextButtonHandler); } /** * Installs the necessary listeners on the previous button, <code>c</code>, * to update the <code>JSpinner</code> in response to a user gesture. * * @param c Component to install the listeners on. * @throws NullPointerException if <code>c</code> is null. * @see #createPreviousButton * @since 1.5 */ protected void installPreviousButtonListeners(Component c) { installButtonListeners(c, previousButtonHandler); } private void installButtonListeners(Component c, ArrowButtonHandler handler) { if (c instanceof JButton) { ((JButton)c).addActionListener(handler); } c.addMouseListener(handler); } /** * Creates a <code>LayoutManager</code> that manages the <code>editor</code>, * <code>nextButton</code>, and <code>previousButton</code> * children of the JSpinner. These three children must be * added with a constraint that identifies their role: * "Editor", "Next", and "Previous". The default layout manager * can handle the absence of any of these children. * * @return a LayoutManager for the editor, next button, and previous button. * @see #createNextButton * @see #createPreviousButton * @see #createEditor */ protected LayoutManager createLayout() { return getHandler(); } /** * Creates a <code>PropertyChangeListener</code> that can be * added to the JSpinner itself. Typically, this listener * will call replaceEditor when the "editor" property changes, * since it's the <code>SpinnerUI's</code> responsibility to * add the editor to the JSpinner (and remove the old one). * This method is called by <code>installListeners</code>. * * @return A PropertyChangeListener for the JSpinner itself * @see #installListeners */ protected PropertyChangeListener createPropertyChangeListener() { return getHandler(); } /** * Creates a decrement button, i.e. component that replaces the spinner * value with the object returned by <code>spinner.getPreviousValue</code>. * By default the <code>previousButton</code> is a {@code JButton}. If the * decrement button is not needed this method should return {@code null}. * * @return a component that will replace the spinner's value with the * previous value in the sequence, or {@code null} * @see #installUI * @see #createNextButton * @see #installPreviousButtonListeners */ protected Component createPreviousButton() { Component c = createArrowButton(SwingConstants.SOUTH); c.setName("Spinner.previousButton"); installPreviousButtonListeners(c); return c; } /** * Creates an increment button, i.e. component that replaces the spinner * value with the object returned by <code>spinner.getNextValue</code>. * By default the <code>nextButton</code> is a {@code JButton}. If the * increment button is not needed this method should return {@code null}. * * @return a component that will replace the spinner's value with the * next value in the sequence, or {@code null} * @see #installUI * @see #createPreviousButton * @see #installNextButtonListeners */ protected Component createNextButton() { Component c = createArrowButton(SwingConstants.NORTH); c.setName("Spinner.nextButton"); installNextButtonListeners(c); return c; } private Component createArrowButton(int direction) { JButton b = new BasicArrowButton(direction); Border buttonBorder = UIManager.getBorder("Spinner.arrowButtonBorder"); if (buttonBorder instanceof UIResource) { // Wrap the border to avoid having the UIResource be replaced by // the ButtonUI. This is the opposite of using BorderUIResource. b.setBorder(new CompoundBorder(buttonBorder, null)); } else { b.setBorder(buttonBorder); } b.setInheritsPopupMenu(true); return b; } /** * This method is called by installUI to get the editor component * of the <code>JSpinner</code>. By default it just returns * <code>JSpinner.getEditor()</code>. Subclasses can override * <code>createEditor</code> to return a component that contains * the spinner's editor or null, if they're going to handle adding * the editor to the <code>JSpinner</code> in an * <code>installUI</code> override. * <p> * Typically this method would be overridden to wrap the editor * with a container with a custom border, since one can't assume * that the editors border can be set directly. * <p> * The <code>replaceEditor</code> method is called when the spinners * editor is changed with <code>JSpinner.setEditor</code>. If you've * overriden this method, then you'll probably want to override * <code>replaceEditor</code> as well. * * @return the JSpinners editor JComponent, spinner.getEditor() by default * @see #installUI * @see #replaceEditor * @see JSpinner#getEditor */ protected JComponent createEditor() { JComponent editor = spinner.getEditor(); maybeRemoveEditorBorder(editor); installEditorBorderListener(editor); editor.setInheritsPopupMenu(true); updateEditorAlignment(editor); return editor; } /** * Called by the <code>PropertyChangeListener</code> when the * <code>JSpinner</code> editor property changes. It's the responsibility * of this method to remove the old editor and add the new one. By * default this operation is just: * <pre> * spinner.remove(oldEditor); * spinner.add(newEditor, "Editor"); * </pre> * The implementation of <code>replaceEditor</code> should be coordinated * with the <code>createEditor</code> method. * * @see #createEditor * @see #createPropertyChangeListener */ protected void replaceEditor(JComponent oldEditor, JComponent newEditor) { spinner.remove(oldEditor); maybeRemoveEditorBorder(newEditor); installEditorBorderListener(newEditor); newEditor.setInheritsPopupMenu(true); spinner.add(newEditor, "Editor"); } private void updateEditorAlignment(JComponent editor) { if (editor instanceof JSpinner.DefaultEditor) { // if editor alignment isn't set in LAF, we get 0 (CENTER) here int alignment = UIManager.getInt("Spinner.editorAlignment"); JTextField text = ((JSpinner.DefaultEditor)editor).getTextField(); text.setHorizontalAlignment(alignment); } } /** * Remove the border around the inner editor component for LaFs * that install an outside border around the spinner, */ private void maybeRemoveEditorBorder(JComponent editor) { if (!UIManager.getBoolean("Spinner.editorBorderPainted")) { if (editor instanceof JPanel && editor.getBorder() == null && editor.getComponentCount() > 0) { editor = (JComponent)editor.getComponent(0); } if (editor != null && editor.getBorder() instanceof UIResource) { editor.setBorder(null); } } } /** * Remove the border around the inner editor component for LaFs * that install an outside border around the spinner, */ private void installEditorBorderListener(JComponent editor) { if (!UIManager.getBoolean("Spinner.editorBorderPainted")) { if (editor instanceof JPanel && editor.getBorder() == null && editor.getComponentCount() > 0) { editor = (JComponent)editor.getComponent(0); } if (editor != null && (editor.getBorder() == null || editor.getBorder() instanceof UIResource)) { editor.addPropertyChangeListener(getHandler()); } } } private void removeEditorBorderListener(JComponent editor) { if (!UIManager.getBoolean("Spinner.editorBorderPainted")) { if (editor instanceof JPanel && editor.getComponentCount() > 0) { editor = (JComponent)editor.getComponent(0); } if (editor != null) { editor.removePropertyChangeListener(getHandler()); } } } /** * Updates the enabled state of the children Components based on the * enabled state of the <code>JSpinner</code>. */ private void updateEnabledState() { updateEnabledState(spinner, spinner.isEnabled()); } /** * Recursively updates the enabled state of the child * <code>Component</code>s of <code>c</code>. */ private void updateEnabledState(Container c, boolean enabled) { for (int counter = c.getComponentCount() - 1; counter >= 0;counter--) { Component child = c.getComponent(counter); if (DefaultLookup.getBoolean(spinner, this, "Spinner.disableOnBoundaryValues", false)) { SpinnerModel model = spinner.getModel(); if (child.getName() == "Spinner.nextButton" && model.getNextValue() == null) { child.setEnabled(false); } else if (child.getName() == "Spinner.previousButton" &&