KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openide > explorer > propertysheet > EditorPropertyDisplayer


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19 /*
20  * EditorPropertyDisplayer_java
21  *
22  * Created on 18 October 2003, 16:36
23  */

24 package org.openide.explorer.propertysheet;
25
26 import org.openide.nodes.Node.Property;
27 import org.openide.util.Utilities;
28
29 import java.awt.Color JavaDoc;
30 import java.awt.Component JavaDoc;
31 import java.awt.Dimension JavaDoc;
32 import java.awt.EventQueue JavaDoc;
33 import java.awt.Image JavaDoc;
34 import java.awt.KeyboardFocusManager JavaDoc;
35 import java.awt.event.FocusEvent JavaDoc;
36 import java.awt.event.KeyEvent JavaDoc;
37
38 import java.beans.FeatureDescriptor JavaDoc;
39 import java.beans.PropertyEditor JavaDoc;
40
41 import java.lang.ref.WeakReference JavaDoc;
42
43 import javax.swing.*;
44
45
46 /** An implementation of PropertyDisplayer_Inline which replicates the inline
47  * editor mode of PropertyPanel. This class is a base class which is simply
48  * responsible for finding and embedding the correct inline editor - it contains
49  * no code for actually updating the value or anything such. That code is in
50  * EditablePropertyDisplayer, to improve readability and maintainability.
51  *
52  * @author Tim Boudreau
53  */

54 class EditorPropertyDisplayer extends JComponent implements PropertyDisplayer_Inline {
55     private Property prop = null;
56     private InplaceEditor inplace = null;
57     private JComponent inner = null;
58     private int radioButtonMax = 0;
59     private boolean showCustomEditorButton = true;
60     private boolean tableUI = false;
61     private boolean useLabels = true;
62     private PropertyEnv env = null;
63     private boolean radioBoolean = false;
64     protected WeakReference JavaDoc<PropertyModel> modelRef = null;
65     protected boolean inReplaceInner = false;
66     private InplaceEditorFactory factory1 = null;
67     private InplaceEditorFactory factory2 = null;
68     private ReusablePropertyEnv reusableEnv = new ReusablePropertyEnv(); //XXX supply from PP?
69

70     /** Creates a new instance of EditorPropertyDisplayer */
71     public EditorPropertyDisplayer(Property p) {
72         this(p, null);
73     }
74
75     EditorPropertyDisplayer(Property p, PropertyModel mdl) {
76         if (p == null) {
77             throw new NullPointerException JavaDoc("Property may not be null"); //NOI18N
78
}
79
80         this.prop = p;
81
82         if (mdl != null) {
83             modelRef = new WeakReference JavaDoc<PropertyModel>(mdl);
84         }
85     }
86
87     public void addNotify() {
88         try {
89             if (inner == null) {
90                 replaceInner();
91             }
92         } finally {
93             super.addNotify();
94         }
95     }
96
97     protected void processFocusEvent(FocusEvent JavaDoc fe) {
98         super.processFocusEvent(fe);
99
100         if ((fe.getID() == FocusEvent.FOCUS_GAINED) && (inner != null)) {
101             inner.requestFocus();
102         }
103     }
104
105     public void removeNotify() {
106         super.removeNotify();
107         setInplaceEditor(null);
108         reusableEnv.clear();
109     }
110
111     public final Component JavaDoc getComponent() {
112         return this;
113     }
114
115     public final Property getProperty() {
116         return prop;
117     }
118
119     public final int getRadioButtonMax() {
120         return radioButtonMax;
121     }
122
123     public final boolean isShowCustomEditorButton() {
124         boolean result = showCustomEditorButton;
125
126         if (getProperty() != null) {
127             Boolean JavaDoc explicit = (Boolean JavaDoc) getProperty().getValue("suppressCustomEditor"); //NOI18N
128

129             if (explicit != null) {
130                 result = !explicit.booleanValue();
131             }
132         }
133
134         return result;
135     }
136
137     public final boolean isTableUI() {
138         return tableUI;
139     }
140
141     public final void refresh() {
142         if (isDisplayable()) {
143             replaceInner();
144         }
145     }
146
147     public final boolean isUseLabels() {
148         return useLabels;
149     }
150
151     public final void setRadioButtonMax(int max) {
152         if (max != radioButtonMax) {
153             int old = radioButtonMax;
154             boolean needChange = false;
155
156             if (inplace != null) {
157                 InplaceEditor innermost = PropUtils.findInnermostInplaceEditor(inplace);
158
159                 if (innermost instanceof JComboBox || innermost instanceof RadioInplaceEditor) {
160                     PropertyEditor JavaDoc ped = innermost.getPropertyEditor();
161                     int tagCount = (ped.getTags() == null) ? (-1) : ped.getTags().length;
162                     needChange = (old <= tagCount) != (max <= tagCount);
163                 }
164             }
165
166             radioButtonMax = max;
167
168             if (needChange && (inner != null)) {
169                 replaceInner();
170                 firePropertyChange("preferredSize", null, null); //NOI18N
171
}
172         }
173     }
174
175     public final void setShowCustomEditorButton(boolean val) {
176         //If the property descriptor explicitly says it does not
177
//want a custom editor button, this overrides anything set on
178
//the PropertyPanel.
179
if (getProperty() != null) {
180             Property p = getProperty();
181             Boolean JavaDoc explicit = (Boolean JavaDoc) p.getValue("suppressCustomEditor"); //NOI18N
182

183             if (explicit != null) {
184                 val = explicit.booleanValue();
185                 System.err.println("Found explicit value: " + val);
186             }
187         }
188
189         if (showCustomEditorButton != val) {
190             showCustomEditorButton = val;
191             replaceInner();
192         }
193     }
194
195     public final void setTableUI(boolean val) {
196         if (val != tableUI) {
197             tableUI = val;
198             replaceInner();
199         }
200     }
201
202     public final void setUseLabels(boolean useLabels) {
203         if (useLabels != this.useLabels) {
204             boolean needChange = false;
205
206             if (isShowing()) {
207                 InplaceEditor innermost = PropUtils.findInnermostInplaceEditor(inplace);
208
209                 needChange = (innermost instanceof RadioInplaceEditor || innermost instanceof JCheckBox);
210             }
211
212             this.useLabels = useLabels;
213
214             if (needChange && (inner != null)) {
215                 replaceInner();
216             }
217         }
218     }
219
220     public final void requestFocus() {
221         if (inner != null) {
222             inner.requestFocus();
223         } else {
224             super.requestFocus();
225         }
226     }
227
228     public final Dimension JavaDoc getPreferredSize() {
229         Dimension JavaDoc result;
230
231         if (inner == null) {
232             //Use the renderer infrastructure to do it if we're not initialized
233
result = new RendererPropertyDisplayer(getProperty()).getRenderer(this).getPreferredSize();
234         } else {
235             result = inner.getPreferredSize();
236         }
237
238         return result;
239     }
240
241     public final boolean requestFocusInWindow() {
242         boolean result;
243
244         if (inner != null) {
245             result = inner.requestFocusInWindow();
246         } else {
247             result = super.requestFocusInWindow();
248         }
249
250         return result;
251     }
252
253     private final void installInner(JComponent c) {
254         synchronized (getTreeLock()) {
255             if (inner != null) {
256                 remove(inner);
257             }
258
259             inner = c;
260
261             if (inner != null) {
262                 c.setBounds(0, 0, getWidth(), getHeight());
263                 add(c);
264             }
265         }
266     }
267
268     protected final void replaceInner() {
269         inReplaceInner = true;
270
271         try {
272             Component JavaDoc focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getPermanentFocusOwner();
273             boolean hadFocus = isEnabled() &&
274                 ((focusOwner == this) || isAncestorOf(focusOwner) ||
275                 ((getInplaceEditor() != null) && getInplaceEditor().isKnownComponent(focusOwner)));
276
277             //Figure out if a combo popup was open, so we can re-open it.
278
//If we're processing a mouse event, close it because that's
279
//the normal behavior of a popup. We want arrow keyboard events
280
//to not trigger closing of the popup if they caused a change
281
//to a value that is marked as invalid
282
boolean wasComboPopup = hadFocus && focusOwner instanceof JComboBox &&
283                 ((JComboBox) focusOwner).isPopupVisible() &&
284                 (EventQueue.getCurrentEvent() instanceof KeyEvent JavaDoc &&
285                 ((((KeyEvent JavaDoc) EventQueue.getCurrentEvent()).getKeyCode() == KeyEvent.VK_UP) ||
286                 (((KeyEvent JavaDoc) EventQueue.getCurrentEvent()).getKeyCode() == KeyEvent.VK_DOWN)));
287
288             // System.err.println("REPLACE INNER - " + prop.getDisplayName() + " focus:" + hadFocus);
289
if (hadFocus) {
290                 //We don't want focus to jump to another component and back
291
KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner();
292             }
293
294             setInplaceEditor(createInplaceEditor());
295
296             if (hadFocus) {
297                 requestFocus();
298
299                 //At this point the focus owner is still null, the event is queued -
300
if (wasComboPopup) {
301                     //We have to let the request focus on the event queue get
302
//processed before this can be done, or the component will
303
//not yet be laid out and the popup will be 1 pixel wide
304
SwingUtilities.invokeLater(
305                         new Runnable JavaDoc() {
306                             public void run() {
307                                 InplaceEditor ied = getInplaceEditor();
308                                 ied = PropUtils.findInnermostInplaceEditor(ied);
309
310                                 JComponent c = ied.getComponent();
311
312                                 if (c instanceof JComboBox && c.isShowing()) {
313                                     ((JComboBox) c).showPopup();
314                                 }
315                             }
316                         }
317                     );
318                 }
319             }
320
321             revalidate();
322             repaint();
323         } catch (Exception JavaDoc e) {
324             e.printStackTrace();
325         } finally {
326             inReplaceInner = false;
327         }
328     }
329
330     protected final JComponent getInner() {
331         return inner;
332     }
333
334     protected void setInplaceEditor(InplaceEditor ed) {
335         if (inplace != ed) {
336             if (inplace != null) {
337                 inplace.clear();
338             }
339
340             inplace = ed;
341
342             if (ed == null) {
343                 installInner(null);
344             } else {
345                 JComponent comp = inplace.getComponent();
346                 prepareComponent(inplace);
347                 installInner(comp);
348             }
349         }
350     }
351
352     public void setEnabled(boolean b) {
353         if (inner != null) {
354             inner.setEnabled(b);
355         }
356
357         super.setEnabled(b);
358     }
359
360     public void setBackground(Color JavaDoc c) {
361         super.setBackground(c);
362
363         if (inner != null) {
364             if ((inplace != null) && inplace.supportsTextEntry()) {
365                 inner.setBackground(PropUtils.getTextFieldBackground());
366             } else {
367                 inner.setBackground(c);
368             }
369         }
370     }
371
372     public void setForeground(Color JavaDoc c) {
373         super.setForeground(c);
374
375         if (inner != null) {
376             if ((inplace != null) && inplace.supportsTextEntry()) {
377                 inner.setForeground(PropUtils.getTextFieldForeground());
378             } else {
379                 inner.setForeground(c);
380             }
381         }
382     }
383
384     protected void prepareComponent(InplaceEditor inplace) {
385         InplaceEditor innermost = PropUtils.findInnermostInplaceEditor(inplace);
386         JComponent comp = innermost.getComponent();
387
388         if (!isTableUI() && inplace.supportsTextEntry()) {
389             comp.setBackground(PropUtils.getTextFieldBackground());
390             comp.setForeground(PropUtils.getTextFieldForeground());
391         } else {
392             comp.setBackground(getBackground());
393
394             if (!isEnabled() || !prop.canWrite()) {
395                 comp.setForeground(UIManager.getColor("textInactiveText"));
396             } else {
397                 comp.setForeground(getForeground());
398             }
399         }
400
401         if( comp instanceof ComboInplaceEditor )
402             comp.setEnabled( isEnabled() && getPropertyEnv().isEditable() );
403         else
404             comp.setEnabled(isEnabled() && PropUtils.checkEnabled(this, inplace.getPropertyEditor(), getPropertyEnv()));
405     }
406
407     @SuppressWarnings JavaDoc("deprecation")
408     public void reshape(int x, int y, int w, int h) {
409         if (inner != null) {
410             inner.setBounds(0, 0, w, h);
411         }
412
413         super.reshape(x, y, w, h);
414     }
415
416     protected void setPropertyEnv(PropertyEnv env) {
417         this.env = env;
418     }
419
420     public final PropertyEnv getPropertyEnv() {
421         return env;
422     }
423
424     protected final InplaceEditor getInplaceEditor() {
425         return inplace;
426     }
427
428     protected void configureButtonPanel(ButtonPanel bp) {
429     }
430
431     /** Basically some hacks to acquire the underlying property descriptor in
432      * the case of a wrapper. This is here because some property editors will
433      * cast the result of PropertyEnv.getFeatureDescriptor() as a specific
434      * implementation type, so even if we're wrapping a property model, we
435      * still need to make sure we're returning the class they expect. */

436     static final FeatureDescriptor JavaDoc findFeatureDescriptor(PropertyDisplayer pd) {
437         if (pd instanceof EditorPropertyDisplayer) {
438             //Issue 38004, more gunk to ensure we get the right feature
439
//descriptor
440
EditorPropertyDisplayer epd = (EditorPropertyDisplayer) pd;
441
442             if (epd.modelRef != null) {
443                 PropertyModel pm = epd.modelRef.get();
444
445                 if (pm instanceof ExPropertyModel) {
446                     FeatureDescriptor JavaDoc fd = ((ExPropertyModel) pm).getFeatureDescriptor();
447
448                     if (fd != null) {
449                         return fd;
450                     }
451                 }
452             }
453         }
454
455         Property p = pd.getProperty();
456
457         if (p instanceof ModelProperty) {
458             return ((ModelProperty) p).getFeatureDescriptor();
459         } else if (p instanceof ModelProperty.DPMWrapper) {
460             return ((ModelProperty.DPMWrapper) p).getFeatureDescriptor();
461         } else {
462             return p;
463         }
464     }
465
466     private InplaceEditor createInplaceEditor() {
467         PropertyEnv env = new PropertyEnv();
468         env.setFeatureDescriptor(findFeatureDescriptor(this));
469
470         InplaceEditor result;
471
472         //Get the real inplace editor
473
InplaceEditor innermost = result = factory(this).getInplaceEditor(getProperty(), env, true);
474
475         // System.err.println(" CREATE INPLACE EDITOR - INNERMOST IS " + innermost);
476
//See if it should be embedded in an instance of ButtonPanel to show
477
//the custom editor button
478
if (isShowCustomEditorButton() && innermost.getPropertyEditor().supportsCustomEditor()) {
479             ButtonPanel bp = new ButtonPanel();
480             bp.setInplaceEditor(innermost);
481
482             // System.err.println(" wrapping in a buttonpanel");
483
configureButtonPanel(bp);
484             result = bp;
485         }
486
487         Icon ic = null;
488
489         //See if there's an icon to display, either invalid state or
490
//a property-specified icon
491
if (env.getState() == env.STATE_INVALID) {
492             ic = new ImageIcon(Utilities.loadImage("org/openide/resources/propertysheet/invalid.gif")); //NOI18N
493
} else if (getProperty().getValue("valueIcon") != null) { //NOI18N
494

495             Object JavaDoc o = getProperty().getValue("valueIcon"); //NOI18N
496

497             if (o instanceof Image JavaDoc) {
498                 ic = new ImageIcon((Image JavaDoc) o);
499             } else {
500                 ic = (Icon) o;
501             }
502         }
503
504         //If we have an icon, use an IconPanel to display it
505
if (ic != null) {
506             IconPanel iconPanel = new IconPanel();
507             iconPanel.setIcon(ic);
508             iconPanel.setInplaceEditor(result);
509
510             // System.err.println(" wrapping in an IconPanel");
511
result = iconPanel;
512         }
513
514         setPropertyEnv(env);
515
516         return result;
517     }
518
519     private InplaceEditorFactory factory(PropertyDisplayer_Inline inline) {
520         InplaceEditorFactory result;
521
522         if (inline.isTableUI()) {
523             if (factory1 == null) {
524                 factory1 = new InplaceEditorFactory(inline.isTableUI(), inline.getReusablePropertyEnv());
525             }
526
527             result = factory1;
528         } else {
529             if (factory2 == null) {
530                 factory2 = new InplaceEditorFactory(inline.isTableUI(), inline.getReusablePropertyEnv());
531             }
532
533             result = factory2;
534         }
535
536         result.setUseRadioBoolean(inline.isRadioBoolean());
537         result.setRadioButtonMax(inline.getRadioButtonMax());
538         result.setUseLabels(inline.isUseLabels());
539
540         return result;
541     }
542
543     public boolean isTitleDisplayed() {
544         if (isUseLabels()) {
545             InplaceEditor inp = null;
546
547             if (inplace != null) {
548                 inp = inplace;
549             } else {
550                 inp = createInplaceEditor();
551             }
552
553             InplaceEditor most = PropUtils.findInnermostInplaceEditor(inp);
554
555             return (most instanceof RadioInplaceEditor || most instanceof CheckboxInplaceEditor);
556         }
557
558         return false;
559     }
560
561     public boolean isRadioBoolean() {
562         return radioBoolean;
563     }
564
565     public void setRadioBoolean(boolean b) {
566         radioBoolean = b;
567     }
568
569     public ReusablePropertyEnv getReusablePropertyEnv() {
570         return reusableEnv;
571     }
572
573     static final Object JavaDoc[] findBeans(PropertyDisplayer pd) {
574         Object JavaDoc[] result = null;
575
576         if (pd instanceof EditorPropertyDisplayer) {
577             //Issue 38132, fiendish evil to support PropertyEnv.getBeans()
578
EditorPropertyDisplayer epd = (EditorPropertyDisplayer) pd;
579
580             if (epd.modelRef != null) {
581                 PropertyModel pm = epd.modelRef.get();
582
583                 if (pm instanceof ExPropertyModel) {
584                     result = ((ExPropertyModel) pm).getBeans();
585                 }
586             }
587         }
588
589         if (result == null) {
590             Property p = pd.getProperty();
591
592             if (p instanceof ModelProperty) {
593                 result = ((ModelProperty) p).getBeans();
594             } else if (p instanceof ModelProperty.DPMWrapper) {
595                 result = ((ModelProperty.DPMWrapper) p).getBeans();
596             } else {
597                 if (
598                     pd instanceof EditorPropertyDisplayer &&
599                         ((EditorPropertyDisplayer) pd).getParent() instanceof PropertyPanel
600                 ) {
601                     result = ((PropertyPanel) ((EditorPropertyDisplayer) pd).getParent()).getBeans();
602                 } else if (
603                     pd instanceof RendererPropertyDisplayer &&
604                         ((RendererPropertyDisplayer) pd).getParent() instanceof PropertyPanel
605                 ) {
606                     result = ((PropertyPanel) ((RendererPropertyDisplayer) pd).getParent()).getBeans();
607                 }
608             }
609         }
610
611         return result;
612     }
613 }
614
Popular Tags