📄 xpstyle.java
字号:
/* * @(#)XPStyle.java 1.34 06/07/13 * * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. *//* * <p>These classes are designed to be used while the * corresponding <code>LookAndFeel</code> class has been installed * (<code>UIManager.setLookAndFeel(new <i>XXX</i>LookAndFeel())</code>). * Using them while a different <code>LookAndFeel</code> is installed * may produce unexpected results, including exceptions. * Additionally, changing the <code>LookAndFeel</code> * maintained by the <code>UIManager</code> without updating the * corresponding <code>ComponentUI</code> of any * <code>JComponent</code>s may also produce unexpected results, * such as the wrong colors showing up, and is generally not * encouraged. * */package com.sun.java.swing.plaf.windows;import java.awt.*;import java.awt.image.*;import java.security.AccessController;import java.util.*;import javax.swing.*;import javax.swing.border.*;import javax.swing.plaf.*;import javax.swing.text.JTextComponent;import sun.awt.image.CachingSurfaceManager;import sun.awt.image.SurfaceManager;import sun.awt.windows.ThemeReader;import sun.security.action.GetPropertyAction;import sun.swing.CachedPainter;import static com.sun.java.swing.plaf.windows.TMSchema.*;/** * Implements Windows XP Styles for the Windows Look and Feel. * * @version 1.34 07/13/06 * @author Leif Samuelsson */class XPStyle { // Singleton instance of this class private static XPStyle xp; // Singleton instance of SkinPainter private static SkinPainter skinPainter = new SkinPainter(); private static Boolean themeActive = null; private HashMap<String, Border> borderMap; private HashMap<String, Color> colorMap; private boolean flatMenus; static { invalidateStyle(); } /** Static method for clearing the hashmap and loading the * current XP style and theme */ static synchronized void invalidateStyle() { xp = null; themeActive = null; skinPainter.flush(); } /** Get the singleton instance of this class * * @return the singleton instance of this class or null if XP styles * are not active or if this is not Windows XP */ static synchronized XPStyle getXP() { if (themeActive == null) { Toolkit toolkit = Toolkit.getDefaultToolkit(); themeActive = (Boolean)toolkit.getDesktopProperty("win.xpstyle.themeActive"); if (themeActive == null) { themeActive = Boolean.FALSE; } if (themeActive.booleanValue()) { GetPropertyAction propertyAction = new GetPropertyAction("swing.noxp"); if (AccessController.doPrivileged(propertyAction) == null && ThemeReader.isThemed() && !(UIManager.getLookAndFeel() instanceof WindowsClassicLookAndFeel)) { xp = new XPStyle(); } } } return xp; } static boolean isVista() { XPStyle xp = XPStyle.getXP(); return (xp != null && xp.isSkinDefined(null, Part.CP_DROPDOWNBUTTONRIGHT)); } /** Get a named <code>String</code> value from the current style * * @param part a <code>Part</code> * @param state a <code>String</code> * @param attributeKey a <code>String</code> * @return a <code>String</code> or null if key is not found * in the current style * * This is currently only used by WindowsInternalFrameTitlePane for painting * title foregound and can be removed when no longer needed */ String getString(Component c, Part part, State state, Prop prop) { return getTypeEnumName(c, part, state, prop); } TypeEnum getTypeEnum(Component c, Part part, State state, Prop prop) { int enumValue = ThemeReader.getEnum(part.getControlName(c), part.getValue(), State.getValue(part, state), prop.getValue()); return TypeEnum.getTypeEnum(prop, enumValue); } private static String getTypeEnumName(Component c, Part part, State state, Prop prop) { int enumValue = ThemeReader.getEnum(part.getControlName(c), part.getValue(), State.getValue(part, state), prop.getValue()); if (enumValue == -1) { return null; } return TypeEnum.getTypeEnum(prop, enumValue).getName(); } /** Get a named <code>int</code> value from the current style * * @param part a <code>Part</code> * @return an <code>int</code> or null if key is not found * in the current style */ int getInt(Component c, Part part, State state, Prop prop, int fallback) { return ThemeReader.getInt(part.getControlName(c), part.getValue(), State.getValue(part, state), prop.getValue()); } /** Get a named <code>Dimension</code> value from the current style * * @param key a <code>String</code> * @return a <code>Dimension</code> or null if key is not found * in the current style * * This is currently only used by WindowsProgressBarUI and the value * should probably be cached there instead of here. */ Dimension getDimension(Component c, Part part, State state, Prop prop) { return ThemeReader.getPosition(part.getControlName(c), part.getValue(), State.getValue(part, state), prop.getValue()); } /** Get a named <code>Point</code> (e.g. a location or an offset) value * from the current style * * @param key a <code>String</code> * @return a <code>Point</code> or null if key is not found * in the current style * * This is currently only used by WindowsInternalFrameTitlePane for painting * title foregound and can be removed when no longer needed */ Point getPoint(Component c, Part part, State state, Prop prop) { Dimension d = ThemeReader.getPosition(part.getControlName(c), part.getValue(), State.getValue(part, state), prop.getValue()); if (d != null) { return new Point(d.width, d.height); } else { return null; } } /** Get a named <code>Insets</code> value from the current style * * @param key a <code>String</code> * @return an <code>Insets</code> object or null if key is not found * in the current style * * This is currently only used to create borders and by * WindowsInternalFrameTitlePane for painting title foregound. * The return value is already cached in those places. */ Insets getMargin(Component c, Part part, State state, Prop prop) { return ThemeReader.getThemeMargins(part.getControlName(c), part.getValue(), State.getValue(part, state), prop.getValue()); } /** Get a named <code>Color</code> value from the current style * * @param part a <code>Part</code> * @return a <code>Color</code> or null if key is not found * in the current style */ synchronized Color getColor(Skin skin, Prop prop, Color fallback) { String key = skin.toString() + "." + prop.name(); Part part = skin.part; Color color = colorMap.get(key); if (color == null) { color = ThemeReader.getColor(part.getControlName(null), part.getValue(), State.getValue(part, skin.state), prop.getValue()); if (color != null) { color = new ColorUIResource(color); colorMap.put(key, color); } } return (color != null) ? color : fallback; } Color getColor(Component c, Part part, State state, Prop prop, Color fallback) { return getColor(new Skin(c, part, state), prop, fallback); } /** Get a named <code>Border</code> value from the current style * * @param part a <code>Part</code> * @return a <code>Border</code> or null if key is not found * in the current style or if the style for the particular * part is not defined as "borderfill". */ synchronized Border getBorder(Component c, Part part) { if (part == Part.MENU) { // Special case because XP has no skin for menus if (flatMenus) { // TODO: The classic border uses this color, but we should // create a new UI property called "PopupMenu.borderColor" // instead. return new XPFillBorder(UIManager.getColor("InternalFrame.borderShadow"), 1); } else { return null; // Will cause L&F to use classic border } } Skin skin = new Skin(c, part, null); Border border = borderMap.get(skin.string); if (border == null) { String bgType = getTypeEnumName(c, part, null, Prop.BGTYPE); if ("borderfill".equalsIgnoreCase(bgType)) { int thickness = getInt(c, part, null, Prop.BORDERSIZE, 1); Color color = getColor(skin, Prop.BORDERCOLOR, Color.black); border = new XPFillBorder(color, thickness); if (part == Part.CP_COMBOBOX) { border = new XPStatefulFillBorder(color, thickness, part, Prop.BORDERCOLOR); } } else if ("imagefile".equalsIgnoreCase(bgType)) { Insets m = getMargin(c, part, null, Prop.SIZINGMARGINS); if (m != null) { if (getBoolean(c, part, null, Prop.BORDERONLY)) { border = new XPImageBorder(c, part); } else if (part == Part.CP_COMBOBOX) { border = new EmptyBorder(1, 1, 1, 1); } else { if(part == Part.TP_BUTTON) { border = new XPEmptyBorder(new Insets(3,3,3,3)); } else { border = new XPEmptyBorder(m); } } } } if (border != null) { borderMap.put(skin.string, border); } } return border; } private class XPFillBorder extends LineBorder implements UIResource { XPFillBorder(Color color, int thickness) { super(color, thickness); } public Insets getBorderInsets(Component c) { return getBorderInsets(c, new Insets(0,0,0,0)); } public Insets getBorderInsets(Component c, Insets insets) { Insets margin = null; // // Ideally we'd have an interface defined for classes which // support margins (to avoid this hackery), but we've // decided against it for simplicity // if (c instanceof AbstractButton) { margin = ((AbstractButton)c).getMargin(); } else if (c instanceof JToolBar) { margin = ((JToolBar)c).getMargin(); } else if (c instanceof JTextComponent) { margin = ((JTextComponent)c).getMargin(); } insets.top = (margin != null? margin.top : 0) + thickness; insets.left = (margin != null? margin.left : 0) + thickness; insets.bottom = (margin != null? margin.bottom : 0) + thickness; insets.right = (margin != null? margin.right : 0) + thickness; return insets; } } private class XPStatefulFillBorder extends XPFillBorder { private final Part part; private final Prop prop; XPStatefulFillBorder(Color color, int thickness, Part part, Prop prop) { super(color, thickness); this.part = part; this.prop = prop; } public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { State state = State.NORMAL; // special casing for comboboxes. // there may be more special cases in the future if(c instanceof JComboBox) { JComboBox cb = (JComboBox)c; // note. in the future this should be replaced with a call // to BasicLookAndFeel.getUIOfType() if(cb.getUI() instanceof WindowsComboBoxUI) { WindowsComboBoxUI wcb = (WindowsComboBoxUI)cb.getUI(); state = wcb.getXPComboBoxState(cb); } } lineColor = getColor(c, part, state, prop, Color.black); super.paintBorder(c, g, x, y, width, height); } } private class XPImageBorder extends AbstractBorder implements UIResource { Skin skin; XPImageBorder(Component c, Part part) { this.skin = getSkin(c, part); } public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { skin.paintSkin(g, x, y, width, height, null); } public Insets getBorderInsets(Component c) { return getBorderInsets(c, new Insets(0,0,0,0)); } public Insets getBorderInsets(Component c, Insets insets) { Insets margin = null; Insets borderInsets = skin.getContentMargin(); if(borderInsets == null) { borderInsets = new Insets(0, 0, 0, 0); } // // Ideally we'd have an interface defined for classes which // support margins (to avoid this hackery), but we've // decided against it for simplicity // if (c instanceof AbstractButton) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -