Fix element positioning in renderer

- Use gtx.Constraints.Min.X/Y instead of image.Point.ToSize()
- Properly position all elements at their region origins
- Fix StatusBar and BottomBar text positioning

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
Greg Pomerantz 2026-05-08 17:26:49 -04:00
parent c452cbef6d
commit aa422ab541
2 changed files with 29 additions and 26 deletions

View File

@ -46,34 +46,30 @@ func (r *Renderer) Draw(gtx layout.Context, elems []Element) {
func (r *Renderer) drawLabel(gtx layout.Context, l Label) { func (r *Renderer) drawLabel(gtx layout.Context, l Label) {
reg := l.Region() reg := l.Region()
c := clip.Rect{
Min: image.Point{X: int(reg.X), Y: int(reg.Y)},
Max: image.Point{X: int(reg.X + reg.W), Y: int(reg.Y + reg.H)},
}.Push(gtx.Ops)
th := material.NewTheme() th := material.NewTheme()
th.Shaper = r.shp th.Shaper = r.shp
size := l.FontSize size := l.FontSize
if size == 0 { if size == 0 {
size = r.theme.FontSize size = r.theme.FontSize
} }
// Position label at region origin
gtx.Constraints.Min.X = int(reg.X)
gtx.Constraints.Min.Y = int(reg.Y)
material.Label(th, size, l.Text).Layout(gtx) material.Label(th, size, l.Text).Layout(gtx)
c.Pop()
} }
func (r *Renderer) drawListView(gtx layout.Context, lv ListView) { func (r *Renderer) drawListView(gtx layout.Context, lv ListView) {
reg := lv.Region() reg := lv.Region()
c := clip.Rect{
Min: image.Point{X: int(reg.X), Y: int(reg.Y)},
Max: image.Point{X: int(reg.X + reg.W), Y: int(reg.Y + reg.H)},
}.Push(gtx.Ops)
th := material.NewTheme() th := material.NewTheme()
th.Shaper = r.shp th.Shaper = r.shp
// Position list view at region origin
gtx.Constraints.Min.X = int(reg.X)
gtx.Constraints.Min.Y = int(reg.Y)
for _, item := range lv.Items { for _, item := range lv.Items {
material.Label(th, r.theme.FontSize, item.Text).Layout(gtx) material.Label(th, r.theme.FontSize, item.Text).Layout(gtx)
} }
c.Pop()
} }
func (r *Renderer) drawStatusBar(gtx layout.Context, sb StatusBar) { func (r *Renderer) drawStatusBar(gtx layout.Context, sb StatusBar) {
@ -81,10 +77,15 @@ func (r *Renderer) drawStatusBar(gtx layout.Context, sb StatusBar) {
th := material.NewTheme() th := material.NewTheme()
th.Shaper = r.shp th.Shaper = r.shp
// Clip to status bar region
c := clip.Rect{
Min: image.Point{X: int(reg.X), Y: int(reg.Y)},
Max: image.Point{X: int(reg.X + reg.W), Y: int(reg.Y + reg.H)},
}.Push(gtx.Ops)
// Line 1: Filename (truncated with ellipsis if needed) // Line 1: Filename (truncated with ellipsis if needed)
filenameLineY := reg.Y filenameLineY := reg.Y
filenameLineH := unit.Dp(24) filenameLineH := unit.Dp(24)
filenameW := reg.W - unit.Dp(16) // 8 DP padding on each side
// Truncate filename if needed // Truncate filename if needed
displayFilename := sb.Filename displayFilename := sb.Filename
@ -93,12 +94,10 @@ func (r *Renderer) drawStatusBar(gtx layout.Context, sb StatusBar) {
displayFilename = displayFilename[:27] + "..." displayFilename = displayFilename[:27] + "..."
} }
clipFilename := clip.Rect{ // Position filename at (reg.X + 8, filenameLineY)
Min: image.Point{X: int(reg.X + unit.Dp(8)), Y: int(filenameLineY)}, gtx.Constraints.Min.X = int(reg.X + unit.Dp(8))
Max: image.Point{X: int(reg.X + filenameW), Y: int(filenameLineY + filenameLineH)}, gtx.Constraints.Min.Y = int(filenameLineY)
}.Push(gtx.Ops)
material.Label(th, r.theme.FontSize, displayFilename).Layout(gtx) material.Label(th, r.theme.FontSize, displayFilename).Layout(gtx)
clipFilename.Pop()
// Line 2: Icons // Line 2: Icons
iconsLineY := filenameLineY + filenameLineH iconsLineY := filenameLineY + filenameLineH
@ -130,6 +129,8 @@ func (r *Renderer) drawStatusBar(gtx layout.Context, sb StatusBar) {
rightX -= unit.Dp(36) rightX -= unit.Dp(36)
r.drawIconButton(gtx, th, "⚠", rightX, iconY) r.drawIconButton(gtx, th, "⚠", rightX, iconY)
} }
c.Pop()
} }
func (r *Renderer) drawBottomBar(gtx layout.Context, bb BottomBar) { func (r *Renderer) drawBottomBar(gtx layout.Context, bb BottomBar) {
@ -146,38 +147,40 @@ func (r *Renderer) drawBottomBar(gtx layout.Context, bb BottomBar) {
// Left: Cursor position // Left: Cursor position
cursorX := reg.X + unit.Dp(8) cursorX := reg.X + unit.Dp(8)
gtx.Constraints.Min.X = int(cursorX) gtx.Constraints.Min.X = int(cursorX)
gtx.Constraints.Min.Y = int(reg.Y)
material.Label(th, r.theme.FontSize, bb.CursorPos).Layout(gtx) material.Label(th, r.theme.FontSize, bb.CursorPos).Layout(gtx)
// Center: Byte position // Center: Byte position
byteX := reg.X + reg.W/2 - unit.Dp(60) // approximate center byteX := reg.X + reg.W/2 - unit.Dp(60) // approximate center
gtx.Constraints.Min.X = int(byteX) gtx.Constraints.Min.X = int(byteX)
gtx.Constraints.Min.Y = int(reg.Y)
material.Label(th, r.theme.FontSize, bb.BytePos).Layout(gtx) material.Label(th, r.theme.FontSize, bb.BytePos).Layout(gtx)
// Right: Word wrap button // Right: Word wrap button
wordWrapX := reg.X + reg.W - unit.Dp(120) wordWrapX := reg.X + reg.W - unit.Dp(120)
gtx.Constraints.Min.X = int(wordWrapX) gtx.Constraints.Min.X = int(wordWrapX)
gtx.Constraints.Min.Y = int(reg.Y)
material.Label(th, r.theme.FontSize, "[Word Wrap: "+boolToString(bb.WordWrap)+"]").Layout(gtx) material.Label(th, r.theme.FontSize, "[Word Wrap: "+boolToString(bb.WordWrap)+"]").Layout(gtx)
c.Pop() c.Pop()
} }
func (r *Renderer) drawButton(gtx layout.Context, btn Button) { func (r *Renderer) drawButton(gtx layout.Context, btn Button) {
reg := btn.Region()
th := material.NewTheme() th := material.NewTheme()
th.Shaper = r.shp th.Shaper = r.shp
// Draw button text // Position button at region origin
gtx.Constraints.Min.X = int(reg.X)
gtx.Constraints.Min.Y = int(reg.Y)
material.Label(th, r.theme.FontSize, btn.Text).Layout(gtx) material.Label(th, r.theme.FontSize, btn.Text).Layout(gtx)
} }
func (r *Renderer) drawIconButton(gtx layout.Context, th *material.Theme, icon string, x, y unit.Dp) { func (r *Renderer) drawIconButton(gtx layout.Context, th *material.Theme, icon string, x, y unit.Dp) {
// Draw icon button // Position icon button at (x, y)
iconRegion := Region{X: x, Y: y, W: unit.Dp(24), H: unit.Dp(24)} gtx.Constraints.Min.X = int(x)
c := clip.Rect{ gtx.Constraints.Min.Y = int(y)
Min: image.Point{X: int(iconRegion.X), Y: int(iconRegion.Y)},
Max: image.Point{X: int(iconRegion.X + iconRegion.W), Y: int(iconRegion.Y + iconRegion.H)},
}.Push(gtx.Ops)
material.Label(th, r.theme.FontSize, icon).Layout(gtx) material.Label(th, r.theme.FontSize, icon).Layout(gtx)
c.Pop()
} }
func boolToString(b bool) string { func boolToString(b bool) string {

BIN
pad

Binary file not shown.