001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package org.netbeans.modules.vmd.io.javame;
042:
043: import org.netbeans.core.api.multiview.MultiViewHandler;
044: import org.netbeans.core.api.multiview.MultiViewPerspective;
045: import org.netbeans.core.api.multiview.MultiViews;
046: import org.netbeans.core.spi.multiview.CloseOperationHandler;
047: import org.netbeans.core.spi.multiview.CloseOperationState;
048: import org.netbeans.core.spi.multiview.MultiViewDescription;
049: import org.netbeans.core.spi.multiview.MultiViewFactory;
050: import org.netbeans.modules.mobility.editor.pub.J2MEDataObject;
051: import org.netbeans.modules.mobility.editor.pub.J2MEDataObject.J2MEEditorSupport;
052: import org.netbeans.modules.vmd.api.io.DataEditorView;
053: import org.netbeans.modules.vmd.api.io.IOUtils;
054: import org.netbeans.modules.vmd.api.io.ProjectTypeInfo;
055: import org.netbeans.modules.vmd.api.io.providers.DocumentSerializer;
056: import org.netbeans.modules.vmd.api.io.providers.IOSupport;
057: import org.netbeans.spi.editor.guards.GuardedEditorSupport;
058: import org.netbeans.spi.editor.guards.GuardedSectionsFactory;
059: import org.netbeans.spi.editor.guards.GuardedSectionsProvider;
060: import org.openide.awt.UndoRedo;
061: import org.openide.cookies.EditCookie;
062: import org.openide.cookies.EditorCookie;
063: import org.openide.cookies.OpenCookie;
064: import org.openide.cookies.PrintCookie;
065: import org.openide.filesystems.FileLock;
066: import org.openide.filesystems.FileSystem;
067: import org.openide.text.CloneableEditor;
068: import org.openide.text.CloneableEditorSupport;
069: import org.openide.util.Utilities;
070: import org.openide.windows.CloneableTopComponent;
071: import org.openide.windows.TopComponent;
072:
073: import javax.swing.text.BadLocationException;
074: import javax.swing.text.EditorKit;
075: import javax.swing.text.StyledDocument;
076: import java.io.*;
077: import org.netbeans.api.project.Project;
078: import org.netbeans.modules.mobility.project.J2MEProject;
079: import org.netbeans.modules.vmd.api.io.DataObjectContext;
080: import org.netbeans.modules.vmd.api.io.ProjectUtils;
081: import org.netbeans.modules.vmd.api.io.serialization.DocumentErrorHandler;
082: import org.netbeans.modules.vmd.api.io.serialization.DocumentErrorHandlerSupport;
083: import org.openide.util.NbBundle;
084:
085: /**
086: * @author David Kaspar
087: */
088: // TODO - save cookie is not added/removed to/from MEDesignEditorSupport based on the saveDocument, notifyModified, notifyUnmodified, notifyClosed
089: public final class MEDesignEditorSupport extends J2MEEditorSupport
090: implements EditorCookie.Observable, OpenCookie, EditCookie,
091: PrintCookie {
092:
093: private MEDesignDataObject dataObject;
094: private CloseOperationHandler closeHandler;
095: private TopComponent mvtc;
096:
097: private MultiViewDescription[] descriptions;
098: private boolean useEditPriority;
099:
100: private GuardsEditor guardsEditor;
101: private GuardedSectionsProvider sections;
102: private UndoRedo.Manager undoRedoManager;
103:
104: // private boolean sourceEditorOpened = false;
105:
106: private FileSystem.AtomicAction atomicSaveAction = new FileSystem.AtomicAction() {
107: public void run() throws IOException {
108: saveDocumentCore();
109: }
110:
111: public int hashCode() {
112: return getClass().hashCode();
113: }
114:
115: public boolean equals(Object obj) {
116: return getClass().equals(obj.getClass());
117: }
118: };
119:
120: public MEDesignEditorSupport(MEDesignDataObject dataObject) {
121: super (dataObject, new Env(dataObject));
122: this .dataObject = dataObject;
123: closeHandler = new CloseHandler(dataObject);
124: }
125:
126: @Override
127: public void saveDocument() throws IOException {
128: dataObject.getPrimaryFile().getFileSystem().runAtomicAction(
129: atomicSaveAction);
130: }
131:
132: public void saveDocumentCore() throws IOException {
133: DocumentSerializer documentSerializer = IOSupport
134: .getDocumentSerializer(dataObject);
135: documentSerializer.waitDocumentLoaded();
136: IOSupport.forceUpdateCode(dataObject);
137: documentSerializer.saveDocument();
138: super .saveDocument();
139: }
140:
141: @Override
142: public boolean notifyModified() {
143: if (!super .notifyModified()) {
144: return false;
145: }
146: updateDisplayName();
147: return true;
148: }
149:
150: @Override
151: protected void notifyUnmodified() {
152: super .notifyUnmodified();
153: updateDisplayName();
154: }
155:
156: @Override
157: protected void notifyClosed() {
158: mvtc = null;
159: super .notifyClosed();
160: IOSupport.notifyDataObjectClosed(dataObject);
161: }
162:
163: @Override
164: public void open() {
165: useEditPriority = false;
166: DataObjectContext context = IOSupport
167: .getDataObjectContext(dataObject);
168: Project project = ProjectUtils.getProject(context);
169: if (project == null || !(project instanceof J2MEProject)) {
170: DocumentErrorHandler errorHandler = new DocumentErrorHandler()
171: .addError(NbBundle.getMessage(
172: MEDesignEditorSupport.class,
173: "MSG_ProjectMissing")); //NOI18N
174: DocumentErrorHandlerSupport.showDocumentErrorHandlerDialog(
175: errorHandler, dataObject.getPrimaryFile());
176: return;
177: }
178: String projectType = IOSupport.resolveProjectType(context);
179: if (projectType == null)
180: return;
181:
182: super .open();
183:
184: TopComponent mvtc = this .mvtc;
185: if (mvtc != null) {
186: MultiViewHandler handler = MultiViews
187: .findMultiViewHandler(mvtc);
188: int index = getIndex();
189: if (index >= 0) {
190: MultiViewPerspective perspective = handler
191: .getPerspectives()[index];
192: handler.requestActive(perspective);
193: handler.requestVisible(perspective);
194: }
195: }
196: }
197:
198: @Override
199: public void edit() {
200: useEditPriority = true;
201:
202: String projectType = IOSupport.resolveProjectType(IOSupport
203: .getDataObjectContext(dataObject));
204: if (projectType == null)
205: return;
206: super .open();
207:
208: TopComponent mvtc = this .mvtc;
209: if (mvtc != null) {
210: MultiViewHandler handler = MultiViews
211: .findMultiViewHandler(mvtc);
212: int index = getIndex();
213: if (index >= 0) {
214: MultiViewPerspective perspective = handler
215: .getPerspectives()[index];
216: handler.requestActive(perspective);
217: handler.requestVisible(perspective);
218: }
219: }
220: }
221:
222: private int getIndex() {
223: MultiViewDescription[] descriptions = this .descriptions;
224: if (descriptions == null)
225: return -1;
226: int bestPriority = Integer.MIN_VALUE;
227: int bestIndex = -1;
228: int index = 0;
229: for (MultiViewDescription description : this .descriptions) {
230: DataEditorView dataEditorView = IOSupport
231: .getDataEditorView(description);
232: int priority = useEditPriority ? dataEditorView
233: .getEditPriority() : dataEditorView
234: .getOpenPriority();
235: if (priority > bestPriority) {
236: bestPriority = priority;
237: bestIndex = index;
238: }
239: index++;
240: }
241: return bestIndex;
242: }
243:
244: @Override
245: public void initializeCloneableEditor(CloneableEditor editor) {
246: super .initializeCloneableEditor(editor);
247: }
248:
249: @Override
250: protected Pane createPane() {
251: String projectType = IOSupport.resolveProjectType(IOSupport
252: .getDataObjectContext(dataObject));
253: if (projectType == null)
254: return super .createPane();
255: descriptions = IOSupport.createEditorSupportPane(IOSupport
256: .getDataObjectContext(dataObject));
257: int index = getIndex();
258: return (CloneableEditorSupport.Pane) MultiViewFactory
259: .createCloneableMultiView(descriptions,
260: index >= 0 ? descriptions[index] : null,
261: closeHandler);
262: }
263:
264: public void setMVTC(TopComponent mvtc) {
265: this .mvtc = mvtc;
266: updateDisplayName();
267: }
268:
269: @Override
270: protected CloneableTopComponent createCloneableTopComponent() {
271: CloneableTopComponent tc = super .createCloneableTopComponent();
272: this .mvtc = tc;
273: updateDisplayName();
274: return tc;
275: }
276:
277: public void updateDisplayName() {
278: final TopComponent tc = mvtc;
279: if (tc == null)
280: return;
281: IOUtils.runInAWTNoBlocking(new Runnable() {
282: public void run() {
283: ProjectTypeInfo projectTypeInfo = ProjectTypeInfo
284: .getProjectTypeInfoFor(IOSupport
285: .getDataObjectContext(dataObject)
286: .getProjectType());
287: tc.setIcon(projectTypeInfo != null ? Utilities
288: .loadImage(projectTypeInfo.getIconResource())
289: : null);
290:
291: String displayName = messageName();
292: if (!displayName.equals(tc.getDisplayName()))
293: tc.setDisplayName(displayName);
294: tc
295: .setToolTipText(dataObject.getPrimaryFile()
296: .getPath());
297: }
298: });
299: }
300:
301: // public Line.Set getLineSet () {
302: // if (! sourceEditorOpened && mvtc != null) {
303: // sourceEditorOpened = true;
304: // MultiViewHandler handler = MultiViews.findMultiViewHandler(mvtc);
305: // for (MultiViewPerspective perspective : handler.getPerspectives()) {
306: // if (perspective.getDisplayName().equals(ProjectUtils.getSourceEditorViewDisplayName ())) {
307: // handler.requestVisible(perspective);
308: // break;
309: // }
310: // }
311: // }
312: // return super.getLineSet ();
313: // }
314:
315: @Override
316: protected UndoRedo.Manager createUndoRedoManager() {
317: undoRedoManager = super .createUndoRedoManager();
318: return undoRedoManager;
319: }
320:
321: void discardAllEdits() {
322: undoRedoManager.discardAllEdits();
323: }
324:
325: FileSystem.AtomicAction getAtomicSaveAction() {
326: return atomicSaveAction;
327: }
328:
329: @Override
330: protected void loadFromStreamToKitHook(StyledDocument doc,
331: InputStream stream, EditorKit kit) throws IOException,
332: BadLocationException {
333: if (sections == null) {
334: guardsEditor = new GuardsEditor(doc);
335: String mimeType = ((CloneableEditorSupport.Env) this .env)
336: .getMimeType();
337: GuardedSectionsFactory factory = GuardedSectionsFactory
338: .find(mimeType);
339: sections = factory.create(guardsEditor);
340: } else {
341: guardsEditor.setDocument(doc);
342: }
343:
344: if (sections != null) {
345: Reader reader = sections.createGuardedReader(stream,
346: getEncoding());
347: try {
348: kit.read(reader, doc, 0);
349: } finally {
350: reader.close();
351: }
352: } else {
353: super .loadFromStreamToKitHook(doc, stream, kit);
354: }
355: }
356:
357: @Override
358: protected void saveFromKitToStreamHook(StyledDocument doc,
359: EditorKit kit, OutputStream stream) throws IOException,
360: BadLocationException {
361: if (sections != null) {
362: Writer w = sections.createGuardedWriter(stream,
363: getEncoding());
364: try {
365: kit.write(w, doc, 0, doc.getLength());
366: } finally {
367: w.close();
368: }
369: } else {
370: super .saveFromKitToStream(doc, kit, stream);
371: }
372: }
373:
374: protected static class Env extends J2MEEditorSupport.Environment {
375:
376: private static final long serialVersionUID = -1;
377:
378: public Env(J2MEDataObject obj) {
379: super (obj);
380: }
381:
382: protected FileLock takeLock() throws IOException {
383: FileLock l;
384: try {
385: l = super .takeLock();
386: IOSupport.setDocumentUpdatingEnabled(getDataObject(),
387: true);
388: return l;
389: } catch (IOException e) {
390: IOSupport.setDocumentUpdatingEnabled(getDataObject(),
391: false);
392: throw e;
393: }
394: }
395:
396: }
397:
398: private static class CloseHandler implements CloseOperationHandler,
399: Serializable {
400:
401: private static final long serialVersionUID = -1;
402: private MEDesignDataObject dataObject;
403:
404: public CloseHandler(MEDesignDataObject dataObject) {
405: this .dataObject = dataObject;
406: }
407:
408: public boolean resolveCloseOperation(
409: CloseOperationState[] elements) {
410: MEDesignEditorSupport editorSupport = dataObject
411: .getEditorSupport();
412: boolean can = editorSupport.canClose();
413: if (can)
414: editorSupport.notifyClosed();
415: return can;
416: }
417:
418: }
419:
420: private class GuardsEditor implements GuardedEditorSupport {
421:
422: private StyledDocument document;
423:
424: public GuardsEditor(StyledDocument document) {
425: this .document = document;
426: }
427:
428: public StyledDocument getDocument() {
429: return document;
430: }
431:
432: public void setDocument(StyledDocument document) {
433: this.document = document;
434: }
435:
436: }
437:
438: }
|