view togglePanel.ur @ 28:7d0014542199

TogglePanel.isOpen
author Adam Chlipala <adam@chlipala.net>
date Sun, 12 Feb 2012 10:27:02 -0500
parents 5905b56e0cd9
children b5432d74841a
line wrap: on
line source
datatype panelState = Open | Closed

con formatCtl = fn ctx :: {Unit} => [[Dyn] ~ ctx] =>
                   {FormatPanel : xml ([Dyn] ++ ctx) [] []
                                  -> xml ([Dyn] ++ ctx) [] []
                                  -> xml ([Dyn] ++ ctx) [] [],
                    OpenCtl : transaction unit -> xml ([Dyn] ++ ctx) [] [],
                    CloseCtl : transaction unit -> xml ([Dyn] ++ ctx) [] []}

val defaultFormat [[Dyn] ~ body'] =
    {FormatPanel = fn ctl panel => <xml>{ctl}{panel}</xml>,
     OpenCtl = fn behaviour => <xml><button value="Open" onclick={behaviour}/></xml>,
     CloseCtl = fn behaviour => <xml><button value="Close" onclick={behaviour}/></xml>}
                    
con togglePanel t ctx = {PanelState : source panelState,
                         FormatCtl : formatCtl ctx,
                         Content : t}

open Gui

fun create [t ::: Type] [ctx ::: {Unit}] (f : formatCtl ctx) (content : t) (startOpen : bool) : transaction (togglePanel t ctx) =
    state <- source (if startOpen then Open else Closed);

    return {PanelState = state,
            FormatCtl = @f,
            Content = content}

fun render [t ::: Type] [ctx ::: {Unit}] (_ : gui t ctx) [[Dyn] ~ ctx] (panel : togglePanel t ctx) =
    let
        val format = panel.FormatCtl !
        val openCtl = format.CloseCtl (set panel.PanelState Closed)
        val closeCtl = format.OpenCtl (set panel.PanelState Open)

        val content = toXml panel.Content
    in
        format.FormatPanel
            <xml>
              <dyn signal={c <- signal panel.PanelState;
                           return
                               (case c of
                                    Open => <xml>{openCtl}</xml>
                                  | Closed => <xml>{closeCtl}</xml>)
                          }/>
            </xml>

            <xml>
              <dyn signal={c <- signal panel.PanelState;
                           return
                               (case c of
                                    Open => <xml>{content}</xml>
                                  | Closed => <xml/>)
                          }/>
            </xml>
    end

fun gui_togglePanel [t ::: Type] [ctx ::: {Unit}] (g : gui t ctx) = mkGui (@render g)

fun isOpen [t] [ctx] (t : togglePanel t ctx) =
    v <- signal t.PanelState;
    return (case v of
                Open => True
              | Closed => False)