KickJava   Java API By Example, From Geeks To Geeks.

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


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.BorderLayout JavaDoc;
23 import java.awt.Color JavaDoc;
24 import java.awt.EventQueue JavaDoc;
25 import java.awt.event.ActionEvent JavaDoc;
26 import java.beans.PropertyChangeEvent JavaDoc;
27 import java.beans.PropertyChangeListener JavaDoc;
28 import java.io.IOException JavaDoc;
29 import java.util.logging.Level JavaDoc;
30 import java.util.logging.Logger JavaDoc;
31 import javax.swing.AbstractAction JavaDoc;
32 import javax.swing.Action JavaDoc;
33 import javax.swing.ActionMap JavaDoc;
34 import javax.swing.InputMap JavaDoc;
35 import javax.swing.JButton JavaDoc;
36 import javax.swing.JComponent JavaDoc;
37 import javax.swing.JToolBar JavaDoc;
38 import javax.swing.KeyStroke JavaDoc;
39 import javax.swing.UIManager JavaDoc;
40 import javax.swing.text.BadLocationException JavaDoc;
41 import javax.swing.text.DefaultEditorKit JavaDoc;
42 import javax.swing.text.StyledDocument JavaDoc;
43 import org.netbeans.core.spi.multiview.CloseOperationState;
44 import org.netbeans.core.spi.multiview.MultiViewElement;
45 import org.netbeans.core.spi.multiview.MultiViewElementCallback;
46 import org.netbeans.core.spi.multiview.MultiViewFactory;
47 import org.netbeans.modules.xml.axi.AXIModel;
48 import org.netbeans.modules.xml.axi.AXIModelFactory;
49 import org.netbeans.modules.xml.schema.core.SchemaDataObject;
50 import org.netbeans.modules.xml.schema.core.SchemaEditorSupport;
51 import org.netbeans.modules.xml.schema.model.SchemaComponent;
52 import org.netbeans.modules.xml.schema.model.SchemaModel;
53 import org.netbeans.modules.xml.schema.ui.basic.SchemaColumnsCategory;
54 import org.netbeans.modules.xml.schema.ui.basic.SchemaSettings;
55 import org.netbeans.modules.xml.schema.ui.basic.SchemaSettings.ViewMode;
56 import org.netbeans.modules.xml.schema.ui.basic.SchemaTreeCategory;
57 import org.netbeans.modules.xml.validation.ShowCookie;
58 import org.netbeans.modules.xml.validation.ValidateAction;
59 import org.netbeans.modules.xml.xam.Component;
60 import org.netbeans.modules.xml.xam.Model.State;
61 import org.netbeans.modules.xml.xam.spi.Validator.ResultItem;
62 import org.netbeans.modules.xml.xam.ui.category.Category;
63 import org.netbeans.modules.xml.xam.ui.category.CategoryPane;
64 import org.netbeans.modules.xml.xam.ui.category.DefaultCategoryPane;
65 import org.netbeans.modules.xml.xam.ui.multiview.ActivatedNodesMediator;
66 import org.netbeans.modules.xml.xam.ui.multiview.CookieProxyLookup;
67 import org.netbeans.modules.xml.xam.ui.undo.QuietUndoManager;
68 import org.openide.ErrorManager;
69 import org.openide.actions.FindAction;
70 import org.openide.explorer.ExplorerManager;
71 import org.openide.util.HelpCtx;
72 import org.openide.util.NbBundle;
73 import org.openide.windows.TopComponent;
74 import org.openide.awt.UndoRedo;
75 import org.openide.explorer.ExplorerUtils;
76 import org.openide.nodes.Node;
77 import org.openide.util.Lookup;
78 import org.openide.util.WeakListeners;
79 import org.openide.util.actions.CallbackSystemAction;
80 import org.openide.util.actions.SystemAction;
81 import org.openide.util.lookup.Lookups;
82
83 /**
84  *
85  * @author Jeri Lockhart
86  * @author Todd Fast, todd.fast@sun.com
87  * @author Nathan Fiedler
88  */

89 public class SchemaColumnViewMultiViewElement extends TopComponent
90         implements MultiViewElement, PropertyChangeListener JavaDoc,
91         ExplorerManager.Provider {
92     /** silence compiler warnings */
93     private static final long serialVersionUID = 1L;
94     /** Used in recovery from malformed model. */
95     private static final String JavaDoc EMPTY_DOC =
96             "<schema xmlns=\"http://www.w3.org/2001/XMLSchema\"/>";
97     private SchemaDataObject schemaDataObject;
98     private SchemaModel schemaModel;
99     private String JavaDoc errorMessage;
100     private transient MultiViewElementCallback multiViewCallback;
101     private CategoryPane categoryPane;
102     private transient JToolBar JavaDoc toolbar;
103     private transient javax.swing.JLabel JavaDoc errorLabel = new javax.swing.JLabel JavaDoc();
104     private ExplorerManager manager;
105
106     /**
107      * Nullary constructor for deserialization.
108      */

109     public SchemaColumnViewMultiViewElement() {
110     }
111
112     public SchemaColumnViewMultiViewElement(SchemaDataObject schemaDataObject) {
113         super();
114         this.schemaDataObject = schemaDataObject;
115         try {
116             initialize();
117         } catch (IOException JavaDoc ex) {
118             ErrorManager.getDefault().log(ErrorManager.ERROR,
119                     NbBundle.getMessage(SchemaColumnViewMultiViewElement.class,
120                     "LBL_ColView_not_created"));
121         }
122     }
123
124     private void initialize() throws IOException JavaDoc {
125         SchemaEditorSupport editor = schemaDataObject.getSchemaEditorSupport();
126     manager = new ExplorerManager();
127         // Install our own actions.
128
CallbackSystemAction globalFindAction =
129                 (CallbackSystemAction) SystemAction.get(FindAction.class);
130         Object JavaDoc mapKey = globalFindAction.getActionMapKey();
131     ActionMap JavaDoc map = getActionMap();
132         map.put(mapKey, new ColumnViewFindAction());
133         map.put(DefaultEditorKit.copyAction, ExplorerUtils.actionCopy(manager));
134         map.put(DefaultEditorKit.cutAction, ExplorerUtils.actionCut(manager));
135         map.put(DefaultEditorKit.pasteAction, ExplorerUtils.actionPaste(manager));
136         map.put("delete", ExplorerUtils.actionDelete(manager, false));
137
138         // Define the keyboard shortcuts for the actions.
139
InputMap JavaDoc keys = getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
140         KeyStroke JavaDoc key = (KeyStroke JavaDoc) globalFindAction.getValue(Action.ACCELERATOR_KEY);
141         if (key == null) {
142             key = KeyStroke.getKeyStroke("control F");
143         }
144         keys.put(key, mapKey);
145
146         ShowCookie showCookie = new ShowCookie() {
147             
148             public void show(ResultItem resultItem) {
149                 final Component JavaDoc component = resultItem.getComponents();
150                 if (categoryPane != null && component instanceof SchemaComponent) {
151                     EventQueue.invokeLater(new Runnable JavaDoc() {
152                         public void run() {
153                             categoryPane.getCategory().showComponent(
154                                     (SchemaComponent) component);
155                         }
156                     });
157                 }
158             }
159         };
160         Node delegate = schemaDataObject.getNodeDelegate();
161         ActivatedNodesMediator nodesMediator =
162                 new ActivatedNodesMediator(delegate);
163         nodesMediator.setExplorerManager(this);
164         CookieProxyLookup cpl = new CookieProxyLookup(new Lookup[] {
165             Lookups.fixed(new Object JavaDoc[] {
166                 // Need ActionMap in lookup so our actions are used.
167
map,
168                 // Need the data object registered in the lookup so that the
169
// projectui code will close our open editor windows when the
170
// project is closed.
171
schemaDataObject,
172                 // The Show Cookie in lookup to show schema component
173
showCookie,
174             }),
175             nodesMediator.getLookup(),
176             // The Node delegate Lookup must be the last one in the list
177
// for the CookieProxyLookup to work properly.
178
delegate.getLookup(),
179         }, delegate);
180         associateLookup(cpl);
181         addPropertyChangeListener("activatedNodes", nodesMediator);
182         addPropertyChangeListener("activatedNodes", cpl);
183         setLayout(new BorderLayout JavaDoc());
184         initUI(true);
185     }
186
187     public ExplorerManager getExplorerManager() {
188     return manager;
189     }
190
191     public void propertyChange(PropertyChangeEvent JavaDoc evt) {
192         String JavaDoc property = evt.getPropertyName();
193         if (!SchemaModel.STATE_PROPERTY.equals(property)) {
194             return;
195         }
196         State newState = (State)evt.getNewValue();
197         if (newState == SchemaModel.State.VALID) {
198             errorMessage = null;
199             recreateUI();
200             return;
201         }
202
203         //model is broken
204
if (errorMessage == null) {
205             errorMessage = NbBundle.getMessage(
206                     SchemaColumnViewMultiViewElement.class,
207                     "MSG_NotWellformedSchema");
208         }
209         setActivatedNodes(new Node[] {schemaDataObject.getNodeDelegate()});
210         emptyUI(errorMessage);
211     }
212
213     public SchemaDataObject getSchemaDataObject() {
214         return schemaDataObject;
215     }
216
217     private SchemaModel getSchemaModel() {
218         try {
219             if(schemaModel != null)
220                 return schemaModel;
221             
222             SchemaEditorSupport editor = getSchemaDataObject().getSchemaEditorSupport();
223             schemaModel = editor.getModel();
224             if (schemaModel != null) {
225                 PropertyChangeListener JavaDoc pcl = (PropertyChangeListener JavaDoc)WeakListeners.
226                         create(PropertyChangeListener JavaDoc.class, this, schemaModel);
227                 schemaModel.addPropertyChangeListener(pcl);
228             }
229         } catch (IOException JavaDoc io) {
230             errorMessage = io.getMessage();
231         }
232         
233         return schemaModel;
234     }
235
236     public int getPersistenceType() {
237         return PERSISTENCE_NEVER;
238     }
239
240     public void setMultiViewCallback(MultiViewElementCallback callback) {
241         multiViewCallback = callback;
242     }
243
244     public CloseOperationState canCloseElement() {
245         // if this is not the last cloned designer, closing is OK
246
if (!SchemaMultiViewSupport.isLastView(multiViewCallback.getTopComponent())) {
247             return CloseOperationState.STATE_OK;
248         }
249         // return a placeholder state - to be sure our CloseHandler is called
250
return MultiViewFactory.createUnsafeCloseState(
251                 "ID_SCHEMA_COLUMNVIEW_CLOSING", // dummy ID // NOI18N
252
MultiViewFactory.NOOP_CLOSE_ACTION,
253                 MultiViewFactory.NOOP_CLOSE_ACTION);
254     }
255
256     /**
257      * Indicates if the schema model is in a valid state.
258      *
259      * @return true if schema is valid, false otherwise.
260      */

261     private boolean isSchemaValid() {
262         SchemaEditorSupport editor = schemaDataObject.getSchemaEditorSupport();
263         try {
264             SchemaModel schemaModel = editor.getModel();
265             if (schemaModel != null &&
266                     schemaModel.getState() == SchemaModel.State.VALID) {
267                 return true;
268             }
269         } catch (IOException JavaDoc io) {
270             // Fall through and return false.
271
}
272         return false;
273     }
274
275     /**
276      * Initializes the UI. Here it checks for the state of the underlying
277      * schema model. If valid, draws the UI, else empties the UI with proper
278      * error message.
279      */

280     private void initUI() {
281         initUI(false);
282     }
283
284     private void initUI(boolean reloadOnModelInvalid) {
285         SchemaModel model = getSchemaModel();
286         if (model != null && model.getState() == SchemaModel.State.VALID) {
287             recreateUI();
288             return;
289         }
290
291         if (model != null && reloadOnModelInvalid) {
292             forceResetDocument(model);
293             if (model.getState() == SchemaModel.State.VALID) {
294                 recreateUI();
295                 return;
296             }
297         }
298
299         // If it comes here, either the schema is not well-formed or invalid.
300
if (errorMessage == null) {
301             errorMessage = NbBundle.getMessage(
302                     SchemaColumnViewMultiViewElement.class,
303                     "MSG_NotWellformedSchema");
304         }
305
306         // Empties the UI, with proper error message, when the underlying
307
// schema model is in INVALID/NOT-WELLFORMED state.
308
emptyUI(errorMessage);
309     }
310     
311     /**
312      * Creates the UI. Creates the abeDesigner only if it was null
313      * or the underlying documnet was found modifed externally.
314      */

315     private void recreateUI() {
316         removeAll();
317         if (categoryPane == null) {
318             categoryPane = new DefaultCategoryPane();
319             SchemaModel model = getSchemaModel();
320             Lookup lookup = getLookup();
321             Category columns = new SchemaColumnsCategory(model, lookup);
322             categoryPane.addCategory(columns);
323             Category tree = new SchemaTreeCategory(model, lookup);
324             categoryPane.addCategory(tree);
325             // Set the default view according to the persisted setting.
326
ViewMode mode = SchemaSettings.getDefault().getViewMode();
327             switch (mode) {
328                 case COLUMN:
329                     categoryPane.setCategory(columns);
330                     break;
331                 case TREE:
332                     categoryPane.setCategory(tree);
333                     break;
334             }
335         }
336         // Add the schema category pane as our primary interface.
337
add(categoryPane.getComponent(), BorderLayout.CENTER);
338         revalidate();
339         repaint();
340     }
341     
342     /**
343      * Empties the UI, with proper error message, when the underlying
344      * schema model is in INVALID/NOT-WELLFORMED state.
345      */

346     private void emptyUI(String JavaDoc errorMessage) {
347         removeAll();
348         errorLabel.setText("<" + errorMessage + ">");
349         errorLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
350         errorLabel.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
351         Color JavaDoc usualWindowBkg = UIManager.getColor("window"); //NOI18N
352
errorLabel.setBackground(usualWindowBkg != null ? usualWindowBkg :
353             Color.white);
354         errorLabel.setOpaque(true);
355         add(errorLabel, BorderLayout.CENTER);
356         revalidate();
357         repaint();
358     }
359
360     /**
361      * Adds the undo/redo manager to the schema model as an undoable
362      * edit listener, so it receives the edits onto the queue.
363      */

364     private void addUndoManager() {
365         SchemaModel model = getSchemaModel();
366         if (model != null) {
367             SchemaEditorSupport editor = schemaDataObject.getSchemaEditorSupport();
368             QuietUndoManager undo = editor.getUndoManager();
369             // Ensure the listener is not added twice.
370
model.removeUndoableEditListener(undo);
371             model.addUndoableEditListener(undo);
372             // Ensure the model is sync'd when undo/redo is invoked,
373
// otherwise the edits are added to the queue and eventually
374
// cause exceptions.
375
undo.setModel(model);
376             AXIModel aModel = AXIModelFactory.getDefault().getModel(model);
377             undo.removeWrapperModel(aModel);
378         }
379     }
380     
381     public void componentActivated() {
382         super.componentActivated();
383         addUndoManager();
384         ExplorerUtils.activateActions(manager, true);
385     }
386
387     public void componentDeactivated() {
388         super.componentDeactivated();
389     ExplorerUtils.activateActions(manager, false);
390     }
391
392     public void componentOpened() {
393         super.componentOpened();
394     }
395
396     public void componentClosed() {
397         super.componentClosed();
398     }
399
400     public void componentShowing() {
401         super.componentShowing();
402         initUI();
403         addUndoManager();
404         if (categoryPane != null) {
405             Category cat = categoryPane.getCategory();
406             if (cat != null) {
407                 cat.componentShown();
408             }
409         }
410     }
411
412     public void componentHidden() {
413         super.componentHidden();
414         if (categoryPane != null) {
415             Category cat = categoryPane.getCategory();
416             if (cat != null) {
417                 cat.componentHidden();
418             }
419         }
420     }
421
422     @SuppressWarnings JavaDoc("deprecation")
423     public void requestFocus() {
424         super.requestFocus();
425         // For Help to work properly, need to take focus.
426
if (categoryPane != null) {
427             categoryPane.getComponent().requestFocus();
428         }
429     }
430
431     @SuppressWarnings JavaDoc("deprecation")
432     public boolean requestFocusInWindow() {
433         boolean retVal = super.requestFocusInWindow();
434         // For Help to work properly, need to take focus.
435
if (categoryPane != null) {
436             return categoryPane.getComponent().requestFocusInWindow();
437         }
438         return retVal;
439     }
440     
441     public JComponent JavaDoc getToolbarRepresentation() {
442         // This is called every time user switches between elements.
443
if (toolbar == null) {
444             try {
445                 SchemaModel model = schemaDataObject
446                         .getSchemaEditorSupport().getModel();
447                 if (model != null && model.getState() == SchemaModel.State.VALID) {
448                     toolbar = new JToolBar JavaDoc();
449                     toolbar.setFloatable(false);
450                     if (categoryPane != null) {
451                         toolbar.addSeparator();
452                         categoryPane.populateToolbar(toolbar);
453                     }
454                     toolbar.addSeparator();
455                     JButton JavaDoc validateButton = toolbar.add(new ValidateAction(model));
456                     validateButton.getAccessibleContext().setAccessibleName(""+
457                             validateButton.getAction().getValue(ValidateAction.NAME));
458                 }
459             } catch (IOException JavaDoc ioe) {
460                 // wait until the model is valid
461
}
462         }
463         return toolbar;
464     }
465
466     public UndoRedo getUndoRedo() {
467     return schemaDataObject.getSchemaEditorSupport().getUndoManager();
468     }
469
470     public JComponent JavaDoc getVisualRepresentation() {
471         return this;
472     }
473     
474     public HelpCtx getHelpCtx() {
475     return new HelpCtx(SchemaColumnViewMultiViewDesc.class);
476     }
477
478     private class ColumnViewFindAction extends AbstractAction JavaDoc {
479         /** silence compiler warnings */
480         private static final long serialVersionUID = 1L;
481
482         /**
483          * Creates a new instance of ColumnViewFindAction.
484          */

485         public ColumnViewFindAction() {
486         }
487
488         public void actionPerformed(ActionEvent JavaDoc event) {
489             SchemaColumnViewMultiViewElement parent =
490                     SchemaColumnViewMultiViewElement.this;
491             if (parent.categoryPane != null) {
492                 CategoryPane pane = parent.categoryPane;
493                 pane.getSearchComponent().showComponent();
494             }
495         }
496     }
497
498     /**
499      * Force the model to sync with a simple document, then sync again with
500      * the original document. This is used to reconstruct the model in the
501      * event that it is in an invalid state.
502      *
503      * @param model the model to be reset.
504      */

505     private void forceResetDocument(SchemaModel model) {
506         SchemaDataObject dobj = getSchemaDataObject();
507         SchemaEditorSupport editor = dobj.getSchemaEditorSupport();
508         StyledDocument JavaDoc doc = editor.getDocument();
509         QuietUndoManager um = editor.getUndoManager();
510         // Must ignore the edits that are about to occur.
511
model.removeUndoableEditListener(um);
512         // Changing the document causes the editor support to end up
513
// creating another MVE, so avoid that altogether by ignoring
514
// the call to updateTitles().
515
editor.ignoreUpdateTitles(true);
516         try {
517             // Reset the model state by forcing it to sync again.
518
String JavaDoc saved = doc.getText(0, doc.getLength());
519             doc.remove(0, doc.getLength());
520             doc.insertString(0, EMPTY_DOC, null);
521             model.sync();
522             doc.remove(0, doc.getLength());
523             doc.insertString(0, saved, null);
524             model.sync();
525             dobj.setModified(false);
526         } catch(BadLocationException JavaDoc e) {
527             Logger.getLogger(SchemaColumnViewMultiViewElement.class.getName()).log(
528                     Level.FINE, "forceResetDocument", e);
529         } catch(IOException JavaDoc e) {
530             Logger.getLogger(SchemaColumnViewMultiViewElement.class.getName()).log(
531                     Level.FINE, "forceResetDocument", e);
532         } finally {
533             editor.ignoreUpdateTitles(false);
534             model.addUndoableEditListener(um);
535         }
536     }
537 }
538
Popular Tags