CtlCandidateTDK // Memory leak fix, etc.
- Also stop reloadData() on init().
This commit is contained in:
parent
6f579fafd8
commit
6229f7deaf
|
@ -10,7 +10,7 @@ import Cocoa
|
|||
import Shared
|
||||
|
||||
/// 候選字窗會用到的資料池單位。
|
||||
public class CandidatePool {
|
||||
public struct CandidatePool {
|
||||
public let blankCell = CandidateCellData(key: " ", displayedText: " ", isSelected: false)
|
||||
public var currentLayout: NSUserInterfaceLayoutOrientation = .horizontal
|
||||
public private(set) var candidateDataAll: [CandidateCellData] = []
|
||||
|
@ -174,7 +174,7 @@ public class CandidatePool {
|
|||
|
||||
// MARK: Public Functions
|
||||
|
||||
public func selectNewNeighborLine(isForward: Bool) {
|
||||
public mutating func selectNewNeighborLine(isForward: Bool) {
|
||||
switch currentLayout {
|
||||
case .horizontal: selectNewNeighborRow(direction: isForward ? .down : .up)
|
||||
case .vertical: selectNewNeighborColumn(direction: isForward ? .right : .left)
|
||||
|
@ -182,7 +182,7 @@ public class CandidatePool {
|
|||
}
|
||||
}
|
||||
|
||||
public func highlight(at indexSpecified: Int) {
|
||||
public mutating func highlight(at indexSpecified: Int) {
|
||||
switch currentLayout {
|
||||
case .horizontal: highlightHorizontal(at: indexSpecified)
|
||||
case .vertical: highlightVertical(at: indexSpecified)
|
||||
|
@ -221,7 +221,7 @@ extension CandidatePool {
|
|||
currentColumnNumber..<min(candidateColumns.count, currentColumnNumber + maxColumnsPerPage)
|
||||
}
|
||||
|
||||
private func selectNewNeighborRow(direction: VerticalDirection) {
|
||||
private mutating func selectNewNeighborRow(direction: VerticalDirection) {
|
||||
let currentSubIndex = candidateDataAll[highlightedIndex].subIndex
|
||||
var result = currentSubIndex
|
||||
switch direction {
|
||||
|
@ -259,7 +259,7 @@ extension CandidatePool {
|
|||
}
|
||||
}
|
||||
|
||||
private func selectNewNeighborColumn(direction: HorizontalDirection) {
|
||||
private mutating func selectNewNeighborColumn(direction: HorizontalDirection) {
|
||||
let currentSubIndex = candidateDataAll[highlightedIndex].subIndex
|
||||
switch direction {
|
||||
case .left:
|
||||
|
@ -288,7 +288,7 @@ extension CandidatePool {
|
|||
}
|
||||
}
|
||||
|
||||
private func highlightHorizontal(at indexSpecified: Int) {
|
||||
private mutating func highlightHorizontal(at indexSpecified: Int) {
|
||||
var indexSpecified = indexSpecified
|
||||
highlightedIndex = indexSpecified
|
||||
if !(0..<candidateDataAll.count).contains(highlightedIndex) {
|
||||
|
@ -321,7 +321,7 @@ extension CandidatePool {
|
|||
}
|
||||
}
|
||||
|
||||
private func highlightVertical(at indexSpecified: Int) {
|
||||
private mutating func highlightVertical(at indexSpecified: Int) {
|
||||
var indexSpecified = indexSpecified
|
||||
highlightedIndex = indexSpecified
|
||||
if !(0..<candidateDataAll.count).contains(highlightedIndex) {
|
||||
|
|
|
@ -13,52 +13,54 @@ import SwiftUI
|
|||
|
||||
@available(macOS 10.15, *)
|
||||
public class CtlCandidateTDK: CtlCandidate {
|
||||
public var thePoolHorizontal: CandidatePool = .init(candidates: [], rowCapacity: 6)
|
||||
public var thePoolVertical: CandidatePool = .init(candidates: [], columnCapacity: 6)
|
||||
public var maxLinesPerPage: Int = 0
|
||||
|
||||
private static var thePoolHorizontal: CandidatePool = .init(candidates: [], rowCapacity: 6)
|
||||
private static var thePoolVertical: CandidatePool = .init(candidates: [], columnCapacity: 6)
|
||||
private static var currentView: NSView = .init()
|
||||
|
||||
@available(macOS 12, *)
|
||||
public var theViewHorizontal: VwrCandidateHorizontal {
|
||||
.init(
|
||||
controller: self, thePool: thePoolHorizontal,
|
||||
private var theViewHorizontal: some View {
|
||||
VwrCandidateHorizontal(
|
||||
controller: self, thePool: Self.thePoolHorizontal,
|
||||
tooltip: tooltip, reverseLookupResult: reverseLookupResult
|
||||
)
|
||||
).edgesIgnoringSafeArea(.top)
|
||||
}
|
||||
|
||||
@available(macOS 12, *)
|
||||
public var theViewVertical: VwrCandidateVertical {
|
||||
.init(
|
||||
controller: self, thePool: thePoolVertical,
|
||||
private var theViewVertical: some View {
|
||||
VwrCandidateVertical(
|
||||
controller: self, thePool: Self.thePoolVertical,
|
||||
tooltip: tooltip, reverseLookupResult: reverseLookupResult
|
||||
)
|
||||
).edgesIgnoringSafeArea(.top)
|
||||
}
|
||||
|
||||
public var theViewHorizontalBackports: VwrCandidateHorizontalBackports {
|
||||
.init(
|
||||
controller: self, thePool: thePoolHorizontal,
|
||||
private var theViewHorizontalBackports: some View {
|
||||
VwrCandidateHorizontalBackports(
|
||||
controller: self, thePool: Self.thePoolHorizontal,
|
||||
tooltip: tooltip, reverseLookupResult: reverseLookupResult
|
||||
)
|
||||
).edgesIgnoringSafeArea(.top)
|
||||
}
|
||||
|
||||
public var theViewVerticalBackports: VwrCandidateVerticalBackports {
|
||||
.init(
|
||||
controller: self, thePool: thePoolVertical,
|
||||
private var theViewVerticalBackports: some View {
|
||||
VwrCandidateVerticalBackports(
|
||||
controller: self, thePool: Self.thePoolVertical,
|
||||
tooltip: tooltip, reverseLookupResult: reverseLookupResult
|
||||
)
|
||||
).edgesIgnoringSafeArea(.top)
|
||||
}
|
||||
|
||||
public var thePool: CandidatePool {
|
||||
private var thePool: CandidatePool {
|
||||
get {
|
||||
switch currentLayout {
|
||||
case .horizontal: return thePoolHorizontal
|
||||
case .vertical: return thePoolVertical
|
||||
case .horizontal: return Self.thePoolHorizontal
|
||||
case .vertical: return Self.thePoolVertical
|
||||
@unknown default: return .init(candidates: [], rowCapacity: 0)
|
||||
}
|
||||
}
|
||||
set {
|
||||
switch currentLayout {
|
||||
case .horizontal: thePoolHorizontal = newValue
|
||||
case .vertical: thePoolVertical = newValue
|
||||
case .horizontal: Self.thePoolHorizontal = newValue
|
||||
case .vertical: Self.thePoolVertical = newValue
|
||||
@unknown default: break
|
||||
}
|
||||
}
|
||||
|
@ -81,7 +83,6 @@ public class CtlCandidateTDK: CtlCandidate {
|
|||
super.init(layout)
|
||||
window = panel
|
||||
currentLayout = layout
|
||||
reloadData()
|
||||
}
|
||||
|
||||
@available(*, unavailable)
|
||||
|
@ -98,17 +99,17 @@ public class CtlCandidateTDK: CtlCandidate {
|
|||
|
||||
switch currentLayout {
|
||||
case .horizontal:
|
||||
thePoolHorizontal = .init(
|
||||
Self.thePoolHorizontal = .init(
|
||||
candidates: delegate.candidatePairs(conv: true).map(\.1), rowCapacity: 6,
|
||||
rows: maxLinesPerPage, selectionKeys: delegate.selectionKeys, locale: locale
|
||||
)
|
||||
thePoolHorizontal.highlight(at: 0)
|
||||
Self.thePoolHorizontal.highlight(at: 0)
|
||||
case .vertical:
|
||||
thePoolVertical = .init(
|
||||
Self.thePoolVertical = .init(
|
||||
candidates: delegate.candidatePairs(conv: true).map(\.1), columnCapacity: 6,
|
||||
columns: maxLinesPerPage, selectionKeys: delegate.selectionKeys, locale: locale
|
||||
)
|
||||
thePoolVertical.highlight(at: 0)
|
||||
Self.thePoolVertical.highlight(at: 0)
|
||||
@unknown default:
|
||||
return
|
||||
}
|
||||
|
@ -122,30 +123,24 @@ public class CtlCandidateTDK: CtlCandidate {
|
|||
case .horizontal:
|
||||
DispatchQueue.main.async { [self] in
|
||||
if #available(macOS 12, *) {
|
||||
let newView = NSHostingView(rootView: theViewHorizontal.edgesIgnoringSafeArea(.top))
|
||||
let newSize = newView.fittingSize
|
||||
window.contentView = newView
|
||||
window.setContentSize(newSize)
|
||||
Self.currentView = NSHostingView(rootView: theViewHorizontal)
|
||||
} else {
|
||||
let newView = NSHostingView(rootView: theViewHorizontalBackports.edgesIgnoringSafeArea(.top))
|
||||
let newSize = newView.fittingSize
|
||||
window.contentView = newView
|
||||
window.setContentSize(newSize)
|
||||
Self.currentView = NSHostingView(rootView: theViewHorizontalBackports)
|
||||
}
|
||||
let newSize = Self.currentView.fittingSize
|
||||
window.contentView = Self.currentView
|
||||
window.setContentSize(newSize)
|
||||
}
|
||||
case .vertical:
|
||||
DispatchQueue.main.async { [self] in
|
||||
if #available(macOS 12, *) {
|
||||
let newView = NSHostingView(rootView: theViewVertical.edgesIgnoringSafeArea(.top))
|
||||
let newSize = newView.fittingSize
|
||||
window.contentView = newView
|
||||
window.setContentSize(newSize)
|
||||
Self.currentView = NSHostingView(rootView: theViewVertical)
|
||||
} else {
|
||||
let newView = NSHostingView(rootView: theViewVerticalBackports.edgesIgnoringSafeArea(.top))
|
||||
let newSize = newView.fittingSize
|
||||
window.contentView = newView
|
||||
window.setContentSize(newSize)
|
||||
Self.currentView = NSHostingView(rootView: theViewVerticalBackports)
|
||||
}
|
||||
let newSize = Self.currentView.fittingSize
|
||||
window.contentView = Self.currentView
|
||||
window.setContentSize(newSize)
|
||||
}
|
||||
@unknown default:
|
||||
return
|
||||
|
|
|
@ -22,20 +22,20 @@ struct CandidatePoolViewUIHorizontal_Previews: PreviewProvider {
|
|||
"吹", "大", "地", "草", "枝", "擺",
|
||||
]
|
||||
static var thePool: CandidatePool {
|
||||
let result = CandidatePool(candidates: testCandidates, rowCapacity: 6)
|
||||
var result = CandidatePool(candidates: testCandidates, rowCapacity: 6)
|
||||
// 下一行待解決:無論這裡怎麼指定高亮選中項是哪一筆,其所在行都得被卷動到使用者眼前。
|
||||
result.highlight(at: 5)
|
||||
return result
|
||||
}
|
||||
|
||||
static var previews: some View {
|
||||
VwrCandidateHorizontal(controller: .init(.horizontal), thePool: thePool).fixedSize()
|
||||
VwrCandidateHorizontal(controller: nil, thePool: thePool).fixedSize()
|
||||
}
|
||||
}
|
||||
|
||||
@available(macOS 12, *)
|
||||
public struct VwrCandidateHorizontal: View {
|
||||
public var controller: CtlCandidateTDK
|
||||
public weak var controller: CtlCandidateTDK?
|
||||
@Environment(\.colorScheme) var colorScheme
|
||||
@State public var thePool: CandidatePool
|
||||
@State public var tooltip: String = ""
|
||||
|
@ -46,7 +46,7 @@ public struct VwrCandidateHorizontal: View {
|
|||
}
|
||||
|
||||
private func didSelectCandidateAt(_ pos: Int) {
|
||||
if let delegate = controller.delegate {
|
||||
if let delegate = controller?.delegate {
|
||||
delegate.candidatePairSelected(at: pos)
|
||||
}
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ public struct VwrCandidateHorizontal: View {
|
|||
}
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
.padding([.horizontal], 5).padding([.top], 5).padding([.bottom], -1)
|
||||
if controller.delegate?.showReverseLookupResult ?? true {
|
||||
if controller?.delegate?.showReverseLookupResult ?? true {
|
||||
ZStack(alignment: .leading) {
|
||||
Color(white: colorScheme == .dark ? 0.15 : 0.97)
|
||||
HStack(alignment: .center, spacing: 4) {
|
||||
|
|
|
@ -21,20 +21,20 @@ struct CandidatePoolViewUIVertical_Previews: PreviewProvider {
|
|||
"吹", "大", "地", "草", "枝", "擺",
|
||||
]
|
||||
static var thePool: CandidatePool {
|
||||
let result = CandidatePool(candidates: testCandidates, columnCapacity: 6, selectionKeys: "123456789")
|
||||
var result = CandidatePool(candidates: testCandidates, columnCapacity: 6, selectionKeys: "123456789")
|
||||
// 下一行待解決:無論這裡怎麼指定高亮選中項是哪一筆,其所在行都得被卷動到使用者眼前。
|
||||
result.highlight(at: 5)
|
||||
return result
|
||||
}
|
||||
|
||||
static var previews: some View {
|
||||
VwrCandidateVertical(controller: .init(.horizontal), thePool: thePool).fixedSize()
|
||||
VwrCandidateVertical(controller: nil, thePool: thePool).fixedSize()
|
||||
}
|
||||
}
|
||||
|
||||
@available(macOS 12, *)
|
||||
public struct VwrCandidateVertical: View {
|
||||
public var controller: CtlCandidateTDK
|
||||
public weak var controller: CtlCandidateTDK?
|
||||
@Environment(\.colorScheme) var colorScheme
|
||||
@State public var thePool: CandidatePool
|
||||
@State public var tooltip: String = ""
|
||||
|
@ -45,7 +45,7 @@ public struct VwrCandidateVertical: View {
|
|||
}
|
||||
|
||||
private func didSelectCandidateAt(_ pos: Int) {
|
||||
if let delegate = controller.delegate {
|
||||
if let delegate = controller?.delegate {
|
||||
delegate.candidatePairSelected(at: pos)
|
||||
}
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ public struct VwrCandidateVertical: View {
|
|||
}
|
||||
}
|
||||
.fixedSize(horizontal: true, vertical: false).padding(5)
|
||||
if controller.delegate?.showReverseLookupResult ?? true {
|
||||
if controller?.delegate?.showReverseLookupResult ?? true {
|
||||
ZStack(alignment: .leading) {
|
||||
Color(white: colorScheme == .dark ? 0.15 : 0.97)
|
||||
HStack(alignment: .center, spacing: 4) {
|
||||
|
|
|
@ -23,20 +23,20 @@ struct CandidatePoolViewUIHorizontalBackports_Previews: PreviewProvider {
|
|||
"吹", "大", "地", "草", "枝", "擺",
|
||||
]
|
||||
static var thePool: CandidatePool {
|
||||
let result = CandidatePool(candidates: testCandidates, rowCapacity: 6)
|
||||
var result = CandidatePool(candidates: testCandidates, rowCapacity: 6)
|
||||
// 下一行待解決:無論這裡怎麼指定高亮選中項是哪一筆,其所在行都得被卷動到使用者眼前。
|
||||
result.highlight(at: 5)
|
||||
return result
|
||||
}
|
||||
|
||||
static var previews: some View {
|
||||
VwrCandidateHorizontalBackports(controller: .init(.horizontal), thePool: thePool).fixedSize()
|
||||
VwrCandidateHorizontalBackports(controller: nil, thePool: thePool).fixedSize()
|
||||
}
|
||||
}
|
||||
|
||||
@available(macOS 10.15, *)
|
||||
public struct VwrCandidateHorizontalBackports: View {
|
||||
public var controller: CtlCandidateTDK
|
||||
public weak var controller: CtlCandidateTDK?
|
||||
@Environment(\.colorScheme) var colorScheme
|
||||
@State public var thePool: CandidatePool
|
||||
@State public var tooltip: String = ""
|
||||
|
@ -47,7 +47,7 @@ public struct VwrCandidateHorizontalBackports: View {
|
|||
}
|
||||
|
||||
private func didSelectCandidateAt(_ pos: Int) {
|
||||
if let delegate = controller.delegate {
|
||||
if let delegate = controller?.delegate {
|
||||
delegate.candidatePairSelected(at: pos)
|
||||
}
|
||||
}
|
||||
|
@ -94,7 +94,7 @@ public struct VwrCandidateHorizontalBackports: View {
|
|||
}
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
.padding([.horizontal], 5).padding([.top], 5).padding([.bottom], -1)
|
||||
if controller.delegate?.showReverseLookupResult ?? true {
|
||||
if controller?.delegate?.showReverseLookupResult ?? true {
|
||||
ZStack(alignment: .leading) {
|
||||
Color(white: colorScheme == .dark ? 0.15 : 0.97)
|
||||
HStack(alignment: .center, spacing: 4) {
|
||||
|
@ -116,7 +116,7 @@ public struct VwrCandidateHorizontalBackports: View {
|
|||
Color(white: colorScheme == .dark ? 0.2 : 0.9)
|
||||
} else {
|
||||
Color(white: colorScheme == .dark ? 0.0 : 1)
|
||||
controller.highlightedColorUIBackports
|
||||
controller?.highlightedColorUIBackports
|
||||
}
|
||||
HStack(alignment: .center) {
|
||||
if !tooltip.isEmpty {
|
||||
|
|
|
@ -22,20 +22,20 @@ struct CandidatePoolViewUIVerticalBackports_Previews: PreviewProvider {
|
|||
"吹", "大", "地", "草", "枝", "擺",
|
||||
]
|
||||
static var thePool: CandidatePool {
|
||||
let result = CandidatePool(candidates: testCandidates, columnCapacity: 6, selectionKeys: "123456789")
|
||||
var result = CandidatePool(candidates: testCandidates, columnCapacity: 6, selectionKeys: "123456789")
|
||||
// 下一行待解決:無論這裡怎麼指定高亮選中項是哪一筆,其所在行都得被卷動到使用者眼前。
|
||||
result.highlight(at: 5)
|
||||
return result
|
||||
}
|
||||
|
||||
static var previews: some View {
|
||||
VwrCandidateVerticalBackports(controller: .init(.horizontal), thePool: thePool).fixedSize()
|
||||
VwrCandidateVerticalBackports(controller: nil, thePool: thePool).fixedSize()
|
||||
}
|
||||
}
|
||||
|
||||
@available(macOS 10.15, *)
|
||||
public struct VwrCandidateVerticalBackports: View {
|
||||
public var controller: CtlCandidateTDK
|
||||
public weak var controller: CtlCandidateTDK?
|
||||
@Environment(\.colorScheme) var colorScheme
|
||||
@State public var thePool: CandidatePool
|
||||
@State public var tooltip: String = ""
|
||||
|
@ -46,7 +46,7 @@ public struct VwrCandidateVerticalBackports: View {
|
|||
}
|
||||
|
||||
private func didSelectCandidateAt(_ pos: Int) {
|
||||
if let delegate = controller.delegate {
|
||||
if let delegate = controller?.delegate {
|
||||
delegate.candidatePairSelected(at: pos)
|
||||
}
|
||||
}
|
||||
|
@ -101,7 +101,7 @@ public struct VwrCandidateVerticalBackports: View {
|
|||
}
|
||||
}
|
||||
.fixedSize(horizontal: true, vertical: false).padding(5)
|
||||
if controller.delegate?.showReverseLookupResult ?? true {
|
||||
if controller?.delegate?.showReverseLookupResult ?? true {
|
||||
ZStack(alignment: .leading) {
|
||||
Color(white: colorScheme == .dark ? 0.15 : 0.97)
|
||||
HStack(alignment: .center, spacing: 4) {
|
||||
|
@ -123,7 +123,7 @@ public struct VwrCandidateVerticalBackports: View {
|
|||
Color(white: colorScheme == .dark ? 0.2 : 0.9)
|
||||
} else {
|
||||
Color(white: colorScheme == .dark ? 0.0 : 1)
|
||||
controller.highlightedColorUIBackports
|
||||
controller?.highlightedColorUIBackports
|
||||
}
|
||||
HStack(alignment: .center) {
|
||||
if !tooltip.isEmpty {
|
||||
|
|
Loading…
Reference in New Issue