//
// Copyright (c) 2016, Brian Frank and Andy Frank
// Licensed under the Academic Free License version 3.0
//
// History:
// 15 Mar 2016 Andy Frank Creation
//
using concurrent
using dom
**
** Sheet
**
// TODO FIXIT: combine Popup + Dialog + Sheet (and add modal/non-modal support)
@NoDoc @Js class Sheet : Box
{
new make() : super()
{
this.uid = nextId.val
nextId.val = uid+1
this->tabIndex = 0
this.style.addClass("domkit-Sheet")
this.onEvent("mousedown", false) |e| { e.stop; if (canDismiss) close }
}
** Can this sheet be dismissed by clicking anywhere in the window?
Bool canDismiss := false
** Return 'true' if this sheet currently open.
Bool isOpen { private set }
** Optional delay for open animation.
@NoDoc Duration? delay := null
** Protected sub-class callback invoked directly before dialog is opened.
protected virtual Void onBeforeOpen() {}
** Callback when a key is pressed while Dialog is open, including
** events that where dispatched outside the dialog. This callback
** is only fired if `canDismiss` is 'false'.
protected Void onKeyDown(|Event e| f) { this.cbKeyDown = f }
** Open this sheet over given element. If sheet
** is already open this method does nothing.
This open(Elem parent, Str height)
{
if (isOpen) return this
ppos := parent.pagePos
this.style.setAll([
"left": "${ppos.x}px",
"top": "${ppos.y}px",
"width": "${parent.size.w}px",
"height": "0px"
])
body := Win.cur.doc.body
body.add(Elem {
it.id = "domkitSheet-mask-$uid"
it.style.addClass("domkit-Sheet-mask")
if (canDismiss)
{
it.onEvent("keydown", false) |e| { e.stop; close }
it.onEvent("mousedown", false) |e| { e.stop; close }
}
else
{
it.onEvent("keydown", false) |e| { cbKeyDown?.call(e) }
}
it.add(this)
})
onBeforeOpen
opts := delay == null ? null : ["transition-delay":delay]
this.transition(["height": height], opts, 250ms) { this.focus; fireOpen(null) }
return this
}
** Close this sheet. If sheet is already closed this method does
** nothing. This method takes an `onClose` callback as a convenience
** to set and close in a single operation.
Void close(|This|? f := null)
{
if (f != null) cbClose = f
this.transition(["height": "0"], null, 250ms)
{
mask := Win.cur.doc.elemById("domkitSheet-mask-$uid")
parent := mask?.parent
if (parent != null)
{
parent.remove(mask)
parent.querySelector("input")?.focus // <-- TODO FIXIT
}
fireClose(null)
}
}
** Callback when sheet is opened.
Void onOpen(|This| f) { cbOpen = f }
** Callback when sheet is closed.
Void onClose(|This| f) { cbClose = f }
private Void fireOpen(Event? e) { cbOpen?.call(this); isOpen=true }
private Void fireClose(Event? e) { cbClose?.call(this); isOpen=false }
private const Int uid
private static const AtomicRef nextId := AtomicRef(0)
private Func? cbOpen
private Func? cbClose
private Func? cbKeyDown
}