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 */
25
26 /*
27 * <p>These classes are designed to be used while the
28 * corresponding <code>LookAndFeel</code> class has been installed
29 * (<code>UIManager.setLookAndFeel(new <i>XXX</i>LookAndFeel())</code>).
30 * Using them while a different <code>LookAndFeel</code> is installed
31 * may produce unexpected results, including exceptions.
32 * Additionally, changing the <code>LookAndFeel</code>
33 * maintained by the <code>UIManager</code> without updating the
34 * corresponding <code>ComponentUI</code> of any
35 * <code>JComponent</code>s may also produce unexpected results,
36 * such as the wrong colors showing up, and is generally not
37 * encouraged.
38 *
39 */
40
41 package com.sun.java.swing.plaf.windows;
42
43 import java.awt.*;
44 import java.awt.image.*;
45 import java.security.AccessController;
46 import java.util.*;
47
48 import javax.swing.*;
49 import javax.swing.border.*;
50 import javax.swing.plaf.*;
51 import javax.swing.text.JTextComponent;
52
53 import sun.awt.image.SunWritableRaster;
54 import sun.awt.windows.ThemeReader;
55 import sun.security.action.GetPropertyAction;
106 if (themeActive.booleanValue()) {
107 GetPropertyAction propertyAction =
108 new GetPropertyAction("swing.noxp");
109 if (AccessController.doPrivileged(propertyAction) == null &&
110 ThemeReader.isThemed() &&
111 !(UIManager.getLookAndFeel()
112 instanceof WindowsClassicLookAndFeel)) {
113
114 xp = new XPStyle();
115 }
116 }
117 }
118 return ThemeReader.isXPStyleEnabled() ? xp : null;
119 }
120
121 static boolean isVista() {
122 XPStyle xp = XPStyle.getXP();
123 return (xp != null && xp.isSkinDefined(null, Part.CP_DROPDOWNBUTTONRIGHT));
124 }
125
126 /** Get a named <code>String</code> value from the current style
127 *
128 * @param part a <code>Part</code>
129 * @param state a <code>String</code>
130 * @param attributeKey a <code>String</code>
131 * @return a <code>String</code> or null if key is not found
132 * in the current style
133 *
134 * This is currently only used by WindowsInternalFrameTitlePane for painting
135 * title foregound and can be removed when no longer needed
136 */
137 String getString(Component c, Part part, State state, Prop prop) {
138 return getTypeEnumName(c, part, state, prop);
139 }
140
141 TypeEnum getTypeEnum(Component c, Part part, State state, Prop prop) {
142 int enumValue = ThemeReader.getEnum(part.getControlName(c), part.getValue(),
143 State.getValue(part, state),
144 prop.getValue());
145 return TypeEnum.getTypeEnum(prop, enumValue);
146 }
147
148 private static String getTypeEnumName(Component c, Part part, State state, Prop prop) {
149 int enumValue = ThemeReader.getEnum(part.getControlName(c), part.getValue(),
150 State.getValue(part, state),
151 prop.getValue());
152 if (enumValue == -1) {
153 return null;
154 }
155 return TypeEnum.getTypeEnum(prop, enumValue).getName();
156 }
157
158
159
160
161 /** Get a named <code>int</code> value from the current style
162 *
163 * @param part a <code>Part</code>
164 * @return an <code>int</code> or null if key is not found
165 * in the current style
166 */
167 int getInt(Component c, Part part, State state, Prop prop, int fallback) {
168 return ThemeReader.getInt(part.getControlName(c), part.getValue(),
169 State.getValue(part, state),
170 prop.getValue());
171 }
172
173 /** Get a named <code>Dimension</code> value from the current style
174 *
175 * @param key a <code>String</code>
176 * @return a <code>Dimension</code> or null if key is not found
177 * in the current style
178 *
179 * This is currently only used by WindowsProgressBarUI and the value
180 * should probably be cached there instead of here.
181 */
182 Dimension getDimension(Component c, Part part, State state, Prop prop) {
183 Dimension d = ThemeReader.getPosition(part.getControlName(c), part.getValue(),
184 State.getValue(part, state),
185 prop.getValue());
186 return (d != null) ? d : new Dimension();
187 }
188
189 /** Get a named <code>Point</code> (e.g. a location or an offset) value
190 * from the current style
191 *
192 * @param key a <code>String</code>
193 * @return a <code>Point</code> or null if key is not found
194 * in the current style
195 *
196 * This is currently only used by WindowsInternalFrameTitlePane for painting
197 * title foregound and can be removed when no longer needed
198 */
199 Point getPoint(Component c, Part part, State state, Prop prop) {
200 Dimension d = ThemeReader.getPosition(part.getControlName(c), part.getValue(),
201 State.getValue(part, state),
202 prop.getValue());
203 return (d != null) ? new Point(d.width, d.height) : new Point();
204 }
205
206 /** Get a named <code>Insets</code> value from the current style
207 *
208 * @param key a <code>String</code>
209 * @return an <code>Insets</code> object or null if key is not found
210 * in the current style
211 *
212 * This is currently only used to create borders and by
213 * WindowsInternalFrameTitlePane for painting title foregound.
214 * The return value is already cached in those places.
215 */
216 Insets getMargin(Component c, Part part, State state, Prop prop) {
217 Insets insets = ThemeReader.getThemeMargins(part.getControlName(c), part.getValue(),
218 State.getValue(part, state),
219 prop.getValue());
220 return (insets != null) ? insets : new Insets(0, 0, 0, 0);
221 }
222
223
224 /** Get a named <code>Color</code> value from the current style
225 *
226 * @param part a <code>Part</code>
227 * @return a <code>Color</code> or null if key is not found
228 * in the current style
229 */
230 synchronized Color getColor(Skin skin, Prop prop, Color fallback) {
231 String key = skin.toString() + "." + prop.name();
232 Part part = skin.part;
233 Color color = colorMap.get(key);
234 if (color == null) {
235 color = ThemeReader.getColor(part.getControlName(null), part.getValue(),
236 State.getValue(part, skin.state),
237 prop.getValue());
238 if (color != null) {
239 color = new ColorUIResource(color);
240 colorMap.put(key, color);
241 }
242 }
243 return (color != null) ? color : fallback;
244 }
245
246 Color getColor(Component c, Part part, State state, Prop prop, Color fallback) {
247 return getColor(new Skin(c, part, state), prop, fallback);
248 }
249
250
251
252 /** Get a named <code>Border</code> value from the current style
253 *
254 * @param part a <code>Part</code>
255 * @return a <code>Border</code> or null if key is not found
256 * in the current style or if the style for the particular
257 * part is not defined as "borderfill".
258 */
259 synchronized Border getBorder(Component c, Part part) {
260 if (part == Part.MENU) {
261 // Special case because XP has no skin for menus
262 if (flatMenus) {
263 // TODO: The classic border uses this color, but we should
264 // create a new UI property called "PopupMenu.borderColor"
265 // instead.
266 return new XPFillBorder(UIManager.getColor("InternalFrame.borderShadow"),
267 1);
268 } else {
269 return null; // Will cause L&F to use classic border
270 }
271 }
272 Skin skin = new Skin(c, part, null);
273 Border border = borderMap.get(skin.string);
274 if (border == null) {
275 String bgType = getTypeEnumName(c, part, null, Prop.BGTYPE);
429 margin = ((JToolBar)c).getMargin();
430 } else if (c instanceof JTextComponent) {
431 margin = ((JTextComponent)c).getMargin();
432 }
433 if (margin != null) {
434 insets.top = margin.top + 2;
435 insets.left = margin.left + 2;
436 insets.bottom = margin.bottom + 2;
437 insets.right = margin.right + 2;
438 }
439 return insets;
440 }
441 }
442 boolean isSkinDefined(Component c, Part part) {
443 return (part.getValue() == 0)
444 || ThemeReader.isThemePartDefined(
445 part.getControlName(c), part.getValue(), 0);
446 }
447
448
449 /** Get a <code>Skin</code> object from the current style
450 * for a named part (component type)
451 *
452 * @param part a <code>Part</code>
453 * @return a <code>Skin</code> object
454 */
455 synchronized Skin getSkin(Component c, Part part) {
456 assert isSkinDefined(c, part) : "part " + part + " is not defined";
457 return new Skin(c, part, null);
458 }
459
460
461 long getThemeTransitionDuration(Component c, Part part, State stateFrom,
462 State stateTo, Prop prop) {
463 return ThemeReader.getThemeTransitionDuration(part.getControlName(c),
464 part.getValue(),
465 State.getValue(part, stateFrom),
466 State.getValue(part, stateTo),
467 (prop != null) ? prop.getValue() : 0);
468 }
469
470
471 /** A class which encapsulates attributes for a given part
472 * (component type) and which provides methods for painting backgrounds
473 * and glyphs
547 return string.hashCode();
548 }
549
550 /** Paint a skin at x, y.
551 *
552 * @param g the graphics context to use for painting
553 * @param dx the destination <i>x</i> coordinate
554 * @param dy the destination <i>y</i> coordinate
555 * @param state which state to paint
556 */
557 void paintSkin(Graphics g, int dx, int dy, State state) {
558 if (state == null) {
559 state = this.state;
560 }
561 paintSkin(g, dx, dy, getWidth(state), getHeight(state), state);
562 }
563
564 /** Paint a skin in an area defined by a rectangle.
565 *
566 * @param g the graphics context to use for painting
567 * @param r a <code>Rectangle</code> defining the area to fill,
568 * may cause the image to be stretched or tiled
569 * @param state which state to paint
570 */
571 void paintSkin(Graphics g, Rectangle r, State state) {
572 paintSkin(g, r.x, r.y, r.width, r.height, state);
573 }
574
575 /** Paint a skin at a defined position and size
576 * This method supports animation.
577 *
578 * @param g the graphics context to use for painting
579 * @param dx the destination <i>x</i> coordinate
580 * @param dy the destination <i>y</i> coordinate
581 * @param dw the width of the area to fill, may cause
582 * the image to be stretched or tiled
583 * @param dh the height of the area to fill, may cause
584 * the image to be stretched or tiled
585 * @param state which state to paint
586 */
587 void paintSkin(Graphics g, int dx, int dy, int dw, int dh, State state) {
|
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 */
25
26 /*
27 * <p>These classes are designed to be used while the
28 * corresponding {@code LookAndFeel} class has been installed
29 * (<code>UIManager.setLookAndFeel(new <i>XXX</i>LookAndFeel())</code>).
30 * Using them while a different {@code LookAndFeel} is installed
31 * may produce unexpected results, including exceptions.
32 * Additionally, changing the {@code LookAndFeel}
33 * maintained by the {@code UIManager} without updating the
34 * corresponding {@code ComponentUI} of any
35 * {@code JComponent}s may also produce unexpected results,
36 * such as the wrong colors showing up, and is generally not
37 * encouraged.
38 *
39 */
40
41 package com.sun.java.swing.plaf.windows;
42
43 import java.awt.*;
44 import java.awt.image.*;
45 import java.security.AccessController;
46 import java.util.*;
47
48 import javax.swing.*;
49 import javax.swing.border.*;
50 import javax.swing.plaf.*;
51 import javax.swing.text.JTextComponent;
52
53 import sun.awt.image.SunWritableRaster;
54 import sun.awt.windows.ThemeReader;
55 import sun.security.action.GetPropertyAction;
106 if (themeActive.booleanValue()) {
107 GetPropertyAction propertyAction =
108 new GetPropertyAction("swing.noxp");
109 if (AccessController.doPrivileged(propertyAction) == null &&
110 ThemeReader.isThemed() &&
111 !(UIManager.getLookAndFeel()
112 instanceof WindowsClassicLookAndFeel)) {
113
114 xp = new XPStyle();
115 }
116 }
117 }
118 return ThemeReader.isXPStyleEnabled() ? xp : null;
119 }
120
121 static boolean isVista() {
122 XPStyle xp = XPStyle.getXP();
123 return (xp != null && xp.isSkinDefined(null, Part.CP_DROPDOWNBUTTONRIGHT));
124 }
125
126 /** Get a named {@code String} value from the current style
127 *
128 * @param part a {@code Part}
129 * @param state a {@code String}
130 * @param attributeKey a {@code String}
131 * @return a {@code String} or null if key is not found
132 * in the current style
133 *
134 * This is currently only used by WindowsInternalFrameTitlePane for painting
135 * title foregound and can be removed when no longer needed
136 */
137 String getString(Component c, Part part, State state, Prop prop) {
138 return getTypeEnumName(c, part, state, prop);
139 }
140
141 TypeEnum getTypeEnum(Component c, Part part, State state, Prop prop) {
142 int enumValue = ThemeReader.getEnum(part.getControlName(c), part.getValue(),
143 State.getValue(part, state),
144 prop.getValue());
145 return TypeEnum.getTypeEnum(prop, enumValue);
146 }
147
148 private static String getTypeEnumName(Component c, Part part, State state, Prop prop) {
149 int enumValue = ThemeReader.getEnum(part.getControlName(c), part.getValue(),
150 State.getValue(part, state),
151 prop.getValue());
152 if (enumValue == -1) {
153 return null;
154 }
155 return TypeEnum.getTypeEnum(prop, enumValue).getName();
156 }
157
158
159
160
161 /** Get a named {@code int} value from the current style
162 *
163 * @param part a {@code Part}
164 * @return an {@code int} or null if key is not found
165 * in the current style
166 */
167 int getInt(Component c, Part part, State state, Prop prop, int fallback) {
168 return ThemeReader.getInt(part.getControlName(c), part.getValue(),
169 State.getValue(part, state),
170 prop.getValue());
171 }
172
173 /** Get a named {@code Dimension} value from the current style
174 *
175 * @param key a {@code String}
176 * @return a {@code Dimension} or null if key is not found
177 * in the current style
178 *
179 * This is currently only used by WindowsProgressBarUI and the value
180 * should probably be cached there instead of here.
181 */
182 Dimension getDimension(Component c, Part part, State state, Prop prop) {
183 Dimension d = ThemeReader.getPosition(part.getControlName(c), part.getValue(),
184 State.getValue(part, state),
185 prop.getValue());
186 return (d != null) ? d : new Dimension();
187 }
188
189 /** Get a named {@code Point} (e.g. a location or an offset) value
190 * from the current style
191 *
192 * @param key a {@code String}
193 * @return a {@code Point} or null if key is not found
194 * in the current style
195 *
196 * This is currently only used by WindowsInternalFrameTitlePane for painting
197 * title foregound and can be removed when no longer needed
198 */
199 Point getPoint(Component c, Part part, State state, Prop prop) {
200 Dimension d = ThemeReader.getPosition(part.getControlName(c), part.getValue(),
201 State.getValue(part, state),
202 prop.getValue());
203 return (d != null) ? new Point(d.width, d.height) : new Point();
204 }
205
206 /** Get a named {@code Insets} value from the current style
207 *
208 * @param key a {@code String}
209 * @return an {@code Insets} object or null if key is not found
210 * in the current style
211 *
212 * This is currently only used to create borders and by
213 * WindowsInternalFrameTitlePane for painting title foregound.
214 * The return value is already cached in those places.
215 */
216 Insets getMargin(Component c, Part part, State state, Prop prop) {
217 Insets insets = ThemeReader.getThemeMargins(part.getControlName(c), part.getValue(),
218 State.getValue(part, state),
219 prop.getValue());
220 return (insets != null) ? insets : new Insets(0, 0, 0, 0);
221 }
222
223
224 /** Get a named {@code Color} value from the current style
225 *
226 * @param part a {@code Part}
227 * @return a {@code Color} or null if key is not found
228 * in the current style
229 */
230 synchronized Color getColor(Skin skin, Prop prop, Color fallback) {
231 String key = skin.toString() + "." + prop.name();
232 Part part = skin.part;
233 Color color = colorMap.get(key);
234 if (color == null) {
235 color = ThemeReader.getColor(part.getControlName(null), part.getValue(),
236 State.getValue(part, skin.state),
237 prop.getValue());
238 if (color != null) {
239 color = new ColorUIResource(color);
240 colorMap.put(key, color);
241 }
242 }
243 return (color != null) ? color : fallback;
244 }
245
246 Color getColor(Component c, Part part, State state, Prop prop, Color fallback) {
247 return getColor(new Skin(c, part, state), prop, fallback);
248 }
249
250
251
252 /** Get a named {@code Border} value from the current style
253 *
254 * @param part a {@code Part}
255 * @return a {@code Border} or null if key is not found
256 * in the current style or if the style for the particular
257 * part is not defined as "borderfill".
258 */
259 synchronized Border getBorder(Component c, Part part) {
260 if (part == Part.MENU) {
261 // Special case because XP has no skin for menus
262 if (flatMenus) {
263 // TODO: The classic border uses this color, but we should
264 // create a new UI property called "PopupMenu.borderColor"
265 // instead.
266 return new XPFillBorder(UIManager.getColor("InternalFrame.borderShadow"),
267 1);
268 } else {
269 return null; // Will cause L&F to use classic border
270 }
271 }
272 Skin skin = new Skin(c, part, null);
273 Border border = borderMap.get(skin.string);
274 if (border == null) {
275 String bgType = getTypeEnumName(c, part, null, Prop.BGTYPE);
429 margin = ((JToolBar)c).getMargin();
430 } else if (c instanceof JTextComponent) {
431 margin = ((JTextComponent)c).getMargin();
432 }
433 if (margin != null) {
434 insets.top = margin.top + 2;
435 insets.left = margin.left + 2;
436 insets.bottom = margin.bottom + 2;
437 insets.right = margin.right + 2;
438 }
439 return insets;
440 }
441 }
442 boolean isSkinDefined(Component c, Part part) {
443 return (part.getValue() == 0)
444 || ThemeReader.isThemePartDefined(
445 part.getControlName(c), part.getValue(), 0);
446 }
447
448
449 /** Get a {@code Skin} object from the current style
450 * for a named part (component type)
451 *
452 * @param part a {@code Part}
453 * @return a {@code Skin} object
454 */
455 synchronized Skin getSkin(Component c, Part part) {
456 assert isSkinDefined(c, part) : "part " + part + " is not defined";
457 return new Skin(c, part, null);
458 }
459
460
461 long getThemeTransitionDuration(Component c, Part part, State stateFrom,
462 State stateTo, Prop prop) {
463 return ThemeReader.getThemeTransitionDuration(part.getControlName(c),
464 part.getValue(),
465 State.getValue(part, stateFrom),
466 State.getValue(part, stateTo),
467 (prop != null) ? prop.getValue() : 0);
468 }
469
470
471 /** A class which encapsulates attributes for a given part
472 * (component type) and which provides methods for painting backgrounds
473 * and glyphs
547 return string.hashCode();
548 }
549
550 /** Paint a skin at x, y.
551 *
552 * @param g the graphics context to use for painting
553 * @param dx the destination <i>x</i> coordinate
554 * @param dy the destination <i>y</i> coordinate
555 * @param state which state to paint
556 */
557 void paintSkin(Graphics g, int dx, int dy, State state) {
558 if (state == null) {
559 state = this.state;
560 }
561 paintSkin(g, dx, dy, getWidth(state), getHeight(state), state);
562 }
563
564 /** Paint a skin in an area defined by a rectangle.
565 *
566 * @param g the graphics context to use for painting
567 * @param r a {@code Rectangle} defining the area to fill,
568 * may cause the image to be stretched or tiled
569 * @param state which state to paint
570 */
571 void paintSkin(Graphics g, Rectangle r, State state) {
572 paintSkin(g, r.x, r.y, r.width, r.height, state);
573 }
574
575 /** Paint a skin at a defined position and size
576 * This method supports animation.
577 *
578 * @param g the graphics context to use for painting
579 * @param dx the destination <i>x</i> coordinate
580 * @param dy the destination <i>y</i> coordinate
581 * @param dw the width of the area to fill, may cause
582 * the image to be stretched or tiled
583 * @param dh the height of the area to fill, may cause
584 * the image to be stretched or tiled
585 * @param state which state to paint
586 */
587 void paintSkin(Graphics g, int dx, int dy, int dw, int dh, State state) {
|