arcgissamples\defensesolutions\MoleBasicSymbols.java
/* Copyright 2010 ESRI * * All rights reserved under the copyright laws of the United States * and applicable international laws, treaties, and conventions. * * You may freely redistribute and use this sample code, with or * without modification, provided you include the original copyright * notice and use restrictions. * * See the use restrictions. * */ package arcgissamples.defensesolutions; import java.awt.*; import java.awt.event.*; import java.util.*; import javax.swing.*; import com.esri.arcgis.carto.*; import com.esri.arcgis.controls.*; import com.esri.arcgis.defensesolutions.*; import com.esri.arcgis.display.*; import com.esri.arcgis.geometry.*; import com.esri.arcgis.system.*; import static com.esri.arcgis.carto.esriViewDrawPhase.*; /** This class is the "controller" part of the model-view-controller. * To the greatest extent possible, MapTocToolbar only has code generator output. * This file is reserved for code written by humans. */ public class MoleBasicSymbols extends IMapControlEvents2Adapter{ private static final long serialVersionUID = -1; private static Random s_random = new Random(); private IPoint m_currentMouseLocation = createPoint (0, 0); private long m_dragStartTime = 0; private boolean m_firstTime = true; private IPoint m_lastMouseClick = createPoint (0, 0); private MapTocToolbar m_mapWindow = new MapTocToolbar(); private IDisplayFeedback m_moveFeedback = null; private Envelope m_selectedBounds = null; private int m_unitCount = 0; private MoleBasicSymbols() { try { // some additional configuration m_mapWindow.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE); updateTitle(); m_mapWindow.getMapBean().addIMapControlEvents2Listener (this); Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); m_mapWindow.setLocation ( (screenSize.width - m_mapWindow.getWidth()) >> 1, (screenSize.height - m_mapWindow.getHeight()) >> 1 ); m_mapWindow.getTxtSIC().setText (DemoSymbols.getSIC(s_random.nextInt())); m_selectedBounds = new Envelope(); // connect ActionListeners to the Swing toolbar m_mapWindow.getBtnAdd200().addActionListener (new ActionListener() { public void actionPerformed (ActionEvent e) { MoleBasicSymbols.this.actionAdd200(); } }); m_mapWindow.getBtnAddArea().addActionListener (new ActionListener() { public void actionPerformed (ActionEvent e) { MoleBasicSymbols.this.actionAddArea(); } }); m_mapWindow.getBtnAddLine().addActionListener (new ActionListener() { public void actionPerformed (ActionEvent e) { MoleBasicSymbols.this.actionAddLine(); } }); m_mapWindow.getBtnAddMoleSymbol().addActionListener (new ActionListener() { public void actionPerformed (ActionEvent e) { MoleBasicSymbols.this.actionAddMoleSymbol(); } }); m_mapWindow.getBtnMoveUnits().addActionListener (new ActionListener() { public void actionPerformed (ActionEvent e) { MoleBasicSymbols.this.actionMoveUnits(); } }); m_mapWindow.getBtnSelect().addActionListener (new ActionListener() { public void actionPerformed (ActionEvent e) { MoleBasicSymbols.this.actionSelect(); } }); m_mapWindow.addWindowListener (new WindowAdapter() { public void windowClosing (WindowEvent e) { try { // tell MOLE to save its settings and release its resources System.out.println ("releasing MOLE resources"); (new MoleCoreHelper()).releaseForceElementRenderer(); } catch ( Exception x ) { x.printStackTrace(); } } }); // show the completed user interface m_mapWindow.setVisible (true); } catch ( Exception e ) { e.printStackTrace(); } } public void onMapReplaced (IMapControlEvents2OnMapReplacedEvent e) { try { // initialize the last mouse click point to the center of the map's extent Envelope extent = (Envelope) m_mapWindow.getMapBean().getActiveView().getExtent(); m_lastMouseClick.putCoords ( extent.getXMin() + extent.getWidth() * 0.5, extent.getYMin() + extent.getHeight() * 0.5 ); // update the window title m_unitCount = 0; updateTitle(); } catch ( Exception x ) { x.printStackTrace(); } } public void onMouseDown (IMapControlEvents2OnMouseDownEvent e) { try { m_lastMouseClick.putCoords (e.getMapX(), e.getMapY()); if ( m_mapWindow.getBtnAddMoleSymbol().isSelected() ) { // "Add MOLE Symbol" command: draw a symbol at the click point drawSymbol (m_lastMouseClick, m_mapWindow.getTxtSIC().getText(), false); m_mapWindow.getTxtSIC().setText (DemoSymbols.getSIC(s_random.nextInt())); } else if ( m_mapWindow.getBtnSelect().isSelected() && selectElements(m_lastMouseClick, m_mapWindow.getMapBean().getActiveView(), m_selectedBounds) ) { // "Select & Drag Graphics" command: initialize mouse tracking to move the selected elements System.out.println ("start tracking at (" + m_lastMouseClick.getX() + ", " + m_lastMouseClick.getY() + ")"); // the envelope feedback draws a rectangle of the selected elements' extent following the mouse IMoveEnvelopeFeedback moveEnvelopeFeedback = new MoveEnvelopeFeedback(); moveEnvelopeFeedback.start (m_selectedBounds, m_lastMouseClick); m_moveFeedback = (IDisplayFeedback) moveEnvelopeFeedback; m_moveFeedback.setDisplayByRef (m_mapWindow.getMapBean().getActiveView().getScreenDisplay()); // the tick count is used to filter out short, unintentional mouse drags m_dragStartTime = System.currentTimeMillis(); } } catch ( Exception x ) { x.printStackTrace(); } } public void onMouseMove (IMapControlEvents2OnMouseMoveEvent e) { try { // update the current map location of the mouse m_currentMouseLocation.putCoords (e.getMapX(), e.getMapY()); // "Select & Drag Graphics" command: move the feedback graphic if ( m_mapWindow.getBtnSelect().isSelected() && e.getButton() == 1 && m_moveFeedback != null ) m_moveFeedback.moveTo (m_currentMouseLocation); } catch ( Exception x ) { x.printStackTrace(); } } public void onMouseUp (IMapControlEvents2OnMouseUpEvent e) { try { if ( m_moveFeedback != null ) { // stop the feedback graphic and save its geometry for future use m_selectedBounds = (Envelope) ((IMoveEnvelopeFeedback)m_moveFeedback).stop(); m_moveFeedback = null; long endTicks = System.currentTimeMillis() - m_dragStartTime; if ( endTicks > 250 ) { // only update the graphics if the minimum move time has elapsed System.out.println ("drag start = (" + m_lastMouseClick.getX() + ", " + m_lastMouseClick.getY() + ")"); System.out.println ("drag end = (" + m_currentMouseLocation.getX() + ", " + m_currentMouseLocation.getY() + ")"); moveGraphics ( m_currentMouseLocation.getX() - m_lastMouseClick.getX(), m_currentMouseLocation.getY() - m_lastMouseClick.getY() ); } } } catch ( Exception x ) { x.printStackTrace(); } } private void actionAdd200() { try { // this one takes a little while, especially when it's the first one chosen Cursor previousCursor = m_mapWindow.getCursor(); m_mapWindow.setCursor (Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); // create concentric rings of units centered around where the user last clicked double centerLon = m_lastMouseClick.getX(); double centerLat = m_lastMouseClick.getY(); final double circleRadiusInRad = 1.0; final int numberPerCircle = 10; for ( int i = 0; i < 200; ++i ) { // draw a random symbol at the next position in the pattern double currentRadius = (i / numberPerCircle) * circleRadiusInRad + circleRadiusInRad; double currentAngle = (i % numberPerCircle) * 2.0 * 3.1415926536 / (double)numberPerCircle; drawSymbol ( createPoint( centerLon + (currentRadius * Math.sin(currentAngle)), centerLat + (currentRadius * Math.cos(currentAngle)) ), DemoSymbols.getSIC(s_random.nextInt()), true ); } //refresh the display and restore the cursor m_mapWindow.getMapBean().getActiveView().partialRefresh (esriViewGraphics, null, null); m_mapWindow.setCursor (previousCursor); } catch ( Exception e ) { e.printStackTrace(); } } private void actionAddArea() { try { // create the symbol using a default symbol ID code (obstacle restricted area) IMoleSymbol moleSymbol = new MoleFillSymbol(); moleSymbol.setSymbolID ("GUMPOGR-------X"); moleSymbol.setTextLabels (getLabels()); moleSymbol.setTextSize (3.0); // override the default fill color and outline symbol - these settings are optional //ILineSymbol lineSymbol = new SimpleLineSymbol(); //lineSymbol.setColor (getRandomColor()); //lineSymbol.setWidth (dRandom(1, 5)); //IFillSymbol fillSymbol = (IFillSymbol) moleSymbol; //fillSymbol.setOutline (lineSymbol); //fillSymbol.setColor (getRandomColor()); // create a new polygon geometry for this symbol (four points in this example) IPointCollection pointCollection = new com.esri.arcgis.geometry.Polygon(); // center the polygon somewhere inside the current map extent IActiveView activeView = m_mapWindow.getMapBean().getActiveView(); Envelope extent = (Envelope) activeView.getExtent(); double lat = dRandom (extent.getYMin(), extent.getYMax()); double lon = dRandom (extent.getXMin(), extent.getXMax()); // place the four corners somewhere within a specified threshold of the center final double threshold = 20; pointCollection.addPoint (createPoint(lon, dRandom(lat, lat + threshold)), null, null); pointCollection.addPoint (createPoint(dRandom(lon, lon + threshold), lat), null, null); pointCollection.addPoint (createPoint(lon, dRandom(lat - threshold, lat)), null, null); pointCollection.addPoint (createPoint(dRandom(lon - threshold, lon), lat), null, null); // set up the graphic element with the random geometry IFillShapeElement fillShapeElement = new PolygonElement(); fillShapeElement.setSymbol ((IFillSymbol)moleSymbol); IElement element = (IElement) fillShapeElement; element.setGeometry ((IGeometry)pointCollection); // add the new element to the map and update the user interface activeView.getGraphicsContainer().addElement (element, 0); activeView.partialRefresh (esriViewGraphics, null, null); ++m_unitCount; updateTitle(); } catch ( Exception e ) { e.printStackTrace(); } } private void actionAddLine() { try { // create the symbol using a default symbol ID code (fix task line) IMoleSymbol moleSymbol = new MoleLineSymbol(); moleSymbol.setSymbolID ("GUTPF---------X"); moleSymbol.setTextLabels (getLabels()); moleSymbol.setTextSize (2.0); // override the default line color and width - these settings are optional //ILineSymbol lineSymbol = (ILineSymbol) moleSymbol; //lineSymbol.setColor (getRandomColor()); //lineSymbol.setWidth (dRandom(1, 5)); // create a new line geometry for the symbol - this symbol requires two points IPointCollection pointCollection = new Polyline(); // place the first endpoint of the line somewhere inside the current map extent IActiveView activeView = m_mapWindow.getMapBean().getActiveView(); Envelope ext = (Envelope) activeView.getExtent(); double lat = dRandom (ext.getYMin(), ext.getYMax()); double lon = dRandom (ext.getXMin(), ext.getXMax()); pointCollection.addPoint (createPoint(lon, lat), null, null); // place the second endpoint somewhere within a specified threshold of the first final double threshold = 20; pointCollection.addPoint ( createPoint( dRandom(lon - threshold, lon + threshold), dRandom(lat - threshold, lat + threshold) ), null, null ); // set up the graphic element with the random geometry ILineElement lineElement = new LineElement(); lineElement.setSymbol ((ILineSymbol)moleSymbol); IElement element = (IElement) lineElement; element.setGeometry ((IGeometry)pointCollection); // add the new element to the map and update the user interface activeView.getGraphicsContainer().addElement (element, 0); activeView.partialRefresh (esriViewGraphics, null, null); ++m_unitCount; updateTitle(); } catch ( Exception e ) { e.printStackTrace(); } } private void actionAddMoleSymbol() { try { // make this button exclusive both in the Swing toolbar and in the Toolbar bean // the primary logic is in onMouseDown boolean selected = m_mapWindow.getBtnAddMoleSymbol().isSelected(); System.out.println ("add MOLE symbol " + (selected ? "selected" : "deselected")); if ( selected ) { m_mapWindow.getToolbarBean().setBuddyControl (null); m_mapWindow.getToolbarBean().esri_setEnabled (false); m_mapWindow.getBtnSelect().setSelected (false); } else { m_mapWindow.getToolbarBean().setBuddyControl (m_mapWindow.getMapBean()); m_mapWindow.getToolbarBean().esri_setEnabled (true); } } catch ( Exception e ) { e.printStackTrace(); } } private void actionMoveUnits() { try { // MoveGraphics only applies to units in the selection - this will erase any previous selection IActiveView activeView = m_mapWindow.getMapBean().getActiveView(); IGraphicsContainerSelect graphicsContainerSelect = (IGraphicsContainerSelect) activeView.getGraphicsContainer(); graphicsContainerSelect.selectAllElements(); moveGraphics (0.75, 0.75); graphicsContainerSelect.unselectAllElements(); activeView.partialRefresh (esriViewGraphics, null, null); m_selectedBounds.setEmpty(); } catch ( Exception e ) { e.printStackTrace(); } } private void actionSelect() { try { // make this button exclusive both in the Swing toolbar and in the Toolbar bean // the primary logic is in onMouseDown and onMouseMove boolean selected = m_mapWindow.getBtnSelect().isSelected(); System.out.println ("select " + (selected ? "selected" : "deselected")); if ( selected ) { m_mapWindow.getToolbarBean().setBuddyControl (null); m_mapWindow.getToolbarBean().esri_setEnabled (false); m_mapWindow.getBtnAddMoleSymbol().setSelected (false); } else { m_mapWindow.getToolbarBean().setBuddyControl (m_mapWindow.getMapBean()); m_mapWindow.getToolbarBean().esri_setEnabled (true); } } catch ( Exception e ) { e.printStackTrace(); } } private void drawSymbol (IPoint location, String sic, boolean suppressRefresh) { try { // the first time we create a symbol, display the wait cursor while MOLE loads up Cursor previousCursor = m_mapWindow.getCursor(); if ( m_firstTime ) m_mapWindow.setCursor (Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); // set up a MOLE symbol for the new graphic; minimally validate the symbol ID code IMoleSymbol moleSymbol = new MoleMarkerSymbol(); if ( sic.length() == 15 ) moleSymbol.setSymbolID (sic); moleSymbol.setTextLabels (getLabels()); // to remove the symbol's fill, uncomment this code //IMoleMarkerSymbol moleMarkerSymbol = (IMoleMarkerSymbol) moleSymbol; //moleMarkerSymbol.setShowFill (false); // initialize the marker symbol size property double size = 36; try { size = Double.valueOf (m_mapWindow.getTxtSize().getText()); } catch ( Exception e ) {} IMarkerSymbol markerSymbol = (IMarkerSymbol) moleSymbol; markerSymbol.setSize (size); // create the graphic element for the marker symbol and add it to the map IMarkerElement markerElement = new MarkerElement(); markerElement.setSymbol (markerSymbol); IElement element = (IElement) markerElement; element.setGeometry ((IGeometry)location); IActiveView activeView = m_mapWindow.getMapBean().getActiveView(); activeView.getGraphicsContainer().addElement (element, 0); if ( ! suppressRefresh ) activeView.partialRefresh (esriViewGraphics, null, null); // update the user interface if ( m_firstTime ) { m_mapWindow.setCursor (previousCursor); m_firstTime = false; } ++m_unitCount; updateTitle(); } catch ( Exception e ) { e.printStackTrace(); } } private void moveGraphics (double deltaX, double deltaY) { try { // move all selected graphics along a delta (change) vector System.out.println ("moving delta = (" + deltaX + ", " + deltaY + ")"); // get reference to graphics container and its selected elements IActiveView activeView = m_mapWindow.getMapBean().getActiveView(); IGraphicsContainer graphicsContainer = activeView.getGraphicsContainer(); IGraphicsContainerSelect graphicsContainerSelect = (IGraphicsContainerSelect) graphicsContainer; IEnumElement enumElement = graphicsContainerSelect.getSelectedElements(); // iterate through the selected elements enumElement.reset(); IElement element = enumElement.next(); while (element != null) { // apply the delta vector to each element's geometry and update it the container IGeometry geometry = element.getGeometry(); ((ITransform2D)geometry).move (deltaX, deltaY); element.setGeometry (geometry); graphicsContainer.updateElement (element); element = enumElement.next(); } // refresh the active view activeView.partialRefresh (esriViewGraphics, null, null); } catch ( Exception e ) { e.printStackTrace(); } } private void updateTitle() { // put the number of symbols in the title bar, when there are any String title = "MOLE Symbols"; if ( m_unitCount == 1 ) title += " (" + m_unitCount + " unit)"; else if ( m_unitCount > 1 ) title += " (" + m_unitCount + " units)"; m_mapWindow.setTitle (title); } private static IPoint createPoint (double x, double y) { IPoint point = null; try { // create a new point instance and initialize its coordinates point = new com.esri.arcgis.geometry.Point(); point.putCoords (x, y); } catch ( Exception e ) { e.printStackTrace(); } return point; } private double dRandom (double low, double high) { // generate a random floating-point number within the indicated range [low, high) return low + s_random.nextDouble() * (high - low); } private static IPropertySet getLabels() { IPropertySet labelSet = null; try { labelSet = new PropertySet(); // all of the below are supported - comment and uncomment to experiment labelSet.setProperty ("Name", "Name"); labelSet.setProperty ("Comment", "Comment"); //labelSet.setProperty ("Parent", "Parent"); //labelSet.setProperty ("Info", "Info"); //labelSet.setProperty ("Strength", "Strength"); //labelSet.setProperty ("EvalRating", "EvalRating"); //labelSet.setProperty ("Location", "Location"); //labelSet.setProperty ("Alt_Depth", "Alt_Depth"); //labelSet.setProperty ("Speed", "Speed"); //labelSet.setProperty ("DTG", "DTG"); //labelSet.setProperty ("HQ", "HQ"); //labelSet.setProperty ("Quantity", "Quantity"); //labelSet.setProperty ("EType", "EType"); //labelSet.setProperty ("Effective", "Effective"); //labelSet.setProperty ("Signature", "Signature"); //labelSet.setProperty ("IFFSIF", "IFFSIF"); } catch ( Exception e ) { e.printStackTrace(); } return labelSet; } private static boolean selectElements (IPoint point, IActiveView activeView, Envelope selectedBounds) { try { // this function is written in such a way that it should be pastable System.out.println ("selecting graphics near (" + point.getX() + ", " + point.getY() + ")"); IGraphicsContainer graphicsContainer = activeView.getGraphicsContainer(); IGraphicsContainerSelect graphicsContainerSelect = (IGraphicsContainerSelect) graphicsContainer; IScreenDisplay screenDisplay = activeView.getScreenDisplay(); boolean selected = false; boolean refreshRequired = false; // start with a precise search, and then widen the tolerance if nothing is found // (you may need to change these tolerances if using this code in your own application) IEnumElement enumElement = graphicsContainer.locateElements (point, 0.0000001); if ( enumElement == null ) enumElement = graphicsContainer.locateElements (point, 0.5); // if no elements were selected if ( enumElement == null ) { // if the previous selection is nonempty if ( graphicsContainerSelect.getElementSelectionCount() > 0 ) { // clear the selection and refresh the display System.out.println ("clearing selection"); graphicsContainerSelect.unselectAllElements(); selectedBounds.setEmpty(); refreshRequired = true; } // else do nothing } else { // get the extent of the selected elements Envelope envelope = new Envelope(); enumElement.reset(); IElement element = enumElement.next(); while ( element != null ) { // establish selectedBounds as the extent of all selected elements element.queryBounds (screenDisplay, envelope); selectedBounds.union (envelope); element = enumElement.next(); } // add all the newly selected elements to the graphics container's selection enumElement.reset(); graphicsContainerSelect.selectElements (enumElement); refreshRequired = selected = true; } // refresh the display if anything has changed if ( refreshRequired ) activeView.partialRefresh (esriViewGraphics, null, null); // return true if any elements on the display are currently selected; selectedBounds has their extent return selected; } catch ( Exception e ) { e.printStackTrace(); } return false; } public static void main (String[] args) { EngineInitializer.initializeVisualBeans(); ToolTipManager.sharedInstance().setLightWeightPopupEnabled (false); new MoleBasicSymbols(); } }