From 56fb6afde0bc9ec9d19cded28365aea66ba48f78 Mon Sep 17 00:00:00 2001 From: Florian Hoelzl <hoelzl@fortiss.org> Date: Mon, 14 Nov 2011 16:14:34 +0000 Subject: [PATCH] Fixed save button behavior. refs 151 --- .../kernel/ui/internal/ActionService.java | 15 ++-- .../kernel/ui/internal/NavigatorService.java | 77 +++++++++++++++---- .../ui/internal/editor/BindingEditor.java | 19 +++-- .../ui/internal/views/NavigatorViewPart.java | 2 +- .../kernel/internal/CommandStackService.java | 19 +++++ .../storage/eclipse/ModelContext.java | 45 +++++------ .../kernel/service/ICommandStackService.java | 11 +++ 7 files changed, 136 insertions(+), 52 deletions(-) diff --git a/org.fortiss.tooling.kernel.ui/trunk/src/org/fortiss/tooling/kernel/ui/internal/ActionService.java b/org.fortiss.tooling.kernel.ui/trunk/src/org/fortiss/tooling/kernel/ui/internal/ActionService.java index 766d98923..cd52e45fa 100644 --- a/org.fortiss.tooling.kernel.ui/trunk/src/org/fortiss/tooling/kernel/ui/internal/ActionService.java +++ b/org.fortiss.tooling.kernel.ui/trunk/src/org/fortiss/tooling/kernel/ui/internal/ActionService.java @@ -25,6 +25,7 @@ import org.eclipse.jface.action.IMenuManager; import org.eclipse.ui.IActionBars; import org.eclipse.ui.actions.ActionFactory; 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.listener.IPersistencyServiceListener; import org.fortiss.tooling.kernel.ui.internal.actions.DeleteAction; @@ -64,7 +65,7 @@ public class ActionService implements IActionService, for (ITopLevelElement context : IPersistencyService.INSTANCE .getTopLevelElements()) { - context.addCommandStackListener(this); + topLevelElementAdded(context); } IPersistencyService.INSTANCE.addTopLevelElementListener(this); } @@ -114,19 +115,21 @@ public class ActionService implements IActionService, /** {@inheritDoc} */ @Override - public void topLevelElementAdded(ITopLevelElement elementContext) { - elementContext.addCommandStackListener(this); + public void topLevelElementAdded(ITopLevelElement element) { + ICommandStackService.INSTANCE.addCommandStackListener( + element.getRootModelElement(), this); } /** {@inheritDoc} */ @Override - public void topLevelElementRemoved(ITopLevelElement elementContext) { - elementContext.removeCommandStackListener(this); + public void topLevelElementRemoved(ITopLevelElement element) { + ICommandStackService.INSTANCE.removeCommandStackListener( + element.getRootModelElement(), this); } /** {@inheritDoc} */ @Override public void topLevelElementChanged(ITopLevelElement element) { - // ignore these changes + // TODO (FH): ignore these changes? } } 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 7fefd2cd0..963a0eebd 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 @@ -20,9 +20,7 @@ package org.fortiss.tooling.kernel.ui.internal; import java.io.IOException; import java.util.EventObject; import java.util.HashMap; -import java.util.HashSet; import java.util.Map; -import java.util.Set; import org.conqat.ide.commons.ui.logging.LoggingUtils; import org.eclipse.core.runtime.CoreException; @@ -31,15 +29,18 @@ import org.eclipse.emf.common.command.CommandStackListener; import org.eclipse.emf.ecore.EObject; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.ISelection; +import org.eclipse.ui.ISaveablesLifecycleListener; +import org.eclipse.ui.PlatformUI; import org.eclipse.ui.Saveable; +import org.eclipse.ui.SaveablesLifecycleEvent; 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.listener.IPersistencyServiceListener; import org.fortiss.tooling.kernel.ui.extension.data.ContextMenuContextProvider; import org.fortiss.tooling.kernel.ui.internal.views.NavigatorViewPart; import org.fortiss.tooling.kernel.ui.service.INavigatorService; -import org.fortiss.tooling.kernel.ui.util.EObjectSelectionUtils; /** * This class implements the {@link INavigatorService} interface. @@ -62,7 +63,8 @@ public class NavigatorService implements INavigatorService, public NavigatorService() { for (ITopLevelElement element : IPersistencyService.INSTANCE .getTopLevelElements()) { - element.addCommandStackListener(this); + ICommandStackService.INSTANCE.addCommandStackListener( + element.getRootModelElement(), this); saveables.put(element, new TopLevelElementSaveable(element)); } IPersistencyService.INSTANCE.addTopLevelElementListener(this); @@ -93,30 +95,37 @@ public class NavigatorService implements INavigatorService, /** {@inheritDoc} */ @Override - public void topLevelElementAdded(ITopLevelElement context) { - context.addCommandStackListener(this); - saveables.put(context, new TopLevelElementSaveable(context)); + public void topLevelElementAdded(ITopLevelElement element) { + element.addCommandStackListener(this); + saveables.put(element, new TopLevelElementSaveable(element)); + notifySaveablesPostOpen(element); refresh(); } /** {@inheritDoc} */ @Override - public void topLevelElementRemoved(ITopLevelElement context) { - context.removeCommandStackListener(this); - saveables.remove(context); + public void topLevelElementRemoved(ITopLevelElement element) { + notifySaveablesPreClose(element); + element.removeCommandStackListener(this); + saveables.remove(element); + notifySaveablesPostClose(element); refresh(); } /** {@inheritDoc} */ @Override public void topLevelElementChanged(ITopLevelElement element) { - // ignore this, {@link MarkerService} will call refresh() + notifySaveablesDirtyChanged(element); + refresh(); // TODO: does {@link MarkerService} call refresh? which method? } /** {@inheritDoc} */ @Override public void commandStackChanged(EventObject event) { + if (event.getSource() instanceof ITopLevelElement) { + notifySaveablesDirtyChanged((ITopLevelElement) event.getSource()); + } refresh(); } @@ -135,16 +144,15 @@ public class NavigatorService implements INavigatorService, /** {@inheritDoc} */ @Override public Saveable[] getActiveSaveables() { - Set<Saveable> result = new HashSet<Saveable>(); - for (EObject selection : EObjectSelectionUtils - .getCurrentSelectionEObjects()) { + EObject selection = navigatorViewPart.getSelectedModelElement(); + if (selection != null) { ITopLevelElement context = IPersistencyService.INSTANCE .getTopLevelElementFor(selection); if (saveables.get(context) != null) { - result.add(saveables.get(context)); + return new Saveable[] { saveables.get(context) }; } } - return result.toArray(new Saveable[result.size()]); + return new Saveable[0]; } /** @@ -214,4 +222,41 @@ public class NavigatorService implements INavigatorService, public void revealModelElement(EObject modelElement) { navigatorViewPart.revealModelElement(modelElement); } + + /** + * Notify {@link ISaveablesLifecycleListener} about saveable change of given + * top-level element. + */ + private void saveablesChanged(int event, ITopLevelElement element) { + Saveable saveable = saveables.get(element); + if (saveable != null) { + ISaveablesLifecycleListener listener = (ISaveablesLifecycleListener) PlatformUI + .getWorkbench().getService( + ISaveablesLifecycleListener.class); + SaveablesLifecycleEvent eventObj = new SaveablesLifecycleEvent( + navigatorViewPart, event, new Saveable[] { saveable }, + false); + listener.handleLifecycleEvent(eventObj); + } + } + + /** Post {@link SaveablesLifecycleEvent#POST_OPEN}. */ + private void notifySaveablesPostOpen(ITopLevelElement element) { + saveablesChanged(SaveablesLifecycleEvent.POST_OPEN, element); + } + + /** Post {@link SaveablesLifecycleEvent#POST_CLOSE}. */ + private void notifySaveablesPostClose(ITopLevelElement element) { + saveablesChanged(SaveablesLifecycleEvent.POST_CLOSE, element); + } + + /** Post {@link SaveablesLifecycleEvent#PRE_CLOSE}. */ + private void notifySaveablesPreClose(ITopLevelElement element) { + saveablesChanged(SaveablesLifecycleEvent.PRE_CLOSE, element); + } + + /** Post {@link SaveablesLifecycleEvent#DIRTY_CHANGED}. */ + private void notifySaveablesDirtyChanged(ITopLevelElement element) { + saveablesChanged(SaveablesLifecycleEvent.DIRTY_CHANGED, element); + } } diff --git a/org.fortiss.tooling.kernel.ui/trunk/src/org/fortiss/tooling/kernel/ui/internal/editor/BindingEditor.java b/org.fortiss.tooling.kernel.ui/trunk/src/org/fortiss/tooling/kernel/ui/internal/editor/BindingEditor.java index eb9529276..007bf67f4 100644 --- a/org.fortiss.tooling.kernel.ui/trunk/src/org/fortiss/tooling/kernel/ui/internal/editor/BindingEditor.java +++ b/org.fortiss.tooling.kernel.ui/trunk/src/org/fortiss/tooling/kernel/ui/internal/editor/BindingEditor.java @@ -36,6 +36,9 @@ import org.eclipse.ui.views.properties.IPropertySheetPage; import org.eclipse.ui.views.properties.tabbed.ITabbedPropertySheetPageContributor; import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage; 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.ui.extension.IModelEditorBinding; import org.fortiss.tooling.kernel.ui.extension.IModelElementHandler; import org.fortiss.tooling.kernel.ui.listener.IBindingEditorPageChangeListener; @@ -52,7 +55,7 @@ import org.fortiss.tooling.kernel.ui.service.IPropertiesService; * @author hoelzlf * @author $Author$ * @version $Rev$ - * @ConQAT.Rating RED Hash: E92400B5E205A0DEA761AE960FA9C463 + * @ConQAT.Rating YELLOW Hash: 1924980FA5DF4510707A559F25799E8A */ public class BindingEditor extends MultiPageEditorPart implements ITabbedPropertySheetPageContributor { @@ -174,13 +177,20 @@ public class BindingEditor extends MultiPageEditorPart implements /** {@inheritDoc} */ @Override public void doSave(IProgressMonitor monitor) { - // TODO (FH): implement issue 151 + ITopLevelElement topElement = IPersistencyService.INSTANCE + .getTopLevelElementFor(editedObject); + try { + topElement.doSave(monitor); + } catch (Exception e) { + LoggingUtils.error(ToolingKernelActivator.getDefault(), + "Error during save of " + topElement.getSaveableName(), e); + } } /** {@inheritDoc} */ @Override public void doSaveAs() { - // TODO (FH): implement issue 151 + // not needed } /** {@inheritDoc} */ @@ -193,8 +203,7 @@ public class BindingEditor extends MultiPageEditorPart implements /** {@inheritDoc} */ @Override public boolean isDirty() { - // TODO (FH): implement issue 151 - return false; + return ICommandStackService.INSTANCE.isDirty(editedObject); } /** {@inheritDoc} */ diff --git a/org.fortiss.tooling.kernel.ui/trunk/src/org/fortiss/tooling/kernel/ui/internal/views/NavigatorViewPart.java b/org.fortiss.tooling.kernel.ui/trunk/src/org/fortiss/tooling/kernel/ui/internal/views/NavigatorViewPart.java index fe47cf1dd..2b12e05e7 100644 --- a/org.fortiss.tooling.kernel.ui/trunk/src/org/fortiss/tooling/kernel/ui/internal/views/NavigatorViewPart.java +++ b/org.fortiss.tooling.kernel.ui/trunk/src/org/fortiss/tooling/kernel/ui/internal/views/NavigatorViewPart.java @@ -180,7 +180,6 @@ public final class NavigatorViewPart extends ViewPart implements ToolingKernelUIActivator.getDefault().getDialogSettings() .put(LINK_WITH_EDITOR_FLAG, this.isChecked()); } - }; linkWithEditorAction.setImageDescriptor(ToolingKernelUIActivator @@ -236,6 +235,7 @@ public final class NavigatorViewPart extends ViewPart implements @Override public void selectionChanged(SelectionChangedEvent event) { IActionService.INSTANCE.refresh(); + firePropertyChange(IWorkbenchPartConstants.PROP_DIRTY); } /** {@inheritDoc} */ 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 8e2a6eb1c..af6934ac9 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 @@ -18,6 +18,7 @@ $Id$ package org.fortiss.tooling.kernel.internal; import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.emf.common.command.CommandStackListener; import org.eclipse.emf.ecore.EObject; import org.fortiss.tooling.kernel.ToolingKernelActivator; import org.fortiss.tooling.kernel.extension.data.ITopLevelElement; @@ -36,6 +37,24 @@ import org.fortiss.tooling.kernel.utils.LoggingUtils; */ public class CommandStackService implements ICommandStackService { + /** {@inheritDoc} */ + @Override + public void addCommandStackListener(EObject target, + CommandStackListener listener) { + ITopLevelElement context = IPersistencyService.INSTANCE + .getTopLevelElementFor(target); + context.addCommandStackListener(listener); + } + + /** {@inheritDoc} */ + @Override + public void removeCommandStackListener(EObject target, + CommandStackListener listener) { + ITopLevelElement context = IPersistencyService.INSTANCE + .getTopLevelElementFor(target); + context.removeCommandStackListener(listener); + } + /** {@inheritDoc} */ @Override public void runAsCommand(EObject target, Runnable runner) { 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 065ee0bdf..f154cc25c 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 @@ -21,8 +21,11 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.lang.reflect.Method; +import java.util.EventObject; import java.util.HashSet; import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; import java.util.Set; import org.eclipse.core.resources.IFile; @@ -36,7 +39,6 @@ import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.ResourceSet; -import org.eclipse.emf.transaction.TransactionalCommandStack; import org.eclipse.emf.transaction.TransactionalEditingDomain; import org.fortiss.tooling.kernel.ToolingKernelActivator; import org.fortiss.tooling.kernel.extension.data.ITopLevelElement; @@ -54,7 +56,7 @@ import org.fortiss.tooling.kernel.utils.LoggingUtils; * @version $Rev$ * @ConQAT.Rating GREEN Hash: AAAEB5802D74F212F47C25AD613B97CF */ -class ModelContext implements ITopLevelElement { +class ModelContext implements ITopLevelElement, CommandStackListener { /** The resource set we are using. */ private final ResourceSet rset; @@ -71,6 +73,9 @@ class ModelContext implements ITopLevelElement { /** The transactional command stack. */ private final AutoUndoCommandStack transactionalCommandStack; + /** Stores the command stack listener for this context. */ + private final List<CommandStackListener> listeners = new LinkedList<CommandStackListener>(); + /** Flag for remembering whether the last change of the file was intended. */ private boolean lastChangeWasIntended = false; @@ -90,6 +95,7 @@ class ModelContext implements ITopLevelElement { r.load(EMFResourceUtils.buildOptionsMap()); transactionalCommandStack = new AutoUndoCommandStack(editingDomain); + transactionalCommandStack.addCommandStackListener(this); checkIDs(); } @@ -103,13 +109,13 @@ class ModelContext implements ITopLevelElement { /** {@inheritDoc} */ @Override public void addCommandStackListener(CommandStackListener listener) { - transactionalCommandStack.addCommandStackListener(listener); + listeners.add(listener); } /** {@inheritDoc} */ @Override public void removeCommandStackListener(CommandStackListener listener) { - transactionalCommandStack.removeCommandStackListener(listener); + listeners.remove(listener); } /** Checks whether all IDs are present and updates {@link #maxId}. */ @@ -203,7 +209,8 @@ class ModelContext implements ITopLevelElement { public void destroy() { // discard changes ((BasicCommandStack) editingDomain.getCommandStack()).saveIsDone(); - + // TODO (FH): close editors + transactionalCommandStack.removeCommandStackListener(this); } /** Returns the file associated with this model. */ @@ -265,25 +272,6 @@ class ModelContext implements ITopLevelElement { lastChangeWasIntended = true; } - /** - * Returns the editing domain of this model's context. Note that the command - * stack contained in the returned editing domain is raw (i.e. does not deal - * with transactions). Usually you should use the command stack returned - * from {@link #getTransactionalCommandStack()}, unless you know what you - * are doing. - */ - public TransactionalEditingDomain getEditingDomain() { - return editingDomain; - } - - /** - * Returns the command stack to be used, which automatically wraps all - * commands in a transaction and provides easy undo/redo. - */ - public TransactionalCommandStack getTransactionalCommandStack() { - return transactionalCommandStack; - } - /** Runs the given runnable as a command. */ @Override public void runAsCommand(final Runnable runnable) { @@ -348,4 +336,13 @@ class ModelContext implements ITopLevelElement { public String getSaveableName() { return getFile().getName(); } + + /** {@inheritDoc} */ + @Override + public void commandStackChanged(EventObject event) { + EventObject relayEvent = new EventObject(this); + for (CommandStackListener l : listeners) { + l.commandStackChanged(relayEvent); + } + } } 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 0d8f6b778..0752e5af2 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 @@ -18,6 +18,7 @@ $Id$ package org.fortiss.tooling.kernel.service; import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.emf.common.command.CommandStackListener; import org.eclipse.emf.ecore.EObject; import org.fortiss.tooling.kernel.internal.CommandStackService; @@ -38,6 +39,16 @@ public interface ICommandStackService { /** Returns the singleton instance of the service. */ public static final ICommandStackService INSTANCE = new CommandStackService(); + /** Adds a command stack listener to the stack of the given target element. */ + void addCommandStackListener(EObject target, CommandStackListener listener); + + /** + * Removes the command stack listener from the stack of the given target + * element. + */ + void removeCommandStackListener(EObject target, + CommandStackListener listener); + /** Runs the given {@link Runnable} within a emfStore transaction. */ void runAsCommand(EObject target, Runnable runner); -- GitLab