// **********************************************************************
//
// <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/omGraphics/EditableOMPoint.java,v $
// $RCSfile: EditableOMPoint.java,v $
// $Revision: 1.16 $
// $Date: 2009/02/25 22:34:03 $
// $Author: dietrick $
//
// **********************************************************************
package com.bbn.openmap.omGraphics;
import java.awt.Component;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
import javax.swing.JComponent;
import javax.swing.JToolBar;
import com.bbn.openmap.gui.GridBagToolBar;
import com.bbn.openmap.omGraphics.editable.GraphicEditState;
import com.bbn.openmap.omGraphics.editable.GraphicSelectedState;
import com.bbn.openmap.omGraphics.editable.GraphicSetOffsetState;
import com.bbn.openmap.omGraphics.editable.GraphicUndefinedState;
import com.bbn.openmap.omGraphics.editable.PointStateMachine;
import com.bbn.openmap.proj.Projection;
import com.bbn.openmap.proj.coords.LatLonPoint;
import com.bbn.openmap.util.Debug;
import com.bbn.openmap.util.stateMachine.State;
/**
* An EditableOMGraphic that encapsulates an OMPoint.
*/
public class EditableOMPoint extends EditableOMGraphic {
protected GrabPoint gpc;
protected OffsetGrabPoint gpo; // offset
protected OMPoint point;
public final static String OffsetResetCmd = "OffsetResetCmd";
public final static int CENTER_POINT_INDEX = 0;
public final static int OFFSET_POINT_INDEX = 1;
/**
* Create the EditableOMPoint, setting the state machine to create the point
* off of the gestures.
*/
public EditableOMPoint() {
createGraphic(null);
}
/**
* Create an EditableOMPoint with the pointType and renderType parameters in
* the GraphicAttributes object.
*/
public EditableOMPoint(GraphicAttributes ga) {
createGraphic(ga);
}
/**
* Create the EditableOMPoint with an OMPoint already defined, ready for
* editing.
*
* @param omc OMPoint that should be edited.
*/
public EditableOMPoint(OMPoint omc) {
setGraphic(omc);
}
/**
* Create and initialize the state machine that interprets the modifying
* gestures/commands, as well as initialize the grab points. Also allocates
* the grab point array needed by the EditableOMPoint.
*/
public void init() {
Debug.message("eomg", "EditableOMPoint.init()");
setCanGrabGraphic(false);
setStateMachine(new PointStateMachine(this));
gPoints = new GrabPoint[2];
}
/**
* Set the graphic within the state machine. If the graphic is null, then
* one shall be created, and located off screen until the gestures driving
* the state machine place it on the map.
*/
public void setGraphic(OMGraphic graphic) {
init();
if (graphic instanceof OMPoint) {
point = (OMPoint) graphic;
stateMachine.setSelected();
setGrabPoints(point);
} else {
createGraphic(null);
}
}
/**
* Create and set the graphic within the state machine. The
* GraphicAttributes describe the type of point to create.
*/
public void createGraphic(GraphicAttributes ga) {
init();
stateMachine.setUndefined();
int renderType = OMGraphic.RENDERTYPE_UNKNOWN;
if (ga != null) {
renderType = ga.getRenderType();
}
if (Debug.debugging("eomg")) {
Debug.output("EditableOMPoint.createGraphic(): rendertype = " + renderType);
}
switch (renderType) {
case (OMGraphic.RENDERTYPE_LATLON):
point = new OMPoint(90f, -180f);
break;
case (OMGraphic.RENDERTYPE_OFFSET):
point = new OMPoint(90f, -180f, 0, 0);
break;
default:
point = new OMPoint(-1, -1);
}
if (ga != null) {
ga.setTo(point);
}
assertGrabPoints();
}
/**
* Get the OMGraphic being created/modified by the EditableOMPoint.
*/
public OMGraphic getGraphic() {
return point;
}
/**
* Set the GrabPoint that is in the middle of being modified, as a result of
* a mouseDragged event, or other selection process.
*/
// public void setMovingPoint(GrabPoint gp) {
// super.setMovingPoint(gp);
// }
/**
* Given a MouseEvent, find a GrabPoint that it is touching, and set the
* moving point to that GrabPoint.
*
* @param e MouseEvent
* @return GrabPoint that is touched by the MouseEvent, null if none are.
*/
public GrabPoint getMovingPoint(MouseEvent e) {
movingPoint = null;
GrabPoint[] gb = getGrabPoints();
Point2D pnt = getProjectionPoint(e);
double x = pnt.getX();
double y = pnt.getY();
for (int i = gb.length - 1; i >= 0; i--) {
if (gb[i] != null && gb[i].distance(x, y) == 0) {
setMovingPoint(gb[i]);
// in case the points are on top of each other, the
// last point in the array will take precedence.
break;
}
}
return movingPoint;
}
/**
* Attach to the Moving OffsetGrabPoint so if it moves, it will move this
* EditableOMGraphic with it. EditableOMGraphic version doesn't do anything,
* each subclass has to decide which of its OffsetGrabPoints should be
* attached to it.
*/
public void attachToMovingGrabPoint(OffsetGrabPoint gp) {
gp.addGrabPoint(gpo);
}
/**
* Detach from a Moving OffsetGrabPoint. The EditableOMGraphic version
* doesn't do anything, each subclass should remove whatever GrabPoint it
* would have attached to an OffsetGrabPoint.
*/
public void detachFromMovingGrabPoint(OffsetGrabPoint gp) {
gp.removeGrabPoint(gpo);
}
protected int lastRenderType = -1;
/**
* Check to make sure the grab points are not null. If they are, allocate
* them, and them assign them to the array.
*/
public void assertGrabPoints() {
int rt = getGraphic().getRenderType();
if (rt != lastRenderType) {
clearGrabPoints();
lastRenderType = rt;
}
if (gpc == null) {
gpc = new GrabPoint(-1, -1);
gPoints[CENTER_POINT_INDEX] = gpc;
}
if (gpo == null) {
gpo = new OffsetGrabPoint(-1, -1);
gPoints[OFFSET_POINT_INDEX] = gpo;
gpo.addGrabPoint(gpc);
}
}
protected void clearGrabPoints() {
gpc = null;
gpo = null;
gPoints[CENTER_POINT_INDEX] = gpc;
gPoints[OFFSET_POINT_INDEX] = gpo;
}
/**
* Set the grab points for the graphic provided, setting them on the extents
* of the graphic. Called when you want to set the grab points off the
* location of the graphic.
*/
public void setGrabPoints(OMGraphic graphic) {
Debug.message("eomg", "EditableOMPoint.setGrabPoints(graphic)");
if (!(graphic instanceof OMPoint)) {
return;
}
assertGrabPoints();
OMPoint point = (OMPoint) graphic;
boolean ntr = point.getNeedToRegenerate();
int renderType = point.getRenderType();
LatLonPoint llp;
int latoffset = 0;
int lonoffset = 0;
boolean doStraight = true;
if (ntr == false) {
if (renderType == OMGraphic.RENDERTYPE_LATLON
|| renderType == OMGraphic.RENDERTYPE_OFFSET) {
if (projection != null) {
double lon = point.getLon();
double lat = point.getLat();
llp = new LatLonPoint.Double(lat, lon);
Point2D p = projection.forward(llp);
if (renderType == OMGraphic.RENDERTYPE_LATLON) {
doStraight = false;
gpc.set((int) p.getX(), (int) p.getY());
} else {
latoffset = (int) p.getY();
lonoffset = (int) p.getX();
gpo.set(lonoffset, latoffset);
}
}
}
if (doStraight) {
gpc.set(lonoffset + point.getX(), latoffset + point.getY());
}
if (renderType == OMGraphic.RENDERTYPE_OFFSET) {
gpo.updateOffsets();
}
} else {
Debug.message("eomg", "EditableOMPoint.setGrabPoints: graphic needs to be regenerated");
}
}
/**
* Take the current location of the GrabPoints, and modify the location
* parameters of the OMPoint with them. Called when you want the graphic to
* change according to the grab points.
*/
public void setGrabPoints() {
int renderType = point.getRenderType();
LatLonPoint llp1;
Debug.message("eomg", "EditableOMPoint.setGrabPoints()");
// Do center point for lat/lon or offset points
if (renderType == OMGraphic.RENDERTYPE_LATLON) {
if (projection != null) {
// movingPoint == gpc
llp1 = (LatLonPoint) projection.inverse(gpc.getX(), gpc.getY(), new LatLonPoint.Double());
point.set(llp1.getY(), llp1.getX());
// point.setNeedToRegenerate set
}
}
boolean settingOffset = getStateMachine().getState() instanceof GraphicSetOffsetState
&& movingPoint == gpo;
// If the center point is moving, the offset distance changes
if (renderType == OMGraphic.RENDERTYPE_OFFSET) {
llp1 = (LatLonPoint) projection.inverse(gpo.getX(), gpo.getY(), new LatLonPoint.Double());
point.setLat(llp1.getY());
point.setLon(llp1.getX());
if (settingOffset || movingPoint == gpc) {
// Don't call point.setLocation because we only want
// to
// setNeedToRegenerate if !settingOffset.
point.setX(gpc.getX() - gpo.getX());
point.setY(gpc.getY() - gpo.getY());
}
if (!settingOffset) {
Debug.message("eomg", "EditableOMPoint: updating offset point");
point.set(gpc.getX() - gpo.getX(), gpc.getY() - gpo.getY());
}
// Set Location has reset the rendertype, but provides
// the convenience of setting the max and min values
// for us.
point.setRenderType(OMGraphic.RENDERTYPE_OFFSET);
}
// Do the point height and width for XY and OFFSET render
// types.
if (renderType == OMGraphic.RENDERTYPE_XY) {
Debug.message("eomg", "EditableOMPoint: updating x/y point");
if (movingPoint == gpc) {
point.set(gpc.getX(), gpc.getY());
}
}
if (projection != null) {
regenerate(projection);
}
}
/**
* Get whether a graphic can be manipulated by its edges, rather than just
* by its grab points.
*/
public boolean getCanGrabGraphic() {
return false;
}
/**
* Called to set the OffsetGrabPoint to the current mouse location, and
* update the OffsetGrabPoint with all the other GrabPoint locations, so
* everything can shift smoothly. Should also set the OffsetGrabPoint to the
* movingPoint. Should be called only once at the beginning of the general
* movement, in order to set the movingPoint. After that, redraw(e) should
* just be called, and the movingPoint will make the adjustments to the
* graphic that are needed.
*/
public void move(java.awt.event.MouseEvent e) {
}
/**
* Use the current projection to place the graphics on the screen. Has to be
* called to at least assure the graphics that they are ready for rendering.
* Called when the graphic position changes.
*
* @param proj com.bbn.openmap.proj.Projection
* @return true
*/
public boolean generate(Projection proj) {
Debug.message("eomgdetail", "EditableOMPoint.generate()");
if (point != null)
point.generate(proj);
for (int i = 0; i < gPoints.length; i++) {
GrabPoint gp = gPoints[i];
if (gp != null) {
gp.generate(proj);
}
}
return true;
}
/**
* Given a new projection, the grab points may need to be repositioned off
* the current position of the graphic. Called when the projection changes.
*/
public void regenerate(Projection proj) {
Debug.message("eomg", "EditableOMPoint.regenerate()");
if (point != null)
point.generate(proj);
setGrabPoints(point);
generate(proj);
}
/**
* Draw the EditableOMPoint parts into the java.awt.Graphics object. The
* grab points are only rendered if the point machine state is
* PointSelectedState.POINT_SELECTED.
*
* @param graphics java.awt.Graphics.
*/
public void render(java.awt.Graphics graphics) {
Debug.message("eomgdetail", "EditableOMPoint.render()");
if (point == null) {
Debug.message("eomg", "EditableOMPoint.render: null point.");
return;
}
State state = getStateMachine().getState();
if (!(state instanceof GraphicUndefinedState)) {
point.setVisible(true);
point.render(graphics);
point.setVisible(false);
int renderType = point.getRenderType();
if (state instanceof GraphicSelectedState || state instanceof GraphicEditState) {
for (int i = 0; i < gPoints.length; i++) {
GrabPoint gp = gPoints[i];
if (gp != null) {
if ((i == OFFSET_POINT_INDEX && renderType == OMGraphic.RENDERTYPE_OFFSET && movingPoint == gpo)
|| (state instanceof GraphicSelectedState && ((i != OFFSET_POINT_INDEX && renderType != OMGraphic.RENDERTYPE_OFFSET) || (renderType == OMGraphic.RENDERTYPE_OFFSET)))
) {
gp.setVisible(true);
gp.render(graphics);
gp.setVisible(false);
}
}
}
}
}
}
/**
* Modifies the gui to not include line type adjustments, and adds widgets
* to control point settings.
*
* @param graphicAttributes the GraphicAttributes to use to get the GUI
* widget from to control those parameters for this EOMG.
* @return java.awt.Component to use to control parameters for this EOMG.
*/
public Component getGUI(GraphicAttributes graphicAttributes) {
Debug.message("eomg", "EditableOMPoint.getGUI");
if (graphicAttributes != null) {
// JComponent panel = graphicAttributes.getColorAndLineGUI();
JComponent panel = createAttributePanel(graphicAttributes);
panel.add(getPointGUI());
return panel;
} else {
return getPointGUI();
}
}
protected JToolBar pToolBar = null;
protected JToolBar getPointGUI() {
if (pToolBar == null) {
pToolBar = new GridBagToolBar();
// Add buttons to toggle oval/rect, radius of point.
}
return pToolBar;
}
}