author | alexsch |
Fri, 16 Jan 2015 19:11:10 +0400 | |
changeset 28986 | 79f293b29d6a |
parent 28070 | 001f640e7016 |
child 30497 | e06f23de57f5 |
permissions | -rw-r--r-- |
12047 | 1 |
/* |
23649
f4f882f0056b
8035692: Fix serial lint warnings in mac-specific code
darcy
parents:
20470
diff
changeset
|
2 |
* Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. |
12047 | 3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 |
* |
|
5 |
* This code is free software; you can redistribute it and/or modify it |
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
|
7 |
* published by the Free Software Foundation. Oracle designates this |
|
8 |
* particular file as subject to the "Classpath" exception as provided |
|
9 |
* by Oracle in the LICENSE file that accompanied this code. |
|
10 |
* |
|
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
15 |
* accompanied this code). |
|
16 |
* |
|
17 |
* You should have received a copy of the GNU General Public License version |
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 |
* |
|
21 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
22 |
* or visit www.oracle.com if you need additional information or have any |
|
23 |
* questions. |
|
24 |
*/ |
|
25 |
||
26 |
package com.apple.laf; |
|
27 |
||
28 |
import java.awt.*; |
|
29 |
import java.awt.event.*; |
|
30 |
||
31 |
import javax.accessibility.*; |
|
32 |
import javax.swing.*; |
|
33 |
import javax.swing.border.Border; |
|
34 |
import javax.swing.event.*; |
|
35 |
import javax.swing.plaf.*; |
|
36 |
import javax.swing.plaf.basic.*; |
|
37 |
import com.apple.laf.ClientPropertyApplicator.Property; |
|
38 |
import apple.laf.JRSUIConstants.Size; |
|
39 |
||
40 |
import com.apple.laf.AquaUtilControlSize.Sizeable; |
|
41 |
import com.apple.laf.AquaUtils.RecyclableSingleton; |
|
42 |
||
43 |
// Inspired by MetalComboBoxUI, which also has a combined text-and-arrow button for noneditables |
|
44 |
public class AquaComboBoxUI extends BasicComboBoxUI implements Sizeable { |
|
45 |
static final String POPDOWN_CLIENT_PROPERTY_KEY = "JComboBox.isPopDown"; |
|
46 |
static final String ISSQUARE_CLIENT_PROPERTY_KEY = "JComboBox.isSquare"; |
|
47 |
||
48 |
public static ComponentUI createUI(final JComponent c) { |
|
49 |
return new AquaComboBoxUI(); |
|
50 |
} |
|
51 |
||
52 |
private boolean wasOpaque; |
|
53 |
public void installUI(final JComponent c) { |
|
54 |
super.installUI(c); |
|
55 |
||
56 |
// this doesn't work right now, because the JComboBox.init() method calls |
|
57 |
// .setOpaque(false) directly, and doesn't allow the LaF to decided. Bad Sun! |
|
58 |
LookAndFeel.installProperty(c, "opaque", Boolean.FALSE); |
|
59 |
||
60 |
wasOpaque = c.isOpaque(); |
|
61 |
c.setOpaque(false); |
|
62 |
} |
|
63 |
||
64 |
public void uninstallUI(final JComponent c) { |
|
65 |
c.setOpaque(wasOpaque); |
|
66 |
super.uninstallUI(c); |
|
67 |
} |
|
68 |
||
69 |
protected void installListeners() { |
|
70 |
super.installListeners(); |
|
71 |
AquaUtilControlSize.addSizePropertyListener(comboBox); |
|
72 |
} |
|
73 |
||
74 |
protected void uninstallListeners() { |
|
75 |
AquaUtilControlSize.removeSizePropertyListener(comboBox); |
|
76 |
super.uninstallListeners(); |
|
77 |
} |
|
78 |
||
79 |
protected void installComponents() { |
|
80 |
super.installComponents(); |
|
81 |
||
82 |
// client properties must be applied after the components have been installed, |
|
83 |
// because isSquare and isPopdown are applied to the installed button |
|
84 |
getApplicator().attachAndApplyClientProperties(comboBox); |
|
85 |
} |
|
86 |
||
87 |
protected void uninstallComponents() { |
|
88 |
getApplicator().removeFrom(comboBox); |
|
89 |
super.uninstallComponents(); |
|
90 |
} |
|
91 |
||
92 |
protected ItemListener createItemListener() { |
|
93 |
return new ItemListener() { |
|
94 |
long lastBlink = 0L; |
|
95 |
public void itemStateChanged(final ItemEvent e) { |
|
96 |
if (e.getStateChange() != ItemEvent.SELECTED) return; |
|
97 |
if (!popup.isVisible()) return; |
|
98 |
||
99 |
// sometimes, multiple selection changes can occur while the popup is up, |
|
100 |
// and blinking more than "once" (in a second) is not desirable |
|
101 |
final long now = System.currentTimeMillis(); |
|
102 |
if (now - 1000 < lastBlink) return; |
|
103 |
lastBlink = now; |
|
104 |
||
25762
c4a3548120c6
8044862: Fix raw and unchecked lint warnings in macosx specific code
henryjen
parents:
25105
diff
changeset
|
105 |
final JList<Object> itemList = popup.getList(); |
12047 | 106 |
final ListUI listUI = itemList.getUI(); |
107 |
if (!(listUI instanceof AquaListUI)) return; |
|
108 |
final AquaListUI aquaListUI = (AquaListUI)listUI; |
|
109 |
||
110 |
final int selectedIndex = comboBox.getSelectedIndex(); |
|
25762
c4a3548120c6
8044862: Fix raw and unchecked lint warnings in macosx specific code
henryjen
parents:
25105
diff
changeset
|
111 |
final ListModel<Object> dataModel = itemList.getModel(); |
12047 | 112 |
if (dataModel == null) return; |
113 |
||
114 |
final Object value = dataModel.getElementAt(selectedIndex); |
|
115 |
AquaUtils.blinkMenu(new AquaUtils.Selectable() { |
|
116 |
public void paintSelected(final boolean selected) { |
|
117 |
aquaListUI.repaintCell(value, selectedIndex, selected); |
|
118 |
} |
|
119 |
}); |
|
120 |
} |
|
121 |
}; |
|
122 |
} |
|
123 |
||
124 |
public void paint(final Graphics g, final JComponent c) { |
|
125 |
// this space intentionally left blank |
|
126 |
} |
|
127 |
||
25762
c4a3548120c6
8044862: Fix raw and unchecked lint warnings in macosx specific code
henryjen
parents:
25105
diff
changeset
|
128 |
protected ListCellRenderer<Object> createRenderer() { |
12047 | 129 |
return new AquaComboBoxRenderer(comboBox); |
130 |
} |
|
131 |
||
132 |
protected ComboPopup createPopup() { |
|
133 |
return new AquaComboBoxPopup(comboBox); |
|
134 |
} |
|
135 |
||
136 |
protected JButton createArrowButton() { |
|
137 |
return new AquaComboBoxButton(this, comboBox, currentValuePane, listBox); |
|
138 |
} |
|
139 |
||
140 |
protected ComboBoxEditor createEditor() { |
|
141 |
return new AquaComboBoxEditor(); |
|
142 |
} |
|
143 |
||
15992
e5287fba4c74
7184945: [macosx] NPE in AquaComboBoxUI since jdk7u6b17, jdk8b47
serb
parents:
13348
diff
changeset
|
144 |
final class AquaComboBoxEditor extends BasicComboBoxEditor |
e5287fba4c74
7184945: [macosx] NPE in AquaComboBoxUI since jdk7u6b17, jdk8b47
serb
parents:
13348
diff
changeset
|
145 |
implements UIResource, DocumentListener { |
e5287fba4c74
7184945: [macosx] NPE in AquaComboBoxUI since jdk7u6b17, jdk8b47
serb
parents:
13348
diff
changeset
|
146 |
|
e5287fba4c74
7184945: [macosx] NPE in AquaComboBoxUI since jdk7u6b17, jdk8b47
serb
parents:
13348
diff
changeset
|
147 |
AquaComboBoxEditor() { |
12047 | 148 |
super(); |
149 |
editor = new AquaCustomComboTextField(); |
|
150 |
editor.addFocusListener(this); |
|
151 |
editor.getDocument().addDocumentListener(this); |
|
152 |
} |
|
153 |
||
15992
e5287fba4c74
7184945: [macosx] NPE in AquaComboBoxUI since jdk7u6b17, jdk8b47
serb
parents:
13348
diff
changeset
|
154 |
@Override |
12047 | 155 |
public void focusGained(final FocusEvent e) { |
15992
e5287fba4c74
7184945: [macosx] NPE in AquaComboBoxUI since jdk7u6b17, jdk8b47
serb
parents:
13348
diff
changeset
|
156 |
if (arrowButton != null) { |
e5287fba4c74
7184945: [macosx] NPE in AquaComboBoxUI since jdk7u6b17, jdk8b47
serb
parents:
13348
diff
changeset
|
157 |
arrowButton.repaint(); |
e5287fba4c74
7184945: [macosx] NPE in AquaComboBoxUI since jdk7u6b17, jdk8b47
serb
parents:
13348
diff
changeset
|
158 |
} |
12047 | 159 |
} |
160 |
||
15992
e5287fba4c74
7184945: [macosx] NPE in AquaComboBoxUI since jdk7u6b17, jdk8b47
serb
parents:
13348
diff
changeset
|
161 |
@Override |
12047 | 162 |
public void focusLost(final FocusEvent e) { |
15992
e5287fba4c74
7184945: [macosx] NPE in AquaComboBoxUI since jdk7u6b17, jdk8b47
serb
parents:
13348
diff
changeset
|
163 |
if (arrowButton != null) { |
e5287fba4c74
7184945: [macosx] NPE in AquaComboBoxUI since jdk7u6b17, jdk8b47
serb
parents:
13348
diff
changeset
|
164 |
arrowButton.repaint(); |
e5287fba4c74
7184945: [macosx] NPE in AquaComboBoxUI since jdk7u6b17, jdk8b47
serb
parents:
13348
diff
changeset
|
165 |
} |
12047 | 166 |
} |
167 |
||
15992
e5287fba4c74
7184945: [macosx] NPE in AquaComboBoxUI since jdk7u6b17, jdk8b47
serb
parents:
13348
diff
changeset
|
168 |
@Override |
12047 | 169 |
public void changedUpdate(final DocumentEvent e) { |
170 |
editorTextChanged(); |
|
171 |
} |
|
172 |
||
15992
e5287fba4c74
7184945: [macosx] NPE in AquaComboBoxUI since jdk7u6b17, jdk8b47
serb
parents:
13348
diff
changeset
|
173 |
@Override |
12047 | 174 |
public void insertUpdate(final DocumentEvent e) { |
175 |
editorTextChanged(); |
|
176 |
} |
|
177 |
||
15992
e5287fba4c74
7184945: [macosx] NPE in AquaComboBoxUI since jdk7u6b17, jdk8b47
serb
parents:
13348
diff
changeset
|
178 |
@Override |
12047 | 179 |
public void removeUpdate(final DocumentEvent e) { |
180 |
editorTextChanged(); |
|
181 |
} |
|
182 |
||
15992
e5287fba4c74
7184945: [macosx] NPE in AquaComboBoxUI since jdk7u6b17, jdk8b47
serb
parents:
13348
diff
changeset
|
183 |
private void editorTextChanged() { |
12047 | 184 |
if (!popup.isVisible()) return; |
185 |
||
186 |
final Object text = editor.getText(); |
|
187 |
||
25762
c4a3548120c6
8044862: Fix raw and unchecked lint warnings in macosx specific code
henryjen
parents:
25105
diff
changeset
|
188 |
final ListModel<Object> model = listBox.getModel(); |
12047 | 189 |
final int items = model.getSize(); |
190 |
for (int i = 0; i < items; i++) { |
|
191 |
final Object element = model.getElementAt(i); |
|
192 |
if (element == null) continue; |
|
193 |
||
194 |
final String asString = element.toString(); |
|
195 |
if (asString == null || !asString.equals(text)) continue; |
|
196 |
||
197 |
popup.getList().setSelectedIndex(i); |
|
198 |
return; |
|
199 |
} |
|
200 |
||
201 |
popup.getList().clearSelection(); |
|
202 |
} |
|
203 |
} |
|
204 |
||
23649
f4f882f0056b
8035692: Fix serial lint warnings in mac-specific code
darcy
parents:
20470
diff
changeset
|
205 |
@SuppressWarnings("serial") // Superclass is not serializable across versions |
12047 | 206 |
class AquaCustomComboTextField extends JTextField { |
23649
f4f882f0056b
8035692: Fix serial lint warnings in mac-specific code
darcy
parents:
20470
diff
changeset
|
207 |
@SuppressWarnings("serial") // anonymous class |
12047 | 208 |
public AquaCustomComboTextField() { |
209 |
final InputMap inputMap = getInputMap(); |
|
210 |
inputMap.put(KeyStroke.getKeyStroke("DOWN"), highlightNextAction); |
|
211 |
inputMap.put(KeyStroke.getKeyStroke("KP_DOWN"), highlightNextAction); |
|
212 |
inputMap.put(KeyStroke.getKeyStroke("UP"), highlightPreviousAction); |
|
213 |
inputMap.put(KeyStroke.getKeyStroke("KP_UP"), highlightPreviousAction); |
|
214 |
||
215 |
inputMap.put(KeyStroke.getKeyStroke("HOME"), highlightFirstAction); |
|
216 |
inputMap.put(KeyStroke.getKeyStroke("END"), highlightLastAction); |
|
217 |
inputMap.put(KeyStroke.getKeyStroke("PAGE_UP"), highlightPageUpAction); |
|
218 |
inputMap.put(KeyStroke.getKeyStroke("PAGE_DOWN"), highlightPageDownAction); |
|
219 |
||
220 |
final Action action = getActionMap().get(JTextField.notifyAction); |
|
221 |
inputMap.put(KeyStroke.getKeyStroke("ENTER"), new AbstractAction() { |
|
222 |
public void actionPerformed(final ActionEvent e) { |
|
223 |
if (popup.isVisible()) { |
|
224 |
triggerSelectionEvent(comboBox, e); |
|
225 |
||
226 |
if (editor instanceof AquaCustomComboTextField) { |
|
227 |
((AquaCustomComboTextField)editor).selectAll(); |
|
228 |
} |
|
229 |
} else { |
|
230 |
action.actionPerformed(e); |
|
231 |
} |
|
232 |
} |
|
233 |
}); |
|
234 |
} |
|
235 |
||
236 |
// workaround for 4530952 |
|
237 |
public void setText(final String s) { |
|
238 |
if (getText().equals(s)) { |
|
239 |
return; |
|
240 |
} |
|
241 |
super.setText(s); |
|
242 |
} |
|
243 |
} |
|
244 |
||
245 |
/** |
|
246 |
* This listener hides the popup when the focus is lost. It also repaints |
|
247 |
* when focus is gained or lost. |
|
248 |
* |
|
249 |
* This override is necessary because the Basic L&F for the combo box is working |
|
250 |
* around a Solaris-only bug that we don't have on Mac OS X. So, remove the lightweight |
|
251 |
* popup check here. rdar://Problem/3518582 |
|
252 |
*/ |
|
253 |
protected FocusListener createFocusListener() { |
|
254 |
return new BasicComboBoxUI.FocusHandler() { |
|
255 |
public void focusLost(final FocusEvent e) { |
|
256 |
hasFocus = false; |
|
257 |
if (!e.isTemporary()) { |
|
258 |
setPopupVisible(comboBox, false); |
|
259 |
} |
|
260 |
comboBox.repaint(); |
|
261 |
||
262 |
// Notify assistive technologies that the combo box lost focus |
|
263 |
final AccessibleContext ac = ((Accessible)comboBox).getAccessibleContext(); |
|
264 |
if (ac != null) { |
|
265 |
ac.firePropertyChange(AccessibleContext.ACCESSIBLE_STATE_PROPERTY, AccessibleState.FOCUSED, null); |
|
266 |
} |
|
267 |
} |
|
268 |
}; |
|
269 |
} |
|
270 |
||
271 |
protected void installKeyboardActions() { |
|
272 |
super.installKeyboardActions(); |
|
273 |
||
13348
c08c50d1ddea
7124330: [macosx] javax.swing.JComboBox throws unexpected ClassCastException
rupashka
parents:
12047
diff
changeset
|
274 |
ActionMap actionMap = new ActionMapUIResource(); |
c08c50d1ddea
7124330: [macosx] javax.swing.JComboBox throws unexpected ClassCastException
rupashka
parents:
12047
diff
changeset
|
275 |
|
12047 | 276 |
actionMap.put("aquaSelectNext", highlightNextAction); |
277 |
actionMap.put("aquaSelectPrevious", highlightPreviousAction); |
|
28986 | 278 |
actionMap.put("enterPressed", triggerSelectionAction); |
12047 | 279 |
actionMap.put("aquaSpacePressed", toggleSelectionAction); |
280 |
||
281 |
actionMap.put("aquaSelectHome", highlightFirstAction); |
|
282 |
actionMap.put("aquaSelectEnd", highlightLastAction); |
|
283 |
actionMap.put("aquaSelectPageUp", highlightPageUpAction); |
|
284 |
actionMap.put("aquaSelectPageDown", highlightPageDownAction); |
|
13348
c08c50d1ddea
7124330: [macosx] javax.swing.JComboBox throws unexpected ClassCastException
rupashka
parents:
12047
diff
changeset
|
285 |
|
20470
555b46436610
8004050: [macosx] The 'ESC' key does not work with jdk8
leonidr
parents:
15992
diff
changeset
|
286 |
actionMap.put("aquaHidePopup", hideAction); |
555b46436610
8004050: [macosx] The 'ESC' key does not work with jdk8
leonidr
parents:
15992
diff
changeset
|
287 |
|
13348
c08c50d1ddea
7124330: [macosx] javax.swing.JComboBox throws unexpected ClassCastException
rupashka
parents:
12047
diff
changeset
|
288 |
SwingUtilities.replaceUIActionMap(comboBox, actionMap); |
12047 | 289 |
} |
290 |
||
23649
f4f882f0056b
8035692: Fix serial lint warnings in mac-specific code
darcy
parents:
20470
diff
changeset
|
291 |
@SuppressWarnings("serial") // Superclass is not serializable across versions |
20470
555b46436610
8004050: [macosx] The 'ESC' key does not work with jdk8
leonidr
parents:
15992
diff
changeset
|
292 |
private abstract class ComboBoxAction extends AbstractAction { |
12047 | 293 |
public void actionPerformed(final ActionEvent e) { |
20470
555b46436610
8004050: [macosx] The 'ESC' key does not work with jdk8
leonidr
parents:
15992
diff
changeset
|
294 |
if (!comboBox.isEnabled() || !comboBox.isShowing()) { |
555b46436610
8004050: [macosx] The 'ESC' key does not work with jdk8
leonidr
parents:
15992
diff
changeset
|
295 |
return; |
555b46436610
8004050: [macosx] The 'ESC' key does not work with jdk8
leonidr
parents:
15992
diff
changeset
|
296 |
} |
12047 | 297 |
|
298 |
if (comboBox.isPopupVisible()) { |
|
299 |
final AquaComboBoxUI ui = (AquaComboBoxUI)comboBox.getUI(); |
|
300 |
performComboBoxAction(ui); |
|
301 |
} else { |
|
302 |
comboBox.setPopupVisible(true); |
|
303 |
} |
|
304 |
} |
|
305 |
||
306 |
abstract void performComboBoxAction(final AquaComboBoxUI ui); |
|
307 |
} |
|
308 |
||
309 |
/** |
|
310 |
* Hilight _but do not select_ the next item in the list. |
|
311 |
*/ |
|
23649
f4f882f0056b
8035692: Fix serial lint warnings in mac-specific code
darcy
parents:
20470
diff
changeset
|
312 |
@SuppressWarnings("serial") // anonymous class |
20470
555b46436610
8004050: [macosx] The 'ESC' key does not work with jdk8
leonidr
parents:
15992
diff
changeset
|
313 |
private Action highlightNextAction = new ComboBoxAction() { |
12047 | 314 |
@Override |
315 |
public void performComboBoxAction(AquaComboBoxUI ui) { |
|
316 |
final int si = listBox.getSelectedIndex(); |
|
317 |
||
318 |
if (si < comboBox.getModel().getSize() - 1) { |
|
319 |
listBox.setSelectedIndex(si + 1); |
|
320 |
listBox.ensureIndexIsVisible(si + 1); |
|
321 |
} |
|
322 |
comboBox.repaint(); |
|
323 |
} |
|
324 |
}; |
|
325 |
||
326 |
/** |
|
327 |
* Hilight _but do not select_ the previous item in the list. |
|
328 |
*/ |
|
23649
f4f882f0056b
8035692: Fix serial lint warnings in mac-specific code
darcy
parents:
20470
diff
changeset
|
329 |
@SuppressWarnings("serial") // anonymous class |
20470
555b46436610
8004050: [macosx] The 'ESC' key does not work with jdk8
leonidr
parents:
15992
diff
changeset
|
330 |
private Action highlightPreviousAction = new ComboBoxAction() { |
12047 | 331 |
@Override |
332 |
void performComboBoxAction(final AquaComboBoxUI ui) { |
|
333 |
final int si = listBox.getSelectedIndex(); |
|
334 |
if (si > 0) { |
|
335 |
listBox.setSelectedIndex(si - 1); |
|
336 |
listBox.ensureIndexIsVisible(si - 1); |
|
337 |
} |
|
338 |
comboBox.repaint(); |
|
339 |
} |
|
340 |
}; |
|
341 |
||
23649
f4f882f0056b
8035692: Fix serial lint warnings in mac-specific code
darcy
parents:
20470
diff
changeset
|
342 |
@SuppressWarnings("serial") // anonymous class |
20470
555b46436610
8004050: [macosx] The 'ESC' key does not work with jdk8
leonidr
parents:
15992
diff
changeset
|
343 |
private Action highlightFirstAction = new ComboBoxAction() { |
12047 | 344 |
@Override |
345 |
void performComboBoxAction(final AquaComboBoxUI ui) { |
|
346 |
listBox.setSelectedIndex(0); |
|
347 |
listBox.ensureIndexIsVisible(0); |
|
348 |
} |
|
349 |
}; |
|
350 |
||
23649
f4f882f0056b
8035692: Fix serial lint warnings in mac-specific code
darcy
parents:
20470
diff
changeset
|
351 |
@SuppressWarnings("serial") // anonymous class |
20470
555b46436610
8004050: [macosx] The 'ESC' key does not work with jdk8
leonidr
parents:
15992
diff
changeset
|
352 |
private Action highlightLastAction = new ComboBoxAction() { |
12047 | 353 |
@Override |
354 |
void performComboBoxAction(final AquaComboBoxUI ui) { |
|
355 |
final int size = listBox.getModel().getSize(); |
|
356 |
listBox.setSelectedIndex(size - 1); |
|
357 |
listBox.ensureIndexIsVisible(size - 1); |
|
358 |
} |
|
359 |
}; |
|
360 |
||
23649
f4f882f0056b
8035692: Fix serial lint warnings in mac-specific code
darcy
parents:
20470
diff
changeset
|
361 |
@SuppressWarnings("serial") // anonymous class |
20470
555b46436610
8004050: [macosx] The 'ESC' key does not work with jdk8
leonidr
parents:
15992
diff
changeset
|
362 |
private Action highlightPageUpAction = new ComboBoxAction() { |
12047 | 363 |
@Override |
364 |
void performComboBoxAction(final AquaComboBoxUI ui) { |
|
365 |
final int current = listBox.getSelectedIndex(); |
|
366 |
final int first = listBox.getFirstVisibleIndex(); |
|
367 |
||
368 |
if (current != first) { |
|
369 |
listBox.setSelectedIndex(first); |
|
370 |
return; |
|
371 |
} |
|
372 |
||
373 |
final int page = listBox.getVisibleRect().height / listBox.getCellBounds(0, 0).height; |
|
374 |
int target = first - page; |
|
375 |
if (target < 0) target = 0; |
|
376 |
||
377 |
listBox.ensureIndexIsVisible(target); |
|
378 |
listBox.setSelectedIndex(target); |
|
379 |
} |
|
380 |
}; |
|
381 |
||
23649
f4f882f0056b
8035692: Fix serial lint warnings in mac-specific code
darcy
parents:
20470
diff
changeset
|
382 |
@SuppressWarnings("serial") // anonymous class |
20470
555b46436610
8004050: [macosx] The 'ESC' key does not work with jdk8
leonidr
parents:
15992
diff
changeset
|
383 |
private Action highlightPageDownAction = new ComboBoxAction() { |
12047 | 384 |
@Override |
385 |
void performComboBoxAction(final AquaComboBoxUI ui) { |
|
386 |
final int current = listBox.getSelectedIndex(); |
|
387 |
final int last = listBox.getLastVisibleIndex(); |
|
388 |
||
389 |
if (current != last) { |
|
390 |
listBox.setSelectedIndex(last); |
|
391 |
return; |
|
392 |
} |
|
393 |
||
394 |
final int page = listBox.getVisibleRect().height / listBox.getCellBounds(0, 0).height; |
|
395 |
final int end = listBox.getModel().getSize() - 1; |
|
396 |
int target = last + page; |
|
397 |
if (target > end) target = end; |
|
398 |
||
399 |
listBox.ensureIndexIsVisible(target); |
|
400 |
listBox.setSelectedIndex(target); |
|
401 |
} |
|
402 |
}; |
|
403 |
||
404 |
// For <rdar://problem/3759984> Java 1.4.2_5: Serializing Swing components not working |
|
405 |
// Inner classes were using a this reference and then trying to serialize the AquaComboBoxUI |
|
406 |
// We shouldn't do that. But we need to be able to get the popup from other classes, so we need |
|
407 |
// a public accessor. |
|
408 |
public ComboPopup getPopup() { |
|
409 |
return popup; |
|
410 |
} |
|
411 |
||
412 |
protected LayoutManager createLayoutManager() { |
|
413 |
return new AquaComboBoxLayoutManager(); |
|
414 |
} |
|
415 |
||
416 |
class AquaComboBoxLayoutManager extends BasicComboBoxUI.ComboBoxLayoutManager { |
|
417 |
public void layoutContainer(final Container parent) { |
|
418 |
if (arrowButton != null && !comboBox.isEditable()) { |
|
419 |
final Insets insets = comboBox.getInsets(); |
|
420 |
final int width = comboBox.getWidth(); |
|
421 |
final int height = comboBox.getHeight(); |
|
422 |
arrowButton.setBounds(insets.left, insets.top, width - (insets.left + insets.right), height - (insets.top + insets.bottom)); |
|
423 |
return; |
|
424 |
} |
|
425 |
||
25762
c4a3548120c6
8044862: Fix raw and unchecked lint warnings in macosx specific code
henryjen
parents:
25105
diff
changeset
|
426 |
final JComboBox<?> cb = (JComboBox<?>) parent; |
12047 | 427 |
final int width = cb.getWidth(); |
428 |
final int height = cb.getHeight(); |
|
429 |
||
430 |
final Insets insets = getInsets(); |
|
431 |
final int buttonHeight = height - (insets.top + insets.bottom); |
|
432 |
final int buttonWidth = 20; |
|
433 |
||
434 |
if (arrowButton != null) { |
|
435 |
arrowButton.setBounds(width - (insets.right + buttonWidth), insets.top, buttonWidth, buttonHeight); |
|
436 |
} |
|
437 |
||
438 |
if (editor != null) { |
|
439 |
final Rectangle editorRect = rectangleForCurrentValue(); |
|
440 |
editorRect.width += 4; |
|
441 |
editor.setBounds(editorRect); |
|
442 |
} |
|
443 |
} |
|
444 |
} |
|
445 |
||
446 |
// This is here because Sun can't use protected like they should! |
|
447 |
protected static final String IS_TABLE_CELL_EDITOR = "JComboBox.isTableCellEditor"; |
|
448 |
||
449 |
protected static boolean isTableCellEditor(final JComponent c) { |
|
450 |
return Boolean.TRUE.equals(c.getClientProperty(AquaComboBoxUI.IS_TABLE_CELL_EDITOR)); |
|
451 |
} |
|
452 |
||
25762
c4a3548120c6
8044862: Fix raw and unchecked lint warnings in macosx specific code
henryjen
parents:
25105
diff
changeset
|
453 |
protected static boolean isPopdown(final JComboBox<?> c) { |
12047 | 454 |
return c.isEditable() || Boolean.TRUE.equals(c.getClientProperty(AquaComboBoxUI.POPDOWN_CLIENT_PROPERTY_KEY)); |
455 |
} |
|
456 |
||
25762
c4a3548120c6
8044862: Fix raw and unchecked lint warnings in macosx specific code
henryjen
parents:
25105
diff
changeset
|
457 |
protected static void triggerSelectionEvent(final JComboBox<?> comboBox, final ActionEvent e) { |
12047 | 458 |
if (!comboBox.isEnabled()) return; |
459 |
||
460 |
final AquaComboBoxUI aquaUi = (AquaComboBoxUI)comboBox.getUI(); |
|
461 |
||
462 |
if (aquaUi.getPopup().getList().getSelectedIndex() < 0) { |
|
463 |
comboBox.setPopupVisible(false); |
|
464 |
} |
|
465 |
||
466 |
if (isTableCellEditor(comboBox)) { |
|
467 |
// Forces the selection of the list item if the combo box is in a JTable |
|
468 |
comboBox.setSelectedIndex(aquaUi.getPopup().getList().getSelectedIndex()); |
|
469 |
return; |
|
470 |
} |
|
471 |
||
472 |
if (comboBox.isPopupVisible()) { |
|
473 |
comboBox.setSelectedIndex(aquaUi.getPopup().getList().getSelectedIndex()); |
|
474 |
comboBox.setPopupVisible(false); |
|
475 |
return; |
|
476 |
} |
|
477 |
||
478 |
// Call the default button binding. |
|
479 |
// This is a pretty messy way of passing an event through to the root pane |
|
480 |
final JRootPane root = SwingUtilities.getRootPane(comboBox); |
|
481 |
if (root == null) return; |
|
482 |
||
483 |
final InputMap im = root.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); |
|
484 |
final ActionMap am = root.getActionMap(); |
|
485 |
if (im == null || am == null) return; |
|
486 |
||
487 |
final Object obj = im.get(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0)); |
|
488 |
if (obj == null) return; |
|
489 |
||
490 |
final Action action = am.get(obj); |
|
491 |
if (action == null) return; |
|
492 |
||
493 |
action.actionPerformed(new ActionEvent(root, e.getID(), e.getActionCommand(), e.getWhen(), e.getModifiers())); |
|
494 |
} |
|
495 |
||
496 |
// This is somewhat messy. The difference here from BasicComboBoxUI.EnterAction is that |
|
497 |
// arrow up or down does not automatically select the |
|
23649
f4f882f0056b
8035692: Fix serial lint warnings in mac-specific code
darcy
parents:
20470
diff
changeset
|
498 |
@SuppressWarnings("serial") // anonymous class |
28070
001f640e7016
8058193: [macosx] Potential incomplete fix for JDK-8031485
pchelko
parents:
25859
diff
changeset
|
499 |
private final Action triggerSelectionAction = new AbstractAction() { |
12047 | 500 |
public void actionPerformed(final ActionEvent e) { |
501 |
triggerSelectionEvent((JComboBox)e.getSource(), e); |
|
502 |
} |
|
28070
001f640e7016
8058193: [macosx] Potential incomplete fix for JDK-8031485
pchelko
parents:
25859
diff
changeset
|
503 |
|
001f640e7016
8058193: [macosx] Potential incomplete fix for JDK-8031485
pchelko
parents:
25859
diff
changeset
|
504 |
@Override |
001f640e7016
8058193: [macosx] Potential incomplete fix for JDK-8031485
pchelko
parents:
25859
diff
changeset
|
505 |
public boolean isEnabled() { |
001f640e7016
8058193: [macosx] Potential incomplete fix for JDK-8031485
pchelko
parents:
25859
diff
changeset
|
506 |
return comboBox.isPopupVisible() && super.isEnabled(); |
001f640e7016
8058193: [macosx] Potential incomplete fix for JDK-8031485
pchelko
parents:
25859
diff
changeset
|
507 |
} |
12047 | 508 |
}; |
509 |
||
23649
f4f882f0056b
8035692: Fix serial lint warnings in mac-specific code
darcy
parents:
20470
diff
changeset
|
510 |
@SuppressWarnings("serial") // anonymous class |
20470
555b46436610
8004050: [macosx] The 'ESC' key does not work with jdk8
leonidr
parents:
15992
diff
changeset
|
511 |
private static final Action toggleSelectionAction = new AbstractAction() { |
12047 | 512 |
public void actionPerformed(final ActionEvent e) { |
25762
c4a3548120c6
8044862: Fix raw and unchecked lint warnings in macosx specific code
henryjen
parents:
25105
diff
changeset
|
513 |
final JComboBox<?> comboBox = (JComboBox<?>) e.getSource(); |
12047 | 514 |
if (!comboBox.isEnabled()) return; |
515 |
if (comboBox.isEditable()) return; |
|
516 |
||
517 |
final AquaComboBoxUI aquaUi = (AquaComboBoxUI)comboBox.getUI(); |
|
518 |
||
519 |
if (comboBox.isPopupVisible()) { |
|
520 |
comboBox.setSelectedIndex(aquaUi.getPopup().getList().getSelectedIndex()); |
|
521 |
comboBox.setPopupVisible(false); |
|
522 |
return; |
|
523 |
} |
|
524 |
||
525 |
comboBox.setPopupVisible(true); |
|
526 |
} |
|
527 |
}; |
|
528 |
||
23649
f4f882f0056b
8035692: Fix serial lint warnings in mac-specific code
darcy
parents:
20470
diff
changeset
|
529 |
@SuppressWarnings("serial") // anonymous class |
25105
e71a28ff54c4
8031485: [macosx] Combo box consuming escape key events
pchelko
parents:
23649
diff
changeset
|
530 |
private final Action hideAction = new AbstractAction() { |
20470
555b46436610
8004050: [macosx] The 'ESC' key does not work with jdk8
leonidr
parents:
15992
diff
changeset
|
531 |
@Override |
555b46436610
8004050: [macosx] The 'ESC' key does not work with jdk8
leonidr
parents:
15992
diff
changeset
|
532 |
public void actionPerformed(final ActionEvent e) { |
25762
c4a3548120c6
8044862: Fix raw and unchecked lint warnings in macosx specific code
henryjen
parents:
25105
diff
changeset
|
533 |
final JComboBox<?> comboBox = (JComboBox<?>) e.getSource(); |
25105
e71a28ff54c4
8031485: [macosx] Combo box consuming escape key events
pchelko
parents:
23649
diff
changeset
|
534 |
comboBox.firePopupMenuCanceled(); |
e71a28ff54c4
8031485: [macosx] Combo box consuming escape key events
pchelko
parents:
23649
diff
changeset
|
535 |
comboBox.setPopupVisible(false); |
e71a28ff54c4
8031485: [macosx] Combo box consuming escape key events
pchelko
parents:
23649
diff
changeset
|
536 |
} |
20470
555b46436610
8004050: [macosx] The 'ESC' key does not work with jdk8
leonidr
parents:
15992
diff
changeset
|
537 |
|
25105
e71a28ff54c4
8031485: [macosx] Combo box consuming escape key events
pchelko
parents:
23649
diff
changeset
|
538 |
@Override |
e71a28ff54c4
8031485: [macosx] Combo box consuming escape key events
pchelko
parents:
23649
diff
changeset
|
539 |
public boolean isEnabled() { |
e71a28ff54c4
8031485: [macosx] Combo box consuming escape key events
pchelko
parents:
23649
diff
changeset
|
540 |
return comboBox.isPopupVisible() && super.isEnabled(); |
20470
555b46436610
8004050: [macosx] The 'ESC' key does not work with jdk8
leonidr
parents:
15992
diff
changeset
|
541 |
} |
555b46436610
8004050: [macosx] The 'ESC' key does not work with jdk8
leonidr
parents:
15992
diff
changeset
|
542 |
}; |
555b46436610
8004050: [macosx] The 'ESC' key does not work with jdk8
leonidr
parents:
15992
diff
changeset
|
543 |
|
12047 | 544 |
public void applySizeFor(final JComponent c, final Size size) { |
545 |
if (arrowButton == null) return; |
|
546 |
final Border border = arrowButton.getBorder(); |
|
547 |
if (!(border instanceof AquaButtonBorder)) return; |
|
548 |
final AquaButtonBorder aquaBorder = (AquaButtonBorder)border; |
|
549 |
arrowButton.setBorder(aquaBorder.deriveBorderForSize(size)); |
|
550 |
} |
|
551 |
||
552 |
public Dimension getMinimumSize(final JComponent c) { |
|
553 |
if (!isMinimumSizeDirty) { |
|
554 |
return new Dimension(cachedMinimumSize); |
|
555 |
} |
|
556 |
||
557 |
final boolean editable = comboBox.isEditable(); |
|
558 |
||
559 |
final Dimension size; |
|
560 |
if (!editable && arrowButton != null && arrowButton instanceof AquaComboBoxButton) { |
|
561 |
final AquaComboBoxButton button = (AquaComboBoxButton)arrowButton; |
|
562 |
final Insets buttonInsets = button.getInsets(); |
|
563 |
// Insets insets = comboBox.getInsets(); |
|
564 |
final Insets insets = new Insets(0, 5, 0, 25);//comboBox.getInsets(); |
|
565 |
||
566 |
size = getDisplaySize(); |
|
567 |
size.width += insets.left + insets.right; |
|
568 |
size.width += buttonInsets.left + buttonInsets.right; |
|
569 |
size.width += buttonInsets.right + 10; |
|
570 |
size.height += insets.top + insets.bottom; |
|
571 |
size.height += buttonInsets.top + buttonInsets.bottom; |
|
572 |
// Min height = Height of arrow button plus 2 pixels fuzz above plus 2 below. 23 + 2 + 2 |
|
573 |
size.height = Math.max(27, size.height); |
|
574 |
} else if (editable && arrowButton != null && editor != null) { |
|
575 |
size = super.getMinimumSize(c); |
|
576 |
final Insets margin = arrowButton.getMargin(); |
|
577 |
size.height += margin.top + margin.bottom; |
|
578 |
} else { |
|
579 |
size = super.getMinimumSize(c); |
|
580 |
} |
|
581 |
||
582 |
final Border border = c.getBorder(); |
|
583 |
if (border != null) { |
|
584 |
final Insets insets = border.getBorderInsets(c); |
|
585 |
size.height += insets.top + insets.bottom; |
|
586 |
size.width += insets.left + insets.right; |
|
587 |
} |
|
588 |
||
589 |
cachedMinimumSize.setSize(size.width, size.height); |
|
590 |
isMinimumSizeDirty = false; |
|
591 |
||
592 |
return new Dimension(cachedMinimumSize); |
|
593 |
} |
|
594 |
||
595 |
@SuppressWarnings("unchecked") |
|
25762
c4a3548120c6
8044862: Fix raw and unchecked lint warnings in macosx specific code
henryjen
parents:
25105
diff
changeset
|
596 |
static final RecyclableSingleton<ClientPropertyApplicator<JComboBox<?>, AquaComboBoxUI>> APPLICATOR = new |
c4a3548120c6
8044862: Fix raw and unchecked lint warnings in macosx specific code
henryjen
parents:
25105
diff
changeset
|
597 |
RecyclableSingleton<ClientPropertyApplicator<JComboBox<?>, AquaComboBoxUI>>() { |
12047 | 598 |
@Override |
25762
c4a3548120c6
8044862: Fix raw and unchecked lint warnings in macosx specific code
henryjen
parents:
25105
diff
changeset
|
599 |
protected ClientPropertyApplicator<JComboBox<?>, AquaComboBoxUI> getInstance() { |
c4a3548120c6
8044862: Fix raw and unchecked lint warnings in macosx specific code
henryjen
parents:
25105
diff
changeset
|
600 |
return new ClientPropertyApplicator<JComboBox<?>, AquaComboBoxUI>( |
12047 | 601 |
new Property<AquaComboBoxUI>(AquaFocusHandler.FRAME_ACTIVE_PROPERTY) { |
602 |
public void applyProperty(final AquaComboBoxUI target, final Object value) { |
|
603 |
if (Boolean.FALSE.equals(value)) { |
|
604 |
if (target.comboBox != null) target.comboBox.hidePopup(); |
|
605 |
} |
|
606 |
if (target.listBox != null) target.listBox.repaint(); |
|
607 |
} |
|
608 |
}, |
|
609 |
new Property<AquaComboBoxUI>("editable") { |
|
610 |
public void applyProperty(final AquaComboBoxUI target, final Object value) { |
|
611 |
if (target.comboBox == null) return; |
|
612 |
target.comboBox.repaint(); |
|
613 |
} |
|
614 |
}, |
|
615 |
new Property<AquaComboBoxUI>("background") { |
|
616 |
public void applyProperty(final AquaComboBoxUI target, final Object value) { |
|
617 |
final Color color = (Color)value; |
|
618 |
if (target.arrowButton != null) target.arrowButton.setBackground(color); |
|
619 |
if (target.listBox != null) target.listBox.setBackground(color); |
|
620 |
} |
|
621 |
}, |
|
622 |
new Property<AquaComboBoxUI>("foreground") { |
|
623 |
public void applyProperty(final AquaComboBoxUI target, final Object value) { |
|
624 |
final Color color = (Color)value; |
|
625 |
if (target.arrowButton != null) target.arrowButton.setForeground(color); |
|
626 |
if (target.listBox != null) target.listBox.setForeground(color); |
|
627 |
} |
|
628 |
}, |
|
629 |
new Property<AquaComboBoxUI>(POPDOWN_CLIENT_PROPERTY_KEY) { |
|
630 |
public void applyProperty(final AquaComboBoxUI target, final Object value) { |
|
631 |
if (!(target.arrowButton instanceof AquaComboBoxButton)) return; |
|
632 |
((AquaComboBoxButton)target.arrowButton).setIsPopDown(Boolean.TRUE.equals(value)); |
|
633 |
} |
|
634 |
}, |
|
635 |
new Property<AquaComboBoxUI>(ISSQUARE_CLIENT_PROPERTY_KEY) { |
|
636 |
public void applyProperty(final AquaComboBoxUI target, final Object value) { |
|
637 |
if (!(target.arrowButton instanceof AquaComboBoxButton)) return; |
|
638 |
((AquaComboBoxButton)target.arrowButton).setIsSquare(Boolean.TRUE.equals(value)); |
|
639 |
} |
|
640 |
} |
|
641 |
) { |
|
25762
c4a3548120c6
8044862: Fix raw and unchecked lint warnings in macosx specific code
henryjen
parents:
25105
diff
changeset
|
642 |
public AquaComboBoxUI convertJComponentToTarget(final JComboBox<?> combo) { |
12047 | 643 |
final ComboBoxUI comboUI = combo.getUI(); |
644 |
if (comboUI instanceof AquaComboBoxUI) return (AquaComboBoxUI)comboUI; |
|
645 |
return null; |
|
646 |
} |
|
647 |
}; |
|
648 |
} |
|
649 |
}; |
|
25762
c4a3548120c6
8044862: Fix raw and unchecked lint warnings in macosx specific code
henryjen
parents:
25105
diff
changeset
|
650 |
static ClientPropertyApplicator<JComboBox<?>, AquaComboBoxUI> getApplicator() { |
12047 | 651 |
return APPLICATOR.get(); |
652 |
} |
|
653 |
} |