module SneathLane.BasicWidgets where
import Control.Applicative (Applicative(..), liftA2)
import Control.Monad (mplus, when)
import Data.Monoid ((<>))
import Data.Functor ((<$))
import Data.Maybe (fromMaybe)
import Control.Arrow ((***))
import SneathLane.Graphics
import SneathLane.Widget
import System.IO.Unsafe (unsafePerformIO)
import Haste (writeLog, catJSStr, toJSString, fromJSStr)
logging x y = unsafePerformIO (writeLog (show x) >> return y)
rectPath ps w h r = QuadraticPath ps (0,r) [((0,0),(r,0)),
((wr,0),(wr,0)),
((w,0),(w,r)),
((w,hr),(w,hr)),
((w,h),(wr,h)),
((r,h),(r,h)),
((0,h),(0,hr)),
((0,r),(0,r))]
button textStyle label = blur
where
blur = Continue (output (RGBA 0 0 0 1)) Nothing Nothing (Focusable focus focus)
focus = Continue (output (RGBA 0 1 0 1)) Nothing Nothing (Focused blur (blur, False) (blur, False) (\key -> case key of
EvKeyDown 13 _ -> Finish ()
_ -> focus))
output clr = handler <$ graphicList [rectPath (PathStyle (Just (clr, 2)) Nothing) (labelWidth + 10) 30 5,
Text textStyle (5,5) label]
handler (EvMouseDown _ LeftButton) = (Nothing, Finish ())
handler _ = (Nothing, blur)
labelWidth = measureText textStyle label
tabs textStyle ts n =
let buttons = zipWith (\(label,_) n' -> button textStyle label >> return (Left n')) ts [0..]
curr = fmap Right $ nextFrame $ snd $ ts !! n
in do
ret <- balancedFold beside buttons `above` curr
case ret of
Right (Finish z) -> Finish z
Right w' -> tabs textStyle (zipWith (\(label,w) n' -> if n' == n then (label, w') else (label, w)) ts [0..]) n
Left n' ->
let (Continue out _ _ _) = curr
(Rect _ _ _ h) = graphicTreeBounds out
in tabs textStyle (zipWith (\(label,w) n -> (label, if n == n' then slideToHeight h 0.2 w else w)) ts [0..]) n'
slideToHeight initialHeight duration (Finish z) = Finish z
slideToHeight initialHeight duration (Continue out mouseOut anim foc) =
let (Rect x y w h) = graphicTreeBounds out
anim' = fromMaybe (\tm -> Continue out mouseOut Nothing foc) anim
anim'' tm = let w' = anim' tm
in if tm > duration
then w'
else slideToHeight (initialHeight + (tm/duration)*(h initialHeight)) (duration tm) w'
out' = Clip (Rect x y w initialHeight) out
mouseOut' = fmap (slideToHeight initialHeight duration) mouseOut
foc' = mapWidgetFocus (slideToHeight initialHeight duration) foc
in Continue out' mouseOut' (Just anim'') foc'
nextFrame widget = case widget of
Finish z -> Finish (Finish z)
Continue out mouseOut anim foc ->
let out' = (fmap . fmap) (\(murl, w) -> (murl, Finish w)) out
mouseOut' = fmap Finish mouseOut
anim' = (fmap . fmap) Finish anim
foc' = mapWidgetFocus Finish foc
in Continue out' mouseOut' anim' foc'
textInput ww ts txt focused = Continue out Nothing Nothing foc
where
out = const (Nothing, textInput ww ts txt True) <$ graphicList [
rectPath (PathStyle (Just (if focused then RGBA 0 0 1 1 else RGBA 0 0 0 1, 1)) Nothing) ww (fromIntegral $ ts_lineHeight ts + 6) 5,
Text ts (5,3) txt
]
foc = if focused
then Focused blur (blur, False) (blur, False) keys
else Focusable focus focus
keys = (\key -> case key of
EvKeyDown 8 _ -> Finish (toJSString $ reverse $ drop 1 $ reverse $ fromJSStr txt, False)
EvKeyDown 13 _ -> Finish (txt, True)
EvKeyInput str -> Finish (catJSStr "" [txt, str], False)
_ -> textInput ww ts txt focused)
blur = textInput ww ts txt False
focus = textInput ww ts txt True
autoComplete ts fcomps txt focused =
let comps = fcomps txt
ww = maximum $ map (measureText ts) (txt:map fst comps)
ti = textInput (ww + 10) ts txt focused
wi = balancedFold above (ti : map showComp comps)
showComp comp = graphicWidget Nothing
(graphicList [
rectPath (PathStyle (Just (RGBA 0.4 0.4 0.4 1, 1)) (Just $ RGBA 0.9 0.9 0.9 1)) (ww + 10) (fromIntegral $ ts_lineHeight ts) 0,
Text ts (5,0) (fst comp)])
in do
(txt', finish) <- wi
case finish of
True -> if null comps
then autoComplete ts fcomps txt True
else return (snd $ head comps)
False -> if txt' /= "" && null (fcomps txt')
then autoComplete ts fcomps txt True
else autoComplete ts fcomps txt' True
simpleFocus fw keys = focus
where
focus = fw $ Focused blur (blur, False) (blur, False) keys
blur = fw $ Focusable focus focus