Choices: review r2 fixes

This commit is contained in:
ZacharyZhang-NY committed 2026-10-05 13:31:15 -04:00
1 parent 332d38b9d8
commit 40a37dfd92
10 files changed
+300 -54

No files matched your search

+71 -38
View File
@@ -40,9 +40,10 @@ const (
sliderMarkH float32 = 18
)
// sliderGeom maps values to x positions across a slider's box.
// sliderGeom maps values to x positions across a slider's box; grid holds the step points.
type sliderGeom struct {
lo, hi, step float64
grid numberInputSpec
trackY float32
}
@@ -51,23 +52,28 @@ func (g sliderGeom) x(r ui.Rect, v float64) float32 {
return r.X + sliderThumb/2 + (r.W-sliderThumb)*max(0, min(1, f))
}
// snap rounds v to the nearest step inside the range.
// snap moves v to the nearest step point inside the range.
func (g sliderGeom) snap(v float64) float64 {
v = max(g.lo, min(g.hi, v))
if g.step <= 0 {
return v
}
v = g.lo + math.Round((v-g.lo)/g.step)*g.step
if v > g.hi {
v -= g.step
}
return math.Round(v*1e9) / 1e9
return g.grid.stepBy(v, 0)
}
// sliderKey is the last key released on a slider, and a move waiting for it.
// move goes n steps from v, 1% of the range each when continuous, staying in range.
func (g sliderGeom) move(v float64, n int) float64 {
if g.step <= 0 {
return max(g.lo, min(g.hi, v+float64(n)*(g.hi-g.lo)/100))
}
return g.grid.stepBy(v, n)
}
// sliderKey is the last key released on a slider, a move waiting for it, and whether its press moved.
type sliderKey struct {
up ui.Key
pending int
acted bool
}
type sliderKeyID struct{}
@@ -85,46 +91,69 @@ func sliderControl(c *ui.Context, v float64, g sliderGeom, from, to float64) (s
ks.up = ev.Key
return true
})
up, dir := ks.up, ks.pending
up, pending, acted := ks.up, ks.pending, ks.acted
ks.up, ks.pending = 0, 0
if up != 0 {
ks.acted = false
}
if _, _, dragged = s.Dragged(); dragged {
return s, max(from, min(to, g.snap(raw))), true
}
unsure := dir != 0
dir, jump, known := 0, false, true
switch {
case raw < v:
dir, unsure = -1, false
case raw > v:
dir, unsure = 1, false
case raw != v:
// MyGo moved the copy 1% (an arrow) or to an end (Home, End), rounded to 1e-9 (ui/widgets.go:375).
dir = 1
if raw < v {
dir = -1
}
end := g.lo
if dir > 0 {
end = g.hi
}
arrow := max(g.lo, min(g.hi, v+float64(dir)*(g.hi-g.lo)/100))
jump = math.Abs(raw-end) < math.Abs(raw-arrow)
if math.Abs(arrow-end) <= 1e-9+math.Abs(end)*1e-12 {
// Near an end an arrow and Home/End agree: the released key tells which it was.
dir, jump, known = sliderKeyMove(up, dir)
}
if up == 0 {
ks.acted = true
}
case pending != 0:
dir, jump, known = sliderKeyMove(up, pending)
case up != 0 && !acted:
// A step finer than MyGo's rounding leaves the copy still: act on the release.
dir, jump, known = sliderKeyMove(up, 0)
}
if dir == 0 {
if !known {
ks.pending = dir
return s, v, false
}
end, limit := g.lo, from
if dir > 0 {
end, limit = g.hi, to
switch {
case dir == 0:
return s, v, false
case jump && dir < 0:
return s, g.snap(from), false
case jump:
return s, g.snap(to), false
}
jump := raw == end
// An arrow within 1% of an end lands on it too: the released key tells which it was.
if unsure || jump && math.Abs(v-end) <= (g.hi-g.lo)/100*(1+1e-9) {
switch up {
case ui.KeyHome, ui.KeyEnd:
jump = true
case ui.KeyLeft, ui.KeyRight, ui.KeyUp, ui.KeyDown:
jump = false
default:
ks.pending = dir
return s, v, false
}
return s, max(from, min(to, g.move(v, dir))), false
}
// sliderKeyMove reads a released key as direction and jump; an unknown key keeps dir, unresolved.
func sliderKeyMove(up ui.Key, dir int) (int, bool, bool) {
switch up {
case ui.KeyLeft, ui.KeyDown:
return -1, false, true
case ui.KeyRight, ui.KeyUp:
return 1, false, true
case ui.KeyHome:
return -1, true, true
case ui.KeyEnd:
return 1, true, true
}
if jump {
return s, limit, false
}
step := g.step
if step <= 0 {
step = (g.hi - g.lo) / 100
}
return s, max(from, min(to, g.snap(v+float64(dir)*step))), false
return dir, false, dir == 0
}
func sliderSetup(min, max, step float64, marks []SliderMark, showValue bool, c *ui.Context) (sliderGeom, float32) {
@@ -135,6 +164,10 @@ func sliderSetup(min, max, step float64, marks []SliderMark, showValue bool, c *
panic("mujica: slider needs Min < Max and Step >= 0")
}
g := sliderGeom{lo: min, hi: max, step: step}
if step > 0 {
// NumberInput's grid: exact bounds and integer step indexes at the decimals Min and Step need.
g.grid = numberInputResolve(NumberInputOptions{Min: min, Max: max, Step: step, Precision: sliderDecimals(min, step)})
}
h := Density(c).ControlHeight()
g.trackY = h / 2
if showValue {