TDKCandidates // Implement page-expansion feature.

This commit is contained in:
ShikiSuen 2023-08-09 23:53:09 +08:00
parent 2abb86f4b8
commit b2ee0e3972
5 changed files with 62 additions and 20 deletions

View File

@ -14,16 +14,17 @@ public class CandidatePool {
// cell
public static let shitCell = CandidateCellData(key: " ", displayedText: "💩", isSelected: false)
public static let blankCell = CandidateCellData(key: " ", displayedText: " ", isSelected: false)
public private(set) var maxLinesPerPage: Int
public private(set) var _maxLinesPerPage: Int
public private(set) var layout: LayoutOrientation
public private(set) var selectionKeys: String
public private(set) var candidateDataAll: [CandidateCellData]
public var candidateLines: [[CandidateCellData]] = []
public var tooltip: String = ""
public var reverseLookupResult: [String] = []
public private(set) var candidateLines: [[CandidateCellData]] = []
public private(set) var highlightedIndex: Int = 0
public private(set) var currentLineNumber = 0
public private(set) var isExpanded: Bool = false
public var metrics: UIMetrics = .allZeroed
public var tooltip: String = ""
public var reverseLookupResult: [String] = []
private var recordedLineRangeForCurrentPage: Range<Int>?
private var previouslyRecordedLineRangeForPreviousPage: Range<Int>?
@ -47,9 +48,15 @@ public class CandidatePool {
public let cellRadius: CGFloat = 4
public var windowRadius: CGFloat { originDelta + cellRadius }
/// /
/// /
public var maxLinesPerPage: Int { isExpanded ? _maxLinesPerPage : 1 }
/// /
public var isMatrix: Bool { maxLinesPerPage > 1 }
/// /
public var isExpandable: Bool { _maxLinesPerPage > 1 }
///
///
public var maxRowWidth: Double { ceil(Double(maxLineCapacity) * Self.blankCell.cellLength()) }
@ -99,15 +106,16 @@ public class CandidatePool {
/// - direction:
/// - locale: zh-Hanszh-Hant
public init(
candidates: [(keyArray: [String], value: String)], lines: Int = 3, selectionKeys: String = "123456789",
candidates: [(keyArray: [String], value: String)], lines: Int = 3, isExpanded expanded: Bool = true, selectionKeys: String = "123456789",
layout: LayoutOrientation = .vertical, locale: String = ""
) {
maxLinesPerPage = 1
_maxLinesPerPage = max(1, lines)
isExpanded = expanded
self.layout = .horizontal
self.selectionKeys = "123456789"
candidateDataAll = []
// compiler
construct(candidates: candidates, lines: lines, selectionKeys: selectionKeys, layout: layout, locale: locale)
construct(candidates: candidates, selectionKeys: selectionKeys, layout: layout, locale: locale)
}
///
@ -117,11 +125,10 @@ public class CandidatePool {
/// - direction:
/// - locale: zh-Hanszh-Hant
private func construct(
candidates: [(keyArray: [String], value: String)], lines: Int = 3, selectionKeys: String = "123456789",
candidates: [(keyArray: [String], value: String)], selectionKeys: String = "123456789",
layout: LayoutOrientation = .vertical, locale: String = ""
) {
self.layout = layout
maxLinesPerPage = max(1, lines)
Self.blankCell.locale = locale
self.selectionKeys = selectionKeys.isEmpty ? "123456789" : selectionKeys
var allCandidates = candidates.map {
@ -172,13 +179,47 @@ public extension CandidatePool {
}
}
func expandIfNeeded(isBackward: Bool) {
guard !candidateLines.isEmpty, !isExpanded, isExpandable else { return }
let candidatesShown: [CandidateCellData] = candidateLines[lineRangeForCurrentPage].flatMap { $0 }
guard !candidatesShown.filter(\.isHighlighted).isEmpty else { return }
isExpanded = true
if candidateLines.count <= _maxLinesPerPage {
recordedLineRangeForCurrentPage = max(0, currentLineNumber - _maxLinesPerPage + 1) ..< currentLineNumber + 1
} else {
switch isBackward {
case true:
if lineRangeForFirstPage.contains(currentLineNumber) {
recordedLineRangeForCurrentPage = lineRangeForFirstPage
} else {
recordedLineRangeForCurrentPage = max(0, currentLineNumber - _maxLinesPerPage + 1) ..< currentLineNumber + 1
}
case false:
if lineRangeForFinalPage.contains(currentLineNumber) {
recordedLineRangeForCurrentPage = lineRangeForFinalPage
} else {
recordedLineRangeForCurrentPage = currentLineNumber ..< min(candidateLines.count, currentLineNumber + _maxLinesPerPage)
}
}
}
updateMetrics()
}
///
/// - Parameter isBackward:
/// - Returns:
@discardableResult func flipPage(isBackward: Bool) -> Bool {
if !isExpanded, isExpandable {
expandIfNeeded(isBackward: isBackward)
return true
}
backupLineRangeForCurrentPage()
defer { flipLineRangeToNeighborPage(isBackward: isBackward) }
return consecutivelyFlipLines(isBackward: isBackward, count: maxLinesPerPage)
var theCount = maxLinesPerPage
let rareConditionA: Bool = isBackward && currentLineNumber == 0
let rareConditionB: Bool = !isBackward && currentLineNumber == candidateLines.count - 1
if rareConditionA || rareConditionB { theCount = 1 }
return consecutivelyFlipLines(isBackward: isBackward, count: theCount)
}
///
@ -196,6 +237,7 @@ public extension CandidatePool {
/// - count:
/// - Returns:
@discardableResult func consecutivelyFlipLines(isBackward: Bool, count: Int) -> Bool {
expandIfNeeded(isBackward: isBackward)
switch isBackward {
case false where currentLineNumber == candidateLines.count - 1:
return highlightNeighborCandidate(isBackward: false)

View File

@ -170,7 +170,7 @@ extension CandidatePool {
arrLine.enumerated().forEach { cellID, currentCell in
let cellString = NSMutableAttributedString(
attributedString: currentCell.attributedString(
noSpacePadding: false, withHighlight: true, isMatrix: maxLinesPerPage > 1
noSpacePadding: false, withHighlight: true, isMatrix: isMatrix
)
)
if lineID != currentLineNumber {
@ -184,7 +184,7 @@ extension CandidatePool {
result.append(spacer)
}
}
if lineID < lineRangeForCurrentPage.upperBound - 1 || maxLinesPerPage > 1 {
if lineID < lineRangeForCurrentPage.upperBound - 1 || isMatrix {
result.append(lineFeed)
} else {
result.append(spacer)
@ -211,7 +211,7 @@ extension CandidatePool {
let currentCell = lineData[inlineIndex]
let cellString = NSMutableAttributedString(
attributedString: currentCell.attributedString(
noSpacePadding: false, withHighlight: true, isMatrix: maxLinesPerPage > 1
noSpacePadding: false, withHighlight: true, isMatrix: isMatrix
)
)
if lineID != currentLineNumber {
@ -221,7 +221,7 @@ extension CandidatePool {
)
}
result.append(cellString)
if maxLinesPerPage > 1, currentCell.displayedText.count > 1 {
if isMatrix, currentCell.displayedText.count > 1 {
if currentCell.isHighlighted {
spacer.addAttribute(
.backgroundColor,

View File

@ -96,7 +96,7 @@ public class CtlCandidateTDK: CtlCandidate, NSWindowDelegate {
CandidateCellData.unifiedSize = candidateFont.pointSize
guard let delegate = delegate else { return }
Self.thePool = .init(
candidates: delegate.candidatePairs(conv: true), lines: maxLinesPerPage,
candidates: delegate.candidatePairs(conv: true), lines: maxLinesPerPage, isExpanded: false,
selectionKeys: delegate.selectionKeys, layout: currentLayout.layoutTDK, locale: locale
)
Self.thePool.tooltip = tooltip

View File

@ -191,7 +191,7 @@
wrappedCell.setHuggingPriority(.fittingSizeCompression, for: .vertical)
Self.makeSimpleConstraint(item: wrappedCell, attribute: .height, relation: .equal, value: cellHeight)
switch thePool.layout {
case .horizontal where thePool.maxLinesPerPage > 1:
case .horizontal where thePool.isMatrix:
Self.makeSimpleConstraint(item: wrappedCell, attribute: .width, relation: .equal, value: cellWidth)
default:
Self.makeSimpleConstraint(item: wrappedCell, attribute: .width, relation: .greaterThanOrEqual, value: cellWidth)
@ -216,7 +216,7 @@
private func generateLineContainer(_ theLine: inout [CandidateCellData]) -> NSStackView {
let isVerticalListing: Bool = thePool.layout == .vertical
let isMatrix = thePool.maxLinesPerPage > 1
let isMatrix = thePool.isMatrix
let vwrCurrentLine = NSStackView()
vwrCurrentLine.spacing = 0
vwrCurrentLine.orientation = isVerticalListing ? .vertical : .horizontal

View File

@ -41,7 +41,7 @@ public struct VwrCandidateTDK: View {
default:
mainViewVertical.background(candidateListBackground)
}
if thePool.maxLinesPerPage > 1 || thePool.layout == .vertical {
if thePool.isMatrix || thePool.layout == .vertical {
statusBarContent
}
}
@ -193,7 +193,7 @@ extension VwrCandidateTDK {
Double(thePool.maxLineCapacity) * (CandidatePool.blankCell.cellLength())
+ spacings
)
return thePool.layout == .horizontal && thePool.maxLinesPerPage > 1 ? maxWindowWith : nil
return thePool.layout == .horizontal && thePool.isMatrix ? maxWindowWith : nil
}
var firstReverseLookupResult: String {