1. /*
  2. * @(#)SynthButtonUI.java 1.20 04/04/16
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package javax.swing.plaf.synth;
  8. import java.awt.*;
  9. import java.awt.event.*;
  10. import java.io.Serializable;
  11. import javax.swing.*;
  12. import javax.swing.border.*;
  13. import java.awt.*;
  14. import java.awt.event.*;
  15. import java.beans.*;
  16. import javax.swing.plaf.*;
  17. import javax.swing.plaf.basic.BasicButtonUI;
  18. import javax.swing.plaf.basic.BasicHTML;
  19. import javax.swing.text.View;
  20. import sun.swing.plaf.synth.SynthUI;
  21. import sun.swing.plaf.synth.DefaultSynthStyle;
  22. /**
  23. * Synth's ButtonUI implementation.
  24. *
  25. * @version 1.20, 04/16/04
  26. * @author Scott Violet
  27. */
  28. class SynthButtonUI extends BasicButtonUI implements
  29. PropertyChangeListener, SynthUI {
  30. private SynthStyle style;
  31. public static ComponentUI createUI(JComponent c) {
  32. return new SynthButtonUI();
  33. }
  34. protected void installDefaults(AbstractButton b) {
  35. updateStyle(b);
  36. LookAndFeel.installProperty(b, "rolloverEnabled", Boolean.TRUE);
  37. }
  38. protected void installListeners(AbstractButton b) {
  39. super.installListeners(b);
  40. b.addPropertyChangeListener(this);
  41. }
  42. void updateStyle(AbstractButton b) {
  43. SynthContext context = getContext(b, SynthConstants.ENABLED);
  44. SynthStyle oldStyle = style;
  45. style = SynthLookAndFeel.updateStyle(context, this);
  46. if (style != oldStyle) {
  47. if (b.getMargin() == null ||
  48. (b.getMargin() instanceof UIResource)) {
  49. Insets margin = (Insets)style.get(context,getPropertyPrefix() +
  50. "margin");
  51. if (margin == null) {
  52. // Some places assume margins are non-null.
  53. margin = SynthLookAndFeel.EMPTY_UIRESOURCE_INSETS;
  54. }
  55. b.setMargin(margin);
  56. }
  57. Object value = style.get(context, getPropertyPrefix() + "iconTextGap");
  58. if (value != null) {
  59. LookAndFeel.installProperty(b, "iconTextGap", value);
  60. }
  61. value = style.get(context, getPropertyPrefix() + "contentAreaFilled");
  62. LookAndFeel.installProperty(b, "contentAreaFilled",
  63. value != null? value : Boolean.TRUE);
  64. if (oldStyle != null) {
  65. uninstallKeyboardActions(b);
  66. installKeyboardActions(b);
  67. }
  68. }
  69. context.dispose();
  70. }
  71. protected void uninstallListeners(AbstractButton b) {
  72. super.uninstallListeners(b);
  73. b.removePropertyChangeListener(this);
  74. }
  75. protected void uninstallDefaults(AbstractButton b) {
  76. SynthContext context = getContext(b, ENABLED);
  77. style.uninstallDefaults(context);
  78. context.dispose();
  79. style = null;
  80. }
  81. public SynthContext getContext(JComponent c) {
  82. return getContext(c, getComponentState(c));
  83. }
  84. SynthContext getContext(JComponent c, int state) {
  85. Region region = getRegion(c);
  86. return SynthContext.getContext(SynthContext.class, c, region,
  87. style, state);
  88. }
  89. private Region getRegion(JComponent c) {
  90. return SynthLookAndFeel.getRegion(c);
  91. }
  92. /**
  93. * Returns the current state of the passed in <code>AbstractButton</code>.
  94. */
  95. private int getComponentState(JComponent c) {
  96. int state = ENABLED;
  97. if (!c.isEnabled()) {
  98. state = DISABLED;
  99. }
  100. if (SynthLookAndFeel.selectedUI == this) {
  101. return SynthLookAndFeel.selectedUIState | SynthConstants.ENABLED;
  102. }
  103. ButtonModel model = ((AbstractButton)c).getModel();
  104. if (model.isPressed()) {
  105. if (model.isArmed()) {
  106. state = PRESSED;
  107. }
  108. else {
  109. state = MOUSE_OVER;
  110. }
  111. }
  112. else if (model.isRollover()) {
  113. state = MOUSE_OVER;
  114. }
  115. if (model.isSelected()) {
  116. state |= SELECTED;
  117. }
  118. if (c.isFocusOwner()) {
  119. state |= FOCUSED;
  120. }
  121. if ((c instanceof JButton) && ((JButton)c).isDefaultButton()) {
  122. state |= DEFAULT;
  123. }
  124. return state;
  125. }
  126. // ********************************
  127. // Paint Methods
  128. // ********************************
  129. public void update(Graphics g, JComponent c) {
  130. SynthContext context = getContext(c);
  131. SynthLookAndFeel.update(context, g);
  132. paintBackground(context, g, c);
  133. paint(context, g);
  134. context.dispose();
  135. }
  136. public void paint(Graphics g, JComponent c) {
  137. SynthContext context = getContext(c);
  138. paint(context, g);
  139. context.dispose();
  140. }
  141. protected void paint(SynthContext context, Graphics g) {
  142. AbstractButton b = (AbstractButton)context.getComponent();
  143. g.setColor(context.getStyle().getColor(context,
  144. ColorType.TEXT_FOREGROUND));
  145. g.setFont(style.getFont(context));
  146. context.getStyle().getGraphicsUtils(context).paintText(
  147. context, g, b.getText(), getIcon(b),
  148. b.getHorizontalAlignment(), b.getVerticalAlignment(),
  149. b.getHorizontalTextPosition(), b.getVerticalTextPosition(),
  150. b.getIconTextGap(), b.getDisplayedMnemonicIndex(),
  151. getTextShiftOffset(context));
  152. }
  153. void paintBackground(SynthContext context, Graphics g, JComponent c) {
  154. context.getPainter().paintButtonBackground(context, g, 0, 0,
  155. c.getWidth(), c.getHeight());
  156. }
  157. public void paintBorder(SynthContext context, Graphics g, int x,
  158. int y, int w, int h) {
  159. context.getPainter().paintButtonBorder(context, g, x, y, w, h);
  160. }
  161. /**
  162. * Returns the default icon. This should NOT callback
  163. * to the JComponent.
  164. *
  165. * @param b AbstractButton the iocn is associated with
  166. * @return default icon
  167. */
  168. protected Icon getDefaultIcon(AbstractButton b) {
  169. SynthContext context = getContext(b);
  170. Icon icon = context.getStyle().getIcon(context, getPropertyPrefix() + "icon");
  171. context.dispose();
  172. return icon;
  173. }
  174. /**
  175. * Returns the Icon to use in painting the button.
  176. */
  177. protected Icon getIcon(AbstractButton b) {
  178. Icon icon = getEnabledIcon(b);
  179. ButtonModel model = b.getModel();
  180. Icon tmpIcon = null;
  181. if (!model.isEnabled()) {
  182. tmpIcon = getSynthDisabledIcon(b);
  183. } else if (model.isPressed() && model.isArmed()) {
  184. tmpIcon = getPressedIcon(b);
  185. } else if (b.isRolloverEnabled() && model.isRollover()) {
  186. tmpIcon = getRolloverIcon(b);
  187. } else if (model.isSelected()) {
  188. tmpIcon = getSelectedIcon(b);
  189. }
  190. if (tmpIcon != null) {
  191. icon = tmpIcon;
  192. }
  193. if(icon == null) {
  194. return getDefaultIcon(b);
  195. }
  196. return icon;
  197. }
  198. private Icon getSynthIcon(AbstractButton b, int synthConstant) {
  199. return style.getIcon(getContext(b, synthConstant), getPropertyPrefix() + "icon");
  200. }
  201. private Icon getEnabledIcon(AbstractButton b) {
  202. Icon tmpIcon = b.getIcon();
  203. if(tmpIcon == null) {
  204. tmpIcon = getSynthIcon(b, SynthConstants.ENABLED);
  205. }
  206. return tmpIcon;
  207. }
  208. private Icon getSelectedIcon(AbstractButton b) {
  209. Icon tmpIcon = b.getSelectedIcon();
  210. if(tmpIcon == null) {
  211. tmpIcon = getSynthIcon(b, SynthConstants.SELECTED);
  212. }
  213. return tmpIcon;
  214. }
  215. private Icon getRolloverIcon(AbstractButton b) {
  216. ButtonModel model = b.getModel();
  217. Icon tmpIcon;
  218. if (model.isSelected()) {
  219. tmpIcon = b.getRolloverSelectedIcon();
  220. if (tmpIcon == null) {
  221. tmpIcon = getSynthIcon(b, SynthConstants.SELECTED);
  222. if (tmpIcon == null) {
  223. tmpIcon = getSelectedIcon(b);
  224. }
  225. }
  226. } else {
  227. tmpIcon = b.getRolloverIcon();
  228. if (tmpIcon == null) {
  229. tmpIcon = getSynthIcon(b, SynthConstants.MOUSE_OVER);
  230. }
  231. }
  232. return tmpIcon;
  233. }
  234. private Icon getPressedIcon(AbstractButton b) {
  235. Icon tmpIcon;
  236. tmpIcon = b.getPressedIcon();
  237. if (tmpIcon == null) {
  238. tmpIcon = getSynthIcon(b, SynthConstants.PRESSED);
  239. if (tmpIcon == null) {
  240. tmpIcon = getSelectedIcon(b);
  241. }
  242. }
  243. return tmpIcon;
  244. }
  245. private Icon getSynthDisabledIcon(AbstractButton b) {
  246. ButtonModel model = b.getModel();
  247. Icon tmpIcon;
  248. if (model.isSelected()) {
  249. tmpIcon = b.getDisabledSelectedIcon();
  250. if(tmpIcon == null) {
  251. tmpIcon = getSynthIcon(b, SynthConstants.DISABLED|SynthConstants.SELECTED);
  252. }
  253. } else {
  254. tmpIcon = b.getDisabledIcon();
  255. if(tmpIcon == null) {
  256. tmpIcon = getSynthIcon(b, SynthConstants.DISABLED);
  257. }
  258. }
  259. return tmpIcon;
  260. }
  261. /**
  262. * Returns the amount to shift the text/icon when painting.
  263. */
  264. protected int getTextShiftOffset(SynthContext state) {
  265. AbstractButton button = (AbstractButton)state.getComponent();
  266. ButtonModel model = button.getModel();
  267. if (model.isArmed() && model.isPressed() &&
  268. button.getPressedIcon() == null) {
  269. return state.getStyle().getInt(state, getPropertyPrefix() +
  270. "textShiftOffset", 0);
  271. }
  272. return 0;
  273. }
  274. // ********************************
  275. // Layout Methods
  276. // ********************************
  277. public Dimension getMinimumSize(JComponent c) {
  278. if (c.getComponentCount() > 0 && c.getLayout() != null) {
  279. return null;
  280. }
  281. AbstractButton b = (AbstractButton)c;
  282. SynthContext ss = getContext(c);
  283. Dimension size = ss.getStyle().getGraphicsUtils(ss).getMinimumSize(
  284. ss, ss.getStyle().getFont(ss), b.getText(), getSizingIcon(b),
  285. b.getHorizontalAlignment(), b.getVerticalAlignment(),
  286. b.getHorizontalTextPosition(),
  287. b.getVerticalTextPosition(), b.getIconTextGap(),
  288. b.getDisplayedMnemonicIndex());
  289. ss.dispose();
  290. return size;
  291. }
  292. public Dimension getPreferredSize(JComponent c) {
  293. if (c.getComponentCount() > 0 && c.getLayout() != null) {
  294. return null;
  295. }
  296. AbstractButton b = (AbstractButton)c;
  297. SynthContext ss = getContext(c);
  298. Dimension size = ss.getStyle().getGraphicsUtils(ss).getPreferredSize(
  299. ss, ss.getStyle().getFont(ss), b.getText(), getSizingIcon(b),
  300. b.getHorizontalAlignment(), b.getVerticalAlignment(),
  301. b.getHorizontalTextPosition(),
  302. b.getVerticalTextPosition(), b.getIconTextGap(),
  303. b.getDisplayedMnemonicIndex());
  304. ss.dispose();
  305. return size;
  306. }
  307. public Dimension getMaximumSize(JComponent c) {
  308. if (c.getComponentCount() > 0 && c.getLayout() != null) {
  309. return null;
  310. }
  311. AbstractButton b = (AbstractButton)c;
  312. SynthContext ss = getContext(c);
  313. Dimension size = ss.getStyle().getGraphicsUtils(ss).getMaximumSize(
  314. ss, ss.getStyle().getFont(ss), b.getText(), getSizingIcon(b),
  315. b.getHorizontalAlignment(), b.getVerticalAlignment(),
  316. b.getHorizontalTextPosition(),
  317. b.getVerticalTextPosition(), b.getIconTextGap(),
  318. b.getDisplayedMnemonicIndex());
  319. ss.dispose();
  320. return size;
  321. }
  322. /**
  323. * Returns the Icon used in calculating the pref/min/max size.
  324. */
  325. protected Icon getSizingIcon(AbstractButton b) {
  326. // NOTE: this is slightly different than BasicButtonUI, where it
  327. // would just use getIcon, but this should be ok.
  328. return (b.isEnabled()) ? b.getIcon() : b.getDisabledIcon();
  329. }
  330. public void propertyChange(PropertyChangeEvent e) {
  331. if (SynthLookAndFeel.shouldUpdateStyle(e)) {
  332. updateStyle((AbstractButton)e.getSource());
  333. }
  334. }
  335. }