Skip to content

Commit bfbb7c4

Browse files
authored
Added option to provide custom editor initializer at gridview level (#256)
* Added option to provide custom editor initializer at gridview level * Fixed Sample app
1 parent d306fb1 commit bfbb7c4

File tree

7 files changed

+122
-60
lines changed

7 files changed

+122
-60
lines changed

ExampleApp/ExampleApp/Commands/CreateGridViewCommand.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ public class CreateGridViewCommand: EditorCommand {
6868
editor.attributedText = NSAttributedString(string: "Table \(id) {\(row), \(col)} Text in cell")
6969
return editor
7070
}
71-
let cell = GridCell(editorInitializer: editorInit, rowSpan: [row], columnSpan: [col], initialHeight: 20)
71+
let cell = GridCell(rowSpan: [row], columnSpan: [col], initialHeight: 20, editorInitializer: editorInit)
7272
cells.append(cell)
7373
}
7474
}

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

+11-4
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,13 @@ class Grid {
4949

5050
private let config: GridConfiguration
5151
private let cellStore: GridCellStore
52+
private let editorInitializer: GridCell.EditorInitializer?
5253

5354
var rowHeights = [GridRowDimension]()
5455
var columnWidths = [GridColumnDimension]()
5556
weak var delegate: GridDelegate?
5657

58+
5759
var currentRowHeights: [CGFloat] {
5860
rowHeights.map { $0.calculatedHeight }
5961
}
@@ -70,8 +72,9 @@ class Grid {
7072
rowHeights.count
7173
}
7274

73-
init(config: GridConfiguration, cells: [GridCell]) {
75+
init(config: GridConfiguration, cells: [GridCell], editorInitializer: GridCell.EditorInitializer? = nil) {
7476
self.config = config
77+
self.editorInitializer = editorInitializer
7578

7679
for column in config.columnsConfiguration {
7780
self.columnWidths.append(GridColumnDimension(width: column.width, collapsedWidth: config.collapsedColumnWidth))
@@ -216,7 +219,8 @@ class Grid {
216219
rowSpan: [row],
217220
columnSpan: [col],
218221
initialHeight: cell.initialHeight,
219-
ignoresOptimizedInit: true
222+
ignoresOptimizedInit: true,
223+
editorInitializer: editorInitializer
220224
)
221225
c.delegate = cell.delegate
222226
newCells.append(c)
@@ -256,7 +260,8 @@ class Grid {
256260
rowSpan: [sanitizedIndex],
257261
columnSpan: [c],
258262
initialHeight: config.initialHeight,
259-
style: config.style)
263+
style: config.style,
264+
editorInitializer: editorInitializer)
260265

261266
if cellAt(rowIndex: sanitizedIndex, columnIndex: c) != nil {
262267
continue
@@ -293,7 +298,9 @@ class Grid {
293298
rowSpan: [r],
294299
columnSpan: [sanitizedIndex],
295300
initialHeight: rowHeights[r].rowConfiguration.initialHeight,
296-
style: config.style)
301+
style: config.style,
302+
editorInitializer: editorInitializer
303+
)
297304

298305
if cellAt(rowIndex: r, columnIndex: sanitizedIndex) != nil {
299306
continue

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

+5-23
Original file line numberDiff line numberDiff line change
@@ -182,29 +182,28 @@ open class GridCell {
182182

183183
let initialHeight: CGFloat
184184

185-
186185
/// Initializes the cell
187186
/// - Parameters:
188-
/// - editorInitializer: Closure for setting up the `EditorView` within the cell. I
189187
/// - rowSpan: Array of row indexes the cells spans. For e.g. a cell with first two rows as merged, will have a value of [0, 1] denoting 0th and 1st index.
190188
/// - columnSpan: Array of column indexes the cells spans. For e.g. a cell with first two columns as merged, will have a value of [0, 1] denoting 0th and 1st index.
191189
/// - initialHeight: Initial height of the cell. This will be updated based on size of editor content on load,
192190
/// - style: Visual style of the cell
193191
/// - gridStyle: Visual style for grid containing cell border color and width
194192
/// - ignoresOptimizedInit: Ignores optimization to initialize editor within the cell. With optimization, the editor is not initialized until the cell is ready to be rendered on the UI thereby not incurring any overheads when creating
195193
/// attributedText containing a `GridView` in an attachment. Defaults to `false`.
194+
/// - editorInitializer: Closure for setting up the `EditorView` within the cell.
196195
/// - Important:
197196
/// Creating a `GridView` with 100s of cells can result in slow performance when creating an attributed string containing the GridView attachment. Using the closure defers the creation until the view is ready to be rendered in the UI.
198197
/// It is recommended to setup all the parts of editor in closure where possible, or wait until after the GridView is rendered. In case, editor must be initialized before the rendering is complete and it is not possible to configure an aspect within the closure itself,
199198
/// `setupEditor()` may be invoked. Use of `setupEditor()` is discouraged.
200-
public init(editorInitializer: @escaping EditorInitializer,
201-
rowSpan: [Int],
199+
public init(rowSpan: [Int],
202200
columnSpan: [Int],
203201
initialHeight: CGFloat = 40,
204202
style: GridCellStyle = .init(),
205203
gridStyle: GridStyle = .default,
206-
ignoresOptimizedInit: Bool = false) {
207-
self.editorInitializer = editorInitializer
204+
ignoresOptimizedInit: Bool = false,
205+
editorInitializer: EditorInitializer? = nil) {
206+
self.editorInitializer = editorInitializer ?? { EditorView(allowAutogrowing: false) }
208207
self.rowSpan = rowSpan
209208
self.columnSpan = columnSpan
210209
self.gridStyle = gridStyle
@@ -228,23 +227,6 @@ open class GridCell {
228227
setup()
229228
}
230229

231-
public convenience init(rowSpan: [Int],
232-
columnSpan: [Int],
233-
initialHeight: CGFloat = 40,
234-
style: GridCellStyle = .init(),
235-
gridStyle: GridStyle = .default,
236-
ignoresOptimizedInit: Bool = true) {
237-
self.init(
238-
editorInitializer: { EditorView(allowAutogrowing: false) },
239-
rowSpan: rowSpan,
240-
columnSpan: columnSpan,
241-
initialHeight: initialHeight,
242-
style: style,
243-
gridStyle: gridStyle,
244-
ignoresOptimizedInit: ignoresOptimizedInit
245-
)
246-
}
247-
248230
/// Sets the focus in the `Editor` within the cell.
249231
public func setFocus() {
250232
editor.setFocus()

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

+11-7
Original file line numberDiff line numberDiff line change
@@ -93,16 +93,16 @@ class GridContentView: UIScrollView {
9393
grid.columnWidths
9494
}
9595

96-
init(config: GridConfiguration, cells: [GridCell]) {
96+
init(config: GridConfiguration, cells: [GridCell], editorInitializer: GridCell.EditorInitializer?) {
9797
self.config = config
98-
grid = Grid(config: config, cells: cells)
98+
grid = Grid(config: config, cells: cells, editorInitializer: editorInitializer)
9999
super.init(frame: .zero)
100100
grid.delegate = self
101101
}
102102

103-
convenience init(config: GridConfiguration) {
104-
let cells = Self.generateCells(config: config)
105-
self.init(config: config, cells: cells)
103+
convenience init(config: GridConfiguration, editorInitializer: GridCell.EditorInitializer?) {
104+
let cells = Self.generateCells(config: config, editorInitializer: editorInitializer)
105+
self.init(config: config, cells: cells, editorInitializer: editorInitializer)
106106
}
107107

108108
required init?(coder: NSCoder) {
@@ -374,7 +374,10 @@ class GridContentView: UIScrollView {
374374
}
375375
}
376376

377-
private static func generateCells(config: GridConfiguration) -> [GridCell] {
377+
private static func generateCells(
378+
config: GridConfiguration,
379+
editorInitializer: GridCell.EditorInitializer?
380+
) -> [GridCell] {
378381
var cells = [GridCell]()
379382
for row in 0..<config.numberOfRows {
380383
let rowStyle = config.rowsConfiguration[row].style
@@ -389,7 +392,8 @@ class GridContentView: UIScrollView {
389392
initialHeight: initialHeight,
390393
style: mergedStyle,
391394
gridStyle: config.style,
392-
ignoresOptimizedInit: config.ignoresOptimizedInit
395+
ignoresOptimizedInit: config.ignoresOptimizedInit,
396+
editorInitializer: editorInitializer
393397
)
394398
cells.append(cell)
395399
}

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

+16-5
Original file line numberDiff line numberDiff line change
@@ -209,14 +209,25 @@ public class GridView: UIView {
209209
}
210210

211211
/// Initializes `GridView` using the provided configuration.
212-
/// - Parameter config: Configuration for `GridView`
213-
public convenience init(config: GridConfiguration) {
214-
let gridView = GridContentView(config: config)
212+
/// - Parameter
213+
/// - config: Configuration for `GridView`
214+
/// - cellEditorInitializer: Custom initializer for `EditorView` within `GridCell`. This will also be used when creating new cells as a
215+
/// return of adding new row or column, or cells being split.
216+
public convenience init(config: GridConfiguration, cellEditorInitializer: GridCell.EditorInitializer? = nil) {
217+
let gridView = GridContentView(config: config, editorInitializer: cellEditorInitializer)
215218
self.init(config: config, gridView: gridView)
216219
}
217220

218-
public convenience init(config: GridConfiguration, cells: [GridCell]) {
219-
let gridView = GridContentView(config: config, cells: cells)
221+
/// Initializes `GridView` using the provided configuration.
222+
/// - Parameters:
223+
/// - config: Configuration for `GridView`
224+
/// - cells: Cells contained within `GridView`
225+
/// - cellEditorInitializer: Custom initializer for `EditorView` within `GridCell`. This will also be used when creating new cells as a
226+
/// return of adding new row or column, or cells being split.
227+
/// - Important:
228+
/// Care must be taken that the number of cells are correct per the configuration provided, failing which the `GridView` rendering may be broken.
229+
public convenience init(config: GridConfiguration, cells: [GridCell], cellEditorInitializer: GridCell.EditorInitializer? = nil) {
230+
let gridView = GridContentView(config: config, cells: cells, editorInitializer: cellEditorInitializer)
220231
self.init(config: config, gridView: gridView)
221232
}
222233

Proton/Tests/Grid/GridTests.swift

+62-20
Original file line numberDiff line numberDiff line change
@@ -51,26 +51,6 @@ class GridTests: XCTestCase {
5151
}
5252
}
5353

54-
func testSome() throws {
55-
let config = GridConfiguration(
56-
columnsConfiguration: [
57-
GridColumnConfiguration(width: .fixed(100)),
58-
GridColumnConfiguration(width: .fixed(100)),
59-
],
60-
rowsConfiguration: [
61-
GridRowConfiguration(initialHeight: 50),
62-
GridRowConfiguration(initialHeight: 50),
63-
GridRowConfiguration(initialHeight: 50),
64-
])
65-
66-
let grid = Grid(config: config, cells: generateCells(config: config))
67-
let cell00 = try XCTUnwrap(grid.cellAt(rowIndex: 0, columnIndex: 0))
68-
let cell01 = try XCTUnwrap(grid.cellAt(rowIndex: 1, columnIndex: 0))
69-
70-
print(grid.frameForCell(cell00, basedOn: CGSize(width: 300, height: 300)))
71-
print(grid.frameForCell(cell01, basedOn: CGSize(width: 300, height: 300)))
72-
}
73-
7454
func testGetsFrameForCell() {
7555
let config = GridConfiguration(
7656
columnsConfiguration: [
@@ -237,6 +217,36 @@ class GridTests: XCTestCase {
237217
waitForExpectations(timeout: 1.0)
238218
}
239219

220+
func testInsertRowUsesCustomEditorInit() {
221+
let expectation = functionExpectation()
222+
223+
let config = GridConfiguration(
224+
columnsConfiguration: [
225+
GridColumnConfiguration(width: .fractional(0.25)),
226+
GridColumnConfiguration(width: .fixed(100.0)),
227+
GridColumnConfiguration(width: .fractional(0.50)),
228+
],
229+
rowsConfiguration: [
230+
GridRowConfiguration(initialHeight: 50),
231+
GridRowConfiguration(initialHeight: 50),
232+
GridRowConfiguration(initialHeight: 50),
233+
])
234+
235+
expectation.expectedFulfillmentCount = config.numberOfColumns
236+
237+
let editorInit = {
238+
expectation.fulfill()
239+
return EditorView(frame: .zero)
240+
}
241+
242+
let grid = Grid(config: config, cells: generateCells(config: config), editorInitializer: editorInit)
243+
grid.insertRow(at: 1, frozenRowMaxIndex: nil, config: GridRowConfiguration(initialHeight: 20), cellDelegate: nil)
244+
let newCells = grid.cells.filter { $0.rowSpan.contains(1) }
245+
newCells.forEach { _ = $0.editor }
246+
247+
waitForExpectations(timeout: 1.0)
248+
}
249+
240250
func testInsertColumn() {
241251
let expectation = functionExpectation()
242252
expectation.expectedFulfillmentCount = 3
@@ -276,6 +286,38 @@ class GridTests: XCTestCase {
276286
waitForExpectations(timeout: 1.0)
277287
}
278288

289+
func testInsertColumnUsesCustomEditorInit() {
290+
let expectation = functionExpectation()
291+
expectation.expectedFulfillmentCount = 3
292+
293+
let config = GridConfiguration(
294+
columnsConfiguration: [
295+
GridColumnConfiguration(width: .fractional(0.25)),
296+
GridColumnConfiguration(width: .fixed(100.0)),
297+
GridColumnConfiguration(width: .fractional(0.50)),
298+
],
299+
rowsConfiguration: [
300+
GridRowConfiguration(initialHeight: 30),
301+
GridRowConfiguration(initialHeight: 40),
302+
GridRowConfiguration(initialHeight: 50),
303+
])
304+
305+
expectation.expectedFulfillmentCount = config.numberOfColumns
306+
307+
let editorInit = {
308+
expectation.fulfill()
309+
return EditorView(frame: .zero)
310+
}
311+
312+
let grid = Grid(config: config, cells: generateCells(config: config), editorInitializer: editorInit)
313+
grid.insertColumn(at: 1, frozenColumnMaxIndex: nil, config: GridColumnConfiguration(width: .fractional(0.30)), cellDelegate: nil)
314+
XCTAssertEqual(grid.numberOfColumns, 4)
315+
let newCells = grid.cells.filter { $0.columnSpan.contains(1) }
316+
newCells.forEach { _ = $0.editor }
317+
318+
waitForExpectations(timeout: 1.0)
319+
}
320+
279321
func testDeletesRow() {
280322
let expectation = functionExpectation()
281323
expectation.expectedFulfillmentCount = 3

Proton/Tests/Grid/GridViewTests.swift

+16
Original file line numberDiff line numberDiff line change
@@ -181,4 +181,20 @@ class GridViewTests: XCTestCase {
181181
XCTAssertEqual(cell, cellToQuery)
182182
}
183183

184+
func testUsesCustomEditorInit() {
185+
let expectation = functionExpectation()
186+
expectation.expectedFulfillmentCount = config.numberOfColumns * config.numberOfRows
187+
188+
let editorInit = {
189+
expectation.fulfill()
190+
return EditorView(frame: .zero)
191+
}
192+
193+
let gridView = GridView(config: config, cellEditorInitializer: editorInit)
194+
let delegate = MockGridViewDelegate()
195+
gridView.delegate = delegate
196+
gridView.gridView.willMove(toWindow: UIWindow())
197+
198+
waitForExpectations(timeout: 1.0)
199+
}
184200
}

0 commit comments

Comments
 (0)