~ubuntu-branches/ubuntu/quantal/netbeans/quantal

« back to all changes in this revision

Viewing changes to openide/explorer/src/org/openide/explorer/propertysheet/RadioInplaceEditor.java

  • Committer: Bazaar Package Importer
  • Author(s): Marek Slama
  • Date: 2008-01-29 14:11:22 UTC
  • Revision ID: james.westby@ubuntu.com-20080129141122-fnzjbo11ntghxfu7
Tags: upstream-6.0.1
ImportĀ upstreamĀ versionĀ 6.0.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 
3
 *
 
4
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
 
5
 *
 
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]"
 
23
 *
 
24
 * Contributor(s):
 
25
 *
 
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.
 
29
 *
 
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.
 
40
 */
 
41
/*
 
42
* RadioInplaceEditor.java
 
43
*
 
44
* Created on 28 September 2003, 01:41
 
45
*/
 
46
package org.openide.explorer.propertysheet;
 
47
 
 
48
import org.openide.util.WeakSet;
 
49
 
 
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;
 
62
 
 
63
import java.beans.PropertyEditor;
 
64
 
 
65
import java.util.ArrayList;
 
66
import java.util.Iterator;
 
67
import java.util.List;
 
68
 
 
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;
 
76
 
 
77
 
 
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.
 
82
 *
 
83
 * @author  Tim Boudreau
 
84
 */
 
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;
 
95
 
 
96
    public RadioInplaceEditor(boolean tableUI) {
 
97
        setLayout(new AutoGridLayout(false));
 
98
        this.tableUI = tableUI;
 
99
        setOpaque(true);
 
100
    }
 
101
 
 
102
    public void clear() {
 
103
        editor = null;
 
104
        env = null;
 
105
        mdl = null;
 
106
        group = null;
 
107
 
 
108
        Component[] c = getComponents();
 
109
 
 
110
        for (int i = 0; i < c.length; i++) {
 
111
            if (c[i] instanceof JRadioButton) {
 
112
                ((JRadioButton) c[i]).removeActionListener(this);
 
113
            }
 
114
        }
 
115
 
 
116
        removeAll();
 
117
        setEnabled(true);
 
118
    }
 
119
 
 
120
    /** Overridden to avoid grabbing the AWT tree lock */
 
121
    public Dimension getPreferredSize() {
 
122
        if (getLayout() != null) {
 
123
            return getLayout().preferredLayoutSize(this);
 
124
        } else {
 
125
            return super.getPreferredSize();
 
126
        }
 
127
    }
 
128
 
 
129
    public void addNotify() {
 
130
        super.addNotify();
 
131
        isFirstEvent = true;
 
132
    }
 
133
 
 
134
    private InvRadioButton[] getButtons(int count) {
 
135
        InvRadioButton[] result = new InvRadioButton[count];
 
136
 
 
137
        Iterator<InvRadioButton> i = buttonCache.iterator();
 
138
        int idx = 0;
 
139
 
 
140
        while (i.hasNext() && (idx < count)) {
 
141
            result[idx] = i.next();
 
142
 
 
143
            if (result[idx] != null) {
 
144
                result[idx].setEnabled(true);
 
145
                result[idx].setSelected(false);
 
146
                idx++;
 
147
            }
 
148
        }
 
149
 
 
150
        for (; idx < count; idx++) {
 
151
            result[idx] = createButton();
 
152
            buttonCache.add(result[idx]);
 
153
        }
 
154
 
 
155
        return result;
 
156
    }
 
157
 
 
158
    public void setEnabled(boolean val) {
 
159
        //        System.err.println("RadioEditor.setEnabled " + val);
 
160
        super.setEnabled(val);
 
161
 
 
162
        Component[] c = getComponents();
 
163
 
 
164
        for (int i = 0; i < c.length; i++) {
 
165
            c[i].setEnabled(val);
 
166
        }
 
167
    }
 
168
 
 
169
    public void setBackground(Color col) {
 
170
        super.setBackground(col);
 
171
 
 
172
        Component[] c = getComponents();
 
173
 
 
174
        for (int i = 0; i < c.length; i++) {
 
175
            c[i].setBackground(col);
 
176
        }
 
177
    }
 
178
 
 
179
    public void setForeground(Color col) {
 
180
        super.setForeground(col);
 
181
 
 
182
        Component[] c = getComponents();
 
183
 
 
184
        for (int i = 0; i < c.length; i++) {
 
185
            c[i].setForeground(col);
 
186
        }
 
187
    }
 
188
 
 
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
 
192
     * button  */
 
193
    public void requestFocus() {
 
194
        Component[] c = getComponents();
 
195
 
 
196
        if (c.length > 0) {
 
197
            for (int i = 0; i < c.length; i++) {
 
198
                if (c[i] instanceof InvRadioButton && ((InvRadioButton) c[i]).isSelected()) {
 
199
                    c[i].requestFocus();
 
200
 
 
201
                    return;
 
202
                }
 
203
            }
 
204
 
 
205
            c[0].requestFocus();
 
206
        } else {
 
207
            super.requestFocus();
 
208
        }
 
209
    }
 
210
 
 
211
    public boolean requestFocusInWindow() {
 
212
        Component[] c = getComponents();
 
213
 
 
214
        for (int i = 0; i < c.length; i++) {
 
215
            if (c[i] instanceof InvRadioButton && ((InvRadioButton) c[i]).isSelected()) {
 
216
                return c[i].requestFocusInWindow();
 
217
            }
 
218
        }
 
219
 
 
220
        return super.requestFocusInWindow();
 
221
    }
 
222
 
 
223
    public void setUseTitle(boolean val) {
 
224
        if (useTitle != val) {
 
225
            useTitle = val;
 
226
 
 
227
            if (env != null) {
 
228
                setBorder(new TitledBorder(env.getFeatureDescriptor().getDisplayName()));
 
229
            }
 
230
        }
 
231
    }
 
232
 
 
233
    public void connect(PropertyEditor pe, PropertyEnv env) {
 
234
        if (!tableUI && (env != null) && useTitle) {
 
235
            setBorder(new TitledBorder(env.getFeatureDescriptor().getDisplayName()));
 
236
        } else {
 
237
            setBorder(null);
 
238
        }
 
239
 
 
240
        editor = pe;
 
241
 
 
242
        String[] tags = editor.getTags();
 
243
        group = new ButtonGroup();
 
244
 
 
245
        InvRadioButton[] buttons = getButtons(tags.length);
 
246
 
 
247
        if (env != null) {
 
248
            setEnabled(env.isEditable());
 
249
        }
 
250
 
 
251
        for (int i = 0; i < tags.length; i++) {
 
252
            InvRadioButton jr = buttons[i];
 
253
            configureButton(jr, tags[i]);
 
254
            add(jr);
 
255
        }
 
256
    }
 
257
 
 
258
    /** Renderer version overrides this to create a subclass that won't
 
259
     * fire changes */
 
260
    protected InvRadioButton createButton() {
 
261
        return new InvRadioButton();
 
262
    }
 
263
 
 
264
    /** Renderer version overrides this */
 
265
    protected void configureButton(InvRadioButton ire, String txt) {
 
266
        ire.addActionListener(this);
 
267
 
 
268
        if (editor.getTags().length == 1) {
 
269
            ire.setEnabled(false);
 
270
        } else {
 
271
            ire.setEnabled(isEnabled());
 
272
        }
 
273
 
 
274
        if (tableUI) {
 
275
            ire.setFocusable(false);
 
276
        } else {
 
277
            ire.setFocusable(true);
 
278
        }
 
279
 
 
280
        ire.setText(txt);
 
281
 
 
282
        if (txt.equals(editor.getAsText())) {
 
283
            ire.setSelected(true);
 
284
        } else {
 
285
            ire.setSelected(false);
 
286
        }
 
287
 
 
288
        ire.setFont(getFont());
 
289
        ire.setBackground(getBackground());
 
290
        ire.setForeground(getForeground());
 
291
        group.add(ire);
 
292
    }
 
293
 
 
294
    public JComponent getComponent() {
 
295
        return this;
 
296
    }
 
297
 
 
298
    public KeyStroke[] getKeyStrokes() {
 
299
        return null;
 
300
    }
 
301
 
 
302
    public PropertyEditor getPropertyEditor() {
 
303
        return editor;
 
304
    }
 
305
 
 
306
    public PropertyModel getPropertyModel() {
 
307
        return mdl;
 
308
    }
 
309
 
 
310
    public Object getValue() {
 
311
        Component[] c = getComponents();
 
312
 
 
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();
 
318
 
 
319
                    return result;
 
320
                }
 
321
            }
 
322
        }
 
323
 
 
324
        return null;
 
325
    }
 
326
 
 
327
    public void handleInitialInputEvent(InputEvent e) {
 
328
        System.err.println("HandleInitialInputEvent");
 
329
        getLayout().layoutContainer(this);
 
330
 
 
331
        if (e instanceof MouseEvent) {
 
332
            Point p = SwingUtilities.convertPoint((JComponent) e.getSource(), ((MouseEvent) e).getPoint(), this);
 
333
            Component c = getComponentAt(p);
 
334
 
 
335
            if (c instanceof JRadioButton) {
 
336
                ((JRadioButton) c).setSelected(true);
 
337
                c.requestFocus();
 
338
                fireActionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, InplaceEditor.COMMAND_SUCCESS));
 
339
            }
 
340
        } else {
 
341
            Component[] c = getComponents();
 
342
 
 
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();
 
347
                    }
 
348
                }
 
349
            }
 
350
        }
 
351
    }
 
352
 
 
353
    public boolean isKnownComponent(Component c) {
 
354
        return (c != null) && ((c == this) || c instanceof InvRadioButton);
 
355
    }
 
356
 
 
357
    public void reset() {
 
358
        setValue(editor.getAsText());
 
359
    }
 
360
 
 
361
    public void setPropertyModel(PropertyModel pm) {
 
362
        mdl = pm;
 
363
    }
 
364
 
 
365
    public void setValue(Object o) {
 
366
        Component[] c = getComponents();
 
367
 
 
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);
 
372
                } else {
 
373
                    //Necessary for renderer, its buttons don't fire changes
 
374
                    ((JRadioButton) c[i]).setSelected(false);
 
375
                }
 
376
            }
 
377
        }
 
378
    }
 
379
 
 
380
    public boolean supportsTextEntry() {
 
381
        return false;
 
382
    }
 
383
 
 
384
    public synchronized void addActionListener(java.awt.event.ActionListener listener) {
 
385
        if (actionListenerList == null) {
 
386
            actionListenerList = new java.util.ArrayList<ActionListener>();
 
387
        }
 
388
 
 
389
        actionListenerList.add(listener);
 
390
    }
 
391
 
 
392
    public synchronized void removeActionListener(java.awt.event.ActionListener listener) {
 
393
        if (actionListenerList != null) {
 
394
            actionListenerList.remove(listener);
 
395
        }
 
396
    }
 
397
 
 
398
    private void fireActionPerformed(final java.awt.event.ActionEvent event) {
 
399
        //        System.err.println("Radio editor firing action performed " + event.getActionCommand());
 
400
        java.util.List list;
 
401
 
 
402
        synchronized (this) {
 
403
            if (actionListenerList == null) {
 
404
                return;
 
405
            }
 
406
 
 
407
            list = (List) ((ArrayList) actionListenerList).clone();
 
408
        }
 
409
 
 
410
        final java.util.List theList = list;
 
411
 
 
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.
 
416
        if (tableUI) {
 
417
            SwingUtilities.invokeLater(
 
418
                new Runnable() {
 
419
                    public void run() {
 
420
                        for (int i = 0; i < theList.size(); i++) {
 
421
                            ((java.awt.event.ActionListener) theList.get(i)).actionPerformed(event);
 
422
                        }
 
423
                    }
 
424
                }
 
425
            );
 
426
        } else {
 
427
            for (int i = 0; i < list.size(); i++) {
 
428
                ((java.awt.event.ActionListener) theList.get(i)).actionPerformed(event);
 
429
            }
 
430
        }
 
431
    }
 
432
 
 
433
    public void actionPerformed(ActionEvent e) {
 
434
        ActionEvent ae = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, InplaceEditor.COMMAND_SUCCESS);
 
435
        fireActionPerformed(ae);
 
436
    }
 
437
 
 
438
    public void paint(Graphics g) {
 
439
        if (isShowing()) {
 
440
            super.paint(g);
 
441
        } else {
 
442
            getLayout().layoutContainer(this);
 
443
 
 
444
            Component[] c = getComponents();
 
445
            Color col = g.getColor();
 
446
 
 
447
            try {
 
448
                g.setColor(getBackground());
 
449
                g.fillRect(0, 0, getWidth(), getHeight());
 
450
 
 
451
                for (int i = 0; i < c.length; i++) {
 
452
                    Rectangle r = c[i].getBounds();
 
453
 
 
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);
 
456
 
 
457
                        try {
 
458
                            c[i].paint(g2);
 
459
                        } finally {
 
460
                            g2.dispose();
 
461
                        }
 
462
                    }
 
463
                }
 
464
 
 
465
                if (getBorder() != null) {
 
466
                    super.paintBorder(g);
 
467
                }
 
468
            } finally {
 
469
                g.setColor(col);
 
470
            }
 
471
        }
 
472
    }
 
473
 
 
474
    public void processMouseEvent(MouseEvent me) {
 
475
        if (isFirstEvent) {
 
476
            handleInitialInputEvent(me);
 
477
            isFirstEvent = false;
 
478
        } else {
 
479
            super.processMouseEvent(me);
 
480
        }
 
481
    }
 
482
 
 
483
    public Component getComponentAt(int x, int y) {
 
484
        getLayout().layoutContainer(this);
 
485
 
 
486
        Component result = super.getComponentAt(x, y);
 
487
        System.err.println("getComponentAt " + x + "," + y + " returning " + result.getName());
 
488
 
 
489
        return result;
 
490
    }
 
491
 
 
492
    /** A JRadioButton that can calculate its preferred size when it
 
493
     * has no parent */
 
494
    class InvRadioButton extends JRadioButton {
 
495
        public InvRadioButton() {
 
496
            super();
 
497
        }
 
498
 
 
499
        public String getName() {
 
500
            return "InvRadioButton - " + getText(); //NOI18N
 
501
        }
 
502
 
 
503
        public void processKeyEvent(java.awt.event.KeyEvent ke) {
 
504
            super.processKeyEvent(ke);
 
505
 
 
506
            if (
 
507
                ((ke.getKeyCode() == ke.VK_ENTER) || (ke.getKeyCode() == ke.VK_ESCAPE)) &&
 
508
                    (ke.getID() == ke.KEY_PRESSED)
 
509
            ) {
 
510
                RadioInplaceEditor.this.fireActionPerformed(
 
511
                    new ActionEvent(
 
512
                        this, ActionEvent.ACTION_PERFORMED,
 
513
                        (ke.getKeyCode() == ke.VK_ENTER) ? COMMAND_SUCCESS : COMMAND_FAILURE
 
514
                    )
 
515
                );
 
516
            }
 
517
        }
 
518
 
 
519
        public Dimension getPreferredSize() {
 
520
            int w = 0;
 
521
            int h = 0;
 
522
            Graphics g = PropUtils.getScratchGraphics(this);
 
523
            FontMetrics fm = g.getFontMetrics(getFont());
 
524
 
 
525
            if (getIcon() != null) {
 
526
                w = getIcon().getIconWidth();
 
527
                h = getIcon().getIconHeight();
 
528
            }
 
529
 
 
530
            if (getBorder() != null) {
 
531
                Insets ins = getBorder().getBorderInsets(this);
 
532
                w += (ins.left + ins.right);
 
533
                h += (ins.bottom + ins.top);
 
534
            }
 
535
 
 
536
            w += (fm.stringWidth(getText()) + 22);
 
537
            h = Math.max(fm.getHeight(), h) + 2;
 
538
 
 
539
            return new Dimension(w, h);
 
540
        }
 
541
    }
 
542
}