@@ -77,10 +77,8 @@ struct PadLayoutEditView: View {
7777 editorContent ( areaW: geo. size. width, areaH: geo. size. height)
7878
7979 VStack {
80- floatingToolbar
80+ compactToolbar
8181 Spacer ( )
82- visibilityRow
83- resetButtons ( isLandscape: true )
8482 }
8583 }
8684 . contentShape ( Rectangle ( ) )
@@ -102,7 +100,7 @@ struct PadLayoutEditView: View {
102100 }
103101
104102 VStack {
105- floatingToolbar
103+ compactToolbar
106104 Spacer ( )
107105 }
108106 }
@@ -134,102 +132,76 @@ struct PadLayoutEditView: View {
134132 }
135133
136134 VStack {
137- HStack {
138- Button ( " Cancel " ) {
139- if let snapshot = originalSnapshot {
140- restore ( snapshot: snapshot)
141- }
142- onDismiss ( )
143- }
144- . padding ( 8 )
145- . background ( . black. opacity ( 0.5 ) , in: Capsule ( ) )
146- Spacer ( )
147- Button ( " Undo " ) {
148- guard let snapshot = undoStack. popLast ( ) else { return }
149- restore ( snapshot: snapshot)
150- }
151- . disabled ( undoStack. isEmpty)
152- . font ( . caption. weight ( . semibold) )
153- . padding ( . horizontal, 10 )
154- . padding ( . vertical, 6 )
155- . background ( . black. opacity ( 0.5 ) , in: Capsule ( ) )
156- Spacer ( )
157- Picker ( " " , selection: $editLandscape) {
158- Text ( " Portrait " ) . tag ( false )
159- Text ( " Landscape " ) . tag ( true )
160- }
161- . pickerStyle ( . segmented)
162- . frame ( width: 168 )
163- . background ( . black. opacity ( 0.3 ) , in: RoundedRectangle ( cornerRadius: 8 ) )
164- Spacer ( )
165- skinPickerMenu
166- Spacer ( )
167- Button ( " Save " ) {
168- NSLog ( " @@PAD_LAYOUT@@ save portrait=%d landscape=%d " , layout. portrait. count, layout. landscape. count)
169- layout. save ( )
170- undoStack. removeAll ( )
171- originalSnapshot = nil
172- onDismiss ( )
173- }
174- . fontWeight ( . semibold)
175- . padding ( 8 )
176- . background ( . black. opacity ( 0.5 ) , in: Capsule ( ) )
177- }
178- . padding ( . horizontal)
179- . padding ( . top, 4 )
135+ compactToolbar
180136 Spacer ( )
181- visibilityRow
182- resetButtons ( isLandscape: false )
183137 }
184138 }
185139 . contentShape ( Rectangle ( ) )
186140 }
187141 }
188142
189- private var floatingToolbar : some View {
190- HStack {
191- Button ( " Cancel " ) {
143+ // MARK: - Compact toolbar
144+ private var compactToolbar : some View {
145+ HStack ( spacing: 12 ) {
146+ // Cancel
147+ Button {
192148 if let snapshot = originalSnapshot {
193149 restore ( snapshot: snapshot)
194150 }
195151 onDismiss ( )
152+ } label: {
153+ Image ( systemName: " xmark.circle.fill " )
154+ . font ( . title2)
155+ . foregroundStyle ( . white)
196156 }
197- . padding ( 8 )
198- . background ( . black. opacity ( 0.5 ) , in: Capsule ( ) )
199- Spacer ( )
200- Button ( " Undo " ) {
157+
158+ // Undo
159+ Button {
201160 guard let snapshot = undoStack. popLast ( ) else { return }
202161 restore ( snapshot: snapshot)
162+ } label: {
163+ Image ( systemName: " arrow.uturn.backward.circle " )
164+ . font ( . title2)
165+ . foregroundStyle ( undoStack. isEmpty ? . white. opacity ( 0.3 ) : . white)
203166 }
204167 . disabled ( undoStack. isEmpty)
205- . font ( . caption. weight ( . semibold) )
206- . padding ( . horizontal, 10 )
207- . padding ( . vertical, 6 )
208- . background ( . black. opacity ( 0.5 ) , in: Capsule ( ) )
168+
209169 Spacer ( )
170+
171+ // Portrait / Landscape
210172 Picker ( " " , selection: $editLandscape) {
211173 Text ( " Portrait " ) . tag ( false )
212174 Text ( " Landscape " ) . tag ( true )
213175 }
214176 . pickerStyle ( . segmented)
215- . frame ( width: 168 )
177+ . frame ( width: 140 )
216178 . background ( . black. opacity ( 0.3 ) , in: RoundedRectangle ( cornerRadius: 8 ) )
179+
217180 Spacer ( )
181+
182+ // Skin picker
218183 skinPickerMenu
219- Spacer ( )
220- Button ( " Save " ) {
184+
185+ // Options (visibility + reset)
186+ optionsMenu
187+
188+ // Save
189+ Button {
221190 NSLog ( " @@PAD_LAYOUT@@ save portrait=%d landscape=%d " , layout. portrait. count, layout. landscape. count)
222191 layout. save ( )
223192 undoStack. removeAll ( )
224193 originalSnapshot = nil
225194 onDismiss ( )
195+ } label: {
196+ Image ( systemName: " checkmark.circle.fill " )
197+ . font ( . title2)
198+ . foregroundStyle ( . green)
226199 }
227- . fontWeight ( . semibold)
228- . padding ( 8 )
229- . background ( . black. opacity ( 0.5 ) , in: Capsule ( ) )
230200 }
231201 . padding ( . horizontal)
232202 . padding ( . top, 4 )
203+ . padding ( . bottom, 8 )
204+ . background ( . black. opacity ( 0.5 ) )
233205 }
234206
235207 private var skinPickerMenu : some View {
@@ -243,81 +215,58 @@ struct PadLayoutEditView: View {
243215 }
244216 } label: {
245217 Image ( systemName: " paintpalette.fill " )
246- . font ( . callout )
218+ . font ( . title2 )
247219 . foregroundStyle ( . white)
248- . frame ( width: 34 , height: 34 )
249- . background ( . black. opacity ( 0.5 ) , in: Circle ( ) )
250220 }
251221 }
252222
253- private func resetButtons( isLandscape: Bool ) -> some View {
254- HStack ( spacing: 12 ) {
255- Button ( " Reset Action " ) {
256- pushSnapshot ( )
257- layout. resetPerButtonActionButtons ( isLandscape: isLandscape)
258- }
259- . font ( . caption)
260- . foregroundStyle ( . red. opacity ( 0.7 ) )
261-
262- Button ( " Reset D-Pad " ) {
263- pushSnapshot ( )
264- layout. resetPerButtonDPad ( isLandscape: isLandscape)
265- }
266- . font ( . caption)
267- . foregroundStyle ( . red. opacity ( 0.7 ) )
268-
269- Button ( " Reset All " ) {
270- pushSnapshot ( )
271- layout. resetAll ( )
223+ private var optionsMenu : some View {
224+ Menu {
225+ // Visibility section
226+ Section ( " Visibility " ) {
227+ ForEach ( PadLayoutStore . groupIDs. filter { $0 != " action " } , id: \. self) { ( id: String ) in
228+ visibilityMenuItem ( id: id)
229+ }
230+ visibilityMenuItem ( id: " cross " , label: " X " )
231+ visibilityMenuItem ( id: " circle " , label: " O " )
232+ visibilityMenuItem ( id: " triangle " , label: " Triangle " )
233+ visibilityMenuItem ( id: " square " , label: " Square " )
272234 }
273- . font ( . caption)
274- . foregroundStyle ( . red. opacity ( 0.7 ) )
275235
276- Button ( " Reset Visibility " ) {
277- pushSnapshot ( )
278- layout. resetControlVisibility ( )
279- }
280- . font ( . caption)
281- . foregroundStyle ( . red. opacity ( 0.7 ) )
282- }
283- . padding ( . bottom, 6 )
284- }
285-
286- private var visibilityRow : some View {
287- ScrollView ( . horizontal, showsIndicators: false ) {
288- HStack ( spacing: 10 ) {
289- // Group toggles (excluding the combined action group)
290- ForEach ( PadLayoutStore . groupIDs. filter { $0 != " action " } , id: \. self) { ( id: String ) in
291- visibilityButton ( id: id)
236+ // Reset section
237+ Section ( " Reset " ) {
238+ Button ( " Reset Action " , role: . destructive) {
239+ pushSnapshot ( )
240+ layout. resetPerButtonActionButtons ( isLandscape: editLandscape)
241+ }
242+ Button ( " Reset D-Pad " , role: . destructive) {
243+ pushSnapshot ( )
244+ layout. resetPerButtonDPad ( isLandscape: editLandscape)
245+ }
246+ Button ( " Reset All " , role: . destructive) {
247+ pushSnapshot ( )
248+ layout. resetAll ( )
249+ }
250+ Button ( " Reset Visibility " , role: . destructive) {
251+ pushSnapshot ( )
252+ layout. resetControlVisibility ( )
292253 }
293- // Per-button action toggles
294- visibilityButton ( id: " cross " , label: " Toggle: X " )
295- visibilityButton ( id: " circle " , label: " Toggle: O " )
296- visibilityButton ( id: " triangle " , label: " Toggle: Triangle " )
297- visibilityButton ( id: " square " , label: " Toggle: Square " )
298254 }
299- . padding ( . horizontal, 12 )
255+ } label: {
256+ Image ( systemName: " ellipsis.circle " )
257+ . font ( . title2)
258+ . foregroundStyle ( . white)
300259 }
301- . frame ( height: 32 )
302- . padding ( . bottom, 4 )
303260 }
304261
305- private func visibilityButton ( id: String , label: String ? = nil ) -> some View {
262+ private func visibilityMenuItem ( id: String , label: String ? = nil ) -> some View {
306263 let visible = layout. isControlVisible ( id)
307264 return Button {
308265 pushSnapshot ( )
309266 layout. setControlVisible ( id, visible: !visible)
310267 } label: {
311- HStack ( spacing: 4 ) {
312- Image ( systemName: visible ? " eye " : " eye.slash " )
313- . font ( . caption2)
314- Text ( label ?? id. uppercased ( ) )
315- . font ( . caption2. weight ( . semibold) )
316- }
317- . foregroundStyle ( visible ? Color . primary : Color . red)
318- . padding ( . horizontal, 8 )
319- . padding ( . vertical, 4 )
320- . background ( visible ? Color . white. opacity ( 0.08 ) : Color . red. opacity ( 0.12 ) , in: Capsule ( ) )
268+ let name = label ?? id. uppercased ( )
269+ Label ( name, systemImage: visible ? " eye " : " eye.slash " )
321270 }
322271 }
323272
0 commit comments