github.com/Seikaijyu/gio@v0.0.1/io/router/semantic_test.go (about)

     1  // SPDX-License-Identifier: Unlicense OR MIT
     2  
     3  package router
     4  
     5  import (
     6  	"fmt"
     7  	"image"
     8  	"reflect"
     9  	"testing"
    10  
    11  	"github.com/Seikaijyu/gio/f32"
    12  	"github.com/Seikaijyu/gio/io/pointer"
    13  	"github.com/Seikaijyu/gio/io/semantic"
    14  	"github.com/Seikaijyu/gio/op"
    15  	"github.com/Seikaijyu/gio/op/clip"
    16  )
    17  
    18  func TestEmptySemantics(t *testing.T) {
    19  	var r Router
    20  	tree := r.AppendSemantics(nil)
    21  	if len(tree) != 1 {
    22  		t.Errorf("expected 1 semantic node for empty tree, got %d", len(tree))
    23  	}
    24  }
    25  
    26  func TestSemanticTree(t *testing.T) {
    27  	var (
    28  		ops op.Ops
    29  		r   Router
    30  	)
    31  	t1 := clip.Rect(image.Rect(0, 0, 75, 75)).Push(&ops)
    32  	semantic.DescriptionOp("child1").Add(&ops)
    33  	t1.Pop()
    34  	t2 := clip.Rect(image.Rect(25, 25, 100, 100)).Push(&ops)
    35  	semantic.DescriptionOp("child2").Add(&ops)
    36  	t2.Pop()
    37  	r.Frame(&ops)
    38  	tests := []struct {
    39  		x, y float32
    40  		desc string
    41  	}{
    42  		{24, 24, "child1"},
    43  		{50, 50, "child2"},
    44  		{100, 100, ""},
    45  	}
    46  	tree := r.AppendSemantics(nil)
    47  	verifyTree(t, 0, tree[0])
    48  	for _, test := range tests {
    49  		p := f32.Pt(test.x, test.y)
    50  		id, found := r.SemanticAt(p)
    51  		if !found {
    52  			t.Errorf("no semantic node at %v", p)
    53  		}
    54  		n, found := lookupNode(tree, id)
    55  		if !found {
    56  			t.Errorf("no id %d in semantic tree", id)
    57  		}
    58  		if got := n.Desc.Description; got != test.desc {
    59  			t.Errorf("got semantic description %s at %v, expected %s", got, p, test.desc)
    60  		}
    61  	}
    62  
    63  	// Verify stable IDs.
    64  	r.Frame(&ops)
    65  	tree2 := r.AppendSemantics(nil)
    66  	if !reflect.DeepEqual(tree, tree2) {
    67  		fmt.Println("First tree:")
    68  		printTree(0, tree[0])
    69  		fmt.Println("Second tree:")
    70  		printTree(0, tree2[0])
    71  		t.Error("same semantic description lead to differing trees")
    72  	}
    73  }
    74  
    75  func TestSemanticDescription(t *testing.T) {
    76  	var ops op.Ops
    77  	pointer.InputOp{Tag: new(int), Kinds: pointer.Press | pointer.Release}.Add(&ops)
    78  	semantic.DescriptionOp("description").Add(&ops)
    79  	semantic.LabelOp("label").Add(&ops)
    80  	semantic.Button.Add(&ops)
    81  	semantic.EnabledOp(false).Add(&ops)
    82  	semantic.SelectedOp(true).Add(&ops)
    83  	var r Router
    84  	r.Frame(&ops)
    85  	tree := r.AppendSemantics(nil)
    86  	got := tree[0].Desc
    87  	exp := SemanticDesc{
    88  		Class:       1,
    89  		Description: "description",
    90  		Label:       "label",
    91  		Selected:    true,
    92  		Disabled:    true,
    93  		Gestures:    ClickGesture,
    94  		Bounds:      image.Rectangle{Min: image.Point{X: -1e+06, Y: -1e+06}, Max: image.Point{X: 1e+06, Y: 1e+06}},
    95  	}
    96  	if got != exp {
    97  		t.Errorf("semantic description mismatch:\nGot:  %+v\nWant: %+v", got, exp)
    98  	}
    99  }
   100  
   101  func lookupNode(tree []SemanticNode, id SemanticID) (SemanticNode, bool) {
   102  	for _, n := range tree {
   103  		if id == n.ID {
   104  			return n, true
   105  		}
   106  	}
   107  	return SemanticNode{}, false
   108  }
   109  
   110  func verifyTree(t *testing.T, parent SemanticID, n SemanticNode) {
   111  	t.Helper()
   112  	if n.ParentID != parent {
   113  		t.Errorf("node %d: got parent %d, want %d", n.ID, n.ParentID, parent)
   114  	}
   115  	for _, c := range n.Children {
   116  		verifyTree(t, n.ID, c)
   117  	}
   118  }
   119  
   120  func printTree(indent int, n SemanticNode) {
   121  	for i := 0; i < indent; i++ {
   122  		fmt.Print("\t")
   123  	}
   124  	fmt.Printf("%d: %+v\n", n.ID, n.Desc)
   125  	for _, c := range n.Children {
   126  		printTree(indent+1, c)
   127  	}
   128  }