/*
* Copyright (C) 2010 Brockmann Consult GmbH (info@brockmann-consult.de)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at your option)
* any later version.
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see http://www.gnu.org/licenses/
*/
package com.bc.ceres.swing.figure;
import java.awt.Cursor;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
public abstract class AbstractInteractor implements Interactor {
private boolean active;
private ArrayList<InteractorListener> listeners;
protected AbstractInteractor() {
listeners = new ArrayList<InteractorListener>(3);
}
@Override
public boolean isActive() {
return active;
}
@Override
public boolean activate() {
if (!active) {
active = canActivateInteractor();
if (isActive()) {
for (InteractorListener listener : getListeners()) {
listener.interactorActivated(this);
}
}
}
return isActive();
}
@Override
public void deactivate() {
if (active) {
active = false;
for (InteractorListener listener : getListeners()) {
listener.interactorDeactivated(this);
}
}
}
@Override
public Cursor getCursor() {
return Cursor.getDefaultCursor();
}
/**
* Invoked when the mouse enters a component.
* <p/>
* The default implementation does nothing.
*
* @param event The mouse event.
*/
@Override
public void mouseEntered(MouseEvent event) {
}
/**
* Invoked when the mouse exits a component.
* <p/>
* The default implementation does nothing.
*
* @param event The mouse event.
*/
@Override
public void mouseExited(MouseEvent event) {
}
/**
* Invoked when a mouse button has been pressed on a component.
* <p/>
* The default implementation does nothing.
*
* @param event The mouse event.
*/
@Override
public void mousePressed(MouseEvent event) {
}
/**
* Invoked when a mouse button has been released on a component.
* <p/>
* The default implementation does nothing.
*
* @param event The mouse event.
*/
@Override
public void mouseReleased(MouseEvent event) {
}
/**
* Invoked when the mouse button has been clicked (pressed
* and released) on a component.
* <p/>
* The default implementation does nothing.
*
* @param event The mouse event.
*/
@Override
public void mouseClicked(MouseEvent event) {
}
/**
* Invoked when a mouse button is pressed on a component and then
* dragged. <code>MOUSE_DRAGGED</code> events will continue to be
* delivered to the component where the drag originated until the
* mouse button is released (regardless of whether the mouse position
* is within the bounds of the component).
* <p/>
* Due to platform-dependent Drag&Drop implementations,
* <code>MOUSE_DRAGGED</code> events may not be delivered during a native
* Drag&Drop operation.
* <p/>
* The default implementation does nothing.
*
* @param event The mouse event.
*/
@Override
public void mouseDragged(MouseEvent event) {
}
/**
* Invoked when the mouse cursor has been moved onto a component
* but no buttons have been pushed.
* <p/>
* The default implementation does nothing.
*
* @param event The mouse event.
*/
@Override
public void mouseMoved(MouseEvent event) {
}
/**
* Invoked when a key has been pressed.
* See the class description for {@link KeyEvent} for a definition of
* a key pressed event.
* <p/>
* The default implementation does nothing.
*
* @param event The key event.
*/
@Override
public void keyPressed(KeyEvent event) {
}
/**
* Invoked when a key has been released.
* See the class description for {@link KeyEvent} for a definition of
* a key released event.
* <p/>
* The default implementation does nothing.
*
* @param event The key event.
*/
@Override
public void keyReleased(KeyEvent event) {
}
/**
* Invoked when a key has been typed.
* See the class description for {@link KeyEvent} for a definition of
* a key typed event.
* <p/>
* The default implementation calls {@link #cancelInteraction(java.awt.event.InputEvent)} if the
* "ESC" key has been typed.
*
* @param event The key event.
*/
@Override
public void keyTyped(KeyEvent event) {
// System.out.println("onKeyTyped: interaction = " + this + ", keyChar = " + (int) event.getKeyChar());
if (event.getKeyChar() == 27) {
cancelInteraction(event);
}
}
@Override
public void addListener(InteractorListener l) {
listeners.add(l);
}
@Override
public void removeListener(InteractorListener l) {
listeners.remove(l);
}
@Override
public InteractorListener[] getListeners() {
return this.listeners.toArray(new InteractorListener[this.listeners.size()]);
}
protected boolean startInteraction(InputEvent inputEvent) {
if (canStartInteraction(inputEvent)) {
for (InteractorListener listener : getListeners()) {
listener.interactionStarted(this, inputEvent);
}
return true;
} else {
return false;
}
}
protected void stopInteraction(InputEvent inputEvent) {
for (InteractorListener listener : getListeners()) {
listener.interactionStopped(this, inputEvent);
}
}
protected void cancelInteraction(InputEvent inputEvent) {
for (InteractorListener listener : getListeners()) {
listener.interactionCancelled(this, inputEvent);
}
}
protected static boolean isSingleButton1Click(MouseEvent e) {
return isLeftMouseButtonDown(e) && e.getClickCount() == 1;
}
protected static boolean isMultiButton1Click(MouseEvent e) {
return isLeftMouseButtonDown(e) && e.getClickCount() > 1;
}
protected static boolean isLeftMouseButtonDown(MouseEvent e) {
return (e.getModifiers() & MouseEvent.BUTTON1_MASK) != 0;
}
private boolean canActivateInteractor() {
for (InteractorListener listener : getListeners()) {
if (listener instanceof InteractorInterceptor) {
final InteractorInterceptor interactorInterceptor = (InteractorInterceptor) listener;
if (!interactorInterceptor.interactorAboutToActivate(this)) {
return false;
}
}
}
return true;
}
private boolean canStartInteraction(InputEvent inputEvent) {
for (InteractorListener listener : getListeners()) {
if (listener instanceof InteractorInterceptor) {
final InteractorInterceptor interactorInterceptor = (InteractorInterceptor) listener;
if (!interactorInterceptor.interactionAboutToStart(this, inputEvent)) {
return false;
}
}
}
return true;
}
}