diff --git a/.gitignore b/.gitignore index 05de7ca..f02d41f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ cmd/hello/hello cmd/cal/cal +*.apk diff --git a/cmd/cal/datetime.go b/cmd/cal/datetime.go index 42c1b76..eea373f 100644 --- a/cmd/cal/datetime.go +++ b/cmd/cal/datetime.go @@ -31,6 +31,10 @@ func _newMonth(y int, m time.Month) SelectableMonth { return *NewMonth(time.Date(y,m,1,0,0,0,0,time.Local)) } +func (sm *SelectableMonth) Refresh() { + *sm = _newMonth(sm.Year, sm.Month) +} + func (sm *SelectableMonth) Previous() { m, y := sm.Month - 1, sm.Year if m > 11 { diff --git a/cmd/cal/main.go b/cmd/cal/main.go index 572c5c5..3dbc8a8 100644 --- a/cmd/cal/main.go +++ b/cmd/cal/main.go @@ -13,7 +13,6 @@ import ( "gioui.org/ui" "gioui.org/ui/app" "gioui.org/ui/layout" - //"gioui.org/ui/measure" "gioui.org/ui/text" "golang.org/x/image/font/sfnt" @@ -33,7 +32,7 @@ func main() { } func NewButton(t string, lops ...gio.LabelOption) gio.Clickable { - lops = append([]gio.LabelOption{gio.Face(face), gio.Align(text.Center)}, lops...) + lops = append([]gio.LabelOption{gio.Face(face), gio.Align(text.Middle)}, lops...) lbl := gio.NewLabel(t, lops...) bg := gio.NewBackground( gio.Color(color.RGBA{A: 0xff, R: 0xf0, G: 0xf0, B: 0xe0}), @@ -96,8 +95,10 @@ func NewCal(sm *SelectableMonth) gio.Widget { } func eventloop() { - w := app.NewWindow(&app.WindowOptions{ - Width: ui.Dp(600), Height: ui.Dp(600), Title: "Tickets"}) + w := app.NewWindow( + app.WithWidth(ui.Dp(600)), + app.WithHeight(ui.Dp(600)), + app.WithTitle("Calendar")) ctx := gio.NewContext(w) sm := NewMonth(time.Now()) @@ -105,18 +106,24 @@ func eventloop() { face = ctx.Faces.For(regular, ui.Sp(20)) if err != nil { log.Fatal("Cannot parse font.") } - margin := gio.NewInset(gio.Size(ui.Dp(10))) - topgrid := gio.NewGrid(3) - lbtn := NewButton(" < ") - mth := gio.NewLabel("", gio.Face(face), gio.Align(text.Center)) - rbtn := NewButton(" > ") - f1 := gio.NewFlex(gio.Axis(layout.Vertical)) - bg := gio.NewBackground( gio.Color(color.RGBA{A: 0xff, R: 0xf0, G: 0xf0, B: 0xe0})) + margin := gio.NewInset(gio.Size(ui.Dp(10))) + f1 := gio.NewFlex(gio.Axis(layout.Vertical)) + f2 := gio.NewFlex(gio.Axis(layout.Horizontal)) + sidegrid := gio.NewGrid(1) + yrs := make([]gio.Widget,6) + curyr := sm.Year + + topgrid := gio.NewGrid(3) + lbtn := NewButton(" < ") + mth := gio.NewLabel("", gio.Face(face), gio.Align(text.Middle)) + rbtn := NewButton(" > ") + var cal gio.Widget + 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)) @@ -128,6 +135,10 @@ func eventloop() { resetCal := func() { cal = NewCal(sm) + for i,_ := range yrs { + yrs[i] = NewButton(fmt.Sprintf("%d",curyr - i), + gio.Align(text.Start)) + } w.Invalidate() } resetCal() @@ -137,18 +148,23 @@ func eventloop() { switch e := e.(type) { case app.DestroyEvent: return - case app.DrawEvent: + case app.UpdateEvent: ctx.Reset(e) mth.SetText(fmt.Sprintf("%s %d",sm.Month.String(),sm.Year)) ows := sm.Ws bg(margin(f1( - topgrid(lbtn,mth,rbtn), - daygrid(sun,mon,tue,wed,thu,fri,sat), - cal, + topgrid(lbtn,mth,rbtn), + f2( + sidegrid(yrs...), + f3( + daygrid(sun,mon,tue,wed,thu,fri,sat), + cal, + ), + ), ))).Layout(ctx) - ctx.Draw() + ctx.Update() for i := time.Sunday; i < 7; i++ { switch { @@ -168,6 +184,13 @@ func eventloop() { sm.Next() resetCal() } + for i,y := range yrs { + if y.(gio.Clickable).Clicked(ctx) { + sm.Year = curyr - i + sm.Refresh() + resetCal() + } + } sm.CheckSel() } }} diff --git a/cmd/hello/main.go b/cmd/hello/main.go index 700dbee..1f33245 100644 --- a/cmd/hello/main.go +++ b/cmd/hello/main.go @@ -3,6 +3,7 @@ package main import ( "git.wow.st/gmp/giowrap" + "image" "image/color" "log" "os" @@ -13,7 +14,7 @@ import ( "gioui.org/ui" "gioui.org/ui/app" - gdraw "gioui.org/ui/draw" + "gioui.org/ui/paint" "gioui.org/ui/f32" "gioui.org/ui/gesture" "gioui.org/ui/layout" @@ -35,7 +36,7 @@ var ( ) func NewButton(face text.Face, t string, c color.RGBA) giowrap.Clickable { - lbl := giowrap.NewLabel(t, giowrap.Face(face), giowrap.Align(text.Center)) + lbl := giowrap.NewLabel(t, giowrap.Face(face), giowrap.Align(text.Middle)) bg := giowrap.NewBackground(giowrap.Color(c), giowrap.Radius(ui.Dp(4))) return giowrap.AsClickable(bg(lbl)) } @@ -79,7 +80,7 @@ hello [main1|main2] } func main1() { - w := app.NewWindow(nil) + w := app.NewWindow() regular, err := sfnt.Parse(goregular.TTF) if err != nil { log.Fatal("Cannot parse font.") @@ -114,7 +115,7 @@ func main1() { switch e := e.(type) { case app.DestroyEvent: return - case app.DrawEvent: + case app.UpdateEvent: ctx.Reset(e) OuterInset( f1( @@ -128,7 +129,7 @@ func main1() { InnerInset(btn2), ), )).Layout(ctx) - ctx.Draw() + ctx.Update() if btn1.Clicked(ctx) { log.Print("Clicked: " + e1.Text() ) } @@ -161,7 +162,7 @@ func main1() { } func main2() { - w := app.NewWindow(nil) + w := app.NewWindow() q := w.Queue() ops := new(ui.Ops) var faces measure.Faces @@ -216,7 +217,7 @@ func main2() { switch e := e.(type) { case app.DestroyEvent: return - case app.DrawEvent: + case app.UpdateEvent: c := &e.Config ops.Reset() faces.Reset(c) @@ -239,14 +240,14 @@ func main2() { cs = b1ins.Begin(c, ops, cs) dims = btn1.Layout(ops, cs) dims = b1ins.End(dims) - pointer.RectAreaOp{Size: dims.Size}.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) r := float32(c.Px(ui.Dp(4))) giowrap.Rrect(ops, wi, h, r, r, r, r) - gdraw.ColorOp{Color: color.RGBA{A: 0xff, R: 0x3c, G: 0x98, B: 0xc6}}.Add(ops) - gdraw.DrawOp{Rect: f32.Rectangle{Max: f32.Point{X: wi, Y: h}}}.Add(ops) + paint.ColorOp{Color: color.RGBA{A: 0xff, R: 0x3c, G: 0x98, B: 0xc6}}.Add(ops) + paint.PaintOp{Rect: f32.Rectangle{Max: f32.Point{X: wi, Y: h}}}.Add(ops) bg1.Add(ops) dims = InnerInset.End(dims) f2c1 := f2.End(dims) @@ -256,13 +257,13 @@ func main2() { cs = b2ins.Begin(c, ops, cs) dims = btn2.Layout(ops, cs) dims = b2ins.End(dims) - pointer.RectAreaOp{Size: dims.Size}.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) giowrap.Rrect(ops, wi, h, r, r, r, r) - gdraw.ColorOp{Color: color.RGBA{A: 0xff, R: 0x3c, G: 0x98, B: 0xc6}}.Add(ops) - gdraw.DrawOp{Rect: f32.Rectangle{Max: f32.Point{X: wi, Y: h}}}.Add(ops) + paint.ColorOp{Color: color.RGBA{A: 0xff, R: 0x3c, G: 0x98, B: 0xc6}}.Add(ops) + paint.PaintOp{Rect: f32.Rectangle{Max: f32.Point{X: wi, Y: h}}}.Add(ops) bg2.Add(ops) dims = InnerInset.End(dims) f2c2 := f2.End(dims) @@ -270,13 +271,13 @@ func main2() { f1c3 := f1.End(dims) dims = f1.Layout(f1c1, f1c2, f1c3) dims = OuterInset.End(dims) - w.Draw(ops) - for _,ev := range click1.Events(q) { + 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() ) } } - for _, ev := range click2.Events(q) { + for ev, ok := click2.Next(q); ok; ev, ok = click2.Next(q) { if ev.Type == gesture.TypeClick { log.Print("Clicked: " + e2.Text() ) } diff --git a/main.go b/main.go index 5609fa3..d3269c2 100644 --- a/main.go +++ b/main.go @@ -14,7 +14,7 @@ import ( "gioui.org/ui/text" "gioui.org/ui/f32" - gdraw "gioui.org/ui/draw" + "gioui.org/ui/paint" "gioui.org/ui/gesture" "gioui.org/ui/pointer" ) @@ -56,15 +56,15 @@ func NewContext(w *app.Window) *Context { } } -func (ctx *Context) Reset(e app.DrawEvent) { +func (ctx *Context) Reset(e app.UpdateEvent) { ctx.c = &e.Config ctx.ops.Reset() ctx.cs = layout.RigidConstraints(e.Size) ctx.Faces.Reset(ctx.c) } -func (ctx *Context) Draw() { - ctx.w.Draw(ctx.ops) +func (ctx *Context) Update() { + ctx.w.Update(ctx.ops) } type Layout func(*Context) @@ -193,22 +193,18 @@ func Rigid() Widget { type AxisOpt struct { axis layout.Axis } func Axis(x layout.Axis) AxisOpt { return AxisOpt{ x } } -type MainAxisAlignmentOpt struct { mainAxisAlignment layout.MainAxisAlignment } -func MainAxisAlignment(x layout.MainAxisAlignment) MainAxisAlignmentOpt { return MainAxisAlignmentOpt{ x } } -type CrossAxisAlignmentOpt struct { crossAxisAlignment layout.CrossAxisAlignment } -func CrossAxisAlignment(x layout.CrossAxisAlignment) CrossAxisAlignmentOpt { return CrossAxisAlignmentOpt{ x } } +type AlignmentOpt struct { alignment layout.Alignment } +func Alignment(x layout.Alignment) AlignmentOpt { return AlignmentOpt{ x } } type FlexOpts struct { AxisOpt - MainAxisAlignmentOpt - CrossAxisAlignmentOpt + AlignmentOpt flexible float32 } type FlexOption interface { DoFlexOption(*FlexOpts) } func (x AxisOpt) DoFlexOption(o *FlexOpts) { o.axis = x.axis } -func (x MainAxisAlignmentOpt) DoFlexOption(o *FlexOpts) { o.mainAxisAlignment = x.mainAxisAlignment } -func (x CrossAxisAlignmentOpt) DoFlexOption(o *FlexOpts) { o.crossAxisAlignment = x.crossAxisAlignment } +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 { @@ -216,8 +212,7 @@ func NewFlex(fos ...FlexOption) Flex { for _,o := range fos { o.DoFlexOption(opts) } f := layout.Flex{ Axis: opts.axis, - MainAxisAlignment: opts.mainAxisAlignment, - CrossAxisAlignment: opts.crossAxisAlignment, + Alignment: opts.alignment, } index := extra.New() extra.data[index] = opts @@ -361,8 +356,8 @@ func (bg *Background) End(ctx *Context) { } Rrect(ctx.ops, w, h, r, r, r, r) } - gdraw.ColorOp{Color: bg.Color}.Add(ctx.ops) - gdraw.DrawOp{Rect: f32.Rectangle{Max: f32.Point{X: w, Y: h}}}.Add(ctx.ops) + paint.ColorOp{Color: bg.Color}.Add(ctx.ops) + paint.PaintOp{Rect: f32.Rectangle{Max: f32.Point{X: w, Y: h}}}.Add(ctx.ops) bg.macro.Add(ctx.ops) stack.Pop() } @@ -371,7 +366,7 @@ func (bg *Background) End(ctx *Context) { func Rrect(ops *ui.Ops, width, height, se, sw, nw, ne float32) { w, h := float32(width), float32(height) const c = 0.55228475 // 4*(sqrt(2)-1)/3 - var b gdraw.PathBuilder + var b paint.PathBuilder b.Init(ops) b.Move(f32.Point{X: w, Y: h - se}) b.Cube(f32.Point{X: 0, Y: se * c}, f32.Point{X: -se + se*c, Y: se}, f32.Point{X: -se, Y: se}) // SE @@ -397,12 +392,12 @@ type cWidget struct { func (w cWidget) Layout(ctx *Context) { w.w.Layout(ctx) - pointer.RectAreaOp{Size: ctx.dims.Size}.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) } func (w cWidget) Clicked(ctx *Context) bool { - for _,e := range w.click.Events(ctx.q) { + for e, ok := w.click.Next(ctx.q); ok; e, ok = w.click.Next(ctx.q) { if e.Type == gesture.TypeClick { ctx.w.Invalidate() return true @@ -417,9 +412,8 @@ func AsClickable(w Widget) cWidget { } type Grid struct { - Axis layout.Axis Cols int - Height int + Height, Width int macro ui.MacroOp ops *ui.Ops @@ -446,11 +440,14 @@ func (g *Grid) Init(ops *ui.Ops, cs layout.Constraints) layout.Constraints { g.row, g.col = 0, 0 cs.Height.Min = 0 - if g.Height != 0 { - cs.Height.Max = g.Height - } + + 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 - cs.Width.Min = cs.Width.Max + if g.Cols > 1 { + cs.Width.Min = cs.Width.Max + } return cs } @@ -470,6 +467,7 @@ 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) @@ -479,10 +477,17 @@ func (g *Grid) Layout(cs ...GridChild) layout.Dimens { rowheight = c.dims.Size.Y } g.col = g.col+1 - x := float32(g.cs.Width.Max / g.Cols) - ui.TransformOp{}.Offset(f32.Point{X: x}).Add(g.ops) - width = width + x - if g.col >= g.Cols { + 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 @@ -493,15 +498,30 @@ func (g *Grid) Layout(cs ...GridChild) layout.Dimens { } if height == 0 { height = rowheight } g.mode = modeNone - return layout.Dimens{ Size: image.Point{ g.cs.Width.Max, height } } + 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)} } -func NewGrid(cols int) WidgetCombinator { +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) {