Skip to content
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

allow various alignment corners & centers #4

Closed
ladyada opened this issue Feb 25, 2019 · 28 comments
Closed

allow various alignment corners & centers #4

ladyada opened this issue Feb 25, 2019 · 28 comments

Comments

@ladyada
Copy link
Member

ladyada commented Feb 25, 2019

easy text alignment based on x, y would allow for pretty UI elements!
needs adafruit/Adafruit_CircuitPython_Bitmap_Font#5

@ladyada
Copy link
Member Author

ladyada commented Mar 2, 2019

@tannewt @jerryneedell @makermelissa @djecken @jedgarpark FYI - im gonna change the way text displays right now because all text is Y offset (i eyeballed it and didnt notice till now)

image

ill make it so the top left corner is the origin point - perhaps it was at one point and we messed with it

@ladyada
Copy link
Member Author

ladyada commented Mar 7, 2019

@tannewt
Copy link
Member

tannewt commented Mar 7, 2019

@ladyada
Copy link
Member Author

ladyada commented Mar 7, 2019

@tannewt
Copy link
Member

tannewt commented Mar 7, 2019

@tannewt
Copy link
Member

tannewt commented Mar 8, 2019

Thinking more about this I don't think we want baseline because it handles multiline text poorly. The examples above don't handle multiline layout themselves but TextArea does.

Before we add anchor options, I think defaulting to vertical center of the left edge of the text would provide the best default behavior for both single and multiline text.

Since the overall bounding box is much larger than most glyphs, I think we should use the capital M's measurements to determine line size. Therefore, the vertical center would be (number_of_lines * height_of_M + (number_of_lines - 1) * line_spacing) / 2 + ascender_height relative to the top left. Ascender height is the difference between the max height and the height of capital M after baseline adjustments.

We cannot base the origin on the actual glyphs because that risks different alignment across aligned TextAreas.

Does that make sense?

Later we can add top left and bottom left anchors based on the M too. We'll also want to expose a bounding box or vertical padding so the user can account for ascenders and descenders.

I also think we should remove width and height in favor a flat max_glyph_count. Width and height are confusing and make no sense with variable font spacing.

@ladyada
Copy link
Member Author

ladyada commented Mar 8, 2019

ok - how would you calculate size of a text area before creating it? we'd have the bounding box be a static function?

@tannewt
Copy link
Member

tannewt commented Mar 8, 2019

Why do you need the size before creating it? The vertical alignment should be done for you.

@ladyada
Copy link
Member Author

ladyada commented Mar 8, 2019

word-wrap calculation?

@ladyada
Copy link
Member Author

ladyada commented Mar 12, 2019

@tannewt ok now that default is center left... i could add justifications like left (default), center and right
want it as an initializer arg?

@tannewt
Copy link
Member

tannewt commented Mar 12, 2019

Would justification change the origin or just the layout? __init__ arg is the way to go.

@ladyada
Copy link
Member Author

ladyada commented Mar 12, 2019

easiest would be changing origin: center would now be center of label (how else could you know for a single line what centering is?) and right would be center-right of label

@tannewt
Copy link
Member

tannewt commented Mar 12, 2019

Asking for clarity. Justification and origin location don't need to be tied to one another. You could center against the widest line.

@ladyada
Copy link
Member Author

ladyada commented Mar 12, 2019

ok if you have a center or right-justified label with text that changes, you'd have to move it every time you changed the text

@tannewt
Copy link
Member

tannewt commented Mar 13, 2019

You could have a separate origin (or anchor) property that changes how the text is positioned. I don't think it's safe to assume changing the justification should also change the origin.

@ladyada
Copy link
Member Author

ladyada commented Mar 13, 2019

ok - we'd have to layout all the glyphs, then move them in a secondary pass

@tannewt
Copy link
Member

tannewt commented Mar 13, 2019

When we add it we could use a nested group to handle the anchor changes. That way the glyphs have fixed position.

@ladyada
Copy link
Member Author

ladyada commented Mar 13, 2019

! good idea - i may get to it this weekend when i redo buttons

@tannewt
Copy link
Member

tannewt commented Mar 13, 2019

Thanks! I appreciate all of your help with the text layout. It is awesome because of you!

@ladyada
Copy link
Member Author

ladyada commented Mar 13, 2019

yay - im still wrapping my head around groups im used to a decade of bitmap alignments

@theacodes
Copy link
Member

Coming back to this because we had someone in the discord run into a case where the M character wasn't present in their bdf and it caused issues. This isn't as uncommon as it might seem - it's super common to see people prepare fonts for just special glyphs.

I also find the behavior of the y of the Label being the vertical center of the text to be extremely surprising, especially for dynamic text that could flow into two lines. It's also not quite correct for non-English glyphs, such as Á.

As a suggestion, I'd propose we go to the same behavior as PICO8, Cairo, and other common font renders: the x and y of the text object should be the top-left of the bounding box. We can add helpers to align the text to other positions.

So, something like:

from adafruit_display_text import TextArea

font = ..
text = TextArea(font, "Hallo Ásta\nGóðan daginn", color=0xFFCC00)

# The extents of the text can be used directly to align the text,
# in this example, it centers the text on the display.
text.x = display.width / 2 - text.width / 2
text.y = display.height / 2 - text.height / 2

# Or helper methods can be used
text.center(display.width / 2, display.height /2)
text.center_horizontal(display.width / 2)
text.center_vertical(display.height / 2)
text.left_align(x=20)
text.right_align(x=160)
text.top_align(y=20)
text.bottom_align(y=120)

@tannewt
Copy link
Member

tannewt commented Oct 18, 2019

We did the vertical y alignment to have the best result when rendering text in a button. Having it be the top left requires adjustment depending on the number of lines of text where vertical centering looks somewhat better.

I'd love to see other options available though.

@makermelissa
Copy link
Contributor

makermelissa commented Oct 18, 2019

Maybe there could be a parameter to have it vertically center as it does now or align to the top by default? That way for button code we could pass a parameter that tells it to align centered and not break code. Or the other way around.

@RichardA1
Copy link

I just came across this while trying to figure out how to recalculate y for multiline dynamic text to do top vertical alignment. I see that it actually recalculates the y position for multiline text, but could there be another parameter that skips that for vertical top option. Something like align=top/center/bottom to change the alignment.

I realize that this was made to make it easy for buttons, but what about adding functionality for Text Box that could have a set size and include word wrapping. and handle text overflow.

@RichardA1
Copy link

I did a pull request to see if I could add the align parameter. It basically just lets you opt out of the y_offset for _update_text so that the text remains aligned at the top.

https://github.com/RichardA1/Adafruit_CircuitPython_Display_Text/blob/master/adafruit_display_text/label.py

@caternuson
Copy link
Contributor

Has this been taken care of by #22 ?

@RichardA1
Copy link

@caternuson Ah, yes that one would work but it did not look like it was live yet. I ended up doing a roundabout way to do top align for the Guide that I am working on and just hoped that something less hacky/redundant would get pushed to this library.

Thanks

@kattni
Copy link
Contributor

kattni commented Apr 29, 2020

This appears to have been resolved.

@kattni kattni closed this as completed Apr 29, 2020
kattni pushed a commit that referenced this issue Aug 17, 2020
simplifying example scripts. Awesome!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants