using System;
using System.Collections.Generic;
using UnityEngine;
namespace FairyGUI
{
///
/// Window class.
/// 窗口使用前首先要设置窗口中需要显示的内容,这通常是在编辑器里制作好的,可以直接使用Window.contentPane进行设置。
/// 建议把设置contentPane等初始化操作放置到Window.onInit方法中。
/// 另外,FairyGUI还提供了一套机制用于窗口动态创建。动态创建是指初始时仅指定窗口需要使用的资源,等窗口需要显示时才实际开始构建窗口的内容。
/// 首先需要在窗口的构造函数中调用Window.addUISource。这个方法需要一个IUISource类型的参数,而IUISource是一个接口,
/// 用户需要自行实现载入相关UI包的逻辑。当窗口第一次显示之前,IUISource的加载方法将会被调用,并等待载入完成后才返回执行Window.OnInit,然后窗口才会显示。
///
/// 如果你需要窗口显示时播放动画效果,那么覆盖doShowAnimation编写你的动画代码,并且在动画结束后调用onShown。覆盖onShown编写其他需要在窗口显示时处理的业务逻辑。
/// 如果你需要窗口隐藏时播放动画效果,那么覆盖doHideAnimation编写你的动画代码,并且在动画结束时调用Window.hideImmediately(注意不是直接调用onHide!)。覆盖onHide编写其他需要在窗口隐藏时处理的业务逻辑。
///
public class Window : GComponent
{
///
///
///
public bool bringToFontOnClick;
GComponent _frame;
GComponent _contentPane;
GObject _modalWaitPane;
GObject _closeButton;
GObject _dragArea;
GObject _contentArea;
bool _modal;
List _uiSources;
bool _inited;
bool _loading;
protected int _requestingCmd;
#if FAIRYGUI_PUERTS
public Action __onInit;
public Action __onShown;
public Action __onHide;
public Action __doShowAnimation;
public Action __doHideAnimation;
#endif
public Window()
: base()
{
_uiSources = new List();
this.tabStopChildren = true;
bringToFontOnClick = UIConfig.bringWindowToFrontOnClick;
displayObject.onAddedToStage.Add(__addedToStage);
displayObject.onRemovedFromStage.Add(__removeFromStage);
displayObject.onTouchBegin.AddCapture(__touchBegin);
this.gameObjectName = "Window";
SetHome(GRoot.inst);
}
///
/// Set a UISource to this window. It must call before the window is shown. When the window is first time to show,
/// UISource.Load is called. Only after all UISource is loaded, the window will continue to init.
/// 为窗口添加一个源。这个方法建议在构造函数调用。当窗口第一次显示前,UISource的Load方法将被调用,然后只有所有的UISource
/// 都ready后,窗口才会继续初始化和显示。
///
///
public void AddUISource(IUISource source)
{
_uiSources.Add(source);
}
///
///
///
public GComponent contentPane
{
set
{
if (_contentPane != value)
{
if (_contentPane != null)
RemoveChild(_contentPane);
_contentPane = value;
if (_contentPane != null)
{
this.gameObjectName = "Window - " + _contentPane.gameObjectName;
_contentPane.gameObjectName = "ContentPane";
AddChild(_contentPane);
this.SetSize(_contentPane.width, _contentPane.height);
_contentPane.AddRelation(this, RelationType.Size);
_contentPane.fairyBatching = true;
_frame = _contentPane.GetChild("frame") as GComponent;
if (_frame != null)
{
this.closeButton = _frame.GetChild("closeButton");
this.dragArea = _frame.GetChild("dragArea");
this.contentArea = _frame.GetChild("contentArea");
}
}
else
{
_frame = null;
this.gameObjectName = "Window";
}
}
}
get
{
return _contentPane;
}
}
///
///
///
public GComponent frame
{
get { return _frame; }
}
///
///
///
public GObject closeButton
{
get { return _closeButton; }
set
{
if (_closeButton != null)
_closeButton.onClick.Remove(closeEventHandler);
_closeButton = value;
if (_closeButton != null)
_closeButton.onClick.Add(closeEventHandler);
}
}
///
///
///
public GObject dragArea
{
get { return _dragArea; }
set
{
if (_dragArea != value)
{
if (_dragArea != null)
{
_dragArea.draggable = false;
_dragArea.onDragStart.Remove(__dragStart);
}
_dragArea = value;
if (_dragArea != null)
{
GGraph graph = _dragArea as GGraph;
if (graph != null && graph.shape.isEmpty)
graph.DrawRect(_dragArea.width, _dragArea.height, 0, Color.clear, Color.clear);
_dragArea.draggable = true;
_dragArea.onDragStart.Add(__dragStart);
}
}
}
}
///
///
///
public GObject contentArea
{
get { return _contentArea; }
set { _contentArea = value; }
}
///
///
///
public GObject modalWaitingPane
{
get { return _modalWaitPane; }
}
///
///
///
public void Show()
{
GRoot.inst.ShowWindow(this);
}
///
///
///
///
public void ShowOn(GRoot r)
{
r.ShowWindow(this);
}
///
///
///
public void Hide()
{
if (this.isShowing)
DoHideAnimation();
}
///
/// Hide window immediately, no OnHide will be called.
///
public void HideImmediately()
{
this.root.HideWindowImmediately(this);
}
///
/// Make the window be center of the screen.
///
///
/// Add relations to ensure keeping center on screen size changed.
public void CenterOn(GRoot r, bool restraint)
{
this.SetXY((int)((r.width - this.width) / 2), (int)((r.height - this.height) / 2));
if (restraint)
{
this.AddRelation(r, RelationType.Center_Center);
this.AddRelation(r, RelationType.Middle_Middle);
}
}
///
/// Switch show and hide status.
///
public void ToggleStatus()
{
if (isTop)
Hide();
else
Show();
}
///
///
///
public bool isShowing
{
get { return parent != null; }
}
///
///
///
public bool isTop
{
get { return parent != null && parent.GetChildIndex(this) == parent.numChildren - 1; }
}
///
///
///
public bool modal
{
get { return _modal; }
set { _modal = value; }
}
///
///
///
public void BringToFront()
{
this.root.BringToFront(this);
}
///
///
///
public void ShowModalWait()
{
ShowModalWait(0);
}
///
/// Display a modal waiting sign in the front.
/// 显示一个等待标志在最前面。等待标志的资源可以通过UIConfig.windowModalWaiting。等待标志组件会设置为屏幕大小,请内部做好关联。
/// 还可以设定一个requestingCmd作为等待的命令字,在CloseModalWait里传入相同的命令字ModalWait将结束,否则CloseModalWait无效。
///
///
public void ShowModalWait(int requestingCmd)
{
if (requestingCmd != 0)
_requestingCmd = requestingCmd;
if (UIConfig.windowModalWaiting != null)
{
if (_modalWaitPane == null)
{
_modalWaitPane = UIPackage.CreateObjectFromURL(UIConfig.windowModalWaiting);
_modalWaitPane.SetHome(this);
}
LayoutModalWaitPane();
AddChild(_modalWaitPane);
}
}
virtual protected void LayoutModalWaitPane()
{
if (_contentArea != null)
{
Vector2 pt = _frame.LocalToGlobal(Vector2.zero);
pt = this.GlobalToLocal(pt);
_modalWaitPane.SetXY((int)pt.x + _contentArea.x, (int)pt.y + _contentArea.y);
_modalWaitPane.SetSize(_contentArea.width, _contentArea.height);
}
else
_modalWaitPane.SetSize(this.width, this.height);
}
///
///
///
///
public bool CloseModalWait()
{
return CloseModalWait(0);
}
///
/// Close modal waiting. If rquestingCmd is equal to the value you transfer in ShowModalWait, mowal wait will be closed.
/// Otherwise, this function has no effect.
/// 关闭模式等待。如果requestingCmd和ShowModalWait传入的不相同,则这个函数没有任何动作,立即返回。
///
///
///
public bool CloseModalWait(int requestingCmd)
{
if (requestingCmd != 0)
{
if (_requestingCmd != requestingCmd)
return false;
}
_requestingCmd = 0;
if (_modalWaitPane != null && _modalWaitPane.parent != null)
RemoveChild(_modalWaitPane);
return true;
}
///
///
///
public bool modalWaiting
{
get { return (_modalWaitPane != null) && _modalWaitPane.inContainer; }
}
///
///
///
public void Init()
{
if (_inited || _loading)
return;
if (_uiSources.Count > 0)
{
_loading = false;
int cnt = _uiSources.Count;
for (int i = 0; i < cnt; i++)
{
IUISource lib = _uiSources[i];
if (!lib.loaded)
{
lib.Load(__uiLoadComplete);
_loading = true;
}
}
if (!_loading)
_init();
}
else
_init();
}
///
///
///
virtual protected void OnInit()
{
#if FAIRYGUI_TOLUA
CallLua("OnInit");
#endif
#if FAIRYGUI_PUERTS
if (__onInit != null)
__onInit();
#endif
}
///
///
///
virtual protected void OnShown()
{
#if FAIRYGUI_TOLUA
CallLua("OnShown");
#endif
#if FAIRYGUI_PUERTS
if (__onShown != null)
__onShown();
#endif
}
///
///
///
virtual protected void OnHide()
{
#if FAIRYGUI_TOLUA
CallLua("OnHide");
#endif
#if FAIRYGUI_PUERTS
if (__onHide != null)
__onHide();
#endif
}
///
///
///
virtual protected void DoShowAnimation()
{
#if FAIRYGUI_TOLUA
if (!CallLua("DoShowAnimation"))
OnShown();
#elif FAIRYGUI_PUERTS
if (__doShowAnimation != null)
__doShowAnimation();
else
OnShown();
#else
OnShown();
#endif
}
///
///
///
virtual protected void DoHideAnimation()
{
#if FAIRYGUI_TOLUA
if (!CallLua("DoHideAnimation"))
HideImmediately();
#elif FAIRYGUI_PUERTS
if (__doHideAnimation != null)
__doHideAnimation();
else
HideImmediately();
#else
HideImmediately();
#endif
}
void __uiLoadComplete()
{
int cnt = _uiSources.Count;
for (int i = 0; i < cnt; i++)
{
IUISource lib = _uiSources[i];
if (!lib.loaded)
return;
}
_loading = false;
_init();
}
void _init()
{
_inited = true;
OnInit();
if (this.isShowing)
DoShowAnimation();
}
override public void Dispose()
{
if (_modalWaitPane != null && _modalWaitPane.parent == null)
_modalWaitPane.Dispose();
//正在加载资源的异步过程中发生意外关闭 应该取消正在加载的load
if (_loading)
{
for (int i = 0; i < _uiSources.Count; ++i)
{
_uiSources[i].Cancel();
}
}
#if FAIRYGUI_PUERTS
__onInit = null;
__onShown = null;
__onHide = null;
__doShowAnimation = null;
__doHideAnimation = null;
#endif
base.Dispose();
}
virtual protected void closeEventHandler(EventContext context)
{
Hide();
}
void __addedToStage()
{
if (!_inited)
Init();
else
DoShowAnimation();
}
void __removeFromStage()
{
CloseModalWait();
OnHide();
}
private void __touchBegin(EventContext context)
{
if (this.isShowing && bringToFontOnClick)
{
BringToFront();
}
}
private void __dragStart(EventContext context)
{
context.PreventDefault();
this.StartDrag((int)context.data);
}
}
}