From 3784ece6dd6505d9f448b8754baa1de54c56d001 Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Mon, 30 Sep 2019 16:42:12 +0200 Subject: [PATCH] all: rename package ui to unit Package ui is now only about units except for the Config.Now method. Remove Now and rename Config to Converter. Add layout.Config to replace the old ui.Config. Signed-off-by: Elias Naur --- app/app.go | 14 +++++++------- app/doc.go | 2 +- app/os_android.go | 2 +- app/os_ios.go | 2 +- app/os_wayland.go | 3 +-- app/window.go | 12 ++++++------ cmd/gogio/js_test.go | 2 +- gesture/gesture.go | 11 ++++++----- internal/fling/animation.go | 10 +++++----- layout/doc.go | 2 +- layout/layout.go | 20 +++++++++++++++----- layout/layout_test.go | 6 +++--- layout/list.go | 2 +- op/op.go | 2 +- text/editor.go | 16 ++++++++-------- text/shape/measure.go | 12 ++++++------ ui/doc.go | 25 ------------------------- ui/ui.go | 16 ---------------- {ui => unit}/unit.go | 33 +++++++++++++++++++++++++++++---- widget/image.go | 4 ++-- 20 files changed, 95 insertions(+), 101 deletions(-) delete mode 100644 ui/doc.go delete mode 100644 ui/ui.go rename {ui => unit}/unit.go (65%) diff --git a/app/app.go b/app/app.go index c1862d6e..c660bee2 100644 --- a/app/app.go +++ b/app/app.go @@ -10,7 +10,7 @@ import ( "strings" "time" - "gioui.org/ui" + "gioui.org/unit" ) // An UpdateEvent is generated when a Window's Update @@ -39,7 +39,7 @@ type DestroyEvent struct { // system decoration such as translucent // system bars and software keyboards. type Insets struct { - Top, Bottom, Left, Right ui.Value + Top, Bottom, Left, Right unit.Value } // A StageEvent is generated whenever the stage of a @@ -146,7 +146,7 @@ func Main() { main() } -// Config implements the ui.Config interface. +// Config implements the layout.Config interface. type Config struct { // Device pixels per dp. pxPerDp float32 @@ -159,14 +159,14 @@ func (c *Config) Now() time.Time { return c.now } -func (c *Config) Px(v ui.Value) int { +func (c *Config) Px(v unit.Value) int { var r float32 switch v.U { - case ui.UnitPx: + case unit.UnitPx: r = v.V - case ui.UnitDp: + case unit.UnitDp: r = c.pxPerDp * v.V - case ui.UnitSp: + case unit.UnitSp: r = c.pxPerSp * v.V default: panic("unknown unit") diff --git a/app/doc.go b/app/doc.go index 6eb37edc..95a7b84f 100644 --- a/app/doc.go +++ b/app/doc.go @@ -18,7 +18,7 @@ contents and state. For example: - import "gioui.org/ui" + import "gioui.org/unit" w := app.NewWindow() for e := range w.Events() { diff --git a/app/os_android.go b/app/os_android.go index e4c05685..c77b9cf9 100644 --- a/app/os_android.go +++ b/app/os_android.go @@ -27,7 +27,7 @@ import ( "gioui.org/f32" "gioui.org/io/key" "gioui.org/io/pointer" - "gioui.org/ui" + "gioui.org/unit" ) type window struct { diff --git a/app/os_ios.go b/app/os_ios.go index 65f07906..65dd198e 100644 --- a/app/os_ios.go +++ b/app/os_ios.go @@ -25,7 +25,7 @@ import ( "gioui.org/f32" "gioui.org/io/key" "gioui.org/io/pointer" - "gioui.org/ui" + "gioui.org/unit" ) type window struct { diff --git a/app/os_wayland.go b/app/os_wayland.go index bf3c17ae..248c7317 100644 --- a/app/os_wayland.go +++ b/app/os_wayland.go @@ -583,8 +583,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() - c.now = time.Now() - if !w.fling.anim.Start(&c, vel) { + if !w.fling.anim.Start(&c, time.Now(), vel) { return } invDist := 1 / vel diff --git a/app/window.go b/app/window.go index 361f3b90..f0302e51 100644 --- a/app/window.go +++ b/app/window.go @@ -13,7 +13,7 @@ import ( "gioui.org/io/event" "gioui.org/io/profile" "gioui.org/op" - "gioui.org/ui" + "gioui.org/unit" ) // WindowOption configures a Window. @@ -22,7 +22,7 @@ type WindowOption struct { } type windowOptions struct { - Width, Height ui.Value + Width, Height unit.Value Title string } @@ -86,8 +86,8 @@ var ackEvent event.Event // BUG: Calling NewWindow more than once is not yet supported. func NewWindow(options ...WindowOption) *Window { opts := &windowOptions{ - Width: ui.Dp(800), - Height: ui.Dp(600), + Width: unit.Dp(800), + Height: unit.Dp(600), Title: "Gio", } @@ -339,7 +339,7 @@ func WithTitle(t string) WindowOption { } // WithWidth returns an option that sets the window width. -func WithWidth(w ui.Value) WindowOption { +func WithWidth(w unit.Value) WindowOption { if w.V <= 0 { panic("width must be larger than or equal to 0") } @@ -351,7 +351,7 @@ func WithWidth(w ui.Value) WindowOption { } // WithHeight returns an option that sets the window height. -func WithHeight(h ui.Value) WindowOption { +func WithHeight(h unit.Value) WindowOption { if h.V <= 0 { panic("height must be larger than or equal to 0") } diff --git a/cmd/gogio/js_test.go b/cmd/gogio/js_test.go index 9241891b..5a4749f7 100644 --- a/cmd/gogio/js_test.go +++ b/cmd/gogio/js_test.go @@ -15,7 +15,7 @@ import ( "github.com/chromedp/chromedp" - _ "gioui.org/ui" // the build tool adds it to go.mod, so keep it there + _ "gioui.org/unit" // the build tool adds it to go.mod, so keep it there ) func TestJSOnChrome(t *testing.T) { diff --git a/gesture/gesture.go b/gesture/gesture.go index d914ea91..9449825d 100644 --- a/gesture/gesture.go +++ b/gesture/gesture.go @@ -11,13 +11,14 @@ package gesture import ( "math" + "time" "gioui.org/f32" "gioui.org/internal/fling" "gioui.org/io/event" "gioui.org/io/pointer" "gioui.org/op" - "gioui.org/ui" + "gioui.org/unit" ) // Click detects click gestures in the form @@ -93,7 +94,7 @@ const ( StateFlinging ) -var touchSlop = ui.Dp(3) +var touchSlop = unit.Dp(3) // Add the handler to the operation list to receive click events. func (c *Click) Add(ops *op.Ops) { @@ -156,7 +157,7 @@ func (s *Scroll) Stop() { // Scroll detects the scrolling distance from the available events and // ongoing fling gestures. -func (s *Scroll) Scroll(cfg ui.Config, q event.Queue, axis Axis) int { +func (s *Scroll) Scroll(cfg unit.Converter, q event.Queue, t time.Time, axis Axis) int { if s.axis != axis { s.axis = axis return 0 @@ -185,7 +186,7 @@ func (s *Scroll) Scroll(cfg ui.Config, q event.Queue, axis Axis) int { } fling := s.estimator.Estimate() if slop, d := float32(cfg.Px(touchSlop)), fling.Distance; d < -slop || d > slop { - s.flinger.Start(cfg, fling.Velocity) + s.flinger.Start(cfg, t, fling.Velocity) } fallthrough case pointer.Cancel: @@ -221,7 +222,7 @@ func (s *Scroll) Scroll(cfg ui.Config, q event.Queue, axis Axis) int { } } } - total += s.flinger.Tick(cfg.Now()) + total += s.flinger.Tick(t) return total } diff --git a/internal/fling/animation.go b/internal/fling/animation.go index 6d9a004d..66dfb880 100644 --- a/internal/fling/animation.go +++ b/internal/fling/animation.go @@ -7,7 +7,7 @@ import ( "runtime" "time" - "gioui.org/ui" + "gioui.org/unit" ) type Animation struct { @@ -21,8 +21,8 @@ type Animation struct { var ( // Pixels/second. - minFlingVelocity = ui.Dp(50) - maxFlingVelocity = ui.Dp(8000) + minFlingVelocity = unit.Dp(50) + maxFlingVelocity = unit.Dp(8000) ) const ( @@ -31,7 +31,7 @@ const ( // Start a fling given a starting velocity. Returns whether a // fling was started. -func (f *Animation) Start(c ui.Config, velocity float32) bool { +func (f *Animation) Start(c unit.Converter, now time.Time, velocity float32) bool { min := float32(c.Px(minFlingVelocity)) v := velocity if -min <= v && v <= min { @@ -43,7 +43,7 @@ func (f *Animation) Start(c ui.Config, velocity float32) bool { } else if v < -max { v = -max } - f.init(c.Now(), v) + f.init(now, v) return true } diff --git a/layout/doc.go b/layout/doc.go index aedb1c69..12bc7c7a 100644 --- a/layout/doc.go +++ b/layout/doc.go @@ -17,7 +17,7 @@ For example, to add space above a widget: gtx.Reset(...) // Configure a top inset. - inset := layout.Inset{Top: ui.Dp(8), ...} + inset := layout.Inset{Top: unit.Dp(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/layout.go b/layout/layout.go index 7cb9715c..4f890bb8 100644 --- a/layout/layout.go +++ b/layout/layout.go @@ -4,10 +4,11 @@ package layout import ( "image" + "time" "gioui.org/io/event" "gioui.org/op" - "gioui.org/ui" + "gioui.org/unit" ) // Constraints represent a set of acceptable ranges for @@ -52,11 +53,20 @@ type Context struct { // operation. Dimensions Dimensions - ui.Config + Config event.Queue *op.Ops } +// Config define the essential properties of +// the environment. +type Config interface { + // Now returns the current animation time. + Now() time.Time + + unit.Converter +} + const ( Start Alignment = iota End @@ -93,7 +103,7 @@ func (s *Context) Layout(cs Constraints, w Widget) Dimensions { } // Reset the context. -func (c *Context) Reset(cfg ui.Config, cs Constraints) { +func (c *Context) Reset(cfg Config, cs Constraints) { c.Constraints = cs c.Dimensions = Dimensions{} c.Config = cfg @@ -129,7 +139,7 @@ func RigidConstraints(size image.Point) Constraints { // Inset adds space around a widget. type Inset struct { - Top, Right, Bottom, Left ui.Value + Top, Right, Bottom, Left unit.Value } // Align aligns a widget in the available space. @@ -171,7 +181,7 @@ func (in Inset) Layout(gtx *Context, w Widget) { // UniformInset returns an Inset with a single inset applied to all // edges. -func UniformInset(v ui.Value) Inset { +func UniformInset(v unit.Value) Inset { return Inset{Top: v, Right: v, Bottom: v, Left: v} } diff --git a/layout/layout_test.go b/layout/layout_test.go index 5c5a8dd5..0524e0d2 100644 --- a/layout/layout_test.go +++ b/layout/layout_test.go @@ -7,7 +7,7 @@ import ( "gioui.org/io/event" "gioui.org/layout" - "gioui.org/ui" + "gioui.org/unit" ) type queue struct{} @@ -26,7 +26,7 @@ func ExampleInset() { gtx.Reset(cfg, cs) // Inset all edges by 10. - inset := layout.UniformInset(ui.Dp(10)) + inset := layout.UniformInset(unit.Dp(10)) inset.Layout(gtx, func() { // Lay out a 50x50 sized widget. layoutWidget(gtx, 50, 50) @@ -146,7 +146,7 @@ func (config) Now() time.Time { return time.Now() } -func (config) Px(v ui.Value) int { +func (config) Px(v unit.Value) int { return int(v.V + .5) } diff --git a/layout/list.go b/layout/list.go index 37f03b09..7a60cfeb 100644 --- a/layout/list.go +++ b/layout/list.go @@ -110,7 +110,7 @@ func (l *List) Dragging() bool { } func (l *List) update() { - d := l.scroll.Scroll(l.ctx.Config, l.ctx.Queue, gesture.Axis(l.Axis)) + d := l.scroll.Scroll(l.ctx.Config, l.ctx.Queue, l.ctx.Now(), gesture.Axis(l.Axis)) l.scrollDelta = d l.offset += d } diff --git a/op/op.go b/op/op.go index dace4a40..de851ef1 100644 --- a/op/op.go +++ b/op/op.go @@ -15,7 +15,7 @@ to a ui/app.Window's Update method. Drawing a colored square: - import "gioui.org/ui" + import "gioui.org/unit" import "gioui.org/app" import "gioui.org/op/paint" diff --git a/text/editor.go b/text/editor.go index 59c93fc4..74448c9f 100644 --- a/text/editor.go +++ b/text/editor.go @@ -16,7 +16,7 @@ import ( "gioui.org/layout" "gioui.org/op" "gioui.org/op/paint" - "gioui.org/ui" + "gioui.org/unit" "golang.org/x/image/math/fixed" ) @@ -88,7 +88,7 @@ const ( // Event returns the next available editor event, or false if none are available. func (e *Editor) Event(gtx *layout.Context) (EditorEvent, bool) { // Crude configuration change detection. - if scale := gtx.Px(ui.Sp(100)); scale != e.oldScale { + if scale := gtx.Px(unit.Sp(100)); scale != e.oldScale { e.invalidate() e.oldScale = scale } @@ -102,7 +102,7 @@ func (e *Editor) Event(gtx *layout.Context) (EditorEvent, bool) { axis = gesture.Vertical smin, smax = sbounds.Min.Y, sbounds.Max.Y } - sdist := e.scroller.Scroll(gtx.Config, gtx.Queue, axis) + sdist := e.scroller.Scroll(gtx.Config, gtx.Queue, gtx.Now(), axis) var soff int if e.SingleLine { e.scrollOff.X += sdist @@ -167,8 +167,8 @@ func (e *Editor) editorEvent(gtx *layout.Context) (EditorEvent, bool) { return nil, false } -func (e *Editor) caretWidth(c ui.Config) fixed.Int26_6 { - oneDp := c.Px(ui.Dp(1)) +func (e *Editor) caretWidth(c unit.Converter) fixed.Int26_6 { + oneDp := c.Px(unit.Dp(1)) return fixed.Int26_6(oneDp * 64) } @@ -182,7 +182,7 @@ func (e *Editor) Layout(gtx *layout.Context) { cs := gtx.Constraints for _, ok := e.Event(gtx); ok; _, ok = e.Event(gtx) { } - twoDp := gtx.Px(ui.Dp(2)) + twoDp := gtx.Px(unit.Dp(2)) e.padLeft, e.padRight = twoDp, twoDp maxWidth := cs.Width.Max if e.SingleLine { @@ -275,7 +275,7 @@ func (e *Editor) Layout(gtx *layout.Context) { stack.Pop() baseline := e.padTop + e.dims.Baseline - pointerPadding := gtx.Px(ui.Dp(4)) + pointerPadding := gtx.Px(unit.Dp(4)) r := image.Rectangle{Max: e.viewSize} r.Min.X -= pointerPadding r.Min.Y -= pointerPadding @@ -563,7 +563,7 @@ func (e *Editor) moveEnd() { e.carXOff = l.Width + a - x } -func (e *Editor) scrollToCaret(c ui.Config) { +func (e *Editor) scrollToCaret(c unit.Converter) { carWidth := e.caretWidth(c) carLine, _, x, y := e.layoutCaret() l := e.lines[carLine] diff --git a/text/shape/measure.go b/text/shape/measure.go index 1c832dbe..df5643f8 100644 --- a/text/shape/measure.go +++ b/text/shape/measure.go @@ -14,7 +14,7 @@ import ( "gioui.org/op" "gioui.org/op/paint" "gioui.org/text" - "gioui.org/ui" + "gioui.org/unit" "golang.org/x/image/font" "golang.org/x/image/font/sfnt" "golang.org/x/image/math/fixed" @@ -22,7 +22,7 @@ import ( // Faces is a cache of text layouts and paths. type Faces struct { - config ui.Config + config unit.Converter faceCache map[faceKey]*Face layoutCache map[layoutKey]cachedLayout pathCache map[pathKey]cachedPath @@ -53,19 +53,19 @@ type pathKey struct { type faceKey struct { font *sfnt.Font - size ui.Value + size unit.Value } // Face is a cached implementation of text.Face. type Face struct { faces *Faces - size ui.Value + size unit.Value font *opentype } // Reset the cache, discarding any measures or paths that // haven't been used since the last call to Reset. -func (f *Faces) Reset(c ui.Config) { +func (f *Faces) Reset(c unit.Converter) { f.config = c f.init() for pk, p := range f.pathCache { @@ -87,7 +87,7 @@ func (f *Faces) Reset(c ui.Config) { } // For returns a Face for the given font and size. -func (f *Faces) For(fnt *sfnt.Font, size ui.Value) *Face { +func (f *Faces) For(fnt *sfnt.Font, size unit.Value) *Face { f.init() fk := faceKey{fnt, size} if f, exist := f.faceCache[fk]; exist { diff --git a/ui/doc.go b/ui/doc.go deleted file mode 100644 index 65ee355d..00000000 --- a/ui/doc.go +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-License-Identifier: Unlicense OR MIT - -/* -Package ui defines operations buffers, units and common operations -for GUI programs written with the Gio module. - -Units - -A Value is a value with a Unit attached. - -Device independent pixel, or dp, is the unit for sizes independent of -the underlying display device. - -Scaled pixels, or sp, is the unit for text sizes. An sp is like dp with -text scaling applied. - -Finally, pixels, or px, is the unit for display dependent pixels. Their -size vary between platforms and displays. - -To maintain a constant visual size across platforms and displays, always -use dps or sps to define user interfaces. Only use pixels for derived -values. - -*/ -package ui diff --git a/ui/ui.go b/ui/ui.go deleted file mode 100644 index 8f083d4f..00000000 --- a/ui/ui.go +++ /dev/null @@ -1,16 +0,0 @@ -// SPDX-License-Identifier: Unlicense OR MIT - -package ui - -import ( - "time" -) - -// Config define the essential properties of -// the environment. -type Config interface { - // Now returns the current animation time. - Now() time.Time - // Px converts a Value to pixels. - Px(v Value) int -} diff --git a/ui/unit.go b/unit/unit.go similarity index 65% rename from ui/unit.go rename to unit/unit.go index 418fbfdf..0fdc60a1 100644 --- a/ui/unit.go +++ b/unit/unit.go @@ -1,6 +1,26 @@ // SPDX-License-Identifier: Unlicense OR MIT -package ui +/* + +Package unit implements device independent units and values. + +A Value is a value with a Unit attached. + +Device independent pixel, or dp, is the unit for sizes independent of +the underlying display device. + +Scaled pixels, or sp, is the unit for text sizes. An sp is like dp with +text scaling applied. + +Finally, pixels, or px, is the unit for display dependent pixels. Their +size vary between platforms and displays. + +To maintain a constant visual size across platforms and displays, always +use dps or sps to define user interfaces. Only use pixels for derived +values. + +*/ +package unit import "fmt" @@ -13,6 +33,11 @@ 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 +} + const ( // UnitPx represent device pixels in the resolution of // the underlying display. @@ -59,7 +84,7 @@ func (u Unit) String() string { } // Add a list of Values. -func Add(c Config, values ...Value) Value { +func Add(c Converter, values ...Value) Value { var sum Value for _, v := range values { sum, v = compatible(c, sum, v) @@ -69,7 +94,7 @@ func Add(c Config, values ...Value) Value { } // Max returns the maximum of a list of Values. -func Max(c Config, values ...Value) Value { +func Max(c Converter, values ...Value) Value { var max Value for _, v := range values { max, v = compatible(c, max, v) @@ -80,7 +105,7 @@ func Max(c Config, values ...Value) Value { return max } -func compatible(c Config, v1, v2 Value) (Value, Value) { +func compatible(c Converter, v1, v2 Value) (Value, Value) { if v1.U == v2.U { return v1, v2 } diff --git a/widget/image.go b/widget/image.go index a77e1e3f..8fc7cb38 100644 --- a/widget/image.go +++ b/widget/image.go @@ -9,7 +9,7 @@ import ( "gioui.org/f32" "gioui.org/layout" "gioui.org/op/paint" - "gioui.org/ui" + "gioui.org/unit" ) // Image is a widget that displays an image. @@ -31,7 +31,7 @@ func (im Image) Layout(gtx *layout.Context) { var w, h int if im.Scale == 0 { const dpPrPx = 160 / 72 - w, h = gtx.Px(ui.Dp(wf*dpPrPx)), gtx.Px(ui.Dp(hf*dpPrPx)) + w, h = gtx.Px(unit.Dp(wf*dpPrPx)), gtx.Px(unit.Dp(hf*dpPrPx)) } else { w, h = int(wf*im.Scale+.5), int(hf*im.Scale+.5) }