/* * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * - Neither the name of Oracle or the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Based on SpinnerDemo, this application listens for * changes in a spinner's values. Specifically, we listen * for when the third spinner changes and then change that * spinner's text color accordingly. * Other files required: * SpringUtilities.java * CyclingSpinnerListModel.java */ package javademo.swing.spinner; import java.awt.Color; import java.awt.Container; import java.util.Calendar; import java.util.Date; import javax.swing.BorderFactory; import javax.swing.JComponent; import javax.swing.JFormattedTextField; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JSpinner; import javax.swing.JTextField; import javax.swing.SpinnerDateModel; import javax.swing.SpinnerListModel; import javax.swing.SpinnerModel; import javax.swing.SpinnerNumberModel; import javax.swing.SpringLayout; import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; public class SpinnerDemo3 extends JPanel implements ChangeListener { private static final long serialVersionUID = 1L; protected Calendar calendar; protected JSpinner dateSpinner; protected Color SPRING_COLOR = new Color(0, 204, 51); protected Color SUMMER_COLOR = Color.RED; protected Color FALL_COLOR = new Color(255, 153, 0); protected Color WINTER_COLOR = Color.CYAN; public SpinnerDemo3(boolean cycleMonths) { super(new SpringLayout()); String[] labels = { "Month: ", "Year: ", "Another Date: " }; int numPairs = labels.length; calendar = Calendar.getInstance(); JFormattedTextField ftf = null; // Add the first label-spinner pair. String[] monthStrings = getMonthStrings(); // get month names SpinnerListModel monthModel = null; if (cycleMonths) { // use custom model monthModel = new CyclingSpinnerListModel(monthStrings); } else { // use standard model monthModel = new SpinnerListModel(monthStrings); } JSpinner spinner = addLabeledSpinner(this, labels[0], monthModel); // Tweak the spinner's formatted text field. ftf = getTextField(spinner); if (ftf != null) { ftf.setColumns(8); // specify more width than we need ftf.setHorizontalAlignment(JTextField.RIGHT); } // Add second label-spinner pair. int currentYear = calendar.get(Calendar.YEAR); SpinnerModel yearModel = new SpinnerNumberModel(currentYear, // initial value currentYear - 100, // min currentYear + 100, // max 1); // step // If we're cycling, hook this model up to the month model. if (monthModel instanceof CyclingSpinnerListModel) { ((CyclingSpinnerListModel)monthModel).setLinkedModel(yearModel); } spinner = addLabeledSpinner(this, labels[1], yearModel); // Make the year be formatted without a thousands separator. spinner.setEditor(new JSpinner.NumberEditor(spinner, "#")); // Add the third label-spinner pair. Date initDate = calendar.getTime(); calendar.add(Calendar.YEAR, -100); Date earliestDate = calendar.getTime(); calendar.add(Calendar.YEAR, 200); Date latestDate = calendar.getTime(); SpinnerDateModel dateModel = new SpinnerDateModel(initDate, earliestDate, latestDate, Calendar.YEAR);// ignored // for user // input dateSpinner = spinner = addLabeledSpinner(this, labels[2], dateModel); spinner.setEditor(new JSpinner.DateEditor(spinner, "MM/yyyy")); // Tweak the spinner's formatted text field. ftf = getTextField(spinner); if (ftf != null) { ftf.setHorizontalAlignment(JTextField.RIGHT); ftf.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 3)); } spinner.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1)); // XXX: No easy way to get to the buttons and change their border. setSeasonalColor(dateModel.getDate()); // initialize color // Listen for changes on the date spinner. dateSpinner.addChangeListener(this); // Lay out the panel. SpringUtilities.makeCompactGrid(this, numPairs, 2, // rows, cols 10, 10, // initX, initY 6, 10); // xPad, yPad } /** * Return the formatted text field used by the editor, or * null if the editor doesn't descend from JSpinner.DefaultEditor. */ public JFormattedTextField getTextField(JSpinner spinner) { JComponent editor = spinner.getEditor(); if (editor instanceof JSpinner.DefaultEditor) { return ((JSpinner.DefaultEditor)editor).getTextField(); } else { System.err.println("Unexpected editor type: " + spinner.getEditor().getClass() + " isn't a descendant of DefaultEditor"); return null; } } /** * Required by the ChangeListener interface. Listens for * changes in the date spinner and does something silly in * response. */ public void stateChanged(ChangeEvent e) { SpinnerModel dateModel = dateSpinner.getModel(); if (dateModel instanceof SpinnerDateModel) { setSeasonalColor(((SpinnerDateModel)dateModel).getDate()); } } protected void setSeasonalColor(Date date) { calendar.setTime(date); int month = calendar.get(Calendar.MONTH); JFormattedTextField ftf = getTextField(dateSpinner); if (ftf == null) return; // Set the color to match northern hemisphere seasonal conventions. switch (month) { case 2: // March case 3: // April case 4: // May ftf.setForeground(SPRING_COLOR); break; case 5: // June case 6: // July case 7: // August ftf.setForeground(SUMMER_COLOR); break; case 8: // September case 9: // October case 10: // November ftf.setForeground(FALL_COLOR); break; default: // December, January, February ftf.setForeground(WINTER_COLOR); } } /** * DateFormatSymbols returns an extra, empty value at the * end of the array of months. Remove it. */ static protected String[] getMonthStrings() { String[] months = new java.text.DateFormatSymbols().getMonths(); int lastIndex = months.length - 1; if (months[lastIndex] == null || months[lastIndex].length() <= 0) { // last item empty String[] monthStrings = new String[lastIndex]; System.arraycopy(months, 0, monthStrings, 0, lastIndex); return monthStrings; } else { // last item not empty return months; } } static protected JSpinner addLabeledSpinner(Container c, String label, SpinnerModel model) { JLabel l = new JLabel(label); c.add(l); JSpinner spinner = new JSpinner(model); l.setLabelFor(spinner); c.add(spinner); return spinner; } /** * Create the GUI and show it. For thread safety, * this method should be invoked from the * event dispatch thread. */ private static void createAndShowGUI() { // Create and set up the window. JFrame frame = new JFrame("SpinnerDemo3"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Add content to the window. frame.add(new SpinnerDemo3(true)); // Display the window. frame.pack(); frame.setVisible(true); } public static void main(String[] args) { // Schedule a job for the event dispatch thread: // creating and showing this application's GUI. SwingUtilities.invokeLater(new Runnable() { public void run() { // Turn off metal's use of bold fonts UIManager.put("swing.boldMetal", Boolean.FALSE); createAndShowGUI(); } }); } }