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
This commit is contained in:
parent
3fc28fd54b
commit
b581abb691
|
|
@ -41,7 +41,7 @@ func run(w *app.Window) error {
|
||||||
// Track pixel dimensions from ConfigEvent (for resize handling)
|
// Track pixel dimensions from ConfigEvent (for resize handling)
|
||||||
var pixelW, pixelH int
|
var pixelW, pixelH int
|
||||||
|
|
||||||
// Create logic instance with initial DP size
|
// Create logic instance with initial DP size and scale=1.0
|
||||||
logic := editor.NewLogic(initialDPW, initialDPH)
|
logic := editor.NewLogic(initialDPW, initialDPH)
|
||||||
|
|
||||||
// Shared state protected by mutex
|
// Shared state protected by mutex
|
||||||
|
|
@ -60,21 +60,29 @@ func run(w *app.Window) error {
|
||||||
case app.DestroyEvent:
|
case app.DestroyEvent:
|
||||||
return e.Err
|
return e.Err
|
||||||
case app.ConfigEvent:
|
case app.ConfigEvent:
|
||||||
// Store pixel dimensions for later conversion
|
// Store pixel dimensions from ConfigEvent
|
||||||
pixelW = e.Config.Size.X
|
pixelW = e.Config.Size.X
|
||||||
pixelH = e.Config.Size.Y
|
pixelH = e.Config.Size.Y
|
||||||
// Use initial DP size until we get the scale from FrameEvent
|
// Convert to DP using current scale (starts at 1.0)
|
||||||
|
dpW := ui.ToDp(ui.Px(pixelW), 1.0)
|
||||||
|
dpH := ui.ToDp(ui.Px(pixelH), 1.0)
|
||||||
|
// Send config event to logic goroutine (in DP)
|
||||||
logic.ConfigChan() <- editor.ConfigEvent{
|
logic.ConfigChan() <- editor.ConfigEvent{
|
||||||
Width: initialDPW,
|
Width: dpW,
|
||||||
Height: initialDPH,
|
Height: dpH,
|
||||||
}
|
}
|
||||||
case app.FrameEvent:
|
case app.FrameEvent:
|
||||||
gtx := app.NewContext(&ops, e)
|
gtx := app.NewContext(&ops, e)
|
||||||
scale := gtx.Metric.PxPerDp
|
newScale := gtx.Metric.PxPerDp
|
||||||
|
|
||||||
|
// If scale changed, send scale event to logic goroutine
|
||||||
|
if newScale != 1.0 {
|
||||||
|
logic.ScaleChan() <- editor.ScaleEvent{Scale: newScale}
|
||||||
|
}
|
||||||
|
|
||||||
// Convert pixel dimensions to DP using actual scale
|
// Convert pixel dimensions to DP using actual scale
|
||||||
dpW := ui.ToDp(ui.Px(pixelW), scale)
|
dpW := ui.ToDp(ui.Px(pixelW), newScale)
|
||||||
dpH := ui.ToDp(ui.Px(pixelH), scale)
|
dpH := ui.ToDp(ui.Px(pixelH), newScale)
|
||||||
|
|
||||||
// Send updated config to logic goroutine
|
// Send updated config to logic goroutine
|
||||||
logic.ConfigChan() <- editor.ConfigEvent{
|
logic.ConfigChan() <- editor.ConfigEvent{
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
package editor
|
package editor
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"sync"
|
||||||
|
|
||||||
"pad/internal/ui"
|
"pad/internal/ui"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -11,6 +13,11 @@ type ConfigEvent struct {
|
||||||
Height 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.
|
// InputEvent represents a user input event routed to an element.
|
||||||
type InputEvent struct {
|
type InputEvent struct {
|
||||||
ElementID string
|
ElementID string
|
||||||
|
|
@ -25,19 +32,22 @@ type ResultEvent struct {
|
||||||
|
|
||||||
// Logic runs the logic goroutine and provides channels for communication.
|
// Logic runs the logic goroutine and provides channels for communication.
|
||||||
type Logic struct {
|
type Logic struct {
|
||||||
state *State
|
state *State
|
||||||
configChan chan ConfigEvent
|
configChan chan ConfigEvent
|
||||||
|
scaleChan chan ScaleEvent
|
||||||
frameChan chan []ui.Element
|
frameChan chan []ui.Element
|
||||||
inputChan chan []InputEvent
|
inputChan chan []InputEvent
|
||||||
resultChan chan ResultEvent
|
resultChan chan ResultEvent
|
||||||
|
mu sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewLogic creates a new Logic instance.
|
// NewLogic creates a new Logic instance.
|
||||||
// screenWidth and screenHeight are in device-independent pixels (Dp).
|
// screenWidth and screenHeight are in device-independent pixels (Dp).
|
||||||
func NewLogic(screenWidth, screenHeight ui.Dp) *Logic {
|
func NewLogic(screenWidth, screenHeight ui.Dp) *Logic {
|
||||||
return &Logic{
|
return &Logic{
|
||||||
state: NewState(screenWidth, screenHeight),
|
state: NewState(screenWidth, screenHeight),
|
||||||
configChan: make(chan ConfigEvent),
|
configChan: make(chan ConfigEvent),
|
||||||
|
scaleChan: make(chan ScaleEvent),
|
||||||
frameChan: make(chan []ui.Element),
|
frameChan: make(chan []ui.Element),
|
||||||
inputChan: make(chan []InputEvent),
|
inputChan: make(chan []InputEvent),
|
||||||
resultChan: make(chan ResultEvent),
|
resultChan: make(chan ResultEvent),
|
||||||
|
|
@ -49,6 +59,11 @@ func (l *Logic) ConfigChan() chan<- ConfigEvent {
|
||||||
return l.configChan
|
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.
|
// FrameChan returns the frame channel for the logic goroutine.
|
||||||
func (l *Logic) FrameChan() <-chan []ui.Element {
|
func (l *Logic) FrameChan() <-chan []ui.Element {
|
||||||
return l.frameChan
|
return l.frameChan
|
||||||
|
|
@ -64,6 +79,22 @@ func (l *Logic) ResultChan() <-chan ResultEvent {
|
||||||
return l.resultChan
|
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.
|
// Run runs the logic goroutine loop.
|
||||||
func (l *Logic) Run() {
|
func (l *Logic) Run() {
|
||||||
for {
|
for {
|
||||||
|
|
|
||||||
|
|
@ -231,7 +231,7 @@ func (r *Renderer) drawBottomBar(gtx layout.Context, bb BottomBar, constraints W
|
||||||
// Right: Word wrap button
|
// Right: Word wrap button
|
||||||
wordWrapXPx := regXPx + barW - r.toPx(Dp(80))
|
wordWrapXPx := regXPx + barW - r.toPx(Dp(80))
|
||||||
wordWrapXDp := r.toDp(wordWrapXPx)
|
wordWrapXDp := r.toDp(wordWrapXPx)
|
||||||
r.drawText(gtx, r.shp, "W:"+boolToString(bb.WordWrap), r.theme.FontSize, wordWrapXDp, drawY, color.NRGBA{R: 0, G: 0, B: 0, A: 255})
|
r.drawText(gtx, r.shp, "Wrap:"+boolToString(bb.WordWrap), r.theme.FontSize, wordWrapXDp, drawY, color.NRGBA{R: 0, G: 0, B: 0, A: 255})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Renderer) drawButton(gtx layout.Context, btn Button, _ WindowConstraints) {
|
func (r *Renderer) drawButton(gtx layout.Context, btn Button, _ WindowConstraints) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user