001: /*
002: * The contents of this file are subject to the terms of the Common Development
003: * and Distribution License (the License). You may not use this file except in
004: * compliance with the License.
005: *
006: * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
007: * or http://www.netbeans.org/cddl.txt.
008: *
009: * When distributing Covered Code, include this CDDL Header Notice in each file
010: * and include the License file at http://www.netbeans.org/cddl.txt.
011: * If applicable, add the following below the CDDL Header, with the fields
012: * enclosed by brackets [] replaced by your own identifying information:
013: * "Portions Copyrighted [year] [name of copyright owner]"
014: *
015: * The Original Software is NetBeans. The Initial Developer of the Original
016: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
017: * Microsystems, Inc. All Rights Reserved.
018: */
019: package org.netbeans.modules.xslt.tmap;
020:
021: import java.awt.event.ActionEvent;
022: import java.io.IOException;
023: import java.util.LinkedList;
024: import java.util.List;
025: import java.util.concurrent.atomic.AtomicBoolean;
026: import java.util.concurrent.atomic.AtomicReference;
027: import javax.swing.AbstractAction;
028: import javax.swing.Action;
029: import javax.xml.transform.Source;
030: import org.netbeans.modules.xslt.tmap.model.api.TMapModel;
031: import org.netbeans.modules.xslt.tmap.multiview.TMapMultiViewSupport;
032: import org.netbeans.spi.xml.cookies.DataObjectAdapters;
033: import org.netbeans.spi.xml.cookies.TransformableSupport;
034: import org.openide.cookies.SaveCookie;
035: import org.openide.filesystems.FileObject;
036: import org.openide.loaders.DataNode;
037: import org.openide.loaders.DataObjectExistsException;
038: import org.openide.loaders.MultiDataObject;
039: import org.openide.nodes.Children;
040: import org.openide.nodes.CookieSet;
041: import org.openide.nodes.Node;
042: import org.openide.util.HelpCtx;
043: import org.openide.util.Lookup;
044: import org.openide.util.NbBundle;
045: import org.openide.util.lookup.AbstractLookup;
046: import org.openide.util.lookup.InstanceContent;
047: import org.openide.util.lookup.Lookups;
048: import org.openide.util.lookup.ProxyLookup;
049:
050: /**
051: * @author Vitaly Bychkov
052: * @version 1.0
053: */
054: public class TMapDataObject extends MultiDataObject {
055: private static final long serialVersionUID = 1L;
056: private static final String IMAGE_ICON_BASE = "org/netbeans/modules/xslt/tmap/resources/tmap.png";
057: private static final String FILE_DESC = "LBL_FileNode_desc"; // NOI18N
058:
059: private transient TMapDataEditorSupport myDataEditorSupport;
060: private transient AtomicReference<Lookup> myLookup = new AtomicReference<Lookup>();
061: private transient AtomicReference<InstanceContent> myServices = new AtomicReference<InstanceContent>();
062: private transient AtomicBoolean isLookupInit = new AtomicBoolean(
063: false);
064:
065: public TMapDataObject(FileObject pf, TMapDataLoader loader)
066: throws DataObjectExistsException, IOException {
067: super (pf, loader);
068: myDataEditorSupport = new TMapDataEditorSupport(this );
069:
070: CookieSet cookies = getCookieSet();
071: cookies.add(getEditorSupport());
072:
073: // add check and validate cookies
074: // InputSource is = DataObjectAdapters.inputSource (this);
075: // cookies.add(new CheckXMLSupport (is));
076: // cookies.add(new ValidateXSLSupport (is));
077:
078: // add xsl transform support
079: Source source = DataObjectAdapters.source(this );
080: cookies.add(new TransformableSupport(source));
081: }
082:
083: /**
084: * the name and location of the transformation descriptor
085: * are fixed and shouldn't be changed
086: */
087: @Override
088: public boolean isRenameAllowed() {
089: return false;
090: }
091:
092: /**
093: * the name and location of the transformation descriptor
094: * are fixed and shouldn't be changed
095: */
096: @Override
097: public boolean isDeleteAllowed() {
098: return false;
099: }
100:
101: /**
102: * the name and location of the transformation descriptor
103: * are fixed and shouldn't be changed
104: */
105: @Override
106: public boolean isMoveAllowed() {
107: return false;
108: }
109:
110: @Override
111: public HelpCtx getHelpCtx() {
112: return new HelpCtx(TMapDataObject.class);
113: }
114:
115: @Override
116: public void setModified(boolean modified) {
117: super .setModified(modified);
118: if (modified) {
119: getCookieSet().add(getSaveCookie());
120: if (isLookupInit.get()) {
121: myServices.get().add(getSaveCookie());
122: }
123: } else {
124: getCookieSet().remove(getSaveCookie());
125: if (isLookupInit.get()) {
126: myServices.get().remove(getSaveCookie());
127: }
128: }
129: }
130:
131: private SaveCookie getSaveCookie() {
132: return new SaveCookie() {
133:
134: public void save() throws IOException {
135: getEditorSupport().saveDocument();
136: }
137:
138: @Override
139: public int hashCode() {
140: return getClass().hashCode();
141: }
142:
143: @Override
144: public boolean equals(Object other) {
145: return other != null
146: && getClass().equals(other.getClass());
147: }
148: };
149: }
150:
151: @Override
152: protected Node createNodeDelegate() {
153: return new TMapDataNode(this , getEditorSupport());
154: }
155:
156: @Override
157: public Lookup getLookup() {
158: if (myLookup.get() == null) {
159:
160: Lookup lookup;
161: List<Lookup> list = new LinkedList<Lookup>();
162:
163: list.add(Lookups.fixed(new Object[] { super .getLookup(),
164: this }));
165:
166: // add lazy initialization
167: InstanceContent.Convertor<Class, Object> conv = new InstanceContent.Convertor<Class, Object>() {
168:
169: public Object convert(Class obj) {
170: if (obj == TMapModel.class) {
171: return getEditorSupport().getTMapModel();
172: }
173:
174: if (obj == TMapDataEditorSupport.class) {
175: return getEditorSupport();
176: }
177:
178: return null;
179: }
180:
181: public Class type(Class obj) {
182: return obj;
183: }
184:
185: public String id(Class obj) {
186: return obj.toString();
187: }
188:
189: public String displayName(Class obj) {
190: return obj.getName();
191: }
192: };
193:
194: list.add(Lookups.fixed(new Class[] { TMapModel.class,
195: TMapDataEditorSupport.class }, conv));
196: //
197:
198: //
199: // WARNING
200: // CANNOT add Lookups.singleton(getNodeDelegate()) or will stack
201: // overflow
202: // WARNING
203: //
204:
205: /*
206: * Services are used for push/pop SaveCookie in lookup. This allow to work
207: * "Save" action on diagram.
208: */
209: myServices.compareAndSet(null, new InstanceContent());
210: myServices.get().add(new Empty()); // FIX for #IZ78702
211: list.add(new AbstractLookup(myServices.get()));
212:
213: lookup = new ProxyLookup(list.toArray(new Lookup[list
214: .size()]));
215:
216: myLookup.compareAndSet(null, lookup);
217: isLookupInit.compareAndSet(false, true);
218: }
219: return myLookup.get();
220: }
221:
222: public TMapDataEditorSupport getEditorSupport() {
223: return myDataEditorSupport;
224: }
225:
226: private static class TMapDataNode extends DataNode {
227:
228: private TMapDataEditorSupport myEditorSupport;
229:
230: public TMapDataNode(TMapDataObject obj,
231: TMapDataEditorSupport support) {
232: super (obj, Children.LEAF);
233: myEditorSupport = support;
234:
235: getCookieSet().add(obj);
236: setIconBaseWithExtension(IMAGE_ICON_BASE);
237: setShortDescription(NbBundle.getMessage(TMapDataNode.class,
238: FILE_DESC));
239: }
240:
241: @Override
242: public Action getPreferredAction() {
243: return new AbstractAction() {
244: private static final long serialVersionUID = 1L;
245:
246: public void actionPerformed(ActionEvent e) {
247: // Fix for #81066
248: if (myEditorSupport.getOpenedPanes() == null
249: || myEditorSupport.getOpenedPanes().length == 0) {
250: myEditorSupport.open();
251: TMapMultiViewSupport support = TMapMultiViewSupport
252: .getInstance();
253: support.requestViewOpen(myEditorSupport);
254: } else {
255: myEditorSupport.open();
256: }
257: }
258: };
259: }
260:
261: /**
262: * the name and location of the transformation descriptor
263: * are fixed and shouldn't be changed
264: */
265: @Override
266: public boolean canRename() {
267: return false;
268: }
269:
270: /**
271: * the name and location of the transformation descriptor
272: * are fixed and shouldn't be changed
273: */
274: @Override
275: public boolean canDestroy() {
276: return super .canDestroy();
277: }
278:
279: /**
280: * the name and location of the transformation descriptor
281: * are fixed and shouldn't be changed
282: */
283: @Override
284: public boolean canCut() {
285: return super .canCut();
286: }
287:
288: protected boolean isWarning() {
289: return false; // TODO - hook in to dataobject
290: }
291:
292: protected boolean isError() {
293: return false; // TODO - hook in to dataobject
294: }
295:
296: /**
297: * to pick up change in warn/error condition call fireIconChange()
298: */
299: // TODO a
300: //// public Image getIcon(int type) {
301: //// if(!isWarning() && !isError())
302: //// return super.getIcon(type);
303: //// else if(isError()) {
304: //// return BadgedIconCache.getErrorIcon(super.getIcon(type));
305: //// }
306: //// else {
307: //// return BadgedIconCache.getWarningIcon(super.getIcon(type));
308: //// }
309: //// }
310: ////
311: //// public Image getOpenedIcon(int type) {
312: //// if(!isWarning() && !isError())
313: //// return super.getOpenedIcon(type);
314: //// else if(isError()) {
315: //// return BadgedIconCache.getErrorIcon(super.getOpenedIcon(type));
316: //// }
317: //// else {
318: //// return BadgedIconCache.getWarningIcon(super.getOpenedIcon(type));
319: //// }
320: //// }
321: @Override
322: public HelpCtx getHelpCtx() {
323: return new HelpCtx(TMapDataObject.class);
324: }
325:
326: // /** Creates a property sheet. */
327: // protected Sheet createSheet() {
328: // Sheet s = super.createSheet();
329: // Sheet.Set ss = s.get(Sheet.PROPERTIES);
330: // if (ss == null) {
331: // ss = Sheet.createPropertiesSet();
332: // s.put(ss);
333: // }
334: // // TODO add some relevant properties: ss.put(...)
335: // return s;
336: // }
337:
338: }
339:
340: private static class Empty {
341:
342: }
343: }
|