Pad/internal/editor/state.go
Greg Pomerantz 620d534454 Break import cycle: use StateReader interface instead of direct State reference
- StateReader interface in ui package (Scale(), ScreenWidth(), ScreenHeight())
- State implements StateReader
- Renderer reads scale/window size via interface, never imports editor
- State fields are private (screenWidth, screenHeight, scale) with accessor methods
- No SetScale/SetWindowSize calls from main.go — Renderer reads from State directly
2026-05-09 20:33:00 -04:00

98 lines
2.7 KiB
Go

package editor
import (
"pad/internal/ui"
)
// State holds all application state owned by the logic goroutine.
// All dimensions are in device-independent pixels (Dp).
type State struct {
screenWidth ui.Dp
screenHeight ui.Dp
scale float32 // pixels per DP, default 1.0
Elems []ui.Element
}
// NewState creates a new State with initial editor layout.
// screenWidth and screenHeight are in device-independent pixels (Dp).
// scale defaults to 1.0 until updated by ScaleEvent.
func NewState(screenWidth, screenHeight ui.Dp) *State {
return &State{
screenWidth: screenWidth,
screenHeight: screenHeight,
scale: 1.0,
Elems: EditorLayout(screenWidth, screenHeight),
}
}
// Scale returns the current scale factor (pixels per DP).
func (s *State) Scale() float32 { return s.scale }
// ScreenWidth returns the current screen width in Dp.
func (s *State) ScreenWidth() ui.Dp { return s.screenWidth }
// ScreenHeight returns the current screen height in Dp.
func (s *State) ScreenHeight() ui.Dp { return s.screenHeight }
// SetScale updates the scale factor and recomputes layout.
func (s *State) SetScale(scale float32) {
s.scale = scale
s.Elems = EditorLayout(s.screenWidth, s.screenHeight)
}
// SetSize updates the screen dimensions and recomputes layout.
func (s *State) SetSize(width, height ui.Dp) {
s.screenWidth = width
s.screenHeight = height
s.Elems = EditorLayout(width, height)
}
// EditorLayout computes regions for the editor page.
// It takes screen dimensions in Dp and returns []Element with regions in Dp.
// This function works exclusively in Dp — no pixel conversions.
func EditorLayout(screenWidth, screenHeight ui.Dp) []ui.Element {
// Margin to avoid clipping on macOS round corners
margin := ui.Dp(10)
// Compute StatusBar region
statusBarHeight := ui.Dp(48)
statusBarRegion := ui.Region{
X: margin,
Y: margin,
W: screenWidth - margin*2,
H: statusBarHeight,
}
// Compute BottomBar region (fixed height, at bottom of screen)
bottomBarHeight := ui.Dp(24)
bottomBarY := screenHeight - margin - bottomBarHeight
bottomBarRegion := ui.Region{
X: margin,
Y: bottomBarY,
W: screenWidth - margin*2,
H: bottomBarHeight,
}
// Create StatusBar with mocked filename
statusBar := ui.NewStatusBar(
statusBarRegion,
"very_long_filename_that_does_not_fit_on_a_single_line_and_it_just_keeps_on_going_and_going_and_going_and_going_and_going.txt",
false, // FilenameExp
true, // CutCopy
false, // Copy
true, // Paste
false, // ConflictIcon
true, // Search
)
// Create BottomBar with mocked data
bottomBar := ui.NewBottomBar(
bottomBarRegion,
"Ln 47, Col 12",
"1024 / 50000",
true, // WordWrap
)
return []ui.Element{statusBar, bottomBar}
}