Refactor into a package.
This commit is contained in:
		
							parent
							
								
									e1fc40e6c6
								
							
						
					
					
						commit
						86245ad484
					
				
							
								
								
									
										75
									
								
								cmd/hello/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								cmd/hello/main.go
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,75 @@ | |||
| package main | ||||
| 
 | ||||
| import ( | ||||
| 	"git.wow.st/gmp/giowrap" | ||||
| 
 | ||||
| 	"log" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"gioui.org/ui" | ||||
| 	"gioui.org/ui/app" | ||||
| 	"gioui.org/ui/layout" | ||||
| 	"gioui.org/ui/text" | ||||
| 
 | ||||
| 	"golang.org/x/image/font/sfnt" | ||||
| 	"golang.org/x/image/font/gofont/goregular" | ||||
| ) | ||||
| 
 | ||||
| func main() { | ||||
| 	go func() { | ||||
| 		w := app.NewWindow(nil) | ||||
| 		regular, err := sfnt.Parse(goregular.TTF) | ||||
| 		if err != nil { | ||||
| 			log.Fatal("Cannot parse font.") | ||||
| 		} | ||||
| 		ctx := giowrap.NewContext(w) | ||||
| 		t := time.NewTicker(time.Second/30) | ||||
| 		e1 := giowrap.NewEditor(ctx.Faces.For(regular, ui.Sp(24)), true) | ||||
| 		e1.SetText("hi there") | ||||
| 		e1.Focus() | ||||
| 
 | ||||
| 		e2 := giowrap.NewEditor(ctx.Faces.For(regular, ui.Sp(24)), true) | ||||
| 		e2.SetText("ok bye") | ||||
| 
 | ||||
| 		f := giowrap.NewFlex(layout.Vertical, layout.Start, layout.Start) | ||||
| 		OuterInset := giowrap.NewInset(ui.Dp(10),ui.Dp(10),ui.Dp(10),ui.Dp(10)) | ||||
| 		InnerInset := giowrap.NewInset(ui.Dp(10),ui.Dp(10),ui.Dp(10),ui.Dp(10)) | ||||
| 
 | ||||
| 		lbl := giowrap.NewButton( | ||||
| 			ctx.Faces.For(regular, ui.Sp(24)), | ||||
| 			"centered", | ||||
| 			text.Center, | ||||
| 		) | ||||
| 		bg := giowrap.NewBackground(giowrap.Rgb(0x3c98c6), ui.Dp(4)) | ||||
| 		btn := bg(lbl) | ||||
| 
 | ||||
| 		for { | ||||
| 			select { | ||||
| 			case <-t.C: | ||||
| 				w.Invalidate() | ||||
| 			case e := <-w.Events(): | ||||
| 				switch e := e.(type) { | ||||
| 				case app.DestroyEvent: | ||||
| 					return | ||||
| 				case app.DrawEvent: | ||||
| 					ctx.Reset(e) | ||||
| 					ctx = giowrap.LayoutWithContext(ctx, | ||||
| 						OuterInset( | ||||
| 						    f( | ||||
| 							e1, | ||||
| 							f.Flexible(5), | ||||
| 							InnerInset(e2), | ||||
| 							f.Flexible(10), | ||||
| 							btn, | ||||
| 						))) | ||||
| 					ctx.Draw() | ||||
| 					if lbl.Clicked(ctx) { | ||||
| 						log.Print("Clicked: " + e2.Text() ) | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	}() | ||||
| 	app.Main() | ||||
| } | ||||
| 
 | ||||
							
								
								
									
										243
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										243
									
								
								main.go
									
									
									
									
									
								
							|  | @ -1,8 +1,8 @@ | |||
| package main | ||||
| package giowrap | ||||
| 
 | ||||
| import ( | ||||
| 	"image/color" | ||||
| 	"log" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"gioui.org/ui" | ||||
| 	"gioui.org/ui/app" | ||||
|  | @ -11,23 +11,27 @@ import ( | |||
| 	"gioui.org/ui/measure" | ||||
| 	"gioui.org/ui/text" | ||||
| 
 | ||||
| 	"golang.org/x/image/font/gofont/goregular" | ||||
| 	"golang.org/x/image/font/sfnt" | ||||
| 	"gioui.org/ui/f32" | ||||
| 	gdraw "gioui.org/ui/draw" | ||||
| 	"gioui.org/ui/gesture" | ||||
| 	"gioui.org/ui/pointer" | ||||
| ) | ||||
| 
 | ||||
| type Context struct { | ||||
| 	Faces measure.Faces | ||||
| 
 | ||||
| 	w *app.Window | ||||
| 	c *app.Config | ||||
| 	q input.Queue | ||||
| 	ops *ui.Ops | ||||
| 	cs layout.Constraints | ||||
| 	dims layout.Dimens | ||||
| 	faces measure.Faces | ||||
| 	extra map[string]interface{} | ||||
| } | ||||
| 
 | ||||
| func NewContext(w *app.Window) Context { | ||||
| 	return Context{ | ||||
| 		w: w, | ||||
| 		ops: new(ui.Ops), | ||||
| 		q: w.Queue(), | ||||
| 		extra: make(map[string]interface{}), | ||||
|  | @ -38,7 +42,30 @@ func (ctx *Context) Reset(e app.DrawEvent) { | |||
| 	ctx.c = &e.Config | ||||
| 	ctx.ops.Reset() | ||||
| 	ctx.cs = layout.RigidConstraints(e.Size) | ||||
| 	ctx.faces.Reset(ctx.c) | ||||
| 	ctx.Faces.Reset(ctx.c) | ||||
| } | ||||
| 
 | ||||
| func (ctx Context) Draw() { | ||||
| 	ctx.w.Draw(ctx.ops) | ||||
| } | ||||
| 
 | ||||
| type Layout func(Context) Context | ||||
| 
 | ||||
| type LayoutCombinator func(...Layout) Layout | ||||
| 
 | ||||
| func LayoutWithContext(ctx Context, ls ...Widget) Context { | ||||
| 	for _, l := range ls { | ||||
| 		ctx = l.Layout(ctx) | ||||
| 	} | ||||
| 	return ctx | ||||
| } | ||||
| 
 | ||||
| type fWidget struct { | ||||
| 	l Layout | ||||
| } | ||||
| 
 | ||||
| func NewfWidget(l Layout) fWidget { | ||||
| 	return fWidget{ l: l } | ||||
| } | ||||
| 
 | ||||
| func (fw fWidget) Layout(ctx Context) Context { | ||||
|  | @ -51,30 +78,37 @@ type Widget interface { | |||
| 
 | ||||
| type WidgetCombinator func(...Widget) Widget | ||||
| 
 | ||||
| type fWidget struct { | ||||
| 	l Layout | ||||
| } | ||||
| 
 | ||||
| type Layout func(Context) Context | ||||
| 
 | ||||
| type LayoutCombinator func(...Layout) Layout | ||||
| 
 | ||||
| func LayoutWithContext(ctx Context, ls ...Layout) Context { | ||||
| 	for _, l := range ls { | ||||
| 		ctx = l(ctx) | ||||
| 	} | ||||
| 	return ctx | ||||
| } | ||||
| 
 | ||||
| type Label struct { | ||||
| type Button struct { | ||||
| 	l *text.Label | ||||
| 	click gesture.Click | ||||
| } | ||||
| 
 | ||||
| func (l *Label) Layout(ctx Context) Context { | ||||
| 	ctx.dims = l.l.Layout(ctx.ops, ctx.cs) | ||||
| func NewButton(face text.Face, t string, alignment text.Alignment) *Button { | ||||
| 	ret := &Button{} | ||||
| 	ret.l = &text.Label{ | ||||
| 		Face: face, | ||||
| 		Text: t, | ||||
| 		Alignment: alignment, | ||||
| 	} | ||||
| 	return ret | ||||
| } | ||||
| 
 | ||||
| func (b *Button) Layout(ctx Context) Context { | ||||
| 	ctx.dims = b.l.Layout(ctx.ops, ctx.cs) | ||||
| 	pointer.RectAreaOp{Size: ctx.dims.Size}.Add(ctx.ops) | ||||
| 	b.click.Add(ctx.ops) | ||||
| 	return ctx | ||||
| } | ||||
| 
 | ||||
| func (b *Button) Clicked(ctx Context) bool { | ||||
| 	for _,e := range b.click.Events(ctx.q) { | ||||
| 		if e.Type == gesture.TypeClick { | ||||
| 			return true | ||||
| 		} | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
| 
 | ||||
| type Editor struct { | ||||
| 	e *text.Editor | ||||
| } | ||||
|  | @ -90,57 +124,24 @@ func (e *Editor) Layout(ctx Context) Context { | |||
| 	return ctx | ||||
| } | ||||
| 
 | ||||
| func main() { | ||||
| 	go func() { | ||||
| 		w := app.NewWindow(nil) | ||||
| 		regular, err := sfnt.Parse(goregular.TTF) | ||||
| 		if err != nil { | ||||
| 			log.Fatal("Cannot parse font.") | ||||
| 		} | ||||
| 		ctx := NewContext(w) | ||||
| 		t := time.NewTicker(time.Second/30) | ||||
| 		e1 := NewEditor(ctx.faces.For(regular, ui.Sp(24)), true) | ||||
| 		e1.e.SetText("hi there") | ||||
| 		e1.e.Focus() | ||||
| 
 | ||||
| 		e2 := NewEditor( ctx.faces.For(regular, ui.Sp(24)), true) | ||||
| 		e2.e.SetText("ok bye") | ||||
| 
 | ||||
| 		f := NewFlex(layout.Vertical, layout.Start, layout.Start) | ||||
| 		ins10a := NewInset(ui.Dp(10),ui.Dp(10),ui.Dp(10),ui.Dp(10)) | ||||
| 		ins10b := NewInset(ui.Dp(10),ui.Dp(10),ui.Dp(10),ui.Dp(10)) | ||||
| 
 | ||||
| 		btn := &Label{} | ||||
| 		btn.l = &text.Label{ | ||||
| 			Face: ctx.faces.For(regular, ui.Sp(24)), | ||||
| 			Text: "centered", | ||||
| 			Alignment: text.Center, | ||||
| func (e *Editor) Text() string { | ||||
| 	return e.e.Text() | ||||
| } | ||||
| 
 | ||||
| 		for { | ||||
| 			select { | ||||
| 			case <-t.C: | ||||
| 				w.Invalidate() | ||||
| 			case e := <-w.Events(): | ||||
| 				switch e := e.(type) { | ||||
| 				case app.DestroyEvent: | ||||
| 					return | ||||
| 				case app.DrawEvent: | ||||
| 					ctx.Reset(e) | ||||
| 					LayoutWithContext(ctx, | ||||
| 						ins10a(f( | ||||
| 							e1, | ||||
| 							Flexible(5), | ||||
| 							ins10b(e2), | ||||
| 							Flexible(10), | ||||
| 							btn, | ||||
| 						)).Layout) | ||||
| 					w.Draw(ctx.ops) | ||||
| func (e *Editor) SetText(s string) { | ||||
| 	e.e.SetText(s) | ||||
| } | ||||
| 
 | ||||
| func (e *Editor) Focus() { | ||||
| 	e.e.Focus() | ||||
| } | ||||
| 
 | ||||
| func Rgb(c uint32) color.RGBA { | ||||
| 	return Argb((0xff << 24) | c) | ||||
| } | ||||
| 	}() | ||||
| 	app.Main() | ||||
| 
 | ||||
| func Argb(c uint32) color.RGBA { | ||||
| 	return color.RGBA{A: uint8(c >> 24), R: uint8(c >> 16), G: uint8(c >> 8), B: uint8(c)} | ||||
| } | ||||
| 
 | ||||
| type FlexChild struct { | ||||
|  | @ -148,24 +149,23 @@ type FlexChild struct { | |||
| 	w Widget | ||||
| } | ||||
| 
 | ||||
| func Flexible(v float32) Widget { | ||||
| 	ret := fWidget{} | ||||
| 	ret.l = func(ctx Context) Context { | ||||
| type Flex WidgetCombinator | ||||
| 
 | ||||
| func (f Flex) Flexible(v float32) Widget { | ||||
| 	return NewfWidget(func(ctx Context) Context { | ||||
| 		ctx.extra["Flexible"] = v | ||||
| 		return ctx | ||||
| 	} | ||||
| 	return ret | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| func NewFlex(axis layout.Axis, mainAxisAlignment layout.MainAxisAlignment, crossAxisAlignment layout.CrossAxisAlignment) WidgetCombinator { | ||||
| func NewFlex(axis layout.Axis, mainAxisAlignment layout.MainAxisAlignment, crossAxisAlignment layout.CrossAxisAlignment) Flex { | ||||
| 	f := layout.Flex{ | ||||
| 		Axis: axis, | ||||
| 		MainAxisAlignment: mainAxisAlignment, | ||||
| 		CrossAxisAlignment: crossAxisAlignment, | ||||
| 	} | ||||
| 	return func(ws ...Widget) Widget { | ||||
| 		ret := fWidget{} | ||||
| 		ret.l = func(ctx Context) Context { | ||||
| 		return NewfWidget(func(ctx Context) Context { | ||||
| 			f.Init(ctx.ops, ctx.cs) | ||||
| 			fcs := make([]layout.FlexChild,len(ws)) | ||||
| 			for i, w := range ws { | ||||
|  | @ -185,16 +185,14 @@ func NewFlex(axis layout.Axis, mainAxisAlignment layout.MainAxisAlignment, cross | |||
| 			ctx.dims = f.Layout(fcs...) | ||||
| 			delete(ctx.extra, "Flexible") | ||||
| 			return ctx | ||||
| 		} | ||||
| 		return ret | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func NewInset(top, right, bottom, left ui.Value) WidgetCombinator { | ||||
| 	ins := layout.Inset{ Top: top, Right: right, Bottom: bottom, Left: left } | ||||
| 	return func(ws ...Widget) Widget { | ||||
| 		ret := fWidget{} | ||||
| 		ret.l = func(ctx Context) Context { | ||||
| 		return NewfWidget(func(ctx Context) Context { | ||||
| 			ctx.cs = ins.Begin(ctx.c, ctx.ops, ctx.cs) | ||||
| 			var dims layout.Dimens | ||||
| 			for _, w := range ws { | ||||
|  | @ -202,8 +200,85 @@ func NewInset(top, right, bottom, left ui.Value) WidgetCombinator { | |||
| 			} | ||||
| 			ctx.dims = ins.End(dims) | ||||
| 			return ctx | ||||
| 		} | ||||
| 		return ret | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| type Background struct { | ||||
| 	Color color.RGBA | ||||
| 	Radius ui.Value | ||||
| 	Inset layout.Inset | ||||
| 
 | ||||
| 	macro ui.MacroOp | ||||
| } | ||||
| 
 | ||||
| type Enclosure interface { | ||||
| 	Begin(Context) Context | ||||
| 	End(Context) Context | ||||
| } | ||||
| 
 | ||||
| func Enclose(e Enclosure, ws ...Widget) Widget { | ||||
| 	return NewfWidget(func(ctx Context) Context { | ||||
| 		ctx = e.Begin(ctx) | ||||
| 		for _,w := range ws { | ||||
| 			ctx = w.Layout(ctx) | ||||
| 		} | ||||
| 		ctx = e.End(ctx) | ||||
| 		return ctx | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| func NewBackground(color color.RGBA, radius ui.Value) WidgetCombinator { | ||||
| 	bg := &Background{ | ||||
| 		Color: color, | ||||
| 		Radius: radius, | ||||
| 		Inset: layout.UniformInset(radius), 	// FIXME: need to be able to
 | ||||
| 	}						// do math ops on Values
 | ||||
| 	return func(ws ...Widget) Widget { | ||||
| 		return Enclose(bg, ws...) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (bg *Background) Begin(ctx Context) Context { | ||||
| 	bg.macro.Record(ctx.ops) | ||||
| 	ctx.cs = bg.Inset.Begin(ctx.c, ctx.ops, ctx.cs) | ||||
| 	return ctx | ||||
| } | ||||
| 
 | ||||
| func (bg *Background) End(ctx Context) Context { | ||||
| 	ctx.dims = bg.Inset.End(ctx.dims) | ||||
| 	bg.macro.Stop() | ||||
| 	//var stack ui.StackOp
 | ||||
| 	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 { | ||||
| 			r = w / 2 | ||||
| 		} | ||||
| 		if r > h / 2 { | ||||
| 			r = h / 2 | ||||
| 		} | ||||
| 		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) | ||||
| 	bg.macro.Add(ctx.ops) | ||||
| 	return ctx | ||||
| } | ||||
| 
 | ||||
| // https://pomax.github.io/bezierinfo/#circles_cubic.
 | ||||
| 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 | ||||
| 	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
 | ||||
| 	b.Line(f32.Point{X: sw - w + se, Y: 0}) | ||||
| 	b.Cube(f32.Point{X: -sw * c, Y: 0}, f32.Point{X: -sw, Y: -sw + sw*c}, f32.Point{X: -sw, Y: -sw}) // SW
 | ||||
| 	b.Line(f32.Point{X: 0, Y: nw - h + sw}) | ||||
| 	b.Cube(f32.Point{X: 0, Y: -nw * c}, f32.Point{X: nw - nw*c, Y: -nw}, f32.Point{X: nw, Y: -nw}) // NW
 | ||||
| 	b.Line(f32.Point{X: w - ne - nw, Y: 0}) | ||||
| 	b.Cube(f32.Point{X: ne * c, Y: 0}, f32.Point{X: ne, Y: ne - ne*c}, f32.Point{X: ne, Y: ne}) // NE
 | ||||
| 	b.End() | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user