Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions TablePro/Models/Query/RowProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,23 @@ final class InMemoryRowProvider: RowProvider {
return columnIndex < rowCache.count ? rowCache[columnIndex] : nil
}

@MainActor
func preWarmDisplayCache(upTo rowCount: Int) {
let count = min(rowCount, totalRowCount)
for row in 0..<count {
let cacheKey = resolveCacheKey(for: row)
guard displayCache[cacheKey] == nil else { continue }
let src = sourceRow(at: row)
let columnCount = columns.count
var rowCache = [String?](repeating: nil, count: columnCount)
for col in 0..<min(src.count, columnCount) {
let ct = col < columnTypes.count ? columnTypes[col] : nil
rowCache[col] = CellDisplayFormatter.format(src[col], columnType: ct)
}
displayCache[cacheKey] = rowCache
}
}

/// Invalidate entire display cache (after settings change, full reload).
func invalidateDisplayCache() {
displayCache.removeAll()
Expand Down
8 changes: 6 additions & 2 deletions TablePro/Views/Results/DataGridCellFactory.swift
Original file line number Diff line number Diff line change
Expand Up @@ -230,8 +230,12 @@ final class DataGridCellFactory {
isNewCell = true
}

// Re-apply single-line properties (editing may reset these on reused cells)
if !isNewCell {
if !isNewCell && (
cell.lineBreakMode != .byTruncatingTail ||
cell.maximumNumberOfLines != 1 ||
cell.cell?.truncatesLastVisibleLine != true ||
cell.cell?.usesSingleLineMode != true
) {
cell.lineBreakMode = .byTruncatingTail
cell.maximumNumberOfLines = 1
cell.cell?.truncatesLastVisibleLine = true
Expand Down
26 changes: 26 additions & 0 deletions TablePro/Views/Results/DataGridCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ final class TableViewCoordinator: NSObject, NSTableViewDelegate, NSTableViewData
var lastReapplyVersion: Int = -1
private(set) var cachedRowCount: Int = 0
private(set) var cachedColumnCount: Int = 0
private(set) var enumOrSetColumns: Set<Int> = []
private(set) var fkColumns: Set<Int> = []
var isSyncingSortDescriptors: Bool = false
/// Suppresses selection delegate callbacks during programmatic selection sync
var isSyncingSelection = false
Expand Down Expand Up @@ -263,6 +265,30 @@ final class TableViewCoordinator: NSObject, NSTableViewDelegate, NSTableViewData
cachedColumnCount = rowProvider.columns.count
}

func rebuildColumnMetadataCache() {
var enumSet = Set<Int>()
var fkSet = Set<Int>()
let columns = rowProvider.columns
let types = rowProvider.columnTypes
let enumValues = rowProvider.columnEnumValues
let fkKeys = rowProvider.columnForeignKeys

for i in 0..<columns.count {
let name = columns[i]
if i < types.count {
let ct = types[i]
if (ct.isEnumType || ct.isSetType) && enumValues[name]?.isEmpty == false {
enumSet.insert(i)
}
}
if fkKeys[name] != nil {
fkSet.insert(i)
}
}
enumOrSetColumns = enumSet
fkColumns = fkSet
}

// MARK: - Font Updates

/// Update fonts on existing visible cell views in-place.
Expand Down
11 changes: 11 additions & 0 deletions TablePro/Views/Results/DataGridView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ struct DataGridView: NSViewRepresentable {
scrollView.documentView = tableView
context.coordinator.tableView = tableView
context.coordinator.onMoveRow = onMoveRow
context.coordinator.rebuildColumnMetadataCache()
if let connectionId {
context.coordinator.observeTeardown(connectionId: connectionId)
}
Expand Down Expand Up @@ -280,6 +281,16 @@ struct DataGridView: NSViewRepresentable {
}

coordinator.updateCache()
coordinator.rebuildColumnMetadataCache()

if previousIdentity == nil || previousIdentity?.rowCount == 0 {
let rowH = tableView.rowHeight
if rowH > 0 {
let visibleRows = Int(tableView.visibleRect.height / rowH) + 5
coordinator.rowProvider.preWarmDisplayCache(upTo: visibleRows)
}
}

coordinator.changeManager = changeManager
coordinator.isEditable = isEditable
coordinator.onRefresh = onRefresh
Expand Down
16 changes: 2 additions & 14 deletions TablePro/Views/Results/Extensions/DataGridView+Columns.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,20 +43,8 @@ extension TableViewCoordinator {
let isDropdown = dropdownColumns?.contains(columnIndex) == true
let isTypePicker = typePickerColumns?.contains(columnIndex) == true

let isEnumOrSet: Bool = {
guard columnIndex < rowProvider.columnTypes.count,
columnIndex < rowProvider.columns.count else { return false }
let ct = rowProvider.columnTypes[columnIndex]
let columnName = rowProvider.columns[columnIndex]
guard ct.isEnumType || ct.isSetType else { return false }
return rowProvider.columnEnumValues[columnName]?.isEmpty == false
}()

let isFKColumn: Bool = {
guard columnIndex < rowProvider.columns.count else { return false }
let columnName = rowProvider.columns[columnIndex]
return rowProvider.columnForeignKeys[columnName] != nil
}()
let isEnumOrSet = enumOrSetColumns.contains(columnIndex)
let isFKColumn = fkColumns.contains(columnIndex)

return cellFactory.makeDataCell(
tableView: tableView,
Expand Down
Loading