@@ -164,73 +164,77 @@ func (r *ToolbarRenderer) paintGear(dc *gg.Context, rect image.Rectangle, scale
164164 dc .Fill ()
165165}
166166
167- // HitTest determines which part of the toolbar was clicked
168- func (r * ToolbarRenderer ) HitTest (x , y , width , height int ) ToolbarHitResult {
169- scale := GetDPIScale ()
170-
171- // Check grip area
172- gripW := int (gripWidth * scale )
173- if x < gripW {
174- return HitGrip
175- }
176-
177- // Check buttons
178- buttonW := int (buttonWidth * scale )
179- buttonX := gripW
167+ // toolbarHit 是一个按钮的命中带(kind + margin 盒;LayoutRow 使各 margin 盒首尾相接,平铺整条满高)。
168+ type toolbarHit struct {
169+ kind ToolbarHitResult
170+ rect image.Rectangle
171+ }
180172
181- // Mode button
182- if x >= buttonX && x < buttonX + buttonW {
183- return HitModeButton
184- }
185- buttonX += buttonW
173+ // toolbarGeometry 是工具栏几何的单一真相源:一次 buildToolbarTree+Layout 的派生结果。
174+ type toolbarGeometry struct {
175+ size image.Point // 整条尺寸(GetToolbarSize)
176+ bounds map [ToolbarHitResult ]image.Rectangle // 各按钮 content 矩形(GetButtonBounds)
177+ hits []toolbarHit // 各按钮 margin 盒,按 x 顺序(HitTest)
178+ }
186179
187- // Width button
188- if x >= buttonX && x < buttonX + buttonW {
189- return HitWidthButton
190- }
191- buttonX += buttonW
180+ // viewOuterRect 返回 View 的 margin 盒(content 矩形外扩自身 Margin)。
181+ func viewOuterRect (v * View ) image.Rectangle {
182+ r := v .Rect ()
183+ return image .Rect (
184+ r .Min .X - v .Margin .Left , r .Min .Y - v .Margin .Top ,
185+ r .Max .X + v .Margin .Right , r .Max .Y + v .Margin .Bottom ,
186+ )
187+ }
192188
193- // Punctuation button
194- if x >= buttonX && x < buttonX + buttonW {
195- return HitPunctButton
189+ // computeGeometry 用零 state/零色构建工具栏 View 树并 Layout,派生几何——命中/边界/尺寸的唯一来源。
190+ // 几何与 state/颜色无关(按钮 FixedW 固定、mode 文字不影响布局),故按需计算、无需缓存。
191+ func (r * ToolbarRenderer ) computeGeometry () toolbarGeometry {
192+ scale := GetDPIScale ()
193+ tt := buildToolbarTree (ToolbarState {}, theme.ResolvedToolbarViews {}, scale )
194+ Layout (tt .root , 0 , 0 , r .TextDrawer ())
195+ return toolbarGeometry {
196+ size : tt .root .Rect ().Size (),
197+ bounds : map [ToolbarHitResult ]image.Rectangle {
198+ HitGrip : tt .grip .Rect (),
199+ HitModeButton : tt .mode .Rect (),
200+ HitWidthButton : tt .width .Rect (),
201+ HitPunctButton : tt .punct .Rect (),
202+ HitSettingsButton : tt .settings .Rect (),
203+ },
204+ hits : []toolbarHit {
205+ {HitGrip , viewOuterRect (tt .grip )},
206+ {HitModeButton , viewOuterRect (tt .mode )},
207+ {HitWidthButton , viewOuterRect (tt .width )},
208+ {HitPunctButton , viewOuterRect (tt .punct )},
209+ {HitSettingsButton , viewOuterRect (tt .settings )},
210+ },
196211 }
197- buttonX += buttonW
212+ }
198213
199- // Settings button
200- if x >= buttonX && x < buttonX + buttonW {
201- return HitSettingsButton
214+ // HitTest determines which part of the toolbar was clicked(查 Layout 派生的命中带,无独立公式)。
215+ func (r * ToolbarRenderer ) HitTest (x , y , width , height int ) ToolbarHitResult {
216+ pt := image .Pt (x , y )
217+ for _ , h := range r .computeGeometry ().hits {
218+ if pt .In (h .rect ) {
219+ return h .kind
220+ }
202221 }
203-
204222 return HitNone
205223}
206224
207- // GetButtonBounds returns the bounds of a specific button
225+ // GetButtonBounds returns the bounds of a specific button(查 Layout 派生的 content 矩形)。
208226func (r * ToolbarRenderer ) GetButtonBounds (button ToolbarHitResult ) (x , y , w , h int ) {
209- scale := GetDPIScale ()
210- height := int (toolbarBaseHeight * scale )
211- gripW := int (gripWidth * scale )
212- buttonW := int (buttonWidth * scale )
213- padding := int (buttonPadding * scale )
214-
215- switch button {
216- case HitGrip :
217- return 0 , 0 , gripW , height
218- case HitModeButton :
219- return gripW + padding , padding , buttonW - padding * 2 , height - padding * 2
220- case HitWidthButton :
221- return gripW + buttonW + padding , padding , buttonW - padding * 2 , height - padding * 2
222- case HitPunctButton :
223- return gripW + buttonW * 2 + padding , padding , buttonW - padding * 2 , height - padding * 2
224- case HitSettingsButton :
225- return gripW + buttonW * 3 + padding , padding , buttonW - padding * 2 , height - padding * 2
227+ rect , ok := r .computeGeometry ().bounds [button ]
228+ if ! ok {
229+ return 0 , 0 , 0 , 0
226230 }
227- return 0 , 0 , 0 , 0
231+ return rect . Min . X , rect . Min . Y , rect . Dx (), rect . Dy ()
228232}
229233
230- // GetToolbarSize returns the toolbar size
234+ // GetToolbarSize returns the toolbar size(Layout 后 root 尺寸)。
231235func (r * ToolbarRenderer ) GetToolbarSize () (width , height int ) {
232- scale := GetDPIScale ()
233- return int ( toolbarBaseWidth * scale ), int ( toolbarBaseHeight * scale )
236+ sz := r . computeGeometry (). size
237+ return sz . X , sz . Y
234238}
235239
236240// CreateModeIndicatorColor returns the color for mode indicator
0 commit comments