Select to view content in your preferred language

override layer.add() method

1019
7
03-26-2011 04:24 AM
GregKnight
Deactivated User
Hi,

I would like to build some custom Graphic and Feature Layers.  I would like to include behavior (mouseOvers, mouseClicks, etc) of the layer's graphics in this customization.  It would seem that in order to do so, I need to override the layer.add() method... although this is not supported according to the API docs.  So, there must be another way...

How do I go about accessing the graphics as they are added to the layer so I can add the appropriate listeners?  Is the approach the same for both graphic/feature layers?

Many thanks,

-g
Tags (2)
0 Kudos
7 Replies
Drew
by
Frequent Contributor
When you get your query results just add the listeners to the graphic.
Below is a code sample..


queryTask.execute(query, new AsyncResponder(onResult, onFault));
    
function onResult(featureSet:FeatureSet, token:Object = null):void
{
 for each (var graphic:Graphic in featureSet.features)
 {
  graphic.addEventListener(MouseEvent.MOUSE_OVER, function(event:MouseEvent):void
  {
   graphic.useHandCursor = true;
   graphic.buttonMode = true;
   map.openHandCursorVisible = false;
   trace("mouse over"); 
  });
  
  graphic.addEventListener(MouseEvent.MOUSE_OUT, function(event:MouseEvent):void
  {
   graphic.useHandCursor = false;
   graphic.buttonMode = false;
   map.openHandCursorVisible = true;
   trace("mouse out");
  });
  graphic.addEventListener(MouseEvent.CLICK, function(event:MouseEvent):void
  {
   trace("Click");
  })
 }
}



Drew
0 Kudos
GregKnight
Deactivated User
That would certainly work if I were using the default graphic/feature layer... but I wish to extend it to create a custom layer as follows:

public class BuildingFeatureLayer extends FeatureLayer
 {
  
  private var defaultSymbol:SimpleFillSymbol = new SimpleFillSymbol();
  private var mouseOverSymbol:SimpleFillSymbol = new SimpleFillSymbol();
  
  public function BuildingFeatureLayer()
  {
   super();

   setLoaded(true);
   
   defaultSymbol.color = 0xFFFFFF;
   defaultSymbol.alpha = 0.1;
   
   mouseOverSymbol.color = 0xFF0000;
   mouseOverSymbol.alpha = 0.5;
   
   this.mode = "snapshot";
   this.symbol=defaultSymbol;
   this.outFields = [];
   this.url="http://<server>/ArcGIS/rest/services/layers/<layername>/MapServer/0"
   this.useAMF=false;
   this.visible=true;
  }

  override protected function updateLayer():void
  {
   super.updateLayer();
  }

                // OVERRIDING THIS METHOD IS NOT PERMITTED BY THE API
                override public function add(graphic:Graphic):void
  {
   graphic.toolTip = graphic.attributes.BUILDING_NAME;
   graphic.addEventListener( MouseEvent.ROLL_OVER, graphic_mouseOverHandler );
   graphic.addEventListener( MouseEvent.ROLL_OUT, graphic_mouseOutHandler );
  }


Problem is, the API does not permit overriding the add(graphic:Graphic) method, so that I can add the necessary listeners.
0 Kudos
Drew
by
Frequent Contributor
On the FeatureLayer there is a "graphicAdd" event. This will give you a graphic to apply the listeners on.
See the below ESRI sample illustrating adding tooltips to a graphic. I have not tested this, but I assume you would apply similar code to as i showed above.

Link:
http://help.arcgis.com/en/webapi/flex/samples/index.html?sample=FeatureLayerWithTooltips

Drew
0 Kudos
ReneRubalcava
Esri Frequent Contributor
I don't see in the docs where overriding the add() method is not supported.
http://help.arcgis.com/en/webapi/flex/apiref/com/esri/ags/layers/GraphicsLayer.html#add()

According to the docs you could add your listeners there, then call super.add(graphic).
I usually try to assign my changes before calling the super.

Or you could add a listener in your constructor for com.esri.ags.events.GraphicEvent.GRAPHIC_ADD event and do it that way.
0 Kudos
GregKnight
Deactivated User
So... no takers eh?  Bjorn? Dasa? Any suggestions?  🙂
0 Kudos
ReneRubalcava
Esri Frequent Contributor
The GraphicEvent.GRAPHIC_ADD method is probably your best approach. I tried it out and it works on all Selection Modes and gives you access to the graphic when it is added.

package org.lacsd.layers
{
 import com.esri.ags.Graphic;
 import com.esri.ags.events.GraphicEvent;
 import com.esri.ags.events.GraphicsLayerEvent;
 import com.esri.ags.layers.FeatureLayer;
 import flash.events.MouseEvent;
 import mx.utils.ObjectUtil;
 public class TestFeatureLayer extends FeatureLayer
 {
  public function TestFeatureLayer(url:String=null, proxyURL:String=null, token:String=null)
  {
   super(url, proxyURL, token);
   
   this.addEventListener(GraphicEvent.GRAPHIC_ADD, onGraphicAdd);
   this.addEventListener(GraphicEvent.GRAPHIC_REMOVE, onGraphicRemove);
   this.addEventListener(GraphicsLayerEvent.GRAPHICS_CLEAR, onGraphicsClear);
  }
  
  private function addListener(graphic:Graphic):void
  {
   graphic.addEventListener(MouseEvent.MOUSE_OVER, function(event:MouseEvent):void
   {
    graphic.useHandCursor = true;
    graphic.buttonMode = true;
    map.openHandCursorVisible = false;
    trace("mouse over"); 
   });
   
   graphic.addEventListener(MouseEvent.MOUSE_OUT, function(event:MouseEvent):void
   {
    graphic.useHandCursor = false;
    graphic.buttonMode = false;
    map.openHandCursorVisible = true;
    trace("mouse out");
   });
   graphic.addEventListener(MouseEvent.CLICK, function(event:MouseEvent):void
   {
    trace("Click");
   })
  
  }
  
  private function onGraphicAdd(event:GraphicEvent):void
  {
   trace("graphic has been added", ObjectUtil.toString(event.graphic.attributes));
   this.addListener(event.graphic);
   // add listeners here
  }
  
  private function onGraphicRemove(event:GraphicEvent):void
  {
   trace("graphic has been removed", ObjectUtil.toString(event.graphic.attributes));
   // remove listeners here
  }
  
  private function onGraphicsClear(event:GraphicsLayerEvent):void
  {
   // may want to find a way to remove listeners here or add them with a weak reference
  }
 }
}


I think the reason you can't override the add() method for FeatureLayer is because the internal Relate/Query tasks interact directly with the GraphicsProvider/SelectedFeatures.
0 Kudos
GregKnight
Deactivated User
there we go...  this is what I was missing:

this.addEventListener(GraphicEvent.GRAPHIC_ADD, onGraphicAdd);
this.addEventListener(GraphicEvent.GRAPHIC_REMOVE, onGraphicRemove);
this.addEventListener(GraphicsLayerEvent.GRAPHICS_CLEAR, onGraphicsClear);


Drew was on the right track -- I just wasnt sure how to grab that event in the context of what I was doing.

I shall give this a whirl... thank you both!

greg
0 Kudos