1 /* 2 * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package javax.swing.undo; 27 28 import java.util.Enumeration; 29 import java.util.Hashtable; 30 import java.util.Vector; 31 32 /** 33 * <P>StateEdit is a general edit for objects that change state. 34 * Objects being edited must conform to the StateEditable interface.</P> 35 * 36 * <P>This edit class works by asking an object to store it's state in 37 * Hashtables before and after editing occurs. Upon undo or redo the 38 * object is told to restore it's state from these Hashtables.</P> 39 * 40 * A state edit is used as follows: 41 * <PRE> 42 * // Create the edit during the "before" state of the object 43 * StateEdit newEdit = new StateEdit(myObject); 44 * // Modify the object 45 * myObject.someStateModifyingMethod(); 46 * // "end" the edit when you are done modifying the object 47 * newEdit.end(); 48 * </PRE> 49 * 50 * <P><EM>Note that when a StateEdit ends, it removes redundant state from 51 * the Hashtables - A state Hashtable is not guaranteed to contain all 52 * keys/values placed into it when the state is stored!</EM></P> 53 * 54 * @see StateEditable 55 * 56 * @author Ray Ryan 57 */ 58 @SuppressWarnings("serial") // Same-version serialization only 59 public class StateEdit 60 extends AbstractUndoableEdit { 61 62 /** 63 * Obsolete RCS version identity. 64 */ 65 protected static final String RCSID = "$Id: StateEdit.java,v 1.6 1997/10/01 20:05:51 sandipc Exp $"; 66 67 // 68 // Attributes 69 // 70 71 /** 72 * The object being edited 73 */ 74 protected StateEditable object; 75 76 /** 77 * The state information prior to the edit 78 */ 79 protected Hashtable<Object,Object> preState; 80 81 /** 82 * The state information after the edit 83 */ 84 protected Hashtable<Object,Object> postState; 85 86 /** 87 * The undo/redo presentation name 88 */ 89 protected String undoRedoName; 90 91 // 92 // Constructors 93 // 94 95 /** 96 * Create and return a new StateEdit. 97 * 98 * @param anObject The object to watch for changing state 99 * 100 * @see StateEdit 101 */ StateEdit(StateEditable anObject)102 public StateEdit(StateEditable anObject) { 103 super(); 104 init (anObject,null); 105 } 106 107 /** 108 * Create and return a new StateEdit with a presentation name. 109 * 110 * @param anObject The object to watch for changing state 111 * @param name The presentation name to be used for this edit 112 * 113 * @see StateEdit 114 */ StateEdit(StateEditable anObject, String name)115 public StateEdit(StateEditable anObject, String name) { 116 super(); 117 init (anObject,name); 118 } 119 120 /** 121 * Initialize the state edit. 122 * @param anObject The object to watch for changing state 123 * @param name The presentation name to be used for this edit 124 */ init(StateEditable anObject, String name)125 protected void init (StateEditable anObject, String name) { 126 this.object = anObject; 127 this.preState = new Hashtable<Object, Object>(11); 128 this.object.storeState(this.preState); 129 this.postState = null; 130 this.undoRedoName = name; 131 } 132 133 134 // 135 // Operation 136 // 137 138 139 /** 140 * Gets the post-edit state of the StateEditable object and 141 * ends the edit. 142 */ end()143 public void end() { 144 this.postState = new Hashtable<Object, Object>(11); 145 this.object.storeState(this.postState); 146 this.removeRedundantState(); 147 } 148 149 /** 150 * Tells the edited object to apply the state prior to the edit 151 */ undo()152 public void undo() { 153 super.undo(); 154 this.object.restoreState(preState); 155 } 156 157 /** 158 * Tells the edited object to apply the state after the edit 159 */ redo()160 public void redo() { 161 super.redo(); 162 this.object.restoreState(postState); 163 } 164 165 /** 166 * Gets the presentation name for this edit 167 */ getPresentationName()168 public String getPresentationName() { 169 return this.undoRedoName; 170 } 171 172 173 // 174 // Internal support 175 // 176 177 /** 178 * Remove redundant key/values in state hashtables. 179 */ removeRedundantState()180 protected void removeRedundantState() { 181 Vector<Object> uselessKeys = new Vector<>(); 182 Enumeration<Object> myKeys = preState.keys(); 183 184 // Locate redundant state 185 while (myKeys.hasMoreElements()) { 186 Object myKey = myKeys.nextElement(); 187 if (postState.containsKey(myKey) && 188 postState.get(myKey).equals(preState.get(myKey))) { 189 uselessKeys.addElement(myKey); 190 } 191 } 192 193 // Remove redundant state 194 for (int i = uselessKeys.size()-1; i >= 0; i--) { 195 Object myKey = uselessKeys.elementAt(i); 196 preState.remove(myKey); 197 postState.remove(myKey); 198 } 199 } 200 201 } // End of class StateEdit 202