KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > xml > schema > ui > nodes > SchemaComponentNode


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-2007 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.xml.schema.ui.nodes;
21
22 import java.awt.Dialog JavaDoc;
23 import java.awt.datatransfer.Transferable JavaDoc;
24 import java.beans.FeatureDescriptor JavaDoc;
25 import java.beans.PropertyChangeEvent JavaDoc;
26 import java.beans.PropertyChangeListener JavaDoc;
27 import java.beans.PropertyEditor JavaDoc;
28 import java.beans.PropertyEditorSupport JavaDoc;
29 import java.io.IOException JavaDoc;
30 import java.lang.ref.SoftReference JavaDoc;
31 import java.lang.reflect.InvocationTargetException JavaDoc;
32 import java.util.ArrayList JavaDoc;
33 import java.util.Collections JavaDoc;
34 import java.util.LinkedList JavaDoc;
35 import java.util.List JavaDoc;
36 import java.util.Set JavaDoc;
37 import javax.swing.Action JavaDoc;
38 import org.netbeans.modules.xml.refactoring.actions.FindUsagesAction;
39 import org.netbeans.modules.xml.refactoring.actions.RefactorAction;
40 import org.netbeans.modules.xml.refactoring.ui.ReferenceableProvider;
41 import org.netbeans.modules.xml.refactoring.ui.util.AnalysisUtilities;
42 import org.netbeans.modules.xml.schema.model.Annotation;
43 import org.netbeans.modules.xml.schema.model.Documentation;
44 import org.netbeans.modules.xml.schema.model.ReferenceableSchemaComponent;
45 import org.netbeans.modules.xml.schema.model.Schema;
46 import org.netbeans.modules.xml.schema.model.SchemaComponent;
47 import org.netbeans.modules.xml.schema.model.SchemaComponentReference;
48 import org.netbeans.modules.xml.schema.model.SchemaModel;
49 import org.netbeans.modules.xml.schema.ui.basic.DesignGotoType;
50 import org.netbeans.modules.xml.schema.ui.basic.SchemaGotoType;
51 import org.netbeans.modules.xml.schema.ui.basic.SchemaSettings;
52 import org.netbeans.modules.xml.schema.ui.basic.UIUtilities;
53 import org.netbeans.modules.xml.xam.dom.Utils;
54 import org.netbeans.modules.xml.xam.ui.ComponentPasteType;
55 import org.netbeans.modules.xml.xam.ui.actions.GotoType;
56 import org.netbeans.modules.xml.xam.ui.actions.SourceGotoType;
57 import org.netbeans.modules.xml.xam.ui.actions.SuperGotoType;
58 import org.netbeans.modules.xml.xam.ui.cookies.GetComponentCookie;
59 import org.netbeans.modules.xml.xam.ui.cookies.GetSuperCookie;
60 import org.netbeans.modules.xml.xam.Component;
61 import org.netbeans.modules.xml.xam.ComponentEvent;
62 import org.netbeans.modules.xml.xam.ComponentListener;
63 import org.netbeans.modules.xml.xam.Nameable;
64 import org.netbeans.modules.xml.xam.Named;
65 import org.netbeans.modules.xml.xam.NamedReferenceable;
66 import org.netbeans.modules.xml.schema.ui.basic.ShowSchemaAction;
67 import org.netbeans.modules.xml.xam.ui.cookies.GotoCookie;
68 import org.netbeans.modules.xml.xam.ui.customizer.Customizer;
69 import org.netbeans.modules.xml.xam.ui.customizer.CustomizerProvider;
70 import org.netbeans.modules.xml.xam.ui.highlight.Highlight;
71 import org.netbeans.modules.xml.xam.ui.highlight.HighlightManager;
72 import org.netbeans.modules.xml.xam.ui.highlight.Highlighted;
73 import org.netbeans.modules.xml.schema.ui.basic.editors.StringEditor;
74 import org.netbeans.modules.xml.schema.ui.nodes.schema.properties.BaseSchemaProperty;
75 import org.netbeans.modules.xml.xam.ui.XAMUtils;
76 import org.netbeans.modules.xml.xam.ui.actions.GoToAction;
77 import org.netbeans.modules.xml.xam.ui.cookies.CountChildrenCookie;
78 import org.openide.DialogDescriptor;
79 import org.openide.DialogDisplayer;
80 import org.openide.ErrorManager;
81 import org.openide.actions.CopyAction;
82 import org.openide.actions.CutAction;
83 import org.openide.actions.DeleteAction;
84 import org.openide.actions.NewAction;
85 import org.openide.actions.PasteAction;
86 import org.openide.actions.PropertiesAction;
87 import org.openide.actions.ReorderAction;
88 import org.openide.explorer.propertysheet.ExPropertyEditor;
89 import org.openide.explorer.propertysheet.PropertyEnv;
90 import org.openide.filesystems.FileObject;
91 import org.openide.loaders.DataObject;
92 import org.openide.loaders.DataObjectNotFoundException;
93 import org.openide.nodes.AbstractNode;
94 import org.openide.nodes.Children;
95 import org.openide.nodes.Index;
96 import org.openide.nodes.Node;
97 import org.openide.nodes.Node.Property;
98 import org.openide.nodes.PropertySupport;
99 import org.openide.nodes.Sheet;
100 import org.openide.util.HelpCtx;
101 import org.openide.util.Lookup;
102 import org.openide.util.NbBundle;
103 import org.openide.util.WeakListeners;
104 import org.openide.util.actions.SystemAction;
105 import org.openide.util.datatransfer.NewType;
106 import org.openide.util.datatransfer.PasteType;
107 import org.openide.util.lookup.AbstractLookup;
108 import org.openide.util.lookup.InstanceContent;
109 import org.openide.util.lookup.Lookups;
110 import org.openide.util.lookup.ProxyLookup;
111
112 /**
113  *
114  * @author Todd Fast, todd.fast@sun.com
115  * @author Nathan Fiedler
116  */

117 public abstract class SchemaComponentNode<T extends SchemaComponent>
118         extends AbstractNode
119         implements Node.Cookie, ComponentListener, PropertyChangeListener JavaDoc,
120         Highlighted, ReferenceableProvider, CountChildrenCookie,
121         GetComponentCookie, GetSuperCookie, GotoCookie {
122
123     /**
124      *
125      *
126      */

127     public SchemaComponentNode(SchemaUIContext context,
128             SchemaComponentReference<T> reference, Children children) {
129         this(context,reference,children,new InstanceContent());
130     }
131     
132     
133     /**
134      * Constructor HACK to allow creating of our own lookup
135      *
136      */

137     private SchemaComponentNode(SchemaUIContext context,
138             SchemaComponentReference<T> reference, Children children,
139             InstanceContent contents) {
140         super(children, createLookup(context, contents));
141         
142         this.context=context;
143         this.reference=reference;
144         this.lookupContents=contents;
145         
146         // Add various objects to the lookup.
147
contents.add(this);
148         // Include the data object in order for the Navigator to
149
// show the structure of the current document.
150
DataObject dobj = getDataObject();
151         if (dobj != null) {
152             contents.add(dobj);
153         }
154         contents.add(context);
155         contents.add(reference);
156         contents.add(new DefaultExpandedCookie(false));
157 // // add customizer provider if provided
158
// CustomizerProvider provider = getCustomizerProvider();
159
// if (provider != null) {
160
// contents.add(provider);
161
// }
162

163         // reorder must be enabled only if its editable node
164
if (children instanceof Index && isEditable() &&
165                 // dont show for schema bug 80138
166
!(reference.get() instanceof Schema)) {
167             contents.add(children);
168         }
169         T comp = reference.get();
170         contents.add(comp);
171         
172         // Listen to changes in the model using a WeakListener. I hold onto
173
// the WeakListener instance so I can explicitly remove it in the
174
// destroy method.
175
SchemaModel model = reference.get().getModel();
176         if (model != null) {
177             weakModelListener=
178                     WeakListeners.propertyChange(this,model);
179             model.addPropertyChangeListener(weakModelListener);
180             weakComponentListener = (ComponentListener) WeakListeners.create(
181                     ComponentListener.class, this, model);
182             model.addComponentListener(weakComponentListener);
183         }
184         // Determine default names for the node
185
if (comp instanceof Named) {
186             // Just set the name, and let the method call below handle
187
// the display name
188
_setName(((Named) comp).getName());
189         } else {
190             _setName(comp.getPeer().getLocalName());
191         }
192         // Need a model for the following to work properly.
193
if (model != null) {
194             // Let the node try to update its display name
195
updateDisplayName();
196             // Let the node try to update its short desc
197
updateShortDescription();
198         }
199
200         setIconBaseWithExtension(
201                 "org/netbeans/modules/xml/schema/ui/nodes/resources/"+
202                 "generic.png");
203
204         referenceSet = Collections.singleton(
205                 (Component) ((SchemaComponentReference) reference).get());
206         highlights = new LinkedList JavaDoc<Highlight>();
207         HighlightManager.getDefault().addHighlighted(this);
208     }
209     
210     /**
211      * Create a lookup for this node, based on the given contents.
212      *
213      * @param context from which a Lookup is retrieved.
214      * @param contents the basis of our new lookup.
215      */

216     private static Lookup createLookup(SchemaUIContext context,
217             InstanceContent contents) {
218         // We want our lookup to be based on the lookup from the context,
219
// which provides a few necessary objects, such as a SaveCookie.
220
// However, we do not want the Nodes or DataObjects, since we
221
// provide our own.
222
return new ProxyLookup(new Lookup[] {
223             // Keep our lookup contents first, so that whatever we add to
224
// the lookup is at the top of the lookup, such as this node,
225
// which provides certain cookies, rather than that of the
226
// currently selected node.
227
new AbstractLookup(contents),
228             Lookups.exclude(context.getLookup(), new Class JavaDoc[] {
229                 Node.class,
230                 DataObject.class,
231             }),
232         });
233     }
234     
235     /**
236      * Attempt to retrieve the DataObject associated with the model that
237      * contains the component this node represents.
238      *
239      * @return schema data object, if available, or null if not.
240      */

241     private DataObject getDataObject() {
242         try {
243             // Include the data object in order for the Navigator to
244
// show the structure of the current document.
245
SchemaModel model = reference.get().getModel();
246             if (model != null) {
247                 FileObject fobj = (FileObject) model.getModelSource().
248                         getLookup().lookup(FileObject.class);
249                 if (fobj != null) {
250                     return DataObject.find(fobj);
251                 }
252             }
253         } catch (DataObjectNotFoundException donfe) {
254             // fall through to return null
255
}
256         return null;
257     }
258     
259     /**
260      * This api returns the customizer provider.
261      * Subclasses must override this api to return appropriate
262      * customizer provider
263      */

264     protected CustomizerProvider getCustomizerProvider() {
265         return null;
266     }
267     
268     /**
269      * Overriden to provide custom customizer.
270      * Gets the customizer component from customizer provider
271      * and displays it as modal dialog.
272      * Subclasses who provide customizer should override
273      * hasCustomizer and return true.
274      */

275     @Override JavaDoc
276             public java.awt.Component JavaDoc getCustomizer() {
277         if(!hasCustomizer()|| !isEditable()) return null;
278         // get it from soft ref
279
if(custRef==null || custRef.get()==null) {
280             CustomizerProvider cp = getCustomizerProvider();
281             if (cp==null) return null;
282             Customizer cust = cp.getCustomizer();
283             if (cust==null || cust.getComponent()==null) return null;
284             custRef = new SoftReference JavaDoc<Customizer>(cust);
285         } else {
286             // might not be in sync so sync
287
custRef.get().reset();
288         }
289         Customizer customizer = custRef.get();
290         DialogDescriptor descriptor = UIUtilities.
291                 getCustomizerDialog(customizer,getTypeDisplayName(),isEditable());
292         Dialog JavaDoc dlg = DialogDisplayer.getDefault().createDialog(descriptor);
293         dlg.getAccessibleContext().setAccessibleDescription(dlg.getTitle());
294         return dlg;
295     }
296     
297     /**
298      *
299      *
300      */

301     public boolean equals(Object JavaDoc o) {
302         // Without this, the tree view collapses when nodes are changed.
303
if (o instanceof SchemaComponentNode) {
304             SchemaComponentNode scn = (SchemaComponentNode) o;
305             SchemaComponentReference scr = scn.getReference();
306             return scr.equals(reference);
307         }
308         return false;
309     }
310     
311     
312     /**
313      *
314      *
315      */

316     public int hashCode() {
317         // Without this, the tree view collapses when nodes are changed.
318
return reference.hashCode();
319     }
320     
321     
322     /**
323      *
324      *
325      */

326     public SchemaUIContext getContext() {
327         return context;
328     }
329     
330     
331     /**
332      *
333      *
334      */

335     public SchemaComponentReference<T> getReference() {
336         return reference;
337     }
338     
339     
340     /**
341      * Returns the contents of the lookup. All cookies and other objects that
342      * should be findable via the lookup should be added to this.
343      *
344      */

345     protected InstanceContent getLookupContents() {
346         return lookupContents;
347     }
348     
349     /**
350      * Determines if this node represents a component that is contained
351      * in a valid (non-null) model.
352      *
353      * @return true if model is valid, false otherwise.
354      */

355     protected boolean isValid() {
356         return getReference().get().getModel() != null;
357     }
358     
359     /**
360      * Determines if this node represents a component that is contained
361      * is editable
362      *
363      * @return true if component is editable, false otherwise.
364      */

365     protected boolean isEditable() {
366         SchemaModel model = getReference().get().getModel();
367         return model != null && model == getContext().getModel() &&
368                 XAMUtils.isWritable(model);
369     }
370     
371     /**
372      * Used by subclasses to update the display name as needed. The default
373      * implementation updates the display name for named schema components.
374      * Note, this method may be called from the constructor, so be sure to
375      * avoid using member variables!
376      *
377      */

378     protected void updateDisplayName() {
379         if (!isValid()) {
380             // If there is no model, exceptions will occur.
381
return;
382         }
383         T component = getReference().get();
384         if (component instanceof Named) {
385             String JavaDoc name=((Named)component).getName();
386             // Automatically keep the name in sync for named schema components.
387
_setName(name);
388             if(name==null||name.equals("")) name = component.getPeer().getLocalName();
389             setDisplayName(name);
390         }
391     }
392     
393     
394     /**
395      * updates the short descrption associated with node.
396      * checks for if there is any annotation with documentation element.
397      */

398     private void updateShortDescription() {
399         if (!isValid()) {
400             // If there is no model, exceptions will occur.
401
return;
402         }
403         T component = getReference().get();
404         Documentation d = null;
405         Annotation a = null;
406         String JavaDoc language = SchemaSettings.getDefault().getLanguage();
407         if (component instanceof Documentation) {
408             d = (Documentation) component;
409         } else if (component instanceof Annotation) {
410             a = (Annotation) component;
411         } else {
412             a = component.getAnnotation();
413         }
414         if (a != null && !a.getDocumentationElements().isEmpty()) {
415             if(language==null) {
416                 d = a.getDocumentationElements().iterator().next();
417             } else {
418                 for (Documentation doc:a.getDocumentationElements()) {
419                     if(language.equals(doc.getLanguage())) {
420                         d = doc;
421                         break;
422                     }
423                 }
424                 if(d==null) {
425                     d = a.getDocumentationElements().iterator().next();
426                 }
427             }
428         }
429         if (d != null) {
430             setShortDescription(d.getContentFragment());
431         } else {
432             setShortDescription(null);
433         }
434     }
435     
436     
437     /**
438      *
439      *
440      */

441     public abstract String JavaDoc getTypeDisplayName();
442     
443     
444     /**
445      *
446      *
447      */

448     protected String JavaDoc getHtmlTypeDisplayName() {
449         return "<font color='#aaaaaa'>("+getTypeDisplayName()+")</font>";
450     }
451     
452     
453     /**
454      *
455      *
456      */

457     public boolean isDefaultExpanded() {
458         DefaultExpandedCookie cookie=(DefaultExpandedCookie)
459         getCookie(DefaultExpandedCookie.class);
460         if (cookie!=null)
461             return cookie.isDefaultExpanded();
462         else
463             return false;
464     }
465     
466     
467     /**
468      *
469      *
470      */

471     public void setDefaultExpanded(boolean value) {
472         DefaultExpandedCookie cookie=(DefaultExpandedCookie)
473         getCookie(DefaultExpandedCookie.class);
474         if (cookie!=null)
475             cookie.setDefaultExpanded(value);
476     }
477     
478     
479     /**
480      * Finds the super definition of the schema component.
481      * Returns null as default implementation
482      * Subclasses which fave global type or reference definitions,
483      * must override to return the global reference.
484      */

485     protected ReferenceableSchemaComponent getSuperDefinition() {
486         return null;
487     }
488
489     public int getChildCount() {
490         return getReference().get().getChildren().size();
491     }
492
493     public Component getComponent() {
494         return getReference().get();
495     }
496
497     public Class JavaDoc<? extends Component> getComponentType() {
498         return getReference().get().getComponentType();
499     }
500
501     // implementation of get super cookie
502
public SchemaComponent getSuper()
503     {
504         return getSuperDefinition();
505     }
506   
507     
508     ////////////////////////////////////////////////////////////////////////////
509
// Node methods
510
////////////////////////////////////////////////////////////////////////////
511

512     /**
513      *
514      *
515      */

516     @Override JavaDoc
517             public HelpCtx getHelpCtx() {
518         return new HelpCtx(getClass());
519     }
520     
521     
522     /**
523      *
524      *
525      */

526     @Override JavaDoc
527             public boolean canCut() {
528         return isEditable();
529     }
530     
531     
532     /**
533      *
534      *
535      */

536     @Override JavaDoc
537             public boolean canCopy() {
538         return true;
539     }
540
541     @Override JavaDoc
542     @SuppressWarnings JavaDoc("unchecked")
543     protected void createPasteTypes(Transferable JavaDoc transferable, List JavaDoc list) {
544         if (isValid() && isEditable()) {
545             PasteType type = ComponentPasteType.getPasteType(
546                     reference.get(), transferable, null);
547             if (type != null) {
548                 list.add(type);
549             }
550         }
551     }
552
553     @Override JavaDoc
554     public PasteType getDropType(Transferable JavaDoc transferable, int action, int index) {
555         if (isValid() && isEditable()) {
556             PasteType type = ComponentPasteType.getDropType(
557                     reference.get(), transferable, null, action, index);
558             if (type != null) {
559                 return type;
560             }
561         }
562         return null;
563     }
564
565     @Override JavaDoc
566             public boolean canDestroy() {
567         SchemaComponent component = getReference().get();
568         if (component instanceof Schema || !isEditable()) {
569             return false;
570         }
571         return true;
572     }
573     
574     
575     /**
576      *
577      *
578      */

579     @Override JavaDoc
580             public boolean canRename() {
581         return supportsRename();
582     }
583     
584     
585     /**
586      * Indicates if the component is nameable.
587      *
588      * @return true if nameable, false otherwise.
589      */

590     private boolean isNameable() {
591         // Need to check the component type instead of the component, to
592
// avoid allowing rename of an element reference, in which the
593
// implementation extends Nameable.
594
return Nameable.class.isAssignableFrom(
595                 getReference().get().getComponentType());
596     }
597     
598     
599     /**
600      * Indicates if the component can be renamed.
601      *
602      * @return true if nameable, false otherwise.
603      */

604     private boolean supportsRename() {
605         // check if its nameable and editable
606
return isNameable() && isEditable();
607     }
608     
609     
610     /**
611      * Set the name property directly without adjusting the associated model
612      *
613      */

614     private void _setName(String JavaDoc value) {
615         // prevent NPE from explorermanager
616
if(value==null) value="";
617         super.setName(value);
618     }
619     
620     
621     /**
622      *
623      *
624      */

625     @Override JavaDoc
626             public void setName(String JavaDoc value) {
627         NamedReferenceable ref = getReferenceable();
628         if(ref==null)
629         {
630             _setName(value);
631             if (supportsRename())
632             {
633                 try
634                 {
635                     getReference().get().getModel().startTransaction();
636                     Nameable n = (Nameable)getReference().get();
637                     n.setName(value);
638                 }
639                 finally
640                 {
641                     getReference().get().getModel().endTransaction();
642                 }
643             }
644         }
645         else
646         {
647             AnalysisUtilities.locallyRenameRefactor((Nameable)ref, value);
648         }
649     }
650     
651     /**
652      * Checks for references to this component, and if none are found,
653      * remove it from the model.
654      */

655     public void destroy() throws IOException JavaDoc {
656         SchemaModel model = getReference().get().getModel();
657         if(model == null) {
658             // fix bug 6421899
659
// this node might have been deleted from model as a result of
660
// deletion of its parent. get model from context and remove
661
// listeners. no need to remove it again from model.
662
model = getContext().getModel();
663             model.removeComponentListener(weakComponentListener);
664             model.removePropertyChangeListener(weakModelListener);
665         } else {
666             model.removeComponentListener(weakComponentListener);
667             model.removePropertyChangeListener(weakModelListener);
668             
669             // Remove the component from the model.
670
SchemaComponent component = getReference().get();
671             try {
672                 model.startTransaction();
673                 model.removeChildComponent(component);
674             } finally {
675                 model.endTransaction();
676             }
677         }
678         super.destroy();
679     }
680     
681     
682     /**
683      *
684      *
685      */

686     @Override JavaDoc
687             protected Sheet createSheet() {
688         super.createSheet();
689         Sheet sheet=Sheet.createDefault();
690         Sheet.Set set=sheet.get(Sheet.PROPERTIES);
691         set.put(
692                 new PropertySupport("kind",String JavaDoc.class,
693                 NbBundle.getMessage(SchemaComponentNode.class,
694                 "PROP_SchemaComponentNode_Kind"),
695                 "",true,false) {
696             public Object JavaDoc getValue() {
697                 return getTypeDisplayName();
698             }
699             
700             public void setValue(Object JavaDoc value) {
701                 // Not modifiable
702
}
703         });
704         
705         try {
706             // id property
707
Property idProperty = new BaseSchemaProperty((SchemaComponent)getReference().get(),
708                     String JavaDoc.class,
709                     SchemaComponent.ID_PROPERTY,
710                     NbBundle.getMessage(SchemaComponentNode.class,
711                     "PROP_SchemaComponentNode_ID"),
712                     NbBundle.getMessage(SchemaComponentNode.class,
713                     "PROP_SchemaComponentNode_IDDesc"),
714                     StringEditor.class
715                     ){
716                 public void setValue(Object JavaDoc o) throws
717                         IllegalAccessException JavaDoc, InvocationTargetException JavaDoc {
718                     if (o instanceof String JavaDoc) {
719                         if("".equals(o)) {
720                             super.setValue(null);
721                         } else if (Utils.isValidNCName(o.toString())){
722                             super.setValue(o);
723                         } else {
724                             String JavaDoc msg = NbBundle.getMessage(BaseSchemaProperty.class,
725                                     "MSG_Neg_Int_Value", o); //NOI18N
726
IllegalArgumentException JavaDoc iae = new IllegalArgumentException JavaDoc(msg);
727                             ErrorManager.getDefault().annotate(iae, ErrorManager.USER,
728                                     msg, msg, null, new java.util.Date JavaDoc());
729                             throw iae;
730                         }
731                     } else {
732                         super.setValue(o);
733                     }
734                 }
735             };
736             set.put(new SchemaModelFlushWrapper(getReference().get(), idProperty));
737         } catch (NoSuchMethodException JavaDoc nsme) {
738             assert false: "properties must be defined";
739         }
740         
741         // If we are a named node, display that in the property sheet
742
if (isNameable())
743             set.put(new PropertySupport.Name(this));
744         
745         if(hasCustomizer()&&isEditable()) {
746             Property structureProp = new PropertySupport.ReadWrite("structure", //NOI18N
747
String JavaDoc.class,
748                     NbBundle.getMessage(SchemaComponentNode.class,
749                     "PROP_SchemaComponentNode_Customize"),
750                     NbBundle.getMessage(SchemaComponentNode.class,
751                     "PROP_SchemaComponentNode_Customize_ShortDesc")) {
752                 public Object JavaDoc getValue() throws IllegalAccessException JavaDoc,InvocationTargetException JavaDoc {
753                     return NbBundle.getMessage(SchemaComponentNode.class,
754                             "PROP_SchemaComponentNode_Customize_Label");
755                 }
756                 public void setValue(Object JavaDoc val) throws IllegalAccessException JavaDoc,IllegalArgumentException JavaDoc,InvocationTargetException JavaDoc {
757                 }
758                 public PropertyEditor JavaDoc getPropertyEditor() {
759                     return new StructurePropertyEditor();
760                 }
761             };
762             set.put(structureProp);
763         }
764
765         return sheet;
766     }
767
768     /**
769      * Indicates if this node should allow reordering of its children.
770      * The default implementation allows reordering only if there is
771      * more than one child component.
772      *
773      * @return true if reordering of this node's children is permitted.
774      */

775     protected boolean allowReordering() {
776         // Check if we have more than one physical child in the model.
777
// Using the node children count results in too many index out
778
// of bounds exceptions.
779
return getReference().get().getChildren().size() > 1;
780     }
781
782     @Override JavaDoc
783     public Action JavaDoc[] getActions(boolean context) {
784         ReadOnlyCookie roc = (ReadOnlyCookie) getContext().getLookup().lookup(
785                 ReadOnlyCookie.class);
786         List JavaDoc<Action JavaDoc> actions = new ArrayList JavaDoc<Action JavaDoc>();
787         if (roc != null && roc.isReadOnly()) {
788             // Set of actions for read-only components.
789
actions.add(SystemAction.get(GoToAction.class));
790         } else {
791             // Set of actions for modifiable components.
792
actions.add(SystemAction.get(CutAction.class));
793             actions.add(SystemAction.get(CopyAction.class));
794             actions.add(SystemAction.get(PasteAction.class));
795             actions.add(null);
796             actions.add(SystemAction.get(NewAction.class));
797             actions.add(SystemAction.get(DeleteAction.class));
798             if (allowReordering()) {
799                 actions.add(SystemAction.get(ReorderAction.class));
800             }
801             actions.add(null);
802             actions.add(SystemAction.get(GoToAction.class));
803             actions.add(SystemAction.get(FindUsagesAction.class));
804             actions.add(null);
805             actions.add(SystemAction.get(RefactorAction.class));
806             actions.add(null);
807             actions.add(SystemAction.get(PropertiesAction.class));
808         }
809         return actions.toArray(new Action JavaDoc[actions.size()]);
810     }
811     
812     @Override JavaDoc
813     public Action JavaDoc getPreferredAction() {
814         // This exists for use in the Navigator.
815
ReadOnlyCookie roc = (ReadOnlyCookie) getCookie(ReadOnlyCookie.class);
816         if (roc != null && roc.isReadOnly()) {
817             return SystemAction.get(ShowSchemaAction.class);
818         }
819         return super.getPreferredAction();
820     }
821     
822     
823    /**
824      * This api returns the factory which gives back new types for this node.
825      * Default FactoryImpl provides addition of annotation.
826      * Subclasses can override this api to allow addition of their allowed
827      * child types.
828      */

829     protected NewTypesFactory getNewTypesFactory() {
830         return new NewTypesFactory();
831     }
832     
833     public final NewType[] getNewTypes() {
834         if(isEditable()) {
835             return getNewTypesFactory().getNewTypes(getReference(), null);
836         }
837         return new NewType[] {};
838     }
839
840     public GotoType[] getGotoTypes() {
841         return GOTO_TYPES;
842     }
843
844     ////////////////////////////////////////////////////////////////////////////
845
// Listener methods
846
////////////////////////////////////////////////////////////////////////////
847

848     public void childrenAdded(ComponentEvent evt) {
849         if (isValid()) {
850             if(evt.getSource() == getReference().get())
851             {
852                 ((RefreshableChildren) getChildren()).refreshChildren();
853             }
854             if(evt.getSource() == getReference().get() ||
855                     evt.getSource() == getReference().get().getAnnotation())
856             {
857                 updateShortDescription();
858             }
859         }
860     }
861     
862     public void childrenDeleted(ComponentEvent evt) {
863         if (isValid()) {
864             if(evt.getSource() == getReference().get())
865             {
866                 ((RefreshableChildren) getChildren()).refreshChildren();
867             }
868             if(evt.getSource() == getReference().get() ||
869                     evt.getSource() == getReference().get().getAnnotation())
870             {
871                 updateShortDescription();
872             }
873         }
874     }
875     
876     public void valueChanged(ComponentEvent evt) {
877         if (isValid())
878         {
879             T component = getReference().get();
880             if(evt.getSource() == component)
881             {
882                 updateDisplayName();
883             }
884             Documentation d = null;
885             if(component instanceof Documentation)
886                 d = (Documentation)component;
887             else if(component instanceof Annotation)
888             {
889                 Annotation a = (Annotation)component;
890                 if(!a.getDocumentationElements().isEmpty())
891                     d = a.getDocumentationElements().iterator().next();
892             }
893             else
894             {
895                 Annotation a = component.getAnnotation();
896                 if(a!=null && !a.getDocumentationElements().isEmpty())
897                     d = a.getDocumentationElements().iterator().next();
898             }
899             if(evt.getSource()==d)
900             {
901                 updateShortDescription();
902             }
903         }
904     }
905     
906     /**
907      * Reacts to granular property change events from model.
908      * Updates displayname if needed.
909      * Fires properties changed events if needed.
910      * Subclasses override if needed.
911      */

912     public void propertyChange(PropertyChangeEvent JavaDoc event) {
913         if (isValid() && event.getSource() == getReference().get()) {
914             try {
915                 updateDisplayName();
916                 String JavaDoc propName = event.getPropertyName();
917                 Sheet.Set propertySet = getSheet().get(Sheet.PROPERTIES);
918                 if(propertySet!=null){
919                     if (propertySet.get(propName)!=null) {
920                         firePropertyChange(propName,event.getOldValue(),
921                                 event.getNewValue());
922                     }
923                     else {
924                         ErrorManager.getDefault().log(ErrorManager.INFORMATIONAL,
925                                 propName + " property is not defined in " +
926                                 getTypeDisplayName());
927                     }
928                 }
929             } catch (IllegalStateException JavaDoc ise) {
930                 // Component is not in the model.
931
ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ise);
932             } catch (NullPointerException JavaDoc npe) {
933                 // Does not reproduce reliably, but catch and log regardless.
934
ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, npe);
935             }
936         }
937     }
938
939     public Set JavaDoc<Component> getComponents() {
940         return referenceSet;
941     }
942     
943     public void highlightAdded(Highlight hl) {
944         highlights.add(hl);
945         fireDisplayNameChange("TempName", getDisplayName());
946     }
947     
948     public void highlightRemoved(Highlight hl) {
949         highlights.remove(hl);
950         fireDisplayNameChange("TempName", getDisplayName());
951     }
952     
953     /**
954      * Given a display name, add the appropriate HTML tags to highlight
955      * the display name as dictated by any Highlights associated with
956      * this node.
957      *
958      * @param name current display name.
959      * @return marked up display name.
960      */

961     protected String JavaDoc applyHighlights(String JavaDoc name) {
962         int count = highlights.size();
963         if (count > 0) {
964             // Apply the last highlight that was added to our list.
965
Highlight hl = highlights.get(count - 1);
966             String JavaDoc type = hl.getType();
967             String JavaDoc code = null;
968
969
970             if (type.equals(Highlight.SEARCH_RESULT)) {
971                 code = "e68b2c";
972             } else if (type.equals(Highlight.SEARCH_RESULT_PARENT)) {
973                 code = "ffc73c";
974             } else if (type.equals(Highlight.FIND_USAGES_RESULT_PARENT)) {
975                 code = "B5E682"; // was c7ff3c chartreuse
976
}else if (type.equals(Highlight.FIND_USAGES_RESULT)) {
977                 code = "8be62c"; // darker green
978
}
979             name = "<strong><font color=\"#" + code + "\">" + name +
980                     "</font></strong>";
981         }
982         return name;
983     }
984     
985     public String JavaDoc getDisplayName() {
986         String JavaDoc instanceName = getDefaultDisplayName();
987         return instanceName.length()==0 ? instanceName :
988            instanceName + " " + "[" + getTypeDisplayName() + "]"; // NOI18N
989
}
990     
991     public String JavaDoc getDefaultDisplayName() {
992     String JavaDoc instanceName = super.getDisplayName();
993         return instanceName == null || instanceName.length() == 0
994         ? "" : instanceName;
995     }
996     
997     public String JavaDoc getHtmlDisplayName() {
998         String JavaDoc name = getDefaultDisplayName();
999         // Need to escape any HTML meta-characters in the name.
1000
if(name!=null)
1001            name = name.replace("<", "&lt;").replace(">", "&gt;");
1002        return applyHighlights(name);
1003    }
1004    
1005    ////////////////////////////////////////////////////////////////////////////
1006
// Inner class
1007
////////////////////////////////////////////////////////////////////////////
1008

1009    private class StructurePropertyEditor extends PropertyEditorSupport JavaDoc
1010            implements ExPropertyEditor {
1011        public boolean supportsCustomEditor() {
1012            return true;
1013        }
1014        
1015        public java.awt.Component JavaDoc getCustomEditor() {
1016            return getCustomizer();
1017        }
1018        
1019        public void attachEnv(PropertyEnv env ) {
1020            FeatureDescriptor JavaDoc desc = env.getFeatureDescriptor();
1021            desc.setValue("canEditAsText", Boolean.FALSE); // NOI18N
1022
}
1023    }
1024
1025    private SchemaUIContext context;
1026    private SchemaComponentReference<T> reference;
1027    private Set JavaDoc<Component> referenceSet;
1028    /** Ordered list of highlights applied to this node. */
1029    private List JavaDoc<Highlight> highlights;
1030    private InstanceContent lookupContents;
1031    private PropertyChangeListener JavaDoc modelListener;
1032    private PropertyChangeListener JavaDoc weakModelListener;
1033    private ComponentListener weakComponentListener;
1034    private SoftReference JavaDoc<Customizer> custRef;
1035    private static final GotoType[] GOTO_TYPES = new GotoType[] {
1036        new SourceGotoType(),
1037        new SchemaGotoType(),
1038        new DesignGotoType(),
1039        new SuperGotoType(),
1040    };
1041
1042    /**
1043     * Implement ReferenceableProvider
1044     *
1045     *
1046     * @returns NamedReferenceable used by Refactoring Find Usage, Safe Delete,
1047     * and Rename
1048     */

1049    public NamedReferenceable getReferenceable() {
1050        SchemaComponent comp = reference.get();
1051        if (comp instanceof NamedReferenceable && isValid() && comp.getModel().
1052                getModelSource().getLookup().lookup(FileObject.class) != null){
1053            return NamedReferenceable.class.cast(comp);
1054        }
1055        return null;
1056    }
1057    
1058    /**
1059     * This api is used to set the back pointer to the ReadOnlySchemaComponentNode,
1060     * which represents this node on UI in case of refrenced components.
1061     */

1062    public void setReferencingNode(final Node referencingNode) {
1063        getLookupContents().add(
1064                new ReferencingNodeProvider() {
1065            public Node getNode() {
1066                return referencingNode;
1067            }
1068        });
1069    }
1070}
1071
Popular Tags