@@ -16,9 +16,15 @@ import ArcGIS
1616import SwiftUI
1717
1818struct SnapGeometryEditsWithUtilityNetworkRulesView : View {
19+ /// The display scale of this environment.
20+ @Environment ( \. displayScale) private var displayScale
21+
1922 /// The view model for the sample.
2023 @StateObject private var model = Model ( )
2124
25+ /// The images representing the different snap rule behavior cases.
26+ @State private var ruleBehaviorImages : [ SnapRuleBehavior ? : Image ] = [ : ]
27+
2228 /// The various states of the sample.
2329 private enum SampleState : Equatable {
2430 /// The sample is being set up.
@@ -94,7 +100,7 @@ struct SnapGeometryEditsWithUtilityNetworkRulesView: View {
94100 VStack ( alignment: . trailing, spacing: 0 ) {
95101 Text ( instructionText)
96102 . multilineTextAlignment ( . center)
97- . frame ( maxWidth: . infinity, alignment : . center )
103+ . frame ( maxWidth: . infinity)
98104 . padding ( 8 )
99105 . background ( . thinMaterial, ignoresSafeAreaEdges: . horizontal)
100106
@@ -110,6 +116,13 @@ struct SnapGeometryEditsWithUtilityNetworkRulesView: View {
110116 . shadow ( radius: 3 )
111117 . padding ( 8 )
112118 . transition ( . move( edge: . trailing) )
119+
120+ Spacer ( )
121+
122+ SnapRuleBehaviorLegend ( images: ruleBehaviorImages)
123+ . frame ( maxWidth: . infinity)
124+ . padding ( 8 )
125+ . background ( . thinMaterial, ignoresSafeAreaEdges: . horizontal)
113126 }
114127 }
115128 . animation ( . default, value: model. selectedElement == nil )
@@ -129,9 +142,12 @@ struct SnapGeometryEditsWithUtilityNetworkRulesView: View {
129142 }
130143 . disabled ( model. snapSourceSettings. isEmpty)
131144 . popover ( isPresented: $sourcesListIsPresented) {
132- SnapSourcesList ( settings: model. snapSourceSettings)
133- . presentationDetents ( [ . fraction( 0.5 ) ] )
134- . frame ( idealWidth: 320 , idealHeight: 390 )
145+ SnapSourcesList (
146+ settings: model. snapSourceSettings,
147+ ruleBehaviorImages: ruleBehaviorImages
148+ )
149+ . presentationDetents ( [ . fraction( 0.5 ) ] )
150+ . frame ( idealWidth: 320 , idealHeight: 390 )
135151 }
136152
137153 Spacer ( )
@@ -149,50 +165,56 @@ struct SnapGeometryEditsWithUtilityNetworkRulesView: View {
149165 }
150166 }
151167 }
168+ . task ( id: displayScale) {
169+ // Creates an image from each rule behavior's symbol.
170+ for behavior in SnapRuleBehavior ? . allCases {
171+ let swatch = try ? await behavior. symbol. makeSwatch ( scale: displayScale)
172+ ruleBehaviorImages [ behavior] = swatch. map ( Image . init ( uiImage: ) )
173+ }
174+ }
152175 }
153176}
154177
155178// MARK: - Helper Views
156179
180+ /// The legend for the different snap rule behavior cases.
181+ private struct SnapRuleBehaviorLegend : View {
182+ /// The images representing the different snap rule behavior cases.
183+ let images : [ SnapRuleBehavior ? : Image ]
184+
185+ var body : some View {
186+ LabeledContent ( " Snapping " ) {
187+ HStack {
188+ ForEach ( SnapRuleBehavior ? . allCases, id: \. self) { behavior in
189+ Label {
190+ Text ( behavior. label)
191+ } icon: {
192+ images [ behavior]
193+ }
194+ }
195+ }
196+ }
197+ . font ( . footnote)
198+ }
199+ }
200+
157201/// A list for enabling and disabling snap source settings.
158202private struct SnapSourcesList : View {
159203 /// The snap source settings to show in the list.
160204 let settings : [ SnapSourceSettings ]
161205
206+ /// The images representing the different snap rule behavior cases.
207+ let ruleBehaviorImages : [ SnapRuleBehavior ? : Image ]
208+
162209 /// The action to dismiss the view.
163210 @Environment ( \. dismiss) private var dismiss
164211
165- /// The display scale of this environment.
166- @Environment ( \. displayScale) private var displayScale
167-
168- /// The images for the snap rule behavior legend.
169- @State private var ruleBehaviorImages : [ SnapRuleBehavior ? : Image ] = [ : ]
170-
171212 var body : some View {
172213 NavigationStack {
173214 Form {
174- Section {
175- ForEach ( Array ( settings. enumerated ( ) ) , id: \. offset) { _, settings in
176- SnapSourceSettingsToggle (
177- settings: settings,
178- image: ruleBehaviorImages [ settings. ruleBehavior]
179- )
180- }
181- }
182-
183- Section ( " Legend " ) {
184- ForEach ( SnapRuleBehavior ? . allCases, id: \. self) { behavior in
185- Label {
186- Text ( behavior. label)
187- } icon: {
188- ruleBehaviorImages [ behavior]
189- }
190- . task ( id: displayScale) {
191- // Creates an image from the rule behavior's symbol.
192- let swatch = try ? await behavior. symbol. makeSwatch ( scale: displayScale)
193- ruleBehaviorImages [ behavior] = Image ( uiImage: swatch ?? UIImage ( ) )
194- }
195- }
215+ ForEach ( Array ( settings. enumerated ( ) ) , id: \. offset) { _, settings in
216+ let image = ruleBehaviorImages [ settings. ruleBehavior]
217+ SnapSourceSettingsToggle ( settings: settings, image: image)
196218 }
197219 }
198220 . navigationTitle ( " Snap Sources " )
@@ -255,12 +277,12 @@ extension Optional<SnapRuleBehavior> {
255277 return [ . none, . rulesLimitSnapping, . rulesPreventSnapping]
256278 }
257279
258- /// The human-readable label for the snap rule behavior.
280+ /// The legend label for the snap rule behavior.
259281 fileprivate var label : String {
260282 switch self {
261- case . rulesLimitSnapping: " Rules Limit Snapping "
262- case . rulesPreventSnapping: " Rules Prevent Snapping "
263- default : " None "
283+ case . rulesLimitSnapping: " Limited "
284+ case . rulesPreventSnapping: " Prevented "
285+ default : " Allowed "
264286 }
265287 }
266288
0 commit comments