Skip to content

Commit f24d467

Browse files
authored
Merge pull request #7 from tgrapperon/view-modifiers
2 parents bab51e0 + a317b20 commit f24d467

File tree

1 file changed

+104
-65
lines changed

1 file changed

+104
-65
lines changed

Sources/SwiftUILayoutGuides/SwiftUILayoutGuides.swift

Lines changed: 104 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,18 @@ public struct WithLayoutMargins<Content>: View where Content: View {
3939
///
4040
/// - Note: This modifier is equivalent to calling ``.fitToReadableContentWidth()`` on
4141
/// the content view.
42+
@available(
43+
iOS, deprecated: 9999.0, message: "Use the `.fitToReadableContentWidth` modifier instead."
44+
)
45+
@available(
46+
macOS, deprecated: 9999.0, message: "Use the `.fitToReadableContentWidth` modifier instead."
47+
)
48+
@available(
49+
tvOS, deprecated: 9999.0, message: "Use the `.fitToReadableContentWidth` modifier instead."
50+
)
51+
@available(
52+
watchOS, deprecated: 9999.0, message: "Use the `.fitToReadableContentWidth` modifier instead."
53+
)
4254
public struct FitReadableContentWidth<Content>: View where Content: View {
4355
let alignment: Alignment
4456
let content: Content
@@ -58,27 +70,24 @@ public struct FitReadableContentWidth<Content>: View where Content: View {
5870
}
5971

6072
public var body: some View {
61-
InsetContent(alignment: alignment, content: content)
62-
.measureLayoutMargins()
63-
}
64-
65-
private struct InsetContent: View {
66-
let alignment: Alignment
67-
let content: Content
68-
@Environment(\.readableContentInsets) var readableContentInsets
69-
var body: some View {
70-
content
71-
.frame(maxWidth: .infinity, alignment: alignment)
72-
.padding(.leading, readableContentInsets.leading)
73-
.padding(.trailing, readableContentInsets.trailing)
74-
}
73+
self.modifier(FitLayoutGuidesWidth(alignment: alignment, kind: .readableContent))
7574
}
7675
}
7776

7877
/// This view makes its content `View` fit the layout margins guide width.
7978
///
8079
/// - Note: This modifier is equivalent to calling ``.fitToLayoutMarginsWidth()`` on
8180
/// the content view.
81+
@available(iOS, deprecated: 9999.0, message: "Use the `.fitToLayoutMarginsWidth` modifier instead.")
82+
@available(
83+
macOS, deprecated: 9999.0, message: "Use the `.fitToLayoutMarginsWidth` modifier instead."
84+
)
85+
@available(
86+
tvOS, deprecated: 9999.0, message: "Use the `.fitToLayoutMarginsWidth` modifier instead."
87+
)
88+
@available(
89+
watchOS, deprecated: 9999.0, message: "Use the `.fitToLayoutMarginsWidth` modifier instead."
90+
)
8291
public struct FitLayoutMarginsWidth<Content>: View where Content: View {
8392
let alignment: Alignment
8493
let content: Content
@@ -98,15 +107,45 @@ public struct FitLayoutMarginsWidth<Content>: View where Content: View {
98107
}
99108

100109
public var body: some View {
101-
InsetContent(alignment: alignment, content: content)
102-
.measureLayoutMargins()
110+
self.modifier(FitLayoutGuidesWidth(alignment: alignment, kind: .layoutMargins))
103111
}
112+
}
104113

105-
private struct InsetContent: View {
114+
internal struct FitLayoutGuidesWidth: ViewModifier {
115+
enum Kind {
116+
case layoutMargins
117+
case readableContent
118+
}
119+
120+
let alignment: Alignment
121+
let kind: Kind
122+
123+
func body(content: Content) -> some View {
124+
switch kind {
125+
case .layoutMargins:
126+
content.modifier(InsetLayoutMargins(alignment: alignment))
127+
.measureLayoutMargins()
128+
case .readableContent:
129+
content.modifier(InsetReadableContent(alignment: alignment))
130+
.measureLayoutMargins()
131+
}
132+
}
133+
134+
private struct InsetReadableContent: ViewModifier {
135+
let alignment: Alignment
136+
@Environment(\.readableContentInsets) var readableContentInsets
137+
func body(content: Content) -> some View {
138+
content
139+
.frame(maxWidth: .infinity, alignment: alignment)
140+
.padding(.leading, readableContentInsets.leading)
141+
.padding(.trailing, readableContentInsets.trailing)
142+
}
143+
}
144+
145+
private struct InsetLayoutMargins: ViewModifier {
106146
let alignment: Alignment
107-
let content: Content
108147
@Environment(\.layoutMarginsInsets) var layoutMarginsInsets
109-
var body: some View {
148+
func body(content: Content) -> some View {
110149
content
111150
.frame(maxWidth: .infinity, alignment: alignment)
112151
.padding(.leading, layoutMarginsInsets.leading)
@@ -124,9 +163,9 @@ extension View {
124163
/// - Note: This modifier is equivalent to wrapping the view inside a
125164
/// ``FitReadableContentWidth`` view.
126165
public func fitToReadableContentWidth(alignment: Alignment = .center) -> some View {
127-
FitReadableContentWidth(alignment: alignment) { self }
166+
self.modifier(FitLayoutGuidesWidth(alignment: alignment, kind: .readableContent))
128167
}
129-
168+
130169
/// Use this modifier to make the view fit the layout margins guide width.
131170
///
132171
/// - Parameter alignment: The `Alignment` to use when the view is smaller than
@@ -135,16 +174,14 @@ extension View {
135174
/// - Note: This modifier is equivalent to wrapping the view inside a
136175
/// ``FitLayoutMarginsWidth`` view.
137176
public func fitToLayoutMarginsWidth(alignment: Alignment = .center) -> some View {
138-
FitLayoutMarginsWidth(alignment: alignment) { self }
177+
self.modifier(FitLayoutGuidesWidth(alignment: alignment, kind: .layoutMargins))
139178
}
140-
141-
142179
/// Use this modifier to populate the ``layoutMarginsInsets`` and ``readableContentInsets``
143180
/// for the target view.
144181
///
145182
/// - Note: You don't have to wrap this view inside a ``WithLayoutMargins`` view.
146183
public func measureLayoutMargins() -> some View {
147-
modifier(LayoutGuidesModifier())
184+
self.modifier(LayoutGuidesModifier())
148185
}
149186
}
150187

@@ -182,11 +219,13 @@ struct LayoutGuidesModifier: ViewModifier {
182219
.environment(\.layoutMarginsInsets, layoutMarginsInsets)
183220
.environment(\.readableContentInsets, readableContentInsets)
184221
.background(
185-
LayoutGuides(onLayoutMarginsGuideChange: {
186-
layoutMarginsInsets = $0
187-
}, onReadableContentGuideChange: {
188-
readableContentInsets = $0
189-
})
222+
LayoutGuides(
223+
onLayoutMarginsGuideChange: {
224+
layoutMarginsInsets = $0
225+
},
226+
onReadableContentGuideChange: {
227+
readableContentInsets = $0
228+
})
190229
)
191230
#endif
192231
}
@@ -213,7 +252,7 @@ struct LayoutGuidesModifier: ViewModifier {
213252
final class LayoutGuidesView: UIView {
214253
var onLayoutMarginsGuideChange: (EdgeInsets) -> Void = { _ in }
215254
var onReadableContentGuideChange: (EdgeInsets) -> Void = { _ in }
216-
255+
217256
override func layoutMarginsDidChange() {
218257
super.layoutMarginsDidChange()
219258
updateLayoutMargins()
@@ -318,43 +357,43 @@ struct LayoutGuidesModifier: ViewModifier {
318357
}
319358
}
320359

321-
#if os(iOS)
322-
@available(iOS 16.0, *)
323-
struct SwiftUILayoutGuides_Previews: PreviewProvider {
324-
static func sample<Content>(_ title: String, _ content: () -> Content) -> some View
325-
where Content: View {
326-
VStack(alignment: .leading) {
327-
Text(title)
328-
.font(Font.system(size: 20, weight: .bold))
329-
.padding()
330-
content()
360+
#if os(iOS)
361+
@available(iOS 16.0, *)
362+
struct SwiftUILayoutGuides_Previews: PreviewProvider {
363+
static func sample<Content>(_ title: String, _ content: () -> Content) -> some View
364+
where Content: View {
365+
VStack(alignment: .leading) {
366+
Text(title)
367+
.font(Font.system(size: 20, weight: .bold))
368+
.padding()
369+
content()
370+
}
371+
.border(Color.primary, width: 2)
331372
}
332-
.border(Color.primary, width: 2)
333-
}
334373

335-
static var previews: some View {
336-
NavigationSplitView {
337-
VStack(spacing: 0) {
338-
sample("ScrollView") { ScrollViewTest() }
339-
sample("List.plain") { ListTest().listStyle(.plain) }
340-
#if os(iOS) || os(tvOS)
341-
sample("List.grouped") { ListTest().listStyle(.grouped) }
342-
sample("List.insetGrouped") { ListTest().listStyle(.insetGrouped) }
343-
#endif
344-
}
345-
} detail: {
346-
VStack(spacing: 0) {
347-
sample("ScrollView") { ScrollViewTest() }
348-
sample("List.plain") { ListTest().listStyle(.plain) }
349-
#if os(iOS) || os(tvOS)
350-
sample("List.grouped") { ListTest().listStyle(.grouped) }
351-
sample("List.insetGrouped") { ListTest().listStyle(.insetGrouped) }
352-
#endif
374+
static var previews: some View {
375+
NavigationSplitView {
376+
VStack(spacing: 0) {
377+
sample("ScrollView") { ScrollViewTest() }
378+
sample("List.plain") { ListTest().listStyle(.plain) }
379+
#if os(iOS) || os(tvOS)
380+
sample("List.grouped") { ListTest().listStyle(.grouped) }
381+
sample("List.insetGrouped") { ListTest().listStyle(.insetGrouped) }
382+
#endif
383+
}
384+
} detail: {
385+
VStack(spacing: 0) {
386+
sample("ScrollView") { ScrollViewTest() }
387+
sample("List.plain") { ListTest().listStyle(.plain) }
388+
#if os(iOS) || os(tvOS)
389+
sample("List.grouped") { ListTest().listStyle(.grouped) }
390+
sample("List.insetGrouped") { ListTest().listStyle(.insetGrouped) }
391+
#endif
392+
}
353393
}
394+
.previewInterfaceOrientation(.landscapeRight)
395+
.previewDevice(PreviewDevice(rawValue: "iPad Pro (11-inch) (4th generation)"))
354396
}
355-
.previewInterfaceOrientation(.landscapeRight)
356-
.previewDevice(PreviewDevice(rawValue: "iPad Pro (11-inch) (4th generation)"))
357397
}
358-
}
359-
#endif
398+
#endif
360399
#endif

0 commit comments

Comments
 (0)