jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaSpinnerUI.java
changeset 35674 8ac51e1179da
parent 32669 8ff453aa551b
equal deleted inserted replaced
35673:61884618e67d 35674:8ac51e1179da
    20  *
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    23  * questions.
    24  */
    24  */
    25 
       
    26 package com.apple.laf;
    25 package com.apple.laf;
    27 
    26 
    28 import java.awt.*;
    27 import java.awt.*;
    29 import java.awt.event.*;
    28 import java.awt.event.*;
    30 import java.beans.*;
    29 import java.beans.*;
    43 
    42 
    44 import com.apple.laf.AquaUtils.RecyclableSingleton;
    43 import com.apple.laf.AquaUtils.RecyclableSingleton;
    45 import com.apple.laf.AquaUtils.RecyclableSingletonFromDefaultConstructor;
    44 import com.apple.laf.AquaUtils.RecyclableSingletonFromDefaultConstructor;
    46 
    45 
    47 /**
    46 /**
    48  * This is originally derived from BasicSpinnerUI, but they made everything private
    47  * This is originally derived from BasicSpinnerUI, but they made everything
    49  * so we can't subclass!
    48  * private so we can't subclass!
    50  */
    49  */
    51 public class AquaSpinnerUI extends SpinnerUI {
    50 public class AquaSpinnerUI extends SpinnerUI {
       
    51 
    52     private static final RecyclableSingleton<? extends PropertyChangeListener> propertyChangeListener
    52     private static final RecyclableSingleton<? extends PropertyChangeListener> propertyChangeListener
    53             = new RecyclableSingletonFromDefaultConstructor<>(PropertyChangeHandler.class);
    53             = new RecyclableSingletonFromDefaultConstructor<>(PropertyChangeHandler.class);
       
    54 
    54     static PropertyChangeListener getPropertyChangeListener() {
    55     static PropertyChangeListener getPropertyChangeListener() {
    55         return propertyChangeListener.get();
    56         return propertyChangeListener.get();
    56     }
    57     }
    57 
    58 
    58     private static final RecyclableSingleton<ArrowButtonHandler> nextButtonHandler
    59     private static final RecyclableSingleton<ArrowButtonHandler> nextButtonHandler
    59             = new RecyclableSingleton<ArrowButtonHandler>() {
    60             = new RecyclableSingleton<ArrowButtonHandler>() {
    60         @Override
    61                 @Override
    61         protected ArrowButtonHandler getInstance() {
    62                 protected ArrowButtonHandler getInstance() {
    62             return new ArrowButtonHandler("increment", true);
    63                     return new ArrowButtonHandler("increment", true);
    63         }
    64                 }
    64     };
    65             };
       
    66 
    65     static ArrowButtonHandler getNextButtonHandler() {
    67     static ArrowButtonHandler getNextButtonHandler() {
    66         return nextButtonHandler.get();
    68         return nextButtonHandler.get();
    67     }
    69     }
    68     private static final RecyclableSingleton<ArrowButtonHandler> previousButtonHandler
    70     private static final RecyclableSingleton<ArrowButtonHandler> previousButtonHandler
    69             = new RecyclableSingleton<ArrowButtonHandler>() {
    71             = new RecyclableSingleton<ArrowButtonHandler>() {
    70         @Override
    72                 @Override
    71         protected ArrowButtonHandler getInstance() {
    73                 protected ArrowButtonHandler getInstance() {
    72             return new ArrowButtonHandler("decrement", false);
    74                     return new ArrowButtonHandler("decrement", false);
    73         }
    75                 }
    74     };
    76             };
       
    77 
    75     static ArrowButtonHandler getPreviousButtonHandler() {
    78     static ArrowButtonHandler getPreviousButtonHandler() {
    76         return previousButtonHandler.get();
    79         return previousButtonHandler.get();
    77     }
    80     }
    78 
    81 
    79     private JSpinner spinner;
    82     private JSpinner spinner;
    90             spinner.add(c, s);
    93             spinner.add(c, s);
    91         }
    94         }
    92     }
    95     }
    93 
    96 
    94     boolean wasOpaque;
    97     boolean wasOpaque;
       
    98 
    95     @Override
    99     @Override
    96     public void installUI(final JComponent c) {
   100     public void installUI(final JComponent c) {
    97         this.spinner = (JSpinner)c;
   101         this.spinner = (JSpinner) c;
    98         installDefaults();
   102         installDefaults();
    99         installListeners();
   103         installListeners();
   100         next = createNextButton();
   104         next = createNextButton();
   101         prev = createPreviousButton();
   105         prev = createPreviousButton();
   102         spinPainter = new SpinPainter(next, prev);
   106         spinPainter = new SpinPainter(next, prev);
   108 
   112 
   109         updateEnabledState();
   113         updateEnabledState();
   110         installKeyboardActions();
   114         installKeyboardActions();
   111 
   115 
   112         // this doesn't work because JSpinner calls setOpaque(true) directly in it's constructor
   116         // this doesn't work because JSpinner calls setOpaque(true) directly in it's constructor
   113     //    LookAndFeel.installProperty(spinner, "opaque", Boolean.FALSE);
   117         //    LookAndFeel.installProperty(spinner, "opaque", Boolean.FALSE);
   114 
       
   115         // ...so we have to handle the is/was opaque ourselves
   118         // ...so we have to handle the is/was opaque ourselves
   116         wasOpaque = spinner.isOpaque();
   119         wasOpaque = spinner.isOpaque();
   117         spinner.setOpaque(false);
   120         spinner.setOpaque(false);
   118     }
   121     }
   119 
   122 
   206         return spinner.getEditor().getBaselineResizeBehavior();
   209         return spinner.getEditor().getBaselineResizeBehavior();
   207     }
   210     }
   208 
   211 
   209     @SuppressWarnings("serial") // Superclass is not serializable across versions
   212     @SuppressWarnings("serial") // Superclass is not serializable across versions
   210     class TransparentButton extends JButton implements SwingConstants {
   213     class TransparentButton extends JButton implements SwingConstants {
       
   214 
   211         boolean interceptRepaints = false;
   215         boolean interceptRepaints = false;
   212 
   216 
   213         public TransparentButton() {
   217         public TransparentButton() {
   214             super();
   218             super();
   215             setFocusable(false);
   219             setFocusable(false);
   217             // otherwise we can't talk to our containing class
   221             // otherwise we can't talk to our containing class
   218             interceptRepaints = true;
   222             interceptRepaints = true;
   219         }
   223         }
   220 
   224 
   221         @Override
   225         @Override
   222         public void paint(final Graphics g) {}
   226         public void paint(final Graphics g) {
       
   227         }
   223 
   228 
   224         @Override
   229         @Override
   225         public void repaint() {
   230         public void repaint() {
   226             // only intercept repaints if we are after this has been initialized
   231             // only intercept repaints if we are after this has been initialized
   227             // otherwise we can't talk to our containing class
   232             // otherwise we can't talk to our containing class
   228             if (interceptRepaints) {
   233             if (interceptRepaints) {
   229                 if (spinPainter == null) return;
   234                 if (spinPainter == null) {
       
   235                     return;
       
   236                 }
   230                 spinPainter.repaint();
   237                 spinPainter.repaint();
   231             }
   238             }
   232             super.repaint();
   239             super.repaint();
   233         }
   240         }
   234     }
   241     }
   244         fixupEditor(newEditor);
   251         fixupEditor(newEditor);
   245         spinner.add(newEditor, "Editor");
   252         spinner.add(newEditor, "Editor");
   246     }
   253     }
   247 
   254 
   248     protected void fixupEditor(final JComponent editor) {
   255     protected void fixupEditor(final JComponent editor) {
   249         if (!(editor instanceof DefaultEditor)) return;
   256         if (!(editor instanceof DefaultEditor)) {
       
   257             return;
       
   258         }
   250 
   259 
   251         editor.setOpaque(false);
   260         editor.setOpaque(false);
   252         editor.setInheritsPopupMenu(true);
   261         editor.setInheritsPopupMenu(true);
   253 
   262 
   254         if (editor.getFont() instanceof UIResource) {
   263         if (editor.getFont() instanceof UIResource) {
   255             editor.setFont(new FontUIResource(spinner.getFont()));
   264             editor.setFont(new FontUIResource(spinner.getFont()));
   256         }
   265         }
   257 
   266 
   258         final JFormattedTextField editorTextField = ((DefaultEditor)editor).getTextField();
   267         final JFormattedTextField editorTextField = ((DefaultEditor) editor).getTextField();
   259         if (editorTextField.getFont() instanceof UIResource) {
   268         if (editorTextField.getFont() instanceof UIResource) {
   260             editorTextField.setFont(new FontUIResource(spinner.getFont()));
   269             editorTextField.setFont(new FontUIResource(spinner.getFont()));
   261         }
   270         }
   262         final InputMap spinnerInputMap = getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
   271         final InputMap spinnerInputMap = getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
   263         final InputMap editorInputMap = editorTextField.getInputMap();
   272         final InputMap editorInputMap = editorTextField.getInputMap();
   275         for (int counter = c.getComponentCount() - 1; counter >= 0; counter--) {
   284         for (int counter = c.getComponentCount() - 1; counter >= 0; counter--) {
   276             final Component child = c.getComponent(counter);
   285             final Component child = c.getComponent(counter);
   277 
   286 
   278             child.setEnabled(enabled);
   287             child.setEnabled(enabled);
   279             if (child instanceof Container) {
   288             if (child instanceof Container) {
   280                 updateEnabledState((Container)child, enabled);
   289                 updateEnabledState((Container) child, enabled);
   281             }
   290             }
   282         }
   291         }
   283     }
   292     }
   284 
   293 
   285     private void installKeyboardActions() {
   294     private void installKeyboardActions() {
   288         SwingUtilities.replaceUIActionMap(spinner, getActionMap());
   297         SwingUtilities.replaceUIActionMap(spinner, getActionMap());
   289     }
   298     }
   290 
   299 
   291     private InputMap getInputMap(final int condition) {
   300     private InputMap getInputMap(final int condition) {
   292         if (condition == JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT) {
   301         if (condition == JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT) {
   293             return (InputMap)UIManager.get("Spinner.ancestorInputMap");
   302             return (InputMap) UIManager.get("Spinner.ancestorInputMap");
   294         }
   303         }
   295         return null;
   304         return null;
   296     }
   305     }
   297 
   306 
   298     private ActionMap getActionMap() {
   307     private ActionMap getActionMap() {
   299         ActionMap map = (ActionMap)UIManager.get("Spinner.actionMap");
   308         ActionMap map = (ActionMap) UIManager.get("Spinner.actionMap");
   300 
   309 
   301         if (map == null) {
   310         if (map == null) {
   302             map = createActionMap();
   311             map = createActionMap();
   303             if (map != null) {
   312             if (map != null) {
   304                 UIManager.getLookAndFeelDefaults().put("Spinner.actionMap", map);
   313                 UIManager.getLookAndFeelDefaults().put("Spinner.actionMap", map);
   314         return map;
   323         return map;
   315     }
   324     }
   316 
   325 
   317     @SuppressWarnings("serial") // Superclass is not serializable across versions
   326     @SuppressWarnings("serial") // Superclass is not serializable across versions
   318     private static class ArrowButtonHandler extends AbstractAction implements MouseListener {
   327     private static class ArrowButtonHandler extends AbstractAction implements MouseListener {
       
   328 
   319         final javax.swing.Timer autoRepeatTimer;
   329         final javax.swing.Timer autoRepeatTimer;
   320         final boolean isNext;
   330         final boolean isNext;
   321         JSpinner spinner = null;
   331         JSpinner spinner = null;
   322 
   332 
   323         ArrowButtonHandler(final String name, final boolean isNext) {
   333         ArrowButtonHandler(final String name, final boolean isNext) {
   328         }
   338         }
   329 
   339 
   330         private JSpinner eventToSpinner(final AWTEvent e) {
   340         private JSpinner eventToSpinner(final AWTEvent e) {
   331             Object src = e.getSource();
   341             Object src = e.getSource();
   332             while ((src instanceof Component) && !(src instanceof JSpinner)) {
   342             while ((src instanceof Component) && !(src instanceof JSpinner)) {
   333                 src = ((Component)src).getParent();
   343                 src = ((Component) src).getParent();
   334             }
   344             }
   335             return (src instanceof JSpinner) ? (JSpinner)src : null;
   345             return (src instanceof JSpinner) ? (JSpinner) src : null;
   336         }
   346         }
   337 
   347 
   338         @Override
   348         @Override
   339         public void actionPerformed(final ActionEvent e) {
   349         public void actionPerformed(final ActionEvent e) {
   340             if (!(e.getSource() instanceof javax.swing.Timer)) {
   350             if (!(e.getSource() instanceof javax.swing.Timer)) {
   341                 // Most likely resulting from being in ActionMap.
   351                 // Most likely resulting from being in ActionMap.
   342                 spinner = eventToSpinner(e);
   352                 spinner = eventToSpinner(e);
   343             }
   353             }
   344 
   354 
   345             if (spinner == null) return;
   355             if (spinner == null) {
       
   356                 return;
       
   357             }
   346 
   358 
   347             try {
   359             try {
   348                 final int calendarField = getCalendarField(spinner);
   360                 final int calendarField = getCalendarField(spinner);
   349                 spinner.commitEdit();
   361                 spinner.commitEdit();
   350                 if (calendarField != -1) {
   362                 if (calendarField != -1) {
   351                     ((SpinnerDateModel)spinner.getModel()).setCalendarField(calendarField);
   363                     ((SpinnerDateModel) spinner.getModel()).setCalendarField(calendarField);
   352                 }
   364                 }
   353                 final Object value = (isNext) ? spinner.getNextValue() : spinner.getPreviousValue();
   365                 final Object value = (isNext) ? spinner.getNextValue() : spinner.getPreviousValue();
   354                 if (value != null) {
   366                 if (value != null) {
   355                     spinner.setValue(value);
   367                     spinner.setValue(value);
   356                     select(spinner);
   368                     select(spinner);
   366          * If the spinner's editor is a DateEditor, this selects the field
   378          * If the spinner's editor is a DateEditor, this selects the field
   367          * associated with the value that is being incremented.
   379          * associated with the value that is being incremented.
   368          */
   380          */
   369         private void select(final JSpinner spinnerComponent) {
   381         private void select(final JSpinner spinnerComponent) {
   370             final JComponent editor = spinnerComponent.getEditor();
   382             final JComponent editor = spinnerComponent.getEditor();
   371             if (!(editor instanceof JSpinner.DateEditor)) return;
   383             if (!(editor instanceof JSpinner.DateEditor)) {
   372 
   384                 return;
   373             final JSpinner.DateEditor dateEditor = (JSpinner.DateEditor)editor;
   385             }
       
   386 
       
   387             final JSpinner.DateEditor dateEditor = (JSpinner.DateEditor) editor;
   374             final JFormattedTextField ftf = dateEditor.getTextField();
   388             final JFormattedTextField ftf = dateEditor.getTextField();
   375             final Format format = dateEditor.getFormat();
   389             final Format format = dateEditor.getFormat();
   376             Object value;
   390             Object value;
   377             if (format == null || (value = spinnerComponent.getValue()) == null) return;
   391             if (format == null || (value = spinnerComponent.getValue()) == null) {
       
   392                 return;
       
   393             }
   378 
   394 
   379             final SpinnerDateModel model = dateEditor.getModel();
   395             final SpinnerDateModel model = dateEditor.getModel();
   380             final DateFormat.Field field = DateFormat.Field.ofCalendarField(model.getCalendarField());
   396             final DateFormat.Field field = DateFormat.Field.ofCalendarField(model.getCalendarField());
   381             if (field == null) return;
   397             if (field == null) {
       
   398                 return;
       
   399             }
   382 
   400 
   383             try {
   401             try {
   384                 final AttributedCharacterIterator iterator = format.formatToCharacterIterator(value);
   402                 final AttributedCharacterIterator iterator = format.formatToCharacterIterator(value);
   385                 if (!select(ftf, iterator, field) && field == DateFormat.Field.HOUR0) {
   403                 if (!select(ftf, iterator, field) && field == DateFormat.Field.HOUR0) {
   386                     select(ftf, iterator, DateFormat.Field.HOUR1);
   404                     select(ftf, iterator, DateFormat.Field.HOUR1);
   387                 }
   405                 }
   388             } catch (final IllegalArgumentException iae) {}
   406             } catch (final IllegalArgumentException iae) {
       
   407             }
   389         }
   408         }
   390 
   409 
   391         /**
   410         /**
   392          * Selects the passed in field, returning true if it is found,
   411          * Selects the passed in field, returning true if it is found, false
   393          * false otherwise.
   412          * otherwise.
   394          */
   413          */
   395         private boolean select(final JFormattedTextField ftf, final AttributedCharacterIterator iterator, final DateFormat.Field field) {
   414         private boolean select(final JFormattedTextField ftf, final AttributedCharacterIterator iterator, final DateFormat.Field field) {
   396             final int max = ftf.getDocument().getLength();
   415             final int max = ftf.getDocument().getLength();
   397 
   416 
   398             iterator.first();
   417             iterator.first();
   399             do {
   418             do {
   400                 final Map<Attribute,Object> attrs = iterator.getAttributes();
   419                 final Map<Attribute, Object> attrs = iterator.getAttributes();
   401                 if (attrs == null || !attrs.containsKey(field)) continue;
   420                 if (attrs == null || !attrs.containsKey(field)) {
       
   421                     continue;
       
   422                 }
   402 
   423 
   403                 final int start = iterator.getRunStart(field);
   424                 final int start = iterator.getRunStart(field);
   404                 final int end = iterator.getRunLimit(field);
   425                 final int end = iterator.getRunLimit(field);
   405                 if (start != -1 && end != -1 && start <= max && end <= max) {
   426                 if (start != -1 && end != -1 && start <= max && end <= max) {
   406                     ftf.select(start, end);
   427                     ftf.select(start, end);
   410             } while (iterator.next() != CharacterIterator.DONE);
   431             } while (iterator.next() != CharacterIterator.DONE);
   411             return false;
   432             return false;
   412         }
   433         }
   413 
   434 
   414         /**
   435         /**
   415          * Returns the calendarField under the start of the selection, or
   436          * Returns the calendarField under the start of the selection, or -1 if
   416          * -1 if there is no valid calendar field under the selection (or
   437          * there is no valid calendar field under the selection (or the spinner
   417          * the spinner isn't editing dates.
   438          * isn't editing dates.
   418          */
   439          */
   419         private int getCalendarField(final JSpinner spinnerComponent) {
   440         private int getCalendarField(final JSpinner spinnerComponent) {
   420             final JComponent editor = spinnerComponent.getEditor();
   441             final JComponent editor = spinnerComponent.getEditor();
   421             if (!(editor instanceof JSpinner.DateEditor)) return -1;
   442             if (!(editor instanceof JSpinner.DateEditor)) {
   422 
   443                 return -1;
   423             final JSpinner.DateEditor dateEditor = (JSpinner.DateEditor)editor;
   444             }
       
   445 
       
   446             final JSpinner.DateEditor dateEditor = (JSpinner.DateEditor) editor;
   424             final JFormattedTextField ftf = dateEditor.getTextField();
   447             final JFormattedTextField ftf = dateEditor.getTextField();
   425             final int start = ftf.getSelectionStart();
   448             final int start = ftf.getSelectionStart();
   426             final JFormattedTextField.AbstractFormatter formatter = ftf.getFormatter();
   449             final JFormattedTextField.AbstractFormatter formatter = ftf.getFormatter();
   427             if (!(formatter instanceof InternationalFormatter)) return -1;
   450             if (!(formatter instanceof InternationalFormatter)) {
   428 
   451                 return -1;
   429             final Format.Field[] fields = ((InternationalFormatter)formatter).getFields(start);
   452             }
       
   453 
       
   454             final Format.Field[] fields = ((InternationalFormatter) formatter).getFields(start);
   430             for (final Field element : fields) {
   455             for (final Field element : fields) {
   431                 if (!(element instanceof DateFormat.Field)) continue;
   456                 if (!(element instanceof DateFormat.Field)) {
       
   457                     continue;
       
   458                 }
   432                 int calendarField;
   459                 int calendarField;
   433 
   460 
   434                 if (element == DateFormat.Field.HOUR1) {
   461                 if (element == DateFormat.Field.HOUR1) {
   435                     calendarField = Calendar.HOUR;
   462                     calendarField = Calendar.HOUR;
   436                 } else {
   463                 } else {
   437                     calendarField = ((DateFormat.Field)element).getCalendarField();
   464                     calendarField = ((DateFormat.Field) element).getCalendarField();
   438                 }
   465                 }
   439 
   466 
   440                 if (calendarField != -1) {
   467                 if (calendarField != -1) {
   441                     return calendarField;
   468                     return calendarField;
   442                 }
   469                 }
   444             return -1;
   471             return -1;
   445         }
   472         }
   446 
   473 
   447         @Override
   474         @Override
   448         public void mousePressed(final MouseEvent e) {
   475         public void mousePressed(final MouseEvent e) {
   449             if (!SwingUtilities.isLeftMouseButton(e) || !e.getComponent().isEnabled()) return;
   476             if (!SwingUtilities.isLeftMouseButton(e) || !e.getComponent().isEnabled()) {
       
   477                 return;
       
   478             }
   450             spinner = eventToSpinner(e);
   479             spinner = eventToSpinner(e);
   451             autoRepeatTimer.start();
   480             autoRepeatTimer.start();
   452 
   481 
   453             focusSpinnerIfNecessary();
   482             focusSpinnerIfNecessary();
   454         }
   483         }
   458             autoRepeatTimer.stop();
   487             autoRepeatTimer.stop();
   459             spinner = null;
   488             spinner = null;
   460         }
   489         }
   461 
   490 
   462         @Override
   491         @Override
   463         public void mouseClicked(final MouseEvent e) {}
   492         public void mouseClicked(final MouseEvent e) {
   464         @Override
   493         }
   465         public void mouseEntered(final MouseEvent e) {}
   494 
   466         @Override
   495         @Override
   467         public void mouseExited(final MouseEvent e) {}
   496         public void mouseEntered(final MouseEvent e) {
       
   497         }
       
   498 
       
   499         @Override
       
   500         public void mouseExited(final MouseEvent e) {
       
   501         }
   468 
   502 
   469         /**
   503         /**
   470          * Requests focus on a child of the spinner if the spinner doesn't
   504          * Requests focus on a child of the spinner if the spinner doesn't have
   471          * have focus.
   505          * focus.
   472          */
   506          */
   473         private void focusSpinnerIfNecessary() {
   507         private void focusSpinnerIfNecessary() {
   474             final Component fo = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
   508             final Component fo = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
   475             if (!spinner.isRequestFocusEnabled() || (fo != null && (SwingUtilities.isDescendingFrom(fo, spinner)))) return;
   509             if (!spinner.isRequestFocusEnabled() || (fo != null && (SwingUtilities.isDescendingFrom(fo, spinner)))) {
       
   510                 return;
       
   511             }
   476             Container root = spinner;
   512             Container root = spinner;
   477 
   513 
   478             if (!root.isFocusCycleRoot()) {
   514             if (!root.isFocusCycleRoot()) {
   479                 root = root.getFocusCycleRootAncestor();
   515                 root = root.getFocusCycleRootAncestor();
   480             }
   516             }
   481 
   517 
   482             if (root == null) return;
   518             if (root == null) {
       
   519                 return;
       
   520             }
   483             final FocusTraversalPolicy ftp = root.getFocusTraversalPolicy();
   521             final FocusTraversalPolicy ftp = root.getFocusTraversalPolicy();
   484             final Component child = ftp.getComponentAfter(root, spinner);
   522             final Component child = ftp.getComponentAfter(root, spinner);
   485 
   523 
   486             if (child != null && SwingUtilities.isDescendingFrom(child, spinner)) {
   524             if (child != null && SwingUtilities.isDescendingFrom(child, spinner)) {
   487                 child.requestFocus();
   525                 child.requestFocus();
   489         }
   527         }
   490     }
   528     }
   491 
   529 
   492     @SuppressWarnings("serial") // Superclass is not serializable across versions
   530     @SuppressWarnings("serial") // Superclass is not serializable across versions
   493     class SpinPainter extends JComponent {
   531     class SpinPainter extends JComponent {
       
   532 
   494         final AquaPainter<JRSUIState> painter = AquaPainter.create(JRSUIStateFactory.getSpinnerArrows());
   533         final AquaPainter<JRSUIState> painter = AquaPainter.create(JRSUIStateFactory.getSpinnerArrows());
   495 
   534 
   496         ButtonModel fTopModel;
   535         ButtonModel fTopModel;
   497         ButtonModel fBottomModel;
   536         ButtonModel fBottomModel;
   498 
   537 
   549             return kPreferredSize;
   588             return kPreferredSize;
   550         }
   589         }
   551     }
   590     }
   552 
   591 
   553     /**
   592     /**
   554      * A simple layout manager for the editor and the next/previous buttons.
   593      * A simple layout manager for the editor and the next/previous buttons. See
   555      * See the AquaSpinnerUI javadoc for more information about exactly
   594      * the AquaSpinnerUI javadoc for more information about exactly how the
   556      * how the components are arranged.
   595      * components are arranged.
   557      */
   596      */
   558     static class SpinnerLayout implements LayoutManager {
   597     static class SpinnerLayout implements LayoutManager {
       
   598 
   559         private Component nextButton = null;
   599         private Component nextButton = null;
   560         private Component previousButton = null;
   600         private Component previousButton = null;
   561         private Component editor = null;
   601         private Component editor = null;
   562         private Component painter = null;
   602         private Component painter = null;
   563 
   603 
   654             setBounds(painter, buttonsX, painterTop, buttonsWidth, painterD.height);
   694             setBounds(painter, buttonsX, painterTop, buttonsWidth, painterD.height);
   655         }
   695         }
   656     }
   696     }
   657 
   697 
   658     /**
   698     /**
   659      * Detect JSpinner property changes we're interested in and delegate.  Subclasses
   699      * Detect JSpinner property changes we're interested in and delegate.
   660      * shouldn't need to replace the default propertyChangeListener (although they
   700      * Subclasses shouldn't need to replace the default propertyChangeListener
   661      * can by overriding createPropertyChangeListener) since all of the interesting
   701      * (although they can by overriding createPropertyChangeListener) since all
   662      * property changes are delegated to protected methods.
   702      * of the interesting property changes are delegated to protected methods.
   663      */
   703      */
   664     static class PropertyChangeHandler implements PropertyChangeListener {
   704     static class PropertyChangeHandler implements PropertyChangeListener {
       
   705 
   665         @Override
   706         @Override
   666         public void propertyChange(final PropertyChangeEvent e) {
   707         public void propertyChange(final PropertyChangeEvent e) {
   667             final String propertyName = e.getPropertyName();
   708             final String propertyName = e.getPropertyName();
   668             final JSpinner spinner = (JSpinner)(e.getSource());
   709             final JSpinner spinner = (JSpinner) (e.getSource());
   669             final SpinnerUI spinnerUI = spinner.getUI();
   710             final SpinnerUI spinnerUI = spinner.getUI();
   670 
   711 
   671             if (spinnerUI instanceof AquaSpinnerUI) {
   712             if (spinnerUI instanceof AquaSpinnerUI) {
   672                 final AquaSpinnerUI ui = (AquaSpinnerUI)spinnerUI;
   713                 final AquaSpinnerUI ui = (AquaSpinnerUI) spinnerUI;
   673 
   714 
   674                 if ("editor".equals(propertyName)) {
   715                 if ("editor".equals(propertyName)) {
   675                     final JComponent oldEditor = (JComponent)e.getOldValue();
   716                     final JComponent oldEditor = (JComponent) e.getOldValue();
   676                     final JComponent newEditor = (JComponent)e.getNewValue();
   717                     final JComponent newEditor = (JComponent) e.getNewValue();
   677                     ui.replaceEditor(oldEditor, newEditor);
   718                     ui.replaceEditor(oldEditor, newEditor);
   678                     ui.updateEnabledState();
   719                     ui.updateEnabledState();
       
   720                 } else if ("componentOrientation".equals(propertyName)) {
       
   721                     ComponentOrientation o
       
   722                             = (ComponentOrientation) e.getNewValue();
       
   723                     if (o != e.getOldValue()) {
       
   724                         JComponent editor = spinner.getEditor();
       
   725                         if (editor != null) {
       
   726                             editor.applyComponentOrientation(o);
       
   727                         }
       
   728                         spinner.revalidate();
       
   729                         spinner.repaint();
       
   730                     }
   679                 } else if ("enabled".equals(propertyName)) {
   731                 } else if ("enabled".equals(propertyName)) {
   680                     ui.updateEnabledState();
   732                     ui.updateEnabledState();
   681                 } else if (JComponent.TOOL_TIP_TEXT_KEY.equals(propertyName)) {
   733                 } else if (JComponent.TOOL_TIP_TEXT_KEY.equals(propertyName)) {
   682                     ui.updateToolTipTextForChildren(spinner);
   734                     ui.updateToolTipTextForChildren(spinner);
   683                 } else if ("font".equals(propertyName)) {
   735                 } else if ("font".equals(propertyName)) {
   684                     JComponent editor = spinner.getEditor();
   736                     JComponent editor = spinner.getEditor();
   685                     if (editor instanceof JSpinner.DefaultEditor) {
   737                     if (editor instanceof JSpinner.DefaultEditor) {
   686                         JTextField tf =
   738                         JTextField tf
   687                                 ((JSpinner.DefaultEditor) editor).getTextField();
   739                                 = ((JSpinner.DefaultEditor) editor).getTextField();
   688                         if (tf != null) {
   740                         if (tf != null) {
   689                             if (tf.getFont() instanceof UIResource) {
   741                             if (tf.getFont() instanceof UIResource) {
   690                                 tf.setFont(new FontUIResource(spinner.getFont()));
   742                                 tf.setFont(new FontUIResource(spinner.getFont()));
   691                             }
   743                             }
   692                         }
   744                         }
   701     void updateToolTipTextForChildren(final JComponent spinnerComponent) {
   753     void updateToolTipTextForChildren(final JComponent spinnerComponent) {
   702         final String toolTipText = spinnerComponent.getToolTipText();
   754         final String toolTipText = spinnerComponent.getToolTipText();
   703         final Component[] children = spinnerComponent.getComponents();
   755         final Component[] children = spinnerComponent.getComponents();
   704         for (final Component element : children) {
   756         for (final Component element : children) {
   705             if (element instanceof JSpinner.DefaultEditor) {
   757             if (element instanceof JSpinner.DefaultEditor) {
   706                 final JTextField tf = ((JSpinner.DefaultEditor)element).getTextField();
   758                 final JTextField tf = ((JSpinner.DefaultEditor) element).getTextField();
   707                 if (tf != null) {
   759                 if (tf != null) {
   708                     tf.setToolTipText(toolTipText);
   760                     tf.setToolTipText(toolTipText);
   709                 }
   761                 }
   710             } else if (element instanceof JComponent) {
   762             } else if (element instanceof JComponent) {
   711                 ((JComponent)element).setToolTipText(toolTipText);
   763                 ((JComponent) element).setToolTipText(toolTipText);
   712             }
   764             }
   713         }
   765         }
   714     }
   766     }
   715 }
   767 }