diff options
Diffstat (limited to 'deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext')
30 files changed, 3427 insertions, 0 deletions
diff --git a/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/Activator.java b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/Activator.java new file mode 100644 index 00000000000..b22de38760d --- /dev/null +++ b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/Activator.java @@ -0,0 +1,72 @@ +/******************************************************************************* + * Copyright (c) 2009 itemis AG (http://www.itemis.eu) 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 + *******************************************************************************/ +package org.eclipse.papyrus.infra.gmfdiag.xtext.glue; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +/** + * The activator class controls the plug-in life cycle + * + * @author koehnlein + */ +public class Activator extends AbstractUIPlugin { + + /** + * The plug-in ID + */ + public static final String PLUGIN_ID = "org.eclipse.papyrus.infra.gmfdiag.xtext.glue"; + + // The shared instance + private static Activator plugin; + + /** + * The constructor + */ + public Activator() { + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext) + */ + @Override + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext) + */ + @Override + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static Activator getDefault() { + return plugin; + } + + /** + * This element comes from the XText/GMF integration example, and was not originally documented. + * @param t + */ + public static void logError(Throwable t) { + getDefault().getLog().log(new Status(IStatus.ERROR, PLUGIN_ID, t.getMessage(), t)); + } +} diff --git a/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/PopupEditorConfiguration.java b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/PopupEditorConfiguration.java new file mode 100644 index 00000000000..3cff16ceb76 --- /dev/null +++ b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/PopupEditorConfiguration.java @@ -0,0 +1,151 @@ +/*****************************************************************************
+ * Copyright (c) 2010 CEA LIST.
+ *
+ *
+ * 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:
+ * CEA LIST - Initial API and implementation
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.infra.gmfdiag.xtext.glue;
+
+import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
+import org.eclipse.jface.dialogs.IInputValidator;
+import org.eclipse.jface.text.source.SourceViewerConfiguration;
+import org.eclipse.papyrus.extensionpoints.editors.configuration.IPopupEditorConfiguration;
+import org.eclipse.papyrus.extensionpoints.editors.ui.IPopupEditorHelper;
+import org.eclipse.papyrus.infra.gmfdiag.xtext.glue.edit.part.IXTextSemanticValidator;
+import org.eclipse.papyrus.infra.gmfdiag.xtext.glue.edit.part.IXtextEMFReconciler;
+import org.eclipse.papyrus.infra.gmfdiag.xtext.glue.edit.part.PopupXtextEditorHelper;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Composite;
+
+import com.google.inject.Injector;
+
+
+/**
+ * @author CEA LIST - Initial contribution and API
+ * This class is provided as a basis for contribution to the extension point directEditors of Papyrus,
+ * for the case of popup editors.
+ * Clients must simply override the method createPopupEditorHelper(Object editPart)
+ *
+ * This class is deprecated, use DefaultDirectEditorConfiguration instead
+ */
+@Deprecated
+public abstract class PopupEditorConfiguration implements IPopupEditorConfiguration {
+
+ private String language = "";
+
+ /**
+ * Default constructor
+ */
+ public PopupEditorConfiguration() {
+ // Auto-generated constructor stub
+ }
+
+ /**
+ * This abstract method must be implemented for the integration of each specific textual editor.
+ * Implementation usually consist in calling createPopupEditorHelper.
+ * The implementation must simply determine the values to be passed as parameters of this method call.
+ *
+ * @param editPart The edit part on which a direct edit has been performed. The type of this element
+ * is Object, in order to avoid direct dependencies with GMF (see the direct editors extension point of
+ * Papyrus). It is however expected that editPart is instanceof IGraphicalEditPart.
+ */
+ public abstract IPopupEditorHelper createPopupEditorHelper(Object editPart) ;
+
+ /**
+ * Basic implementation which simply consists in returning a new PopupXtextEditorHelper
+ * @param editPart The editPart on which a direct edit has been performed.
+ * @param xtextInjector The xtextInjector.
+ * @param xtextEditorContextUpdater The IXtextEditorContextUpdater, to update the currently select xtext editor
+ * @param modelReconciler The IXtextEMFReconciler, to update the context UML model with changes textually specified in the popup xtext editor
+ * @param textToEdit the initialization text, used as the initial textual content for the popup xtext editor
+ * @param fileExtension the extension for the temporary textual file (underlying the editor)
+ * @param semanticValidator the semantic validator used to semantically validate the model before saving
+ * @return IPopupEditorHelper
+ */
+ public IPopupEditorHelper createPopupEditorHelper(IGraphicalEditPart editPart,
+ Injector xtextInjector,
+ IXtextEMFReconciler modelReconciler,
+ String textToEdit,
+ String fileExtension,
+ IXTextSemanticValidator semanticValidator) {
+
+ return new PopupXtextEditorHelper(editPart,
+ xtextInjector,
+ modelReconciler,
+ textToEdit,
+ fileExtension,
+ semanticValidator);
+ }
+
+ ////
+
+ public int getStyle() {
+ // Auto-generated method stub
+ return 0;
+ }
+
+ public Point getPreferedSize() {
+ // Auto-generated method stub
+ return null;
+ }
+
+ public SourceViewerConfiguration getSourceViewerConfiguration() {
+ // Auto-generated method stub
+ return null;
+ }
+
+ public String getTextToEdit(Object editedObject) {
+ // Auto-generated method stub
+ return null;
+ }
+
+ public Object preEditAction(Object editedObject) {
+ // Auto-generated method stub
+ return null;
+ }
+
+ public Object postEditAction(Object editedObject, String newText) {
+ // Auto-generated method stub
+ return null;
+ }
+
+ public Composite createExtendedDialogArea(Composite parent) {
+ // Auto-generated method stub
+ return null;
+ }
+
+ public String getLanguage() {
+ return language;
+ }
+
+ public void setLanguage(String language) {
+ this.language = "" + language ;
+ }
+
+
+ public IInputValidator getInputValidator() {
+ // Auto-generated method stub
+ return null;
+ }
+
+ public void setInputValidator(IInputValidator validator) {
+ // Auto-generated method stub
+
+ }
+
+ public Selection getTextSelection(String value, Object editedObject) {
+ // Auto-generated method stub
+ return null;
+ }
+
+
+
+}
diff --git a/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/concurrency/ConcurrentModificationObserver.java b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/concurrency/ConcurrentModificationObserver.java new file mode 100644 index 00000000000..a4a7936d051 --- /dev/null +++ b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/concurrency/ConcurrentModificationObserver.java @@ -0,0 +1,91 @@ +/******************************************************************************* + * Copyright (c) 2009 itemis AG (http://www.itemis.eu) 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 + *******************************************************************************/ +package org.eclipse.papyrus.infra.gmfdiag.xtext.glue.concurrency; + +import org.eclipse.emf.transaction.TransactionalEditingDomain; +import org.eclipse.gmf.runtime.diagram.ui.parts.DiagramEditor; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IEditorReference; +import org.eclipse.ui.IPartListener; +import org.eclipse.ui.IStartup; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.PlatformUI; + +/** + * Detects concurrent modifications of GMF and Xtext editors based on Xtext's dirty state management. + * + * @author koehnlein + */ +public class ConcurrentModificationObserver implements IPartListener { + + private EditingDomainAdapter.Factory factory; + + /** + * This element comes from the XText/GMF integration example, and was not originally documented. + * @param activePage + */ + public ConcurrentModificationObserver(IWorkbenchPage activePage) { + factory = new EditingDomainAdapter.Factory(); + for (IEditorReference editorRef : activePage.getEditorReferences()) { + IEditorPart editor = editorRef.getEditor(false); + if (editor != null) { + partOpened(editor); + } + } + } + + public void partOpened(IWorkbenchPart part) { + if (part instanceof DiagramEditor) { + TransactionalEditingDomain editingDomain = ((DiagramEditor) part).getEditingDomain(); + factory.adapt(editingDomain, EditingDomainAdapter.class); + } + } + + public void partClosed(IWorkbenchPart part) { + if (part instanceof DiagramEditor) { + // as long as bug 299920 is not fixed, we have to dispose the adapter manually + TransactionalEditingDomain editingDomain = ((DiagramEditor) part).getEditingDomain(); + if (editingDomain != null) { + EditingDomainAdapter adapter = (EditingDomainAdapter) factory.adapt(editingDomain, + EditingDomainAdapter.class); + if (adapter != null) { + adapter.dispose(); + } + } + } + } + + public void partActivated(IWorkbenchPart part) { + // do nothing + } + + public void partDeactivated(IWorkbenchPart part) { + // do nothing + } + + public void partBroughtToTop(IWorkbenchPart part) { + // do nothing + } + + /** + * This element comes from the XText/GMF integration example, and was not originally documented. + */ + public static class Initializer implements IStartup { + public void earlyStartup() { + Display.getDefault().asyncExec(new Runnable() { + public void run() { + IWorkbenchPage activePage = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + activePage.addPartListener(new ConcurrentModificationObserver(activePage)); + } + }); + } + } + +} diff --git a/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/concurrency/EditingDomainAdapter.java b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/concurrency/EditingDomainAdapter.java new file mode 100644 index 00000000000..cb51de74209 --- /dev/null +++ b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/concurrency/EditingDomainAdapter.java @@ -0,0 +1,256 @@ +package org.eclipse.papyrus.infra.gmfdiag.xtext.glue.concurrency; + +import java.util.List; +import java.util.Map; + +import org.apache.log4j.Logger; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.emf.common.command.Command; +import org.eclipse.emf.common.notify.Adapter; +import org.eclipse.emf.common.notify.Notifier; +import org.eclipse.emf.common.notify.impl.AdapterFactoryImpl; +import org.eclipse.emf.common.notify.impl.AdapterImpl; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.emf.transaction.NotificationFilter; +import org.eclipse.emf.transaction.ResourceSetChangeEvent; +import org.eclipse.emf.transaction.ResourceSetListener; +import org.eclipse.emf.transaction.RollbackException; +import org.eclipse.emf.transaction.TransactionalEditingDomain; +import org.eclipse.emf.transaction.TransactionalEditingDomain.Lifecycle; +import org.eclipse.emf.transaction.TransactionalEditingDomainEvent; +import org.eclipse.emf.transaction.TransactionalEditingDomainListener; +import org.eclipse.emf.transaction.util.TransactionUtil; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.papyrus.infra.gmfdiag.xtext.glue.Activator; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.xtext.resource.IResourceServiceProvider; +import org.eclipse.xtext.resource.XtextResource; +import org.eclipse.xtext.ui.editor.IDirtyResource; +import org.eclipse.xtext.ui.editor.IDirtyStateManager; +import org.eclipse.xtext.ui.shared.Access; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; + +/** + * This element comes from the XText/GMF integration example, and was not originally documented. + */ +public class EditingDomainAdapter extends AdapterImpl implements ResourceSetListener, + TransactionalEditingDomainListener { + + /** + * This element comes from the XText/GMF integration example, and was not originally documented. + */ + public static class Factory extends AdapterFactoryImpl { + @Override + public boolean isFactoryForType(Object type) { + return super.isFactoryForType(type == EditingDomainAdapter.class); + } + + @Override + protected Object resolve(Object object, Object type) { + if (object instanceof TransactionalEditingDomain) { + return adapt(((TransactionalEditingDomain) object).getResourceSet(), type); + } + return super.resolve(object, type); + } + + @Override + protected Adapter createAdapter(Notifier target) { + if (target instanceof ResourceSet) { + return new EditingDomainAdapter(TransactionUtil.getEditingDomain(target)); + } else { + return null; + } + } + } + + private final TransactionalEditingDomain editingDomain; + + private IDirtyStateManager dirtyStateManager; + + private Map<URI, IDirtyResource> uri2dirtyResource; + + private static final Logger LOG = Logger.getLogger(EditingDomainAdapter.class); + + protected EditingDomainAdapter(TransactionalEditingDomain editingDomain) { + this.editingDomain = editingDomain; + editingDomain.addResourceSetListener(this); + dirtyStateManager = Access.getIDirtyStateManager().get(); + uri2dirtyResource = Maps.newHashMap(); + Lifecycle lifecycle = TransactionUtil.getAdapter(editingDomain, Lifecycle.class); + lifecycle.addTransactionalEditingDomainListener(this); + } + + public NotificationFilter getFilter() { + return null; + } + + public boolean isAggregatePrecommitListener() { + return true; + } + + public boolean isPostcommitOnly() { + return false; + } + + public boolean isPrecommitOnly() { + return false; + } + + public void resourceSetChanged(ResourceSetChangeEvent event) { + List<URI> remainingURIs = Lists.newArrayList(uri2dirtyResource.keySet()); + for (Resource resource : editingDomain.getResourceSet().getResources()) { + if (resource instanceof XtextResource) { + XtextResource xtextResource = (XtextResource) resource; + remainingURIs.remove(xtextResource.getURI()); + IDirtyResource dirtyResource = uri2dirtyResource.get(xtextResource.getURI()); + if (xtextResource.isModified()) { + if (dirtyResource == null) { + createAndRegisterDirtyState(xtextResource); + } + } else { + if (dirtyResource != null) { + uri2dirtyResource.remove(xtextResource.getURI()); + dirtyStateManager.discardDirtyState(dirtyResource); + } + } + } + } + // removed resources + for (URI remainingURI : remainingURIs) { + IDirtyResource dirtyResource = uri2dirtyResource.get(remainingURI); + dirtyStateManager.discardDirtyState(dirtyResource); + uri2dirtyResource.remove(remainingURI); + } + } + + public Command transactionAboutToCommit(ResourceSetChangeEvent event) throws RollbackException { + List<XtextResource> resourcesWithConflicts = null; + for (Resource resource : editingDomain.getResourceSet().getResources()) { + if (resource instanceof XtextResource && resource.isModified()) { + XtextResource xtextResource = (XtextResource) resource; + IDirtyResource dirtyResource = uri2dirtyResource.get(xtextResource.getURI()); + if (dirtyResource == null) { + if (!createAndRegisterDirtyState(xtextResource)) { + if (resourcesWithConflicts == null) { + resourcesWithConflicts = Lists.newArrayList(); + } + resourcesWithConflicts.add(xtextResource); + } + } + } + } + if (resourcesWithConflicts != null) { + if (queryApplyChanges()) { + for (XtextResource resourceWithConflicts : resourcesWithConflicts) { + try { + IDirtyResource dirtyResource = createDirtyResource(resourceWithConflicts); + // assert resource is serializable + dirtyResource.getContents(); + dirtyStateManager.announceDirtyStateChanged(dirtyResource); + } catch (Exception exc) { + LOG.error("Error serializing resource", exc); + } + } + } else { + throw new RollbackException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + "Transaction aborted by user")); + } + } + return null; + } + + protected boolean createAndRegisterDirtyState(XtextResource xtextResource) { + IDirtyResource dirtyResource = createDirtyResource(xtextResource); + if (dirtyResource == null) { + return true; + } else { + boolean isSuccess = dirtyStateManager.manageDirtyState(dirtyResource); + if (isSuccess) { + uri2dirtyResource.put(xtextResource.getURI(), dirtyResource); + } + return isSuccess; + } + } + + protected IDirtyResource createDirtyResource(XtextResource xtextResource) { + IResourceServiceProvider resourceServiceProvider = IResourceServiceProvider.Registry.INSTANCE + .getResourceServiceProvider(xtextResource.getURI()); + if (resourceServiceProvider == null) { + return null; + } + return new SimpleDirtyResource(xtextResource, resourceServiceProvider); + } + + public void editingDomainDisposing(TransactionalEditingDomainEvent event) { + dispose(); + } + + /** + * This element comes from the XText/GMF integration example, and was not originally documented. + */ + public void dispose() { + if (uri2dirtyResource != null) { + for (IDirtyResource dirtyResource : uri2dirtyResource.values()) { + dirtyStateManager.discardDirtyState(dirtyResource); + } + uri2dirtyResource = null; + } + Lifecycle lifecycle = TransactionUtil.getAdapter(editingDomain, Lifecycle.class); + if (lifecycle != null) { + lifecycle.removeTransactionalEditingDomainListener(this); + } + editingDomain.removeResourceSetListener(this); + } + + protected boolean queryApplyChanges() { + DialogPrompter dialogPrompter = new DialogPrompter(); + Display.getDefault().syncExec(dialogPrompter); + boolean yesResult = dialogPrompter.isYesResult(); + return yesResult; + } + + protected class DialogPrompter implements Runnable { + + private boolean isYesResult; + + public boolean isYesResult() { + return isYesResult; + } + + public void run() { + Shell shell = Display.getDefault().getActiveShell(); + isYesResult = MessageDialog.open(MessageDialog.QUESTION, shell, "Concurrent Modification", + "Other editors have a modified version of models you are going to change.\n" + + "If apply your changes you are loosing the possibility to save the others.\n" + + "Apply changes anyway?", SWT.NONE); + } + } + + public void transactionClosed(TransactionalEditingDomainEvent event) { + // do nothing + } + + public void transactionClosing(TransactionalEditingDomainEvent event) { + // do nothing + } + + public void transactionInterrupted(TransactionalEditingDomainEvent event) { + // do nothing + } + + public void transactionStarted(TransactionalEditingDomainEvent event) { + // do nothing + } + + public void transactionStarting(TransactionalEditingDomainEvent event) { + // do nothing + } + +} diff --git a/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/concurrency/SimpleDirtyResource.java b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/concurrency/SimpleDirtyResource.java new file mode 100644 index 00000000000..1108a6dbf91 --- /dev/null +++ b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/concurrency/SimpleDirtyResource.java @@ -0,0 +1,65 @@ +/******************************************************************************* + * Copyright (c) 2010 itemis AG (http://www.itemis.eu) 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 + *******************************************************************************/ +package org.eclipse.papyrus.infra.gmfdiag.xtext.glue.concurrency; + +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.xtext.resource.IResourceDescription; +import org.eclipse.xtext.resource.IResourceDescription.Manager; +import org.eclipse.xtext.resource.IResourceServiceProvider; +import org.eclipse.xtext.resource.XtextResource; +import org.eclipse.xtext.ui.editor.IDirtyResource; + +/** + * An implementation of {@link IDirtyResource} for resources without an underlying document. + * + * @author koehnlein - Initial contribution and API + */ +public class SimpleDirtyResource implements IDirtyResource { + + private XtextResource resource; + + private Manager resourceDescriptionManager; + + /** + * This element comes from the XText/GMF integration example, and was not originally documented. + * @param resource + * @param resourceServiceProvider + */ + public SimpleDirtyResource(XtextResource resource, IResourceServiceProvider resourceServiceProvider) { + this.resource = resource; + this.resourceDescriptionManager = resourceServiceProvider.getResourceDescriptionManager(); + } + + public String getContents() { + return resource.getSerializer().serialize(resource.getContents().get(0)); + } + + public String getActualContents() { + return getContents(); + } + + public IResourceDescription getDescription() { + return resourceDescriptionManager.getResourceDescription(resource); + } + + public URI getURI() { + return resource.getURI(); + } + + /** + * This element comes from the XText/GMF integration example, and was not originally documented. + * @return Resource + */ + public Resource getResource() { + return resource; + } + + + +} diff --git a/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/contentassist/CompletionProposalUtils.java b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/contentassist/CompletionProposalUtils.java new file mode 100644 index 00000000000..0e46b3393f8 --- /dev/null +++ b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/contentassist/CompletionProposalUtils.java @@ -0,0 +1,152 @@ +/*****************************************************************************
+ * Copyright (c) 2010 CEA LIST.
+ *
+ *
+ * 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:
+ * CEA LIST - Initial API and implementation
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.infra.gmfdiag.xtext.glue.contentassist;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.papyrus.infra.core.utils.DisplayUtils;
+import org.eclipse.uml2.uml.Element;
+import org.eclipse.uml2.uml.NamedElement;
+import org.eclipse.uml2.uml.Namespace;
+import org.eclipse.uml2.uml.Package;
+import org.eclipse.xtext.ui.editor.contentassist.ContentAssistContext;
+
+/**
+ * @author CEA LIST - Initial contribution and API
+ */
+public class CompletionProposalUtils {
+
+ protected final static ILabelProvider labelProvider = DisplayUtils.getLabelProvider() ;
+
+ /**
+ * Public Utility method for creating a completion proposal
+ *
+ * @param namedElement The named element for which completion proposal must be created
+ * @param completionString The actual completion string
+ * @param displayString The way the completion is displayed in the completion list
+ * @param context Some information related to the context of the completion
+ * @return completion proposal
+ */
+ public static CustomCompletionProposal createCompletionProposal(NamedElement namedElement,
+ String completionString,
+ String displayString,
+ ContentAssistContext context) {
+ String additionalProposalInfo = "" + namedElement.getQualifiedName() + "\n" + '(' + namedElement.eClass().getName() + ')' ;
+
+ CustomCompletionProposal completionProposal = new CustomCompletionProposal(completionString, // String to be inserted
+ context.getOffset(), // Offset
+ context.getSelectedText().length(), // Replacement length
+ completionString.length(), // cursorPosition
+ labelProvider.getImage(namedElement) , // image
+ " " + displayString, // displayString
+ null , // contextInformation
+ additionalProposalInfo, // additionalProposalInfo
+ context);
+ return completionProposal ;
+ }
+
+ /**
+ * Public Utility method for creating a completion proposal with replacement of prefix
+ *
+ * @param namedElement The named element for which completion proposal must be created
+ * @param completionString The actual completion string
+ * @param displayString The way the completion is displayed in the completion list
+ * @param context Some information related to the context of the completion
+ * @return completion proposal
+ */
+ public static CustomCompletionProposal createCompletionProposalWithReplacementOfPrefix(NamedElement namedElement,
+ String completionString,
+ String displayString,
+ ContentAssistContext context) {
+ String additionalProposalInfo = "" + namedElement.getQualifiedName() + "\n" + '(' + namedElement.eClass().getName() + ')' ;
+
+ CustomCompletionProposal completionProposal = new CustomCompletionProposal(completionString, // String to be inserted
+ context.getOffset() - context.getPrefix().length(), // Offset
+ context.getPrefix().length(), // Replacement length
+ completionString.length(), // cursorPosition
+ labelProvider.getImage(namedElement) , // image
+ " " + displayString, // displayString
+ null , // contextInformation
+ additionalProposalInfo, // additionalProposalInfo
+ context);
+ return completionProposal ;
+ }
+
+ /**
+ * Public Utility method for creating a completion proposal
+ *
+ * @param completionString The actual completion string
+ * @param displayString The way the completion is displayed in the completion list
+ * @param context Some information related to the context of the completion
+ * @return completion proposal
+ */
+ public static CustomCompletionProposal createCompletionProposal(String completionString,
+ String displayString,
+ ContentAssistContext context) {
+
+ CustomCompletionProposal completionProposal = new CustomCompletionProposal(completionString, // String to be inserted
+ context.getOffset(), // Offset
+ context.getSelectedText().length(), // Replacement length
+ completionString.length(), // cursorPosition
+ null , // image
+ " " + displayString, // displayString
+ null , // contextInformation
+ null, // additionalProposalInfo
+ context);
+ return completionProposal ;
+ }
+
+ /**
+ * Public utility method that computes a qualified name, taking into account packages imported by the namespace model
+ *
+ * @param namedElement
+ * @param model
+ * @return the qualified name label
+ */
+ public static String getQualifiedNameLabelWithSufficientDepth(NamedElement namedElement, Namespace model) {
+ String label = "" ;
+
+ List<Package> importedPackages = new ArrayList<Package>(model.getImportedPackages()) ;
+
+ List<Namespace> visitedNamespaces = new ArrayList<Namespace>() ;
+ Namespace currentNamespace = namedElement.getNamespace() ;
+
+ boolean rootFound = false ;
+ boolean modelIsTheRoot = false ;
+
+ while (currentNamespace != null && !rootFound) {
+ visitedNamespaces.add(currentNamespace) ;
+ if (importedPackages.contains(currentNamespace) || currentNamespace == model) {
+ rootFound = true ;
+ if (currentNamespace == model)
+ modelIsTheRoot = true ;
+ }
+ Element owner = currentNamespace.getOwner() ;
+ while (owner != null && !(owner instanceof Namespace))
+ owner = owner.getOwner() ;
+
+ currentNamespace = owner != null ? (Namespace)owner : null ;
+ }
+
+ for (int i = visitedNamespaces.size() - 1 - (modelIsTheRoot ? 1 : 0) ; i >= 0 ; i--) {
+ label += visitedNamespaces.get(i).getName() + "::" ;
+ }
+
+ return label + namedElement.getName() ;
+ }
+
+}
diff --git a/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/contentassist/CustomCompletionProposal.java b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/contentassist/CustomCompletionProposal.java new file mode 100644 index 00000000000..31f79f3e1a5 --- /dev/null +++ b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/contentassist/CustomCompletionProposal.java @@ -0,0 +1,132 @@ +/*****************************************************************************
+ * Copyright (c) 2010 CEA LIST.
+ *
+ *
+ * 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:
+ * CEA LIST - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.infra.gmfdiag.xtext.glue.contentassist;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.contentassist.CompletionProposal;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.jface.text.contentassist.ICompletionProposalExtension;
+import org.eclipse.jface.text.contentassist.IContextInformation;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.xtext.ui.editor.contentassist.ContentAssistContext;
+
+/**
+ * @author CEA LIST - Initial contribution and API
+ */
+public class CustomCompletionProposal implements ICompletionProposal, ICompletionProposalExtension {
+
+ private CompletionProposal completionProposal ;
+ private int fReplacementOffset ;
+ private ContentAssistContext fContentAssistContext ;
+ private String fReplacementString ;
+
+ /**
+ * @param replacementString
+ * @param replacementOffset
+ * @param replacementLength
+ * @param cursorPosition
+ * @param image
+ * @param displayString
+ * @param contextInformation
+ * @param additionalProposalInfo
+ * @param contentAssistContext
+ *
+ */
+ public CustomCompletionProposal (String replacementString,
+ int replacementOffset,
+ int replacementLength,
+ int cursorPosition,
+ Image image,
+ String displayString,
+ IContextInformation contextInformation,
+ String additionalProposalInfo,
+ ContentAssistContext contentAssistContext) {
+ completionProposal = new CompletionProposal(replacementString,
+ replacementOffset,
+ replacementLength,
+ cursorPosition,
+ image,
+ displayString,
+ contextInformation,
+ additionalProposalInfo) ;
+ fReplacementOffset = replacementOffset ;
+ fReplacementString = replacementString ;
+ fContentAssistContext = contentAssistContext ;
+ }
+
+ public void apply(IDocument document, char trigger, int offset) {
+ try {
+ int length = 0 ;
+ if (offset != fReplacementOffset)
+ length = offset - fReplacementOffset ;
+ else
+ length = fContentAssistContext.getSelectedText().length() ;
+ document.replace(fReplacementOffset ,
+ length,
+ fReplacementString) ;
+ }
+ catch (BadLocationException e) {
+ // ignore
+ }
+ }
+
+ public boolean isValidFor(IDocument document, int offset) {
+ try {
+ int length = offset - fReplacementOffset ;
+ return completionProposal.getDisplayString().toLowerCase().contains(document.get(fReplacementOffset, length).toLowerCase()) ;
+ }
+ catch (BadLocationException e) {
+ // ignore
+ }
+ return false;
+ }
+
+ public char[] getTriggerCharacters() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public int getContextInformationPosition() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public void apply(IDocument document) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public Point getSelection(IDocument document) {
+ return completionProposal.getSelection(document);
+ }
+
+ public String getAdditionalProposalInfo() {
+ return completionProposal.getAdditionalProposalInfo();
+ }
+
+ public String getDisplayString() {
+ return completionProposal.getDisplayString();
+ }
+
+ public Image getImage() {
+ return completionProposal.getImage();
+ }
+
+ public IContextInformation getContextInformation() {
+ return completionProposal.getContextInformation();
+ }
+
+}
diff --git a/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/edit/part/AntlrParserWrapper.java b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/edit/part/AntlrParserWrapper.java new file mode 100644 index 00000000000..2b61fd571cd --- /dev/null +++ b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/edit/part/AntlrParserWrapper.java @@ -0,0 +1,123 @@ +/******************************************************************************* + * Copyright (c) 2009 itemis AG (http://www.itemis.eu) 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 + *******************************************************************************/ +package org.eclipse.papyrus.infra.gmfdiag.xtext.glue.edit.part; + +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.gmf.runtime.common.core.command.ICommand; +import org.eclipse.gmf.runtime.common.ui.services.parser.IParser; +import org.eclipse.gmf.runtime.common.ui.services.parser.IParserEditStatus; +import org.eclipse.jface.text.contentassist.IContentAssistProcessor; +import org.eclipse.xtext.parser.IParseResult; +import org.eclipse.xtext.ui.editor.contentassist.XtextContentAssistProcessor; + +import com.google.inject.Inject; +import com.google.inject.Injector; +//import org.eclipse.xtext.parser.antlr.IAntlrParser; +//import org.eclipse.xtext.parsetree.CompositeNode; +//import org.eclipse.xtext.parsetree.NodeAdapter; +//import org.eclipse.xtext.parsetree.NodeUtil; +//import org.eclipse.xtext.parsetree.SyntaxError; + +/** + * Wraps a (partial) Xtext parser in a GMF {@link IParser}. + * + * @author koehnlein + */ +public class AntlrParserWrapper implements IParser { + + @Inject + private XtextContentAssistProcessor xtextContentAssistProcessor; + + @Inject + private org.eclipse.xtext.parser.IParser xtextParser; + + private final String parserRuleName; + + private final IParser originalParser; + + /** + * This element comes from the XText/GMF integration example, and was not originally documented. + * @param parserRuleName + * @param originalParser + * @param xtextInjector + */ + public AntlrParserWrapper(String parserRuleName, IParser originalParser, Injector xtextInjector) { + this.parserRuleName = parserRuleName; + this.originalParser = originalParser; + xtextInjector.injectMembers(this); + } + + public IContentAssistProcessor getCompletionProcessor(IAdaptable element) { + // TODO does not work. need to fake an XtextDocument + return xtextContentAssistProcessor; + } + + public String getEditString(IAdaptable element, int flags) { +// EObject semanticElement = (EObject) element.getAdapter(EObject.class); +// if (semanticElement != null) { +// NodeAdapter nodeAdapter = NodeUtil.getNodeAdapter(semanticElement); +// if (nodeAdapter != null) { +// return nodeAdapter.getParserNode().serialize().trim(); +// } +// } + return "invalid"; + } + + public ICommand getParseCommand(IAdaptable element, final String newString, int flags) { +// EObject semanticElement = (EObject) element.getAdapter(EObject.class); +// if (semanticElement != null) { +// IParseResult parseResult = xtextParser.parse(parserRuleName, new StringInputStream(newString)); +// if (isValidParseResult(parseResult, semanticElement)) { +// NodeAdapter nodeAdapter = NodeUtil.getNodeAdapter(semanticElement); +// if (nodeAdapter != null) { +// final ICompositeNode parserNode = nodeAdapter.getParserNode(); +// final XtextResource semanticResource = (XtextResource) semanticElement.eResource(); +// ICommand reparseCommand = UpdateXtextResourceTextCommand.createUpdateCommand(semanticResource, +// parserNode.getOffset(), parserNode.getLength(), newString); +// return reparseCommand; +// } +// } +// } +// return UnexecutableCommand.INSTANCE; + return null ; + } + + public String getPrintString(IAdaptable element, int flags) { + return originalParser.getPrintString(element, flags); + } + + public boolean isAffectingEvent(Object event, int flags) { + return false; + } + + public IParserEditStatus isValidEditString(IAdaptable element, String editString) { +// try { +// IParseResult parseResult = xtextParser.parse(parserRuleName, new StringInputStream(editString)); +// if (isValidParseResult(parseResult, (EObject) element.getAdapter(EObject.class))) { +// return new ParserEditStatus(IStatus.OK, Activator.PLUGIN_ID, IParserEditStatus.EDITABLE, "OK", null); +// } else { +// SyntaxError syntaxError = parseResult.getParseErrors().get(0); +// return new ParserEditStatus(IStatus.INFO, Activator.PLUGIN_ID, IParserEditStatus.UNEDITABLE, +// syntaxError.getMessage(), null); +// } +// } catch (Exception exc) { +// return new ParserEditStatus(IStatus.INFO, Activator.PLUGIN_ID, IParserEditStatus.UNEDITABLE, exc +// .getMessage(), exc); +// } + return null ; + } + + private boolean isValidParseResult(IParseResult parseResult, EObject semanticElement) { +// EObject rootASTElement = parseResult.getRootASTElement(); +// return parseResult.getParseErrors().isEmpty() && rootASTElement != null && semanticElement != null +// && semanticElement.eClass() == rootASTElement.eClass(); + return false ; + } + +} diff --git a/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/edit/part/DefaultXtextSemanticValidator.java b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/edit/part/DefaultXtextSemanticValidator.java new file mode 100644 index 00000000000..64f0219be9c --- /dev/null +++ b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/edit/part/DefaultXtextSemanticValidator.java @@ -0,0 +1,32 @@ +/*****************************************************************************
+ * Copyright (c) 2010 CEA LIST.
+ *
+ *
+ * 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:
+ * CEA LIST - Initial API and implementation
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.infra.gmfdiag.xtext.glue.edit.part;
+
+/**
+ * Default implementation for IXtextSemanticValidator.
+ *
+ * @author CEA LIST - Initial contribution and API
+ */
+public class DefaultXtextSemanticValidator implements IXTextSemanticValidator {
+
+ /**
+ * Default implementation. Always returns true.
+ * @return always returns true.
+ */
+ public boolean validate() {
+ return true;
+ }
+
+}
diff --git a/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/edit/part/IXTextSemanticValidator.java b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/edit/part/IXTextSemanticValidator.java new file mode 100644 index 00000000000..274ca08acec --- /dev/null +++ b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/edit/part/IXTextSemanticValidator.java @@ -0,0 +1,33 @@ +/*****************************************************************************
+ * Copyright (c) 2010 CEA LIST.
+ *
+ *
+ * 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:
+ * CEA LIST - Initial API and implementation
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.infra.gmfdiag.xtext.glue.edit.part;
+
+/**
+ * Optional interface to be implemented by each client plug-in. The validation is taken into account before
+ * closing a textual editor, in order to determine if the model contains semantic errors. If it contains
+ * semantic errors, modifications are not saved in order to avoid corrupting the context UML model.
+ *
+ * @author CEA LIST - Initial contribution and API
+ */
+public interface IXTextSemanticValidator {
+
+
+ /**
+ *
+ * @return Implementations must return true if the xtext model is semantically valid
+ */
+ public boolean validate() ;
+
+}
diff --git a/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/edit/part/IXtextEMFReconciler.java b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/edit/part/IXtextEMFReconciler.java new file mode 100644 index 00000000000..137c58a0462 --- /dev/null +++ b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/edit/part/IXtextEMFReconciler.java @@ -0,0 +1,36 @@ +/*****************************************************************************
+ * Copyright (c) 2010 CEA LIST.
+ *
+ *
+ * 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:
+ * CEA LIST - Initial API and implementation
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.infra.gmfdiag.xtext.glue.edit.part;
+
+import org.eclipse.emf.ecore.EObject;
+
+/**
+ * This interface is used for the reconciliation of the context UML model with respect to the textual
+ * specification obtained via edition from a popup xtext editor, in the case where this edition implies
+ * changes in the original model.
+ *
+ * @author CEA LIST - Initial contribution and API
+ */
+public interface IXtextEMFReconciler {
+
+ /**
+ * This method is called for performing the reconciliation, in the case where the popup xtext editor is
+ * closed with request for saving (i.e., by pressing ctrl + enter).
+ * @param modelObject The context UML model element
+ * @param xtextObject The xtext object resulting from the textual specification
+ */
+ void reconcile (EObject modelObject, EObject xtextObject) ;
+
+}
diff --git a/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/edit/part/PopupXtextEditorHelper.java b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/edit/part/PopupXtextEditorHelper.java new file mode 100644 index 00000000000..475ec38eee0 --- /dev/null +++ b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/edit/part/PopupXtextEditorHelper.java @@ -0,0 +1,477 @@ +/*******************************************************************************
+ * Copyright (c) 2009 itemis AG (http://www.itemis.eu) 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
+ *******************************************************************************/
+package org.eclipse.papyrus.infra.gmfdiag.xtext.glue.edit.part;
+
+
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.commands.operations.IOperationHistory;
+import org.eclipse.core.commands.operations.IUndoContext;
+import org.eclipse.core.expressions.Expression;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
+import org.eclipse.gmf.runtime.diagram.ui.parts.DiagramEditDomain;
+import org.eclipse.gmf.runtime.diagram.ui.parts.IDiagramEditDomain;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.commands.ActionHandler;
+import org.eclipse.jface.text.ITextOperationTarget;
+import org.eclipse.jface.text.contentassist.ContentAssistant;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.text.source.SourceViewer;
+import org.eclipse.jface.text.templates.TemplateException;
+import org.eclipse.jface.viewers.TextCellEditor;
+import org.eclipse.papyrus.commands.CheckedOperationHistory;
+import org.eclipse.papyrus.extensionpoints.editors.ui.IPopupEditorHelper;
+import org.eclipse.papyrus.infra.gmfdiag.xtext.glue.Activator;
+import org.eclipse.papyrus.infra.gmfdiag.xtext.glue.partialEditing.CustomXtextSourceViewer;
+import org.eclipse.papyrus.infra.gmfdiag.xtext.glue.partialEditing.ISyntheticResourceProvider;
+import org.eclipse.papyrus.infra.gmfdiag.xtext.glue.partialEditing.OperationHistoryListener;
+import org.eclipse.papyrus.infra.gmfdiag.xtext.glue.partialEditing.PartialModelEditor;
+import org.eclipse.papyrus.infra.gmfdiag.xtext.glue.partialEditing.SourceViewerHandle;
+import org.eclipse.papyrus.infra.gmfdiag.xtext.glue.partialEditing.SourceViewerHandleFactory;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.FocusListener;
+import org.eclipse.swt.graphics.FontMetrics;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.text.undo.DocumentUndoManagerRegistry;
+import org.eclipse.text.undo.IDocumentUndoManager;
+import org.eclipse.ui.ActiveShellExpression;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchCommandConstants;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.console.actions.TextViewerAction;
+import org.eclipse.ui.handlers.IHandlerActivation;
+import org.eclipse.ui.handlers.IHandlerService;
+import org.eclipse.ui.texteditor.ITextEditorActionConstants;
+import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
+import org.eclipse.ui.texteditor.IUpdate;
+import org.eclipse.xtext.parser.IParseResult;
+import org.eclipse.xtext.resource.XtextResource;
+import org.eclipse.xtext.ui.editor.model.IXtextDocument;
+import org.eclipse.xtext.util.concurrent.IUnitOfWork;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.inject.Injector;
+
+/**
+ * Base class to handle a small in-diagram XtextEditor.
+ *
+ * Override the generated <code>performDirectEdit</code> methods in the EditPart of the label to be directly edited, and
+ * call {@link #showEditor()} instead of opening the default {@link TextCellEditor}.
+ *
+ * @author koehnlein
+ * @author CEA LIST (A. Cuccuru, A. Radermacher): Modifications for the integration into Papyrus
+ * Changes:
+ * - Added "implements" relationship towards IPopupEditorHelper,
+ * related to the DirectEditor extension point of Papyrus
+ * - Signature of the constructor modified
+ * - Method showEditor modified, with the creation of a temporary file, underlying the popup xtext editor
+ * - Method closeEditor modified, with new statements for managing the reconciliation between the original
+ * UML model and the textual specification resulting from the edition in the popup xtext editor. The
+ * temporary text file created by showEditor is also deleted.
+ * - Method createXTextEditor modified. Now uses the Papyrus IEditorSite, and also adds a focus listener for
+ * managing the context eobject and current xtext editor.
+ * - Method setEditorRegin modified (needs some work...)
+ * - Method setEditorBounds modified (needs some work...)
+ * - Method activateServices and deactivateServices, for managing the key binding of the context diagram
+ * editor.
+ */
+
+public class PopupXtextEditorHelper implements IPopupEditorHelper {
+
+ private static IGraphicalEditPart hostEditPart;
+ private IEditorPart diagramEditor;
+ private int editorOffset;
+ private int initialEditorSize;
+ private int initialDocumentSize;
+ private Composite xtextEditorComposite;
+ private final Injector xtextInjector;
+ private XtextResource xtextResource;
+ private String semanticElementFragment;
+ private EObject semanticElement ;
+ private String textToEdit ;
+ /** prevent the reconciliation from being applied twice (See Bug 395439) */
+ private boolean closing = false;
+
+ /**
+ * get the host editpart
+ * @return the editpart
+ */
+ public static IGraphicalEditPart getHostEditPart() {
+ return hostEditPart;
+ }
+
+ /**
+ * The file extension used to dynamically select the appropriate xtext editor
+ */
+ public static String fileExtension ;
+ private IXtextEMFReconciler modelReconciler;
+ private ISyntheticResourceProvider resourceProvider ;
+ private SourceViewerHandle sourceViewerHandle ;
+
+ /**
+ * @return The source viewer handle for this PopupXtextEditorHelper
+ *
+ */
+ public SourceViewerHandle getSourceViewerHandle() {
+ return sourceViewerHandle;
+ }
+
+ private PartialModelEditor partialEditor ;
+ private Shell diagramShell ;
+ private OperationHistoryListener operationHistoryListener;
+ private IXTextSemanticValidator semanticValidator ;
+ /**
+ * The context EObject for this editor. It can be used for content assist, verification, etc.
+ */
+ public static EObject context ;
+
+ /**
+ *
+ */
+ public static boolean ignoreFocusLost = false ;
+
+ /**
+ * This element was originally undocumented in the XText/GMF integration example
+ *
+ * Modifications performed by CEA LIST
+ * - Signature changed: was public PopupXtextEditorHelper(IGraphicalEditPart editPart, Injector xtextInjector)
+ * @param editPart The editPart on which a direct edit has been performed.
+ * @param xtextInjector The xtextInjector.
+ * @param modelReconciler The IXtextEMFReconciler, to update the context UML model with changes textually specified in the popup xtext editor
+ * @param textToEdit the initialization text, used as the initial textual content for the popup xtext editor
+ * @param fileExtension the extension for the temporary textual file (underlying the editor)
+ * @param semanticValidator the semantic validator used to semantically validate the xtext model before saving
+ */
+ public PopupXtextEditorHelper(IGraphicalEditPart editPart,
+ Injector xtextInjector,
+ IXtextEMFReconciler modelReconciler,
+ String textToEdit,
+ String fileExtension,
+ IXTextSemanticValidator semanticValidator) {
+ this.hostEditPart = editPart;
+ this.xtextInjector = xtextInjector ;
+ this.textToEdit = "" + textToEdit ;
+ this.modelReconciler = modelReconciler ;
+ PopupXtextEditorHelper.fileExtension = "" + fileExtension ;
+ this.semanticValidator = semanticValidator ;
+ ignoreFocusLost = false ;
+ }
+
+ /**
+ * This element was originally not documented in the XText / GMF integration example.
+ *
+ */
+ public void showEditor() {
+ try {
+ semanticElement = hostEditPart.resolveSemanticElement();
+ if (semanticElement == null) {
+ return;
+ }
+ context = semanticElement ;
+ Resource semanticResource = semanticElement.eResource();
+
+ semanticElementFragment = semanticResource.getURIFragment(semanticElement);
+ if (semanticElementFragment == null || "".equals(semanticElementFragment)) {
+ return;
+ }
+ IDiagramEditDomain diagramEditDomain = hostEditPart.getDiagramEditDomain();
+
+ diagramEditor = ((DiagramEditDomain) diagramEditDomain).getEditorPart();
+
+ createXtextEditor(null) ;
+
+ } catch (Exception e) {
+ Activator.logError(e);
+ }
+ }
+
+ /**
+ * This element was originally not documented in the XText/GMF integration example.
+ *
+ * Changes performed by CEA LIST:
+ * - new statements for managing the reconciliation between the original UML model and
+ * the textual specification resulting from the edition in the popup xtext editor.
+ * @param isReconcile Determines whether a reconciliation must be performed or not
+ */
+ public void closeEditor(boolean isReconcile) {
+ if (sourceViewerHandle != null) {
+ if (!closing) {
+ if (isReconcile && this.semanticValidator.validate()) {
+ try {
+ final IXtextDocument xtextDocument = sourceViewerHandle.getDocument();
+ if (!isDocumentHasErrors(xtextDocument)) {
+ int documentGrowth = xtextDocument.getLength() - initialDocumentSize;
+ String newText = xtextDocument.get(editorOffset, initialEditorSize + documentGrowth);
+ xtextResource = partialEditor.createResource(newText);
+ if (xtextResource.getAllContents().hasNext())
+ modelReconciler.reconcile(semanticElement, xtextResource.getAllContents().next());
+ }
+ } catch (Exception exc) {
+ Activator.logError(exc);
+ }
+ }
+ }
+ try {
+ closing = true;
+ xtextEditorComposite.setVisible(false);
+ xtextEditorComposite.dispose();
+ } finally {
+ closing = false;
+ }
+ }
+ SourceViewerHandle.bindPartialModelEditorClass(null) ;
+ }
+
+ /**
+ * This element was originally not documented in the XText/GMF integration example
+ *
+ * Changes performed by CEA LIST:
+ * - adds a focus listener for managing the context eobject and current xtext editor.
+ *
+ * @param editorInput
+ */
+ private void createXtextEditor(IEditorInput editorInput) throws Exception {
+ diagramShell = diagramEditor.getSite().getShell();
+ xtextEditorComposite = new Shell(SWT.RESIZE) ;
+ xtextEditorComposite.setLayout(new FillLayout());
+
+
+ resourceProvider = xtextInjector.getInstance(ISyntheticResourceProvider.class) ;
+ SourceViewerHandleFactory factory = xtextInjector.getInstance(SourceViewerHandleFactory.class) ;
+ sourceViewerHandle = factory.create(xtextEditorComposite, resourceProvider) ;
+ partialEditor = sourceViewerHandle.createPartialEditor("", textToEdit, "", semanticElement, modelReconciler) ;
+ registerKeyListener();
+ setEditorBounds();
+
+ initializeActions();
+ installUndoRedoSupport(sourceViewerHandle.getViewer());
+
+ sourceViewerHandle.getViewer().getTextWidget().addFocusListener(new FocusListener() {
+
+ public void focusLost(FocusEvent e) {
+ checkedClose();
+ }
+
+ public void focusGained(FocusEvent e) {
+ context = semanticElement ;
+ }
+ }) ;
+
+ xtextEditorComposite.setVisible(true);
+ sourceViewerHandle.getViewer().showAnnotationsOverview(true) ;
+ sourceViewerHandle.getViewer().getTextWidget().setFocus() ;
+
+ // This last statement is used to trigger initial validation
+ sourceViewerHandle.getViewer().getTextWidget().append("") ;
+ }
+
+ /**
+ * Perform additional checks before close
+ * (added by CEA LIST)
+ */
+ private void checkedClose() {
+ context = semanticElement ;
+ if (! keyListener.isContentAssistActive()) {
+ // additional sanity check: on X11 systems, the focus is already lost during resize.
+ // An unwanted closing can be prevented by verifying if the activeShell still points
+ // to the xtextEditorComposite
+ if (xtextEditorComposite.getDisplay().getActiveShell() != xtextEditorComposite) {
+ if (!ignoreFocusLost) {
+ closeEditor(true) ;
+ }
+ else
+ closeEditor(false) ;
+ }
+ }
+ }
+
+
+ private PopupXtextEditorKeyListener keyListener ;
+
+ private void registerKeyListener() {
+ //XtextSourceViewer sourceViewer = (XtextSourceViewer) xtextEditor.getInternalSourceViewer();
+ final StyledText xtextTextWidget = sourceViewerHandle.getViewer().getTextWidget();
+ CustomXtextSourceViewer viewer = (CustomXtextSourceViewer)sourceViewerHandle.getViewer() ;
+ keyListener =
+ new PopupXtextEditorKeyListener
+ (this, (ContentAssistant) viewer.getContentAssistant());
+ //keyListener.installUndoRedoSupport(sourceViewerHandle.getViewer()) ;
+ xtextTextWidget.addVerifyKeyListener(keyListener);
+ xtextTextWidget.addKeyListener(keyListener);
+ }
+
+ /**
+ * This element was originally not documented in the XText/GMF integration example
+ *
+ * Modifications from CEA LIST:
+ * - modifications to rules for computing the initial location and size of the popup editor.
+ * This still needs some work...
+ */
+ private void setEditorBounds() {
+
+ String editString = "" + textToEdit ;
+ int[] numLinesNumColums = StringUtil.getNumLinesNumColumns(editString) ;
+ int numLines = numLinesNumColums[0] ;
+ int numColumns = numLinesNumColums[1];
+ // ninimal sizes
+ if (numLines < 5) {
+ numLines = 5;
+ }
+ if (numColumns < 60) {
+ numColumns = 60;
+ }
+
+ IFigure figure = hostEditPart.getFigure() ;
+ Rectangle bounds = figure.getBounds().getCopy();
+ figure.translateToAbsolute(bounds) ;
+ Point newCoord = diagramShell.getDisplay().map(hostEditPart.getViewer().getControl(), null, new Point(bounds.x, bounds.y)) ;
+ bounds.x = newCoord.x ;
+ bounds.y = newCoord.y ;
+
+ // not used, delivers wrong results
+ // FontData fontData = figure.getFont().getFontData()[0];
+ // int fontHeightInPixel = fontData.getHeight();
+
+ GC gc = new GC (xtextEditorComposite);
+ FontMetrics fm = gc.getFontMetrics ();
+ int width = numColumns * fm.getAverageCharWidth () + 40;
+ int height = numLines * fm.getHeight();
+ gc.dispose ();
+
+ // xtextEditorComposite contains a composite which in turn contains the text widget and an area for markers.
+ // Take difference between client area and size into account. Cannot set size of text widget directly,
+ // since suitable packing is not supported by the layout of the text widget's parent.
+ org.eclipse.swt.graphics.Rectangle clientArea = xtextEditorComposite.getClientArea();
+ // only correct height, since width is estimated anyway.
+ height += xtextEditorComposite.getSize().y - clientArea.height;
+ xtextEditorComposite.setBounds(bounds.x, bounds.y, width, height);
+ }
+
+
+
+
+ private boolean isDocumentHasErrors(final IXtextDocument xtextDocument) {
+ return (xtextDocument.readOnly(new IUnitOfWork<Boolean, XtextResource>() {
+ public Boolean exec(XtextResource state) throws Exception {
+ IParseResult parseResult = state.getParseResult();
+ return !state.getErrors().isEmpty() || parseResult == null || parseResult.hasSyntaxErrors();
+ }
+ }));
+ }
+
+ protected Status createErrorStatus(String message, TemplateException e) {
+ return new Status(IStatus.ERROR,
+ "org.eclipse.papyrus.property.editor.xtext",message, e);
+
+ }
+
+
+ protected void installUndoRedoSupport(SourceViewer viewer) {
+ IDocumentUndoManager undoManager = DocumentUndoManagerRegistry.getDocumentUndoManager(viewer.getDocument());
+ final IUndoContext context = undoManager.getUndoContext();
+ IOperationHistory operationHistory = CheckedOperationHistory.getInstance();
+ operationHistoryListener = new OperationHistoryListener(context, new IUpdate() {
+ public void update() {
+ updateAction(ITextEditorActionConstants.REDO);
+ updateAction(ITextEditorActionConstants.UNDO);
+ }
+ });
+ operationHistory.addOperationHistoryListener(operationHistoryListener);
+ }
+
+ private Map<String, org.eclipse.ui.console.actions.TextViewerAction> fGlobalActions= Maps.newHashMapWithExpectedSize(10);
+ private List<String> fSelectionActions = Lists.newArrayListWithExpectedSize(3);
+
+ protected void updateAction(String actionId) {
+ IAction action= fGlobalActions.get(actionId);
+ if (action instanceof IUpdate)
+ ((IUpdate) action).update();
+ }
+
+ protected void uninstallUndoRedoSupport() {
+ IOperationHistory operationHistory = PlatformUI.getWorkbench().getOperationSupport().getOperationHistory();
+ operationHistory.removeOperationHistoryListener(operationHistoryListener);
+ operationHistoryListener = null;
+ }
+
+ private void initializeActions() {
+ final List<IHandlerActivation> handlerActivations= Lists.newArrayListWithExpectedSize(3);
+ final IHandlerService handlerService= (IHandlerService) PlatformUI.getWorkbench().getAdapter(IHandlerService.class);
+ final Expression expression= new ActiveShellExpression(sourceViewerHandle.getViewer().getControl().getShell());
+
+ diagramShell.addDisposeListener(new DisposeListener() {
+ public void widgetDisposed(DisposeEvent e) {
+ handlerService.deactivateHandlers(handlerActivations);
+ }
+ });
+
+ TextViewerAction action= new TextViewerAction(sourceViewerHandle.getViewer(), ITextOperationTarget.UNDO);
+ action.setText("UNDO");
+ fGlobalActions.put(ITextEditorActionConstants.UNDO, action);
+
+ action= new TextViewerAction(sourceViewerHandle.getViewer(), ITextOperationTarget.REDO);
+ action.setText("REDO");
+ fGlobalActions.put(ITextEditorActionConstants.REDO, action);
+
+ action= new TextViewerAction(sourceViewerHandle.getViewer(), ITextOperationTarget.CUT);
+ action.setText("CUT");
+ fGlobalActions.put(ITextEditorActionConstants.CUT, action);
+
+ action= new TextViewerAction(sourceViewerHandle.getViewer(), ITextOperationTarget.COPY);
+ action.setText("COPY");
+ fGlobalActions.put(ITextEditorActionConstants.COPY, action);
+
+ action= new TextViewerAction(sourceViewerHandle.getViewer(), ITextOperationTarget.PASTE);
+ action.setText("PASTE");
+ fGlobalActions.put(ITextEditorActionConstants.PASTE, action);
+
+ action= new TextViewerAction(sourceViewerHandle.getViewer(), ITextOperationTarget.SELECT_ALL);
+ action.setText("SELECT_ALL");
+ fGlobalActions.put(ITextEditorActionConstants.SELECT_ALL, action);
+
+ action= new TextViewerAction(sourceViewerHandle.getViewer(), ISourceViewer.CONTENTASSIST_PROPOSALS);
+ action.setText("CONTENTASSIST_PROPOSALS");
+ fGlobalActions.put(ITextEditorActionConstants.CONTENT_ASSIST, action);
+
+ fSelectionActions.add(ITextEditorActionConstants.CUT);
+ fSelectionActions.add(ITextEditorActionConstants.COPY);
+ fSelectionActions.add(ITextEditorActionConstants.PASTE);
+
+ sourceViewerHandle.getViewer().getTextWidget().addFocusListener(new FocusListener() {
+ public void focusLost(FocusEvent e) {
+ handlerService.deactivateHandlers(handlerActivations);
+ }
+ public void focusGained(FocusEvent e) {
+ IAction action= fGlobalActions.get(ITextEditorActionConstants.REDO);
+ handlerActivations.add(handlerService.activateHandler(IWorkbenchCommandConstants.EDIT_REDO, new ActionHandler(action), expression));
+ action= fGlobalActions.get(ITextEditorActionConstants.UNDO);
+ handlerActivations.add(handlerService.activateHandler(IWorkbenchCommandConstants.EDIT_UNDO, new ActionHandler(action), expression));
+ action= fGlobalActions.get(ITextEditorActionConstants.CONTENT_ASSIST);
+ handlerActivations.add(handlerService.activateHandler(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS, new ActionHandler(action), expression));
+ }
+ });
+
+ }
+}
diff --git a/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/edit/part/PopupXtextEditorKeyListener.java b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/edit/part/PopupXtextEditorKeyListener.java new file mode 100644 index 00000000000..0cc682bb923 --- /dev/null +++ b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/edit/part/PopupXtextEditorKeyListener.java @@ -0,0 +1,98 @@ +/******************************************************************************* + * Copyright (c) 2010 itemis AG (http://www.itemis.eu) 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 + *******************************************************************************/ +package org.eclipse.papyrus.infra.gmfdiag.xtext.glue.edit.part; + +import org.eclipse.jface.text.contentassist.ContentAssistEvent; +import org.eclipse.jface.text.contentassist.ContentAssistant; +import org.eclipse.jface.text.contentassist.ICompletionListener; +import org.eclipse.jface.text.contentassist.ICompletionProposal; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.VerifyKeyListener; +import org.eclipse.swt.events.KeyAdapter; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.VerifyEvent; + +/** + * @author koehnlein + */ +public class PopupXtextEditorKeyListener extends KeyAdapter implements VerifyKeyListener { + + private final PopupXtextEditorHelper popupXtextEditorHelper; + + private ContentAssistant contentAssistant; + + private boolean isIgnoreNextESC; + + /** + * This element comes from the XText/GMF integration example, and was not originally documented. + * @param popupXtextEditorHelper + * @param contentAssistant + */ + public PopupXtextEditorKeyListener(PopupXtextEditorHelper popupXtextEditorHelper, ContentAssistant contentAssistant) { + this.popupXtextEditorHelper = popupXtextEditorHelper; + this.contentAssistant = contentAssistant; + isIgnoreNextESC = false; + } + + @Override + public void keyPressed(KeyEvent e) { + int keyCode = e.keyCode; + if ((e.stateMask & SWT.CTRL) != 0 && ((keyCode == SWT.KEYPAD_CR) || (keyCode == SWT.CR))) { + this.popupXtextEditorHelper.closeEditor(true); + } + if (keyCode == SWT.ESC) { + if (isIgnoreNextESC) { + isIgnoreNextESC = false; + } else { + PopupXtextEditorHelper.ignoreFocusLost = true ; + this.popupXtextEditorHelper.closeEditor(false); + } + } + if ((e.stateMask & SWT.CTRL) != 0 && (keyCode == ' ')) { + this.contentAssistant.setRepeatedInvocationMode(true) ; + this.contentAssistant.showPossibleCompletions() ; + + this.isIgnoreNextESC = true ; + contentAssistant.addCompletionListener(new ICompletionListener() { + + public void selectionChanged(ICompletionProposal proposal, boolean smartToggle) { + } + + public void assistSessionStarted(ContentAssistEvent event) { + } + + public void assistSessionEnded(ContentAssistEvent event) { + try { + popupXtextEditorHelper.getSourceViewerHandle().getViewer().getTextWidget().setFocus() ; + } + catch (Exception e) { + //ignore + } + } + }) ; + } + } + + public void verifyKey(VerifyEvent e) { + if (e.keyCode == SWT.ESC && isContentAssistActive()) { + isIgnoreNextESC = true; + } + if ((e.stateMask & SWT.CTRL) != 0 && ((e.keyCode == SWT.KEYPAD_CR) || (e.keyCode == SWT.CR))) { + e.doit = false; + } + } + + /** + * @return true if the proposal popup has focus + * + */ + public boolean isContentAssistActive() { + return contentAssistant != null && contentAssistant.hasProposalPopupFocus(); + } + +}
\ No newline at end of file diff --git a/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/edit/part/StringUtil.java b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/edit/part/StringUtil.java new file mode 100644 index 00000000000..e15dc5553f6 --- /dev/null +++ b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/edit/part/StringUtil.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2009 itemis AG (http://www.itemis.eu) 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 + *******************************************************************************/ +package org.eclipse.papyrus.infra.gmfdiag.xtext.glue.edit.part; + +/** + * @author koehnlein + */ +public class StringUtil { + + /** + * This element comes from the XText/GMF integration example, and was not originally documented. + * @param s + * @return int + */ + public static int[] getNumLinesNumColumns(String s) { + int numLines = 1; + int numColumns = 0; + int[] dimensions = new int[2] ; + dimensions[0] = numLines ; + dimensions[1] = 0 ; + for (char c : s.toCharArray()) { + if (c == '\n') { + ++numLines; + dimensions[1] = Math.max(dimensions[1], numColumns) ; + numColumns = 0 ; + } + else { + ++numColumns; + } + } + dimensions[0] = numLines ; + dimensions[1] = Math.max(dimensions[1], numColumns) ; + return dimensions; + } + +} diff --git a/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/editingdomain/ChangeAggregatorAdapter.java b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/editingdomain/ChangeAggregatorAdapter.java new file mode 100644 index 00000000000..d3a9fdc516f --- /dev/null +++ b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/editingdomain/ChangeAggregatorAdapter.java @@ -0,0 +1,163 @@ +/******************************************************************************* + * Copyright (c) 2009 itemis AG (http://www.itemis.eu) 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 + *******************************************************************************/ +package org.eclipse.papyrus.infra.gmfdiag.xtext.glue.editingdomain; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import org.eclipse.emf.common.notify.Notification; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.util.EContentAdapter; +import org.eclipse.xtext.resource.XtextResource; + +import com.google.common.collect.Lists; + +/** + * @author Knut Wannheden - Initial contribution and API + * @author Jan Koehnlein + */ +public class ChangeAggregatorAdapter extends EContentAdapter { + + private Collection<EObject> modifiedObjects = new LinkedHashSet<EObject>(); + + private boolean isRecording = false; + + private boolean isSuspended = false; + + @Override + public void notifyChanged(Notification notification) { + super.notifyChanged(notification); + + if (!doRecord(notification)) + return; + + if (notification.getNotifier() instanceof EObject) { + recordObjectModification((EObject) notification.getNotifier()); + } + } + + protected void recordObjectModification(EObject obj) { + if (obj.eResource() == null || false == obj.eResource() instanceof XtextResource) + modifiedObjects.remove(obj); + else + modifiedObjects.add(obj); + } + + protected boolean doRecord(Notification notification) { + if (!isRecording || isSuspended || notification.isTouch()) + return false; + + switch (notification.getEventType()) { + case Notification.ADD: + case Notification.ADD_MANY: + case Notification.MOVE: + case Notification.REMOVE: + case Notification.REMOVE_MANY: + case Notification.SET: + case Notification.UNSET: + return true; + default: + return false; + } + } + + private void reset() { + modifiedObjects.clear(); + } + + /** + * This element comes from the XText/GMF integration example, and was not originally documented. + */ + public void beginRecording() { + reset(); + isRecording = true; + } + + /** + * This element comes from the XText/GMF integration example, and was not originally documented. + */ + public void endRecording() { + isRecording = false; + } + + /** + * This element comes from the XText/GMF integration example, and was not originally documented. + * @param isSuspended + */ + public void setSuspended(boolean isSuspended) { + this.isSuspended = isSuspended; + } + + /** + * This element comes from the XText/GMF integration example, and was not originally documented. + * @return List<EOject> + */ + public List<EObject> getModificationRoots() { + Map<Resource, List<EObject>> resource2ChangePathMap = new HashMap<Resource, List<EObject>>(); + for (EObject eObject : modifiedObjects) { + if (!eObject.eIsProxy()) { + Resource resource = eObject.eResource(); + List<EObject> resourceChangePath = resource2ChangePathMap.get(resource); + if (resourceChangePath == null) { + resourceChangePath = allContainers(eObject); + resource2ChangePathMap.put(resource, resourceChangePath); + } else { + resourceChangePath.retainAll(allContainers(eObject)); + } + } + } + List<EObject> modificationRoots = new ArrayList<EObject>(resource2ChangePathMap.size()); + for (List<EObject> changePath : resource2ChangePathMap.values()) { + if (!changePath.isEmpty()) { + modificationRoots.add(changePath.get(changePath.size() - 1)); + } + } + return modificationRoots; + } + + private LinkedList<EObject> allContainers(EObject eObject) { + final LinkedList<EObject> allContainers = Lists.newLinkedList(); + allContainers.add(eObject); + EObject currentContainer = eObject.eContainer(); + final Resource resource = eObject.eResource(); + while (currentContainer != null && resource == currentContainer.eResource()) { + allContainers.addFirst(currentContainer); + currentContainer = currentContainer.eContainer(); + } + return allContainers; + } + + /** + * Only attach to XtextResources + */ + @Override + protected void setTarget(Resource target) { + if (target instanceof XtextResource) { + super.setTarget(target); + } + } + + @Override + protected void setTarget(EObject target) { + if (target.eResource() instanceof XtextResource) { + super.setTarget(target); + } + } + + @Override + public boolean isAdapterForType(Object type) { + return type == ChangeAggregatorAdapter.class; + } + +}
\ No newline at end of file diff --git a/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/editingdomain/SemanticRootUnloadListener.java b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/editingdomain/SemanticRootUnloadListener.java new file mode 100644 index 00000000000..6fb03239ea9 --- /dev/null +++ b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/editingdomain/SemanticRootUnloadListener.java @@ -0,0 +1,95 @@ +/******************************************************************************* + * Copyright (c) 2009 itemis AG (http://www.itemis.eu) 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 + *******************************************************************************/ +package org.eclipse.papyrus.infra.gmfdiag.xtext.glue.editingdomain; + +import org.eclipse.emf.common.command.Command; +import org.eclipse.emf.common.notify.Notification; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.transaction.NotificationFilter; +import org.eclipse.emf.transaction.ResourceSetChangeEvent; +import org.eclipse.emf.transaction.ResourceSetListener; +import org.eclipse.emf.transaction.RollbackException; +import org.eclipse.gef.EditPart; +import org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramEditPart; +import org.eclipse.xtext.resource.XtextResource; + +/** + * Reloads the semantic root element (the element of the diagram) on changes and refreshes the diagram. GMF does by + * default not listen to such events which can occur in an {@link XtextResource}, if the document changes close to the + * root element. + * + * Activate an instance of this in the {@link EditPart#activate()} method of the {@link DiagramEditPart}. + * + * @author koehnlein + */ +public class SemanticRootUnloadListener implements ResourceSetListener { + + private DiagramEditPart rootEditPart; + private EObject semanticRootElement; + + /** + * This element comes from the XText/GMF integration example, and was not originally documented. + * @param rootEditPart + * + */ + public SemanticRootUnloadListener(DiagramEditPart rootEditPart) { + this.rootEditPart = rootEditPart; + this.semanticRootElement = rootEditPart.resolveSemanticElement(); + } + + /** + * This element comes from the XText/GMF integration example, and was not originally documented. + */ + public void activate() { + rootEditPart.getEditingDomain().addResourceSetListener(this); + } + + /** + * This element comes from the XText/GMF integration example, and was not originally documented. + */ + public void deactivate() { + rootEditPart.getEditingDomain().removeResourceSetListener(this); + } + + public NotificationFilter getFilter() { + return new NotificationFilter.Custom() { + @Override + public boolean matches(Notification notification) { + int featureID = notification.getFeatureID(Resource.class); + Object notifier = notification.getNotifier(); + int eventType = notification.getEventType(); + return notification.getOldValue() == semanticRootElement && featureID == Resource.RESOURCE__CONTENTS + && (eventType == Notification.REMOVE || eventType == Notification.SET) + && notifier instanceof Resource; + } + }; + } + + public boolean isAggregatePrecommitListener() { + return false; + } + + public boolean isPostcommitOnly() { + return true; + } + + public boolean isPrecommitOnly() { + return false; + } + + public void resourceSetChanged(ResourceSetChangeEvent event) { + semanticRootElement = rootEditPart.resolveSemanticElement(); + rootEditPart.refresh(); + } + + public Command transactionAboutToCommit(ResourceSetChangeEvent event) throws RollbackException { + return null; + } + +} diff --git a/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/editingdomain/UpdateXtextResourceTextCommand.java b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/editingdomain/UpdateXtextResourceTextCommand.java new file mode 100644 index 00000000000..a1f4a622e05 --- /dev/null +++ b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/editingdomain/UpdateXtextResourceTextCommand.java @@ -0,0 +1,107 @@ +/******************************************************************************* + * Copyright (c) 2009 itemis AG (http://www.itemis.eu) 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 + *******************************************************************************/ +package org.eclipse.papyrus.infra.gmfdiag.xtext.glue.editingdomain; + +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.emf.common.command.Command; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.emf.transaction.RecordingCommand; +import org.eclipse.emf.transaction.TransactionalEditingDomain; +import org.eclipse.emf.transaction.util.TransactionUtil; +import org.eclipse.gmf.runtime.common.core.command.CommandResult; +import org.eclipse.gmf.runtime.common.core.command.ICommand; +import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand; +import org.eclipse.xtext.resource.XtextResource; + +/** + * A Command that deactivates the {@link ChangeAggregatorAdapter} and updates a textual section of an Xtext model in an + * Xtext resource. Used to avoid cycles in the change aggregation. + * + * @author koehnlein + */ +public class UpdateXtextResourceTextCommand { + + /** + * This element comes from the XText/GMF integration example, and was not originally documented. + * @param xtextResource + * @param offset + * @param length + * @param newText + * @return Command + */ + public static Command createEMFCommand(final XtextResource xtextResource, final int offset, final int length, + final String newText) { + final TransactionalEditingDomain editingDomain = TransactionUtil.getEditingDomain(xtextResource); + if (editingDomain == null) { + return null; + } + ResourceSet resourceSet = editingDomain.getResourceSet(); + final ChangeAggregatorAdapter changeAggregator = (ChangeAggregatorAdapter) EcoreUtil.getAdapter(resourceSet + .eAdapters(), ChangeAggregatorAdapter.class); + return new RecordingCommand(editingDomain, "update xtext resource") { + @Override + protected void doExecute() { + try { + if (changeAggregator != null) { + changeAggregator.setSuspended(true); + } + xtextResource.update(offset, length, newText); + xtextResource.setModified(true); + } finally { + if (changeAggregator != null) { + changeAggregator.setSuspended(false); + } + } + + } + }; + } + + /** + * This element comes from the XText/GMF integration example, and was not originally documented. + * @param xtextResource + * @param offset + * @param length + * @param newText + * @return ICommand + */ + public static ICommand createUpdateCommand(final XtextResource xtextResource, final int offset, final int length, + final String newText) { + final TransactionalEditingDomain editingDomain = TransactionUtil.getEditingDomain(xtextResource); + if (editingDomain == null) { + return null; + } + ResourceSet resourceSet = editingDomain.getResourceSet(); + final ChangeAggregatorAdapter changeAggregator = (ChangeAggregatorAdapter) EcoreUtil.getAdapter(resourceSet + .eAdapters(), ChangeAggregatorAdapter.class); + return new AbstractTransactionalCommand(editingDomain, "update xtext resource", null) { + @Override + protected CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info) + throws ExecutionException { + try { + if (changeAggregator != null) { + changeAggregator.setSuspended(true); + } + xtextResource.update(offset, length, newText); + xtextResource.setModified(true); + return CommandResult.newOKCommandResult(); + } catch (Exception exc) { + return CommandResult.newErrorCommandResult(exc); + } finally { + if (changeAggregator != null) { + changeAggregator.setSuspended(false); + } + } + } + }; + } + +} diff --git a/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/editingdomain/XtextNodeModelReconciler.java b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/editingdomain/XtextNodeModelReconciler.java new file mode 100644 index 00000000000..4605d2a1a5c --- /dev/null +++ b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/editingdomain/XtextNodeModelReconciler.java @@ -0,0 +1,135 @@ +/******************************************************************************* + * Copyright (c) 2009 itemis AG (http://www.itemis.eu) 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 + *******************************************************************************/ +package org.eclipse.papyrus.infra.gmfdiag.xtext.glue.editingdomain; + +import org.eclipse.core.commands.operations.IOperationHistory; +import org.eclipse.core.commands.operations.IOperationHistoryListener; +import org.eclipse.core.commands.operations.OperationHistoryEvent; +import org.eclipse.emf.common.command.CommandStack; +import org.eclipse.emf.common.notify.impl.AdapterImpl; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.emf.transaction.TransactionalEditingDomain; +import org.eclipse.emf.transaction.TransactionalEditingDomain.Lifecycle; +import org.eclipse.emf.transaction.TransactionalEditingDomainEvent; +import org.eclipse.emf.transaction.TransactionalEditingDomainListener; +import org.eclipse.emf.transaction.util.TransactionUtil; +import org.eclipse.emf.workspace.IWorkspaceCommandStack; +//import org.eclipse.xtext.parsetree.CompositeNode; +//import org.eclipse.xtext.parsetree.NodeAdapter; +//import org.eclipse.xtext.parsetree.NodeUtil; + +/** + * Reconciles the node models of all XtextResources in a TransactionalEditingDomain with semantic changes. + * + * @author koehnlein + */ +public class XtextNodeModelReconciler extends AdapterImpl implements TransactionalEditingDomainListener, + IOperationHistoryListener { + + private TransactionalEditingDomain editingDomain; + + private ChangeAggregatorAdapter changeAggregator; + + private XtextNodeModelReconciler(TransactionalEditingDomain editingDomain) { + this.editingDomain = editingDomain; + Lifecycle lifecycle = TransactionUtil.getAdapter(editingDomain, Lifecycle.class); + lifecycle.addTransactionalEditingDomainListener(this); + changeAggregator = new ChangeAggregatorAdapter(); + editingDomain.getResourceSet().eAdapters().add(changeAggregator); + CommandStack commandStack = editingDomain.getCommandStack(); + if (commandStack instanceof IWorkspaceCommandStack) { + IOperationHistory operationHistory = ((IWorkspaceCommandStack) commandStack).getOperationHistory(); + operationHistory.addOperationHistoryListener(this); + } + changeAggregator.beginRecording(); + } + + public void editingDomainDisposing(TransactionalEditingDomainEvent event) { + changeAggregator.endRecording(); + CommandStack commandStack = editingDomain.getCommandStack(); + if (commandStack instanceof IWorkspaceCommandStack) { + IOperationHistory operationHistory = ((IWorkspaceCommandStack) commandStack).getOperationHistory(); + operationHistory.removeOperationHistoryListener(this); + } + editingDomain.getResourceSet().eAdapters().remove(changeAggregator); + Lifecycle lifecycle = TransactionUtil.getAdapter(editingDomain, Lifecycle.class); + lifecycle.removeTransactionalEditingDomainListener(XtextNodeModelReconciler.this); + } + + public void transactionClosed(TransactionalEditingDomainEvent event) { + // ignore + } + + public void transactionClosing(TransactionalEditingDomainEvent event) { + // ignore + } + + public void transactionInterrupted(TransactionalEditingDomainEvent event) { + // ignore + } + + public void transactionStarted(TransactionalEditingDomainEvent event) { + // ignore + } + + public void transactionStarting(TransactionalEditingDomainEvent event) { + // ignore + } + + /** + * This element comes from the XText/GMF integration example, and was not originally documented. + * @param editingDomain + * @return XtextNodeModelReconciler + * + */ + public static XtextNodeModelReconciler adapt(TransactionalEditingDomain editingDomain) { + XtextNodeModelReconciler adapter = (XtextNodeModelReconciler) EcoreUtil.getAdapter(editingDomain + .getResourceSet().eAdapters(), XtextNodeModelReconciler.class); + if (adapter == null) { + adapter = new XtextNodeModelReconciler(editingDomain); + } + return adapter; + } + + public void historyNotification(OperationHistoryEvent event) { + int eventType = event.getEventType(); +// switch (eventType) { +// case OperationHistoryEvent.DONE: +// case OperationHistoryEvent.UNDONE: +// case OperationHistoryEvent.REDONE: +// changeAggregator.endRecording(); +// ICommand updateXtextResourceTextCommand = null; +// for (EObject modificationRoot : changeAggregator.getModificationRoots()) { +// XtextResource xtextResource = (XtextResource) modificationRoot.eResource(); +// NodeAdapter nodeAdapter = NodeUtil.getNodeAdapter(modificationRoot); +// CompositeNode parserNode = nodeAdapter.getParserNode(); +// Serializer serializer = xtextResource.getSerializer(); +// String newText = serializer.serialize(modificationRoot); +// ICommand newCommand = UpdateXtextResourceTextCommand.createUpdateCommand(xtextResource, parserNode +// .getOffset(), parserNode.getLength(), newText); +// if (updateXtextResourceTextCommand == null) { +// updateXtextResourceTextCommand = newCommand; +// } else { +// updateXtextResourceTextCommand.compose(newCommand); +// } +// } +// try { +// if (updateXtextResourceTextCommand != null) { +// updateXtextResourceTextCommand.execute(null, null); +// } +// } catch (ExecutionException exc) { +// Activator.logError(exc); +// } +// changeAggregator.beginRecording(); +// break; +// default: +// // ignore +// } + + } +} diff --git a/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/partialEditing/CustomXtextSourceViewer.java b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/partialEditing/CustomXtextSourceViewer.java new file mode 100644 index 00000000000..577dcd58091 --- /dev/null +++ b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/partialEditing/CustomXtextSourceViewer.java @@ -0,0 +1,63 @@ +/*****************************************************************************
+ * Copyright (c) 2011 CEA LIST.
+ *
+ *
+ * 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:
+ * CEA LIST - Initial API and implementation
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.infra.gmfdiag.xtext.glue.partialEditing;
+
+import org.eclipse.jface.text.DocumentCommand;
+import org.eclipse.jface.text.contentassist.IContentAssistant;
+import org.eclipse.jface.text.source.IOverviewRuler;
+import org.eclipse.jface.text.source.IVerticalRuler;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.xtext.ui.editor.XtextSourceViewer;
+
+/**
+ * This class extends XtextSourceViewer with the method getContentAssistant()
+ * This method was available on XtextSourceViewer in Xtext 1.0, and used
+ * for integration in Papyrus.
+ *
+ * @author CEA LIST - Initial contribution and API
+ */
+public class CustomXtextSourceViewer extends XtextSourceViewer {
+
+ /**
+ * @param parent
+ * @param ruler
+ * @param overviewRuler
+ * @param showsAnnotationOverview
+ * @param styles
+ *
+ */
+ public CustomXtextSourceViewer(Composite parent, IVerticalRuler ruler, IOverviewRuler overviewRuler,
+ boolean showsAnnotationOverview, int styles) {
+ super(parent, ruler, overviewRuler, showsAnnotationOverview, styles);
+ }
+
+ /**
+ * Used in papyrus integration for managing content assist in popup editors.
+ * @return the content assistant
+ *
+ */
+ public IContentAssistant getContentAssistant() {
+ return fContentAssistant;
+ }
+
+ @Override
+ protected void customizeDocumentCommand(DocumentCommand command) {
+ // TODO: TextViewer.customizeDocumentCommand generates exceptions. Why?
+ //super.customizeDocumentCommand(command);
+ }
+
+
+
+}
diff --git a/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/partialEditing/HighlightingHelper.java b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/partialEditing/HighlightingHelper.java new file mode 100644 index 00000000000..0f0e7114282 --- /dev/null +++ b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/partialEditing/HighlightingHelper.java @@ -0,0 +1,161 @@ +/******************************************************************************* + * Copyright (c) 2010 itemis AG (http://www.itemis.eu) 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 + *******************************************************************************/ +package org.eclipse.papyrus.infra.gmfdiag.xtext.glue.partialEditing; + +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; +import org.eclipse.xtext.ui.editor.XtextPresentationReconciler; +import org.eclipse.xtext.ui.editor.XtextSourceViewer; +import org.eclipse.xtext.ui.editor.XtextSourceViewerConfiguration; +import org.eclipse.xtext.ui.editor.preferences.IPreferenceStoreAccess; +import org.eclipse.xtext.ui.editor.syntaxcoloring.HighlightingPresenter; + +import com.google.inject.Inject; +import com.google.inject.Provider; + +/** + * @author Sebastian Zarnekow - Initial contribution and API + */ +public class HighlightingHelper implements IPropertyChangeListener { + + @Inject + private Provider<HighlightingReconciler> reconcilerProvider; + + @Inject + private Provider<HighlightingPresenter> presenterProvider; + + @Inject + private IPreferenceStoreAccess preferenceStoreAccessor; + + /** Highlighting presenter */ + private HighlightingPresenter fPresenter; + /** Highlighting reconciler */ + private HighlightingReconciler fReconciler; + + /** The source viewer */ + private XtextSourceViewer fSourceViewer; + /** The source viewer configuration */ + private XtextSourceViewerConfiguration fConfiguration; + /** The presentation reconciler */ + private XtextPresentationReconciler fPresentationReconciler; + + /** + * @param configuration + * @param sourceViewer + * + */ + public void install(XtextSourceViewerConfiguration configuration, XtextSourceViewer sourceViewer) { + fSourceViewer= sourceViewer; + fConfiguration= configuration; + fPresentationReconciler= (XtextPresentationReconciler) fConfiguration.getPresentationReconciler(sourceViewer); + preferenceStoreAccessor.getPreferenceStore().addPropertyChangeListener(this); + enable(); + } + + /** + * Enable advanced highlighting. + */ + private void enable() { + fPresenter= getPresenterProvider().get(); + fPresenter.install(fSourceViewer, fPresentationReconciler); + + if (fSourceViewer.getDocument() != null) { + fReconciler= reconcilerProvider.get(); + fReconciler.install(fSourceViewer, fPresenter); + } + } + + /** + * + */ + public void uninstall() { + disable(); + preferenceStoreAccessor.getPreferenceStore().removePropertyChangeListener(this); + fSourceViewer= null; + fConfiguration= null; + fPresentationReconciler= null; + } + + /** + * Disable advanced highlighting. + */ + private void disable() { + if (fReconciler != null) { + fReconciler.uninstall(); + fReconciler= null; + } + + if (fPresenter != null) { + fPresenter.uninstall(); + fPresenter= null; + } + } + + /** + * Returns this hightlighter's reconciler. + * + * @return the highlighter reconciler or <code>null</code> if none + */ + public HighlightingReconciler getReconciler() { + return fReconciler; + } + + /** + * @param reconcilerProvider + * + */ + public void setReconcilerProvider(Provider<HighlightingReconciler> reconcilerProvider) { + this.reconcilerProvider = reconcilerProvider; + } + + /** + * @return Provider<HightlightingReconciler> + * + */ + public Provider<HighlightingReconciler> getReconcilerProvider() { + return reconcilerProvider; + } + + /** + * @param presenterProvider + * + */ + + public void setPresenterProvider(Provider<HighlightingPresenter> presenterProvider) { + this.presenterProvider = presenterProvider; + } + + /** + * @return Provider<HightlightingPresented> + */ + public Provider<HighlightingPresenter> getPresenterProvider() { + return presenterProvider; + } + + /** + * @param preferenceStoreAccessor + * + */ + public void setPreferenceStoreAccessor(IPreferenceStoreAccess preferenceStoreAccessor) { + this.preferenceStoreAccessor = preferenceStoreAccessor; + } + + /** + * @return IPreferenceStoreAccessor + * + */ + public IPreferenceStoreAccess getPreferenceStoreAccessor() { + return preferenceStoreAccessor; + } + + public void propertyChange(PropertyChangeEvent event) { + if (fReconciler != null && event.getProperty().contains(".syntaxColorer.tokenStyles")) + fReconciler.refresh(); + } +} + diff --git a/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/partialEditing/HighlightingReconciler.java b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/partialEditing/HighlightingReconciler.java new file mode 100644 index 00000000000..bce3698527e --- /dev/null +++ b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/partialEditing/HighlightingReconciler.java @@ -0,0 +1,291 @@ +/******************************************************************************* + * Copyright (c) 2010 itemis AG (http://www.itemis.eu) 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 + *******************************************************************************/ +package org.eclipse.papyrus.infra.gmfdiag.xtext.glue.partialEditing; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.ITextInputListener; +import org.eclipse.jface.text.TextAttribute; +import org.eclipse.jface.text.TextPresentation; +import org.eclipse.swt.widgets.Display; +import org.eclipse.xtext.resource.XtextResource; +import org.eclipse.xtext.ui.editor.XtextSourceViewer; +import org.eclipse.xtext.ui.editor.model.IXtextDocument; +import org.eclipse.xtext.ui.editor.model.IXtextModelListener; +import org.eclipse.xtext.ui.editor.model.XtextDocument; +import org.eclipse.xtext.ui.editor.syntaxcoloring.AttributedPosition; +import org.eclipse.xtext.ui.editor.syntaxcoloring.HighlightingPresenter; +import org.eclipse.xtext.ui.editor.syntaxcoloring.IHighlightedPositionAcceptor; +import org.eclipse.xtext.ui.editor.syntaxcoloring.ISemanticHighlightingCalculator; +import org.eclipse.xtext.ui.editor.syntaxcoloring.ITextAttributeProvider; +import org.eclipse.xtext.ui.editor.syntaxcoloring.MergingHighlightedPositionAcceptor; +import org.eclipse.xtext.util.concurrent.IUnitOfWork; + +import com.google.inject.Inject; + +/** + * @author Sebastian Zarnekow - Initial contribution and API + */ +public class HighlightingReconciler implements ITextInputListener, IXtextModelListener, IHighlightedPositionAcceptor { + + @Inject(optional=true) + private ISemanticHighlightingCalculator calculator; + + @Inject + private ITextAttributeProvider attributeProvider; + + /** The source viewer this highlighting reconciler is installed on */ + private XtextSourceViewer sourceViewer; + /** The highlighting presenter */ + private HighlightingPresenter presenter; + + /** Background job's added highlighted positions */ + private final List<AttributedPosition> addedPositions = new ArrayList<AttributedPosition>(); + /** Background job's removed highlighted positions */ + private List<AttributedPosition> removedPositions = new ArrayList<AttributedPosition>(); + /** Number of removed positions */ + private int removedPositionCount; + + /** + * Reconcile operation lock. + * + * @since 3.2 + */ + private final Object fReconcileLock = new Object(); + /** + * <code>true</code> if any thread is executing <code>reconcile</code>, <code>false</code> otherwise. + * + * @since 3.2 + */ + private boolean reconciling = false; + + /** + * Start reconciling positions. + */ + private void startReconcilingPositions() { + presenter.addAllPositions(removedPositions); + removedPositionCount = removedPositions.size(); + } + + /** + * Reconcile positions based on the AST subtrees + * + * @param subtrees + * the AST subtrees + */ + private void reconcilePositions(XtextResource resource) { + // for (int i= 0, n= subtrees.length; i < n; i++) + // subtrees[i].accept(fCollector); + MergingHighlightedPositionAcceptor acceptor = new MergingHighlightedPositionAcceptor(calculator); + acceptor.provideHighlightingFor(resource, this); +// calculator.provideHighlightingFor(resource, this); + List<AttributedPosition> oldPositions = removedPositions; + List<AttributedPosition> newPositions = new ArrayList<AttributedPosition>(removedPositionCount); + for (int i = 0, n = oldPositions.size(); i < n; i++) { + AttributedPosition current = oldPositions.get(i); + if (current != null) + newPositions.add(current); + } + removedPositions = newPositions; + } + + /** + * Add a position with the given range and highlighting if it does not exist already. + * @param offset The range offset + * @param length The range length + * @param highlighting The highlighting + */ + public void addPosition(int offset, int length, String... ids) { + TextAttribute highlighting = ids.length == 1 ? + attributeProvider.getAttribute(ids[0]) + : attributeProvider.getMergedAttributes(ids); + boolean isExisting= false; + // TODO: use binary search + for (int i= 0, n= removedPositions.size(); i < n; i++) { + AttributedPosition position= removedPositions.get(i); + if (position == null) + continue; + if (position.isEqual(offset, length, highlighting)) { + isExisting= true; + removedPositions.set(i, null); + removedPositionCount--; + break; + } + } + + if (!isExisting) { + AttributedPosition position= presenter.createHighlightedPosition(offset, length, highlighting); + addedPositions.add(position); + } + } + + /** + * Update the presentation. + * + * @param textPresentation + * the text presentation + * @param addedPositions + * the added positions + * @param removedPositions + * the removed positions + */ + private void updatePresentation(TextPresentation textPresentation, List<AttributedPosition> addedPositions, + List<AttributedPosition> removedPositions) { + Runnable runnable = presenter.createUpdateRunnable(textPresentation, addedPositions, removedPositions); + if (runnable == null) + return; + + Display display = getDisplay(); + display.asyncExec(runnable); + } + + private Display getDisplay() { + return this.sourceViewer.getControl().getDisplay(); + } + + /** + * Stop reconciling positions. + */ + private void stopReconcilingPositions() { + removedPositions.clear(); + removedPositionCount = 0; + addedPositions.clear(); + } + + /** + * Install this reconciler on the given editor and presenter. + * + * @param editor + * the editor + * @param sourceViewer + * the source viewer + * @param presenter + * the highlighting presenter + */ + public void install(XtextSourceViewer sourceViewer, HighlightingPresenter presenter) { + this.presenter = presenter; + this.sourceViewer = sourceViewer; + if (calculator != null) { + ((IXtextDocument) sourceViewer.getDocument()).addModelListener(this); + sourceViewer.addTextInputListener(this); + } + refresh(); + } + + /** + * Uninstall this reconciler from the editor + */ + public void uninstall() { + if (presenter != null) + presenter.setCanceled(true); + + if (sourceViewer.getDocument() != null) { + if (calculator != null) { + XtextDocument document = (XtextDocument) sourceViewer.getDocument(); + document.removeModelListener(this); + sourceViewer.removeTextInputListener(this); + } + } + + sourceViewer = null; + presenter = null; + } + + /* + * @see org.eclipse.jface.text.ITextInputListener#inputDocumentAboutToBeChanged(org.eclipse.jface.text.IDocument, org.eclipse.jface.text.IDocument) + */ + public void inputDocumentAboutToBeChanged(IDocument oldInput, IDocument newInput) { + if (oldInput != null) + ((IXtextDocument) oldInput).removeModelListener(this); + } + + /* + * @see org.eclipse.jface.text.ITextInputListener#inputDocumentChanged(org.eclipse.jface.text.IDocument, org.eclipse.jface.text.IDocument) + */ + public void inputDocumentChanged(IDocument oldInput, IDocument newInput) { + if (newInput != null) { + refresh(); + ((IXtextDocument) newInput).addModelListener(this); + } + } + + /** + * Refreshes the highlighting. + */ + public void refresh() { + if (calculator != null) { + ((XtextDocument) sourceViewer.getDocument()).readOnly(new IUnitOfWork.Void<XtextResource>() { + @Override + public void process(XtextResource state) throws Exception { + modelChanged(state); + } + }); + } else { + Display display = getDisplay(); + display.asyncExec(presenter.createSimpleUpdateRunnable()); + } + } + + public void modelChanged(XtextResource resource) { + // ensure at most one thread can be reconciling at any time + synchronized (fReconcileLock) { + if (reconciling) + return; + reconciling = true; + } + final HighlightingPresenter highlightingPresenter = presenter; + try { + if (highlightingPresenter == null) + return; + + highlightingPresenter.setCanceled(false); + + if (highlightingPresenter.isCanceled()) + return; + + startReconcilingPositions(); + + if (!highlightingPresenter.isCanceled()) { + reconcilePositions(resource); + } + + final TextPresentation[] textPresentation = new TextPresentation[1]; + if (!highlightingPresenter.isCanceled()) { + textPresentation[0] = highlightingPresenter.createPresentation(addedPositions, removedPositions); + } + + if (!highlightingPresenter.isCanceled()) + updatePresentation(textPresentation[0], addedPositions, removedPositions); + + stopReconcilingPositions(); + } + finally { + synchronized (fReconcileLock) { + reconciling = false; + } + } + } + + /** + * @param calculator + * + */ + public void setCalculator(ISemanticHighlightingCalculator calculator) { + this.calculator = calculator; + } + + /** + * @return ISemanticHighlightingCalculator + * + */ + public ISemanticHighlightingCalculator getCalculator() { + return calculator; + } +} diff --git a/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/partialEditing/IActionContributor.java b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/partialEditing/IActionContributor.java new file mode 100644 index 00000000000..1805f2bfcc9 --- /dev/null +++ b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/partialEditing/IActionContributor.java @@ -0,0 +1,47 @@ +/*******************************************************************************
+ * Copyright (c) 2010 itemis AG (http://www.itemis.eu) 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
+ *******************************************************************************/
+package org.eclipse.papyrus.infra.gmfdiag.xtext.glue.partialEditing;
+
+import java.util.List;
+
+import com.google.inject.Binding;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Singleton;
+import com.google.inject.TypeLiteral;
+
+/**
+ *
+ */
+public interface IActionContributor {
+ /**
+ * hook used to contribute any actions on editor start up.
+ * @param editor
+ */
+ public void contributeActions(PartialModelEditor editor);
+
+
+ /**
+ * composite action contributor delegating call to all registered {@link IActionContributor}
+ */
+ @Singleton
+ public class CompositeImpl implements IActionContributor {
+
+ @Inject
+ private Injector injector;
+
+ public void contributeActions(PartialModelEditor editor) {
+ List<Binding<IActionContributor>> bindingsByType = injector.findBindingsByType(TypeLiteral.get(IActionContributor.class));
+ for (Binding<IActionContributor> binding : bindingsByType) {
+ IActionContributor actionContributor = injector.getInstance(binding.getKey());
+ actionContributor.contributeActions(editor);
+ }
+ }
+
+ }
+}
\ No newline at end of file diff --git a/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/partialEditing/IPartialContentAssistParser.java b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/partialEditing/IPartialContentAssistParser.java new file mode 100644 index 00000000000..95133155d81 --- /dev/null +++ b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/partialEditing/IPartialContentAssistParser.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2010 itemis AG (http://www.itemis.eu) 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 + *******************************************************************************/ +package org.eclipse.papyrus.infra.gmfdiag.xtext.glue.partialEditing; + +import org.eclipse.xtext.AbstractRule; +import org.eclipse.xtext.ui.editor.contentassist.antlr.IContentAssistParser; + +/** + * @author Sebastian Zarnekow - Initial contribution and API + */ +public interface IPartialContentAssistParser extends IContentAssistParser { + + /** + * @param rule + * + */ + void initializeFor(AbstractRule rule); + +} diff --git a/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/partialEditing/ISyntheticResourceProvider.java b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/partialEditing/ISyntheticResourceProvider.java new file mode 100644 index 00000000000..50d9eab79d1 --- /dev/null +++ b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/partialEditing/ISyntheticResourceProvider.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2010 itemis AG (http://www.itemis.eu) 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 + *******************************************************************************/ +package org.eclipse.papyrus.infra.gmfdiag.xtext.glue.partialEditing; + +import org.eclipse.xtext.resource.XtextResource; + +import com.google.inject.ImplementedBy; + +/** + * + */ +@ImplementedBy(SyntheticResourceProvider.class) +public interface ISyntheticResourceProvider { + /** + * @return XtextResource + * + */ + XtextResource createResource(); +}
\ No newline at end of file diff --git a/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/partialEditing/OperationHistoryListener.java b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/partialEditing/OperationHistoryListener.java new file mode 100644 index 00000000000..9db63acc890 --- /dev/null +++ b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/partialEditing/OperationHistoryListener.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2010 itemis AG (http://www.itemis.eu) 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 + *******************************************************************************/ +package org.eclipse.papyrus.infra.gmfdiag.xtext.glue.partialEditing; + +import org.eclipse.core.commands.operations.IOperationHistoryListener; +import org.eclipse.core.commands.operations.IUndoContext; +import org.eclipse.core.commands.operations.OperationHistoryEvent; +import org.eclipse.ui.texteditor.IUpdate; + +/** + * + */ +public class OperationHistoryListener implements IOperationHistoryListener { + private final IUndoContext context; + private final IUpdate update; + + /** + * @param context + * @param update + * + */ + public OperationHistoryListener(IUndoContext context, IUpdate update) { + this.context = context; + this.update = update; + } + + public void historyNotification(OperationHistoryEvent event) { + final int type= event.getEventType(); + switch (type) { + case OperationHistoryEvent.UNDONE: + case OperationHistoryEvent.REDONE: + case OperationHistoryEvent.OPERATION_NOT_OK: + // if this is one of our operations + if (event.getOperation().hasContext(context)) { + update.update(); + } + } + } +}
\ No newline at end of file diff --git a/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/partialEditing/PartialContentAssistContextFactory.java b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/partialEditing/PartialContentAssistContextFactory.java new file mode 100644 index 00000000000..c6baf0199e1 --- /dev/null +++ b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/partialEditing/PartialContentAssistContextFactory.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2010 itemis AG (http://www.itemis.eu) 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 + *******************************************************************************/ +package org.eclipse.papyrus.infra.gmfdiag.xtext.glue.partialEditing; + +import org.eclipse.xtext.ui.editor.contentassist.antlr.ParserBasedContentAssistContextFactory; + +/** + * @author Sebastian Zarnekow - Initial contribution and API + */ +public class PartialContentAssistContextFactory extends ParserBasedContentAssistContextFactory { + +// /** +// * @param partialContentAssistParser +// * +// */ +// @Inject +// public void setPartialParser(IPartialContentAssistParser partialContentAssistParser) { +// super.setParser(partialContentAssistParser); +// } +// +// /** +// * @param rule +// * +// */ +// public void initializeFor(AbstractRule rule) { +// ((IPartialContentAssistParser) getParser()).initializeFor(rule); +// } + +} diff --git a/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/partialEditing/PartialModelEditor.java b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/partialEditing/PartialModelEditor.java new file mode 100644 index 00000000000..79d3cbb2d32 --- /dev/null +++ b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/partialEditing/PartialModelEditor.java @@ -0,0 +1,163 @@ +package org.eclipse.papyrus.infra.gmfdiag.xtext.glue.partialEditing; + +import java.util.Collections; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.ISynchronizable; +import org.eclipse.jface.text.source.AnnotationModel; +import org.eclipse.jface.text.source.SourceViewer; +import org.eclipse.papyrus.infra.gmfdiag.xtext.glue.edit.part.IXtextEMFReconciler; +import org.eclipse.xtext.resource.XtextResource; +import org.eclipse.xtext.ui.editor.model.XtextDocument; +import org.eclipse.xtext.util.StringInputStream; + +/** + * + */ +public class PartialModelEditor { + + protected final SourceViewer viewer; + protected final boolean insertLineBreaks; + protected final ISyntheticResourceProvider resourceProvider; + protected EObject semanticElement ; + protected IXtextEMFReconciler modelReconciler ; + //private final Injector xtextInjector ; + + /** + * @param viewer + * @param resourceProvider + * @param insertLineBreaks + * @param semanticElement + * @param modelReconciler + * + */ + public PartialModelEditor(SourceViewer viewer, + ISyntheticResourceProvider resourceProvider, + boolean insertLineBreaks, + EObject semanticElement, + IXtextEMFReconciler modelReconciler) { + //this.xtextInjector = xtextInjector ; + this.viewer = viewer; + this.resourceProvider = resourceProvider; + this.insertLineBreaks = insertLineBreaks; + this.semanticElement = semanticElement ; + this.modelReconciler = modelReconciler ; + } + + /** + * @param document + * @param prefix + * @param editablePart + * @param suffix + * + */ + public void setModel(XtextDocument document, String prefix, String editablePart, String suffix) { + if (insertLineBreaks) { + String delimiter = document.getLegalLineDelimiters()[0]; + prefix = prefix + delimiter; + suffix = delimiter + suffix; + } + String model = prefix + editablePart + suffix; + document.set(model); + XtextResource resource = createResource(model); + document.setInput(resource); + AnnotationModel annotationModel = new AnnotationModel(); + if (document instanceof ISynchronizable) { + Object lock= ((ISynchronizable)document).getLockObject(); + if (lock == null) { + lock= new Object(); + ((ISynchronizable)document).setLockObject(lock); + } + ((ISynchronizable) annotationModel).setLockObject(lock); + } + viewer.setDocument(document, annotationModel, prefix.length(), editablePart.length()); + viewer.getUndoManager().reset(); + } + + /** + * @param content + * @return XtextResource + * + */ + public XtextResource createResource(String content) { + XtextResource result = resourceProvider.createResource(); + try { + result.load(new StringInputStream(content, result.getEncoding()), Collections.emptyMap()); + } catch (Exception e) { + throw new RuntimeException(e); + } + return result; + } + + /** + * @param prefix + * @param editablePart + * @param suffix + * + */ + public void updateModel(String prefix, String editablePart, String suffix) { + IDocument document= viewer.getDocument(); + if (insertLineBreaks) { + String delimiter = document.getLegalLineDelimiters()[0]; + prefix = prefix + delimiter; + suffix = delimiter + suffix; + } + String model = prefix + editablePart + suffix; + viewer.setRedraw(false); + viewer.getUndoManager().disconnect(); + document.set(model); + viewer.setVisibleRegion(prefix.length(), editablePart.length()); + viewer.getUndoManager().connect(viewer); + viewer.setRedraw(true); + } + + /** + * @param prefix + * + */ + public void updatePrefix(String prefix) { + try { + IDocument document= viewer.getDocument(); + IRegion visibleRegion = viewer.getVisibleRegion(); + String editablePart = document.get(visibleRegion.getOffset(), visibleRegion.getLength()); + int suffixOffset = visibleRegion.getOffset() + visibleRegion.getLength(); + String suffix = ""; + if (document.getLength() - suffixOffset > 0) { + suffix = document.get(suffixOffset, document.getLength() - suffixOffset); + if (insertLineBreaks) { + String delimiter = document.getLegalLineDelimiters()[0]; + suffix = suffix.substring(delimiter.length()); + } + } + updateModel(prefix, editablePart, suffix); + } catch(BadLocationException e) { + throw new RuntimeException(e); + } + } + + /** + * @return String + * + */ + public String getEditablePart() { + IDocument doc= viewer.getDocument(); + IRegion visible= viewer.getVisibleRegion(); + try { + return doc.get(visible.getOffset(), visible.getLength()); + } catch (BadLocationException e) { + return ""; //$NON-NLS-1$ + } + } + + /** + * @return String + * + */ + public String getSerializedModel() { + return viewer.getDocument().get(); + } + +} diff --git a/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/partialEditing/SourceViewerHandle.java b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/partialEditing/SourceViewerHandle.java new file mode 100644 index 00000000000..52fe8a87962 --- /dev/null +++ b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/partialEditing/SourceViewerHandle.java @@ -0,0 +1,131 @@ +/******************************************************************************* + * Copyright (c) 2010 itemis AG (http://www.itemis.eu) 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 + *******************************************************************************/ +package org.eclipse.papyrus.infra.gmfdiag.xtext.glue.partialEditing; + +import java.lang.reflect.Constructor; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.jface.text.source.SourceViewer; +import org.eclipse.papyrus.infra.gmfdiag.xtext.glue.edit.part.IXtextEMFReconciler; +import org.eclipse.xtext.ui.editor.XtextSourceViewer; +import org.eclipse.xtext.ui.editor.XtextSourceViewerConfiguration; +import org.eclipse.xtext.ui.editor.model.XtextDocument; +import org.eclipse.xtext.ui.editor.validation.IValidationIssueProcessor; + +import com.google.inject.Injector; + +/** + * + */ +public class SourceViewerHandle { + protected IValidationIssueProcessor issueProcessor; + protected final XtextSourceViewer viewer; + protected final ISyntheticResourceProvider resourceProvider; + protected final XtextDocument document; + protected final XtextSourceViewerConfiguration configuration; + protected static Class partialModelEditorClass = null ; + private Class defaultModelEditorClass = PartialModelEditor.class ; + protected EObject semanticElement ; + protected IXtextEMFReconciler modelReconciler ; + + SourceViewerHandle(XtextDocument document, XtextSourceViewer viewer, XtextSourceViewerConfiguration configuration, ISyntheticResourceProvider resourceProvider, Injector xtextInjector) { + this.document = document; + this.viewer = viewer; + this.configuration = configuration; + this.resourceProvider = resourceProvider; + } + + /** + * @param issueProcessor + * + */ + public void setIssueProcessor(IValidationIssueProcessor issueProcessor) { + this.issueProcessor = issueProcessor; + } + + /** + * @return IValidationIssueProcessor + * + */ + public IValidationIssueProcessor getIssueProcessor() { + return issueProcessor; + } + + /** + * @return XtextSourceViewer + * + */ + public XtextSourceViewer getViewer() { + return viewer; + } + + /** + * @return XtextDocument + * + */ + public XtextDocument getDocument() { + return document; + } + + /** + * @return XtextSourceViewerConfiguration + * + */ + public XtextSourceViewerConfiguration getConfiguration() { + return configuration; + } + + /** + * @param prefix + * @param editablePart + * @param suffix + * @param semanticElement + * @param modelReconciler + * @return PartialModelEditor + * + */ + public PartialModelEditor createPartialEditor(String prefix, String editablePart, String suffix, EObject semanticElement, IXtextEMFReconciler modelReconciler) { + //PartialModelEditor result = new PartialModelEditor(viewer, resourceProvider, false); + PartialModelEditor result = null; + try { + if (partialModelEditorClass == null) + partialModelEditorClass = defaultModelEditorClass ; + Constructor c = partialModelEditorClass.getConstructor(SourceViewer.class, + ISyntheticResourceProvider.class, + boolean.class, + EObject.class, + IXtextEMFReconciler.class + ) ; + this.semanticElement = semanticElement ; + this.modelReconciler = modelReconciler ; + result = (PartialModelEditor)c.newInstance(viewer, resourceProvider, false, semanticElement, modelReconciler) ; + result.setModel(getDocument(), prefix, editablePart, suffix); + } + catch (Exception e) { + e.printStackTrace() ; + } + // result.setModel(getDocument(), prefix, editablePart, suffix); + return result; + } + + /** + * @param modelEditorClass + * + */ + public static void bindPartialModelEditorClass(Class modelEditorClass) { + partialModelEditorClass = modelEditorClass ; + } + + /** + * @return PartialModelEditor + * + */ + public PartialModelEditor createPartialEditor() { + return createPartialEditor("", "", "", null, null); + } +}
\ No newline at end of file diff --git a/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/partialEditing/SourceViewerHandleFactory.java b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/partialEditing/SourceViewerHandleFactory.java new file mode 100644 index 00000000000..c4b05c671f5 --- /dev/null +++ b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/partialEditing/SourceViewerHandleFactory.java @@ -0,0 +1,130 @@ +/******************************************************************************* + * Copyright (c) 2010 itemis AG (http://www.itemis.eu) 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 + *******************************************************************************/ +package org.eclipse.papyrus.infra.gmfdiag.xtext.glue.partialEditing; + +import java.util.Iterator; +import java.util.List; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jface.text.source.IOverviewRuler; +import org.eclipse.jface.text.source.ISharedTextColors; +import org.eclipse.jface.text.source.IVerticalRuler; +import org.eclipse.jface.text.source.OverviewRuler; +import org.eclipse.jface.text.source.VerticalRuler; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.editors.text.EditorsUI; +import org.eclipse.ui.texteditor.AnnotationPreference; +import org.eclipse.ui.texteditor.DefaultMarkerAnnotationAccess; +import org.eclipse.ui.texteditor.MarkerAnnotationPreferences; +import org.eclipse.ui.texteditor.SourceViewerDecorationSupport; +import org.eclipse.xtext.ui.editor.XtextSourceViewer; +import org.eclipse.xtext.ui.editor.XtextSourceViewerConfiguration; +import org.eclipse.xtext.ui.editor.model.XtextDocument; +import org.eclipse.xtext.ui.editor.preferences.IPreferenceStoreAccess; +import org.eclipse.xtext.ui.editor.quickfix.IssueResolutionProvider; +import org.eclipse.xtext.ui.editor.validation.AnnotationIssueProcessor; +import org.eclipse.xtext.ui.editor.validation.IValidationIssueProcessor; +import org.eclipse.xtext.ui.editor.validation.ValidationJob; +import org.eclipse.xtext.validation.CheckMode; +import org.eclipse.xtext.validation.IResourceValidator; +import org.eclipse.xtext.validation.Issue; + +import com.google.common.collect.Iterators; +import com.google.inject.Inject; +import com.google.inject.Injector; +import com.google.inject.Provider; + +/** + * @author Sebastian Zarnekow - Initial contribution and API + */ +public class SourceViewerHandleFactory { + + @Inject + private XtextSourceViewer.Factory sourceViewerFactory; + + @Inject + private Provider<XtextSourceViewerConfiguration> sourceViewerConfigurationProvider; + + @Inject + private Provider<XtextDocument> documentProvider; + + @Inject + private IResourceValidator resourceValidator; + + @Inject + private IPreferenceStoreAccess preferenceStoreAccess; + + private Injector xtextInjector ; + + protected static final int VERTICAL_RULER_WIDTH= 12; + + /** + * @param parent + * @param resourceProvider + * @return SourceViewerHandle + * + */ + public SourceViewerHandle create(Composite parent, ISyntheticResourceProvider resourceProvider) { + final IVerticalRuler ruler = new VerticalRuler(VERTICAL_RULER_WIDTH, new DefaultMarkerAnnotationAccess()); + final IOverviewRuler oRuler = new OverviewRuler(new DefaultMarkerAnnotationAccess(), VERTICAL_RULER_WIDTH, getSharedColors()); + //final XtextSourceViewer viewer = sourceViewerFactory.createSourceViewer(parent, ruler, oRuler, true, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL); + final XtextSourceViewer viewer = new CustomXtextSourceViewer(parent, ruler, oRuler, false, SWT.V_SCROLL | SWT.H_SCROLL); + /* + * final IVerticalRuler ruler = new VerticalRuler(VERTICAL_RULER_WIDTH, null) ; + final XtextSourceViewer viewer = new CustomXtextSourceViewer(parent, ruler, null, true, SWT.None); + */ + + + XtextSourceViewerConfiguration viewerConfiguration = sourceViewerConfigurationProvider.get(); + viewer.configure(viewerConfiguration); + + final SourceViewerDecorationSupport viewerDecorationSupport = new SourceViewerDecorationSupport(viewer, null, new DefaultMarkerAnnotationAccess(), getSharedColors()); + MarkerAnnotationPreferences annotationPreferences = new MarkerAnnotationPreferences(); + Iterator<AnnotationPreference> e= Iterators.filter(annotationPreferences.getAnnotationPreferences().iterator(), AnnotationPreference.class); + while (e.hasNext()) + viewerDecorationSupport.setAnnotationPreference(e.next()); + viewerDecorationSupport.install(preferenceStoreAccess.getPreferenceStore()); + parent.addDisposeListener(new DisposeListener() { + public void widgetDisposed(DisposeEvent e) { + viewerDecorationSupport.dispose(); + } + }); + final XtextDocument document = documentProvider.get(); + final SourceViewerHandle result = new SourceViewerHandle(document, viewer, viewerConfiguration, resourceProvider, xtextInjector); + ValidationJob job = new ValidationJob(resourceValidator, document, + new IValidationIssueProcessor() { + private AnnotationIssueProcessor annotationIssueProcessor; + + public void processIssues(List<Issue> issues, IProgressMonitor monitor) { + if(viewer.getTextWidget() == null) { + // the text widget is disposed => don't try displaying errors in this widget + return; + } + IValidationIssueProcessor issueProcessor = result.getIssueProcessor(); + if (issueProcessor != null) + issueProcessor.processIssues(issues, monitor); + if (annotationIssueProcessor == null) { + annotationIssueProcessor = new AnnotationIssueProcessor(document, + viewer.getAnnotationModel(), + new IssueResolutionProvider.NullImpl()); + } + if (annotationIssueProcessor != null) + annotationIssueProcessor.processIssues(issues, monitor); + } + }, CheckMode.FAST_ONLY); + document.setValidationJob(job); + return result; + } + + protected ISharedTextColors getSharedColors() { + return EditorsUI.getSharedTextColors(); + } +} diff --git a/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/partialEditing/SyntheticResourceProvider.java b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/partialEditing/SyntheticResourceProvider.java new file mode 100644 index 00000000000..616ce3a3dc0 --- /dev/null +++ b/deprecated/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/partialEditing/SyntheticResourceProvider.java @@ -0,0 +1,56 @@ +/******************************************************************************* + * Copyright (c) 2010 itemis AG (http://www.itemis.eu) 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 + *******************************************************************************/ +package org.eclipse.papyrus.infra.gmfdiag.xtext.glue.partialEditing; + +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.papyrus.infra.gmfdiag.xtext.glue.edit.part.PopupXtextEditorHelper; +import org.eclipse.xtext.IGrammarAccess; +import org.eclipse.xtext.resource.XtextResource; +import org.eclipse.xtext.resource.XtextResourceSet; + +import com.google.inject.Inject; +import com.google.inject.Provider; + +/** + * @author Sebastian Zarnekow - Initial contribution and API + */ +public class SyntheticResourceProvider implements ISyntheticResourceProvider { + + /** + * + */ + public static final String SYNTHETIC_SCHEME = "synthetic"; + + //@Inject + //private IResourceSetProvider resourceSetProvider; + @Inject + private Provider<XtextResourceSet> resourceSetProvider; + + @Inject + private IGrammarAccess grammarAccess; + + + + public XtextResource createResource() { + ResourceSet resourceSet = resourceSetProvider.get(); +// EObject context = PopupXtextEditorHelper.context ; +// ResourceSet resourceSet = context.eResource().getResourceSet() ; + Resource grammarResource = resourceSet.createResource( + URI.createURI(SYNTHETIC_SCHEME + ":/" + grammarAccess.getGrammar().getName() + ".xtext")); + grammarResource.getContents().add(EcoreUtil.copy(grammarAccess.getGrammar())); + XtextResource result = (XtextResource) resourceSet.createResource( + URI.createURI(SYNTHETIC_SCHEME + ":/" + grammarAccess.getGrammar().getName() + "." + PopupXtextEditorHelper.fileExtension)); + resourceSet.getResources().add(result); + return result ; + + } + +} |