Sander Schobers
0f03760e66
Refactored Size (on Renderer) to return geom.Point instead of geom.PointF32. Refactored Width and Height (on Texture) to return int instead of float32. Refactored texture dimensions to be represented by ints instead of float32s.
152 lines
3.5 KiB
Go
152 lines
3.5 KiB
Go
package ui
|
|
|
|
import (
|
|
"image/color"
|
|
"reflect"
|
|
|
|
"opslag.de/schobers/geom"
|
|
|
|
"opslag.de/schobers/zntg"
|
|
)
|
|
|
|
const DefaultDebugOverlay = "ui-default-debug"
|
|
|
|
func controlChildren(control Control) []Control {
|
|
container, ok := control.(*ContainerBase)
|
|
if ok {
|
|
return container.Children
|
|
}
|
|
|
|
proxy, ok := control.(*Proxy)
|
|
if ok {
|
|
return []Control{proxy.Content}
|
|
}
|
|
return controlChildrenReflect(reflect.ValueOf(control))
|
|
}
|
|
|
|
func controlChildrenReflect(control reflect.Value) []Control {
|
|
switch control.Kind() {
|
|
case reflect.Interface:
|
|
return controlChildrenReflect(control.Elem())
|
|
case reflect.Ptr:
|
|
return controlChildrenReflect(control.Elem())
|
|
}
|
|
if reflect.TypeOf(ContainerBase{}) == control.Type() {
|
|
container := control.Interface().(ContainerBase)
|
|
return container.Children
|
|
}
|
|
if reflect.TypeOf(Proxy{}) == control.Type() {
|
|
proxy := control.Interface().(Proxy)
|
|
return []Control{proxy.Content}
|
|
}
|
|
if control.NumField() == 0 {
|
|
return nil
|
|
}
|
|
field := control.Type().Field(0)
|
|
if !field.Anonymous {
|
|
return nil
|
|
}
|
|
return controlChildrenReflect(control.Field(0))
|
|
}
|
|
|
|
func controlName(control Control) string {
|
|
typ := reflect.TypeOf(control)
|
|
return typ.Elem().Name()
|
|
}
|
|
|
|
type debugOverlay struct {
|
|
ControlBase
|
|
|
|
root Control
|
|
|
|
hoverNodes *controlNode
|
|
|
|
boundsColor color.Color
|
|
textColor color.Color
|
|
textShadowColor color.Color
|
|
}
|
|
|
|
func NewDebugOverlay(root Control) *debugOverlay {
|
|
return &debugOverlay{
|
|
root: root,
|
|
boundsColor: zntg.MustHexColor(`#00FF003F`),
|
|
textColor: zntg.MustHexColor(`#FFFFFF3F`),
|
|
textShadowColor: zntg.MustHexColor(`#0000003F`),
|
|
}
|
|
}
|
|
|
|
func (o *debugOverlay) renderControl(ctx Context, control Control) {
|
|
renderer := ctx.Renderer()
|
|
// bounds := control.Bounds()
|
|
// renderer.Rectangle(bounds, o.boundsColor, 1)
|
|
|
|
var maxY float32
|
|
var renderHoverNode func(pos geom.PointF32, node *controlNode)
|
|
renderHoverNode = func(pos geom.PointF32, node *controlNode) {
|
|
if node == nil {
|
|
return
|
|
}
|
|
nameTexture, err := ctx.Fonts().TextTexture("debug", color.White, node.Name)
|
|
if err != nil {
|
|
return
|
|
}
|
|
defer nameTexture.Destroy()
|
|
nameTextureWidth := float32(nameTexture.Width())
|
|
nameTextureHeight := float32(nameTexture.Height())
|
|
renderer.FillRectangle(pos.RectRel2D(nameTextureWidth, nameTextureHeight), color.Black)
|
|
renderer.DrawTexturePoint(nameTexture, pos)
|
|
childPos := pos.Add2D(nameTextureWidth+8, 0)
|
|
for _, child := range node.Children {
|
|
if childPos.Y == maxY {
|
|
childPos.Y = maxY + nameTextureHeight
|
|
}
|
|
renderHoverNode(childPos, child)
|
|
maxY = childPos.Y
|
|
childPos.Y += nameTextureHeight + 8
|
|
}
|
|
}
|
|
renderHoverNode(geom.PtF32(4, 4), o.hoverNodes)
|
|
|
|
children := controlChildren(control)
|
|
for _, child := range children {
|
|
o.renderControl(ctx, child)
|
|
}
|
|
}
|
|
|
|
func createHoverNodes(hover geom.PointF32, control Control) *controlNode {
|
|
if !hover.In(control.Bounds()) {
|
|
return nil
|
|
}
|
|
node := &controlNode{Name: controlName(control)}
|
|
for _, child := range controlChildren(control) {
|
|
childNode := createHoverNodes(hover, child)
|
|
if childNode != nil {
|
|
node.Children = append(node.Children, childNode)
|
|
}
|
|
}
|
|
return node
|
|
}
|
|
|
|
func (o *debugOverlay) Handle(ctx Context, e Event) bool {
|
|
switch e := e.(type) {
|
|
case *MouseMoveEvent:
|
|
o.hoverNodes = createHoverNodes(e.Pos(), o.root)
|
|
case *MouseLeaveEvent:
|
|
o.hoverNodes = nil
|
|
}
|
|
return false
|
|
}
|
|
|
|
func (o *debugOverlay) Hidden() {}
|
|
|
|
func (o *debugOverlay) Render(ctx Context) {
|
|
o.renderControl(ctx, o.root)
|
|
}
|
|
|
|
func (o *debugOverlay) Shown() {}
|
|
|
|
type controlNode struct {
|
|
Name string
|
|
Children []*controlNode
|
|
}
|