KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > xml > schema > core > multiview > SchemaSourceMultiViewElement


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.core.multiview;
21
22 import java.awt.event.ActionEvent JavaDoc;
23 import java.awt.event.ActionListener JavaDoc;
24 import java.awt.EventQueue JavaDoc;
25 import java.io.IOException JavaDoc;
26 import java.io.ObjectInput JavaDoc;
27 import java.io.ObjectOutput JavaDoc;
28 import java.util.List JavaDoc;
29 import javax.swing.JComponent JavaDoc;
30 import javax.swing.JEditorPane JavaDoc;
31 import javax.swing.Timer JavaDoc;
32 import javax.swing.event.CaretEvent JavaDoc;
33 import javax.swing.event.CaretListener JavaDoc;
34 import javax.swing.text.Document JavaDoc;
35 import javax.swing.text.StyledDocument JavaDoc;
36 import org.netbeans.core.spi.multiview.CloseOperationState;
37 import org.netbeans.core.spi.multiview.MultiViewElement;
38 import org.netbeans.core.spi.multiview.MultiViewElementCallback;
39 import org.netbeans.core.spi.multiview.MultiViewFactory;
40 import org.netbeans.modules.xml.schema.core.SchemaDataObject;
41 import org.netbeans.modules.xml.schema.core.SchemaEditorSupport;
42 import org.netbeans.modules.xml.schema.model.SchemaComponent;
43 import org.netbeans.modules.xml.schema.model.SchemaModel;
44 import org.netbeans.modules.xml.schema.ui.basic.UIUtilities;
45 import org.netbeans.modules.xml.schema.ui.nodes.StructuralSchemaNodeFactory;
46 import org.netbeans.modules.xml.validation.ShowCookie;
47 import org.netbeans.modules.xml.xam.Component;
48 import org.netbeans.modules.xml.xam.spi.Validator.ResultItem;
49 import org.openide.awt.UndoRedo;
50 import org.openide.nodes.Node;
51 import org.openide.nodes.NodeAdapter;
52 import org.openide.nodes.NodeEvent;
53 import org.openide.text.CloneableEditor;
54 import org.openide.text.NbDocument;
55 import org.openide.util.Lookup;
56 import org.openide.util.RequestProcessor;
57 import org.openide.util.lookup.Lookups;
58
59 /**
60  * The source editor for schema documents.
61  *
62  * @author Jeri Lockhart
63  * @author Nathan Fiedler
64  */

65 public class SchemaSourceMultiViewElement extends CloneableEditor
66         implements MultiViewElement {
67     private static final long serialVersionUID = 4403502726950453345L;
68     private transient JComponent JavaDoc toolbar;
69     private transient MultiViewElementCallback multiViewCallback;
70     private SchemaDataObject schemaDataObject;
71
72     /**
73      * Constructs a new instance of SchemaSourceMultiViewElement.
74      */

75     public SchemaSourceMultiViewElement() {
76         // Needed for deserialization, do not remove.
77
super();
78     }
79
80     /**
81      * Constructs a new instance of SchemaSourceMultiViewElement.
82      *
83      * @param dobj schema data object being edited.
84      */

85     public SchemaSourceMultiViewElement(SchemaDataObject dobj) {
86         super(dobj.getSchemaEditorSupport());
87         this.schemaDataObject = dobj;
88
89         // Initialize the editor support properly, which only needs to be
90
// done when the editor is created (deserialization is working
91
// due to CloneableEditor.readResolve() initializing the editor).
92
// Note that this relies on the source view being the first in the
93
// array of MultiViewDescription instances in SchemaMultiViewSupport,
94
// since that results in the source view being created and opened
95
// by default, only to be hidden when the DataObject default action
96
// makes the columns view appear.
97
// This initialization fixes CR 6380287 by ensuring that the Node
98
// listener is registered with the DataObject Node delegate.
99
dobj.getSchemaEditorSupport().initializeCloneableEditor(this);
100         initialize();
101     }
102
103     /**
104      * create lookup, caretlistener, timer
105      */

106     private void initialize() {
107         ShowCookie showCookie = new ShowCookie() {
108             
109             public void show(ResultItem resultItem) {
110                 if(isActiveTC()) {
111                     Component JavaDoc component = resultItem.getComponents();
112                     if(component instanceof SchemaComponent) {
113                         int position = ((SchemaComponent)component).findPosition();
114                         getEditorPane().setCaretPosition(position);
115                     } else {
116                         int line = resultItem.getLineNumber();
117                         try {
118                             int position = NbDocument.findLineOffset(
119                                     (StyledDocument JavaDoc)getEditorPane().getDocument(),line);
120                             getEditorPane().setCaretPosition(position);
121                         } catch (IndexOutOfBoundsException JavaDoc iob) {
122                             // nothing
123
}
124                     }
125                 }
126             }
127         };
128
129         // create and associate lookup
130
Node delegate = schemaDataObject.getNodeDelegate();
131         SourceCookieProxyLookup lookup = new SourceCookieProxyLookup(new Lookup[] {
132             Lookups.fixed(new Object JavaDoc[] {
133                 // Need ActionMap in lookup so editor actions work.
134
getActionMap(),
135                 // Need the data object registered in the lookup so that the
136
// projectui code will close our open editor windows when the
137
// project is closed.
138
schemaDataObject,
139                 // The Show Cookie in lookup to show schema component
140
showCookie,
141             }),
142         },delegate);
143         associateLookup(lookup);
144         addPropertyChangeListener("activatedNodes", lookup);
145
146         caretListener = new CaretListener JavaDoc() {
147             public void caretUpdate(CaretEvent JavaDoc e) {
148                 timerSelNodes.restart();
149             }
150         };
151
152         timerSelNodes = new Timer JavaDoc(1, new ActionListener JavaDoc() {
153             public void actionPerformed(ActionEvent JavaDoc e) {
154                 if (!isActiveTC() || getEditorPane() == null) {
155                     return;
156                 }
157                 selectElementsAtOffset();
158             }
159         });
160         timerSelNodes.setRepeats(false);
161     }
162     
163     public JComponent JavaDoc getToolbarRepresentation() {
164         Document JavaDoc doc = getEditorPane().getDocument();
165         if (doc instanceof NbDocument.CustomToolbar) {
166             if (toolbar == null) {
167                 toolbar = ((NbDocument.CustomToolbar) doc).createToolbar(getEditorPane());
168             }
169             return toolbar;
170         }
171         return null;
172     }
173     
174     public JComponent JavaDoc getVisualRepresentation() {
175     return this;
176     }
177     
178     public void setMultiViewCallback(final MultiViewElementCallback callback) {
179     multiViewCallback = callback;
180     }
181     
182     public void requestVisible() {
183     if (multiViewCallback != null)
184         multiViewCallback.requestVisible();
185     else
186         super.requestVisible();
187     }
188     
189     public void requestActive() {
190     if (multiViewCallback != null)
191         multiViewCallback.requestActive();
192     else
193         super.requestActive();
194     }
195     
196     protected String JavaDoc preferredID() {
197     return getClass().getName();
198     }
199     
200     
201     public UndoRedo getUndoRedo() {
202     return schemaDataObject.getSchemaEditorSupport().getUndoManager();
203     }
204
205     /**
206      * The close last method should be called only for the last clone.
207      * If there are still existing clones this method must return false. The
208      * implementation from the FormEditor always returns true but this is
209      * not the expected behavior. The intention is to close the editor support
210      * once the last editor has been closed, using the silent close to avoid
211      * displaying a new dialog which is already being displayed via the
212      * close handler.
213      */

214     protected boolean closeLast() {
215     SchemaEditorSupport ses = schemaDataObject.getSchemaEditorSupport();
216     JEditorPane JavaDoc[] editors = ses.getOpenedPanes();
217     if (editors == null || editors.length == 0) {
218         return ses.silentClose();
219     }
220     return false;
221     }
222
223     public CloseOperationState canCloseElement() {
224         // if this is not the last cloned xml editor component, closing is OK
225
if (!SchemaMultiViewSupport.isLastView(multiViewCallback.getTopComponent())) {
226             return CloseOperationState.STATE_OK;
227         }
228         // return a placeholder state - to be sure our CloseHandler is called
229
return MultiViewFactory.createUnsafeCloseState(
230                 "ID_TEXT_CLOSING", // dummy ID // NOI18N
231
MultiViewFactory.NOOP_CLOSE_ACTION,
232                 MultiViewFactory.NOOP_CLOSE_ACTION);
233     }
234
235     public void componentActivated() {
236         JEditorPane JavaDoc p = getEditorPane();
237         if (p != null) {
238             p.addCaretListener(caretListener);
239         }
240         if(timerSelNodes!=null) {
241             timerSelNodes.restart();
242         }
243         super.componentActivated();
244         SchemaEditorSupport editor = schemaDataObject.getSchemaEditorSupport();
245         editor.addUndoManagerToDocument();
246     }
247
248     public void componentDeactivated() {
249         // Note: componentDeactivated() is called when the entire
250
// MultiViewTopComponent is deactivated, _not_ when switching
251
// between the multiview elements.
252
JEditorPane JavaDoc p = getEditorPane();
253         if (p != null) {
254             p.removeCaretListener(caretListener);
255         }
256         synchronized (this) {
257             if (selectionTask != null) {
258                 selectionTask.cancel();
259                 selectionTask = null;
260             }
261         }
262         if(timerSelNodes!=null) {
263             timerSelNodes.stop();
264         }
265         super.componentDeactivated();
266         SchemaEditorSupport editor = schemaDataObject.getSchemaEditorSupport();
267         // Sync model before having undo manager listen to the model,
268
// lest we get redundant undoable edits added to the queue.
269
editor.syncModel();
270         editor.removeUndoManagerFromDocument();
271     }
272     
273     public void componentOpened() {
274     super.componentOpened();
275     }
276     
277     public void componentClosed() {
278     super.componentClosed();
279     }
280     
281     public void componentShowing() {
282     super.componentShowing();
283         SchemaEditorSupport editor = schemaDataObject.getSchemaEditorSupport();
284         editor.addUndoManagerToDocument();
285     }
286     
287     public void componentHidden() {
288     super.componentHidden();
289         SchemaEditorSupport editor = schemaDataObject.getSchemaEditorSupport();
290         // Sync model before having undo manager listen to the model,
291
// lest we get redundant undoable edits added to the queue.
292
editor.syncModel();
293         editor.removeUndoManagerFromDocument();
294     }
295     
296     public void writeExternal(ObjectOutput JavaDoc out) throws IOException JavaDoc {
297     // The superclass persists things such as the caret position.
298
super.writeExternal(out);
299     out.writeObject(schemaDataObject);
300     }
301     
302     public void readExternal(ObjectInput JavaDoc in)
303     throws IOException JavaDoc, ClassNotFoundException JavaDoc {
304     super.readExternal(in);
305     // Since we are persistent and not created by the descriptor when
306
// deserialized, we need to retrieve the data object for ourselves.
307
Object JavaDoc firstObject = in.readObject();
308     if (firstObject instanceof SchemaDataObject) {
309         schemaDataObject = (SchemaDataObject) firstObject;
310     }
311     initialize();
312     }
313     
314     // node support
315
/** Root node of schema model */
316     private Node rootNode;
317     /** current selection*/
318     private Node selectedNode;
319     /** listens to selected node destroyed event */
320     private NodeAdapter nl;
321     /** Timer which countdowns the "update selected element node" time. */
322     private Timer JavaDoc timerSelNodes;
323     /** Listener on caret movements */
324     private CaretListener JavaDoc caretListener;
325     /* task */
326     private transient RequestProcessor.Task selectionTask = null;
327  /** Selects element at the caret position. */
328     void selectElementsAtOffset()
329     {
330         if(selectionTask!=null)
331         {
332             selectionTask.cancel();
333             selectionTask = null;
334         }
335         RequestProcessor rp = new RequestProcessor("schema source view processor "+hashCode());
336         selectionTask = rp.create(new Runnable JavaDoc()
337         {
338             public void run()
339             {
340                 if (!isActiveTC() || schemaDataObject == null ||
341                         !schemaDataObject.isValid() || schemaDataObject.isTemplate())
342                 {
343                     return;
344                 }
345                 Node n = findNode(getEditorPane().getCaret().getDot());
346                 // default to node delegate if node not found
347
if(n==null)
348                 {
349                     setActivatedNodes(new Node[] {
350                         schemaDataObject.getNodeDelegate() });
351                 }
352                 else
353                 {
354                     if(selectedNode!=n)
355                     {
356                         if(nl==null)
357                         {
358                             nl = new NodeAdapter()
359                             {
360                                 public void nodeDestroyed(NodeEvent ev)
361                                 {
362                                     if(ev.getNode()==selectedNode)
363                                     {
364                                         selectElementsAtOffset();
365                                     }
366                                 }
367                             };
368                         }
369                         else if(selectedNode!=null)
370                         {
371                             selectedNode.removeNodeListener(nl);
372                         }
373                         selectedNode = n;
374                         selectedNode.addNodeListener(nl);
375                         setActivatedNodes(new Node[] { selectedNode });
376                     }
377                 }
378             }
379         });
380         if(EventQueue.isDispatchThread()) {
381             selectionTask.run();
382         } else {
383             EventQueue.invokeLater(selectionTask);
384         }
385     }
386     
387     private Node findNode(int offset)
388     {
389         try
390         {
391             SchemaEditorSupport support = schemaDataObject.getSchemaEditorSupport();
392             if(support==null) return null;
393             SchemaModel model = support.getModel();
394             if(model==null||model.getState()!=SchemaModel.State.VALID) return null;
395             if(rootNode==null)
396                 rootNode = new StructuralSchemaNodeFactory(support.getModel(),
397                         schemaDataObject.getNodeDelegate().getLookup()).createRootNode();
398             if(rootNode==null) return null;
399             SchemaComponent sc = (SchemaComponent) support.getModel().
400                     findComponent(offset);
401             if(sc==null) return null;
402             List JavaDoc<Node> path = UIUtilities.findPathFromRoot(rootNode,sc);
403             if(!path.isEmpty())
404                 return path.get(path.size()-1);
405         }
406         catch (IOException JavaDoc ioe)
407         {
408         }
409         return null;
410     }
411     
412     protected boolean isActiveTC()
413     {
414         return getRegistry().getActivated() == multiViewCallback.getTopComponent();
415     }
416     
417 }
418
Popular Tags