/*
* @(#)AbstractDrawingEditorAction.java
*
* Copyright (c) 1996-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.draw.action;
import javax.annotation.Nullable;
import org.jhotdraw.draw.Drawing;
import org.jhotdraw.draw.DrawingEditor;
import org.jhotdraw.draw.DrawingView;
import javax.swing.*;
import javax.swing.undo.*;
import java.beans.*;
import org.jhotdraw.beans.WeakPropertyChangeListener;
/**
* This abstract class can be extended to implement an {@code Action} that acts
* on behalf of a {@link org.jhotdraw.draw.DrawingEditor}.
* <p>
* By default the enabled state of this action reflects the enabled state of the
* {@code DrawingEditor}. When many actions listen to the enabled state of the
* drawing editor this can considerably slow down the editor. If updating the
* enabled state is not necessary, you can prevent the action from doing so using
* {@link #setUpdateEnabledState}.
* <p>
* {@code AbstractDrawingEditorAction} listens using a
* {@link WeakPropertyChangeListener} on the {@code DrawingEditor} and thus may
* become garbage collected if it is not referenced by any other object.
*
* @author Werner Randelshofer
* @version $Id$
*/
public abstract class AbstractDrawingEditorAction extends AbstractAction {
private static final long serialVersionUID = 1L;
protected DrawingEditor editor;
private class EventHandler implements PropertyChangeListener {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if ("enabled".equals(evt.getPropertyName())) {
updateEnabledState();
}
}
};
@Nullable private EventHandler eventHandler = new EventHandler();
/** Creates a new instance. */
public AbstractDrawingEditorAction(DrawingEditor editor) {
setEditor(editor);
}
public void setEditor(DrawingEditor newValue) {
if (eventHandler != null) {
unregisterEventHandler();
}
editor = newValue;
if (eventHandler != null) {
registerEventHandler();
updateEnabledState();
}
}
protected void updateEnabledState() {
setEnabled(editor != null && editor.isEnabled());
}
public DrawingEditor getEditor() {
return editor;
}
protected DrawingView getView() {
return editor.getActiveView();
}
protected Drawing getDrawing() {
return getView().getDrawing();
}
/** Updates the enabled state of this action to reflect the enabled state
* of the active {@code DrawingView}. If no drawing view is active, this
* action is disabled.
*/
protected void fireUndoableEditHappened(UndoableEdit edit) {
getDrawing().fireUndoableEditHappened(edit);
}
/** By default, the enabled state of this action is updated to reflect
* the enabled state of the active {@code DrawingView}.
* Since this is not always necessary, and since many listening actions
* may considerably slow down the drawing editor, you can switch this
* behavior off here.
*
* @param newValue Specify false to prevent automatic updating of the
* enabled state.
*/
public void setUpdateEnabledState(boolean newValue) {
// Note: eventHandler != null yields true, if we are currently updating
// the enabled state.
if (eventHandler != null != newValue) {
if (newValue) {
eventHandler = new EventHandler();
registerEventHandler();
} else {
unregisterEventHandler();
eventHandler = null;
}
}
if (newValue) {
updateEnabledState();
}
}
/** Returns true, if this action automatically updates its enabled
* state to reflect the enabled state of the active {@code DrawingView}.
*/
public boolean isUpdatEnabledState() {
return eventHandler != null;
}
/** Unregisters the event handler from the drawing editor and the
* active drawing view.
*/
private void unregisterEventHandler() {
if (editor != null) {
editor.removePropertyChangeListener(eventHandler);
}
}
/** Registers the event handler from the drawing editor and the
* active drawing view.
*/
private void registerEventHandler() {
if (editor != null) {
editor.addPropertyChangeListener(new WeakPropertyChangeListener(eventHandler));
}
}
}