可以最小化停靠的弹出窗口

参看了一些网上的最小化窗口,发现大多都是添加在容器中的面板,所以利用popupmanager写了个组件,需要用到flexlib.swc的ButtonScrollingCanvas和自己写的PopUp组件(已贴出)。skin是自动生成的,稍作修改。
工具代码:

package pizazz.flex4.utility{
import flash.display.Stage;
import flash.events.MouseEvent;
import flash.geom.Point;
import mx.core.IUIComponent;
import spark.components.Button;

public class UIUtil{
public static function buttonFactory(label:String,
onClick:Function = null, width:Number = NaN,
icon:Class = null, target:Button = null):Button{
if(!target){
target = new Button();
}
if(onClick != null){
target.addEventListener(MouseEvent.CLICK, onClick);
}
if(icon != null){
target.setStyle("icon", icon);
}
target.setStyle("cornerRadius", 0);
ParamUtil.setParam(target, {
"width": width,
"label": label
});
return target;
}

public static function includeContainer(target:IUIComponent,
stage:Stage):Point{
var _x:Number = target.x;
var _y:Number = target.y;
if(_x > stage.stageWidth){
target.x = stage.stageWidth > target.width ?
stage.stageWidth - target.width : 0;
}else if(_x < 0){
target.x = 0;
}
if(_y > stage.stageHeight){
target.y = stage.stageHeight > target.height ?
stage.stageHeight - target.height : 0;
}else if(_y < 0){
target.y = 0;
}
return new Point(target.x, target.y);
}
}
}

组件代码:
pizazz\flex4\container\skin\MinimizeButtonSkin.mxml

<?xml version="1.0" encoding="utf-8"?>
<s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:fb="http://ns.adobe.com/flashbuilder/2009"
alpha.disabled="0.5">
<fx:Metadata>
<![CDATA[
[HostComponent("spark.components.Button")]
]]>
</fx:Metadata>
<fx:Script fb:purpose="styling">
private static const exclusions:Array = ["xSymbol"];
private static const symbols:Array = ["xFill1", "xFill2"];

override public function get colorizeExclusions():Array{
return exclusions;
}

override public function get symbolItems():Array{
return symbols
}
</fx:Script>
<s:states>
<s:State name="up" />
<s:State name="over"/>
<s:State name="down" />
<s:State name="disabled" />
</s:states>
<s:RectangularDropShadow id="dropShadow" blurX="0" blurY="0" alpha="0"
alpha.over="0.85" alpha.down=".85" distance="1" angle="90"
color="0xFFFFFF" left="0" top="0" right="0" bottom="0"/>
<s:Rect left="0" top="0" right="0" bottom="0">
<s:stroke>
<s:SolidColorStroke color="0x000000" alpha="0.0" alpha.over="0.7"
alpha.down="0.7" weight="1"/>
</s:stroke>
<s:fill>
<s:SolidColor color="0xCCCCCC" alpha="0" alpha.down="0.7" />
</s:fill>
</s:Rect>
<s:Rect id="cbshad" left="1" right="1" top="1" height="1" >
<s:fill>
<s:SolidColor color="0x000000" color.over="0xFFFFFF" alpha="0"
alpha.over=".85" alpha.down="0.22" />
</s:fill>
</s:Rect>
<s:Group top="1" left="1" id="xSymbol">
<s:Path blendMode="normal" alpha=".85"
data="M 3 10 L 3 9 L 4 9 L 4 8 L 9 8 L 9 9 L 10 9 L 10 10 Z">
<s:fill>
<s:SolidColor id="xFill1" color="0x000000" />
</s:fill>
</s:Path>
<s:Path blendMode="normal" alpha=".75"
data="M 3 9 L 3 8 L 4 8 L 4 9 L 3 9 M 10 9 L 10 8 L 9 8 L 9 9 Z">
<s:fill>
<s:SolidColor id="xFill2" color="0x000000" />
</s:fill>
</s:Path>
<s:Path blendMode="normal" alpha=".85"
data="M 3 10 L 3 11 L 10 11 L 10 10 L 3 10 Z">
<s:fill>
<s:SolidColor color="0xFFFFFF" />
</s:fill>
</s:Path>
</s:Group>
</s:SparkSkin>

pizazz\flex4\container\skin\WindowTemplateSkin.mxml

<?xml version="1.0" encoding="utf-8"?>
<s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:fb="http://ns.adobe.com/flashbuilder/2009"
alpha.disabled="0.5" alpha.disabledWithControlBar="0.5"
blendMode="normal" mouseEnabled="false">
<fx:Metadata>
<![CDATA[
[HostComponent("pizazz.flex4.container.WindowTemplate")]
]]>
</fx:Metadata>
<fx:Script>
static private const exclusions:Array = ["background",
"titleDisplay", "contentGroup"];

override public function get colorizeExclusions():Array {
return exclusions;
}

override protected function initializationComplete():void{
useChromeColor = true;
super.initializationComplete();
}

override protected function updateDisplayList(unscaledWidth:Number,
unscaledHeight:Number):void{
if (getStyle("borderVisible") == true){
border.visible = true;
background.left = background.top = background.right =
background.bottom = 1;
contents.left = contents.top = contents.right =
contents.bottom = 1;
}else{
border.visible = false;
background.left = background.top = background.right =
background.bottom = 0;
contents.left = contents.top = contents.right =
contents.bottom = 0;
}
dropShadow.visible = getStyle("dropShadowVisible");

var cr:Number = getStyle("cornerRadius");
var withControls:Boolean =
(currentState == "disabledWithControlBar" ||
currentState == "normalWithControlBar" ||
currentState == "inactiveWithControlBar");

if (cornerRadius != cr){
cornerRadius = cr;
dropShadow.tlRadius = cornerRadius;
dropShadow.trRadius = cornerRadius;
dropShadow.blRadius = withControls ? cornerRadius : 0;
dropShadow.brRadius = withControls ? cornerRadius : 0;
setPartCornerRadii(topMaskRect, withControls);
setPartCornerRadii(border, withControls);
setPartCornerRadii(background, withControls);
}

if (bottomMaskRect){
setPartCornerRadii(bottomMaskRect, withControls);
}
borderStroke.color = getStyle("borderColor");
borderStroke.alpha = getStyle("borderAlpha");
backgroundFill.color = getStyle("backgroundColor");
backgroundFill.alpha = getStyle("backgroundAlpha");
super.updateDisplayList(unscaledWidth, unscaledHeight);
}

private function setPartCornerRadii(target:Rect,
includeBottom:Boolean):void{
target.topLeftRadiusX = cornerRadius;
target.topRightRadiusX = cornerRadius;
target.bottomLeftRadiusX = includeBottom ? cornerRadius : 0;
target.bottomRightRadiusX = includeBottom ? cornerRadius : 0;
}
private var cornerRadius:Number;
</fx:Script>
<s:states>
<s:State name="normal" />
<s:State name="inactive" stateGroups="inactiveGroup" />
<s:State name="disabled" />
<s:State name="minimize" />
<s:State name="normalWithControlBar" stateGroups="withControls" />
<s:State name="inactiveWithControlBar"
stateGroups="withControls, inactiveGroup" />
<s:State name="disabledWithControlBar" stateGroups="withControls" />
</s:states>
<s:RectangularDropShadow id="dropShadow" blurX="20" blurY="20"
alpha="0.32" alpha.inactiveGroup="0.22" distance="11"
distance.inactiveGroup="7" angle="90" color="0x000000" left="0"
top="0" right="0" bottom="0"/>
<s:Group left="0" right="0" top="0" bottom="0">
<s:Group left="1" top="1" right="1" bottom="1" id="topGroupMask">
<s:Rect id="topMaskRect" left="0" top="0" right="0" bottom="0">
<s:fill>
<s:SolidColor alpha="0"/>
</s:fill>
</s:Rect>
</s:Group>
<s:Group left="1" top="1" right="1" bottom="1" id="bottomGroupMask"
includeIn="withControls">
<s:Rect id="bottomMaskRect" left="0" top="0" right="0" bottom="0">
<s:fill>
<s:SolidColor alpha="0"/>
</s:fill>
</s:Rect>
</s:Group>
<s:Rect id="border" left="0" right="0" top="0" bottom="0" >
<s:stroke>
<s:SolidColorStroke id="borderStroke" weight="1" />
</s:stroke>
</s:Rect>
<s:Rect id="background" left="1" top="1" right="1" bottom="1">
<s:fill>
<s:SolidColor id="backgroundFill" color="#FFFFFF"/>
</s:fill>
</s:Rect>
<s:Group left="1" right="1" top="1" bottom="1" id="contents">
<s:layout>
<s:VerticalLayout gap="0" horizontalAlign="justify" />
</s:layout>
<s:Group id="topGroup" mask="{topGroupMask}">
<s:Rect id="tbFill" left="0" right="0" top="0" bottom="1">
<s:fill>
<s:LinearGradient rotation="90">
<s:GradientEntry color="0xD2D2D2"
color.inactiveGroup="0xEAEAEA"/>
<s:GradientEntry color="0x9A9A9A"
color.inactiveGroup="0xCECECE"/>
</s:LinearGradient>
</s:fill>
</s:Rect>
<s:Rect id="tbHilite" left="0" right="0" top="0" bottom="0">
<s:stroke>
<s:LinearGradientStroke rotation="90" weight="1">
<s:GradientEntry color="0xE6E6E6" />
<s:GradientEntry color="0xFFFFFF" alpha="0.22"/>
</s:LinearGradientStroke>
</s:stroke>
<s:fill>
<s:LinearGradient rotation="90">
<s:GradientEntry color="0xFFFFFF" alpha="0.15" />
<s:GradientEntry color="0xFFFFFF" alpha="0.15"
ratio="0.44"/>
<s:GradientEntry color="0xFFFFFF" alpha="0"
ratio="0.4401"/>
</s:LinearGradient>
</s:fill>
</s:Rect>
<s:Rect id="tbDiv" left="0" right="0" height="1" bottom="0">
<s:fill>
<s:SolidColor color="0x000000" alpha="0.75" />
</s:fill>
</s:Rect>
<s:Label id="titleDisplay" maxDisplayedLines="1" left="9"
right="36" top="1" bottom="0" minHeight="24"
verticalAlign="middle" fontWeight="bold" />
<s:Group id="moveArea" left="0" right="0" top="0" bottom="0" />
<s:Button id="minimizeButton" toolTip="最小化" width="15"
excludeFrom="minimize" right="26" top="7" height="15"
skinClass="pizazz.flex4.container.skin.MinimizeButtonSkin" />
<s:Button id="closeButton" toolTip="关闭" width="15" height="15"
skinClass="spark.skins.spark.TitleWindowCloseButtonSkin"
right="7" top="7" />
</s:Group>
<s:Group id="contentGroup" excludeFrom="minimize" width="100%"
height="100%" minWidth="0" minHeight="0">
</s:Group>
<s:Group id="bottomGroup" minWidth="0" minHeight="0"
includeIn="withControls">
<s:Group left="0" right="0" top="0" bottom="0"
mask="{bottomGroupMask}">
<s:Rect left="0" right="0" top="0" height="1" alpha="0.22">
<s:fill>
<s:SolidColor color="0x000000" />
</s:fill>
</s:Rect>
<s:Rect left="0" right="0" top="1" bottom="0">
<s:stroke>
<s:LinearGradientStroke rotation="90" weight="1">
<s:GradientEntry color="0xFFFFFF" />
<s:GradientEntry color="0xD8D8D8" />
</s:LinearGradientStroke>
</s:stroke>
</s:Rect>
<s:Rect left="1" right="1" top="2" bottom="1">
<s:fill>
<s:LinearGradient rotation="90">
<s:GradientEntry color="0xEDEDED"/>
<s:GradientEntry color="0xCDCDCD"/>
</s:LinearGradient>
</s:fill>
</s:Rect>
</s:Group>
<s:Group id="controlBarGroup" left="0" right="0" top="1"
bottom="1" minWidth="0" minHeight="0">
<s:layout>
<s:HorizontalLayout paddingLeft="10" paddingRight="10"
paddingTop="7" paddingBottom="7" gap="10" />
</s:layout>
</s:Group>
</s:Group>
</s:Group>
</s:Group>
</s:SparkSkin>


package pizazz.flex4.container{
import flash.utils.Dictionary;
import flexlib.containers.ButtonScrollingCanvas;
import pizazz.flex4.container.component.WindowItem;
import spark.components.HGroup;

public class WindowBar extends ButtonScrollingCanvas{
private const _container:HGroup = new HGroup();
private const _items:Dictionary = new Dictionary();
private var _size:int = 0;
private var _index:int = 0;

public function get size():int{
return _size;
}

public function WindowBar(){
super();
WindowTemplate.init(this);
_container.percentWidth = 100;
height = 24;
buttonWidth = 20;
}

override protected function createChildren():void{
super.createChildren();
addElement(_container);
}

public function addData(item:WindowTemplate):void{
if(!_items[item]){
_items[item] = new WindowItem(item, _size);
_size++;
}
}

public function removeData(item:WindowTemplate):void{
var _target:WindowItem = _items[item];
if(_target){
delete _items[item];
if(_target.index != _size - 1){
for each(var _item:WindowItem in _items){
if(_item.index > _target.index){
_item.index--;
}
}
}
_size--;
}
}

public function getIndex(item:WindowTemplate):int{
for each(var _item:WindowItem in _items){
if(_item.item == item){
return _item.index;
}
}
return -1;
}

public function getItem(index:int):WindowTemplate{
if(index >= 0){
for each(var _item:WindowItem in _items){
if(_item.index == index){
return _item.item;
}
}
}
return null;
}

public function addToBar(item:WindowTemplate):void{
_container.addElement(item);
}

public function removeFromBar(item:WindowTemplate):void{
if(_container.getElementIndex(item) != -1){
_container.removeElement(item);
}
}
}
}


package pizazz.flex4.container{
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Point;
import pizazz.flex4.container.skin.WindowTemplateSkin;
import pizazz.flex4.manager.PopUp;
import pizazz.flex4.utility.UIUtil;
import spark.components.Button;
import spark.components.TitleWindow;

[Event(name="minimize", type="flash.events.Event")]
[SkinState("normal")]
[SkinState("minimize")]

public class WindowTemplate extends TitleWindow{
[SkinPart(required="true")]
public var minimizeButton:Button;
public var sign:String = "";
private var _closeable:Boolean = true;
private var _minimizable:Boolean = true;
private var _mask:Boolean = false;
private var _isPanel:Boolean = false;
private var _addrPoint:Point = new Point();
private var _areaPoint:Point = new Point();
private var _state:String = STATE_NORMAL;
private static var _bar:WindowBar;

public static const STATE_MINIMIZE:String = "minimize";
public static const STATE_NORMAL:String = "normal";
/**
* 是否为面板模式
*/
public function set isPanel(value:Boolean):void{
_isPanel = value;
}
/**
* 是否显示最小化按钮
*/
public function set minimizable(value:Boolean):void{
_minimizable = value;
}
/**
* 是否显示关闭按钮
*/
public function set closeable(value:Boolean):void{
_closeable = value;
}
/**
* 获取最小化停靠栏
* @return 最小化停靠栏
*/
public function get bar():WindowBar{
return _bar;
}

public function WindowTemplate(){
super();
minWidth = 160;
setStyle("skinClass", WindowTemplateSkin);
}
/**
* 弹出面板
* @param mask 是否为模态窗口
* @param sign 窗口弹出唯一标志
*/
public function open(mask:Boolean = false, sign:String = ""):Boolean{
return PopUp.openWindow(this, (_mask = mask), sign);
}
/**
* 关闭面板
*/
public function shut():void{
if(_state == STATE_MINIMIZE && _bar != null){
_bar.removeFromBar(this);
}
if(_bar != null){
_bar.removeData(this);
}
PopUp.closeWindow(this);
}

override protected function partAdded(partName:String,
instance:Object):void{
super.partAdded(partName, instance);
if(instance == closeButton){
if(!_closeable || _isPanel){
closeButton.visible = false;
closeButton.includeInLayout = false;
}
closeButton.addEventListener(MouseEvent.CLICK,
buttonClickHandler);
}else if(instance == minimizeButton){
if(!_minimizable || _isPanel){
minimizeButton.visible = false;
minimizeButton.includeInLayout = false;
}else if(!_closeable){
minimizeButton.right = 7;
}
minimizeButton.owner = this;
minimizeButton.addEventListener(MouseEvent.CLICK,
buttonClickHandler);
}
}

override protected function moveArea_mouseDownHandler(
event:MouseEvent):void{
super.moveArea_mouseDownHandler(event);
if(_state == STATE_MINIMIZE && !isPopUp && !_isPanel){
toNormal();
}
}

override protected function getCurrentSkinState():String{
return _state;
}

override protected function createChildren():void{
super.createChildren();
if(_bar != null && !_isPanel){
_bar.addData(this);
}else if(_bar == null){
_minimizable = false;
}
}

private function buttonClickHandler(event:MouseEvent):void{
if(event.currentTarget == minimizeButton){
toMinimize();
dispatchEvent(new Event("minimize"));
}else if(event.currentTarget == closeButton){
shut();
}
event.preventDefault();
}
/**
* 窗口标准状态
*/
public function toNormal():void{
if(_bar != null){
_bar.removeFromBar(this);
}
PopUp.updateState(this);
open(_mask, sign);
updateState(STATE_NORMAL, _addrPoint.x, _addrPoint.y,
_areaPoint.x, _areaPoint.y);
}
/**
* 窗口最小化状态
*/
public function toMinimize():void{
_addrPoint = new Point(x, y);
_areaPoint = new Point(width, height);
updateState(STATE_MINIMIZE, x, y, 200, 24);
PopUp.updateState(this, STATE_MINIMIZE);
if(_bar != null){
_bar.addToBar(this);
}
}

public static function init(bar:WindowBar):void{
_bar = bar;
}

private function updateState(state:String, addrX:int,
addrY:int, areaWidth:uint, areaHeight:uint):void{
_state = state;
x = addrX;
y = addrY;
width = areaWidth;
height = areaHeight;
invalidateSkinState();
}

override protected function moveArea_mouseUpHandler(event:Event):void{
super.moveArea_mouseUpHandler(event);
UIUtil.includeContainer(this, stage);
}
}
}

组件执行:

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:container="pizazz.flex4.container.*"
minWidth="955" minHeight="600" creationComplete="init()" >
<s:layout>
<s:BasicLayout />
</s:layout>
<fx:Script>
<![CDATA[
import mx.controls.Alert;
import pizazz.flex4.container.WindowTemplate;
import pizazz.flex4.manager.PopUp;
import pizazz.flex4.utility.UIUtil;

private var num:int = 0;

private function init():void{
PopUp.init(this);
panelWindow();
}

private function panelWindow():void{
const _panel:WindowTemplate = new WindowTemplate();
_panel.isPanel = true;
_panel.x = 100;
_panel.y = 30;
_panel.width = 320;
_panel.height = 240;
_panel.title = "非弹出窗口";
addElement(_panel);
}

private function minimizeWindow():void{
var _window:WindowTemplate = windowFactory();
_window.closeable = false;
_window.title = "无关闭按钮窗口";
_window.open();
_window.toMinimize();
}

private function normalWindow():void{
var _window:WindowTemplate = windowFactory();
_window.title = "默认弹出窗口";
_window.minimizable = false;
_window.open(false, "unique");
}

private function openWindow():void{
var _window:WindowTemplate = windowFactory();
_window.title = "窗口" + num++;
_window.open();
}

private function windowFactory():WindowTemplate{
const _window:WindowTemplate = new WindowTemplate();
_window.width = 320;
_window.height = 240;
_window.addElement(UIUtil.buttonFactory("显示",
function(event:MouseEvent):void{
var i:int = _window.bar.getIndex(_window);
Alert.show("窗口总数:" + _window.bar.size +
"\n当前序列:" + i);
}
, 100));
return _window;
}
]]>
</fx:Script>
<s:HGroup>
<s:Button width="100" label="打开窗口" click="openWindow()" />
<s:Button width="100" label="缩小窗口" click="minimizeWindow()" />
<s:Button width="100" label="普通窗口" click="normalWindow()" />
</s:HGroup>
<container:WindowBar width="{width}" bottom="0" />
</s:Application>

视图:
[img]http://dl.iteye.com/upload/attachment/342497/7e9b2c4a-f06b-3154-b630-40aaa3dded72.png[/img]

[color=yellow]当模态窗口和最小化按钮并存时,点击最小化不符合操作逻辑。[/color]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值