KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > swing > LookAndFeel


1 /*
2  * @(#)LookAndFeel.java 1.38 05/01/04
3  *
4  * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package javax.swing;
9
10 import java.awt.Font JavaDoc;
11 import java.awt.event.InputEvent JavaDoc;
12 import java.awt.event.KeyEvent JavaDoc;
13 import java.awt.Color JavaDoc;
14 import java.awt.Component JavaDoc;
15 import java.awt.SystemColor JavaDoc;
16 import java.awt.Toolkit JavaDoc;
17
18 import javax.swing.text.*;
19 import javax.swing.border.*;
20 import javax.swing.plaf.*;
21
22 import java.net.URL JavaDoc;
23 import com.sun.java.swing.SwingUtilities2;
24
25 import java.util.StringTokenizer JavaDoc;
26
27
28 /**
29  * Completely characterizes a look and feel from the point of view
30  * of the pluggable look and feel components.
31  *
32  * @version 1.38 01/04/05
33  * @author Tom Ball
34  * @author Hans Muller
35  */

36 public abstract class LookAndFeel
37 {
38
39     /**
40      * Convenience method for initializing a component's foreground
41      * and background color properties with values from the current
42      * defaults table. The properties are only set if the current
43      * value is either null or a UIResource.
44      *
45      * @param c the target component for installing default color/font properties
46      * @param defaultBgName the key for the default background
47      * @param defaultFgName the key for the default foreground
48      *
49      * @see #installColorsAndFont
50      * @see UIManager#getColor
51      */

52     public static void installColors(JComponent JavaDoc c,
53                      String JavaDoc defaultBgName,
54                                      String JavaDoc defaultFgName)
55     {
56         Color JavaDoc bg = c.getBackground();
57     if (bg == null || bg instanceof UIResource) {
58         c.setBackground(UIManager.getColor(defaultBgName));
59     }
60
61         Color JavaDoc fg = c.getForeground();
62     if (fg == null || fg instanceof UIResource) {
63         c.setForeground(UIManager.getColor(defaultFgName));
64     }
65     }
66
67
68     /**
69      * Convenience method for initializing a components foreground
70      * background and font properties with values from the current
71      * defaults table. The properties are only set if the current
72      * value is either null or a UIResource.
73      *
74      * @param c the target component for installing default color/font properties
75      * @param defaultBgName the key for the default background
76      * @param defaultFgName the key for the default foreground
77      * @param defaultFontName the key for the default font
78      *
79      * @see #installColors
80      * @see UIManager#getColor
81      * @see UIManager#getFont
82      */

83     public static void installColorsAndFont(JComponent JavaDoc c,
84                                          String JavaDoc defaultBgName,
85                                          String JavaDoc defaultFgName,
86                                          String JavaDoc defaultFontName) {
87         Font JavaDoc f = c.getFont();
88     if (f == null || f instanceof UIResource) {
89         c.setFont(UIManager.getFont(defaultFontName));
90     }
91
92     installColors(c, defaultBgName, defaultFgName);
93     }
94
95
96     /**
97      * Convenience method for installing a component's default Border
98      * object on the specified component if either the border is
99      * currently null or already an instance of UIResource.
100      * @param c the target component for installing default border
101      * @param defaultBorderName the key specifying the default border
102      */

103     public static void installBorder(JComponent JavaDoc c, String JavaDoc defaultBorderName) {
104         Border b = c.getBorder();
105         if (b == null || b instanceof UIResource) {
106             c.setBorder(UIManager.getBorder(defaultBorderName));
107         }
108     }
109
110
111     /**
112      * Convenience method for un-installing a component's default
113      * border on the specified component if the border is
114      * currently an instance of UIResource.
115      * @param c the target component for uninstalling default border
116      */

117     public static void uninstallBorder(JComponent JavaDoc c) {
118         if (c.getBorder() instanceof UIResource) {
119             c.setBorder(null);
120         }
121     }
122
123     /**
124      * Convenience method for installing a property with the specified name
125      * and value on a component if that property has not already been set
126      * by the client program. This method is intended to be used by
127      * UI delegate instances that need to specify a default value for a
128      * property of primitive type (boolean, int, ..), but do not wish
129      * to override a value set by the client. Since primitive property
130      * values cannot be wrapped with the UIResource marker, this method
131      * uses private state to determine whether the property has been set
132      * by the client.
133      * @throws IllegalArgumentException if the specified property is not
134      * one which can be set using this method
135      * @throws ClassCastException may be thrown if the property value
136      * specified does not match the property's type
137      * @throws NullPointerException may be thrown if c or propertyValue is null
138      * @param c the target component for installing the property
139      * @param propertyName String containing the name of the property to be set
140      * @param propertyValue Object containing the value of the property
141      */

142     public static void installProperty(JComponent JavaDoc c,
143                        String JavaDoc propertyName, Object JavaDoc propertyValue) {
144         c.setUIProperty(propertyName, propertyValue);
145     }
146
147     /**
148      * Convenience method for building lists of KeyBindings.
149      * <p>
150      * Return an array of KeyBindings, one for each KeyStroke,Action pair
151      * in <b>keyBindingList</b>. A KeyStroke can either be a string in
152      * the format specified by the <code>KeyStroke.getKeyStroke</code>
153      * method or a KeyStroke object.
154      * <p>
155      * Actions are strings. Here's an example:
156      * <pre>
157      * JTextComponent.KeyBinding[] multilineBindings = makeKeyBindings( new Object[] {
158      * "UP", DefaultEditorKit.upAction,
159      * "DOWN", DefaultEditorKit.downAction,
160      * "PAGE_UP", DefaultEditorKit.pageUpAction,
161      * "PAGE_DOWN", DefaultEditorKit.pageDownAction,
162      * "ENTER", DefaultEditorKit.insertBreakAction,
163      * "TAB", DefaultEditorKit.insertTabAction
164      * });
165      * </pre>
166      *
167      * @param keyBindingList an array of KeyStroke,Action pairs
168      * @return an array of KeyBindings
169      */

170     public static JTextComponent.KeyBinding[] makeKeyBindings(Object JavaDoc[] keyBindingList)
171     {
172     JTextComponent.KeyBinding[] rv = new JTextComponent.KeyBinding[keyBindingList.length / 2];
173
174     for(int i = 0; i < keyBindingList.length; i += 2) {
175         KeyStroke JavaDoc keystroke = (keyBindingList[i] instanceof KeyStroke JavaDoc)
176         ? (KeyStroke JavaDoc)keyBindingList[i]
177         : KeyStroke.getKeyStroke((String JavaDoc)keyBindingList[i]);
178         String JavaDoc action = (String JavaDoc)keyBindingList[i+1];
179         rv[i / 2] = new JTextComponent.KeyBinding(keystroke, action);
180     }
181
182     return rv;
183     }
184
185     /**
186      * Creates a InputMap from <code>keys</code>. <code>keys</code>
187      * describes the InputMap, with every even number item being a String
188      * giving the KeyStroke as speced in
189      * <code>KeyStroke.getKeyStroke(String)</code>
190      * (or a KeyStroke), and every odd number item the Object
191      * used to determine the associated Action in an ActionMap.
192      *
193      * @since 1.3
194      */

195     public static InputMap JavaDoc makeInputMap(Object JavaDoc[] keys) {
196     InputMap JavaDoc retMap = new InputMapUIResource();
197     loadKeyBindings(retMap, keys);
198     return retMap;
199     }
200
201     /**
202      * Creates a ComponentInputMap from <code>keys</code>. <code>keys</code>
203      * describes the InputMap, with every even number item being a String
204      * giving
205      * the KeyStroke as speced in <code>KeyStroke.getKeyStroke(String)</code>
206      * (or a KeyStroke), and every odd number item the Object
207      * used to determine the associated Action in an ActionMap.
208      *
209      * @since 1.3
210      */

211     public static ComponentInputMap JavaDoc makeComponentInputMap(JComponent JavaDoc c,
212                               Object JavaDoc[] keys) {
213     ComponentInputMap JavaDoc retMap = new ComponentInputMapUIResource(c);
214     loadKeyBindings(retMap, keys);
215     return retMap;
216     }
217
218
219     /**
220      * Loads the bindings in <code>keys</code> into <code>retMap</code>.
221      * This does not remove any existing bindings in <code>retMap</code>.
222      * <code>keys</code>
223      * describes the InputMap, with every even number item being a String
224      * giving
225      * the KeyStroke as speced in <code>KeyStroke.getKeyStroke(String)</code>
226      * (or a KeyStroke), and every odd number item the Object
227      * used to determine the associated Action in an ActionMap.
228      *
229      * @since 1.3
230      */

231     public static void loadKeyBindings(InputMap JavaDoc retMap, Object JavaDoc[] keys) {
232     if (keys != null) {
233         for (int counter = 0, maxCounter = keys.length;
234          counter < maxCounter; counter++) {
235         Object JavaDoc keyStrokeO = keys[counter++];
236         KeyStroke JavaDoc ks = (keyStrokeO instanceof KeyStroke JavaDoc) ?
237                         (KeyStroke JavaDoc)keyStrokeO :
238                         KeyStroke.getKeyStroke((String JavaDoc)keyStrokeO);
239         retMap.put(ks, keys[counter]);
240         }
241     }
242     }
243
244     /**
245      * Utility method that creates a UIDefaults.LazyValue that creates
246      * an ImageIcon UIResource for the specified <code>gifFile</code>
247      * filename.
248      */

249     public static Object JavaDoc makeIcon(final Class JavaDoc<?> baseClass, final String JavaDoc gifFile) {
250         return SwingUtilities2.makeIcon(baseClass, baseClass, gifFile);
251     }
252
253     /**
254      * Invoked when the user attempts an invalid operation,
255      * such as pasting into an uneditable <code>JTextField</code>
256      * that has focus. The default implementation beeps. Subclasses
257      * that wish different behavior should override this and provide
258      * the additional feedback.
259      *
260      * @param component the <code>Component</code> the error occurred in,
261      * may be <code>null</code>
262      * indicating the error condition is not directly
263      * associated with a <code>Component</code>
264      * @since 1.4
265      */

266     public void provideErrorFeedback(Component JavaDoc component) {
267     Toolkit JavaDoc toolkit = null;
268     if (component != null) {
269         toolkit = component.getToolkit();
270     } else {
271         toolkit = Toolkit.getDefaultToolkit();
272     }
273     toolkit.beep();
274     } // provideErrorFeedback()
275

276     /**
277      * Returns the value of the specified system desktop property by
278      * invoking <code>Toolkit.getDefaultToolkit().getDesktopProperty()</code>.
279      * If the current value of the specified property is null, the
280      * fallbackValue is returned.
281      * @param systemPropertyName the name of the system desktop property being queried
282      * @param fallbackValue the object to be returned as the value if the system value is null
283      * @return the current value of the desktop property
284      *
285      * @see java.awt.Toolkit#getDesktopProperty
286      *
287      */

288     public static Object JavaDoc getDesktopPropertyValue(String JavaDoc systemPropertyName, Object JavaDoc fallbackValue) {
289     Object JavaDoc value = Toolkit.getDefaultToolkit().getDesktopProperty(systemPropertyName);
290     if (value == null) {
291         return fallbackValue;
292     } else if (value instanceof Color JavaDoc) {
293         return new ColorUIResource((Color JavaDoc)value);
294     } else if (value instanceof Font JavaDoc) {
295         return new FontUIResource((Font JavaDoc)value);
296     }
297     return value;
298     }
299
300     /**
301      * Returns an <code>Icon</code> with a disabled appearance.
302      * This method is used to generate a disabled <code>Icon</code> when
303      * one has not been specified. For example, if you create a
304      * <code>JButton</code> and only specify an <code>Icon</code> via
305      * <code>setIcon</code> this method will be called to generate the
306      * disabled <code>Icon</code>. If null is passed as <code>icon</code>
307      * this method returns null.
308      * <p>
309      * Some look and feels might not render the disabled Icon, in which
310      * case they will ignore this.
311      *
312      * @param component JComponent that will display the Icon, may be null
313      * @param icon Icon to generate disable icon from.
314      * @return Disabled icon, or null if a suitable Icon can not be
315      * generated.
316      * @since 1.5
317      */

318     public Icon JavaDoc getDisabledIcon(JComponent JavaDoc component, Icon JavaDoc icon) {
319         if (icon instanceof ImageIcon JavaDoc) {
320             return new IconUIResource(new ImageIcon JavaDoc(GrayFilter.
321                    createDisabledImage(((ImageIcon JavaDoc)icon).getImage())));
322         }
323         return null;
324     }
325
326     /**
327      * Returns an <code>Icon</code> for use by disabled
328      * components that are also selected. This method is used to generate an
329      * <code>Icon</code> for components that are in both the disabled and
330      * selected states but do not have a specific <code>Icon</code> for this
331      * state. For example, if you create a <code>JButton</code> and only
332      * specify an <code>Icon</code> via <code>setIcon</code> this method
333      * will be called to generate the disabled and selected
334      * <code>Icon</code>. If null is passed as <code>icon</code> this method
335      * returns null.
336      * <p>
337      * Some look and feels might not render the disabled and selected Icon,
338      * in which case they will ignore this.
339      *
340      * @param component JComponent that will display the Icon, may be null
341      * @param icon Icon to generate disabled and selected icon from.
342      * @return Disabled and Selected icon, or null if a suitable Icon can not
343      * be generated.
344      * @since 1.5
345      */

346     public Icon JavaDoc getDisabledSelectedIcon(JComponent JavaDoc component, Icon JavaDoc icon) {
347         return getDisabledIcon(component, icon);
348     }
349
350     /**
351      * Return a short string that identifies this look and feel, e.g.
352      * "CDE/Motif". This string should be appropriate for a menu item.
353      * Distinct look and feels should have different names, e.g.
354      * a subclass of MotifLookAndFeel that changes the way a few components
355      * are rendered should be called "CDE/Motif My Way"; something
356      * that would be useful to a user trying to select a L&F from a list
357      * of names.
358      */

359     public abstract String JavaDoc getName();
360
361
362     /**
363      * Return a string that identifies this look and feel. This string
364      * will be used by applications/services that want to recognize
365      * well known look and feel implementations. Presently
366      * the well known names are "Motif", "Windows", "Mac", "Metal". Note
367      * that a LookAndFeel derived from a well known superclass
368      * that doesn't make any fundamental changes to the look or feel
369      * shouldn't override this method.
370      */

371     public abstract String JavaDoc getID();
372
373
374     /**
375      * Return a one line description of this look and feel implementation,
376      * e.g. "The CDE/Motif Look and Feel". This string is intended for
377      * the user, e.g. in the title of a window or in a ToolTip message.
378      */

379     public abstract String JavaDoc getDescription();
380
381
382     /**
383      * Returns true if the <code>LookAndFeel</code> returned
384      * <code>RootPaneUI</code> instances support providing Window decorations
385      * in a <code>JRootPane</code>.
386      * <p>
387      * The default implementation returns false, subclasses that support
388      * Window decorations should override this and return true.
389      *
390      * @return True if the RootPaneUI instances created support client side
391      * decorations
392      * @see JDialog#setDefaultLookAndFeelDecorated
393      * @see JFrame#setDefaultLookAndFeelDecorated
394      * @see JRootPane#setWindowDecorationStyle
395      * @since 1.4
396      */

397     public boolean getSupportsWindowDecorations() {
398         return false;
399     }
400
401     /**
402      * If the underlying platform has a "native" look and feel, and this
403      * is an implementation of it, return true. For example a CDE/Motif
404      * look and implementation would return true when the underlying
405      * platform was Solaris.
406      */

407     public abstract boolean isNativeLookAndFeel();
408
409
410     /**
411      * Return true if the underlying platform supports and or permits
412      * this look and feel. This method returns false if the look
413      * and feel depends on special resources or legal agreements that
414      * aren't defined for the current platform.
415      *
416      * @see UIManager#setLookAndFeel
417      */

418     public abstract boolean isSupportedLookAndFeel();
419
420
421     /**
422      * UIManager.setLookAndFeel calls this method before the first
423      * call (and typically the only call) to getDefaults(). Subclasses
424      * should do any one-time setup they need here, rather than
425      * in a static initializer, because look and feel class objects
426      * may be loaded just to discover that isSupportedLookAndFeel()
427      * returns false.
428      *
429      * @see #uninitialize
430      * @see UIManager#setLookAndFeel
431      */

432     public void initialize() {
433     }
434
435
436     /**
437      * UIManager.setLookAndFeel calls this method just before we're
438      * replaced by a new default look and feel. Subclasses may
439      * choose to free up some resources here.
440      *
441      * @see #initialize
442      */

443     public void uninitialize() {
444     }
445
446     /**
447      * This method is called once by UIManager.setLookAndFeel to create
448      * the look and feel specific defaults table. Other applications,
449      * for example an application builder, may also call this method.
450      *
451      * @see #initialize
452      * @see #uninitialize
453      * @see UIManager#setLookAndFeel
454      */

455     public UIDefaults JavaDoc getDefaults() {
456         return null;
457     }
458
459     /**
460      * Returns a string that displays and identifies this
461      * object's properties.
462      *
463      * @return a String representation of this object
464      */

465     public String JavaDoc toString() {
466     return "[" + getDescription() + " - " + getClass().getName() + "]";
467     }
468 }
469
Popular Tags