Update gio version. Add side grid for year selection to cmd/cal.

This commit is contained in:
Greg 2019-08-22 14:40:30 -04:00
parent 25847d5921
commit 014ace99a6
5 changed files with 112 additions and 63 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
cmd/hello/hello cmd/hello/hello
cmd/cal/cal cmd/cal/cal
*.apk

View File

@ -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)) 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() { func (sm *SelectableMonth) Previous() {
m, y := sm.Month - 1, sm.Year m, y := sm.Month - 1, sm.Year
if m > 11 { if m > 11 {

View File

@ -13,7 +13,6 @@ import (
"gioui.org/ui" "gioui.org/ui"
"gioui.org/ui/app" "gioui.org/ui/app"
"gioui.org/ui/layout" "gioui.org/ui/layout"
//"gioui.org/ui/measure"
"gioui.org/ui/text" "gioui.org/ui/text"
"golang.org/x/image/font/sfnt" "golang.org/x/image/font/sfnt"
@ -33,7 +32,7 @@ func main() {
} }
func NewButton(t string, lops ...gio.LabelOption) gio.Clickable { 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...) lbl := gio.NewLabel(t, lops...)
bg := gio.NewBackground( bg := gio.NewBackground(
gio.Color(color.RGBA{A: 0xff, R: 0xf0, G: 0xf0, B: 0xe0}), gio.Color(color.RGBA{A: 0xff, R: 0xf0, G: 0xf0, B: 0xe0}),
@ -96,8 +95,10 @@ func NewCal(sm *SelectableMonth) gio.Widget {
} }
func eventloop() { func eventloop() {
w := app.NewWindow(&app.WindowOptions{ w := app.NewWindow(
Width: ui.Dp(600), Height: ui.Dp(600), Title: "Tickets"}) app.WithWidth(ui.Dp(600)),
app.WithHeight(ui.Dp(600)),
app.WithTitle("Calendar"))
ctx := gio.NewContext(w) ctx := gio.NewContext(w)
sm := NewMonth(time.Now()) sm := NewMonth(time.Now())
@ -105,18 +106,24 @@ func eventloop() {
face = ctx.Faces.For(regular, ui.Sp(20)) face = ctx.Faces.For(regular, ui.Sp(20))
if err != nil { log.Fatal("Cannot parse font.") } 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( bg := gio.NewBackground(
gio.Color(color.RGBA{A: 0xff, R: 0xf0, G: 0xf0, B: 0xe0})) 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 var cal gio.Widget
f3 := gio.NewFlex(gio.Axis(layout.Vertical))
daygrid := gio.NewGrid(7) daygrid := gio.NewGrid(7)
sun := NewSLabel("Sun",&sm.Ws[time.Sunday], 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)) mon := NewSLabel("Mon",&sm.Ws[time.Monday], gio.Align(text.End))
@ -128,6 +135,10 @@ func eventloop() {
resetCal := func() { resetCal := func() {
cal = NewCal(sm) cal = NewCal(sm)
for i,_ := range yrs {
yrs[i] = NewButton(fmt.Sprintf("%d",curyr - i),
gio.Align(text.Start))
}
w.Invalidate() w.Invalidate()
} }
resetCal() resetCal()
@ -137,7 +148,7 @@ func eventloop() {
switch e := e.(type) { switch e := e.(type) {
case app.DestroyEvent: case app.DestroyEvent:
return return
case app.DrawEvent: case app.UpdateEvent:
ctx.Reset(e) 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))
@ -145,10 +156,15 @@ func eventloop() {
ows := sm.Ws ows := sm.Ws
bg(margin(f1( bg(margin(f1(
topgrid(lbtn,mth,rbtn), topgrid(lbtn,mth,rbtn),
f2(
sidegrid(yrs...),
f3(
daygrid(sun,mon,tue,wed,thu,fri,sat), daygrid(sun,mon,tue,wed,thu,fri,sat),
cal, cal,
),
),
))).Layout(ctx) ))).Layout(ctx)
ctx.Draw() ctx.Update()
for i := time.Sunday; i < 7; i++ { for i := time.Sunday; i < 7; i++ {
switch { switch {
@ -168,6 +184,13 @@ func eventloop() {
sm.Next() sm.Next()
resetCal() resetCal()
} }
for i,y := range yrs {
if y.(gio.Clickable).Clicked(ctx) {
sm.Year = curyr - i
sm.Refresh()
resetCal()
}
}
sm.CheckSel() sm.CheckSel()
} }
}} }}

View File

@ -3,6 +3,7 @@ package main
import ( import (
"git.wow.st/gmp/giowrap" "git.wow.st/gmp/giowrap"
"image"
"image/color" "image/color"
"log" "log"
"os" "os"
@ -13,7 +14,7 @@ import (
"gioui.org/ui" "gioui.org/ui"
"gioui.org/ui/app" "gioui.org/ui/app"
gdraw "gioui.org/ui/draw" "gioui.org/ui/paint"
"gioui.org/ui/f32" "gioui.org/ui/f32"
"gioui.org/ui/gesture" "gioui.org/ui/gesture"
"gioui.org/ui/layout" "gioui.org/ui/layout"
@ -35,7 +36,7 @@ var (
) )
func NewButton(face text.Face, t string, c color.RGBA) giowrap.Clickable { 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))) bg := giowrap.NewBackground(giowrap.Color(c), giowrap.Radius(ui.Dp(4)))
return giowrap.AsClickable(bg(lbl)) return giowrap.AsClickable(bg(lbl))
} }
@ -79,7 +80,7 @@ hello [main1|main2]
} }
func main1() { func main1() {
w := app.NewWindow(nil) w := app.NewWindow()
regular, err := sfnt.Parse(goregular.TTF) regular, err := sfnt.Parse(goregular.TTF)
if err != nil { if err != nil {
log.Fatal("Cannot parse font.") log.Fatal("Cannot parse font.")
@ -114,7 +115,7 @@ func main1() {
switch e := e.(type) { switch e := e.(type) {
case app.DestroyEvent: case app.DestroyEvent:
return return
case app.DrawEvent: case app.UpdateEvent:
ctx.Reset(e) ctx.Reset(e)
OuterInset( OuterInset(
f1( f1(
@ -128,7 +129,7 @@ func main1() {
InnerInset(btn2), InnerInset(btn2),
), ),
)).Layout(ctx) )).Layout(ctx)
ctx.Draw() ctx.Update()
if btn1.Clicked(ctx) { if btn1.Clicked(ctx) {
log.Print("Clicked: " + e1.Text() ) log.Print("Clicked: " + e1.Text() )
} }
@ -161,7 +162,7 @@ func main1() {
} }
func main2() { func main2() {
w := app.NewWindow(nil) w := app.NewWindow()
q := w.Queue() q := w.Queue()
ops := new(ui.Ops) ops := new(ui.Ops)
var faces measure.Faces var faces measure.Faces
@ -216,7 +217,7 @@ func main2() {
switch e := e.(type) { switch e := e.(type) {
case app.DestroyEvent: case app.DestroyEvent:
return return
case app.DrawEvent: case app.UpdateEvent:
c := &e.Config c := &e.Config
ops.Reset() ops.Reset()
faces.Reset(c) faces.Reset(c)
@ -239,14 +240,14 @@ func main2() {
cs = b1ins.Begin(c, ops, cs) cs = b1ins.Begin(c, ops, cs)
dims = btn1.Layout(ops, cs) dims = btn1.Layout(ops, cs)
dims = b1ins.End(dims) 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) click1.Add(ops)
bg1.Stop() bg1.Stop()
wi, h := float32(dims.Size.X), float32(dims.Size.Y) wi, h := float32(dims.Size.X), float32(dims.Size.Y)
r := float32(c.Px(ui.Dp(4))) r := float32(c.Px(ui.Dp(4)))
giowrap.Rrect(ops, wi, h, r, r, r, r) giowrap.Rrect(ops, wi, h, r, r, r, r)
gdraw.ColorOp{Color: color.RGBA{A: 0xff, R: 0x3c, G: 0x98, B: 0xc6}}.Add(ops) paint.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.PaintOp{Rect: f32.Rectangle{Max: f32.Point{X: wi, Y: h}}}.Add(ops)
bg1.Add(ops) bg1.Add(ops)
dims = InnerInset.End(dims) dims = InnerInset.End(dims)
f2c1 := f2.End(dims) f2c1 := f2.End(dims)
@ -256,13 +257,13 @@ func main2() {
cs = b2ins.Begin(c, ops, cs) cs = b2ins.Begin(c, ops, cs)
dims = btn2.Layout(ops, cs) dims = btn2.Layout(ops, cs)
dims = b2ins.End(dims) 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) click2.Add(ops)
bg2.Stop() bg2.Stop()
wi, h = float32(dims.Size.X), float32(dims.Size.Y) wi, h = float32(dims.Size.X), float32(dims.Size.Y)
giowrap.Rrect(ops, wi, h, r, r, r, r) giowrap.Rrect(ops, wi, h, r, r, r, r)
gdraw.ColorOp{Color: color.RGBA{A: 0xff, R: 0x3c, G: 0x98, B: 0xc6}}.Add(ops) paint.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.PaintOp{Rect: f32.Rectangle{Max: f32.Point{X: wi, Y: h}}}.Add(ops)
bg2.Add(ops) bg2.Add(ops)
dims = InnerInset.End(dims) dims = InnerInset.End(dims)
f2c2 := f2.End(dims) f2c2 := f2.End(dims)
@ -270,13 +271,13 @@ func main2() {
f1c3 := f1.End(dims) f1c3 := f1.End(dims)
dims = f1.Layout(f1c1, f1c2, f1c3) dims = f1.Layout(f1c1, f1c2, f1c3)
dims = OuterInset.End(dims) dims = OuterInset.End(dims)
w.Draw(ops) w.Update(ops)
for _,ev := range click1.Events(q) { for ev, ok := click1.Next(q); ok; ev, ok = click1.Next(q) {
if ev.Type == gesture.TypeClick { if ev.Type == gesture.TypeClick {
log.Print("Clicked: " + e1.Text() ) 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 { if ev.Type == gesture.TypeClick {
log.Print("Clicked: " + e2.Text() ) log.Print("Clicked: " + e2.Text() )
} }

76
main.go
View File

@ -14,7 +14,7 @@ import (
"gioui.org/ui/text" "gioui.org/ui/text"
"gioui.org/ui/f32" "gioui.org/ui/f32"
gdraw "gioui.org/ui/draw" "gioui.org/ui/paint"
"gioui.org/ui/gesture" "gioui.org/ui/gesture"
"gioui.org/ui/pointer" "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.c = &e.Config
ctx.ops.Reset() ctx.ops.Reset()
ctx.cs = layout.RigidConstraints(e.Size) ctx.cs = layout.RigidConstraints(e.Size)
ctx.Faces.Reset(ctx.c) ctx.Faces.Reset(ctx.c)
} }
func (ctx *Context) Draw() { func (ctx *Context) Update() {
ctx.w.Draw(ctx.ops) ctx.w.Update(ctx.ops)
} }
type Layout func(*Context) type Layout func(*Context)
@ -193,22 +193,18 @@ func Rigid() Widget {
type AxisOpt struct { axis layout.Axis } type AxisOpt struct { axis layout.Axis }
func Axis(x layout.Axis) AxisOpt { return AxisOpt{ x } } func Axis(x layout.Axis) AxisOpt { return AxisOpt{ x } }
type MainAxisAlignmentOpt struct { mainAxisAlignment layout.MainAxisAlignment } type AlignmentOpt struct { alignment layout.Alignment }
func MainAxisAlignment(x layout.MainAxisAlignment) MainAxisAlignmentOpt { return MainAxisAlignmentOpt{ x } } func Alignment(x layout.Alignment) AlignmentOpt { return AlignmentOpt{ x } }
type CrossAxisAlignmentOpt struct { crossAxisAlignment layout.CrossAxisAlignment }
func CrossAxisAlignment(x layout.CrossAxisAlignment) CrossAxisAlignmentOpt { return CrossAxisAlignmentOpt{ x } }
type FlexOpts struct { type FlexOpts struct {
AxisOpt AxisOpt
MainAxisAlignmentOpt AlignmentOpt
CrossAxisAlignmentOpt
flexible float32 flexible float32
} }
type FlexOption interface { DoFlexOption(*FlexOpts) } type FlexOption interface { DoFlexOption(*FlexOpts) }
func (x AxisOpt) DoFlexOption(o *FlexOpts) { o.axis = x.axis } func (x AxisOpt) DoFlexOption(o *FlexOpts) { o.axis = x.axis }
func (x MainAxisAlignmentOpt) DoFlexOption(o *FlexOpts) { o.mainAxisAlignment = x.mainAxisAlignment } func (x AlignmentOpt) DoFlexOption(o *FlexOpts) { o.alignment = x.alignment }
func (x CrossAxisAlignmentOpt) DoFlexOption(o *FlexOpts) { o.crossAxisAlignment = x.crossAxisAlignment }
// NewFlex returns a WidgetCombinator that wraps the layout.Flex element. // NewFlex returns a WidgetCombinator that wraps the layout.Flex element.
func NewFlex(fos ...FlexOption) Flex { func NewFlex(fos ...FlexOption) Flex {
@ -216,8 +212,7 @@ func NewFlex(fos ...FlexOption) Flex {
for _,o := range fos { o.DoFlexOption(opts) } for _,o := range fos { o.DoFlexOption(opts) }
f := layout.Flex{ f := layout.Flex{
Axis: opts.axis, Axis: opts.axis,
MainAxisAlignment: opts.mainAxisAlignment, Alignment: opts.alignment,
CrossAxisAlignment: opts.crossAxisAlignment,
} }
index := extra.New() index := extra.New()
extra.data[index] = opts extra.data[index] = opts
@ -361,8 +356,8 @@ func (bg *Background) End(ctx *Context) {
} }
Rrect(ctx.ops, w, h, r, r, r, r) Rrect(ctx.ops, w, h, r, r, r, r)
} }
gdraw.ColorOp{Color: bg.Color}.Add(ctx.ops) paint.ColorOp{Color: bg.Color}.Add(ctx.ops)
gdraw.DrawOp{Rect: f32.Rectangle{Max: f32.Point{X: w, Y: h}}}.Add(ctx.ops) paint.PaintOp{Rect: f32.Rectangle{Max: f32.Point{X: w, Y: h}}}.Add(ctx.ops)
bg.macro.Add(ctx.ops) bg.macro.Add(ctx.ops)
stack.Pop() stack.Pop()
} }
@ -371,7 +366,7 @@ func (bg *Background) End(ctx *Context) {
func Rrect(ops *ui.Ops, width, height, se, sw, nw, ne float32) { func Rrect(ops *ui.Ops, width, height, se, sw, nw, ne float32) {
w, h := float32(width), float32(height) w, h := float32(width), float32(height)
const c = 0.55228475 // 4*(sqrt(2)-1)/3 const c = 0.55228475 // 4*(sqrt(2)-1)/3
var b gdraw.PathBuilder var b paint.PathBuilder
b.Init(ops) b.Init(ops)
b.Move(f32.Point{X: w, Y: h - se}) 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 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) { func (w cWidget) Layout(ctx *Context) {
w.w.Layout(ctx) 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) w.click.Add(ctx.ops)
} }
func (w cWidget) Clicked(ctx *Context) bool { 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 { if e.Type == gesture.TypeClick {
ctx.w.Invalidate() ctx.w.Invalidate()
return true return true
@ -417,9 +412,8 @@ func AsClickable(w Widget) cWidget {
} }
type Grid struct { type Grid struct {
Axis layout.Axis
Cols int Cols int
Height int Height, Width int
macro ui.MacroOp macro ui.MacroOp
ops *ui.Ops 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 g.row, g.col = 0, 0
cs.Height.Min = 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.Max = g.cs.Width.Max / g.Cols
if g.Cols > 1 {
cs.Width.Min = cs.Width.Max cs.Width.Min = cs.Width.Max
}
return cs return cs
} }
@ -470,6 +467,7 @@ func (g *Grid) Layout(cs ...GridChild) layout.Dimens {
rowheight := 0 rowheight := 0
height := 0 height := 0
var width float32 var width float32
var maxwidth float32
for _,c := range cs { for _,c := range cs {
var stack ui.StackOp var stack ui.StackOp
stack.Push(g.ops) stack.Push(g.ops)
@ -479,10 +477,17 @@ func (g *Grid) Layout(cs ...GridChild) layout.Dimens {
rowheight = c.dims.Size.Y rowheight = c.dims.Size.Y
} }
g.col = g.col+1 g.col = g.col+1
x := float32(g.cs.Width.Max / 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) ui.TransformOp{}.Offset(f32.Point{X: x}).Add(g.ops)
width = width + x width = width + x
if g.col >= g.Cols { } else {
g.col = 0 g.col = 0
ui.TransformOp{}.Offset(f32.Point{ X: -width, Y: float32(rowheight) }).Add(g.ops) ui.TransformOp{}.Offset(f32.Point{ X: -width, Y: float32(rowheight) }).Add(g.ops)
g.row = g.row + 1 g.row = g.row + 1
@ -493,15 +498,30 @@ func (g *Grid) Layout(cs ...GridChild) layout.Dimens {
} }
if height == 0 { height = rowheight } if height == 0 { height = rowheight }
g.mode = modeNone 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 { func toPointF(p image.Point) f32.Point {
return f32.Point{X: float32(p.X), Y: float32(p.Y)} 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 } g := &Grid{ Cols: cols }
for _, gop := range gops {
gop.DoGridOption(g)
}
gcs := make([]GridChild,0) gcs := make([]GridChild,0)
return func(ws ...Widget) Widget { return func(ws ...Widget) Widget {
return NewfWidget(func(ctx *Context) { return NewfWidget(func(ctx *Context) {