-
Notifications
You must be signed in to change notification settings - Fork 2.6k
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
Fix for Issue 11218: Improve workflow of Panels #15675
base: master
Are you sure you want to change the base?
Conversation
Note: there was a previous attempt at fixing this issue. I provided this fix because it looks like that person is no longer active with the issue. My fix covers both horizontal and vertical panels, and does not require any special case for tabs--it's meant to be a general solution for any tab. |
DockPanelView* panel = dynamic_cast<DockPanelView*>(dock); | ||
if (panel) { | ||
DockPanelView* destinationPanel = findPanelForTab(panel); |
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 was an issue with using findPanelForTab, as it returns the default location for a tab (the first it finds in the allowed panels), not its current location. I've renamed this method findFirstPanelForTab(), and created a new method findCurrentPanelForTab(), which searches for the tab in all valid panels.
return; | ||
if (panel->isOpen()) { | ||
if (panel->floating()) { | ||
shouldOpen = !panel->hasFocus(); |
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.
The calls to hasFocus() are to meet the requirement that the hotkey should first focus the panel (if it's open and not focused), and only then is it ok to close it.
} else if (tabNotCurrent) { | ||
destinationPanel->setCurrentTabIndex(tabIndex); | ||
if (!panel->isOpen()) { | ||
panel->open(); |
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.
As it turns out, if you simply open a closed panel, it will open at its last closed location, which is great.
@@ -557,11 +557,9 @@ void DockBase::applySizeConstraints() | |||
m_dockWidget->setMaximumSize(maximumSize); | |||
|
|||
if (KDDockWidgets::FloatingWindow* window = m_dockWidget->floatingWindow()) { | |||
window->setMinimumSize(minimumSize); |
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.
If these lines aren't removed, they will limit the size of the opened floating window to be smaller than it was last sized for.
@@ -329,6 +329,12 @@ void StateDragging::onEntry() | |||
void StateDragging::onExit() | |||
{ | |||
m_maybeCancelDrag.stop(); | |||
|
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.
Previously saveLastFloatingGeometry() was only called when starting the drag. This means only the previous rect was saved. So, save it when the drag is finished as well.
@@ -128,6 +129,14 @@ bool WidgetResizeHandler::eventFilter(QObject *o, QEvent *e) | |||
updateCursor(CursorPosition_Undefined); | |||
auto mouseEvent = static_cast<QMouseEvent *>(e); | |||
|
|||
// When we stop dragging a floating window which has a single dock widget, we save the position |
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.
It also turned out that resizing the window wouldn't update the saved rect, so I added this.
Ok this is starting to look very good! I've made my observations here: https://www.dropbox.com/s/w255zb15o6h5mrk/Screen%20Recording%202023-01-05%20at%203.41.42%20pm.mov?dl=0 I would also add that I do not believe that a selected/opened panel is receiving keyboard focus at the moment, but I'd really like @shoogle to have a look at this as well to ensure everything still meets our keyboard navigation rules. And it's probably worth mentioning that I'm currently only testing this on macOS. It should also be tested on Windows and Linux before we merge it. Tagging @DmitryArefiev and @abariska to have a look at as well when they are back from vacation. Many thanks! |
It looks like something strange happened while rebasing... I see some commits that shouldn't appear in this PR. I would recommend doing Regarding the changes in |
@bkunda That vertical dock bug is interesting. It appears to be caused by the way that KDDockWidgets' layout algorithm works. It attempts to steal space from immediate neighbors when inserting an item back into a list of items. I think that only works if you add the items in the reverse order that you removed them. For example, consider a vertical list of panel items A, B, C (top to bottom) each sized to be 300px high.
You can try the above using, e.g., Properties, Palette, and Instruments panels for A, B, C, and you'll end up with a squished Palette. So, IMO KDDockWidgets has a bug in how layout happens on re-adding an item. I think a solution would be for each item to steal from the largest of all neighbors until the neighbors are equal sized, at which point it steals from all proportionally. That would be run on each side of the insertion. I'm new to this code, so I could be missing some other way to configure the behavior. @cbjeukendrup I'll take a look, thanks for bringing that up. Looks like I may have more changes to make to that package. I want to make sure I'm not fixing behavior that MS currently depends on, but these do feel like bugs. |
I'll look forward to seeing how this works in practice! Keep referring to @cbjeukendrup for technical questions as |
eeb027f
to
8e7545f
Compare
@bkunda Here's a video with the new LongestNeighboursFirst strategy for adding in a panel. I think it's questionable whether this is better or worse than just equalizing all relative sizes when adding a new panel (which can be added with less code changes). I think it's better because it favors the new panel that you want to see, but I can see the case against adding a new strategy for third party maintenance reasons. If you think it's worth committing, I can do that next. Longestneighborsfirstdemo-Ms-11218-1.mp4 |
@hanoixan it's a nifty solution, but I wonder how it would go if the selection filter were also included in the mix? The more I see this in action, the more I think that we should – in the case of vertically-docked panels that all end up being closed – simply re-open them in their default (i.e. full-height) position. The necessity of returning a half-docked panel to its former position is arguably voided when all the panels are closed, because you can't reopen a single previously half-docked panel in any position other than full height. So I don't think we need to commit this latest solution. Your previous solution was all working fine, and just needs the vertically-docked panels to be reopened at full-height if they are part of a set in which all panels are closed 🙂. |
@bkunda It works ok with the selection filter. When you say The other option I thought of was that when a dock gets opened, it would just force an equalization of all open docks after it's added. Given that toggling a panel closed from the middle of two neighbors steals from them equally, this almost feels like a symmetric behavior. |
Yes, except without squashing any panels down to the very bottom of the window (as it does in my video at 1:41). In terms of solving the problem I've identified in my video above, I think having all the panels open at full height in this particular situation is likely to be simplest. In particular, I'm thinking that:
The only exception to this might be if the user opens the panels in the reverse order to which they initially closed them, but this really requires the user to have memorised their position before carefully triggering the right sequence of shortcuts to close and reopen them. I don't think it is necessary to support this kind of behaviour at the present minute (although my mind always remains open to changing if enough of a demand is shown). Our workspaces feature should be the place where users configure their precise arrangement of panels. |
@bkunda I need some clarity on this. It sounds like what you're saying is that we would have these two situations and behaviors:
If this is what you mean, I like it. It would feel clear that when you close a tab, it loses its exact representation. When you reopen it, you want to see it fully by default, but it's then up to you to set up anything more custom. This aligns with the fact that this widget system doesn't let us recreate exact historical layouts easily (as shows in my video), so perhaps we don't try to promise that we can? |
Yes...almost. I wouldn't want to lose what you've already built though, whereby if two panels are stacked on top of one another, and the user closes the lower panel: if they immediately then re-open that panel, it opens in its last position, not at full-height. Re-opening at full height only makes sense if the parent panel is no longer open. |
@cbjeukendrup Following @bkunda's request above, I would like to be able to query whether the last parent that owned a panel is the current parent that will own it, when calling edit: If that's true, it seems like we either have to invent some model for tracking that, or take the easier road of appending the tab to the larger space's tabs on any re-open. Open to other options of course. |
That's right, if I understand you correctly. The panels are all siblings, regardless of whether one is tabbed together with another or that they are stacked vertically or next to each other horizontally. The |
But on a related note, when I think about having to toggle twice to make a panel disappear, because it wasn't in focus on the first press, it makes me wonder if it will be perceived as a bug, and annoy users. |
@bkunda Ping from above message. I just want to know:
Just trying to get this issue done, and maybe leave the focus issue as a separate one. |
Hi @hanoixan, sorry for the delay.
If "open as usual" means "open in its last opened position", then yes. This sounds right.
If you're not happy with your solution here, then yes perhaps remove it. We may need to fix the focus implementation as a separate issue (@shoogle might have more to say on this). Thank you again! |
Yes that does need to be fixed before merging. |
@DmitryArefiev That is the issue with adding panels back in the same order they were removed. Similar to your example, consider two panels that each take up 500px of height in a frame, P1 (top) and P2 (bottom). P2 is removed retaining a size of 500px. P1 now has 1000px (expanding in P2's absence) when it is removed. P2 is brought back at 500px, but expands to 1000px to fill the height. P1 is going to be added back at its last known 1000px, and because of the neighbor growth strategy in KDDockWidgets, it will push P2 most of the way to the bottom. A more complex example is above at #15675 (comment). The solution that I want to implement this weekend is to handle the following cases:
There may be a better solution here, but I don't think there's a way to configure KDDockWidgets to fix this. It seems like this will need an extension to that lib's behavior. A separate change is that I want to remove the focus behavior, because it's not working as expected. |
@hanoixan Got it. Thanks! |
I've spent some time trying to find a way around this, but any changes to the rules for how widgets are inserted into tab layouts vs. adding new tabs is handled within KDDockWidgets, behind a private implementation. I don't think I can change the behavior unless I change KDDockWidgets. That seems like something out of scope for this issue, and would take coordination from a higher level engineer who has more ownership over this dependency. @bkunda @DmitryArefiev Unless someone can point me at a solution, I don't think there's anything more I can do here besides pull out the current focus handling code, and submit that. |
@RomanPudashkin Maybe you can help |
I was going through some old issues and came across #11242, which also seems to be fixed by this PR. |
It would be good if this fix does address that. I've assigned it to the 4.x shortlist. I think it might just need some input from @RomanPudashkin (when he's ready) to tidy-up one remaining aspect. |
In MS4.1, [properties panel] will revert position to left-sided tabs if the user previously situated it to the RHS of the screen and disabled then re-enabled its view. Will this PR fix that?... |
fa1f8d3
to
525a11a
Compare
Resolves: #11218
Resolves: #11242
This PR changes the behavior of toggling and open/closing tabbed panels. It affects the open/close/toggle behavior of both horizontal and vertical tabbed panels. New behavior: