Skip to content

Commit

Permalink
Major restructuring for #12 and #17 (#18)
Browse files Browse the repository at this point in the history
  • Loading branch information
reedes authored Mar 3, 2022
1 parent 9bf9d06 commit 902d5a5
Show file tree
Hide file tree
Showing 40 changed files with 1,113 additions and 820 deletions.
101 changes: 54 additions & 47 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,20 +74,22 @@ struct ContentView: View {
GridItem(.flexible(minimum: 35, maximum: 50), alignment: .leading),
]

@ViewBuilder
private func header(_ ctx: TablerSortContext<Fruit>) -> some View {
Text("ID")
Text("Name")
Text("Weight")
Text("Color")
LazyVGrid(columns: gridItems) {
Text("ID")
Text("Name")
Text("Weight")
Text("Color")
}
}

@ViewBuilder
private func row(_ element: Fruit) -> some View {
Text(element.id)
Text(element.name).foregroundColor(element.color)
Text(String(format: "%.0f g", element.weight))
Image(systemName: "rectangle.fill").foregroundColor(element.color)
LazyVGrid(columns: gridItems) {
Text(element.id)
Text(element.name).foregroundColor(element.color)
Text(String(format: "%.0f g", element.weight))
Image(systemName: "rectangle.fill").foregroundColor(element.color)
}
}

var body: some View {
Expand All @@ -98,8 +100,8 @@ struct ContentView: View {
.padding()
}

private var config: TablerListConfig<Fruit> {
TablerListConfig<Fruit>(gridItems: gridItems)
private var config: TablerConfig<Fruit> {
TablerConfig<Fruit>()
}
}
```
Expand All @@ -108,26 +110,29 @@ struct ContentView: View {

You can choose from any of eleven (11) variants, which break down along the following lines:

* List-based, ScrollView/LazyVStack-based, and ScrollView/LazyVGrid-based
* Selection types offered: none, single-select, and multi-select, depending on base
* Unbound elements in row view, where you're presenting table rows read-only\*
* Bound elements in row view, where you're presenting tables rows that can be updated directly (see Bound section below)

Base | Selection of rows | Element wrapping | View name | Notes
--- | --- | --- | --- | ---
List | No Select | (none) | TablerList |
List | No Select | Binding\<Element> | TablerListB |
List | Single-select | (none) | TablerList1 |
List | Single-select | Binding\<Element> | TablerList1B |
List | Multi-select | (none) | TablerListM |
List | Multi-select | Binding\<Element> | TablerListMB |
Stack | No Select | (none) | TablerStack |
Stack | No Select | Binding\<Element> | TablerStackB |
Stack | Single-select | (none) | TablerStack1 |
Stack | Single-select | Binding\<Element> | TablerStack1B |
Grid | No Select | (none) | TablerGrid | Experimental. Needs bound version, select, etc.

\* 'unbound' variants can be used with Core Data (where values are bound by alternative means)
* Three foundations: List-based, ScrollView/LazyVStack-based, and ScrollView/LazyVGrid-based
* Selection types offered: none, single-select, and multi-select; availability depending on base
* RAC - usable with `RandomAccessCollection` (e.g., array of struct), with or without binding
* CD - usable with Core Data, with or without binding

Base | Row Selection | RAC | CD | View name | Element wrapping | Notes
--- | --- | --- | --- | --- | --- | ---
List | No Select | ✓ | ✓ | TablerList | (none) |
List | No Select | ✓ | | TablerListB | Binding\<Element> |
List | No Select | | ✓ | TablerListC | ObservedObject |
List | Single-select | ✓ | ✓ | TablerList1 | (none) |
List | Single-select | ✓ | | TablerList1B | Binding\<Element> |
List | Single-Select | | ✓ | TablerList1C | ObservedObject |
List | Multi-select | ✓ | ✓ | TablerListM | (none) |
List | Multi-select | ✓ | | TablerListMB | Binding\<Element> |
List | Multi-select | | ✓ | TablerListMC | ObservedObject |
Stack | No Select | ✓ | ✓ | TablerStack | (none) |
Stack | No Select | ✓ | | TablerStackB | Binding\<Element> |
Stack | No Select | | ✓ | TablerStackC | ObservedObject |
Stack | Single-select | ✓ | ✓ | TablerStack1 | (none) |
Stack | Single-select | ✓ | | TablerStack1B | Binding\<Element> |
Stack | Single-select | | ✓ | TablerStack1C | ObservedObject |
Grid | No Select | ✓ | ✓ | TablerGrid | (none) | Experimental. Needs bound version, select, etc.

## Column Sorting

Expand All @@ -139,15 +144,16 @@ From the demo app, an example of using the sort capability, where an indicator d
private typealias Context = TablerContext<Fruit>
private typealias Sort = TablerSort<Fruit>

@ViewBuilder
private func header(_ ctx: Binding<Context>) -> some View {
Sort.columnTitle("ID", ctx, \.id)
.onTapGesture { tablerSort(ctx, &fruits, \.id) { $0.id < $1.id } }
Sort.columnTitle("Name", ctx, \.name)
.onTapGesture { tablerSort(ctx, &fruits, \.name) { $0.name < $1.name } }
Sort.columnTitle("Weight", ctx, \.weight)
.onTapGesture { tablerSort(ctx, &fruits, \.weight) { $0.weight < $1.weight } }
Text("Color")
LazyVGrid(columns: gridItems) {
Sort.columnTitle("ID", ctx, \.id)
.onTapGesture { tablerSort(ctx, &fruits, \.id) { $0.id < $1.id } }
Sort.columnTitle("Name", ctx, \.name)
.onTapGesture { tablerSort(ctx, &fruits, \.name) { $0.name < $1.name } }
Sort.columnTitle("Weight", ctx, \.weight)
.onTapGesture { tablerSort(ctx, &fruits, \.weight) { $0.weight < $1.weight } }
Text("Color")
}
}
```

Expand All @@ -164,14 +170,15 @@ macOS | iOS
When used with 'bound' variants (e.g., `TablerListB`), the data can be modified directly, mutating your data source. From the demo:

```swift
@ViewBuilder
private func brow(_ element: Binding<Fruit>) -> some View {
Text(element.wrappedValue.id)
TextField("Name", text: element.name)
.textFieldStyle(.roundedBorder)
Text(String(format: "%.0f g", element.wrappedValue.weight))
ColorPicker("Color", selection: element.color)
.labelsHidden()
LazyVGrid(columns: gridItems) {
Text(element.wrappedValue.id)
TextField("Name", text: element.name)
.textFieldStyle(.roundedBorder)
Text(String(format: "%.0f g", element.wrappedValue.weight))
ColorPicker("Color", selection: element.color)
.labelsHidden()
}
}
```

Expand Down
32 changes: 17 additions & 15 deletions Sources/Grid/Internal/BaseGrid.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,36 +20,43 @@ import SwiftUI

// Grid-based list
struct BaseGrid<Element, Header, Rows>: View
where Element: Identifiable,
Header: View,
Rows: View
where Element: Identifiable,
Header: View,
Rows: View
{
typealias Config = TablerGridConfig<Element>
typealias Config = TablerConfig<Element>
typealias Context = TablerContext<Element>
typealias HeaderContent = (Binding<Context>) -> Header
typealias RowContent = () -> Rows


private var config: Config
@Binding private var context: Context
private let gridItems: [GridItem]
private let headerContent: HeaderContent
private let rowsContent: RowContent

init(context: Binding<Context>,
init(config: Config,
context: Binding<Context>,
gridItems: [GridItem],
headerContent: @escaping HeaderContent,
rowsContent: @escaping RowContent) {
rowsContent: @escaping RowContent)
{
self.config = config
_context = context
self.gridItems = gridItems
self.headerContent = headerContent
self.rowsContent = rowsContent
}

var body: some View {
BaseTable(context: $context,
headerContent: headerContent) { buildHeader in

VStack(spacing: config.rowSpacing) {
buildHeader()

ScrollView {
LazyVGrid(columns: config.gridItems,
LazyVGrid(columns: gridItems,
alignment: config.alignment,
spacing: config.rowSpacing) {
rowsContent()
Expand All @@ -59,9 +66,4 @@ where Element: Identifiable,
.padding(config.paddingInsets)
}
}

private var config: Config {
guard let c = context.config as? Config else { return Config(gridItems: []) }
return c
}
}
60 changes: 0 additions & 60 deletions Sources/Grid/Internal/BaseGridRow.swift

This file was deleted.

47 changes: 47 additions & 0 deletions Sources/Grid/Internal/GridItemMod.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
//
// GridItemMod.swift
//
// Copyright 2022 FlowAllocator LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

import SwiftUI

struct GridItemMod<Element>: ViewModifier
where Element: Identifiable
{
typealias Config = TablerConfig<Element>

let config: Config
let element: Element

init(_ config: Config,
_ element: Element)
{
self.config = config
self.element = element
}

func body(content: Content) -> some View {
content
.foregroundColor(colorPair?.0 ?? .primary)
.background(colorPair?.1 ?? Color.clear)
}

// MARK: Helpers

private var colorPair: (Color, Color)? {
config.onRowColor?(element)
}
}
Loading

0 comments on commit 902d5a5

Please sign in to comment.