widget: move scrollbar indicator if dragging starts outside of it

Signed-off-by: Dominik Honnef <dominik@honnef.co>
This commit is contained in:
Dominik Honnef
2022-06-30 01:21:05 +02:00
committed by Elias Naur
parent f229601e2d
commit 6981a88720
+29 -13
View File
@@ -87,21 +87,37 @@ func (s *Scrollbar) Layout(gtx layout.Context, axis layout.Axis, viewportStart,
if !s.dragging { if !s.dragging {
s.dragging = true s.dragging = true
s.oldDragPos = normalizedDragOffset s.oldDragPos = normalizedDragOffset
}
s.delta += normalizedDragOffset - s.oldDragPos
if viewportStart+s.delta < 0 { if normalizedDragOffset < viewportStart || normalizedDragOffset > viewportEnd {
// Adjust normalizedDragOffset - and thus the future s.oldDragPos - so that futile dragging up has to be // The user started dragging somewhere on the track that isn't covered by the indicator. Consider this a
// countered with dragging down again. Otherwise, dragging up would have no effect, but dragging down would // click in addition to a drag and jump to the clicked point.
// immediately start scrolling. We want the user to undo their ineffective drag first. //
normalizedDragOffset -= viewportStart + s.delta // TODO(dh): this isn't perfect. We only get the pointer.Drag event once the user has actually dragged,
// Limit s.delta to the maximum amount scrollable // which means that if the user presses the mouse button and neither releases it nor drags it, nothing
s.delta = -viewportStart // will happen.
} else if viewportEnd+s.delta > 1 { pos := axis.Convert(image.Point{
normalizedDragOffset += (1 - viewportEnd) - s.delta X: int(event.Position.X),
s.delta = 1 - viewportEnd Y: int(event.Position.Y),
})
normalizedPos := float32(pos.X) / trackHeight
s.delta += normalizedPos - viewportStart
}
} else {
s.delta += normalizedDragOffset - s.oldDragPos
if viewportStart+s.delta < 0 {
// Adjust normalizedDragOffset - and thus the future s.oldDragPos - so that futile dragging up has to be
// countered with dragging down again. Otherwise, dragging up would have no effect, but dragging down would
// immediately start scrolling. We want the user to undo their ineffective drag first.
normalizedDragOffset -= viewportStart + s.delta
// Limit s.delta to the maximum amount scrollable
s.delta = -viewportStart
} else if viewportEnd+s.delta > 1 {
normalizedDragOffset += (1 - viewportEnd) - s.delta
s.delta = 1 - viewportEnd
}
s.oldDragPos = normalizedDragOffset
} }
s.oldDragPos = normalizedDragOffset
} }
// Process events from the indicator so that hover is // Process events from the indicator so that hover is