zntg/ui/contentscrollbar.go

190 lines
4.0 KiB
Go
Raw Normal View History

2018-08-03 06:46:10 +00:00
package ui
import (
"math"
"opslag.de/schobers/galleg/allegro5"
"opslag.de/schobers/geom"
)
var _ Control = &ContentScrollbar{}
type ContentScrollbarValueChangedFn func(float64)
type ContentScrollbar struct {
ControlBase
Length float64
Value float64
Orientation Orientation
OnChanged ContentScrollbarValueChangedFn
handle *contentScrollbarHandle
}
type contentScrollbarHandle struct {
ControlBase
}
func (h *contentScrollbarHandle) Render(ctx Context) {
var c = ctx.Palette().Primary()
if h.IsOver {
if h.IsPressed {
} else {
}
}
var min = h.Bounds.Min.To32()
var max = h.Bounds.Max.To32()
allegro5.DrawFilledRectangle(min.X, min.Y, max.X, max.Y, c)
}
func (s *ContentScrollbar) Created(ctx Context, p Container) error {
s.ControlBase.Created(ctx, p)
s.handle = &contentScrollbarHandle{}
s.handle.Created(ctx, nil)
return nil
}
func (s *ContentScrollbar) Destroyed(ctx Context) {
s.handle.Destroyed(ctx)
}
func (s *ContentScrollbar) barViewRange() (float64, float64) {
var min, max float64
switch s.Orientation {
case OrientationHorizontal:
min = s.Bounds.Min.X
max = s.Bounds.Max.X
default:
min = s.Bounds.Max.Y
max = s.Bounds.Min.Y
}
var length = (max - min)
var bar = length
if s.Length > length {
bar = length * length / s.Length
}
if bar < 20 {
if length < 40 {
bar = .5 * length
} else {
bar = 20
}
}
return min + .5*bar, max - .5*bar
}
func (s *ContentScrollbar) barViewCenter() float64 {
switch s.Orientation {
case OrientationHorizontal:
return (s.Bounds.Min.Y + s.Bounds.Max.Y) * .5
default:
return (s.Bounds.Min.X + s.Bounds.Max.X) * .5
}
}
func (s *ContentScrollbar) toValue(x, y float64) float64 {
var n = y
if OrientationHorizontal == s.Orientation {
n = x
}
var min, max = s.barViewRange()
if min == max {
return 0
}
var delta = s.Length - (max - min)
var off = (n - min) / (max - min)
var v = off * (s.Length - (max - min))
if v < 0 {
v = 0
} else if v > delta {
v = delta
}
return v
}
func (s *ContentScrollbar) change(v float64) {
if v != s.Value {
s.Value = v
var onChanged = s.OnChanged
if nil != onChanged {
onChanged(v)
}
}
}
func (s *ContentScrollbar) snapTo(x, y int) {
var val = s.toValue(float64(x), float64(y))
s.change(val)
}
func (s *ContentScrollbar) increment(d int) {
// var val = s.Value + d
// if val < s.Minimum {
// val = s.Minimum
// } else if val > s.Maximum {
// val = s.Maximum
// }
// s.change(val)
}
func (s *ContentScrollbar) Handle(ctx Context, ev allegro5.Event) {
s.ControlBase.Handle(ctx, ev)
s.handle.Handle(ctx, ev)
switch e := ev.(type) {
case *allegro5.MouseMoveEvent:
if s.handle.IsPressed {
s.snapTo(e.X, e.Y)
}
if 0 != e.DeltaZ && s.IsOver {
var d = e.DeltaZ
if allegro5.IsAnyKeyDown(allegro5.KeyLShift, allegro5.KeyRShift) {
d *= 10
}
s.increment(d)
}
case *allegro5.MouseButtonDownEvent:
if !s.handle.IsPressed && s.IsOver {
s.snapTo(e.X, e.Y)
}
}
}
func (s *ContentScrollbar) DesiredSize(Context) geom.PointF {
switch s.Orientation {
case OrientationHorizontal:
return geom.PtF(math.NaN(), ScrollbarWidth)
}
return geom.PtF(ScrollbarWidth, math.NaN())
}
func (s *ContentScrollbar) SetRect(rect geom.RectangleF) {
switch s.Orientation {
case OrientationHorizontal:
if rect.Dy() > ScrollbarWidth {
rect.Min.Y = rect.Max.Y - ScrollbarWidth
}
default:
if rect.Dx() > ScrollbarWidth {
rect.Min.X = rect.Max.X - ScrollbarWidth
}
}
s.ControlBase.SetRect(rect)
// var min, max = s.barViewRange()
// var off = float64(s.Value-s.Minimum) / float64(s.Maximum-s.Minimum)
// var centerH = min + (max-min)*off
// var r = 0.5 * float64(s.handles[0].Width())
// var center = s.barViewCenter()
// switch s.Orientation {
// case OrientationHorizontal:
// s.handle.SetRect(geom.RectF(centerH-r, center-r, centerH+r, center+r))
// default:
// s.handle.SetRect(geom.RectF(center-r, centerH-r, center+r, centerH+r))
// }
}
func (s *ContentScrollbar) Render(ctx Context) {
s.handle.Render(ctx)
s.ControlBase.Render(ctx)
}