simple-ui-0.3.0: src/Simple/UI/Widgets/Widget.hs
{-
* Programmer: Piotr Borek
* E-mail: piotrborek@op.pl
* Copyright 2017 Piotr Borek
*
* Distributed under the terms of the GPL (GNU Public License)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE ViewPatterns #-}
module Simple.UI.Widgets.Widget (
WidgetClass,
Widget,
castToWidget,
overrideWidget,
overrideWidgetHelper,
overrideHelper,
widgetNew,
connectColorsTo,
keyPressed,
widgetInitialized,
draw,
colorForeground,
colorBackground,
colorStyle,
colorForegroundSelected,
colorBackgroundSelected,
colorStyleSelected,
enabled,
visible,
name,
computeSize,
setColors,
getColors,
virtualWidgetName,
virtualWidgetComputeSize
) where
import qualified Graphics.Vty as Vty
import Control.Lens (Lens', makeLenses, (&), (.~),
(^.))
import Control.Monad (unless)
import Control.Monad.State.Strict (State, execState)
import Simple.UI.Core.Attribute
import Simple.UI.Core.Draw
import Simple.UI.Core.Internal.UIApp
import Simple.UI.Core.ListenerList
data Widget = Widget
{ _widgetKeyPressed :: ListenerList (Vty.Key -> [Vty.Modifier]-> UIApp' ())
, _widgetDraw :: ListenerList (Drawing -> Int -> Int -> UIApp' ())
, _widgetInitialized :: ListenerList (UIApp' ())
, _widgetColorForeground :: Attribute Vty.Color
, _widgetColorBackground :: Attribute Vty.Color
, _widgetColorStyle :: Attribute DrawStyle
, _widgetColorForegroundSelected :: Attribute Vty.Color
, _widgetColorBackgroundSelected :: Attribute Vty.Color
, _widgetColorStyleSelected :: Attribute DrawStyle
, _widgetEnabled :: Attribute Bool
, _widgetVisible :: Attribute Bool
, _widgetInitializedFlag :: Attribute Bool
--
, _widgetName :: String
, _widgetComputeSize :: UIApp' (Int, Int)
}
data VirtualWidget = VirtualWidget
{ _virtualWidgetName :: String
, _virtualWidgetComputeSize :: UIApp' (Int, Int)
}
makeLenses ''VirtualWidget
class WidgetClass w where
castToWidget :: w -> Widget
overrideWidget :: w -> State VirtualWidget () -> w
keyPressed :: w -> ListenerList (Vty.Key -> [Vty.Modifier]-> UIApp' ())
keyPressed = _widgetKeyPressed . castToWidget
widgetInitialized :: w -> ListenerList (UIApp' ())
widgetInitialized = _widgetInitialized . castToWidget
draw :: w -> ListenerList (Drawing -> Int -> Int -> UIApp' ())
draw = _widgetDraw . castToWidget
colorForeground :: w -> Attribute Vty.Color
colorForeground = _widgetColorForeground . castToWidget
colorBackground :: w -> Attribute Vty.Color
colorBackground = _widgetColorBackground . castToWidget
colorStyle :: w -> Attribute DrawStyle
colorStyle = _widgetColorStyle . castToWidget
colorForegroundSelected :: w -> Attribute Vty.Color
colorForegroundSelected = _widgetColorForegroundSelected . castToWidget
colorBackgroundSelected :: w -> Attribute Vty.Color
colorBackgroundSelected = _widgetColorBackgroundSelected . castToWidget
colorStyleSelected :: w -> Attribute DrawStyle
colorStyleSelected = _widgetColorStyleSelected . castToWidget
enabled :: w -> Attribute Bool
enabled = _widgetEnabled . castToWidget
visible :: w -> Attribute Bool
visible = _widgetVisible . castToWidget
name :: w -> String
name = _widgetName . castToWidget
computeSize :: w -> UIApp u (Int, Int)
computeSize = liftUIApp' . _widgetComputeSize . castToWidget
instance WidgetClass Widget where
castToWidget = id
overrideWidget widget m = widget
{ _widgetName = _virtualWidgetName s
, _widgetComputeSize = _virtualWidgetComputeSize s
}
where
s = execState m VirtualWidget
{ _virtualWidgetName = name widget
, _virtualWidgetComputeSize = computeSize widget
}
widgetNew :: UIApp u Widget
widgetNew = do
p <- listenerNew
d <- listenerNew
i <- listenerNew
fgColor <- attributeNew Vty.white
bgColor <- attributeNew Vty.black
style <- attributeNew DrawStyleNormal
selFgColor <- attributeNew Vty.white
selBgColor <- attributeNew Vty.brightBlack
selStyle <- attributeNew DrawStyleNormal
en <- attributeNew True
v <- attributeNew True
inited <- attributeNew False
let widget = Widget
{ _widgetKeyPressed = p
, _widgetDraw = d
, _widgetInitialized = i
, _widgetColorForeground = fgColor
, _widgetColorBackground = bgColor
, _widgetColorStyle = style
, _widgetColorForegroundSelected = selFgColor
, _widgetColorBackgroundSelected = selBgColor
, _widgetColorStyleSelected = selStyle
, _widgetEnabled = en
, _widgetVisible = v
, _widgetName = "widget"
, _widgetComputeSize = return (1, 1)
, _widgetInitializedFlag = inited
}
on_ widget draw $ \_ _ _ -> do
initedFlag <- get widget _widgetInitializedFlag
unless initedFlag $ do
set widget _widgetInitializedFlag True
fire widget _widgetInitialized ()
return widget
overrideHelper :: WidgetClass p => (p -> State s () -> p) -> Lens' w p -> w -> State s () -> w
overrideHelper overrideFunc parentLens widget f = widget & parentLens .~ overrideFunc parent f
where
parent = widget ^. parentLens
overrideWidgetHelper :: WidgetClass p => Lens' w p -> w -> State VirtualWidget () -> w
overrideWidgetHelper = overrideHelper overrideWidget
connectColorsTo :: (WidgetClass w, WidgetClass v) => w -> v -> UIApp u ()
connectColorsTo (castToWidget -> widget) (castToWidget -> vidget) = do
colorForeground widget `connectAttrTo` colorForeground vidget
colorBackground widget `connectAttrTo` colorBackground vidget
colorStyle widget `connectAttrTo` colorStyle vidget
colorForegroundSelected widget `connectAttrTo` colorForegroundSelected vidget
colorBackgroundSelected widget `connectAttrTo` colorBackgroundSelected vidget
colorStyleSelected widget `connectAttrTo` colorStyleSelected vidget
setColors :: WidgetClass w => w -> (Vty.Color, Vty.Color, DrawStyle, Vty.Color, Vty.Color, DrawStyle) -> UIApp u ()
setColors widget (foreground, background, style, selForeground, selBackground, selStyle) = do
set widget colorForeground foreground
set widget colorBackground background
set widget colorStyle style
set widget colorForegroundSelected selForeground
set widget colorBackgroundSelected selBackground
set widget colorStyleSelected selStyle
getColors :: WidgetClass w => w -> UIApp u (Vty.Color, Vty.Color, DrawStyle, Vty.Color, Vty.Color, DrawStyle)
getColors widget = do
foreground <- get widget colorForeground
background <- get widget colorBackground
style <- get widget colorStyle
selForeground <- get widget colorForegroundSelected
selBackground <- get widget colorBackgroundSelected
selStyle <- get widget colorStyleSelected
return (foreground, background, style, selForeground, selBackground, selStyle)