Methods Summary |
---|
public void | addOperation(UndoOperation op, int mergeMode)Add a new UndoOperation to the current update.
if (mWorking == null) {
throw new IllegalStateException("Must be called during an update");
}
UndoOwner owner = op.getOwner();
if (owner.mManager != this) {
throw new IllegalArgumentException(
"Given operation's owner is not in this undo manager.");
}
if (mergeMode != MERGE_MODE_NONE && !mMerged && !mWorking.hasData()) {
UndoState state = getTopUndo(null);
if (state != null && (mergeMode == MERGE_MODE_ANY || !state.hasMultipleOwners())
&& state.canMerge() && state.hasOperation(op.getOwner())) {
mWorking.destroy();
mWorking = state;
mUndos.remove(state);
mMerged = true;
}
}
mWorking.addOperation(op);
|
public void | beginUpdate(java.lang.CharSequence label)Start creating a new undo state. Multiple calls to this function will nest until
they are all matched by a later call to {@link #endUpdate}.
if (mInUndo) {
throw new IllegalStateException("Can't being update while performing undo/redo");
}
if (mUpdateCount <= 0) {
createWorkingState();
mMerged = false;
mUpdateCount = 0;
}
mWorking.updateLabel(label);
mUpdateCount++;
|
public int | commitState(UndoOwner owner)Commit the last finished undo state. This undo state can no longer be
modified with further {@link #MERGE_MODE_UNIQUE} or
{@link #MERGE_MODE_ANY} merge modes. If called while inside of an update,
this will push any changes in the current update on to the undo stack
and result with a fresh undo state, behaving as if {@link #endUpdate()}
had been called enough to unwind the current update, then the last state
committed, and {@link #beginUpdate} called to restore the update nesting.
if (mWorking != null && mWorking.hasData()) {
if (owner == null || mWorking.hasOperation(owner)) {
mWorking.setCanMerge(false);
int commitId = mWorking.getCommitId();
pushWorkingState();
createWorkingState();
mMerged = true;
return commitId;
}
} else {
UndoState state = getTopUndo(null);
if (state != null && (owner == null || state.hasOperation(owner))) {
state.setCanMerge(false);
return state.getCommitId();
}
}
return -1;
|
public int | countRedos(UndoOwner[] owners)Return the number of redo states on the undo stack.
if (owners == null) {
return mRedos.size();
}
int count=0;
int i=0;
while ((i=findNextState(mRedos, owners, i)) >= 0) {
count++;
i++;
}
return count;
|
public int | countUndos(UndoOwner[] owners)Return the number of undo states on the undo stack.
if (owners == null) {
return mUndos.size();
}
int count=0;
int i=0;
while ((i=findNextState(mUndos, owners, i)) >= 0) {
count++;
i++;
}
return count;
|
private void | createWorkingState()
mWorking = new UndoState(this, mCommitId++);
if (mCommitId < 0) {
mCommitId = 1;
}
|
public void | endUpdate()Finish the creation of an undo state, matching a previous call to
{@link #beginUpdate}.
if (mWorking == null) {
throw new IllegalStateException("Must be called during an update");
}
mUpdateCount--;
if (mUpdateCount == 0) {
pushWorkingState();
}
|
int | findNextState(java.util.ArrayList states, UndoOwner[] owners, int from)
final int N = states.size();
if (from < 0) {
from = 0;
}
if (from >= N) {
return -1;
}
if (owners == null) {
return from;
}
while (from < N) {
UndoState state = states.get(from);
if (matchOwners(state, owners)) {
return from;
}
from++;
}
return -1;
|
int | findPrevState(java.util.ArrayList states, UndoOwner[] owners, int from)
final int N = states.size();
if (from == -1) {
from = N-1;
}
if (from >= N) {
return -1;
}
if (owners == null) {
return from;
}
while (from >= 0) {
UndoState state = states.get(from);
if (matchOwners(state, owners)) {
return from;
}
from--;
}
return -1;
|
public int | forgetRedos(UndoOwner[] owners, int count)
if (count < 0) {
count = mRedos.size();
}
int removed = 0;
for (int i=0; i<mRedos.size() && removed < count; i++) {
UndoState state = mRedos.get(i);
if (count > 0 && matchOwners(state, owners)) {
state.destroy();
mRedos.remove(i);
removed++;
}
}
return removed;
|
public int | forgetUndos(UndoOwner[] owners, int count)
if (count < 0) {
count = mUndos.size();
}
int removed = 0;
for (int i=0; i<mUndos.size() && removed < count; i++) {
UndoState state = mUndos.get(i);
if (count > 0 && matchOwners(state, owners)) {
state.destroy();
mUndos.remove(i);
removed++;
}
}
return removed;
|
public int | getHistorySize()Return the current maximum number of undo states.
return mHistorySize;
|
public UndoOperation | getLastOperation(int mergeMode)Return the most recent {@link UndoOperation} that was added to the update.
return getLastOperation(null, null, mergeMode);
|
public UndoOperation | getLastOperation(UndoOwner owner, int mergeMode)Return the most recent {@link UndoOperation} that was added to the update and
has the given owner.
return getLastOperation(null, owner, mergeMode);
|
public T | getLastOperation(java.lang.Class clazz, UndoOwner owner, int mergeMode)Return the most recent {@link UndoOperation} that was added to the update and
has the given owner.
if (mWorking == null) {
throw new IllegalStateException("Must be called during an update");
}
if (mergeMode != MERGE_MODE_NONE && !mMerged && !mWorking.hasData()) {
UndoState state = getTopUndo(null);
UndoOperation<?> last;
if (state != null && (mergeMode == MERGE_MODE_ANY || !state.hasMultipleOwners())
&& state.canMerge() && (last=state.getLastOperation(clazz, owner)) != null) {
if (last.allowMerge()) {
mWorking.destroy();
mWorking = state;
mUndos.remove(state);
mMerged = true;
return (T)last;
}
}
}
return mWorking.getLastOperation(clazz, owner);
|
public UndoOwner | getOwner(java.lang.String tag, java.lang.Object data)
if (tag == null) {
throw new NullPointerException("tag can't be null");
}
if (data == null) {
throw new NullPointerException("data can't be null");
}
UndoOwner owner = mOwners.get(tag);
if (owner != null) {
if (owner.mData != data) {
if (owner.mData != null) {
throw new IllegalStateException("Owner " + owner + " already exists with data "
+ owner.mData + " but giving different data " + data);
}
owner.mData = data;
}
return owner;
}
owner = new UndoOwner(tag);
owner.mManager = this;
owner.mData = data;
mOwners.put(tag, owner);
return owner;
|
public java.lang.CharSequence | getRedoLabel(UndoOwner[] owners)Return the user-visible label for the top redo state on the stack.
UndoState state = getTopRedo(owners);
return state != null ? state.getLabel() : null;
|
android.content.UndoManager$UndoState | getTopRedo(UndoOwner[] owners)
if (mRedos.size() <= 0) {
return null;
}
int i = findPrevState(mRedos, owners, -1);
return i >= 0 ? mRedos.get(i) : null;
|
android.content.UndoManager$UndoState | getTopUndo(UndoOwner[] owners)
if (mUndos.size() <= 0) {
return null;
}
int i = findPrevState(mUndos, owners, -1);
return i >= 0 ? mUndos.get(i) : null;
|
public java.lang.CharSequence | getUndoLabel(UndoOwner[] owners)Return the user-visible label for the top undo state on the stack.
UndoState state = getTopUndo(owners);
return state != null ? state.getLabel() : null;
|
public int | getUpdateNestingLevel()Return the number of times {@link #beginUpdate} has been called without a matching
{@link #endUpdate} call.
return mUpdateCount;
|
public boolean | hasOperation(UndoOwner owner)Check whether there is an {@link UndoOperation} in the current {@link #beginUpdate}
undo state.
if (mWorking == null) {
throw new IllegalStateException("Must be called during an update");
}
return mWorking.hasOperation(owner);
|
public boolean | isInUndo()Returns true if we are currently inside of an undo/redo operation. This is
useful for editors to know whether they should be generating new undo state
when they see edit operations happening.
return mInUndo;
|
public boolean | isInUpdate()Returns true if currently inside of a {@link #beginUpdate}.
return mUpdateCount > 0;
|
boolean | matchOwners(android.content.UndoManager$UndoState state, UndoOwner[] owners)
if (owners == null) {
return true;
}
for (int i=0; i<owners.length; i++) {
if (state.matchOwner(owners[i])) {
return true;
}
}
return false;
|
private void | pushWorkingState()
int N = mUndos.size() + 1;
if (mWorking.hasData()) {
mUndos.add(mWorking);
forgetRedos(null, -1);
mWorking.commit();
if (N >= 2) {
// The state before this one can no longer be merged, ever.
// The only way to get back to it is for the user to perform
// an undo.
mUndos.get(N-2).makeExecuted();
}
} else {
mWorking.destroy();
}
mWorking = null;
if (mHistorySize >= 0 && N > mHistorySize) {
forgetUndos(null, N - mHistorySize);
}
|
public int | redo(UndoOwner[] owners, int count)Perform redo of last/top count undo states in the transient redo stack.
The states impacted by this can be limited through owners.
if (mWorking != null) {
throw new IllegalStateException("Can't be called during an update");
}
int num = 0;
int i = -1;
mInUndo = true;
while (count > 0 && (i=findPrevState(mRedos, owners, i)) >= 0) {
UndoState state = mRedos.remove(i);
state.redo();
mUndos.add(state);
count--;
num++;
}
mInUndo = false;
return num;
|
void | removeOwner(UndoOwner owner)
// XXX need to figure out how to prune.
if (false) {
mOwners.remove(owner.mTag);
owner.mManager = null;
}
|
public void | restoreInstanceState(android.os.Parcelable state)Restore an undo state previously created with {@link #saveInstanceState()}. This will
restore the UndoManager's state to almost exactly what it was at the point it had
been previously saved; the only information not restored is the data object
associated with each {@link UndoOwner}, which requires separate calls to
{@link #getOwner(String, Object)} to re-associate the owner with its data.
if (mUpdateCount > 0) {
throw new IllegalStateException("Can't save state while updating");
}
forgetUndos(null, -1);
forgetRedos(null, -1);
ParcelableParcel pp = (ParcelableParcel)state;
Parcel p = pp.getParcel();
mHistorySize = p.readInt();
mStateOwners = new UndoOwner[p.readInt()];
int stype;
while ((stype=p.readInt()) != 0) {
UndoState ustate = new UndoState(this, p, pp.getClassLoader());
if (stype == 1) {
mUndos.add(0, ustate);
} else {
mRedos.add(0, ustate);
}
}
|
UndoOwner | restoreOwner(android.os.Parcel in)
int idx = in.readInt();
UndoOwner owner = mStateOwners[idx];
if (owner == null) {
String tag = in.readString();
owner = new UndoOwner(tag);
mStateOwners[idx] = owner;
mOwners.put(tag, owner);
}
return owner;
|
public android.os.Parcelable | saveInstanceState()Flatten the current undo state into a Parcelable object, which can later be restored
with {@link #restoreInstanceState(android.os.Parcelable)}.
if (mUpdateCount > 0) {
throw new IllegalStateException("Can't save state while updating");
}
ParcelableParcel pp = new ParcelableParcel(getClass().getClassLoader());
Parcel p = pp.getParcel();
mStateSeq++;
if (mStateSeq <= 0) {
mStateSeq = 0;
}
mNextSavedIdx = 0;
p.writeInt(mHistorySize);
p.writeInt(mOwners.size());
// XXX eventually we need to be smart here about limiting the
// number of undo states we write to not exceed X bytes.
int i = mUndos.size();
while (i > 0) {
p.writeInt(1);
i--;
mUndos.get(i).writeToParcel(p);
}
i = mRedos.size();
p.writeInt(i);
while (i > 0) {
p.writeInt(2);
i--;
mRedos.get(i).writeToParcel(p);
}
p.writeInt(0);
return pp;
|
void | saveOwner(UndoOwner owner, android.os.Parcel out)
if (owner.mStateSeq == mStateSeq) {
out.writeInt(owner.mSavedIdx);
} else {
owner.mStateSeq = mStateSeq;
owner.mSavedIdx = mNextSavedIdx;
out.writeInt(owner.mSavedIdx);
out.writeString(owner.mTag);
mNextSavedIdx++;
}
|
public void | setHistorySize(int size)Set the maximum number of undo states that will be retained.
mHistorySize = size;
if (mHistorySize >= 0 && countUndos(null) > mHistorySize) {
forgetUndos(null, countUndos(null) - mHistorySize);
}
|
public void | setUndoLabel(java.lang.CharSequence label)Forcibly set a new for the new undo state being built within a {@link #beginUpdate}.
Any existing label will be replaced with this one.
if (mWorking == null) {
throw new IllegalStateException("Must be called during an update");
}
mWorking.setLabel(label);
|
public void | suggestUndoLabel(java.lang.CharSequence label)Set a new for the new undo state being built within a {@link #beginUpdate}, but
only if there is not a label currently set for it.
if (mWorking == null) {
throw new IllegalStateException("Must be called during an update");
}
mWorking.updateLabel(label);
|
public boolean | uncommitState(int commitId, UndoOwner owner)Attempt to undo a previous call to {@link #commitState}. This will work
if the undo state at the top of the stack has the given id, and has not been
involved in an undo operation. Otherwise false is returned.
if (mWorking != null && mWorking.getCommitId() == commitId) {
if (owner == null || mWorking.hasOperation(owner)) {
return mWorking.setCanMerge(true);
}
} else {
UndoState state = getTopUndo(null);
if (state != null && (owner == null || state.hasOperation(owner))) {
if (state.getCommitId() == commitId) {
return state.setCanMerge(true);
}
}
}
return false;
|
public int | undo(UndoOwner[] owners, int count)Perform undo of last/top count undo states. The states impacted
by this can be limited through owners.
if (mWorking != null) {
throw new IllegalStateException("Can't be called during an update");
}
int num = 0;
int i = -1;
mInUndo = true;
UndoState us = getTopUndo(null);
if (us != null) {
us.makeExecuted();
}
while (count > 0 && (i=findPrevState(mUndos, owners, i)) >= 0) {
UndoState state = mUndos.remove(i);
state.undo();
mRedos.add(state);
count--;
num++;
}
mInUndo = false;
return num;
|