Skip to content

Commit cee711f

Browse files
committed
Update README for V3.0. Adopt left:right and top:bottom for HSplit and VSplit init. Fix previews.
1 parent 4607ab4 commit cee711f

10 files changed

+380
-169
lines changed

Demo/SplitDemo/DemoApp.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ struct DemoApp: View {
1818
switch demoID {
1919
case .simpleDefaults:
2020
HSplit(
21-
primary: { Color.green },
22-
secondary: { Color.red }
21+
left: { Color.green },
22+
right: { Color.red }
2323
)
2424
case .simpleAdjustable:
2525
Split(

Demo/SplitDemo/DemoModel.swift

+4-4
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ enum DemoID: String, CaseIterable {
2323
/// The `label` is used for the Menu, `description` for the Text at the bottom.
2424
///
2525
/// The `holders` identify the LayoutHolder and SideHolders that can be used to control
26-
/// the various SplitViews in the demo. These need to be defined once, so that the
27-
/// DemoToolbar at the top and the individual SplitViews are holding onto the same
26+
/// the various Split views in the demo. These need to be defined once, so that the
27+
/// DemoToolbar at the top and the individual Split views are holding onto the same
2828
/// ObservableObject.
2929
let demos: [DemoID : Demo] = [
3030
.simpleDefaults :
@@ -70,14 +70,14 @@ let demos: [DemoID : Demo] = [
7070
]
7171

7272
/// Demo holds onto the labels for the Menu and descriptions for the Text at the bottom, along with
73-
/// the SplitStateHolders that are used by the DemoToolbar buttons and the SplitViews themselves.
73+
/// the SplitStateHolders that are used by the DemoToolbar buttons and the Split views themselves.
7474
struct Demo {
7575
var label: String
7676
var description: String
7777
var holders: [SplitStateHolder] = []
7878
}
7979

80-
/// The combination of LayoutHolder and SideHolder used in one SplitView.
80+
/// The combination of LayoutHolder and SideHolder used in one Split view.
8181
///
8282
/// Has to be Identifiable because we ForEach over the `demo.holders` to create the
8383
/// Buttons dynamically.

Demo/SplitDemo/DemoSplitter.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import SplitView
1111
/// A custom splitter for the `.customSplitter` demo.
1212
///
1313
/// Note a custom splitter must conform to SplitDivider protocol, which means it is a View that can tell the
14-
/// SplitView what its `visibleThickness` is. The SplitView separates the `primary` and `secondary`
14+
/// Split view what its `visibleThickness` is. The Split view separates the `primary` and `secondary`
1515
/// views by the `visibleThickness` of the SplitDivider.
1616
///
1717
/// A custom splitter should be sensitive to the layout, because if the layout changes, then the splitter needs to

README.md

+213-105
Large diffs are not rendered by default.

Sources/SplitView/HSplit.swift

+33-3
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public struct HSplit<P: View, D: View, S: View>: View {
1818

1919
public var body: some View {
2020
Split(primary: { primary }, secondary: { secondary })
21-
.layout(.horizontal)
21+
.layout(LayoutHolder(.horizontal))
2222
.styling(styling)
2323
.constraints(constraints)
2424
.splitter {
@@ -29,12 +29,12 @@ public struct HSplit<P: View, D: View, S: View>: View {
2929
.hide(hide)
3030
}
3131

32-
public init(@ViewBuilder primary: @escaping ()->P, @ViewBuilder secondary: @escaping ()->S) where D == Splitter {
32+
public init(@ViewBuilder left: @escaping ()->P, @ViewBuilder right: @escaping ()->S) where D == Splitter {
3333
let fraction = FractionHolder()
3434
let hide = SideHolder()
3535
let styling = SplitStyling()
3636
let constraints = SplitConstraints()
37-
self.init(fraction: fraction, hide: hide, styling: styling, constraints: constraints, primary: { primary() }, splitter: { D() }, secondary: { secondary() })
37+
self.init(fraction: fraction, hide: hide, styling: styling, constraints: constraints, primary: { left() }, splitter: { D() }, secondary: { right() })
3838
}
3939

4040
private init(fraction: FractionHolder, hide: SideHolder, styling: SplitStyling, constraints: SplitConstraints, @ViewBuilder primary: @escaping ()->P, @ViewBuilder splitter: @escaping ()->D, @ViewBuilder secondary: @escaping ()->S) {
@@ -63,11 +63,13 @@ public struct HSplit<P: View, D: View, S: View>: View {
6363
return HSplit<P, T, S>(fraction: fraction, hide: hide, styling: styling, constraints: constraints, primary: { primary }, splitter: splitter, secondary: { secondary })
6464
}
6565

66+
/// Return a new instance of HSplit with `constraints` set to these values.
6667
public func constraints(minPFraction: CGFloat? = nil, minSFraction: CGFloat? = nil, priority: SplitSide? = nil) -> HSplit {
6768
let constraints = SplitConstraints(minPFraction: minPFraction, minSFraction: minSFraction, priority: priority)
6869
return HSplit(fraction: fraction, hide: hide, styling: styling, constraints: constraints, primary: { primary }, splitter: { splitter }, secondary: { secondary })
6970
}
7071

72+
/// Return a new instance of HSplit with `styling` set to these values.
7173
public func styling(color: Color? = nil, inset: CGFloat? = nil, visibleThickness: CGFloat? = nil, invisibleThickness: CGFloat? = nil) -> HSplit {
7274
let styling = SplitStyling(color: color, inset: inset, visibleThickness: visibleThickness, invisibleThickness: invisibleThickness)
7375
return HSplit(fraction: fraction, hide: hide, styling: styling, constraints: constraints, primary: { primary }, splitter: { splitter }, secondary: { secondary })
@@ -94,3 +96,31 @@ public struct HSplit<P: View, D: View, S: View>: View {
9496
}
9597

9698
}
99+
100+
struct HSplit_Previews: PreviewProvider {
101+
static var previews: some View {
102+
HSplit(
103+
left: { Color.green },
104+
right: {
105+
VSplit(
106+
top: { Color.red },
107+
bottom: {
108+
HSplit(
109+
left: { Color.blue },
110+
right: { Color.yellow }
111+
)
112+
}
113+
)
114+
}
115+
)
116+
117+
HSplit(
118+
left: {
119+
VSplit(top: { Color.red }, bottom: { Color.green })
120+
},
121+
right: {
122+
VSplit(top: { Color.yellow }, bottom: { Color.blue })
123+
}
124+
)
125+
}
126+
}

Sources/SplitView/Split.swift

+54-43
Original file line numberDiff line numberDiff line change
@@ -205,10 +205,9 @@ public struct Split<P: View, D: View, S: View>: View {
205205
private func isDraggable() -> Bool {
206206
guard hide.side != nil || minPFraction != nil || minSFraction != nil else { return true }
207207
guard let side = hide.side else { return true }
208-
switch side {
209-
case .primary:
208+
if side.isPrimary {
210209
return minPFraction == nil
211-
case .secondary:
210+
} else {
212211
return minSFraction == nil
213212
}
214213
}
@@ -250,7 +249,7 @@ public struct Split<P: View, D: View, S: View>: View {
250249

251250
/// Return a new Split with the `splitter` set to a new type.
252251
///
253-
/// If the splitter is a SplitDivider, get its `visibleThickness` and set that in `styling` before returning.
252+
/// If the splitter is a SplitDivider, then get its `visibleThickness` and set it in `styling` before returning.
254253
public func splitter<T>(@ViewBuilder _ splitter: @escaping ()->T) -> Split<P, T, S> where T: View {
255254
let newSplitter = splitter()
256255
if let splitDivider = newSplitter as? (any SplitDivider) {
@@ -259,82 +258,94 @@ public struct Split<P: View, D: View, S: View>: View {
259258
return Split<P, T, S>(layout, fraction: fraction, hide: hide, styling: styling, constraints: constraints, primary: { primary }, splitter: splitter, secondary: { secondary })
260259
}
261260

261+
/// Return a new instance of Split with `constraints` set to a SplitConstraints holding these values.
262262
public func constraints(minPFraction: CGFloat? = nil, minSFraction: CGFloat? = nil, priority: SplitSide? = nil) -> Split {
263263
let constraints = SplitConstraints(minPFraction: minPFraction, minSFraction: minSFraction, priority: priority)
264264
return Split(layout, fraction: fraction, hide: hide, styling: styling, constraints: constraints, primary: { primary }, splitter: { splitter }, secondary: { secondary })
265265
}
266266

267+
/// Return a new instance of Split with `constraints` set to this SplitConstraints.
268+
///
269+
/// This is a convenience method for HSplit and VSplit.
267270
public func constraints(_ constraints: SplitConstraints) -> Split {
268271
self.constraints(minPFraction: constraints.minPFraction, minSFraction: constraints.minSFraction, priority: constraints.priority)
269272
}
270273

274+
/// Return a new instance of Split with `styling` set to a SplitStyling holding these values.
275+
///
276+
/// This is a convenience method for `Splitter.line()` which is also used by `Splitter.invisible()`.
271277
public func styling(color: Color? = nil, inset: CGFloat? = nil, visibleThickness: CGFloat? = nil, invisibleThickness: CGFloat? = nil) -> Split {
272278
let styling = SplitStyling(color: color, inset: inset, visibleThickness: visibleThickness, invisibleThickness: invisibleThickness)
273279
return Split(layout, fraction: fraction, hide: hide, styling: styling, constraints: constraints, primary: { primary }, splitter: { splitter }, secondary: { secondary })
274280
}
275281

282+
/// Return a new instance of Split with `styling` set to this SplitStyling.
283+
///
284+
/// This is a convenience method for HSplit and VSplit.
276285
public func styling(_ styling: SplitStyling) -> Split {
277286
self.styling(color: styling.color, inset: styling.inset, visibleThickness: styling.visibleThickness, invisibleThickness: styling.invisibleThickness)
278287
}
279288

280-
/// Return a new instance of Split with `layout` set to this LayoutHolder
289+
/// Return a new instance of Split with `layout` set to this LayoutHolder.
290+
///
291+
/// Split only supports `layout` specified using a LayoutHolder because if you are not going
292+
/// to change the `layout`, then you should just use HSplit or VSplit.
281293
public func layout(_ layout: LayoutHolder) -> Split {
282294
Split(layout, fraction: fraction, hide: hide, styling: styling, constraints: constraints, primary: { primary }, splitter: { splitter }, secondary: { secondary })
283295
}
284296

285-
/// Return a new instance of Split with `layout` set to a LayoutHolder holding onto this SplitLayout
286-
public func layout(_ layout: SplitLayout) -> Split {
287-
self.layout(LayoutHolder(layout))
288-
}
289-
290-
/// Return a new instance of Split with `fraction` set to this FractionHolder
297+
/// Return a new instance of Split with `fraction` set to this FractionHolder.
291298
public func fraction(_ fraction: FractionHolder) -> Split {
292299
Split(layout, fraction: fraction, hide: hide, styling: styling, constraints: constraints, primary: { primary }, splitter: { splitter }, secondary: { secondary })
293300
}
294301

295-
/// Return a new instance of Split with `fraction` set to a FractionHolder holding onto this CGFloat
302+
/// Return a new instance of Split with `fraction` set to a FractionHolder holding onto this CGFloat.
296303
public func fraction(_ fraction: CGFloat) -> Split {
297304
self.fraction(FractionHolder(fraction))
298305
}
299306

300-
/// Return a new instance of Split with `hide` set to this SideHolder
307+
/// Return a new instance of Split with `hide` set to this SideHolder.
301308
public func hide(_ side: SideHolder) -> Split {
302309
Split(layout, fraction: fraction, hide: side, styling: styling, constraints: constraints, primary: { primary }, splitter: { splitter }, secondary: { secondary })
303310
}
304311

305-
/// Return a new instance of Split with `hide` set to a SideHolder holding onto this SplitSide
312+
/// Return a new instance of Split with `hide` set to a SideHolder holding onto this SplitSide.
306313
public func hide(_ side: SplitSide) -> Split {
307314
self.hide(SideHolder(side))
308315
}
309316

310317
}
311318

312-
//struct Split_Previews: PreviewProvider {
313-
// static var previews: some View {
314-
// Split(.horizontal,
315-
// fraction: FractionHolder(0.75),
316-
// primary: { Color.red },
317-
// splitter: { Splitter.horizontal },
318-
// secondary: {
319-
// Split(.vertical,
320-
// primary: { Color.blue },
321-
// splitter: { Splitter.vertical },
322-
// secondary: {
323-
// Split(.vertical,
324-
// primary: { Color.green },
325-
// splitter: { Splitter.vertical },
326-
// secondary: { Color.yellow }
327-
// )
328-
// }
329-
// )
330-
// }
331-
// )
332-
// .frame(width: 400, height: 400)
333-
// Split(.horizontal,
334-
// primary: { Split(.vertical, primary: { Color.red }, splitter: { Splitter.vertical }, secondary: { Color.green }) },
335-
// splitter: { Splitter.horizontal },
336-
// secondary: { Split(.horizontal, primary: { Color.blue }, splitter: { Splitter.horizontal }, secondary: { Color.yellow }) }
337-
// )
338-
// .frame(width: 400, height: 400)
339-
// }
340-
//}
319+
struct Split_Previews: PreviewProvider {
320+
static var previews: some View {
321+
Split(
322+
primary: { Color.green },
323+
secondary: {
324+
Split(
325+
primary: { Color.red },
326+
secondary: {
327+
Split(
328+
primary: { Color.blue },
329+
secondary: { Color.yellow }
330+
)
331+
.layout(LayoutHolder(.horizontal))
332+
}
333+
)
334+
.layout(LayoutHolder(.vertical))
335+
}
336+
)
337+
.layout(LayoutHolder(.horizontal))
338+
339+
Split(
340+
primary: {
341+
Split(primary: { Color.red }, secondary: { Color.green })
342+
.layout(LayoutHolder(.vertical))
343+
},
344+
secondary: {
345+
Split(primary: { Color.yellow }, secondary: { Color.blue })
346+
.layout(LayoutHolder(.vertical))
347+
}
348+
)
349+
.layout(LayoutHolder(.horizontal))
350+
}
351+
}

Sources/SplitView/SplitEnums.swift

+14-5
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,22 @@ public enum SplitLayout: String, CaseIterable {
1515

1616
/// The two sides of a SplitView.
1717
///
18-
/// For `SplitLayout.Horizontal`, `Primary` is left, `Secondary` is right.
19-
/// For `SplitLayout.Vertical`, `Primary` is top, `Secondary` is bottom.
20-
/// Used to identify the side (if any) which is hidden.
18+
/// Use `isPrimary` and `isSecondary` rather than accessing the cases directly.
19+
///
20+
/// For `SplitLayout.horizontal`, `primary` is left, `secondary` is right.
21+
/// For `SplitLayout.vertical`, `primary` is top, `secondary` is bottom.
22+
///
23+
/// For convenience and clarity when creating and constraining an HSplit view, you can use
24+
/// `left` and `right` instead of `primary` and `secondary`. Similarly you can
25+
/// use `top` and `bottom` when creating and constraining a VSplit view.
2126
public enum SplitSide: String {
2227
case primary
2328
case secondary
29+
case left
30+
case right
31+
case top
32+
case bottom
2433

25-
var isPrimary: Bool { self == .primary }
26-
var isSecondary: Bool { self == .secondary }
34+
var isPrimary: Bool { self == .primary || self == .left || self == .top }
35+
var isSecondary: Bool { self == .secondary || self == .right || self == .bottom }
2736
}

Sources/SplitView/SplitHolders.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
import Foundation
99

10-
/// An ObservableObject that `SplitView` observes to change what its `layout` is.
10+
/// An ObservableObject that `Split` view observes to change what its `layout` is.
1111
///
1212
/// Use the static `usingUserDefaults` method to save state automatically in `UserDefaults.standard`.
1313
public class LayoutHolder: ObservableObject {
@@ -51,7 +51,7 @@ public class LayoutHolder: ObservableObject {
5151

5252
}
5353

54-
/// An ObservableObject that `SplitView` observes to change what fraction of the width/height the `splitter`
54+
/// An ObservableObject that `Split` view observes to change what fraction of the width/height the `splitter`
5555
/// will be positioned at upon open.
5656
///
5757
/// Use the static `usingUserDefaults` method to save state automatically in `UserDefaults.standard`.
@@ -79,7 +79,7 @@ public class FractionHolder: ObservableObject {
7979
}
8080
}
8181

82-
/// An ObservableObject that `SplitView` observes to change whether one of the `SplitSide`s is hidden.
82+
/// An ObservableObject that `Split` view observes to change whether one of the `SplitSide`s is hidden.
8383
///
8484
/// Use the static `usingUserDefaults` method to save state automatically in `UserDefaults.standard`.
8585
public class SideHolder: ObservableObject {

Sources/SplitView/Splitter.swift

+23
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,26 @@ public struct Splitter: SplitDivider {
7777
}
7878

7979
}
80+
81+
struct Splitter_Previews: PreviewProvider {
82+
static var previews: some View {
83+
Splitter()
84+
.environmentObject(LayoutHolder(.horizontal))
85+
.environmentObject(SplitStyling())
86+
Splitter(color: Color.red, inset: 2, visibleThickness: 8, invisibleThickness: 30)
87+
.environmentObject(LayoutHolder(.horizontal))
88+
.environmentObject(SplitStyling())
89+
Splitter.line()
90+
.environmentObject(LayoutHolder(.horizontal))
91+
.environmentObject(SplitStyling())
92+
Splitter()
93+
.environmentObject(LayoutHolder(.vertical))
94+
.environmentObject(SplitStyling())
95+
Splitter(color: Color.red, inset: 2, visibleThickness: 8, invisibleThickness: 30)
96+
.environmentObject(LayoutHolder(.vertical))
97+
.environmentObject(SplitStyling())
98+
Splitter.line()
99+
.environmentObject(LayoutHolder(.vertical))
100+
.environmentObject(SplitStyling())
101+
}
102+
}

0 commit comments

Comments
 (0)