diff --git a/core/org.eclipse.cdt.ui/ChangeLog b/core/org.eclipse.cdt.ui/ChangeLog index 8ba930a44f0..6de89752acd 100644 --- a/core/org.eclipse.cdt.ui/ChangeLog +++ b/core/org.eclipse.cdt.ui/ChangeLog @@ -1,3 +1,6 @@ +2004-03-11 Hoda Amer + Added the undo manager for the renaming refactor. + 2004-03-11 John Camelon Updated content assist to not clear() the Scanner's definition map. diff --git a/core/org.eclipse.cdt.ui/plugin.properties b/core/org.eclipse.cdt.ui/plugin.properties index 14731ce2c92..7f1020f8105 100644 --- a/core/org.eclipse.cdt.ui/plugin.properties +++ b/core/org.eclipse.cdt.ui/plugin.properties @@ -102,6 +102,8 @@ refactoringMenu.label= Re&factor # Refactoring Refactoring.renameAction.label= Re&name +Refactoring.undoAction.label= &Undo +Refactoring.redoAction.label= Re&do # Open Type OpenTypeAction.label= Open &Type... diff --git a/core/org.eclipse.cdt.ui/plugin.xml b/core/org.eclipse.cdt.ui/plugin.xml index 50a8fc94d98..864644fec2d 100644 --- a/core/org.eclipse.cdt.ui/plugin.xml +++ b/core/org.eclipse.cdt.ui/plugin.xml @@ -312,7 +312,19 @@ label="%Refactoring.renameAction.label" class="org.eclipse.cdt.ui.refactoring.RenameAction" menubarPath="org.eclipse.cdt.ui.refactoring.menu/reorgGroup" - id="org.eclipse.cdt.ui.actions.Rename"> + id="org.eclipse.cdt.ui.actions.refactor.Rename"> + + + + @@ -508,13 +520,13 @@ = 1. + */ + private int capacity; + + /** + * The current number of listeners. + * Maintains invariant: 0 <= size <= listeners.length. + */ + private int size; + + /** + * The list of listeners. Initially null but initialized + * to an array of size capacity the first time a listener is added. + * Maintains invariant: listeners != null IFF size != 0 + */ + private Object[] listeners= null; + + /** + * The empty array singleton instance, returned by getListeners() + * when size == 0. + */ + private static final Object[] EmptyArray= new Object[0]; + + /** + * Creates a listener list with an initial capacity of 3. + */ + public ListenerList() { + this(3); + } + + /** + * Creates a listener list with the given initial capacity. + * + * @param capacity the number of listeners which this list can initially accept + * without growing its internal representation; must be at least 1 + */ + public ListenerList(int capacity) { + Assert.isTrue(capacity >= 1); + this.capacity= capacity; + } + + /** + * Adds the given listener to this list. Has no effect if an identical listener + * is already registered. + * + * @param listener the listener + */ + public void add(Object listener) { + Assert.isNotNull(listener); + if (size == 0) { + listeners= new Object[capacity]; + } else { + // check for duplicates using identity + for (int i= 0; i < size; ++i) { + if (listeners[i] == listener) { + return; + } + } + // grow array if necessary + if (size == listeners.length) { + System.arraycopy(listeners, 0, listeners= new Object[size * 2 + 1], 0, size); + } + } + listeners[size++]= listener; + } + + /** + * Returns an array containing all the registered listeners. + * The resulting array is unaffected by subsequent adds or removes. + * If there are no listeners registered, the result is an empty array + * singleton instance (no garbage is created). + * Use this method when notifying listeners, so that any modifications + * to the listener list during the notification will have no effect on the + * notification itself. + * + * @return the list of registered listeners + */ + public Object[] getListeners() { + if (size == 0) + return EmptyArray; + Object[] result= new Object[size]; + System.arraycopy(listeners, 0, result, 0, size); + return result; + } + + /** + * Returns whether this listener list is empty. + * + * @return true if there are no registered listeners, and + * false otherwise + */ + public boolean isEmpty() { + return size == 0; + } + + /** + * Removes the given listener from this list. Has no effect if an identical + * listener was not already registered. + * + * @param listener the listener + */ + public void remove(Object listener) { + Assert.isNotNull(listener); + for (int i= 0; i < size; ++i) { + if (listeners[i] == listener) { + if (--size == 0) { + listeners= new Object[1]; + } else { + if (i < size) { + listeners[i]= listeners[size]; + } + listeners[size]= null; + } + return; + } + } + } + + /** + * Returns the number of registered listeners. + * + * @return the number of registered listeners + */ + public int size() { + return size; + } +} diff --git a/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/corext/refactoring/UndoManager.java b/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/corext/refactoring/UndoManager.java new file mode 100644 index 00000000000..0fd0767c41f --- /dev/null +++ b/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/corext/refactoring/UndoManager.java @@ -0,0 +1,373 @@ +/********************************************************************** + * Copyright (c) 2004 Rational Software Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * IBM Rational Software - Initial API and implementation +***********************************************************************/ + +package org.eclipse.cdt.internal.corext.refactoring; + +import java.util.Stack; + +import org.eclipse.cdt.core.model.CModelException; +import org.eclipse.cdt.core.model.CoreModel; +import org.eclipse.cdt.core.model.ElementChangedEvent; +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ICElementDelta; +import org.eclipse.cdt.core.model.IElementChangedListener; +import org.eclipse.cdt.core.model.ITranslationUnit; +import org.eclipse.cdt.internal.corext.Assert; +import org.eclipse.cdt.internal.corext.refactoring.base.ChangeContext; +import org.eclipse.cdt.internal.corext.refactoring.base.IChange; +import org.eclipse.cdt.internal.corext.refactoring.base.IUndoManager; +import org.eclipse.cdt.internal.corext.refactoring.base.IUndoManagerListener; +import org.eclipse.cdt.internal.corext.refactoring.base.RefactoringStatus; +import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IResourceChangeEvent; +import org.eclipse.core.resources.IResourceChangeListener; +import org.eclipse.core.resources.IResourceDelta; +import org.eclipse.core.resources.IResourceDeltaVisitor; +import org.eclipse.core.resources.IWorkspaceRunnable; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.SubProgressMonitor; + +/** + * Default implementation of IUndoManager. + */ +public class UndoManager implements IUndoManager { + + private class FlushListener implements IElementChangedListener { + public void elementChanged(ElementChangedEvent event) + { + // If we don't have anything to undo or redo don't examine the tree. + if (fUndoChanges.isEmpty() && fRedoChanges.isEmpty()) + return; + + processDelta(event.getDelta()); + } + + private boolean processDelta(ICElementDelta delta) + { + int kind= delta.getKind(); + int details= delta.getFlags(); + int type= delta.getElement().getElementType(); + ICElementDelta[] affectedChildren= delta.getAffectedChildren(); + if (affectedChildren == null) + return true; + + switch (type) { + // Consider containers for class files. + case ICElement.C_MODEL: + case ICElement.C_PROJECT: + case ICElement.C_CCONTAINER: + // If we did something different than changing a child we flush the the undo / redo stack. + if (kind != ICElementDelta.CHANGED + || ((details & ICElementDelta.F_CHILDREN) == 0)) { + flush(); + return false; + } + break; + case ICElement.C_UNIT: + // if we have changed a primary working copy (e.g created, removed, ...) + // then we do nothing. + ITranslationUnit unit= (ITranslationUnit)delta.getElement(); + // If we change a working copy we do nothing + if (unit.isWorkingCopy()) { + // Don't examine children of a working copy but keep processing siblings. + return true; + } else { + flush(); + return false; + } + } + for (int i= 0; i < affectedChildren.length; i++) { + if (!processDelta(affectedChildren[i])) + return false; + } + return true; + } + } + + private class SaveListener implements IResourceChangeListener { + public void resourceChanged(IResourceChangeEvent event) { + IResourceDeltaVisitor visitor= new IResourceDeltaVisitor() { + public boolean visit(IResourceDelta delta) throws CoreException { + IResource resource= delta.getResource(); + if (resource.getType() == IResource.FILE && delta.getKind() == IResourceDelta.CHANGED && + (delta.getFlags() & IResourceDelta.CONTENT) != 0) { + if(CoreModel.getDefault().isValidTranslationUnitName(resource.getName())) { + ITranslationUnit unit= (ITranslationUnit)CoreModel.getDefault().create((IFile)resource); + if (unit != null && unit.exists()) { + flush(); + return false; + } + } + } + return true; + } + }; + try { + IResourceDelta delta= event.getDelta(); + if (delta != null) + delta.accept(visitor); + } catch (CoreException e) { + CUIPlugin.getDefault().log(e.getStatus()); + } + } + } + + private Stack fUndoChanges; + private Stack fRedoChanges; + private Stack fUndoNames; + private Stack fRedoNames; + private ListenerList fListeners; + private FlushListener fFlushListener; + private SaveListener fSaveListener; + + /** + * Creates a new undo manager with an empty undo and redo stack. + */ + public UndoManager() { + flush(); + } + + /* (Non-Javadoc) + * Method declared in IUndoManager. + */ + public void addListener(IUndoManagerListener listener) { + if (fListeners == null) + fListeners= new ListenerList(); + fListeners.add(listener); + } + + /* (Non-Javadoc) + * Method declared in IUndoManager. + */ + public void removeListener(IUndoManagerListener listener) { + if (fListeners == null) + return; + fListeners.remove(listener); + } + + /* (Non-Javadoc) + * Method declared in IUndoManager. + */ + public void aboutToPerformRefactoring() { + // Remove the resource change listener since we are changing code. + if (fFlushListener != null) + CoreModel.getDefault().removeElementChangedListener(fFlushListener); + if (fSaveListener != null) + ResourcesPlugin.getWorkspace().removeResourceChangeListener(fSaveListener); + } + + /* (Non-Javadoc) + * Method declared in IUndoManager. + */ + public void refactoringPerformed(boolean success) { + if (success) { + if (fFlushListener != null) + CoreModel.getDefault().addElementChangedListener(fFlushListener); + if (fSaveListener != null) + ResourcesPlugin.getWorkspace().addResourceChangeListener(fSaveListener); + } else { + flush(); + } + } + + /* (non-Javadoc) + * @see IUndoManager#shutdown() + */ + public void shutdown() { + if (fFlushListener != null) + CoreModel.getDefault().removeElementChangedListener(fFlushListener); + if (fSaveListener != null) + ResourcesPlugin.getWorkspace().removeResourceChangeListener(fSaveListener); + } + + /* (Non-Javadoc) + * Method declared in IUndoManager. + */ + public void flush() { + flushUndo(); + flushRedo(); + if (fFlushListener != null) + CoreModel.getDefault().removeElementChangedListener(fFlushListener); + if (fSaveListener != null) + ResourcesPlugin.getWorkspace().removeResourceChangeListener(fSaveListener); + + fFlushListener= null; + fSaveListener= null; + } + + private void flushUndo(){ + fUndoChanges= new Stack(); + fUndoNames= new Stack(); + fireUndoStackChanged(); + } + + private void flushRedo(){ + fRedoChanges= new Stack(); + fRedoNames= new Stack(); + fireRedoStackChanged(); + } + + /* (Non-Javadoc) + * Method declared in IUndoManager. + */ + public void addUndo(String refactoringName, IChange change){ + Assert.isNotNull(refactoringName, "refactoring"); //$NON-NLS-1$ + Assert.isNotNull(change, "change"); //$NON-NLS-1$ + fUndoNames.push(refactoringName); + fUndoChanges.push(change); + flushRedo(); + if (fFlushListener == null) { + fFlushListener= new FlushListener(); + CoreModel.getDefault().addElementChangedListener(fFlushListener); + } + if (fSaveListener == null) { + fSaveListener= new SaveListener(); + ResourcesPlugin.getWorkspace().addResourceChangeListener(fSaveListener); + } + fireUndoStackChanged(); + } + + /* (Non-Javadoc) + * Method declared in IUndoManager. + */ + public RefactoringStatus performUndo(ChangeContext context, IProgressMonitor pm) throws CModelException{ + // PR: 1GEWDUH: ITPJCORE:WINNT - Refactoring - Unable to undo refactor change + RefactoringStatus result= new RefactoringStatus(); + + if (fUndoChanges.empty()) + return result; + + IChange change= (IChange)fUndoChanges.peek(); + + executeChange(result, context, change, pm); + + if (!result.hasError()) { + fUndoChanges.pop(); + fRedoNames.push(fUndoNames.pop()); + fRedoChanges.push(change.getUndoChange()); + fireUndoStackChanged(); + fireRedoStackChanged(); + } + return result; + } + + /* (Non-Javadoc) + * Method declared in IUndoManager. + */ + public RefactoringStatus performRedo(ChangeContext context, IProgressMonitor pm) throws CModelException{ + // PR: 1GEWDUH: ITPJCORE:WINNT - Refactoring - Unable to undo refactor change + RefactoringStatus result= new RefactoringStatus(); + + if (fRedoChanges.empty()) + return result; + + IChange change= (IChange)fRedoChanges.peek(); + + + executeChange(result, context, change, pm); + + if (!result.hasError()) { + fRedoChanges.pop(); + fUndoNames.push(fRedoNames.pop()); + fUndoChanges.push(change.getUndoChange()); + fireRedoStackChanged(); + fireUndoStackChanged(); + } + + return result; + } + + private void executeChange(RefactoringStatus status, final ChangeContext context, final IChange change, IProgressMonitor pm) throws CModelException { + if (fFlushListener != null) + CoreModel.getDefault().removeElementChangedListener(fFlushListener); + if (fSaveListener != null) + ResourcesPlugin.getWorkspace().removeResourceChangeListener(fSaveListener); + try { + pm.beginTask("", 10); //$NON-NLS-1$ + status.merge(change.aboutToPerform(context, new SubProgressMonitor(pm, 2))); + if (status.hasError()) + return; + + CoreModel.run( + new IWorkspaceRunnable() { + public void run(IProgressMonitor innerPM) throws CoreException { + change.perform(context, innerPM); + } + }, + new SubProgressMonitor(pm, 8)); + } catch (CModelException e){ + throw e; + } catch (CoreException e) { + throw new CModelException(e); + } finally { + change.performed(); + if (fFlushListener != null) + CoreModel.getDefault().addElementChangedListener(fFlushListener); + if (fSaveListener != null) + ResourcesPlugin.getWorkspace().addResourceChangeListener(fSaveListener); + pm.done(); + } + } + + /* (Non-Javadoc) + * Method declared in IUndoManager. + */ + public boolean anythingToRedo(){ + return !fRedoChanges.empty(); + } + + /* (Non-Javadoc) + * Method declared in IUndoManager. + */ + public boolean anythingToUndo(){ + return !fUndoChanges.empty(); + } + + /* (Non-Javadoc) + * Method declared in IUndoManager. + */ + public String peekUndoName() { + if (fUndoNames.size() > 0) + return (String)fUndoNames.peek(); + return null; + } + + /* (Non-Javadoc) + * Method declared in IUndoManager. + */ + public String peekRedoName() { + if (fRedoNames.size() > 0) + return (String)fRedoNames.peek(); + return null; + } + + private void fireUndoStackChanged() { + if (fListeners == null) + return; + Object[] listeners= fListeners.getListeners(); + for (int i= 0; i < listeners.length; i++) { + ((IUndoManagerListener)listeners[i]).undoStackChanged(this); + } + } + + private void fireRedoStackChanged() { + if (fListeners == null) + return; + Object[] listeners= fListeners.getListeners(); + for (int i= 0; i < listeners.length; i++) { + ((IUndoManagerListener)listeners[i]).redoStackChanged(this); + } + } +} diff --git a/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/corext/refactoring/base/IUndoManager.java b/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/corext/refactoring/base/IUndoManager.java new file mode 100644 index 00000000000..4de9400f3ce --- /dev/null +++ b/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/corext/refactoring/base/IUndoManager.java @@ -0,0 +1,128 @@ +/********************************************************************** + * Copyright (c) 2004 Rational Software Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * IBM Rational Software - Initial API and implementation +***********************************************************************/ +package org.eclipse.cdt.internal.corext.refactoring.base; + +import org.eclipse.core.runtime.IProgressMonitor; + +import org.eclipse.cdt.core.model.CModelException; + +/** + * An undo manager keeps track of changes performed by refactorings. Use performUndo + * and performRedo to undo and redo changes. + *

+ * NOTE: This interface is not intended to be implemented or extended. Use Refactoring.getUndoManager() + * to access the undo manager.

+ *

+ * NOTE: This class/interface is part of an interim API that is still under development + * and expected to change significantly before reaching stability. It is being made available at + * this early stage to solicit feedback from pioneering adopters on the understanding that any + * code that uses this API will almost certainly be broken (repeatedly) as the API evolves.

+ */ +public interface IUndoManager { + + /** + * Adds a listener to the undo manager. + * + * @param listener the listener to be added to the undo manager + */ + public void addListener(IUndoManagerListener listener); + + /** + * Removes the given listener from this undo manager. + * + * @param listener the listener to be removed + */ + public void removeListener(IUndoManagerListener listener); + + /** + * The refactoring infrastructure is going to perform a refactoring. + */ + public void aboutToPerformRefactoring(); + + /** + * The execution of a refactoring is completed. + * + * @param success true if the refactoring has been executed successful. + * Otherwise false. + */ + public void refactoringPerformed(boolean success); + + /** + * Adds a new undo change to this undo manager. + * + * @param name the name of the refactoring the change was created + * for. The name must not be null + * @param change the undo change. The change must not be null + */ + public void addUndo(String name, IChange change); + + /** + * Returns true if there is anything to undo, otherwise + * false. + * + * @return true if there is anything to undo, otherwise + * false + */ + public boolean anythingToUndo(); + + /** + * Returns the name of the top most undo. + * + * @return the top most undo name. The main purpose of the name is to + * render it in the UI. Returns null if there aren't any changes to undo + */ + public String peekUndoName(); + + /** + * Undo the top most undo change. + * + * @param pm a progress monitor to report progress during performing + * the undo change. The progress monitor must not be null + * @return a status indicating if the undo preflight produced any error + */ + public RefactoringStatus performUndo(ChangeContext context, IProgressMonitor pm) throws CModelException; + + /** + * Returns true if there is anything to redo, otherwise + * false. + * + * @return true if there is anything to redo, otherwise + * false + */ + public boolean anythingToRedo(); + + /** + * Returns the name of the top most redo. + * + * @return the top most redo name. The main purpose of the name is to + * render it in the UI. Returns null if there are no any changes to redo. + */ + public String peekRedoName(); + + /** + * Redo the top most redo change. + * + * @param pm a progress monitor to report progress during performing + * the redo change. The progress monitor must not be null + * @return a status indicating if the undo preflight produced any error + */ + public RefactoringStatus performRedo(ChangeContext context, IProgressMonitor pm) throws CModelException; + + /** + * Flushes the undo manager's undo and redo stacks. + */ + public void flush(); + + /** + * Shut down the undo manager. + */ + public void shutdown(); +} diff --git a/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/corext/refactoring/base/IUndoManagerListener.java b/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/corext/refactoring/base/IUndoManagerListener.java new file mode 100644 index 00000000000..49935948127 --- /dev/null +++ b/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/corext/refactoring/base/IUndoManagerListener.java @@ -0,0 +1,30 @@ +/********************************************************************** + * Copyright (c) 2004 Rational Software Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * IBM Rational Software - Initial API and implementation +***********************************************************************/ +package org.eclipse.cdt.internal.corext.refactoring.base; + + +/** + * Listener to monitor changes made to an UndoManager + */ +public interface IUndoManagerListener { + + /** + * This method is called by the undo manager if an undo change has been + * added to it. + */ + public void undoStackChanged(IUndoManager manager); + + /** + * This method is called by the undo manager if a redo change has been + * added to it. + */ + public void redoStackChanged(IUndoManager manager); +} diff --git a/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/corext/refactoring/base/Refactoring.java b/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/corext/refactoring/base/Refactoring.java index c0324845434..284e39f28dd 100644 --- a/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/corext/refactoring/base/Refactoring.java +++ b/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/corext/refactoring/base/Refactoring.java @@ -16,6 +16,8 @@ import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.SubProgressMonitor; +import org.eclipse.cdt.internal.corext.refactoring.UndoManager; + /** * Superclass for all refactorings. *

@@ -26,6 +28,12 @@ import org.eclipse.core.runtime.SubProgressMonitor; */ public abstract class Refactoring implements IRefactoring, IAdaptable { + private static IUndoManager fgUndoManager= new UndoManager(); + + public static IUndoManager getUndoManager() { + return fgUndoManager; + } + /* non java-doc * for debugging only diff --git a/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/corext/refactoring/base/UndoManagerAdapter.java b/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/corext/refactoring/base/UndoManagerAdapter.java new file mode 100644 index 00000000000..5a57620b0af --- /dev/null +++ b/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/corext/refactoring/base/UndoManagerAdapter.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.corext.refactoring.base; + +/** + * An adapter implementation for IUndoManagerListener. + */ +public class UndoManagerAdapter implements IUndoManagerListener { + + /* (non-Javadoc) + * Method declared in IUndoManagerListener + */ + public void undoStackChanged(IUndoManager manager) { + } + + /* (non-Javadoc) + * Method declared in IUndoManagerListener + */ + public void redoStackChanged(IUndoManager manager) { + } +} + diff --git a/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/corext/refactoring/refactoring.properties b/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/corext/refactoring/refactoring.properties index 1633d93d2dc..74e55ca71a1 100644 --- a/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/corext/refactoring/refactoring.properties +++ b/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/corext/refactoring/refactoring.properties @@ -327,7 +327,7 @@ RenameTypeRefactoring.creating_change=Preparing preview... RenameTypeRefactoring.rename_constructor=rename constructor RenameTypeRefactoring.searching=Searching for references... RenameTypeRefactoring.update_reference=update type reference -RenameTypeRefactoring.name=Rename type ''{0}'' to ''{1}'' +RenameTypeRefactoring.name=Rename ''{0}'' to ''{1}'' RenameTypeRefactoring.enclosed=Type ''{0}'' is enclosed in a type named ''{1}'' RenameTypeRefactoring.encloses=Type ''{0}'' encloses a type named ''{1}'' RenameTypeRefactoring.exists=Type named ''{0}'' already exists in package ''{1}'' diff --git a/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/ui/refactoring/PerformRefactoringUtil.java b/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/ui/refactoring/PerformRefactoringUtil.java index cfaec9a0d50..623d9b96238 100644 --- a/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/ui/refactoring/PerformRefactoringUtil.java +++ b/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/ui/refactoring/PerformRefactoringUtil.java @@ -29,6 +29,7 @@ import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.internal.corext.refactoring.base.ChangeAbortException; import org.eclipse.cdt.internal.corext.refactoring.base.ChangeContext; import org.eclipse.cdt.internal.corext.refactoring.base.IChange; +import org.eclipse.cdt.internal.corext.refactoring.base.IUndoManager; import org.eclipse.cdt.internal.corext.refactoring.base.Refactoring; import org.eclipse.cdt.internal.ui.ICStatusConstants; @@ -43,16 +44,16 @@ public class PerformRefactoringUtil { public static boolean performRefactoring(PerformChangeOperation op, Refactoring refactoring, IRunnableContext execContext, Shell parent) { ChangeContext context= new ChangeContext(new ChangeExceptionHandler(parent)); boolean success= false; -// IUndoManager undoManager= Refactoring.getUndoManager(); + IUndoManager undoManager= Refactoring.getUndoManager(); try{ op.setChangeContext(context); -// undoManager.aboutToPerformRefactoring(); + undoManager.aboutToPerformRefactoring(); execContext.run(false, false, op); if (op.changeExecuted()) { if (! op.getChange().isUndoable()){ success= false; } else { -// undoManager.addUndo(refactoring.getName(), op.getChange().getUndoChange()); + undoManager.addUndo(refactoring.getName(), op.getChange().getUndoChange()); success= true; } } @@ -71,7 +72,7 @@ public class PerformRefactoringUtil { return false; } finally { context.clearPerformedChanges(); -// undoManager.refactoringPerformed(success); + undoManager.refactoringPerformed(success); } return true; diff --git a/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/ui/refactoring/RefactoringExecutionHelper.java b/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/ui/refactoring/RefactoringExecutionHelper.java new file mode 100644 index 00000000000..430455d245a --- /dev/null +++ b/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/ui/refactoring/RefactoringExecutionHelper.java @@ -0,0 +1,223 @@ +/********************************************************************** + * Copyright (c) 2004 Rational Software Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * IBM Rational Software - Initial API and implementation +***********************************************************************/ +package org.eclipse.cdt.internal.ui.refactoring; + +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.swt.widgets.Shell; + +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.operation.IRunnableContext; +import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.jface.text.Assert; +import org.eclipse.jface.text.IRewriteTarget; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.SubProgressMonitor; + +import org.eclipse.core.resources.IWorkspaceRunnable; + +import org.eclipse.ui.IEditorPart; + +import org.eclipse.cdt.core.model.CoreModel; + +import org.eclipse.cdt.internal.corext.refactoring.base.ChangeAbortException; +import org.eclipse.cdt.internal.corext.refactoring.base.ChangeContext; +import org.eclipse.cdt.internal.corext.refactoring.base.IChange; +import org.eclipse.cdt.internal.corext.refactoring.base.IRefactoring; +import org.eclipse.cdt.internal.corext.refactoring.base.IUndoManager; +import org.eclipse.cdt.internal.corext.refactoring.base.Refactoring; +import org.eclipse.cdt.internal.corext.refactoring.base.RefactoringStatus; + +import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.cdt.internal.ui.refactoring.AbortChangeExceptionHandler; +import org.eclipse.cdt.internal.ui.refactoring.ChangeExceptionHandler; +import org.eclipse.cdt.internal.ui.util.ExceptionHandler; + +/** + * A helper class to execute a refactoring. The class takes care of pushing the + * undo change onto the undo stack and folding editor edits into one editor + * undo object. + */ +public class RefactoringExecutionHelper { + + private final IRefactoring fRefactoring; + private final Shell fParent; + private final IRunnableContext fExecContext; + private final int fStopSeverity; + private final boolean fNeedsSavedEditors; + private ChangeContext fContext; + + private class Operation implements IRunnableWithProgress { + public IChange fChange; + public void run(IProgressMonitor pm) throws InvocationTargetException, InterruptedException { + try { + pm.beginTask("", 10); //$NON-NLS-1$ + pm.subTask(""); //$NON-NLS-1$ + RefactoringStatus status= fRefactoring.checkPreconditions(new SubProgressMonitor(pm, 4, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK)); + if (status.getSeverity() >= fStopSeverity) { + RefactoringStatusDialog dialog= new RefactoringStatusDialog(fParent, status, fRefactoring.getName(), false); + if(dialog.open() == IDialogConstants.CANCEL_ID) { + throw new InterruptedException(); + } + } + fChange= fRefactoring.createChange(new SubProgressMonitor(pm, 2, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK)); + try { + fChange.aboutToPerform(fContext, new NullProgressMonitor()); + CoreModel.run(new IWorkspaceRunnable() { + public void run(IProgressMonitor monitor) throws CoreException { + fChange.perform(fContext, monitor); + } + }, new SubProgressMonitor(pm, 4, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK)); + } finally { + fChange.performed(); + } + } catch (ChangeAbortException e) { + throw new InvocationTargetException(e); + } catch (CoreException e) { + throw new InvocationTargetException(e); + } finally { + pm.done(); + } + } + public boolean isExecuted() { + return fChange != null; + } + public boolean isUndoable() { + return fChange.isUndoable(); + } + public IChange getUndoChange() { + return fChange.getUndoChange(); + } + } + + public RefactoringExecutionHelper(IRefactoring refactoring, int stopSevertity, boolean needsSavedEditors, Shell parent, IRunnableContext context) { + super(); + Assert.isNotNull(refactoring); + Assert.isNotNull(parent); + Assert.isNotNull(context); + fRefactoring= refactoring; + fStopSeverity= stopSevertity; + fParent= parent; + fExecContext= context; + fNeedsSavedEditors= needsSavedEditors; + } + + public void perform() throws InterruptedException, InvocationTargetException { + RefactoringSaveHelper saveHelper= new RefactoringSaveHelper(); + if (fNeedsSavedEditors && !saveHelper.saveEditors(fParent)) + throw new InterruptedException(); + fContext= new ChangeContext(new ChangeExceptionHandler(fParent)); + boolean success= false; + IUndoManager undoManager= Refactoring.getUndoManager(); + Operation op= new Operation(); + IRewriteTarget[] targets= null; + try{ + targets= getRewriteTargets(); + beginCompoundChange(targets); + undoManager.aboutToPerformRefactoring(); + fExecContext.run(false, false, op); + if (op.isExecuted()) { + if (!op.isUndoable()) { + success= false; + } else { + undoManager.addUndo(fRefactoring.getName(), op.getUndoChange()); + success= true; + } + } + } catch (InvocationTargetException e) { + Throwable t= e.getTargetException(); + if (t instanceof ChangeAbortException) { + handleChangeAbortException((ChangeAbortException)t); + } else { + throw e; + } + } finally { + fContext.clearPerformedChanges(); + undoManager.refactoringPerformed(success); + saveHelper.triggerBuild(); + if (targets != null) + endCompoundChange(targets); + } + } + + private void handleChangeAbortException(ChangeAbortException exception) { + if (!fContext.getTryToUndo()) + return; + + IRunnableWithProgress op= new IRunnableWithProgress() { + public void run(IProgressMonitor monitor) throws InterruptedException, InvocationTargetException { + try { + CoreModel.run(new IWorkspaceRunnable() { + public void run(IProgressMonitor pm) throws CoreException { + ChangeContext undoContext= new ChangeContext(new AbortChangeExceptionHandler()); + IChange[] changes= fContext.getPerformedChanges(); + pm.beginTask(RefactoringMessages.getString("RefactoringWizard.undoing"), changes.length); //$NON-NLS-1$ + IProgressMonitor sub= new NullProgressMonitor(); + for (int i= changes.length - 1; i >= 0; i--) { + IChange change= changes[i]; + pm.subTask(change.getName()); + change.getUndoChange().perform(undoContext, sub); + pm.worked(1); + } + } + }, monitor); + } catch (ChangeAbortException e) { + throw new InvocationTargetException(e.getThrowable()); + } catch (CoreException e) { + throw new InvocationTargetException(e); + } finally { + monitor.done(); + } + } + }; + + try { + fExecContext.run(false, false, op); + } catch (InvocationTargetException e) { + handleUnexpectedException(e); + } catch (InterruptedException e) { + // not possible. Operation not cancelable. + } + } + + private void handleUnexpectedException(InvocationTargetException e) { + ExceptionHandler.handle(e, RefactoringMessages.getString("RefactoringWizard.refactoring"), RefactoringMessages.getString("RefactoringWizard.unexpected_exception_1")); //$NON-NLS-2$ //$NON-NLS-1$ + } + + private static void beginCompoundChange(IRewriteTarget[] targets) { + for (int i= 0; i < targets.length; i++) { + targets[i].beginCompoundChange(); + } + } + + private static void endCompoundChange(IRewriteTarget[] targets) { + for (int i= 0; i < targets.length; i++) { + targets[i].endCompoundChange(); + } + } + + private static IRewriteTarget[] getRewriteTargets() { + IEditorPart[] editors= CUIPlugin.getInstanciatedEditors(); + List result= new ArrayList(editors.length); + for (int i= 0; i < editors.length; i++) { + IRewriteTarget target= (IRewriteTarget)editors[i].getAdapter(IRewriteTarget.class); + if (target != null) { + result.add(target); + } + } + return (IRewriteTarget[]) result.toArray(new IRewriteTarget[result.size()]); + } +} diff --git a/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/ui/refactoring/TextInputWizardPage.java b/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/ui/refactoring/TextInputWizardPage.java index fd097af7305..935280e8842 100644 --- a/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/ui/refactoring/TextInputWizardPage.java +++ b/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/ui/refactoring/TextInputWizardPage.java @@ -129,8 +129,8 @@ public abstract class TextInputWizardPage extends UserInputWizardPage{ } if ((! isInitialInputValid()) && text.equals(fInitialValue)){ setPageComplete(false); - //setErrorMessage(null); - setErrorMessage(RefactoringMessages.getString("RenameInputWizardPage.no_undo")); //$NON-NLS-1$ + setErrorMessage(null); + //setErrorMessage(RefactoringMessages.getString("RenameInputWizardPage.no_undo")); //$NON-NLS-1$ restoreMessage(); return; } diff --git a/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/ui/refactoring/UserInputWizardPage.java b/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/ui/refactoring/UserInputWizardPage.java index 737117027fc..8e7c0fe3f4e 100644 --- a/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/ui/refactoring/UserInputWizardPage.java +++ b/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/ui/refactoring/UserInputWizardPage.java @@ -54,8 +54,8 @@ public abstract class UserInputWizardPage extends RefactoringWizardPage { setErrorMessage(status.getFirstMessage(severity)); } else { setPageComplete(true); - //setErrorMessage(null); - setErrorMessage(RefactoringMessages.getString("RenameInputWizardPage.no_undo")); //$NON-NLS-1$ + setErrorMessage(null); + //setErrorMessage(RefactoringMessages.getString("RenameInputWizardPage.no_undo")); //$NON-NLS-1$ if (severity == RefactoringStatus.OK) setMessage(null, NONE); else diff --git a/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/ui/refactoring/actions/RedoRefactoringAction.java b/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/ui/refactoring/actions/RedoRefactoringAction.java new file mode 100644 index 00000000000..7a692d4b57a --- /dev/null +++ b/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/ui/refactoring/actions/RedoRefactoringAction.java @@ -0,0 +1,111 @@ +/********************************************************************** + * Copyright (c) 2004 Rational Software Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * IBM Rational Software - Initial API and implementation +***********************************************************************/ + +package org.eclipse.cdt.internal.ui.refactoring.actions; + +import java.lang.reflect.InvocationTargetException; + +import org.eclipse.core.runtime.IProgressMonitor; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.jface.viewers.ISelection; + +import org.eclipse.cdt.core.model.CModelException; + +import org.eclipse.cdt.internal.corext.refactoring.base.ChangeAbortException; +import org.eclipse.cdt.internal.corext.refactoring.base.ChangeContext; +import org.eclipse.cdt.internal.corext.refactoring.base.IUndoManager; +import org.eclipse.cdt.internal.corext.refactoring.base.Refactoring; +import org.eclipse.cdt.internal.corext.refactoring.base.UndoManagerAdapter; +import org.eclipse.cdt.internal.ui.refactoring.RefactoringMessages; + +public class RedoRefactoringAction extends UndoManagerAction { + + private int fPatternLength; + + public RedoRefactoringAction() { + } + + /* (non-Javadoc) + * Method declared in UndoManagerAction + */ + protected String getName() { + // PR: 1GEWDUH: ITPJCORE:WINNT - Refactoring - Unable to undo refactor change + return RefactoringMessages.getString("RedoRefactoringAction.name"); //$NON-NLS-1$ + } + + /* (non-Javadoc) + * Method declared in UndoManagerAction + */ + protected IRunnableWithProgress createOperation(final ChangeContext context) { + // PR: 1GEWDUH: ITPJCORE:WINNT - Refactoring - Unable to undo refactor change + return new IRunnableWithProgress(){ + public void run(IProgressMonitor pm) throws InvocationTargetException { + try { + setPreflightStatus(Refactoring.getUndoManager().performRedo(context, pm)); + } catch (CModelException e) { + throw new InvocationTargetException(e); + } catch (ChangeAbortException e) { + throw new InvocationTargetException(e); + } + } + + }; + } + + /* (non-Javadoc) + * Method declared in UndoManagerAction + */ + protected UndoManagerAdapter createUndoManagerListener() { + return new UndoManagerAdapter() { + public void redoStackChanged(IUndoManager manager) { + IAction action= getAction(); + if (action == null) + return; + boolean enabled= false; + String text= null; + if (manager.anythingToRedo()) { + enabled= true; + text= getActionText(); + } else { + text= RefactoringMessages.getString("RedoRefactoringAction.label"); //$NON-NLS-1$ + } + action.setEnabled(enabled); + action.setText(text); + } + }; + } + + /* (non-Javadoc) + * Method declared in IActionDelegate + */ + public void selectionChanged(IAction action, ISelection s) { +// if (!isHooked()) { + hookListener(action); + fPatternLength= RefactoringMessages.getString("RedoRefactoringAction.extendedLabel").length(); //$NON-NLS-1$ + IUndoManager undoManager = Refactoring.getUndoManager(); + if (undoManager.anythingToRedo()) { + if (undoManager.peekRedoName() != null) + action.setText(getActionText()); + action.setEnabled(true); + } else { + action.setEnabled(false); + } +// } + } + + private String getActionText() { + return shortenText(RefactoringMessages.getFormattedString( + "RedoRefactoringAction.extendedLabel", //$NON-NLS-1$ + Refactoring.getUndoManager().peekRedoName()), fPatternLength); + } +} diff --git a/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/ui/refactoring/RenameRefactoringAction.java b/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/ui/refactoring/actions/RenameRefactoringAction.java similarity index 78% rename from core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/ui/refactoring/RenameRefactoringAction.java rename to core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/ui/refactoring/actions/RenameRefactoringAction.java index 4cf3d658e7d..269daa3bfd4 100644 --- a/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/ui/refactoring/RenameRefactoringAction.java +++ b/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/ui/refactoring/actions/RenameRefactoringAction.java @@ -8,33 +8,28 @@ * Contributors: * IBM Rational Software - Initial API and implementation ***********************************************************************/ -package org.eclipse.cdt.internal.ui.refactoring; +package org.eclipse.cdt.internal.ui.refactoring.actions; +import org.eclipse.cdt.internal.corext.refactoring.RenameRefactoring; +import org.eclipse.cdt.internal.ui.refactoring.RefactoringMessages; +import org.eclipse.cdt.internal.ui.refactoring.UserInterfaceStarter; +import org.eclipse.cdt.internal.ui.util.ExceptionHandler; +import org.eclipse.cdt.ui.actions.SelectionDispatchAction; import org.eclipse.core.runtime.CoreException; - -import org.eclipse.swt.widgets.Shell; - import org.eclipse.jface.action.IAction; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; - +import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IWorkbenchSite; -import org.eclipse.cdt.internal.corext.refactoring.RenameRefactoring; - -import org.eclipse.cdt.internal.ui.refactoring.UserInterfaceStarter; -import org.eclipse.cdt.internal.ui.util.ExceptionHandler; - -import org.eclipse.cdt.ui.actions.SelectionDispatchAction; - public class RenameRefactoringAction extends SelectionDispatchAction { public RenameRefactoringAction(IWorkbenchSite site) { super(site); - setText("Rename ..."); + setText(RefactoringMessages.getString("RenameRefactoringAction.text"));//$NON-NLS-1$ } /* (non-Javadoc) @@ -54,7 +49,8 @@ public class RenameRefactoringAction extends SelectionDispatchAction { RenameRefactoring refactoring= new RenameRefactoring(element); run(refactoring, getShell()); } catch (CoreException e) { - ExceptionHandler.handle(e, getShell(), "Rename Refactoring", "Unexpected Exception occured"); + ExceptionHandler.handle(e, getShell(), RefactoringMessages.getString("RenameRefactoringAction.label"), //$NON-NLS-1$ + RefactoringMessages.getString("RenameRefactoringAction.unexpected_exception"));//$NON-NLS-1$ } } @@ -73,9 +69,9 @@ public class RenameRefactoringAction extends SelectionDispatchAction { if (refactoring.isAvailable()) { UserInterfaceStarter.run(refactoring, parent); } else { - MessageDialog.openInformation(parent, - "Rename Refactoring", - "No refactoring available to process the selected element."); + MessageDialog.openInformation(parent, RefactoringMessages.getString("RenameRefactoringAction.label"), //$NON-NLS-1$ + RefactoringMessages.getString("RenameRefactoringAction.no_refactoring_available")//$NON-NLS-1$ + ); } } } diff --git a/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/ui/refactoring/actions/UndoManagerAction.java b/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/ui/refactoring/actions/UndoManagerAction.java new file mode 100644 index 00000000000..2efd357c0c3 --- /dev/null +++ b/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/ui/refactoring/actions/UndoManagerAction.java @@ -0,0 +1,185 @@ +/********************************************************************** + * Copyright (c) 2004 Rational Software Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * IBM Rational Software - Initial API and implementation +***********************************************************************/ + +package org.eclipse.cdt.internal.ui.refactoring.actions; + +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.MultiStatus; +import org.eclipse.core.runtime.Status; + +import org.eclipse.swt.widgets.Shell; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.dialogs.ErrorDialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.operation.IRunnableWithProgress; + +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IFileEditorInput; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.IWorkbenchWindowActionDelegate; +import org.eclipse.ui.PlatformUI; + +import org.eclipse.cdt.internal.corext.refactoring.base.ChangeContext; +import org.eclipse.cdt.internal.corext.refactoring.base.Refactoring; +import org.eclipse.cdt.internal.corext.refactoring.base.RefactoringStatus; +import org.eclipse.cdt.internal.corext.refactoring.base.RefactoringStatusEntry; +import org.eclipse.cdt.internal.corext.refactoring.base.UndoManagerAdapter; +import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.cdt.internal.ui.refactoring.RefactoringMessages; +import org.eclipse.cdt.internal.ui.refactoring.AbortChangeExceptionHandler; +import org.eclipse.cdt.internal.ui.util.ExceptionHandler; + +abstract class UndoManagerAction implements IWorkbenchWindowActionDelegate { + + private static final int MAX_LENGTH= 30; + + private RefactoringStatus fPreflightStatus; + private IAction fAction; + private IWorkbenchWindow fWorkbenchWindow; + private UndoManagerAdapter fUndoManagerListener; + + public UndoManagerAction() { + } + + protected abstract IRunnableWithProgress createOperation(ChangeContext context); + + protected abstract UndoManagerAdapter createUndoManagerListener(); + + protected abstract String getName(); + + protected IWorkbenchWindow getWorkbenchWindow() { + return fWorkbenchWindow; + } + + protected IAction getAction() { + return fAction; + } + + protected boolean isHooked() { + return fAction != null; + } + + protected void hookListener(IAction action) { + if (isHooked()) + return; + fAction= action; + fUndoManagerListener= createUndoManagerListener(); + Refactoring.getUndoManager().addListener(fUndoManagerListener); + } + + protected String shortenText(String text, int patternLength) { + int length= text.length(); + final int finalLength = MAX_LENGTH + patternLength; + if (text.length() <= finalLength) + return text; + StringBuffer result= new StringBuffer(); + int mid= finalLength / 2; + result.append(text.substring(0, mid)); + result.append("..."); //$NON-NLS-1$ + result.append(text.substring(length - mid)); + return result.toString(); + } + + /* (non-Javadoc) + * Method declared in IActionDelegate + */ + public void dispose() { + if (fUndoManagerListener != null) + Refactoring.getUndoManager().removeListener(fUndoManagerListener); + fWorkbenchWindow= null; + fAction= null; + fUndoManagerListener= null; + } + + /* (non-Javadoc) + * Method declared in IActionDelegate + */ + public void init(IWorkbenchWindow window) { + fWorkbenchWindow= window; + } + + /* (non-Javadoc) + * Method declared in IActionDelegate + */ + public void run(IAction action) { + Shell parent= fWorkbenchWindow.getShell(); + ChangeContext context= new ChangeContext(new AbortChangeExceptionHandler(), getUnsavedFiles()); + IRunnableWithProgress op= createOperation(context); + try { + // Don't execute in separate thread since it updates the UI. + PlatformUI.getWorkbench().getActiveWorkbenchWindow().run(false, false, op); + } catch (InvocationTargetException e) { + Refactoring.getUndoManager().flush(); + ExceptionHandler.handle(e, RefactoringMessages.getString("UndoManagerAction.error"), RefactoringMessages.getString("UndoManagerAction.internal_error")); //$NON-NLS-2$ //$NON-NLS-1$ + } catch (InterruptedException e) { + // Opertation isn't cancelable. + } finally { + context.clearPerformedChanges(); + } + + if (fPreflightStatus != null && fPreflightStatus.hasError()) { + String name= getName(); + MultiStatus status = createMultiStatus(); + String message= RefactoringMessages.getFormattedString("UndoManagerAction.cannot_be_executed", name); //$NON-NLS-1$ + ErrorDialog error= new ErrorDialog(parent, name, message, status, IStatus.ERROR) { + public void create() { + super.create(); + buttonPressed(IDialogConstants.DETAILS_ID); + } + }; + error.open(); + } + fPreflightStatus= null; + } + + /* package */ void setPreflightStatus(RefactoringStatus status) { + fPreflightStatus= status; + } + + private MultiStatus createMultiStatus() { + MultiStatus status= new MultiStatus( + CUIPlugin.getPluginId(), + IStatus.ERROR, + RefactoringMessages.getString("UndoManagerAction.unsaved_filed"), //$NON-NLS-1$ + null); + String id= CUIPlugin.getPluginId(); + for (Iterator iter= fPreflightStatus.getEntries().iterator(); iter.hasNext(); ) { + RefactoringStatusEntry entry= (RefactoringStatusEntry)iter.next(); + status.merge(new Status( + IStatus.ERROR, + id, + IStatus.ERROR, + entry.getMessage(), + null)); + } + return status; + } + + private IFile[] getUnsavedFiles() { + IEditorPart[] parts= CUIPlugin.getDirtyEditors(); + List result= new ArrayList(parts.length); + for (int i= 0; i < parts.length; i++) { + IEditorInput input= parts[i].getEditorInput(); + if (input instanceof IFileEditorInput) { + result.add(((IFileEditorInput)input).getFile()); + } + } + return (IFile[])result.toArray(new IFile[result.size()]); + } +} diff --git a/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/ui/refactoring/actions/UndoRefactoringAction.java b/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/ui/refactoring/actions/UndoRefactoringAction.java new file mode 100644 index 00000000000..7c297a283a4 --- /dev/null +++ b/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/ui/refactoring/actions/UndoRefactoringAction.java @@ -0,0 +1,111 @@ +/********************************************************************** + * Copyright (c) 2004 Rational Software Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * IBM Rational Software - Initial API and implementation +***********************************************************************/ + +package org.eclipse.cdt.internal.ui.refactoring.actions; + +import java.lang.reflect.InvocationTargetException; + +import org.eclipse.core.runtime.IProgressMonitor; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.jface.viewers.ISelection; + +import org.eclipse.cdt.core.model.CModelException; + +import org.eclipse.cdt.internal.corext.refactoring.base.ChangeAbortException; +import org.eclipse.cdt.internal.corext.refactoring.base.ChangeContext; +import org.eclipse.cdt.internal.corext.refactoring.base.IUndoManager; +import org.eclipse.cdt.internal.corext.refactoring.base.Refactoring; +import org.eclipse.cdt.internal.corext.refactoring.base.UndoManagerAdapter; +import org.eclipse.cdt.internal.ui.refactoring.RefactoringMessages; + +public class UndoRefactoringAction extends UndoManagerAction { + + private int fPatternLength; + + public UndoRefactoringAction() { + } + + /* (non-Javadoc) + * Method declared in UndoManagerAction + */ + protected String getName() { + // PR: 1GEWDUH: ITPJCORE:WINNT - Refactoring - Unable to undo refactor change + return RefactoringMessages.getString("UndoRefactoringAction.name"); //$NON-NLS-1$ + } + + /* (non-Javadoc) + * Method declared in UndoManagerAction + */ + protected IRunnableWithProgress createOperation(final ChangeContext context) { + // PR: 1GEWDUH: ITPJCORE:WINNT - Refactoring - Unable to undo refactor change + return new IRunnableWithProgress(){ + public void run(IProgressMonitor pm) throws InvocationTargetException { + try { + setPreflightStatus(Refactoring.getUndoManager().performUndo(context, pm)); + } catch (CModelException e) { + throw new InvocationTargetException(e); + } catch (ChangeAbortException e) { + throw new InvocationTargetException(e); + } + } + + }; + } + + /* (non-Javadoc) + * Method declared in UndoManagerAction + */ + protected UndoManagerAdapter createUndoManagerListener() { + return new UndoManagerAdapter() { + public void undoStackChanged(IUndoManager manager) { + IAction action= getAction(); + if (action == null) + return; + boolean enabled= false; + String text= null; + if (manager.anythingToUndo()) { + enabled= true; + text= getActionText(); + } else { + text= RefactoringMessages.getString("UndoRefactoringAction.label"); //$NON-NLS-1$ + } + action.setEnabled(enabled); + action.setText(text); + } + }; + } + + /* (non-Javadoc) + * Method declared in IActionDelegate + */ + public void selectionChanged(IAction action, ISelection s) { +// if (!isHooked()) { + hookListener(action); + fPatternLength= RefactoringMessages.getString("UndoRefactoringAction.extendedLabel").length(); //$NON-NLS-1$ + IUndoManager undoManager = Refactoring.getUndoManager(); + if (undoManager.anythingToUndo()) { + if (undoManager.peekUndoName() != null) + action.setText(getActionText()); + action.setEnabled(true); + } else { + action.setEnabled(false); + } +// } + } + + private String getActionText() { + return shortenText(RefactoringMessages.getFormattedString( + "UndoRefactoringAction.extendedLabel", //$NON-NLS-1$ + Refactoring.getUndoManager().peekUndoName()), fPatternLength); + } +} diff --git a/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/ui/refactoring/refactoringui.properties b/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/ui/refactoring/refactoringui.properties index 4de57e1f341..a83de52d2be 100644 --- a/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/ui/refactoring/refactoringui.properties +++ b/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/internal/ui/refactoring/refactoringui.properties @@ -76,7 +76,7 @@ SurroundWithTryCatchAction.no_exceptions=No uncaught exceptions are thrown by th RefactoringGroup.rename_method_message=Enter the new name for this method. RefactoringGroup.rename_method_title=Rename Method RefactoringGroup.rename_type_message=Enter the new name for this type. -RefactoringGroup.rename_type_title=Rename Type +RefactoringGroup.rename_type_title=Rename Element RefactoringGroup.modify_Parameters_label=Change Method Si&gnature... RefactoringGroup.pull_Up_label=Pu&ll Up... RefactoringGroup.move_label=&Move... @@ -167,6 +167,11 @@ RedoRefactoringAction.label=&Redo RedoRefactoringAction.extendedLabel=Redo - {0} RedoRefactoringAction.name=Redo +RenameRefactoringAction.label=Rename Refactoring +RenameRefactoringAction.text=Rename... +RenameRefactoringAction.no_refactoring_available=No refactoring available to process the selected element. +RenameRefactoringAction.unexpected_exception=Unexpected Exception occured. + ####################################### # Misc ####################################### diff --git a/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/ui/refactoring/RedoAction.java b/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/ui/refactoring/RedoAction.java new file mode 100644 index 00000000000..ae8bd556c6a --- /dev/null +++ b/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/ui/refactoring/RedoAction.java @@ -0,0 +1,86 @@ +/********************************************************************** + * Copyright (c) 2004 Rational Software Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * IBM Rational Software - Initial API and implementation +***********************************************************************/ + +package org.eclipse.cdt.ui.refactoring; + +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.internal.ui.refactoring.actions.RedoRefactoringAction; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.ui.IViewActionDelegate; +import org.eclipse.ui.IViewPart; + +/** + * TODO: Provide description for "RefactoringRenameAction". + */ +public class RedoAction extends Action implements IViewActionDelegate { +// private IViewPart fView; +// private IAction fAction; + RedoRefactoringAction refactoringAction = new RedoRefactoringAction(); + +// protected IViewPart getView() { +// return fView; +// } + +// protected void setView(IViewPart view) { +// fView = view; +// } +// protected IAction getAction() { +// return fAction; +// } + +// protected void setAction(IAction action) { +// fAction = action; +// } + /** + * TODO: Implement the "RefactoringRenameAction" constructor. + */ + public RedoAction() { + } + /* (non-Javadoc) + * @see org.eclipse.ui.IViewActionDelegate#init(org.eclipse.ui.IViewPart) + */ + public void init(IViewPart view) { +// setView(view); + refactoringAction.init(view.getSite().getWorkbenchWindow()); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction) + */ + public void run(IAction action) { + refactoringAction.run(action); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.IActionDelegate#selectionChanged(org.eclipse.jface.action.IAction, org.eclipse.jface.viewers.ISelection) + */ + public void selectionChanged(IAction action, ISelection selection) { + refactoringAction.selectionChanged(action, selection); +// setAction(action); +// if (!(selection instanceof IStructuredSelection)) { +// return; +// } +// IStructuredSelection sel= (IStructuredSelection)selection; +// Object o= sel.getFirstElement(); +// if (!(o instanceof ICElement)) { +// return; +// } + } + +// private IStructuredSelection getSelection() { +// return (IStructuredSelection)getView().getViewSite().getSelectionProvider().getSelection(); +// } + +} + diff --git a/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/ui/refactoring/RenameAction.java b/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/ui/refactoring/RenameAction.java index 8333cc542ae..e0d84e21728 100644 --- a/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/ui/refactoring/RenameAction.java +++ b/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/ui/refactoring/RenameAction.java @@ -12,7 +12,7 @@ package org.eclipse.cdt.ui.refactoring; import org.eclipse.cdt.core.model.ICElement; -import org.eclipse.cdt.internal.ui.refactoring.RenameRefactoringAction; +import org.eclipse.cdt.internal.ui.refactoring.actions.RenameRefactoringAction; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IAction; import org.eclipse.jface.viewers.ISelection; diff --git a/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/ui/refactoring/UndoAction.java b/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/ui/refactoring/UndoAction.java new file mode 100644 index 00000000000..8fe179052d7 --- /dev/null +++ b/core/org.eclipse.cdt.ui/refactor/org/eclipse/cdt/ui/refactoring/UndoAction.java @@ -0,0 +1,86 @@ +/********************************************************************** + * Copyright (c) 2004 Rational Software Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * IBM Rational Software - Initial API and implementation +***********************************************************************/ + +package org.eclipse.cdt.ui.refactoring; + +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.internal.ui.refactoring.actions.UndoRefactoringAction; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.ui.IViewActionDelegate; +import org.eclipse.ui.IViewPart; + +/** + * TODO: Provide description for "RefactoringRenameAction". + */ +public class UndoAction extends Action implements IViewActionDelegate { +// private IViewPart fView; +// private IAction fAction; + UndoRefactoringAction refactoringAction = new UndoRefactoringAction(); + +// protected IViewPart getView() { +// return fView; +// } + +// protected void setView(IViewPart view) { +// fView = view; +// } +// protected IAction getAction() { +// return fAction; +// } + +// protected void setAction(IAction action) { +// fAction = action; +// } + /** + * TODO: Implement the "RefactoringRenameAction" constructor. + */ + public UndoAction() { + } + /* (non-Javadoc) + * @see org.eclipse.ui.IViewActionDelegate#init(org.eclipse.ui.IViewPart) + */ + public void init(IViewPart view) { +// setView(view); + refactoringAction.init(view.getSite().getWorkbenchWindow()); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction) + */ + public void run(IAction action) { + refactoringAction.run(action); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.IActionDelegate#selectionChanged(org.eclipse.jface.action.IAction, org.eclipse.jface.viewers.ISelection) + */ + public void selectionChanged(IAction action, ISelection selection) { + refactoringAction.selectionChanged(action, selection); +// setAction(action); +// if (!(selection instanceof IStructuredSelection)) { +// return; +// } +// IStructuredSelection sel= (IStructuredSelection)selection; +// Object o= sel.getFirstElement(); +// if (!(o instanceof ICElement)) { +// return; +// } + } + +// private IStructuredSelection getSelection() { +// return (IStructuredSelection)getView().getViewSite().getSelectionProvider().getSelection(); +// } + +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CUIPlugin.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CUIPlugin.java index 96b2695c928..b6ac7e72d40 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CUIPlugin.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CUIPlugin.java @@ -25,6 +25,7 @@ import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.core.model.IWorkingCopy; import org.eclipse.cdt.internal.core.model.IBufferFactory; +import org.eclipse.cdt.internal.corext.refactoring.base.Refactoring; import org.eclipse.cdt.internal.ui.BuildConsoleManager; import org.eclipse.cdt.internal.ui.CElementAdapterFactory; import org.eclipse.cdt.internal.ui.CPluginImages; @@ -34,7 +35,6 @@ import org.eclipse.cdt.internal.ui.editor.CDocumentProvider; import org.eclipse.cdt.internal.ui.editor.SharedTextColors; import org.eclipse.cdt.internal.ui.editor.WorkingCopyManager; import org.eclipse.cdt.internal.ui.editor.asm.AsmTextTools; -import org.eclipse.cdt.ui.browser.typeinfo.AllTypesCache; import org.eclipse.cdt.internal.ui.preferences.BuildConsolePreferencePage; import org.eclipse.cdt.internal.ui.preferences.CEditorPreferencePage; import org.eclipse.cdt.internal.ui.preferences.CPluginPreferencePage; @@ -42,6 +42,7 @@ import org.eclipse.cdt.internal.ui.text.CTextTools; import org.eclipse.cdt.internal.ui.util.ImageDescriptorRegistry; import org.eclipse.cdt.internal.ui.util.ProblemMarkerManager; import org.eclipse.cdt.internal.ui.util.Util; +import org.eclipse.cdt.ui.browser.typeinfo.AllTypesCache; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.ResourcesPlugin; @@ -304,6 +305,7 @@ public class CUIPlugin extends AbstractUIPlugin { fDocumentProvider.shutdown(); fDocumentProvider= null; } + Refactoring.getUndoManager().shutdown(); } private void runUI(Runnable run) { diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/actions/RenameAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/actions/RenameAction.java index 774d33879c2..ee8b7ffa0eb 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/actions/RenameAction.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/actions/RenameAction.java @@ -12,7 +12,7 @@ package org.eclipse.cdt.ui.actions; import org.eclipse.cdt.internal.ui.ICHelpContextIds; import org.eclipse.cdt.internal.ui.refactoring.RefactoringMessages; -import org.eclipse.cdt.internal.ui.refactoring.RenameRefactoringAction; +import org.eclipse.cdt.internal.ui.refactoring.actions.RenameRefactoringAction; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.SelectionChangedEvent;