adafruit / Adafruit_CircuitPython_DisplayIO_Layout

A Circuitpython helper library for display element layout using displayio.
MIT License
9 stars 14 forks source link

Why is `anchor_point` reset for cell contents? #49

Open todbot opened 3 years ago

todbot commented 3 years ago

I was looking into a question someone in #help-with-circuitpython had about centering text, and noticed in this conditional, if the content has anchor_point, it's then reset to (0,0). https://github.com/adafruit/Adafruit_CircuitPython_DisplayIO_Layout/blob/e5e8b5a4fbd03701d38faf3a086ef82ffd330658/adafruit_displayio_layout/layouts/grid_layout.py#L155

FoamyGuy commented 3 years ago

The logic used to determine the anchored_position starting on the next line

https://github.com/adafruit/Adafruit_CircuitPython_DisplayIO_Layout/blob/main/adafruit_displayio_layout/layouts/grid_layout.py#L156-L161

assumes that the anchor point of the content object will be (0, 0) or Top Left corner of the rectangle that the represents the content object. If the anchor_point were something different it would run the risk of the content not being placed inside the Grid cell, it may run outside of the cell that it's supposed to go into.

FoamyGuy commented 3 years ago

That being said some sort of gravity = center or possibly even right functionality would be a good feature to add. I'm definitely open to those if anyone wants to make a PR that adds the ability for it to use 0.5 anchor points and computes the center of it's cell instead of the top left like it does now.

todbot commented 3 years ago

Hmm I guess I'm unclear on what anchor_point even means in terms of local coordinates vs container coordinates. The anchoring parameters have never been very clear to me, and I assumed an object with anchor_point=(0.5,0.5) would be placed in the center of the object's container. I think this is not how the anchoring stuff has traditionally been used. (For instance, in this conception, anchored_position becomes irrelevant)

FoamyGuy commented 3 years ago

anchor_point will only have any effect if anchored_position is used also. These two guide sections provide good visualizations of how they work together: https://learn.adafruit.com/circuitpython-display_text-library/label-placement#anchored-positioning-3084380-8 and https://learn.adafruit.com/circuit-python-tft-gizmo-candy-hearts/how-it-works#text-positioning-3055539-7 The anchor point is the point within the object (Label or other Widget) that you will position it relative to. The anchored_position then is the location in pixels within the parent where the anchor_point will get aligned on top of.

The anchor_position location is in pixels within the objects parent's coordinate space. In the most basic usage it's parent is the display itself and thus it's placed in screen coordinates. But it can go inside of other parents like Groups or Widgets which end up having their own coordinate space.

todbot commented 3 years ago

Yeah I've been over those guides many times. And I can get anchoring to work when I have full control over the layout. I think my main issue with the current anchoring system is it's pretending to be a relative parameter (anchor_point) that a component can set on init, but it requires absolute-positioning knowledge of its container (anchored_position), something the container may not even know on component init.

It feels at odds with other layout managers I've known (Qt, Swing, CSS, etc) where the component only knows its preferred/min/max size and it is the component container that is given hints on how to lay out that component (left/center/right, top/center/bottom, padding, margin, and so on).