vChewing-macOS/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/CandidateCellData.swift

226 lines
8.7 KiB
Swift
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// (c) 2022 and onwards The vChewing Project (MIT-NTL License).
// ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT)
// ... with NTL restriction stating that:
// No trademark license is granted to use the trade names, trademarks, service
// marks, or product names of Contributor, except as required to fulfill notice
// requirements defined in MIT License.
import Cocoa
import Shared
import SwiftUI
import SwiftUIBackports
// MARK: - Classes used by Candidate Window
/// class 便
public class CandidateCellData: Hashable {
public var locale = ""
public static var unifiedSize: Double = 16
public static var highlightBackground: NSColor = {
if #available(macOS 10.14, *) {
return .selectedContentBackgroundColor
}
return NSColor.alternateSelectedControlColor
}()
public var key: String
public var displayedText: String
public var size: Double { Self.unifiedSize }
public var isSelected: Bool = false
public var whichRow: Int = 0 //
public var whichColumn: Int = 0 //
public var index: Int = 0
public var subIndex: Int = 0
public var fontSizeCandidate: Double { CandidateCellData.unifiedSize }
public var fontSizeKey: Double { max(ceil(CandidateCellData.unifiedSize * 0.6), 11) }
public var fontColorKey: NSColor {
isSelected ? .selectedMenuItemTextColor.withAlphaComponent(0.8) : .secondaryLabelColor
}
public var fontColorCandidate: NSColor { isSelected ? .selectedMenuItemTextColor : .labelColor }
public init(key: String, displayedText: String, isSelected: Bool = false) {
self.key = key
self.displayedText = displayedText
self.isSelected = isSelected
}
public static func == (lhs: CandidateCellData, rhs: CandidateCellData) -> Bool {
lhs.key == rhs.key && lhs.displayedText == rhs.displayedText
}
public func hash(into hasher: inout Hasher) {
hasher.combine(key)
hasher.combine(displayedText)
}
public var cellLength: Int {
if displayedText.count <= 2 { return Int(ceil(size * 3)) }
let rect = attributedStringForLengthCalculation.boundingRect(
with: NSSize(width: 1600.0, height: 1600.0), options: [.usesLineFragmentOrigin]
)
let rawResult = ceil(rect.width)
return Int(rawResult)
}
public var attributedStringHeader: NSAttributedString {
let paraStyleKey = NSMutableParagraphStyle()
paraStyleKey.setParagraphStyle(NSParagraphStyle.default)
paraStyleKey.alignment = .natural
let paraStyle = NSMutableParagraphStyle()
paraStyle.setParagraphStyle(NSParagraphStyle.default)
paraStyle.alignment = .natural
let theFontForCandidateKey: NSFont = {
if #available(macOS 10.15, *) {
return NSFont.monospacedSystemFont(ofSize: fontSizeKey, weight: .regular)
}
return NSFont.monospacedDigitSystemFont(ofSize: fontSizeKey, weight: .regular)
}()
var attrKey: [NSAttributedString.Key: AnyObject] = [
.font: theFontForCandidateKey,
.paragraphStyle: paraStyleKey,
]
if isSelected {
attrKey[.foregroundColor] = NSColor.white.withAlphaComponent(0.8)
} else {
attrKey[.foregroundColor] = NSColor.secondaryLabelColor
}
let attrStrKey = NSMutableAttributedString(string: key, attributes: attrKey)
return attrStrKey
}
public var attributedStringForLengthCalculation: NSAttributedString {
let paraStyleKey = NSMutableParagraphStyle()
paraStyleKey.setParagraphStyle(NSParagraphStyle.default)
paraStyleKey.alignment = .natural
let paraStyle = NSMutableParagraphStyle()
paraStyle.setParagraphStyle(NSParagraphStyle.default)
paraStyle.alignment = .natural
paraStyle.lineBreakMode = .byWordWrapping
let attrCandidate: [NSAttributedString.Key: AnyObject] = [
.font: NSFont.monospacedDigitSystemFont(ofSize: size, weight: .regular),
.paragraphStyle: paraStyle,
]
let attrStrCandidate = NSMutableAttributedString(string: displayedText + " ", attributes: attrCandidate)
return attrStrCandidate
}
public var attributedString: NSAttributedString {
let paraStyleKey = NSMutableParagraphStyle()
paraStyleKey.setParagraphStyle(NSParagraphStyle.default)
paraStyleKey.alignment = .natural
let paraStyle = NSMutableParagraphStyle()
paraStyle.setParagraphStyle(NSParagraphStyle.default)
paraStyle.alignment = .natural
paraStyle.lineBreakMode = .byWordWrapping
var attrCandidate: [NSAttributedString.Key: AnyObject] = [
.font: NSFont.monospacedDigitSystemFont(ofSize: size, weight: .regular),
.paragraphStyle: paraStyle,
]
if isSelected {
attrCandidate[.foregroundColor] = NSColor.white
} else {
attrCandidate[.foregroundColor] = NSColor.labelColor
}
if #available(macOS 12, *) {
if UserDefaults.standard.bool(forKey: UserDef.kHandleDefaultCandidateFontsByLangIdentifier.rawValue) {
attrCandidate[.languageIdentifier] = self.locale as AnyObject
}
}
let attrStrCandidate = NSMutableAttributedString(string: displayedText, attributes: attrCandidate)
return attrStrCandidate
}
public var charDescriptions: String {
var result = displayedText
if displayedText.contains("("), displayedText.count > 2 {
result = displayedText.replacingOccurrences(of: "(", with: "").replacingOccurrences(of: ")", with: "")
}
return result.charDescriptions.joined(separator: "\n")
}
public var minWidthToDrawInSwiftUI: Double {
Double(cellLength) + ((displayedText.count > 2) ? 0 : fontSizeKey + 0) + ceil(fontSizeCandidate * 0.4)
}
}
// MARK: - Contents specifically made for macOS 12 and newer.
@available(macOS 12, *)
public extension CandidateCellData {
var attributedStringForSwiftUI: some View {
var result: some View {
ZStack(alignment: .leading) {
if isSelected {
Color(nsColor: CandidateCellData.highlightBackground).ignoresSafeArea().cornerRadius(6)
}
VStack(spacing: 0) {
HStack(spacing: 4) {
if UserDefaults.standard.bool(forKey: UserDef.kHandleDefaultCandidateFontsByLangIdentifier.rawValue) {
Text(AttributedString(attributedStringHeader))
Text(AttributedString(attributedString))
} else {
Text(verbatim: key).font(.system(size: fontSizeKey).monospaced())
.foregroundColor(.init(nsColor: fontColorKey)).lineLimit(1)
Text(verbatim: displayedText)
.font(.init(CTFontCreateUIFontForLanguage(.system, fontSizeCandidate, locale as CFString)!))
.foregroundColor(.init(nsColor: fontColorCandidate)).lineLimit(1)
}
}.padding(3)
}.frame(minWidth: minWidthToDrawInSwiftUI, alignment: .leading)
}.fixedSize(horizontal: false, vertical: true)
}
return result
}
}
// MARK: - Contents specifically made for macOS 10.15 and macOS 11.
@available(macOS 10.15, *)
public extension CandidateCellData {
var themeColorBackports: some View {
//
let result: Color = {
switch locale {
case "zh-Hans": return Color.red
case "zh-Hant": return Color.blue
case "ja": return Color.pink
default: return Color.accentColor
}
}()
return result.opacity(0.85)
}
var attributedStringForSwiftUIBackports: some View {
var result: some View {
ZStack(alignment: .leading) {
if isSelected {
themeColorBackports.cornerRadius(6)
VStack(spacing: 0) {
HStack(spacing: 4) {
Text(verbatim: key).font(.custom("Menlo", size: fontSizeKey))
.foregroundColor(Color.white.opacity(0.8)).lineLimit(1)
Text(verbatim: displayedText)
.font(.init(CTFontCreateUIFontForLanguage(.system, fontSizeCandidate, locale as CFString)!))
.foregroundColor(Color(white: 1)).lineLimit(1)
}.padding(3).foregroundColor(Color(white: 0.9))
}.frame(minWidth: minWidthToDrawInSwiftUI, alignment: .leading)
} else {
VStack(spacing: 0) {
HStack(spacing: 4) {
Text(verbatim: key).font(.custom("Menlo", size: fontSizeKey))
.foregroundColor(Color.secondary).lineLimit(1)
Text(verbatim: displayedText)
.font(.init(CTFontCreateUIFontForLanguage(.system, fontSizeCandidate, locale as CFString)!))
.foregroundColor(Color.primary).lineLimit(1)
}.padding(3).foregroundColor(Color(white: 0.9))
}.frame(minWidth: minWidthToDrawInSwiftUI, alignment: .leading)
}
}.fixedSize(horizontal: false, vertical: true)
}
return result
}
}