MOLE custom callback
arcgissamples\defensesolutions\MOLECustomCallback.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 com.esri.arcgis.defensesolutions.*;
import com.esri.arcgis.display.IDisplay;
import java.io.IOException;
import com.esri.arcgis.interop.AutomationException;
import java.awt.event.*;
import java.awt.*;
import java.io.File;

import javax.swing.*;

import com.esri.arcgis.beans.map.MapBean;
import com.esri.arcgis.beans.toolbar.ToolbarBean;
import com.esri.arcgis.controls.*;

import com.esri.arcgis.systemUI.*;
import com.esri.arcgis.system.*;
import com.esri.arcgis.display.*;
import com.esri.arcgis.geometry.*;

/**
 * Title: CustomCallback
 * Description: Demonstrates how to
 * 1. Create and Draw Force Element Graphics using CachedGraphics
 * 2. Subscribe to the AfterDraw event on a DisplayList
 *
 * See sample description in help system for more detailed information
 */
public class MOLECustomCallback extends JFrame implements ActionListener {
  private static final long serialVersionUID = 1L;

  MapControl mapControl;

  MapBean mapBean = null;
  ToolbarBean toolbarBean = null;

  JTextField sicText;
  JTextField nameText;
  JTextField parentText;

  JLabel sicLabel;
  JLabel nameLabel;
  JLabel parentLabel;

  JPanel mainPanel;
  JPanel buttonPanel;

  JCheckBox chkDraw;
  boolean bDrawOnClick = false;

  // Set the Default Path that works in windows with eclipse.
  // If not running from Eclipse (Linux/Solaris), the application
  // uses the AGSDEVKITJAVA environment variable to locate the data directory
  static String dataPath = ".." + File.separator + ".." +
  File.separator + "data" + File.separator;

  static String worldPath = dataPath + "world" + File.separator;
  static String baseMapShp = "dissolvecntry.shp";

  IDisplayList displayList = null;
  IFEGraphicFactory feFactory = null;

  // String Array to pass values between UI and mouse events:
  // 0: SIC, 1: Name, 2:Parent
  String[] symProps;

  public MOLECustomCallback() {
    super("Custom Callback");

    try {

      initUI();

      mapBean.addIMapControlEvents2Listener(new mapControlListener());

      checkOrSetDataPath();

      mapBean.addShapeFile(worldPath, baseMapShp);


      // Show a Progress Bar to let the user know that this will take a few secs
      JProgressBar aJProgressBar = new JProgressBar();
      aJProgressBar.setIndeterminate(true);
      JFrame theFrame = new JFrame("Waiting on Renderer Initialization");
      theFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      Container contentPane = theFrame.getContentPane();
      contentPane.add(aJProgressBar, BorderLayout.NORTH);
      theFrame.setSize(500, 100);
      theFrame.setVisible(true);
      // end of Progress Bar creation code

      initMole();

      // Hide the progress bar
      theFrame.setVisible(false);
    } catch (Exception ex) {
      ex.printStackTrace();
    }

  }

  public static void main(String[] args) {
    try {
      //Call initializer prior to using ArcGIS Java Beans
      EngineInitializer.initializeVisualBeans();

      //Initialize Engine license
      AoInitialize aoInit = new AoInitialize();
      if (aoInit.isProductCodeAvailable( com.esri.arcgis.system.esriLicenseProductCode.esriLicenseProductCodeEngine) == com.esri.arcgis.system.esriLicenseStatus.esriLicenseAvailable )
        aoInit.initialize(esriLicenseProductCode.esriLicenseProductCodeEngine);
      else {
        JOptionPane.showInputDialog( "Could not initialize an ArcGIS Engine license. Exiting application.");
        System.exit(-1);
      }

      new MOLECustomCallback();

    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  /**
   * Initializes MOLE data members
   *
   */
  public void initMole() {
    try {
      symProps = new String[]{"SFGPUCI---AHUSG", "", ""};

      ILeaderingProperties leaderProps;
      IAutoGroupRule groupRule;
      IPropertySet propertySet;
      IForceElementDisplayList feDisplayList;

      // Create the factory
      feFactory = (IFEGraphicFactory) new FEGraphicFactory();
      // turn on the labels
      turnOnAllLabels(feFactory);

      displayList = new ForceElementDisplayList();
      feDisplayList = (IForceElementDisplayList)displayList;

      feDisplayList.setSize(0.075 * ((Envelope)mapBean.getExtent()).getHeight());

      try
      {
        //set up leadering
        leaderProps = (ILeaderingProperties)displayList;
        leaderProps.setIsLeaderingEnabled(true);
        leaderProps.setLeaderStyleByRef(new BracketLeaderStyle());

        leaderProps.getLeaderRuleSet().reset();

        // Must use proxy for this cast, normal cast doesn't work
        // groupRule = (IAutoGroupRule)leaderProps.getLeaderRuleSet().next();
        groupRule = new IAutoGroupRuleProxy(leaderProps.getLeaderRuleSet().next());

        while(groupRule != null)
        {

          if(groupRule.getName().equalsIgnoreCase("Proximity Rule"))
          {
            propertySet = groupRule.getPropertySet();
            propertySet.setProperty("Tolerance", new Double(10.0));
          }
          try{
            groupRule = new IAutoGroupRuleProxy(leaderProps.
                getLeaderRuleSet().next());
          } catch(Exception ex) {groupRule = null;}
        }
      }
      catch (Exception ex)
      {
        ex.printStackTrace();
      }

      //prepare custom callback object
      displayList.setCallBackByRef(new MyCallback());

    } catch(Exception e){e.printStackTrace();}

  }

  /**
   * Configures the labels setting for the FEGraphicFactory
   *
   * @param feGraphicFactory IFEGraphicFactory to configure labels for
   */
  public void turnOnAllLabels(IFEGraphicFactory feGraphicFactory)
  {
    try
    {
      if (feFactory == null)
        return;

      IEnumAttributeLabel enumAttributeLabel = (IEnumAttributeLabel)feGraphicFactory;

      // 1. Cycle through the IEnumAttributeLabel's
      // 2. Set the visibility on each to true
      enumAttributeLabel.reset();
      for (int i=0; i < enumAttributeLabel.getCount(); i++) {
        IAttributeLabel pAttrib = enumAttributeLabel.nextLabel();

        // Uncomment if this output is desired
        // System.out.println("IEnumAttributeLabel.IAttributeLabel[" + i + "]=" +
        //    pAttrib.getName() + ":" + pAttrib.isVisible());

        pAttrib.setIsVisible(true);
      }

    }
    catch (Exception ex)
    {
      ex.printStackTrace();
    }

  }

  /**
   * Checks for the required directory and prompts the user if it can't be found
   */
  public void checkOrSetDataPath()
  {
    // see if the required data files exist, check one of the files
    String checkFile = worldPath + baseMapShp;
    boolean exists = (new File(checkFile)).exists();
    if (!exists) {
      // we may not be running from IDE, see if AGSDEVKITJAVA defined and use it
      String arcgishome= null;
      try{
        arcgishome = System.getenv("AGSDEVKITJAVA");
      }catch(Error e){
        arcgishome = JOptionPane.showInputDialog("Please enter the path to the ArcGIS Engine directory");
      }
      dataPath = arcgishome+File.separator+"java"+File.separator+"samples"+File.separator+
      "data"+File.separator;

      worldPath = dataPath + "world" + File.separator;

      // check again if it exists
      checkFile = worldPath + baseMapShp;
      exists = (new File(checkFile)).exists();
      if (!exists) {
        // File or directory does not exist, that's bad, better warn the user
        // and let them try to correct
        JOptionPane.showMessageDialog(this, "Could not find required data directory\n" +
        "Warning: Application will not run as expected");
      }

    }
  }

  /**
   * Configures the UI
   */
  public void initUI(){
    //build the UI
    try{
      BorderLayout layout = new BorderLayout();
      SpringLayout blayout = new SpringLayout();

      layout.setHgap(3);
      layout.setVgap(3);
      mainPanel = new JPanel(layout);
      buttonPanel = new JPanel(blayout);

      mapBean = new MapBean();
      toolbarBean = new ToolbarBean();

      sicLabel = new JLabel("Symbol ID:");
      nameLabel = new JLabel("Name:");
      parentLabel = new JLabel("Parent:");

      sicText = new JTextField("SFGPUCI---AHUSG");
      nameText = new JTextField();
      parentText = new JTextField();

      chkDraw = new JCheckBox("Draw Graphic On Click");
      chkDraw.addActionListener(this);

      sicText.setPreferredSize(new Dimension(135, 25));
      sicText.setMaximumSize(new Dimension(135, 25));
      nameText.setPreferredSize(new Dimension(135, 25));
      nameText.setMaximumSize(new Dimension(135, 25));
      parentText.setPreferredSize(new Dimension(135, 25));
      parentText.setMaximumSize(new Dimension(135, 25));

      sicLabel.setPreferredSize(new Dimension(70, 25));
      sicLabel.setMaximumSize(new Dimension(70, 25));
      nameLabel.setPreferredSize(new Dimension(55, 25));
      nameLabel.setMaximumSize(new Dimension(55, 25));
      parentLabel.setPreferredSize(new Dimension(55, 25));
      parentLabel.setMaximumSize(new Dimension(55, 25));
      chkDraw.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);

      buttonPanel.add(sicText);
      buttonPanel.add(sicLabel);
      buttonPanel.add(nameText);
      buttonPanel.add(nameLabel);
      buttonPanel.add(parentText);
      buttonPanel.add(parentLabel);
      buttonPanel.add(chkDraw);

      blayout.putConstraint(SpringLayout.NORTH, sicLabel, 8, SpringLayout.NORTH, buttonPanel);
      blayout.putConstraint(SpringLayout.WEST, sicLabel, 8, SpringLayout.WEST, buttonPanel);

      blayout.putConstraint(SpringLayout.WEST, chkDraw, 3, SpringLayout.WEST, sicLabel);
      blayout.putConstraint(SpringLayout.NORTH, chkDraw, 10, SpringLayout.SOUTH, sicLabel);

      blayout.putConstraint(SpringLayout.NORTH, sicText, 0, SpringLayout.NORTH, sicLabel);
      blayout.putConstraint(SpringLayout.WEST, sicText, 5, SpringLayout.EAST, sicLabel);

      blayout.putConstraint(SpringLayout.NORTH, nameLabel, 0, SpringLayout.NORTH, sicText);
      blayout.putConstraint(SpringLayout.WEST, nameLabel, 5, SpringLayout.EAST, sicText);

      blayout.putConstraint(SpringLayout.NORTH, nameText, 0, SpringLayout.NORTH, nameLabel);
      blayout.putConstraint(SpringLayout.WEST, nameText, 5, SpringLayout.EAST, nameLabel);

      blayout.putConstraint(SpringLayout.NORTH, parentLabel, 8, SpringLayout.SOUTH, nameLabel);
      blayout.putConstraint(SpringLayout.WEST, parentLabel, 0, SpringLayout.WEST, nameLabel);

      blayout.putConstraint(SpringLayout.NORTH, parentText, 0, SpringLayout.NORTH, parentLabel);
      blayout.putConstraint(SpringLayout.WEST, parentText, 5, SpringLayout.EAST, parentLabel);

      blayout.putConstraint(SpringLayout.SOUTH, buttonPanel, 10, SpringLayout.SOUTH, parentText);
      blayout.putConstraint(SpringLayout.EAST, buttonPanel, 10, SpringLayout.EAST, parentText);

      //prepare main panel
      mainPanel.add(mapBean, BorderLayout.CENTER);
      mainPanel.add(buttonPanel, BorderLayout.SOUTH);
      mainPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));

      mainPanel.add(toolbarBean, BorderLayout.NORTH);

      // Toolbar initialization
      toolbarBean.setBuddyControl(mapBean);

      toolbarBean.addItem(new ControlsMapZoomInTool(), 0, -1, true, 0,
          esriCommandStyles.esriCommandStyleIconAndText); //ZoomIn
      toolbarBean.addItem(new ControlsMapZoomOutTool(), 0, -1, false, 0,
          esriCommandStyles.esriCommandStyleIconAndText); //ZoomOut
      toolbarBean.addItem(new ControlsMapZoomInFixedCommand(), 0, -1, false, 0,
          esriCommandStyles.esriCommandStyleIconAndText);
      toolbarBean.addItem(new ControlsMapZoomOutFixedCommand(), 0, -1, false, 0,
          esriCommandStyles.esriCommandStyleIconAndText);
      toolbarBean.addItem(new ControlsMapPanTool(), 0, -1, true, //Pan
          0, esriCommandStyles.esriCommandStyleIconOnly);
      toolbarBean.addItem(new ControlsMapFullExtentCommand(), 0, -1, true,
          0, esriCommandStyles.esriCommandStyleIconOnly);// Full Extent
          // end of Toolbar initialization

      getContentPane().add(mainPanel);

      // key event listeners
      parentText.addKeyListener(new textListener());
      sicText.addKeyListener(new textListener());
      nameText.addKeyListener(new textListener());

      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

      setSize(700, 600);

      setVisible(true);

    }catch(Exception e){e.printStackTrace();}

  }

  public class mapControlListener extends IMapControlEvents2Adapter {
    private static final long serialVersionUID = 1L;

    public void onAfterDraw(IMapControlEvents2OnAfterDrawEvent
        imapControlEvents2OnAfterDrawEvent) throws
        IOException, AutomationException {
      final IDisplay display = mapBean.getActiveView().getScreenDisplay();

      try {
        if (displayList != null)
        {
          ((IForceElementDisplayList)displayList)
          .setSize(0.075 * ((Envelope)mapBean.getExtent()).getHeight());
          displayList.draw(display, null, null);
        }
      } catch (Exception e) {
        e.printStackTrace();
      }

    }

    public void onDoubleClick(IMapControlEvents2OnDoubleClickEvent
        imapControlEvents2OnDoubleClickEvent) throws
        IOException, AutomationException {
      try {
        mapBean.setExtent(mapBean.getFullExtent());

      } catch (Exception e) {
        e.printStackTrace();
      }
    }

    public void onMouseDown(IMapControlEvents2OnMouseDownEvent
        imapControlEvents2OnMouseDownEvent) throws
        IOException, AutomationException {

      try {
        if (imapControlEvents2OnMouseDownEvent.getButton() == 2) {
          mapBean.setExtent(mapBean.trackRectangle());
        } else {

          if (!bDrawOnClick)
            return;

          IFEGraphic feGraphic;
          ICachedGraphic cachedGraphic;
          IForceElement feObject;
          IPoint point;

          //Use low level factory to create generic graphic object
          cachedGraphic = (ICachedGraphic)feFactory.make(symProps[0]);

          //set location and size in map units
          point = mapBean.toMapPoint(
              imapControlEvents2OnMouseDownEvent.getX(),
              imapControlEvents2OnMouseDownEvent.getY());

          cachedGraphic.setGeometryByRef(point);
          cachedGraphic.setSize(0.075 *
              ((Envelope)mapBean.getExtent()).getHeight());

          feObject = new ForceElement();
          feObject.setMessageString(symProps[0]);
          feObject.getPropertySet().setProperty("Name", symProps[1]);
          feObject.getPropertySet().setProperty("Parent", symProps[2]);
          feObject.setShapeByRef(point);

          //assign force element object and cached graphic to Force Element Graphic
          feGraphic = (IFEGraphic)cachedGraphic;
          feGraphic.setForceElementByRef(feObject);

          //set default 2525B force element graphic style
          IFEGraphicStyle graphicStyle;
          graphicStyle = new FEGraphicStyle();

          feGraphic.setStyleByRef(graphicStyle);
          displayList.add(cachedGraphic);

          mapBean.getActiveView().refresh();
        }

      } catch (Exception e) {
        e.printStackTrace();
      }

    }

  }

  //  Handle actions
  public void actionPerformed(ActionEvent e) {

    if (e.getSource() == chkDraw)
    {
      if(chkDraw.isSelected())
      {
        bDrawOnClick = true;
      }
      else {
        bDrawOnClick = false;
      }
    }
  }

  // handle text actions
  public class textListener extends KeyAdapter {
    public void keyTyped(KeyEvent e) {

      try{
        if(e.getSource().equals(nameText))
        {
          Runnable r = new Runnable(){
            public void run(){
              symProps[1] = nameText.getText();
            }
          };
          javax.swing.SwingUtilities.invokeLater(r);
        }
        else if(e.getSource().equals(parentText))
        {
          Runnable r = new Runnable(){
            public void run(){
              symProps[2] = parentText.getText();
            }
          };
          javax.swing.SwingUtilities.invokeLater(r);

        }
        else if(e.getSource().equals(sicText))
        {
          Runnable r = new Runnable(){
            public void run(){
              symProps[0] = sicText.getText();
            }
          };
          javax.swing.SwingUtilities.invokeLater(r);

        }


      }catch(Exception ex){ex.printStackTrace();}
    }
  }

  public class MyCallback implements ICallBack {
    private static final long serialVersionUID = 1L;

    public void afterGraphicDraw(IDisplay iDisplay,
        ICachedGraphic iCachedGraphic) throws
        IOException, AutomationException {
      try{
        ISimpleFillSymbol simpleFillSymbol;
        IRgbColor color;
        ISimpleLineSymbol lineSymbol;

        color = new RgbColor();
        color.setGreen(255);

        lineSymbol = new SimpleLineSymbol();
        lineSymbol.setColor(color);
        lineSymbol.setWidth(2);

        simpleFillSymbol = new SimpleFillSymbol();
        simpleFillSymbol.setStyle(esriSimpleFillStyle.esriSFSNull);
        simpleFillSymbol.setOutline(lineSymbol);

        IEnvelope[] envelope = {new Envelope()};

        iCachedGraphic.queryBounds(iDisplay, envelope);

        iDisplay.setSymbol((ISymbol)simpleFillSymbol);
        iDisplay.drawRectangle(envelope[0]);
      }catch(Exception e){e.printStackTrace();}
    }

    public void beforeGraphicDraw(IDisplay iDisplay,
        ICachedGraphic iCachedGraphic,
        boolean[] booleanArray) throws
        IOException, AutomationException {

    }

  }
}