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 !
QQ:307073463
Email:jingtaodeemail@qq.com
MSN:sunjingtao@live.com
显示效果:
本文基于署名 2.5 中国大陆许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名孙镜涛(包含链接),具体操作方式可参考此处。如您有任何疑问或者授权方面的协商,请给我留言。