Skip to content

Commit bb0f9b1

Browse files
authored
Grid from cells (#173)
* Added ability to create Grid from cells * Allow free scrolling in GridView * Added ability to collapse/expand grid rows/columns
1 parent 0fae1a6 commit bb0f9b1

22 files changed

+624
-213
lines changed

ExampleApp/ExampleApp/AdvancedFeatures/CommandsExampleViewController.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ extension CommandsExampleViewController: GridViewDelegate {
326326
let columnActions = [
327327
UIAction(title: "Add column right", image: UIImage(systemName: "arrow.right"),
328328
handler: { (_) in
329-
let result = gridView.insertColumn(at: cell.columnSpan.max()! + 1, configuration: GridColumnConfiguration(dimension: .fixed(100)))
329+
let result = gridView.insertColumn(at: cell.columnSpan.max()! + 1, configuration: GridColumnConfiguration(width: .fixed(100)))
330330
if case let Result.failure(error) = result {
331331
print("Failed to insert: \(error)")
332332
}

ExampleApp/ExampleApp/Commands/CreateGridViewCommand.swift

+6-6
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,12 @@ public class CreateGridViewCommand: EditorCommand {
3535
let config = GridConfiguration(
3636
columnsConfiguration: [
3737
// GridColumnConfiguration(dimension: .fixed(150)),
38-
GridColumnConfiguration(dimension: .fractional(0.25)),
39-
GridColumnConfiguration(dimension: .fractional(0.25)),
40-
GridColumnConfiguration(dimension: .fractional(0.25)),
41-
GridColumnConfiguration(dimension: .fractional(0.25)),
42-
GridColumnConfiguration(dimension: .fractional(0.25)),
43-
GridColumnConfiguration(dimension: .fractional(0.25)),
38+
GridColumnConfiguration(width: .fractional(0.25)),
39+
GridColumnConfiguration(width: .fractional(0.25)),
40+
GridColumnConfiguration(width: .fractional(0.25)),
41+
GridColumnConfiguration(width: .fractional(0.25)),
42+
GridColumnConfiguration(width: .fractional(0.25)),
43+
GridColumnConfiguration(width: .fractional(0.25)),
4444
],
4545
rowsConfiguration: [
4646
GridRowConfiguration(initialHeight: 40),

Proton/Sources/Swift/Grid/Core/Grid.swift

+47-5
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,18 @@ import UIKit
2424

2525
class GridRowDimension {
2626
var currentHeight: CGFloat
27+
var isCollapsed: Bool
2728
let rowConfiguration: GridRowConfiguration
2829

29-
init(rowConfiguration: GridRowConfiguration) {
30+
var calculatedHeight: CGFloat {
31+
guard !isCollapsed else { return 2 }
32+
return currentHeight
33+
}
34+
35+
init(rowConfiguration: GridRowConfiguration, isCollapsed: Bool = false) {
3036
self.rowConfiguration = rowConfiguration
3137
currentHeight = rowConfiguration.initialHeight
38+
self.isCollapsed = isCollapsed
3239
}
3340
}
3441

@@ -46,7 +53,7 @@ class Grid {
4653
weak var delegate: GridDelegate?
4754

4855
var currentRowHeights: [CGFloat] {
49-
rowHeights.map { $0.currentHeight }
56+
rowHeights.map { $0.calculatedHeight }
5057
}
5158

5259
var cells: [GridCell] {
@@ -65,7 +72,7 @@ class Grid {
6572
self.config = config
6673

6774
for column in config.columnsConfiguration {
68-
self.columnWidths.append(column.dimension)
75+
self.columnWidths.append(GridColumnDimension(width: column.width))
6976
}
7077

7178
for row in config.rowsConfiguration {
@@ -152,7 +159,7 @@ class Grid {
152159
let proposedWidth = columnWidths[index].value(basedOn: totalWidth) + delta
153160
guard index < columnWidths.count,
154161
delegate?.grid(self, shouldChangeColumnWidth: proposedWidth, for: index) ?? true else { return }
155-
columnWidths[index] = .fixed(columnWidths[index].value(basedOn: totalWidth) + delta)
162+
columnWidths[index].width = .fixed(columnWidths[index].value(basedOn: totalWidth) + delta)
156163
}
157164

158165
func changeRowHeight(index: Int, delta: CGFloat) {
@@ -271,7 +278,7 @@ class Grid {
271278
if sanitizedIndex < numberOfColumns {
272279
cellStore.moveCellColumnIndex(from: sanitizedIndex, by: 1)
273280
}
274-
columnWidths.insert(config.dimension, at: sanitizedIndex)
281+
columnWidths.insert(GridColumnDimension(width: config.width), at: sanitizedIndex)
275282

276283
var cells = [GridCell]()
277284
for r in 0..<numberOfRows {
@@ -347,6 +354,41 @@ class Grid {
347354
}
348355

349356
}
357+
358+
func collapseRow(at index: Int) {
359+
rowHeights[index].isCollapsed = true
360+
}
361+
362+
func expandRow(at index: Int) {
363+
rowHeights[index].isCollapsed = false
364+
}
365+
366+
func collapseColumn(at index: Int) {
367+
columnWidths[index].isCollapsed = true
368+
// Hide editor failing which resizing column ends up elongating column based on content in cell
369+
cells.forEach {
370+
if $0.columnSpan.contains(index) {
371+
$0.hideEditor()
372+
}
373+
}
374+
}
375+
376+
func expandColumn(at index: Int) {
377+
columnWidths[index].isCollapsed = false
378+
cells.forEach {
379+
if $0.columnSpan.contains(index) {
380+
$0.showEditor()
381+
}
382+
}
383+
}
384+
385+
func getCollapsedRowIndices() -> [Int] {
386+
return rowHeights.indices.filter { rowHeights[$0].isCollapsed }
387+
}
388+
389+
func getCollapsedColumnIndices() -> [Int] {
390+
return columnWidths.indices.filter { columnWidths[$0].isCollapsed }
391+
}
350392
}
351393

352394
public enum GridViewError: Error {

Proton/Sources/Swift/Grid/Core/GridConfiguration.swift

+19-4
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,22 @@
2121
import Foundation
2222
import UIKit
2323

24-
public enum GridColumnDimension {
24+
class GridColumnDimension {
25+
var isCollapsed: Bool
26+
var width: GridColumnWidth
27+
28+
init(width: GridColumnWidth, isCollapsed: Bool = false) {
29+
self.isCollapsed = isCollapsed
30+
self.width = width
31+
}
32+
33+
func value(basedOn total: CGFloat) -> CGFloat {
34+
guard !isCollapsed else { return 2 }
35+
return width.value(basedOn: total)
36+
}
37+
}
38+
39+
public enum GridColumnWidth {
2540
case fixed(CGFloat)
2641
case fractional(CGFloat)
2742

@@ -36,11 +51,11 @@ public enum GridColumnDimension {
3651
}
3752

3853
public struct GridColumnConfiguration {
39-
public let dimension: GridColumnDimension
54+
public let width: GridColumnWidth
4055
public let style: GridCellStyle
4156

42-
public init(dimension: GridColumnDimension, style: GridCellStyle = .init()) {
43-
self.dimension = dimension
57+
public init(width: GridColumnWidth, style: GridCellStyle = .init()) {
58+
self.width = width
4459
self.style = style
4560
}
4661
}

Proton/Sources/Swift/Grid/View/GridCell.swift

+9-1
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ public class GridCell {
157157

158158
let initialHeight: CGFloat
159159

160-
init(rowSpan: [Int], columnSpan: [Int], initialHeight: CGFloat, style: GridCellStyle = .init(), gridStyle: GridStyle = .default) {
160+
init(rowSpan: [Int], columnSpan: [Int], initialHeight: CGFloat = 40, style: GridCellStyle = .init(), gridStyle: GridStyle = .default) {
161161
self.rowSpan = rowSpan
162162
self.columnSpan = columnSpan
163163
self.gridStyle = gridStyle
@@ -231,6 +231,14 @@ public class GridCell {
231231
heightAnchorConstraint
232232
])
233233
}
234+
235+
func hideEditor() {
236+
editor.removeFromSuperview()
237+
}
238+
239+
func showEditor() {
240+
contentView.addSubview(editor)
241+
}
234242
}
235243

236244
extension GridCell: BoundsObserving {

Proton/Sources/Swift/Grid/View/GridContentView.swift

+37-3
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ class GridContentView: UIScrollView {
5959
weak var gridContentViewDelegate: GridContentViewDelegate?
6060
weak var boundsObserver: BoundsObserving?
6161

62+
var isFreeScrollingEnabled = false
63+
6264
var cells: [GridCell] {
6365
grid.cells
6466
}
@@ -86,15 +88,19 @@ class GridContentView: UIScrollView {
8688
}
8789
}
8890

89-
init(config: GridConfiguration) {
91+
init(config: GridConfiguration, cells: [GridCell]) {
9092
self.config = config
91-
let cells = Self.generateCells(config: config)
9293
grid = Grid(config: config, cells: cells)
9394
super.init(frame: .zero)
9495
grid.delegate = self
9596
setup()
9697
}
9798

99+
convenience init(config: GridConfiguration) {
100+
let cells = Self.generateCells(config: config)
101+
self.init(config: config, cells: cells)
102+
}
103+
98104
required init?(coder: NSCoder) {
99105
fatalError("init(coder:) has not been implemented")
100106
}
@@ -210,6 +216,34 @@ class GridContentView: UIScrollView {
210216
gridContentViewDelegate?.gridContentView(self, didAddNewColumnAt: index)
211217
}
212218

219+
func collapseRow(at index: Int) {
220+
grid.collapseRow(at: index)
221+
invalidateCellLayout()
222+
}
223+
224+
func expandRow(at index: Int) {
225+
grid.expandRow(at: index)
226+
invalidateCellLayout()
227+
}
228+
229+
func collapseColumn(at index: Int) {
230+
grid.collapseColumn(at: index)
231+
invalidateCellLayout()
232+
}
233+
234+
func expandColumn(at index: Int) {
235+
grid.expandColumn(at: index)
236+
invalidateCellLayout()
237+
}
238+
239+
func getCollapsedRowIndices() -> [Int] {
240+
return grid.getCollapsedRowIndices()
241+
}
242+
243+
func getCollapsedColumnIndices() -> [Int] {
244+
return grid.getCollapsedColumnIndices()
245+
}
246+
213247
func cellAt(rowIndex: Int, columnIndex: Int) -> GridCell? {
214248
grid.cellAt(rowIndex: rowIndex, columnIndex: columnIndex)
215249
}
@@ -391,7 +425,7 @@ extension GridContentView: DynamicBoundsProviding {
391425

392426
extension GridContentView: UIGestureRecognizerDelegate {
393427
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
394-
return false
428+
return isFreeScrollingEnabled
395429
}
396430
}
397431

Proton/Sources/Swift/Grid/View/GridView.swift

+43-4
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,13 @@ public class GridView: UIView {
160160
}
161161
}
162162

163+
/// Allows scrolling grid in any direction. Defaults to `false`
164+
/// Default behaviour restricts scrolling to horizontal or vertical direction at a time.
165+
public var isFreeScrollingEnabled: Bool {
166+
get { gridView.isFreeScrollingEnabled }
167+
set { gridView.isFreeScrollingEnabled = newValue }
168+
}
169+
163170
/// Maximum index up till which columns are frozen. Columns are frozen from 0 to this index value.
164171
public var frozenColumnMaxIndex: Int? {
165172
return gridView.frozenColumnMaxIndex
@@ -200,11 +207,20 @@ public class GridView: UIView {
200207
gridView.numberOfRows
201208
}
202209

203-
204210
/// Initializes `GridView` using the provided configuration.
205211
/// - Parameter config: Configuration for `GridView`
206-
public init(config: GridConfiguration) {
207-
self.gridView = GridContentView(config: config)
212+
public convenience init(config: GridConfiguration) {
213+
let gridView = GridContentView(config: config)
214+
self.init(config: config, gridView: gridView)
215+
}
216+
217+
public convenience init(config: GridConfiguration, cells: [GridCell]) {
218+
let gridView = GridContentView(config: config, cells: cells)
219+
self.init(config: config, gridView: gridView)
220+
}
221+
222+
private init(config: GridConfiguration, gridView: GridContentView) {
223+
self.gridView = gridView
208224
let boundsShadowColors = [
209225
config.boundsLimitShadowColors.primary.cgColor,
210226
config.boundsLimitShadowColors.secondary.cgColor
@@ -388,7 +404,6 @@ public class GridView: UIView {
388404
}
389405
}
390406

391-
392407
/// Inserts a new row at given index.
393408
/// - Parameters:
394409
/// - index: Index at which new row should be inserted.
@@ -441,6 +456,30 @@ public class GridView: UIView {
441456
gridView.frozenRowMaxIndex = nil
442457
}
443458

459+
public func collapseRow(at index: Int) {
460+
gridView.collapseRow(at: index)
461+
}
462+
463+
func expandRow(at index: Int) {
464+
gridView.expandRow(at: index)
465+
}
466+
467+
func collapseColumn(at index: Int) {
468+
gridView.collapseColumn(at: index)
469+
}
470+
471+
func expandColumn(at index: Int) {
472+
gridView.expandColumn(at: index)
473+
}
474+
475+
func getCollapsedRowIndices() -> [Int] {
476+
return gridView.getCollapsedRowIndices()
477+
}
478+
479+
func getCollapsedColumnIndices() -> [Int] {
480+
return gridView.getCollapsedColumnIndices()
481+
}
482+
444483
/// Gets the cell at given row and column index. Indexes may be contained in a merged cell.
445484
/// - Parameters:
446485
/// - rowIndex: Row index for the cell

Proton/Tests/Attachments/GridViewAttachment.swift

+6
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ public class GridViewAttachment: Attachment {
3333
super.init(view, size: .fullWidth)
3434
view.boundsObserver = self
3535
}
36+
37+
public init(config: GridConfiguration, cells: [GridCell]) {
38+
view = GridView(config: config, cells: cells)
39+
super.init(view, size: .fullWidth)
40+
view.boundsObserver = self
41+
}
3642
}
3743

3844
extension GridView: AttachmentViewIdentifying {

0 commit comments

Comments
 (0)