wxWidgets / wxWidgets

Cross-Platform C++ GUI Library
https://www.wxwidgets.org/
6.32k stars 1.79k forks source link

wxAuiNotebook should have the ability to show close buttons on only some tabs #25072

Open craftyjon opened 3 weeks ago

craftyjon commented 3 weeks ago

Description

KiCad would like to use wxAuiNotebook in situations where there are some permanent tabs that the user should not be able to close, and some transient tabs that can be opened and closed by user action. It doesn't seem to be possible to show a close button on only some tabs right now. We propose that there be some kind of API added to set close button behavior per-page instead of only the global style flags.

vadz commented 3 weeks ago

Is it the same as the concept of "pinned" tabs or something different? We've had requests for adding support for pinned tabs, that have a special "pin" icon, always appear to the left (well, "near", taking RTL languages into account) side of the bar and are treated differently by some operations, e.g. "Close all" may not close the pinned tabs.

However at least in MSVS, which is a typical example of a complex TDI app, pinned tabs still have a close button...

So do we need "normal", "pinned" and "pinned and not closeable" ("fixed"?) states perhaps?

craftyjon commented 3 weeks ago

I think it's a different concept. Pinning tabs is a user action, like when the user decides they want to mark some tabs as special and then have them shown differently or not affected by some actions.

What we are talking about is removing the ability for the user to interact with certain tabs. Maybe "locked" state or something like this. No close button, and less important but a nice follow on, being able to disable drag and drop on these tabs might also be nice.

The use case for this is when we are using a single wxAuiNotebook to hold child tabs that have different concepts: some of these child tabs are "documents" that the user might open and close, and the others are "fixed UI" that the user should have no control over opening/closing. Pinning usually refers to when the children are all "documents" but the user wants to mark some of the documents as special.

Recent Firefox actually has a parallel example of this:

image

The left-most "tab" is "Firefox View", a UI feature that acts like a tab but cannot be closed or rearranged by the user. Then there is a pinned tab for Wikipedia, then a normal tab.

Note that I'm not asking for specific additional visual distinction between "locked tabs", regular tabs, and "pinned tabs" if they also get added (unlike the Firefox example where they draw an additional separator). I just want there to not be a non-functional close button.

craftyjon commented 3 weeks ago

@imciner2 points out that if wxAuiNotebook were refactored to be more overrideable in client code, it would be easier for us to just implement this special logic inside KiCad

imciner2 commented 3 weeks ago

@imciner2 points out that if wxAuiNotebook were refactored to be more overrideable in client code, it would be easier for us to just implement this special logic inside KiCad

Yep, this comes back to storing objects vs. pointers in the AUI controls (e.g., similar to the previous problem with AUI toolbars discussed here: https://github.com/wxWidgets/wxWidgets/pull/23311). In the wxAuiNotebook, the tabs are stored using an object of type wxAuiTabContainer directly, not a pointer. This means we can't just implement a new tab container that overrides the behavior of wxAuiTabContainer::GetCloseButtonState() to hide the button on the tabs we want, because there is no way to actually have the wxAuiNotebook accept/use our custom class.

Edit: Also, the function we would want to change - wxAuiTabContainer::GetCloseButtonState() is private in the class, so we can't even override the base class version nicely.

vadz commented 3 weeks ago

I see, thanks. I like "Locked" term, and I understand that it's different from "Pinned", but I think I may implement both of them at the same time because they do share some, even if not all, characteristics, e.g. they can't be moved (via drag and drop) in another group, i.e. together with the normal tabs (BTW, can locked tabs still be moved to another position in the "locked tabs" group or should even this be forbidden?).

As for suggestion by @imciner2, this would be tempting, of course, but it's not that simple to understand what are the hooks/events to provide without making them neither over general nor so specific to this particular use case that they wouldn't be useful for doing anything else. And, of course, we still need to implement at least

  1. "No close" style (BTW, I wonder how is this supposed to work with wxAUI_NB_CLOSE_BUTTON, we probably need to disable it when a non-closable tab is active).
  2. Special rendering for pinned/locked tabs.
  3. Support for restricting drag and drop inside a single group (but forbidding dragging entirely would be simpler).

in wxAUI itself. So I think it might make more sense to just implement support for this in wxAUI itself entirely, at least pinned tabs are a pretty common feature and if Firefox started using locked tabs, chances are they may become common too. Of course, if you'd like to implement this yourself, instead of waiting for me to do it (although the wait shouldn't be too long, hopefully, because I did plan to work on adding support for pinned tabs anyhow, and this bumps it up to the head of my TODO queue), please let me know and I can wait for your PRs. Just be warned that I'm working on #25073 now, which will change a few things in the related areas of code, so if you do want to work on this yourself, it may be better to wait until I finish this (and, of course, if you have any comments about that feature, please don't hesitate to leave them in the other issue!).

craftyjon commented 3 weeks ago

(BTW, can locked tabs still be moved to another position in the "locked tabs" group or should even this be forbidden?).

We would like to forbid this. Might be nice to make this configurable in case some other users don't want to forbid it.