-
-
Notifications
You must be signed in to change notification settings - Fork 689
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
widget to display multi-line text #766
Comments
I'm guessing from the It sounds like a new MultilineLabel widget (or, at least, a new word-wrap option on the Label widget) is called for. If anyone is interested in hacking around on this, Dan Yeaw's talk from PyCon 2019 may be instructive. |
Yes, static text (which seems to be called Support for the following (extend existing Label widget or new widget if necessary):
How does one currently display a long line/paragraph(s) of text? |
Currently? One doesn't :-) The current Label widget assumes it's a simple text annotation of an input widget. There are side effects of allowing a label to do something like word wrap (e.g., consider the box algorithm - should the box try to be the size of the label, or should the label wrap to be the size of the available box?). That's why a new widget is required. |
If a new widget is required then I'm ok with that, especially if it's simpler to use and maintain, etc. But, (thinking out loud), couldn't it depend on attributes of the widget (with defaults being the same as Label's current behvaiour)? i.e. Label with extra settable attributes to define behaviour. A new widget could be a derived class (or a function/decorator?) with to attributes set to suitable values for multiline static text? e.g. wrapping would occur when some "max_width" limit was reached. If "max_width" was not set (
What to do with text "off-screen"? Truncate or allow to scroll if a "row_scroll" or "column_scroll" attribute is set. |
I guess there is no "rich text" widget either. e.g. a widget that can display text with some chars/words in bold and/or italics and/or other styles and/or coloured, etc. What would be the proposed widget for that? Would the multiline widget morph into that too? I guess some kind of web widget could do it, but is that fit the Toga way? Can unicode deal with all that? I found https://www.babelstone.co.uk/Unicode/text.html which shows that it can, but the encoded text for styled chars/words is not easy to author - e.g. can't just insert a start/end style marker within text. |
To clarify - an extra attribute on the existing Label widget (is multiline=True) may be a viable option for implementing multiline text. In the case of TextInput vs MultilineTextInput, it wasn't possible to easily accommodate both behaviors in a single widget because the MultilineTextInput requires the use of an internal scrollbox. That particular constraint won't exist for a multiline Label, but I can easily imagine that the complexities of managing multiline text might mean that the implementation of Label ends up being covered with block of "if self.multiline" logic - at which point, you have to question whether you actually have 2 different widgets. Subclassing may also be an option. There will, after all, be some common behavior (e.g., setting the text); so, having MultilineLabel be a subclass of Label that overrides significant pieces of logic may also be a viable option. In short - we're at the point where some exploratory work is needed to work out what is viable. As for a "rich text" widget - again, it depends what you mean. If you mean static text, then I imagine MultilineLabel should encompass some of that; or, in one interpretation, we already have that capability with WebView. If you mean a rich text editor - well, that's a much bigger project. A rich text editor (and more specifically, a code editor) is definitely on my wish list; but it's also a big task. In the past, I've hacked together a rough demo of such a widget using the WebView with a rich content editor embedded in it - and while that is sufficient to get something working, it's not my ideal end solution. However, as a stop gap measure... maybe it's enough? I'm not sure what you've got in mind when you refer to "Unicode" as an option here. Unicode is a text encoding scheme, not a markup mechanism. There are some limited styling hacks you can use based on switching code planes; but they're not really intended for styling, and they're entirely dependent on the underlying font having representations for code points on the planes you use (i.e., there's no guarantee that the symbols on the Fraktur math codeplane will actually appear consistently between fonts, between platforms, or even appear at all). |
I have a box layout problem on iOS when using my MutilineLabel function. It seems to layout ok on macOS (apart from some missing text on the label itself). i.e. the width of the box looks ok on macOS but not on iOS. Here is trimmed down code that I'm using. #!/usr/bin/env python
from __future__ import annotations
from typing import ( Optional, List )
import toga
from toga.style import Pack
from toga.style.pack import ( COLUMN, ROW, CENTER )
#!============================================================================
def MultilineLabel( text : str,
box_style : Pack = None,
label_style : Pack = None,
) -> toga.Box :
"""
Return a Toga Box of Toga Label widgets to mimic a multiline label widget.
"""
box = toga.Box( id = None,
style = box_style,
children = [ toga.Label( t, style=label_style ) for t in text.split() ]
)
return box
#!============================================================================
class SGGC_Live( toga.App ) :
def startup( self ) :
#! Create the main window
self.main_window = toga.MainWindow( title=self.name )
#!
#! populate boxes with widgets
#!
head_box = toga.Box( id = 'head_box',
style = Pack( direction=COLUMN, padding=10, background_color='teal' ),
children = [
toga.Label( 'SGGC 2019', style=Pack( text_align=CENTER ) ),
toga.Label( 'South Gippsland Golf Inc', style=Pack( text_align=CENTER ) ),
],
)
days_box = toga.Box( id = 'days_box',
style = Pack( direction=ROW, padding=10, background_color='teal' ),
children = [
toga.Label( 'Day1', style=Pack( flex=0, text_align=CENTER ) ),
# toga.Label( 'Day2', style=Pack( flex=0, text_align=CENTER ) ),
MultilineLabel( "Sat\n15th\nFeb",
box_style = Pack( direction=COLUMN, flex=0, background_color='yellow' ),
label_style = Pack( text_align=CENTER, flex=0 )
),
toga.Label( 'DayX', style=Pack( flex=0, text_align=CENTER ) ),
]
)
body_box = toga.Box( id = 'body_box',
style = Pack( direction=COLUMN, flex=1, padding=10 ),
children = [
toga.Box( style=Pack( flex=1 ) ),
toga.Label( 'Body', style=Pack( text_align=CENTER, flex=1 ) ),
toga.Label( 'Body', style=Pack( text_align=CENTER, flex=1 ) ),
toga.Label( 'Body', style=Pack( text_align=CENTER, flex=1 ) ),
toga.Box( style=Pack( flex=1 ) ),
],
)
foot_box = toga.Box( id = 'foot_box',
style = Pack( direction=ROW, flex=0, padding=10, background_color='teal' ),
children = [
toga.Label( 'F1', style=Pack( flex=1, text_align=CENTER ) ),
toga.Label( 'F2', style=Pack( flex=1, text_align=CENTER ) ),
toga.Label( 'F3', style=Pack( flex=1, text_align=CENTER ) ),
],
)
main_box = toga.Box( id = 'main_box',
style = Pack( direction=COLUMN, flex=0 ),
children = [ head_box, days_box, body_box, foot_box ],
)
self.main_window.content = main_box
#! Show the main window
self.main_window.show()
#!============================================================================
def main() :
return SGGC_Live( 'SGGC Live', 'au.com.etrix.sggc_live' ) If I uncomment the line to show toga label Day2, and comment out the MultilineLabel call, I get the following screenshots. If I comment out the toga label Day2, and uncomment the MultilineLabel call (as code above), I get: Is this a Toga issue or have I missed something? Even if I have made a mistake, I would expect the same result on both platforms. |
If I change the box style of the MultilineLable widget to box_style = Pack( direction=ROW, flex=0, background_color='yellow' ), but I want the |
If I set the box style I'm not sure if this is the correct way of specifying this or whether this is a "workaround". box_style = Pack( direction=COLUMN, flex=0, width=1, background_color='yellow' ), |
|
From the documentation, it seems MultilineTextInput is not supported on Android? Are there any alternatives? |
@aitoehigie At present, no. The widget set on Android is limited, as the platform itself has only recently been rebuilt. We're in the process of filling in the gaps. |
For future reference: #1498 fixed newlines in labels on all platforms except iOS, which is tracked by #1501. Automatic word wrapping is a much harder issue, because as Russell said on Discord:
The most common requirement would be "width determined by other constraints, then as tall as necessary to fit the text". But I’m not sure if this can be accommodated by the current layout algorithm, because as I understand it, each widget declares its minimum width and height simultaneously, and then its parent container assigns actual width and height simultaneously. In order for one to depend on the other, we’d need two phases. For example, a ROW box would first determine the widths of its children, and then ask each child what its height would be for the assigned width. I'm sure we can take some guidance from CSS here. |
CSS is definitely the standard to follow here - it's pretty much the raison d'être of CSS. Pack definitely isn't up to the task as-is, because it doesn't have any line break/reflow mechanism. I don't know how much effort is worth putting into Pack vs improving Colosseum; I suspect it will be more worthwhile to keep Pack simple and make Colosseum the focus of complex layout. We will also likely need to lean on platform specific implementations of text reflow to make multiline labels work. |
I'm going to close this; we now support newlines in labels, which allows for multiline labels. A full reflow model for text would require a radical redesign of Pack. |
Is there a Toga widget to display multiline text?
The closest I can see is using a
MultilineTextInput
withreadonly=True
.At the moment I'm creating multiple labels within a box, which gets tedious, although I could pass a string with embedded newline chars to a function to do it programatically.
The text was updated successfully, but these errors were encountered: