/*
* @(#)AbstractApplicationAction.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.app.action;
import edu.umd.cs.findbugs.annotations.Nullable;
import java.beans.*;
import javax.swing.*;
import org.jhotdraw.app.Application;
import org.jhotdraw.app.Disposable;
import org.jhotdraw.beans.WeakPropertyChangeListener;
/**
* This abstract class can be extended to implement an {@code Action} that acts
* on an {@link Application}.
* <p>
* If the {@code Application} object is disabled, the
* {@code AbstractApplicationAction} is disabled as well.
* <p>
* {@code AbstractApplicationAction} listens using a
* {@link WeakPropertyChangeListener} on the {@code Application} and thus may
* become garbage collected if it is not referenced by any other object.
* <p>
* Application actions are typically created by an {@link org.jhotdraw.app.ApplicationModel},
* and can be retrieved using getAction(String) from the application model.
* Application model typically links the actions to menu items and toolbars that
* it creates. Applicaton model may also put actions into its {@link org.jhotdraw.app.View}s,
* so that they can be linked to components of a view.
*
*
* @author Werner Randelshofer.
* @version $Id$
*/
public abstract class AbstractApplicationAction extends AbstractAction implements Disposable {
private static final long serialVersionUID = 1L;
@Nullable private Application app;
@Nullable private PropertyChangeListener applicationListener;
/** Creates a new instance. */
public AbstractApplicationAction(Application app) {
this.app = app;
installApplicationListeners(app);
updateApplicationEnabled();
}
/*
* Installs listeners on the application object.
*/
protected void installApplicationListeners(Application app) {
if (applicationListener == null) {
applicationListener = createApplicationListener();
}
app.addPropertyChangeListener(new WeakPropertyChangeListener(applicationListener));
}
/**
* Installs listeners on the application object.
*/
protected void uninstallApplicationListeners(Application app) {
app.removePropertyChangeListener(applicationListener);
}
private PropertyChangeListener createApplicationListener() {
return new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName() == "enabled") { // Strings get interned
updateApplicationEnabled();
}
}
};
}
public Application getApplication() {
return app;
}
/**
* Updates the enabled state of this action depending on the new enabled
* state of the application.
*/
protected void updateApplicationEnabled() {
firePropertyChange("enabled",
Boolean.valueOf(!isEnabled()),
Boolean.valueOf(isEnabled()));
}
/**
* Returns true if the action is enabled.
* The enabled state of the action depends on the state that has been set
* using setEnabled() and on the enabled state of the application.
*
* @return true if the action is enabled, false otherwise
* @see Action#isEnabled
*/
@Override
public boolean isEnabled() {
return app != null && app.isEnabled() && enabled;
}
/**
* Enables or disables the action. The enabled state of the action
* depends on the value that is set here and on the enabled state of
* the application.
*
* @param newValue true to enable the action, false to
* disable it
* @see Action#setEnabled
*/
@Override
public void setEnabled(boolean newValue) {
boolean oldValue = this.enabled;
this.enabled = newValue;
firePropertyChange("enabled",
Boolean.valueOf(oldValue && app.isEnabled()),
Boolean.valueOf(newValue && app.isEnabled()));
}
@Override
public final void dispose() {
if (app != null) {
uninstallApplicationListeners(app);
app = null;
}
}
}