CtlCandidateTDK // Memory leak fix, etc.

- Also stop reloadData() on init().
This commit is contained in:
ShikiSuen 2022-11-25 12:54:24 +08:00
parent 6f579fafd8
commit 6229f7deaf
6 changed files with 68 additions and 73 deletions

View File

@ -10,7 +10,7 @@ import Cocoa
import Shared import Shared
/// ///
public class CandidatePool { public struct CandidatePool {
public let blankCell = CandidateCellData(key: " ", displayedText: " ", isSelected: false) public let blankCell = CandidateCellData(key: " ", displayedText: " ", isSelected: false)
public var currentLayout: NSUserInterfaceLayoutOrientation = .horizontal public var currentLayout: NSUserInterfaceLayoutOrientation = .horizontal
public private(set) var candidateDataAll: [CandidateCellData] = [] public private(set) var candidateDataAll: [CandidateCellData] = []
@ -174,7 +174,7 @@ public class CandidatePool {
// MARK: Public Functions // MARK: Public Functions
public func selectNewNeighborLine(isForward: Bool) { public mutating func selectNewNeighborLine(isForward: Bool) {
switch currentLayout { switch currentLayout {
case .horizontal: selectNewNeighborRow(direction: isForward ? .down : .up) case .horizontal: selectNewNeighborRow(direction: isForward ? .down : .up)
case .vertical: selectNewNeighborColumn(direction: isForward ? .right : .left) 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 { switch currentLayout {
case .horizontal: highlightHorizontal(at: indexSpecified) case .horizontal: highlightHorizontal(at: indexSpecified)
case .vertical: highlightVertical(at: indexSpecified) case .vertical: highlightVertical(at: indexSpecified)
@ -221,7 +221,7 @@ extension CandidatePool {
currentColumnNumber..<min(candidateColumns.count, currentColumnNumber + maxColumnsPerPage) currentColumnNumber..<min(candidateColumns.count, currentColumnNumber + maxColumnsPerPage)
} }
private func selectNewNeighborRow(direction: VerticalDirection) { private mutating func selectNewNeighborRow(direction: VerticalDirection) {
let currentSubIndex = candidateDataAll[highlightedIndex].subIndex let currentSubIndex = candidateDataAll[highlightedIndex].subIndex
var result = currentSubIndex var result = currentSubIndex
switch direction { switch direction {
@ -259,7 +259,7 @@ extension CandidatePool {
} }
} }
private func selectNewNeighborColumn(direction: HorizontalDirection) { private mutating func selectNewNeighborColumn(direction: HorizontalDirection) {
let currentSubIndex = candidateDataAll[highlightedIndex].subIndex let currentSubIndex = candidateDataAll[highlightedIndex].subIndex
switch direction { switch direction {
case .left: case .left:
@ -288,7 +288,7 @@ extension CandidatePool {
} }
} }
private func highlightHorizontal(at indexSpecified: Int) { private mutating func highlightHorizontal(at indexSpecified: Int) {
var indexSpecified = indexSpecified var indexSpecified = indexSpecified
highlightedIndex = indexSpecified highlightedIndex = indexSpecified
if !(0..<candidateDataAll.count).contains(highlightedIndex) { 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 var indexSpecified = indexSpecified
highlightedIndex = indexSpecified highlightedIndex = indexSpecified
if !(0..<candidateDataAll.count).contains(highlightedIndex) { if !(0..<candidateDataAll.count).contains(highlightedIndex) {

View File

@ -13,52 +13,54 @@ import SwiftUI
@available(macOS 10.15, *) @available(macOS 10.15, *)
public class CtlCandidateTDK: CtlCandidate { 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 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, *) @available(macOS 12, *)
public var theViewHorizontal: VwrCandidateHorizontal { private var theViewHorizontal: some View {
.init( VwrCandidateHorizontal(
controller: self, thePool: thePoolHorizontal, controller: self, thePool: Self.thePoolHorizontal,
tooltip: tooltip, reverseLookupResult: reverseLookupResult tooltip: tooltip, reverseLookupResult: reverseLookupResult
) ).edgesIgnoringSafeArea(.top)
} }
@available(macOS 12, *) @available(macOS 12, *)
public var theViewVertical: VwrCandidateVertical { private var theViewVertical: some View {
.init( VwrCandidateVertical(
controller: self, thePool: thePoolVertical, controller: self, thePool: Self.thePoolVertical,
tooltip: tooltip, reverseLookupResult: reverseLookupResult tooltip: tooltip, reverseLookupResult: reverseLookupResult
) ).edgesIgnoringSafeArea(.top)
} }
public var theViewHorizontalBackports: VwrCandidateHorizontalBackports { private var theViewHorizontalBackports: some View {
.init( VwrCandidateHorizontalBackports(
controller: self, thePool: thePoolHorizontal, controller: self, thePool: Self.thePoolHorizontal,
tooltip: tooltip, reverseLookupResult: reverseLookupResult tooltip: tooltip, reverseLookupResult: reverseLookupResult
) ).edgesIgnoringSafeArea(.top)
} }
public var theViewVerticalBackports: VwrCandidateVerticalBackports { private var theViewVerticalBackports: some View {
.init( VwrCandidateVerticalBackports(
controller: self, thePool: thePoolVertical, controller: self, thePool: Self.thePoolVertical,
tooltip: tooltip, reverseLookupResult: reverseLookupResult tooltip: tooltip, reverseLookupResult: reverseLookupResult
) ).edgesIgnoringSafeArea(.top)
} }
public var thePool: CandidatePool { private var thePool: CandidatePool {
get { get {
switch currentLayout { switch currentLayout {
case .horizontal: return thePoolHorizontal case .horizontal: return Self.thePoolHorizontal
case .vertical: return thePoolVertical case .vertical: return Self.thePoolVertical
@unknown default: return .init(candidates: [], rowCapacity: 0) @unknown default: return .init(candidates: [], rowCapacity: 0)
} }
} }
set { set {
switch currentLayout { switch currentLayout {
case .horizontal: thePoolHorizontal = newValue case .horizontal: Self.thePoolHorizontal = newValue
case .vertical: thePoolVertical = newValue case .vertical: Self.thePoolVertical = newValue
@unknown default: break @unknown default: break
} }
} }
@ -81,7 +83,6 @@ public class CtlCandidateTDK: CtlCandidate {
super.init(layout) super.init(layout)
window = panel window = panel
currentLayout = layout currentLayout = layout
reloadData()
} }
@available(*, unavailable) @available(*, unavailable)
@ -98,17 +99,17 @@ public class CtlCandidateTDK: CtlCandidate {
switch currentLayout { switch currentLayout {
case .horizontal: case .horizontal:
thePoolHorizontal = .init( Self.thePoolHorizontal = .init(
candidates: delegate.candidatePairs(conv: true).map(\.1), rowCapacity: 6, candidates: delegate.candidatePairs(conv: true).map(\.1), rowCapacity: 6,
rows: maxLinesPerPage, selectionKeys: delegate.selectionKeys, locale: locale rows: maxLinesPerPage, selectionKeys: delegate.selectionKeys, locale: locale
) )
thePoolHorizontal.highlight(at: 0) Self.thePoolHorizontal.highlight(at: 0)
case .vertical: case .vertical:
thePoolVertical = .init( Self.thePoolVertical = .init(
candidates: delegate.candidatePairs(conv: true).map(\.1), columnCapacity: 6, candidates: delegate.candidatePairs(conv: true).map(\.1), columnCapacity: 6,
columns: maxLinesPerPage, selectionKeys: delegate.selectionKeys, locale: locale columns: maxLinesPerPage, selectionKeys: delegate.selectionKeys, locale: locale
) )
thePoolVertical.highlight(at: 0) Self.thePoolVertical.highlight(at: 0)
@unknown default: @unknown default:
return return
} }
@ -122,30 +123,24 @@ public class CtlCandidateTDK: CtlCandidate {
case .horizontal: case .horizontal:
DispatchQueue.main.async { [self] in DispatchQueue.main.async { [self] in
if #available(macOS 12, *) { if #available(macOS 12, *) {
let newView = NSHostingView(rootView: theViewHorizontal.edgesIgnoringSafeArea(.top)) Self.currentView = NSHostingView(rootView: theViewHorizontal)
let newSize = newView.fittingSize
window.contentView = newView
window.setContentSize(newSize)
} else { } else {
let newView = NSHostingView(rootView: theViewHorizontalBackports.edgesIgnoringSafeArea(.top)) Self.currentView = NSHostingView(rootView: theViewHorizontalBackports)
let newSize = newView.fittingSize
window.contentView = newView
window.setContentSize(newSize)
} }
let newSize = Self.currentView.fittingSize
window.contentView = Self.currentView
window.setContentSize(newSize)
} }
case .vertical: case .vertical:
DispatchQueue.main.async { [self] in DispatchQueue.main.async { [self] in
if #available(macOS 12, *) { if #available(macOS 12, *) {
let newView = NSHostingView(rootView: theViewVertical.edgesIgnoringSafeArea(.top)) Self.currentView = NSHostingView(rootView: theViewVertical)
let newSize = newView.fittingSize
window.contentView = newView
window.setContentSize(newSize)
} else { } else {
let newView = NSHostingView(rootView: theViewVerticalBackports.edgesIgnoringSafeArea(.top)) Self.currentView = NSHostingView(rootView: theViewVerticalBackports)
let newSize = newView.fittingSize
window.contentView = newView
window.setContentSize(newSize)
} }
let newSize = Self.currentView.fittingSize
window.contentView = Self.currentView
window.setContentSize(newSize)
} }
@unknown default: @unknown default:
return return

View File

@ -22,20 +22,20 @@ struct CandidatePoolViewUIHorizontal_Previews: PreviewProvider {
"", "", "", "", "", "", "", "", "", "", "", "",
] ]
static var thePool: CandidatePool { static var thePool: CandidatePool {
let result = CandidatePool(candidates: testCandidates, rowCapacity: 6) var result = CandidatePool(candidates: testCandidates, rowCapacity: 6)
// 使 // 使
result.highlight(at: 5) result.highlight(at: 5)
return result return result
} }
static var previews: some View { static var previews: some View {
VwrCandidateHorizontal(controller: .init(.horizontal), thePool: thePool).fixedSize() VwrCandidateHorizontal(controller: nil, thePool: thePool).fixedSize()
} }
} }
@available(macOS 12, *) @available(macOS 12, *)
public struct VwrCandidateHorizontal: View { public struct VwrCandidateHorizontal: View {
public var controller: CtlCandidateTDK public weak var controller: CtlCandidateTDK?
@Environment(\.colorScheme) var colorScheme @Environment(\.colorScheme) var colorScheme
@State public var thePool: CandidatePool @State public var thePool: CandidatePool
@State public var tooltip: String = "" @State public var tooltip: String = ""
@ -46,7 +46,7 @@ public struct VwrCandidateHorizontal: View {
} }
private func didSelectCandidateAt(_ pos: Int) { private func didSelectCandidateAt(_ pos: Int) {
if let delegate = controller.delegate { if let delegate = controller?.delegate {
delegate.candidatePairSelected(at: pos) delegate.candidatePairSelected(at: pos)
} }
} }
@ -93,7 +93,7 @@ public struct VwrCandidateHorizontal: View {
} }
.fixedSize(horizontal: false, vertical: true) .fixedSize(horizontal: false, vertical: true)
.padding([.horizontal], 5).padding([.top], 5).padding([.bottom], -1) .padding([.horizontal], 5).padding([.top], 5).padding([.bottom], -1)
if controller.delegate?.showReverseLookupResult ?? true { if controller?.delegate?.showReverseLookupResult ?? true {
ZStack(alignment: .leading) { ZStack(alignment: .leading) {
Color(white: colorScheme == .dark ? 0.15 : 0.97) Color(white: colorScheme == .dark ? 0.15 : 0.97)
HStack(alignment: .center, spacing: 4) { HStack(alignment: .center, spacing: 4) {

View File

@ -21,20 +21,20 @@ struct CandidatePoolViewUIVertical_Previews: PreviewProvider {
"", "", "", "", "", "", "", "", "", "", "", "",
] ]
static var thePool: CandidatePool { 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) result.highlight(at: 5)
return result return result
} }
static var previews: some View { static var previews: some View {
VwrCandidateVertical(controller: .init(.horizontal), thePool: thePool).fixedSize() VwrCandidateVertical(controller: nil, thePool: thePool).fixedSize()
} }
} }
@available(macOS 12, *) @available(macOS 12, *)
public struct VwrCandidateVertical: View { public struct VwrCandidateVertical: View {
public var controller: CtlCandidateTDK public weak var controller: CtlCandidateTDK?
@Environment(\.colorScheme) var colorScheme @Environment(\.colorScheme) var colorScheme
@State public var thePool: CandidatePool @State public var thePool: CandidatePool
@State public var tooltip: String = "" @State public var tooltip: String = ""
@ -45,7 +45,7 @@ public struct VwrCandidateVertical: View {
} }
private func didSelectCandidateAt(_ pos: Int) { private func didSelectCandidateAt(_ pos: Int) {
if let delegate = controller.delegate { if let delegate = controller?.delegate {
delegate.candidatePairSelected(at: pos) delegate.candidatePairSelected(at: pos)
} }
} }
@ -100,7 +100,7 @@ public struct VwrCandidateVertical: View {
} }
} }
.fixedSize(horizontal: true, vertical: false).padding(5) .fixedSize(horizontal: true, vertical: false).padding(5)
if controller.delegate?.showReverseLookupResult ?? true { if controller?.delegate?.showReverseLookupResult ?? true {
ZStack(alignment: .leading) { ZStack(alignment: .leading) {
Color(white: colorScheme == .dark ? 0.15 : 0.97) Color(white: colorScheme == .dark ? 0.15 : 0.97)
HStack(alignment: .center, spacing: 4) { HStack(alignment: .center, spacing: 4) {

View File

@ -23,20 +23,20 @@ struct CandidatePoolViewUIHorizontalBackports_Previews: PreviewProvider {
"", "", "", "", "", "", "", "", "", "", "", "",
] ]
static var thePool: CandidatePool { static var thePool: CandidatePool {
let result = CandidatePool(candidates: testCandidates, rowCapacity: 6) var result = CandidatePool(candidates: testCandidates, rowCapacity: 6)
// 使 // 使
result.highlight(at: 5) result.highlight(at: 5)
return result return result
} }
static var previews: some View { static var previews: some View {
VwrCandidateHorizontalBackports(controller: .init(.horizontal), thePool: thePool).fixedSize() VwrCandidateHorizontalBackports(controller: nil, thePool: thePool).fixedSize()
} }
} }
@available(macOS 10.15, *) @available(macOS 10.15, *)
public struct VwrCandidateHorizontalBackports: View { public struct VwrCandidateHorizontalBackports: View {
public var controller: CtlCandidateTDK public weak var controller: CtlCandidateTDK?
@Environment(\.colorScheme) var colorScheme @Environment(\.colorScheme) var colorScheme
@State public var thePool: CandidatePool @State public var thePool: CandidatePool
@State public var tooltip: String = "" @State public var tooltip: String = ""
@ -47,7 +47,7 @@ public struct VwrCandidateHorizontalBackports: View {
} }
private func didSelectCandidateAt(_ pos: Int) { private func didSelectCandidateAt(_ pos: Int) {
if let delegate = controller.delegate { if let delegate = controller?.delegate {
delegate.candidatePairSelected(at: pos) delegate.candidatePairSelected(at: pos)
} }
} }
@ -94,7 +94,7 @@ public struct VwrCandidateHorizontalBackports: View {
} }
.fixedSize(horizontal: false, vertical: true) .fixedSize(horizontal: false, vertical: true)
.padding([.horizontal], 5).padding([.top], 5).padding([.bottom], -1) .padding([.horizontal], 5).padding([.top], 5).padding([.bottom], -1)
if controller.delegate?.showReverseLookupResult ?? true { if controller?.delegate?.showReverseLookupResult ?? true {
ZStack(alignment: .leading) { ZStack(alignment: .leading) {
Color(white: colorScheme == .dark ? 0.15 : 0.97) Color(white: colorScheme == .dark ? 0.15 : 0.97)
HStack(alignment: .center, spacing: 4) { HStack(alignment: .center, spacing: 4) {
@ -116,7 +116,7 @@ public struct VwrCandidateHorizontalBackports: View {
Color(white: colorScheme == .dark ? 0.2 : 0.9) Color(white: colorScheme == .dark ? 0.2 : 0.9)
} else { } else {
Color(white: colorScheme == .dark ? 0.0 : 1) Color(white: colorScheme == .dark ? 0.0 : 1)
controller.highlightedColorUIBackports controller?.highlightedColorUIBackports
} }
HStack(alignment: .center) { HStack(alignment: .center) {
if !tooltip.isEmpty { if !tooltip.isEmpty {

View File

@ -22,20 +22,20 @@ struct CandidatePoolViewUIVerticalBackports_Previews: PreviewProvider {
"", "", "", "", "", "", "", "", "", "", "", "",
] ]
static var thePool: CandidatePool { 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) result.highlight(at: 5)
return result return result
} }
static var previews: some View { static var previews: some View {
VwrCandidateVerticalBackports(controller: .init(.horizontal), thePool: thePool).fixedSize() VwrCandidateVerticalBackports(controller: nil, thePool: thePool).fixedSize()
} }
} }
@available(macOS 10.15, *) @available(macOS 10.15, *)
public struct VwrCandidateVerticalBackports: View { public struct VwrCandidateVerticalBackports: View {
public var controller: CtlCandidateTDK public weak var controller: CtlCandidateTDK?
@Environment(\.colorScheme) var colorScheme @Environment(\.colorScheme) var colorScheme
@State public var thePool: CandidatePool @State public var thePool: CandidatePool
@State public var tooltip: String = "" @State public var tooltip: String = ""
@ -46,7 +46,7 @@ public struct VwrCandidateVerticalBackports: View {
} }
private func didSelectCandidateAt(_ pos: Int) { private func didSelectCandidateAt(_ pos: Int) {
if let delegate = controller.delegate { if let delegate = controller?.delegate {
delegate.candidatePairSelected(at: pos) delegate.candidatePairSelected(at: pos)
} }
} }
@ -101,7 +101,7 @@ public struct VwrCandidateVerticalBackports: View {
} }
} }
.fixedSize(horizontal: true, vertical: false).padding(5) .fixedSize(horizontal: true, vertical: false).padding(5)
if controller.delegate?.showReverseLookupResult ?? true { if controller?.delegate?.showReverseLookupResult ?? true {
ZStack(alignment: .leading) { ZStack(alignment: .leading) {
Color(white: colorScheme == .dark ? 0.15 : 0.97) Color(white: colorScheme == .dark ? 0.15 : 0.97)
HStack(alignment: .center, spacing: 4) { HStack(alignment: .center, spacing: 4) {
@ -123,7 +123,7 @@ public struct VwrCandidateVerticalBackports: View {
Color(white: colorScheme == .dark ? 0.2 : 0.9) Color(white: colorScheme == .dark ? 0.2 : 0.9)
} else { } else {
Color(white: colorScheme == .dark ? 0.0 : 1) Color(white: colorScheme == .dark ? 0.0 : 1)
controller.highlightedColorUIBackports controller?.highlightedColorUIBackports
} }
HStack(alignment: .center) { HStack(alignment: .center) {
if !tooltip.isEmpty { if !tooltip.isEmpty {