AbstractTool.java
/*
* @(#)AbstractTool.java
*
* Project: JHotdraw - a GUI framework for technical drawings
* http://www.jhotdraw.org
* http://jhotdraw.sourceforge.net
* Copyright: © by the original author(s) and all contributors
* License: Lesser GNU Public License (LGPL)
* http://www.opensource.org/licenses/lgpl-license.html
*/
package CH.ifa.draw.standard;
import CH.ifa.draw.framework.*;
import CH.ifa.draw.util.Undoable;
import java.util.*;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.KeyEvent;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
/**
* Default implementation support for Tools.
*
* @see DrawingView
* @see Tool
*
* @version <$CURRENT_VERSION$>
*/
public abstract class AbstractTool implements Tool, ViewChangeListener {
private DrawingEditor myDrawingEditor;
/**
* The position of the initial mouse down.
*/
protected int fAnchorX, fAnchorY;
private Undoable myUndoActivity;
private AbstractTool.EventDispatcher myEventDispatcher;
private boolean myIsUsable;
/**
* Flag to indicate whether to perform usable checks or not
*/
private boolean myIsEnabled;
/**
* Constructs a tool for the given view.
*/
public AbstractTool(DrawingEditor newDrawingEditor) {
myDrawingEditor = newDrawingEditor;
setEventDispatcher(createEventDispatcher());
setEnabled(true);
editor().addViewChangeListener(this);
}
/**
* Activates the tool for use on the given view. This method is called
* whenever the user switches to this tool. Use this method to
* reinitialize a tool.
* Since tools will be disabled unless it is useable, there will always
* be an active view when this is called. based on isUsable()
*/
public void activate() {
if (view() != null) {
view().clearSelection();
getEventDispatcher().fireToolActivatedEvent();
}
}
/**
* Deactivates the tool. This method is called whenever the user
* switches to another tool. Use this method to do some clean-up
* when the tool is switched. Subclassers should always call
* super.deactivate.
*/
public void deactivate() {
if (isActive()) {
if (view() != null) {
view().setCursor(Cursor.getDefaultCursor());
}
getEventDispatcher().fireToolDeactivatedEvent();
}
}
/**
* Fired when the selected view changes.
* Subclasses should always call super. ViewSelectionChanged() this allows
* the tools state to be updated and referenced to the new view.
*/
public void viewSelectionChanged(DrawingView oldView, DrawingView newView) {
if (isActive()) {
deactivate();
activate();
}
checkUsable();
}
/**
* Sent when a new view is created
*/
public void viewCreated(DrawingView view) {
}
/**
* Send when an existing view is about to be destroyed.
*/
public void viewDestroying(DrawingView view) {
}
/**
* Handles mouse down events in the drawing view.
*/
public void mouseDown(MouseEvent e, int x, int y) {
fAnchorX = x;
fAnchorY = y;
}
/**
* Handles mouse drag events in the drawing view.
*/
public void mouseDrag(MouseEvent e, int x, int y) {
}
/**
* Handles mouse up in the drawing view.
*/
public void mouseUp(MouseEvent e, int x, int y) {
}
/**
* Handles mouse moves (if the mouse button is up).
*/
public void mouseMove(MouseEvent evt, int x, int y) {
}
/**
* Handles key down events in the drawing view.
*/
public void keyDown(KeyEvent evt, int key) {
}
/**
* Gets the tool's drawing.
*/
public Drawing drawing() {
return view().drawing();
}
/**
* Gets the tool's editor.
*/
public DrawingEditor editor() {
return myDrawingEditor;
}
/**
* Gets the tool's view (convienence method).
*/
public DrawingView view() {
return editor().view();
}
/**
* Tests if the tool can be used or "executed."
*/
public boolean isUsable() {
return isEnabled() && myIsUsable;
}
public void setUsable(boolean newIsUsable) {
// perform notification only if the usable state of the tool has changed
if (isUsable() != newIsUsable) {
myIsUsable = newIsUsable;
if (isUsable()) {
getEventDispatcher().fireToolUsableEvent();
}
else {
getEventDispatcher().fireToolUnusableEvent();
}
}
}
public void setEnabled(boolean newIsEnabled) {
// perform notification only if the usable state of the tool has changed
if (isEnabled() != newIsEnabled) {
myIsEnabled = newIsEnabled;
if (isEnabled()) {
getEventDispatcher().fireToolEnabledEvent();
}
else {
getEventDispatcher().fireToolDisabledEvent();
setUsable(false);
deactivate();
}
}
}
public boolean isEnabled() {
return myIsEnabled;
}
public Undoable getUndoActivity() {
return myUndoActivity;
}
public void setUndoActivity(Undoable newUndoActivity) {
myUndoActivity = newUndoActivity;
}
public boolean isActive() {
return (editor().tool() == this) && isUsable();
}
public void addToolListener(ToolListener newToolListener) {
getEventDispatcher().addToolListener(newToolListener);
}
public void removeToolListener(ToolListener oldToolListener) {
getEventDispatcher().removeToolListener(oldToolListener);
}
private void setEventDispatcher(AbstractTool.EventDispatcher newEventDispatcher) {
myEventDispatcher = newEventDispatcher;
}
protected AbstractTool.EventDispatcher getEventDispatcher() {
return myEventDispatcher;
}
public AbstractTool.EventDispatcher createEventDispatcher() {
return new AbstractTool.EventDispatcher(this);
}
protected void checkUsable() {
if (isEnabled()) {
setUsable((view() != null) && view().isInteractive());
}
}
public static class EventDispatcher {
private Vector myRegisteredListeners;
private Tool myObservedTool;
public EventDispatcher(Tool newObservedTool) {
myRegisteredListeners = new Vector();
myObservedTool = newObservedTool;
}
public void fireToolUsableEvent() {
Enumeration le = myRegisteredListeners.elements();
while (le.hasMoreElements()) {
((ToolListener)le.nextElement()).toolUsable(new EventObject(myObservedTool));
}
}
public void fireToolUnusableEvent() {
Enumeration le = myRegisteredListeners.elements();
while (le.hasMoreElements()) {
((ToolListener)le.nextElement()).toolUnusable(new EventObject(myObservedTool));
}
}
public void fireToolActivatedEvent() {
Enumeration le = myRegisteredListeners.elements();
while (le.hasMoreElements()) {
((ToolListener)le.nextElement()).toolActivated(new EventObject(myObservedTool));
}
}
public void fireToolDeactivatedEvent() {
Enumeration le = myRegisteredListeners.elements();
while (le.hasMoreElements()) {
((ToolListener)le.nextElement()).toolDeactivated(new EventObject(myObservedTool));
}
}
public void fireToolEnabledEvent() {
Enumeration le = myRegisteredListeners.elements();
while (le.hasMoreElements()) {
((ToolListener)le.nextElement()).toolEnabled(new EventObject(myObservedTool));
}
}
public void fireToolDisabledEvent() {
Enumeration le = myRegisteredListeners.elements();
while (le.hasMoreElements()) {
((ToolListener)le.nextElement()).toolDisabled(new EventObject(myObservedTool));
}
}
public void addToolListener(ToolListener newToolListener) {
if (!myRegisteredListeners.contains(newToolListener)) {
myRegisteredListeners.add(newToolListener);
}
}
public void removeToolListener(ToolListener oldToolListener) {
if (myRegisteredListeners.contains(oldToolListener)) {
myRegisteredListeners.remove(oldToolListener);
}
}
}
}