Proposal: Introduce an operation (called for these purposes AnchorOp) that defers content aligned to a particular rectangle in the existing layout. The deferred content should be displayed such that one corner of the deferred layout is aligned to one corner of the anchor rectangle. The choice of corner is decided by which corner provides the most space for the deferred content.
Thanks to Elias, Lucas, and Egon for talking through this with me during the community call office hours! We also discussed an operation that would just nudge content as little as possible until it was entirely on-screen, but anchoring seems like it would produce better results.
Anchoring can be modeled in terms of three rectangles:
- The window frame as the outermost boundary of drawable content
- The area in which we want to anchor some content
- The dimensions of the content we want to anchor
The goal of anchoring content is always to ensure that the dimensions of the anchored content fit within the window frame as much as possible, and (secondarily) that the position of the anchored content is as close to the requested positioning as possible with respect to the anchor area.
I think there are a few kinds of positioning that we'd want to take into account:
- wanting the anchored content to either cover or not cover the anchor area
- wanting the anchored content to share a corner, edge, or center with the anchor area (if possible)
- wanting the anchored content to always be aligned on a particular axis (drop-down menus won't want the options to appear beside them instead of above/below them)
- wanting to bias the anchored content positioning in a particular direction in cases where multiple valid positionings are available.
For instance, right click context menus:
- will want the anchor area to be a 1x1 pixel rectangle at the location of the right-click
- will want to cover the anchor area
- will want corner-to-corner alignment when possible between the anchor area and the menu
- will want to bias towards the aligning the NW corner in the case of ties
Something like a material design context menu in an app bar has similar constraints:
- will want the anchor area to be the triggering button's dimensions
- will want to cover the anchor area
- will want corner to corner alignment between the menu and the button
- will want a NE bias for LTR layouts and an NW bias for RTL
A dropdown menu like the HTML select will want:
- the anchor area is the always-visible portion of the select
- will not want to cover the anchor area
- will want to present options vertically above/below itself, but not beside
- will want corner/corner and/or edge/edge alignment
- will want to bias towards dropping the anchored content downwards when it fits in both directions
- will be able to constrain the size of the dropdown area so that it can always fit by taking the window height, subtracting its own height, dividing by two, and constraining the anchored content vertically to that size
A tooltip will want:
- the anchor area to be the control it describes
- will not want to cover the anchor area (at least in some design systems, I suppose it can cover it)
- will want to be centered on an edge relative to the anchor area
I'm uncertain of the best way to describe the relationships between the rectangles in an API, and perhaps this is overly complex. These are just the primary use-cases for anchoring that occur to me.
I think this could be done very easily if each widget could get two pieces of information: The current screen size and the absolute screen position of the widget. Now I handle this by globaly storing the screen size and mouse position, and using that to show a tool tip and dropdown box. This works well for mouse clicks, but not for keyboard activation. Could this info be put into the Context (gtx)?
I think that was mentioned at Community Call. But, since Gio uses "Immediate Mode" such information is "not reliable", far I remember. I'm using similar construction for
List, in order to get the current position of the element in the list. :S
It's less about unreliable absolute positioning and more about the fact that we support general 2D affine transformations. How do you communicate the absolute screen position when the current drawing canvas has been rotated 45 degrees? However, Elias has been thinking of exposing something along these lines with some specific caveats about transformations. I can't say more now, but we will likely solve this by exposing a way to resolve a position relative to some transform.