KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > xml > wsdl > ui > netbeans > module > WSDLEditorSupport


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.wsdl.ui.netbeans.module;
21
22 import java.awt.EventQueue JavaDoc;
23 import java.io.IOException JavaDoc;
24 import java.io.Serializable JavaDoc;
25 import java.util.ArrayList JavaDoc;
26 import java.util.Enumeration JavaDoc;
27 import java.util.List JavaDoc;
28 import java.util.Set JavaDoc;
29 import javax.swing.text.AbstractDocument JavaDoc;
30 import javax.swing.text.StyledDocument JavaDoc;
31 import org.netbeans.core.api.multiview.MultiViewHandler;
32 import org.netbeans.core.api.multiview.MultiViews;
33 import org.netbeans.core.spi.multiview.CloseOperationHandler;
34 import org.netbeans.core.spi.multiview.CloseOperationState;
35 import org.netbeans.modules.xml.retriever.catalog.Utilities;
36 import org.netbeans.modules.xml.wsdl.model.WSDLModel;
37 import org.netbeans.modules.xml.wsdl.model.WSDLModelFactory;
38 import org.netbeans.modules.xml.xam.ModelSource;
39 import org.netbeans.modules.xml.xam.ui.undo.QuietUndoManager;
40 import org.openide.DialogDisplayer;
41 import org.openide.NotifyDescriptor;
42 import org.openide.awt.UndoRedo;
43 import org.openide.cookies.CloseCookie;
44 import org.openide.cookies.EditCookie;
45 import org.openide.cookies.EditorCookie;
46 import org.openide.cookies.LineCookie;
47 import org.openide.cookies.OpenCookie;
48 import org.openide.filesystems.FileLock;
49 import org.openide.filesystems.FileObject;
50 import org.openide.loaders.DataObject;
51 import org.openide.text.CloneableEditor;
52 import org.openide.text.CloneableEditorSupport;
53 import org.openide.text.CloneableEditorSupport.Pane;
54 import org.openide.text.DataEditorSupport;
55 import org.openide.util.NbBundle;
56 import org.openide.util.Task;
57 import org.openide.util.TaskListener;
58 import org.openide.windows.CloneableTopComponent;
59 import org.openide.windows.Mode;
60 import org.openide.windows.TopComponent;
61 import org.openide.windows.WindowManager;
62
63
64 /**
65  *
66  * @author Jeri Lockhart
67  * @author Todd Fast, todd.fast@sun.com
68  */

69 public class WSDLEditorSupport extends DataEditorSupport
70         implements WSDLModelCookie, OpenCookie, EditCookie,
71         EditorCookie.Observable, LineCookie, CloseCookie {
72     /** Used for managing the prepareTask listener. */
73     private transient Task prepareTask2;
74
75     /**
76      *
77      *
78      */

79     public WSDLEditorSupport(WSDLDataObject sobj) {
80         super(sobj, new WSDLEditorEnv(sobj));
81         setMIMEType("text/xml");
82         //TODO: we need to use below one eventually
83
//setMIMEType(WSDLDataLoader.MIME_TYPE);
84
}
85     
86     
87     /**
88      *
89      *
90      */

91     public WSDLEditorEnv getEnv() {
92         return (WSDLEditorEnv)env;
93     }
94
95     @Override JavaDoc
96     protected Pane createPane() {
97         TopComponent tc = WSDLMultiViewFactory.createMultiView(
98                 (WSDLDataObject) getDataObject());
99         // Note that initialization of the editor happens separately,
100
// and we only need to handle that during the initial creation
101
// of the text editor.
102
Mode editorMode = WindowManager.getDefault().findMode(
103                 WSDLEditorSupport.EDITOR_MODE);
104         if (editorMode != null) {
105             editorMode.dockInto(tc);
106         }
107         return (Pane) tc;
108     }
109
110     /**
111      *
112      *
113      */

114     public static boolean isLastView(TopComponent tc) {
115         
116         if (!(tc instanceof CloneableTopComponent))
117             return false;
118         
119         boolean oneOrLess = true;
120         Enumeration JavaDoc en =
121             ((CloneableTopComponent)tc).getReference().getComponents();
122         if (en.hasMoreElements()) {
123             en.nextElement();
124             if (en.hasMoreElements())
125                 oneOrLess = false;
126         }
127         
128         return oneOrLess;
129     }
130     
131     // Change method access to public
132
@Override JavaDoc
133     public void initializeCloneableEditor(CloneableEditor editor) {
134         super.initializeCloneableEditor(editor);
135         // Force the title to update so the * left over from when the
136
// modified data object was discarded is removed from the title.
137
EventQueue.invokeLater(new Runnable JavaDoc() {
138             public void run() {
139                 // Have to do this later to avoid infinite loop.
140
updateTitles();
141             }
142         });
143     }
144     
145     @Override JavaDoc
146     protected void updateTitles() {
147         // This method is invoked by DataEditorSupport.DataNodeListener
148
// whenever the DataNode displayName property is changed. It is
149
// also called when the CloneableEditorSupport is (un)modified.
150

151         // Let the superclass handle the CloneableEditor instances.
152
super.updateTitles();
153
154         // We need to get the title updated on the MultiViewTopComponent.
155
EventQueue.invokeLater(new Runnable JavaDoc() {
156             public void run() {
157                 // Create a list of TopComponents associated with the
158
// editor's data object, starting with the active
159
// TopComponent. Add all open TopComponents in any
160
// mode that are associated with the DataObject.
161
// [Note that EDITOR_MODE does not contain editors in
162
// split mode.]
163
List JavaDoc<TopComponent> associatedTCs = new ArrayList JavaDoc<TopComponent>();
164                 DataObject targetDO = getDataObject();
165                 TopComponent activeTC = TopComponent.getRegistry().getActivated();
166                 if (activeTC != null && targetDO == (DataObject) activeTC.getLookup().lookup(
167                         DataObject.class)) {
168                     associatedTCs.add(activeTC);
169                 }
170                 Set JavaDoc openTCs = TopComponent.getRegistry().getOpened();
171                 for (Object JavaDoc tc : openTCs) {
172                     TopComponent tcc = (TopComponent) tc;
173                     if (targetDO == (DataObject) tcc.getLookup().lookup(
174                             DataObject.class)) {
175                         associatedTCs.add(tcc);
176                     }
177                 }
178                 for (TopComponent tc : associatedTCs) {
179                     // Make sure this is a multiview window, and not just some
180
// window that has our DataObject (e.g. Projects, Files).
181
MultiViewHandler mvh = MultiViews.findMultiViewHandler(tc);
182                     if (mvh != null) {
183                         tc.setHtmlDisplayName(messageHtmlName());
184                         String JavaDoc name = messageName();
185                         tc.setDisplayName(name);
186                         tc.setName(name);
187                         tc.setToolTipText(messageToolTip());
188                     }
189                 }
190             }
191         });
192     }
193
194     @Override JavaDoc
195     protected UndoRedo.Manager createUndoRedoManager() {
196         // Override so the superclass will use our proxy undo manager
197
// instead of the default, then we can intercept edits.
198
return new QuietUndoManager(super.createUndoRedoManager());
199         // Note we cannot set the document on the undo manager right
200
// now, as CES is probably trying to open the document.
201
}
202
203     /**
204      * Returns the UndoRedo.Manager instance managed by this editor support.
205      *
206      * @return UndoRedo.Manager instance.
207      */

208     public QuietUndoManager getUndoManager() {
209         return (QuietUndoManager) getUndoRedo();
210     }
211
212     @Override JavaDoc
213     public Task prepareDocument() {
214         Task task = super.prepareDocument();
215         // Avoid listening to the same task more than once.
216
if (task != prepareTask2) {
217             prepareTask2 = task;
218             task.addTaskListener(new TaskListener() {
219                 public void taskFinished(Task task) {
220                     QuietUndoManager undo = getUndoManager();
221                     StyledDocument JavaDoc doc = getDocument();
222                     synchronized (undo) {
223                         // Now that the document is ready, pass it to the manager.
224
undo.setDocument((AbstractDocument JavaDoc) doc);
225                         if (!undo.isCompound()) {
226                             // The superclass prepareDocument() adds the undo/redo
227
// manager as a listener -- we need to remove it since
228
// we will initially listen to the model instead.
229
doc.removeUndoableEditListener(undo);
230                             // If not listening to document, then listen to model.
231
addUndoManagerToModel(undo);
232                         }
233                     }
234                     prepareTask2 = null;
235                 }
236             });
237         }
238         return task;
239     }
240     public Task reloadDocument() {
241         Task task = super.reloadDocument();
242         task.addTaskListener(new TaskListener() {
243             public void taskFinished(Task task) {
244                 EventQueue.invokeLater(new Runnable JavaDoc() {
245                     public void run() {
246                         QuietUndoManager undo = getUndoManager();
247                         StyledDocument JavaDoc doc = getDocument();
248                         // The superclass reloadDocument() adds the undo
249
// manager as an undoable edit listener.
250
synchronized (undo) {
251                             if (!undo.isCompound()) {
252                                 doc.removeUndoableEditListener(undo);
253                             }
254                         }
255                     }
256                 });
257             }
258         });
259         return task;
260     }
261
262     protected void notifyClosed() {
263         // Stop listening to the undoable edit sources when we are closed.
264
QuietUndoManager undo = getUndoManager();
265         StyledDocument JavaDoc doc = getDocument();
266         synchronized (undo) {
267             // May be null when closing the editor.
268
if (doc != null) {
269                 doc.removeUndoableEditListener(undo);
270                 undo.endCompound();
271                 undo.setDocument(null);
272             }
273             try {
274                 WSDLModel model = getModel();
275                 if (model != null) {
276                     model.removeUndoableEditListener(undo);
277                 }
278                 // Must unset the model when no longer listening to it.
279
undo.setModel(null);
280             } catch (IOException JavaDoc ioe) {
281                 // Model is gone, but just removing the listener is not
282
// going to matter anyway.
283
}
284         }
285         super.notifyClosed();
286     }
287
288     public WSDLModel getModel() throws IOException JavaDoc {
289     WSDLDataObject dobj = getEnv().getWSDLDataObject();
290     ModelSource modelSource = Utilities.getModelSource(dobj.getPrimaryFile(), true);
291         if(modelSource != null) {
292             return WSDLModelFactory.getDefault().getModel(modelSource);
293         }
294     
295         return null;
296     }
297
298     /**
299      * Adds the undo/redo manager to the document as an undoable edit
300      * listener, so it receives the edits onto the queue. The manager
301      * will be removed from the model as an undoable edit listener.
302      *
303      * <p>This method may be called repeatedly.</p>
304      */

305     public void addUndoManagerToDocument() {
306         // This method may be called repeatedly.
307
// Stop the undo manager from listening to the model, as it will
308
// be listening to the document now.
309
QuietUndoManager undo = getUndoManager();
310         StyledDocument JavaDoc doc = getDocument();
311         synchronized (undo) {
312             try {
313                 WSDLModel model = getModel();
314                 if (model != null) {
315                     model.removeUndoableEditListener(undo);
316                 }
317                 // Must unset the model when no longer listening to it.
318
undo.setModel(null);
319             } catch (IOException JavaDoc ioe) {
320                 // Model is gone, but just removing the listener is not
321
// going to matter anyway.
322
}
323             // Document may be null if the cloned views are not behaving correctly.
324
if (doc != null) {
325                 // Ensure the listener is not added twice.
326
doc.removeUndoableEditListener(undo);
327                 doc.addUndoableEditListener(undo);
328                 // Start the compound mode of the undo manager, such that when
329
// we are hidden, we will treat all of the edits as a single
330
// compound edit. This avoids having the user invoke undo
331
// numerous times when in the model view.
332
undo.beginCompound();
333             }
334         }
335     }
336
337     /**
338      * Removes the undo/redo manager undoable edit listener from the
339      * document, to stop receiving undoable edits. The manager will
340      * be added to the model as an undoable edit listener.
341      *
342      * <p>This method may be called repeatedly.</p>
343      */

344     public void removeUndoManagerFromDocument() {
345         // This method may be called repeatedly.
346
QuietUndoManager undo = getUndoManager();
347         StyledDocument JavaDoc doc = getDocument();
348         synchronized (undo) {
349             // May be null when closing the editor.
350
if (doc != null) {
351                 doc.removeUndoableEditListener(undo);
352                 undo.endCompound();
353             }
354             // Have the undo manager listen to the model when it is not
355
// listening to the document.
356
addUndoManagerToModel(undo);
357         }
358     }
359
360     /**
361      * Add the undo/redo manager undoable edit listener to the model.
362      *
363      * <p>Caller should synchronize on the undo manager prior to calling
364      * this method, to avoid thread concurrency issues.</p>
365      *
366      * @param undo the undo manager.
367      */

368     private void addUndoManagerToModel(QuietUndoManager undo) {
369         // This method may be called repeatedly.
370
try {
371             WSDLModel model = getModel();
372             if (model != null) {
373                 // Ensure the listener is not added twice.
374
model.removeUndoableEditListener(undo);
375                 model.addUndoableEditListener(undo);
376                 // Ensure the model is sync'd when undo/redo is invoked,
377
// otherwise the edits are added to the queue and eventually
378
// cause exceptions.
379
undo.setModel(model);
380             }
381         } catch (IOException JavaDoc ioe) {
382             // Model is gone, nothing will work, return immediately.
383
}
384     }
385
386     /**
387      * This method allows the close behavior of CloneableEditorSupport to be
388      * invoked from the SourceMultiViewElement. The close method of
389      * CloneableEditorSupport at least clears the undo queue and releases
390      * the swing document.
391      */

392     public boolean silentClose() {
393     return super.close(false);
394     }
395
396     /**
397      * Have the WSDL model sync with the document.
398      */

399     public void syncModel() {
400         // Only sync the document if the change relates to loss of focus,
401
// which indicates that we are switching from the source view.
402
// Update the tree with the modified text.
403
try {
404             if(getModel() != null) {
405                 getModel().sync();
406             }
407         } catch (Throwable JavaDoc ioe) {
408             // The document cannot be parsed
409
NotifyDescriptor nd = new NotifyDescriptor.Message(NbBundle.getMessage(WSDLEditorSupport.class, "MSG_NotWellformedWsdl"), NotifyDescriptor.ERROR_MESSAGE);
410             DialogDisplayer.getDefault().notify(nd);
411         }
412         
413     }
414     
415     ////////////////////////////////////////////////////////////////////////////
416
// Inner class
417
////////////////////////////////////////////////////////////////////////////
418

419     /**
420      * Env class extends DataEditorSupport.Env.
421      */

422     protected static class WSDLEditorEnv extends DataEditorSupport.Env {
423         
424         static final long serialVersionUID =1099957785497677206L;
425         
426         public WSDLEditorEnv(WSDLDataObject obj) {
427             super(obj);
428         }
429         
430         public CloneableEditorSupport findTextEditorSupport() {
431             return getWSDLDataObject().getWSDLEditorSupport();
432         }
433         
434         public WSDLDataObject getWSDLDataObject(){
435             return (WSDLDataObject) getDataObject();
436         }
437         
438         @Override JavaDoc
439         protected FileObject getFile() {
440             return getDataObject().getPrimaryFile();
441         }
442         
443         @Override JavaDoc
444         protected FileLock takeLock() throws IOException JavaDoc {
445             return getDataObject().getPrimaryFile().lock();
446         }
447     }
448     
449     
450     
451     
452     ////////////////////////////////////////////////////////////////////////////
453
// Inner class
454
////////////////////////////////////////////////////////////////////////////
455

456     /**
457      * Implementation of CloseOperationHandler for multiview. Ensures both
458      * column view and xml editor are correctly closed, data saved, etc. Holds
459      * a reference to DataObject only - to be serializable with the
460      * multiview TopComponent without problems.
461      */

462     public static class CloseHandler implements CloseOperationHandler, Serializable JavaDoc {
463         private static final long serialVersionUID =-3838395157610633251L;
464         private DataObject dataObject;
465
466         private CloseHandler() {
467             super();
468         }
469
470         public CloseHandler(DataObject dobj) {
471             dataObject = dobj;
472         }
473
474         private WSDLEditorSupport getWSDLEditorSupport() {
475             return dataObject instanceof WSDLDataObject ?
476                 ((WSDLDataObject) dataObject).getWSDLEditorSupport() : null;
477         }
478
479         public boolean resolveCloseOperation(CloseOperationState[] elements) {
480             WSDLEditorSupport wsdlEditor = getWSDLEditorSupport();
481         boolean canClose = wsdlEditor != null ? wsdlEditor.canClose() : true;
482         // during the shutdown sequence this is called twice. The first time
483
// through the multi-view infrastructure. The second time is done through
484
// the TopComponent close. If the file is dirty and the user chooses
485
// to discard changes, the second time will also ask whether the
486
// to save or discard changes.
487
if (canClose) {
488         dataObject.setModified(false);
489         }
490         return canClose;
491         }
492     }
493 }
494
Popular Tags