haskell-game / dear-imgui.hs

Haskell bindings to Dear ImGui, an immediate mode GUI toolkit

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Handling of Begin/End pairs

sheaf opened this issue · comments

commented

Is there any situation in which users might need to use beginXXX/endXXX in an atypical way? As far as I understand:

  • begin/end, beginChild/endChild, beginGroup/endGroup, beginTooltip/endTooltip, beginChildFrame/endChildFrame must always occur in matching pairs, so we can replace them with simple with-style functions,
  • beginCombo/endCombo, beginListBox/endListBox, beginMenuBar/endMenuBar, beginMainMenuBar/endMainMenuBar, beginPopup/endPopup, beginTable/endTable, beginTabBar/endTabBar, beginDragDropSource/endDragDropSource, beginDragDropTarget/endDragDropTarget all require a matching end function precisely when the begin function returned True. Is there any other way to use them than with the whenTrue idiom we are currently using in the example?

If there is literally no other valid usage pattern, I would recommend entirely replacing the beginXXX/endXXX functions with bracketed functions. Then users aren't confused about which one to use, and can't get it wrong.
If there are valid usage patterns, then of course we should keep the individual beginXXX/endXXX functions, and provide additional helpers.

I think we're trying to be as faithful to the C bindings as possible. I was going to put bracket-like functions in DearImgui.Simple or something (or maybe that's was DearImgui is and we have DearImgui.Raw, like SDL)

Mandating with-style may mess with some nontrivial control flow that may be used to generate UI.

I'm (+) 1 on making them readily available and doing the right thing.
Stowing away SDL-style raw bindings is a good idea too.

I just tried adding a with-wrapper with Control.Exception.bracket and was instantly struck down by MonadIO constraint clashing with rigid IO type.

That can be handled with at least the following options:

  1. Provide "sequential" brackets of the form (beginXXX name >>= action) <* endXXX.
  2. Use base bracket and restrict actions to IO.
  3. Switch to unliftio bracket (and use MonadUnliftIO everywhere).

My preferences are 3 > 1 >> 2. But don't have a clear model of what should happen when some widget-emitting code errors out.

Given how unsound exception handling during UI construction is I went forth and made at least basic begin/action/end sequence wrappers.

Given how unsound exception handling during UI construction is I went forth and made at least basic begin/action/end sequence wrappers.

Nevermind, in the PR I added unliftio to deps and used its brackets.

commented

Nevermind, in the PR I added unliftio to deps and used its brackets.

Yeah, I think that's the best way to go. We're already using unliftio for the Vulkan backend anyway.