Implement dynamic layer
arcgissamples\display\MyDynamicLayer.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.display;

import java.io.IOException;
import java.net.UnknownHostException;
import java.util.Random;

import com.esri.arcgis.carto.IDynamicLayer;
import com.esri.arcgis.carto.ILayer;
import com.esri.arcgis.display.CharacterMarkerSymbol;
import com.esri.arcgis.display.ICharacterMarkerSymbol;
import com.esri.arcgis.display.IDisplay;
import com.esri.arcgis.display.IDynamicDisplay;
import com.esri.arcgis.display.IDynamicGlyph;
import com.esri.arcgis.display.IDynamicGlyphFactory;
import com.esri.arcgis.display.IDynamicSymbolProperties;
import com.esri.arcgis.display.IDynamicSymbolProperties2;
import com.esri.arcgis.display.ISymbol;
import com.esri.arcgis.display.RgbColor;
import com.esri.arcgis.display.esriDynamicDrawPhase;
import com.esri.arcgis.display.esriDynamicSymbolType;
import com.esri.arcgis.geodatabase.IGeoDataset;
import com.esri.arcgis.geometry.Envelope;
import com.esri.arcgis.geometry.IEnvelopeGEN;
import com.esri.arcgis.geometry.ISpatialReference;
import com.esri.arcgis.geometry.Point;
import com.esri.arcgis.interop.AutomationException;
import com.esri.arcgis.system.ITrackCancel;
import com.esri.arcgis.system.IUID;
import com.esri.arcgis.system.IVariantStream;
import com.esri.arcgis.system.esriDrawPhase;

public class MyDynamicLayer implements Runnable, IDynamicLayer,ILayer,IGeoDataset{
  private static final long serialVersionUID = 1L;
  private IDynamicSymbolProperties dynamicSymbolProps = null;
    private IDynamicGlyphFactory dynamicGlyphFactory= null;
   
    private String name="";
  private IEnvelopeGEN extent=null;
  private ISpatialReference spatialRef = null;
  private boolean isCached = false;
  private boolean isValid=true; 
  private boolean isVisible = true;
  private double maximumScale, minimumScale = 0;
  private boolean showTips = false;
  private boolean isDirtyImmediate;
  private boolean isDirtyCompiled;
  private int recompileRate;
  private Point point=null;
  private boolean bOnce = true;
  private IDynamicGlyph markerGlyph = null;
  
  private double stepX = 0;
  private double stepY = 0;

   public MyDynamicLayer() {
      try {
        //set Name of the Layer
        this.setName("Dynamic Layer");
        //Start the thread
        Thread dirtybitThread=new Thread(this);
        dirtybitThread.start();
      } catch (UnknownHostException e) {
        e.printStackTrace();
      } catch (IOException e) {
        e.printStackTrace();
      }
      
    }
   
   /*
    * @see java.lang.Runnable#run()
    * This method sets the dirty flag for the layer every 30ms 
    */  
  public void run() {
    try {
      while(true){
        if(isVisible())
        this.setDynamicLayerDirty(esriDynamicDrawPhase.esriDDPImmediate,true);
        Thread.sleep(30);
      }
      } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }    
  }
  
  public String getName() throws IOException, AutomationException {
    return name;
  }

  public void setName(String layerName) throws IOException, AutomationException {
    name = layerName;
  }
  
   /*
    * @see com.esri.arcgis.carto.IDynamicLayer#drawDynamicLayer(int, com.esri.arcgis.display.IDisplay, com.esri.arcgis.display.IDynamicDisplay)
    * This method renders the dynamic layer
    */
  public void drawDynamicLayer(int dynamicDrawPhase, IDisplay display, IDynamicDisplay dynamicDisplay) {
    try {
      //Step i: If not valid or visible
      if (!(this.isValid())|| !(this.isVisible())) return;
      
      //Step ii: Check for the phase
      if (dynamicDrawPhase!=esriDynamicDrawPhase.esriDDPImmediate) return;
      
      //Step iii: get the current envelope                           
      IEnvelopeGEN visibleExtent = (IEnvelopeGEN)display.getDisplayTransformation().getFittedBounds();
      
      /*
       *Best Practice:Need to do it only once to 
       * avoid reinitializing variables
       * and creating glyphs,( glyphs are expensive)
       */
      if (bOnce){

        //Step iv: Create a simple glyph from marker symbol

        try {
          dynamicGlyphFactory = dynamicDisplay.getDynamicGlyphFactory();
          dynamicSymbolProps = (IDynamicSymbolProperties2)dynamicDisplay;

          //Create a marker symbol
          ICharacterMarkerSymbol markerSymbol = new CharacterMarkerSymbol();
          markerSymbol.setSize(25.0);
          //Set the symbol color to white
          RgbColor color=new RgbColor();
          color.setRGB(0xFFFFFF);
          markerSymbol.setColor(color);
          markerSymbol.setCharacterIndex(92);
          //create the dynamic glyph from IDynamicGlyphFactory
          markerGlyph = dynamicGlyphFactory.createDynamicGlyph((ISymbol)markerSymbol);

        } catch (Exception e) {
          System.out.println("Exception in MyDynamicLayer#CreatingGlyph");
          e.printStackTrace();
        } 

        //Step v: Initialize dynamic item's random initial position and define the Step increments
        Random r = new Random();
        double X = visibleExtent.getXMin() + r.nextDouble() * visibleExtent.getWidth();
        double Y = visibleExtent.getYMin() + r.nextDouble() * visibleExtent.getHeight();
        stepX = visibleExtent.getWidth() / 250;
        stepY = visibleExtent.getHeight() / 250;

        //create a point location to draw
        point = new Point();
        point.putCoords(X, Y);

        //set the once value to false
        bOnce = false;
      }


      //Step vi: define properties and draw the marker symbol
      dynamicSymbolProps.setDynamicGlyphByRef((esriDynamicSymbolType.esriDSymbolMarker),
          markerGlyph);
      //Set the color of the glyph
      dynamicSymbolProps.setColor(esriDynamicSymbolType.esriDSymbolMarker, 1.0f, 0.0f,
          0.0f, 1.0f);
      //Set the scale of the glyph
      dynamicSymbolProps.setScale(esriDynamicSymbolType.esriDSymbolMarker, 1.0f, 1.0f);
      //Draw the marker symbol on the given point
      dynamicDisplay.drawMarker(point);

      //Step vii : update the point location for the next draw cycle                            
      point.setX(point.getX()+stepX);
      point.setY(point.getY()+stepY);

      //make sure that the point falls within the visible extent
      if (point.getX() > visibleExtent.getXMax())
        stepX = - Math.abs(stepX);
      if (point.getX() < visibleExtent.getXMin())
        stepX = Math.abs(stepX);
      if (point.getY() > visibleExtent.getYMax())
        stepY = - Math.abs(stepY);
      if (point.getY() < visibleExtent.getYMin())
        stepY = Math.abs(stepY);

      //Step viii: set the dirty flag to false in order to stop the drawing in immediate phase
      setDynamicLayerDirty(esriDynamicDrawPhase.esriDDPImmediate, false);
    } catch (Exception e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
  
  /*
   * @see com.esri.arcgis.carto.IDynamicLayer#getDynamicRecompileRate()
   * This method is called by the DD framework to determine the recompile rate for the layer
   */
  public int getDynamicRecompileRate() throws IOException, AutomationException {
    return this.recompileRate;
  }
  
  /*
   * @see com.esri.arcgis.carto.IDynamicLayer#setDynamicLayerDirty(int, boolean)
   * This method sets the dirty flag for the dynamic layer for the corresponding phases
   */
  public void setDynamicLayerDirty(int drawPhase, boolean dirtyFlag) throws IOException, AutomationException {
     if (drawPhase == esriDynamicDrawPhase.esriDDPImmediate)
         isDirtyImmediate = dirtyFlag;
     else
       isDirtyCompiled = dirtyFlag;
  }
  /*
   * @see com.esri.arcgis.carto.IDynamicLayer#isDynamicLayerDirty(int)
   * This method is called by the DD framework every draw cycle to check whether the layer is dirty
   * If the layer is dirty the DD framework calls the drawDynamicLayer() method to render the layer
   */
   public boolean isDynamicLayerDirty(int drawPhase) throws IOException, AutomationException {
      if (drawPhase == esriDynamicDrawPhase.esriDDPImmediate)
            return isDirtyImmediate;
      else
          return isDirtyCompiled;
  }

   public boolean isValid() throws IOException, AutomationException {
    return isValid;
  }

  public double getMinimumScale() throws IOException, AutomationException {
    return minimumScale;
  }

  public void setMinimumScale(double scale) throws IOException, AutomationException {
    minimumScale = scale;    
  }

  public double getMaximumScale() throws IOException, AutomationException {
    return maximumScale;
  }

  public void setMaximumScale(double scale) throws IOException, AutomationException {
    maximumScale = scale;
  }

  public boolean isVisible() throws IOException, AutomationException {
    return isVisible;
  }

  public void setVisible(boolean visible) throws IOException, AutomationException {
    isVisible = visible;
  }

  public boolean isShowTips() throws IOException, AutomationException {
    return showTips;
  }

  public void setShowTips(boolean tips) throws IOException, AutomationException {
    showTips = tips;
  }

  public boolean isCached() throws IOException, AutomationException {
  
    return isCached;
  }

  public void setCached(boolean cached) throws IOException, AutomationException {
    isCached = cached;  
  }
  
  public void setSpatialReferenceByRef(ISpatialReference spatialRef) throws IOException, AutomationException {
    this.spatialRef = spatialRef;  
  }
  
  public ISpatialReference getSpatialReference() throws IOException, AutomationException {
    return spatialRef;
  }

  public Envelope getExtent() throws IOException, AutomationException {
    return (Envelope)extent;
  }

  public IUID getID() throws IOException, AutomationException {
    return null;
  }
  
public void load(IVariantStream arg0) throws IOException, AutomationException {
    //Not Supported in Java
  }

  public void save(IVariantStream arg0) throws IOException, AutomationException {
    //Not Supported in Java
  }
  
  public Envelope getAreaOfInterest() throws IOException, AutomationException {
    return (Envelope)extent;
  }
  
  public double getLastMinimumScale() throws IOException, AutomationException {
    return 0;
  }

  public double getLastMaximumScale() throws IOException, AutomationException {
    return 0;
  }

  public String ILayerGeneralProperties_getLayerDescription() throws IOException, AutomationException {
    return null;
  }
  
public void setLayerDescription(String arg0) throws IOException, AutomationException {
    
  }
  
  public String getTipText(double arg0, double arg1, double arg2) throws IOException, AutomationException {
    return null;
  }
  
  public int getSupportedDrawPhases() throws IOException, AutomationException {
    return esriDrawPhase.esriDPAnnotation;
  }

  //Method not implemented;Layer will be drawn only in dynamic mode
  public void draw(int arg0, IDisplay arg1, ITrackCancel arg2) throws IOException, AutomationException{
  
}


}