001    /* BasicColorChooserUI.java --
002       Copyright (C) 2004, 2005 Free Software Foundation, Inc.
003    
004    This file is part of GNU Classpath.
005    
006    GNU Classpath is free software; you can redistribute it and/or modify
007    it under the terms of the GNU General Public License as published by
008    the Free Software Foundation; either version 2, or (at your option)
009    any later version.
010    
011    GNU Classpath is distributed in the hope that it will be useful, but
012    WITHOUT ANY WARRANTY; without even the implied warranty of
013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014    General Public License for more details.
015    
016    You should have received a copy of the GNU General Public License
017    along with GNU Classpath; see the file COPYING.  If not, write to the
018    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019    02110-1301 USA.
020    
021    Linking this library statically or dynamically with other modules is
022    making a combined work based on this library.  Thus, the terms and
023    conditions of the GNU General Public License cover the whole
024    combination.
025    
026    As a special exception, the copyright holders of this library give you
027    permission to link this library with independent modules to produce an
028    executable, regardless of the license terms of these independent
029    modules, and to copy and distribute the resulting executable under
030    terms of your choice, provided that you also meet, for each linked
031    independent module, the terms and conditions of the license of that
032    module.  An independent module is a module which is not derived from
033    or based on this library.  If you modify this library, you may extend
034    this exception to your version of the library, but you are not
035    obligated to do so.  If you do not wish to do so, delete this
036    exception statement from your version. */
037    
038    
039    package javax.swing.plaf.basic;
040    
041    import java.awt.BorderLayout;
042    import java.awt.Container;
043    import java.beans.PropertyChangeEvent;
044    import java.beans.PropertyChangeListener;
045    
046    import javax.swing.JColorChooser;
047    import javax.swing.JComponent;
048    import javax.swing.JPanel;
049    import javax.swing.JTabbedPane;
050    import javax.swing.LookAndFeel;
051    import javax.swing.colorchooser.AbstractColorChooserPanel;
052    import javax.swing.colorchooser.ColorChooserComponentFactory;
053    import javax.swing.event.ChangeEvent;
054    import javax.swing.event.ChangeListener;
055    import javax.swing.plaf.ColorChooserUI;
056    import javax.swing.plaf.ComponentUI;
057    
058    /**
059     * This is the UI Class for the JColorChooser in the Basic Look and Feel.
060     */
061    public class BasicColorChooserUI extends ColorChooserUI
062    {
063      /**
064       * This helper class handles property changes from the JColorChooser.
065       */
066      public class PropertyHandler implements PropertyChangeListener
067      {
068        /**
069         * This method is called when any of the properties of the JColorChooser
070         * change.
071         *
072         * @param e The PropertyChangeEvent.
073         */
074        public void propertyChange(PropertyChangeEvent e)
075        {
076          if (e.getPropertyName() == JColorChooser.CHOOSER_PANELS_PROPERTY)
077            makeTabs(chooser.getChooserPanels());
078          else if (e.getPropertyName() == JColorChooser.PREVIEW_PANEL_PROPERTY)
079            updatePreviewPanel(chooser.getPreviewPanel());
080          else if (e.getPropertyName() == JColorChooser.SELECTION_MODEL_PROPERTY)
081            ((AbstractColorChooserPanel) pane.getSelectedComponent())
082            .updateChooser();
083    
084          chooser.repaint();
085        }
086      }
087    
088      /**
089       * This is a helper class that listens to the Model of the JColorChooser for
090       * color change events so it can update the preview panel.
091       */
092      private class PreviewListener implements ChangeListener
093      {
094        /**
095         * This method is called whenever the JColorChooser's color changes.
096         *
097         * @param e The ChangeEvent.
098         */
099        public void stateChanged(ChangeEvent e)
100        {
101          if (pane != null)
102            {
103              AbstractColorChooserPanel panel = (AbstractColorChooserPanel) pane
104                                                .getSelectedComponent();
105              if (panel != null)
106                panel.updateChooser();
107            }
108          chooser.repaint();
109        }
110      }
111    
112      /**
113       * This helper class listens to the JTabbedPane that is used for tab
114       * changes.
115       */
116      private class TabPaneListener implements ChangeListener
117      {
118        /**
119         * This method is called whenever a different tab is selected in the
120         * JTabbedPane.
121         *
122         * @param e The ChangeEvent.
123         */
124        public void stateChanged(ChangeEvent e)
125        {
126          // Need to do this because we don't update all the tabs when they're not
127          // visible, so they are not informed of new colors when they're hidden.
128          AbstractColorChooserPanel comp = (AbstractColorChooserPanel) pane
129                                           .getSelectedComponent();
130          comp.updateChooser();
131        }
132      }
133    
134      /** An array of default choosers to use in the JColorChooser. */
135      protected AbstractColorChooserPanel[] defaultChoosers;
136    
137      /** The listener for the preview panel. */
138      protected ChangeListener previewListener;
139    
140      /** The PropertyChangeListener for the JColorChooser. */
141      protected PropertyChangeListener propertyChangeListener;
142    
143      /**
144       * The JColorChooser this is installed on.
145       */
146      protected JColorChooser chooser;
147    
148      /** The JTabbedPane that is used. */
149      JTabbedPane pane;
150    
151      /** The Container that holds the preview panel. */
152      private Container prevContainer;
153    
154      /**
155       * Creates a new BasicColorChooserUI object.
156       */
157      public BasicColorChooserUI()
158      {
159        super();
160      }
161    
162      /**
163       * This method creates a new UI Component for the given JComponent.
164       *
165       * @param c The JComponent to create an UI for.
166       *
167       * @return A new BasicColorChooserUI.
168       */
169      public static ComponentUI createUI(JComponent c)
170      {
171        return new BasicColorChooserUI();
172      }
173    
174      /**
175       * This method creates the default chooser panels for the JColorChooser.
176       *
177       * @return The default chooser panels.
178       */
179      protected AbstractColorChooserPanel[] createDefaultChoosers()
180      {
181        return ColorChooserComponentFactory.getDefaultChooserPanels();
182      }
183    
184      /**
185       * This method installs the UI Component for the given JComponent.
186       *
187       * @param c The JComponent to install this UI for.
188       */
189      public void installUI(JComponent c)
190      {
191        if (c instanceof JColorChooser)
192          {
193            chooser = (JColorChooser) c;
194            chooser.setLayout(new BorderLayout());
195    
196            // Do this first, so we avoid doing work for property change events.
197            defaultChoosers = createDefaultChoosers();
198            chooser.setChooserPanels(defaultChoosers);
199            pane = new JTabbedPane();
200    
201            pane.addChangeListener(new ChangeListener()
202                {
203                  public void stateChanged(ChangeEvent e)
204                  {
205                    pane.repaint();
206                  }
207                });
208    
209            makeTabs(defaultChoosers);
210    
211            chooser.add(pane, BorderLayout.NORTH);
212    
213            installPreviewPanel();
214    
215            installDefaults();
216            installListeners();
217          }
218      }
219    
220      /**
221       * This method adds tabs to the JTabbedPane for the chooserPanels defined in
222       * the JColorChooser.
223       * This is package-private to avoid an accessor method.
224       *
225       * @param panels The Panels that need tabs to be made for them.
226       */
227      void makeTabs(AbstractColorChooserPanel[] panels)
228      {
229        pane.removeAll();
230        for (int i = 0; i < panels.length; i++)
231          pane.addTab(panels[i].getDisplayName(), panels[i].getSmallDisplayIcon(),
232                      panels[i]);
233      }
234    
235      /**
236       * This method uninstalls this UI for the given JComponent.
237       *
238       * @param c The JComponent that will have this UI removed.
239       */
240      public void uninstallUI(JComponent c)
241      {
242        uninstallListeners();
243        uninstallDefaults();
244        uninstallDefaultChoosers();
245    
246        pane = null;
247        chooser = null;
248      }
249    
250      /**
251       * Uninstalls the default color choosers that have been installed by this UI.
252       */
253      protected void uninstallDefaultChoosers()
254      {
255        defaultChoosers = null;
256      }
257    
258      /**
259       * This method installs the preview panel for the JColorChooser.
260       */
261      protected void installPreviewPanel()
262      {
263        updatePreviewPanel(ColorChooserComponentFactory.getPreviewPanel());
264      }
265    
266      /**
267       * This is a helper method that swaps the existing preview panel with the
268       * given panel.
269       * This is package-private to avoid an accessor method.
270       *
271       * @param preview The new preview panel.
272       */
273      void updatePreviewPanel(JComponent preview)
274      {
275        if (prevContainer == null)
276          {
277            prevContainer = new JPanel();
278            prevContainer.setLayout(new BorderLayout());
279            chooser.add(prevContainer, BorderLayout.CENTER);
280          }
281        prevContainer.removeAll();
282        prevContainer.add(preview, BorderLayout.CENTER);
283      }
284    
285      /**
286       * This method installs the default properties given by the Basic Look and
287       * Feel.
288       */
289      protected void installDefaults()
290      {
291        LookAndFeel.installColorsAndFont(chooser, "ColorChooser.background",
292                                         "ColorChooser.foreground",
293                                         "ColorChooser.font");
294      }
295    
296      /**
297       * This method uninstalls the default properties given by the Basic Look and
298       * Feel.
299       */
300      protected void uninstallDefaults()
301      {
302        chooser.setBackground(null);
303        chooser.setForeground(null);
304        chooser.setFont(null);
305      }
306    
307      /**
308       * This method installs any listeners required for this UI to function.
309       */
310      protected void installListeners()
311      {
312        propertyChangeListener = createPropertyChangeListener();
313        previewListener = new PreviewListener();
314    
315        chooser.addPropertyChangeListener(propertyChangeListener);
316        chooser.getSelectionModel().addChangeListener(previewListener);
317    
318        pane.addChangeListener(new TabPaneListener());
319      }
320    
321      /**
322       * This method creates the PropertyChangeListener used for listening to the
323       * JColorChooser.
324       *
325       * @return A PropertyChangeListener.
326       */
327      protected PropertyChangeListener createPropertyChangeListener()
328      {
329        return new PropertyHandler();
330      }
331    
332      /**
333       * This method uninstalls any listeners that were previously installed by
334       * the UI.
335       */
336      protected void uninstallListeners()
337      {
338        chooser.removePropertyChangeListener(propertyChangeListener);
339        chooser.getSelectionModel().removeChangeListener(previewListener);
340    
341        previewListener = null;
342        propertyChangeListener = null;
343      }
344    }