Repo // Utilizing NSAttributedString.boundingDimension.
This commit is contained in:
parent
7d4e7ae551
commit
d3454ccd56
|
@ -12,11 +12,15 @@ let package = Package(
|
||||||
targets: ["NSAttributedTextView"]
|
targets: ["NSAttributedTextView"]
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
dependencies: [],
|
dependencies: [
|
||||||
|
.package(path: "../vChewing_CocoaExtension"),
|
||||||
|
],
|
||||||
targets: [
|
targets: [
|
||||||
.target(
|
.target(
|
||||||
name: "NSAttributedTextView",
|
name: "NSAttributedTextView",
|
||||||
dependencies: []
|
dependencies: [
|
||||||
|
.product(name: "CocoaExtension", package: "vChewing_CocoaExtension"),
|
||||||
|
]
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
// Modified by The vChewing Project in order to use it with AppKit.
|
// Modified by The vChewing Project in order to use it with AppKit.
|
||||||
|
|
||||||
import Cocoa
|
import Cocoa
|
||||||
|
import CocoaExtension
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
@available(macOS 10.15, *)
|
@available(macOS 10.15, *)
|
||||||
|
@ -107,20 +108,14 @@ public class NSAttributedTextView: NSView {
|
||||||
default: return attributedStringValue(areaCalculation: true)
|
default: return attributedStringValue(areaCalculation: true)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
var rect = attrString.boundingRect(
|
var textWH = attrString.boundingDimension
|
||||||
with: NSSize(width: 1600.0, height: 1600.0),
|
|
||||||
options: [.usesLineFragmentOrigin, .usesFontLeading, .usesDeviceMetrics]
|
|
||||||
)
|
|
||||||
rect.size.height *= 1.03
|
|
||||||
rect.size.height = max(rect.size.height, NSFont.systemFontSize * 1.1)
|
|
||||||
rect.size.height = ceil(rect.size.height)
|
|
||||||
rect.size.width *= 1.03
|
|
||||||
rect.size.width = max(rect.size.width, NSFont.systemFontSize * 1.05)
|
|
||||||
rect.size.width = ceil(rect.size.width)
|
|
||||||
if direction != .horizontal {
|
if direction != .horizontal {
|
||||||
rect = .init(x: rect.minX, y: rect.minY, width: rect.height, height: rect.width)
|
textWH.height *= 1.03
|
||||||
|
textWH.height = max(textWH.height, NSFont.systemFontSize * 1.1)
|
||||||
|
textWH.height = ceil(textWH.height)
|
||||||
|
textWH = .init(width: textWH.height, height: textWH.width)
|
||||||
}
|
}
|
||||||
return rect
|
return .init(origin: .zero, size: textWH)
|
||||||
}
|
}
|
||||||
|
|
||||||
override public func draw(_ rect: CGRect) {
|
override public func draw(_ rect: CGRect) {
|
||||||
|
|
|
@ -58,11 +58,7 @@ public class CandidateCellData: Hashable {
|
||||||
|
|
||||||
public var cellLength: Int {
|
public var cellLength: Int {
|
||||||
if displayedText.count <= 2 { return Int(ceil(size * 3)) }
|
if displayedText.count <= 2 { return Int(ceil(size * 3)) }
|
||||||
let rect = attributedStringForLengthCalculation.boundingRect(
|
return Int(ceil(attributedStringForLengthCalculation.boundingDimension.width))
|
||||||
with: NSSize(width: 1600.0, height: 1600.0), options: [.usesLineFragmentOrigin]
|
|
||||||
)
|
|
||||||
let rawResult = ceil(rect.width)
|
|
||||||
return Int(rawResult)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public var attributedStringHeader: NSAttributedString {
|
public var attributedStringHeader: NSAttributedString {
|
||||||
|
|
|
@ -12,11 +12,15 @@ let package = Package(
|
||||||
targets: ["NotifierUI"]
|
targets: ["NotifierUI"]
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
dependencies: [],
|
dependencies: [
|
||||||
|
.package(path: "../vChewing_CocoaExtension"),
|
||||||
|
],
|
||||||
targets: [
|
targets: [
|
||||||
.target(
|
.target(
|
||||||
name: "NotifierUI",
|
name: "NotifierUI",
|
||||||
dependencies: []
|
dependencies: [
|
||||||
|
.product(name: "CocoaExtension", package: "vChewing_CocoaExtension"),
|
||||||
|
]
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
// requirements defined in MIT License.
|
// requirements defined in MIT License.
|
||||||
|
|
||||||
import Cocoa
|
import Cocoa
|
||||||
|
import CocoaExtension
|
||||||
|
|
||||||
public class Notifier: NSWindowController {
|
public class Notifier: NSWindowController {
|
||||||
public static func notify(message: String) {
|
public static func notify(message: String) {
|
||||||
|
@ -78,10 +79,8 @@ public class Notifier: NSWindowController {
|
||||||
let attrStringAlt = NSMutableAttributedString(string: additionalString, attributes: attrAlt)
|
let attrStringAlt = NSMutableAttributedString(string: additionalString, attributes: attrAlt)
|
||||||
attrString.insert(attrStringAlt, at: attrString.length)
|
attrString.insert(attrStringAlt, at: attrString.length)
|
||||||
|
|
||||||
let textRect: NSRect = attrString.boundingRect(
|
let textWH = attrString.boundingDimension
|
||||||
with: NSSize(width: 1600.0, height: 1600.0), options: [.usesLineFragmentOrigin]
|
let windowWidth = Double(4) * kLargeFontSize + textWH.width
|
||||||
)
|
|
||||||
let windowWidth = Double(4) * kLargeFontSize + textRect.width
|
|
||||||
let contentRect = NSRect(x: 0, y: 0, width: windowWidth, height: 60.0)
|
let contentRect = NSRect(x: 0, y: 0, width: windowWidth, height: 60.0)
|
||||||
var windowRect = contentRect
|
var windowRect = contentRect
|
||||||
windowRect.origin.x = screenRect.maxX - windowRect.width - 10
|
windowRect.origin.x = screenRect.maxX - windowRect.width - 10
|
||||||
|
@ -123,8 +122,8 @@ public class Notifier: NSWindowController {
|
||||||
theWindow.contentView?.addSubview(lblMessage)
|
theWindow.contentView?.addSubview(lblMessage)
|
||||||
|
|
||||||
let x = lblMessage.frame.origin.x
|
let x = lblMessage.frame.origin.x
|
||||||
let y = ((theWindow.frame.height) - textRect.height) / 1.9
|
let y = ((theWindow.frame.height) - textWH.height) / 1.9
|
||||||
let newFrame = NSRect(x: x, y: y, width: theWindow.frame.width, height: textRect.height)
|
let newFrame = NSRect(x: x, y: y, width: theWindow.frame.width, height: textWH.height)
|
||||||
lblMessage.frame = newFrame
|
lblMessage.frame = newFrame
|
||||||
|
|
||||||
super.init(window: theWindow)
|
super.init(window: theWindow)
|
||||||
|
|
|
@ -164,13 +164,10 @@ public class PopupCompositionBuffer: NSWindowController {
|
||||||
|
|
||||||
private func adjustSize() {
|
private func adjustSize() {
|
||||||
let attrString = messageTextField.attributedStringValue
|
let attrString = messageTextField.attributedStringValue
|
||||||
var rect = attrString.boundingRect(
|
var rect = NSRect(origin: .zero, size: attrString.boundingDimension)
|
||||||
with: NSSize(width: 1600.0, height: 1600.0),
|
|
||||||
options: [.usesLineFragmentOrigin, .usesFontLeading]
|
|
||||||
)
|
|
||||||
rect.size.width = max(rect.size.width, 20 * Double(attrString.string.count)) + 2
|
|
||||||
rect.size.height *= 1.2
|
rect.size.height *= 1.2
|
||||||
rect.size.height = max(22, rect.size.height)
|
rect.size.height = max(22, rect.size.height)
|
||||||
|
rect.size.width = max(rect.size.width, 20 * Double(attrString.string.count)) + 2
|
||||||
if isTypingDirectionVertical {
|
if isTypingDirectionVertical {
|
||||||
rect = .init(x: rect.minX, y: rect.minY, width: rect.height, height: rect.width)
|
rect = .init(x: rect.minX, y: rect.minY, width: rect.height, height: rect.width)
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,7 +119,7 @@ public class InputHandler: InputHandlerProtocol {
|
||||||
|
|
||||||
var isHaninKeyboardSymbolMode = false
|
var isHaninKeyboardSymbolMode = false
|
||||||
|
|
||||||
static let tooltipHaninKeyboardSymbolMode: String = "\("Hanin Keyboard Symbol Input.".localized) "
|
static let tooltipHaninKeyboardSymbolMode: String = "\("Hanin Keyboard Symbol Input.".localized)"
|
||||||
|
|
||||||
// MARK: - Codepoint Input Buffer.
|
// MARK: - Codepoint Input Buffer.
|
||||||
|
|
||||||
|
@ -134,12 +134,13 @@ public class InputHandler: InputHandlerProtocol {
|
||||||
var tooltipCodePointInputMode: String {
|
var tooltipCodePointInputMode: String {
|
||||||
let commonTerm = NSMutableString()
|
let commonTerm = NSMutableString()
|
||||||
commonTerm.insert("Code Point Input.".localized, at: 0)
|
commonTerm.insert("Code Point Input.".localized, at: 0)
|
||||||
switch IMEApp.currentInputMode {
|
if !(delegate?.isVerticalTyping ?? false) {
|
||||||
case .imeModeCHS: commonTerm.insert("[GB] ", at: 0)
|
switch IMEApp.currentInputMode {
|
||||||
case .imeModeCHT: commonTerm.insert("[Big5] ", at: 0)
|
case .imeModeCHS: commonTerm.insert("[GB] ", at: 0)
|
||||||
default: break
|
case .imeModeCHT: commonTerm.insert("[Big5] ", at: 0)
|
||||||
|
default: break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
commonTerm.append(" ")
|
|
||||||
return commonTerm.description
|
return commonTerm.description
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -204,7 +204,7 @@ extension InputHandler {
|
||||||
if calligrapher.isEmpty, isWildcardKeyInput {
|
if calligrapher.isEmpty, isWildcardKeyInput {
|
||||||
delegate.callError("3606B9C0")
|
delegate.callError("3606B9C0")
|
||||||
var newEmptyState = compositor.isEmpty ? IMEState.ofEmpty() : generateStateOfInputting()
|
var newEmptyState = compositor.isEmpty ? IMEState.ofEmpty() : generateStateOfInputting()
|
||||||
newEmptyState.tooltip = NSLocalizedString("Wildcard key cannot be the initial key.", comment: "") + " "
|
newEmptyState.tooltip = NSLocalizedString("Wildcard key cannot be the initial key.", comment: "")
|
||||||
newEmptyState.data.tooltipColorState = .redAlert
|
newEmptyState.data.tooltipColorState = .redAlert
|
||||||
newEmptyState.tooltipDuration = 1.0
|
newEmptyState.tooltipDuration = 1.0
|
||||||
delegate.switchState(newEmptyState)
|
delegate.switchState(newEmptyState)
|
||||||
|
@ -345,7 +345,7 @@ extension InputHandler {
|
||||||
delegate.callError("D220B880:輸入的字碼沒有對應的字元。")
|
delegate.callError("D220B880:輸入的字碼沒有對應的字元。")
|
||||||
var updatedState = IMEState.ofAbortion()
|
var updatedState = IMEState.ofAbortion()
|
||||||
updatedState.tooltipDuration = 0
|
updatedState.tooltipDuration = 0
|
||||||
updatedState.tooltip = "Invalid Code Point.".localized + " "
|
updatedState.tooltip = "Invalid Code Point.".localized
|
||||||
delegate.switchState(updatedState)
|
delegate.switchState(updatedState)
|
||||||
isCodePointInputMode = true
|
isCodePointInputMode = true
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -166,7 +166,7 @@ extension InputHandler {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
var newState = generateStateOfInputting()
|
var newState = generateStateOfInputting()
|
||||||
newState.tooltip = NSLocalizedString(tooltipMessage, comment: "") + " "
|
newState.tooltip = NSLocalizedString(tooltipMessage, comment: "")
|
||||||
newState.data.tooltipColorState = tooltipColorState
|
newState.data.tooltipColorState = tooltipColorState
|
||||||
newState.tooltipDuration = 1.85
|
newState.tooltipDuration = 1.85
|
||||||
delegate.switchState(newState)
|
delegate.switchState(newState)
|
||||||
|
@ -185,7 +185,7 @@ extension InputHandler {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
var newState = generateStateOfInputting()
|
var newState = generateStateOfInputting()
|
||||||
newState.tooltip = NSLocalizedString(tooltipMessage, comment: "") + " "
|
newState.tooltip = NSLocalizedString(tooltipMessage, comment: "")
|
||||||
newState.data.tooltipColorState = .warning
|
newState.data.tooltipColorState = .warning
|
||||||
newState.tooltipDuration = 1.85
|
newState.tooltipDuration = 1.85
|
||||||
delegate.switchState(newState)
|
delegate.switchState(newState)
|
||||||
|
@ -808,7 +808,6 @@ extension InputHandler {
|
||||||
} else {
|
} else {
|
||||||
newTooltip.insert((newIndex + 1).description + " / " + candidates.count.description, at: 0)
|
newTooltip.insert((newIndex + 1).description + " / " + candidates.count.description, at: 0)
|
||||||
}
|
}
|
||||||
newTooltip.append(" ")
|
|
||||||
newState.tooltip = newTooltip.description
|
newState.tooltip = newTooltip.description
|
||||||
vCLog(newState.tooltip)
|
vCLog(newState.tooltip)
|
||||||
newState.tooltipDuration = 0
|
newState.tooltipDuration = 0
|
||||||
|
|
|
@ -233,7 +233,7 @@ extension SessionCtl: CtlCandidateDelegate {
|
||||||
tooltipMessage = succeeded ? "! Succeeded in filtering a candidate." : "⚠︎ Failed from filtering a candidate."
|
tooltipMessage = succeeded ? "! Succeeded in filtering a candidate." : "⚠︎ Failed from filtering a candidate."
|
||||||
}
|
}
|
||||||
if !succeeded { newState.data.tooltipColorState = .redAlert }
|
if !succeeded { newState.data.tooltipColorState = .redAlert }
|
||||||
newState.tooltip = NSLocalizedString(tooltipMessage, comment: "") + " "
|
newState.tooltip = NSLocalizedString(tooltipMessage, comment: "")
|
||||||
switchState(newState)
|
switchState(newState)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,7 +99,7 @@ public extension SessionCtl {
|
||||||
if !LMMgr.currentLM.isCoreLMLoaded {
|
if !LMMgr.currentLM.isCoreLMLoaded {
|
||||||
if (event as InputSignalProtocol).isReservedKey { return false }
|
if (event as InputSignalProtocol).isReservedKey { return false }
|
||||||
var newState: IMEStateProtocol = IMEState.ofEmpty()
|
var newState: IMEStateProtocol = IMEState.ofEmpty()
|
||||||
newState.tooltip = NSLocalizedString("Factory dictionary not loaded yet.", comment: "") + " "
|
newState.tooltip = NSLocalizedString("Factory dictionary not loaded yet.", comment: "")
|
||||||
newState.tooltipDuration = 1.85
|
newState.tooltipDuration = 1.85
|
||||||
newState.data.tooltipColorState = .redAlert
|
newState.data.tooltipColorState = .redAlert
|
||||||
switchState(newState)
|
switchState(newState)
|
||||||
|
|
Loading…
Reference in New Issue