98 static synchronized XPStyle getXP() {
99 if (themeActive == null) {
100 Toolkit toolkit = Toolkit.getDefaultToolkit();
101 themeActive =
102 (Boolean)toolkit.getDesktopProperty("win.xpstyle.themeActive");
103 if (themeActive == null) {
104 themeActive = Boolean.FALSE;
105 }
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 xp;
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);
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 return ThemeReader.getPosition(part.getControlName(c), part.getValue(),
184 State.getValue(part, state),
185 prop.getValue());
186 }
187
188 /** Get a named <code>Point</code> (e.g. a location or an offset) value
189 * from the current style
190 *
191 * @param key a <code>String</code>
192 * @return a <code>Point</code> or null if key is not found
193 * in the current style
194 *
195 * This is currently only used by WindowsInternalFrameTitlePane for painting
196 * title foregound and can be removed when no longer needed
197 */
198 Point getPoint(Component c, Part part, State state, Prop prop) {
199 Dimension d = ThemeReader.getPosition(part.getControlName(c), part.getValue(),
200 State.getValue(part, state),
201 prop.getValue());
202 if (d != null) {
203 return new Point(d.width, d.height);
204 } else {
205 return null;
206 }
207 }
208
209 /** Get a named <code>Insets</code> value from the current style
210 *
211 * @param key a <code>String</code>
212 * @return an <code>Insets</code> object or null if key is not found
213 * in the current style
214 *
215 * This is currently only used to create borders and by
216 * WindowsInternalFrameTitlePane for painting title foregound.
217 * The return value is already cached in those places.
218 */
219 Insets getMargin(Component c, Part part, State state, Prop prop) {
220 return ThemeReader.getThemeMargins(part.getControlName(c), part.getValue(),
221 State.getValue(part, state),
222 prop.getValue());
223 }
224
225
226 /** Get a named <code>Color</code> value from the current style
227 *
228 * @param part a <code>Part</code>
229 * @return a <code>Color</code> or null if key is not found
230 * in the current style
231 */
232 synchronized Color getColor(Skin skin, Prop prop, Color fallback) {
233 String key = skin.toString() + "." + prop.name();
234 Part part = skin.part;
235 Color color = colorMap.get(key);
236 if (color == null) {
237 color = ThemeReader.getColor(part.getControlName(null), part.getValue(),
238 State.getValue(part, skin.state),
239 prop.getValue());
240 if (color != null) {
241 color = new ColorUIResource(color);
242 colorMap.put(key, color);
492
493 Skin(Component component, Part part, State state) {
494 this.component = component;
495 this.part = part;
496 this.state = state;
497
498 String str = part.getControlName(component) +"." + part.name();
499 if (state != null) {
500 str += "("+state.name()+")";
501 }
502 string = str;
503 }
504
505 Insets getContentMargin() {
506 /* idk: it seems margins are the same for all 'big enough'
507 * bounding rectangles.
508 */
509 int boundingWidth = 100;
510 int boundingHeight = 100;
511
512 return ThemeReader.getThemeBackgroundContentMargins(
513 part.getControlName(null), part.getValue(),
514 0, boundingWidth, boundingHeight);
515 }
516
517 private int getWidth(State state) {
518 if (size == null) {
519 size = getPartSize(part, state);
520 }
521 return size.width;
522 }
523
524 int getWidth() {
525 return getWidth((state != null) ? state : State.NORMAL);
526 }
527
528 private int getHeight(State state) {
529 if (size == null) {
530 size = getPartSize(part, state);
531 }
532 return size.height;
533 }
534
535 int getHeight() {
536 return getHeight((state != null) ? state : State.NORMAL);
537 }
538
539 public String toString() {
540 return string;
541 }
542
543 public boolean equals(Object obj) {
544 return (obj instanceof Skin && ((Skin)obj).string.equals(string));
545 }
546
547 public int hashCode() {
548 return string.hashCode();
549 }
550
551 /** Paint a skin at x, y.
552 *
569 * may cause the image to be stretched or tiled
570 * @param state which state to paint
571 */
572 void paintSkin(Graphics g, Rectangle r, State state) {
573 paintSkin(g, r.x, r.y, r.width, r.height, state);
574 }
575
576 /** Paint a skin at a defined position and size
577 * This method supports animation.
578 *
579 * @param g the graphics context to use for painting
580 * @param dx the destination <i>x</i> coordinate
581 * @param dy the destination <i>y</i> coordinate
582 * @param dw the width of the area to fill, may cause
583 * the image to be stretched or tiled
584 * @param dh the height of the area to fill, may cause
585 * the image to be stretched or tiled
586 * @param state which state to paint
587 */
588 void paintSkin(Graphics g, int dx, int dy, int dw, int dh, State state) {
589 if (ThemeReader.isGetThemeTransitionDurationDefined()
590 && component instanceof JComponent
591 && SwingUtilities.getAncestorOfClass(CellRendererPane.class,
592 component) == null) {
593 AnimationController.paintSkin((JComponent) component, this,
594 g, dx, dy, dw, dh, state);
595 } else {
596 paintSkinRaw(g, dx, dy, dw, dh, state);
597 }
598 }
599
600 /** Paint a skin at a defined position and size. This method
601 * does not trigger animation. It is needed for the animation
602 * support.
603 *
604 * @param g the graphics context to use for painting
605 * @param dx the destination <i>x</i> coordinate.
606 * @param dy the destination <i>y</i> coordinate.
607 * @param dw the width of the area to fill, may cause
608 * the image to be stretched or tiled
609 * @param dh the height of the area to fill, may cause
610 * the image to be stretched or tiled
611 * @param state which state to paint
612 */
613 void paintSkinRaw(Graphics g, int dx, int dy, int dw, int dh, State state) {
614 skinPainter.paint(null, g, dx, dy, dw, dh, this, state);
615 }
616
617 /** Paint a skin at a defined position and size
618 *
619 * @param g the graphics context to use for painting
620 * @param dx the destination <i>x</i> coordinate
621 * @param dy the destination <i>y</i> coordinate
622 * @param dw the width of the area to fill, may cause
623 * the image to be stretched or tiled
624 * @param dh the height of the area to fill, may cause
625 * the image to be stretched or tiled
626 * @param state which state to paint
627 * @param borderFill should test if the component uses a border fill
628 and skip painting if it is
629 */
630 void paintSkin(Graphics g, int dx, int dy, int dw, int dh, State state,
631 boolean borderFill) {
632 if(borderFill && "borderfill".equals(getTypeEnumName(component, part,
633 state, Prop.BGTYPE))) {
634 return;
635 }
636 skinPainter.paint(null, g, dx, dy, dw, dh, this, state);
637 }
638 }
639
640 private static class SkinPainter extends CachedPainter {
641 SkinPainter() {
642 super(30);
643 flush();
644 }
645
646 public void flush() {
647 super.flush();
648 }
649
650 protected void paintToImage(Component c, Image image, Graphics g,
651 int w, int h, Object[] args) {
667 // since we modify the data in it.
668 ThemeReader.paintBackground(SunWritableRaster.stealData(dbi, 0),
669 part.getControlName(c), part.getValue(),
670 State.getValue(part, state),
671 0, 0, w, h, w);
672 SunWritableRaster.markDirty(dbi);
673 }
674
675 protected Image createImage(Component c, int w, int h,
676 GraphicsConfiguration config, Object[] args) {
677 return new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
678 }
679 }
680
681 @SuppressWarnings("serial") // Superclass is not serializable across versions
682 static class GlyphButton extends JButton {
683 private Skin skin;
684
685 public GlyphButton(Component parent, Part part) {
686 XPStyle xp = getXP();
687 skin = xp.getSkin(parent, part);
688 setBorder(null);
689 setContentAreaFilled(false);
690 setMinimumSize(new Dimension(5, 5));
691 setPreferredSize(new Dimension(16, 16));
692 setMaximumSize(new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE));
693 }
694
695 public boolean isFocusTraversable() {
696 return false;
697 }
698
699 protected State getState() {
700 State state = State.NORMAL;
701 if (!isEnabled()) {
702 state = State.DISABLED;
703 } else if (getModel().isPressed()) {
704 state = State.PRESSED;
705 } else if (getModel().isRollover()) {
706 state = State.HOT;
707 }
708 return state;
709 }
710
711 public void paintComponent(Graphics g) {
712 Dimension d = getSize();
713 skin.paintSkin(g, 0, 0, d.width, d.height, getState());
714 }
715
716 public void setPart(Component parent, Part part) {
717 XPStyle xp = getXP();
718 skin = xp.getSkin(parent, part);
719 revalidate();
720 repaint();
721 }
722
723 protected void paintBorder(Graphics g) {
724 }
725
726
727 }
728
729 // Private constructor
730 private XPStyle() {
731 flatMenus = getSysBoolean(Prop.FLATMENUS);
732
733 colorMap = new HashMap<String, Color>();
734 borderMap = new HashMap<String, Border>();
735 // Note: All further access to the maps must be synchronized
736 }
737
738
|
98 static synchronized XPStyle getXP() {
99 if (themeActive == null) {
100 Toolkit toolkit = Toolkit.getDefaultToolkit();
101 themeActive =
102 (Boolean)toolkit.getDesktopProperty("win.xpstyle.themeActive");
103 if (themeActive == null) {
104 themeActive = Boolean.FALSE;
105 }
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);
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);
490
491 Skin(Component component, Part part, State state) {
492 this.component = component;
493 this.part = part;
494 this.state = state;
495
496 String str = part.getControlName(component) +"." + part.name();
497 if (state != null) {
498 str += "("+state.name()+")";
499 }
500 string = str;
501 }
502
503 Insets getContentMargin() {
504 /* idk: it seems margins are the same for all 'big enough'
505 * bounding rectangles.
506 */
507 int boundingWidth = 100;
508 int boundingHeight = 100;
509
510 Insets insets = ThemeReader.getThemeBackgroundContentMargins(
511 part.getControlName(null), part.getValue(),
512 0, boundingWidth, boundingHeight);
513 return (insets != null) ? insets : new Insets(0, 0, 0, 0);
514 }
515
516 private int getWidth(State state) {
517 if (size == null) {
518 size = getPartSize(part, state);
519 }
520 return (size != null) ? size.width : 0;
521 }
522
523 int getWidth() {
524 return getWidth((state != null) ? state : State.NORMAL);
525 }
526
527 private int getHeight(State state) {
528 if (size == null) {
529 size = getPartSize(part, state);
530 }
531 return (size != null) ? size.height : 0;
532 }
533
534 int getHeight() {
535 return getHeight((state != null) ? state : State.NORMAL);
536 }
537
538 public String toString() {
539 return string;
540 }
541
542 public boolean equals(Object obj) {
543 return (obj instanceof Skin && ((Skin)obj).string.equals(string));
544 }
545
546 public int hashCode() {
547 return string.hashCode();
548 }
549
550 /** Paint a skin at x, y.
551 *
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) {
588 if (XPStyle.getXP() == null) {
589 return;
590 }
591 if (ThemeReader.isGetThemeTransitionDurationDefined()
592 && component instanceof JComponent
593 && SwingUtilities.getAncestorOfClass(CellRendererPane.class,
594 component) == null) {
595 AnimationController.paintSkin((JComponent) component, this,
596 g, dx, dy, dw, dh, state);
597 } else {
598 paintSkinRaw(g, dx, dy, dw, dh, state);
599 }
600 }
601
602 /** Paint a skin at a defined position and size. This method
603 * does not trigger animation. It is needed for the animation
604 * support.
605 *
606 * @param g the graphics context to use for painting
607 * @param dx the destination <i>x</i> coordinate.
608 * @param dy the destination <i>y</i> coordinate.
609 * @param dw the width of the area to fill, may cause
610 * the image to be stretched or tiled
611 * @param dh the height of the area to fill, may cause
612 * the image to be stretched or tiled
613 * @param state which state to paint
614 */
615 void paintSkinRaw(Graphics g, int dx, int dy, int dw, int dh, State state) {
616 if (XPStyle.getXP() == null) {
617 return;
618 }
619 skinPainter.paint(null, g, dx, dy, dw, dh, this, state);
620 }
621
622 /** Paint a skin at a defined position and size
623 *
624 * @param g the graphics context to use for painting
625 * @param dx the destination <i>x</i> coordinate
626 * @param dy the destination <i>y</i> coordinate
627 * @param dw the width of the area to fill, may cause
628 * the image to be stretched or tiled
629 * @param dh the height of the area to fill, may cause
630 * the image to be stretched or tiled
631 * @param state which state to paint
632 * @param borderFill should test if the component uses a border fill
633 and skip painting if it is
634 */
635 void paintSkin(Graphics g, int dx, int dy, int dw, int dh, State state,
636 boolean borderFill) {
637 if (XPStyle.getXP() == null) {
638 return;
639 }
640 if(borderFill && "borderfill".equals(getTypeEnumName(component, part,
641 state, Prop.BGTYPE))) {
642 return;
643 }
644 skinPainter.paint(null, g, dx, dy, dw, dh, this, state);
645 }
646 }
647
648 private static class SkinPainter extends CachedPainter {
649 SkinPainter() {
650 super(30);
651 flush();
652 }
653
654 public void flush() {
655 super.flush();
656 }
657
658 protected void paintToImage(Component c, Image image, Graphics g,
659 int w, int h, Object[] args) {
675 // since we modify the data in it.
676 ThemeReader.paintBackground(SunWritableRaster.stealData(dbi, 0),
677 part.getControlName(c), part.getValue(),
678 State.getValue(part, state),
679 0, 0, w, h, w);
680 SunWritableRaster.markDirty(dbi);
681 }
682
683 protected Image createImage(Component c, int w, int h,
684 GraphicsConfiguration config, Object[] args) {
685 return new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
686 }
687 }
688
689 @SuppressWarnings("serial") // Superclass is not serializable across versions
690 static class GlyphButton extends JButton {
691 private Skin skin;
692
693 public GlyphButton(Component parent, Part part) {
694 XPStyle xp = getXP();
695 skin = xp != null ? xp.getSkin(parent, part) : null;
696 setBorder(null);
697 setContentAreaFilled(false);
698 setMinimumSize(new Dimension(5, 5));
699 setPreferredSize(new Dimension(16, 16));
700 setMaximumSize(new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE));
701 }
702
703 public boolean isFocusTraversable() {
704 return false;
705 }
706
707 protected State getState() {
708 State state = State.NORMAL;
709 if (!isEnabled()) {
710 state = State.DISABLED;
711 } else if (getModel().isPressed()) {
712 state = State.PRESSED;
713 } else if (getModel().isRollover()) {
714 state = State.HOT;
715 }
716 return state;
717 }
718
719 public void paintComponent(Graphics g) {
720 if (XPStyle.getXP() == null || skin == null) {
721 return;
722 }
723 Dimension d = getSize();
724 skin.paintSkin(g, 0, 0, d.width, d.height, getState());
725 }
726
727 public void setPart(Component parent, Part part) {
728 XPStyle xp = getXP();
729 skin = xp != null ? xp.getSkin(parent, part) : null;
730 revalidate();
731 repaint();
732 }
733
734 protected void paintBorder(Graphics g) {
735 }
736
737
738 }
739
740 // Private constructor
741 private XPStyle() {
742 flatMenus = getSysBoolean(Prop.FLATMENUS);
743
744 colorMap = new HashMap<String, Color>();
745 borderMap = new HashMap<String, Border>();
746 // Note: All further access to the maps must be synchronized
747 }
748
749
|