// **********************************************************************
//
// <copyright>
//
// BBN Technologies
// 10 Moulton Street
// Cambridge, MA 02138
// (617) 873-8000
//
// Copyright (C) BBNT Solutions LLC. All rights reserved.
//
// </copyright>
// **********************************************************************
//
// $Source: /cvs/distapps/openmap/src/openmap/com/bbn/openmap/event/ProjMapBeanKeyListener.java,v $
// $RCSfile: ProjMapBeanKeyListener.java,v $
// $Revision: 1.5 $
// $Date: 2006/02/27 23:19:31 $
// $Author: dietrick $
//
// **********************************************************************
package com.bbn.openmap.event;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import com.bbn.openmap.MapBean;
import com.bbn.openmap.proj.ProjectionStack;
import com.bbn.openmap.proj.ProjectionStackTrigger;
/**
* The ProjMapBeanKeyListener is a KeyListener that gets events when
* the MapBean has focus, and responds to certain keys by changing the
* projection. The arrow keys pan the map, and 'z' zooms in. Shift-z
* zooms out. The less than/comma key tells a projection stack to go
* back to the last projection, and the greater than/period tells it
* to go to the next projection. The MapBean has to have focus for
* these to work which is usually gained by clicking on the map.
*/
public class ProjMapBeanKeyListener extends MapBeanKeyListener implements
ProjectionStackTrigger {
/**
* Default Zoom In Factor is 2, meaning that the scale number will
* be cut in half to zoom in and doubled to zoom out.
*/
protected transient float zoomFactor = 2f;
protected PanSupport panners;
protected ZoomSupport zoomers;
protected ListenerSupport<ActionListener> projListeners;
public ProjMapBeanKeyListener() {
panners = new PanSupport(this);
zoomers = new ZoomSupport(this);
projListeners = new ListenerSupport<ActionListener>(this);
}
public void keyReleased(KeyEvent e) {
int keyCode = e.getKeyCode();
// When we can control rates, we'll use shift for double pan,
// and ctrl for half pan
// int modifiers = e.getModifiers();
switch (keyCode) {
case KeyEvent.VK_UP:
case KeyEvent.VK_KP_UP:
panners.firePan(0f/* PanEvent.NORTH */);
break;
case KeyEvent.VK_DOWN:
case KeyEvent.VK_KP_DOWN:
panners.firePan(180f/* PanEvent.SOUTH */);
break;
case KeyEvent.VK_LEFT:
case KeyEvent.VK_KP_LEFT:
panners.firePan(-90f/* PanEvent.WEST */);
break;
case KeyEvent.VK_RIGHT:
case KeyEvent.VK_KP_RIGHT:
panners.firePan(90f/* PanEvent.EAST */);
break;
case KeyEvent.VK_Z:
if (e.isShiftDown()) {
zoomers.fireZoom(ZoomEvent.RELATIVE, zoomFactor);
} else {
zoomers.fireZoom(ZoomEvent.RELATIVE, 1f / zoomFactor);
}
break;
// VK_PLUS doesn't react on '+' events...
case KeyEvent.VK_EQUALS:
zoomers.fireZoom(ZoomEvent.RELATIVE, 1f / zoomFactor);
break;
case KeyEvent.VK_MINUS:
zoomers.fireZoom(ZoomEvent.RELATIVE, zoomFactor);
break;
case KeyEvent.VK_COMMA:
fireProjectionStackEvent(ProjectionStack.BackProjCmd);
break;
case KeyEvent.VK_PERIOD:
fireProjectionStackEvent(ProjectionStack.ForwardProjCmd);
break;
}
}
/**
* In addition to the super.setMapBean() method, also sets the
* MapBean as a zoom and pan listener.
*/
public void setMapBean(MapBean map) {
if (mapBean != null) {
panners.remove(map);
zoomers.remove(map);
}
super.setMapBean(map);
if (mapBean != null) {
panners.add(map);
zoomers.add(map);
}
}
/**
* Called by keyReleased when the period/comma keys are pressed.
*/
protected void fireProjectionStackEvent(String command) {
if (projListeners.isEmpty()) {
return;
}
ActionEvent event = new ActionEvent(this, 0, command);
for (ActionListener listener : projListeners) {
listener.actionPerformed(event);
}
}
/**
* Add an ActionListener for events that trigger events to shift
* the Projection stack.
*/
public void addActionListener(ActionListener al) {
projListeners.add(al);
}
/**
* Remove an ActionListener that receives events that trigger
* events to shift the Projection stack.
*/
public void removeActionListener(ActionListener al) {
projListeners.remove(al);
}
/**
* To receive a status to let the trigger know if any projections
* in the forward or backward stacks exist, possibly to disable
* any gui widgets. Does nothing, we don't care here.
*
* @param containsBackProjections there is at least one past
* projection in the back cache.
* @param containsForwardProjections there is at least one future
* projection in the forward cache. Used when a past
* projection is being used.
*/
public void updateProjectionStackStatus(boolean containsBackProjections,
boolean containsForwardProjections) {}
/**
* In addition to the MapBean, find a projection stack so the less
* than/greater than works on that.
*/
public void findAndInit(Object someObj) {
super.findAndInit(someObj);
if (someObj instanceof ProjectionStack) {
addActionListener((ActionListener) someObj);
}
}
public void findAndUndo(Object someObj) {
super.findAndUndo(someObj);
if (someObj instanceof ProjectionStack) {
removeActionListener((ActionListener) someObj);
}
}
}