fltkhs icon indicating copy to clipboard operation
fltkhs copied to clipboard

Modal issues

Open ericu opened this issue 4 years ago • 6 comments

I'm having trouble figuring out how to do a modal window from scratch. I think there's at least one API issue, but even with that, it's not working.

First, FL.modal should be returning Ref WindowBase, not Ref Widget. That's an easy fix. But then when I call it and compare it to my modal window, I get a different pointer back. Am I missing something obvious, and/or is there a more straightforward way to do this than whileM_?

Here's my test code:

showTextEditor :: Text -> IO (Maybe Text)
showTextEditor t = do
  curActive <- FL.modal
  putStrLn $ show ("curActive is ", curActive)
  let size = toSize (300, 200)
  -- TODO: Just Position.
  win <- doubleWindowNew size Nothing (Just "Title")
  setModal win
  buff <- textBufferNew Nothing Nothing
  edit <- textEditorNew (toRectangle (20,20,(300-40),(200-40))) Nothing
  setBuffer edit (Just buff)
  setText buff t
  showWidget win
  let showing = do
        active <- FL.modal
        putStrLn $ show ("showing; active is ", active)
        putStrLn $ show ("showing; win is ", win)
        case active of
          Nothing -> return False
          Just w -> return $ w == (safeCast win)

  putStrLn "Showing"
  whileM_ showing (void FL.wait)
  t' <- getText buff
  putStrLn "Done"

  return $ Just t'

Output:

("curActive is ",Nothing)
Showing
("showing; active is ",Just (Ref 0x00007fa9d0232b30))
("showing; win is ",Ref 0x00007fa9d0204f40)
Done

ericu avatar Jul 13 '19 17:07 ericu

I think you're right and there's an issue with modal, when I did it I used shown and yes I believe looping on FL.wait is currently the best way. And you're right that making modals should be much easier.

deech avatar Jul 13 '19 17:07 deech

Aha! I was looking for shown first and couldn't find it. That's what I used in my old C++ app that I've been replacing. That works fine. Still have to figure out how to detect OK/Cancel without using an IORef.

I'm making a bunch of modal editors for various attributes, some of which may be complex enough to need runtime generation, which is why I'm not using Fluid. Plus I'd like to avoid C++ entirely.

Ah, looking at your code, I see you just use an IORef. So I'll just do that. Thanks!

Incidentally, regarding the pointer mismatches, I recall having similar problems when using FLTK with C++ years ago [my bugs, not theirs]. I hit problems due to multiple inheritance and using the wrong order of casts, such that I'd get a slightly wrong pointer, since it got confused about base class offsets. I don't understand out safeCast works. I doubt that's the problem here since the two pointers are so far apart, but I thought I'd mention it just in case.

ericu avatar Jul 13 '19 18:07 ericu

I'm not sure how much making-modals-easier you want to build into the library, and how much you want to remain a thin wrapper around FLTK. But you can always supply sample code. Here's what I'm playing around with to cut down on repetition:

showModal widget getValue = do
  Width widgetW <- getW widget
  Height widgetH <- getH widget
  ref <- newIORef Nothing
  let buttonW = 80
      buttonH = 35
      borderPadX = 4
      borderPadY = 4
      buttonPadX = 2 * borderPadX + (widgetW - 2 * buttonW) `div` 3
      buttonPadY = 4
      widgetX = borderPadX
      widgetY = borderPadY
      windowW = widgetW + 2 * borderPadX
      windowH = widgetH + buttonH + borderPadY + 2 * buttonPadY
      size = toSize (windowW, windowH)

  -- TODO: Just Position.
  window <- doubleWindowNew size Nothing (Just "Edit Comment")
  setModal window
  cancel <- buttonNew (toRectangle (buttonPadX,
                                    widgetY + widgetH + buttonPadY,
                                    buttonW, buttonH)) (Just "Cancel")
  let cancelCallback _ = hide window
  setCallback cancel cancelCallback
  ok <- buttonNew (toRectangle (2 * buttonPadX + buttonW,
                                widgetY + widgetH + buttonPadY,
                                buttonW, buttonH)) (Just "OK")
  let okCallback _ = do
        v <- getValue widget
        writeIORef ref $ Just v
        hide window
  setCallback ok okCallback

  addResizable window widget
  resize widget $ toRectangle (widgetX, widgetY, widgetW, widgetH)
  showWidget window

  whileM_ (shown window) (void FL.wait)

  readIORef ref

showTextEditor :: Text -> IO (Maybe Text)
showTextEditor t = do
  let editorW = 300
      editorH = 400
  buff <- textBufferNew Nothing Nothing
  edit <- textEditorNew (toRectangle (0, 0, editorW, editorH)) Nothing
  setBuffer edit (Just buff)
  setText buff t

  showModal (safeCast edit) (\_ -> getText buff)

ericu avatar Jul 14 '19 00:07 ericu

I fixed the issue with modal.

deech avatar Jul 18 '19 20:07 deech

If this fix mentioned above works could you close this issue?

deech avatar Jul 30 '19 22:07 deech

The compilation issue is fixed; the pointer mismatch remains. It's not stopping me from working--I coded it around it as above. But FL.modal isn't returning what it's supposed to.

ericu avatar Jul 31 '19 03:07 ericu