001: /*******************************************************************************
002: * Copyright (c) 2005, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.ui.operations;
011:
012: import org.eclipse.core.commands.ExecutionException;
013: import org.eclipse.core.commands.operations.IOperationHistory;
014: import org.eclipse.core.commands.operations.IUndoContext;
015: import org.eclipse.core.commands.operations.IUndoableOperation;
016: import org.eclipse.core.commands.operations.LinearUndoViolationDetector;
017: import org.eclipse.core.runtime.IAdaptable;
018: import org.eclipse.core.runtime.IStatus;
019: import org.eclipse.core.runtime.Status;
020: import org.eclipse.jface.dialogs.MessageDialog;
021: import org.eclipse.osgi.util.NLS;
022: import org.eclipse.ui.IWorkbenchPart;
023: import org.eclipse.ui.IWorkbenchPart2;
024: import org.eclipse.ui.internal.Workbench;
025: import org.eclipse.ui.internal.WorkbenchMessages;
026:
027: /**
028: * <p>
029: * An operation approver that prompts the user to see if linear undo violations
030: * are permitted. A linear undo violation is detected when an operation being
031: * undone or redone shares an undo context with another operation appearing more
032: * recently in the history.
033: * </p>
034: * <p>
035: * This class may be instantiated by clients.
036: * </p>
037: *
038: * @since 3.1
039: */
040: public final class LinearUndoViolationUserApprover extends
041: LinearUndoViolationDetector {
042:
043: private IWorkbenchPart part;
044:
045: private IUndoContext context;
046:
047: /**
048: * Create a LinearUndoViolationUserApprover associated with the specified
049: * workbench part.
050: *
051: * @param context
052: * the undo context with the linear undo violation
053: * @param part
054: * the part that should be used for prompting the user
055: */
056: public LinearUndoViolationUserApprover(IUndoContext context,
057: IWorkbenchPart part) {
058: super ();
059: this .part = part;
060: this .context = context;
061: }
062:
063: /*
064: * (non-Javadoc)
065: *
066: * @see org.eclipse.core.commands.operations.LinearUndoViolationDetector#allowLinearRedoViolation(org.eclipse.core.commands.operations.IUndoableOperation,
067: * org.eclipse.core.commands.operations.IUndoContext,
068: * org.eclipse.core.commands.operations.IOperationHistory,
069: * org.eclipse.core.runtime.IAdaptable)
070: */
071: protected IStatus allowLinearRedoViolation(
072: IUndoableOperation operation, IUndoContext context,
073: IOperationHistory history, IAdaptable uiInfo) {
074:
075: if (this .context != context) {
076: return Status.OK_STATUS;
077: }
078:
079: final String message = NLS.bind(
080: WorkbenchMessages.Operations_linearRedoViolation,
081: getTitle(part), operation.getLabel());
082: final boolean[] proceed = new boolean[1];
083: Workbench.getInstance().getDisplay().syncExec(new Runnable() {
084: public void run() {
085: // Show a dialog.
086: part.setFocus();
087: proceed[0] = MessageDialog.openQuestion(part.getSite()
088: .getShell(), getTitle(part), message);
089: }
090: });
091:
092: if (proceed[0]) {
093: // redo the local changes first
094: while (operation != history.getRedoOperation(context)) {
095: try {
096: IStatus status = history
097: .redo(context, null, uiInfo);
098: if (!status.isOK()) {
099: // flush the redo history because the operation
100: // failed
101: history.dispose(context, false, true, false);
102: return Status.CANCEL_STATUS;
103: }
104: } catch (ExecutionException e) {
105: // flush the redo history here because it failed.
106: history.dispose(context, false, true, false);
107: return Status.CANCEL_STATUS;
108: }
109: }
110: return Status.OK_STATUS;
111: }
112:
113: return Status.CANCEL_STATUS;
114: }
115:
116: /*
117: * (non-Javadoc)
118: *
119: * @see org.eclipse.core.commands.operations.LinearUndoViolationDetector#allowLinearUndoViolation(org.eclipse.core.commands.operations.IUndoableOperation,
120: * org.eclipse.core.commands.operations.IUndoContext,
121: * org.eclipse.core.commands.operations.IOperationHistory,
122: * org.eclipse.core.runtime.IAdaptable)
123: */
124: protected IStatus allowLinearUndoViolation(
125: IUndoableOperation operation, IUndoContext context,
126: IOperationHistory history, IAdaptable uiInfo) {
127:
128: if (this .context != context) {
129: return Status.OK_STATUS;
130: }
131:
132: final String message = NLS.bind(
133: WorkbenchMessages.Operations_linearUndoViolation,
134: getTitle(part), operation.getLabel());
135: final boolean[] proceed = new boolean[1];
136: Workbench.getInstance().getDisplay().syncExec(new Runnable() {
137: public void run() {
138: // Show a dialog.
139: part.setFocus();
140: proceed[0] = MessageDialog.openQuestion(part.getSite()
141: .getShell(), getTitle(part), message);
142: }
143: });
144:
145: if (proceed[0]) {
146: // redo the local changes first
147: while (operation != history.getUndoOperation(context)) {
148: try {
149: IStatus status = history
150: .undo(context, null, uiInfo);
151: if (!status.isOK()) {
152: // flush the operation history because the operation
153: // failed.
154: history.dispose(context, true, false, false);
155: return Status.CANCEL_STATUS;
156: }
157: } catch (ExecutionException e) {
158: // flush the undo history here because something went wrong.
159: history.dispose(context, true, false, false);
160: return Status.CANCEL_STATUS;
161: }
162: }
163: return Status.OK_STATUS;
164: }
165: return Status.CANCEL_STATUS;
166: }
167:
168: /*
169: * Get the title for the specified part. Use the newer interface
170: * IWorkbenchPart2 if available.
171: */
172: private String getTitle(IWorkbenchPart part) {
173: String title;
174: if (part instanceof IWorkbenchPart2) {
175: title = ((IWorkbenchPart2) part).getPartName();
176: } else {
177: title = part.getTitle();
178: }
179: // Null title is unexpected, but use an empty string if encountered.
180: if (title == null) {
181: title = ""; //$NON-NLS-1$
182: }
183: return title;
184: }
185: }
|