Pad/internal/editor/logic.go
Greg Pomerantz b581abb691 Redesign ConfigEvent/Scale handling: ConfigEvent sets size, FrameEvent updates scale
- Logic layer has separate ConfigChan and ScaleChan
- ConfigEvent: width/height in Dp, set on ConfigEvent
- ScaleEvent: scale factor, set on FrameEvent when scale changes
- Logic has ScreenSize() accessor for layout/rendering pipeline
- Logic has SetScale() to update scale and recompute layout
- main.go: ConfigEvent stores pixels, converts to DP using current scale
- main.go: FrameEvent gets actual scale, sends ScaleEvent if changed
2026-05-09 19:59:27 -04:00

122 lines
3.1 KiB
Go

package editor
import (
"sync"
"pad/internal/ui"
)
// ConfigEvent represents a window configuration change (resize, orientation).
// Width and Height are in device-independent pixels (Dp).
type ConfigEvent struct {
Width ui.Dp
Height ui.Dp
}
// ScaleEvent represents a metric change (HiDPI scale factor).
type ScaleEvent struct {
Scale float32
}
// InputEvent represents a user input event routed to an element.
type InputEvent struct {
ElementID string
Type ui.InputType
Data any
}
// ResultEvent represents a completed async task result.
type ResultEvent struct {
// Future: add result fields here
}
// Logic runs the logic goroutine and provides channels for communication.
type Logic struct {
state *State
configChan chan ConfigEvent
scaleChan chan ScaleEvent
frameChan chan []ui.Element
inputChan chan []InputEvent
resultChan chan ResultEvent
mu sync.Mutex
}
// NewLogic creates a new Logic instance.
// screenWidth and screenHeight are in device-independent pixels (Dp).
func NewLogic(screenWidth, screenHeight ui.Dp) *Logic {
return &Logic{
state: NewState(screenWidth, screenHeight),
configChan: make(chan ConfigEvent),
scaleChan: make(chan ScaleEvent),
frameChan: make(chan []ui.Element),
inputChan: make(chan []InputEvent),
resultChan: make(chan ResultEvent),
}
}
// ConfigChan returns the config channel for the logic goroutine.
func (l *Logic) ConfigChan() chan<- ConfigEvent {
return l.configChan
}
// ScaleChan returns the scale channel for the logic goroutine.
func (l *Logic) ScaleChan() chan<- ScaleEvent {
return l.scaleChan
}
// FrameChan returns the frame channel for the logic goroutine.
func (l *Logic) FrameChan() <-chan []ui.Element {
return l.frameChan
}
// InputChan returns the input channel for the logic goroutine.
func (l *Logic) InputChan() chan<- []InputEvent {
return l.inputChan
}
// ResultChan returns the result channel for the logic goroutine.
func (l *Logic) ResultChan() <-chan ResultEvent {
return l.resultChan
}
// ScreenSize returns the current screen dimensions in Dp.
func (l *Logic) ScreenSize() (ui.Dp, ui.Dp) {
l.mu.Lock()
defer l.mu.Unlock()
return l.state.ScreenWidth, l.state.ScreenHeight
}
// SetScale updates the scale factor and recomputes layout.
func (l *Logic) SetScale(scale float32) {
l.mu.Lock()
defer l.mu.Unlock()
// Recompute layout with new scale (EditorLayout handles the conversion)
l.state.Elems = EditorLayout(l.state.ScreenWidth, l.state.ScreenHeight)
l.frameChan <- l.state.Elems
}
// Run runs the logic goroutine loop.
func (l *Logic) Run() {
for {
select {
case cfg := <-l.configChan:
// Update screen size and recompute layout
l.state.ScreenWidth = cfg.Width
l.state.ScreenHeight = cfg.Height
l.state.Elems = EditorLayout(cfg.Width, cfg.Height)
l.frameChan <- l.state.Elems
case <-l.inputChan:
// Process input (not implemented in mockup)
l.frameChan <- l.state.Elems
case <-l.resultChan:
// Handle result (not implemented in mockup)
l.frameChan <- l.state.Elems
}
}
}
// State returns the current state.
func (l *Logic) State() *State {
return l.state
}