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
This commit is contained in:
parent
21b4df59a3
commit
620d534454
|
|
@ -38,14 +38,15 @@ func run(w *app.Window) error {
|
|||
initialDPW := ui.Dp(390)
|
||||
initialDPH := ui.Dp(844)
|
||||
|
||||
// Track pixel dimensions from ConfigEvent (for resize handling)
|
||||
var pixelW, pixelH int
|
||||
// Track previous scale to detect changes
|
||||
prevScale := float32(1.0)
|
||||
|
||||
// Create logic instance with initial DP size and scale=1.0
|
||||
logic := editor.NewLogic(initialDPW, initialDPH)
|
||||
|
||||
// Set State reference on Renderer — it reads scale/window size from State directly
|
||||
renderer.SetState(logic.State())
|
||||
|
||||
// Shared state protected by mutex
|
||||
var mu sync.Mutex
|
||||
var elems []ui.Element
|
||||
|
|
@ -62,19 +63,14 @@ func run(w *app.Window) error {
|
|||
case app.DestroyEvent:
|
||||
return e.Err
|
||||
case app.ConfigEvent:
|
||||
// Store pixel dimensions from ConfigEvent
|
||||
pixelW = e.Config.Size.X
|
||||
pixelH = e.Config.Size.Y
|
||||
// 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)
|
||||
// Convert pixel dimensions to DP using current scale (starts at 1.0)
|
||||
dpW := ui.ToDp(ui.Px(e.Config.Size.X), 1.0)
|
||||
dpH := ui.ToDp(ui.Px(e.Config.Size.Y), 1.0)
|
||||
// Send config event to logic goroutine (in DP)
|
||||
logic.ConfigChan() <- editor.ConfigEvent{
|
||||
Width: dpW,
|
||||
Height: dpH,
|
||||
}
|
||||
// Update renderer with window size from State
|
||||
renderer.SetWindowSize(pixelW, pixelH)
|
||||
case app.FrameEvent:
|
||||
gtx := app.NewContext(&ops, e)
|
||||
newScale := gtx.Metric.PxPerDp
|
||||
|
|
@ -85,9 +81,6 @@ func run(w *app.Window) error {
|
|||
prevScale = newScale
|
||||
}
|
||||
|
||||
// Update renderer with current scale from State
|
||||
renderer.SetScale(logic.Scale())
|
||||
|
||||
// Acquire mutex, read frame, draw, release mutex
|
||||
mu.Lock()
|
||||
currentElems := elems
|
||||
|
|
|
|||
|
|
@ -25,9 +25,7 @@ type ConfigUpdate interface {
|
|||
}
|
||||
|
||||
func (e ConfigEvent) apply(s *State) {
|
||||
s.ScreenWidth = e.Width
|
||||
s.ScreenHeight = e.Height
|
||||
s.Elems = EditorLayout(e.Width, e.Height)
|
||||
s.SetSize(e.Width, e.Height)
|
||||
}
|
||||
|
||||
func (e ScaleEvent) apply(s *State) {
|
||||
|
|
@ -93,14 +91,14 @@ func (l *Logic) ResultChan() <-chan ResultEvent {
|
|||
func (l *Logic) ScreenSize() (ui.Dp, ui.Dp) {
|
||||
l.mu.Lock()
|
||||
defer l.mu.Unlock()
|
||||
return l.state.ScreenWidth, l.state.ScreenHeight
|
||||
return l.state.ScreenWidth(), l.state.ScreenHeight()
|
||||
}
|
||||
|
||||
// Scale returns the current scale factor (pixels per DP).
|
||||
func (l *Logic) Scale() float32 {
|
||||
l.mu.Lock()
|
||||
defer l.mu.Unlock()
|
||||
return l.state.Scale
|
||||
return l.state.Scale()
|
||||
}
|
||||
|
||||
// Run runs the logic goroutine loop.
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@ import (
|
|||
// 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
|
||||
screenWidth ui.Dp
|
||||
screenHeight ui.Dp
|
||||
scale float32 // pixels per DP, default 1.0
|
||||
Elems []ui.Element
|
||||
}
|
||||
|
||||
|
|
@ -18,17 +18,33 @@ type State struct {
|
|||
// 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,
|
||||
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)
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -15,50 +15,52 @@ import (
|
|||
"golang.org/x/image/math/fixed"
|
||||
)
|
||||
|
||||
// StateReader provides access to scale and window dimensions from State.
|
||||
// Implemented by editor.State to avoid import cycles.
|
||||
type StateReader interface {
|
||||
Scale() float32
|
||||
ScreenWidth() Dp
|
||||
ScreenHeight() Dp
|
||||
}
|
||||
|
||||
// Renderer consumes a slice of elements and draws them.
|
||||
type Renderer struct {
|
||||
theme Theme
|
||||
shp *text.Shaper
|
||||
scale float32 // pixels per DP, from State.Scale
|
||||
// Window dimensions in physical pixels, from State
|
||||
windowW int
|
||||
windowH int
|
||||
state StateReader // read-only access to State for scale/window size
|
||||
}
|
||||
|
||||
// New creates a new Renderer.
|
||||
func New(th Theme, shp *text.Shaper) *Renderer {
|
||||
return &Renderer{theme: th, shp: shp, scale: 1.0}
|
||||
return &Renderer{theme: th, shp: shp}
|
||||
}
|
||||
|
||||
// SetScale updates the renderer's scale factor from State.Scale.
|
||||
func (r *Renderer) SetScale(scale float32) {
|
||||
r.scale = scale
|
||||
// SetState sets the State reference for the Renderer.
|
||||
// The Renderer reads scale and window size from State directly.
|
||||
func (r *Renderer) SetState(state StateReader) {
|
||||
r.state = state
|
||||
}
|
||||
|
||||
// SetWindowSize updates the window dimensions in physical pixels from State.
|
||||
func (r *Renderer) SetWindowSize(w, h int) {
|
||||
r.windowW = w
|
||||
r.windowH = h
|
||||
}
|
||||
|
||||
// toPx converts Dp to physical pixels using the renderer's scale.
|
||||
// toPx converts Dp to physical pixels using the scale from State.
|
||||
func (r *Renderer) toPx(dp Dp) Px {
|
||||
return ToPx(dp, r.scale)
|
||||
return ToPx(dp, r.state.Scale())
|
||||
}
|
||||
|
||||
// toDp converts physical pixels to Dp using the renderer's scale.
|
||||
// toDp converts physical pixels to Dp using the scale from State.
|
||||
func (r *Renderer) toDp(px Px) Dp {
|
||||
return ToDp(px, r.scale)
|
||||
return ToDp(px, r.state.Scale())
|
||||
}
|
||||
|
||||
// Draw iterates elements and draws each in slice order (back-to-front).
|
||||
// Window constraints come from State (set via SetWindowSize), not from gtx.
|
||||
// Scale comes from State (set via SetScale), not from gtx.Metric.PxPerDp.
|
||||
// All scale and window size values come from State, never from gtx.
|
||||
func (r *Renderer) Draw(gtx layout.Context, elems []Element) {
|
||||
// Use window dimensions from State — never from gtx.Constraints
|
||||
// Use window dimensions from State — convert DP to pixels using State.Scale
|
||||
state := r.state
|
||||
windowWPx := int(r.toPx(state.ScreenWidth()))
|
||||
windowHPx := int(r.toPx(state.ScreenHeight()))
|
||||
initialConstraints := WindowConstraints{
|
||||
Min: image.Point{X: 0, Y: 0},
|
||||
Max: image.Point{X: r.windowW, Y: r.windowH},
|
||||
Max: image.Point{X: windowWPx, Y: windowHPx},
|
||||
}
|
||||
|
||||
for _, e := range elems {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user