-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/
-- | Library for Arrowized Graphical User Interfaces.
--
@package UISF
@version 0.3.0.2
-- | Auxiliary functions for use with UISF or other arrows.
module FRP.UISF.AuxFunctions
-- | SEvent is short for "Stream Event" and is a type synonym for Maybe.
type SEvent = Maybe
-- | Time is simply represented as a Double.
type Time = Double
-- | DeltaT is a type synonym referring to a change in Time.
type DeltaT = Double
-- | Instances of this class have arrowized access to time. This is
-- convenient in many cases where time is necessary but we would prefer
-- not to make it an explicit argument.
class ArrowTime a
time :: ArrowTime a => a () Time
-- | Instances of the ArrowIO class have an arrowized ability to perform IO
-- actions.
class Arrow a => ArrowIO a
liftAIO :: ArrowIO a => (b -> IO c) -> a b c
initialAIO :: ArrowIO a => IO d -> (d -> a b c) -> a b c
-- | constA is an arrowized version of const.
constA :: Arrow a => c -> a b c
-- | constSF is a convenience composing constA with the given SF.
constSF :: Arrow a => b -> a b d -> a c d
-- | edge generates an event whenever the Boolean input signal changes from
-- False to True -- in signal processing this is called an ``edge
-- detector,'' and thus the name chosen here.
edge :: ArrowCircuit a => a Bool (SEvent ())
-- | The signal function (accum v) starts with the value v, but then
-- applies the function attached to the first event to that value to get
-- the next value, and so on.
accum :: ArrowCircuit a => b -> a (SEvent (b -> b)) b
-- | The signal function unique will produce an event each time its input
-- signal changes.
unique :: Eq e => ArrowCircuit a => a e (SEvent e)
-- | hold is a signal function whose output starts as the value of the
-- static argument. This value is held until the first input event
-- happens, at which point it changes to the value attached to that
-- event, which it then holds until the next event, and so on.
hold :: ArrowCircuit a => b -> a (SEvent b) b
-- | Now is a signal function that produces one event and then forever
-- after produces nothing. It is essentially an impulse function.
now :: ArrowCircuit a => a () (SEvent ())
-- | mergeE merges two events with the given resolution function.
mergeE :: (a -> a -> a) -> SEvent a -> SEvent a -> SEvent a
-- | This is an infix specialization of mergeE to lists.
(~++) :: SEvent [a] -> SEvent [a] -> SEvent [a]
-- | Combines the input list of arrows into one arrow that takes a list of
-- inputs and returns a list of outputs.
concatA :: Arrow a => [a b c] -> a [b] [c]
-- | This is a special case of foldA for lists.
runDynamic :: ArrowChoice a => a b c -> a [b] [c]
-- | This essentially allows an arrow that processes b to c to take [b] and
-- recursively generate cs, combining them all into a final output d.
foldA :: ArrowChoice a => (c -> d -> d) -> d -> a b c -> a [b] d
-- | For folding results of a list of signal functions.
foldSF :: Arrow a => (b -> c -> c) -> c -> [a () b] -> a () c
-- | This behaves much like the maybe function except lifted to the
-- ArrowChoice level. The arrow behaves like its first argument when the
-- input stream is Nothing and like its second when it is a Just value.
maybeA :: ArrowChoice a => a () c -> a b c -> a (Maybe b) c
-- | This lifts the arrow to an event-based arrow that behaves as a
-- constant stream of Nothing when there is no event.
evMap :: ArrowChoice a => a b c -> a (SEvent b) (SEvent c)
-- | A delay component.
delay :: ArrowCircuit a => forall b. b -> a b b
-- | vdelay is a delay function that delays for a variable amount of time.
-- It takes the current time, an amount of time to delay, and an event
-- stream and delays the event stream by the delay amount. vdelay, like
-- fdelay, guarantees that the order of events in is the same as the
-- order of events out and that no event will be skipped. If the events
-- are too dense or the delay argument drops too quickly, some events may
-- be over delayed.
vdelay :: (ArrowTime a, ArrowCircuit a) => a (DeltaT, SEvent b) (SEvent b)
-- | fdelay is a delay function that delays for a fixed amount of time,
-- given as the static argument. It returns a signal function that takes
-- the current time and an event stream and delays the event stream by
-- the delay amount. fdelay guarantees that the order of events in is the
-- same as the order of events out and that no event will be skipped.
-- However, if events are too densely packed in the signal (compared to
-- the clock rate of the underlying arrow), then some events may be over
-- delayed.
fdelay :: (ArrowTime a, ArrowCircuit a) => DeltaT -> a (SEvent b) (SEvent b)
-- | vcdelay is a continuous version of vdelay. It will always emit the
-- value that was produced dt seconds earlier (erring on the side of an
-- older value if necessary). Be warned that this version of delay can
-- both omit some data entirely and emit the same data multiple times. As
-- such, it is usually inappropriate for events (use vdelay). vcdelay
-- takes a maxDT argument that stands for the maximum delay time
-- that it can handle. This is to prevent a space leak.
--
-- Implementation note: Rather than keep a single buffer, we keep two
-- sequences that act to produce a sort of lens for a buffer. qlow has
-- all the values that are older than what we currently need, and qhigh
-- has all of the newer ones. Obviously, as time moves forward and the
-- delay amount variably changes, values are moved back and forth between
-- these two sequences as necessary. This should provide a slight
-- performance boost.
vcdelay :: (ArrowTime a, ArrowCircuit a) => DeltaT -> b -> a (DeltaT, b) b
-- | fcdelay is a continuous version of fdelay. It takes an initial value
-- to emit for the first dt seconds. After that, the delay will always be
-- accurate, but some data may be ommitted entirely. As such, it is not
-- advisable to use fcdelay for event streams where every event must be
-- processed (that's what fdelay is for).
fcdelay :: (ArrowTime a, ArrowCircuit a) => b -> DeltaT -> a b b
-- | timer is a variable duration timer. This timer takes the current time
-- as well as the (variable) time between events and returns an SEvent
-- steam. When the second argument is non-positive, the output will be a
-- steady stream of events. As long as the clock speed is fast enough
-- compared to the timer frequency, this should give accurate and
-- predictable output and stay synchronized with any other timer and with
-- time itself.
timer :: (ArrowTime a, ArrowCircuit a) => a DeltaT (SEvent ())
-- | genEvents is a timer that instead of returning unit events returns the
-- next element of the input list. When the input list is empty, the
-- output stream becomes all Nothing.
genEvents :: (ArrowTime a, ArrowCircuit a) => [b] -> a DeltaT (SEvent b)
-- | Tempo is just a Double.
type Tempo = Double
-- | The BufferOperation data type wraps up the data and operational
-- commands to control an eventbuffer.
data BufferOperation b
-- | No Buffer Operation
NoBOp :: BufferOperation b
-- | Erase the buffer
ClearBuffer :: BufferOperation b
-- | Skip ahead a certain amount of time in the buffer
SkipAheadInBuffer :: DeltaT -> BufferOperation b
-- | Merge data into the buffer
MergeInBuffer :: [(DeltaT, b)] -> BufferOperation b
-- | Append data to the end of the buffer
AppendToBuffer :: [(DeltaT, b)] -> BufferOperation b
-- | Set a new play status (True = Playing, False = Paused)
SetBufferPlayStatus :: Bool -> (BufferOperation b) -> BufferOperation b
-- | Set the buffer's tempo
SetBufferTempo :: Tempo -> (BufferOperation b) -> BufferOperation b
-- | eventBuffer allows for a timed series of events to be prepared and
-- emitted. The streaming input is a BufferOperation, described above.
-- Note that the default play status is playing and the default tempo is
-- 1. Just as MIDI files have events timed based on ticks since the last
-- event, the events here are timed based on seconds since the last
-- event. If an event is to occur 0.0 seconds after the last event, then
-- it is assumed to be played at the same time as the last event, and all
-- simultaneous events are emitted at the same timestep. In addition to
-- any events emitted, a streaming Bool is emitted that is True if the
-- buffer is empty and False if the buffer is full (meaning that events
-- will still come).
eventBuffer :: (ArrowTime a, ArrowCircuit a) => a (BufferOperation b) (SEvent [b], Bool)
-- | eventBuffer' is a version that takes Time explicitly rather than with
-- ArrowTime.
eventBuffer' :: ArrowCircuit a => a (BufferOperation b, Time) (SEvent [b], Bool)
-- | An arrow type comprising Mealy-style automata, each step of which is
-- is a computation in the original arrow type.
newtype Automaton (a :: * -> * -> *) b c :: (* -> * -> *) -> * -> * -> *
Automaton :: a b (c, Automaton a b c) -> Automaton b c
-- | The asyncV functions is for "Virtual time" asynchrony. The embedded
-- signal function is given along with an expected clockrate, and the
-- output conforms to that clockrate as well as it can.
--
-- The clockrate is the simulated rate of the input signal function. The
-- buffer is the amount of time the given signal function is allowed to
-- get ahead of real time. The threadHandler is where the ThreadId of the
-- forked thread is sent.
--
-- The output signal function takes and returns values in real time. The
-- input must be paired with time, and the return values are the list of
-- bs generated in the given time step, each time stamped. Note that the
-- returned list may be long if the clockrate is much faster than real
-- time and potentially empty if it's slower. Note also that the caller
-- can check the time stamp on the element at the end of the list to see
-- if the inner, "simulated" signal function is performing as fast as it
-- should.
asyncV :: (ArrowIO a, NFData c) => Double -> DeltaT -> (ThreadId -> a () ()) -> (Automaton (->) b c) -> a (b, Time) [(c, Time)]
-- | The asyncE (E for "Event") function takes a signal function (an
-- Automaton) and converts it into an asynchronous event-based signal
-- function usable in a ArrowIO signal function context. The output arrow
-- takes events of type a, feeds them to the asynchronously running input
-- signal function, and returns events with the output b whenever they
-- are ready. The input signal function is expected to run slowly
-- compared to the output one, but it is capable of running just as fast.
asyncE :: (ArrowIO a, ArrowLoop a, ArrowCircuit a, ArrowChoice a, NFData c) => (ThreadId -> a () ()) -> (Automaton (->) b c) -> a (SEvent b) (SEvent c)
-- | The asyncC (C for "Continuous time") function allows a continuous
-- signal function to run as fast as it can asynchronously. There are no
-- guarantees that all input data make it to the asynchronous signal
-- function; if this is required, asyncE should be used instead. Rather,
-- the embedded signal function runs as fast as it can on whatever value
-- it has most recently seen. Its results are bundled together in a list
-- to be returned to the main signal function.
asyncC :: (ArrowIO a, NFData c) => (ThreadId -> a () ()) -> (Automaton (->) b c) -> a b [c]
-- | This is a version of asyncC that does IO actions on either end of the
-- embedded signal function.
asyncC' :: (ArrowIO a, ArrowLoop a, ArrowCircuit a, ArrowChoice a, NFData b) => (ThreadId -> a () ()) -> (b -> IO d, e -> IO ()) -> (Automaton (->) (b, d) (c, e)) -> a b [c]
module FRP.UISF.SOE
runGraphics :: IO () -> IO ()
type Title = String
type Size = (Int, Int)
data Window
openWindow :: Title -> Size -> IO Window
getMainWindowSize :: IO Size
clearWindow :: Window -> IO ()
drawInWindow :: Window -> Graphic -> IO ()
drawInWindowNow :: Window -> Graphic -> IO ()
-- | setGraphic set the given Graphic over empty (black) background for
-- display in current Window.
setGraphic :: Window -> Graphic -> IO ()
setGraphic' :: Window -> Graphic -> IO ()
setDirty :: Window -> IO ()
closeWindow :: Window -> IO ()
openWindowEx :: Title -> Maybe Point -> Maybe Size -> RedrawMode -> IO Window
data RedrawMode
drawGraphic :: RedrawMode
drawBufferedGraphic :: RedrawMode
-- | Graphic is just a wrapper for OpenGL IO
data Graphic
nullGraphic :: Graphic
emptyGraphic :: Graphic
overGraphic :: Graphic -> Graphic -> Graphic
overGraphics :: [Graphic] -> Graphic
translateGraphic :: (Int, Int) -> Graphic -> Graphic
data Color
Black :: Color
Blue :: Color
Green :: Color
Cyan :: Color
Red :: Color
Magenta :: Color
Yellow :: Color
White :: Color
type RGB = Color3 GLfloat
type RGBA = Color4 GLfloat
rgb :: (Integral r, Integral g, Integral b) => r -> g -> b -> RGB
rgba :: (Integral r, Integral g, Integral b, Integral a) => r -> g -> b -> a -> RGBA
withColor :: Color -> Graphic -> Graphic
withColor' :: Color a => a -> Graphic -> Graphic
text :: Point -> String -> Graphic
type Point = (Int, Int)
ellipse :: Point -> Point -> Graphic
shearEllipse :: Point -> Point -> Point -> Graphic
line :: Point -> Point -> Graphic
polygon :: [Point] -> Graphic
polyline :: [Point] -> Graphic
polyBezier :: [Point] -> Graphic
type Angle = GLfloat
arc :: Point -> Point -> Angle -> Angle -> Graphic
scissorGraphic :: (Point, Size) -> Graphic -> Graphic
-- | Key is represented by either a character key or a special key.
data Key :: *
CharKey :: Char -> Key
SpecialKey :: SpecialKey -> Key
-- | Special key is a key not represented in the 32 - 127 printable ASCII
-- range.
data SpecialKey :: *
UNKNOWN :: SpecialKey
ESC :: SpecialKey
F1 :: SpecialKey
F2 :: SpecialKey
F3 :: SpecialKey
F4 :: SpecialKey
F5 :: SpecialKey
F6 :: SpecialKey
F7 :: SpecialKey
F8 :: SpecialKey
F9 :: SpecialKey
F10 :: SpecialKey
F11 :: SpecialKey
F12 :: SpecialKey
F13 :: SpecialKey
F14 :: SpecialKey
F15 :: SpecialKey
F16 :: SpecialKey
F17 :: SpecialKey
F18 :: SpecialKey
F19 :: SpecialKey
F20 :: SpecialKey
F21 :: SpecialKey
F22 :: SpecialKey
F23 :: SpecialKey
F24 :: SpecialKey
F25 :: SpecialKey
UP :: SpecialKey
DOWN :: SpecialKey
LEFT :: SpecialKey
RIGHT :: SpecialKey
LSHIFT :: SpecialKey
RSHIFT :: SpecialKey
LCTRL :: SpecialKey
RCTRL :: SpecialKey
LALT :: SpecialKey
RALT :: SpecialKey
TAB :: SpecialKey
ENTER :: SpecialKey
BACKSPACE :: SpecialKey
INSERT :: SpecialKey
DEL :: SpecialKey
PAGEUP :: SpecialKey
PAGEDOWN :: SpecialKey
HOME :: SpecialKey
END :: SpecialKey
KP_0 :: SpecialKey
KP_1 :: SpecialKey
KP_2 :: SpecialKey
KP_3 :: SpecialKey
KP_4 :: SpecialKey
KP_5 :: SpecialKey
KP_6 :: SpecialKey
KP_7 :: SpecialKey
KP_8 :: SpecialKey
KP_9 :: SpecialKey
KP_DIVIDE :: SpecialKey
KP_MULTIPLY :: SpecialKey
KP_SUBTRACT :: SpecialKey
KP_ADD :: SpecialKey
KP_DECIMAL :: SpecialKey
KP_EQUAL :: SpecialKey
KP_ENTER :: SpecialKey
data UIEvent
Key :: Char -> ([Char], [SpecialKey]) -> Bool -> UIEvent
char :: UIEvent -> Char
modifiers :: UIEvent -> ([Char], [SpecialKey])
isDown :: UIEvent -> Bool
SKey :: SpecialKey -> ([Char], [SpecialKey]) -> Bool -> UIEvent
skey :: UIEvent -> SpecialKey
modifiers :: UIEvent -> ([Char], [SpecialKey])
isDown :: UIEvent -> Bool
Button :: Point -> Bool -> Bool -> UIEvent
pt :: UIEvent -> Point
isLeft :: UIEvent -> Bool
isDown :: UIEvent -> Bool
MouseMove :: Point -> UIEvent
pt :: UIEvent -> Point
Resize :: Size -> UIEvent
Refresh :: UIEvent
Closed :: UIEvent
NoUIEvent :: UIEvent
hasShiftModifier :: ([Char], [SpecialKey]) -> Bool
hasCtrlModifier :: ([Char], [SpecialKey]) -> Bool
hasAltModifier :: ([Char], [SpecialKey]) -> Bool
maybeGetWindowEvent :: Double -> Window -> IO (Maybe UIEvent)
-- | getWindowEvent and maybeGetWindowEvent both take an additional
-- argument sleepTime that tells how long to sleep in the case where
-- there are no window events to return. This is used to allow the cpu to
-- take other tasks at these times rather than needlessly spinning. The
-- sleepTime parameter used to be fixed at 0.01.
getWindowEvent :: Double -> Window -> IO UIEvent
-- | 32-bit unsigned integer type
data Word32 :: *
-- | use GLFW's high resolution timer
timeGetTime :: IO Double
word32ToInt :: Word32 -> Int
-- | Designed to be used with Key, CharKey, or SpecialKey
isKeyPressed :: Enum a => a -> IO Bool
instance Eq Color
instance Ord Color
instance Bounded Color
instance Enum Color
instance Ix Color
instance Show Color
instance Read Color
instance Show UIEvent
module FRP.UISF.UITypes
-- | The termination procedure is simply a potential IO action.
type TerminationProc = Maybe (IO ())
-- | The null termination procedure is no action.
nullTP :: TerminationProc
-- | A method for merging two termination procedures.
mergeTP :: TerminationProc -> TerminationProc -> TerminationProc
-- | A rendering context specifies the following:
data CTX
CTX :: Flow -> Rect -> Bool -> CTX
-- | A layout direction to flow widgets.
flow :: CTX -> Flow
-- | A rectangle bound of current drawing area to render a UI component. It
-- specifies the max size of a widget, not the actual size. It's up to
-- each individual widget to decide where in this bound to put itself.
bounds :: CTX -> Rect
-- | A flag to tell whether we are in a conjoined state or not. A conjoined
-- context will duplicate itself for subcomponents rather than splitting.
-- This can be useful for making compound widgets when one widget takes
-- up space and the other performs some side effect having to do with
-- that space.
isConjoined :: CTX -> Bool
-- | Flow determines widget ordering.
data Flow
TopDown :: Flow
BottomUp :: Flow
LeftRight :: Flow
RightLeft :: Flow
-- | A dimension specifies size.
type Dimension = (Int, Int)
-- | A rectangle has a corner point and a dimension.
type Rect = (Point, Dimension)
-- | Layouts for individual widgets typically come in a few standard
-- flavors, so we have this convenience function for their creation. This
-- function takes layout information for first the horizontal dimension
-- and then the vertical.
makeLayout :: LayoutType -> LayoutType -> Layout
-- | A dimension can either be:
data LayoutType
-- | Stretchy with a minimum size in pixels
Stretchy :: Int -> LayoutType
minSize :: LayoutType -> Int
-- | Fixed with a size measured in pixels
Fixed :: Int -> LayoutType
fixedSize :: LayoutType -> Int
-- | The null layout is useful for "widgets" that do not appear or take up
-- space on the screen.
nullLayout :: Layout
-- | More complicated layouts can be manually constructed with direct
-- access to the Layout data type.
--
--
-- - hFill and vFill specify how much stretching space (in comparative
-- units) in the horizontal and vertical directions should be allocated
-- for this widget.
-- - hFixed and vFixed specify how much non-stretching space (in
-- pixels) of width and height should be allocated for this widget.
-- - minW and minH specify minimum values (in pixels) of width and
-- height for the widget's stretchy dimensions.
--
data Layout
Layout :: Int -> Int -> Int -> Int -> Int -> Int -> Layout
hFill :: Layout -> Int
vFill :: Layout -> Int
hFixed :: Layout -> Int
vFixed :: Layout -> Int
minW :: Layout -> Int
minH :: Layout -> Int
-- | Divides the CTX among the two given layouts.
divideCTX :: CTX -> Layout -> Layout -> (CTX, CTX)
-- | Merge two layouts into one.
mergeLayout :: Flow -> Layout -> Layout -> Layout
-- | Merging two graphics can be achieved with overGraphic, but the
-- mergeGraphic function additionally constrains the graphics based on
-- their layouts and the context. TODO: Make sure this works as well as
-- it should
mergeGraphics :: CTX -> (Graphic, Layout) -> (Graphic, Layout) -> Graphic
-- | The dirty bit is a bit to indicate if the widget needs to be redrawn.
type DirtyBit = Bool
-- | The Focus type helps focusable widgets communicate with each other
-- about which widget is in focus. It consists of a WidgetID and a
-- FocusInfo.
type Focus = (WidgetID, FocusInfo)
-- | The WidgetID for any given widget is dynamic based on how many
-- focusable widgets are active at the moment. It is designed basically
-- as a counter that focusable widgets will automatically (via the
-- focusable function) increment.
type WidgetID = Int
-- | The FocusInfo means one of the following:
data FocusInfo
-- | Indicates that this widget is a subwidget of a widget that is in
-- focus. Thus, this widget too is in focus, and this widget should pass
-- HasFocus forward.
HasFocus :: FocusInfo
-- | Indicates that there is no focus information to communicate between
-- widgets.
NoFocus :: FocusInfo
-- | Indicates that the widget whose id is given should take focus. That
-- widget should then pass NoFocus onward.
SetFocusTo :: WidgetID -> FocusInfo
-- | Any widget that sees this value should recognize that they are no
-- longer in focus. This is useful for nested focus.
DenyFocus :: FocusInfo
instance Eq Flow
instance Show Flow
instance Show CTX
instance Eq Layout
instance Show Layout
instance Show FocusInfo
instance Eq FocusInfo
-- | A simple Graphical User Interface with concepts borrowed from Phooey
-- by Conal Elliot.
module FRP.UISF.UISF
data UISF b c
UISF :: (Flow -> Layout) -> ((CTX, Focus, Time, UIEvent, b) -> IO (DirtyBit, Focus, Graphic, TerminationProc, c, UISF b c)) -> UISF b c
uisfLayout :: UISF b c -> Flow -> Layout
uisfFun :: UISF b c -> (CTX, Focus, Time, UIEvent, b) -> IO (DirtyBit, Focus, Graphic, TerminationProc, c, UISF b c)
-- | Lift an IO source to UISF.
uisfSource :: IO b -> UISF () b
-- | Lift an IO sink to UISF.
uisfSink :: (a -> IO ()) -> UISF a ()
-- | Lift an IO pipe to UISF.
uisfPipe :: (a -> IO b) -> UISF a b
-- | Lift an IO source to an event-based UISF.
uisfSourceE :: IO b -> UISF (SEvent ()) (SEvent b)
-- | Lift an IO sink to an event-based UISF.
uisfSinkE :: (a -> IO ()) -> UISF (SEvent a) (SEvent ())
-- | Lift an IO pipe to an event-based UISF.
uisfPipeE :: (a -> IO b) -> UISF (SEvent a) (SEvent b)
-- | Get the time signal from a UISF.
getTime :: UISF () Time
-- | Get the context signal from a UISF.
getCTX :: UISF () CTX
-- | Get the UIEvent signal from a UISF.
getEvents :: UISF () UIEvent
-- | Get the focus data from a UISF.
getFocusData :: UISF () Focus
-- | Add a termination procedure to a UISF.
addTerminationProc :: IO () -> UISF a a
-- | Get the mouse position from a UISF.
getMousePosition :: UISF () Point
-- | This function creates a UISF with the given parameters.
mkUISF :: Layout -> ((CTX, Focus, Time, UIEvent, a) -> (DirtyBit, Focus, Graphic, TerminationProc, b)) -> UISF a b
-- | We can also lift a signal function to a UISF asynchronously.
asyncUISFE :: NFData b => Automaton (->) a b -> UISF (SEvent a) (SEvent b)
-- | This is the standard one that appropriately keeps track of simulated
-- time vs real time.
--
-- The clockrate is the simulated rate of the input signal function. The
-- buffer is the number of time steps the given signal function is
-- allowed to get ahead of real time. The real amount of time that it can
-- get ahead is the buffer divided by the clockrate seconds. The output
-- signal function takes and returns values in real time. The return
-- values are the list of bs generated in the given time step, each time
-- stamped.
--
-- Note that the returned list may be long if the clockrate is much
-- faster than real time and potentially empty if it's slower. Note also
-- that the caller can check the time stamp on the element at the end of
-- the list to see if the inner, "simulated" signal function is
-- performing as fast as it should.
asyncUISFV :: NFData b => Double -> Double -> Automaton (->) a b -> UISF a [(b, Time)]
leftRight :: UISF a b -> UISF a b
rightLeft :: UISF a b -> UISF a b
topDown :: UISF a b -> UISF a b
bottomUp :: UISF a b -> UISF a b
conjoin :: UISF a b -> UISF a b
unconjoin :: UISF a b -> UISF a b
-- | Set a new layout for this widget.
setLayout :: Layout -> UISF a b -> UISF a b
-- | A convenience function for setLayout, setSize sets the layout to a
-- fixed size (in pixels).
setSize :: Dimension -> UISF a b -> UISF a b
-- | Add space padding around a widget.
pad :: (Int, Int, Int, Int) -> UISF a b -> UISF a b
-- | The UIParams data type provides an interface for modifying some of the
-- settings for runUI without forcing runUI to take a zillion arguments.
-- Typical usage will be to modify the below defaultUIParams using record
-- syntax.
data UIParams
UIParams :: IO () -> IO () -> String -> Dimension -> Flow -> Double -> UIParams
-- | An initialization action.
uiInitialize :: UIParams -> IO ()
-- | A termination action.
uiClose :: UIParams -> IO ()
-- | The UI window's title.
uiTitle :: UIParams -> String
-- | The size of the UI window.
uiSize :: UIParams -> Dimension
-- | The initial Flow setting.
uiInitFlow :: UIParams -> Flow
-- | How long the UI will sleep between clock ticks if no events are
-- detected. This should be probably be set to O(milliseconds), but it
-- can be set to 0 for better performance (but also higher CPU usage)
uiTickDelay :: UIParams -> Double
-- | This is the default UIParams value and what is used in runUI'.
defaultUIParams :: UIParams
-- | Run the UISF with the given parameters.
runUI :: UIParams -> UISF () () -> IO ()
-- | Run the UISF with the default settings.
runUI' :: UISF () () -> IO ()
instance [overlap ok] ArrowTime UISF
instance [overlap ok] ArrowIO UISF
instance [overlap ok] ArrowCircuit UISF
instance [overlap ok] ArrowChoice UISF
instance [overlap ok] ArrowLoop UISF
instance [overlap ok] Arrow UISF
instance [overlap ok] Category UISF
-- | A simple Graphical User Interface based on FRP. It uses the SOE
-- graphics library, and draws custom widgets on the screen.
--
-- SOE graphics uses OpenGL as the primitive drawing routine, and GLFW
-- library to provide window and input support.
--
-- The monadic UI concept is borrowed from Phooey by Conal Elliott.
module FRP.UISF.Widget
-- | Labels are always left aligned and vertically centered.
label :: String -> UISF a a
-- | DisplayStr is an output widget showing the instantaneous value of a
-- signal of strings.
displayStr :: UISF String ()
-- | display is a widget that takes any show-able value and displays it.
display :: Show a => UISF a ()
-- | withDisplay is a widget modifier that modifies the given widget so
-- that it also displays its output value.
withDisplay :: Show b => UISF a b -> UISF a b
-- | Textbox is a widget showing the instantaneous value of a signal of
-- strings.
--
-- The textbox widget will often be used with ArrowLoop (the rec
-- keyword). However, it uses delay internally, so there should be
-- no fear of a blackhole.
--
-- The textbox widget supports mouse clicks and typing as well as the
-- left, right, end, home, delete, and backspace special keys.
textbox :: UISF String String
-- | This variant of the textbox takes a static argument that is the
-- initial value in the textbox. Then, it takes a stream of 'SEvent
-- String' and only externally updates the contents of the textbox when
-- an event occurs.
textboxE :: String -> UISF (SEvent String) String
-- | Title frames a UI by borders, and displays a static title text.
title :: String -> UISF a b -> UISF a b
-- | A button is a focusable input widget with a state of being on or off.
-- It can be activated with either a button press or the enter key.
-- (Currently, there is no support for the space key due to non-special
-- keys not having Release events.) Buttons also show a static label.
--
-- The regular button is down as long as the mouse button or key press is
-- down and then returns to up.
button :: String -> UISF () Bool
-- | The sticky button, on the other hand, once pressed, remains depressed
-- until is is clicked again to be released. Thus, it looks like a
-- button, but it behaves more like a checkbox.
stickyButton :: String -> UISF () Bool
-- | Checkbox allows selection or deselection of an item. It has a static
-- label as well as an initial state.
checkbox :: String -> Bool -> UISF () Bool
-- | The checkGroup widget creates a group of checkboxes that all
-- send their outputs to the same output stream. It takes a static list
-- of labels for the check boxes and assumes they all start unchecked.
--
-- The output stream is a list of each a value that was paired with a
-- String value for which the check box is checked.
checkGroup :: [(String, a)] -> UISF () [a]
-- | Radio button presents a list of choices and only one of them can be
-- selected at a time. It takes a static list of choices (as Strings) and
-- the index of the initially selected one, and the widget itself returns
-- the continuous stream representing the index of the selected choice.
radio :: [String] -> Int -> UISF () Int
-- | The listbox widget creates a box with selectable entries. The input
-- stream is the list of entries as well as which entry is currently
-- selected, and the output stream is the index of the newly selected
-- entry. Note that the index can be greater than the length of the list
-- (simply indicating no choice selected).
listbox :: (Eq a, Show a) => UISF ([a], Int) Int
-- | Horizontal Continuous Slider
hSlider :: RealFrac a => (a, a) -> a -> UISF () a
-- | Vertical Continuous Slider
vSlider :: RealFrac a => (a, a) -> a -> UISF () a
-- | Horizontal Discrete Slider
hiSlider :: Integral a => a -> (a, a) -> a -> UISF () a
-- | Vertical Discrete Slider
viSlider :: Integral a => a -> (a, a) -> a -> UISF () a
-- | The realtimeGraph widget creates a graph of the data with trailing
-- values. It takes a dimension parameter, the length of the history of
-- the graph measured in time, and a color for the graphed line. The
-- signal function then takes an input stream of (value,time) event
-- pairs, but since there can be zero or more points at once, we use []
-- rather than SEvent for the type. The values in the (value,time)
-- event pairs should be between -1 and 1.
realtimeGraph :: RealFrac a => Layout -> Time -> Color -> UISF [(a, Time)] ()
-- | The histogram widget creates a histogram of the input map. It assumes
-- that the elements are to be displayed linearly and evenly spaced.
histogram :: RealFrac a => Layout -> UISF (SEvent [a]) ()
-- | The histogramWithScale widget creates a histogram and an x coordinate
-- scale.
histogramWithScale :: RealFrac a => Layout -> UISF (SEvent [(a, String)]) ()
-- | mkWidget is a helper function to make stateful widgets easier to
-- write. In essence, it breaks down the idea of a widget into 4
-- constituent components: state, layout, computation, and drawing.
--
-- As mkWidget allows for making stateful widgets, the first
-- parameter is simply the initial state.
--
-- The layout is the static layout that this widget will use. It cannot
-- be dependent on any streaming arguments, but a layout can have
-- "stretchy" sides so that it can expand/shrink to fit an area. Learn
-- more about making layouts in UITypes UI Layout section --
-- specifically, check out the makeLayout function and the
-- LayoutType data type.
--
-- The computation is where the logic of the widget is held. This
-- function takes as input the streaming argument a, the widget's state,
-- a Rect of coordinates indicating the area that has been allotted for
-- this widget, and the UIEvent that is triggering this widget's
-- activation (see the definition of UIEvent in SOE). The output
-- consists of the streaming output, the new state, and the dirty bit,
-- which represents whether the widget needs to be redrawn.
--
-- Lastly, the drawing routine takes the same Rect as the computation, a
-- Bool that is true when this widget is in focus and false otherwise,
-- and the current state of the widget (technically, this state is the
-- one freshly returned from the computation). Its output is the Graphic
-- that this widget should display.
mkWidget :: s -> Layout -> (a -> s -> Rect -> UIEvent -> (b, s, DirtyBit)) -> (Rect -> Bool -> s -> Graphic) -> UISF a b
-- | Occasionally, one may want to display a non-interactive graphic in the
-- UI. mkBasicWidget facilitates this. It takes a layout and a
-- simple drawing routine and produces a non-interacting widget.
mkBasicWidget :: Layout -> (Rect -> Graphic) -> UISF a a
-- | The toggle is useful in the creation of both checkboxes and
-- radio buttons. It displays on/off according to its input, and
-- when the mouse is clicked on it, it will output True (otherwise it
-- outputs False).
--
-- The UISF returned from a call to toggle accepts the state stream and
-- returns whether the toggle is being clicked.
toggle :: Eq s => s -> Layout -> (Rect -> Bool -> s -> Graphic) -> UISF s Bool
-- | The mkSlider widget builder is useful in the creation of all sliders.
mkSlider :: Eq a => Bool -> (a -> Int -> Int) -> (Int -> Int -> a) -> (Int -> Int -> a -> a) -> a -> UISF () a
-- | Canvas displays any graphics. The input is a signal of graphics events
-- because we only want to redraw the screen when the input is there.
canvas :: Dimension -> UISF (SEvent Graphic) ()
-- | canvas' uses a layout and a graphic generator. This allows it to
-- behave similarly to canvas, but it can adjust in cases with
-- stretchy layouts.
canvas' :: Layout -> (a -> Dimension -> Graphic) -> UISF (SEvent a) ()
-- | cyclebox is a clickable widget that cycles through a predefined set
-- set of appearances/output values.
cyclebox :: Layout -> [(Rect -> Bool -> Graphic, b)] -> Int -> UISF () b
-- | cyclebox' is a cyclebox that additionally accepts input events that
-- can set it to a particular appearance/output.
cyclebox' :: Layout -> [(Rect -> Bool -> Graphic, b)] -> Int -> UISF (SEvent Int) b
-- | Making a widget focusable makes it accessible to tabbing and allows it
-- to see any mouse button clicks and keystrokes when it is actually in
-- focus.
focusable :: UISF a b -> UISF a b
-- | Although mouse button clicks and keystrokes will be available once a
-- widget marks itself as focusable, the widget may also simply want to
-- know whether it is currently in focus to change its appearance. This
-- can be achieved with the following signal function.
isInFocus :: UISF () Bool
module FRP.UISF
data UISF b c
-- | Run the UISF with the default settings.
runUI' :: UISF () () -> IO ()
-- | Run the UISF with the given parameters.
runUI :: UIParams -> UISF () () -> IO ()
-- | The UIParams data type provides an interface for modifying some of the
-- settings for runUI without forcing runUI to take a zillion arguments.
-- Typical usage will be to modify the below defaultUIParams using record
-- syntax.
data UIParams
UIParams :: IO () -> IO () -> String -> Dimension -> Flow -> Double -> UIParams
-- | An initialization action.
uiInitialize :: UIParams -> IO ()
-- | A termination action.
uiClose :: UIParams -> IO ()
-- | The UI window's title.
uiTitle :: UIParams -> String
-- | The size of the UI window.
uiSize :: UIParams -> Dimension
-- | The initial Flow setting.
uiInitFlow :: UIParams -> Flow
-- | How long the UI will sleep between clock ticks if no events are
-- detected. This should be probably be set to O(milliseconds), but it
-- can be set to 0 for better performance (but also higher CPU usage)
uiTickDelay :: UIParams -> Double
-- | This is the default UIParams value and what is used in runUI'.
defaultUIParams :: UIParams
-- | A dimension specifies size.
type Dimension = (Int, Int)
-- | Labels are always left aligned and vertically centered.
label :: String -> UISF a a
-- | DisplayStr is an output widget showing the instantaneous value of a
-- signal of strings.
displayStr :: UISF String ()
-- | display is a widget that takes any show-able value and displays it.
display :: Show a => UISF a ()
-- | withDisplay is a widget modifier that modifies the given widget so
-- that it also displays its output value.
withDisplay :: Show b => UISF a b -> UISF a b
-- | Textbox is a widget showing the instantaneous value of a signal of
-- strings.
--
-- The textbox widget will often be used with ArrowLoop (the rec
-- keyword). However, it uses delay internally, so there should be
-- no fear of a blackhole.
--
-- The textbox widget supports mouse clicks and typing as well as the
-- left, right, end, home, delete, and backspace special keys.
textbox :: UISF String String
-- | This variant of the textbox takes a static argument that is the
-- initial value in the textbox. Then, it takes a stream of 'SEvent
-- String' and only externally updates the contents of the textbox when
-- an event occurs.
textboxE :: String -> UISF (SEvent String) String
-- | Title frames a UI by borders, and displays a static title text.
title :: String -> UISF a b -> UISF a b
-- | A button is a focusable input widget with a state of being on or off.
-- It can be activated with either a button press or the enter key.
-- (Currently, there is no support for the space key due to non-special
-- keys not having Release events.) Buttons also show a static label.
--
-- The regular button is down as long as the mouse button or key press is
-- down and then returns to up.
button :: String -> UISF () Bool
-- | The sticky button, on the other hand, once pressed, remains depressed
-- until is is clicked again to be released. Thus, it looks like a
-- button, but it behaves more like a checkbox.
stickyButton :: String -> UISF () Bool
-- | Checkbox allows selection or deselection of an item. It has a static
-- label as well as an initial state.
checkbox :: String -> Bool -> UISF () Bool
-- | The checkGroup widget creates a group of checkboxes that all
-- send their outputs to the same output stream. It takes a static list
-- of labels for the check boxes and assumes they all start unchecked.
--
-- The output stream is a list of each a value that was paired with a
-- String value for which the check box is checked.
checkGroup :: [(String, a)] -> UISF () [a]
-- | Radio button presents a list of choices and only one of them can be
-- selected at a time. It takes a static list of choices (as Strings) and
-- the index of the initially selected one, and the widget itself returns
-- the continuous stream representing the index of the selected choice.
radio :: [String] -> Int -> UISF () Int
-- | Horizontal Continuous Slider
hSlider :: RealFrac a => (a, a) -> a -> UISF () a
-- | Vertical Continuous Slider
vSlider :: RealFrac a => (a, a) -> a -> UISF () a
-- | Horizontal Discrete Slider
hiSlider :: Integral a => a -> (a, a) -> a -> UISF () a
-- | Vertical Discrete Slider
viSlider :: Integral a => a -> (a, a) -> a -> UISF () a
-- | The realtimeGraph widget creates a graph of the data with trailing
-- values. It takes a dimension parameter, the length of the history of
-- the graph measured in time, and a color for the graphed line. The
-- signal function then takes an input stream of (value,time) event
-- pairs, but since there can be zero or more points at once, we use []
-- rather than SEvent for the type. The values in the (value,time)
-- event pairs should be between -1 and 1.
realtimeGraph :: RealFrac a => Layout -> Time -> Color -> UISF [(a, Time)] ()
data Color
Black :: Color
Blue :: Color
Green :: Color
Cyan :: Color
Red :: Color
Magenta :: Color
Yellow :: Color
White :: Color
-- | The histogram widget creates a histogram of the input map. It assumes
-- that the elements are to be displayed linearly and evenly spaced.
histogram :: RealFrac a => Layout -> UISF (SEvent [a]) ()
-- | The histogramWithScale widget creates a histogram and an x coordinate
-- scale.
histogramWithScale :: RealFrac a => Layout -> UISF (SEvent [(a, String)]) ()
-- | The listbox widget creates a box with selectable entries. The input
-- stream is the list of entries as well as which entry is currently
-- selected, and the output stream is the index of the newly selected
-- entry. Note that the index can be greater than the length of the list
-- (simply indicating no choice selected).
listbox :: (Eq a, Show a) => UISF ([a], Int) Int
-- | Canvas displays any graphics. The input is a signal of graphics events
-- because we only want to redraw the screen when the input is there.
canvas :: Dimension -> UISF (SEvent Graphic) ()
-- | canvas' uses a layout and a graphic generator. This allows it to
-- behave similarly to canvas, but it can adjust in cases with
-- stretchy layouts.
canvas' :: Layout -> (a -> Dimension -> Graphic) -> UISF (SEvent a) ()
topDown :: UISF a b -> UISF a b
bottomUp :: UISF a b -> UISF a b
leftRight :: UISF a b -> UISF a b
rightLeft :: UISF a b -> UISF a b
-- | Add space padding around a widget.
pad :: (Int, Int, Int, Int) -> UISF a b -> UISF a b
-- | A convenience function for setLayout, setSize sets the layout to a
-- fixed size (in pixels).
setSize :: Dimension -> UISF a b -> UISF a b
-- | Set a new layout for this widget.
setLayout :: Layout -> UISF a b -> UISF a b
-- | Layouts for individual widgets typically come in a few standard
-- flavors, so we have this convenience function for their creation. This
-- function takes layout information for first the horizontal dimension
-- and then the vertical.
makeLayout :: LayoutType -> LayoutType -> Layout
-- | A dimension can either be:
data LayoutType
-- | Stretchy with a minimum size in pixels
Stretchy :: Int -> LayoutType
minSize :: LayoutType -> Int
-- | Fixed with a size measured in pixels
Fixed :: Int -> LayoutType
fixedSize :: LayoutType -> Int
-- | Get the time signal from a UISF.
getTime :: UISF () Time
-- | This is the standard one that appropriately keeps track of simulated
-- time vs real time.
--
-- The clockrate is the simulated rate of the input signal function. The
-- buffer is the number of time steps the given signal function is
-- allowed to get ahead of real time. The real amount of time that it can
-- get ahead is the buffer divided by the clockrate seconds. The output
-- signal function takes and returns values in real time. The return
-- values are the list of bs generated in the given time step, each time
-- stamped.
--
-- Note that the returned list may be long if the clockrate is much
-- faster than real time and potentially empty if it's slower. Note also
-- that the caller can check the time stamp on the element at the end of
-- the list to see if the inner, "simulated" signal function is
-- performing as fast as it should.
asyncUISFV :: NFData b => Double -> Double -> Automaton (->) a b -> UISF a [(b, Time)]
-- | We can also lift a signal function to a UISF asynchronously.
asyncUISFE :: NFData b => Automaton (->) a b -> UISF (SEvent a) (SEvent b)
module FRP.UISF.Examples.Examples
-- | This example displays the time from the start of the GUI application.
timeEx :: UISF () ()
-- | This example shows off buttons and state by presenting a plus
-- and minus button with a counter that is adjusted by them.
buttonEx :: UISF () ()
-- | This example shows off the checkbox widgets.
checkboxEx :: UISF () ()
-- | This example shows off the radio button widget.
radioButtonEx :: UISF () ()
-- | This example shows off integral sliders (horizontal hiSliders
-- in this case).
shoppinglist :: UISF () ()
-- | This example shows off both vertical sliders as well as the
-- canvas widget. The canvas widget can be used to easily create
-- custom graphics in the GUI. Here, it is used to make a color swatch
-- that is controllable with RGB values by the sliders.
colorDemo :: UISF () ()
-- | This example shows off the textboxE widget. Text can be typed
-- in, and that text is transferred to the display widget below
-- when the button is pressed.
textboxdemo :: UISF () ()
-- | This is the main demo that incorporates all of the other examples
-- together. In addition to demonstrating how different widgets can
-- connect, it also shows off the tabbing behavior built in to the GUI.
-- Pressing tab cycles through focusable elements, and pressing shift-tab
-- cycles in reverse.
main :: IO ()
module FRP.UISF.Examples.Crud
type Database a = [a]
data NameEntry
NameEntry :: String -> String -> NameEntry
firstName :: NameEntry -> String
lastName :: NameEntry -> String
defaultnames :: Database NameEntry
-- | This function will run the crud GUI with the default names.
crud :: IO ()
-- | main = crud
main :: IO ()
-- | This is the main function that creates the crud GUI. It takes an
-- initial database of names as an argument. See notes below on the use
-- of banana brackets and nested do blocks.
crudUISF :: Database NameEntry -> UISF () ()
instance Eq NameEntry
instance Show NameEntry