commit f3041515ab836bc0d851bb0ae30847ae328b7ef1
parent 414d6c95c04974df0c75c1bb8283ec55f1888e95
Author: Thomas Vigouroux <me@vigoux.eu>
Date: Fri, 26 Apr 2024 07:18:49 +0200
feat: add comment editor
Diffstat:
M | main.go | | | 98 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------- |
1 file changed, 73 insertions(+), 25 deletions(-)
diff --git a/main.go b/main.go
@@ -11,12 +11,15 @@ import (
"gioui.org/app"
"gioui.org/f32"
"gioui.org/io/event"
+ "gioui.org/io/key"
"gioui.org/io/pointer"
"gioui.org/layout"
"gioui.org/op"
"gioui.org/op/clip"
"gioui.org/op/paint"
"gioui.org/unit"
+ "gioui.org/widget"
+ "gioui.org/widget/material"
// "gioui.org/text"
// "gioui.org/widget/material"
@@ -24,19 +27,34 @@ import (
"github.com/rooklift/sgf"
)
-type Goban struct {
- Board *sgf.Board
+type App struct {
+ Node *sgf.Node
+ Editor material.EditorStyle
}
-func (g *Goban) Layout(gtx layout.Context) layout.Dimensions {
+func (g *App) SetNode(node *sgf.Node) {
+ // XXX: Maybe not the right place to do that
+ if g.Node != nil {
+ g.Node.SetValue("C", g.Editor.Editor.Text())
+ }
+
+ g.Node = node
+
+ val, ok := node.GetValue("C")
+ if ok {
+ g.Editor.Editor.SetText(val)
+ }
+}
+
+func (g *App) LayoutGoban(gtx layout.Context) layout.Dimensions {
size := min(gtx.Constraints.Max.X, gtx.Constraints.Max.Y)
black := color.NRGBA{A: 0xFF}
white := color.NRGBA{A: 0xFF, R: 0xFF, G: 0xFF, B: 0xFF}
- offset := float32(size) / float32(g.Board.Size)
// Handle inputs within the goban area
{
defer clip.Rect(image.Rect(0, 0, size, size)).Push(gtx.Ops).Pop()
+ offset := float32(size) / float32(g.Node.Board().Size)
event.Op(gtx.Ops, g)
@@ -44,30 +62,60 @@ func (g *Goban) Layout(gtx layout.Context) layout.Dimensions {
ev, ok := gtx.Event(pointer.Filter{
Target: g,
Kinds: pointer.Press,
+ }, key.Filter{
+ Name: key.NameDownArrow,
+ }, key.Filter{
+ Name: key.NameUpArrow,
})
if !ok {
break
}
- e, ok := ev.(pointer.Event)
- if !ok {
- continue
- }
-
- switch e.Kind {
- case pointer.Press:
- xpos := int(e.Position.X / offset)
- ypos := int(e.Position.Y / offset)
- g.Board.Play(sgf.Point(xpos, ypos))
+ switch ev.(type) {
+ case pointer.Event:
+ {
+ e := ev.(pointer.Event)
+ switch e.Kind {
+ case pointer.Press:
+ xpos := int(e.Position.X / offset)
+ ypos := int(e.Position.Y / offset)
+ newnode, err := g.Node.Play(sgf.Point(xpos, ypos))
+ if err == nil {
+ g.SetNode(newnode)
+ }
+ }
+ }
+ case key.Event:
+ {
+ e := ev.(key.Event)
+ log.Print(e)
+ if e.State == key.Press {
+ switch e.Name {
+ case key.NameDownArrow:
+ child := g.Node.MainChild()
+ if child != nil {
+ g.SetNode(child)
+ }
+ case key.NameUpArrow:
+ parent := g.Node.Parent()
+ if parent != nil {
+ g.SetNode(parent)
+ }
+ }
+ }
+ }
}
}
}
+ board := g.Node.Board()
+ offset := float32(size) / float32(board.Size)
+
// Draw the frame
var path clip.Path
path.Begin(gtx.Ops)
foffset := offset / 2
- for i := 0; i < g.Board.Size; i++ {
+ for i := 0; i < board.Size; i++ {
ioffset := float32(offset)*float32(i) + foffset
// Line from left to right
path.MoveTo(f32.Pt(ioffset, foffset))
@@ -84,10 +132,10 @@ func (g *Goban) Layout(gtx layout.Context) layout.Dimensions {
}.Op())
// Now draw the stones
- for x := 0; x < g.Board.Size; x++ {
- for y := 0; y < g.Board.Size; y++ {
- if g.Board.State[x][y] != sgf.EMPTY {
- scolor := g.Board.State[x][y]
+ for x := 0; x < board.Size; x++ {
+ for y := 0; y < board.Size; y++ {
+ if board.State[x][y] != sgf.EMPTY {
+ scolor := board.State[x][y]
fx := float32(x)
fy := float32(y)
rect := image.Rect(int(fx*offset), int(fy*offset), int((fx+1)*offset), int((fy+1)*offset))
@@ -136,10 +184,12 @@ func ColorBox(gtx layout.Context, size image.Point, color color.NRGBA) layout.Di
func run(window *app.Window) error {
// theme := material.NewTheme()
var ops op.Ops
+ th := material.NewTheme()
- goban := Goban{
- Board: sgf.NewBoard(19),
+ goban := App{
+ Editor: material.Editor(th, new(widget.Editor), ""),
}
+ goban.SetNode(sgf.LoadArgOrQuit(1))
for {
switch e := window.Event().(type) {
@@ -151,11 +201,9 @@ func run(window *app.Window) error {
layout.Flex{}.Layout(gtx,
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
- return layout.UniformInset(unit.Dp(30)).Layout(gtx, goban.Layout)
- }),
- layout.Flexed(0.5, func(gtx layout.Context) layout.Dimensions {
- return ColorBox(gtx, gtx.Constraints.Min, blue)
+ return layout.UniformInset(unit.Dp(30)).Layout(gtx, goban.LayoutGoban)
}),
+ layout.Flexed(0.5, goban.Editor.Layout),
)
// Pass the drawing operations to the GPU.