Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Experiment: make ref wrappers optional #144

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 49 additions & 12 deletions src/DearImGui.hs
Original file line number Diff line number Diff line change
Expand Up @@ -570,21 +570,58 @@ arrowButton strId dir = liftIO do
withCString strId \strIdPtr ->
Raw.arrowButton strIdPtr dir


-- | Wraps @ImGui::Checkbox()@.
checkbox :: (HasSetter ref Bool, HasGetter ref Bool, MonadIO m) => String -> ref -> m Bool
checkbox label ref = liftIO do
currentValue <- get ref
with (bool 0 1 currentValue) \boolPtr -> do
changed <- withCString label \labelPtr ->
Raw.checkbox labelPtr boolPtr

when changed do
newValue <- peek boolPtr
ref $=! (newValue == 1)

return changed
checkbox label ref = stateful ref $ checkboxM label
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The wrapped functions aren't even needed if widgets are to have their "mutable" arguments stated last.

There can be statefulN-family for widgets that mutate N arguments at once.

-- With all arguments expanded
dragFloatRange2 desc speed minValue maxValue minFmt maxFmt refMin refMax = ...

-- Just add your values
dragFloatRange01 label = dragFloatRange2 label 0.01 0 1 "%.1f" "%.1f"

action rMin rMax = do
  changed <- stateful2 rMin rMax $
    dragFloatRange01 "from zero to hero"
  when changed do
    ...


-- | Wraps @ImGui::Checkbox()@.
checkboxM :: (MonadIO m) => String -> Bool -> m (Maybe Bool)
checkboxM label currentValue =
changing
(bool 0 1 currentValue)
( \valuePtr ->
withCString label \labelPtr ->
Raw.checkbox labelPtr valuePtr
)
(pure . (/=) 0)

{-# INLINEABLE changing #-}
changing
:: (MonadIO m, Storable a1)
=> a1
-> (Ptr a1 -> IO Bool)
-> (a1 -> IO a2)
-> m (Maybe a2)
changing oldValue action extract = liftIO do
with oldValue \valuePtr ->
action valuePtr >>=
peekChanged valuePtr extract

{-# INLINEABLE peekChanged #-}
peekChanged
:: (MonadIO m, Storable a1)
=> Ptr a1 -> (a1 -> m a2) -> Bool -> m (Maybe a2)
peekChanged ptr action flag = do
if flag then
liftIO (peek ptr) >>=
fmap Just . action
else
pure Nothing

{-# INLINEABLE stateful #-}
stateful
:: (HasGetter t a, MonadIO m, HasSetter t a)
=> t -> (a -> m (Maybe a)) -> m Bool
stateful ref action = get ref >>= action >>= maybeSet ref

{-# INLINEABLE maybeSet #-}
maybeSet :: (HasSetter t a, MonadIO f) => t -> Maybe a -> f Bool
maybeSet ref = \case
Nothing ->
pure False
Just val -> do
ref $=! val
pure True

progressBar :: MonadIO m => Float -> Maybe String -> m ()
progressBar progress overlay = liftIO do
Expand Down