zntg/ui/scrollbar.go

81 lines
2.2 KiB
Go
Raw Normal View History

package ui
import (
"opslag.de/schobers/geom"
)
type Scrollbar struct {
ControlBase
Orientation Orientation
Content float32
Offset float32
handle ScrollbarHandle
startDragOffset float32
}
func BuildScrollbar(o Orientation, fn func(s *Scrollbar)) *Scrollbar {
var s = &Scrollbar{Orientation: o, Content: 0, Offset: 0}
s.handle.OnDragStart(func(_ Context, _ Control, _ geom.PointF32) {
s.startDragOffset = s.Offset
})
s.handle.OnDragMove(func(_ Context, _ Control, start, move geom.PointF32) {
var length = s.Orientation.SizeParallel(s.bounds)
var handleMaxOffset = length - s.Orientation.SizeParallel(s.handle.bounds)
var hidden = s.Content - length
var offset = (s.Orientation.LengthParallel(move) - s.Orientation.LengthParallel(start)) / handleMaxOffset
s.Offset = geom.Max32(0, geom.Min32(s.startDragOffset+offset*hidden, hidden))
})
fn(s)
return s
}
func (s *Scrollbar) Arrange(ctx Context, bounds geom.RectangleF32, offset geom.PointF32) {
s.ControlBase.Arrange(ctx, bounds, offset)
s.updateBar(ctx)
}
func (s *Scrollbar) DesiredSize(ctx Context) geom.PointF32 {
return s.Orientation.Pt(geom.NaN32(), ctx.Style().Dimensions.ScrollbarWidth)
}
func (s *Scrollbar) Handle(ctx Context, e Event) {
s.handle.Handle(ctx, e)
s.ControlBase.Handle(ctx, e)
}
func (s *Scrollbar) Render(ctx Context) {
s.handle.Render(ctx)
}
func (s *Scrollbar) updateBar(ctx Context) {
var length = s.Orientation.SizeParallel(s.bounds)
var width = ctx.Style().Dimensions.ScrollbarWidth
var handleLength = length
var handleOffset = s.Orientation.LengthParallel(s.bounds.Min)
if s.Content > length {
handleLength = geom.Max32(2*width, length/s.Content)
var hidden = s.Content - length
var offset = geom.Min32(1, s.Offset/hidden)
handleOffset = handleOffset + offset*(length-handleLength)
}
var min = s.Orientation.Pt(handleOffset, s.Orientation.LengthPerpendicular(s.bounds.Max)-width)
s.handle.Arrange(ctx, s.Orientation.Rect(min, handleLength, width), s.offset)
}
type ScrollbarHandle struct {
ControlBase
}
func (h *ScrollbarHandle) Render(ctx Context) {
h.RenderBackground(ctx)
p := ctx.Style().Palette
fill := p.Primary
if h.over {
fill = p.PrimaryHighlight
}
ctx.Renderer().FillRectangle(h.bounds.Inset(1), fill)
}