Flex PropertyGrid 实现

PropertyGrid在界面设计工具中是比较常用的组件,在.NET的WinForm设计中,PropertyGrid作为内置的组件来实现对button、label等组件的属性设置,不仅满足了设计时的需要,还能够在运行时提供美观实用的帮助;但是Flex作为目前界面设计展现方向上的主流技术,并没有提供该组件。为了弥补这一不足,本文将介绍并实现Flex PropertyGrid组件模型。

    PropertyGrid模型可以分为两个部分,即行为模型和数据展现模型。

所谓的行为模型就是PropertyGrid所包含的事件及其在不同状态下的展示方式。事件部分我们暂且只支持PropertyGrid的selectedObjectChanged事件。展示方式主要是悬浮状态下,Mini选项卡开启,鼠标移到Mini选项卡的时候PropertyGrid主面板弹出,鼠标移出PropertyGrid时,PropertyGrid自动关闭,同时显示出Mini选项卡,;非悬浮状态下,PropertyGrid停靠在Container中,Mini选项卡关闭。

数据展现模型就是PropertyGrid所展示内容的元数据定义,用这些定义好的元数据标记数据类型后,PropertyGrid可以自动的从数据类型实例中读取元数据定义,并根据类别、描述等信息自动展示。

事件模型处理相关代码如下

[Event(name="selectedObjectChanged",type="propertygrid.PropertyGridEvent")]

    [Event(name="floatStateChanged",type="propertygrid.PropertyGridEvent")];

    public class IPropertyGrid extends Canvas

    {

        //是否悬浮

        private var isFloat:Boolean=false;

        //悬浮状态需要的mini属性卡

        private var miniPropertyGird:Canvas=null;

        //当前选择对象

        private var selectedObject:Object=null;

        

        //属性窗口容器

        public var container:DisplayObjectContainer=null;

        //属性窗口内容展示区

        public var content:VBox=null;

        //悬浮状态切换图片

        public var title_img_pin:Image=null;

        //最小化图片

        public var title_img_min:Image=null;

        

        /**

         * 构造函数

         * */

        public function IPropertyGrid()

        {

            this.addEventListener(FlexEvent.CREATION_COMPLETE,init);

            this.addEventListener(PropertyGridEvent.FLOAT_STATE_CHANGED,floateStateChangedHandler);

        }

        

        /**

         * 悬浮状态切换的处理函数

         *

         * 逻辑:悬浮状态,从容器中移除属性窗口,将mini属性窗口增加到容器中,同时为属性窗口增加Rollout处理函数

         *         内嵌状态,将属性窗口增加到容器,从容器中mini属性窗口,移除属性窗口的Rollout处理函数

         * */

        public function floateStateChangedHandler(e:PropertyGridEvent):void

        {

            if(isFloat)

            {

                this.container.removeChild(this);

                this.container.addChild(miniPropertyGird);

                this.addEventListener(MouseEvent.ROLL_OUT,mouseClosePropGrid);

            }

            else

            {

                this.container.addChild(this);

                this.container.removeChild(miniPropertyGird);

                this.removeEventListener(MouseEvent.ROLL_OUT,mouseClosePropGrid);

            }

        }

        

        /**

         * 获取当前选中对象

         * */

        public function get SelectedObj():Object

        {

            return this.selectedObject;

        }

        

        /**

         * 更改当前选中对象,并触发SELECTED_OBJECT_CHANGED事件

         * */

        public function set SelectedObj(obj:Object):void

        {

            if(this.selectedObject!=obj)

            {

                this.selectedObject=obj;

                dispatchEvent(new PropertyGridEvent(PropertyGridEvent.SELECTED_OBJECT_CHANGED));

            }

        }

        

        /**

         * 初始化函数

         * */

        public function init(e:FlexEvent):void

        {

            Assert.notNull(container,"container");

            Assert.notNull(content,"content");

            Assert.notNull(title_img_pin,"title_img_pin");

            Assert.notNull(title_img_min,"title_img_min");

            title_img_pin.addEventListener(MouseEvent.CLICK,changeFloatState);

            title_img_min.addEventListener(MouseEvent.CLICK,minPropertyGrid);

            initMiniPropertyGrid();

        }

                

        /**

         * 更改悬浮状态函数

         * */

        public function changeFloatState(e:MouseEvent):void

        {

            this.isFloat=!this.isFloat;

            dispatchEvent(new PropertyGridEvent(PropertyGridEvent.FLOAT_STATE_CHANGED));

        }

        

        /**

         * 悬浮状态下显示属性窗口函数

         * */

        public function showPropertyGrid(e:MouseEvent):void

        {

            var point:Point=new Point(container.x+container.width-this.width,container.y);

            var targetPoint:Point=container.localToGlobal(point);

            this.x=targetPoint.x;

            this.y=targetPoint.y;

            this.height=container.height;

            PopUpManager.addPopUp(this,container,false);

            var effect:WipeLeft=new WipeLeft();

            effect.duration=300;

            effect.target=this;

            effect.play();

        }

        

        /**

         * 初始化mini属性窗口

         * */

        public function initMiniPropertyGrid():void

        {

            miniPropertyGird=new Canvas();

            miniPropertyGird.height=100;

            miniPropertyGird.width=25;

            miniPropertyGird.setStyle("top",0);

            miniPropertyGird.setStyle("right",0);

            var img:Image=new Image();

            img.source="assets/propertygrid.png";

            img.percentHeight=100;

            img.percentWidth=100;

            img.addEventListener(MouseEvent.MOUSE_OVER,showPropertyGrid);

            

            miniPropertyGird.addChild(img);

        }

        

        /**

         * 最小化属性窗口函数

         * */

        public function minPropertyGrid(e:MouseEvent):void

        {

            PopUpManager.removePopUp(this);

        }

        

        /**

         * 关闭悬浮状态属性窗口处理函数

         * */

        public function mouseClosePropGrid(e:MouseEvent):void

        {

            var pg:IPropertyGrid=e.target as IPropertyGrid;

            if(pg!=null)

            {

                PopUpManager.removePopUp(pg);

            }

        }

        

        /**

         * 增加属性窗口单元

         *

         * @param title:单元标题

         * */

        public function addGridUnit(title:String):GridUnit

        {

            var tgrid:GridUnit=new GridUnit();

            PopUpManager.addPopUp(tgrid,Application.application.document);

            tgrid.title_content.text=title;

            this.content.addChild(tgrid);

            return tgrid;

        }

    }

 

    /**

     * @desc:    属性窗口事件

     *     SELECTED_OBJECT_CHANGED        当前选中对象改变时触发的事件

     *     FLOAT_STATE_CHANGED            悬浮状态发生改变时触发的事件

     *

     * @author:    sunjingtao

     * */

    public class PropertyGridEvent extends Event

    {

        public static const SELECTED_OBJECT_CHANGED:String="selectedObjectChanged";

        public static const FLOAT_STATE_CHANGED:String="floatStateChanged";

        public function PropertyGridEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false)

        {

            super(type, bubbles, cancelable);

        }

        

    }

 

数据模型部分想要做好就比较复杂,但是主要就是反射相关知识以及元数据的使用

反射:describeType函数

元数据:编译时增加编译参数-keep-as3-metadata+=MetaData1,MetaData2…

 

使用

假设我们对以下对象进行属性设置:

    public class Activity

    {

        [Appearance(name="imageSource",description="图像资源")]

        public var ImageSource:String;

        

        [Behavior(name="do1",description="行为")]

        public var DoEvent1:String;

        

        [Behavior(name="do2",description="行为")]

        public var DoEvent2:String;

        

        public var Test:String;

        

        public function Activity(source:String,doEvent:String)

        {

            this.ImageSource=source;

            this.DoEvent1=doEvent+"11";

            this.DoEvent2=doEvent+"22";

        }

    }

 

主程序为:

<?xml version="1.0" encoding="utf-8"?>

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"

    xmlns:propertygrid="ui.propertygrid.*">

<mx:Script>

    <![CDATA[

        import datastructure.Map;

        import mx.managers.PopUpManager;

        import ui.propertygrid.GridUnit;

        import mx.controls.Label;

        import mx.containers.GridItem;

        import mx.containers.GridRow;

        import mx.collections.ArrayCollection;

        import reflect.MetaDataInfo;

        import reflect.MetaData;

        import mx.containers.FormItem;

        import reflect.Variable;

        import reflect.InstanceInfo;

        import flash.utils.describeType;

        import xdesigner.Activity;

        private function doParse():void

        {

            var act:Activity=new Activity("source","doEvent");

            var instance:MetaDataInfo=new MetaDataInfo(act);

            for each(var key:String in instance.Keys)

            {

                var tgrid:GridUnit=propgrid.addGridUnit(key);

                for each(var obj:Object in instance.getMetaDataRefObjs(key))

                {

                    if(obj is Variable)

                    {

                        var variable:Variable=obj as Variable;

                        var map:Map=new Map();

                        map.push("text",variable.Value);

                        tgrid.addRow(variable.Name,new Label(),map);

                    }

                }

            }

            

        }

    ]]>

</mx:Script>

<mx:Canvas id="container" width="100%" height="100%">

    <mx:Canvas width="100%" height="100%" borderStyle="solid" borderColor="#F5F7F9">

        <propertygrid:PropertyGrid id="propgrid" container="{container}" x="81" y="31">

            

        </propertygrid:PropertyGrid>

    </mx:Canvas>

</mx:Canvas>

<mx:Button label="Parse" click="doParse()"/>

</mx:Application>

 

原创文章,转载请注明出处!
All CopyRight Reserved

主页:http://jingtao.cnblogs.com

QQ:307073463
Email:jingtaodeemail@qq.com
MSN:sunjingtao@live.com

 

显示效果:

 

posted @ 2010-06-21 20:45  镜涛  阅读(2029)  评论(1编辑  收藏  举报
Creative Commons License

本文基于署名 2.5 中国大陆许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名孙镜涛(包含链接)。如您有任何疑问或者授权方面的协商,请给我留言