Skip to content

Add support for Wrapping for RadioGroup option strings#6369

Open
qiulaidongfeng wants to merge 10 commits into
fyne-io:developfrom
qiulaidongfeng:develop
Open

Add support for Wrapping for RadioGroup option strings#6369
qiulaidongfeng wants to merge 10 commits into
fyne-io:developfrom
qiulaidongfeng:develop

Conversation

@qiulaidongfeng

Copy link
Copy Markdown

add field Wrapping to RadioGroup.
In order to enable word wrapping
for text exceeding the screen
when creating a single choice question UI,
similar to the TextWrapBreak for widget.Label

Fixes #5656

@andydotxyz andydotxyz left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for looking at this. It is too late for 2.8 unfortunately as we have passed feature freeze, but if you target 2.9 we can land it after release.

It is worrying that there are so many layout changes for an optional new parameter - can you comment on that?

A few inline comments about things that don't seem quite right too.

Comment thread widget/radio_group_extended_test.go Outdated
test.WithTestTheme(t, func() {
render.Refresh()
customTextSize = render.label.TextSize
customTextSize = render.label.Theme()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes no sense...

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is because previously we set txt.TextSize = i.Theme().Size(theme.SizeNameText) in radioItemRenderer.Refresh, but RichText does not have this field. so my do r.label.Segments[0].(*TextSegment).Style.SizeName = theme.SizeNameText,but it not change Size() result. If there is a better way to do this, please let me know. Thank you

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I meant more literally - it makes no sense to have a fyne.Theme that is called customTextSize.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you want to check the text size output for a widget you can use WidgetRenderer(...) to get the renderer and then call Objects() on that to get the canvas.Text.

Comment thread widget/radio_item.go Outdated

func newRadioItem(label string, onTap func(*radioItem)) *radioItem {
i := &radioItem{Label: label, onTap: onTap}
func newRadioItem(label string, Wrapping fyne.TextWrap, onTap func(*radioItem)) *radioItem {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like this does not propagate change if Wrapping is set after initial creation

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

Comment thread widget/radio_group.go Outdated
}
var itemHeight, itemWidth float32
minSize := r.radio.MinSize()
minSize := s

@andydotxyz andydotxyz Jun 21, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks incorrect - the minSize of an object should not be set to its current size

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I revised the code to demonstrate my intention. Specifically, when RichText uses fyne.TextWrapBreak, its MinSize might not occupy enough screen space, resulting in unexpected line breaks.

@andydotxyz andydotxyz added the after-release For when an ongoing release is finished. label Jun 21, 2026
@coveralls

coveralls commented Jun 21, 2026

Copy link
Copy Markdown

Coverage Status

coverage: 59.817% (+0.01%) from 59.806% — qiulaidongfeng:develop into fyne-io:develop

@qiulaidongfeng

Copy link
Copy Markdown
Author

Thanks for your quick reply.

It is worrying that there are so many layout changes for an optional new parameter - can you comment on that?

This is inevitable as radioItemRenderer has been changed from using canvas.Text to widget.RichText.
However, I believe the following benefits make it worthwhile to do so:
It improves the readability and development efficiency of the code. Previously, for similar UI, I needed to write

func newRadio(options []string, onclick func(string)) (*fyne.Container, func(tf bool, sigle int, typ int)) {
	var selected string
	var checkboxes []*widget.Check
	content := container.NewVBox()
	for i, option := range options {
		label := widget.NewLabel(option)
		label.Wrapping = fyne.TextWrapBreak 

		check := widget.NewCheck("", func(checked bool) {
			if checked {
				for j, cb := range checkboxes {
					if j != i {
						cb.SetChecked(false)
					} else {
						selected = options[j]
						onclick(selected)
					}
				}
			} else {
				selected = ""
			}
		})
		checkboxes = append(checkboxes, check)
		hbox := container.NewVBox(check, label)
		content.Add(hbox)
	}
	return content, func(b bool, single int, typ int) {
		if typ == 0 {
			if b {
				checkboxes[0].SetChecked(true)
			} else {
				checkboxes[1].SetChecked(true)
			}
			return
		}
		checkboxes[single].SetChecked(true)
	}
}

This is just to make text display using the existing fyne.TextWrapBreak.

Secondly, this is similar to word-break: break-all and only requires one line, which is easy to learn.
If we can accomplish roughly the same thing more simply,
it will help Go programmers with HTML experience like me learn Fyne faster.

@andydotxyz andydotxyz left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With this the type of Wrapping is now different for RadioItem vs RadioGroup - inconsistency is bad.
I think you'll need a different approach to updating (typically a render retains a reference to the type it renders, perhaps that works here?

Comment thread widget/radio_item.go Outdated
@andydotxyz andydotxyz removed the after-release For when an ongoing release is finished. label Jul 16, 2026

@andydotxyz andydotxyz left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a couple of comments inline.

However the big issue here is what you see in all the test changes - the widget is no longer the same size. Moving text -> RichText does make sizing changes but they need to be handled internally. I suspect your usage of InlineIconSize are trying to approximate, but it looks wrong.

Comment thread widget/radio_group_extended_test.go Outdated
test.WithTestTheme(t, func() {
render.Refresh()
customTextSize = render.label.TextSize
customTextSize = render.label.Theme()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I meant more literally - it makes no sense to have a fyne.Theme that is called customTextSize.

Comment thread widget/radio_group_extended_test.go Outdated
test.WithTestTheme(t, func() {
render.Refresh()
customTextSize = render.label.TextSize
customTextSize = render.label.Theme()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you want to check the text size output for a widget you can use WidgetRenderer(...) to get the renderer and then call Objects() on that to get the canvas.Text.

Comment thread widget/radio_item.go
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

Successfully merging this pull request may close these issues.

Add support for Wrapping for RadioGroup option strings

3 participants