001: /*
002: * (C) Copyright IBM Corp. 1998-2004. All Rights Reserved.
003: *
004: * The program is provided "as is" without any warranty express or
005: * implied, including the warranty of non-infringement and the implied
006: * warranties of merchantibility and fitness for a particular purpose.
007: * IBM will not be liable for any damages suffered by you as a result
008: * of using the Program. In no event will IBM be liable for any
009: * special, indirect or consequential damages or lost profits even if
010: * IBM has been advised of the possibility of their occurrence. IBM
011: * will not be liable for any third party claims against you.
012: */
013: package com.ibm.richtext.textpanel;
014:
015: final class SimpleCommandLog {
016: static final String COPYRIGHT = "(C) Copyright IBM Corp. 1998-1999 - All Rights Reserved";
017: private Command fLastCommand = null;
018: private Command fCurrentCommand = null;
019: private PanelEventBroadcaster fListener;
020:
021: private boolean fBaseIsModified;
022:
023: private int fLogSize = 14;
024:
025: public SimpleCommandLog(PanelEventBroadcaster listener) {
026: fListener = listener;
027: fBaseIsModified = false;
028: }
029:
030: /** adds the specfied command to the top of the command stack
031: * (any undone commands on the stack are removed)
032: * This function assumes the command has already been executed (i.e., its execute() method
033: * has been called, or an equivalent action has been taken) */
034: void add(Command newCommand) {
035: // if there are commands on the stack that have been undone, they are
036: // dropped on the floor here
037: newCommand.setPreviousCommand(fCurrentCommand);
038:
039: final Command oldLastCommand = fLastCommand;
040: fLastCommand = null;
041:
042: fCurrentCommand = newCommand;
043: limitCommands(fLogSize);
044:
045: if (oldLastCommand != null) {
046: fListener
047: .textStateChanged(TextPanelEvent.UNDO_STATE_CHANGED);
048: }
049: }
050:
051: /**
052: * If the command list is longer than logSize, truncate it.
053: * This method traverses the list each time, and is not a model
054: * of efficiency. It's a temporary way to plug this memory leak
055: * until I can implement a bounded command log.
056: */
057: private void limitCommands(int logSize) {
058:
059: if (logSize == 0) {
060: fCurrentCommand = null;
061: } else {
062: Command currentCommand = fCurrentCommand;
063: int remaining = logSize - 1;
064: while (currentCommand != null && remaining > 0) {
065: currentCommand = currentCommand.previousCommand();
066: remaining -= 1;
067: }
068: if (currentCommand != null) {
069: currentCommand.setPreviousCommand(null);
070: }
071: }
072: }
073:
074: /** adds the specfied command to the top of the command stack and executes it */
075: void addAndDo(Command newCommand) {
076: add(newCommand);
077: newCommand.execute();
078:
079: fListener.textStateChanged(TextPanelEvent.UNDO_STATE_CHANGED);
080: }
081:
082: /** undoes the command on the top of the command stack, if there is one */
083: void undo() {
084: if (fCurrentCommand != null) {
085: Command current = fCurrentCommand;
086: current.undo();
087:
088: fCurrentCommand = current.previousCommand();
089:
090: current.setPreviousCommand(fLastCommand);
091: fLastCommand = current;
092:
093: fListener
094: .textStateChanged(TextPanelEvent.UNDO_STATE_CHANGED);
095: }
096: }
097:
098: /** redoes the last undone command on the command stack, if there are any */
099: void redo() {
100: if (fLastCommand != null) {
101: Command last = fLastCommand;
102: last.redo();
103:
104: fLastCommand = last.previousCommand();
105:
106: last.setPreviousCommand(fCurrentCommand);
107: fCurrentCommand = last;
108:
109: fListener
110: .textStateChanged(TextPanelEvent.UNDO_STATE_CHANGED);
111: }
112: }
113:
114: public boolean canUndo() {
115: return fCurrentCommand != null;
116: }
117:
118: public boolean canRedo() {
119: return fLastCommand != null;
120: }
121:
122: public boolean isModified() {
123:
124: if (fCurrentCommand == null) {
125: return fBaseIsModified;
126: } else {
127: return fCurrentCommand.isModified();
128: }
129: }
130:
131: public void setModified(boolean modified) {
132:
133: if (fCurrentCommand == null) {
134: fBaseIsModified = modified;
135: } else {
136: fCurrentCommand.setModified(modified);
137: }
138: }
139:
140: public void clearLog() {
141:
142: if (fCurrentCommand != null) {
143: fBaseIsModified = fCurrentCommand.isModified();
144: }
145: // variable not used boolean changed = fCurrentCommand != null || fLastCommand != null;
146: fCurrentCommand = null;
147: fLastCommand = null;
148:
149: fListener.textStateChanged(TextPanelEvent.UNDO_STATE_CHANGED);
150: }
151:
152: public void setLogSize(int size) {
153:
154: if (size < 0) {
155: throw new IllegalArgumentException(
156: "log size cannot be negative");
157: }
158:
159: if (size < fLogSize) {
160: limitCommands(size);
161: }
162:
163: fLogSize = size;
164:
165: if (fLastCommand != null || size == 0) {
166: fLastCommand = null;
167: fListener
168: .textStateChanged(TextPanelEvent.UNDO_STATE_CHANGED);
169: }
170: }
171:
172: public int getLogSize() {
173:
174: return fLogSize;
175: }
176: }
|