?? projectionstack.java
字號:
// **********************************************************************// // <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/proj/ProjectionStack.java,v $// $RCSfile: ProjectionStack.java,v $// $Revision: 1.3.2.2 $// $Date: 2004/10/14 18:27:38 $// $Author: dietrick $// // **********************************************************************package com.bbn.openmap.proj;import java.awt.Container;import java.awt.Point;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.util.Stack;import com.bbn.openmap.LatLonPoint;import com.bbn.openmap.MapBean;import com.bbn.openmap.OMComponent;import com.bbn.openmap.event.ProjectionEvent;import com.bbn.openmap.event.ProjectionListener;import com.bbn.openmap.util.Debug;/** * Provides Projection Stack, to listen for projection changes and * remember them as they pass by. As a Tool, it provides a GUI so * that past projections can be retrieved, and, if a past projection * is being displayed, a forward projection stack is activated to * provide a path to get to the last projection set in the MapBean. * ProjectionStackTriggers should hook themselves up to the * ProjectionStack. The ProjectionStack is responsible for finding * and connecting to the MapBean. */public class ProjectionStack extends OMComponent implements ActionListener, ProjectionListener { public final static int DEFAULT_MAX_SIZE = 10; public final static int REMEMBER_ALL = -1; /** * The currentProjection should be the top item on the backStack. */ protected transient ProjHolder currentProjection; protected transient String currentProjectionID; protected transient Container face; protected transient MapBean mapBean; protected int stackSize = DEFAULT_MAX_SIZE; public final static transient String BackProjCmd = "backProjection"; public final static transient String ForwardProjCmd = "forwardProjection"; public final static transient String ClearBackStackCmd = "clearBackStack"; public final static transient String ClearForwardStackCmd = "clearForwardStack"; public final static transient String ClearStacksCmd = "clearStacks"; protected Stack backStack; protected Stack forwardStack; protected ProjectionStackSupport triggers; /** * Create the projection submenu. */ public ProjectionStack() {} public void setMapBean(MapBean map) { if (mapBean != null) { mapBean.removeProjectionListener(this); } if (map != null) { map.addProjectionListener(this); } mapBean = map; } public MapBean getMapBean() { return mapBean; } public void actionPerformed(ActionEvent ae) { String command = ae.getActionCommand().intern(); Debug.message("projectionstack", "ProjectionStack.actionPerformed(): " + command); boolean changeProjection = false; // This is important. We need to set the current projection // before setting the projection in the MapBean. That way, // the projectionChanged method actions won't get fired if (command == BackProjCmd && backStack != null && backStack.size() > 1) { pop(); currentProjection = (ProjHolder)backStack.peek(); changeProjection = true; } else if (command == ForwardProjCmd && forwardStack != null && !forwardStack.empty()) { currentProjection = backPop(); changeProjection = true; } else { clearStacks((command == ClearBackStackCmd || command == ClearStacksCmd), (command == ClearForwardStackCmd || command == ClearStacksCmd)); // fireStackStatus is called in clearStacks } if (changeProjection && mapBean != null) { if (Debug.debugging("projectionstack")) { Debug.output("ProjectionStack.actionPerformed() changing mapbean projection to : " + currentProjection); } Projection currProj = currentProjection.create(mapBean.getWidth(), mapBean.getHeight()); mapBean.setProjection(currProj); fireStackStatus(); } } //------------------------------------------------------------ // ProjectionListener interface //------------------------------------------------------------ /** * The Map projection has changed. * @param e ProjectionEvent */ public void projectionChanged(ProjectionEvent e) { if (Debug.debugging("projectionstack")) { System.out.println("ProjectionStack.projectionChanged()"); } Projection newProj = e.getProjection(); // If the ProjectionStack doesn't already know about the // projection change, that means that it didn't instigate it, // and the new projection needs to get added to the stack, // with the forwardStack cleared. if (currentProjection == null || !currentProjection.equals(newProj)) { Debug.message("projectionstack", "ProjectionStack.projectionChanged() pushing projection on backStack"); // push on the backStack, clear the forwardStack; currentProjection = push(new ProjHolder(newProj)); if (forwardStack != null) { forwardStack.clear(); } fireStackStatus(); } else { Debug.message("projectionstack", "ProjectionStack.projectionChanged() new projection matches current projection, no action."); } } /** * Clear out the chosen projection stacks and fire an event to * update the triggers on stack status. * @param clearBackStack clear out the backward projection stack. * @param clearForwardStack clear out the forward projection stack. */ public synchronized void clearStacks(boolean clearBackStack, boolean clearForwardStack) { if (clearBackStack && backStack != null) { ProjHolder currentProj = pop(); // current projection backStack.clear(); push(currentProj); } if (clearForwardStack && forwardStack != null) { forwardStack.clear(); } fireStackStatus(); } /** * Take a ProjHolder off the backStack, and push it on the forward * stack. * @return the ProjHolder pushed onto the forwardStack. */ protected synchronized ProjHolder pop() { ProjHolder proj = (ProjHolder)backStack.pop(); if (forwardStack == null) { forwardStack = new Stack(); } while (forwardStack.size() >= stackSize) { forwardStack.removeElementAt(0); } forwardStack.push(proj); return proj; } /** * Take a ProjHolder off the forwardStack, and push it on the backStack. * @return the ProjHolder pushed on the backStack. */ protected synchronized ProjHolder backPop() { ProjHolder proj = (ProjHolder)forwardStack.pop(); // This has almost no chance of happening... if (backStack == null) { backStack = new Stack(); } while (backStack.size() >= stackSize) { backStack.removeElementAt(0); } backStack.push(proj); return proj; } /** * Put a new ProjHolder on the backStack, to remember for later in * case we need to back up. * @param proj ProjHolder. * @return the ProjHolder pushed on the backStack. */ protected synchronized ProjHolder push(ProjHolder proj) { if (backStack == null) { backStack = new Stack(); } if (backStack.size() >= stackSize) { backStack.removeElementAt(0); } return (ProjHolder)backStack.push(proj); } public void fireStackStatus() { fireStackStatus((backStack != null && backStack.size() > 1), (forwardStack != null && !forwardStack.empty())); } public void fireStackStatus(boolean enableBackButton, boolean enableForwardButton) { if (triggers != null) { if (Debug.debugging("projectionstack")) { Debug.output("ProjectionStack.fireStackStatus(" + enableBackButton + ", " + enableForwardButton + ")"); } triggers.fireStackStatus(enableBackButton, enableForwardButton); } } /** * ProjectionStackTriggers should call this method, and all will be well. */ public void addProjectionStackTrigger(ProjectionStackTrigger trigger) { trigger.addActionListener(this); if (triggers == null) { triggers = new ProjectionStackSupport(); } triggers.add(trigger); trigger.updateProjectionStackStatus((backStack != null && backStack.size() > 1), (forwardStack != null && !forwardStack.empty())); } /** * ProjectionStackTriggers should call this method, and all will be well. */ public void removeProjectionStackTrigger(ProjectionStackTrigger trigger) { trigger.removeActionListener(this); if (triggers != null) { triggers.remove(trigger); if (triggers.size() == 0) { triggers = null; } } } //------------------------------------------------------------ // BeanContextMembershipListener and BeanContextChild interface //------------------------------------------------------------ /** * Look at the object received in a MapHandler status message and * disconnect from it if necessary. */ public void findAndUndo(Object someObj) { if (someObj instanceof com.bbn.openmap.MapBean) { Debug.message("projectionstack","ProjectionStack removing a MapBean."); MapBean map = getMapBean(); if (map != null && map == (MapBean)someObj) { setMapBean(null); } } } /** * Look at the object received in a MapHandler status message and * connect to it if necessary. */ public void findAndInit(Object someObj) { if (someObj instanceof com.bbn.openmap.MapBean) { Debug.message("projectionstack","ProjectionStack found a MapBean."); setMapBean((MapBean)someObj); } } public class ProjHolder { public Class projClass; public float scale; public LatLonPoint center; protected Point tmpPoint1; protected Point tmpPoint2; public ProjHolder(Projection proj) { projClass = proj.getClass(); scale = proj.getScale(); center = proj.getCenter(); } public boolean equals(Projection proj) { // For some reason, the ProjectionFactory can mess up the // center lat/lons, so that the center isn't EXACTLY what // they were when the projection was created. It's almost // like it decides what map it can draw, and then figures // out what the coordinate of the center pixel of the // projection it created was. Doing this projection hack // seems to accurately determine what projections are // acutally identical visually, which is what you want to // know anyway. Point tmpPoint1 = proj.forward(proj.getCenter()); Point tmpPoint2 = proj.forward(center); boolean same = (projClass == proj.getClass() && scale == proj.getScale() && // NOT GOOD ENOUGH! Sometimes, the // slighest difference causes a false // false.// MoreMath.approximately_equal(center.getLatitude(), // proj.getCenter().getLatitude(), // .00001f) &&// MoreMath.approximately_equal(center.getLongitude(), // proj.getCenter().getLongitude(), // .00001f) // This seems to work... tmpPoint1.x == tmpPoint2.x && tmpPoint1.y == tmpPoint2.y ); return same; } public Projection create(int width, int height) { return ProjectionFactory.makeProjection(projClass, center.getLatitude(), center.getLongitude(), scale, width, height); } public String toString() { return ("[ProjHolder: class(" + projClass.getName() + "), scale(" + scale + "), center(" + center + ")]"); } }}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -