blob: b3753e553bbbeb02259ea2d70ec62d7c74a9e0af [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2001, 2004 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.wst.xsd.ui.internal;
import java.util.ArrayList;
import java.util.EventObject;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IPath;
import org.eclipse.emf.common.command.BasicCommandStack;
import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.common.command.CommandStackListener;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IPartListener;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.editors.text.ILocationProvider;
import org.eclipse.wst.common.ui.properties.internal.provisional.ITabbedPropertySheetPageContributor;
import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.sse.core.internal.provisional.exceptions.SourceEditingRuntimeException;
import org.eclipse.wst.sse.core.internal.undo.IStructuredTextUndoManager;
import org.eclipse.wst.sse.ui.internal.StructuredTextEditor;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
import org.eclipse.wst.xsd.ui.internal.graph.XSDGraphViewer;
import org.eclipse.wst.xsd.ui.internal.text.XSDModelAdapter;
import org.eclipse.wst.xsd.ui.internal.util.OpenOnSelectionHelper;
import org.eclipse.xsd.XSDConcreteComponent;
import org.eclipse.xsd.XSDSchema;
import org.eclipse.xsd.util.XSDConstants;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.ProcessingInstruction;
// public class XSDEditor extends StructuredTextMultiPageEditorPart
public class XSDEditor extends XSDMultiPageEditorPart implements ITabbedPropertySheetPageContributor
{
protected XSDTextEditor textEditor;
IFile resourceFile;
XSDSelectionManager xsdSelectionManager;
XSDModelAdapter schemalNodeAdapter;
private IStructuredModel result;
public XSDEditor()
{
super();
xsdSelectionManager = new XSDSelectionManager();
}
InternalPartListener partListener = new InternalPartListener(this);
// show outline view - defect 266116
public void init(IEditorSite site, IEditorInput editorInput) throws PartInitException
{
super.init(site, editorInput);
IWorkbenchWindow dw=PlatformUI.getWorkbench().getActiveWorkbenchWindow();
IWorkbenchPage page=dw.getActivePage();
getSite().getPage().addPartListener(partListener);
try
{
if (page != null)
{
// page.showView("org.eclipse.ui.views.ContentOutline");
page.showView("org.eclipse.ui.views.PropertySheet");
}
} catch (PartInitException e)
{
// e.printStackTrace();
}
}
// For team support
// protected PropertyDirtyChangeListener propertyChangeListener;
/**
* Creates the pages of this multi-page editor.
* <p>
* Subclasses of <code>MultiPageEditor</code> must implement this method.
* </p>
*/
protected void createPages()
{
try
{
if (!loadFile())
return;
// source page MUST be created before design page, now
createSourcePage();
addSourcePage();
buildXSDModel();
// comment this line out to hide the graph page
//
createAndAddGraphPage();
int pageIndexToShow = getDefaultPageTypeIndex();
setActivePage(pageIndexToShow);
addCommandStackListener();
XSDEditorPlugin.getPlugin().getPreferenceStore().addPropertyChangeListener(preferenceStoreListener);
}
catch (PartInitException exception)
{
throw new SourceEditingRuntimeException(exception, XSDEditorPlugin.getXSDString("An_error_has_occurred_when1_ERROR_")); //$NON-NLS-1$ = "An error has occurred when initializing the input for the the editor's source page."
}
}
public void buildXSDModel()
{
try
{
Document document = ((IDOMModel)getModel()).getDocument();
if (document.getChildNodes().getLength() == 0)
{
// this is an empty document. Create a default schema tag now
//TODO cs :oops I need to add this method back
createDefaultSchemaNode(document);
}
if (document instanceof INodeNotifier)
{
INodeNotifier notifier = (INodeNotifier)document;
schemalNodeAdapter = (XSDModelAdapter)notifier.getAdapterFor(XSDModelAdapter.class);
if (schemalNodeAdapter == null)
{
schemalNodeAdapter = new XSDModelAdapter();
notifier.addAdapter(schemalNodeAdapter);
schemalNodeAdapter.createSchema(document.getDocumentElement());
}
}
}
catch (Exception e)
{
// XSDEditorPlugin.getPlugin().getMsgLogger().write("Failed to create Model");
// XSDEditorPlugin.getPlugin().getMsgLogger().write(e);
// e.printStackTrace();
}
// XSDResourceFactoryImpl.validate(xsdSchema, input.getFile().getContents(true));
}
public String[] getPropertyCategories()
{
return new String[] { "general", "namespace", "other", "attributes", "documentation", "facets" }; //$NON-NLS-1$
}
/**
* @see org.eclipse.wst.common.ui.properties.internal.provisional.ITabbedPropertySheetPageContributor#getContributorId()
*/
public String getContributorId()
{
return "org.eclipse.wst.xsd.ui.internal.XSDEditor";
//return getSite().getId();
}
protected CommandStackListener commandStackListener;
protected void addCommandStackListener()
{
if (commandStackListener == null)
{
IStructuredTextUndoManager undoManager = getModel().getUndoManager();
commandStackListener = new CommandStackListener()
{
/**
* @see org.eclipse.emf.common.command.CommandStackListener#commandStackChanged(EventObject)
*/
public void commandStackChanged(EventObject event)
{
Object obj = event.getSource();
if (obj instanceof BasicCommandStack)
{
BasicCommandStack stack = (BasicCommandStack) obj;
Command recentCommand = stack.getMostRecentCommand();
Command redoCommand = stack.getRedoCommand();
Command undoCommand = stack.getUndoCommand();
if (recentCommand == redoCommand)
{
// there must have been an undo reset info tasks
resetInformationTasks();
}
}
}
};
//TODO WTP Port undoManager.getCommandStack().addCommandStackListener(commandStackListener);
}
}
protected void pageChange(int arg)
{
super.pageChange(arg);
}
protected void removeCommandStackListener()
{
if (commandStackListener != null)
{
IStructuredTextUndoManager undoManager = getModel().getUndoManager();
//TODO WTP Port undoManager.getCommandStack().removeCommandStackListener(commandStackListener);
}
}
// This is from the IValidateEditEditor interface
/* public void undoChange()
{
StructuredTextUndoManager undoManager = textEditor.getModel().getUndoManager();
undoManager.undo();
// Make the editor clean
textEditor.getModel().setDirtyState(false);
} */
private class PreferenceStoreListener implements IPropertyChangeListener
{
/**
* @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(PropertyChangeEvent)
*/
public void propertyChange(PropertyChangeEvent event)
{
}
}
protected IPropertyChangeListener preferenceStoreListener = new PreferenceStoreListener();
protected int getDefaultPageTypeIndex()
{
int pageIndex = sourcePageIndex;
if (XSDEditorPlugin.getPlugin().getDefaultPage().equals(XSDEditorPlugin.GRAPH_PAGE))
{
if (graphPageIndex != -1)
pageIndex = graphPageIndex;
}
return pageIndex;
}
int currentPage = -1;
public String getCurrentPageType()
{
// should update pref. for valid pages
if (getActivePage() != -1)
{
currentPage = getActivePage();
}
if (currentPage == graphPageIndex)
{
return XSDEditorPlugin.GRAPH_PAGE;
}
else
{
return XSDEditorPlugin.SOURCE_PAGE;
}
}
public Object getActivePart()
{
return getSite().getWorkbenchWindow().getActivePage().getActivePart();
}
public void dispose()
{
// propertyChangeListener.dispose();
removeCommandStackListener();
XSDEditorPlugin.getPlugin().setDefaultPage(getCurrentPageType());
XSDEditorPlugin.getPlugin().getPreferenceStore().removePropertyChangeListener(preferenceStoreListener);
getSite().getPage().removePartListener(partListener);
super.dispose();
}
protected boolean loadFile()
{
Object input = getEditorInput();
if (input instanceof IFileEditorInput)
{
resourceFile = ((IFileEditorInput) input).getFile();
}
else if (input instanceof ILocationProvider)
{
IPath path = ((ILocationProvider)input).getPath(input);
String ext = path.getFileExtension();
if (ext != null && ext.equals("xsd"))
{
return true;
}
return false;
}
else
{
return false;
}
return true;
}
/**
* Method openOnGlobalReference.
* The comp argument is a resolved xsd schema object from another file. This is created and called from another
* schema model to allow F3 navigation to open a new editor and choose the referenced object within that editor context
* @param comp
*/
public void openOnGlobalReference(XSDConcreteComponent comp)
{
openOnSelectionHelper.openOnGlobalReference(comp);
}
protected OpenOnSelectionHelper openOnSelectionHelper;
public OpenOnSelectionHelper getOpenOnSelectionHelper()
{
return openOnSelectionHelper;
}
/**
* @see org.eclipse.wst.xsd.ui.internal.XSDMultiPageEditorPart#createTextEditor()
*/
protected StructuredTextEditor createTextEditor()
{
return new XSDTextEditor(this);
}
/*
* @see StructuredTextMultiPageEditorPart#createSourcePage()
*/
protected void createSourcePage() throws PartInitException
{
super.createSourcePage();
textEditor = (XSDTextEditor) getTextEditor();
openOnSelectionHelper = new OpenOnSelectionHelper(textEditor);
}
int sourcePageIndex = -1;
/**
* Adds the source page of the multi-page editor.
*/
protected void addSourcePage() throws PartInitException {
sourcePageIndex = addPage(textEditor, getEditorInput());
setPageText(sourcePageIndex, XSDEditorPlugin.getXSDString("_UI_TAB_SOURCE"));
// defect 223043 ... do textEditor.setModel() here instead of in createSourcePage()
// the update's critical, to get viewer selection manager and highlighting to work
IEditorInput editorInput = getEditorInput();
if (editorInput instanceof IFileEditorInput)
{
textEditor.setModel((IFileEditorInput)getEditorInput());
}
else
{
// textEditor.setModel(editorInput);
}
textEditor.update();
firePropertyChange(PROP_TITLE);
}
int graphPageIndex = -1;
XSDGraphViewer graphViewer;
/**
* Creates the graph page and adds it to the multi-page editor.
*/
protected void createAndAddGraphPage() throws PartInitException
{
graphViewer = new XSDGraphViewer(this);
graphViewer.setSchema(getXSDSchema());
Control graphControl = graphViewer.createControl(getContainer());
graphPageIndex = addPage(graphControl);
setPageText(graphPageIndex, XSDEditorPlugin.getXSDString("_UI_TAB_GRAPH"));
// graphViewer.setViewerSelectionManager(textEditor.getViewerSelectionManager());
graphViewer.setSelectionManager(getSelectionManager());
// this forces the editor to initially select the top level schema object
//
getSelectionManager().setSelection(new StructuredSelection(textEditor.getXSDSchema()));
}
/*
* @see IAdaptable#getAdapter(Class)
*/
public Object getAdapter(Class key)
{
Object result = null;
if (key == ISelectionProvider.class)
{
result = xsdSelectionManager;
}
else
{
result = textEditor.getAdapter(key);
}
return result;
}
public XSDSelectionManager getSelectionManager()
{
return xsdSelectionManager;
}
/**
* @see org.eclipse.wst.xsd.ui.internal.XSDMultiPageEditorPart#doSaveAs()
*/
public void doSaveAs()
{
super.doSaveAs();
}
public void doSave(org.eclipse.core.runtime.IProgressMonitor monitor)
{
super.doSave(monitor);
}
public void reparseSchema()
{
// TODO cs : Are there no better ways to make the model
// reload it's dependencies? This seems rather extreme.
//
Document document = ((IDOMModel)getModel()).getDocument();
if (schemalNodeAdapter != null)
{
schemalNodeAdapter.createSchema(document.getDocumentElement());
}
}
/**
* Returns the xsdSchema.
* @return XSDSchema
*/
public XSDSchema getXSDSchema()
{
return schemalNodeAdapter != null ? schemalNodeAdapter.getSchema() : null;
}
/**
* Returns the resourceFile.
* @return IFile
*/
public IFile getFileResource()
{
return resourceFile;
}
/**
* Get the IDocument from the text viewer
*/
public IDocument getEditorIDocument()
{
IDocument document = textEditor.getTextViewer().getDocument();
return document;
}
/**
* Create ref integrity tasks in task list
*/
public void createTasksInTaskList(ArrayList messages)
{
// DisplayErrorInTaskList tasks = new DisplayErrorInTaskList(getEditorIDocument(), getFileResource(), messages);
// tasks.run();
}
public void resetInformationTasks()
{
// DisplayErrorInTaskList.removeInfoMarkers(getFileResource());
}
public XSDGraphViewer getGraphViewer()
{
return graphViewer;
}
public IEditorPart getActiveEditorPage()
{
return getActiveEditor();
}
public XSDTextEditor getXSDTextEditor()
{
return textEditor;
}
class InternalPartListener implements IPartListener
{
XSDEditor editor;
public InternalPartListener(XSDEditor editor)
{
this.editor = editor;
}
public void partActivated(IWorkbenchPart part)
{
if (part == editor)
{
ISelection selection = getSelectionManager().getSelection();
if (selection != null)
{
if (getCurrentPageType().equals(XSDEditorPlugin.GRAPH_PAGE))
{
getSelectionManager().selectionChanged(new SelectionChangedEvent(editor.getGraphViewer().getComponentViewer(), selection));
}
else if (getCurrentPageType().equals(XSDEditorPlugin.SOURCE_PAGE))
{
getSelectionManager().setSelection(selection);
}
}
}
}
public void partBroughtToTop(IWorkbenchPart part)
{
}
public void partClosed(IWorkbenchPart part)
{
}
public void partDeactivated(IWorkbenchPart part)
{
}
public void partOpened(IWorkbenchPart part)
{
}
}
/**
* Method createDefaultSchemaNode. Should only be called to insert a schema node into an empty document
*/
public void createDefaultSchemaNode(Document document)
{
if (document.getChildNodes().getLength() == 0)
{
// if it is a completely empty file, then add the encoding and version processing instruction
//TODO String encoding = EncodingHelper.getDefaultEncodingTag();
String encoding = "UTF-8";
ProcessingInstruction instr = document.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"" + encoding + "\"");
document.appendChild(instr);
}
// Create a default schema tag now
// String defaultPrefixForTargetNamespace = getFileResource().getProjectRelativePath().removeFileExtension().lastSegment();
String defaultPrefixForTargetNamespace = "tns";
String prefixForSchemaNamespace = "";
String schemaNamespaceAttribute = "xmlns";
if (XSDEditorPlugin.getPlugin().isQualifyXMLSchemaLanguage())
{
// Added this if check before disallowing blank prefixes in the preferences...
// Can take this out. See also NewXSDWizard
if (XSDEditorPlugin.getPlugin().getXMLSchemaPrefix().trim().length() > 0)
{
prefixForSchemaNamespace = XSDEditorPlugin.getPlugin().getXMLSchemaPrefix() + ":";
schemaNamespaceAttribute += ":" + XSDEditorPlugin.getPlugin().getXMLSchemaPrefix();
}
}
document.appendChild(document.createTextNode("\n"));
Element element = document.createElement(prefixForSchemaNamespace + XSDConstants.SCHEMA_ELEMENT_TAG);
element.setAttribute(schemaNamespaceAttribute,"http://www.w3.org/2001/XMLSchema");
String defaultTargetURI = XSDEditorPlugin.getPlugin().getXMLSchemaTargetNamespace();
element.setAttribute(XSDConstants.TARGETNAMESPACE_ATTRIBUTE, defaultTargetURI);
element.setAttribute("xmlns:" + defaultPrefixForTargetNamespace, defaultTargetURI);
document.appendChild(element);
}
}