-
-
Notifications
You must be signed in to change notification settings - Fork 17
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
dyn-view with hidden observable dependencies #23
Comments
This is a limitation of |
That makes sense, and is kind of what I figured. It's unfortunate that
That is unexpected, in some way, but also makes sense. Unfortunately the use of the At any rate, this might give me the motivation I need to drop some of the |
I just pushed a set of changes to track hidden deps in racket-gui-easy/examples/issue-23-short-circuiting.rkt Lines 70 to 84 in 424ad3b
|
This is wonderful! I haven't updated to try this out yet, but I plan to soon. I completely follow the |
Yes, I think they should generally be avoided. Ultimately, views are objects with internal mutable state so re-using the same view can be problematic. In that case specifically, |
I want to expand on this some more, in case I forget some of these details by the next time I get to work on this stuff. Initially, when I came up with I think for now I'm going to leave things as they are so we can see how much this trips people up. If it turns out to cause a lot of pain and confusion, what we can do is change those views that are stateful to parameterize their state per native widget instance. To give a concrete example, |
Ok, that seems to make sense to me at the moment. One last question: I saw a |
No, it won't be public. I added it for internal use only and mostly as a way of getting around changing the You can bind the top level window's renderer (or store it in your own param) and use it to make modal dialogs already (see "examples/modal.rkt"). What you can't currently do is bind the renderer for a dialog because rendering a dialog blocks until the dialog is closed. I haven't yet thought of a nice way to get around that. |
Got it, thanks! |
Here's an example of making your own parameter, for the record. I couldn't think of a thread-safe/re-entrant way to do it without a parameter containing a thunk: #lang racket
(require racket/gui/easy)
(define cr (make-parameter (thunk #f)))
(define root
(parameterize ([cr (thunk root)])
(render
(window
(button
"Click me"
(lambda ()
(render
(dialog
(text "hello"))
((cr))))))))) The view construction could then be placed in its own function(s) as long as it had access to the parameter. Thunk-ing is necessary because without it the value |
Thank you for this; unless you feel strongly otherwise, I'm going to close this issue because I was successfully able to update to 0.5 and use a cond-view where I had this dyn-view before. 🎉 ❤️ |
Thanks to work by @Bogdanp in Bogdanp/racket-gui-easy#23, I can replace the `dyn-view` + `obs-combine cons` hack with an actual `cond-view`, now that `if-view` and descendants are more dynamic and do not force ahead-of-time evaluation. Note that `make-monster-group-view` returns to receiving `@ability-decks` like it effectively did in 90114f2 Then, because `@action` is derived from it (along with `@mg` and therefore `@e`), the returned view correctly depends on `@ability-decks`, which was the reason for the `obs-combine cons` hack in the first place!
I had a function that looked like this:
[Ignore the
(cons _
patterns; I am still deciding how best to restructure the data for that part.]The
make-creature-view
function is used in alist-view
over an observable@creatures
which holds items that are eitherplayer?
ormonster-group?
(again, ignoring the initialcons
bits).The
dyn-view
lets me do the job of anif-view
/cond-view
but without constructing the sub-views of all conditional branches when the data doesn't match what is needed (e.g., with acond-view
here, I can't avoid that themonster-group-view
gets aplayer?
or vice-versa, because the sub-views are constructed greedily). At least, I think this is why I am usingdyn-view
; I can't remember.But here's where things get interesting: the view returned by
make-player-view
has no dependencies other than@e
, which (conveniently) thedyn-view
also monitors and reacts to. On the other hand,make-monster-group-view
creates a view that depends on an observable not mentioned here. I update it in response to other events and was expecting the GUI to update with new information, but it doesn't (presumably becausedyn-view
doesn't know about it, so can't forward updates, so nothing is redrawn).There's a very silly hack to fix this (notice the
obs-combine
and the extracons
patterns):This works (!) but isn't scalable or maintainable: if more dependencies are added to
make-monster-group-view
, they need to balloon into theobs-combine
andmatch
, too. And if one is forgotten, there's a sort of "spooky action at a distance" bug like the lack of updates I described above.I actually first tried a slightly better version that used
(obs-combine (lambda (a e) e) @ability-decks @e)
, but that didn't work. It only improved thematch
, too; my points above still apply.Have you encountered something like this before? Do you have a suggestion to alleviate this? It's like I want the static parts of
if-view
but the dynamic parts ofdyn-view
(again, because of the issue I have with disjoint data).The text was updated successfully, but these errors were encountered: