From 596e32161041eb3b4b064942a0be5cb728a3793a Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Wed, 17 Jun 2020 11:47:14 +0200 Subject: [PATCH] all: make unit.Converter concrete and rename to Metric An interface for scaling dp and sp is overkill, at least for all current uses. Make it a concrete struct type, and rename it to the shorter and more precise Metric. Signed-off-by: Elias Naur --- app/internal/window/os_android.go | 6 ++--- app/internal/window/os_ios.go | 6 ++--- app/internal/window/os_js.go | 13 ++++----- app/internal/window/os_macos.go | 11 ++++---- app/internal/window/os_wayland.go | 15 ++++++----- app/internal/window/os_windows.go | 11 ++++---- app/internal/window/os_x11.go | 7 ++--- app/internal/window/window.go | 24 ----------------- gesture/gesture.go | 2 +- internal/fling/animation.go | 2 +- io/system/system.go | 9 ++----- layout/context.go | 13 +++------ layout/list.go | 2 +- unit/unit.go | 44 ++++++++++++++++++++++++++----- widget/editor.go | 6 ++--- 15 files changed, 86 insertions(+), 85 deletions(-) diff --git a/app/internal/window/os_android.go b/app/internal/window/os_android.go index fcce9d98..347c8785 100644 --- a/app/internal/window/os_android.go +++ b/app/internal/window/os_android.go @@ -396,9 +396,9 @@ func (w *window) draw(sync bool) { Y: int(height), }, Insets: w.insets, - Config: &config{ - pxPerDp: ppdp, - pxPerSp: w.fontScale * ppdp, + Metric: unit.Metric{ + PxPerDp: ppdp, + PxPerSp: w.fontScale * ppdp, }, }, Sync: sync, diff --git a/app/internal/window/os_ios.go b/app/internal/window/os_ios.go index f63c24c4..10971892 100644 --- a/app/internal/window/os_ios.go +++ b/app/internal/window/os_ios.go @@ -119,9 +119,9 @@ func (w *window) draw(sync bool) { Bottom: unit.Px(float32(params.bottom)), Left: unit.Px(float32(params.left)), }, - Config: &config{ - pxPerDp: float32(params.dpi) * inchPrDp, - pxPerSp: float32(params.sdpi) * inchPrDp, + Metric: unit.Metric{ + PxPerDp: float32(params.dpi) * inchPrDp, + PxPerSp: float32(params.sdpi) * inchPrDp, }, }, Sync: sync, diff --git a/app/internal/window/os_js.go b/app/internal/window/os_js.go index 551a645f..3f383256 100644 --- a/app/internal/window/os_js.go +++ b/app/internal/window/os_js.go @@ -15,6 +15,7 @@ import ( "gioui.org/io/key" "gioui.org/io/pointer" "gioui.org/io/system" + "gioui.org/unit" ) type window struct { @@ -407,7 +408,7 @@ func (w *window) ShowTextInput(show bool) { func (w *window) draw(sync bool) { width, height, scale, cfg := w.config() - if cfg == (config{}) || width == 0 || height == 0 { + if cfg == (unit.Metric{}) || width == 0 || height == 0 { return } w.mu.Lock() @@ -420,13 +421,13 @@ func (w *window) draw(sync bool) { X: width, Y: height, }, - Config: &cfg, + Metric: cfg, }, Sync: sync, }) } -func (w *window) config() (int, int, float32, config) { +func (w *window) config() (int, int, float32, unit.Metric) { rect := w.cnv.Call("getBoundingClientRect") width, height := rect.Get("width").Float(), rect.Get("height").Float() scale := w.window.Get("devicePixelRatio").Float() @@ -438,9 +439,9 @@ func (w *window) config() (int, int, float32, config) { w.cnv.Set("width", iw) w.cnv.Set("height", ih) } - return iw, ih, float32(scale), config{ - pxPerDp: float32(scale), - pxPerSp: float32(scale), + return iw, ih, float32(scale), unit.Metric{ + PxPerDp: float32(scale), + PxPerSp: float32(scale), } } diff --git a/app/internal/window/os_macos.go b/app/internal/window/os_macos.go index fef2acda..2378cdb0 100644 --- a/app/internal/window/os_macos.go +++ b/app/internal/window/os_macos.go @@ -17,6 +17,7 @@ import ( "gioui.org/io/key" "gioui.org/io/pointer" "gioui.org/io/system" + "gioui.org/unit" _ "gioui.org/app/internal/cocoainit" ) @@ -236,16 +237,16 @@ func (w *window) draw() { X: width, Y: height, }, - Config: &cfg, + Metric: cfg, }, Sync: true, }) } -func configFor(scale float32) config { - return config{ - pxPerDp: scale, - pxPerSp: scale, +func configFor(scale float32) unit.Metric { + return unit.Metric{ + PxPerDp: scale, + PxPerSp: scale, } } diff --git a/app/internal/window/os_wayland.go b/app/internal/window/os_wayland.go index 87209bb6..c85f177f 100644 --- a/app/internal/window/os_wayland.go +++ b/app/internal/window/os_wayland.go @@ -25,6 +25,7 @@ import ( "gioui.org/io/key" "gioui.org/io/pointer" "gioui.org/io/system" + "gioui.org/unit" syscall "golang.org/x/sys/unix" ) @@ -873,7 +874,7 @@ func (w *window) flushFling() { w.fling.yExtrapolation = fling.Extrapolation{} vel := float32(math.Sqrt(float64(estx.Velocity*estx.Velocity + esty.Velocity*esty.Velocity))) _, _, c := w.config() - if !w.fling.anim.Start(&c, time.Now(), vel) { + if !w.fling.anim.Start(c, time.Now(), vel) { return } invDist := 1 / vel @@ -1359,11 +1360,11 @@ func (w *window) updateOutputs() { } } -func (w *window) config() (int, int, config) { +func (w *window) config() (int, int, unit.Metric) { width, height := w.width*w.scale, w.height*w.scale - return width, height, config{ - pxPerDp: w.ppdp * float32(w.scale), - pxPerSp: w.ppsp * float32(w.scale), + return width, height, unit.Metric{ + PxPerDp: w.ppdp * float32(w.scale), + PxPerSp: w.ppsp * float32(w.scale), } } @@ -1377,7 +1378,7 @@ func (w *window) draw(sync bool) { return } width, height, cfg := w.config() - if cfg == (config{}) { + if cfg == (unit.Metric{}) { return } if anim && w.lastFrameCallback == nil { @@ -1392,7 +1393,7 @@ func (w *window) draw(sync bool) { X: width, Y: height, }, - Config: &cfg, + Metric: cfg, }, Sync: sync, }) diff --git a/app/internal/window/os_windows.go b/app/internal/window/os_windows.go index 41c0d079..1279a155 100644 --- a/app/internal/window/os_windows.go +++ b/app/internal/window/os_windows.go @@ -19,6 +19,7 @@ import ( syscall "golang.org/x/sys/windows" "gioui.org/app/internal/windows" + "gioui.org/unit" "gioui.org/f32" "gioui.org/io/key" @@ -377,7 +378,7 @@ func (w *window) draw(sync bool) { X: w.width, Y: w.height, }, - Config: &cfg, + Metric: cfg, }, Sync: sync, }) @@ -586,12 +587,12 @@ func convertKeyCode(code uintptr) (string, bool) { return r, true } -func configForDC() config { +func configForDC() unit.Metric { dpi := windows.GetSystemDPI() const inchPrDp = 1.0 / 96.0 ppdp := float32(dpi) * inchPrDp - return config{ - pxPerDp: ppdp, - pxPerSp: ppdp, + return unit.Metric{ + PxPerDp: ppdp, + PxPerSp: ppdp, } } diff --git a/app/internal/window/os_x11.go b/app/internal/window/os_x11.go index 89bf0646..fdf7d3a3 100644 --- a/app/internal/window/os_x11.go +++ b/app/internal/window/os_x11.go @@ -37,6 +37,7 @@ import ( "gioui.org/io/key" "gioui.org/io/pointer" "gioui.org/io/system" + "gioui.org/unit" "gioui.org/app/internal/xkb" syscall "golang.org/x/sys/unix" @@ -64,7 +65,7 @@ type x11Window struct { atom C.Atom } stage system.Stage - cfg config + cfg unit.Metric width int height int notify struct { @@ -193,7 +194,7 @@ loop: X: w.width, Y: w.height, }, - Config: &w.cfg, + Metric: w.cfg, }, Sync: syn, }) @@ -474,7 +475,7 @@ func newX11Window(gioWin Callbacks, opts *Options) error { } ppsp := x11DetectUIScale(dpy) - cfg := config{pxPerDp: ppsp, pxPerSp: ppsp} + cfg := unit.Metric{PxPerDp: ppsp, PxPerSp: ppsp} swa := C.XSetWindowAttributes{ event_mask: C.ExposureMask | C.FocusChangeMask | // update C.KeyPressMask | C.KeyReleaseMask | // keyboard diff --git a/app/internal/window/window.go b/app/internal/window/window.go index d3b30129..f4fa7eca 100644 --- a/app/internal/window/window.go +++ b/app/internal/window/window.go @@ -6,7 +6,6 @@ package window import ( "errors" - "math" "gioui.org/gpu/backend" "gioui.org/io/event" @@ -71,29 +70,6 @@ type windowAndOptions struct { opts *Options } -// config implements the system.Config interface. -type config struct { - // Device pixels per dp. - pxPerDp float32 - // Device pixels per sp. - pxPerSp float32 -} - -func (c *config) Px(v unit.Value) int { - var r float32 - switch v.U { - case unit.UnitPx: - r = v.V - case unit.UnitDp: - r = c.pxPerDp * v.V - case unit.UnitSp: - r = c.pxPerSp * v.V - default: - panic("unknown unit") - } - return int(math.Round(float64(r))) -} - func newWindowRendezvous() *windowRendezvous { wr := &windowRendezvous{ in: make(chan windowAndOptions), diff --git a/gesture/gesture.go b/gesture/gesture.go index 30d825e3..e13240b7 100644 --- a/gesture/gesture.go +++ b/gesture/gesture.go @@ -204,7 +204,7 @@ func (s *Scroll) Stop() { // Scroll detects the scrolling distance from the available events and // ongoing fling gestures. -func (s *Scroll) Scroll(cfg unit.Converter, q event.Queue, t time.Time, axis Axis) int { +func (s *Scroll) Scroll(cfg unit.Metric, q event.Queue, t time.Time, axis Axis) int { if s.axis != axis { s.axis = axis return 0 diff --git a/internal/fling/animation.go b/internal/fling/animation.go index 4a644890..bb6f8a2e 100644 --- a/internal/fling/animation.go +++ b/internal/fling/animation.go @@ -31,7 +31,7 @@ const ( // Start a fling given a starting velocity. Returns whether a // fling was started. -func (f *Animation) Start(c unit.Converter, now time.Time, velocity float32) bool { +func (f *Animation) Start(c unit.Metric, now time.Time, velocity float32) bool { min := float32(c.Px(minFlingVelocity)) v := velocity if -min <= v && v <= min { diff --git a/io/system/system.go b/io/system/system.go index 4704789e..8abac6d8 100644 --- a/io/system/system.go +++ b/io/system/system.go @@ -17,10 +17,11 @@ import ( // operations that describes what to display and how to handle // input. type FrameEvent struct { - Config Config // Now is the current animation. Use Now instead of time.Now to // synchronize animation and to avoid the time.Now call overhead. Now time.Time + // Metric converts device independent dp and sp to device pixels. + Metric unit.Metric // Size is the dimensions of the window. Size image.Point // Insets is the insets to apply. @@ -51,12 +52,6 @@ type FrameEvent struct { Queue event.Queue } -// Config defines the essential properties of -// the environment. -type Config interface { - unit.Converter -} - // DestroyEvent is the last event sent through // a window event channel. type DestroyEvent struct { diff --git a/layout/context.go b/layout/context.go index 3c5c6393..f47233b8 100644 --- a/layout/context.go +++ b/layout/context.go @@ -3,7 +3,6 @@ package layout import ( - "math" "time" "gioui.org/io/event" @@ -20,7 +19,7 @@ type Context struct { // layout. Constraints Constraints - Config system.Config + Metric unit.Metric // By convention, a nil Queue is a signal to widgets to draw themselves // in a disabled state. Queue event.Queue @@ -47,18 +46,14 @@ func NewContext(ops *op.Ops, e system.FrameEvent) Context { Ops: ops, Now: e.Now, Queue: e.Queue, - Config: e.Config, + Metric: e.Metric, Constraints: Exact(e.Size), } } -// Px maps the value to pixels. If no configuration is set, -// Px returns the rounded value of v. +// Px maps the value to pixels. func (c Context) Px(v unit.Value) int { - if c.Config == nil { - return int(math.Round(float64(v.V))) - } - return c.Config.Px(v) + return c.Metric.Px(v) } // Events returns the events available for the key. If no diff --git a/layout/list.go b/layout/list.go index 689a80ad..b2753cf5 100644 --- a/layout/list.go +++ b/layout/list.go @@ -121,7 +121,7 @@ func (l *List) Dragging() bool { } func (l *List) update() { - d := l.scroll.Scroll(l.ctx, l.ctx, l.ctx.Now, gesture.Axis(l.Axis)) + d := l.scroll.Scroll(l.ctx.Metric, l.ctx, l.ctx.Now, gesture.Axis(l.Axis)) l.scrollDelta = d l.Position.Offset += d } diff --git a/unit/unit.go b/unit/unit.go index 05220ae1..fd2245ca 100644 --- a/unit/unit.go +++ b/unit/unit.go @@ -22,7 +22,10 @@ values. */ package unit -import "fmt" +import ( + "fmt" + "math" +) // Value is a value with a unit. type Value struct { @@ -33,9 +36,13 @@ type Value struct { // Unit represents a unit for a Value. type Unit uint8 -// Converter converts Values to pixels. -type Converter interface { - Px(v Value) int +// 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 { + // PxPerDp is the device-dependent pixels per dp. + PxPerDp float32 + // PxPerSp is the device-dependent pixels per sp. + PxPerSp float32 } const ( @@ -90,7 +97,7 @@ func (u Unit) String() string { } // Add a list of Values. -func Add(c Converter, values ...Value) Value { +func Add(c Metric, values ...Value) Value { var sum Value for _, v := range values { sum, v = compatible(c, sum, v) @@ -100,7 +107,7 @@ func Add(c Converter, values ...Value) Value { } // Max returns the maximum of a list of Values. -func Max(c Converter, values ...Value) Value { +func Max(c Metric, values ...Value) Value { var max Value for _, v := range values { max, v = compatible(c, max, v) @@ -111,7 +118,30 @@ func Max(c Converter, values ...Value) Value { return max } -func compatible(c Converter, v1, v2 Value) (Value, Value) { +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 } diff --git a/widget/editor.go b/widget/editor.go index 2c1b4142..6223ebc9 100644 --- a/widget/editor.go +++ b/widget/editor.go @@ -129,7 +129,7 @@ func (e *Editor) processPointer(gtx layout.Context) { axis = gesture.Vertical smin, smax = sbounds.Min.Y, sbounds.Max.Y } - sdist := e.scroller.Scroll(gtx, gtx, gtx.Now, axis) + sdist := e.scroller.Scroll(gtx.Metric, gtx, gtx.Now, axis) var soff int if e.SingleLine { e.scrollRel(sdist, 0) @@ -143,7 +143,7 @@ func (e *Editor) processPointer(gtx layout.Context) { case evt.Type == gesture.TypePress && evt.Source == pointer.Mouse, evt.Type == gesture.TypeClick && evt.Source == pointer.Touch: e.blinkStart = gtx.Now - e.moveCoord(gtx, image.Point{ + e.moveCoord(gtx.Metric, image.Point{ X: int(math.Round(float64(evt.Position.X))), Y: int(math.Round(float64(evt.Position.Y))), }) @@ -426,7 +426,7 @@ func (e *Editor) scrollAbs(x, y int) { } } -func (e *Editor) moveCoord(c unit.Converter, pos image.Point) { +func (e *Editor) moveCoord(c unit.Metric, pos image.Point) { var ( prevDesc fixed.Int26_6 carLine int