diff --git a/internal/ui/render.go b/internal/ui/render.go index 5c4ba0f..b4ed8dd 100644 --- a/internal/ui/render.go +++ b/internal/ui/render.go @@ -1,6 +1,7 @@ package ui import ( + "fmt" "image" "image/color" @@ -29,6 +30,7 @@ func New(th Theme, shp *text.Shaper) *Renderer { // Draw iterates elements and draws each in slice order (back-to-front). func (r *Renderer) Draw(gtx layout.Context, elems []Element) { for _, e := range elems { + fmt.Printf("[DEBUG Draw] elem type=%T visible=%v\n", e, e.Visible()) if !e.Visible() { continue } @@ -146,21 +148,35 @@ func (r *Renderer) drawStatusBar(gtx layout.Context, sb StatusBar) { func (r *Renderer) drawBottomBar(gtx layout.Context, bb BottomBar) { reg := bb.Region() - // BottomBar text at reg.Y (top of bar), using drawText for consistent rendering. - // The BottomBar region is at the bottom of the screen with 10DP margin. - bottomY := reg.Y + fmt.Printf("[DEBUG drawBottomBar] reg=(%d, %d, %d, %d)\n", gtx.Dp(reg.X), gtx.Dp(reg.Y), gtx.Dp(reg.W), gtx.Dp(reg.H)) + fmt.Printf("[DEBUG drawBottomBar] constraints=(%d, %d, %d, %d)\n", + gtx.Constraints.Min.X, gtx.Constraints.Min.Y, + gtx.Constraints.Max.X, gtx.Constraints.Max.Y) + + // Clamp BottomBar Y to visible window area. + // The region Y may be outside the visible area (e.g. 3308 DP when window is 1688px). + // gtx.Constraints.Max.Y is in physical pixels. Convert to DP using gtx.Metric.PxPerDp. + scale := gtx.Metric.PxPerDp + bottomBarHeightPx := int(24 * scale) + marginPx := int(10 * scale) + drawYPx := gtx.Constraints.Max.Y - bottomBarHeightPx - marginPx + drawY := unit.Dp(float64(drawYPx) / float64(scale)) + fmt.Printf("[DEBUG drawBottomBar] drawY=%d (clamped from %d)\n", gtx.Dp(drawY), gtx.Dp(reg.Y)) // Left: Cursor position cursorX := reg.X + unit.Dp(8) - r.drawText(gtx, r.shp, bb.CursorPos, r.theme.FontSize, cursorX, bottomY, color.NRGBA{R: 0, G: 0, B: 0, A: 255}) + fmt.Printf("[DEBUG drawBottomBar] cursor=(%d, %d) text=%q\n", gtx.Dp(cursorX), gtx.Dp(drawY), bb.CursorPos) + r.drawText(gtx, r.shp, bb.CursorPos, r.theme.FontSize, cursorX, drawY, color.NRGBA{R: 0, G: 0, B: 0, A: 255}) // Center: Byte position byteX := reg.X + reg.W/2 - unit.Dp(60) // approximate center - r.drawText(gtx, r.shp, bb.BytePos, r.theme.FontSize, byteX, bottomY, color.NRGBA{R: 0, G: 0, B: 0, A: 255}) + fmt.Printf("[DEBUG drawBottomBar] byte=(%d, %d) text=%q\n", gtx.Dp(byteX), gtx.Dp(drawY), bb.BytePos) + r.drawText(gtx, r.shp, bb.BytePos, r.theme.FontSize, byteX, drawY, color.NRGBA{R: 0, G: 0, B: 0, A: 255}) // Right: Word wrap button wordWrapX := reg.X + reg.W - unit.Dp(80) - r.drawText(gtx, r.shp, "W:"+boolToString(bb.WordWrap), r.theme.FontSize, wordWrapX, bottomY, color.NRGBA{R: 0, G: 0, B: 0, A: 255}) + fmt.Printf("[DEBUG drawBottomBar] wordwrap=(%d, %d) text=%q\n", gtx.Dp(wordWrapX), gtx.Dp(drawY), "W:"+boolToString(bb.WordWrap)) + r.drawText(gtx, r.shp, "W:"+boolToString(bb.WordWrap), r.theme.FontSize, wordWrapX, drawY, color.NRGBA{R: 0, G: 0, B: 0, A: 255}) } func (r *Renderer) drawButton(gtx layout.Context, btn Button) {