Skip to content

Support centering the *container.Scroll content on a position (when content can scroll) #5940

@Nazgand

Description

@Nazgand

Checklist

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

Is your feature request related to a problem?

I have working code to do so here, but the feature should be built into Fyne.

func PositionRelativeTo(descendant, ancestor fyne.CanvasObject) fyne.Position {
	if descendant == nil || ancestor == nil || descendant == ancestor {
		return fyne.NewPos(0, 0)
	}

	path := findPathToDescendant(ancestor, descendant)
	if len(path) == 0 {
		return fyne.NewPos(0, 0)
	}

	relPos := fyne.NewPos(0, 0)
	for _, node := range path[1:] { // Skip ancestor.
		relPos = relPos.Add(node.RelPos)
	}

	return relPos
}

func findPathToDescendant(root, target fyne.CanvasObject) []PathNode {
	if root == nil || target == nil {
		return nil
	}

	path := []PathNode{{Obj: root, RelPos: fyne.NewPos(0, 0)}}

	if root == target {
		return path
	}

	if cont, ok := root.(*fyne.Container); ok {
		for _, child := range cont.Objects {
			if childPath := findPathToDescendant(child, target); childPath != nil {
				childRelPos := child.Position()
				childPath[0].RelPos = childRelPos
				return append(path, childPath...)
			}
		}
	}

	return nil
}

type PathNode struct {
	Obj    fyne.CanvasObject
	RelPos fyne.Position
}

func CenterDescendantOfScroll(scroll *container.Scroll, descendant fyne.CanvasObject) {
	TargetOffset := PositionRelativeTo(descendant, scroll.Content)
	TargetOffset = TargetOffset.AddXY(descendant.Size().Width/2,
		descendant.Size().Height/2).SubtractXY(scroll.Size().Width/2,
		scroll.Size().Height/2)
	TargetOffset.X = max(TargetOffset.X, 0)
	TargetOffset.X = min(TargetOffset.X,
		scroll.Content.Size().Width-scroll.Size().Width)
	TargetOffset.Y = max(TargetOffset.Y, 0)
	TargetOffset.Y = min(TargetOffset.Y,
		scroll.Content.Size().Height-scroll.Size().Height)
	scroll.Offset = TargetOffset
}

Is it possible to construct a solution with the existing API?

Possible, but it should be 1 line of code.

Describe the solution you'd like to see.

With

var scroll *container.Scroll
var descendant fyne.CanvasObject

I should be able to simply call

scroll.CenterDescendant(descendant)

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions