From 3d374913420204ff764171e21a25cb910fccccb1 Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Mon, 25 Apr 2022 10:08:01 +0200 Subject: [PATCH] all: [API] replace unit.Value with separate unit.Dp, unit.Sp types The unit.Value is a struct and thus more inconvenient to use than its underlying float32 type. In addition, most uses don't need a general value, but rather a specific unit given by the context. This change replaces unit.Value with two float32 units, Dp and Sp. It also changes variables and parameters of unit.Value to a specific unit type matching the context. That is, unit.Dp everywhere except for text sizes which are in Sp. Switching to typed float32s has multiple advantages - They can be constants: const touchSlop = unit.Dp(16) - Casting untyped constants is no longer necessary: insets := layout.UniformInset(16) - Calculation with values is natural: func (s ScrollbarStyle) Width() unit.Dp { return s.Indicator.MinorWidth + s.Track.MinorPadding + s.Track.MinorPadding } The main API change is that calls to gtx.Px must be replaced with either gtx.Dp or gtx.Sp depending on the unit. Idea by Christophe Meessen. Signed-off-by: Elias Naur --- app/ime_test.go | 4 +- app/os_android.go | 18 ++-- app/os_ios.go | 18 ++-- app/os_js.go | 5 +- app/window.go | 44 +++++----- gesture/gesture.go | 8 +- internal/fling/animation.go | 13 ++- io/system/system.go | 3 +- layout/context.go | 19 +++-- layout/doc.go | 2 +- layout/example_test.go | 3 +- layout/layout.go | 18 ++-- unit/unit.go | 132 ++++-------------------------- widget/border.go | 8 +- widget/decorations.go | 3 +- widget/editor.go | 6 +- widget/editor_test.go | 24 +++--- widget/icon.go | 4 +- widget/image.go | 2 +- widget/label.go | 4 +- widget/material/button.go | 26 +++--- widget/material/checkable.go | 12 +-- widget/material/checkbox.go | 5 +- widget/material/decorations.go | 28 +++---- widget/material/editor.go | 2 +- widget/material/label.go | 26 +++--- widget/material/list.go | 32 ++++---- widget/material/list_test.go | 4 +- widget/material/loader.go | 3 +- widget/material/progressbar.go | 6 +- widget/material/progresscircle.go | 3 +- widget/material/radiobutton.go | 5 +- widget/material/slider.go | 8 +- widget/material/switch.go | 13 ++- widget/material/theme.go | 8 +- 35 files changed, 212 insertions(+), 307 deletions(-) diff --git a/app/ime_test.go b/app/ime_test.go index ac763f7f..814e7b2a 100644 --- a/app/ime_test.go +++ b/app/ime_test.go @@ -35,7 +35,7 @@ func FuzzIME(f *testing.F) { var r router.Router gtx := layout.Context{Ops: new(op.Ops), Queue: &r} // Layout once to register focus. - e.Layout(gtx, cache, text.Font{}, unit.Px(10), nil) + e.Layout(gtx, cache, text.Font{}, unit.Sp(10), nil) r.Frame(gtx.Ops) var state editorState @@ -103,7 +103,7 @@ func FuzzIME(f *testing.F) { } } cmds = cmds[cmdLen:] - e.Layout(gtx, cache, text.Font{}, unit.Px(10), nil) + e.Layout(gtx, cache, text.Font{}, unit.Sp(10), nil) r.Frame(gtx.Ops) newState := r.EditorState() // We don't track caret position. diff --git a/app/os_android.go b/app/os_android.go index 58422a07..163927eb 100644 --- a/app/os_android.go +++ b/app/os_android.go @@ -154,7 +154,7 @@ type window struct { dpi int fontScale float32 - insets system.Insets + insets image.Rectangle stage system.Stage started bool @@ -586,12 +586,7 @@ func Java_org_gioui_GioView_onFocusChange(env *C.JNIEnv, class C.jclass, view C. //export Java_org_gioui_GioView_onWindowInsets func Java_org_gioui_GioView_onWindowInsets(env *C.JNIEnv, class C.jclass, view C.jlong, top, right, bottom, left C.jint) { w := cgo.Handle(view).Value().(*window) - w.insets = system.Insets{ - Top: unit.Px(float32(top)), - Bottom: unit.Px(float32(bottom)), - Left: unit.Px(float32(left)), - Right: unit.Px(float32(right)), - } + w.insets = image.Rect(int(left), int(top), int(right), int(bottom)) if w.stage >= system.StageRunning { w.draw(env, true) } @@ -830,11 +825,18 @@ func (w *window) draw(env *C.JNIEnv, sync bool) { } const inchPrDp = 1.0 / 160 ppdp := float32(w.dpi) * inchPrDp + dppp := unit.Dp(1.0 / ppdp) + insets := system.Insets{ + Top: unit.Dp(w.insets.Min.Y) * dppp, + Bottom: unit.Dp(w.insets.Max.Y) * dppp, + Left: unit.Dp(w.insets.Min.X) * dppp, + Right: unit.Dp(w.insets.Max.X) * dppp, + } w.callbacks.Event(frameEvent{ FrameEvent: system.FrameEvent{ Now: time.Now(), Size: w.config.Size, - Insets: w.insets, + Insets: insets, Metric: unit.Metric{ PxPerDp: ppdp, PxPerSp: w.fontScale * ppdp, diff --git a/app/os_ios.go b/app/os_ios.go index ad7124d0..c381dc1c 100644 --- a/app/os_ios.go +++ b/app/os_ios.go @@ -150,6 +150,11 @@ func (w *window) draw(sync bool) { w.w.Event(system.StageEvent{Stage: system.StageRunning}) } const inchPrDp = 1.0 / 163 + m := unit.Metric{ + PxPerDp: float32(params.dpi) * inchPrDp, + PxPerSp: float32(params.sdpi) * inchPrDp, + } + dppp := unit.Dp(1. / m.PxPerDp) w.w.Event(frameEvent{ FrameEvent: system.FrameEvent{ Now: time.Now(), @@ -158,15 +163,12 @@ func (w *window) draw(sync bool) { Y: int(params.height + .5), }, Insets: system.Insets{ - Top: unit.Px(float32(params.top)), - Bottom: unit.Px(float32(params.bottom)), - Left: unit.Px(float32(params.left)), - Right: unit.Px(float32(params.right)), - }, - Metric: unit.Metric{ - PxPerDp: float32(params.dpi) * inchPrDp, - PxPerSp: float32(params.sdpi) * inchPrDp, + Top: unit.Dp(params.top) * dppp, + Bottom: unit.Dp(params.bottom) * dppp, + Left: unit.Dp(params.left) * dppp, + Right: unit.Dp(params.right) * dppp, }, + Metric: m, }, Sync: sync, }) diff --git a/app/os_js.go b/app/os_js.go index 5d65c3ae..23e68ff9 100644 --- a/app/os_js.go +++ b/app/os_js.go @@ -643,10 +643,11 @@ func (w *window) draw(sync bool) { } func (w *window) getConfig() (image.Point, system.Insets, unit.Metric) { + invscale := unit.Dp(1. / w.scale) return image.Pt(w.config.Size.X, w.config.Size.Y), system.Insets{ - Bottom: unit.Px(w.inset.Y), - Right: unit.Px(w.inset.X), + Bottom: unit.Dp(w.inset.Y) * invscale, + Right: unit.Dp(w.inset.X) * invscale, }, unit.Metric{ PxPerDp: w.scale, PxPerSp: w.scale, diff --git a/app/window.go b/app/window.go index 7c349203..62c3d0ba 100644 --- a/app/window.go +++ b/app/window.go @@ -138,7 +138,7 @@ var ackEvent event.Event // iOS, Android, WebAssembly. func NewWindow(options ...Option) *Window { defaultOptions := []Option{ - Size(unit.Dp(800), unit.Dp(600)), + Size(800, 600), Title("Gio"), } options = append(defaultOptions, options...) @@ -546,8 +546,8 @@ func (w *Window) moveFocus(dir router.FocusDirection, d driver) { default: return } - const scrollABit = 50 - dist := v.Mul(w.metric.Px(unit.Dp(scrollABit))) + const scrollABit = unit.Dp(50) + dist := v.Mul(int(w.metric.Dp(scrollABit))) w.queue.q.ScrollFocus(dist) } w.setNextFrame(time.Time{}) @@ -805,12 +805,12 @@ func (w *Window) processEvent(d driver, e event.Event) bool { wrapper.Reset() viewport := image.Rectangle{ Min: image.Point{ - X: e2.Metric.Px(e2.Insets.Left), - Y: e2.Metric.Px(e2.Insets.Top), + X: e2.Metric.Dp(e2.Insets.Left), + Y: e2.Metric.Dp(e2.Insets.Top), }, Max: image.Point{ - X: e2.Size.X - e2.Metric.Px(e2.Insets.Right), - Y: e2.Size.Y - e2.Metric.Px(e2.Insets.Bottom), + X: e2.Size.X - e2.Metric.Dp(e2.Insets.Right), + Y: e2.Size.Y - e2.Metric.Dp(e2.Insets.Bottom), }, } // Scroll to focus if viewport is shrinking in any dimension. @@ -1034,50 +1034,50 @@ func Title(t string) Option { } // Size sets the size of the window. The mode will be changed to Windowed. -func Size(w, h unit.Value) Option { - if w.V <= 0 { +func Size(w, h unit.Dp) Option { + if w <= 0 { panic("width must be larger than or equal to 0") } - if h.V <= 0 { + if h <= 0 { panic("height must be larger than or equal to 0") } return func(m unit.Metric, cnf *Config) { cnf.Mode = Windowed cnf.Size = image.Point{ - X: m.Px(w), - Y: m.Px(h), + X: m.Dp(w), + Y: m.Dp(h), } } } // MaxSize sets the maximum size of the window. -func MaxSize(w, h unit.Value) Option { - if w.V <= 0 { +func MaxSize(w, h unit.Dp) Option { + if w <= 0 { panic("width must be larger than or equal to 0") } - if h.V <= 0 { + if h <= 0 { panic("height must be larger than or equal to 0") } return func(m unit.Metric, cnf *Config) { cnf.MaxSize = image.Point{ - X: m.Px(w), - Y: m.Px(h), + X: m.Dp(w), + Y: m.Dp(h), } } } // MinSize sets the minimum size of the window. -func MinSize(w, h unit.Value) Option { - if w.V <= 0 { +func MinSize(w, h unit.Dp) Option { + if w <= 0 { panic("width must be larger than or equal to 0") } - if h.V <= 0 { + if h <= 0 { panic("height must be larger than or equal to 0") } return func(m unit.Metric, cnf *Config) { cnf.MinSize = image.Point{ - X: m.Px(w), - Y: m.Px(h), + X: m.Dp(w), + Y: m.Dp(h), } } } diff --git a/gesture/gesture.go b/gesture/gesture.go index af4aecf8..95d64171 100644 --- a/gesture/gesture.go +++ b/gesture/gesture.go @@ -157,7 +157,7 @@ const ( StateFlinging ) -var touchSlop = unit.Dp(3) +const touchSlop = unit.Dp(3) // Add the handler to the operation list to receive click events. func (c *Click) Add(ops *op.Ops) { @@ -303,7 +303,7 @@ func (s *Scroll) Scroll(cfg unit.Metric, q event.Queue, t time.Time, axis Axis) break } fling := s.estimator.Estimate() - if slop, d := float32(cfg.Px(touchSlop)), fling.Distance; d < -slop || d > slop { + if slop, d := float32(cfg.Dp(touchSlop)), fling.Distance; d < -slop || d > slop { s.flinger.Start(cfg, t, fling.Velocity) } fallthrough @@ -329,7 +329,7 @@ func (s *Scroll) Scroll(cfg unit.Metric, q event.Queue, t time.Time, axis Axis) v := int(math.Round(float64(val))) dist := s.last - v if e.Priority < pointer.Grabbed { - slop := cfg.Px(touchSlop) + slop := cfg.Dp(touchSlop) if dist := dist; dist >= slop || -slop >= dist { s.grab = true } @@ -407,7 +407,7 @@ func (d *Drag) Events(cfg unit.Metric, q event.Queue, axis Axis) []pointer.Event } if e.Priority < pointer.Grabbed { diff := e.Position.Sub(d.start) - slop := cfg.Px(touchSlop) + slop := cfg.Dp(touchSlop) if diff.X*diff.X+diff.Y*diff.Y > float32(slop*slop) { d.grab = true } diff --git a/internal/fling/animation.go b/internal/fling/animation.go index bb6f8a2e..ac152ffc 100644 --- a/internal/fling/animation.go +++ b/internal/fling/animation.go @@ -19,25 +19,22 @@ type Animation struct { v0 float32 } -var ( - // Pixels/second. - minFlingVelocity = unit.Dp(50) - maxFlingVelocity = unit.Dp(8000) -) - const ( + // dp/second. + minFlingVelocity = unit.Dp(50) + maxFlingVelocity = unit.Dp(8000) thresholdVelocity = 1 ) // Start a fling given a starting velocity. Returns whether a // fling was started. func (f *Animation) Start(c unit.Metric, now time.Time, velocity float32) bool { - min := float32(c.Px(minFlingVelocity)) + min := float32(c.Dp(minFlingVelocity)) v := velocity if -min <= v && v <= min { return false } - max := float32(c.Px(maxFlingVelocity)) + max := float32(c.Dp(maxFlingVelocity)) if v > max { v = max } else if v < -max { diff --git a/io/system/system.go b/io/system/system.go index 150bcd11..49b9c4a3 100644 --- a/io/system/system.go +++ b/io/system/system.go @@ -45,7 +45,8 @@ type DestroyEvent struct { // system decoration such as translucent // system bars and software keyboards. type Insets struct { - Top, Bottom, Left, Right unit.Value + // Values are in pixels. + Top, Bottom, Left, Right unit.Dp } // A StageEvent is generated whenever the stage of a diff --git a/layout/context.go b/layout/context.go index f06e1cb0..3a1dbc22 100644 --- a/layout/context.go +++ b/layout/context.go @@ -52,15 +52,15 @@ func NewContext(ops *op.Ops, e system.FrameEvent) Context { size := e.Size if e.Insets != (system.Insets{}) { - left := e.Metric.Px(e.Insets.Left) - top := e.Metric.Px(e.Insets.Top) + left := e.Metric.Dp(e.Insets.Left) + top := e.Metric.Dp(e.Insets.Top) op.Offset(image.Point{ X: left, Y: top, }).Add(ops) - size.X -= left + e.Metric.Px(e.Insets.Right) - size.Y -= top + e.Metric.Px(e.Insets.Bottom) + size.X -= left + e.Metric.Dp(e.Insets.Right) + size.Y -= top + e.Metric.Dp(e.Insets.Bottom) } return Context{ @@ -72,9 +72,14 @@ func NewContext(ops *op.Ops, e system.FrameEvent) Context { } } -// Px maps the value to pixels. -func (c Context) Px(v unit.Value) int { - return c.Metric.Px(v) +// Dp converts v to pixels. +func (c Context) Dp(v unit.Dp) int { + return c.Metric.Dp(v) +} + +// Sp converts v to pixels. +func (c Context) Sp(v unit.Sp) int { + return c.Metric.Sp(v) } // Events returns the events available for the key. If no diff --git a/layout/doc.go b/layout/doc.go index 38240848..1eb7f1cb 100644 --- a/layout/doc.go +++ b/layout/doc.go @@ -16,7 +16,7 @@ For example, to add space above a widget: var gtx layout.Context // Configure a top inset. - inset := layout.Inset{Top: unit.Dp(8), ...} + inset := layout.Inset{Top: 8, ...} // Use the inset to lay out a widget. inset.Layout(gtx, func() { // Lay out widget and determine its size given the constraints diff --git a/layout/example_test.go b/layout/example_test.go index 7e782368..e2f4a2f7 100644 --- a/layout/example_test.go +++ b/layout/example_test.go @@ -6,7 +6,6 @@ import ( "gioui.org/layout" "gioui.org/op" - "gioui.org/unit" ) func ExampleInset() { @@ -19,7 +18,7 @@ func ExampleInset() { } // Inset all edges by 10. - inset := layout.UniformInset(unit.Dp(10)) + inset := layout.UniformInset(10) dims := inset.Layout(gtx, func(gtx layout.Context) layout.Dimensions { // Lay out a 50x50 sized widget. dims := layoutWidget(gtx, 50, 50) diff --git a/layout/layout.go b/layout/layout.go index 79ed367c..7f873406 100644 --- a/layout/layout.go +++ b/layout/layout.go @@ -113,15 +113,15 @@ func (c Constraints) Constrain(size image.Point) image.Point { // constraints. The minimum constraints will be adjusted to ensure // they do not exceed the maximum. type Inset struct { - Top, Bottom, Left, Right unit.Value + Top, Bottom, Left, Right unit.Dp } // Layout a widget. func (in Inset) Layout(gtx Context, w Widget) Dimensions { - top := gtx.Px(in.Top) - right := gtx.Px(in.Right) - bottom := gtx.Px(in.Bottom) - left := gtx.Px(in.Left) + top := gtx.Dp(in.Top) + right := gtx.Dp(in.Right) + bottom := gtx.Dp(in.Bottom) + left := gtx.Dp(in.Left) mcs := gtx.Constraints mcs.Max.X -= left + right if mcs.Max.X < 0 { @@ -153,7 +153,7 @@ func (in Inset) Layout(gtx Context, w Widget) Dimensions { // UniformInset returns an Inset with a single inset applied to all // edges. -func UniformInset(v unit.Value) Inset { +func UniformInset(v unit.Dp) Inset { return Inset{Top: v, Right: v, Bottom: v, Left: v} } @@ -213,14 +213,14 @@ func (d Direction) Position(widget, bounds image.Point) image.Point { // Spacer adds space between widgets. type Spacer struct { - Width, Height unit.Value + Width, Height unit.Dp } func (s Spacer) Layout(gtx Context) Dimensions { return Dimensions{ Size: image.Point{ - X: gtx.Px(s.Width), - Y: gtx.Px(s.Height), + X: gtx.Dp(s.Width), + Y: gtx.Dp(s.Height), }, } } diff --git a/unit/unit.go b/unit/unit.go index fd2245ca..5e678225 100644 --- a/unit/unit.go +++ b/unit/unit.go @@ -2,9 +2,7 @@ /* -Package unit implements device independent units and values. - -A Value is a value with a Unit attached. +Package unit implements device independent units. Device independent pixel, or dp, is the unit for sizes independent of the underlying display device. @@ -23,19 +21,9 @@ values. package unit import ( - "fmt" "math" ) -// Value is a value with a unit. -type Value struct { - V float32 - U Unit -} - -// Unit represents a unit for a Value. -type Unit uint8 - // Metric converts Values to device-dependent pixels, px. The zero // value represents a 1-to-1 scale from dp, sp to pixels. type Metric struct { @@ -45,113 +33,29 @@ type Metric struct { PxPerSp float32 } -const ( - // UnitPx represent device pixels in the resolution of - // the underlying display. - UnitPx Unit = iota - // UnitDp represents device independent pixels. 1 dp will +type ( + // Dp represents device independent pixels. 1 dp will // have the same apparent size across platforms and // display resolutions. - UnitDp - // UnitSp is like UnitDp but for font sizes. - UnitSp + Dp float32 + // Sp is like UnitDp but for font sizes. + Sp float32 ) -// Px returns the Value for v device pixels. -func Px(v float32) Value { - return Value{V: v, U: UnitPx} -} - -// Dp returns the Value for v device independent -// pixels. -func Dp(v float32) Value { - return Value{V: v, U: UnitDp} -} - -// Sp returns the Value for v scaled dps. -func Sp(v float32) Value { - return Value{V: v, U: UnitSp} -} - -// Scale returns the value scaled by s. -func (v Value) Scale(s float32) Value { - v.V *= s - return v -} - -func (v Value) String() string { - return fmt.Sprintf("%g%s", v.V, v.U) -} - -func (u Unit) String() string { - switch u { - case UnitPx: - return "px" - case UnitDp: - return "dp" - case UnitSp: - return "sp" - default: - panic("unknown unit") +// Dp converts v to pixels, rounded to the nearest integer value. +func (c Metric) Dp(v Dp) int { + s := c.PxPerDp + if s == 0. { + s = 1. } + return int(math.Round(float64(s) * float64(v))) } -// Add a list of Values. -func Add(c Metric, values ...Value) Value { - var sum Value - for _, v := range values { - sum, v = compatible(c, sum, v) - sum.V += v.V +// Sp converts v to pixels, rounded to the nearest integer value. +func (c Metric) Sp(v Sp) int { + s := c.PxPerSp + if s == 0. { + s = 1. } - return sum -} - -// Max returns the maximum of a list of Values. -func Max(c Metric, values ...Value) Value { - var max Value - for _, v := range values { - max, v = compatible(c, max, v) - if v.V > max.V { - max.V = v.V - } - } - return max -} - -func (c Metric) Px(v Value) int { - var r float32 - switch v.U { - case UnitPx: - r = v.V - case UnitDp: - s := c.PxPerDp - if s == 0 { - s = 1 - } - r = s * v.V - case UnitSp: - s := c.PxPerSp - if s == 0 { - s = 1 - } - r = s * v.V - default: - panic("unknown unit") - } - return int(math.Round(float64(r))) -} - -func compatible(c Metric, v1, v2 Value) (Value, Value) { - if v1.U == v2.U { - return v1, v2 - } - if v1.V == 0 { - v1.U = v2.U - return v1, v2 - } - if v2.V == 0 { - v2.U = v1.U - return v1, v2 - } - return Px(float32(c.Px(v1))), Px(float32(c.Px(v2))) + return int(math.Round(float64(s) * float64(v))) } diff --git a/widget/border.go b/widget/border.go index e90e8dcf..3dd60ef8 100644 --- a/widget/border.go +++ b/widget/border.go @@ -15,16 +15,16 @@ import ( // Border lays out a widget and draws a border inside it. type Border struct { Color color.NRGBA - CornerRadius unit.Value - Width unit.Value + CornerRadius unit.Dp + Width unit.Dp } func (b Border) Layout(gtx layout.Context, w layout.Widget) layout.Dimensions { dims := w(gtx) sz := dims.Size - rr := gtx.Px(b.CornerRadius) - width := gtx.Px(b.Width) + rr := gtx.Dp(b.CornerRadius) + width := gtx.Dp(b.Width) sz.X -= width sz.Y -= width diff --git a/widget/decorations.go b/widget/decorations.go index 2a6efd96..b20a2bff 100644 --- a/widget/decorations.go +++ b/widget/decorations.go @@ -10,7 +10,6 @@ import ( "gioui.org/io/system" "gioui.org/layout" "gioui.org/op/clip" - "gioui.org/unit" ) // Decorations handles the states of window decorations. @@ -67,7 +66,7 @@ func (d *Decorations) Clickable(action system.Action) *Clickable { // LayoutResize lays out the resize actions. func (d *Decorations) LayoutResize(gtx layout.Context, actions system.Action) { cs := gtx.Constraints.Max - wh := gtx.Px(unit.Dp(10)) + wh := gtx.Dp(10) s := []struct { system.Action image.Rectangle diff --git a/widget/editor.go b/widget/editor.go index 79c1247f..4bee3fa2 100644 --- a/widget/editor.go +++ b/widget/editor.go @@ -497,12 +497,12 @@ func (e *Editor) calculateViewSize(gtx layout.Context) image.Point { } // Layout lays out the editor. If content is not nil, it is laid out on top. -func (e *Editor) Layout(gtx layout.Context, sh text.Shaper, font text.Font, size unit.Value, content layout.Widget) layout.Dimensions { +func (e *Editor) Layout(gtx layout.Context, sh text.Shaper, font text.Font, size unit.Sp, content layout.Widget) layout.Dimensions { if e.locale != gtx.Locale { e.locale = gtx.Locale e.invalidate() } - textSize := fixed.I(gtx.Px(size)) + textSize := fixed.I(gtx.Sp(size)) if e.font != font || e.textSize != textSize { e.invalidate() e.font = font @@ -776,7 +776,7 @@ func (e *Editor) PaintText(gtx layout.Context) { // caretWidth returns the width occupied by the caret for the current // gtx. func (e *Editor) caretWidth(gtx layout.Context) int { - carWidth2 := gtx.Px(unit.Dp(1)) / 2 + carWidth2 := gtx.Dp(1) / 2 if carWidth2 < 1 { carWidth2 = 1 } diff --git a/widget/editor_test.go b/widget/editor_test.go index 1344ca27..66e285ef 100644 --- a/widget/editor_test.go +++ b/widget/editor_test.go @@ -47,7 +47,7 @@ func TestEditorZeroDimensions(t *testing.T) { Locale: english, } cache := text.NewCache(gofont.Collection()) - fontSize := unit.Px(10) + fontSize := unit.Sp(10) font := text.Font{} e := new(Editor) dims := e.Layout(gtx, cache, font, fontSize, nil) @@ -63,7 +63,7 @@ func TestEditorConfigurations(t *testing.T) { Locale: english, } cache := text.NewCache(gofont.Collection()) - fontSize := unit.Px(10) + fontSize := unit.Sp(10) font := text.Font{} sentence := "\n\n\n\n\n\n\n\n\n\n\n\nthe quick brown fox jumps over the lazy dog" runes := len([]rune(sentence)) @@ -103,7 +103,7 @@ func TestEditor(t *testing.T) { Locale: english, } cache := text.NewCache(gofont.Collection()) - fontSize := unit.Px(10) + fontSize := unit.Sp(10) font := text.Font{} // Regression test for bad in-cluster rune offset math. @@ -206,7 +206,7 @@ func TestEditorRTL(t *testing.T) { Locale: arabic, } cache := text.NewCache(arabicCollection) - fontSize := unit.Px(10) + fontSize := unit.Sp(10) font := text.Font{} e.SetCaret(0, 0) // shouldn't panic @@ -282,7 +282,7 @@ func TestEditorLigature(t *testing.T) { Face: face, }, }) - fontSize := unit.Px(10) + fontSize := unit.Sp(10) font := text.Font{} /* @@ -399,7 +399,7 @@ func TestEditorDimensions(t *testing.T) { Locale: english, } cache := text.NewCache(gofont.Collection()) - fontSize := unit.Px(10) + fontSize := unit.Sp(10) font := text.Font{} dims := e.Layout(gtx, cache, font, fontSize, nil) if dims.Size.X == 0 { @@ -446,7 +446,7 @@ func TestEditorCaretConsistency(t *testing.T) { Locale: english, } cache := text.NewCache(gofont.Collection()) - fontSize := unit.Px(10) + fontSize := unit.Sp(10) font := text.Font{} for _, a := range []text.Alignment{text.Start, text.Middle, text.End} { e := &Editor{ @@ -539,7 +539,7 @@ func TestEditorMoveWord(t *testing.T) { Locale: english, } cache := text.NewCache(gofont.Collection()) - fontSize := unit.Px(10) + fontSize := unit.Sp(10) font := text.Font{} e.SetText(t) e.Layout(gtx, cache, font, fontSize, nil) @@ -644,7 +644,7 @@ func TestEditorInsert(t *testing.T) { Locale: english, } cache := text.NewCache(gofont.Collection()) - fontSize := unit.Px(10) + fontSize := unit.Sp(10) font := text.Font{} e.SetText(t) e.Layout(gtx, cache, font, fontSize, nil) @@ -734,7 +734,7 @@ func TestEditorDeleteWord(t *testing.T) { Locale: english, } cache := text.NewCache(gofont.Collection()) - fontSize := unit.Px(10) + fontSize := unit.Sp(10) font := text.Font{} e.SetText(t) e.Layout(gtx, cache, font, fontSize, nil) @@ -789,7 +789,7 @@ g 2 4 6 8 g } cache := text.NewCache(gofont.Collection()) font := text.Font{} - fontSize := unit.Px(10) + fontSize := unit.Sp(10) selected := func(start, end int) string { // Layout once with no events; populate e.lines. @@ -879,7 +879,7 @@ func TestSelectMove(t *testing.T) { } cache := text.NewCache(gofont.Collection()) font := text.Font{} - fontSize := unit.Px(10) + fontSize := unit.Sp(10) // Layout once to populate e.lines and get focus. gtx.Queue = newQueue(key.FocusEvent{Focus: true}) diff --git a/widget/icon.go b/widget/icon.go index cd184396..380b8d98 100644 --- a/widget/icon.go +++ b/widget/icon.go @@ -24,7 +24,7 @@ type Icon struct { imgColor color.NRGBA } -var defaultIconSize = unit.Dp(24) +const defaultIconSize = unit.Dp(24) // NewIcon returns a new Icon from IconVG data. func NewIcon(data []byte) (*Icon, error) { @@ -39,7 +39,7 @@ func NewIcon(data []byte) (*Icon, error) { func (ic *Icon) Layout(gtx layout.Context, color color.NRGBA) layout.Dimensions { sz := gtx.Constraints.Min.X if sz == 0 { - sz = gtx.Metric.Px(defaultIconSize) + sz = gtx.Dp(defaultIconSize) } size := gtx.Constraints.Constrain(image.Pt(sz, sz)) defer clip.Rect{Max: size}.Push(gtx.Ops).Pop() diff --git a/widget/image.go b/widget/image.go index 3493a939..c30941d9 100644 --- a/widget/image.go +++ b/widget/image.go @@ -39,7 +39,7 @@ func (im Image) Layout(gtx layout.Context) layout.Dimensions { size := im.Src.Size() wf, hf := float32(size.X), float32(size.Y) - w, h := gtx.Px(unit.Dp(wf*scale)), gtx.Px(unit.Dp(hf*scale)) + w, h := gtx.Dp(unit.Dp(wf*scale)), gtx.Dp(unit.Dp(hf*scale)) dims, trans := im.Fit.scale(gtx.Constraints, im.Position, layout.Dimensions{Size: image.Pt(w, h)}) defer clip.Rect{Max: dims.Size}.Push(gtx.Ops).Pop() diff --git a/widget/label.go b/widget/label.go index 71d31b21..8d77774f 100644 --- a/widget/label.go +++ b/widget/label.go @@ -96,9 +96,9 @@ func (p1 screenPos) Less(p2 screenPos) bool { return p1.Y < p2.Y || (p1.Y == p2.Y && p1.X < p2.X) } -func (l Label) Layout(gtx layout.Context, s text.Shaper, font text.Font, size unit.Value, txt string) layout.Dimensions { +func (l Label) Layout(gtx layout.Context, s text.Shaper, font text.Font, size unit.Sp, txt string) layout.Dimensions { cs := gtx.Constraints - textSize := fixed.I(gtx.Px(size)) + textSize := fixed.I(gtx.Sp(size)) lines := s.LayoutString(font, textSize, cs.Max.X, gtx.Locale, txt) if max := l.MaxLines; max > 0 && len(lines) > max { lines = lines[:max] diff --git a/widget/material/button.go b/widget/material/button.go index b21cc1cf..bf71be9b 100644 --- a/widget/material/button.go +++ b/widget/material/button.go @@ -23,9 +23,9 @@ type ButtonStyle struct { // Color is the text color. Color color.NRGBA Font text.Font - TextSize unit.Value + TextSize unit.Sp Background color.NRGBA - CornerRadius unit.Value + CornerRadius unit.Dp Inset layout.Inset Button *widget.Clickable shaper text.Shaper @@ -33,7 +33,7 @@ type ButtonStyle struct { type ButtonLayoutStyle struct { Background color.NRGBA - CornerRadius unit.Value + CornerRadius unit.Dp Button *widget.Clickable } @@ -43,7 +43,7 @@ type IconButtonStyle struct { Color color.NRGBA Icon *widget.Icon // Size is the icon size. - Size unit.Value + Size unit.Dp Inset layout.Inset Button *widget.Clickable Description string @@ -53,12 +53,12 @@ func Button(th *Theme, button *widget.Clickable, txt string) ButtonStyle { return ButtonStyle{ Text: txt, Color: th.Palette.ContrastFg, - CornerRadius: unit.Dp(4), + CornerRadius: 4, Background: th.Palette.ContrastBg, - TextSize: th.TextSize.Scale(14.0 / 16.0), + TextSize: th.TextSize * 14.0 / 16.0, Inset: layout.Inset{ - Top: unit.Dp(10), Bottom: unit.Dp(10), - Left: unit.Dp(12), Right: unit.Dp(12), + Top: 10, Bottom: 10, + Left: 12, Right: 12, }, Button: button, shaper: th.Shaper, @@ -69,7 +69,7 @@ func ButtonLayout(th *Theme, button *widget.Clickable) ButtonLayoutStyle { return ButtonLayoutStyle{ Button: button, Background: th.Palette.ContrastBg, - CornerRadius: unit.Dp(4), + CornerRadius: 4, } } @@ -78,8 +78,8 @@ func IconButton(th *Theme, button *widget.Clickable, icon *widget.Icon, descript Background: th.Palette.ContrastBg, Color: th.Palette.ContrastFg, Icon: icon, - Size: unit.Dp(24), - Inset: layout.UniformInset(unit.Dp(12)), + Size: 24, + Inset: layout.UniformInset(12), Button: button, Description: description, } @@ -129,7 +129,7 @@ func (b ButtonLayoutStyle) Layout(gtx layout.Context, w layout.Widget) layout.Di semantic.Button.Add(gtx.Ops) return layout.Stack{Alignment: layout.Center}.Layout(gtx, layout.Expanded(func(gtx layout.Context) layout.Dimensions { - rr := gtx.Px(b.CornerRadius) + rr := gtx.Dp(b.CornerRadius) defer clip.UniformRRect(image.Rectangle{Max: gtx.Constraints.Min}, rr).Push(gtx.Ops).Pop() background := b.Background switch { @@ -178,7 +178,7 @@ func (b IconButtonStyle) Layout(gtx layout.Context) layout.Dimensions { }), layout.Stacked(func(gtx layout.Context) layout.Dimensions { return b.Inset.Layout(gtx, func(gtx layout.Context) layout.Dimensions { - size := gtx.Px(b.Size) + size := gtx.Dp(b.Size) if b.Icon != nil { gtx.Constraints.Min = image.Point{X: size} b.Icon.Layout(gtx, b.Color) diff --git a/widget/material/checkable.go b/widget/material/checkable.go index 9b597d31..6a370e3f 100644 --- a/widget/material/checkable.go +++ b/widget/material/checkable.go @@ -19,9 +19,9 @@ type checkable struct { Label string Color color.NRGBA Font text.Font - TextSize unit.Value + TextSize unit.Sp IconColor color.NRGBA - Size unit.Value + Size unit.Dp shaper text.Shaper checkedStateIcon *widget.Icon uncheckedStateIcon *widget.Icon @@ -39,7 +39,7 @@ func (c *checkable) layout(gtx layout.Context, checked, hovered bool) layout.Dim layout.Rigid(func(gtx layout.Context) layout.Dimensions { return layout.Stack{Alignment: layout.Center}.Layout(gtx, layout.Stacked(func(gtx layout.Context) layout.Dimensions { - size := gtx.Px(c.Size) * 4 / 3 + size := gtx.Dp(c.Size) * 4 / 3 dims := layout.Dimensions{ Size: image.Point{X: size, Y: size}, } @@ -55,8 +55,8 @@ func (c *checkable) layout(gtx layout.Context, checked, hovered bool) layout.Dim return dims }), layout.Stacked(func(gtx layout.Context) layout.Dimensions { - return layout.UniformInset(unit.Dp(2)).Layout(gtx, func(gtx layout.Context) layout.Dimensions { - size := gtx.Px(c.Size) + return layout.UniformInset(2).Layout(gtx, func(gtx layout.Context) layout.Dimensions { + size := gtx.Dp(c.Size) col := c.IconColor if gtx.Queue == nil { col = f32color.Disabled(col) @@ -72,7 +72,7 @@ func (c *checkable) layout(gtx layout.Context, checked, hovered bool) layout.Dim }), layout.Rigid(func(gtx layout.Context) layout.Dimensions { - return layout.UniformInset(unit.Dp(2)).Layout(gtx, func(gtx layout.Context) layout.Dimensions { + return layout.UniformInset(2).Layout(gtx, func(gtx layout.Context) layout.Dimensions { paint.ColorOp{Color: c.Color}.Add(gtx.Ops) return widget.Label{}.Layout(gtx, c.shaper, c.Font, c.TextSize, c.Label) }) diff --git a/widget/material/checkbox.go b/widget/material/checkbox.go index afd758db..920a66f0 100644 --- a/widget/material/checkbox.go +++ b/widget/material/checkbox.go @@ -5,7 +5,6 @@ package material import ( "gioui.org/io/semantic" "gioui.org/layout" - "gioui.org/unit" "gioui.org/widget" ) @@ -21,8 +20,8 @@ func CheckBox(th *Theme, checkBox *widget.Bool, label string) CheckBoxStyle { Label: label, Color: th.Palette.Fg, IconColor: th.Palette.ContrastBg, - TextSize: th.TextSize.Scale(14.0 / 16.0), - Size: unit.Dp(26), + TextSize: th.TextSize * 14.0 / 16.0, + Size: 26, shaper: th.Shaper, checkedStateIcon: th.Icon.CheckBoxChecked, uncheckedStateIcon: th.Icon.CheckBoxUnchecked, diff --git a/widget/material/decorations.go b/widget/material/decorations.go index 6fe6f86f..9e11e964 100644 --- a/widget/material/decorations.go +++ b/widget/material/decorations.go @@ -53,7 +53,7 @@ func (d *DecorationsStyle) Layout(gtx layout.Context) layout.Dimensions { func (d *DecorationsStyle) layoutDecorations(gtx layout.Context) layout.Dimensions { gtx.Constraints.Min.Y = 0 - inset := layout.UniformInset(unit.Dp(10)) + inset := layout.UniformInset(10) return layout.Flex{ Axis: layout.Horizontal, Alignment: layout.Middle, @@ -116,7 +116,7 @@ func (d *DecorationsStyle) layoutDecorations(gtx layout.Context) layout.Dimensio ) } -var ( +const ( winIconSize = unit.Dp(20) winIconMargin = unit.Dp(4) winIconStroke = unit.Dp(2) @@ -124,10 +124,10 @@ var ( // minimizeWindows draws a line icon representing the minimize action. func minimizeWindow(gtx layout.Context) layout.Dimensions { - size := gtx.Px(winIconSize) + size := gtx.Dp(winIconSize) size32 := float32(size) - margin := float32(gtx.Px(winIconMargin)) - width := float32(gtx.Px(winIconStroke)) + margin := float32(gtx.Dp(winIconMargin)) + width := float32(gtx.Dp(winIconStroke)) var p clip.Path p.Begin(gtx.Ops) p.MoveTo(f32.Point{X: margin, Y: size32 - margin}) @@ -143,9 +143,9 @@ func minimizeWindow(gtx layout.Context) layout.Dimensions { // maximizeWindow draws a rectangle representing the maximize action. func maximizeWindow(gtx layout.Context) layout.Dimensions { - size := gtx.Px(winIconSize) - margin := gtx.Px(winIconMargin) - width := gtx.Px(winIconStroke) + size := gtx.Dp(winIconSize) + margin := gtx.Dp(winIconMargin) + width := gtx.Dp(winIconStroke) r := clip.RRect{ Rect: image.Rect(margin, margin, size-margin, size-margin), } @@ -166,9 +166,9 @@ func maximizeWindow(gtx layout.Context) layout.Dimensions { // maximizedWindow draws interleaved rectangles representing the un-maximize action. func maximizedWindow(gtx layout.Context) layout.Dimensions { - size := gtx.Px(winIconSize) - margin := gtx.Px(winIconMargin) - width := gtx.Px(winIconStroke) + size := gtx.Dp(winIconSize) + margin := gtx.Dp(winIconMargin) + width := gtx.Dp(winIconStroke) r := clip.RRect{ Rect: image.Rect(margin, margin, size-2*margin, size-2*margin), } @@ -192,10 +192,10 @@ func maximizedWindow(gtx layout.Context) layout.Dimensions { // closeWindow draws a cross representing the close action. func closeWindow(gtx layout.Context) layout.Dimensions { - size := gtx.Px(winIconSize) + size := gtx.Dp(winIconSize) size32 := float32(size) - margin := float32(gtx.Px(winIconMargin)) - width := float32(gtx.Px(winIconStroke)) + margin := float32(gtx.Dp(winIconMargin)) + width := float32(gtx.Dp(winIconStroke)) var p clip.Path p.Begin(gtx.Ops) p.MoveTo(f32.Point{X: margin, Y: margin}) diff --git a/widget/material/editor.go b/widget/material/editor.go index 06df5386..d650ae2f 100644 --- a/widget/material/editor.go +++ b/widget/material/editor.go @@ -17,7 +17,7 @@ import ( type EditorStyle struct { Font text.Font - TextSize unit.Value + TextSize unit.Sp // Color is the text color. Color color.NRGBA // Hint contains the text displayed when the editor is empty. diff --git a/widget/material/label.go b/widget/material/label.go index a0ece845..587388fd 100644 --- a/widget/material/label.go +++ b/widget/material/label.go @@ -22,47 +22,47 @@ type LabelStyle struct { // MaxLines limits the number of lines. Zero means no limit. MaxLines int Text string - TextSize unit.Value + TextSize unit.Sp shaper text.Shaper } func H1(th *Theme, txt string) LabelStyle { - label := Label(th, th.TextSize.Scale(96.0/16.0), txt) + label := Label(th, th.TextSize*96.0/16.0, txt) label.Font.Weight = text.Light return label } func H2(th *Theme, txt string) LabelStyle { - label := Label(th, th.TextSize.Scale(60.0/16.0), txt) + label := Label(th, th.TextSize*60.0/16.0, txt) label.Font.Weight = text.Light return label } func H3(th *Theme, txt string) LabelStyle { - return Label(th, th.TextSize.Scale(48.0/16.0), txt) + return Label(th, th.TextSize*48.0/16.0, txt) } func H4(th *Theme, txt string) LabelStyle { - return Label(th, th.TextSize.Scale(34.0/16.0), txt) + return Label(th, th.TextSize*34.0/16.0, txt) } func H5(th *Theme, txt string) LabelStyle { - return Label(th, th.TextSize.Scale(24.0/16.0), txt) + return Label(th, th.TextSize*24.0/16.0, txt) } func H6(th *Theme, txt string) LabelStyle { - label := Label(th, th.TextSize.Scale(20.0/16.0), txt) + label := Label(th, th.TextSize*20.0/16.0, txt) label.Font.Weight = text.Medium return label } func Subtitle1(th *Theme, txt string) LabelStyle { - return Label(th, th.TextSize.Scale(16.0/16.0), txt) + return Label(th, th.TextSize*16.0/16.0, txt) } func Subtitle2(th *Theme, txt string) LabelStyle { - label := Label(th, th.TextSize.Scale(14.0/16.0), txt) + label := Label(th, th.TextSize*14.0/16.0, txt) label.Font.Weight = text.Medium return label } @@ -72,18 +72,18 @@ func Body1(th *Theme, txt string) LabelStyle { } func Body2(th *Theme, txt string) LabelStyle { - return Label(th, th.TextSize.Scale(14.0/16.0), txt) + return Label(th, th.TextSize*14.0/16.0, txt) } func Caption(th *Theme, txt string) LabelStyle { - return Label(th, th.TextSize.Scale(12.0/16.0), txt) + return Label(th, th.TextSize*12.0/16.0, txt) } func Overline(th *Theme, txt string) LabelStyle { - return Label(th, th.TextSize.Scale(10.0/16.0), txt) + return Label(th, th.TextSize*10.0/16.0, txt) } -func Label(th *Theme, size unit.Value, txt string) LabelStyle { +func Label(th *Theme, size unit.Sp, txt string) LabelStyle { return LabelStyle{ Text: txt, Color: th.Palette.Fg, diff --git a/widget/material/list.go b/widget/material/list.go index 367c63a7..81a7c984 100644 --- a/widget/material/list.go +++ b/widget/material/list.go @@ -50,7 +50,7 @@ type ScrollTrackStyle struct { // MajorPadding and MinorPadding along the major and minor axis of the // scrollbar's track. This is used to keep the scrollbar from touching // the edges of the content area. - MajorPadding, MinorPadding unit.Value + MajorPadding, MinorPadding unit.Dp // Color of the track background. Color color.NRGBA } @@ -59,16 +59,16 @@ type ScrollTrackStyle struct { type ScrollIndicatorStyle struct { // MajorMinLen is the smallest that the scroll indicator is allowed to // be along the major axis. - MajorMinLen unit.Value + MajorMinLen unit.Dp // MinorWidth is the width of the scroll indicator across the minor axis. - MinorWidth unit.Value + MinorWidth unit.Dp // Color and HoverColor are the normal and hovered colors of the scroll // indicator. Color, HoverColor color.NRGBA // CornerRadius is the corner radius of the rectangular indicator. 0 // will produce square corners. 0.5*MinorWidth will produce perfectly // round corners. - CornerRadius unit.Value + CornerRadius unit.Dp } // ScrollbarStyle configures the presentation of a scrollbar. @@ -89,13 +89,13 @@ func Scrollbar(th *Theme, state *widget.Scrollbar) ScrollbarStyle { return ScrollbarStyle{ Scrollbar: state, Track: ScrollTrackStyle{ - MajorPadding: unit.Dp(2), - MinorPadding: unit.Dp(2), + MajorPadding: 2, + MinorPadding: 2, }, Indicator: ScrollIndicatorStyle{ - MajorMinLen: unit.Dp(8), - MinorWidth: unit.Dp(6), - CornerRadius: unit.Dp(3), + MajorMinLen: 8, + MinorWidth: 6, + CornerRadius: 3, Color: lightFg, HoverColor: darkFg, }, @@ -104,8 +104,8 @@ func Scrollbar(th *Theme, state *widget.Scrollbar) ScrollbarStyle { // Width returns the minor axis width of the scrollbar in its current // configuration (taking padding for the scroll track into account). -func (s ScrollbarStyle) Width(metric unit.Metric) unit.Value { - return unit.Add(metric, s.Indicator.MinorWidth, s.Track.MinorPadding, s.Track.MinorPadding) +func (s ScrollbarStyle) Width() unit.Dp { + return s.Indicator.MinorWidth + s.Track.MinorPadding + s.Track.MinorPadding } // Layout the scrollbar. @@ -119,7 +119,7 @@ func (s ScrollbarStyle) Layout(gtx layout.Context, axis layout.Axis, viewportSta convert := axis.Convert maxMajorAxis := convert(gtx.Constraints.Max).X gtx.Constraints.Min.X = maxMajorAxis - gtx.Constraints.Min.Y = gtx.Px(s.Width(gtx.Metric)) + gtx.Constraints.Min.Y = gtx.Dp(s.Width()) gtx.Constraints.Min = convert(gtx.Constraints.Min) gtx.Constraints.Max = gtx.Constraints.Min @@ -179,15 +179,15 @@ func (s ScrollbarStyle) layout(gtx layout.Context, axis layout.Axis, viewportSta trackLen := gtx.Constraints.Min.X viewStart := int(math.Round(float64(viewportStart) * float64(trackLen))) viewEnd := int(math.Round(float64(viewportEnd) * float64(trackLen))) - indicatorLen := max(viewEnd-viewStart, gtx.Px(s.Indicator.MajorMinLen)) + indicatorLen := max(viewEnd-viewStart, gtx.Dp(s.Indicator.MajorMinLen)) if viewStart+indicatorLen > trackLen { viewStart = trackLen - indicatorLen } indicatorDims := axis.Convert(image.Point{ X: indicatorLen, - Y: gtx.Px(s.Indicator.MinorWidth), + Y: gtx.Dp(s.Indicator.MinorWidth), }) - radius := gtx.Px(s.Indicator.CornerRadius) + radius := gtx.Dp(s.Indicator.CornerRadius) // Lay out the indicator. offset := axis.Convert(image.Pt(viewStart, 0)) @@ -247,7 +247,7 @@ func (l ListStyle) Layout(gtx layout.Context, length int, w layout.ListElement) originalConstraints := gtx.Constraints // Determine how much space the scrollbar occupies. - barWidth := gtx.Px(l.Width(gtx.Metric)) + barWidth := gtx.Dp(l.Width()) if l.AnchorStrategy == Occupy { diff --git a/widget/material/list_test.go b/widget/material/list_test.go index e7c95a81..a4fd370a 100644 --- a/widget/material/list_test.go +++ b/widget/material/list_test.go @@ -38,7 +38,7 @@ func TestListAnchorStrategies(t *testing.T) { } return layout.Dimensions{Size: image.Point{ X: gtx.Constraints.Max.X, - Y: gtx.Px(unit.Dp(20)), + Y: gtx.Dp(20), }} } @@ -47,7 +47,7 @@ func TestListAnchorStrategies(t *testing.T) { elements := 100 th := material.NewTheme(gofont.Collection()) materialList := material.List(th, &list) - indicatorWidth := gtx.Px(materialList.Width(gtx.Metric)) + indicatorWidth := gtx.Dp(materialList.Width()) materialList.AnchorStrategy = material.Occupy occupyDims := materialList.Layout(gtx, elements, space) diff --git a/widget/material/loader.go b/widget/material/loader.go index 4565b32a..20f6ccde 100644 --- a/widget/material/loader.go +++ b/widget/material/loader.go @@ -13,7 +13,6 @@ import ( "gioui.org/op" "gioui.org/op/clip" "gioui.org/op/paint" - "gioui.org/unit" ) type LoaderStyle struct { @@ -32,7 +31,7 @@ func (l LoaderStyle) Layout(gtx layout.Context) layout.Dimensions { diam = minY } if diam == 0 { - diam = gtx.Px(unit.Dp(24)) + diam = gtx.Dp(24) } sz := gtx.Constraints.Constrain(image.Pt(diam, diam)) radius := sz.X / 2 diff --git a/widget/material/progressbar.go b/widget/material/progressbar.go index 28eae15c..d13978a4 100644 --- a/widget/material/progressbar.go +++ b/widget/material/progressbar.go @@ -29,10 +29,10 @@ func ProgressBar(th *Theme, progress float32) ProgressBarStyle { func (p ProgressBarStyle) Layout(gtx layout.Context) layout.Dimensions { shader := func(width int, color color.NRGBA) layout.Dimensions { - var maxHeight = unit.Dp(4) - rr := gtx.Px(unit.Dp(2)) + const maxHeight = unit.Dp(4) + rr := gtx.Dp(2) - d := image.Point{X: width, Y: gtx.Px(maxHeight)} + d := image.Point{X: width, Y: gtx.Dp(maxHeight)} defer clip.UniformRRect(image.Rectangle{Max: image.Pt(width, d.Y)}, rr).Push(gtx.Ops).Pop() paint.ColorOp{Color: color}.Add(gtx.Ops) diff --git a/widget/material/progresscircle.go b/widget/material/progresscircle.go index 083e8d89..80fdcff1 100644 --- a/widget/material/progresscircle.go +++ b/widget/material/progresscircle.go @@ -10,7 +10,6 @@ import ( "gioui.org/layout" "gioui.org/op" "gioui.org/op/paint" - "gioui.org/unit" ) type ProgressCircleStyle struct { @@ -31,7 +30,7 @@ func (p ProgressCircleStyle) Layout(gtx layout.Context) layout.Dimensions { diam = minY } if diam == 0 { - diam = gtx.Px(unit.Dp(24)) + diam = gtx.Dp(24) } sz := gtx.Constraints.Constrain(image.Pt(diam, diam)) radius := sz.X / 2 diff --git a/widget/material/radiobutton.go b/widget/material/radiobutton.go index 5292bfd3..5d2692ef 100644 --- a/widget/material/radiobutton.go +++ b/widget/material/radiobutton.go @@ -5,7 +5,6 @@ package material import ( "gioui.org/io/semantic" "gioui.org/layout" - "gioui.org/unit" "gioui.org/widget" ) @@ -25,8 +24,8 @@ func RadioButton(th *Theme, group *widget.Enum, key, label string) RadioButtonSt Color: th.Palette.Fg, IconColor: th.Palette.ContrastBg, - TextSize: th.TextSize.Scale(14.0 / 16.0), - Size: unit.Dp(26), + TextSize: th.TextSize * 14.0 / 16.0, + Size: 26, shaper: th.Shaper, checkedStateIcon: th.Icon.RadioChecked, uncheckedStateIcon: th.Icon.RadioUnchecked, diff --git a/widget/material/slider.go b/widget/material/slider.go index fd48a087..9c02be90 100644 --- a/widget/material/slider.go +++ b/widget/material/slider.go @@ -31,19 +31,19 @@ type SliderStyle struct { Color color.NRGBA Float *widget.Float - FingerSize unit.Value + FingerSize unit.Dp } func (s SliderStyle) Layout(gtx layout.Context) layout.Dimensions { - thumbRadius := gtx.Px(unit.Dp(6)) - trackWidth := gtx.Px(unit.Dp(2)) + thumbRadius := gtx.Dp(6) + trackWidth := gtx.Dp(2) axis := s.Float.Axis // Keep a minimum length so that the track is always visible. minLength := thumbRadius + 3*thumbRadius + thumbRadius // Try to expand to finger size, but only if the constraints // allow for it. - touchSizePx := min(gtx.Px(s.FingerSize), axis.Convert(gtx.Constraints.Max).Y) + touchSizePx := min(gtx.Dp(s.FingerSize), axis.Convert(gtx.Constraints.Max).Y) sizeMain := max(axis.Convert(gtx.Constraints.Min).X, minLength) sizeCross := max(2*thumbRadius, touchSizePx) size := axis.Convert(image.Pt(sizeMain, sizeCross)) diff --git a/widget/material/switch.go b/widget/material/switch.go index 024ddd15..62472242 100644 --- a/widget/material/switch.go +++ b/widget/material/switch.go @@ -12,7 +12,6 @@ import ( "gioui.org/op" "gioui.org/op/clip" "gioui.org/op/paint" - "gioui.org/unit" "gioui.org/widget" ) @@ -40,9 +39,9 @@ func Switch(th *Theme, swtch *widget.Bool, description string) SwitchStyle { // Layout updates the switch and displays it. func (s SwitchStyle) Layout(gtx layout.Context) layout.Dimensions { - trackWidth := gtx.Px(unit.Dp(36)) - trackHeight := gtx.Px(unit.Dp(16)) - thumbSize := gtx.Px(unit.Dp(20)) + trackWidth := gtx.Dp(36) + trackHeight := gtx.Dp(16) + thumbSize := gtx.Dp(20) trackOff := (thumbSize - trackHeight) / 2 // Draw track. @@ -67,7 +66,7 @@ func (s SwitchStyle) Layout(gtx layout.Context) layout.Dimensions { t.Pop() // Draw thumb ink. - inkSize := gtx.Px(unit.Dp(44)) + inkSize := gtx.Dp(44) rr := inkSize / 2 inkOff := image.Point{ X: trackWidth/2 - rr, @@ -107,13 +106,13 @@ func (s SwitchStyle) Layout(gtx layout.Context) layout.Dimensions { // Draw thumb shadow, a translucent disc slightly larger than the // thumb itself. // Center shadow horizontally and slightly adjust its Y. - paint.FillShape(gtx.Ops, argb(0x55000000), circle(thumbRadius, thumbRadius+gtx.Px(unit.Dp(.25)), thumbRadius+1)) + paint.FillShape(gtx.Ops, argb(0x55000000), circle(thumbRadius, thumbRadius+gtx.Dp(.25), thumbRadius+1)) // Draw thumb. paint.FillShape(gtx.Ops, col, circle(thumbRadius, thumbRadius, thumbRadius)) // Set up click area. - clickSize := gtx.Px(unit.Dp(40)) + clickSize := gtx.Dp(40) clickOff := image.Point{ X: (thumbSize - clickSize) / 2, Y: (trackHeight-clickSize)/2 + trackOff, diff --git a/widget/material/theme.go b/widget/material/theme.go index 5b3e6278..65135275 100644 --- a/widget/material/theme.go +++ b/widget/material/theme.go @@ -34,7 +34,7 @@ type Palette struct { type Theme struct { Shaper text.Shaper Palette - TextSize unit.Value + TextSize unit.Sp Icon struct { CheckBoxChecked *widget.Icon CheckBoxUnchecked *widget.Icon @@ -43,7 +43,7 @@ type Theme struct { } // FingerSize is the minimum touch target size. - FingerSize unit.Value + FingerSize unit.Dp } func NewTheme(fontCollection []text.FontFace) *Theme { @@ -56,7 +56,7 @@ func NewTheme(fontCollection []text.FontFace) *Theme { ContrastBg: rgb(0x3f51b5), ContrastFg: rgb(0xffffff), } - t.TextSize = unit.Sp(16) + t.TextSize = 16 t.Icon.CheckBoxChecked = mustIcon(widget.NewIcon(icons.ToggleCheckBox)) t.Icon.CheckBoxUnchecked = mustIcon(widget.NewIcon(icons.ToggleCheckBoxOutlineBlank)) @@ -64,7 +64,7 @@ func NewTheme(fontCollection []text.FontFace) *Theme { t.Icon.RadioUnchecked = mustIcon(widget.NewIcon(icons.ToggleRadioButtonUnchecked)) // 38dp is on the lower end of possible finger size. - t.FingerSize = unit.Dp(38) + t.FingerSize = 38 return t }