From 51f1f32123728a59f6a6bd6df726631ed52f5ebb Mon Sep 17 00:00:00 2001 From: Florian Hoelzl <hoelzl@fortiss.org> Date: Sun, 27 Nov 2011 16:17:59 +0000 Subject: [PATCH] implemented close editors on delete feature renamed ProjectRootElementUtils -> ModelElementUtils refs 309 --- .../internal/ModelEditorBindingService.java | 119 +++++++++++++++--- .../kernel/ui/internal/NavigatorService.java | 10 +- .../service/IModelEditorBindingService.java | 4 +- .../extension/data/ITopLevelElement.java | 7 +- .../kernel/internal/CommandStackService.java | 13 +- .../storage/eclipse/ModelContext.java | 4 +- .../kernel/service/ICommandStackService.java | 3 +- ...ementUtils.java => ModelElementUtils.java} | 17 ++- 8 files changed, 152 insertions(+), 25 deletions(-) rename org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/utils/{ProjectRootElementUtils.java => ModelElementUtils.java} (90%) diff --git a/org.fortiss.tooling.kernel.ui/trunk/src/org/fortiss/tooling/kernel/ui/internal/ModelEditorBindingService.java b/org.fortiss.tooling.kernel.ui/trunk/src/org/fortiss/tooling/kernel/ui/internal/ModelEditorBindingService.java index 0469ef778..3a18b33fb 100644 --- a/org.fortiss.tooling.kernel.ui/trunk/src/org/fortiss/tooling/kernel/ui/internal/ModelEditorBindingService.java +++ b/org.fortiss.tooling.kernel.ui/trunk/src/org/fortiss/tooling/kernel/ui/internal/ModelEditorBindingService.java @@ -19,19 +19,31 @@ package org.fortiss.tooling.kernel.ui.internal; import java.util.Collections; import java.util.Comparator; +import java.util.EventObject; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.conqat.lib.commons.collections.CollectionUtils; +import org.eclipse.emf.common.command.CommandStackListener; import org.eclipse.emf.ecore.EObject; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IPartListener; +import org.eclipse.ui.IPartService; +import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.fortiss.tooling.kernel.ToolingKernelActivator; +import org.fortiss.tooling.kernel.extension.data.ITopLevelElement; +import org.fortiss.tooling.kernel.service.ICommandStackService; +import org.fortiss.tooling.kernel.service.IPersistencyService; import org.fortiss.tooling.kernel.service.base.EObjectAwareServiceBase; import org.fortiss.tooling.kernel.ui.extension.IModelEditorBinding; import org.fortiss.tooling.kernel.ui.internal.editor.ExtendableMultiPageEditor; import org.fortiss.tooling.kernel.ui.internal.editor.ModelElementEditorInput; import org.fortiss.tooling.kernel.ui.service.IModelEditorBindingService; import org.fortiss.tooling.kernel.utils.LoggingUtils; +import org.fortiss.tooling.kernel.utils.ModelElementUtils; /** * This class implements the {@link IModelEditorBindingService} interface. @@ -43,7 +55,7 @@ import org.fortiss.tooling.kernel.utils.LoggingUtils; */ public class ModelEditorBindingService extends EObjectAwareServiceBase<IModelEditorBinding<EObject>> implements - IModelEditorBindingService { + IModelEditorBindingService, IPartListener, CommandStackListener { /** The compositor extension point ID. */ private static final String EXTENSION_POINT_NAME = "org.fortiss.tooling.kernel.ui.modelEditorBinding"; @@ -54,6 +66,12 @@ public class ModelEditorBindingService extends /** The handler class attribute name. */ private static final String HANDLER_CLASS_ATTRIBUTE_NAME = "binding"; + /** Stores the currently opened editors and their model elements. */ + private final Map<IEditorPart, EObject> currentEditors = new HashMap<IEditorPart, EObject>(); + + /** Stores the command stack registrations. */ + private final Map<EObject, ITopLevelElement> currentCommandStacks = new HashMap<EObject, ITopLevelElement>(); + /** Constructor. */ public ModelEditorBindingService() { super(); @@ -71,15 +89,26 @@ public class ModelEditorBindingService extends return; } try { - PlatformUI + IEditorPart part = PlatformUI .getWorkbench() .getActiveWorkbenchWindow() .getActivePage() .openEditor(new ModelElementEditorInput(element), ExtendableMultiPageEditor.ID); + currentEditors.put(part, element); + // ensure registration with part service + IPartService service = (IPartService) part.getSite().getService( + IPartService.class); + service.addPartListener(this); + // ensure registration with command stack service + ITopLevelElement top = IPersistencyService.INSTANCE + .getTopLevelElementFor(element); + ICommandStackService.INSTANCE.addCommandStackListener(top, this); + currentCommandStacks.put(element, top); } catch (final PartInitException e) { LoggingUtils.error(ToolingKernelActivator.getDefault(), - "Could not open editor with ID " + ExtendableMultiPageEditor.ID, e); + "Could not open editor with ID " + + ExtendableMultiPageEditor.ID, e); } } @@ -126,16 +155,78 @@ public class ModelEditorBindingService extends /** {@inheritDoc} */ @Override - public void closeEditors(EObject rootElement) { - // TODO (FH): implement - - // for (final IEditorPart editor : editors) { - // editor.getSite().getShell().getDisplay().asyncExec(new Runnable() { - // @Override - // public void run() { - // editor.getSite().getPage().closeEditor(editor, false); - // } - // }); - // } + public void closeEditors(EObject parentElement) { + for (IEditorPart editor : currentEditors.keySet()) { + EObject editedElement = currentEditors.get(editor); + if (ModelElementUtils + .isChildElementOf(editedElement, parentElement)) { + closeEditor(editor); + } + } + } + + /** Closes the given editor. */ + private void closeEditor(final IEditorPart editor) { + editor.getSite().getShell().getDisplay().asyncExec(new Runnable() { + @Override + public void run() { + editor.getSite().getPage().closeEditor(editor, false); + } + }); + } + + /** {@inheritDoc} */ + @Override + public void partActivated(IWorkbenchPart part) { + // ignore + } + + /** {@inheritDoc} */ + @Override + public void partBroughtToTop(IWorkbenchPart part) { + // ignore + } + + /** {@inheritDoc} */ + @Override + public void partClosed(IWorkbenchPart part) { + if (currentEditors.containsKey(part)) { + EObject eo = currentEditors.get(part); + ITopLevelElement top = currentCommandStacks.get(eo); + currentCommandStacks.remove(eo); + currentEditors.remove(part); + // clean up command stack registration + for (IEditorPart other : currentEditors.keySet()) { + if (top == currentCommandStacks.get(currentEditors.get(other))) { + return; + } + } + // no other editor references the command stack of top anymore + ICommandStackService.INSTANCE.removeCommandStackListener(top, this); + } + } + + /** {@inheritDoc} */ + @Override + public void partDeactivated(IWorkbenchPart part) { + // ignore + } + + /** {@inheritDoc} */ + @Override + public void partOpened(IWorkbenchPart part) { + // can be ignored + } + + /** {@inheritDoc} */ + @Override + public void commandStackChanged(EventObject event) { + for (IEditorPart part : currentEditors.keySet()) { + ITopLevelElement top = IPersistencyService.INSTANCE + .getTopLevelElementFor(currentEditors.get(part)); + if (top == null) { + closeEditor(part); + } + } } } diff --git a/org.fortiss.tooling.kernel.ui/trunk/src/org/fortiss/tooling/kernel/ui/internal/NavigatorService.java b/org.fortiss.tooling.kernel.ui/trunk/src/org/fortiss/tooling/kernel/ui/internal/NavigatorService.java index a0afd321d..70f481b99 100644 --- a/org.fortiss.tooling.kernel.ui/trunk/src/org/fortiss/tooling/kernel/ui/internal/NavigatorService.java +++ b/org.fortiss.tooling.kernel.ui/trunk/src/org/fortiss/tooling/kernel/ui/internal/NavigatorService.java @@ -114,6 +114,10 @@ public class NavigatorService implements INavigatorService, /** {@inheritDoc} */ @Override public void topLevelElementRemoved(final ITopLevelElement element) { + if (element == null) { + return; + } + new UIJob("NavigatorServiceSafeableRefresh") { @Override public IStatus runInUIThread(IProgressMonitor monitor) { @@ -153,7 +157,9 @@ public class NavigatorService implements INavigatorService, /** {@inheritDoc} */ @Override public void refresh() { - navigatorViewPart.refresh(); + if (navigatorViewPart != null) { + navigatorViewPart.refresh(); + } } /** {@inheritDoc} */ @@ -251,7 +257,7 @@ public class NavigatorService implements INavigatorService, private void saveablesChanged(int event, ITopLevelElement element, boolean force) { Saveable saveable = saveables.get(element); - if (saveable != null) { + if (saveable != null && navigatorViewPart != null) { ISaveablesLifecycleListener listener = (ISaveablesLifecycleListener) PlatformUI .getWorkbench().getService( ISaveablesLifecycleListener.class); diff --git a/org.fortiss.tooling.kernel.ui/trunk/src/org/fortiss/tooling/kernel/ui/service/IModelEditorBindingService.java b/org.fortiss.tooling.kernel.ui/trunk/src/org/fortiss/tooling/kernel/ui/service/IModelEditorBindingService.java index 345350157..681e87e6f 100644 --- a/org.fortiss.tooling.kernel.ui/trunk/src/org/fortiss/tooling/kernel/ui/service/IModelEditorBindingService.java +++ b/org.fortiss.tooling.kernel.ui/trunk/src/org/fortiss/tooling/kernel/ui/service/IModelEditorBindingService.java @@ -32,7 +32,7 @@ import org.fortiss.tooling.kernel.ui.internal.ModelEditorBindingService; * @author hoelzl * @author $Author$ * @version $Rev$ - * @ConQAT.Rating GREEN Hash: 820B5843566C65139914E39B21E01710 + * @ConQAT.Rating GREEN Hash: 6A80D8ED088608C52D21BC3F4B73BE8B */ public interface IModelEditorBindingService { @@ -43,7 +43,7 @@ public interface IModelEditorBindingService { void openInEditor(EObject element); /** Closes editors which depend on the given element or a sub-element. */ - void closeEditors(EObject rootElement); + void closeEditors(EObject parentElement); /** Returns registered editor bindings for the given {@link EObject}. */ List<IModelEditorBinding<EObject>> getBindings(EObject element); diff --git a/org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/extension/data/ITopLevelElement.java b/org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/extension/data/ITopLevelElement.java index db8b1de6b..02f9d5498 100644 --- a/org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/extension/data/ITopLevelElement.java +++ b/org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/extension/data/ITopLevelElement.java @@ -40,7 +40,7 @@ import org.fortiss.tooling.kernel.extension.IStorageProvider; * @author hoelzl * @author $Author$ * @version $Rev$ - * @ConQAT.Rating GREEN Hash: 85B4A36E3F052F4BED404969E3CDB7B0 + * @ConQAT.Rating GREEN Hash: 627F8F0B59A57FB8FE9CD20F70C02C7F */ public interface ITopLevelElement { @@ -50,7 +50,10 @@ public interface ITopLevelElement { /** Executes the given {@link Runnable} as model changing command. */ void runAsCommand(Runnable runner); - /** Adds a command stack listener. */ + /** + * Adds a command stack listener. Has no effect if an identical listener is + * already registered. + */ void addCommandStackListener(CommandStackListener listener); /** Removes the command stack listener. */ diff --git a/org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/internal/CommandStackService.java b/org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/internal/CommandStackService.java index 4e56d142a..2b01546bd 100644 --- a/org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/internal/CommandStackService.java +++ b/org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/internal/CommandStackService.java @@ -41,14 +41,23 @@ public class CommandStackService implements ICommandStackService { @Override public void addCommandStackListener(ITopLevelElement target, CommandStackListener listener) { - target.addCommandStackListener(listener); + if (target != null) { + target.addCommandStackListener(listener); + } } /** {@inheritDoc} */ @Override public void removeCommandStackListener(ITopLevelElement target, CommandStackListener listener) { - target.removeCommandStackListener(listener); + if (target != null) { + target.removeCommandStackListener(listener); + } else { + for (ITopLevelElement top : IPersistencyService.INSTANCE + .getTopLevelElements()) { + top.removeCommandStackListener(listener); + } + } } /** {@inheritDoc} */ diff --git a/org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/internal/storage/eclipse/ModelContext.java b/org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/internal/storage/eclipse/ModelContext.java index e2eeb0d5e..7b609da21 100644 --- a/org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/internal/storage/eclipse/ModelContext.java +++ b/org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/internal/storage/eclipse/ModelContext.java @@ -109,7 +109,9 @@ class ModelContext implements ITopLevelElement, CommandStackListener { /** {@inheritDoc} */ @Override public void addCommandStackListener(CommandStackListener listener) { - listeners.add(listener); + if (!listeners.contains(listener)) { + listeners.add(listener); + } } /** {@inheritDoc} */ diff --git a/org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/service/ICommandStackService.java b/org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/service/ICommandStackService.java index d0077d5d8..350d3f39d 100644 --- a/org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/service/ICommandStackService.java +++ b/org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/service/ICommandStackService.java @@ -46,7 +46,8 @@ public interface ICommandStackService { /** * Removes the command stack listener from the stack of the given target - * element. + * element. If the target element is <code>null</code> the listener is + * removed from all current command stacks. */ void removeCommandStackListener(ITopLevelElement target, CommandStackListener listener); diff --git a/org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/utils/ProjectRootElementUtils.java b/org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/utils/ModelElementUtils.java similarity index 90% rename from org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/utils/ProjectRootElementUtils.java rename to org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/utils/ModelElementUtils.java index 0456bd9d5..ad818bd2b 100644 --- a/org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/utils/ProjectRootElementUtils.java +++ b/org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/utils/ModelElementUtils.java @@ -36,7 +36,7 @@ import org.fortiss.tooling.kernel.service.IPersistencyService; * @version $Rev$ * @ConQAT.Rating GREEN Hash: AA5BFF29ABFE9DEB170DB51BDB3B5427 */ -public final class ProjectRootElementUtils { +public final class ModelElementUtils { /** * Returns the instance of a project root element corresponding to the given @@ -103,4 +103,19 @@ public final class ProjectRootElementUtils { } return null; } + + /** + * Determines if the given element is an indirect child of the given parent + * element. + */ + public static boolean isChildElementOf(EObject element, + EObject parentElement) { + while (element.eContainer() != null) { + if (element.eContainer() == parentElement) { + return true; + } + element = element.eContainer(); + } + return false; + } } -- GitLab