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
Custom popup placement callback #15667
base: master
Are you sure you want to change the base?
Conversation
I think this PR is a good example of an old discussion where we need to start organizing controls by feature/control rather than putting them all together. In this case I think
Small projects in the MVVM world organize by type, I get that. But inevitably with large projects you end up organizing by project/namespace and then by feature. All large-scale projects I've worked on evolve to organize by feature. |
/// <summary> | ||
/// Defines custom placement parameters for a Popup control. | ||
/// </summary> | ||
public record struct CustomPopupPlacement |
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.
I would also break this out into a new file.
Additionally, if it was me, I would make is a class so it could actually be extended if ever needed. This is too complex of a type to lock-down to a struct in my opinion.
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.
I can see PopupPositionRequest being complex (which is why it's a class already), but why CustomPopupPlacement? Essentially, it's just a three enums and a Point property.
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.
In my mind struct is for primitives types (int, size, etc.) this is more complex. The reason to make it a class is to not limit yourself in the future (keep the door open for future extension by developers). There also doesn't appear to be a performance reason for this to be a struct.
So my criteria would be
- Everything is a class by default in an object-oriented language
- Is it a primitive type? then make it a struct
- Is it performance critical? then make it a struct.
- Is it a special-case?
It fails both of these struct tests and isn't a special case so my convention would be to make it a class. By default types should be a class in an object oriented language like C# -- not a struct. I do think Avalonia went a little too far with struct usage elsewhere.
I haven't tried the current prototype implementation yet, but my original thought after digging in when writing the issue was that we could improve over WPF's implementation by still allowing default positioning logic to run but also give the callback, if specified, a way to further adjust it. After doing a quick review of the code changes for this PR, this is a summary of the public API changes:
My thoughts on the updates are:
The main reasons that I suggest the changes above are that it keeps the APIs simple and open for possible future expansion. But more importantly, the callback would receive all the pre-initialized anchor/gravity/constraint/offset values and the callback could leave them as-is or adjust them. Consider a case where we set It's very open ended with the suggested changes without requiring the developer to do too much either. I'm happy to discuss further. |
This is a very good idea! |
I might end up wrong here, but positioning API wasn't changed in couple of years, without any need or plans to change it either. Especially when current positioning API is mirroring wayland as a common denominator. I also not sure about reusing the same class (CustomPopupPlacement) for callback input and output. Since input will always include additional parameters - anchor rect and popup size. While these values are never returned from the callback. Marking them readonly helps a little, but is it really worth it?
I am going to leave this PR as is for now, as I am currently on vacation. More opinions are welcomed here. |
You can test this PR using the following package version. |
What does the pull request do?
Implements Placement.Custom for Popup and Popup-based controls - Flyout, Tooltip, ContextMenu.
Differences from WPF implementation:
Size targetSize
argument. I don't see any limitations to provide full rect here though.New APIs:
Obsolete APIs changes (no binary breaking changes, except NotClientImplementable interface):
Checklist
Breaking changes
None.
Obsoletions / Deprecations
See API changes.
Fixed issues
Fixes #15233