1. /*
  2. * @(#)SynthButtonUI.java 1.16 03/01/23
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package com.sun.java.swing.plaf.gtk;
  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 javax.swing.plaf.ButtonUI;
  16. import javax.swing.plaf.basic.BasicHTML;
  17. import javax.swing.plaf.UIResource;
  18. import javax.swing.plaf.ComponentUI;
  19. import javax.swing.text.View;
  20. /**
  21. * Synth's ButtonUI, derives from BasicButtonUI 1.106.
  22. *
  23. * @version 1.16, 01/23/03
  24. * @author Jeff Dinkins
  25. */
  26. class SynthButtonUI extends ButtonUI implements SynthUI {
  27. /**
  28. * The SkinsButtonListener is shared among all buttons.
  29. */
  30. private static SynthButtonListener sharedButtonListener;
  31. private SynthStyle style;
  32. /**
  33. * Returns a ButtonUI implementation.
  34. */
  35. public static ComponentUI createUI(JComponent c) {
  36. return new SynthButtonUI();
  37. }
  38. /**
  39. * Returns the prefix used in looking up property values.
  40. */
  41. protected String getPropertyPrefix() {
  42. return "Button.";
  43. }
  44. // ********************************
  45. // Install PLAF
  46. // ********************************
  47. public void installUI(JComponent c) {
  48. installDefaults((AbstractButton)c);
  49. installListeners((AbstractButton)c);
  50. installKeyboardActions((AbstractButton)c);
  51. BasicHTML.updateRenderer(c, ((AbstractButton) c).getText());
  52. }
  53. protected void installDefaults(AbstractButton b) {
  54. fetchStyle(b);
  55. b.setRolloverEnabled(true);
  56. }
  57. protected void installListeners(AbstractButton b) {
  58. SynthButtonListener listener = createButtonListener(b);
  59. if (listener != null) {
  60. b.addMouseListener(listener);
  61. b.addMouseMotionListener(listener);
  62. b.addFocusListener(listener);
  63. b.addPropertyChangeListener(listener);
  64. b.addChangeListener(listener);
  65. }
  66. }
  67. protected void installKeyboardActions(AbstractButton b) {
  68. SynthButtonListener listener = getButtonListener(b);
  69. if (listener != null) {
  70. listener.installKeyboardActions(b);
  71. }
  72. }
  73. void fetchStyle(AbstractButton b) {
  74. SynthContext context = getContext(b, SynthConstants.ENABLED);
  75. SynthStyle oldStyle = style;
  76. style = SynthLookAndFeel.updateStyle(context, this);
  77. if (style != oldStyle) {
  78. if (b.getMargin() == null ||
  79. (b.getMargin() instanceof UIResource)) {
  80. Insets margin = (Insets)style.get(context,getPropertyPrefix() +
  81. "margin");
  82. if (margin == null) {
  83. // Some places assume margins are non-null.
  84. margin = SynthLookAndFeel.EMPTY_UIRESOURCE_INSETS;
  85. }
  86. b.setMargin(margin);
  87. }
  88. int iconTextGap = style.getInt(context, getPropertyPrefix() +
  89. "iconTextGap", -1);
  90. if (iconTextGap != -1) {
  91. b.setIconTextGap(iconTextGap);
  92. }
  93. b.setContentAreaFilled(style.getBoolean(context,
  94. getPropertyPrefix() + "contentAreaFilled", true));
  95. }
  96. context.dispose();
  97. }
  98. // ********************************
  99. // Uninstall PLAF
  100. // ********************************
  101. public void uninstallUI(JComponent c) {
  102. uninstallKeyboardActions((AbstractButton) c);
  103. uninstallListeners((AbstractButton) c);
  104. uninstallDefaults((AbstractButton) c);
  105. BasicHTML.updateRenderer(c, "");
  106. }
  107. protected void uninstallKeyboardActions(AbstractButton b) {
  108. SynthButtonListener listener = getButtonListener(b);
  109. if (listener != null) {
  110. listener.uninstallKeyboardActions(b);
  111. }
  112. }
  113. protected void uninstallListeners(AbstractButton b) {
  114. SynthButtonListener listener = getButtonListener(b);
  115. if (listener != null) {
  116. b.removeMouseListener(listener);
  117. b.removeMouseListener(listener);
  118. b.removeMouseMotionListener(listener);
  119. b.removeFocusListener(listener);
  120. b.removeChangeListener(listener);
  121. b.removePropertyChangeListener(listener);
  122. }
  123. }
  124. protected void uninstallDefaults(AbstractButton b) {
  125. SynthContext context = getContext(b, ENABLED);
  126. style.uninstallDefaults(context);
  127. context.dispose();
  128. style = null;
  129. }
  130. // ********************************
  131. // Create Listeners
  132. // ********************************
  133. protected SynthButtonListener createButtonListener(AbstractButton b) {
  134. if (sharedButtonListener == null) {
  135. sharedButtonListener = new SynthButtonListener();
  136. }
  137. return sharedButtonListener;
  138. }
  139. public SynthContext getContext(JComponent c) {
  140. return getContext(c, getComponentState(c));
  141. }
  142. SynthContext getContext(JComponent c, int state) {
  143. Region region = getRegion(c);
  144. return SynthContext.getContext(SynthContext.class, c, region,
  145. style, state);
  146. }
  147. private Region getRegion(JComponent c) {
  148. return SynthLookAndFeel.getRegion(c);
  149. }
  150. /**
  151. * Returns the current state of the passed in <code>AbstractButton</code>.
  152. */
  153. private int getComponentState(JComponent c) {
  154. int state = ENABLED;
  155. if (!c.isEnabled()) {
  156. state = DISABLED;
  157. }
  158. ButtonModel model = ((AbstractButton)c).getModel();
  159. if (model.isPressed()) {
  160. if (model.isArmed()) {
  161. state = PRESSED;
  162. }
  163. else {
  164. state = MOUSE_OVER;
  165. }
  166. }
  167. else if (model.isRollover()) {
  168. state = MOUSE_OVER;
  169. }
  170. if (model.isSelected()) {
  171. state |= SELECTED;
  172. }
  173. if (c.isFocusOwner()) {
  174. state |= FOCUSED;
  175. }
  176. if ((c instanceof JButton) && ((JButton)c).isDefaultButton()) {
  177. state |= DEFAULT;
  178. }
  179. return state;
  180. }
  181. // ********************************
  182. // Paint Methods
  183. // ********************************
  184. /**
  185. * Notifies this UI delegate that it's time to paint the specified
  186. * component. This method is invoked by <code>JComponent</code>
  187. * when the specified component is being painted.
  188. * <p>If <code>c</code> is opaque, this will paint the background using
  189. * the <code>GraphicsEngine</code> method <code>paintBackground</code>.
  190. */
  191. public void update(Graphics g, JComponent c) {
  192. SynthContext context = getContext(c);
  193. SynthLookAndFeel.update(context, g);
  194. paint(context, g);
  195. context.dispose();
  196. }
  197. public void paint(Graphics g, JComponent c) {
  198. SynthContext context = getContext(c);
  199. paint(context, g);
  200. context.dispose();
  201. }
  202. protected void paint(SynthContext context, Graphics g) {
  203. AbstractButton b = (AbstractButton)context.getComponent();
  204. g.setColor(context.getStyle().getColor(context,
  205. ColorType.TEXT_FOREGROUND));
  206. g.setFont(style.getFont(context));
  207. context.getStyle().getSynthGraphics(context).paintText(
  208. context, g, b.getText(), getIcon(b),
  209. b.getHorizontalAlignment(), b.getVerticalAlignment(),
  210. b.getHorizontalTextPosition(), b.getVerticalTextPosition(),
  211. b.getIconTextGap(), b.getDisplayedMnemonicIndex(),
  212. getTextShiftOffset(context));
  213. }
  214. /**
  215. * Returns the Icon to use in painting the button.
  216. */
  217. protected Icon getIcon(AbstractButton b) {
  218. Icon icon = b.getIcon();
  219. if (icon == null) {
  220. return null;
  221. }
  222. ButtonModel model = b.getModel();
  223. Icon tmpIcon = null;
  224. if (!model.isEnabled()) {
  225. if (model.isSelected()) {
  226. tmpIcon = b.getDisabledSelectedIcon();
  227. } else {
  228. tmpIcon = b.getDisabledIcon();
  229. }
  230. } else if (model.isPressed() && model.isArmed()) {
  231. tmpIcon = b.getPressedIcon();
  232. if (tmpIcon == null) {
  233. tmpIcon = b.getSelectedIcon();
  234. }
  235. } else if (b.isRolloverEnabled() && model.isRollover()) {
  236. if (model.isSelected()) {
  237. tmpIcon = b.getRolloverSelectedIcon();
  238. if (tmpIcon == null) {
  239. tmpIcon = b.getSelectedIcon();
  240. }
  241. } else {
  242. tmpIcon = b.getRolloverIcon();
  243. }
  244. } else if (model.isSelected()) {
  245. tmpIcon = b.getSelectedIcon();
  246. }
  247. if (tmpIcon != null) {
  248. icon = tmpIcon;
  249. }
  250. return icon;
  251. }
  252. /**
  253. * Returns the amount to shift the text/icon when painting.
  254. */
  255. protected int getTextShiftOffset(SynthContext state) {
  256. AbstractButton button = (AbstractButton)state.getComponent();
  257. ButtonModel model = button.getModel();
  258. if (model.isArmed() && model.isPressed() &&
  259. button.getPressedIcon() != null) {
  260. int tso = state.getStyle().getInt(state, getPropertyPrefix() +
  261. "textShiftOffset", -1);
  262. if (tso != -1) {
  263. return tso;
  264. }
  265. }
  266. return 0;
  267. }
  268. // ********************************
  269. // Layout Methods
  270. // ********************************
  271. public Dimension getMinimumSize(JComponent c) {
  272. if (c.getComponentCount() > 0 && c.getLayout() != null) {
  273. return null;
  274. }
  275. AbstractButton b = (AbstractButton)c;
  276. SynthContext ss = getContext(c);
  277. Dimension size = ss.getStyle().getSynthGraphics(ss).getMinimumSize(
  278. ss, ss.getStyle().getFont(ss), b.getText(), getSizingIcon(b),
  279. b.getHorizontalAlignment(), b.getVerticalAlignment(),
  280. b.getHorizontalTextPosition(),
  281. b.getVerticalTextPosition(), b.getIconTextGap(),
  282. b.getDisplayedMnemonicIndex());
  283. ss.dispose();
  284. return size;
  285. }
  286. public Dimension getPreferredSize(JComponent c) {
  287. if (c.getComponentCount() > 0 && c.getLayout() != null) {
  288. return null;
  289. }
  290. AbstractButton b = (AbstractButton)c;
  291. SynthContext ss = getContext(c);
  292. Dimension size = ss.getStyle().getSynthGraphics(ss).getPreferredSize(
  293. ss, ss.getStyle().getFont(ss), b.getText(), getSizingIcon(b),
  294. b.getHorizontalAlignment(), b.getVerticalAlignment(),
  295. b.getHorizontalTextPosition(),
  296. b.getVerticalTextPosition(), b.getIconTextGap(),
  297. b.getDisplayedMnemonicIndex());
  298. ss.dispose();
  299. return size;
  300. }
  301. public Dimension getMaximumSize(JComponent c) {
  302. if (c.getComponentCount() > 0 && c.getLayout() != null) {
  303. return null;
  304. }
  305. AbstractButton b = (AbstractButton)c;
  306. SynthContext ss = getContext(c);
  307. Dimension size = ss.getStyle().getSynthGraphics(ss).getMaximumSize(
  308. ss, ss.getStyle().getFont(ss), b.getText(), getSizingIcon(b),
  309. b.getHorizontalAlignment(), b.getVerticalAlignment(),
  310. b.getHorizontalTextPosition(),
  311. b.getVerticalTextPosition(), b.getIconTextGap(),
  312. b.getDisplayedMnemonicIndex());
  313. ss.dispose();
  314. return size;
  315. }
  316. /**
  317. * Returns the Icon used in calculating the pref/min/max size.
  318. */
  319. protected Icon getSizingIcon(AbstractButton b) {
  320. // NOTE: this is slightly different than BasicButtonUI, where it
  321. // would just use getIcon, but this should be ok.
  322. return (b.isEnabled()) ? b.getIcon() : b.getDisabledIcon();
  323. }
  324. /**
  325. * Returns the SkinsButtonListener install on the passed in button.
  326. */
  327. private SynthButtonListener getButtonListener(AbstractButton b) {
  328. return (SynthButtonListener)SynthLookAndFeel.getSynthEventListener(b);
  329. }
  330. }