vChewing-macOS/Source/Modules/WindowControllers/CtlRevLookupWindow.swift

167 lines
6.0 KiB
Swift

// (c) 2021 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 AppKit
import LangModelAssembly
import MainAssembly
import Shared
class CtlRevLookupWindow: NSWindowController, NSWindowDelegate {
static var shared: CtlRevLookupWindow?
@objc var observation: NSKeyValueObservation?
static func show() {
if shared == nil { Self.shared = .init(window: FrmRevLookupWindow()) }
guard let shared = Self.shared, let window = shared.window as? FrmRevLookupWindow else { return }
shared.window = window
window.delegate = shared
window.setPosition(vertical: .bottom, horizontal: .right, padding: 20)
window.orderFrontRegardless() //
window.level = .statusBar
shared.showWindow(shared)
NSApp.popup()
}
}
class FrmRevLookupWindow: NSWindow {
public lazy var inputField = NSTextField()
public lazy var resultView = NSTextView()
private lazy var clipView = NSClipView()
private lazy var scrollView = NSScrollView()
private lazy var button = NSButton()
private lazy var view = NSView()
static func reloadData() {
LMMgr.connectCoreDB()
}
init() {
super.init(
contentRect: CGRect(x: 196, y: 240, width: 480, height: 340),
styleMask: [.titled, .closable],
backing: .buffered, defer: true
)
setupUI()
}
private func setupUI() {
contentView = view
allowsToolTipsWhenApplicationIsInactive = false
autorecalculatesKeyViewLoop = false
isReleasedWhenClosed = false
title = "Reverse Lookup (Phonabets)".localized
view.addSubview(inputField)
view.addSubview(scrollView)
view.addSubview(button)
view.wantsLayer = true
button.autoresizingMask = [.maxXMargin, .minYMargin]
button.frame = CGRect(x: 446, y: 319, width: 31, height: 21)
button.setContentHuggingPriority(.defaultHigh, for: .vertical)
button.alignment = .center
button.bezelStyle = .recessed
button.font = NSFont.systemFont(ofSize: 12)
button.imageScaling = .scaleProportionallyDown
button.title = "👓"
button.cell.map { $0 as? NSButtonCell }??.isBordered = true
button.target = self
button.action = #selector(keyboardConfirmed(_:))
button.keyEquivalent = String(utf16CodeUnits: [unichar(NSEvent.SpecialKey.enter.rawValue)], count: 1) as String
scrollView.autoresizingMask = [.maxXMargin, .minYMargin]
scrollView.borderType = .noBorder
scrollView.frame = CGRect(x: 0, y: 0, width: 480, height: 320)
scrollView.hasHorizontalScroller = false
scrollView.horizontalLineScroll = 10
scrollView.horizontalPageScroll = 10
scrollView.verticalLineScroll = 10
scrollView.verticalPageScroll = 10
clipView.documentView = resultView
clipView.autoresizingMask = [.width, .height]
clipView.drawsBackground = false
clipView.frame = CGRect(x: 0, y: 0, width: 480, height: 320)
resultView.autoresizingMask = [.width, .height]
resultView.backgroundColor = NSColor.textBackgroundColor
resultView.frame = CGRect(x: 0, y: 0, width: 480, height: 320)
resultView.importsGraphics = false
resultView.insertionPointColor = NSColor.textColor
resultView.isEditable = false
resultView.isRichText = false
resultView.isVerticallyResizable = true
resultView.maxSize = CGSize(width: 774, height: 10_000_000)
resultView.minSize = CGSize(width: 480, height: 320)
resultView.smartInsertDeleteEnabled = true
resultView.textColor = NSColor.textColor
resultView.wantsLayer = true
resultView.font = NSFont.systemFont(ofSize: 13)
resultView.string = "Maximum 15 results returnable.".localized
scrollView.contentView = clipView
inputField.autoresizingMask = [.maxXMargin, .minYMargin]
inputField.frame = CGRect(x: 0, y: 320, width: 441, height: 20)
inputField.setContentHuggingPriority(.defaultHigh, for: .vertical)
inputField.backgroundColor = NSColor.textBackgroundColor
inputField.drawsBackground = true
inputField.font = NSFont.systemFont(ofSize: 13)
inputField.isBezeled = true
inputField.isEditable = true
inputField.isSelectable = true
inputField.lineBreakMode = .byClipping
inputField.textColor = NSColor.controlTextColor
inputField.cell.map { $0 as? NSTextFieldCell }??.isScrollable = true
inputField.cell.map { $0 as? NSTextFieldCell }??.sendsActionOnEndEditing = true
inputField.cell.map { $0 as? NSTextFieldCell }??.usesSingleLineMode = true
inputField.action = #selector(keyboardConfirmed(_:))
inputField.toolTip =
"Maximum 15 results returnable.".localized
}
@objc func keyboardConfirmed(_: Any?) {
if inputField.stringValue.isEmpty { return }
resultView.string = "\n" + "Loading…".localized
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
self.updateResult(with: self.inputField.stringValue)
}
}
private func updateResult(with input: String) {
guard !input.isEmpty else { return }
button.isEnabled = false
inputField.isEnabled = false
let strBuilder = NSMutableString()
strBuilder.append("\n")
strBuilder.append("Char\tReading(s)\n".localized)
strBuilder.append("==\t====\n")
var i = 0
theLoop: for char in input.map(\.description) {
if i == 15 {
strBuilder.append("Maximum 15 results returnable.".localized + "\n")
break theLoop
}
let arrResult = vChewingLM.LMInstantiator.getFactoryReverseLookupData(with: char)?.deduplicated ?? []
if !arrResult.isEmpty {
strBuilder.append(char + "\t")
strBuilder.append(arrResult.joined(separator: ", "))
strBuilder.append("\n")
i += 1
}
}
resultView.string = strBuilder.description
button.isEnabled = true
inputField.isEnabled = true
}
}