2
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
6
* The contents of this file are subject to the terms of either the GNU
7
* General Public License Version 2 only ("GPL") or the Common
8
* Development and Distribution License("CDDL") (collectively, the
9
* "License"). You may not use this file except in compliance with the
10
* License. You can obtain a copy of the License at
11
* http://www.netbeans.org/cddl-gplv2.html
12
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
* specific language governing permissions and limitations under the
14
* License. When distributing the software, include this License Header
15
* Notice in each file and include the License file at
16
* nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
17
* particular file as subject to the "Classpath" exception as provided
18
* by Sun in the GPL Version 2 section of the License file that
19
* accompanied this code. If applicable, add the following below the
20
* License Header, with the fields enclosed by brackets [] replaced by
21
* your own identifying information:
22
* "Portions Copyrighted [year] [name of copyright owner]"
26
* The Original Software is NetBeans. The Initial Developer of the Original
27
* Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
* Microsystems, Inc. All Rights Reserved.
30
* If you wish your version of this file to be governed by only the CDDL
31
* or only the GPL Version 2, indicate your decision by adding
32
* "[Contributor] elects to include this software in this distribution
33
* under the [CDDL or GPL Version 2] license." If you do not indicate a
34
* single choice of license, a recipient has the option to distribute
35
* your version of this file under either the CDDL, the GPL Version 2 or
36
* to extend the choice of license to its licensees as provided above.
37
* However, if you add GPL Version 2 code and therefore, elected the GPL
38
* Version 2 license, then the option applies only if the new code is
39
* made subject to such option by the copyright holder.
42
* RadioInplaceEditor.java
44
* Created on 28 September 2003, 01:41
46
package org.openide.explorer.propertysheet;
48
import org.openide.util.WeakSet;
50
import java.awt.Color;
51
import java.awt.Component;
52
import java.awt.Dimension;
53
import java.awt.FontMetrics;
54
import java.awt.Graphics;
55
import java.awt.Insets;
56
import java.awt.Point;
57
import java.awt.Rectangle;
58
import java.awt.event.ActionEvent;
59
import java.awt.event.ActionListener;
60
import java.awt.event.InputEvent;
61
import java.awt.event.MouseEvent;
63
import java.beans.PropertyEditor;
65
import java.util.ArrayList;
66
import java.util.Iterator;
67
import java.util.List;
69
import javax.swing.ButtonGroup;
70
import javax.swing.JComponent;
71
import javax.swing.JPanel;
72
import javax.swing.JRadioButton;
73
import javax.swing.KeyStroke;
74
import javax.swing.SwingUtilities;
75
import javax.swing.border.TitledBorder;
78
/** An inplace editor that represents the contents of a property editor's
79
* getTags() method as a set of radio buttons. For larger sets of choices
80
* it is preferable to use a combo box, but for situations where only 3 to 5
81
* options are available, this is preferable.
83
* @author Tim Boudreau
85
class RadioInplaceEditor extends JPanel implements InplaceEditor, ActionListener {
86
private transient List<ActionListener> actionListenerList;
87
protected transient PropertyEditor editor = null;
88
protected transient PropertyEnv env = null;
89
protected transient PropertyModel mdl = null;
90
protected transient ButtonGroup group = null;
91
private boolean tableUI = false;
92
boolean isFirstEvent = false;
93
private WeakSet<InvRadioButton> buttonCache = new WeakSet<InvRadioButton>();
94
private boolean useTitle = false;
96
public RadioInplaceEditor(boolean tableUI) {
97
setLayout(new AutoGridLayout(false));
98
this.tableUI = tableUI;
102
public void clear() {
108
Component[] c = getComponents();
110
for (int i = 0; i < c.length; i++) {
111
if (c[i] instanceof JRadioButton) {
112
((JRadioButton) c[i]).removeActionListener(this);
120
/** Overridden to avoid grabbing the AWT tree lock */
121
public Dimension getPreferredSize() {
122
if (getLayout() != null) {
123
return getLayout().preferredLayoutSize(this);
125
return super.getPreferredSize();
129
public void addNotify() {
134
private InvRadioButton[] getButtons(int count) {
135
InvRadioButton[] result = new InvRadioButton[count];
137
Iterator<InvRadioButton> i = buttonCache.iterator();
140
while (i.hasNext() && (idx < count)) {
141
result[idx] = i.next();
143
if (result[idx] != null) {
144
result[idx].setEnabled(true);
145
result[idx].setSelected(false);
150
for (; idx < count; idx++) {
151
result[idx] = createButton();
152
buttonCache.add(result[idx]);
158
public void setEnabled(boolean val) {
159
// System.err.println("RadioEditor.setEnabled " + val);
160
super.setEnabled(val);
162
Component[] c = getComponents();
164
for (int i = 0; i < c.length; i++) {
165
c[i].setEnabled(val);
169
public void setBackground(Color col) {
170
super.setBackground(col);
172
Component[] c = getComponents();
174
for (int i = 0; i < c.length; i++) {
175
c[i].setBackground(col);
179
public void setForeground(Color col) {
180
super.setForeground(col);
182
Component[] c = getComponents();
184
for (int i = 0; i < c.length; i++) {
185
c[i].setForeground(col);
189
/** In 1.4, panels can and will receive focus; if we define our own
190
* focus policy, we're responsible for all possible subcomponents.
191
* Therfore just proxy requestFocusInWindow for the selected radio
193
public void requestFocus() {
194
Component[] c = getComponents();
197
for (int i = 0; i < c.length; i++) {
198
if (c[i] instanceof InvRadioButton && ((InvRadioButton) c[i]).isSelected()) {
207
super.requestFocus();
211
public boolean requestFocusInWindow() {
212
Component[] c = getComponents();
214
for (int i = 0; i < c.length; i++) {
215
if (c[i] instanceof InvRadioButton && ((InvRadioButton) c[i]).isSelected()) {
216
return c[i].requestFocusInWindow();
220
return super.requestFocusInWindow();
223
public void setUseTitle(boolean val) {
224
if (useTitle != val) {
228
setBorder(new TitledBorder(env.getFeatureDescriptor().getDisplayName()));
233
public void connect(PropertyEditor pe, PropertyEnv env) {
234
if (!tableUI && (env != null) && useTitle) {
235
setBorder(new TitledBorder(env.getFeatureDescriptor().getDisplayName()));
242
String[] tags = editor.getTags();
243
group = new ButtonGroup();
245
InvRadioButton[] buttons = getButtons(tags.length);
248
setEnabled(env.isEditable());
251
for (int i = 0; i < tags.length; i++) {
252
InvRadioButton jr = buttons[i];
253
configureButton(jr, tags[i]);
258
/** Renderer version overrides this to create a subclass that won't
260
protected InvRadioButton createButton() {
261
return new InvRadioButton();
264
/** Renderer version overrides this */
265
protected void configureButton(InvRadioButton ire, String txt) {
266
ire.addActionListener(this);
268
if (editor.getTags().length == 1) {
269
ire.setEnabled(false);
271
ire.setEnabled(isEnabled());
275
ire.setFocusable(false);
277
ire.setFocusable(true);
282
if (txt.equals(editor.getAsText())) {
283
ire.setSelected(true);
285
ire.setSelected(false);
288
ire.setFont(getFont());
289
ire.setBackground(getBackground());
290
ire.setForeground(getForeground());
294
public JComponent getComponent() {
298
public KeyStroke[] getKeyStrokes() {
302
public PropertyEditor getPropertyEditor() {
306
public PropertyModel getPropertyModel() {
310
public Object getValue() {
311
Component[] c = getComponents();
313
// System.out.println("GetSelection is " + group.getSelection());
314
for (int i = 0; i < c.length; i++) {
315
if (c[i] instanceof JRadioButton) {
316
if (group.getSelection() == ((JRadioButton) c[i]).getModel()) {
317
String result = ((JRadioButton) c[i]).getText();
327
public void handleInitialInputEvent(InputEvent e) {
328
System.err.println("HandleInitialInputEvent");
329
getLayout().layoutContainer(this);
331
if (e instanceof MouseEvent) {
332
Point p = SwingUtilities.convertPoint((JComponent) e.getSource(), ((MouseEvent) e).getPoint(), this);
333
Component c = getComponentAt(p);
335
if (c instanceof JRadioButton) {
336
((JRadioButton) c).setSelected(true);
338
fireActionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, InplaceEditor.COMMAND_SUCCESS));
341
Component[] c = getComponents();
343
for (int i = 0; i < c.length; i++) {
344
if (c[i] instanceof JRadioButton) {
345
if (((JRadioButton) c[i]).isSelected()) {
346
c[i].requestFocusInWindow();
353
public boolean isKnownComponent(Component c) {
354
return (c != null) && ((c == this) || c instanceof InvRadioButton);
357
public void reset() {
358
setValue(editor.getAsText());
361
public void setPropertyModel(PropertyModel pm) {
365
public void setValue(Object o) {
366
Component[] c = getComponents();
368
for (int i = 0; i < c.length; i++) {
369
if (c[i] instanceof JRadioButton) {
370
if (((JRadioButton) c[i]).getText().equals(o)) {
371
((JRadioButton) c[i]).setSelected(true);
373
//Necessary for renderer, its buttons don't fire changes
374
((JRadioButton) c[i]).setSelected(false);
380
public boolean supportsTextEntry() {
384
public synchronized void addActionListener(java.awt.event.ActionListener listener) {
385
if (actionListenerList == null) {
386
actionListenerList = new java.util.ArrayList<ActionListener>();
389
actionListenerList.add(listener);
392
public synchronized void removeActionListener(java.awt.event.ActionListener listener) {
393
if (actionListenerList != null) {
394
actionListenerList.remove(listener);
398
private void fireActionPerformed(final java.awt.event.ActionEvent event) {
399
// System.err.println("Radio editor firing action performed " + event.getActionCommand());
402
synchronized (this) {
403
if (actionListenerList == null) {
407
list = (List) ((ArrayList) actionListenerList).clone();
410
final java.util.List theList = list;
412
//When used in a table, the typical case is that the editor is instantiated,
413
//processes its mouse event, fires an event and is immediately removed.
414
//Using invokeLater allows the table to repaint appropriately for selection,
415
//etc, reducing flicker.
417
SwingUtilities.invokeLater(
420
for (int i = 0; i < theList.size(); i++) {
421
((java.awt.event.ActionListener) theList.get(i)).actionPerformed(event);
427
for (int i = 0; i < list.size(); i++) {
428
((java.awt.event.ActionListener) theList.get(i)).actionPerformed(event);
433
public void actionPerformed(ActionEvent e) {
434
ActionEvent ae = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, InplaceEditor.COMMAND_SUCCESS);
435
fireActionPerformed(ae);
438
public void paint(Graphics g) {
442
getLayout().layoutContainer(this);
444
Component[] c = getComponents();
445
Color col = g.getColor();
448
g.setColor(getBackground());
449
g.fillRect(0, 0, getWidth(), getHeight());
451
for (int i = 0; i < c.length; i++) {
452
Rectangle r = c[i].getBounds();
454
if (g.hitClip(r.x, r.y, r.width, r.height)) {
455
Graphics g2 = g.create(r.x, r.y, r.width, r.height);
465
if (getBorder() != null) {
466
super.paintBorder(g);
474
public void processMouseEvent(MouseEvent me) {
476
handleInitialInputEvent(me);
477
isFirstEvent = false;
479
super.processMouseEvent(me);
483
public Component getComponentAt(int x, int y) {
484
getLayout().layoutContainer(this);
486
Component result = super.getComponentAt(x, y);
487
System.err.println("getComponentAt " + x + "," + y + " returning " + result.getName());
492
/** A JRadioButton that can calculate its preferred size when it
494
class InvRadioButton extends JRadioButton {
495
public InvRadioButton() {
499
public String getName() {
500
return "InvRadioButton - " + getText(); //NOI18N
503
public void processKeyEvent(java.awt.event.KeyEvent ke) {
504
super.processKeyEvent(ke);
507
((ke.getKeyCode() == ke.VK_ENTER) || (ke.getKeyCode() == ke.VK_ESCAPE)) &&
508
(ke.getID() == ke.KEY_PRESSED)
510
RadioInplaceEditor.this.fireActionPerformed(
512
this, ActionEvent.ACTION_PERFORMED,
513
(ke.getKeyCode() == ke.VK_ENTER) ? COMMAND_SUCCESS : COMMAND_FAILURE
519
public Dimension getPreferredSize() {
522
Graphics g = PropUtils.getScratchGraphics(this);
523
FontMetrics fm = g.getFontMetrics(getFont());
525
if (getIcon() != null) {
526
w = getIcon().getIconWidth();
527
h = getIcon().getIconHeight();
530
if (getBorder() != null) {
531
Insets ins = getBorder().getBorderInsets(this);
532
w += (ins.left + ins.right);
533
h += (ins.bottom + ins.top);
536
w += (fm.stringWidth(getText()) + 22);
537
h = Math.max(fm.getHeight(), h) + 2;
539
return new Dimension(w, h);