UndoRedo on Nodes (Part 1)

When a change is made to the property in the Properties Window, below, the undo/redo functionality becomes enabled:

When undo/redo are invoked, e.g., via the buttons in the toolbar, the display name of the node changes accordingly. The only problem I have is that the buttons only become enabled when the Person Window is selected, not when the Properties Window is selected, which would be desirable.

Here's the Person object:

public class Person implements PropertyChangeListener {
 
    private String name;
    public static final String PROP_NAME = "name";
 
    public Person(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        String oldName = this.name;
        this.name = name;
        propertyChangeSupport.firePropertyChange(PROP_NAME, oldName, name);
    }
 
    private transient final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
 
    public void addPropertyChangeListener(PropertyChangeListener listener) {
        propertyChangeSupport.addPropertyChangeListener(listener);
    }
 
    public void removePropertyChangeListener(PropertyChangeListener listener) {
        propertyChangeSupport.removePropertyChangeListener(listener);
    }
 
    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        propertyChangeSupport.firePropertyChange(evt);
    }
 
}

And here's the Node with UndoRedo enablement:

public class PersonNode extends AbstractNode implements UndoRedo.Provider, PropertyChangeListener {

    private UndoRedo.Manager manager = new UndoRedo.Manager();
    private boolean undoRedoEvent;

    public PersonNode(Person person) {
        super(Children.LEAF, Lookups.singleton(person));
        person.addPropertyChangeListener(this);
        setDisplayName(person.getName());
    }

    @Override
    protected Sheet createSheet() {
        Sheet sheet = Sheet.createDefault();
        Sheet.Set set = Sheet.createPropertiesSet();
        set.put(new NameProperty(getLookup().lookup(Person.class)));
        sheet.put(set);
        return sheet;
    }

    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        if (evt.getPropertyName().equals(Person.PROP_NAME)) {
            firePropertyChange(evt.getPropertyName(), evt.getOldValue(), evt.getNewValue());
        }
    }

    public void fireUndoableEvent(String property, Person source, Object oldValue, Object newValue) {
        manager.addEdit(new MyAbstractUndoableEdit(source, oldValue, newValue));
    }

    @Override
    public UndoRedo getUndoRedo() {
        return manager;
    }

    @Override
    public String getDisplayName() {
        Person p = getLookup().lookup(Person.class);
        if (p != null) {
            return p.getName();
        }
        return super.getDisplayName();
    }

    private class NameProperty extends PropertySupport.ReadWrite<String> {

        private Person p;

        public NameProperty(Person p) {
            super("name", String.class, "Name", "Name of Person");
            this.p = p;
        }

        @Override
        public String getValue() throws IllegalAccessException, InvocationTargetException {
            return p.getName();
        }

        @Override
        public void setValue(String newValue) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
            String oldValue = p.getName();
            p.setName(newValue);
            if (!undoRedoEvent) {
                fireUndoableEvent("name", p, oldValue, newValue);
                fireDisplayNameChange(oldValue, newValue);
            }
        }
 
    }

    class MyAbstractUndoableEdit extends AbstractUndoableEdit {

        private final String oldValue;
        private final String newValue;
        private final Person source;

        private MyAbstractUndoableEdit(Person source, Object oldValue, Object newValue) {
            this.oldValue = oldValue.toString();
            this.newValue = newValue.toString();
            this.source = source;
        }

        @Override
        public boolean canRedo() {
            return true;
        }

        @Override
        public boolean canUndo() {
            return true;
        }

        @Override
        public void undo() throws CannotUndoException {
            undoRedoEvent = true;
            source.setName(oldValue.toString());
            fireDisplayNameChange(oldValue, newValue);
            undoRedoEvent = false;
        }

        @Override
        public void redo() throws CannotUndoException {
            undoRedoEvent = true;
            source.setName(newValue.toString());
            fireDisplayNameChange(oldValue, newValue);
            undoRedoEvent = false;
        }
    }

}

Does anyone out there know how to have the Undo/Redo functionality enabled when the Properties Window is selected?

Comments:

Post a Comment:
  • HTML Syntax: NOT allowed
About

Geertjan Wielenga (@geertjanw) is a Principal Product Manager in the Oracle Developer Tools group living & working in Amsterdam. He is a Java technology enthusiast, evangelist, trainer, speaker, and writer. He blogs here daily.

The focus of this blog is mostly on NetBeans (a development tool primarily for Java programmers), with an occasional reference to NetBeans, and sometimes diverging to topics relating to NetBeans. And then there are days when NetBeans is mentioned, just for a change.

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
12
13
14
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today