ctlCandidate // Add pageCounter.
This commit is contained in:
parent
cf0c99a06d
commit
ad5263c6e3
|
@ -487,12 +487,18 @@ extension ctlInputMethod {
|
|||
|
||||
ctlCandidateCurrent.delegate = nil
|
||||
|
||||
/// 下面這一段本可直接指定 currentLayout,但這樣的話翻頁按鈕位置無法精準地重新繪製。
|
||||
/// 所以只能重新初期化。壞處就是得在 ctlCandidate() 當中與 SymbolTable 控制有關的地方
|
||||
/// 新增一個空狀態請求、防止縱排與橫排選字窗同時出現。
|
||||
/// layoutCandidateView 在這裡無法起到糾正作用。
|
||||
/// 該問題徹底解決的價值並不大,直接等到 macOS 10.x 全線淘汰之後用 SwiftUI 重寫選字窗吧。
|
||||
|
||||
if isCandidateWindowVertical { // 縱排輸入時強制使用縱排選字窗
|
||||
ctlCandidateCurrent.currentLayout = .vertical
|
||||
ctlCandidateCurrent = .init(.vertical)
|
||||
} else if mgrPrefs.useHorizontalCandidateList {
|
||||
ctlCandidateCurrent.currentLayout = .horizontal
|
||||
ctlCandidateCurrent = .init(.horizontal)
|
||||
} else {
|
||||
ctlCandidateCurrent.currentLayout = .vertical
|
||||
ctlCandidateCurrent = .init(.vertical)
|
||||
}
|
||||
|
||||
// set the attributes for the candidate panel (which uses NSAttributedString)
|
||||
|
@ -667,6 +673,7 @@ extension ctlInputMethod: ctlCandidateDelegate {
|
|||
let node = state.node.children?[index]
|
||||
{
|
||||
if let children = node.children, !children.isEmpty {
|
||||
handle(state: .Empty(), client: client) // 防止縱橫排選字窗同時出現
|
||||
handle(
|
||||
state: .SymbolTable(node: node, isTypingVertical: state.isTypingVertical),
|
||||
client: currentClient
|
||||
|
|
|
@ -33,6 +33,7 @@ private class vwrCandidateUniversal: NSView {
|
|||
var action: Selector?
|
||||
weak var target: AnyObject?
|
||||
var isVerticalLayout: Bool = false
|
||||
var fractionFontSize: CGFloat = 12.0
|
||||
|
||||
private var keyLabels: [String] = []
|
||||
private var displayedCandidates: [String] = []
|
||||
|
@ -135,6 +136,7 @@ private class vwrCandidateUniversal: NSView {
|
|||
let labelFontSize = labelFont.pointSize
|
||||
let candidateFontSize = candidateFont.pointSize
|
||||
let biggestSize = max(labelFontSize, candidateFontSize)
|
||||
fractionFontSize = round(biggestSize * 0.75)
|
||||
keyLabelWidth = ceil(labelFontSize)
|
||||
keyLabelHeight = ceil(labelFontSize * 2)
|
||||
candidateTextHeight = ceil(candidateFontSize * 1.20)
|
||||
|
@ -365,6 +367,7 @@ public class ctlCandidateUniversal: ctlCandidate {
|
|||
private var candidateView: vwrCandidateUniversal
|
||||
private var prevPageButton: NSButton
|
||||
private var nextPageButton: NSButton
|
||||
private var pageCounterLabel: NSTextField
|
||||
private var currentPageIndex: Int = 0
|
||||
override public var currentLayout: Layout {
|
||||
get { candidateView.isVerticalLayout ? .vertical : .horizontal }
|
||||
|
@ -400,10 +403,12 @@ public class ctlCandidateUniversal: ctlCandidate {
|
|||
|
||||
panel.contentView?.addSubview(candidateView)
|
||||
|
||||
// MARK: Add Buttons
|
||||
|
||||
contentRect.size = NSSize(width: 20.0, height: 10.0) // Reduce the button width
|
||||
let buttonAttribute: [NSAttributedString.Key: Any] = [.font: NSFont.systemFont(ofSize: 9.0)]
|
||||
|
||||
nextPageButton = NSButton(frame: contentRect)
|
||||
nextPageButton = .init(frame: contentRect)
|
||||
NSColor.controlBackgroundColor.setFill()
|
||||
NSBezierPath.fill(nextPageButton.bounds)
|
||||
nextPageButton.wantsLayer = true
|
||||
|
@ -416,7 +421,7 @@ public class ctlCandidateUniversal: ctlCandidate {
|
|||
nextPageButton.attributedTitle = NSMutableAttributedString(
|
||||
string: " ", attributes: buttonAttribute
|
||||
) // Next Page Arrow
|
||||
prevPageButton = NSButton(frame: contentRect)
|
||||
prevPageButton = .init(frame: contentRect)
|
||||
NSColor.controlBackgroundColor.setFill()
|
||||
NSBezierPath.fill(prevPageButton.bounds)
|
||||
prevPageButton.wantsLayer = true
|
||||
|
@ -432,6 +437,24 @@ public class ctlCandidateUniversal: ctlCandidate {
|
|||
panel.contentView?.addSubview(nextPageButton)
|
||||
panel.contentView?.addSubview(prevPageButton)
|
||||
|
||||
// MARK: Add Page Counter
|
||||
|
||||
contentRect.size = NSSize(width: 40.0, height: 20.0)
|
||||
pageCounterLabel = .init(frame: contentRect)
|
||||
pageCounterLabel.isEditable = false
|
||||
pageCounterLabel.isSelectable = false
|
||||
pageCounterLabel.isBezeled = false
|
||||
pageCounterLabel.textColor = NSColor(
|
||||
red: 0.86, green: 0.86, blue: 0.86, alpha: 1.00
|
||||
)
|
||||
pageCounterLabel.drawsBackground = true
|
||||
pageCounterLabel.backgroundColor = NSColor(
|
||||
red: 0.18, green: 0.18, blue: 0.18, alpha: 1.00
|
||||
)
|
||||
panel.contentView?.addSubview(pageCounterLabel)
|
||||
|
||||
// MARK: Post-Init()
|
||||
|
||||
super.init(window: panel)
|
||||
currentLayout = layout
|
||||
|
||||
|
@ -443,6 +466,8 @@ public class ctlCandidateUniversal: ctlCandidate {
|
|||
|
||||
prevPageButton.target = self
|
||||
prevPageButton.action = #selector(pageButtonAction(_:))
|
||||
|
||||
pageCounterLabel.font = pageCounterFont
|
||||
}
|
||||
|
||||
@available(*, unavailable)
|
||||
|
@ -529,6 +554,30 @@ extension ctlCandidateUniversal {
|
|||
return totalCount / keyLabelCount + ((totalCount % keyLabelCount) != 0 ? 1 : 0)
|
||||
}
|
||||
|
||||
// 用來顯示頁面計數器的 NSFont。因為結果可 nil,所以最好 guard-let 再用。
|
||||
private var pageCounterFont: NSFont? {
|
||||
var pointSize: CGFloat { candidateView.fractionFontSize }
|
||||
let systemFontDesc = NSFont.systemFont(ofSize: pointSize, weight: .light).fontDescriptor
|
||||
let fractionFontDesc = systemFontDesc.addingAttributes(
|
||||
[
|
||||
NSFontDescriptor.AttributeName.traits: [
|
||||
[
|
||||
NSFontDescriptor.FeatureKey.typeIdentifier: kFractionsType,
|
||||
NSFontDescriptor.FeatureKey.selectorIdentifier: kDiagonalFractionsSelector,
|
||||
]
|
||||
]
|
||||
]
|
||||
)
|
||||
return NSFont(descriptor: fractionFontDesc, size: pointSize) ?? nil
|
||||
}
|
||||
|
||||
// 用來生成拿給頁面計數器用的顯示字串。
|
||||
// TODO: 這衰洨的 pageCount 總是返回空字串,需要調查。
|
||||
private var pageCounterText: String {
|
||||
if pageCount < 2 { return .init() }
|
||||
return "\(currentPageIndex + 1)/"
|
||||
}
|
||||
|
||||
private func layoutCandidateView() {
|
||||
guard let delegate = delegate else {
|
||||
return
|
||||
|
@ -551,23 +600,25 @@ extension ctlCandidateUniversal {
|
|||
var frameRect = candidateView.frame
|
||||
frameRect.size = newSize
|
||||
candidateView.frame = frameRect
|
||||
let counterHeight: CGFloat = newSize.height - 24
|
||||
|
||||
if pageCount > 1, mgrPrefs.showPageButtonsInCandidateWindow {
|
||||
var buttonRect = nextPageButton.frame
|
||||
let spacing: CGFloat = 0.0
|
||||
|
||||
if currentLayout == .horizontal { buttonRect.size.height = floor(newSize.height / 2) }
|
||||
var buttonOriginY = newSize.height - (buttonRect.size.height * 2.0 + spacing)
|
||||
if currentLayout == .horizontal { buttonOriginY /= 2.0 }
|
||||
|
||||
let buttonOriginY: CGFloat = {
|
||||
if currentLayout == .vertical {
|
||||
return counterHeight
|
||||
}
|
||||
return (newSize.height - (buttonRect.size.height * 2.0 + spacing)) / 2.0
|
||||
}()
|
||||
buttonRect.origin = NSPoint(x: newSize.width, y: buttonOriginY)
|
||||
nextPageButton.frame = buttonRect
|
||||
|
||||
buttonRect.origin = NSPoint(
|
||||
x: newSize.width, y: buttonOriginY + buttonRect.size.height + spacing
|
||||
)
|
||||
prevPageButton.frame = buttonRect
|
||||
|
||||
newSize.width += 20
|
||||
nextPageButton.isHidden = false
|
||||
prevPageButton.isHidden = false
|
||||
|
@ -576,6 +627,36 @@ extension ctlCandidateUniversal {
|
|||
prevPageButton.isHidden = true
|
||||
}
|
||||
|
||||
if !pageCounterText.isEmpty {
|
||||
let attrString = NSAttributedString(
|
||||
string: pageCounterText.appending(String(pageCount)),
|
||||
attributes: [
|
||||
.font: pageCounterFont as AnyObject
|
||||
]
|
||||
)
|
||||
pageCounterLabel.attributedStringValue = attrString
|
||||
var rect = attrString.boundingRect(
|
||||
with: NSSize(width: 1600.0, height: 1600.0),
|
||||
options: .usesLineFragmentOrigin
|
||||
)
|
||||
|
||||
rect.size.height += 3
|
||||
let rectOriginY: CGFloat =
|
||||
(currentLayout == .horizontal)
|
||||
? (newSize.height - rect.height) / 2
|
||||
: counterHeight
|
||||
let rectOriginX: CGFloat =
|
||||
mgrPrefs.showPageButtonsInCandidateWindow
|
||||
? newSize.width
|
||||
: newSize.width + 4
|
||||
rect.origin = NSPoint(x: rectOriginX, y: rectOriginY)
|
||||
pageCounterLabel.frame = rect
|
||||
newSize.width += rect.width + 4
|
||||
pageCounterLabel.isHidden = false
|
||||
} else {
|
||||
pageCounterLabel.isHidden = true
|
||||
}
|
||||
|
||||
frameRect = window?.frame ?? NSRect.zero
|
||||
|
||||
let topLeftPoint = NSPoint(x: frameRect.origin.x, y: frameRect.origin.y + frameRect.size.height)
|
||||
|
|
Loading…
Reference in New Issue