Files
AynaLivePlayer/gui/component/split.go

167 lines
4.2 KiB
Go

package component
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget"
)
type FixedSplit struct {
widget.BaseWidget
Offset float64
Horizontal bool
SeparatorThickness float32
Leading fyne.CanvasObject
Trailing fyne.CanvasObject
}
func NewFixedHSplitContainer(leading, trailing fyne.CanvasObject, offset float64) *FixedSplit {
return NewFixedSplitContainer(leading, trailing, true, offset)
}
func NewFixedVSplitContainer(top, bottom fyne.CanvasObject, offset float64) *FixedSplit {
return NewFixedSplitContainer(top, bottom, false, offset)
}
func NewFixedSplitContainer(leading, trailing fyne.CanvasObject, horizontal bool, offset float64) *FixedSplit {
s := &FixedSplit{
Offset: offset, // Sensible default, can be overridden with SetOffset
SeparatorThickness: theme.SeparatorThicknessSize(),
Horizontal: horizontal,
Leading: leading,
Trailing: trailing,
}
s.BaseWidget.ExtendBaseWidget(s)
return s
}
func (s *FixedSplit) CreateRenderer() fyne.WidgetRenderer {
s.BaseWidget.ExtendBaseWidget(s)
d := widget.NewSeparator()
return &fixedSplitContainerRenderer{
split: s,
divider: d,
objects: []fyne.CanvasObject{s.Leading, d, s.Trailing},
}
}
func (s *FixedSplit) SetOffset(offset float64) {
if s.Offset == offset {
return
}
s.Offset = offset
s.Refresh()
}
func (s *FixedSplit) SetSepThickness(thickness float32) {
if s.SeparatorThickness == thickness {
return
}
s.SeparatorThickness = thickness
s.Refresh()
}
type fixedSplitContainerRenderer struct {
split *FixedSplit
divider *widget.Separator
objects []fyne.CanvasObject
}
func (r *fixedSplitContainerRenderer) Destroy() {
}
func (r *fixedSplitContainerRenderer) Layout(size fyne.Size) {
var dividerPos, leadingPos, trailingPos fyne.Position
var dividerSize, leadingSize, trailingSize fyne.Size
if r.split.Horizontal {
lw, tw := r.computeSplitLengths(size.Width, r.split.Leading.MinSize().Width, r.split.Trailing.MinSize().Width)
leadingPos.X = 0
leadingSize.Width = lw
leadingSize.Height = size.Height
dividerPos.X = lw
dividerSize.Width = r.split.SeparatorThickness
dividerSize.Height = size.Height
trailingPos.X = lw + dividerSize.Width
trailingSize.Width = tw
trailingSize.Height = size.Height
} else {
lh, th := r.computeSplitLengths(size.Height, r.split.Leading.MinSize().Height, r.split.Trailing.MinSize().Height)
leadingPos.Y = 0
leadingSize.Width = size.Width
leadingSize.Height = lh
dividerPos.Y = lh
dividerSize.Width = size.Width
dividerSize.Height = r.split.SeparatorThickness
trailingPos.Y = lh + dividerSize.Height
trailingSize.Width = size.Width
trailingSize.Height = th
}
r.divider.Move(dividerPos)
r.divider.Resize(dividerSize)
r.split.Leading.Move(leadingPos)
r.split.Leading.Resize(leadingSize)
r.split.Trailing.Move(trailingPos)
r.split.Trailing.Resize(trailingSize)
canvas.Refresh(r.divider)
canvas.Refresh(r.split.Leading)
canvas.Refresh(r.split.Trailing)
}
func (r *fixedSplitContainerRenderer) MinSize() fyne.Size {
s := fyne.NewSize(0, 0)
for _, o := range r.objects {
min := o.MinSize()
if r.split.Horizontal {
s.Width += min.Width
s.Height = fyne.Max(s.Height, min.Height)
} else {
s.Width = fyne.Max(s.Width, min.Width)
s.Height += min.Height
}
}
return s
}
func (r *fixedSplitContainerRenderer) Objects() []fyne.CanvasObject {
return r.objects
}
func (r *fixedSplitContainerRenderer) Refresh() {
r.objects[0] = r.split.Leading
// [1] is divider which doesn't change
r.objects[2] = r.split.Trailing
r.Layout(r.split.Size())
canvas.Refresh(r.split)
}
func (r *fixedSplitContainerRenderer) computeSplitLengths(total, lMin, tMin float32) (float32, float32) {
available := float64(total - r.split.SeparatorThickness)
if available <= 0 {
return 0, 0
}
ld := float64(lMin)
tr := float64(tMin)
offset := r.split.Offset
min := ld / available
max := 1 - tr/available
if min <= max {
if offset < min {
offset = min
}
if offset > max {
offset = max
}
} else {
offset = ld / (ld + tr)
}
ld = offset * available
tr = available - ld
return float32(ld), float32(tr)
}