2
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
6
* The contents of this file are subject to the terms of either the GNU
7
* General Public License Version 2 only ("GPL") or the Common
8
* Development and Distribution License("CDDL") (collectively, the
9
* "License"). You may not use this file except in compliance with the
10
* License. You can obtain a copy of the License at
11
* http://www.netbeans.org/cddl-gplv2.html
12
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
* specific language governing permissions and limitations under the
14
* License. When distributing the software, include this License Header
15
* Notice in each file and include the License file at
16
* nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
17
* particular file as subject to the "Classpath" exception as provided
18
* by Sun in the GPL Version 2 section of the License file that
19
* accompanied this code. If applicable, add the following below the
20
* License Header, with the fields enclosed by brackets [] replaced by
21
* your own identifying information:
22
* "Portions Copyrighted [year] [name of copyright owner]"
26
* The Original Software is NetBeans. The Initial Developer of the Original
27
* Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
28
* Microsystems, Inc. All Rights Reserved.
30
* If you wish your version of this file to be governed by only the CDDL
31
* or only the GPL Version 2, indicate your decision by adding
32
* "[Contributor] elects to include this software in this distribution
33
* under the [CDDL or GPL Version 2] license." If you do not indicate a
34
* single choice of license, a recipient has the option to distribute
35
* your version of this file under either the CDDL, the GPL Version 2 or
36
* to extend the choice of license to its licensees as provided above.
37
* However, if you add GPL Version 2 code and therefore, elected the GPL
38
* Version 2 license, then the option applies only if the new code is
39
* made subject to such option by the copyright holder.
42
package org.netbeans.modules.xml.schema.ui.nodes;
44
import java.awt.Dialog;
45
import java.awt.datatransfer.Transferable;
46
import java.beans.FeatureDescriptor;
47
import java.beans.PropertyChangeEvent;
48
import java.beans.PropertyChangeListener;
49
import java.beans.PropertyEditor;
50
import java.beans.PropertyEditorSupport;
51
import java.io.IOException;
52
import java.lang.ref.SoftReference;
53
import java.lang.reflect.InvocationTargetException;
54
import java.util.ArrayList;
55
import java.util.Collections;
56
import java.util.LinkedList;
57
import java.util.List;
59
import javax.swing.Action;
60
import org.netbeans.modules.refactoring.api.ui.RefactoringActionsFactory;
61
import org.netbeans.modules.xml.refactoring.spi.SharedUtils;
63
//import org.netbeans.modules.xml.refactoring.actions.RefactorAction;
64
import org.netbeans.modules.xml.refactoring.ui.ReferenceableProvider;
65
import org.netbeans.modules.xml.schema.model.Annotation;
66
import org.netbeans.modules.xml.schema.model.Documentation;
67
import org.netbeans.modules.xml.schema.model.ReferenceableSchemaComponent;
68
import org.netbeans.modules.xml.schema.model.Schema;
69
import org.netbeans.modules.xml.schema.model.SchemaComponent;
70
import org.netbeans.modules.xml.schema.model.SchemaComponentReference;
71
import org.netbeans.modules.xml.schema.model.SchemaModel;
72
import org.netbeans.modules.xml.schema.ui.basic.DesignGotoType;
73
import org.netbeans.modules.xml.schema.ui.basic.SchemaGotoType;
74
import org.netbeans.modules.xml.schema.ui.basic.SchemaSettings;
75
import org.netbeans.modules.xml.schema.ui.basic.UIUtilities;
76
import org.netbeans.modules.xml.xam.dom.Utils;
77
import org.netbeans.modules.xml.xam.ui.ComponentPasteType;
78
import org.netbeans.modules.xml.xam.ui.actions.GotoType;
79
import org.netbeans.modules.xml.xam.ui.actions.SourceGotoType;
80
import org.netbeans.modules.xml.xam.ui.actions.SuperGotoType;
81
import org.netbeans.modules.xml.xam.ui.cookies.GetComponentCookie;
82
import org.netbeans.modules.xml.xam.ui.cookies.GetSuperCookie;
83
import org.netbeans.modules.xml.xam.Component;
84
import org.netbeans.modules.xml.xam.ComponentEvent;
85
import org.netbeans.modules.xml.xam.ComponentListener;
86
import org.netbeans.modules.xml.xam.Nameable;
87
import org.netbeans.modules.xml.xam.Named;
88
import org.netbeans.modules.xml.xam.NamedReferenceable;
89
import org.netbeans.modules.xml.schema.ui.basic.ShowSchemaAction;
90
import org.netbeans.modules.xml.xam.ui.cookies.GotoCookie;
91
import org.netbeans.modules.xml.xam.ui.customizer.Customizer;
92
import org.netbeans.modules.xml.xam.ui.customizer.CustomizerProvider;
93
import org.netbeans.modules.xml.xam.ui.highlight.Highlight;
94
import org.netbeans.modules.xml.xam.ui.highlight.HighlightManager;
95
import org.netbeans.modules.xml.xam.ui.highlight.Highlighted;
96
import org.netbeans.modules.xml.schema.ui.basic.editors.StringEditor;
97
import org.netbeans.modules.xml.schema.ui.nodes.schema.properties.BaseSchemaProperty;
98
import org.netbeans.modules.xml.xam.ui.XAMUtils;
99
import org.netbeans.modules.xml.xam.ui.actions.GoToAction;
100
import org.netbeans.modules.xml.xam.ui.cookies.CountChildrenCookie;
101
import org.openide.DialogDescriptor;
102
import org.openide.DialogDisplayer;
103
import org.openide.ErrorManager;
104
import org.openide.actions.CopyAction;
105
import org.openide.actions.CutAction;
106
import org.openide.actions.DeleteAction;
107
import org.openide.actions.NewAction;
108
import org.openide.actions.PasteAction;
109
import org.openide.actions.PropertiesAction;
110
import org.openide.actions.ReorderAction;
111
import org.openide.explorer.propertysheet.ExPropertyEditor;
112
import org.openide.explorer.propertysheet.PropertyEnv;
113
import org.openide.filesystems.FileObject;
114
import org.openide.loaders.DataObject;
115
import org.openide.loaders.DataObjectNotFoundException;
116
import org.openide.nodes.AbstractNode;
117
import org.openide.nodes.Children;
118
import org.openide.nodes.Index;
119
import org.openide.nodes.Node;
120
import org.openide.nodes.Node.Property;
121
import org.openide.nodes.PropertySupport;
122
import org.openide.nodes.Sheet;
123
import org.openide.util.HelpCtx;
124
import org.openide.util.Lookup;
125
import org.openide.util.NbBundle;
126
import org.openide.util.WeakListeners;
127
import org.openide.util.actions.SystemAction;
128
import org.openide.util.datatransfer.NewType;
129
import org.openide.util.datatransfer.PasteType;
130
import org.openide.util.lookup.AbstractLookup;
131
import org.openide.util.lookup.InstanceContent;
132
import org.openide.util.lookup.Lookups;
133
import org.openide.util.lookup.ProxyLookup;
137
* @author Todd Fast, todd.fast@sun.com
138
* @author Nathan Fiedler
140
public abstract class SchemaComponentNode<T extends SchemaComponent>
142
implements Node.Cookie, ComponentListener, PropertyChangeListener,
143
Highlighted, ReferenceableProvider, CountChildrenCookie,
144
GetComponentCookie, GetSuperCookie, GotoCookie {
150
public SchemaComponentNode(SchemaUIContext context,
151
SchemaComponentReference<T> reference, Children children) {
152
this(context,reference,children,new InstanceContent());
157
* Constructor HACK to allow creating of our own lookup
160
private SchemaComponentNode(SchemaUIContext context,
161
SchemaComponentReference<T> reference, Children children,
162
InstanceContent contents) {
163
super(children, createLookup(context, contents));
165
this.context=context;
166
this.reference=reference;
167
this.lookupContents=contents;
169
// Add various objects to the lookup.
171
// Include the data object in order for the Navigator to
172
// show the structure of the current document.
173
DataObject dobj = getDataObject();
177
contents.add(context);
178
contents.add(reference);
179
contents.add(new DefaultExpandedCookie(false));
180
// // add customizer provider if provided
181
// CustomizerProvider provider = getCustomizerProvider();
182
// if (provider != null) {
183
// contents.add(provider);
186
// reorder must be enabled only if its editable node
187
if (children instanceof Index && isEditable() &&
188
// dont show for schema bug 80138
189
!(reference.get() instanceof Schema)) {
190
contents.add(children);
192
T comp = reference.get();
195
// Listen to changes in the model using a WeakListener. I hold onto
196
// the WeakListener instance so I can explicitly remove it in the
198
SchemaModel model = reference.get().getModel();
201
WeakListeners.propertyChange(this,model);
202
model.addPropertyChangeListener(weakModelListener);
203
weakComponentListener = (ComponentListener) WeakListeners.create(
204
ComponentListener.class, this, model);
205
model.addComponentListener(weakComponentListener);
207
// Determine default names for the node
208
if (comp instanceof Named) {
209
// Just set the name, and let the method call below handle
211
_setName(((Named) comp).getName());
213
_setName(comp.getPeer().getLocalName());
215
// Need a model for the following to work properly.
217
// Let the node try to update its display name
219
// Let the node try to update its short desc
220
updateShortDescription();
223
setIconBaseWithExtension(
224
"org/netbeans/modules/xml/schema/ui/nodes/resources/"+
227
referenceSet = Collections.singleton(
228
(Component) ((SchemaComponentReference) reference).get());
229
highlights = new LinkedList<Highlight>();
230
HighlightManager.getDefault().addHighlighted(this);
234
* Create a lookup for this node, based on the given contents.
236
* @param context from which a Lookup is retrieved.
237
* @param contents the basis of our new lookup.
239
private static Lookup createLookup(SchemaUIContext context,
240
InstanceContent contents) {
241
// We want our lookup to be based on the lookup from the context,
242
// which provides a few necessary objects, such as a SaveCookie.
243
// However, we do not want the Nodes or DataObjects, since we
245
return new ProxyLookup(new Lookup[] {
246
// Keep our lookup contents first, so that whatever we add to
247
// the lookup is at the top of the lookup, such as this node,
248
// which provides certain cookies, rather than that of the
249
// currently selected node.
250
new AbstractLookup(contents),
251
Lookups.exclude(context.getLookup(), new Class[] {
259
* Attempt to retrieve the DataObject associated with the model that
260
* contains the component this node represents.
262
* @return schema data object, if available, or null if not.
264
private DataObject getDataObject() {
266
// Include the data object in order for the Navigator to
267
// show the structure of the current document.
268
SchemaModel model = reference.get().getModel();
270
FileObject fobj = (FileObject) model.getModelSource().
271
getLookup().lookup(FileObject.class);
273
return DataObject.find(fobj);
276
} catch (DataObjectNotFoundException donfe) {
277
// fall through to return null
283
* This api returns the customizer provider.
284
* Subclasses must override this api to return appropriate
285
* customizer provider
287
protected CustomizerProvider getCustomizerProvider() {
292
* Overriden to provide custom customizer.
293
* Gets the customizer component from customizer provider
294
* and displays it as modal dialog.
295
* Subclasses who provide customizer should override
296
* hasCustomizer and return true.
299
public java.awt.Component getCustomizer() {
300
if(!hasCustomizer()|| !isEditable()) return null;
301
// get it from soft ref
302
if(custRef==null || custRef.get()==null) {
303
CustomizerProvider cp = getCustomizerProvider();
304
if (cp==null) return null;
305
Customizer cust = cp.getCustomizer();
306
if (cust==null || cust.getComponent()==null) return null;
307
custRef = new SoftReference<Customizer>(cust);
309
// might not be in sync so sync
310
custRef.get().reset();
312
Customizer customizer = custRef.get();
313
DialogDescriptor descriptor = UIUtilities.
314
getCustomizerDialog(customizer,getTypeDisplayName(),isEditable());
315
Dialog dlg = DialogDisplayer.getDefault().createDialog(descriptor);
316
dlg.getAccessibleContext().setAccessibleDescription(dlg.getTitle());
324
public boolean equals(Object o) {
325
// Without this, the tree view collapses when nodes are changed.
326
if (o instanceof SchemaComponentNode) {
327
SchemaComponentNode scn = (SchemaComponentNode) o;
328
SchemaComponentReference scr = scn.getReference();
329
return scr.equals(reference);
339
public int hashCode() {
340
// Without this, the tree view collapses when nodes are changed.
341
return reference.hashCode();
349
public SchemaUIContext getContext() {
358
public SchemaComponentReference<T> getReference() {
364
* Returns the contents of the lookup. All cookies and other objects that
365
* should be findable via the lookup should be added to this.
368
protected InstanceContent getLookupContents() {
369
return lookupContents;
373
* Determines if this node represents a component that is contained
374
* in a valid (non-null) model.
376
* @return true if model is valid, false otherwise.
378
protected boolean isValid() {
379
return getReference().get().getModel() != null;
383
* Determines if this node represents a component that is contained
386
* @return true if component is editable, false otherwise.
388
protected boolean isEditable() {
389
SchemaModel model = getReference().get().getModel();
390
return model != null && model == getContext().getModel() &&
391
XAMUtils.isWritable(model);
395
* Used by subclasses to update the display name as needed. The default
396
* implementation updates the display name for named schema components.
397
* Note, this method may be called from the constructor, so be sure to
398
* avoid using member variables!
401
protected void updateDisplayName() {
403
// If there is no model, exceptions will occur.
406
T component = getReference().get();
407
if (component instanceof Named) {
408
String name=((Named)component).getName();
409
// Automatically keep the name in sync for named schema components.
411
if(name==null||name.equals("")) name = component.getPeer().getLocalName();
412
setDisplayName(name);
418
* updates the short descrption associated with node.
419
* checks for if there is any annotation with documentation element.
421
private void updateShortDescription() {
423
// If there is no model, exceptions will occur.
426
T component = getReference().get();
427
Documentation d = null;
429
String language = SchemaSettings.getDefault().getLanguage();
430
if (component instanceof Documentation) {
431
d = (Documentation) component;
432
} else if (component instanceof Annotation) {
433
a = (Annotation) component;
435
a = component.getAnnotation();
437
if (a != null && !a.getDocumentationElements().isEmpty()) {
439
d = a.getDocumentationElements().iterator().next();
441
for (Documentation doc:a.getDocumentationElements()) {
442
if(language.equals(doc.getLanguage())) {
448
d = a.getDocumentationElements().iterator().next();
453
setShortDescription(d.getContentFragment());
455
setShortDescription(null);
464
public abstract String getTypeDisplayName();
471
protected String getHtmlTypeDisplayName() {
472
return "<font color='#aaaaaa'>("+getTypeDisplayName()+")</font>";
480
public boolean isDefaultExpanded() {
481
DefaultExpandedCookie cookie=(DefaultExpandedCookie)
482
getCookie(DefaultExpandedCookie.class);
484
return cookie.isDefaultExpanded();
494
public void setDefaultExpanded(boolean value) {
495
DefaultExpandedCookie cookie=(DefaultExpandedCookie)
496
getCookie(DefaultExpandedCookie.class);
498
cookie.setDefaultExpanded(value);
503
* Finds the super definition of the schema component.
504
* Returns null as default implementation
505
* Subclasses which fave global type or reference definitions,
506
* must override to return the global reference.
508
protected ReferenceableSchemaComponent getSuperDefinition() {
512
public int getChildCount() {
513
return getReference().get().getChildren().size();
516
public Component getComponent() {
517
return getReference().get();
520
public Class<? extends Component> getComponentType() {
521
return getReference().get().getComponentType();
524
// implementation of get super cookie
525
public SchemaComponent getSuper()
527
return getSuperDefinition();
531
////////////////////////////////////////////////////////////////////////////
533
////////////////////////////////////////////////////////////////////////////
540
public HelpCtx getHelpCtx() {
541
if(this instanceof SchemaComponentNode)
542
return new HelpCtx(SchemaComponentNode.class);
543
return new HelpCtx(getClass());
552
public boolean canCut() {
562
public boolean canCopy() {
567
@SuppressWarnings("unchecked")
568
protected void createPasteTypes(Transferable transferable, List list) {
569
if (isValid() && isEditable()) {
570
PasteType type = ComponentPasteType.getPasteType(
571
reference.get(), transferable, null);
579
public PasteType getDropType(Transferable transferable, int action, int index) {
580
if (isValid() && isEditable()) {
581
PasteType type = ComponentPasteType.getDropType(
582
reference.get(), transferable, null, action, index);
591
public boolean canDestroy() {
592
SchemaComponent component = getReference().get();
593
if (component instanceof Schema || !isEditable()) {
605
public boolean canRename() {
606
return supportsRename();
611
* Indicates if the component is nameable.
613
* @return true if nameable, false otherwise.
615
private boolean isNameable() {
616
// Need to check the component type instead of the component, to
617
// avoid allowing rename of an element reference, in which the
618
// implementation extends Nameable.
619
return Nameable.class.isAssignableFrom(
620
getReference().get().getComponentType());
625
* Indicates if the component can be renamed.
627
* @return true if nameable, false otherwise.
629
private boolean supportsRename() {
630
// check if its nameable and editable
631
return isNameable() && isEditable();
636
* Set the name property directly without adjusting the associated model
639
private void _setName(String value) {
640
// prevent NPE from explorermanager
641
if(value==null) value="";
642
super.setName(value);
651
public void setName(String value) {
652
NamedReferenceable ref = getReferenceable();
656
if (supportsRename())
660
getReference().get().getModel().startTransaction();
661
Nameable n = (Nameable)getReference().get();
666
getReference().get().getModel().endTransaction();
672
SharedUtils.locallyRenameRefactor((Nameable)ref, value);
677
* Checks for references to this component, and if none are found,
678
* remove it from the model.
680
public void destroy() throws IOException {
681
SchemaModel model = getReference().get().getModel();
684
// this node might have been deleted from model as a result of
685
// deletion of its parent. get model from context and remove
686
// listeners. no need to remove it again from model.
687
model = getContext().getModel();
688
model.removeComponentListener(weakComponentListener);
689
model.removePropertyChangeListener(weakModelListener);
691
model.removeComponentListener(weakComponentListener);
692
model.removePropertyChangeListener(weakModelListener);
694
// Remove the component from the model.
695
SchemaComponent component = getReference().get();
697
model.startTransaction();
698
model.removeChildComponent(component);
699
//need to provide a hook
702
model.endTransaction();
709
* This is a hook for the subclasses if they want to do something special in the same transaction.
710
* For example, when an import gets deleted, we should also remove the namespace declaration.
712
protected void cleanup() {
713
//default implementation needs to be empty
714
//subclasses should override, if they want do extra stuff inside the same transaction.
715
//See AdvancedImportNode for details.
724
protected Sheet createSheet() {
726
Sheet sheet=Sheet.createDefault();
727
Sheet.Set set=sheet.get(Sheet.PROPERTIES);
729
new PropertySupport("kind",String.class,
730
NbBundle.getMessage(SchemaComponentNode.class,
731
"PROP_SchemaComponentNode_Kind"),
733
public Object getValue() {
734
return getTypeDisplayName();
737
public void setValue(Object value) {
744
Property idProperty = new BaseSchemaProperty((SchemaComponent)getReference().get(),
746
SchemaComponent.ID_PROPERTY,
747
NbBundle.getMessage(SchemaComponentNode.class,
748
"PROP_SchemaComponentNode_ID"),
749
NbBundle.getMessage(SchemaComponentNode.class,
750
"PROP_SchemaComponentNode_IDDesc"),
753
public void setValue(Object o) throws
754
IllegalAccessException, InvocationTargetException {
755
if (o instanceof String) {
757
super.setValue(null);
758
} else if (Utils.isValidNCName(o.toString())){
761
String msg = NbBundle.getMessage(BaseSchemaProperty.class,
762
"MSG_Neg_Int_Value", o); //NOI18N
763
IllegalArgumentException iae = new IllegalArgumentException(msg);
764
ErrorManager.getDefault().annotate(iae, ErrorManager.USER,
765
msg, msg, null, new java.util.Date());
773
set.put(new SchemaModelFlushWrapper(getReference().get(), idProperty));
774
} catch (NoSuchMethodException nsme) {
775
assert false: "properties must be defined";
778
// If we are a named node, display that in the property sheet
780
set.put(new PropertySupport.Name(this));
782
if(hasCustomizer()&&isEditable()) {
783
Property structureProp = new PropertySupport.ReadWrite("structure", //NOI18N
785
NbBundle.getMessage(SchemaComponentNode.class,
786
"PROP_SchemaComponentNode_Customize"),
787
NbBundle.getMessage(SchemaComponentNode.class,
788
"PROP_SchemaComponentNode_Customize_ShortDesc")) {
789
public Object getValue() throws IllegalAccessException,InvocationTargetException {
790
return NbBundle.getMessage(SchemaComponentNode.class,
791
"PROP_SchemaComponentNode_Customize_Label");
793
public void setValue(Object val) throws IllegalAccessException,IllegalArgumentException,InvocationTargetException {
795
public PropertyEditor getPropertyEditor() {
796
return new StructurePropertyEditor();
799
set.put(structureProp);
806
* Indicates if this node should allow reordering of its children.
807
* The default implementation allows reordering only if there is
808
* more than one child component.
810
* @return true if reordering of this node's children is permitted.
812
protected boolean allowReordering() {
813
// Check if we have more than one physical child in the model.
814
// Using the node children count results in too many index out
815
// of bounds exceptions.
816
return getReference().get().getChildren().size() > 1;
820
public Action[] getActions(boolean context) {
821
ReadOnlyCookie roc = (ReadOnlyCookie) getContext().getLookup().lookup(
822
ReadOnlyCookie.class);
823
List<Action> actions = new ArrayList<Action>();
824
if (roc != null && roc.isReadOnly()) {
825
// Set of actions for read-only components.
826
actions.add(SystemAction.get(GoToAction.class));
828
// Set of actions for modifiable components.
829
actions.add(SystemAction.get(CutAction.class));
830
actions.add(SystemAction.get(CopyAction.class));
831
actions.add(SystemAction.get(PasteAction.class));
833
actions.add(SystemAction.get(NewAction.class));
834
actions.add(SystemAction.get(DeleteAction.class));
835
if (allowReordering()) {
836
actions.add(SystemAction.get(ReorderAction.class));
839
actions.add(SystemAction.get(GoToAction.class));
840
//actions.add(SystemAction.get(FindUsagesAction.class));
841
//new action based on new refactoring API
842
actions.add(RefactoringActionsFactory.whereUsedAction());
844
//actions.add(SystemAction.get(RefactorAction.class));
845
//new action based on new refactoring API
846
actions.add(RefactoringActionsFactory.editorSubmenuAction());
848
actions.add(SystemAction.get(PropertiesAction.class));
850
return actions.toArray(new Action[actions.size()]);
854
public Action getPreferredAction() {
855
// This exists for use in the Navigator.
856
ReadOnlyCookie roc = (ReadOnlyCookie) getCookie(ReadOnlyCookie.class);
857
if (roc != null && roc.isReadOnly()) {
858
return SystemAction.get(ShowSchemaAction.class);
860
return super.getPreferredAction();
865
* This api returns the factory which gives back new types for this node.
866
* Default FactoryImpl provides addition of annotation.
867
* Subclasses can override this api to allow addition of their allowed
870
protected NewTypesFactory getNewTypesFactory() {
871
return new NewTypesFactory();
874
public final NewType[] getNewTypes() {
876
return getNewTypesFactory().getNewTypes(getReference(), null);
878
return new NewType[] {};
881
public GotoType[] getGotoTypes() {
885
////////////////////////////////////////////////////////////////////////////
887
////////////////////////////////////////////////////////////////////////////
889
public void childrenAdded(ComponentEvent evt) {
891
if(evt.getSource() == getReference().get())
893
((RefreshableChildren) getChildren()).refreshChildren();
895
if(evt.getSource() == getReference().get() ||
896
evt.getSource() == getReference().get().getAnnotation())
898
updateShortDescription();
903
public void childrenDeleted(ComponentEvent evt) {
905
if(evt.getSource() == getReference().get())
907
((RefreshableChildren) getChildren()).refreshChildren();
909
if(evt.getSource() == getReference().get() ||
910
evt.getSource() == getReference().get().getAnnotation())
912
updateShortDescription();
917
public void valueChanged(ComponentEvent evt) {
920
T component = getReference().get();
921
if(evt.getSource() == component)
925
Documentation d = null;
926
if(component instanceof Documentation)
927
d = (Documentation)component;
928
else if(component instanceof Annotation)
930
Annotation a = (Annotation)component;
931
if(!a.getDocumentationElements().isEmpty())
932
d = a.getDocumentationElements().iterator().next();
936
Annotation a = component.getAnnotation();
937
if(a!=null && !a.getDocumentationElements().isEmpty())
938
d = a.getDocumentationElements().iterator().next();
940
if(evt.getSource()==d)
942
updateShortDescription();
948
* Reacts to granular property change events from model.
949
* Updates displayname if needed.
950
* Fires properties changed events if needed.
951
* Subclasses override if needed.
953
public void propertyChange(PropertyChangeEvent event) {
954
if (isValid() && event.getSource() == getReference().get()) {
957
String propName = event.getPropertyName();
958
Sheet.Set propertySet = getSheet().get(Sheet.PROPERTIES);
959
if(propertySet!=null){
960
if (propertySet.get(propName)!=null) {
961
firePropertyChange(propName,event.getOldValue(),
962
event.getNewValue());
965
ErrorManager.getDefault().log(ErrorManager.INFORMATIONAL,
966
propName + " property is not defined in " +
967
getTypeDisplayName());
970
} catch (IllegalStateException ise) {
971
// Component is not in the model.
972
ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ise);
973
} catch (NullPointerException npe) {
974
// Does not reproduce reliably, but catch and log regardless.
975
ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, npe);
980
public Set<Component> getComponents() {
984
public void highlightAdded(Highlight hl) {
986
fireDisplayNameChange("TempName", getDisplayName());
989
public void highlightRemoved(Highlight hl) {
990
highlights.remove(hl);
991
fireDisplayNameChange("TempName", getDisplayName());
995
* Given a display name, add the appropriate HTML tags to highlight
996
* the display name as dictated by any Highlights associated with
999
* @param name current display name.
1000
* @return marked up display name.
1002
protected String applyHighlights(String name) {
1003
int count = highlights.size();
1005
// Apply the last highlight that was added to our list.
1006
Highlight hl = highlights.get(count - 1);
1007
String type = hl.getType();
1011
if (type.equals(Highlight.SEARCH_RESULT)) {
1013
} else if (type.equals(Highlight.SEARCH_RESULT_PARENT)) {
1015
} else if (type.equals(Highlight.FIND_USAGES_RESULT_PARENT)) {
1016
code = "B5E682"; // was c7ff3c chartreuse
1017
}else if (type.equals(Highlight.FIND_USAGES_RESULT)) {
1018
code = "8be62c"; // darker green
1020
name = "<strong><font color=\"#" + code + "\">" + name +
1026
public String getDisplayName() {
1027
String instanceName = getDefaultDisplayName();
1028
return instanceName.length()==0 ? instanceName :
1029
instanceName + " " + "[" + getTypeDisplayName() + "]"; // NOI18N
1032
public String getDefaultDisplayName() {
1033
String instanceName = super.getDisplayName();
1034
return instanceName == null || instanceName.length() == 0
1035
? "" : instanceName;
1038
public String getHtmlDisplayName() {
1039
String name = getDefaultDisplayName();
1040
// Need to escape any HTML meta-characters in the name.
1042
name = name.replace("<", "<").replace(">", ">");
1043
return applyHighlights(name);
1046
////////////////////////////////////////////////////////////////////////////
1048
////////////////////////////////////////////////////////////////////////////
1050
private class StructurePropertyEditor extends PropertyEditorSupport
1051
implements ExPropertyEditor {
1052
public boolean supportsCustomEditor() {
1056
public java.awt.Component getCustomEditor() {
1057
return getCustomizer();
1060
public void attachEnv(PropertyEnv env ) {
1061
FeatureDescriptor desc = env.getFeatureDescriptor();
1062
desc.setValue("canEditAsText", Boolean.FALSE); // NOI18N
1066
private SchemaUIContext context;
1067
private SchemaComponentReference<T> reference;
1068
private Set<Component> referenceSet;
1069
/** Ordered list of highlights applied to this node. */
1070
private List<Highlight> highlights;
1071
private InstanceContent lookupContents;
1072
private PropertyChangeListener modelListener;
1073
private PropertyChangeListener weakModelListener;
1074
private ComponentListener weakComponentListener;
1075
private SoftReference<Customizer> custRef;
1076
private static final GotoType[] GOTO_TYPES = new GotoType[] {
1077
new SourceGotoType(),
1078
new SchemaGotoType(),
1079
new DesignGotoType(),
1080
new SuperGotoType(),
1084
* Implement ReferenceableProvider
1087
* @returns NamedReferenceable used by Refactoring Find Usage, Safe Delete,
1090
public NamedReferenceable getReferenceable() {
1091
SchemaComponent comp = reference.get();
1092
if (comp instanceof NamedReferenceable && isValid() && comp.getModel().
1093
getModelSource().getLookup().lookup(FileObject.class) != null){
1094
return NamedReferenceable.class.cast(comp);
1100
* This api is used to set the back pointer to the ReadOnlySchemaComponentNode,
1101
* which represents this node on UI in case of refrenced components.
1103
public void setReferencingNode(final Node referencingNode) {
1104
getLookupContents().add(
1105
new ReferencingNodeProvider() {
1106
public Node getNode() {
1107
return referencingNode;