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

Render of widgets implementing layout.SpacerObject look bad #4731

Open
2 tasks done
chran554 opened this issue Mar 22, 2024 · 5 comments
Open
2 tasks done

Render of widgets implementing layout.SpacerObject look bad #4731

chran554 opened this issue Mar 22, 2024 · 5 comments
Labels
unverified A bug that has been reported but not verified

Comments

@chran554
Copy link

chran554 commented Mar 22, 2024

Checklist

  • I have searched the issue tracker for open issues that relate to the same problem, before opening a new one.
  • This issue only relates to a single bug. I will open new issues for any other problems.

Describe the bug

Widgets implementing the layout.SpacerObject interface seem to be rendered badly.

Documentation for the interface state "any object" can be used for spacing.

// SpacerObject is any object that can be used to space out child objects
type SpacerObject interface {
	ExpandVertical() bool
	ExpandHorizontal() bool
}

(In my case I wanted an expanding button on each side of a label i a Horizontal box. It was "increase zoom" and "decrease zoom" around a "current zoom" label.)

How to reproduce

Make a widget implement the layout.SpacerObject interface and insert into Vertical or Horizontal box.

(In the code example below and in the the screen shot there is no "tapping"-events at all on the buttons on the empty areas to left and right of the "middle" button.)

Screenshots

image image image

Example code

package main

import (
	"fmt"
	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/app"
	"fyne.io/fyne/v2/container"
	"fyne.io/fyne/v2/widget"
)

type SpacingButton struct {
	widget.Button
}

type SpacingLabel struct {
	widget.Label
}

func NewSpacingLabel(text string) *SpacingLabel {
	label := &SpacingLabel{}
	label.Text = text

	label.ExtendBaseWidget(label)
	return label
}

func (sb *SpacingLabel) ExpandVertical() bool {
	return false
}

func (sb *SpacingLabel) ExpandHorizontal() bool {
	return true
}

func NewSpacingButton(label string, tapped func()) *SpacingButton {
	button := &SpacingButton{}
	button.Text = label
	button.OnTapped = tapped

	button.ExtendBaseWidget(button)
	return button
}

func (sb *SpacingButton) ExpandVertical() bool {
	return false
}

func (sb *SpacingButton) ExpandHorizontal() bool {
	return true
}

func main() {
	application := app.New()
	window := application.NewWindow("Spacing button")
	window.Resize(fyne.NewSize(200, 50))

	c := container.NewHBox(
		NewSpacingButton("left", func() { fmt.Println("tapped left") }),
		widget.NewButton("middle", nil),
		NewSpacingButton("right", func() { fmt.Println("tapped right") }),
	)

	window.SetContent(c)
	window.ShowAndRun()
}

Fyne version

fyne cli version: v2.4.4

Go compiler version

go version go1.22.1 darwin/arm64

Operating system and version

macOS Sonoma Version 14.2.1 (23C71)

Additional Information

No response

@chran554 chran554 added the unverified A bug that has been reported but not verified label Mar 22, 2024
@andydotxyz
Copy link
Member

The objects you are building are not spacers though... (spacers are the blank area between elements packed into a box).
You should not use HBox if you want items to expand in width - it is designed to compress widgets to their smallest width.

@andydotxyz
Copy link
Member

andydotxyz commented Mar 22, 2024

Hmm, it would seem that the layout code is treating spacers as data structures and ignoring whether or not they are widgets...

Screenshot 2024-03-22 at 15 38 39

It was never intended that a full widget would be used as a "spacer" but I suppose the API does allow it so we should fix this up.

func main() {
	a := app.New()
	w := a.NewWindow("Hello")

	w.SetContent(container.NewHBox(
		layout.NewSpacer(),
		widget.NewLabel("Middle"),
		layout.NewSpacer(),
	))

	w.ShowAndRun()
}

@chran554
Copy link
Author

It was never intended that a full widget would be used as a "spacer" but I suppose the API does allow it so we should fix this up.

I think that could be a brilliant addition to the layout functionality for VBox and HBox.

FYI: I've been using ordinary spacer with VBox and HBox, but I tried out the interface on buttons for the first time as I needed expanding buttons on each side of a label, and there is no layout that provide that behaviour.

@chran554
Copy link
Author

chran554 commented Mar 22, 2024

Quick idea:

In addition to let all widgets, the standard fyne or your own, implement layout.SpacerObject you could also provide a wrapper container(?) for a widget. The wrapper implement layout.SpacerObject and your widget would fully expand within that wrapper.

Something like a function layout.NewSpacerObject(fyne.CanvasObject):

leftButton := widget.NewButton("I am greedy, nil)

w.SetContent(container.NewHBox(
	layout.NewSpacerObject(leftButton),
	widget.NewLabel("Middle"),
	layout.NewSpacer(),
))

@andydotxyz
Copy link
Member

Quick idea:

In addition to let all widgets, the standard fyne or your own, implement layout.SpacerObject you could also provide a wrapper container(?) for a widget. The wrapper implement layout.SpacerObject and your widget would fully expand within that wrapper.

Something like a function layout.NewSpacerObject(fyne.CanvasObject):

leftButton := widget.NewButton("I am greedy, nil)

w.SetContent(container.NewHBox(
	layout.NewSpacerObject(leftButton),
	widget.NewLabel("Middle"),
	layout.NewSpacer(),
))

I see how that could feel like a nice shorthand but it actually goes against how the standard layouts and constructors work. There are wrappers in the fyne-x repo where the design principles are less strict - it could probably be added there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
unverified A bug that has been reported but not verified
Projects
None yet
Development

No branches or pull requests

2 participants