diff --git a/cmd/cal/datetime.go b/cmd/cal/datetime.go index eea373f..4297dc3 100644 --- a/cmd/cal/datetime.go +++ b/cmd/cal/datetime.go @@ -5,21 +5,21 @@ import ( ) func _daysIn(t time.Time) int { - y,m,_ := t.Date() - t2 := time.Date(y,m+1,1,0,0,0,0,time.UTC) - return t2.AddDate(0,0,-1).Day() + y, m, _ := t.Date() + t2 := time.Date(y, m+1, 1, 0, 0, 0, 0, time.UTC) + return t2.AddDate(0, 0, -1).Day() } type SelectableMonth struct { - Ws [7]bool - S [32]bool + Ws [7]bool + S [32]bool Year, Pad, DaysIn int - Month time.Month - Weekday time.Weekday + Month time.Month + Weekday time.Weekday } func NewMonth(t time.Time) *SelectableMonth { - t = time.Date(t.Year(), t.Month(),1,0,0,0,0,time.Local) + t = time.Date(t.Year(), t.Month(), 1, 0, 0, 0, 0, time.Local) ret := &SelectableMonth{} ret.Year, ret.Month, ret.Weekday = t.Year(), t.Month(), t.Weekday() ret.DaysIn = _daysIn(t) @@ -28,7 +28,7 @@ func NewMonth(t time.Time) *SelectableMonth { } func _newMonth(y int, m time.Month) SelectableMonth { - return *NewMonth(time.Date(y,m,1,0,0,0,0,time.Local)) + return *NewMonth(time.Date(y, m, 1, 0, 0, 0, 0, time.Local)) } func (sm *SelectableMonth) Refresh() { @@ -36,21 +36,21 @@ func (sm *SelectableMonth) Refresh() { } func (sm *SelectableMonth) Previous() { - m, y := sm.Month - 1, sm.Year + m, y := sm.Month-1, sm.Year if m > 11 { m = 0 y += 1 } - *sm = _newMonth(y,m) + *sm = _newMonth(y, m) } func (sm *SelectableMonth) Next() { - m, y := sm.Month + 1, sm.Year - if m <0 { + m, y := sm.Month+1, sm.Year + if m < 0 { m = 11 y -= 1 } - *sm = _newMonth(y,m) + *sm = _newMonth(y, m) } func (sm *SelectableMonth) SelectWeekday(d time.Weekday) *SelectableMonth { @@ -77,7 +77,7 @@ func (sm *SelectableMonth) DeselectWeekday(d time.Weekday) *SelectableMonth { func (sm *SelectableMonth) CheckSel() *SelectableMonth { alldays := func(d time.Weekday) bool { - for i := int(d) + 1 - sm.Pad; i <= 31; i+= 7 { + for i := int(d) + 1 - sm.Pad; i <= 31; i += 7 { if i < 1 { continue } @@ -102,8 +102,10 @@ func (sm *SelectableMonth) Weekdays() int { var i int for w := 0; w <= 6; w++ { for d := 1; d < 6; d++ { - x := w * 7 + d + 1 - sm.Pad - if x < 0 || x >= sm.DaysIn { break } + x := w*7 + d + 1 - sm.Pad + if x < 0 || x >= sm.DaysIn { + break + } if sm.S[x] { i++ } @@ -116,12 +118,22 @@ func (sm *SelectableMonth) Weekends() int { var i int for w := 0; w <= 6; w++ { x := w*7 + 1 - sm.Pad - if x < 0 { continue } - if x >= sm.DaysIn { break } - if sm.S[x] { i++ } - x = w*7+6 + 1 - sm.Pad - if x < 0 || x >= sm.DaysIn { break } - if sm.S[x] { i++ } + if x < 0 { + continue + } + if x >= sm.DaysIn { + break + } + if sm.S[x] { + i++ + } + x = w*7 + 6 + 1 - sm.Pad + if x < 0 || x >= sm.DaysIn { + break + } + if sm.S[x] { + i++ + } } return i } @@ -129,7 +141,7 @@ func (sm *SelectableMonth) Weekends() int { // a day within a SelectableMonth type Day struct { Num int - sm *SelectableMonth + sm *SelectableMonth } func (sm *SelectableMonth) Day(i int) *Day { @@ -157,19 +169,19 @@ func (d *Day) ifexists() *Day { } func (d *Day) Next() *Day { - ret := &Day{d.Num+1, d.sm} + ret := &Day{d.Num + 1, d.sm} return ret.ifexists() } func (d *Day) Prev() *Day { - ret := &Day{d.Num-1, d.sm} + ret := &Day{d.Num - 1, d.sm} return ret.ifexists() } func (sm *SelectableMonth) Days() []*Day { - ret := make([]*Day,0) + ret := make([]*Day, 0) for d := sm.Day(1); d.exists(); d = d.Next() { - ret = append(ret,d) + ret = append(ret, d) } return ret } @@ -186,7 +198,7 @@ func (d *Day) Selected() bool { type Week struct { Num int - sm *SelectableMonth + sm *SelectableMonth } func (w *Week) exists() bool { @@ -211,9 +223,9 @@ func (sm *SelectableMonth) Week(i int) *Week { } func (sm *SelectableMonth) Weeks() []*Week { - ret := make([]*Week,0) + ret := make([]*Week, 0) for w := sm.Week(1); w.exists(); w = w.Next() { - ret = append(ret,w) + ret = append(ret, w) } return ret } @@ -222,28 +234,28 @@ func (w *Week) Day(i int) *Day { if i < 1 || i > 7 { return nil } - wday := (w.Num - 1) * 7 + i + wday := (w.Num-1)*7 + i if w.Num != 1 { wday -= w.sm.Pad } - ret := &Day{ wday, w.sm } + ret := &Day{wday, w.sm} return ret.ifexists() } func (w *Week) Next() *Week { - ret := &Week{ w.Num + 1, w.sm } + ret := &Week{w.Num + 1, w.sm} return ret.ifexists() } func (w *Week) Prev() *Week { - ret := &Week{ w.Num - 1, w.sm } + ret := &Week{w.Num - 1, w.sm} return ret.ifexists() } func (w *Week) Days() []*Day { - ret := make([]*Day,0) + ret := make([]*Day, 0) for d := w.Day(1); d.In(w); d = d.Next() { - ret = append(ret,d) + ret = append(ret, d) } return ret } diff --git a/cmd/cal/main.go b/cmd/cal/main.go index 3dbc8a8..1579f0e 100644 --- a/cmd/cal/main.go +++ b/cmd/cal/main.go @@ -4,8 +4,8 @@ package main import ( "fmt" - "log" "image/color" + "log" "time" gio "git.wow.st/gmp/giowrap" @@ -15,12 +15,12 @@ import ( "gioui.org/ui/layout" "gioui.org/ui/text" - "golang.org/x/image/font/sfnt" "golang.org/x/image/font/gofont/goregular" + "golang.org/x/image/font/sfnt" ) var ( - sel int32 + sel int32 face text.Face ) @@ -41,24 +41,24 @@ func NewButton(t string, lops ...gio.LabelOption) gio.Clickable { } type SLabel struct { - w gio.Clickable - bg *gio.Background + w gio.Clickable + bg *gio.Background active *bool } func NewSLabel(t string, active *bool, lops ...gio.LabelOption) *SLabel { ret := &SLabel{} - lops = append([]gio.LabelOption{gio.Face(face)},lops...) + lops = append([]gio.LabelOption{gio.Face(face)}, lops...) lbl := gio.NewLabel(t, lops...) bg := &gio.Background{ - Color: color.RGBA{A: 0xff, R: 0xf0, G: 0xf0, B: 0xe0}, + Color: color.RGBA{A: 0xff, R: 0xf0, G: 0xf0, B: 0xe0}, Radius: ui.Dp(4), - Inset: layout.UniformInset(ui.Dp(4)), + Inset: layout.UniformInset(ui.Dp(4)), } if *active { bg.Color = color.RGBA{A: 0xff, R: 0xf0, G: 0xf0, B: 0xe0} } - l := gio.AsClickable(gio.Enclose(bg,lbl)) + l := gio.AsClickable(gio.Enclose(bg, lbl)) ret.w = l ret.bg = bg ret.active = active @@ -83,12 +83,12 @@ func (w *SLabel) Layout(ctx *gio.Context) { func NewCal(sm *SelectableMonth) gio.Widget { pad := gio.NewLabel("", gio.Face(face), gio.Align(text.End)) - ds := make([]gio.Widget,42) + ds := make([]gio.Widget, 42) for i := 0; i < len(ds); i++ { - if i < sm.Pad || i >= sm.DaysIn + sm.Pad { + if i < sm.Pad || i >= sm.DaysIn+sm.Pad { ds[i] = pad } else { - ds[i] = NewSLabel(fmt.Sprintf("%d",i+1-sm.Pad), &sm.S[i+1-sm.Pad], gio.Align(text.End)) + ds[i] = NewSLabel(fmt.Sprintf("%d", i+1-sm.Pad), &sm.S[i+1-sm.Pad], gio.Align(text.End)) } } return gio.NewGrid(7)(ds...) @@ -104,7 +104,9 @@ func eventloop() { regular, err := sfnt.Parse(goregular.TTF) face = ctx.Faces.For(regular, ui.Sp(20)) - if err != nil { log.Fatal("Cannot parse font.") } + if err != nil { + log.Fatal("Cannot parse font.") + } bg := gio.NewBackground( gio.Color(color.RGBA{A: 0xff, R: 0xf0, G: 0xf0, B: 0xe0})) @@ -113,7 +115,7 @@ func eventloop() { f1 := gio.NewFlex(gio.Axis(layout.Vertical)) f2 := gio.NewFlex(gio.Axis(layout.Horizontal)) sidegrid := gio.NewGrid(1) - yrs := make([]gio.Widget,6) + yrs := make([]gio.Widget, 6) curyr := sm.Year topgrid := gio.NewGrid(3) @@ -125,74 +127,75 @@ func eventloop() { f3 := gio.NewFlex(gio.Axis(layout.Vertical)) daygrid := gio.NewGrid(7) - sun := NewSLabel("Sun",&sm.Ws[time.Sunday], gio.Align(text.End)) - mon := NewSLabel("Mon",&sm.Ws[time.Monday], gio.Align(text.End)) - tue := NewSLabel("Tue",&sm.Ws[time.Tuesday], gio.Align(text.End)) - wed := NewSLabel("Wed",&sm.Ws[time.Wednesday], gio.Align(text.End)) - thu := NewSLabel("Thu",&sm.Ws[time.Thursday], gio.Align(text.End)) - fri := NewSLabel("Fri",&sm.Ws[time.Friday], gio.Align(text.End)) - sat := NewSLabel("Sat",&sm.Ws[time.Saturday], gio.Align(text.End)) + sun := NewSLabel("Sun", &sm.Ws[time.Sunday], gio.Align(text.End)) + mon := NewSLabel("Mon", &sm.Ws[time.Monday], gio.Align(text.End)) + tue := NewSLabel("Tue", &sm.Ws[time.Tuesday], gio.Align(text.End)) + wed := NewSLabel("Wed", &sm.Ws[time.Wednesday], gio.Align(text.End)) + thu := NewSLabel("Thu", &sm.Ws[time.Thursday], gio.Align(text.End)) + fri := NewSLabel("Fri", &sm.Ws[time.Friday], gio.Align(text.End)) + sat := NewSLabel("Sat", &sm.Ws[time.Saturday], gio.Align(text.End)) resetCal := func() { cal = NewCal(sm) - for i,_ := range yrs { - yrs[i] = NewButton(fmt.Sprintf("%d",curyr - i), + for i, _ := range yrs { + yrs[i] = NewButton(fmt.Sprintf("%d", curyr-i), gio.Align(text.Start)) } w.Invalidate() } resetCal() - for { select { - case e:= <-w.Events(): - switch e := e.(type) { - case app.DestroyEvent: - return - case app.UpdateEvent: - ctx.Reset(e) + for { + select { + case e := <-w.Events(): + switch e := e.(type) { + case app.DestroyEvent: + return + case app.UpdateEvent: + ctx.Reset(e) - mth.SetText(fmt.Sprintf("%s %d",sm.Month.String(),sm.Year)) + mth.SetText(fmt.Sprintf("%s %d", sm.Month.String(), sm.Year)) - ows := sm.Ws - bg(margin(f1( - topgrid(lbtn,mth,rbtn), - f2( - sidegrid(yrs...), - f3( - daygrid(sun,mon,tue,wed,thu,fri,sat), - cal, - ), - ), - ))).Layout(ctx) - ctx.Update() + ows := sm.Ws + bg(margin(f1( + topgrid(lbtn, mth, rbtn), + f2( + sidegrid(yrs...), + f3( + daygrid(sun, mon, tue, wed, thu, fri, sat), + cal, + ), + ), + ))).Layout(ctx) + ctx.Update() - for i := time.Sunday; i < 7; i++ { - switch { - case sm.Ws[i] && !ows[i]: - sm.SelectWeekday(i) - resetCal() - case !sm.Ws[i] && ows[i]: - sm.DeselectWeekday(i) + for i := time.Sunday; i < 7; i++ { + switch { + case sm.Ws[i] && !ows[i]: + sm.SelectWeekday(i) + resetCal() + case !sm.Ws[i] && ows[i]: + sm.DeselectWeekday(i) + resetCal() + } + } + if lbtn.Clicked(ctx) { + sm.Previous() resetCal() } - } - if lbtn.Clicked(ctx) { - sm.Previous() - resetCal() - } - if rbtn.Clicked(ctx) { - sm.Next() - resetCal() - } - for i,y := range yrs { - if y.(gio.Clickable).Clicked(ctx) { - sm.Year = curyr - i - sm.Refresh() + if rbtn.Clicked(ctx) { + sm.Next() resetCal() } + for i, y := range yrs { + if y.(gio.Clickable).Clicked(ctx) { + sm.Year = curyr - i + sm.Refresh() + resetCal() + } + } + sm.CheckSel() } - sm.CheckSel() } - }} + } } - diff --git a/cmd/grid/grid.go b/cmd/grid/grid.go new file mode 100644 index 0000000..1898530 --- /dev/null +++ b/cmd/grid/grid.go @@ -0,0 +1,62 @@ +package main + +import ( + "image" + + "gioui.org/ui" + "gioui.org/ui/app" + "gioui.org/ui/f32" + "gioui.org/ui/layout" + "gioui.org/ui/paint" + + gio "git.wow.st/gmp/giowrap" +) + +func main() { + go func() { + w := app.NewWindow() + ops := new(ui.Ops) + gcs := make([]gio.GridChild, 0) + + for e := range w.Events() { + if e, ok := e.(app.UpdateEvent); ok { + ops.Reset() + c := &e.Config + cs := layout.RigidConstraints(e.Size) + nrows := 5 + ncols := 10 + grid := gio.Grid{Cols: ncols} + cs = grid.Init(ops, cs) + + for i := 0; i < nrows*ncols; i++ { + grid.Begin() + dims := layoutRect(c, ops, cs) + gcs = append(gcs, grid.End(dims)) + } + + grid.Layout(gcs...) + w.Update(ops) + gcs = gcs[0:0] + } + } + }() + app.Main() +} + +func layoutRect(c ui.Config, ops *ui.Ops, cs layout.Constraints) layout.Dimens { + ins := layout.UniformInset(ui.Px(10)) + cs = ins.Begin(c, ops, cs) + paint.PaintOp{Rect: f32.Rectangle{ + Max: f32.Point{ + X: float32(cs.Width.Max), + Y: float32(cs.Width.Max), + }, + }}.Add(ops) + dims := layout.Dimens{ + Size: image.Point{ + X: cs.Width.Max, + Y: cs.Width.Max, + }, + } + return ins.End(dims) +} diff --git a/cmd/hello/main.go b/cmd/hello/main.go index 1f33245..017eb28 100644 --- a/cmd/hello/main.go +++ b/cmd/hello/main.go @@ -14,25 +14,25 @@ import ( "gioui.org/ui" "gioui.org/ui/app" - "gioui.org/ui/paint" "gioui.org/ui/f32" "gioui.org/ui/gesture" "gioui.org/ui/layout" "gioui.org/ui/measure" + "gioui.org/ui/paint" "gioui.org/ui/pointer" "gioui.org/ui/text" - "golang.org/x/image/font/sfnt" "golang.org/x/image/font/gofont/goregular" + "golang.org/x/image/font/sfnt" ) var ( - FPS int = 100 - frames int64 - frametime int64 // nanoseconds + FPS int = 100 + frames int64 + frametime int64 // nanoseconds maxframetime int64 - mux sync.Mutex - Profile bool = false + mux sync.Mutex + Profile bool = false ) func NewButton(face text.Face, t string, c color.RGBA) giowrap.Clickable { @@ -56,25 +56,27 @@ func main() { a1 = ms.Alloc runtime.GC() runtime.ReadMemStats(ms) - log.Printf("Alloc: %d - %d = %d (%d per frame)", a1, ms.Alloc, a1 - ms.Alloc, (a1 - ms.Alloc) / (3 * uint64(FPS))) - log.Printf("Frametime: %d max Frametime: %d us\n", frametime / (frames * 1000), maxframetime / 1000) + log.Printf("Alloc: %d - %d = %d (%d per frame)", a1, ms.Alloc, a1-ms.Alloc, (a1-ms.Alloc)/(3*uint64(FPS))) + log.Printf("Frametime: %d max Frametime: %d us\n", frametime/(frames*1000), maxframetime/1000) frames = 0 frametime = 0 maxframetime = 0 mux.Unlock() } }() - switch os.Args[1] { - case "", "main1": - log.Print("main1()") - go main1() - case "main2": - log.Print("main2()") - go main2() - default: - log.Fatal(`Usage: + if len(os.Args) > 1 { + switch os.Args[1] { + case "", "main1": + log.Print("main1()") + go main1() + case "main2": + log.Print("main2()") + go main2() + default: + log.Fatal(`Usage: hello [main1|main2] `) + } } app.Main() } @@ -86,11 +88,11 @@ func main1() { log.Fatal("Cannot parse font.") } ctx := giowrap.NewContext(w) - t := time.NewTicker(time.Second/time.Duration(FPS)) - e1 := giowrap.NewEditor("text 1",giowrap.Face(ctx.Faces.For(regular, ui.Sp(24)))) + t := time.NewTicker(time.Second / time.Duration(FPS)) + e1 := giowrap.NewEditor("text 1", giowrap.Face(ctx.Faces.For(regular, ui.Sp(24)))) e1.Focus() - e2 := giowrap.NewEditor("text 2",giowrap.Face(ctx.Faces.For(regular, ui.Sp(24)))) + e2 := giowrap.NewEditor("text 2", giowrap.Face(ctx.Faces.For(regular, ui.Sp(24)))) f1 := giowrap.NewFlex(giowrap.Axis(layout.Vertical)) OuterInset := giowrap.NewInset(giowrap.Size(ui.Dp(10))) @@ -118,7 +120,7 @@ func main1() { case app.UpdateEvent: ctx.Reset(e) OuterInset( - f1( + f1( e1, giowrap.Flexible(5), InnerInset(e2), @@ -131,21 +133,27 @@ func main1() { )).Layout(ctx) ctx.Update() if btn1.Clicked(ctx) { - log.Print("Clicked: " + e1.Text() ) + log.Print("Clicked: " + e1.Text()) } if btn2.Clicked(ctx) { - log.Print("Clicked: " + e2.Text() ) + log.Print("Clicked: " + e2.Text()) } } dur := time.Since(stime).Nanoseconds() mux.Lock() frames = frames + 1 frametime = frametime + dur - if dur > maxframetime { maxframetime = dur } + if dur > maxframetime { + maxframetime = dur + } mux.Unlock() } - if profiled { continue } - if time.Since(startTime) < time.Second * 10 { continue } + if profiled { + continue + } + if time.Since(startTime) < time.Second*10 { + continue + } if Profile { profiled = true f, err := os.Create("memprofile.pprof") @@ -170,26 +178,26 @@ func main2() { if err != nil { log.Fatal("Cannot parse font.") } - t := time.NewTicker(time.Second/time.Duration(FPS)) + t := time.NewTicker(time.Second / time.Duration(FPS)) e1 := &text.Editor{ - Face: faces.For(regular, ui.Sp(24)), + Face: faces.For(regular, ui.Sp(24)), SingleLine: true, } e1.Focus() e1.SetText("text 1") e2 := &text.Editor{ - Face: faces.For(regular, ui.Sp(24)), + Face: faces.For(regular, ui.Sp(24)), SingleLine: true, } e2.Focus() e2.SetText("text 2") - f1 := layout.Flex{ Axis: layout.Vertical } + f1 := layout.Flex{Axis: layout.Vertical} OuterInset := layout.UniformInset(ui.Dp(10)) InnerInset := layout.UniformInset(ui.Dp(10)) - f2 := layout.Flex{ Axis: layout.Horizontal } + f2 := layout.Flex{Axis: layout.Horizontal} btn1 := text.Label{ Face: faces.For(regular, ui.Sp(24)), @@ -240,7 +248,7 @@ func main2() { cs = b1ins.Begin(c, ops, cs) dims = btn1.Layout(ops, cs) dims = b1ins.End(dims) - pointer.RectAreaOp{image.Rect(0,0,dims.Size.X,dims.Size.Y)}.Add(ops) + pointer.RectAreaOp{image.Rect(0, 0, dims.Size.X, dims.Size.Y)}.Add(ops) click1.Add(ops) bg1.Stop() wi, h := float32(dims.Size.X), float32(dims.Size.Y) @@ -257,7 +265,7 @@ func main2() { cs = b2ins.Begin(c, ops, cs) dims = btn2.Layout(ops, cs) dims = b2ins.End(dims) - pointer.RectAreaOp{image.Rect(0,0,dims.Size.X,dims.Size.Y)}.Add(ops) + pointer.RectAreaOp{image.Rect(0, 0, dims.Size.X, dims.Size.Y)}.Add(ops) click2.Add(ops) bg2.Stop() wi, h = float32(dims.Size.X), float32(dims.Size.Y) @@ -274,12 +282,12 @@ func main2() { w.Update(ops) for ev, ok := click1.Next(q); ok; ev, ok = click1.Next(q) { if ev.Type == gesture.TypeClick { - log.Print("Clicked: " + e1.Text() ) + log.Print("Clicked: " + e1.Text()) } } for ev, ok := click2.Next(q); ok; ev, ok = click2.Next(q) { if ev.Type == gesture.TypeClick { - log.Print("Clicked: " + e2.Text() ) + log.Print("Clicked: " + e2.Text()) } } } @@ -287,11 +295,17 @@ func main2() { mux.Lock() frames = frames + 1 frametime = frametime + dur - if dur > maxframetime { maxframetime = dur } + if dur > maxframetime { + maxframetime = dur + } mux.Unlock() } - if profiled { continue } - if time.Since(startTime) < time.Second * 10 { continue } + if profiled { + continue + } + if time.Since(startTime) < time.Second*10 { + continue + } if Profile { profiled = true f, err := os.Create("memprofile.pprof") @@ -306,4 +320,3 @@ func main2() { } } } - diff --git a/cmd/scroll/main.go b/cmd/scroll/main.go index fbd0752..ddfbf69 100644 --- a/cmd/scroll/main.go +++ b/cmd/scroll/main.go @@ -1,8 +1,8 @@ package main import ( - "image/color" "fmt" + "image/color" "log" gio "git.wow.st/gmp/giowrap" @@ -12,36 +12,36 @@ import ( "gioui.org/ui/layout" "gioui.org/ui/text" - "golang.org/x/image/font/sfnt" "golang.org/x/image/font/gofont/goregular" + "golang.org/x/image/font/sfnt" ) var ( - face text.Face - black color.RGBA = color.RGBA{ A: 0xff, R: 0x00, G: 0x00, B: 0x00 } - gray2 color.RGBA = color.RGBA{ A: 0xff, R: 0x70, G: 0x70, B: 0x70 } - gray1 color.RGBA = color.RGBA{ A: 0xff, R: 0x50, G: 0x50, B: 0x50 } + face text.Face + black color.RGBA = color.RGBA{A: 0xff, R: 0x00, G: 0x00, B: 0x00} + gray2 color.RGBA = color.RGBA{A: 0xff, R: 0xc0, G: 0xc0, B: 0xc0} + gray1 color.RGBA = color.RGBA{A: 0xff, R: 0x70, G: 0x70, B: 0x70} ) type SLabel struct { - w gio.Clickable - bg *gio.Background + w gio.Clickable + bg *gio.Background active *bool } func NewSLabel(t string, active *bool, lops ...gio.LabelOption) *SLabel { ret := &SLabel{} - lops = append([]gio.LabelOption{gio.Face(face)},lops...) + lops = append([]gio.LabelOption{gio.Face(face)}, lops...) lbl := gio.NewLabel(t, lops...) bg := &gio.Background{ - Color: gray2, + Color: gray2, Radius: ui.Dp(4), - Inset: layout.UniformInset(ui.Dp(4)), + Inset: layout.UniformInset(ui.Dp(4)), } if *active { bg.Color = gray1 } - l := gio.AsClickable(gio.Enclose(bg,lbl)) + l := gio.AsClickable(gio.Enclose(bg, lbl)) ret.w = l ret.bg = bg ret.active = active @@ -72,7 +72,7 @@ func main() { } func diffInsets(x, y app.Insets) bool { - return x.Top != y.Top || + return x.Top != y.Top || x.Bottom != y.Bottom || x.Left != y.Left || x.Right != y.Right @@ -87,7 +87,9 @@ func eventloop() { regular, err := sfnt.Parse(goregular.TTF) face = ctx.Faces.For(regular, ui.Sp(16)) - if err != nil { log.Fatal("Cannot parse font.") } + if err != nil { + log.Fatal("Cannot parse font.") + } sysbg := gio.NewBackground(gio.Color(black)) bg := gio.NewBackground(gio.Color(gray2)) @@ -108,51 +110,52 @@ func eventloop() { labs[i] = make([]gio.Widget, numlabs) sels[i] = make([]bool, numlabs) for j := 0; j < numlabs; j++ { - labs[i][j] = NewSLabel(fmt.Sprintf("%03d",i * j), &sels[i][j]) + labs[i][j] = NewSLabel(fmt.Sprintf("%03d", i*16+j), &sels[i][j]) } } sysinset := gio.NewInset(gio.Size(ui.Dp(0))) resetSysinset := func(x app.Insets) { sysinset = gio.NewInset(gio.Top(x.Top), gio.Bottom(x.Bottom), - gio.Left(x.Left), gio.Right(x.Right)) + gio.Left(x.Left), gio.Right(x.Right)) } var oldInsets app.Insets - for { select { - case e:= <-w.Events(): - switch e := e.(type) { - case app.DestroyEvent: - return - case app.UpdateEvent: - ctx.Reset(e) - if diffInsets(e.Insets, oldInsets) { - oldInsets = e.Insets - resetSysinset(e.Insets) + for { + select { + case e := <-w.Events(): + switch e := e.(type) { + case app.DestroyEvent: + return + case app.UpdateEvent: + ctx.Reset(e) + if diffInsets(e.Insets, oldInsets) { + oldInsets = e.Insets + resetSysinset(e.Insets) + } + + sysbg(sysinset(bg(margin( + f1(lbar, f2(topbar, sh( + sv(labs[0]...), + sv(labs[1]...), + sv(labs[2]...), + sv(labs[3]...), + sv(labs[4]...), + sv(labs[5]...), + sv(labs[6]...), + sv(labs[7]...), + sv(labs[8]...), + sv(labs[9]...), + sv(labs[10]...), + sv(labs[11]...), + sv(labs[12]...), + sv(labs[13]...), + sv(labs[14]...), + sv(labs[15]...), + ))))))).Layout(ctx) + ctx.Update() } - - sysbg(sysinset(bg(margin( - f1(lbar,f2(topbar,sh( - sv(labs[0]...), - sv(labs[1]...), - sv(labs[2]...), - sv(labs[3]...), - sv(labs[4]...), - sv(labs[5]...), - sv(labs[6]...), - sv(labs[7]...), - sv(labs[8]...), - sv(labs[9]...), - sv(labs[10]...), - sv(labs[11]...), - sv(labs[12]...), - sv(labs[13]...), - sv(labs[14]...), - sv(labs[15]...), - ))))))).Layout(ctx) - ctx.Update() } - }} + } } - diff --git a/grid.go b/grid.go new file mode 100644 index 0000000..7783c5e --- /dev/null +++ b/grid.go @@ -0,0 +1,147 @@ +package giowrap + +import ( + "image" + + "gioui.org/ui" + "gioui.org/ui/f32" + "gioui.org/ui/layout" +) + +type Grid struct { + Cols int + Height, Width int + + macro ui.MacroOp + ops *ui.Ops + cs layout.Constraints + mode gridMode + row, col int +} + +type GridChild struct { + dims layout.Dimens + macro ui.MacroOp +} + +type gridMode uint8 + +const ( + modeNone gridMode = iota + modeBegun +) + +func (g *Grid) Init(ops *ui.Ops, cs layout.Constraints) layout.Constraints { + g.mode = modeBegun + g.ops = ops + g.cs = cs + g.row, g.col = 0, 0 + + cs.Height.Min = 0 + + if g.Height != 0 { + g.cs.Height.Max = g.Height + } + if g.Width != 0 { + g.cs.Width.Max = g.Width + } + + cs.Width.Max = g.cs.Width.Max / g.Cols + if g.Cols > 1 { + cs.Width.Min = cs.Width.Max + } + return cs +} + +func (g *Grid) Begin() { + g.macro.Record(g.ops) +} + +func (g *Grid) End(dims layout.Dimens) GridChild { + if g.mode != modeBegun { + panic("Must call Grid.Begin() before adding children.") + } + g.macro.Stop() + return GridChild{dims: dims, macro: g.macro} +} + +func (g *Grid) Layout(cs ...GridChild) layout.Dimens { + rowheight := 0 + height := 0 + var width float32 + var maxwidth float32 + for _, c := range cs { + var stack ui.StackOp + stack.Push(g.ops) + c.macro.Add(g.ops) + stack.Pop() + if c.dims.Size.Y > rowheight { + rowheight = c.dims.Size.Y + } + g.col = g.col + 1 + var x float32 + if g.Cols == 1 { + x = float32(c.dims.Size.X) + if x > maxwidth { + maxwidth = x + } + } else { + x = float32(g.cs.Width.Max / g.Cols) + } + if g.col < g.Cols { + ui.TransformOp{}.Offset(f32.Point{X: x}).Add(g.ops) + width = width + x + } else { + g.col = 0 + ui.TransformOp{}.Offset(f32.Point{X: -width, Y: float32(rowheight)}).Add(g.ops) + g.row = g.row + 1 + height = height + rowheight + width = 0 + rowheight = 0 + } + } + if height == 0 { + height = rowheight + } + g.mode = modeNone + var dwidth int + if g.Cols == 1 { + dwidth = int(maxwidth) + } else { + dwidth = g.cs.Width.Max + } + return layout.Dimens{Size: image.Point{dwidth, height}} +} + +func toPointF(p image.Point) f32.Point { + return f32.Point{X: float32(p.X), Y: float32(p.Y)} +} + +type GridOption interface{ DoGridOption(*Grid) } + +type HeightOpt struct{ height int } + +func Height(x int) HeightOpt { return HeightOpt{x} } +func (x HeightOpt) DoGridOption(g *Grid) { g.Height = x.height } + +func NewGrid(cols int, gops ...GridOption) WidgetCombinator { + g := &Grid{Cols: cols} + for _, gop := range gops { + gop.DoGridOption(g) + } + gcs := make([]GridChild, 0) + return func(ws ...Widget) Widget { + return NewfWidget(func(ctx *Context) { + cs := g.Init(ctx.ops, ctx.cs) + ctx.cs = cs + for _, w := range ws { + g.Begin() + w.Layout(ctx) + ctx.cs = cs // widget layout can modify constraints... + gcs = append(gcs, g.End(ctx.dims)) + } + ctx.dims = g.Layout(gcs...) + gcs = gcs[0:0] + }) + } +} diff --git a/main.go b/main.go index 61d06bc..329c90e 100644 --- a/main.go +++ b/main.go @@ -14,8 +14,8 @@ import ( "gioui.org/ui/text" "gioui.org/ui/f32" - "gioui.org/ui/paint" "gioui.org/ui/gesture" + "gioui.org/ui/paint" "gioui.org/ui/pointer" ) @@ -29,10 +29,12 @@ var extra Extra func (e *Extra) New() int { e.Lock() - if e.data == nil { e.data = make([]interface{},0) } + if e.data == nil { + e.data = make([]interface{}, 0) + } ret := e.max e.max = e.max + 1 - e.data = append(e.data,nil) + e.data = append(e.data, nil) e.Unlock() return ret } @@ -40,19 +42,19 @@ func (e *Extra) New() int { type Context struct { Faces measure.Faces - w *app.Window - c *app.Config - q input.Queue - ops *ui.Ops - cs layout.Constraints + w *app.Window + c *app.Config + q input.Queue + ops *ui.Ops + cs layout.Constraints dims layout.Dimens } func NewContext(w *app.Window) *Context { return &Context{ - w: w, + w: w, ops: new(ui.Ops), - q: w.Queue(), + q: w.Queue(), } } @@ -79,28 +81,34 @@ type Label struct { l *text.Label } -type FaceOpt struct { face text.Face } -func Face(x text.Face) FaceOpt { return FaceOpt { x } } -type AlignOpt struct { alignment text.Alignment } -func Align(x text.Alignment) AlignOpt { return AlignOpt { x } } +type FaceOpt struct{ face text.Face } + +func Face(x text.Face) FaceOpt { return FaceOpt{x} } + +type AlignOpt struct{ alignment text.Alignment } + +func Align(x text.Alignment) AlignOpt { return AlignOpt{x} } type LabelOpts struct { FaceOpt c *color.RGBA AlignOpt } -type LabelOption interface { DoLabelOption(*LabelOpts) } -func (x FaceOpt) DoLabelOption(o *LabelOpts) { o.face = x.face } +type LabelOption interface{ DoLabelOption(*LabelOpts) } + +func (x FaceOpt) DoLabelOption(o *LabelOpts) { o.face = x.face } func (x AlignOpt) DoLabelOption(o *LabelOpts) { o.alignment = x.alignment } -func (x ColorOpt) DoLabelOption(o *LabelOpts) { o.c = &x.c; } +func (x ColorOpt) DoLabelOption(o *LabelOpts) { o.c = &x.c } func NewLabel(t string, lops ...LabelOption) *Label { ret := &Label{} opts := &LabelOpts{} - for _,o := range lops { o.DoLabelOption(opts) } + for _, o := range lops { + o.DoLabelOption(opts) + } ret.l = &text.Label{ - Face: opts.face, - Text: t, + Face: opts.face, + Text: t, Alignment: opts.alignment, } if opts.c != nil { // got a color option... @@ -124,22 +132,26 @@ type Editor struct { e *text.Editor } -type SinglelineOpt struct { singleline bool } -func Singleline(x bool) SinglelineOpt { return SinglelineOpt{ x } } +type SinglelineOpt struct{ singleline bool } + +func Singleline(x bool) SinglelineOpt { return SinglelineOpt{x} } type EditorOpts struct { FaceOpt SinglelineOpt } -type EditorOption interface { DoEditorOption(*EditorOpts) } -func (x FaceOpt) DoEditorOption(o *EditorOpts) { o.face = x.face } +type EditorOption interface{ DoEditorOption(*EditorOpts) } + +func (x FaceOpt) DoEditorOption(o *EditorOpts) { o.face = x.face } func (x SinglelineOpt) DoEditorOption(o *EditorOpts) { o.singleline = x.singleline } func NewEditor(t string, eops ...EditorOption) *Editor { ret := &Editor{} opts := &EditorOpts{} - for _,o := range eops { o.DoEditorOption(opts) } - ret.e = &text.Editor{ Face: opts.face, SingleLine: opts.singleline } + for _, o := range eops { + o.DoEditorOption(opts) + } + ret.e = &text.Editor{Face: opts.face, SingleLine: opts.singleline} ret.SetText(t) return ret } @@ -148,16 +160,16 @@ func (e *Editor) Layout(ctx *Context) { ctx.dims = e.e.Layout(ctx.c, ctx.q, ctx.ops, ctx.cs) } -func (e *Editor) Text() string { return e.e.Text() } +func (e *Editor) Text() string { return e.e.Text() } func (e *Editor) SetText(s string) { e.e.SetText(s) } -func (e *Editor) Focus() { e.e.Focus() } +func (e *Editor) Focus() { e.e.Focus() } type fWidget struct { l Layout } func NewfWidget(l Layout) fWidget { - return fWidget{ l: l } + return fWidget{l: l} } func (fw fWidget) Layout(ctx *Context) { @@ -167,13 +179,13 @@ func (fw fWidget) Layout(ctx *Context) { type Stack WidgetCombinator func NewStack() Stack { - s := layout.Stack{ Alignment: layout.Center } - scs := make([]layout.StackChild,0) + s := layout.Stack{Alignment: layout.Center} + scs := make([]layout.StackChild, 0) return func(ws ...Widget) Widget { return NewfWidget(func(ctx *Context) { s.Init(ctx.ops, ctx.cs) - for _,w := range ws { + for _, w := range ws { ctx.cs = s.Rigid() w.Layout(ctx) scs = append(scs, s.End(ctx.dims)) @@ -186,19 +198,23 @@ func NewStack() Stack { type List = WidgetCombinator -type AxisOpt struct { axis layout.Axis } -func Axis(x layout.Axis) AxisOpt { return AxisOpt{ x } } +type AxisOpt struct{ axis layout.Axis } + +func Axis(x layout.Axis) AxisOpt { return AxisOpt{x} } type ListOpts struct { AxisOpt } -type ListOption interface { DoListOption(*ListOpts) } +type ListOption interface{ DoListOption(*ListOpts) } + func (x AxisOpt) DoListOption(o *ListOpts) { o.axis = x.axis } func NewList(los ...ListOption) List { opts := &ListOpts{} - for _,o := range los { o.DoListOption(opts) } - l := layout.List { Axis: opts.axis } + for _, o := range los { + o.DoListOption(opts) + } + l := layout.List{Axis: opts.axis} return func(ws ...Widget) Widget { return NewfWidget(func(ctx *Context) { for l.Init(ctx.c, ctx.q, ctx.ops, ctx.cs, len(ws)); l.More(); l.Next() { @@ -234,8 +250,9 @@ func Rigid() Widget { }) } -type AlignmentOpt struct { alignment layout.Alignment } -func Alignment(x layout.Alignment) AlignmentOpt { return AlignmentOpt{ x } } +type AlignmentOpt struct{ alignment layout.Alignment } + +func Alignment(x layout.Alignment) AlignmentOpt { return AlignmentOpt{x} } type FlexOpts struct { AxisOpt @@ -243,26 +260,29 @@ type FlexOpts struct { flexible float32 } -type FlexOption interface { DoFlexOption(*FlexOpts) } -func (x AxisOpt) DoFlexOption(o *FlexOpts) { o.axis = x.axis } +type FlexOption interface{ DoFlexOption(*FlexOpts) } + +func (x AxisOpt) DoFlexOption(o *FlexOpts) { o.axis = x.axis } func (x AlignmentOpt) DoFlexOption(o *FlexOpts) { o.alignment = x.alignment } // NewFlex returns a WidgetCombinator that wraps the layout.Flex element. func NewFlex(fos ...FlexOption) Flex { opts := &FlexOpts{} - for _,o := range fos { o.DoFlexOption(opts) } + for _, o := range fos { + o.DoFlexOption(opts) + } f := layout.Flex{ - Axis: opts.axis, + Axis: opts.axis, Alignment: opts.alignment, } index := extra.New() extra.data[index] = opts // do not call "make" inside the Layout function - fcs := make([]layout.FlexChild,0) + fcs := make([]layout.FlexChild, 0) return func(ws ...Widget) Widget { return NewfWidget(func(ctx *Context) { - // ensure child widgets write options to the right place + // ensure child widgets write options to the right place extra.cur = index opts := extra.data[index].(*FlexOpts) f.Init(ctx.ops, ctx.cs) @@ -285,24 +305,32 @@ type InsetOpts struct { top, right, bottom, left ui.Value } -type InsetOption interface { DoInsetOption(*InsetOpts) } +type InsetOption interface{ DoInsetOption(*InsetOpts) } -type TopOpt struct { top ui.Value } -func Top(x ui.Value) TopOpt { return TopOpt{ x } } -type RightOpt struct { right ui.Value } -func Right(x ui.Value) RightOpt { return RightOpt{ x } } -type BottomOpt struct { bottom ui.Value } -func Bottom(x ui.Value) BottomOpt { return BottomOpt{ x } } -type LeftOpt struct { left ui.Value } -func Left(x ui.Value) LeftOpt { return LeftOpt{ x } } +type TopOpt struct{ top ui.Value } -func (x TopOpt) DoInsetOption(o *InsetOpts) { o.top = x.top } -func (x RightOpt) DoInsetOption(o *InsetOpts) { o.right = x.right } +func Top(x ui.Value) TopOpt { return TopOpt{x} } + +type RightOpt struct{ right ui.Value } + +func Right(x ui.Value) RightOpt { return RightOpt{x} } + +type BottomOpt struct{ bottom ui.Value } + +func Bottom(x ui.Value) BottomOpt { return BottomOpt{x} } + +type LeftOpt struct{ left ui.Value } + +func Left(x ui.Value) LeftOpt { return LeftOpt{x} } + +func (x TopOpt) DoInsetOption(o *InsetOpts) { o.top = x.top } +func (x RightOpt) DoInsetOption(o *InsetOpts) { o.right = x.right } func (x BottomOpt) DoInsetOption(o *InsetOpts) { o.bottom = x.bottom } -func (x LeftOpt) DoInsetOption(o *InsetOpts) { o.left = x.left } +func (x LeftOpt) DoInsetOption(o *InsetOpts) { o.left = x.left } -type SizeOpt struct { size ui.Value } -func Size(x ui.Value) SizeOpt { return SizeOpt{ x } } +type SizeOpt struct{ size ui.Value } + +func Size(x ui.Value) SizeOpt { return SizeOpt{x} } func (x SizeOpt) DoInsetOption(o *InsetOpts) { o.top = x.size o.right = x.size @@ -313,8 +341,10 @@ func (x SizeOpt) DoInsetOption(o *InsetOpts) { //NewInset returns a WidgetCombinator that wraps the layout.Inset element. func NewInset(insos ...InsetOption) WidgetCombinator { opts := &InsetOpts{} - for _,o := range insos { o.DoInsetOption(opts) } - ins := layout.Inset{ Top: opts.top, Right: opts.right, Bottom: opts.bottom, Left: opts.left } + for _, o := range insos { + o.DoInsetOption(opts) + } + ins := layout.Inset{Top: opts.top, Right: opts.right, Bottom: opts.bottom, Left: opts.left} return func(ws ...Widget) Widget { return NewfWidget(func(ctx *Context) { ctx.cs = ins.Begin(ctx.c, ctx.ops, ctx.cs) @@ -327,9 +357,9 @@ func NewInset(insos ...InsetOption) WidgetCombinator { } type Background struct { - Color color.RGBA + Color color.RGBA Radius ui.Value - Inset layout.Inset + Inset layout.Inset macro ui.MacroOp } @@ -342,7 +372,7 @@ type Enclosure interface { func Enclose(e Enclosure, ws ...Widget) Widget { return NewfWidget(func(ctx *Context) { e.Begin(ctx) - for _,w := range ws { + for _, w := range ws { w.Layout(ctx) } e.End(ctx) @@ -350,27 +380,31 @@ func Enclose(e Enclosure, ws ...Widget) Widget { } type BackgroundOpts struct { - c color.RGBA + c color.RGBA radius ui.Value } -type BackgroundOption interface { DoBackgroundOption(*BackgroundOpts) } +type BackgroundOption interface{ DoBackgroundOption(*BackgroundOpts) } -type ColorOpt struct { c color.RGBA } -func Color(x color.RGBA) ColorOpt { return ColorOpt{ x } } +type ColorOpt struct{ c color.RGBA } + +func Color(x color.RGBA) ColorOpt { return ColorOpt{x} } func (x ColorOpt) DoBackgroundOption(o *BackgroundOpts) { o.c = x.c } -type RadiusOpt struct { radius ui.Value } -func Radius(x ui.Value) RadiusOpt { return RadiusOpt { x } } +type RadiusOpt struct{ radius ui.Value } + +func Radius(x ui.Value) RadiusOpt { return RadiusOpt{x} } func (x RadiusOpt) DoBackgroundOption(o *BackgroundOpts) { o.radius = x.radius } func NewBackground(bos ...BackgroundOption) WidgetCombinator { opts := &BackgroundOpts{} - for _,o := range bos { o.DoBackgroundOption(opts) } + for _, o := range bos { + o.DoBackgroundOption(opts) + } bg := &Background{ - Color: opts.c, + Color: opts.c, Radius: opts.radius, - Inset: layout.UniformInset(opts.radius), + Inset: layout.UniformInset(opts.radius), } return func(ws ...Widget) Widget { return Enclose(bg, ws...) @@ -389,10 +423,10 @@ func (bg *Background) End(ctx *Context) { stack.Push(ctx.ops) w, h := float32(ctx.dims.Size.X), float32(ctx.dims.Size.Y) if r := float32(ctx.c.Px(bg.Radius)); r > 0 { - if r > w / 2 { + if r > w/2 { r = w / 2 } - if r > h / 2 { + if r > h/2 { r = h / 2 } Rrect(ctx.ops, w, h, r, r, r, r) @@ -427,13 +461,13 @@ type Clickable interface { //cWidget is a clickable Widget that provides the Clicked() method. type cWidget struct { - w Widget + w Widget click *gesture.Click } func (w cWidget) Layout(ctx *Context) { w.w.Layout(ctx) - pointer.RectAreaOp{image.Rect(0,0,ctx.dims.Size.X,ctx.dims.Size.Y)}.Add(ctx.ops) + pointer.RectAreaOp{image.Rect(0, 0, ctx.dims.Size.X, ctx.dims.Size.Y)}.Add(ctx.ops) w.click.Add(ctx.ops) } @@ -449,133 +483,5 @@ func (w cWidget) Clicked(ctx *Context) bool { //Clickable converts any Widget into a clickable Widget. func AsClickable(w Widget) cWidget { - return cWidget{ w: w, click: new(gesture.Click) } -} - -type Grid struct { - Cols int - Height, Width int - - macro ui.MacroOp - ops *ui.Ops - cs layout.Constraints - mode gridMode - row, col int -} - -type GridChild struct { - dims layout.Dimens - macro ui.MacroOp -} - -type gridMode uint8 -const ( - modeNone gridMode = iota - modeBegun -) - -func (g *Grid) Init(ops *ui.Ops, cs layout.Constraints) layout.Constraints { - g.mode = modeBegun - g.ops = ops - g.cs = cs - g.row, g.col = 0, 0 - - cs.Height.Min = 0 - - if g.Height != 0 { g.cs.Height.Max = g.Height } - if g.Width != 0 { g.cs.Width.Max = g.Width } - - cs.Width.Max = g.cs.Width.Max / g.Cols - if g.Cols > 1 { - cs.Width.Min = cs.Width.Max - } - return cs -} - -func (g *Grid) Begin() { - g.macro.Record(g.ops) -} - -func (g *Grid) End(dims layout.Dimens) GridChild { - if g.mode != modeBegun { - panic("Must call Grid.Begin() before adding children.") - } - g.macro.Stop() - return GridChild{ dims: dims, macro: g.macro } -} - -func (g *Grid) Layout(cs ...GridChild) layout.Dimens { - rowheight := 0 - height := 0 - var width float32 - var maxwidth float32 - for _,c := range cs { - var stack ui.StackOp - stack.Push(g.ops) - c.macro.Add(g.ops) - stack.Pop() - if c.dims.Size.Y > rowheight { - rowheight = c.dims.Size.Y - } - g.col = g.col+1 - var x float32 - if g.Cols == 1 { - x = float32(c.dims.Size.X) - if x > maxwidth { maxwidth = x } - } else { - x = float32(g.cs.Width.Max / g.Cols) - } - if g.col < g.Cols { - ui.TransformOp{}.Offset(f32.Point{X: x}).Add(g.ops) - width = width + x - } else { - g.col = 0 - ui.TransformOp{}.Offset(f32.Point{ X: -width, Y: float32(rowheight) }).Add(g.ops) - g.row = g.row + 1 - height = height + rowheight - width = 0 - rowheight = 0 - } - } - if height == 0 { height = rowheight } - g.mode = modeNone - var dwidth int - if g.Cols == 1 { - dwidth = int(maxwidth) - } else { - dwidth = g.cs.Width.Max - } - return layout.Dimens{ Size: image.Point{ dwidth, height } } -} - -func toPointF(p image.Point) f32.Point { - return f32.Point{X: float32(p.X), Y: float32(p.Y)} -} - -type GridOption interface { DoGridOption(*Grid) } - -type HeightOpt struct { height int } -func Height(x int) HeightOpt { return HeightOpt{ x } } -func (x HeightOpt) DoGridOption(g *Grid) { g.Height = x.height } - -func NewGrid(cols int, gops ...GridOption) WidgetCombinator { - g := &Grid{ Cols: cols } - for _, gop := range gops { - gop.DoGridOption(g) - } - gcs := make([]GridChild,0) - return func(ws ...Widget) Widget { - return NewfWidget(func(ctx *Context) { - cs := g.Init(ctx.ops, ctx.cs) - ctx.cs = cs - for _,w := range ws { - g.Begin() - w.Layout(ctx) - ctx.cs = cs // widget layout can modify constraints... - gcs = append(gcs,g.End(ctx.dims)) - } - ctx.dims = g.Layout(gcs...) - gcs = gcs[0:0] - }) - } + return cWidget{w: w, click: new(gesture.Click)} }