Explorar o código

Refactoring due to model changes.
Added lockable undo/redo actions .

markus.muehlbrandt@itemis.de %!s(int64=14) %!d(string=hai) anos
pai
achega
0a7a40a458

+ 2 - 1
de.itemis.gmf.utils/plugins/de.itemis.gmf.runtime.commons/META-INF/MANIFEST.MF

@@ -14,7 +14,8 @@ Require-Bundle: org.eclipse.gmf.runtime.diagram.ui.properties;bundle-version="1.
  org.eclipse.jface.databinding;bundle-version="1.5.0";visibility:=reexport,
  org.eclipse.core.databinding.property;bundle-version="1.4.0";visibility:=reexport,
  org.eclipse.emf.databinding.edit;bundle-version="1.2.0";visibility:=reexport
-Export-Package: de.itemis.gmf.runtime.commons.commands,
+Export-Package: de.itemis.gmf.runtime.commons.actions,
+ de.itemis.gmf.runtime.commons.commands,
  de.itemis.gmf.runtime.commons.editparts,
  de.itemis.gmf.runtime.commons.editpolicies,
  de.itemis.gmf.runtime.commons.figures,

+ 57 - 0
de.itemis.gmf.utils/plugins/de.itemis.gmf.runtime.commons/src/de/itemis/gmf/runtime/commons/actions/GlobalUndoRedoLock.java

@@ -0,0 +1,57 @@
+package de.itemis.gmf.runtime.commons.actions;
+
+/**
+ * Copied from
+ * org.eclipse.gmf.runtime.common.ui.action.actions.global.GlobalUndoRedoLock
+ * because of visibility restrictions.
+ * 
+ */
+public class GlobalUndoRedoLock {
+	/**
+	 * Lock instance.
+	 */
+	public static final GlobalUndoRedoLock INSTANCE = new GlobalUndoRedoLock();
+
+	/**
+	 * The locking object.
+	 */
+	private Object owner = null;
+	
+	/**
+	 * Private constructor.
+	 */
+	private GlobalUndoRedoLock() {
+		// private
+	}
+
+	/**
+	 * Acquires the lock if the lock is free and returns true, otherwise false.
+	 * 
+	 * @param key the key Object which can release the lock.
+	 * @return <code>true</code> if lock acquired, otherwise <code>false</code>
+	 */
+	synchronized boolean acquire(Object key) {
+		if (owner == null) {
+			owner = key;
+			return true;
+		}
+		return false;
+	}
+	
+	/**
+	 * Releases the lock if the key is correct. If the key is incorrect,
+	 * then an IllegalArgumentException is thrown.
+	 * 
+	 * @param key the key which acquired the lock
+	 */
+	synchronized void release(Object key) {
+		if (owner == key) {
+			owner = null;
+			return;
+		}
+		if (owner == null) {
+			return;
+		}
+		throw new IllegalArgumentException("Unable to release lock, incorrect key."); //$NON-NLS-1$
+	}
+}

+ 6 - 0
de.itemis.gmf.utils/plugins/de.itemis.gmf.runtime.commons/src/de/itemis/gmf/runtime/commons/actions/ILockableAction.java

@@ -0,0 +1,6 @@
+package de.itemis.gmf.runtime.commons.actions;
+
+public interface ILockableAction {
+
+	public void setLocked(Boolean lock);
+}

+ 44 - 0
de.itemis.gmf.utils/plugins/de.itemis.gmf.runtime.commons/src/de/itemis/gmf/runtime/commons/actions/LockableGlobalRedoAction.java

@@ -0,0 +1,44 @@
+package de.itemis.gmf.runtime.commons.actions;
+
+import org.eclipse.core.commands.operations.IUndoContext;
+import org.eclipse.gmf.runtime.common.ui.action.global.GlobalActionId;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchPartSite;
+import org.eclipse.ui.operations.OperationHistoryActionHandler;
+import org.eclipse.ui.operations.RedoActionHandler;
+
+import de.itemis.gmf.runtime.commons.actions.LockableGlobalUndoRedoAction;
+
+public class LockableGlobalRedoAction extends LockableGlobalUndoRedoAction {
+
+	/**
+	 * Initializes me with a workbench page.
+	 * 
+	 * @param workbenchPage
+	 *            the page
+	 */
+	public LockableGlobalRedoAction(IWorkbenchPage workbenchPage) {
+		super(workbenchPage);
+	}
+
+	/**
+	 * Initializes me with a workbench part.
+	 * 
+	 * @param workbenchPart
+	 *            the part
+	 */
+	public LockableGlobalRedoAction(IWorkbenchPart workbenchPart) {
+		super(workbenchPart);
+	}
+
+	public String getActionId() {
+		return GlobalActionId.REDO;
+	}
+
+	@Override
+	protected OperationHistoryActionHandler getOperationHistoryActionHandler(
+			IWorkbenchPartSite site, IUndoContext context) {
+		return new RedoActionHandler(site, context);
+	}
+}

+ 44 - 0
de.itemis.gmf.utils/plugins/de.itemis.gmf.runtime.commons/src/de/itemis/gmf/runtime/commons/actions/LockableGlobalUndoAction.java

@@ -0,0 +1,44 @@
+package de.itemis.gmf.runtime.commons.actions;
+
+import org.eclipse.core.commands.operations.IUndoContext;
+import org.eclipse.gmf.runtime.common.ui.action.global.GlobalActionId;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchPartSite;
+import org.eclipse.ui.operations.OperationHistoryActionHandler;
+import org.eclipse.ui.operations.UndoActionHandler;
+
+import de.itemis.gmf.runtime.commons.actions.LockableGlobalUndoRedoAction;
+
+public class LockableGlobalUndoAction extends LockableGlobalUndoRedoAction {
+	
+	/**
+	 * Initializes me with a workbench page.
+	 * 
+	 * @param workbenchPage
+	 *            the page
+	 */
+	public LockableGlobalUndoAction(IWorkbenchPage workbenchPage) {
+		super(workbenchPage);
+	}
+
+	/**
+	 * Initializes me with a workbench part.
+	 * 
+	 * @param workbenchPart
+	 *            the part
+	 */
+	public LockableGlobalUndoAction(IWorkbenchPart workbenchPart) {
+		super(workbenchPart);
+	}
+
+	public String getActionId() {
+		return GlobalActionId.UNDO;
+	}
+
+	@Override
+	protected OperationHistoryActionHandler getOperationHistoryActionHandler(
+			IWorkbenchPartSite site, IUndoContext context) {
+		return new UndoActionHandler(site, context);
+	}
+}

+ 311 - 0
de.itemis.gmf.utils/plugins/de.itemis.gmf.runtime.commons/src/de/itemis/gmf/runtime/commons/actions/LockableGlobalUndoRedoAction.java

@@ -0,0 +1,311 @@
+package de.itemis.gmf.runtime.commons.actions;
+
+import org.eclipse.core.commands.operations.IUndoContext;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.gmf.runtime.common.ui.action.global.GlobalAction;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchPartSite;
+import org.eclipse.ui.operations.OperationHistoryActionHandler;
+
+import de.itemis.gmf.runtime.commons.actions.ILockableAction;
+
+/**
+ * Code is based on {@link GlobalUndoAction} and {@link GlobalRedoAction} merged
+ * to an abstract class to avoid duplicate code and extended to deal with
+ * editors which support yakindu simulation.
+ * 
+ * @author muehlbrandt
+ * 
+ */
+public abstract class LockableGlobalUndoRedoAction extends GlobalAction implements ILockableAction {
+
+	/**
+	 * My operation framework action handler delegate.
+	 */
+	private OperationHistoryActionHandler delegate;
+
+	/**
+	 * My undo context.
+	 */
+	private IUndoContext undoContext;
+
+	/**
+	 * Property change listener to listen for changes in my delegate.
+	 */
+	private IPropertyChangeListener listener;
+
+	/**
+	 * Flag to block the execution of this action if simulation is enabled
+	 */
+	private boolean isLocked = false;
+	
+	/**
+	 * Initializes me with a workbench page.
+	 * 
+	 * @param workbenchPage
+	 *            the page
+	 */
+	
+	public LockableGlobalUndoRedoAction(IWorkbenchPage workbenchPage) {
+		super(workbenchPage);
+	}
+
+	/**
+	 * Initilizes me with a workbench part.
+	 * 
+	 * @param workbenchPart
+	 *            the part
+	 */
+	public LockableGlobalUndoRedoAction(IWorkbenchPart workbenchPart) {
+		super(workbenchPart);
+	}
+
+	/**
+	 * Extends the superclass implementation to update the operation history
+	 * undo action handler to which I delegate.
+	 */
+	protected void setWorkbenchPart(IWorkbenchPart workbenchPart) {
+		super.setWorkbenchPart(workbenchPart);
+		initializeWithContext(getUndoContext());
+	}
+	
+	protected abstract OperationHistoryActionHandler getOperationHistoryActionHandler(IWorkbenchPartSite site, IUndoContext context);
+	
+    /**
+     * Initializes me with a new undo <code>context</code>.
+     * 
+     * @param context
+     *            the undo context
+     */
+    protected void initializeWithContext(IUndoContext context) {
+		if (delegate != null) {
+			delegate.removePropertyChangeListener(getDelegateListener());
+			delegate.dispose();
+			delegate = null;
+		}
+
+		if (context != null) {
+			IWorkbenchPart part = getWorkbenchPart();
+
+			if (part != null) {
+				delegate = getOperationHistoryActionHandler(part.getSite(), context);
+				delegate.setPruneHistory(true);
+				delegate.addPropertyChangeListener(getDelegateListener());
+			}
+		}
+		
+		// force enablement update in UI
+		boolean enabled = isEnabled();
+		firePropertyChange(IAction.ENABLED, Boolean.valueOf(!enabled), Boolean
+				.valueOf(enabled));
+    }
+
+	/**
+	 * Gets my property change listener to listen for changes in my delegate.
+	 */
+	private IPropertyChangeListener getDelegateListener() {
+		if (listener == null) {
+			listener = new IPropertyChangeListener() {
+
+				public void propertyChange(PropertyChangeEvent event) {
+					// propagate to my own listeners
+					firePropertyChange(event.getProperty(),
+							event.getOldValue(), event.getNewValue());
+				}
+			};
+		}
+		return listener;
+	}
+
+	/**
+	 * Delegates to the operation framework action handler.
+	 */
+	public ImageDescriptor getImageDescriptor() {
+		if (delegate != null) {
+			return delegate.getImageDescriptor();
+		} else {
+			return null;
+		}
+	}
+
+	/**
+	 * Delegates to the operation framework action handler.
+	 */
+	public ImageDescriptor getDisabledImageDescriptor() {
+		if (delegate != null) {
+			return delegate.getDisabledImageDescriptor();
+		} else {
+			return null;
+		}
+	}
+
+	/**
+	 * Delegates to the operation framework action handler.
+	 */
+	public ImageDescriptor getHoverImageDescriptor() {
+		if (delegate != null) {
+			return delegate.getHoverImageDescriptor();
+		} else {
+			return null;
+		}
+	}
+
+	/**
+	 * Delegates to the operation framework action handler.
+	 */
+	public String getText() {
+		if (delegate != null) {
+			return delegate.getText();
+		} else {
+			return null;
+		}
+	}
+
+	/**
+	 * Delegates to the operation framework action handler.
+	 */
+	public String getToolTipText() {
+		if (delegate != null) {
+			return delegate.getToolTipText();
+		} else {
+			return null;
+		}
+	}
+
+	/**
+	 * Delegates to the operation framework action handler.
+	 */
+	public String getDescription() {
+		if (delegate != null) {
+			return delegate.getDescription();
+		} else {
+			return null;
+		}
+	}
+
+	/**
+	 * Delegates to the operation framework action handler.
+	 */
+	public boolean isEnabled() {
+		if (delegate != null) {
+			return delegate.isEnabled();
+		}
+		return false;
+	}
+
+	/**
+	 * Delegates to the operation framework action handler.
+	 */
+	public boolean isHandled() {
+		if (delegate != null) {
+			return delegate.isHandled();
+		} else {
+			return false;
+		}
+	}
+
+	/**
+	 * Delegates to the operation framework action handler.
+	 */
+	public void setChecked(boolean checked) {
+		if (delegate != null) {
+			delegate.setChecked(checked);
+		}
+	}
+
+	/**
+	 * Delegates to the operation framework action handler.
+	 */
+	protected void doRun(IProgressMonitor progressMonitor) {
+		if (delegate != null && !isLocked) {
+			Object key = new Object();
+			if (GlobalUndoRedoLock.INSTANCE.acquire(key)) {
+				try {
+					delegate.run();
+				} finally {
+					GlobalUndoRedoLock.INSTANCE.release(key);
+				}
+			}
+		}
+	}
+
+	/**
+	 * Delegates to the operation framework action handler.
+	 */
+	public void refresh() {
+		if (delegate != null) {
+			delegate.update();
+		}
+		setText(getText());
+	}
+
+	/**
+	 * Sets my undo context.
+	 * 
+	 * @param undoContext
+	 *            my undo context
+	 */
+	public final void setUndoContext(IUndoContext context) {
+		this.undoContext = context;
+		initializeWithContext(context);
+	}
+
+	/**
+	 * Gets my undo context. If it has not been explicitly set, derives the undo
+	 * context from my workbench part.
+	 * 
+	 * @return my undo context. May be <code>null</code> if no one has set my
+	 *         undo context and my workbench part does not adapt to
+	 *         {@link IUndoContext}.
+	 */
+	public final IUndoContext getUndoContext() {
+
+		if (undoContext == null) {
+			IWorkbenchPart part = getWorkbenchPart();
+
+			if (part != null) {
+				return (IUndoContext) part.getAdapter(IUndoContext.class);
+			}
+		}
+		return undoContext;
+	}
+
+	/**
+	 * Listens to the operation history events.
+	 */
+	protected boolean isOperationHistoryListener() {
+		return true;
+	}
+
+    /**
+     * Sets my delegate to <code>null</code>.
+     */
+	public void dispose() {
+
+		if (delegate != null) {
+            // Doesn't call delegate.dispose() because the delegate is itself a
+            // part listener and will dispose of itself when its part closes.
+            // See https://bugs.eclipse.org/bugs/show_bug.cgi?id=131781
+			delegate.removePropertyChangeListener(getDelegateListener());
+			delegate = null;
+		}
+
+		super.dispose();
+	}
+	
+	/**
+	 * No work indicator type since my delegate takes care of showing progress.
+	 */
+	public WorkIndicatorType getWorkIndicatorType() {
+		return WorkIndicatorType.NONE;
+	}
+
+	public void setLocked(Boolean lock) {
+		isLocked = lock;
+	}
+}

+ 58 - 3
de.itemis.gmf.utils/plugins/de.itemis.gmf.runtime.commons/src/de/itemis/gmf/runtime/commons/highlighting/HighlightingSupportAdapter.java

@@ -2,6 +2,7 @@ package de.itemis.gmf.runtime.commons.highlighting;
 
 import java.lang.reflect.Method;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -18,12 +19,18 @@ import org.eclipse.gmf.runtime.diagram.ui.figures.BorderedNodeFigure;
 import org.eclipse.gmf.runtime.diagram.ui.parts.IDiagramWorkbenchPart;
 import org.eclipse.gmf.runtime.diagram.ui.resources.editor.parts.DiagramDocumentEditor;
 import org.eclipse.gmf.runtime.gef.ui.figures.DefaultSizeNodeFigure;
+import org.eclipse.jface.action.IAction;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.graphics.Color;
 import org.eclipse.swt.graphics.Image;
 import org.eclipse.swt.graphics.ImageData;
 import org.eclipse.swt.graphics.PaletteData;
 import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.actions.ActionFactory;
+
+import de.itemis.gmf.runtime.commons.actions.ILockableAction;
 
 /**
  * 
@@ -96,6 +103,13 @@ public class HighlightingSupportAdapter implements IHighlightingSupport {
 	private final Map<Color, Color> greyscaleColors = new HashMap<Color, Color>();
 	private boolean locked = false;
 	private final IDiagramWorkbenchPart diagramWorkbenchPart;
+	
+	private static String[] GLOBAL_ACTION_IDS = { 
+		ActionFactory.UNDO.getId(),
+		ActionFactory.REDO.getId() 
+	};
+	
+	//private Map<String,Boolean> globalActionStates = new HashMap<String, Boolean>();
 
 	public HighlightingSupportAdapter(IDiagramWorkbenchPart diagramWorkbenchPart) {
 		this.diagramWorkbenchPart = diagramWorkbenchPart;
@@ -247,7 +261,9 @@ public class HighlightingSupportAdapter implements IHighlightingSupport {
 		if (locked) {
 			throw new IllegalStateException("Editor already locked!");
 		}
-
+		
+		disableGlobalActions();
+		
 		setSanityCheckEnablementState(false);
 		diagramWorkbenchPart.getDiagramEditPart().disableEditMode();
 
@@ -292,7 +308,9 @@ public class HighlightingSupportAdapter implements IHighlightingSupport {
 		if (!locked) {
 			throw new IllegalStateException("Editor not locked!");
 		}
-
+		
+		restoreGlobalActions();
+		
 		// restore all elements still being highlighted
 		for (ColorMemento figureState : figureStates.values()) {
 			figureState.restore();
@@ -309,5 +327,42 @@ public class HighlightingSupportAdapter implements IHighlightingSupport {
 
 		locked = false;
 	}
-
+	
+	private void disableGlobalActions() {
+		for (String actionID:Arrays.asList(GLOBAL_ACTION_IDS)) {
+			disableGlobalAction(actionID);
+		}
+	}
+	
+	private void restoreGlobalActions(){
+		for (String actionID:Arrays.asList(GLOBAL_ACTION_IDS)) {
+			restoreGlobalAction(actionID);
+		}
+	}
+	
+	private void disableGlobalAction(String actionID) {
+		IAction action = getGlobalAction(actionID);
+		if (action != null && action instanceof ILockableAction) {
+			((ILockableAction)action).setLocked(true);
+		}
+	}
+	
+	private void restoreGlobalAction(String actionID) {
+		IAction action = getGlobalAction(actionID);
+		if (action != null && action instanceof ILockableAction) {
+			((ILockableAction) action).setLocked(false);
+		}
+	}
+	
+	private IAction getGlobalAction(String actionID) {
+//		return GlobalActionManager.getInstance().getGlobalAction(diagramWorkbenchPart, actionID);
+		
+		Object adapter = diagramWorkbenchPart.getAdapter(IEditorPart.class);
+		if (adapter != null) {
+			IEditorPart editorPart = (IEditorPart) adapter;
+			IActionBars actionBars = editorPart.getEditorSite().getActionBars();
+			return actionBars.getGlobalActionHandler(actionID);
+		}
+		return null;
+	}
 }