-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Implementing a rich-segmented text view widget #2074
Comments
Thanks for this, lots of good thoughts. I'm not sure that I would agree with the addition of Overall the concept of segments is clearly required, but it would better match the Fyne semantic API if they were defined with meaning instead of theme attributes. For example Perhaps you can expand on what the struct based illustration has
Indeed - the intention is that the wrapping code should include it. Personally I would prefer that the hypen/ellipsis is always on, but if it is to be controlled it could be either through the |
The switch bounds := bounds.(type) {
case ThemedSegment:
case WidgetSegment:
case string: // does not compile!
}
I think that if we don't expose an API that allows changing attributes arbitrarily and restrict the API to a preset of attributes, then that would be very bad; it would restrict the user heavily in what they can do. With the interface API, something like this can still probably be implemented and used on the interfaces. Otherwise, I think a theme constructor to construct a prestyled segment would work. But I don't think the API should be limited to just preset styles. |
As an API beased on semantics and intent there would need to be a really strong reason to expose explicit style manipulation. |
The flexibility to do any styling is a reason to expose explicit style manipulation. I'm not sure what you mean. Why would you want to restrict the user over exposing a more customizable and flexible API? I'm not sure what that would help accomplish. Not to mention, the goal of this API would be to expose a low-level flexible widget that other widgets can be based on in the first place, so why restrict them to something less? From what I can see of |
I am trying to keep us in-line with the semantic widget API that is styled by the theme. And so "heading" is the semantic portion and "larger text, bold" is in the theme.
We don't really have low-level widgets, so the path is potentially unclear. Maybe this is not truly a The |
For the record, I am proposing a new package
Not necessarily. I don't think the library should enforce this assumption onto others. It strictly limits the usage of such a thing. |
This is only not true if an app completely replaces the theme. |
Whether or not the user needs to choose a color depending on the theme should be up to the user; it shouldn't be forced that the user must do it that way. There are cases where the user may receive raw hex colors and would prefer the exact colors to be used in place rather than having the library try to be smarter than it should be. I do agree that there should be an API that handles this, but it should absolutely not be the only API available. In other words, the entire point of my proposal is to have an API that delegates the choices to the user, not the library. The library can (and should) have higher-level APIs that make certain choices for the user, but it should absolutely not force the user in a certain way. |
The approach we have taken is that the standard widgets will do standard things, and can be extended to customise. I think that fits in this case as well. |
If you start with a restrictive widget that's not nearly as flexible as this, then how can they be "extended" to be as customizable? |
Well, I suppose that is the purpose of a design exercise. |
I think that being simple shouldn't mean to limit what the end user can do. As I see it, the current proposal is simple: it provides a bare-bone way to style texts without any concern regarding the current theme, leaving full control to the user while being easier to implement (there are only primitive styling to be implemented). This freedom from simplicity would also allow extending the widget to make higher-level ones, such as widgets that have predefined style-sets for Markdown and such. |
Then it does not fit in the
What I am trying to say is that the opposite is possible. Basic widgets provide basic APIs, with the ability to extend to add custom behavior. Apps using the basic widgets should look great no matter what. In this regard only errors should be red (for example) and primary text will always match the user's default theme (unless the app provides an alternative theme). Perhaps this relates to #1741 - we are trying to deffine a colour pallete based on semantics rather than values, which will lead to a much better match of TextGrid to the theme approach described above. |
I'm not proposing a new widget in the
I fail to see how this would be carried out if the "basic API" locks the user to only a very limited set of styles. |
Hopefully something like the following would support semantic basis for the main API whilst remaining extensible: var (
RichTextStyleInline RichTextStyle
RichTextStyleParagraph RichTextStyle
RichTextStyleHeading RichTextStyle
RichTextStyleSubHeading RichTextStyle
RichTextStyleQuote RichTextStyle
RichTextStyleURL RichTextURL
RichTextStyleEmphasis RichTextStyle
)
type RichText struct {
BaseWidget
Segments []TextSegment
}
type TextSegment struct {
Text string
Type RichTextStyle
}
type RichTextStyle interface {
Alignment() fyne.TextAlign
Inline() bool
TextSize() float32
TextStyle() fyne.TextStyle
Segments() []TextSegment
}
type RichTextURL interface {
RichTextStyle
URL() url.URL
} |
Main discussion is happening on Text Refactor and further discussion of the rich text aspects at #21 |
Closing this to focus discussions on the items above. |
Preamble
UI frameworks should have a comprehensive API to allow users style different segments of texts as well as inserting images or even allowing absolute positioning of arbitrary widgets. A use case for this would be formatting a chat message to have rich formatting.
An example of a UI framework that does this is GTK3: the
GtkTextView
widget allows styling segments of texts as well as inserting arbitrary widgets (!). This flexibility not only allows font sizes, colors and other attributes to be modified dynamically over certain regions of texts, but it also allows inserting inline images, similar to how inline emojis can be implemented in HTML.As of right now, the only widget that can display some kind of text styling is the Label widget, but the widget does not allow dynamic typing over different segments of texts.
Existing Issue
Issue #149 proposes a widget for previewing Markdown for a rich text widget. There are several issues with having a widget just for Markdown, but the most obvious one would be the limitation to only Markdown and not any other arbitrary markup formats. Instead, it would be much better to have a widget that allows flexible text segmenting and styling, and then to write a separate Markdown-to-segments converter.
Proposal
Part 1: Existing Modifications
It would be nice for
fyne.TextStyle
to be appended to be richer and express more of what Markdown has to offer:This isn't particularly within the scope of this proposal, but it would make the "rich" text much richer.
Part 2: Package
richtext
The new
richtext
package proposed will provide a multi-line text widget capable of displaying a large block of text with segments attributed to bounds within the text region. The base for the texts and its segments should be:The segment interfaces are intentionally left as interfaces instead of structs to allow the caller to arbitrarily implement their own dynamic styling segments. The API might incur too much boilerplate on the caller, however, and interface-to-interface assertions tend to be slow. A struct version of these segments may work out:
The struct idea seems to be much more sound; it also seems more straightforward to use and would take less boilerplate. The
map
constructs insideThemedSegment
are slightly weird, however.Note that this is merely an initial draft, and that suggestions and improvements are very welcomed. I've also considered adding
fyne.TextAlign
into the Segment, but how it would work exactly, I wouldn't have anything for reference.Appendix
None of the changes proposed above should be breaking.
As of right now, it seems that Fyne does not yet hyphenate or ellipsize broken or overflowing words. It would be nice in the future to include toggling them when they do get added.See #1660.
Reference
This API was largely based off of my text segment API for a chat protocol. The reference documentation of its text segment API can be found here. This file contains a simple implementation of a segment that changes the color of a segment of text.
Not all of these APIs will translate to Fyne, however. Fyne is a UI framework/library, so its APIs should ideally be tied down to the core styling, while something like cchat is a chat library, so its segments would describe a more abstract style of text.
The text was updated successfully, but these errors were encountered: