Skip to content

Commit c375d46

Browse files
author
Reed Es
committed
Another attempt at #30, with full Row Overlay support
1 parent 0cf0526 commit c375d46

15 files changed

+931
-61
lines changed

README.md

+27-28
Original file line numberDiff line numberDiff line change
@@ -120,32 +120,31 @@ _Tabler_ offers twenty-one (21) variants of table views from which you can choos
120120
* RAC - if checked, can be used with `RandomAccessCollection` (e.g., array of struct values)
121121
* CD - if checked, can be used with Core Data
122122
* Filter - if checked, `config.filter` is supported (see caveat below)
123-
* RO - if checked, you have option to use a Row Overlay
124123
* Bound - the mechanism through which values are bound, if at all
125124

126-
View | Type | Select | RAC | CD | Filter | RO | Bound
127-
--- | --- | --- | --- | --- | --- | --- | ---
128-
`TablerList` | **List** | | ✓ | ✓ | ✓ | ✓ |
129-
`TablerListB` | **List** | | ✓ | | ✓\* | ✓ | `Binding<Element>`
130-
`TablerListC` | **List** | | | ✓ | | ✓ | `NSManagedObject`
131-
`TablerList1` | **List** | Single | ✓ | ✓ | ✓ | ✓ |
132-
`TablerList1B` | **List** | Single | ✓ | | ✓\* | ✓ | `Binding<Element>`
133-
`TablerList1C` | **List** | Single | | ✓ | | ✓ | `NSManagedObject`
134-
`TablerListM` | **List** | Multi | ✓ | ✓ | ✓ | ✓ |
135-
`TablerListMB` | **List** | Multi | ✓ | | ✓\* | ✓ | `Binding<Element>`
136-
`TablerListMC` | **List** | Multi | | ✓ | | ✓ | `NSManagedObject`
137-
`TablerStack` | **Stack** | | ✓ | ✓ | ✓ | ✓ |
138-
`TablerStackB` | **Stack** | | ✓ | | ✓\* | ✓ | `Binding<Element>`
139-
`TablerStackC` | **Stack** | | | ✓ | | ✓ | `NSManagedObject`
140-
`TablerStack1` | **Stack** | Single | ✓ | ✓ | ✓ | ✓ |
141-
`TablerStack1B` | **Stack** | Single | ✓ | | ✓\* | ✓ | `Binding<Element>`
142-
`TablerStack1C` | **Stack** | Single | | ✓ | | ✓ | `NSManagedObject`
143-
`TablerGrid` | **Grid** | | ✓ | ✓ | ✓ | |
144-
`TablerGridB` | **Grid** | | ✓ | | | | `Binding<Element>`
145-
`TablerGridC` | **Grid** | | | ✓ | | | `NSManagedObject`
146-
`TablerGrid1` | **Grid** | Single | ✓ | ✓ | ✓ | |
147-
`TablerGrid1B` | **Grid** | Single | ✓ | | | | `Binding<Element>`
148-
`TablerGrid1C` | **Grid** | Single | | ✓ | | | `NSManagedObject`
125+
View | Type | Select | RAC | CD | Filter | Bound
126+
--- | --- | --- | --- | --- | --- | ---
127+
`TablerList` | **List** | | ✓ | ✓ | ✓ |
128+
`TablerListB` | **List** | | ✓ | | ✓\* | `Binding<Element>`
129+
`TablerListC` | **List** | | | ✓ | | `NSManagedObject`
130+
`TablerList1` | **List** | Single | ✓ | ✓ | ✓ |
131+
`TablerList1B` | **List** | Single | ✓ | | ✓\* | `Binding<Element>`
132+
`TablerList1C` | **List** | Single | | ✓ | | `NSManagedObject`
133+
`TablerListM` | **List** | Multi | ✓ | ✓ | ✓ |
134+
`TablerListMB` | **List** | Multi | ✓ | | ✓\* | `Binding<Element>`
135+
`TablerListMC` | **List** | Multi | | ✓ | | `NSManagedObject`
136+
`TablerStack` | **Stack** | | ✓ | ✓ | ✓ |
137+
`TablerStackB` | **Stack** | | ✓ | | ✓\* | `Binding<Element>`
138+
`TablerStackC` | **Stack** | | | ✓ | | `NSManagedObject`
139+
`TablerStack1` | **Stack** | Single | ✓ | ✓ | ✓ |
140+
`TablerStack1B` | **Stack** | Single | ✓ | | ✓\* | `Binding<Element>`
141+
`TablerStack1C` | **Stack** | Single | | ✓ | | `NSManagedObject`
142+
`TablerGrid` | **Grid** | | ✓ | ✓ | ✓ |
143+
`TablerGridB` | **Grid** | | ✓ | | | `Binding<Element>`
144+
`TablerGridC` | **Grid** | | | ✓ | | `NSManagedObject`
145+
`TablerGrid1` | **Grid** | Single | ✓ | ✓ | ✓ |
146+
`TablerGrid1B` | **Grid** | Single | ✓ | | | `Binding<Element>`
147+
`TablerGrid1C` | **Grid** | Single | | ✓ | | `NSManagedObject`
149148

150149
\* filtering with Binding-based data likely not scalable as implemented. If you can find a better way to implement, submit a pull request!
151150

@@ -290,6 +289,8 @@ Note that for Core Data, the user's changes will need to be saved to the Managed
290289

291290
You have the option to specify a row background, such as to impart information, or as a selection indicator.
292291

292+
Row Background, as the name suggests, sits BEHIND the row.
293+
293294
macOS | iOS
294295
:---:|:---:
295296
![](https://github.com/openalloc/SwiftTabler/blob/main/Images/macOSc.png) | ![](https://github.com/openalloc/SwiftTabler/blob/main/Images/iOSc.png)
@@ -330,12 +331,12 @@ private func rowBackground(fruit: Fruit) -> some View {
330331
}
331332
```
332333

333-
Row Background, as the name suggests, sits BELOW the row.
334-
335334
## Row Overlay
336335

337336
Similar to a row background, an overlay can be used to impart information, or to use as a selection indicator.
338337

338+
Row overlay, as the name suggests, sits ATOP the row.
339+
339340
An example of a selection indicator using row overlay:
340341

341342
```swift
@@ -357,8 +358,6 @@ private func rowOverlay(fruit: Fruit) -> some View {
357358
}
358359
```
359360

360-
Row overlay, as the name suggests, sits ABOVE the row.
361-
362361
## Hover Effect
363362

364363
Available for macOS. It's enabled by default using the system's accent color.

Sources/Grid/TablerGrid.swift

+72-3
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,12 @@
1919
import SwiftUI
2020

2121
/// Grid-based table
22-
public struct TablerGrid<Element, Header, Row, RowBack, Results>: View
22+
public struct TablerGrid<Element, Header, Row, RowBack, RowOver, Results>: View
2323
where Element: Identifiable,
2424
Header: View,
2525
Row: View,
2626
RowBack: View,
27+
RowOver: View,
2728
Results: RandomAccessCollection,
2829
Results.Element == Element
2930
{
@@ -33,25 +34,28 @@ public struct TablerGrid<Element, Header, Row, RowBack, Results>: View
3334
public typealias HeaderContent = (Binding<Context>) -> Header
3435
public typealias RowContent = (Element) -> Row
3536
public typealias RowBackground = (Element) -> RowBack
37+
public typealias RowOverlay = (Element) -> RowOver
3638

3739
// MARK: Parameters
3840

3941
private let config: Config
4042
private let headerContent: HeaderContent
4143
private let rowContent: RowContent
4244
private let rowBackground: RowBackground
45+
private let rowOverlay: RowOverlay
4346
private var results: Results
4447

4548
public init(_ config: Config = .init(),
4649
@ViewBuilder header: @escaping HeaderContent,
4750
@ViewBuilder row: @escaping RowContent,
4851
@ViewBuilder rowBackground: @escaping RowBackground,
49-
results: Results)
50-
{
52+
@ViewBuilder rowOverlay: @escaping RowOverlay,
53+
results: Results) {
5154
self.config = config
5255
headerContent = header
5356
rowContent = row
5457
self.rowBackground = rowBackground
58+
self.rowOverlay = rowOverlay
5559
self.results = results
5660
_context = State(initialValue: TablerContext(config))
5761
}
@@ -80,41 +84,106 @@ public extension TablerGrid {
8084
init(_ config: Config,
8185
@ViewBuilder row: @escaping RowContent,
8286
@ViewBuilder rowBackground: @escaping RowBackground,
87+
@ViewBuilder rowOverlay: @escaping RowOverlay,
8388
results: Results)
8489
where Header == EmptyView
8590
{
8691
self.init(config,
8792
header: { _ in EmptyView() },
8893
row: row,
8994
rowBackground: rowBackground,
95+
rowOverlay: rowOverlay,
96+
results: results)
97+
}
98+
99+
// omitting Overlay
100+
init(_ config: Config,
101+
@ViewBuilder header: @escaping HeaderContent,
102+
@ViewBuilder row: @escaping RowContent,
103+
@ViewBuilder rowBackground: @escaping RowBackground,
104+
results: Results)
105+
where RowOver == EmptyView
106+
{
107+
self.init(config,
108+
header: header,
109+
row: row,
110+
rowBackground: rowBackground,
111+
rowOverlay: { _ in EmptyView() },
90112
results: results)
91113
}
92114

93115
// omitting Background
94116
init(_ config: Config,
95117
@ViewBuilder header: @escaping HeaderContent,
96118
@ViewBuilder row: @escaping RowContent,
119+
@ViewBuilder rowOverlay: @escaping RowOverlay,
97120
results: Results)
98121
where RowBack == EmptyView
99122
{
100123
self.init(config,
101124
header: header,
102125
row: row,
103126
rowBackground: { _ in EmptyView() },
127+
rowOverlay: rowOverlay,
128+
results: results)
129+
}
130+
131+
// omitting Header AND Overlay
132+
init(_ config: Config,
133+
@ViewBuilder row: @escaping RowContent,
134+
@ViewBuilder rowBackground: @escaping RowBackground,
135+
results: Results)
136+
where Header == EmptyView, RowOver == EmptyView
137+
{
138+
self.init(config,
139+
header: { _ in EmptyView() },
140+
row: row,
141+
rowBackground: rowBackground,
142+
rowOverlay: { _ in EmptyView() },
104143
results: results)
105144
}
106145

107146
// omitting Header AND Background
108147
init(_ config: Config,
109148
@ViewBuilder row: @escaping RowContent,
149+
@ViewBuilder rowOverlay: @escaping RowOverlay,
110150
results: Results)
111151
where Header == EmptyView, RowBack == EmptyView
112152
{
113153
self.init(config,
114154
header: { _ in EmptyView() },
115155
row: row,
116156
rowBackground: { _ in EmptyView() },
157+
rowOverlay: rowOverlay,
158+
results: results)
159+
}
160+
161+
// omitting Background AND Overlay
162+
init(_ config: Config,
163+
@ViewBuilder header: @escaping HeaderContent,
164+
@ViewBuilder row: @escaping RowContent,
165+
results: Results)
166+
where RowBack == EmptyView, RowOver == EmptyView
167+
{
168+
self.init(config,
169+
header: header,
170+
row: row,
171+
rowBackground: { _ in EmptyView() },
172+
rowOverlay: { _ in EmptyView() },
117173
results: results)
118174
}
119175

176+
// omitting Header, Background, AND Overlay
177+
init(_ config: Config,
178+
@ViewBuilder row: @escaping RowContent,
179+
results: Results)
180+
where Header == EmptyView, RowBack == EmptyView, RowOver == EmptyView
181+
{
182+
self.init(config,
183+
header: { _ in EmptyView() },
184+
row: row,
185+
rowBackground: { _ in EmptyView() },
186+
rowOverlay: { _ in EmptyView() },
187+
results: results)
188+
}
120189
}

0 commit comments

Comments
 (0)