1. /*
  2. * @(#)SynthComboBoxUI.java 1.15 03/12/19
  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.lang.reflect.*;
  11. import javax.swing.*;
  12. import javax.accessibility.*;
  13. import javax.swing.FocusManager;
  14. import javax.swing.plaf.*;
  15. import javax.swing.border.*;
  16. import javax.swing.text.*;
  17. import javax.swing.event.*;
  18. import javax.swing.plaf.basic.*;
  19. import java.beans.PropertyChangeListener;
  20. import java.beans.PropertyChangeEvent;
  21. import sun.awt.AppContext;
  22. import sun.swing.plaf.synth.SynthUI;
  23. /**
  24. * Synth's ComboBoxUI.
  25. *
  26. * @version 1.15, 12/19/03
  27. * @author Scott Violet
  28. */
  29. class SynthComboBoxUI extends BasicComboBoxUI implements
  30. PropertyChangeListener, SynthUI {
  31. private SynthStyle style;
  32. private boolean useListColors;
  33. public static ComponentUI createUI(JComponent c) {
  34. return new SynthComboBoxUI();
  35. }
  36. protected void installDefaults() {
  37. updateStyle(comboBox);
  38. }
  39. private void updateStyle(JComboBox comboBox) {
  40. SynthStyle oldStyle = style;
  41. SynthContext context = getContext(comboBox, ENABLED);
  42. style = SynthLookAndFeel.updateStyle(context, this);
  43. if (style != oldStyle) {
  44. useListColors = style.getBoolean(context,
  45. "ComboBox.rendererUseListColors", true);
  46. if (oldStyle != null) {
  47. uninstallKeyboardActions();
  48. installKeyboardActions();
  49. }
  50. }
  51. context.dispose();
  52. }
  53. protected void installListeners() {
  54. comboBox.addPropertyChangeListener(this);
  55. super.installListeners();
  56. }
  57. protected void uninstallDefaults() {
  58. SynthContext context = getContext(comboBox, ENABLED);
  59. style.uninstallDefaults(context);
  60. context.dispose();
  61. style = null;
  62. }
  63. protected void uninstallListeners() {
  64. comboBox.removePropertyChangeListener(this);
  65. super.uninstallListeners();
  66. }
  67. public SynthContext getContext(JComponent c) {
  68. return getContext(c, getComponentState(c));
  69. }
  70. private SynthContext getContext(JComponent c, int state) {
  71. return SynthContext.getContext(SynthContext.class, c,
  72. SynthLookAndFeel.getRegion(c), style, state);
  73. }
  74. private Region getRegion(JComponent c) {
  75. return SynthLookAndFeel.getRegion(c);
  76. }
  77. private int getComponentState(JComponent c) {
  78. return SynthLookAndFeel.getComponentState(c);
  79. }
  80. protected ComboPopup createPopup() {
  81. SynthComboPopup popup = new SynthComboPopup( comboBox );
  82. return popup;
  83. }
  84. protected ListCellRenderer createRenderer() {
  85. return new SynthComboBoxRenderer();
  86. }
  87. protected ComboBoxEditor createEditor() {
  88. return new SynthComboBoxEditor();
  89. }
  90. //
  91. // end UI Initialization
  92. //======================
  93. public void propertyChange(PropertyChangeEvent e) {
  94. if (SynthLookAndFeel.shouldUpdateStyle(e)) {
  95. updateStyle(comboBox);
  96. }
  97. }
  98. protected JButton createArrowButton() {
  99. SynthArrowButton button = new SynthArrowButton(SwingConstants.SOUTH);
  100. button.setName("ComboBox.arrowButton");
  101. return button;
  102. }
  103. //=================================
  104. // begin ComponentUI Implementation
  105. public void update(Graphics g, JComponent c) {
  106. SynthContext context = getContext(c);
  107. SynthLookAndFeel.update(context, g);
  108. context.getPainter().paintComboBoxBackground(context, g, 0, 0,
  109. c.getWidth(), c.getHeight());
  110. paint(context, g);
  111. context.dispose();
  112. }
  113. public void paint(Graphics g, JComponent c) {
  114. SynthContext context = getContext(c);
  115. paint(context, g);
  116. context.dispose();
  117. }
  118. protected void paint(SynthContext context, Graphics g) {
  119. hasFocus = comboBox.hasFocus();
  120. if ( !comboBox.isEditable() ) {
  121. Rectangle r = rectangleForCurrentValue();
  122. paintCurrentValue(g,r,hasFocus);
  123. }
  124. }
  125. public void paintBorder(SynthContext context, Graphics g, int x,
  126. int y, int w, int h) {
  127. context.getPainter().paintComboBoxBorder(context, g, x, y, w, h);
  128. }
  129. /**
  130. * Paints the currently selected item.
  131. */
  132. public void paintCurrentValue(Graphics g,Rectangle bounds,boolean hasFocus) {
  133. ListCellRenderer renderer = comboBox.getRenderer();
  134. Component c;
  135. if ( hasFocus && !isPopupVisible(comboBox) ) {
  136. c = renderer.getListCellRendererComponent( listBox,
  137. comboBox.getSelectedItem(),
  138. -1,
  139. false,
  140. false );
  141. }
  142. else {
  143. c = renderer.getListCellRendererComponent( listBox,
  144. comboBox.getSelectedItem(),
  145. -1,
  146. false,
  147. false );
  148. }
  149. // Fix for 4238829: should lay out the JPanel.
  150. boolean shouldValidate = false;
  151. if (c instanceof JPanel) {
  152. shouldValidate = true;
  153. }
  154. if (c instanceof UIResource) {
  155. c.setName("ComboBox.renderer");
  156. currentValuePane.paintComponent(g,c,comboBox,bounds.x,bounds.y,
  157. bounds.width,bounds.height, shouldValidate);
  158. }
  159. else {
  160. currentValuePane.paintComponent(g,c,comboBox,bounds.x,bounds.y,
  161. bounds.width,bounds.height, shouldValidate);
  162. }
  163. }
  164. /**
  165. * From BasicComboBoxRenderer v 1.18.
  166. */
  167. private class SynthComboBoxRenderer extends JLabel implements ListCellRenderer, UIResource {
  168. public SynthComboBoxRenderer() {
  169. super();
  170. setText(" ");
  171. }
  172. public String getName() {
  173. // As SynthComboBoxRenderer's are asked for a size BEFORE they
  174. // are parented getName is overriden to force the name to be
  175. // ComboBox.renderer if it isn't set. If we didn't do this the
  176. // wrong style could be used for size calculations.
  177. String name = super.getName();
  178. if (name == null) {
  179. return "ComboBox.renderer";
  180. }
  181. return name;
  182. }
  183. public Component getListCellRendererComponent(JList list, Object value,
  184. int index, boolean isSelected, boolean cellHasFocus) {
  185. setName("ComboBox.listRenderer");
  186. SynthLookAndFeel.resetSelectedUI();
  187. if (isSelected) {
  188. setBackground(list.getSelectionBackground());
  189. setForeground(list.getSelectionForeground());
  190. if (!useListColors) {
  191. SynthLookAndFeel.setSelectedUI(
  192. (SynthLabelUI)SynthLookAndFeel.getUIOfType(getUI(),
  193. SynthLabelUI.class), isSelected, cellHasFocus,
  194. list.isEnabled());
  195. }
  196. }
  197. else {
  198. setBackground(list.getBackground());
  199. setForeground(list.getForeground());
  200. }
  201. setFont(list.getFont());
  202. if (value instanceof Icon) {
  203. setIcon((Icon)value);
  204. setText("");
  205. }
  206. else {
  207. String text = (value == null) ? " " : value.toString();
  208. if ("".equals(text)) {
  209. text = " ";
  210. }
  211. setText(text);
  212. }
  213. return this;
  214. }
  215. public void paint(Graphics g) {
  216. super.paint(g);
  217. SynthLookAndFeel.resetSelectedUI();
  218. }
  219. }
  220. /**
  221. * From BasicCombBoxEditor v 1.24.
  222. */
  223. private static class SynthComboBoxEditor implements
  224. ComboBoxEditor, UIResource {
  225. protected JTextField editor;
  226. private Object oldValue;
  227. public SynthComboBoxEditor() {
  228. editor = new JTextField("",9);
  229. editor.setName("ComboBox.textField");
  230. }
  231. public Component getEditorComponent() {
  232. return editor;
  233. }
  234. /**
  235. * Sets the item that should be edited.
  236. *
  237. * @param anObject the displayed value of the editor
  238. */
  239. public void setItem(Object anObject) {
  240. String text;
  241. if ( anObject != null ) {
  242. text = anObject.toString();
  243. oldValue = anObject;
  244. } else {
  245. text = "";
  246. }
  247. // workaround for 4530952
  248. if (!text.equals(editor.getText())) {
  249. editor.setText(text);
  250. }
  251. }
  252. public Object getItem() {
  253. Object newValue = editor.getText();
  254. if (oldValue != null && !(oldValue instanceof String)) {
  255. // The original value is not a string. Should return the value in it's
  256. // original type.
  257. if (newValue.equals(oldValue.toString())) {
  258. return oldValue;
  259. } else {
  260. // Must take the value from the editor and get the value and cast it to the new type.
  261. Class cls = oldValue.getClass();
  262. try {
  263. Method method = cls.getMethod("valueOf", new Class[]{String.class});
  264. newValue = method.invoke(oldValue, new Object[] { editor.getText()});
  265. } catch (Exception ex) {
  266. // Fail silently and return the newValue (a String object)
  267. }
  268. }
  269. }
  270. return newValue;
  271. }
  272. public void selectAll() {
  273. editor.selectAll();
  274. editor.requestFocus();
  275. }
  276. public void addActionListener(ActionListener l) {
  277. editor.addActionListener(l);
  278. }
  279. public void removeActionListener(ActionListener l) {
  280. editor.removeActionListener(l);
  281. }
  282. }
  283. }