Source Code Cross Referenced for SynthLookAndFeel.java in  » 6.0-JDK-Core » swing » javax » swing » plaf » synth » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Home
Java Source Code / Java Documentation
1.6.0 JDK Core
2.6.0 JDK Modules
3.6.0 JDK Modules com.sun
4.6.0 JDK Modules com.sun.java
5.6.0 JDK Modules sun
6.6.0 JDK Platform
7.Ajax
8.Apache Harmony Java SE
9.Aspect oriented
10.Authentication Authorization
11.Blogger System
12.Build
13.Byte Code
14.Cache
15.Chart
16.Chat
17.Code Analyzer
18.Collaboration
19.Content Management System
20.Database Client
21.Database DBMS
22.Database JDBC Connection Pool
23.Database ORM
24.Development
25.EJB Server
26.ERP CRM Financial
27.ESB
28.Forum
29.Game
30.GIS
31.Graphic 3D
32.Graphic Library
33.Groupware
34.HTML Parser
35.IDE
36.IDE Eclipse
37.IDE Netbeans
38.Installer
39.Internationalization Localization
40.Inversion of Control
41.Issue Tracking
42.J2EE
43.J2ME
44.JBoss
45.JMS
46.JMX
47.Library
48.Mail Clients
49.Music
50.Net
51.Parser
52.PDF
53.Portal
54.Profiler
55.Project Management
56.Report
57.RSS RDF
58.Rule Engine
59.Science
60.Scripting
61.Search Engine
62.Security
63.Sevlet Container
64.Source Control
65.Swing Library
66.Template Engine
67.Test Coverage
68.Testing
69.UML
70.Web Crawler
71.Web Framework
72.Web Mail
73.Web Server
74.Web Services
75.Web Services apache cxf 2.2.6
76.Web Services AXIS2
77.Wiki Engine
78.Workflow Engines
79.XML
80.XML UI
Java Source Code / Java Documentation » 6.0 JDK Core » swing » javax.swing.plaf.synth 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001        /*
002         * Copyright 2002-2006 Sun Microsystems, Inc.  All Rights Reserved.
003         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004         *
005         * This code is free software; you can redistribute it and/or modify it
006         * under the terms of the GNU General Public License version 2 only, as
007         * published by the Free Software Foundation.  Sun designates this
008         * particular file as subject to the "Classpath" exception as provided
009         * by Sun in the LICENSE file that accompanied this code.
010         *
011         * This code is distributed in the hope that it will be useful, but WITHOUT
012         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014         * version 2 for more details (a copy is included in the LICENSE file that
015         * accompanied this code).
016         *
017         * You should have received a copy of the GNU General Public License version
018         * 2 along with this work; if not, write to the Free Software Foundation,
019         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020         *
021         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022         * CA 95054 USA or visit www.sun.com if you need additional information or
023         * have any questions.
024         */
025        package javax.swing.plaf.synth;
026
027        import java.awt.*;
028        import java.beans.*;
029        import java.io.*;
030        import java.lang.ref.*;
031        import java.net.*;
032        import java.security.*;
033        import java.text.*;
034        import java.util.*;
035        import javax.swing.*;
036        import javax.swing.plaf.*;
037        import javax.swing.plaf.basic.*;
038
039        import sun.awt.*;
040        import sun.security.action.*;
041        import sun.swing.*;
042        import sun.swing.plaf.synth.*;
043
044        /**
045         * SynthLookAndFeel provides the basis for creating a customized look and
046         * feel. SynthLookAndFeel does not directly provide a look, all painting is
047         * delegated.
048         * You need to either provide a configuration file, by way of the
049         * {@link #load} method, or provide your own {@link SynthStyleFactory}
050         * to {@link #setStyleFactory}. Refer to the
051         * <a href="package-summary.html">package summary</a> for an example of
052         * loading a file, and {@link javax.swing.plaf.synth.SynthStyleFactory} for
053         * an example of providing your own <code>SynthStyleFactory</code> to
054         * <code>setStyleFactory</code>.
055         * <p>
056         * <strong>Warning:</strong>
057         * This class implements {@link Serializable} as a side effect of it 
058         * extending {@link BasicLookAndFeel}. It is not intended to be serialized.
059         * An attempt to serialize it will 
060         * result in {@link NotSerializableException}.
061         * 
062         * @serial exclude 
063         * @version 1.48, 05/24/05
064         * @since 1.5
065         * @author Scott Violet
066         */
067        public class SynthLookAndFeel extends BasicLookAndFeel {
068            /**
069             * Used in a handful of places where we need an empty Insets.
070             */
071            static final Insets EMPTY_UIRESOURCE_INSETS = new InsetsUIResource(
072                    0, 0, 0, 0);
073
074            /**
075             * AppContext key to get the current SynthStyleFactory.
076             */
077            private static final Object STYLE_FACTORY_KEY = new StringBuffer(
078                    "com.sun.java.swing.plaf.gtk.StyleCache");
079
080            /**
081             * The last SynthStyleFactory that was asked for from AppContext
082             * <code>lastContext</code>.
083             */
084            private static SynthStyleFactory lastFactory;
085            /**
086             * If this is true it indicates there is more than one AppContext active
087             * and that we need to make sure in getStyleCache the requesting
088             * AppContext matches that of <code>lastContext</code> before returning
089             * it.
090             */
091            private static boolean multipleApps;
092            /**
093             * AppContext lastLAF came from.
094             */
095            private static AppContext lastContext;
096
097            // Refer to setSelectedUI
098            static ComponentUI selectedUI;
099            // Refer to setSelectedUI
100            static int selectedUIState;
101
102            /**
103             * SynthStyleFactory for the this SynthLookAndFeel.
104             */
105            private SynthStyleFactory factory;
106
107            /**
108             * Map of defaults table entries. This is populated via the load
109             * method.
110             */
111            private Map defaultsMap;
112
113            private Handler _handler;
114
115            /**
116             * Used by the renderers. For the most part the renderers are implemented
117             * as Labels, which is problematic in so far as they are never selected.
118             * To accomodate this SynthLabelUI checks if the current 
119             * UI matches that of <code>selectedUI</code> (which this methods sets), if
120             * it does, then a state as set by this method is returned. This provides
121             * a way for labels to have a state other than selected.
122             */
123            static void setSelectedUI(ComponentUI uix, boolean selected,
124                    boolean focused, boolean enabled, boolean rollover) {
125                selectedUI = uix;
126                selectedUIState = 0;
127                if (selected) {
128                    selectedUIState = SynthConstants.SELECTED;
129                    if (focused) {
130                        selectedUIState |= SynthConstants.FOCUSED;
131                    }
132                } else if (rollover && enabled) {
133                    selectedUIState |= SynthConstants.MOUSE_OVER
134                            | SynthConstants.ENABLED;
135                    if (focused) {
136                        selectedUIState |= SynthConstants.FOCUSED;
137                    }
138                } else {
139                    selectedUIState = SynthConstants.FOCUSED;
140                    if (enabled) {
141                        selectedUIState |= SynthConstants.ENABLED;
142                    } else {
143                        selectedUIState |= SynthConstants.DISABLED;
144                    }
145                }
146            }
147
148            /**
149             * Clears out the selected UI that was last set in setSelectedUI.
150             */
151            static void resetSelectedUI() {
152                selectedUI = null;
153            }
154
155            /**
156             * Sets the SynthStyleFactory that the UI classes provided by
157             * synth will use to obtain a SynthStyle.
158             *
159             * @param cache SynthStyleFactory the UIs should use.
160             */
161            public static void setStyleFactory(SynthStyleFactory cache) {
162                // We assume the setter is called BEFORE the getter has been invoked
163                // for a particular AppContext.
164                synchronized (SynthLookAndFeel.class) {
165                    AppContext context = AppContext.getAppContext();
166                    if (!multipleApps && context != lastContext
167                            && lastContext != null) {
168                        multipleApps = true;
169                    }
170                    lastFactory = cache;
171                    lastContext = context;
172                    context.put(STYLE_FACTORY_KEY, cache);
173                }
174            }
175
176            /**
177             * Returns the current SynthStyleFactory.
178             *
179             * @return SynthStyleFactory
180             */
181            public static SynthStyleFactory getStyleFactory() {
182                synchronized (SynthLookAndFeel.class) {
183                    if (!multipleApps) {
184                        return lastFactory;
185                    }
186                    AppContext context = AppContext.getAppContext();
187
188                    if (lastContext == context) {
189                        return lastFactory;
190                    }
191                    lastContext = context;
192                    lastFactory = (SynthStyleFactory) AppContext
193                            .getAppContext().get(STYLE_FACTORY_KEY);
194                    return lastFactory;
195                }
196            }
197
198            /**
199             * Returns the component state for the specified component. This should
200             * only be used for Components that don't have any special state beyond
201             * that of ENABLED, DISABLED or FOCUSED. For example, buttons shouldn't
202             * call into this method.
203             */
204            static int getComponentState(Component c) {
205                if (c.isEnabled()) {
206                    if (c.isFocusOwner()) {
207                        return SynthUI.ENABLED | SynthUI.FOCUSED;
208                    }
209                    return SynthUI.ENABLED;
210                }
211                return SynthUI.DISABLED;
212            }
213
214            /**
215             * Gets a SynthStyle for the specified region of the specified component.
216             * This is not for general consumption, only custom UIs should call this
217             * method.
218             *
219             * @param c JComponent to get the SynthStyle for
220             * @param region Identifies the region of the specified component
221             * @return SynthStyle to use.
222             */
223            public static SynthStyle getStyle(JComponent c, Region region) {
224                return getStyleFactory().getStyle(c, region);
225            }
226
227            /**
228             * Returns true if the Style should be updated in response to the
229             * specified PropertyChangeEvent. This forwards to
230             * <code>shouldUpdateStyleOnAncestorChanged</code> as necessary.
231             */
232            static boolean shouldUpdateStyle(PropertyChangeEvent event) {
233                String eName = event.getPropertyName();
234                if ("name" == eName) {
235                    // Always update on a name change
236                    return true;
237                } else if ("componentOrientation" == eName) {
238                    // Always update on a component orientation change
239                    return true;
240                } else if ("ancestor" == eName && event.getNewValue() != null) {
241                    // Only update on an ancestor change when getting a valid
242                    // parent and the LookAndFeel wants this.
243                    LookAndFeel laf = UIManager.getLookAndFeel();
244                    return (laf instanceof  SynthLookAndFeel && ((SynthLookAndFeel) laf)
245                            .shouldUpdateStyleOnAncestorChanged());
246                }
247                return false;
248            }
249
250            /**
251             * A convience method that will reset the Style of StyleContext if
252             * necessary.
253             *
254             * @return newStyle
255             */
256            static SynthStyle updateStyle(SynthContext context, SynthUI ui) {
257                SynthStyle newStyle = getStyle(context.getComponent(), context
258                        .getRegion());
259                SynthStyle oldStyle = context.getStyle();
260
261                if (newStyle != oldStyle) {
262                    if (oldStyle != null) {
263                        oldStyle.uninstallDefaults(context);
264                    }
265                    context.setStyle(newStyle);
266                    newStyle.installDefaults(context, ui);
267                }
268                return newStyle;
269            }
270
271            /**
272             * Updates the style associated with <code>c</code>, and all its children.
273             * This is a lighter version of
274             * <code>SwingUtilities.updateComponentTreeUI</code>.
275             *
276             * @param c Component to update style for.
277             */
278            public static void updateStyles(Component c) {
279                _updateStyles(c);
280                c.repaint();
281            }
282
283            // Implementation for updateStyles
284            private static void _updateStyles(Component c) {
285                if (c instanceof  JComponent) {
286                    // Yes, this is hacky. A better solution is to get the UI
287                    // and cast, but JComponent doesn't expose a getter for the UI
288                    // (each of the UIs do), making that approach impractical.
289                    String name = c.getName();
290                    c.setName(null);
291                    if (name != null) {
292                        c.setName(name);
293                    }
294                    ((JComponent) c).revalidate();
295                }
296                Component[] children = null;
297                if (c instanceof  JMenu) {
298                    children = ((JMenu) c).getMenuComponents();
299                } else if (c instanceof  Container) {
300                    children = ((Container) c).getComponents();
301                }
302                if (children != null) {
303                    for (int i = 0; i < children.length; i++) {
304                        updateStyles(children[i]);
305                    }
306                }
307            }
308
309            /**
310             * Returns the Region for the JComponent <code>c</code>.
311             *
312             * @param c JComponent to fetch the Region for
313             * @return Region corresponding to <code>c</code>
314             */
315            public static Region getRegion(JComponent c) {
316                return Region.getRegion(c);
317            }
318
319            /**
320             * A convenience method to return where the foreground should be
321             * painted for the Component identified by the passed in
322             * AbstractSynthContext.
323             */
324            static Insets getPaintingInsets(SynthContext state, Insets insets) {
325                if (state.isSubregion()) {
326                    insets = state.getStyle().getInsets(state, insets);
327                } else {
328                    insets = state.getComponent().getInsets(insets);
329                }
330                return insets;
331            }
332
333            /**
334             * A convenience method that handles painting of the background.
335             * All SynthUI implementations should override update and invoke
336             * this method.
337             */
338            static void update(SynthContext state, Graphics g) {
339                paintRegion(state, g, null);
340            }
341
342            /**
343             * A convenience method that handles painting of the background for
344             * subregions. All SynthUI's that have subregions should invoke
345             * this method, than paint the foreground.
346             */
347            static void updateSubregion(SynthContext state, Graphics g,
348                    Rectangle bounds) {
349                paintRegion(state, g, bounds);
350            }
351
352            private static void paintRegion(SynthContext state, Graphics g,
353                    Rectangle bounds) {
354                JComponent c = state.getComponent();
355                SynthStyle style = state.getStyle();
356                int x, y, width, height;
357
358                if (bounds == null) {
359                    x = 0;
360                    y = 0;
361                    width = c.getWidth();
362                    height = c.getHeight();
363                } else {
364                    x = bounds.x;
365                    y = bounds.y;
366                    width = bounds.width;
367                    height = bounds.height;
368                }
369
370                // Fill in the background, if necessary.
371                boolean subregion = state.isSubregion();
372                if ((subregion && style.isOpaque(state))
373                        || (!subregion && c.isOpaque())) {
374                    g.setColor(style.getColor(state, ColorType.BACKGROUND));
375                    g.fillRect(x, y, width, height);
376                }
377            }
378
379            static boolean isLeftToRight(Component c) {
380                return c.getComponentOrientation().isLeftToRight();
381            }
382
383            /**
384             * Returns the ui that is of type <code>klass</code>, or null if
385             * one can not be found.
386             */
387            static Object getUIOfType(ComponentUI ui, Class klass) {
388                if (klass.isInstance(ui)) {
389                    return ui;
390                }
391                return null;
392            }
393
394            /**
395             * Creates the Synth look and feel <code>ComponentUI</code> for
396             * the passed in <code>JComponent</code>.
397             *
398             * @param c JComponent to create the <code>ComponentUI</code> for
399             * @return ComponentUI to use for <code>c</code>
400             */
401            public static ComponentUI createUI(JComponent c) {
402                String key = c.getUIClassID().intern();
403
404                if (key == "ButtonUI") {
405                    return SynthButtonUI.createUI(c);
406                } else if (key == "CheckBoxUI") {
407                    return SynthCheckBoxUI.createUI(c);
408                } else if (key == "CheckBoxMenuItemUI") {
409                    return SynthCheckBoxMenuItemUI.createUI(c);
410                } else if (key == "ColorChooserUI") {
411                    return SynthColorChooserUI.createUI(c);
412                } else if (key == "ComboBoxUI") {
413                    return SynthComboBoxUI.createUI(c);
414                } else if (key == "DesktopPaneUI") {
415                    return SynthDesktopPaneUI.createUI(c);
416                } else if (key == "DesktopIconUI") {
417                    return SynthDesktopIconUI.createUI(c);
418                } else if (key == "EditorPaneUI") {
419                    return SynthEditorPaneUI.createUI(c);
420                } else if (key == "FileChooserUI") {
421                    return SynthFileChooserUI.createUI(c);
422                } else if (key == "FormattedTextFieldUI") {
423                    return SynthFormattedTextFieldUI.createUI(c);
424                } else if (key == "InternalFrameUI") {
425                    return SynthInternalFrameUI.createUI(c);
426                } else if (key == "LabelUI") {
427                    return SynthLabelUI.createUI(c);
428                } else if (key == "ListUI") {
429                    return SynthListUI.createUI(c);
430                } else if (key == "MenuBarUI") {
431                    return SynthMenuBarUI.createUI(c);
432                } else if (key == "MenuUI") {
433                    return SynthMenuUI.createUI(c);
434                } else if (key == "MenuItemUI") {
435                    return SynthMenuItemUI.createUI(c);
436                } else if (key == "OptionPaneUI") {
437                    return SynthOptionPaneUI.createUI(c);
438                } else if (key == "PanelUI") {
439                    return SynthPanelUI.createUI(c);
440                } else if (key == "PasswordFieldUI") {
441                    return SynthPasswordFieldUI.createUI(c);
442                } else if (key == "PopupMenuSeparatorUI") {
443                    return SynthSeparatorUI.createUI(c);
444                } else if (key == "PopupMenuUI") {
445                    return SynthPopupMenuUI.createUI(c);
446                } else if (key == "ProgressBarUI") {
447                    return SynthProgressBarUI.createUI(c);
448                } else if (key == "RadioButtonUI") {
449                    return SynthRadioButtonUI.createUI(c);
450                } else if (key == "RadioButtonMenuItemUI") {
451                    return SynthRadioButtonMenuItemUI.createUI(c);
452                } else if (key == "RootPaneUI") {
453                    return SynthRootPaneUI.createUI(c);
454                } else if (key == "ScrollBarUI") {
455                    return SynthScrollBarUI.createUI(c);
456                } else if (key == "ScrollPaneUI") {
457                    return SynthScrollPaneUI.createUI(c);
458                } else if (key == "SeparatorUI") {
459                    return SynthSeparatorUI.createUI(c);
460                } else if (key == "SliderUI") {
461                    return SynthSliderUI.createUI(c);
462                } else if (key == "SpinnerUI") {
463                    return SynthSpinnerUI.createUI(c);
464                } else if (key == "SplitPaneUI") {
465                    return SynthSplitPaneUI.createUI(c);
466                } else if (key == "TabbedPaneUI") {
467                    return SynthTabbedPaneUI.createUI(c);
468                } else if (key == "TableUI") {
469                    return SynthTableUI.createUI(c);
470                } else if (key == "TableHeaderUI") {
471                    return SynthTableHeaderUI.createUI(c);
472                } else if (key == "TextAreaUI") {
473                    return SynthTextAreaUI.createUI(c);
474                } else if (key == "TextFieldUI") {
475                    return SynthTextFieldUI.createUI(c);
476                } else if (key == "TextPaneUI") {
477                    return SynthTextPaneUI.createUI(c);
478                } else if (key == "ToggleButtonUI") {
479                    return SynthToggleButtonUI.createUI(c);
480                } else if (key == "ToolBarSeparatorUI") {
481                    return SynthSeparatorUI.createUI(c);
482                } else if (key == "ToolBarUI") {
483                    return SynthToolBarUI.createUI(c);
484                } else if (key == "ToolTipUI") {
485                    return SynthToolTipUI.createUI(c);
486                } else if (key == "TreeUI") {
487                    return SynthTreeUI.createUI(c);
488                } else if (key == "ViewportUI") {
489                    return SynthViewportUI.createUI(c);
490                }
491                return null;
492            }
493
494            /**
495             * Creates a SynthLookAndFeel.
496             * <p>
497             * For the returned <code>SynthLookAndFeel</code> to be useful you need to
498             * invoke <code>load</code> to specify the set of
499             * <code>SynthStyle</code>s, or invoke <code>setStyleFactory</code>.
500             *
501             * @see #load
502             * @see #setStyleFactory
503             */
504            public SynthLookAndFeel() {
505                factory = new DefaultSynthStyleFactory();
506                _handler = new Handler();
507            }
508
509            /**
510             * Loads the set of <code>SynthStyle</code>s that will be used by
511             * this <code>SynthLookAndFeel</code>. <code>resourceBase</code> is
512             * used to resolve any path based resources, for example an
513             * <code>Image</code> would be resolved by
514             * <code>resourceBase.getResource(path)</code>. Refer to
515             * <a href="doc-files/synthFileFormat.html">Synth File Format</a>
516             * for more information.
517             *
518             * @param input InputStream to load from
519             * @param resourceBase used to resolve any images or other resources
520             * @throws ParseException if there is an error in parsing
521             * @throws IllegalArgumentException if input or resourceBase is <code>null</code>
522             */
523            public void load(InputStream input, Class<?> resourceBase)
524                    throws ParseException {
525                if (resourceBase == null) {
526                    throw new IllegalArgumentException(
527                            "You must supply a valid resource base Class");
528                }
529
530                if (defaultsMap == null) {
531                    defaultsMap = new HashMap();
532                }
533
534                new SynthParser().parse(input,
535                        (DefaultSynthStyleFactory) factory, null, resourceBase,
536                        defaultsMap);
537            }
538
539            /**
540             * Loads the set of <code>SynthStyle</code>s that will be used by
541             * this <code>SynthLookAndFeel</code>. Path based resources are resolved
542             * relatively to the specified <code>URL</code> of the style. For example
543             * an <code>Image</code> would be resolved by
544             * <code>new URL(synthFile, path)</code>. Refer to
545             * <a href="doc-files/synthFileFormat.html">Synth File Format</a> for more
546             * information.
547             *
548             * @param url the <code>URL</code> to load the set of
549             *     <code>SynthStyle</code> from
550             * @throws ParseException if there is an error in parsing
551             * @throws IllegalArgumentException if synthSet is <code>null</code>
552             * @throws IOException if synthSet cannot be opened as an <code>InputStream</code>
553             * @since 1.6
554             */
555            public void load(URL url) throws ParseException, IOException {
556                if (url == null) {
557                    throw new IllegalArgumentException(
558                            "You must supply a valid Synth set URL");
559                }
560
561                if (defaultsMap == null) {
562                    defaultsMap = new HashMap();
563                }
564
565                InputStream input = url.openStream();
566                new SynthParser().parse(input,
567                        (DefaultSynthStyleFactory) factory, url, null,
568                        defaultsMap);
569            }
570
571            /**
572             * Called by UIManager when this look and feel is installed.
573             */
574            public void initialize() {
575                super .initialize();
576                DefaultLookup.setDefaultLookup(new SynthDefaultLookup());
577                setStyleFactory(factory);
578                KeyboardFocusManager.getCurrentKeyboardFocusManager()
579                        .addPropertyChangeListener(_handler);
580            }
581
582            /**
583             * Called by UIManager when this look and feel is uninstalled.
584             */
585            public void uninitialize() {
586                KeyboardFocusManager.getCurrentKeyboardFocusManager()
587                        .removePropertyChangeListener(_handler);
588                // We should uninstall the StyleFactory here, but unfortunately
589                // there are a handful of things that retain references to the
590                // LookAndFeel and expect things to work
591                super .uninitialize();
592            }
593
594            /**
595             * Returns the defaults for this SynthLookAndFeel.
596             *
597             * @return Defaults table.
598             */
599            public UIDefaults getDefaults() {
600                UIDefaults table = new UIDefaults(60, 0.75f);
601
602                Region.registerUIs(table);
603                table.setDefaultLocale(Locale.getDefault());
604                table
605                        .addResourceBundle("com.sun.swing.internal.plaf.basic.resources.basic");
606                table
607                        .addResourceBundle("com.sun.swing.internal.plaf.synth.resources.synth");
608
609                // SynthTabbedPaneUI supports rollover on tabs, GTK does not
610                table.put("TabbedPane.isTabRollover", Boolean.TRUE);
611
612                // These need to be defined for JColorChooser to work.
613                table.put("ColorChooser.swatchesRecentSwatchSize",
614                        new Dimension(10, 10));
615                table.put("ColorChooser.swatchesDefaultRecentColor", Color.RED);
616                table.put("ColorChooser.swatchesSwatchSize", new Dimension(10,
617                        10));
618
619                // These are needed for PopupMenu.
620                table.put("PopupMenu.selectedWindowInputMapBindings",
621                        new Object[] { "ESCAPE", "cancel", "DOWN",
622                                "selectNext", "KP_DOWN", "selectNext", "UP",
623                                "selectPrevious", "KP_UP", "selectPrevious",
624                                "LEFT", "selectParent", "KP_LEFT",
625                                "selectParent", "RIGHT", "selectChild",
626                                "KP_RIGHT", "selectChild", "ENTER", "return",
627                                "SPACE", "return" });
628                table.put(
629                        "PopupMenu.selectedWindowInputMapBindings.RightToLeft",
630                        new Object[] { "LEFT", "selectChild", "KP_LEFT",
631                                "selectChild", "RIGHT", "selectParent",
632                                "KP_RIGHT", "selectParent", });
633
634                // enabled antialiasing depending on desktop settings
635                flushUnreferenced();
636                Object aaTextInfo = getAATextInfo();
637                table.put(SwingUtilities2.AA_TEXT_PROPERTY_KEY, aaTextInfo);
638                new AATextListener(this );
639
640                if (defaultsMap != null) {
641                    table.putAll(defaultsMap);
642                }
643                return table;
644            }
645
646            /**
647             * Returns true, SynthLookAndFeel is always supported.
648             *
649             * @return true.
650             */
651            public boolean isSupportedLookAndFeel() {
652                return true;
653            }
654
655            /**
656             * Returns false, SynthLookAndFeel is not a native look and feel.
657             *
658             * @return false
659             */
660            public boolean isNativeLookAndFeel() {
661                return false;
662            }
663
664            /**
665             * Returns a textual description of SynthLookAndFeel.
666             *
667             * @return textual description of synth.
668             */
669            public String getDescription() {
670                return "Synth look and feel";
671            }
672
673            /**
674             * Return a short string that identifies this look and feel.
675             *
676             * @return a short string identifying this look and feel.
677             */
678            public String getName() {
679                return "Synth look and feel";
680            }
681
682            /**
683             * Return a string that identifies this look and feel.
684             *
685             * @return a short string identifying this look and feel.
686             */
687            public String getID() {
688                return "Synth";
689            }
690
691            /**
692             * Returns whether or not the UIs should update their
693             * <code>SynthStyles</code> from the <code>SynthStyleFactory</code>
694             * when the ancestor of the <code>JComponent</code> changes. A subclass
695             * that provided a <code>SynthStyleFactory</code> that based the
696             * return value from <code>getStyle</code> off the containment hierarchy
697             * would override this method to return true.
698             *
699             * @return whether or not the UIs should update their
700             * <code>SynthStyles</code> from the <code>SynthStyleFactory</code>
701             * when the ancestor changed.
702             */
703            public boolean shouldUpdateStyleOnAncestorChanged() {
704                return false;
705            }
706
707            /**
708             * Returns the antialiasing information as specified by the host desktop.
709             * Antialiasing might be forced off if the desktop is GNOME and the user
710             * has set his locale to Chinese, Japanese or Korean. This is consistent
711             * with what GTK does. See com.sun.java.swing.plaf.gtk.GtkLookAndFeel
712             * for more information about CJK and antialiased fonts.
713             * 
714             * @return the text antialiasing information associated to the desktop 
715             */
716            private static Object getAATextInfo() {
717                String language = Locale.getDefault().getLanguage();
718                String desktop = (String) AccessController
719                        .doPrivileged(new GetPropertyAction("sun.desktop"));
720
721                boolean isCjkLocale = (Locale.CHINESE.getLanguage().equals(
722                        language)
723                        || Locale.JAPANESE.getLanguage().equals(language) || Locale.KOREAN
724                        .getLanguage().equals(language));
725                boolean isGnome = "gnome".equals(desktop);
726                boolean isLocal = SwingUtilities2.isLocalDisplay();
727
728                boolean setAA = isLocal && (!isGnome || !isCjkLocale);
729
730                Object aaTextInfo = SwingUtilities2.AATextInfo
731                        .getAATextInfo(setAA);
732                return aaTextInfo;
733            }
734
735            private static ReferenceQueue queue = new ReferenceQueue();
736
737            private static void flushUnreferenced() {
738                AATextListener aatl;
739                while ((aatl = (AATextListener) queue.poll()) != null) {
740                    aatl.dispose();
741                }
742            }
743
744            private static class AATextListener extends WeakReference implements 
745                    PropertyChangeListener {
746                private String key = SunToolkit.DESKTOPFONTHINTS;
747
748                AATextListener(LookAndFeel laf) {
749                    super (laf, queue);
750                    Toolkit tk = Toolkit.getDefaultToolkit();
751                    tk.addPropertyChangeListener(key, this );
752                }
753
754                public void propertyChange(PropertyChangeEvent pce) {
755                    UIDefaults defaults = UIManager.getLookAndFeelDefaults();
756                    if (defaults.getBoolean("Synth.doNotSetTextAA")) {
757                        dispose();
758                        return;
759                    }
760
761                    LookAndFeel laf = (LookAndFeel) get();
762                    if (laf == null || laf != UIManager.getLookAndFeel()) {
763                        dispose();
764                        return;
765                    }
766
767                    Object aaTextInfo = getAATextInfo();
768                    defaults.put(SwingUtilities2.AA_TEXT_PROPERTY_KEY,
769                            aaTextInfo);
770
771                    updateUI();
772                }
773
774                void dispose() {
775                    Toolkit tk = Toolkit.getDefaultToolkit();
776                    tk.removePropertyChangeListener(key, this );
777                }
778
779                /**
780                 * Updates the UI of the passed in window and all its children.
781                 */
782                private static void updateWindowUI(Window window) {
783                    updateStyles(window);
784                    Window ownedWins[] = window.getOwnedWindows();
785                    for (int i = 0; i < ownedWins.length; i++) {
786                        updateWindowUI(ownedWins[i]);
787                    }
788                }
789
790                /**
791                 * Updates the UIs of all the known Frames.
792                 */
793                private static void updateAllUIs() {
794                    Frame appFrames[] = Frame.getFrames();
795                    for (int i = 0; i < appFrames.length; i++) {
796                        updateWindowUI(appFrames[i]);
797                    }
798                }
799
800                /**
801                 * Indicates if an updateUI call is pending.
802                 */
803                private static boolean updatePending;
804
805                /**
806                 * Sets whether or not an updateUI call is pending.
807                 */
808                private static synchronized void setUpdatePending(boolean update) {
809                    updatePending = update;
810                }
811
812                /**
813                 * Returns true if a UI update is pending.
814                 */
815                private static synchronized boolean isUpdatePending() {
816                    return updatePending;
817                }
818
819                protected void updateUI() {
820                    if (!isUpdatePending()) {
821                        setUpdatePending(true);
822                        Runnable uiUpdater = new Runnable() {
823                            public void run() {
824                                updateAllUIs();
825                                setUpdatePending(false);
826                            }
827                        };
828                        SwingUtilities.invokeLater(uiUpdater);
829                    }
830                }
831            }
832
833            private void writeObject(java.io.ObjectOutputStream out)
834                    throws IOException {
835                throw new NotSerializableException(this .getClass().getName());
836            }
837
838            private class Handler implements  PropertyChangeListener {
839                public void propertyChange(PropertyChangeEvent evt) {
840                    String propertyName = evt.getPropertyName();
841                    Object newValue = evt.getNewValue();
842                    Object oldValue = evt.getOldValue();
843
844                    if ("focusOwner" == propertyName) {
845                        if (oldValue instanceof  JComponent) {
846                            repaintIfBackgroundsDiffer((JComponent) oldValue);
847
848                        }
849
850                        if (newValue instanceof  JComponent) {
851                            repaintIfBackgroundsDiffer((JComponent) newValue);
852                        }
853                    } else if ("managingFocus" == propertyName) {
854                        // De-register listener on old keyboard focus manager and
855                        // register it on the new one.
856                        KeyboardFocusManager manager = (KeyboardFocusManager) evt
857                                .getSource();
858                        if (((Boolean) newValue).equals(Boolean.FALSE)) {
859                            manager.removePropertyChangeListener(_handler);
860                        } else {
861                            manager.addPropertyChangeListener(_handler);
862                        }
863                    }
864                }
865
866                /**
867                 * This is a support method that will check if the background colors of
868                 * the specified component differ between focused and unfocused states.
869                 * If the color differ the component will then repaint itself.
870                 *
871                 * @comp the component to check
872                 */
873                private void repaintIfBackgroundsDiffer(JComponent comp) {
874                    ComponentUI ui = (ComponentUI) comp
875                            .getClientProperty(SwingUtilities2.COMPONENT_UI_PROPERTY_KEY);
876                    if (ui instanceof  SynthUI) {
877                        SynthUI synthUI = (SynthUI) ui;
878                        SynthContext context = synthUI.getContext(comp);
879                        SynthStyle style = context.getStyle();
880                        int state = context.getComponentState();
881
882                        // Get the current background color.
883                        Color currBG = style.getColor(context,
884                                ColorType.BACKGROUND);
885
886                        // Get the last background color.
887                        state ^= SynthConstants.FOCUSED;
888                        context.setComponentState(state);
889                        Color lastBG = style.getColor(context,
890                                ColorType.BACKGROUND);
891
892                        // Reset the component state back to original.
893                        state ^= SynthConstants.FOCUSED;
894                        context.setComponentState(state);
895
896                        // Repaint the component if the backgrounds differed.
897                        if (currBG != null && !currBG.equals(lastBG)) {
898                            comp.repaint();
899                        }
900                        context.dispose();
901                    }
902                }
903            }
904        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.