diff --git a/src/EditorView.swift b/src/EditorView.swift index f090450..27f8eae 100644 --- a/src/EditorView.swift +++ b/src/EditorView.swift @@ -321,81 +321,129 @@ class MarkdownTableView: NSView, NSTextFieldDelegate { var onTableChanged: ((ParsedTable) -> Void)? private var cellFields: [[NSTextField]] = [] - private let cellHeight: CGFloat = 26 - private let cellPadding: CGFloat = 4 - private let headerHeight: CGFloat = 28 + private var columnWidths: [CGFloat] = [] + private var rowHeights: [CGFloat] = [] + private var tableWidth: CGFloat = 0 + + private let minColWidth: CGFloat = 40 + private let minRowHeight: CGFloat = 24 + private let defaultHeaderHeight: CGFloat = 28 + private let defaultCellHeight: CGFloat = 26 + private let dividerHitZone: CGFloat = 6 + + private enum DragMode { case none, column(Int), row(Int) } + private var dragMode: DragMode = .none + private var dragStartPoint: NSPoint = .zero + private var dragStartSize: CGFloat = 0 init(table: ParsedTable, width: CGFloat) { self.table = table + self.tableWidth = width super.init(frame: .zero) wantsLayer = true layer?.backgroundColor = Theme.current.base.cgColor layer?.cornerRadius = 4 layer?.borderWidth = 1 layer?.borderColor = Theme.current.surface2.cgColor - buildGrid(width: width) + initSizes(width: width) + buildGrid() + setupTrackingArea() } required init?(coder: NSCoder) { fatalError() } - private func buildGrid(width: CGFloat) { + private func initSizes(width: CGFloat) { + let colCount = table.headers.count + guard colCount > 0 else { return } + let available = width - CGFloat(colCount + 1) + let colW = available / CGFloat(colCount) + columnWidths = Array(repeating: max(colW, minColWidth), count: colCount) + + rowHeights = [] + rowHeights.append(defaultHeaderHeight) + for _ in 0.. CGFloat { + var x: CGFloat = 1 + for i in 0.. CGFloat { + let th = totalHeight + var y = th + for i in 0...row { + y -= rowHeights[i] + } + return y + } + + private func buildGrid() { subviews.forEach { $0.removeFromSuperview() } cellFields = [] let colCount = table.headers.count guard colCount > 0 else { return } - let colWidth = (width - CGFloat(colCount + 1)) / CGFloat(colCount) - let totalRows = 1 + table.rows.count - let totalHeight = headerHeight + CGFloat(table.rows.count) * cellHeight + let th = totalHeight + let totalWidth = columnX(for: colCount) + 1 - frame.size = NSSize(width: width, height: totalHeight) + frame.size = NSSize(width: totalWidth, height: th) - // Header row - let headerBg = NSView(frame: NSRect(x: 0, y: totalHeight - headerHeight, width: width, height: headerHeight)) + let headerBg = NSView(frame: NSRect(x: 0, y: th - rowHeights[0], width: totalWidth, height: rowHeights[0])) headerBg.wantsLayer = true headerBg.layer?.backgroundColor = Theme.current.surface0.cgColor addSubview(headerBg) var headerFields: [NSTextField] = [] for (col, header) in table.headers.enumerated() { - let x = CGFloat(col) * colWidth + CGFloat(col + 1) - let field = makeCell(text: header, frame: NSRect(x: x, y: totalHeight - headerHeight + 2, width: colWidth, height: headerHeight - 4), isHeader: true, row: -1, col: col) + let x = columnX(for: col) + let h = rowHeights[0] + let field = makeCell(text: header, frame: NSRect(x: x, y: th - h + 2, width: columnWidths[col], height: h - 4), isHeader: true, row: -1, col: col) addSubview(field) headerFields.append(field) } cellFields.append(headerFields) - // Data rows for (rowIdx, row) in table.rows.enumerated() { var rowFields: [NSTextField] = [] - let y = totalHeight - headerHeight - CGFloat(rowIdx + 1) * cellHeight + let y = rowY(for: rowIdx + 1) + let h = rowHeights[rowIdx + 1] for (col, cell) in row.enumerated() where col < colCount { - let x = CGFloat(col) * colWidth + CGFloat(col + 1) - let field = makeCell(text: cell, frame: NSRect(x: x, y: y + 2, width: colWidth, height: cellHeight - 4), isHeader: false, row: rowIdx, col: col) + let x = columnX(for: col) + let field = makeCell(text: cell, frame: NSRect(x: x, y: y + 2, width: columnWidths[col], height: h - 4), isHeader: false, row: rowIdx, col: col) addSubview(field) rowFields.append(field) } while rowFields.count < colCount { let col = rowFields.count - let x = CGFloat(col) * colWidth + CGFloat(col + 1) - let field = makeCell(text: "", frame: NSRect(x: x, y: y + 2, width: colWidth, height: cellHeight - 4), isHeader: false, row: rowIdx, col: col) + let x = columnX(for: col) + let field = makeCell(text: "", frame: NSRect(x: x, y: y + 2, width: columnWidths[col], height: h - 4), isHeader: false, row: rowIdx, col: col) addSubview(field) rowFields.append(field) } cellFields.append(rowFields) } - // Grid lines + let totalRows = 1 + table.rows.count for i in 1.. Int? { + let colCount = table.headers.count + for i in 1.. Int? { + let totalRows = 1 + table.rows.count + for i in 0..