/* * @(#)PropertyChangeEdit.java * * Copyright (c) 2009-2010 The authors and contributors of JHotDraw. * * You may not use, copy or modify this file, except in compliance with the * accompanying license terms. */ package org.jhotdraw.undo; import java.beans.PropertyDescriptor; import java.lang.reflect.Method; import javax.swing.undo.AbstractUndoableEdit; import javax.swing.undo.CannotRedoException; import javax.swing.undo.UndoableEdit; /** * An {@code UndoableEdit} event which can undo a change of a JavaBeans property. * * @author Werner Randelshofer * @version $Id$ */ public class PropertyChangeEdit extends AbstractUndoableEdit { private static final long serialVersionUID = 1L; /** * The object to be provided as the "source" of the JavaBeans property. */ private Object source; /** * The name of the JavaBeans property. */ private String propertyName; /** * The old value of the JavaBeans property. */ private Object oldValue; /** * The new value of the JavaBeans property. */ private Object newValue; /** The type of the property. */ private Class<?> type; private String presentationName; /** Creates a new PropertyChangeEdit. */ public PropertyChangeEdit(Object source, String propertyName, Object oldValue, Object newValue) { this(source,propertyName,propertyNameToPresentationName(propertyName),oldValue,newValue); } /** Creates a new PropertyChangeEdit. */ public PropertyChangeEdit(Object source, String propertyName, String presentationName, Object oldValue, Object newValue) { this.source = source; this.propertyName = propertyName; this.presentationName = presentationName; this.oldValue = oldValue; this.newValue = newValue; } /** * Returns the setter for the property. * * @return the setter method. */ protected Method getSetter() { try { PropertyDescriptor desc=new PropertyDescriptor(propertyName,source.getClass()); return desc.getWriteMethod(); } catch (Exception e) { InternalError ie = new InternalError("Couldn't find setter for property \"" + propertyName + "\" in " + source); ie.initCause(e); throw ie; } } /** Undoes the change. */ @Override public void undo() throws CannotRedoException { super.undo(); try { getSetter().invoke(source, oldValue); } catch (Exception e) { InternalError ie = new InternalError("Couldn't invoke setter for property \"" + propertyName + "\" in " + source); ie.initCause(e); throw ie; } } /** Redoes the change. */ @Override public void redo() throws CannotRedoException { super.redo(); try { getSetter().invoke(source, newValue); } catch (Exception e) { InternalError ie = new InternalError("Couldn't invoke setter for property \"" + propertyName + "\" in " + source); ie.initCause(e); throw ie; } } /** Returns the presentation name of the undoable edit. * This is the same as the property name, unless you have set a different * presentation name. */ @Override public String getPresentationName() { return presentationName; } /** Sets the presentation name of the undoable edit. */ public void setPresentationName(String presentationName) { this.presentationName = presentationName; } /** Adds the specified edit to this one, if it is a {@code PropertyChangeEdit} * from the same owner and the same property. * * @param anEdit Edit to be added. * @return True if added. */ @Override public boolean addEdit(UndoableEdit anEdit) { if (anEdit instanceof PropertyChangeEdit) { PropertyChangeEdit that = (PropertyChangeEdit) anEdit; if (that.source == this.source && that.propertyName.equals(this.propertyName)) { this.newValue = that.newValue; return true; } } return false; } /** Returns a string representation of this object useful for debugging. */ @Override public String toString() { return super.toString() + " [" + propertyName + "," + oldValue + "," + newValue + "]"; } /** Converts a property name into a presentation name. */ public static String propertyNameToPresentationName(String s) { StringBuilder b = new StringBuilder(); boolean wasUpperCase = true; for (int i = 0; i < s.length(); i++) { if (Character.isUpperCase(s.charAt(i))) { if (!wasUpperCase) { b.append(' '); } wasUpperCase = true; } else { wasUpperCase = false; } b.append(i==0?Character.toUpperCase(s.charAt(i)):s.charAt(i)); } return b.toString(); } }