summaryrefslogtreecommitdiffstats
path: root/rba.tool.editor.ui/src/rba/tool/editor/ui/editor
diff options
context:
space:
mode:
Diffstat (limited to 'rba.tool.editor.ui/src/rba/tool/editor/ui/editor')
-rw-r--r--rba.tool.editor.ui/src/rba/tool/editor/ui/editor/model/edit/processor/RBAModelProcessorUtil.xtend177
-rw-r--r--rba.tool.editor.ui/src/rba/tool/editor/ui/editor/model/edit/refactoring/RBAModelRenameElementUtil.java143
-rw-r--r--rba.tool.editor.ui/src/rba/tool/editor/ui/editor/model/edit/refactoring/RBAModelRenameRefactoringController.xtend24
-rw-r--r--rba.tool.editor.ui/src/rba/tool/editor/ui/editor/model/edit/refactoring/RBAModelSyncUtil.java175
-rw-r--r--rba.tool.editor.ui/src/rba/tool/editor/ui/editor/model/manager/ResourceManagerUI.xtend428
-rw-r--r--rba.tool.editor.ui/src/rba/tool/editor/ui/editor/templates/RBAModelTemplateRegistry.xtend99
-rw-r--r--rba.tool.editor.ui/src/rba/tool/editor/ui/editor/templates/RBAModelTemplateStore.xtend30
-rw-r--r--rba.tool.editor.ui/src/rba/tool/editor/ui/editor/templates/TemplateRegistry.xtend23
8 files changed, 1099 insertions, 0 deletions
diff --git a/rba.tool.editor.ui/src/rba/tool/editor/ui/editor/model/edit/processor/RBAModelProcessorUtil.xtend b/rba.tool.editor.ui/src/rba/tool/editor/ui/editor/model/edit/processor/RBAModelProcessorUtil.xtend
new file mode 100644
index 0000000..5eebb92
--- /dev/null
+++ b/rba.tool.editor.ui/src/rba/tool/editor/ui/editor/model/edit/processor/RBAModelProcessorUtil.xtend
@@ -0,0 +1,177 @@
+package rba.tool.editor.ui.editor.model.edit.processor
+
+import java.util.ArrayList
+import java.util.Collection
+import java.util.Collections
+import java.util.List
+import java.util.ListIterator
+import org.eclipse.emf.common.util.BasicEList
+import org.eclipse.emf.common.util.EList
+import org.eclipse.emf.common.util.URI
+import org.eclipse.emf.common.util.WrappedException
+import org.eclipse.emf.ecore.EObject
+import org.eclipse.emf.ecore.EStructuralFeature
+import org.eclipse.emf.ecore.util.EcoreUtil
+import org.eclipse.xtext.resource.XtextResource
+import org.eclipse.xtext.util.concurrent.IUnitOfWork
+import rba.tool.editor.ui.editor.model.edit.refactoring.RBAModelRenameElementUtil
+
+class RBAModelProcessorUtil {
+
+ public static final int NO_INDEX = -1;
+ public static final Object UNSET_VALUE = new Object();
+
+ def public static IUnitOfWork.Void<XtextResource> getAddProcessor(EObject owner, EStructuralFeature feature, Object object, int index) {
+ return new IUnitOfWork.Void<XtextResource>() {
+ override process(XtextResource xtextResource) throws Exception {
+ val allOwners = xtextResource.allContents.toIterable.filter[it === owner].toList();
+ if(!allOwners.isEmpty()) {
+ doAddProcess(allOwners.get(0), feature, object, index);
+ }
+ }
+ };
+ }
+
+ def public static IUnitOfWork.Void<XtextResource> getRemoveProcessor(EObject owner, EStructuralFeature feature, Collection<Object> collection) {
+ return new IUnitOfWork.Void<XtextResource>() {
+ override process(XtextResource xtextResource) throws Exception {
+ val allOwners = xtextResource.allContents.toIterable.filter[it === owner].toList();
+ if(!allOwners.isEmpty()) {
+ doRemoveProcess(allOwners.get(0), feature, collection);
+ }
+ }
+ };
+ }
+
+ def public static IUnitOfWork.Void<XtextResource> getSetProcessor(EObject owner, EStructuralFeature feature, Object value) {
+ return new IUnitOfWork.Void<XtextResource>() {
+ override process(XtextResource xtextResource) throws Exception {
+ val EObject docOwner = RBAModelProcessorUtil.findEObjectByURI(owner, xtextResource);
+ if(docOwner !== null && !docOwner.eIsProxy) {
+ doSetProcess(docOwner, feature, value);
+ }
+ }
+ };
+ }
+
+ def public static void doSetNameProcess(String value) {
+ RBAModelRenameElementUtil.INSTANCE.execute(value);
+ }
+
+ def public static IUnitOfWork.Void<XtextResource> getUnexecutableProcessor() {
+ return new IUnitOfWork.Void<XtextResource>() {
+ override process(XtextResource xtextResource) throws Exception {
+ return;
+ }
+ };
+ }
+
+ def public static void doAddProcess(EObject owner, EStructuralFeature feature, Object object, int index) {
+ if(feature.isMany()) {
+ val sibling = owner.eGet(feature) as List<Object>;
+ if(!sibling.contains(object)) {
+ sibling.add(if(index === NO_INDEX || index > sibling.size()) sibling.size() else index, object);
+ }
+ } else {
+ owner.eSet(feature, object);
+ }
+ }
+
+ def public static void doRemoveProcess(EObject owner, EStructuralFeature feature, Collection<Object> collection) {
+ if(feature.isMany()) {
+ val List<Object> objects = new ArrayList<Object>(collection);
+ val List<Object> sibling = owner.eGet(feature) as List<Object>;
+ for (obj : objects) {
+ if(sibling.contains(obj)) {
+ sibling.remove(obj);
+ }
+ }
+ } else {
+ if(feature.isUnsettable()) {
+ owner.eUnset(feature);
+ }
+ }
+ }
+
+ def public static void doSetProcess(EObject owner, EStructuralFeature feature, Object value) {
+ if(feature.isMany()) {
+ val List<Object> values = if(value == UNSET_VALUE) Collections.EMPTY_LIST else value as List<Object>;
+ val EList<Object> oldValues = owner.eGet(feature) as EList<Object>;
+
+ if(!oldValues.isEmpty()) {
+ if(!values.isEmpty()) {
+ val List<Object> removedValues = new BasicEList.FastCompare<Object>(oldValues);
+ removedValues.removeAll(values);
+
+ // If we aren't simply removing all the old values...
+ if(!removedValues.equals(oldValues)) {
+ // If there are values to remove, append a command for them.
+ if(!removedValues.isEmpty()) {
+ oldValues.removeAll(removedValues);
+ }
+
+ // Determine the values that will remain and move them into the right order, if necessary.
+ val EList<Object> remainingValues = new BasicEList.FastCompare<Object>(oldValues);
+ var count = -1;
+ for (object : values) {
+ val position = remainingValues.indexOf(object);
+ if(position != -1 && position != count.operator_plusPlus()) {
+ oldValues.move(count, position);
+ remainingValues.move(count, position);
+ }
+ }
+
+ // Determine the values to be added and add them at the right position.
+ val List<Object> addedValues = new BasicEList.FastCompare<Object>(values);
+ addedValues.removeAll(remainingValues);
+ if(!addedValues.isEmpty()) {
+ var addIndex = remainingValues.size();
+ for (val ListIterator<?> i = values.listIterator(values.size()); i.hasPrevious();) {
+ val Object object = i.previous();
+ if(addedValues.contains(object)) {
+ doAddProcess(owner, feature, object, addIndex);
+ } else {
+ addIndex.operator_minusMinus();
+ }
+ }
+ }
+ return;
+ }
+ }
+ oldValues.clear();
+ }
+
+ if(!values.isEmpty()) {
+ oldValues.addAll(values);
+ } else if(value == UNSET_VALUE && feature.isUnsettable()) {
+ owner.eUnset(feature);
+ }
+ } else {
+ if(value == UNSET_VALUE && feature.isUnsettable()) {
+ owner.eUnset(feature);
+ } else {
+ owner.eSet(feature, value);
+ }
+ }
+ }
+
+ def public static EObject findEObjectByURI(EObject object, XtextResource resource) {
+ val URI uri = EcoreUtil.getURI(object);
+ if(uri !== null) {
+ return findEObjectByURI(uri, resource);
+ }
+ return null;
+ }
+
+ def public static EObject findEObjectByURI(URI uri, XtextResource resource) {
+ if(uri.fragment() !== null) {
+ try {
+ val EObject result = resource.getEObject(uri.fragment());
+ return result;
+ } catch(IllegalArgumentException e) {
+ } catch(WrappedException e) {
+ }
+ }
+ return null;
+ }
+}
diff --git a/rba.tool.editor.ui/src/rba/tool/editor/ui/editor/model/edit/refactoring/RBAModelRenameElementUtil.java b/rba.tool.editor.ui/src/rba/tool/editor/ui/editor/model/edit/refactoring/RBAModelRenameElementUtil.java
new file mode 100644
index 0000000..cd84388
--- /dev/null
+++ b/rba.tool.editor.ui/src/rba/tool/editor/ui/editor/model/edit/refactoring/RBAModelRenameElementUtil.java
@@ -0,0 +1,143 @@
+package rba.tool.editor.ui.editor.model.edit.refactoring;
+
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.resource.ResourceSet;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.xtext.ide.refactoring.IRenameStrategy2;
+import org.eclipse.xtext.nodemodel.INode;
+import org.eclipse.xtext.resource.EObjectAtOffsetHelper;
+import org.eclipse.xtext.resource.IGlobalServiceProvider;
+import org.eclipse.xtext.resource.ILocationInFileProvider;
+import org.eclipse.xtext.resource.XtextResource;
+import org.eclipse.xtext.ui.editor.XtextEditor;
+import org.eclipse.xtext.ui.editor.utils.EditorUtils;
+import org.eclipse.xtext.ui.refactoring.IRenameStrategy;
+import org.eclipse.xtext.ui.refactoring.IRenameStrategy.Provider.NoSuchStrategyException;
+import org.eclipse.xtext.ui.refactoring.ui.IRenameContextFactory;
+import org.eclipse.xtext.ui.refactoring.ui.IRenameElementContext;
+import org.eclipse.xtext.ui.refactoring.ui.RefactoringPreferences;
+import org.eclipse.xtext.ui.refactoring.ui.RefactoringType;
+import org.eclipse.xtext.ui.refactoring2.rename.ISimpleNameProvider;
+import org.eclipse.xtext.util.ITextRegion;
+import org.eclipse.xtext.util.TextRegion;
+import org.eclipse.xtext.util.concurrent.IUnitOfWork;
+
+import com.google.inject.Inject;
+
+import rba.tool.editor.ui.activator.ExtensionEditorActivator;
+
+public class RBAModelRenameElementUtil {
+
+ public static RBAModelRenameElementUtil INSTANCE = new RBAModelRenameElementUtil();
+
+ @Inject
+ private EObjectAtOffsetHelper eObjectAtOffsetHelper;
+
+ @Inject
+ private ILocationInFileProvider locationInFileProvider;
+
+ @Inject
+ protected RBAModelRenameRefactoringController renameRefactoringController;
+
+ @Inject
+ protected IGlobalServiceProvider globalServiceProvider;
+
+ @Inject
+ protected RefactoringPreferences preferences;
+
+ @Inject
+ protected IRenameContextFactory renameContextFactory;
+
+ @Inject
+ protected RBAModelSyncUtil syncUtil;
+
+ private RBAModelRenameElementUtil() {
+ ExtensionEditorActivator.getInstance().injectMembers(this);
+ }
+
+ public void execute(String value) {
+ try {
+ final XtextEditor editor = EditorUtils.getActiveXtextEditor();
+ if (editor != null) {
+ syncUtil.totalSync(preferences.isSaveAllBeforeRefactoring(), renameRefactoringController.getActiveLinkedMode() == null);
+ final ITextSelection selection = (ITextSelection) editor.getSelectionProvider().getSelection();
+ IRenameElementContext renameElementContext = editor.getDocument().priorityReadOnly(new IUnitOfWork<IRenameElementContext, XtextResource>() {
+ @Override
+ public IRenameElementContext exec(XtextResource resource) throws Exception {
+ EObject selectedElement = eObjectAtOffsetHelper.resolveElementAt(resource, selection.getOffset());
+ if (selectedElement != null) {
+ IRenameElementContext renameElementContext = renameContextFactory.createRenameElementContext(selectedElement, editor, selection, resource);
+ if (isRefactoringEnabled(renameElementContext, resource))
+ return renameElementContext;
+ }
+ return null;
+ }
+ });
+ if (renameElementContext != null) {
+ startRenameElement(renameElementContext, value);
+ }
+ }
+ } catch (OperationCanceledException e) {
+ MessageDialog.openError(Display.getCurrent().getActiveShell(), "Error initializing refactoring 1", "\nSee log for details");
+ // cancelled by user, ok
+ return;
+ } catch (InterruptedException e) {
+ MessageDialog.openError(Display.getCurrent().getActiveShell(), "Error initializing refactoring 2", "\nSee log for details");
+ // cancelled by user, ok
+ return;
+ } catch (Exception exc) {
+ exc.printStackTrace();
+ MessageDialog.openError(Display.getCurrent().getActiveShell(), "Error initializing refactoring", exc.getMessage() + "\nSee log for details");
+ }
+ }
+
+ public IRenameElementContext createRenameElementContext(EObject targetElement, final XtextEditor triggeringEditor, final ITextSelection selection,
+ XtextResource triggeringResource) {
+ return renameContextFactory.createRenameElementContext(targetElement, triggeringEditor, selection, triggeringResource);
+ }
+
+ protected boolean isRefactoringEnabled(IRenameElementContext renameElementContext, XtextResource resource) {
+ ResourceSet resourceSet = resource.getResourceSet();
+ if (renameElementContext != null && resourceSet != null) {
+ EObject targetElement = resourceSet.getEObject(renameElementContext.getTargetElementURI(), true);
+ if (targetElement != null && !targetElement.eIsProxy()) {
+ if (targetElement.eResource() == resource && renameElementContext.getTriggeringEditorSelection() instanceof ITextSelection) {
+ ITextSelection textSelection = (ITextSelection) renameElementContext.getTriggeringEditorSelection();
+ ITextRegion selectedRegion = new TextRegion(textSelection.getOffset(), textSelection.getLength());
+ INode crossReferenceNode = eObjectAtOffsetHelper.getCrossReferenceNode(resource, selectedRegion);
+ if (crossReferenceNode == null) {
+ // selection is on the declaration. make sure it's the name
+ ITextRegion significantRegion = locationInFileProvider.getSignificantTextRegion(targetElement);
+ if (!significantRegion.contains(selectedRegion))
+ return false;
+ }
+ }
+ IRenameStrategy.Provider renameStrategyProvider = globalServiceProvider.findService(targetElement, IRenameStrategy.Provider.class);
+ try {
+ if (renameStrategyProvider.get(targetElement, renameElementContext) != null) {
+ return true;
+ } else {
+ IRenameStrategy2 strategy2 = globalServiceProvider.findService(targetElement, IRenameStrategy2.class);
+ ISimpleNameProvider simpleNameProvider = globalServiceProvider.findService(targetElement, ISimpleNameProvider.class);
+ return strategy2 != null && simpleNameProvider.canRename(targetElement);
+ }
+
+ } catch (NoSuchStrategyException e) {
+ MessageDialog.openInformation(Display.getCurrent().getActiveShell(), "Cannot rename element", e.getMessage());
+ }
+ }
+ }
+ return false;
+ }
+
+ protected void startRenameElement(IRenameElementContext renameElementContext, String value) throws InterruptedException {
+ // renameRefactoringController.startRefactoring(renameElementContext);
+ // renameRefactoringController.startRefactoring(RefactoringType.REFACTORING_DIALOG);
+ renameRefactoringController.initialize(renameElementContext);
+ renameRefactoringController.setNewNameText(value);
+ renameRefactoringController.startRefactoring(RefactoringType.REFACTORING_DIALOG);
+ }
+}
diff --git a/rba.tool.editor.ui/src/rba/tool/editor/ui/editor/model/edit/refactoring/RBAModelRenameRefactoringController.xtend b/rba.tool.editor.ui/src/rba/tool/editor/ui/editor/model/edit/refactoring/RBAModelRenameRefactoringController.xtend
new file mode 100644
index 0000000..737d004
--- /dev/null
+++ b/rba.tool.editor.ui/src/rba/tool/editor/ui/editor/model/edit/refactoring/RBAModelRenameRefactoringController.xtend
@@ -0,0 +1,24 @@
+package rba.tool.editor.ui.editor.model.edit.refactoring
+
+import com.google.inject.Singleton
+import org.eclipse.xtext.ui.editor.XtextEditor
+import org.eclipse.xtext.ui.refactoring.ui.RenameRefactoringController
+
+@Singleton
+class RBAModelRenameRefactoringController extends RenameRefactoringController {
+
+ private String newNameText;
+
+ override protected getOriginalName(XtextEditor xtextEditor) {
+ if(this instanceof RBAModelRenameRefactoringController) {
+ return newNameText;
+ } else {
+ super.getOriginalName(xtextEditor);
+ }
+ }
+
+ def public void setNewNameText(String name) {
+ this.newNameText = name;
+ }
+
+}
diff --git a/rba.tool.editor.ui/src/rba/tool/editor/ui/editor/model/edit/refactoring/RBAModelSyncUtil.java b/rba.tool.editor.ui/src/rba/tool/editor/ui/editor/model/edit/refactoring/RBAModelSyncUtil.java
new file mode 100644
index 0000000..ae6cfb3
--- /dev/null
+++ b/rba.tool.editor.ui/src/rba/tool/editor/ui/editor/model/edit/refactoring/RBAModelSyncUtil.java
@@ -0,0 +1,175 @@
+package rba.tool.editor.ui.editor.model.edit.refactoring;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.IncrementalProjectBuilder;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.SubMonitor;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IEditorReference;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.xtext.resource.XtextResource;
+import org.eclipse.xtext.service.OperationCanceledError;
+import org.eclipse.xtext.ui.editor.XtextEditor;
+import org.eclipse.xtext.ui.editor.model.XtextDocument;
+import org.eclipse.xtext.util.concurrent.IUnitOfWork;
+
+import com.google.inject.Inject;
+
+public class RBAModelSyncUtil {
+
+ @Inject(optional = true)
+ private IWorkbench workbench;
+
+ @Inject(optional = true)
+ private IWorkspace workspace;
+
+ public void totalSync(final boolean saveAll, boolean useProgressDialog) throws InvocationTargetException, InterruptedException {
+ totalSync(saveAll, useProgressDialog, true);
+ }
+
+ public void totalSync(final boolean saveAll, boolean useProgressDialog, boolean fork) throws InvocationTargetException, InterruptedException {
+ if (Display.getCurrent() != null && workbench != null) {
+ if (useProgressDialog) {
+ workbench.getProgressService().run(fork, true, new IRunnableWithProgress() {
+ @Override
+ public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
+ doReconcileAndBuild(saveAll, monitor);
+ }
+ });
+ } else {
+ doReconcileAndBuild(saveAll, null);
+ }
+ }
+ }
+
+ private void doReconcileAndBuild(final boolean saveAll, IProgressMonitor monitor) throws InterruptedException {
+ try {
+ SubMonitor progress = SubMonitor.convert(monitor, 10);
+ reconcileAllEditors(workbench, saveAll, progress.newChild(1));
+ if (progress.isCanceled()) {
+ throw new InterruptedException();
+ }
+ waitForBuild(progress.newChild(4));
+ if (progress.isCanceled()) {
+ throw new InterruptedException();
+ }
+ yieldToQueuedDisplayJobs(progress.newChild(1));
+ if (progress.isCanceled()) {
+ throw new InterruptedException();
+ }
+ waitForAutoBuild(progress.newChild(4));
+ } catch (OperationCanceledException e) {
+ throw new InterruptedException();
+ }
+ }
+
+ public void totalSync(final boolean saveAll) throws InvocationTargetException, InterruptedException {
+ totalSync(saveAll, true);
+ }
+
+ public void reconcileAllEditors(IWorkbench workbench, final boolean saveAll, final IProgressMonitor monitor) {
+ for (IWorkbenchWindow window : workbench.getWorkbenchWindows()) {
+ for (IWorkbenchPage page : window.getPages()) {
+ for (IEditorReference editorReference : page.getEditorReferences()) {
+ if (monitor.isCanceled())
+ return;
+ final IEditorPart editor = editorReference.getEditor(false);
+ if (editor != null) {
+ if (editor instanceof XtextEditor) {
+ waitForReconciler((XtextEditor) editor);
+ }
+ if (saveAll) {
+ Display display = workbench.getDisplay();
+ display.syncExec(new Runnable() {
+ @Override
+ public void run() {
+ if (editor.isDirty()) {
+ editor.doSave(monitor);
+ }
+ }
+ });
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * this methods blocks until the following jobs have finished, - the reconciler - the editor validation job - the dirty
+ * state editor updater job
+ */
+ public void waitForReconciler(XtextEditor editor) {
+ try {
+ editor.getDocument().readOnly(new IUnitOfWork.Void<XtextResource>() {
+ @Override
+ public void process(XtextResource state) throws Exception {
+ // this doesn't execute before the reconciler has finished
+ }
+ });
+ // reconciling schedules both, validation and dirty state
+ Job validationJob = ((XtextDocument) editor.getDocument()).getValidationJob();
+ validationJob.join();
+ editor.getDirtyStateEditorSupport().waitForUpdateEditorJob();
+ } catch (OperationCanceledException e) {
+ } catch (OperationCanceledError e) {
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void waitForBuild(IProgressMonitor monitor) {
+ try {
+ workspace.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, monitor);
+ } catch (CoreException e) {
+ throw new OperationCanceledException(e.getMessage());
+ }
+ }
+
+ /**
+ * @deprecated we should not rely on auto build to be triggered. Use {@link #waitForBuild(IProgressMonitor)} instead.
+ */
+ @Deprecated
+ public void waitForAutoBuild(IProgressMonitor monitor) {
+ boolean wasInterrupted = false;
+ do {
+ try {
+ Job.getJobManager().join(ResourcesPlugin.FAMILY_AUTO_BUILD, monitor);
+ wasInterrupted = false;
+ } catch (OperationCanceledException e) {
+ throw e;
+ } catch (InterruptedException e) {
+ wasInterrupted = true;
+ }
+ } while (wasInterrupted);
+ }
+
+ public void yieldToQueuedDisplayJobs(IProgressMonitor monitor) {
+ yieldToQueuedDisplayJobs(monitor, 50000);
+ }
+
+ public void yieldToQueuedDisplayJobs(IProgressMonitor monitor, int maxJobsToYieldTo) {
+ int count = 0;
+ if (Display.getCurrent() != null) {
+ while (count < maxJobsToYieldTo && Display.getCurrent().readAndDispatch()) {
+ if (monitor.isCanceled())
+ throw new OperationCanceledException();
+ ++count;
+ }
+ if (count == maxJobsToYieldTo) {
+ System.out.println("maxJobsToYieldTo probably exceeded. Worked: " + count);
+ }
+ }
+ }
+
+}
diff --git a/rba.tool.editor.ui/src/rba/tool/editor/ui/editor/model/manager/ResourceManagerUI.xtend b/rba.tool.editor.ui/src/rba/tool/editor/ui/editor/model/manager/ResourceManagerUI.xtend
new file mode 100644
index 0000000..105d9de
--- /dev/null
+++ b/rba.tool.editor.ui/src/rba/tool/editor/ui/editor/model/manager/ResourceManagerUI.xtend
@@ -0,0 +1,428 @@
+package rba.tool.editor.ui.editor.model.manager
+
+import com.google.inject.Inject
+import java.util.ArrayList
+import java.util.Collection
+import java.util.Collections
+import java.util.List
+import org.eclipse.core.resources.IProject
+import org.eclipse.core.resources.IncrementalProjectBuilder
+import org.eclipse.core.resources.ResourcesPlugin
+import org.eclipse.core.runtime.IProgressMonitor
+import org.eclipse.core.runtime.OperationCanceledException
+import org.eclipse.core.runtime.SubMonitor
+import org.eclipse.core.runtime.jobs.Job
+import org.eclipse.emf.common.util.URI
+import org.eclipse.emf.ecore.EAttribute
+import org.eclipse.emf.ecore.EObject
+import org.eclipse.emf.ecore.EReference
+import org.eclipse.emf.ecore.EStructuralFeature
+import org.eclipse.emf.ecore.resource.ResourceSet
+import org.eclipse.emf.ecore.util.EcoreUtil
+import org.eclipse.emf.edit.provider.ComposeableAdapterFactory
+import org.eclipse.emf.edit.provider.IEditingDomainItemProvider
+import org.eclipse.jface.dialogs.MessageDialog
+import org.eclipse.swt.widgets.Display
+import org.eclipse.ui.IEditorPart
+import org.eclipse.xtext.resource.ILocationInFileProvider
+import org.eclipse.xtext.resource.XtextResource
+import org.eclipse.xtext.serializer.ISerializer
+import org.eclipse.xtext.service.OperationCanceledError
+import org.eclipse.xtext.ui.editor.LanguageSpecificURIEditorOpener
+import org.eclipse.xtext.ui.editor.XtextEditor
+import org.eclipse.xtext.ui.editor.model.IXtextDocument
+import org.eclipse.xtext.ui.editor.utils.EditorUtils
+import org.eclipse.xtext.util.ITextRegion
+import org.eclipse.xtext.util.concurrent.IUnitOfWork
+import rba.core.provider.RBACoreItemProviderAdapterFactory
+import rba.sound.provider.RBASoundItemProviderAdapterFactory
+import rba.tool.editor.resource.IRBAModelResourceLoader
+import rba.tool.editor.ui.activator.ExtensionEditorActivator
+import rba.tool.editor.ui.editor.model.edit.processor.RBAModelProcessorUtil
+import rba.tool.editor.ui.resource.RBAModelResourceSetProvider
+import rba.view.provider.RBAViewItemProviderAdapterFactory
+
+class ResourceManagerUI {
+
+ public static ResourceManagerUI INSTANCE = new ResourceManagerUI();
+
+ @Inject private RBAModelResourceSetProvider resourceSetProvider;
+
+ @Inject private LanguageSpecificURIEditorOpener editorOpener ;
+
+ @Inject private ILocationInFileProvider locationProvider;
+
+ @Inject private ISerializer serializer;
+
+ @Inject IRBAModelResourceLoader resourceLoader;
+
+ private List<ComposeableAdapterFactory> adapterFactorys = new ArrayList<ComposeableAdapterFactory>;
+
+ private IProject currentProject;
+
+ private new() {
+ ExtensionEditorActivator.getInstance().injectMembers(this);
+ adapterFactorys.add(new RBACoreItemProviderAdapterFactory());
+ adapterFactorys.add(new RBAViewItemProviderAdapterFactory());
+ adapterFactorys.add(new RBASoundItemProviderAdapterFactory());
+ }
+
+ def public IProject getCurrentProject() {
+ return currentProject;
+ }
+
+ def public void setCurrentProject(IProject project) {
+ currentProject = project;
+ }
+
+ def public boolean isCurrentProject(IProject project) {
+ if (project === null || !project.isOpen()) {
+ return false;
+ }
+
+ if (project.equals(currentProject)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ def public ResourceSet getCurrentResourceSet() {
+ return resourceSetProvider.getResourceSet(currentProject);
+ }
+
+ def public void setCurrentResourceSet(ResourceSet resourceSet) {
+ resourceSetProvider.setResourceSet(currentProject, resourceSet);
+ }
+
+ def public IXtextDocument getXtextDocument(IEditorPart openEditor) {
+ val XtextEditor xtextEditor = EditorUtils.getXtextEditor(openEditor);
+ if (xtextEditor !== null) {
+ return xtextEditor.getDocument();
+ }
+ return null;
+ }
+
+ def public void add(EObject owner, EStructuralFeature feature, Object object, int index) {
+ val Object outerOwner = owner ?: getParent(object);
+ if (outerOwner === null) {
+ return;
+ }
+ if (!(outerOwner instanceof EObject)) {
+ return;
+ }
+
+ if (feature === null || object === null) {
+ return;
+ }
+
+ if (!isValid(outerOwner as EObject, feature)) {
+ return;
+ }
+
+ val editorPart = open(outerOwner as EObject, false);
+ var IXtextDocument document = getXtextDocument(editorPart);
+
+ if (document !== null) {
+ document.modify(RBAModelProcessorUtil.getAddProcessor(outerOwner as EObject, feature, object, if (index < 0) RBAModelProcessorUtil.NO_INDEX else index));
+ }
+ }
+
+ def public void remove(EObject owner, EStructuralFeature feature, Object object) {
+ val Object outerOwner = owner ?: getParent(object);
+ if (outerOwner === null) {
+ return;
+ }
+ if (!(outerOwner instanceof EObject)) {
+ return;
+ }
+
+ remove(outerOwner as EObject, feature, Collections.singleton(object));
+ }
+
+ def public void remove(EObject owner, EStructuralFeature feature, Collection<Object> collection) {
+ if (owner !== null) {
+ if (feature === null || collection === null || collection.isEmpty()) {
+ return;
+ }
+
+ if (!isValid(owner, feature)) {
+ return;
+ }
+
+ val editorPart = open(owner as EObject, false);
+ var IXtextDocument document = getXtextDocument(editorPart);
+
+ if (document !== null) {
+ document.modify(RBAModelProcessorUtil.getRemoveProcessor(owner as EObject, feature, collection));
+ }
+ } else {
+ remove(feature, collection);
+ }
+ }
+
+ def public void remove(EStructuralFeature feature, Collection<Object> collection) {
+ if (feature === null || collection === null || collection.isEmpty()) {
+ return;
+ }
+
+ val List<Object> objects = new ArrayList<Object>(collection);
+ while (!objects.isEmpty()) {
+ // We will iterate over the whole collection, removing some as we go.
+ val remainingObjects = objects.listIterator();
+
+ // Take the first object, and remove it.
+ val object = remainingObjects.next();
+ remainingObjects.remove();
+
+ // Determine the object's parent.
+ val parent = getParent(object);
+ if (parent instanceof EObject) {
+ // Now we want to find all the other objects with this same parent.
+ // So we can collection siblings together and give the parent control over their removal.
+ val List<Object> siblings = new ArrayList<Object>();
+ siblings.add(object);
+
+ while (remainingObjects.hasNext()) {
+ // Get the next object and check if it has the same parent.
+ val otherObject = remainingObjects.next();
+ val otherParent = getParent(otherObject);
+ if (otherParent == parent) {
+ // Remove the object and add it as a sibling.
+ remainingObjects.remove();
+ siblings.add(otherObject);
+ }
+ }
+ remove(parent as EObject, feature, siblings);
+ }
+ }
+ }
+
+ def public void set(EObject owner, EStructuralFeature feature, Object value) {
+ val Object outerOwner = owner ?: getParent(value);
+ if (outerOwner === null) {
+ return;
+ }
+ if (!(outerOwner instanceof EObject)) {
+ return;
+ }
+
+ if (feature === null) {
+ return;
+ }
+
+ if (!isValid(owner, feature)) {
+ return;
+ }
+
+ val innerValue = value ?: RBAModelProcessorUtil.UNSET_VALUE;
+ val editorPart = open(outerOwner as EObject, false);
+ var IXtextDocument document = getXtextDocument(editorPart);
+
+ if (document !== null) {
+ document.modify(RBAModelProcessorUtil.getSetProcessor(outerOwner as EObject, feature, innerValue));
+ selectAndReveal(editorPart, EcoreUtil.getURI(outerOwner as EObject), feature, true);
+ }
+ }
+
+ def public void unset(EObject owner, EStructuralFeature feature) {
+ if (owner === null || feature === null) {
+ return;
+ }
+
+ if (!isValid(owner, feature)) {
+ return;
+ }
+
+ val editorPart = open(owner as EObject, false);
+ var IXtextDocument document = getXtextDocument(editorPart);
+
+ if (document !== null) {
+ document.modify(RBAModelProcessorUtil.getSetProcessor(owner, feature, RBAModelProcessorUtil.UNSET_VALUE));
+ }
+ }
+
+ def public void setName(EObject owner, EStructuralFeature feature, Object value) {
+ val Object outerOwner = owner ?: getParent(value);
+ if (outerOwner === null) {
+ return;
+ }
+ if (!(outerOwner instanceof EObject)) {
+ return;
+ }
+
+ val XtextEditor editor = open(outerOwner as EObject, true);
+ if (editor === null) {
+ return;
+ }
+
+ if (feature === null) {
+ return;
+ }
+
+ if (!isValid(owner, feature)) {
+ return;
+ }
+
+ if (!(value instanceof String)) {
+ return;
+ }
+ val innerValue = value as String;
+
+ RBAModelProcessorUtil.doSetNameProcess(innerValue)
+ }
+
+ def public void waitForBuildProgress(Object family, IProgressMonitor monitor) {
+ var boolean wasInterrupted = false;
+ do {
+ try {
+ Job.getJobManager().join(family, monitor);
+ wasInterrupted = false;
+ } catch (OperationCanceledException e) {
+ throw e;
+ } catch (InterruptedException e) {
+ wasInterrupted = true;
+ }
+ } while (wasInterrupted);
+ }
+
+ def public XtextEditor open(EObject eObject, boolean select) {
+ val resource = eObject.eResource();
+ if (resource === null) {
+ return null;
+ }
+
+ val editorPart = editorOpener.open(EcoreUtil.getURI(eObject), select);
+ if (!(editorPart instanceof XtextEditor)) {
+ return null;
+ }
+
+ return (editorPart as XtextEditor);
+ }
+
+ def public XtextEditor open(URI uri, boolean select) {
+ if (uri === null || uri.isEmpty()) {
+ return null
+ }
+
+ val editorPart = editorOpener.open(uri, select);
+ if (!(editorPart instanceof XtextEditor)) {
+ return null;
+ }
+
+ return (editorPart as XtextEditor);
+ }
+
+ def private Object getParent(Object object) {
+ for (adapterFactory : adapterFactorys) {
+ val IEditingDomainItemProvider editingDomainItemProvider = adapterFactory.adapt(object, IEditingDomainItemProvider) as IEditingDomainItemProvider;
+ if (editingDomainItemProvider !== null) {
+ return editingDomainItemProvider.getParent(object);
+ }
+ }
+ return null;
+ }
+
+ def private static isValid(EObject owner, EStructuralFeature feature) {
+ if (feature instanceof EReference && owner.eClass().getEAllReferences().contains(feature)) {
+ return true;
+ }
+ if (feature instanceof EAttribute && owner.eClass().getEAllAttributes().contains(feature)) {
+ return true;
+ }
+ return false;
+ }
+
+ def public void switchToProject(IProject project, IProgressMonitor monitor) throws InterruptedException {
+ if (project === null) {
+ return;
+ }
+
+ try {
+ val SubMonitor progress = SubMonitor.convert(monitor, 10);
+ doSwitch(project, progress.newChild(2));
+ if (progress.isCanceled()) {
+ throw new InterruptedException();
+ }
+ doBuild(project, progress.newChild(6));
+ if (progress.isCanceled()) {
+ throw new InterruptedException();
+ }
+ waitForBuildProgress(ResourcesPlugin.FAMILY_MANUAL_BUILD, progress.newChild(2));
+ } catch (Exception e) {
+ throw new InterruptedException(e.getMessage());
+ }
+ }
+
+ def public boolean doConfirm(IProject project, boolean showConfirmDialog) throws InterruptedException {
+ if (project === null || !project.isOpen()) {
+ throw new InterruptedException();
+ }
+ if (isCurrentProject(project)) {
+ return true;
+ }
+
+ val boolean confirm = if (showConfirmDialog)
+ MessageDialog.openConfirm(Display.getCurrent().getActiveShell(), "Switch Project", "Do you want to switch to [" + project.getName() + "] project?")
+ else
+ true;
+
+ return confirm;
+ }
+
+ def private void doSwitch(IProject project, IProgressMonitor monitor) {
+ try {
+ setCurrentProject(project);
+ } catch (Exception e) {
+ throw new InterruptedException(e.getMessage());
+ }
+ }
+
+ def private void doBuild(IProject project, IProgressMonitor monitor) {
+ try {
+ project.build(IncrementalProjectBuilder.FULL_BUILD, monitor);
+ } catch (Exception e) {
+ throw new InterruptedException(e.getMessage());
+ }
+ }
+
+ def private void selectAndReveal(IEditorPart openEditor, URI uri, EStructuralFeature feature, boolean select) {
+ if (openEditor instanceof XtextEditor && select) {
+ val xtextEditor = openEditor as XtextEditor;
+ var boolean success = false;
+ var int tries = 0;
+ while (!success || tries >= 5) {
+ try {
+ xtextEditor.getDocument().readOnly(new IUnitOfWork.Void<XtextResource>() {
+ override process(XtextResource resource) throws Exception {
+ if (resource !== null) {
+ val EObject object = RBAModelProcessorUtil.findEObjectByURI(uri, resource);
+ if (object !== null) {
+ val ITextRegion location = if (feature !== null)
+ locationProvider.getSignificantTextRegion(object, feature, 0)
+ else
+ locationProvider.getSignificantTextRegion(object);
+ xtextEditor.selectAndReveal(location.getOffset(), location.getLength());
+ }
+ }
+ }
+ });
+ xtextEditor.doSave(null)
+ success = true;
+ } catch (OperationCanceledException e) {
+ } catch (OperationCanceledError e) {
+ } finally {
+ tries++;
+ }
+ }
+ }
+ }
+
+ def public String serialize(EObject object) {
+ return serializer.serialize(object)
+ }
+
+ def public void loadAndResolveResource(ResourceSet resourceSet, URI[] URIs, IProject project) {
+ resourceLoader.loadAndResolveResource(resourceSet, URIs, project);
+ }
+}
diff --git a/rba.tool.editor.ui/src/rba/tool/editor/ui/editor/templates/RBAModelTemplateRegistry.xtend b/rba.tool.editor.ui/src/rba/tool/editor/ui/editor/templates/RBAModelTemplateRegistry.xtend
new file mode 100644
index 0000000..0b1126c
--- /dev/null
+++ b/rba.tool.editor.ui/src/rba/tool/editor/ui/editor/templates/RBAModelTemplateRegistry.xtend
@@ -0,0 +1,99 @@
+package rba.tool.editor.ui.editor.templates
+
+import com.google.common.collect.Lists
+import com.google.inject.Inject
+import com.google.inject.Singleton
+import java.util.List
+import java.util.Map
+import org.apache.commons.lang.StringUtils
+import org.eclipse.jface.text.templates.Template
+import org.eclipse.xtext.EcoreUtil2
+import org.eclipse.xtext.GrammarUtil
+import org.eclipse.xtext.IGrammarAccess
+import org.eclipse.xtext.Keyword
+import org.eclipse.xtext.ui.editor.templates.ContextTypeIdHelper
+import rba.tool.editor.ui.util.CharacterUtil
+
+@Singleton
+class RBAModelTemplateRegistry extends TemplateRegistry {
+
+ private final Map<String, String> PATTERNS = newLinkedHashMap(
+ "rba.tool.editor.RBAModel.kw_runtime:" -> "${true}",
+ "rba.tool.editor.RBAModel.kw_global:" -> "${false}",
+ "rba.tool.editor.RBAModel.kw_description:" -> "\"${}\"",
+ "rba.tool.editor.RBAModel.kw_width:" -> "${0}",
+ "rba.tool.editor.RBAModel.kw_height:" -> "${0}",
+ "rba.tool.editor.RBAModel.kw_x:" -> "${0}",
+ "rba.tool.editor.RBAModel.kw_y:" -> "${0}",
+ "rba.tool.editor.RBAModel.kw_attenuateValue:" -> "${0}",
+ "rba.tool.editor.RBAModel.kw_loserType:" -> "${NEVER_GIVEUP}",
+ "rba.tool.editor.RBAModel.kw_arbitrationPolicy:" -> "${DEFAULT}",
+ "rba.tool.editor.RBAModel.kw_basePoint:" -> "${LEFT_TOP}",
+ "rba.tool.editor.RBAModel.kw_type:" -> "${DEFAULT}",
+ "rba.tool.editor.RBAModel.kw_allocatable:" -> "[${cursor}]",
+ "rba.tool.editor.RBAModel.kw_subarea:" -> "[${cursor}]",
+ "rba.tool.editor.RBAModel.kw_sizeReference:" -> "${size_id}",
+ "rba.tool.editor.RBAModel.kw_layout:" -> "",
+ "rba.tool.editor.RBAModel.kw_visibility:" -> "${STANDARD_VALUE}",
+ "rba.tool.editor.RBAModel.kw_priority:" -> "${STANDARD_VALUE}",
+ "rba.tool.editor.RBAModel.kw_value:" -> "${STANDARD_VALUE}",
+ "rba.tool.editor.RBAModel.kw_zorder:" -> "${STANDARD_VALUE}",
+ "rba.tool.editor.RBAModel.kw_contentStateRef:" -> "${contentState_id}",
+ "rba.tool.editor.RBAModel.kw_areaReference:" -> "${area_id}",
+ "rba.tool.editor.RBAModel.kw_condition:" -> "",
+ "rba.tool.editor.RBAModel.kw_area:" -> "${area_id}",
+ "rba.tool.editor.RBAModel.kw_content:" -> "${content_id}"
+ ) ;
+
+ private final ContextTypeIdHelper helper;
+
+ @Inject
+ public new(IGrammarAccess grammarAccess, ContextTypeIdHelper helper) {
+ this.helper = helper;
+ registerTemplates(grammarAccess);
+ }
+
+ def protected void registerTemplates(IGrammarAccess grammarAccess) {
+ val List<Template> allTemplates = Lists.newArrayList();
+ for (parserRule : GrammarUtil.allParserRules(grammarAccess.getGrammar())) {
+ var Template template;
+ for (keyword : EcoreUtil2.getAllContentsOfType(parserRule, Keyword)) {
+ if (CharacterUtil.isKeywordWorthyToPropose(keyword)) {
+ val name = keyword.value;
+ if (!StringUtils.isEmpty(name)) {
+ if (StringUtils.endsWith(name, ":")) {
+ template = new Template(name, "", getId(keyword), getPattern(keyword), true);
+ } else {
+ template = new Template(name, "", getId(keyword), name, true);
+ }
+ allTemplates.add(template);
+ }
+ }
+ }
+ }
+ for (enumRule : GrammarUtil.allEnumRules(grammarAccess.getGrammar())) {
+ var Template template;
+ for (keyword : EcoreUtil2.getAllContentsOfType(enumRule, Keyword)) {
+ if (CharacterUtil.isKeywordWorthyToPropose(keyword)) {
+ val name = keyword.value;
+ if (!StringUtils.isEmpty(name)) {
+ template = new Template(name, "", getId(keyword), name, true);
+ allTemplates.add(template);
+ }
+ }
+ }
+ }
+
+ for (template : allTemplates) {
+ addTemplate(template);
+ }
+ }
+
+ def public String getId(Keyword k) {
+ return helper.getId(k);
+ }
+
+ def private String getPattern(Keyword k) {
+ return StringUtils.join(#[k.value, " ", PATTERNS.get(getId(k)) ?: ""]);
+ }
+}
diff --git a/rba.tool.editor.ui/src/rba/tool/editor/ui/editor/templates/RBAModelTemplateStore.xtend b/rba.tool.editor.ui/src/rba/tool/editor/ui/editor/templates/RBAModelTemplateStore.xtend
new file mode 100644
index 0000000..7330f91
--- /dev/null
+++ b/rba.tool.editor.ui/src/rba/tool/editor/ui/editor/templates/RBAModelTemplateStore.xtend
@@ -0,0 +1,30 @@
+package rba.tool.editor.ui.editor.templates
+
+import com.google.inject.Inject
+import com.google.inject.Singleton
+import java.util.ArrayList
+import java.util.List
+import org.eclipse.jface.preference.IPreferenceStore
+import org.eclipse.jface.text.templates.ContextTypeRegistry
+import org.eclipse.jface.text.templates.Template
+import org.eclipse.ui.plugin.AbstractUIPlugin
+import org.eclipse.xtext.ui.editor.templates.XtextTemplateStore
+
+@Singleton
+class RBAModelTemplateStore extends XtextTemplateStore {
+
+ private TemplateRegistry templateRegistry;
+
+ @Inject
+ new(TemplateRegistry templateRegistry, ContextTypeRegistry registry, IPreferenceStore store, String key, AbstractUIPlugin plugin) {
+ super(registry, store, key, plugin);
+ this.templateRegistry = templateRegistry;
+ }
+
+ override getTemplates(String contextTypeId) {
+ val List<Template> templates = new ArrayList<Template>(super.getTemplates(contextTypeId));
+ val template = templateRegistry.getTemplate(contextTypeId);
+ if (template !== null) templates.add(template);
+ return templates.toArray(newArrayOfSize(templates.size()));
+ }
+}
diff --git a/rba.tool.editor.ui/src/rba/tool/editor/ui/editor/templates/TemplateRegistry.xtend b/rba.tool.editor.ui/src/rba/tool/editor/ui/editor/templates/TemplateRegistry.xtend
new file mode 100644
index 0000000..edba477
--- /dev/null
+++ b/rba.tool.editor.ui/src/rba/tool/editor/ui/editor/templates/TemplateRegistry.xtend
@@ -0,0 +1,23 @@
+package rba.tool.editor.ui.editor.templates
+
+import java.util.Iterator
+import java.util.LinkedHashMap
+import java.util.Map
+import org.eclipse.jface.text.templates.Template
+
+class TemplateRegistry {
+
+ private final Map<String, Template> fTemplates = new LinkedHashMap<String, Template>();
+
+ def public void addTemplate(Template template) {
+ fTemplates.put(template.contextTypeId, template);
+ }
+
+ def public Template getTemplate(String id) {
+ return fTemplates.get(id);
+ }
+
+ def public Iterator<Template> templates() {
+ return fTemplates.values().iterator();
+ }
+}