fltkhs
fltkhs copied to clipboard
What is the purpose of duplicate functions?
For example, the Button module defines
handleButtonBaseresizeButtonBasehideButtonBaseshowWidgetButtonBase
but there also exists
impl ~ (Event -> IO (Either UnknownEvent ())) => Op (Handle ()) ButtonBase orig impl- etc.
with (as far as I can tell) the same types. Is there a difference between these? Thanks!
It's so one can call base class methods. While the type signatures are the same the underlying method call is different.
I see... I'm still having some difficulty understanding. Which call is which? I'm not entirely clear on what BaseButton is, and the source you linked also mentions DerivedButton. However, neither of these are defined in FLTK proper, at least according to this diagram.
I read over the docs a bit more and I'm starting to understand. My understanding now is that in fltkhs, FooBase is Fl_Foo. The non-Base versions have no analogous class in C++. A Ref Foo, then, is exactly the same thing as a Ref FooBase (which is to say, has exactly the same API as, and whose functions behave identically to), except for the things you mentioned in #112.
Yes exactly and I admit this is confusing. Basically the inheritance chain looks like:
ABase -> A
|
v
BBase -> B
|
V
CBase -> C
|
v
where A,B, and C are the widgets you construct and use. Notice it is impossible use the *new functions to create any Base widgets. The reason for this confusing architecture is that every widget that you use on the Haskell side has a custom destructor that cleans up callbacks into the Haskell runtime when it's deleted so the GHC GC can free the resources they close over. Because of that each user constructable widget is essentially a branch point the inheritance chain.
Interesting! A follow-up question, if I were to write my own Button, would I subclass like this?
WidgetBase -> Widget
|
v
ButtonBase -> Button
-> MyButton
Or like this?
WidgetBase -> Widget
|
v
ButtonBase -> Button -> MyButton
If the former, is there any functionality in Button that I'm "leaving behind"...? (And presumably would want to re-implement in MyButton)
If you want to create your own button you'd use buttonCustom which allows you to customize a small set of essential functions. Overriding arbitrary functions in the inheritance chain is not supported.
Got it. Another question (sorry!) - the *Base types do crop up in the API, for example in
getParent :: Ref WidgetBase -> IO (Maybe (Ref GroupBase))
you're going to get back a Ref GroupBase no matter what type you started with. Is there a reason why this isn't Ref Group - going off of an assumption that the *Base types are somewhat "internal"?
Also while this is limiting you can do quite a bit with just those. The entire fltkhs-themes package relies mostly custon draw and handle to get a completely different look-and-feel.
Ah yes, they do crop up in return types, you're right. You don't want a Ref Group there because it is only guaranteed to be a GroupBase (ie. Fl_Group) since the parent may not have been constructed by you but by methods on the C++ side. This is also why getChild returns Ref WidgetBase instead of widget.
Very helpful! Could you clarify why one might not want to immediately upcast every Foo they encounter to a BaseFoo? I'm still struggling to understand the essence of the distinction (from an API standpoint).
Oh - is the answer that in doing so, you'd toss out your custom overrides?
Hmm.. let me think about that. You maybe right, you can't really add member functions to a child when you override so a Foo could be used safely as BaseFoo but you shouldn't need to upcast like that for normal cases. Even when passing some MyButton into another function I have a Parent constraint that does the check for you.