TDKCandidates // Ensure compatibility with macOS 10.9 Mavericks.

* Refine constraint calculation methods.
* Reintroduce `window.isOpaque = false`.
* Fix translatesAutoresizingMaskIntoConstraints().
* Debugging dimensions of UI components.
* Avoid using zero rects on construction.
This commit is contained in:
ShikiSuen 2023-02-28 16:58:13 +08:00
parent cf04e09acd
commit ab4ae41af6
3 changed files with 96 additions and 13 deletions

View File

@ -15,6 +15,7 @@ import SwiftUIBackports
/// class 便
public class CandidateCellData: Hashable {
public var visualDimension: CGSize = .zero
public var locale = ""
public static var unifiedSize: Double = 16
public var key: String

View File

@ -89,6 +89,7 @@ public class CtlCandidateTDK: CtlCandidate, NSWindowDelegate {
Self.thePool.reverseLookupResult = reverseLookupResult
}
DispatchQueue.main.async { [self] in
window.isOpaque = false
window.backgroundColor = .clear
viewCheck: if #available(macOS 10.15, *) {
if useCocoa {

View File

@ -13,13 +13,15 @@ import Shared
public class VwrCandidateTDKCocoa: NSStackView {
public weak var controller: CtlCandidateTDK?
public var thePool: CandidatePool
private var lineDimension: CGSize = .zero
private var candidateAreaDimension: CGSize = .zero
// MARK: - Constructors.
public init(controller: CtlCandidateTDK? = nil, thePool pool: CandidatePool) {
self.controller = controller
thePool = pool
super.init(frame: .init(origin: .zero, size: .zero))
super.init(frame: .init(origin: .zero, size: .init(width: 114_514, height: 114_514)))
refresh()
}
@ -33,6 +35,15 @@ public class VwrCandidateTDKCocoa: NSStackView {
public extension VwrCandidateTDKCocoa {
func refresh() {
defer {
vCLog(Self.strForConstraintStatistics.description)
Self.strForConstraintStatistics = .init()
}
// 便 constraints
var arrStackViewsOfLines = [NSStackView]()
//
lineDimension = .zero
candidateAreaDimension = .zero
//
edgeInsets = .init(top: 5, left: 5, bottom: 5, right: 5)
wantsLayer = true
@ -51,6 +62,7 @@ public extension VwrCandidateTDKCocoa {
var theLine = thePool.candidateLines[lineID]
let vwrCurrentLine = generateLineContainer(&theLine)
candidateContainer.addView(vwrCurrentLine, in: isVerticalListing ? .top : .leading)
arrStackViewsOfLines.append(vwrCurrentLine)
}
if thePool.maxLinesPerPage - thePool.lineRangeForCurrentPage.count > 0 {
thePool.lineRangeForFinalPageBlanked.enumerated().forEach { _ in
@ -60,26 +72,54 @@ public extension VwrCandidateTDKCocoa {
}
let vwrCurrentLine = generateLineContainer(&theLine)
candidateContainer.addView(vwrCurrentLine, in: isVerticalListing ? .top : .leading)
arrStackViewsOfLines.append(vwrCurrentLine)
}
}
//
switch thePool.layout {
case .vertical:
let minHeight = Double(thePool.maxLineCapacity)
* drawCellCocoa(thePool.blankCell).fittingSize.height
candidateContainer.subviews.forEach { vwrCurrentLine in
Self.makeSimpleConstraint(item: vwrCurrentLine, attribute: .height, relation: .equal, value: minHeight)
var accumulatedWidth: CGFloat = 0
var lines = [[CandidateCellData]]()
thePool.lineRangeForCurrentPage.forEach { lines.append(thePool.candidateLines[$0]) }
arrStackViewsOfLines.enumerated().forEach { viewLineID, vwrCurrentLine in
var columnWidth: CGFloat = 0
if (0 ..< lines.count).contains(viewLineID), !lines.isEmpty {
let line = Array(lines[viewLineID])
columnWidth = line.map(\.visualDimension.width).max() ?? lineDimension.width
} else {
columnWidth = thePool.blankCell.visualDimension.width
}
accumulatedWidth += columnWidth
Self.makeSimpleConstraint(item: vwrCurrentLine, attribute: .width, relation: .equal, value: columnWidth)
Self.makeSimpleConstraint(item: vwrCurrentLine, attribute: .height, relation: .equal, value: lineDimension.height)
Self.addStatistics(vwrCurrentLine, memo: "vwrCurrentLine")
}
case .horizontal where thePool.maxLinesPerPage > 1:
let containerWidth = candidateContainer.fittingSize.width
candidateContainer.subviews.forEach { vwrCurrentLine in
Self.makeSimpleConstraint(item: vwrCurrentLine, attribute: .width, relation: .equal, value: containerWidth)
candidateAreaDimension.width = accumulatedWidth
candidateAreaDimension.height = lineDimension.height
case .horizontal:
arrStackViewsOfLines.forEach { vwrCurrentLine in
Self.makeSimpleConstraint(item: vwrCurrentLine, attribute: .width, relation: .equal, value: lineDimension.width)
Self.makeSimpleConstraint(item: vwrCurrentLine, attribute: .height, relation: .equal, value: lineDimension.height)
Self.addStatistics(vwrCurrentLine, memo: "vwrCurrentLine")
}
default: break
candidateAreaDimension.width = lineDimension.width
candidateAreaDimension.height = lineDimension.height * Double(thePool.maxLinesPerPage)
}
Self.makeSimpleConstraint(item: candidateContainer, attribute: .width, relation: .equal, value: candidateAreaDimension.width)
Self.makeSimpleConstraint(item: candidateContainer, attribute: .height, relation: .equal, value: candidateAreaDimension.height)
Self.addStatistics(candidateContainer, memo: "candidateContainer")
let vwrPeripherals = Self.makeLabel(thePool.attributedDescriptionBottomPanes)
Self.makeSimpleConstraint(
item: vwrPeripherals, attribute: .height, relation: .greaterThanOrEqual,
value: vwrPeripherals.fittingSize.height
)
Self.makeSimpleConstraint(
item: vwrPeripherals, attribute: .width, relation: .greaterThanOrEqual,
value: vwrPeripherals.fittingSize.width
)
//
let finalContainer = NSStackView()
@ -94,12 +134,23 @@ public extension VwrCandidateTDKCocoa {
finalContainer.spacing = 5
} else {
finalContainer.spacing = 2
Self.makeSimpleConstraint(item: vwrPeripherals, attribute: .width, relation: .greaterThanOrEqual, value: vwrPeripherals.fittingSize.width)
}
Self.addStatistics(vwrPeripherals, memo: "vwrPeripherals")
finalContainer.orientation = finalContainerOrientation
finalContainer.alignment = finalContainerOrientation == .vertical ? .leading : .centerY
finalContainer.addView(candidateContainer, in: .leading)
finalContainer.addView(vwrPeripherals, in: .leading)
Self.makeSimpleConstraint(
item: finalContainer, attribute: .width,
relation: .equal, value: finalContainer.fittingSize.width
)
Self.makeSimpleConstraint(
item: finalContainer, attribute: .height,
relation: .equal, value: finalContainer.fittingSize.height
)
Self.addStatistics(finalContainer, memo: "finalContainer")
//
subviews.forEach { removeView($0) }
@ -119,6 +170,9 @@ private extension VwrCandidateTDKCocoa {
let theCell = theCell ?? thePool.blankCell
let cellLabel = VwrCandidateCell(cell: theCell)
cellLabel.target = self
Self.makeSimpleConstraint(item: cellLabel, attribute: .width, relation: .equal, value: cellLabel.fittingSize.width)
Self.makeSimpleConstraint(item: cellLabel, attribute: .height, relation: .equal, value: cellLabel.fittingSize.height)
Self.addStatistics(cellLabel, memo: "cellLabel")
let wrappedCell = NSStackView()
let padding: CGFloat = 3
wrappedCell.edgeInsets = .init(top: padding, left: padding, bottom: padding, right: padding)
@ -128,11 +182,10 @@ private extension VwrCandidateTDKCocoa {
wrappedCell.layer?.backgroundColor = theCell.themeColorCocoa.cgColor
wrappedCell.layer?.cornerRadius = padding * 2
}
let cellWidth = thePool.cellWidth(theCell).min ?? wrappedCell.fittingSize.width
let cellWidth = max(thePool.cellWidth(theCell).min ?? wrappedCell.fittingSize.width, wrappedCell.fittingSize.width)
let cellHeight = wrappedCell.fittingSize.height
wrappedCell.setHuggingPriority(.fittingSizeCompression, for: .horizontal)
wrappedCell.setHuggingPriority(.fittingSizeCompression, for: .vertical)
wrappedCell.translatesAutoresizingMaskIntoConstraints = false
Self.makeSimpleConstraint(item: wrappedCell, attribute: .height, relation: .equal, value: cellHeight)
switch thePool.layout {
case .horizontal where thePool.maxLinesPerPage > 1:
@ -140,6 +193,8 @@ private extension VwrCandidateTDKCocoa {
default:
Self.makeSimpleConstraint(item: wrappedCell, attribute: .width, relation: .greaterThanOrEqual, value: cellWidth)
}
Self.addStatistics(wrappedCell, memo: "wrappedCell")
theCell.visualDimension = .init(width: cellWidth, height: cellHeight)
return wrappedCell
}
@ -162,9 +217,20 @@ private extension VwrCandidateTDKCocoa {
let vwrCurrentLine = NSStackView()
vwrCurrentLine.spacing = 0
vwrCurrentLine.orientation = isVerticalListing ? .vertical : .horizontal
var cellHeight = 0.0
var lineSize: CGSize = .zero
let isCurrentLine = theLine.hasHighlightedCell
theLine.forEach { theCell in
vwrCurrentLine.addView(drawCellCocoa(theCell), in: isVerticalListing ? .top : .leading)
switch thePool.layout {
case .horizontal:
lineSize.width += theCell.visualDimension.width
lineSize.height = max(lineSize.height, theCell.visualDimension.height)
case .vertical:
lineSize.width = max(lineSize.width, theCell.visualDimension.width)
lineSize.height += theCell.visualDimension.height
}
cellHeight = max(theCell.visualDimension.height, cellHeight)
}
let lineBg = lineBackground(isCurrentLine: isCurrentLine, isMatrix: isMatrix)
vwrCurrentLine.wantsLayer = isCurrentLine && isMatrix
@ -172,6 +238,11 @@ private extension VwrCandidateTDKCocoa {
vwrCurrentLine.layer?.backgroundColor = lineBg.cgColor
vwrCurrentLine.layer?.cornerRadius = 6
}
lineDimension.width = max(lineSize.width, lineDimension.width)
switch thePool.layout {
case .horizontal: lineDimension.height = max(lineSize.height, lineDimension.height)
case .vertical: lineDimension.height = cellHeight * Double(thePool.maxLineCapacity)
}
return vwrCurrentLine
}
@ -192,7 +263,17 @@ private extension VwrCandidateTDKCocoa {
// MARK: - Constraint Utilities
private extension VwrCandidateTDKCocoa {
static var strForConstraintStatistics = NSMutableString(string: "TDKCandidates Dimensions (Debug):\n")
static func addStatistics(_ target: NSView, memo: String = "") {
if Self.strForConstraintStatistics.length == 0 {
Self.strForConstraintStatistics.append("TDKCandidates Dimensions (Debug):\n")
}
Self.strForConstraintStatistics.append("\(target.fittingSize) \(memo)\n")
}
static func makeSimpleConstraint(item: NSView, attribute: NSLayoutConstraint.Attribute, relation: NSLayoutConstraint.Relation, value: CGFloat) {
item.translatesAutoresizingMaskIntoConstraints = false
let widthConstraint = NSLayoutConstraint(
item: item, attribute: attribute, relatedBy: relation, toItem: nil,
attribute: NSLayoutConstraint.Attribute.notAnAttribute, multiplier: 1, constant: value
@ -208,7 +289,7 @@ private extension VwrCandidateTDKCocoa {
public var cellData: CandidateCellData
public init(cell: CandidateCellData) {
cellData = cell
super.init(frame: .init(origin: .zero, size: .zero))
super.init(frame: .init(origin: .zero, size: .init(width: 114_514, height: 114_514)))
isSelectable = false
isEditable = false
isBordered = false