1. /*
  2. * @(#)CompoundEdit.java 1.25 04/05/05
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package javax.swing.undo;
  8. import java.util.*;
  9. /**
  10. * A concrete subclass of AbstractUndoableEdit, used to assemble little
  11. * UndoableEdits into great big ones.
  12. *
  13. * @version 1.25 05/05/04
  14. * @author Ray Ryan
  15. */
  16. public class CompoundEdit extends AbstractUndoableEdit {
  17. /**
  18. * True if this edit has never received <code>end</code>.
  19. */
  20. boolean inProgress;
  21. /**
  22. * The collection of <code>UndoableEdit</code>s
  23. * undone/redone en masse by this <code>CompoundEdit</code>.
  24. */
  25. protected Vector<UndoableEdit> edits;
  26. public CompoundEdit() {
  27. super();
  28. inProgress = true;
  29. edits = new Vector<UndoableEdit>();
  30. }
  31. /**
  32. * Sends <code>undo</code> to all contained
  33. * <code>UndoableEdits</code> in the reverse of
  34. * the order in which they were added.
  35. */
  36. public void undo() throws CannotUndoException {
  37. super.undo();
  38. int i = edits.size();
  39. while (i-- > 0) {
  40. UndoableEdit e = (UndoableEdit)edits.elementAt(i);
  41. e.undo();
  42. }
  43. }
  44. /**
  45. * Sends <code>redo</code> to all contained
  46. * <code>UndoableEdit</code>s in the order in
  47. * which they were added.
  48. */
  49. public void redo() throws CannotRedoException {
  50. super.redo();
  51. Enumeration cursor = edits.elements();
  52. while (cursor.hasMoreElements()) {
  53. ((UndoableEdit)cursor.nextElement()).redo();
  54. }
  55. }
  56. /**
  57. * Returns the last <code>UndoableEdit</code> in
  58. * <code>edits</code>, or <code>null</code>
  59. * if <code>edits</code> is empty.
  60. */
  61. protected UndoableEdit lastEdit() {
  62. int count = edits.size();
  63. if (count > 0)
  64. return (UndoableEdit)edits.elementAt(count-1);
  65. else
  66. return null;
  67. }
  68. /**
  69. * Sends <code>die</code> to each subedit,
  70. * in the reverse of the order that they were added.
  71. */
  72. public void die() {
  73. int size = edits.size();
  74. for (int i = size-1; i >= 0; i--)
  75. {
  76. UndoableEdit e = (UndoableEdit)edits.elementAt(i);
  77. // System.out.println("CompoundEdit(" + i + "): Discarding " +
  78. // e.getUndoPresentationName());
  79. e.die();
  80. }
  81. super.die();
  82. }
  83. /**
  84. * If this edit is <code>inProgress</code>,
  85. * accepts <code>anEdit</code> and returns true.
  86. *
  87. * <p>The last edit added to this <code>CompoundEdit</code>
  88. * is given a chance to <code>addEdit(anEdit)</code>.
  89. * If it refuses (returns false), <code>anEdit</code> is
  90. * given a chance to <code>replaceEdit</code> the last edit.
  91. * If <code>anEdit</code> returns false here,
  92. * it is added to <code>edits</code>.
  93. *
  94. * @param anEdit the edit to be added
  95. * @return true if the edit is <code>inProgress</code>
  96. * otherwise returns false
  97. */
  98. public boolean addEdit(UndoableEdit anEdit) {
  99. if (!inProgress) {
  100. return false;
  101. } else {
  102. UndoableEdit last = lastEdit();
  103. // If this is the first subedit received, just add it.
  104. // Otherwise, give the last one a chance to absorb the new
  105. // one. If it won't, give the new one a chance to absorb
  106. // the last one.
  107. if (last == null) {
  108. edits.addElement(anEdit);
  109. }
  110. else if (!last.addEdit(anEdit)) {
  111. if (anEdit.replaceEdit(last)) {
  112. edits.removeElementAt(edits.size()-1);
  113. }
  114. edits.addElement(anEdit);
  115. }
  116. return true;
  117. }
  118. }
  119. /**
  120. * Sets <code>inProgress</code> to false.
  121. *
  122. * @see #canUndo
  123. * @see #canRedo
  124. */
  125. public void end() {
  126. inProgress = false;
  127. }
  128. /**
  129. * Returns false if <code>isInProgress</code> or if super
  130. * returns false.
  131. *
  132. * @see #isInProgress
  133. */
  134. public boolean canUndo() {
  135. return !isInProgress() && super.canUndo();
  136. }
  137. /**
  138. * Returns false if <code>isInProgress</code> or if super
  139. * returns false.
  140. *
  141. * @see #isInProgress
  142. */
  143. public boolean canRedo() {
  144. return !isInProgress() && super.canRedo();
  145. }
  146. /**
  147. * Returns true if this edit is in progress--that is, it has not
  148. * received end. This generally means that edits are still being
  149. * added to it.
  150. *
  151. * @see #end
  152. */
  153. public boolean isInProgress() {
  154. return inProgress;
  155. }
  156. /**
  157. * Returns true if any of the <code>UndoableEdit</code>s
  158. * in <code>edits</code> do.
  159. * Returns false if they all return false.
  160. */
  161. public boolean isSignificant() {
  162. Enumeration cursor = edits.elements();
  163. while (cursor.hasMoreElements()) {
  164. if (((UndoableEdit)cursor.nextElement()).isSignificant()) {
  165. return true;
  166. }
  167. }
  168. return false;
  169. }
  170. /**
  171. * Returns <code>getPresentationName</code> from the
  172. * last <code>UndoableEdit</code> added to
  173. * <code>edits</code>. If <code>edits</code> is empty,
  174. * calls super.
  175. */
  176. public String getPresentationName() {
  177. UndoableEdit last = lastEdit();
  178. if (last != null) {
  179. return last.getPresentationName();
  180. } else {
  181. return super.getPresentationName();
  182. }
  183. }
  184. /**
  185. * Returns <code>getUndoPresentationName</code>
  186. * from the last <code>UndoableEdit</code>
  187. * added to <code>edits</code>.
  188. * If <code>edits</code> is empty, calls super.
  189. */
  190. public String getUndoPresentationName() {
  191. UndoableEdit last = lastEdit();
  192. if (last != null) {
  193. return last.getUndoPresentationName();
  194. } else {
  195. return super.getUndoPresentationName();
  196. }
  197. }
  198. /**
  199. * Returns <code>getRedoPresentationName</code>
  200. * from the last <code>UndoableEdit</code>
  201. * added to <code>edits</code>.
  202. * If <code>edits</code> is empty, calls super.
  203. */
  204. public String getRedoPresentationName() {
  205. UndoableEdit last = lastEdit();
  206. if (last != null) {
  207. return last.getRedoPresentationName();
  208. } else {
  209. return super.getRedoPresentationName();
  210. }
  211. }
  212. /**
  213. * Returns a string that displays and identifies this
  214. * object's properties.
  215. *
  216. * @return a String representation of this object
  217. */
  218. public String toString()
  219. {
  220. return super.toString()
  221. + " inProgress: " + inProgress
  222. + " edits: " + edits;
  223. }
  224. }