namespace("WM");
WM.Window = (function()
{
var template_html = multiline(function(){/* \
*/});
function Window(manager, title, x, y, width, height, parent_node, user_data)
{
this.Manager = manager;
this.ParentNode = parent_node || document.body;
this.userData = user_data;
this.OnMove = null;
this.OnResize = null;
this.Visible = false;
this.AnimatedShow = false;
// Clone the window template and locate key nodes within it
this.Node = DOM.Node.CreateHTML(template_html);
this.TitleBarNode = DOM.Node.FindWithClass(this.Node, "WindowTitleBar");
this.TitleBarTextNode = DOM.Node.FindWithClass(this.Node, "WindowTitleBarText");
this.TitleBarCloseNode = DOM.Node.FindWithClass(this.Node, "WindowTitleBarClose");
this.ResizeHandleNode = DOM.Node.FindWithClass(this.Node, "WindowResizeHandle");
this.BodyNode = DOM.Node.FindWithClass(this.Node, "WindowBody");
// Setup the position and dimensions of the window
this.SetPosition(x, y);
this.SetSize(width, height);
// Set the title text
this.TitleBarTextNode.innerHTML = title;
// Hook up event handlers
DOM.Event.AddHandler(this.Node, "mousedown", Bind(this, "SetTop"));
DOM.Event.AddHandler(this.TitleBarNode, "mousedown", Bind(this, "BeginMove"));
DOM.Event.AddHandler(this.ResizeHandleNode, "mousedown", Bind(this, "BeginResize"));
DOM.Event.AddHandler(this.TitleBarCloseNode, "mouseup", Bind(this, "Hide"));
// Create delegates for removable handlers
this.MoveDelegate = Bind(this, "Move");
this.EndMoveDelegate = Bind(this, "EndMove")
this.ResizeDelegate = Bind(this, "Resize");
this.EndResizeDelegate = Bind(this, "EndResize");
}
Window.prototype.SetOnMove = function(on_move)
{
this.OnMove = on_move;
}
Window.prototype.SetOnResize = function(on_resize)
{
this.OnResize = on_resize;
}
Window.prototype.Show = function()
{
if (this.Node.parentNode != this.ParentNode)
{
this.ShowNoAnim();
Anim.Animate(Bind(this, "OpenAnimation"), 0, 1, 1);
}
}
Window.prototype.ShowNoAnim = function()
{
// Add to the document
this.ParentNode.appendChild(this.Node);
this.AnimatedShow = false;
this.Visible = true;
}
Window.prototype.Hide = function(evt)
{
if (this.Node.parentNode == this.ParentNode && evt.button == 0)
{
if (this.AnimatedShow)
{
// Trigger animation that ends with removing the window from the document
Anim.Animate(
Bind(this, "CloseAnimation"),
0, 1, 0.25,
Bind(this, "HideNoAnim"));
}
else
{
this.HideNoAnim();
}
}
}
Window.prototype.HideNoAnim = function()
{
if (this.Node.parentNode == this.ParentNode)
{
// Remove node
this.ParentNode.removeChild(this.Node);
this.Visible = false;
}
}
Window.prototype.Close = function()
{
this.HideNoAnim();
this.Manager.RemoveWindow(this);
}
Window.prototype.SetTop = function()
{
this.Manager.SetTopWindow(this);
}
Window.prototype.SetTitle = function(title)
{
this.TitleBarTextNode.innerHTML = title;
}
// TODO: Update this
Window.prototype.AddControl = function(control)
{
// Get all arguments to this function and replace the first with this window node
var args = [].slice.call(arguments);
args[0] = this.BodyNode;
// Create the control and call its Init method with the modified arguments
var instance = new control();
instance.Init.apply(instance, args);
return instance;
}
Window.prototype.AddControlNew = function(control)
{
control.ParentNode = this.BodyNode;
this.BodyNode.appendChild(control.Node);
return control;
}
Window.prototype.RemoveControl = function(control)
{
if (control.ParentNode == this.BodyNode)
{
control.ParentNode.removeChild(control.Node);
}
}
Window.prototype.Scale = function(t)
{
// Calculate window bounds centre/extents
var ext_x = this.Size[0] / 2;
var ext_y = this.Size[1] / 2;
var mid_x = this.Position[0] + ext_x;
var mid_y = this.Position[1] + ext_y;
// Scale from the mid-point
DOM.Node.SetPosition(this.Node, [ mid_x - ext_x * t, mid_y - ext_y * t ]);
DOM.Node.SetSize(this.Node, [ this.Size[0] * t, this.Size[1] * t ]);
}
Window.prototype.OpenAnimation = function(val)
{
// Power ease in
var t = 1 - Math.pow(1 - val, 8);
this.Scale(t);
DOM.Node.SetOpacity(this.Node, 1 - Math.pow(1 - val, 8));
this.AnimatedShow = true;
}
Window.prototype.CloseAnimation = function(val)
{
// Power ease out
var t = 1 - Math.pow(val, 4);
this.Scale(t);
DOM.Node.SetOpacity(this.Node, t);
}
Window.prototype.NotifyChange = function()
{
if (this.OnMove)
{
var pos = DOM.Node.GetPosition(this.Node);
this.OnMove(this, pos);
}
}
Window.prototype.BeginMove = function(evt)
{
// Calculate offset of the window from the mouse down position
var mouse_pos = DOM.Event.GetMousePosition(evt);
this.Offset = [ mouse_pos[0] - this.Position[0], mouse_pos[1] - this.Position[1] ];
// Dynamically add handlers for movement and release
DOM.Event.AddHandler(document, "mousemove", this.MoveDelegate);
DOM.Event.AddHandler(document, "mouseup", this.EndMoveDelegate);
DOM.Event.StopDefaultAction(evt);
}
Window.prototype.Move = function(evt)
{
// Use the offset at the beginning of movement to drag the window around
var mouse_pos = DOM.Event.GetMousePosition(evt);
var offset = this.Offset;
var pos = [ mouse_pos[0] - offset[0], mouse_pos[1] - offset[1] ];
this.SetPosition(pos[0], pos[1]);
if (this.OnMove)
this.OnMove(this, pos);
DOM.Event.StopDefaultAction(evt);
}
Window.prototype.EndMove = function(evt)
{
// Remove handlers added during mouse down
DOM.Event.RemoveHandler(document, "mousemove", this.MoveDelegate);
DOM.Event.RemoveHandler(document, "mouseup", this.EndMoveDelegate);
DOM.Event.StopDefaultAction(evt);
}
Window.prototype.BeginResize = function(evt)
{
// Calculate offset of the window from the mouse down position
var mouse_pos = DOM.Event.GetMousePosition(evt);
this.MousePosBeforeResize = [ mouse_pos[0], mouse_pos[1] ];
this.SizeBeforeResize = this.Size;
// Dynamically add handlers for movement and release
DOM.Event.AddHandler(document, "mousemove", this.ResizeDelegate);
DOM.Event.AddHandler(document, "mouseup", this.EndResizeDelegate);
DOM.Event.StopDefaultAction(evt);
}
Window.prototype.Resize = function(evt)
{
// Use the offset at the beginning of movement to drag the window around
var mouse_pos = DOM.Event.GetMousePosition(evt);
var offset = [ mouse_pos[0] - this.MousePosBeforeResize[0], mouse_pos[1] - this.MousePosBeforeResize[1] ];
this.SetSize(this.SizeBeforeResize[0] + offset[0], this.SizeBeforeResize[1] + offset[1]);
if (this.OnResize)
this.OnResize(this, this.Size);
DOM.Event.StopDefaultAction(evt);
}
Window.prototype.EndResize = function(evt)
{
// Remove handlers added during mouse down
DOM.Event.RemoveHandler(document, "mousemove", this.ResizeDelegate);
DOM.Event.RemoveHandler(document, "mouseup", this.EndResizeDelegate);
DOM.Event.StopDefaultAction(evt);
}
Window.prototype.SetPosition = function(x, y)
{
this.Position = [ x, y ];
DOM.Node.SetPosition(this.Node, this.Position);
}
Window.prototype.SetSize = function(w, h)
{
w = Math.max(80, w);
h = Math.max(15, h);
this.Size = [ w, h ];
DOM.Node.SetSize(this.Node, this.Size);
if (this.OnResize)
this.OnResize(this, this.Size);
}
Window.prototype.GetZIndex = function()
{
return parseInt(this.Node.style.zIndex);
}
return Window;
})();