-
Notifications
You must be signed in to change notification settings - Fork 567
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
Sub windows (squashed from previous branch) #1254
Conversation
Have you tried restricting subwindows so that the data binding stuff requires a special widget to work? Like, instead of allowing every It would also be much less flexible, of course, but it would still cover the main use-cases I can think of. For tooltips, you need a |
That’s what I had initially. It was extremely odd in actual use. |
To expand on this:
|
Will just chime in and say I haven't looked at the code much but playing around with the example it looks promising! |
Other things I forgot to mention:
|
Is anyone interested in this? Its been 2 months. |
I'm very interested in this feature but I've just been too busy to really give it much concerted thought. I'll try and give this PR a closer look in the next day or two. Thanks for the bump! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall I think this is a pretty clean solution. A few comments inline mostly related to API and what types exactly we will need to expose, but that's just a polish question.
A few other things:
- before we merge we'll need to get docs and related up to the quality of the rest of the public API; I've avoided nitpicking any of that since it feels like this is very much a first draft.
- sub windows should close when a parent window closes. The easiest thing to do here might be to just keep a map at the application root that tracks each window's subwindows, and we can check that when closing a window to ensure we also close its children?
- this is also demonstrating the need for some mechanism that allows a window to be sized based on the size of its child. That is outside of the scope of this PR, but it's something we will need in order for this to become properly useful. As a hack we might be able to bake this into the
SubWindowHost
? - we're also really going to need to start having focus state take window focus into account; with this I can get multiple windows on screen, each with a focused text box and a blinking cursor. Also out of scope for this particular PR, but want to at least make note.
In any case I think this has a lot of promise and I'd be happy to see it get merged if you're still interested. Thanks!
I'll have to remind myself how all of this works. I do vaguely remember there being some issues with ordering of generating ids etc. Agree on the closing windows etc, I think the host can manage it without any extra data structures if the 'non syncing' case is removed. I can't remember if it was actually needed. You are right that this was not meant to be fully finished, because there is no point polishing things before the general approach is agreed to be sensible. Getting that agreement or rejection shouldn't take months on features that are unavoidably required. |
…w-squash # Conflicts: # CHANGELOG.md # druid/src/contexts.rs # druid/src/core.rs # druid/src/lib.rs # druid/src/win_handler.rs
I've updated it a bit. The main thing is the window closing. It does feel surprising that we don't have a window closed lifecycle that flows down to widgets, but I can see that might be complex to get right (e.g is it allowed to cancel the window being closed? Or delay it for an animation...) |
Cool, I'll take a look at this shortly. Window closed is a tricky one; there is a method called on the app delegate when a window is added or removed, but there's no ability to cancel that action. We could think about whether we need to send some event down to the widgets as well, but that's definitely tricky... do we send it before the window dies? afterwards? What are widgets supposed to do here? The thinking at the time was that if you need to handle this logic then you should just use an |
@rjwittams is this ready for review? Or is there an open question about the window closing? |
I'll try to do something for the window closing soon on this branch. But it should be fairly independent of what is here now I think... so up to you. I'll un draft it at that point |
Add WindowDisconnected event. Close sub windows when their owning WidgetPod gets a WindowDisconnected event.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks very promising. A handful of little things inline, but overall I think this is very close.
Some higher-level things:
I find the example confusing: why am I seeing display resolutions? where do I click? what does what? I think longer term we'll want something a bit more intuitive, here.
related: when you show a tool-tip, the tool-tip window gets focus (on macOS). We'll need to figure this out when we try to actually implement tooltips.
In any case I'm not super worried about that; most of the major use-cases for this (tooltips, combo boxes, etc) are things where we will want to build the implementations ourselves on top of the sub-window machinery, and we can figure out an API for that, then.
There are some things we'll need to figure out: how do we correctly size the window to fit the text for a combo box or a tooltip? I have some ideas here, but we'll have to experiment. Ditto with positioning of the window, which is particularly important in the case of a combo box.
I suspect there may be a few other things that will shake out when we try to build on top of this, but I'm happy for that to be future work.
Thanks for finishing this up!
This was because back in the mists of time this was linked up with the screen PR. I was also using this example to test mac monitor discovery. |
Co-authored-by: Colin Rofls <[email protected]>
Co-authored-by: Colin Rofls <[email protected]>
yea I can see that it worked for testing, and I think it's fine for now, it's just not a great example in the long-term. We can open an issue to revisit that when we merge this. |
And: everytime I try to edit docs through the github suggestions feature something breaks 😒 |
Docs are v fiddly |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay a few more small notes but this looks basically there.
Do you have any planned next steps for this? There are some obvious things this opens up; a major one for me would be doing combo boxes. I'm happy to take that on myself, but don't want to step on any toes..
druid/src/core.rs
Outdated
let prev_env = self.env.as_ref().filter(|p| !p.same(env)); | ||
let env_changed = prev_env.is_some(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there's an env_changed
method available on UpdateCtx
.
druid/src/core.rs
Outdated
let prev_env = self.env.as_ref().filter(|p| !p.same(env)); | ||
let env_changed = prev_env.is_some(); | ||
let data_changed = self.old_data.as_ref().filter(|p| !p.same(data)).is_some(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
won't this be incorrect in the case where there is no old data?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For some reason I thought that couldn't happen but not sure why...
druid/src/event.rs
Outdated
/// that the window *will* close just because this event is received; for instance, you should | ||
/// avoid destructive side effects such as cleaning up resources. | ||
/// | ||
/// [`set_handled`]: struct.EventCtx.html#method.set_handled |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we should now be able to use the intra-doc-link syntax, like:
/// [`set_handled`]: struct.EventCtx.html#method.set_handled | |
/// [`set_handled`]: crate::EventCtx::set_handled |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, looks good.
Do you have any planned followup, for this? Are there any issues we should open, for instance? (maybe one about improving the example?)
I was planning to try out a few things. Combo boxes/drop downs (need to look at html/gtk/etc to see whats expected... ). I think theres some common helper bits for slidey out bits, eg date pickers and colour pickers share parts of that too. Draggy droppy tabs. Multiwindow docking layout (IDE like). I was going to do these out of tree (nursery I guess), until they are a fait accompli to go in. I find the current model of maturing "large" (>100 lines?) code drops (reviewers programming mediated by PR comments and the original developer) really extremely unproductive. I think people just following up with their own commits (especially naming and style, doc fixes, personal taste) works a lot better. I'm not saying review has no merits but the cost of it as practiced on the PRs I've currently done is maybe 15 or 20x the effort of actual development. I think maybe this works with a swarm of people inside a large tech firm. Not so sure with the current resource levels and lack of 'deadline + goal pressure' (that kind of forces acceptance of 'good enough' and incremental improvement). Obviously in order for this to work, some core changes may always be needed and I think it also drives druid itself to be more extensible from the outside if core widgets could be moved outside and still work. There may be some churn (e.g duplicating a widget to nursery to work on it then promote the changed one back when rematured). |
Please read this description before going through the diff.
This was the first cut of sub windows that I did in a few days at the beginning of August, not really updated significantly since then, but it has taken this long to get to the point of making a PR due to dependent things and general delays.
This was not supposed to be fully finished or finalised, more of a proof of concept or a starting point that is expected to be expanded upon, because I thought it needed actual discussion before really doing a lot with it (making 'proper' tooltips or combo boxes, etc), or wiring through new events etc if that was the route people wanted to go. I did not think it would take quite so long to get to the point of being able to discuss it.
The general idea is that we make a window with a SubWindowHost in it via our surrounding widget pod, and then that widget pod synchronises its app data with the SubWindowHost via commands. It could be special events instead, and I'm unconvinced that the command stuff in here is exactly the right way to do it (specifically the command handling is all done just before the widget pods child gets it, as I didn't want to interfere with the targeted command unwrapping stuff (that I think could be unwrapping this command?). It might be fine, but it does look a bit different to all the other event handling in WidgetPod).
This whole mechanism is clearly driven by the 'focusing'/ lenses/app data model of current druid and its limitations. As that might be abandoned, possibly people do not want to spend time thinking about it.
It is likely to be far more productive to clone this, play with the sub_window.rs example and start from there than to read the diff from start to finish. The example has a couple of things in it - that once again, are not supposed to be fully finished or finalised in any way whatsoever:
Things that I've not tackled:
I haven't tested any of this on windows as I don't have it at the moment.
Maybe this can serve as a starting point or idea for someone else later on if it isn't what people want to spend time on at the moment.