Skip to content

Commit

Permalink
Fix bug that the root view is not drawn (#62)
Browse files Browse the repository at this point in the history
Fix #61

Root view should call it's draw handlers method when it is set.
  • Loading branch information
yohamta authored Jun 11, 2023
1 parent 170e42a commit 78826a5
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 27 deletions.
2 changes: 2 additions & 0 deletions child_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,7 @@ type mockFlags struct {
IsReleased bool
IsCancel bool
IsUpdated bool
IsDrawn bool
IsMouseMoved bool
IsSwiped bool
}
Expand All @@ -362,6 +363,7 @@ func (h *mockHandler) HandleUpdate() {

func (h *mockHandler) HandleDraw(screen *ebiten.Image, frame image.Rectangle) {
h.Frame = frame
h.IsDrawn = true
}

func (h *mockHandler) HandlePress(x, y int, t ebiten.TouchID) {
Expand Down
68 changes: 42 additions & 26 deletions container.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,32 +29,48 @@ func (ct *containerEmbed) processEvent() {
// Draw draws it's children
func (ct *containerEmbed) Draw(screen *ebiten.Image) {
for _, c := range ct.children {
b := c.bounds
if !c.absolute {
b = c.bounds.Add(ct.frame.Min)
}
if !c.item.Hidden && c.item.Display != DisplayNone && c.item.Handler != nil {
for {
if h, ok := c.item.Handler.(DrawHandler); ok {
h.HandleDraw(screen, b)
break
}
if h, ok := c.item.Handler.(Drawer); ok {
h.Draw(screen, b, c.item)
break
}
break
}
}
c.item.Draw(screen)
if Debug {
pos := fmt.Sprintf("(%d, %d)-(%d, %d):%s:%s", b.Min.X, b.Min.Y, b.Max.X, b.Max.Y, c.item.TagName, c.item.ID)
graphic.FillRect(screen, &graphic.FillRectOpts{
Color: color.RGBA{0, 0, 0, 200},
Rect: image.Rect(b.Min.X, b.Min.Y, b.Min.X+len(pos)*6, b.Min.Y+12),
})
ebitenutil.DebugPrintAt(screen, pos, b.Min.X, b.Min.Y)
}
ct.drawChild(screen, c)
}
}

func (ct *containerEmbed) drawChild(screen *ebiten.Image, child *child) {
b := ct.computeBounds(child)
if ct.shouldDrawChild(child) {
ct.handleDraw(screen, b, child)
}
child.item.Draw(screen)
ct.debugDraw(screen, b, child)
}

func (ct *containerEmbed) computeBounds(child *child) image.Rectangle {
if child.absolute {
return child.bounds
}
return child.bounds.Add(ct.frame.Min)
}

func (ct *containerEmbed) handleDraw(screen *ebiten.Image, b image.Rectangle, child *child) {
if h, ok := child.item.Handler.(DrawHandler); ok {
h.HandleDraw(screen, b)
return
}
if h, ok := child.item.Handler.(Drawer); ok {
h.Draw(screen, b, child.item)
}
}

func (ct *containerEmbed) shouldDrawChild(child *child) bool {
return !child.item.Hidden && child.item.Display != DisplayNone && child.item.Handler != nil
}

func (ct *containerEmbed) debugDraw(screen *ebiten.Image, b image.Rectangle, child *child) {
if Debug {
pos := fmt.Sprintf("(%d, %d)-(%d, %d):%s:%s", b.Min.X, b.Min.Y, b.Max.X, b.Max.Y, child.item.TagName, child.item.ID)
graphic.FillRect(screen, &graphic.FillRectOpts{
Color: color.RGBA{0, 0, 0, 200},
Rect: image.Rect(b.Min.X, b.Min.Y, b.Min.X+len(pos)*6, b.Min.Y+12),
})
ebitenutil.DebugPrintAt(screen, pos, b.Min.X, b.Min.Y)
}
}

Expand Down
7 changes: 6 additions & 1 deletion html.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,12 @@ Loop:
panic(fmt.Sprintf("invalid html: %s", input))
}
view := dummy.PopChild()
view.Handler = opts.Handler
// the root view should be dirty for the first time
// even if the view does not have any children
view.isDirty = true
if opts.Handler != nil {
view.Handler = opts.Handler
}
return view
}

Expand Down
31 changes: 31 additions & 0 deletions html_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,37 @@ func TestParseHTML(t *testing.T) {
require.True(t, h.IsUpdated)
},
},
{
name: "root handler",
html: `
<body>
<mock-handler></mock-handler>
</body>`,
opts: &ParseOptions{
Components: map[string]Component{
"mock-handler": func() Handler {
return &mockHandler{}
},
},
Width: 100,
Height: 200,
},
expected: (&View{
Width: 100,
Height: 200,
}),
after: func(t *testing.T, v *View) {
v.Update()
v.Draw(nil)
h := v.Handler.(*mockHandler)
require.True(t, h.IsUpdated)
require.True(t, h.IsDrawn)
require.Equal(t, 0, h.Frame.Min.X)
require.Equal(t, 100, h.Frame.Max.X)
require.Equal(t, 0, h.Frame.Min.Y)
require.Equal(t, 200, h.Frame.Max.Y)
},
},
{
name: "hidden attribute",
html: `
Expand Down
13 changes: 13 additions & 0 deletions view.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@ func (v *View) Draw(screen *ebiten.Image) {
if v.isDirty {
v.startLayout()
}
if !v.hasParent {
v.handleDrawRoot(screen, v.frame)
}
if !v.Hidden && v.Display != DisplayNone {
v.containerEmbed.Draw(screen)
}
Expand Down Expand Up @@ -397,6 +400,16 @@ func (v *View) Config() ViewConfig {
return cfg
}

func (v *View) handleDrawRoot(screen *ebiten.Image, b image.Rectangle) {
if h, ok := v.Handler.(DrawHandler); ok {
h.HandleDraw(screen, b)
return
}
if h, ok := v.Handler.(Drawer); ok {
h.Draw(screen, b, v)
}
}

// This is for debugging and testing.
type ViewConfig struct {
TagName string
Expand Down

0 comments on commit 78826a5

Please sign in to comment.