From 11506a974e903f5de60355f28650d1c2601401f2 Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Mon, 2 Dec 2019 13:13:15 +0100 Subject: [PATCH] layout: add NewContext, make zero value Contexts useful While here, unexport the Queue and Config fields. The NewContext cosntructor is shorter, and there is no reason to expose the fields to accidental mutation. Signed-off-by: Elias Naur --- layout/context.go | 44 ++++++++++++++++++++++++++++++++++++++++--- layout/layout_test.go | 41 ++++++++++------------------------------ layout/list.go | 2 +- widget/editor.go | 2 +- 4 files changed, 53 insertions(+), 36 deletions(-) diff --git a/layout/context.go b/layout/context.go index ee84a5c1..39317e96 100644 --- a/layout/context.go +++ b/layout/context.go @@ -4,13 +4,18 @@ package layout import ( "image" + "math" + "time" "gioui.org/io/event" "gioui.org/io/system" "gioui.org/op" + "gioui.org/unit" ) // Context carries the state needed by almost all layouts and widgets. +// A zero value Context never returns events, map units to pixels +// with a scale of 1.0, and returns the zero time from Now. type Context struct { // Constraints track the constraints for the active widget or // layout. @@ -19,11 +24,18 @@ type Context struct { // operation. Dimensions Dimensions - system.Config - event.Queue + cfg system.Config + queue event.Queue *op.Ops } +// NewContext returns a Context for an event queue. +func NewContext(q event.Queue) *Context { + return &Context{ + queue: q, + } +} + // layout a widget with a set of constraints and return its // dimensions. The widget dimensions are constrained abd the previous // constraints are restored after layout. @@ -42,9 +54,35 @@ func ctxLayout(gtx *Context, cs Constraints, w Widget) Dimensions { func (c *Context) Reset(cfg system.Config, size image.Point) { c.Constraints = RigidConstraints(size) c.Dimensions = Dimensions{} - c.Config = cfg + c.cfg = cfg if c.Ops == nil { c.Ops = new(op.Ops) } c.Ops.Reset() } + +// Now returns the configuration time or the the zero time. +func (c *Context) Now() time.Time { + if c.cfg == nil { + return time.Time{} + } + return c.cfg.Now() +} + +// Px maps the value to pixels. If no configuration is set, +// Px returns the rounded value of v. +func (c *Context) Px(v unit.Value) int { + if c.cfg == nil { + return int(math.Round(float64(v.V))) + } + return c.cfg.Px(v) +} + +// Events returns the events available for the key. If no +// queue is configured, Events returns nil. +func (c *Context) Events(k event.Key) []event.Event { + if c.queue == nil { + return nil + } + return c.queue.Events(k) +} diff --git a/layout/layout_test.go b/layout/layout_test.go index fc45171d..0cc59cf0 100644 --- a/layout/layout_test.go +++ b/layout/layout_test.go @@ -3,23 +3,14 @@ package layout_test import ( "fmt" "image" - "time" - "gioui.org/io/event" "gioui.org/layout" "gioui.org/unit" ) -type queue struct{} - -type config struct{} - -var q queue -var cfg = new(config) - func ExampleInset() { - gtx := &layout.Context{Queue: q} - gtx.Reset(cfg, image.Point{X: 100, Y: 100}) + gtx := new(layout.Context) + gtx.Reset(nil, image.Point{X: 100, Y: 100}) // Loose constraints with no minimal size. gtx.Constraints.Width.Min = 0 gtx.Constraints.Height.Min = 0 @@ -40,9 +31,9 @@ func ExampleInset() { } func ExampleAlign() { - gtx := &layout.Context{Queue: q} + gtx := new(layout.Context) // Rigid constraints with both minimum and maximum set. - gtx.Reset(cfg, image.Point{X: 100, Y: 100}) + gtx.Reset(nil, image.Point{X: 100, Y: 100}) align := layout.Align(layout.Center) align.Layout(gtx, func() { @@ -59,8 +50,8 @@ func ExampleAlign() { } func ExampleFlex() { - gtx := &layout.Context{Queue: q} - gtx.Reset(cfg, image.Point{X: 100, Y: 100}) + gtx := new(layout.Context) + gtx.Reset(nil, image.Point{X: 100, Y: 100}) flex := layout.Flex{} @@ -84,8 +75,8 @@ func ExampleFlex() { } func ExampleStack() { - gtx := &layout.Context{Queue: q} - gtx.Reset(cfg, image.Point{X: 100, Y: 100}) + gtx := new(layout.Context) + gtx.Reset(nil, image.Point{X: 100, Y: 100}) stack := layout.Stack{} @@ -107,8 +98,8 @@ func ExampleStack() { } func ExampleList() { - gtx := &layout.Context{Queue: q} - gtx.Reset(cfg, image.Point{X: 100, Y: 100}) + gtx := new(layout.Context) + gtx.Reset(nil, image.Point{X: 100, Y: 100}) // The list is 1e6 elements, but only 5 fit the constraints. const listLen = 1e6 @@ -134,15 +125,3 @@ func layoutWidget(ctx *layout.Context, width, height int) { }, } } - -func (config) Now() time.Time { - return time.Now() -} - -func (config) Px(v unit.Value) int { - return int(v.V + .5) -} - -func (queue) Events(k event.Key) []event.Event { - return nil -} diff --git a/layout/list.go b/layout/list.go index 6af3da04..c585ce6a 100644 --- a/layout/list.go +++ b/layout/list.go @@ -122,7 +122,7 @@ func (l *List) Dragging() bool { } func (l *List) update() { - d := l.scroll.Scroll(l.ctx.Config, l.ctx.Queue, l.ctx.Now(), gesture.Axis(l.Axis)) + d := l.scroll.Scroll(l.ctx, l.ctx, l.ctx.Now(), gesture.Axis(l.Axis)) l.scrollDelta = d l.Position.Offset += d } diff --git a/widget/editor.go b/widget/editor.go index 8ae14ae3..ef282c7f 100644 --- a/widget/editor.go +++ b/widget/editor.go @@ -114,7 +114,7 @@ func (e *Editor) processPointer(gtx *layout.Context) { axis = gesture.Vertical smin, smax = sbounds.Min.Y, sbounds.Max.Y } - sdist := e.scroller.Scroll(gtx.Config, gtx.Queue, gtx.Now(), axis) + sdist := e.scroller.Scroll(gtx, gtx, gtx.Now(), axis) var soff int if e.SingleLine { e.scrollRel(sdist, 0)