Pad/internal/editor/state.go

93 lines
2.8 KiB
Go

package editor
import (
"pad/internal/ui"
)
// State holds all application state owned by the logic goroutine.
type State struct {
PixelWidth int // raw pixel width from Gio ConfigEvent
PixelHeight int // raw pixel height from Gio ConfigEvent
scale float32
WordWrap bool
Elems []ui.Element
}
func NewState() *State {
return &State{scale: 1.0}
}
func (s *State) SetScale(scale float32) {
s.scale = scale
}
func (s *State) Scale() float32 {
return s.scale
}
// layout converts stored pixel dimensions to Dp using the current scale
// and computes the element tree. Called only when a frame is needed.
func (s *State) layout() []ui.Element {
dpW := ui.ToDp(ui.Px(s.PixelWidth), s.scale)
dpH := ui.ToDp(ui.Px(s.PixelHeight), s.scale)
s.Elems = EditorLayout(dpW, dpH, s.WordWrap)
return s.Elems
}
// ToggleWordWrap toggles the word wrap setting.
func ToggleWordWrap(data any) {
TheState.WordWrap = !TheState.WordWrap
}
// EditorLayout computes the element tree for the editor page.
func EditorLayout(screenWidth, screenHeight ui.Dp, wordWrap bool) []ui.Element {
margin := ui.Dp(10)
// --- Top bar: filename on row 1, icons on row 2 ---
statusBarRegion := ui.Region{
X: margin, Y: margin,
W: screenWidth - margin*2,
H: ui.Dp(52),
}
statusBarW := statusBarRegion.W
statusBar := ui.NewContainer(
statusBarRegion,
ui.Color{R: 230, G: 230, B: 230, A: 255},
[]ui.Element{
// Row 1: filename
ui.NewLabel("a very long file name that probably will eventually need to be truncated.txt", 14, ui.Region{X: 0, Y: ui.Dp(2), W: statusBarW, H: ui.Dp(20)}, ui.AlignStart, "", nil),
// Row 2: cut, copy, paste icons
ui.NewIcon("cut", ui.Region{X: ui.Dp(0), Y: ui.Dp(28), W: ui.IconSize, H: ui.IconSize}, 0),
ui.NewIcon("copy", ui.Region{X: ui.Dp(48), Y: ui.Dp(28), W: ui.IconSize, H: ui.IconSize}, 0),
ui.NewIcon("paste", ui.Region{X: ui.Dp(96), Y: ui.Dp(28), W: ui.IconSize, H: ui.IconSize}, 0),
},
)
// --- Bottom bar ---
bottomBarHeight := ui.BottomBarHeight
bottomBarY := screenHeight - margin - bottomBarHeight
bottomBarRegion := ui.Region{
X: margin, Y: bottomBarY,
W: screenWidth - margin*2,
H: bottomBarHeight,
}
bottomBarW := bottomBarRegion.W
wrapText := "Wrap: Off"
if wordWrap {
wrapText = "Wrap: On"
}
bottomBar := ui.NewContainer(
bottomBarRegion,
ui.Color{R: 230, G: 230, B: 230, A: 255},
[]ui.Element{
ui.NewLabel("Ln 47, Col 12", 12, ui.Region{X: 0, Y: ui.Dp(2), W: bottomBarW, H: ui.Dp(20)}, ui.AlignStart, "", nil),
ui.NewLabel("1024 / 50000", 12, ui.Region{X: 0, Y: ui.Dp(2), W: bottomBarW, H: ui.Dp(20)}, ui.AlignCenter, "", nil),
ui.NewLabel(wrapText, 12, ui.Region{X: 0, Y: ui.Dp(2), W: bottomBarW, H: ui.Dp(20)}, ui.AlignEnd, "wrap", []ui.Interaction{
{Gesture: ui.Tap, Handler: ToggleWordWrap},
}),
},
)
return []ui.Element{statusBar, bottomBar}
}