2013/02/27

Customized Interactions on Network in TWaver Flex

The following several interactive modes have been provided in TWaver as default:


In most cases, they are sufficient, but customized interactions are also available. Now we will introduce how to customize interactive mode with the combination of just a "pan" and the general interactive modes:
If an element is selected, then all the operations will be performed on it; if not, then the "pan" interactive mode as dragging the background.
Generally, in "pan" interactive mode, elements cannot be selected and dragged. It is the same as general map interactive mode and they can only show the range of dragging. But through some operations element-dragging and background-dragging can be separated.
The logic of the method "handleMouseDown" has been changed.
public class CustomInteractionHandler extends BasicInteractionHandler {
        private var pressPoint:Point;
        private var oldButtonMode:Boolean;
        private var olduseHandCursor:Boolean;

        public function CustomInteractionHandler(network:Network) {
            super(network);
            installListeners();
        }

        override public function installListeners():void {
            this.network.addEventListener(MouseEvent.MOUSE_DOWN, handleMouseDown);
            this.network.addEventListener(MouseEvent.MOUSE_UP, handleMouseUp);
        }

        /**
         * @inheritDoc
         *
         */
        override public function uninstallListeners():void {
            this.network.removeEventListener(MouseEvent.MOUSE_DOWN, handleMouseDown);
            this.network.removeEventListener(MouseEvent.MOUSE_UP, handleMouseUp);
        }

        private function handleMouseDown(e:MouseEvent):void {
            if (!this.network.isValidMouseEvent(e) || this.network.isMovingElement || this.network.isEditingElement) {
                return;
            }
            var element:IElement=network.getElementByMouseEvent(e);
            if (element) {
                if (!this.network.selectionModel.contains(element)) {
                    this.network.selectionModel.setSelection(element);
                }
            } else {
                this.network.selectionModel.clearSelection();
                pressPoint=new Point(e.stageX, e.stageY);
                this.network.addEventListener(MouseEvent.MOUSE_MOVE, handleMouseMove);
                oldButtonMode=this.network.buttonMode;
                olduseHandCursor=this.network.useHandCursor;
                this.network.useHandCursor=true
                this.network.buttonMode=true
                this.network.cursorManager.removeAllCursors();
            }

        }

        private function handleMouseUp(e:MouseEvent):void {
            if (pressPoint != null) {
                pressPoint=null;
                this.network.buttonMode=oldButtonMode;
                this.network.useHandCursor=olduseHandCursor;
                this.network.removeEventListener(MouseEvent.MOUSE_MOVE, handleMouseMove);
            }
        }

        private function handleMouseMove(e:MouseEvent):void {
            if (!e.buttonDown) {
                pressPoint=null;
                this.network.buttonMode=oldButtonMode;
                this.network.useHandCursor=olduseHandCursor;
                this.network.removeEventListener(MouseEvent.MOUSE_MOVE, handleMouseMove);
                return;
            }
            if (this.network.verticalScrollBar == null && this.network.horizontalScrollBar == null) {
                return;
            }
            var xOffset:Number=pressPoint.x - e.stageX;
            var yOffset:Number=pressPoint.y - e.stageY;
            pressPoint.x-=xOffset;
            pressPoint.y-=yOffset;
            this.network.horizontalScrollPosition+=xOffset;
            this.network.verticalScrollPosition+=yOffset;
        }
    }
Now it has become much more simpler.
network.interactionHandlers=new Collection([
       new CustomInteractionHandler(this),
new DefaultInteractionHandler(this),]);

2013/02/22

How to customize Icon in Menu in TWaver Flex

Icon in Menu must be specified through iconField and iconFunction. But in the two methods above, Icon has to be done with Class name of embedded resources. So if you would like to set dynamic image (like URL) as Icon in Menu, MenuItemRenderer must be customized.
First, set a class CustomMenuItemRender to inherit MenuItemRenderer with a parameter added as the component of customized Icon.
 private var image:UIComponent = new UIComponent();
Then rewrite the method “measure” (to calculate the width and height of “MenuItem”).
 override protected function measure():void {
    super.measure();
  
    if (separatorIcon || listData == null) {
        return;
    }
  
    var imageAsset:IImageAsset = Utils.getImageAsset(data.@iconName);
    if(imageAsset == null){
        return;
    }
    measuredWidth += imageAsset.width;
    if(imageAsset.height > measuredHeight){
        measuredHeight = imageAsset.height;
    }
}
Rewrite the method “commitProperties” (Rewrite and add Icon & set the width and height of Icon).
 override protected function commitProperties():void {
    super.commitProperties();
   
    if (separatorIcon || listData == null) {
        return;
    }
   
    var imageAsset:IImageAsset = Utils.getImageAsset(data.@iconName);
    if(imageAsset == null){
        return;
    }
    image.width = imageAsset.width;
    image.height = imageAsset.height;
    image.graphics.beginBitmapFill(imageAsset.getBitmapData());
    image.graphics.drawRect(0, 0, image.width, image.height);
    image.graphics.endFill();
    if(!this.contains(image)){
        this.addChild(image);
    }
}
Rewrite the method “updateDisplayList”(specify the position of Icon: since Icon is at the left side, so we’d better first call the method “super” before the movement of Label):
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void{
    super.updateDisplayList(unscaledWidth, unscaledHeight);
   
    if (separatorIcon || listData == null) {
        return;
    }
   
    var imageAsset:IImageAsset = Utils.getImageAsset(data.@iconName);
    if(imageAsset == null){
        return;
    }
    if(typeIcon){
        typeIcon.x += imageAsset.width;
    }
    if(label){
        label.x += imageAsset.width;
    }
}
Rewrite the method “measuredIconWidth” (to calculate the width of Icon):
override public function get measuredIconWidth():Number {
    var imageAsset:IImageAsset = Utils.getImageAsset(data.@iconName);
    if(imageAsset == null){
        return 0 ;
    }else{
        var horizontalGap:Number = getStyle("horizontalGap");
        return imageAsset.width + horizontalGap;
    }
}
At last, specify “ItemRenderer” of Menu with customized CustomMenuItemRenderer. Notice that the name of icon specified by iconName should be used. (Here is the name of the registered image in TWawer.) Also, other names can be used. Do not forget to change “@iconNme” in “CustomMenuItemRenderer”.
var menu:Menu = Menu.createMenu(network, myMenuData, false);
menu.labelField = "@label";
menu.itemRenderer = new ClassFactory(CustomMenuItemRenderer);
var point:Point = network.getLogicalPoint(event.mouseEvent);
network.callLater(function():void{
    menu.show(point.x, point.y);
});
Specify the XML file of the data in Menu as follows:
    <mx:XML format="e4x" id="myMenuData">
        <root>
            <menuitem label="www.servasoftware.com" iconName="databox_icon">
                <menuitem label="TWaver" type="check" toggled="true">
                    <menuitem label="Java" type="radio" groupName="one"/>
                    <menuitem label="Web" type="radio" groupName="one" toggled="true"/>
                    <menuitem label="Flex" type="radio" groupName="one" iconName="bus_icon"/>
                    <menuitem label="Silverlight" type="radio" groupName="one"/>
                </menuitem>
                <menuitem type="separator"/>
                <menuitem label="2BizBox" iconName="data_icon"/>
            </menuitem>
            <menuitem label="www.2bizbox.com"/>
            <menuitem label="twaver.servasoft.com"/>
        </root>
    </mx:XML>
</code>

Please see the official document for more on the method MenuItemRenderer:

http://livedocs.adobe.com/flex/3/html/help.html?content=menucontrols_3.htmlhttp://livedocs.adobe.com/flex/3/html/help.html?content=menucontrols_3.html
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/controls/menuClasses/MenuItemRenderer.html