KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > form > RADComponentNode


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 package org.netbeans.modules.form;
21
22 import java.awt.*;
23 import java.awt.datatransfer.*;
24 import java.text.MessageFormat JavaDoc;
25 import java.util.*;
26 import java.beans.*;
27 import java.security.*;
28 import javax.swing.Action JavaDoc;
29
30 import org.openide.ErrorManager;
31 import org.openide.actions.*;
32 import org.openide.cookies.*;
33 import org.openide.loaders.*;
34 import org.openide.nodes.*;
35 import org.openide.util.*;
36 import org.openide.util.actions.SystemAction;
37 import org.openide.util.datatransfer.NewType;
38 import org.openide.explorer.propertysheet.editors.NodeCustomizer;
39
40 import org.netbeans.modules.form.actions.*;
41 import org.netbeans.modules.form.layoutsupport.*;
42 import org.netbeans.modules.form.project.ClassSource;
43
44
45 public class RADComponentNode extends FormNode
46     implements RADComponentCookie, FormPropertyCookie
47 {
48    private final static MessageFormat JavaDoc nodeNameFormat =
49         new MessageFormat JavaDoc(
50             FormUtils.getBundleString("FMT_ComponentNodeName")); // NOI18N
51
private final static MessageFormat JavaDoc nodeNoNameFormat =
52         new MessageFormat JavaDoc(
53             FormUtils.getBundleString("FMT_UnnamedComponentNodeName")); // NOI18N
54

55     private RADComponent component;
56     private Action JavaDoc[] actions;
57     private boolean highlightDisplayName;
58     
59     public RADComponentNode(RADComponent component) {
60         this(component instanceof ComponentContainer ?
61                 new RADChildren((ComponentContainer)component) : Children.LEAF,
62              component);
63     }
64
65     public RADComponentNode(Children children, RADComponent component) {
66         super(children, component.getFormModel());
67         this.component = component;
68         component.setNodeReference(this);
69 // getCookieSet().add(this);
70
if (component instanceof ComponentContainer)
71             getCookieSet().add(new ComponentsIndex());
72         updateName();
73     }
74
75     void updateName() {
76         String JavaDoc compClassName = Utilities.getShortClassName(
77                                              component.getBeanClass());
78         if (component == component.getFormModel().getTopRADComponent())
79             setDisplayName(nodeNoNameFormat.format(
80                 new Object JavaDoc[] { compClassName }));
81         else
82             setDisplayName(nodeNameFormat.format(
83                 new Object JavaDoc[] { getName(), compClassName }));
84     }
85
86     public void fireComponentPropertiesChange() {
87         firePropertyChange(null, null, null);
88     }
89
90     public void fireComponentPropertySetsChange() {
91         firePropertySetsChange(null, null);
92     }
93
94     public Image getIcon(int iconType) {
95         // try to get a special icon
96
Image icon = BeanSupport.getBeanIcon(component.getBeanClass(), iconType);
97         if (icon != null) return icon;
98
99         // get icon from BeanInfo
100
java.beans.BeanInfo JavaDoc bi = component.getBeanInfo();
101         if (bi != null) {
102             icon = bi.getIcon(iconType);
103             if (icon != null) return icon;
104         }
105
106         // use default icon
107
return super.getIcon(iconType);
108     }
109
110     public Image getOpenedIcon(int iconType) {
111         return getIcon(iconType);
112     }
113
114     public HelpCtx getHelpCtx() {
115         return new HelpCtx("gui.component-inspector"); // NOI18N
116
}
117
118     public Node.PropertySet[] getPropertySets() {
119         return component.getProperties();
120     }
121
122     /* List new types that can be created in this node.
123      * @return new types
124      */

125     public NewType[] getNewTypes() {
126         return component.getNewTypes();
127     }
128
129     public Action JavaDoc getPreferredAction() {
130         if (component instanceof RADVisualContainer)
131             return SystemAction.get(EditContainerAction.class);
132 // if (component.getEventHandlers().getDefaultEvent() != null)
133
return SystemAction.get(DefaultRADAction.class);
134
135 // return null;
136
}
137
138     public Action JavaDoc[] getActions(boolean context) {
139         if (actions == null) { // from AbstractNode
140
ArrayList actions = new ArrayList(20);
141             RADComponent topComp = component.getFormModel().getTopRADComponent();
142             
143             if (component.isReadOnly()) {
144                 if (component == topComp) {
145                     actions.add(SystemAction.get(TestAction.class));
146                     actions.add(null);
147                 }
148                 Event[] events = component.getKnownEvents();
149                 for (int i=0; i < events.length; i++) {
150                     if (events[i].hasEventHandlers()) {
151                         actions.add(SystemAction.get(EventsAction.class));
152                         actions.add(null);
153                         break;
154                     }
155                 }
156
157                 actions.add(SystemAction.get(CopyAction.class));
158             } else {
159                 java.util.List JavaDoc actionProps = component.getActionProperties();
160                 Iterator iter = actionProps.iterator();
161                 while (iter.hasNext()) {
162                     final RADProperty prop = (RADProperty)iter.next();
163                     Action JavaDoc action = new PropertyAction(prop);
164                     actions.add(action);
165                 }
166                 if (InPlaceEditLayer.supportsEditingFor(component.getBeanClass(), false)) {
167                     actions.add(SystemAction.get(InPlaceEditAction.class));
168                 }
169                 if (component != topComp) {
170                     actions.add(SystemAction.get(ChangeVariableNameAction.class));
171                 }
172                 if (component == topComp) {
173                     actions.add(SystemAction.get(TestAction.class));
174                 }
175                 actions.add(SystemAction.get(EventsAction.class));
176                 actions.add(null);
177
178                 actions.add(SystemAction.get(AlignAction.class));
179                 actions.add(SystemAction.get(SetAnchoringAction.class));
180                 actions.add(SystemAction.get(SetResizabilityAction.class));
181                 actions.add(SystemAction.get(ChooseSameSizeAction.class));
182                 actions.add(SystemAction.get(DefaultSizeAction.class));
183                 actions.add(SystemAction.get(CustomizeEmptySpaceAction.class));
184                 actions.add(null);
185
186                 if (component instanceof RADVisualContainer) {
187                     if (!((RADVisualContainer)component).hasDedicatedLayoutSupport()) {
188                         actions.add(SystemAction.get(EditContainerAction.class));
189                         if (topComp != null && component != topComp) {
190                             actions.add(SystemAction.get(EditFormAction.class));
191                         }
192                         actions.add(SystemAction.get(SelectLayoutAction.class));
193                         actions.add(SystemAction.get(CustomizeLayoutAction.class));
194                     }
195                     actions.add(SystemAction.get(AddAction.class));
196                 }
197                 if (getNewTypes().length != 0) {
198                     actions.add(null);
199                     actions.add(SystemAction.get(NewAction.class));
200                 }
201                 if (component != topComp) {
202                     actions.add(SystemAction.get(MoveUpAction.class));
203                     actions.add(SystemAction.get(MoveDownAction.class));
204                 }
205                 if (component instanceof ComponentContainer) {
206                     actions.add(SystemAction.get(ReorderAction.class));
207                 }
208                 actions.add(null);
209
210                 if (component != topComp) {
211                     actions.add(SystemAction.get(CutAction.class));
212                 }
213                 actions.add(SystemAction.get(CopyAction.class));
214                 if (component instanceof ComponentContainer) {
215                     actions.add(SystemAction.get(PasteAction.class));
216                 }
217                 if (component != topComp) {
218                     actions.add(SystemAction.get(DeleteAction.class));
219                 }
220
221                 actions.add(null);
222                 actions.add(SystemAction.get(CustomCodeAction.class));
223             }
224             actions.add(null);
225
226             javax.swing.Action JavaDoc[] superActions = super.getActions(context);
227             for (int i=0; i < superActions.length; i++)
228                 actions.add(superActions[i]);
229
230             this.actions = new Action JavaDoc[actions.size()];
231             actions.toArray(this.actions);
232         }
233
234         return actions;
235     }
236
237     /** Set the system name. Fires a property change event.
238      * Also may change the display name according to {@link #displayFormat}.
239      *
240      * @param s the new name
241      */

242     public String JavaDoc getName() {
243         return component.getName();
244     }
245
246     /** Set the system name. Fires a property change event.
247      * Also may change the display name according to {@link #displayFormat}.
248      *
249      * @param s the new name
250      */

251     public void setName(String JavaDoc s) {
252         component.setName(s);
253     }
254
255     /** Can this node be renamed?
256      * @return <code>false</code>
257      */

258     public boolean canRename() {
259         return !component.isReadOnly()
260                && component != component.getFormModel().getTopRADComponent();
261     }
262
263     /** Can this node be destroyed?
264      * @return <CODE>false</CODE>
265      */

266     public boolean canDestroy() {
267         return !component.isReadOnly()
268                && component != component.getFormModel().getTopRADComponent();
269     }
270
271     /** Remove the node from its parent and deletes it.
272      * The default
273      * implementation obtains write access to
274      * the {@link Children#MUTEX children's lock}, and removes
275      * the node from its parent(if any). Also fires a property change.
276      * <P>
277      * This may be overridden by subclasses to do any additional
278      * cleanup.
279      *
280      * @exception IOException if something fails
281      */

282     public void destroy() throws java.io.IOException JavaDoc {
283         RADComponent parent = component.getParentComponent();
284         if (parent != null) {
285             Object JavaDoc bean = parent.getBeanInstance();
286             if (bean.getClass() == javax.swing.JScrollPane JavaDoc.class) {
287                 if (parent.getAuxValue("autoScrollPane") != null) { // NOI18N
288
component = parent;
289                 }
290             }
291         }
292         if (EventQueue.isDispatchThread()) {
293             component.getFormModel().removeComponent(component, true);
294         } else {
295             EventQueue.invokeLater(new Runnable JavaDoc() {
296                 public void run() {
297                     component.getFormModel().removeComponent(component, true);
298                 }
299             });
300         }
301         component.setNodeReference(null);
302         super.destroy();
303     }
304
305     /** Test whether there is a customizer for this node. If true,
306      * the customizer can be obtained via {@link #getCustomizer}.
307      *
308      * @return <CODE>true</CODE> if there is a customizer
309      */

310     public boolean hasCustomizer() {
311         return !component.isReadOnly()
312                && component.getBeanInfo().getBeanDescriptor()
313                                                  .getCustomizerClass() != null;
314     }
315
316     /** Creates the customizer component for the node.
317      * @return the component, or null if there is no customizer
318      */

319     protected Component createCustomizer() {
320         Class JavaDoc customizerClass =
321             component.getBeanInfo().getBeanDescriptor().getCustomizerClass();
322         if (customizerClass == null)
323             return null;
324
325         Object JavaDoc customizerObject;
326         try {
327             customizerObject = customizerClass.newInstance();
328         }
329         catch (InstantiationException JavaDoc e) {
330             ErrorManager.getDefault().notify(ErrorManager.WARNING, e);
331             return null;
332         }
333         catch (IllegalAccessException JavaDoc e) {
334             ErrorManager.getDefault().notify(ErrorManager.WARNING, e);
335             return null;
336         }
337
338         if (!(customizerObject instanceof Component)
339                 || !(customizerObject instanceof Customizer))
340             return null;
341
342         if (customizerObject instanceof FormAwareEditor)
343             ((FormAwareEditor)customizerObject)
344                 .setFormModel(component.getFormModel());
345
346         if (customizerObject instanceof NodeCustomizer)
347             ((NodeCustomizer)customizerObject)
348                 .attach(component.getNodeReference());
349
350         Customizer customizer = (Customizer) customizerObject;
351
352         customizer.setObject(component.getBeanInstance());
353
354         customizer.addPropertyChangeListener(new PropertyChangeListener() {
355             public void propertyChange(PropertyChangeEvent evt) {
356                 FormProperty[] properties;
357                 if (evt.getPropertyName() != null) {
358                     FormProperty changedProperty =
359                         component.getBeanProperty(evt.getPropertyName());
360                     if (changedProperty != null)
361                         properties = new FormProperty[] { changedProperty };
362                     else return; // non-existing property?
363
}
364                 else {
365                     properties = component.getAllBeanProperties();
366                     evt = null;
367                 }
368                 updatePropertiesFromCustomizer(properties, evt);
369             }
370         });
371         // [undo/redo for customizer probably does not work...]
372

373         return (Component) customizerObject;
374     }
375
376     private void updatePropertiesFromCustomizer(
377                      final FormProperty[] properties,
378                      final PropertyChangeEvent evt)
379     {
380         // we run this as privileged to avoid security problems - because
381
// the property change is fired from untrusted bean customizer code
382
AccessController.doPrivileged(new PrivilegedAction() {
383             public Object JavaDoc run() {
384                 Object JavaDoc oldValue = evt != null ? evt.getOldValue() : null;
385                 Object JavaDoc newValue = evt != null ? evt.getNewValue() : null;
386
387                 for (int i=0; i < properties.length; i++) {
388                     FormProperty prop = properties[i];
389                     try {
390                         prop.reinstateProperty();
391 // if (prop.isChanged()) // [what if changed to default value?]
392
prop.propertyValueChanged(oldValue, newValue);
393                     }
394                     catch (Exception JavaDoc ex) { // unlikely to happen
395
ex.printStackTrace();
396                     }
397                 }
398                 return null;
399             }
400         });
401     }
402
403     // -----------------------------------------------------------------------------------------
404
// Clipboard operations
405

406     /** Test whether this node can be copied.
407      * The default implementation returns <code>true</code>.
408      * @return <code>true</code> if it can
409      */

410     public boolean canCopy() {
411         return true;
412     }
413
414     /** Test whether this node can be cut.
415      * The default implementation assumes it can if this node is writeable.
416      * @return <code>true</code> if it can
417      */

418     public boolean canCut() {
419         return !component.isReadOnly()
420                && component != component.getFormModel().getTopRADComponent();
421     }
422
423     /** Copy this node to the clipboard.
424      *
425      * @return The transferable for RACComponentNode
426      * @throws IOException if it could not copy
427      */

428     public Transferable clipboardCopy() throws java.io.IOException JavaDoc {
429         return new CopySupport.RADTransferable(
430                                    CopySupport.getComponentCopyFlavor(),
431                                    component);
432     }
433
434     /** Cut this node to the clipboard.
435      *
436      * @return {@link Transferable} with one flavor, {@link RAD_COMPONENT_COPY_FLAVOR }
437      * @throws IOException if it could not cut
438      */

439     public Transferable clipboardCut() throws java.io.IOException JavaDoc {
440         return new CopySupport.RADTransferable(
441                                    CopySupport.getComponentCutFlavor(),
442                                    component);
443     }
444
445     /** Accumulate the paste types that this node can handle
446      * for a given transferable.
447      * @param t a transferable containing clipboard data
448      * @param s a list of {@link PasteType}s that will have added to it all
449      * types valid for this node
450      */

451     protected void createPasteTypes(Transferable t, java.util.List JavaDoc s) {
452         if (component.isReadOnly())
453             return;
454
455         boolean copy = t.isDataFlavorSupported(
456                              CopySupport.getComponentCopyFlavor());
457         boolean cut = t.isDataFlavorSupported(
458                             CopySupport.getComponentCutFlavor());
459
460         if (copy || cut) { // copy or cut some RADComponent
461
RADComponent transComp = null;
462             try {
463                 Object JavaDoc data = t.getTransferData(t.getTransferDataFlavors()[0]);
464                 if (data instanceof RADComponent)
465                     transComp = (RADComponent) data;
466             }
467             catch (UnsupportedFlavorException e) {} // should not happen
468
catch (java.io.IOException JavaDoc e) {} // should not happen
469

470             if (transComp != null
471                 // cut only to another container
472
&& (!cut || CopySupport.canPasteCut(transComp,
473                                                     component.getFormModel(),
474                                                     component))
475                 // must be a valid source/target combination
476
&& (MetaComponentCreator.canAddComponent(
477                                              transComp.getBeanClass(),
478                                              component)
479                     || (!cut && MetaComponentCreator.canApplyComponent(
480                                                      transComp.getBeanClass(),
481                                                      component)))
482                 // hack needed due to screwed design of menu metacomponents
483
&& (!(component instanceof RADMenuComponent)
484                     || transComp instanceof RADMenuItemComponent))
485             { // pasting is allowed
486
s.add(new CopySupport.RADPaste(t,
487                                                component.getFormModel(),
488                                                component));
489             }
490         }
491         else { // java or class node could be copied
492
ClassSource classSource = CopySupport.getCopiedBeanClassSource(t);
493             if (classSource != null) {
494 // && (MetaComponentCreator.canAddComponent(cls, component)
495
// || MetaComponentCreator.canApplyComponent(cls, component)))
496
s.add(new CopySupport.ClassPaste(
497                         t, classSource, component.getFormModel(), component));
498             }
499         }
500     }
501
502     // -----------------------------------------------------------------------------
503
// RADComponentCookie implementation
504

505     public RADComponent getRADComponent() {
506         return component;
507     }
508
509     // -----------------------------------
510
// FormPropertyCookie implementation
511

512     public FormProperty getProperty(String JavaDoc name) {
513         return (FormProperty)
514                component.getPropertyByName(name, FormProperty.class, true);
515 // Node.Property prop = component.getPropertyByName(name, true);
516
// return (FormProperty) (prop instanceof FormProperty ? prop : null);
517
}
518
519     // -----------------------------------------------------------------------------
520
// Innerclasses
521

522     public static class RADChildren extends FormNodeChildren {
523         private ComponentContainer container;
524         private Object JavaDoc keyLayout;
525
526         public RADChildren(ComponentContainer container) {
527             super();
528             this.container = container;
529             updateKeys();
530         }
531
532         // FormNodeChildren implementation
533
protected void updateKeys() {
534             RADComponent[] subComps = container.getSubBeans();
535             ArrayList keys = new ArrayList(subComps.length + 2);
536
537             if (container instanceof RADVisualContainer) {
538                 RADVisualContainer visualCont = (RADVisualContainer) container;
539
540                 RADComponent menuComp = visualCont.getContainerMenu();
541                 if (menuComp != null)
542                     keys.add(menuComp);
543
544                 if (visualCont.shouldHaveLayoutNode()) {
545                     keyLayout = visualCont.getLayoutSupport().getLayoutDelegate(); //new Object(); // [need not be recreated every time]
546
keys.add(keyLayout);
547                 }
548
549                 for (int i=0; i < subComps.length; i++)
550                     if (subComps[i] != menuComp)
551                         keys.add(subComps[i]);
552             }
553             else {
554                 for (int i=0; i < subComps.length; i++)
555                     keys.add(subComps[i]);
556             }
557
558             setKeys(keys);
559         }
560
561         protected Node[] createNodes(Object JavaDoc key) {
562             Node node;
563             if (key == keyLayout)
564                 node = new LayoutNode((RADVisualContainer)container);
565             else {
566                 node = new RADComponentNode((RADComponent)key);
567                 node.getChildren().getNodes(); // enforce subnodes creation
568
}
569             return new Node[] { node };
570         }
571     }
572
573     private final class ComponentsIndex extends org.openide.nodes.Index.Support {
574
575         public Node[] getNodes() {
576             RADComponent[] comps;
577             if (component instanceof RADVisualContainer)
578                 comps = ((RADVisualContainer)component).getSubComponents();
579             else if (component instanceof ComponentContainer)
580                 comps = ((ComponentContainer)component).getSubBeans();
581             else
582                 comps = null;
583
584             Node[] nodes = new Node[comps != null ? comps.length : 0];
585             for (int i = 0; i < comps.length; i++)
586                 nodes[i] = comps[i].getNodeReference();
587
588             return nodes;
589         }
590
591         public int getNodesCount() {
592             return getNodes().length;
593         }
594
595         public void reorder(int[] perm) {
596             if (component instanceof ComponentContainer) {
597                 ComponentContainer cont = (ComponentContainer) component;
598                 cont.reorderSubComponents(perm);
599                 component.getFormModel().fireComponentsReordered(cont, perm);
600             }
601         }
602     }
603     
604     private static final class ChangeVariableNameAction extends RenameAction {
605         public String JavaDoc getName() {
606             return NbBundle.getMessage(ChangeVariableNameAction.class, "ChangeVariableNameAction"); // NOI18N
607
}
608     }
609
610     public String JavaDoc getHtmlDisplayName() {
611         if(highlightDisplayName) {
612             return "<html><b>" + getDisplayName() + "</b></html>"; // NOI18N
613
} else {
614             return "<html>" + getDisplayName() + "</html>"; // NOI18N
615
}
616     }
617     
618     void highlightDisplayName(boolean highlight) {
619         if(highlight != highlightDisplayName) {
620             highlightDisplayName = highlight;
621             fireDisplayNameChange(null, getDisplayName());
622         }
623     }
624 }
625
Popular Tags