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-2007 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:
042: package org.netbeans.modules.xml.schema.multiview;
043:
044: import java.awt.EventQueue;
045: import java.util.Collection;
046: import java.util.Collections;
047: import java.util.Enumeration;
048: import java.util.HashSet;
049: import org.netbeans.core.api.multiview.MultiViewHandler;
050: import org.netbeans.core.api.multiview.MultiViewPerspective;
051: import org.netbeans.core.api.multiview.MultiViews;
052: import org.netbeans.core.spi.multiview.MultiViewDescription;
053: import org.netbeans.core.spi.multiview.MultiViewFactory;
054: import org.netbeans.modules.xml.axi.AXIComponent;
055: import org.netbeans.modules.xml.axi.AXIModel;
056: import org.netbeans.modules.xml.axi.AXIModelFactory;
057: import org.netbeans.modules.xml.schema.SchemaDataObject;
058: import org.netbeans.modules.xml.schema.SchemaEditorSupport;
059: import org.netbeans.modules.xml.schema.model.SchemaComponent;
060: import org.netbeans.modules.xml.xam.Model;
061: import org.netbeans.modules.xml.xam.ui.cookies.GetComponentCookie;
062: import org.netbeans.modules.xml.xam.ui.cookies.ViewComponentCookie;
063: import org.netbeans.modules.xml.xam.ui.cookies.ViewComponentCookie.View;
064: import org.netbeans.modules.xml.validation.ShowCookie;
065: import org.netbeans.modules.xml.xam.Component;
066: import org.netbeans.modules.xml.xam.spi.Validator.ResultItem;
067: import org.openide.nodes.Node;
068: import org.openide.windows.CloneableTopComponent;
069: import org.openide.windows.TopComponent;
070:
071: /**
072: * Class for creating the Schema Multiview and implementation
073: * of ViewComponentCookie, which has methods to open the multiview elements
074: * of the Schema Multiview. The instance of this class is in the
075: * SchemaDataObject cookie set.
076: *
077: *
078: *
079: * @author Jeri Lockhart
080: * @author Ajit Bhate
081: */
082: public class SchemaMultiViewSupport implements ViewComponentCookie,
083: ShowCookie {
084: public static final String SCHEMA_EDITOR_HELP_ID = "SCHEMA_EDITOR_HELP_ID";
085: /** The dataobject it supports. */
086: private SchemaDataObject dobj;
087:
088: /**
089: * Constructor
090: */
091: public SchemaMultiViewSupport(SchemaDataObject dobj) {
092: this .dobj = dobj;
093: }
094:
095: /**
096: * Create the Schema Multiview
097: */
098: public static CloneableTopComponent createMultiView(
099: SchemaDataObject schemaDataObject) {
100: MultiViewDescription views[] = new MultiViewDescription[3];
101:
102: // Put the source element first so that client code can find its
103: // CloneableEditorSupport.Pane implementation.
104: views[0] = getSchemaSourceMultiviewDesc(schemaDataObject);
105: views[1] = getSchemaColumnViewMultiViewDesc(schemaDataObject);
106: views[2] = getSchemaABEMultiviewDesc(schemaDataObject);
107:
108: // Make the column view the default element.
109: CloneableTopComponent multiview = MultiViewFactory
110: .createCloneableMultiView(views, views[0],
111: new SchemaEditorSupport.CloseHandler(
112: schemaDataObject));
113:
114: // This handles the "show file extensions" option automatically.
115: String name = schemaDataObject.getNodeDelegate()
116: .getDisplayName();
117: multiview.setDisplayName(name);
118: multiview.setName(name);
119: return multiview;
120: }
121:
122: private static MultiViewDescription getSchemaColumnViewMultiViewDesc(
123: final SchemaDataObject schemaDataObject) {
124: return new SchemaColumnViewMultiViewDesc(schemaDataObject);
125: }
126:
127: private static MultiViewDescription getSchemaSourceMultiviewDesc(
128: final SchemaDataObject schemaDataObject) {
129: return new SchemaSourceMultiViewDesc(schemaDataObject);
130: }
131:
132: private static MultiViewDescription getSchemaABEMultiviewDesc(
133: final SchemaDataObject schemaDataObject) {
134: return new SchemaABEViewMultiViewDesc(schemaDataObject);
135: }
136:
137: /**
138: * Returns true if the given TopComponent is the last one in the
139: * set of cloneable windows.
140: *
141: * @param tc TopComponent.
142: * @return false if tc is not cloneable, or there are one or more
143: * clones; true if it is the last clone.
144: */
145: public static boolean isLastView(TopComponent tc) {
146: if (!(tc instanceof CloneableTopComponent)) {
147: return false;
148: }
149: boolean oneOrLess = true;
150: Enumeration en = ((CloneableTopComponent) tc).getReference()
151: .getComponents();
152: if (en.hasMoreElements()) {
153: en.nextElement();
154: if (en.hasMoreElements()) {
155: oneOrLess = false;
156: }
157: }
158: return oneOrLess;
159: }
160:
161: /**
162: * Shows the desired multiview element. Must be called after the editor
163: * has been opened (i.e. SchemaEditorSupport.open()) so the TopComponent
164: * will be the active one in the registry.
165: *
166: * @param id identifier of the multiview element.
167: */
168: private static void requestMultiviewActive(String id) {
169: TopComponent activeTC = TopComponent.getRegistry()
170: .getActivated();
171: MultiViewHandler handler = MultiViews
172: .findMultiViewHandler(activeTC);
173: if (handler != null) {
174: MultiViewPerspective[] perspectives = handler
175: .getPerspectives();
176: for (MultiViewPerspective perspective : perspectives) {
177: if (perspective.preferredID().equals(id)) {
178: handler.requestActive(perspective);
179: }
180: }
181: }
182: }
183:
184: /**
185: * Finds the preferredID of active multiview element.
186: * If activated tc is not mvtc returns null;
187: *
188: * @return identifier of the active multiview element.
189: */
190: private static String getMultiviewActive() {
191: TopComponent activeTC = TopComponent.getRegistry()
192: .getActivated();
193: MultiViewHandler handler = MultiViews
194: .findMultiViewHandler(activeTC);
195: if (handler != null) {
196: return handler.getSelectedPerspective().preferredID();
197: }
198: return null;
199: }
200:
201: /**
202: * Finds the activated components of active top component.
203: *
204: * @return collection of the active components.
205: */
206: private static Collection<Component> getActiveComponents() {
207: TopComponent activeTC = TopComponent.getRegistry()
208: .getActivated();
209: Collection<Component> activeComponents = Collections.emptySet();
210: for (Node n : activeTC.getActivatedNodes()) {
211: GetComponentCookie cake = n
212: .getCookie(GetComponentCookie.class);
213: Component component = null;
214: if (cake != null)
215: component = cake.getComponent();
216: if (component == null)
217: component = n.getLookup().lookup(Component.class);
218: if (component != null) {
219: if (activeComponents.isEmpty())
220: activeComponents = new HashSet<Component>();
221: activeComponents.add(component);
222: }
223: }
224: return activeComponents;
225: }
226:
227: public void view(final View view, final Component component,
228: final Object... parameters) {
229:
230: if (!EventQueue.isDispatchThread()) {
231: EventQueue.invokeLater(new Runnable() {
232: public void run() {
233: viewInSwingThread(view, component, parameters);
234: }
235: });
236: } else {
237: viewInSwingThread(view, component, parameters);
238: }
239: }
240:
241: private void viewInSwingThread(View view, Component component,
242: Object... parameters) {
243: if (canView(view, component)) {
244: if (view == View.SUPER) {
245: // preserve the view
246: TopComponent activeTC = TopComponent.getRegistry()
247: .getActivated();
248: SchemaDataObject sdobj = activeTC.getLookup().lookup(
249: SchemaDataObject.class);
250: if (dobj != sdobj) // must be multifile
251: {
252: String activeMVTCId = getMultiviewActive();
253: view = View.STRUCTURE;
254: if (SchemaABEViewMultiViewDesc.PREFERRED_ID
255: .equals(activeMVTCId))
256: view = View.DESIGN;
257: else if (SchemaSourceMultiViewDesc.PREFERRED_ID
258: .equals(activeMVTCId))
259: view = View.SOURCE;
260: }
261: }
262: SchemaEditorSupport editor = dobj.getSchemaEditorSupport();
263: editor.open();
264: // activate view if needed
265: switch (view) {
266: case STRUCTURE:
267: if (component instanceof AXIComponent)
268: component = ((AXIComponent) component).getPeer();
269: requestMultiviewActive(SchemaColumnViewMultiViewDesc.PREFERRED_ID);
270: break;
271: case DESIGN:
272: requestMultiviewActive(SchemaABEViewMultiViewDesc.PREFERRED_ID);
273: break;
274: case SOURCE:
275: if (component instanceof AXIComponent)
276: component = ((AXIComponent) component).getPeer();
277: requestMultiviewActive(SchemaSourceMultiViewDesc.PREFERRED_ID);
278: break;
279: }
280: // show component in current multiview
281: TopComponent activeTC = TopComponent.getRegistry()
282: .getActivated();
283: ShowCookie showCookie = activeTC.getLookup().lookup(
284: ShowCookie.class);
285: ResultItem resultItem = null;
286: if (parameters != null && parameters.length != 0) {
287: for (Object o : parameters) {
288: if (o instanceof ResultItem) {
289: resultItem = (ResultItem) o;
290: break;
291: }
292: }
293: }
294: if (resultItem == null)
295: resultItem = new ResultItem(null, null, component, null);
296: if (showCookie != null)
297: showCookie.show(resultItem);
298: }
299: }
300:
301: public void show(ResultItem resultItem) {
302: View view = View.SOURCE;
303: Component component = resultItem.getComponents();
304: if (component != null && component.getModel() != null
305: && component.getModel().getState() == Model.State.VALID) {
306: // preserve the view
307: TopComponent activeTC = TopComponent.getRegistry()
308: .getActivated();
309: SchemaDataObject sdobj = activeTC.getLookup().lookup(
310: SchemaDataObject.class);
311: if (dobj == sdobj) { // we can preserve the view
312: String activeMVTCId = getMultiviewActive();
313: if (SchemaABEViewMultiViewDesc.PREFERRED_ID
314: .equals(activeMVTCId)) {
315: AXIModel axiModel = null;
316: if (component instanceof AXIComponent) {
317: axiModel = ((AXIComponent) component)
318: .getModel();
319: } else if (component instanceof SchemaComponent) {
320: axiModel = AXIModelFactory.getDefault()
321: .getModel(
322: ((SchemaComponent) component)
323: .getModel());
324: }
325: if (axiModel != null
326: && axiModel.getState() == AXIModel.State.VALID) {
327: view = View.DESIGN;
328: }
329: } else if (SchemaColumnViewMultiViewDesc.PREFERRED_ID
330: .equals(activeMVTCId))
331: view = View.STRUCTURE;
332: }
333: }
334: view(view, component, resultItem);
335: }
336:
337: public boolean canView(View view, Component component) {
338: if (view != null) {
339: switch (view) {
340: case SOURCE:
341: if (!SchemaSourceMultiViewDesc.PREFERRED_ID
342: .equals(getMultiviewActive())
343: || !getActiveComponents().contains(component)) {
344: if (component instanceof AXIComponent)
345: return ((AXIComponent) component).getPeer() != null;
346: return true;
347: } else
348: return false;
349: case STRUCTURE:
350: if (!(component instanceof SchemaComponent || component instanceof AXIComponent))
351: return false;
352: if (component instanceof AXIComponent
353: && ((AXIComponent) component).getPeer() == null)
354: return false;
355: if (SchemaColumnViewMultiViewDesc.PREFERRED_ID
356: .equals(getMultiviewActive())
357: && getActiveComponents().contains(component)) {
358: TopComponent activeTC = TopComponent.getRegistry()
359: .getActivated();
360: SchemaDataObject sdobj = activeTC.getLookup()
361: .lookup(SchemaDataObject.class);
362: return sdobj != dobj;
363: } else
364: return true;
365: case DESIGN:
366: if (SchemaABEViewMultiViewDesc.PREFERRED_ID
367: .equals(getMultiviewActive()))
368: return false;
369: AXIModel axiModel = null;
370: if (component instanceof AXIComponent) {
371: axiModel = ((AXIComponent) component).getModel();
372: } else if (component instanceof SchemaComponent) {
373: axiModel = AXIModelFactory.getDefault().getModel(
374: ((SchemaComponent) component).getModel());
375: if (!axiModel.canView((SchemaComponent) component))
376: return false;
377: }
378: if (axiModel != null
379: && axiModel.getState() == AXIModel.State.VALID) {
380: return true;
381: }
382: return false;
383: case SUPER:
384: return true;
385: }
386: }
387: return false;
388: }
389: }
|