Skip to content

Commit b7d29e4

Browse files
authored
Merge pull request #1675 from cogentcore/markdown
update gomarkdown version to fix dependabot, add Flip option to Slider
2 parents 575e856 + a045d0b commit b7d29e4

39 files changed

Lines changed: 154 additions & 88 deletions

core/scroll.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ func (fr *Frame) positionScroll(d math32.Dims) {
168168
}
169169
sb.SetState(false, states.Invisible)
170170
sb.Max = maxSize
171-
sb.setVisiblePercent(visPct)
171+
sb.SetVisiblePercent(visPct)
172172
// fmt.Println(ly, d, "vis pct:", asz/csz)
173173
sb.SetValue(sb.Value) // keep in range
174174
fr.This.(Layouter).SetScrollParams(d, sb)

core/slider.go

Lines changed: 73 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ import (
2626

2727
// Slider is a slideable widget that provides slider functionality with a draggable
2828
// thumb and a clickable track. The [styles.Style.Direction] determines the direction
29-
// in which the slider slides.
29+
// in which the slider slides: Row = left-to-right, Column = top-to-bottom (use Flip
30+
// to invert these directions).
3031
type Slider struct {
3132
Frame
3233

@@ -60,6 +61,10 @@ type Slider struct {
6061
// It defaults to 0.2, and will be at least as big as [Slider.Step].
6162
PageStep float32
6263

64+
// Flip inverts the direction that the slider slides: if true, then
65+
// Row = right-to-left and Column = bottom-to-top.
66+
Flip bool
67+
6368
// Icon is an optional icon to use for the dragging thumb.
6469
Icon icons.Icon
6570

@@ -106,7 +111,7 @@ type Slider struct {
106111

107112
// Computed values below:
108113

109-
// logical position of the slider relative to Size
114+
// logical position of the slider in dots (pixels), relative to Size
110115
pos float32
111116

112117
// previous Change event emitted value; don't re-emit Change if it is the same
@@ -216,20 +221,18 @@ func (sr *Slider) Init() {
216221
sr.slideStartPos = sr.pos
217222
})
218223
sr.On(events.SlideMove, func(e events.Event) {
219-
del := e.StartDelta()
220-
if sr.Styles.Direction == styles.Row {
221-
sr.setSliderPosEvent(sr.slideStartPos + float32(del.X))
222-
} else {
223-
sr.setSliderPosEvent(sr.slideStartPos + float32(del.Y))
224+
del := math32.FromPoint(e.StartDelta()).Dim(sr.Styles.Direction.Dim())
225+
if sr.Flip {
226+
del = -del
224227
}
228+
sr.setSliderPosEvent(sr.slideStartPos + del)
225229
})
226230
sr.On(events.SlideStop, func(e events.Event) {
227-
del := e.StartDelta()
228-
if sr.Styles.Direction == styles.Row {
229-
sr.setSliderPosEvent(sr.slideStartPos + float32(del.X))
230-
} else {
231-
sr.setSliderPosEvent(sr.slideStartPos + float32(del.Y))
231+
del := math32.FromPoint(e.StartDelta()).Dim(sr.Styles.Direction.Dim())
232+
if sr.Flip {
233+
del = -del
232234
}
235+
sr.setSliderPosEvent(sr.slideStartPos + del)
233236
sr.sendChange()
234237
})
235238
sr.On(events.Click, func(e events.Event) {
@@ -262,36 +265,47 @@ func (sr *Slider) Init() {
262265
if DebugSettings.KeyEventTrace {
263266
slog.Info("SliderBase KeyInput", "widget", sr, "keyFunction", kf)
264267
}
268+
step := sr.Step
269+
if sr.PageStep < sr.Step {
270+
sr.PageStep = 2 * sr.Step
271+
}
272+
pageStep := sr.PageStep
273+
if sr.Flip {
274+
step = -step
275+
pageStep = -pageStep
276+
}
265277
switch kf {
266278
case keymap.MoveUp:
267-
sr.setValueEvent(sr.Value - sr.Step)
279+
sr.setValueEvent(sr.Value - step)
268280
e.SetHandled()
269281
case keymap.MoveLeft:
270-
sr.setValueEvent(sr.Value - sr.Step)
282+
sr.setValueEvent(sr.Value - step)
271283
e.SetHandled()
272284
case keymap.MoveDown:
273-
sr.setValueEvent(sr.Value + sr.Step)
285+
sr.setValueEvent(sr.Value + step)
274286
e.SetHandled()
275287
case keymap.MoveRight:
276-
sr.setValueEvent(sr.Value + sr.Step)
288+
sr.setValueEvent(sr.Value + step)
277289
e.SetHandled()
278290
case keymap.PageUp:
279-
if sr.PageStep < sr.Step {
280-
sr.PageStep = 2 * sr.Step
281-
}
282-
sr.setValueEvent(sr.Value - sr.PageStep)
291+
sr.setValueEvent(sr.Value - pageStep)
283292
e.SetHandled()
284293
case keymap.PageDown:
285-
if sr.PageStep < sr.Step {
286-
sr.PageStep = 2 * sr.Step
287-
}
288-
sr.setValueEvent(sr.Value + sr.PageStep)
294+
sr.setValueEvent(sr.Value + pageStep)
289295
e.SetHandled()
290296
case keymap.Home:
291-
sr.setValueEvent(sr.Min)
297+
if sr.Flip {
298+
sr.setValueEvent(sr.Max)
299+
} else {
300+
sr.setValueEvent(sr.Min)
301+
}
292302
e.SetHandled()
293303
case keymap.End:
294-
sr.setValueEvent(sr.Max)
304+
if sr.Flip {
305+
sr.setValueEvent(sr.Min)
306+
} else {
307+
sr.setValueEvent(sr.Max)
308+
}
295309
e.SetHandled()
296310
}
297311
})
@@ -386,15 +400,13 @@ func (sr *Slider) setSliderPos(pos float32) {
386400
if sz <= 0 {
387401
return
388402
}
389-
390403
thsz := sr.slideThumbSize()
391404
thszh := .5 * thsz
392405
sr.pos = math32.Clamp(pos, thszh, sz-thszh)
393406
prel := (sr.pos - thszh) / (sz - thsz)
394407
effmax := sr.effectiveMax()
395408
val := math32.Truncate(sr.Min+prel*(effmax-sr.Min), sr.Precision)
396409
val = math32.Clamp(val, sr.Min, effmax)
397-
// fmt.Println(pos, thsz, prel, val)
398410
sr.Value = val
399411
sr.snapValue()
400412
sr.setPosFromValue(sr.Value) // go back the other way to be fully consistent
@@ -433,7 +445,7 @@ func (sr *Slider) setPosFromValue(val float32) {
433445
}
434446

435447
// setVisiblePercent sets the [Slider.visiblePercent] value for a [SliderScrollbar].
436-
func (sr *Slider) setVisiblePercent(val float32) *Slider {
448+
func (sr *Slider) SetVisiblePercent(val float32) *Slider {
437449
sr.visiblePercent = math32.Clamp(val, 0, 1)
438450
return sr
439451
}
@@ -480,8 +492,14 @@ func (sr *Slider) WidgetTooltip(pos image.Point) (string, image.Point) {
480492
// pointToRelPos translates a point in scene local pixel coords into relative
481493
// position within the slider content range
482494
func (sr *Slider) pointToRelPos(pt image.Point) float32 {
483-
ptf := math32.FromPoint(pt).Dim(sr.Styles.Direction.Dim())
484-
return ptf - sr.Geom.Pos.Content.Dim(sr.Styles.Direction.Dim())
495+
dim := sr.Styles.Direction.Dim()
496+
ptf := math32.FromPoint(pt).Dim(dim)
497+
pos := sr.Geom.Pos.Content.Dim(dim)
498+
sz := sr.Geom.Size.Actual.Content.Dim(dim)
499+
if sr.Flip {
500+
return (pos + sz) - ptf
501+
}
502+
return ptf - pos
485503
}
486504

487505
// scrollScale returns scaled value of scroll delta
@@ -508,14 +526,17 @@ func (sr *Slider) Render() {
508526
if sr.ValueColor != nil {
509527
thsz := sr.slideThumbSize()
510528
osz := sr.thumbSizeDots().Dim(od)
529+
origsz := sz.Dim(od)
511530
tpos := pos
512-
tpos = tpos.AddDim(dim, sr.pos)
513-
tpos = tpos.SubDim(dim, thsz*.5)
531+
tpos = tpos.AddDim(od, 0.5*(osz-origsz))
514532
tsz := sz
515533
tsz.SetDim(dim, thsz)
516-
origsz := sz.Dim(od)
517534
tsz.SetDim(od, osz)
518-
tpos = tpos.AddDim(od, 0.5*(osz-origsz))
535+
if sr.Flip {
536+
tpos.SetDim(dim, (pos.Dim(dim)+sz.Dim(dim)-sr.pos)-thsz*.5)
537+
} else {
538+
tpos = tpos.AddDim(dim, sr.pos-thsz*.5)
539+
}
519540
vabg := sr.Styles.ComputeActualBackgroundFor(sr.ValueColor, pabg)
520541
pc.Fill.Color = vabg
521542
sr.RenderBoxGeom(tpos, tsz, styles.Border{Radius: st.Border.Radius}) // thumb
@@ -537,22 +558,30 @@ func (sr *Slider) Render() {
537558
bsz := sz
538559
bsz.SetDim(od, trsz)
539560
bpos := pos
540-
bpos = bpos.AddDim(od, .5*(sz.Dim(od)-trsz))
561+
thsz := sr.thumbSizeDots()
562+
tpos := pos
563+
564+
if sr.Flip {
565+
tpos.SetDim(dim, pos.Dim(dim)+sz.Dim(dim)-sr.pos)
566+
} else {
567+
tpos.SetDim(dim, pos.Dim(dim)+sr.pos)
568+
}
569+
tpos = tpos.AddDim(od, 0.5*sz.Dim(od)) // ctr
570+
bpos = bpos.AddDim(od, 0.5*(sz.Dim(od)-trsz))
541571
pc.Fill.Color = st.ActualBackground
542572
sr.RenderBoxGeom(bpos, bsz, styles.Border{Radius: st.Border.Radius}) // track
543573

544574
if sr.ValueColor != nil {
545-
bsz.SetDim(dim, sr.pos)
546575
vabg := sr.Styles.ComputeActualBackgroundFor(sr.ValueColor, pabg)
547576
pc.Fill.Color = vabg
548-
sr.RenderBoxGeom(bpos, bsz, styles.Border{Radius: st.Border.Radius})
577+
bsz.SetDim(dim, sr.pos)
578+
if sr.Flip {
579+
tp := tpos.SubDim(od, 0.5*trsz)
580+
sr.RenderBoxGeom(tp, bsz, styles.Border{Radius: st.Border.Radius})
581+
} else {
582+
sr.RenderBoxGeom(bpos, bsz, styles.Border{Radius: st.Border.Radius})
583+
}
549584
}
550-
551-
thsz := sr.thumbSizeDots()
552-
tpos := pos
553-
tpos.SetDim(dim, pos.Dim(dim)+sr.pos)
554-
tpos = tpos.AddDim(od, 0.5*sz.Dim(od)) // ctr
555-
556585
// render thumb as icon or box
557586
if sr.Icon.IsSet() && sr.HasChildren() {
558587
ic := sr.Child(0).(*Icon)

core/typegen.go

Lines changed: 24 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/content/body.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Categories = ["Widgets"]
33
+++
44

5-
A **body** is a [[frame]] that contains the main [[app]] content. It is contained within a [[scene]], which is the root node of a window or dialog.
5+
A **body** is a [[frame]] that contains the main [[app]] content ([[doc:core.Body]]). It is contained within a [[scene]], which is the root node of a window or dialog.
66

77
The `b` widget in these docs examples represents the body that you typically add widgets to:
88

docs/content/button.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Categories = ["Widgets"]
33
+++
44

5-
A **button** is a [[widget]] that a user can click on to trigger an action. See [[func button]] for a button [[bind|bound]] to a function.
5+
A **button** is a [[widget]] that a user can click on to trigger an action ([[doc:core.Button]]). See [[func button]] for a button [[bind|bound]] to a function.
66

77
## Properties
88

docs/content/canvas.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Categories = ["Widgets"]
33
+++
44

5-
A **canvas** is a [[widget]] that allows you to manually render anything. All canvas coordinates are on a normalized 0-1 scale.
5+
A **canvas** is a [[widget]] that allows you to manually render anything ([[doc:core.Canvas]]). All canvas coordinates are on a normalized 0-1 scale.
66

77
If you want to render SVG files, use an [[SVG]] widget instead. For images, use an [[image]] widget. For videos, use a [[video]] widget. For HTML, see [[HTML]].
88

docs/content/chooser.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Categories = ["Widgets"]
33
+++
44

5-
A **chooser** is [[widget]] that allow users to choose one option among a list of items.
5+
A **chooser** is [[widget]] that allow users to choose one option among a list of items ([[doc:core.Chooser]]).
66

77
## Properties
88

docs/content/collapser.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Categories = ["Widgets"]
33
+++
44

5-
A **collapser** is a [[widget]] that can be collapsed or expanded by a user. It contains a summary part which is always visible, and a details part which is only visible when the collapser is expanded. Collapsers are similar to HTML's `&lt;details&gt;` and `&lt;summary&gt;` tags.
5+
A **collapser** is a [[widget]] that can be collapsed or expanded by a user ([[doc:core.Collapser]]). It contains a summary part which is always visible, and a details part which is only visible when the collapser is expanded. Collapsers are similar to HTML's `&lt;details&gt;` and `&lt;summary&gt;` tags.
66

77
You can make a collapser:
88

docs/content/date-picker.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Categories = ["Widgets"]
33
+++
44

5-
A **date picker** is a [[widget]] that allows users to select a year, month, and day.
5+
A **date picker** is a [[widget]] that allows users to select a year, month, and day ([[doc:core.DatePicker]]).
66

77
Also see a [[time picker]] that allows users to select an hour and minute, a unified [[time picker#time input]] that allows users to select both a date and time using [[text field]]s and [[dialog]]s, and a [[time picker#duration input]].
88

docs/content/dialog.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Categories = ["Widgets"]
33
+++
44

5-
A **dialog** is a type of [[stage]] that displays content on top of the surrounding window.
5+
A **dialog** is a type of [[stage]] that displays content on top of the surrounding window ([[doc:core.Dialog]]).
66

77
## Simple
88

0 commit comments

Comments
 (0)