1/*
2 * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
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
23 * questions.
24 */
25package sun.swing;
26
27import java.awt.Color;
28import java.awt.Insets;
29import javax.swing.*;
30import javax.swing.border.Border;
31import javax.swing.plaf.ComponentUI;
32import sun.awt.AppContext;
33
34/**
35 * DefaultLookup provides a way to customize the lookup done by the
36 * UIManager. The default implementation of DefaultLookup forwards
37 * the call to the UIManager.
38 * <p>
39 * <b>WARNING:</b> While this class is public, it should not be treated as
40 * public API and its API may change in incompatable ways between dot dot
41 * releases and even patch releases. You should not rely on this class even
42 * existing.
43 *
44 * @author Scott Violet
45 */
46public class DefaultLookup {
47    /**
48     * Key used to store DefaultLookup for AppContext.
49     */
50    private static final Object DEFAULT_LOOKUP_KEY = new
51                                        StringBuffer("DefaultLookup");
52    /**
53     * Thread that last asked for a default.
54     */
55    private static Thread currentDefaultThread;
56    /**
57     * DefaultLookup for last thread.
58     */
59    private static DefaultLookup currentDefaultLookup;
60
61    /**
62     * If true, a custom DefaultLookup has been set.
63     */
64    private static boolean isLookupSet;
65
66
67    /**
68     * Sets the DefaultLookup instance to use for the current
69     * <code>AppContext</code>. Null implies the UIManager should be
70     * used.
71     */
72    public static void setDefaultLookup(DefaultLookup lookup) {
73        synchronized(DefaultLookup.class) {
74            if (!isLookupSet && lookup == null) {
75                // Null was passed in, and no one has invoked setDefaultLookup
76                // with a non-null value, we don't need to do anything.
77                return;
78            }
79            else if (lookup == null) {
80                // null was passed in, but someone has invoked setDefaultLookup
81                // with a non-null value, use an instance of DefautLookup
82                // which will fallback to UIManager.
83                lookup = new DefaultLookup();
84            }
85            isLookupSet = true;
86            AppContext.getAppContext().put(DEFAULT_LOOKUP_KEY, lookup);
87            currentDefaultThread = Thread.currentThread();
88            currentDefaultLookup = lookup;
89        }
90    }
91
92    public static Object get(JComponent c, ComponentUI ui, String key) {
93        boolean lookupSet;
94        synchronized(DefaultLookup.class) {
95            lookupSet = isLookupSet;
96        }
97        if (!lookupSet) {
98            // No one has set a valid DefaultLookup, use UIManager.
99            return UIManager.get(key, c.getLocale());
100        }
101        Thread thisThread = Thread.currentThread();
102        DefaultLookup lookup;
103        synchronized(DefaultLookup.class) {
104            // See if we've already cached the DefaultLookup for this thread,
105            // and use it if we have.
106            if (thisThread == currentDefaultThread) {
107                // It is cached, use it.
108                lookup = currentDefaultLookup;
109            }
110            else {
111                // Not cached, get the DefaultLookup to use from the AppContext
112                lookup = (DefaultLookup)AppContext.getAppContext().get(
113                                                   DEFAULT_LOOKUP_KEY);
114                if (lookup == null) {
115                    // Fallback to DefaultLookup, which will redirect to the
116                    // UIManager.
117                    lookup = new DefaultLookup();
118                    AppContext.getAppContext().put(DEFAULT_LOOKUP_KEY, lookup);
119                }
120                // Cache the values to make the next lookup easier.
121                currentDefaultThread = thisThread;
122                currentDefaultLookup = lookup;
123            }
124        }
125        return lookup.getDefault(c, ui, key);
126    }
127
128    //
129    // The following are convenience method that all use getDefault.
130    //
131    public static int getInt(JComponent c, ComponentUI ui, String key,
132                             int defaultValue) {
133        Object iValue = get(c, ui, key);
134
135        if (iValue == null || !(iValue instanceof Number)) {
136            return defaultValue;
137        }
138        return ((Number)iValue).intValue();
139    }
140
141    public static int getInt(JComponent c, ComponentUI ui, String key) {
142        return getInt(c, ui, key, -1);
143    }
144
145    public static Insets getInsets(JComponent c, ComponentUI ui, String key,
146                                   Insets defaultValue) {
147        Object iValue = get(c, ui, key);
148
149        if (iValue == null || !(iValue instanceof Insets)) {
150            return defaultValue;
151        }
152        return (Insets)iValue;
153    }
154
155    public static Insets getInsets(JComponent c, ComponentUI ui, String key) {
156        return getInsets(c, ui, key, null);
157    }
158
159    public static boolean getBoolean(JComponent c, ComponentUI ui, String key,
160                                     boolean defaultValue) {
161        Object iValue = get(c, ui, key);
162
163        if (iValue == null || !(iValue instanceof Boolean)) {
164            return defaultValue;
165        }
166        return ((Boolean)iValue).booleanValue();
167    }
168
169    public static boolean getBoolean(JComponent c, ComponentUI ui, String key) {
170        return getBoolean(c, ui, key, false);
171    }
172
173    public static Color getColor(JComponent c, ComponentUI ui, String key,
174                                 Color defaultValue) {
175        Object iValue = get(c, ui, key);
176
177        if (iValue == null || !(iValue instanceof Color)) {
178            return defaultValue;
179        }
180        return (Color)iValue;
181    }
182
183    public static Color getColor(JComponent c, ComponentUI ui, String key) {
184        return getColor(c, ui, key, null);
185    }
186
187    public static Icon getIcon(JComponent c, ComponentUI ui, String key,
188            Icon defaultValue) {
189        Object iValue = get(c, ui, key);
190        if (iValue == null || !(iValue instanceof Icon)) {
191            return defaultValue;
192        }
193        return (Icon)iValue;
194    }
195
196    public static Icon getIcon(JComponent c, ComponentUI ui, String key) {
197        return getIcon(c, ui, key, null);
198    }
199
200    public static Border getBorder(JComponent c, ComponentUI ui, String key,
201            Border defaultValue) {
202        Object iValue = get(c, ui, key);
203        if (iValue == null || !(iValue instanceof Border)) {
204            return defaultValue;
205        }
206        return (Border)iValue;
207    }
208
209    public static Border getBorder(JComponent c, ComponentUI ui, String key) {
210        return getBorder(c, ui, key, null);
211    }
212
213    public Object getDefault(JComponent c, ComponentUI ui, String key) {
214        // basic
215        return UIManager.get(key, c.getLocale());
216    }
217}
218