/* ******************************************************************************
* Copyright (c) 2006-2012 XMind Ltd. and others.
*
* This file is a part of XMind 3. XMind releases 3 and
* above are dual-licensed under the Eclipse Public License (EPL),
* which is available at http://www.eclipse.org/legal/epl-v10.html
* and the GNU Lesser General Public License (LGPL),
* which is available at http://www.gnu.org/licenses/lgpl.html
* See http://www.xmind.net/license.html for details.
*
* Contributors:
* XMind Ltd. - initial API and implementation
*******************************************************************************/
package org.xmind.gef;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.xmind.gef.command.CommandStackEvent;
import org.xmind.gef.command.ICommandStack;
import org.xmind.gef.command.ICommandStackListener;
public class SelectionStack implements ISelectionStack, ICommandStackListener {
private ISelectionProvider selectionProvider = null;
private ICommandStack commandStack = null;
private List<ISelection> selections = null;
private int cursor = 0;
/*
* (non-Javadoc)
*
* @see
* org.xmind.ui.mindmap.editor.ISelectionStack#setSelectionProvider(org.
* eclipse.jface.viewers.ISelectionProvider)
*/
public void setSelectionProvider(ISelectionProvider selectionProvider) {
if (selectionProvider == this.selectionProvider)
return;
this.selectionProvider = selectionProvider;
this.selections = null;
this.cursor = 0;
}
/*
* (non-Javadoc)
*
* @see
* org.xmind.ui.mindmap.editor.ISelectionStack#setCommandStack(org.xmind
* .gef.command.ICommandStack)
*/
public void setCommandStack(ICommandStack commandStack) {
ICommandStack oldCS = this.commandStack;
if (commandStack == oldCS)
return;
if (oldCS != null) {
oldCS.removeCSListener(this);
}
this.commandStack = commandStack;
if (commandStack != null) {
commandStack.addCSListener(this);
}
}
public void handleCommandStackEvent(CommandStackEvent event) {
if (selectionProvider == null)
return;
if (selections == null)
selections = new ArrayList<ISelection>(30);
if ((event.getStatus() & GEF.CS_PRE_EXECUTE) != 0)
preExecute();
else if ((event.getStatus() & GEF.CS_PRE_UNDO) != 0)
preUndo();
else if ((event.getStatus() & GEF.CS_PRE_REDO) != 0)
preRedo();
else if ((event.getStatus() & GEF.CS_POST_EXECUTE) != 0)
postExecute();
else if ((event.getStatus() & GEF.CS_POST_UNDO) != 0)
postUndo();
else if ((event.getStatus() & GEF.CS_POST_REDO) != 0)
postRedo();
}
/**
* Snapshots the current selection and push it into stack, and clear all
* cached selections from the current position on.
*/
protected void preExecute() {
clearFromCursor();
if (cursor >= 0 && cursor <= selections.size()) {
ISelection selection = selectionProvider.getSelection();
selections.add(cursor, selection);
}
}
/**
* Clears all cached selections from the current position on.
*/
protected void clearFromCursor() {
if (cursor <= 0) {
selections.clear();
} else {
while (cursor < selections.size()) {
selections.remove(selections.size() - 1);
}
}
}
/**
* Try to preserve the previous selection after a command is executed.
*/
protected void postExecute() {
restoreSelection();
++cursor;
}
/**
* Snapshots the current selection and push it into the stack if there's no
* selection on the current position before a command is about to be undone.
*/
protected void preUndo() {
ISelection selection = selectionProvider.getSelection();
if (cursor == selections.size()) {
selections.add(cursor, selection);
} else if (cursor >= 0 && cursor < selections.size()) {
// ISelection cached = selections.get(cursor);
// if (cached == null)
selections.set(cursor, selection);
}
}
/**
* Restores the previous selection that had been cached before this command
* was executed or redone.
*/
protected void postUndo() {
--cursor;
restoreSelection();
}
/**
* Snapshots the current selection and push it into the stack if there's no
* selection on the current position before a command is about to be redone.
*/
protected void preRedo() {
if (cursor >= 0 && cursor < selections.size()) {
// ISelection cached = selections.get(cursor);
// if (cached == null) {
ISelection selection = selectionProvider.getSelection();
selections.set(cursor, selection);
// }
} else if (cursor == selections.size()) {
ISelection selection = selectionProvider.getSelection();
selections.add(cursor, selection);
}
}
/**
* Restores the previous selection that had been cached before this command
* was undone.
*/
protected void postRedo() {
++cursor;
restoreSelection();
}
/**
* Restores the current selection to the selection provider. Does nothing is
* no selection is accessible.
*/
protected void restoreSelection() {
if (cursor >= 0 && cursor < selections.size()) {
ISelection selection = selections.get(cursor);
if (selection != null) {
selectionProvider.setSelection(selection);
}
}
}
}