Repo // Add NSAttributedTextView.
This commit is contained in:
parent
87ac82f242
commit
599c576fc9
|
@ -0,0 +1,116 @@
|
|||
// (c) 2021 and onwards Fuziki (MIT License).
|
||||
// ====================
|
||||
// This code is released under the MIT license (SPDX-License-Identifier: MIT)
|
||||
|
||||
// Ref: https://qiita.com/fuziki/items/b31055a69330a3ce55a5
|
||||
// Modified by The vChewing Project in order to use it with AppKit.
|
||||
|
||||
import Cocoa
|
||||
import SwiftUI
|
||||
|
||||
@available(macOS 10.15, *)
|
||||
public struct VText: NSViewRepresentable {
|
||||
public var text: String?
|
||||
|
||||
public func makeNSView(context _: Context) -> NSAttributedTextView {
|
||||
let nsView = NSAttributedTextView()
|
||||
nsView.direction = .vertical
|
||||
nsView.text = text
|
||||
return nsView
|
||||
}
|
||||
|
||||
public func updateNSView(_ nsView: NSAttributedTextView, context _: Context) {
|
||||
nsView.text = text
|
||||
}
|
||||
}
|
||||
|
||||
@available(macOS 10.15, *)
|
||||
public struct HText: NSViewRepresentable {
|
||||
public var text: String?
|
||||
|
||||
public func makeNSView(context _: Context) -> NSAttributedTextView {
|
||||
let nsView = NSAttributedTextView()
|
||||
nsView.direction = .horizontal
|
||||
nsView.text = text
|
||||
return nsView
|
||||
}
|
||||
|
||||
public func updateNSView(_ nsView: NSAttributedTextView, context _: Context) {
|
||||
nsView.text = text
|
||||
}
|
||||
}
|
||||
|
||||
public class NSAttributedTextView: NSView {
|
||||
public enum writingDirection: String {
|
||||
case horizontal
|
||||
case vertical
|
||||
case verticalReversed
|
||||
}
|
||||
|
||||
public var direction: writingDirection = .horizontal
|
||||
public var fontSize: CGFloat = NSFont.systemFontSize {
|
||||
didSet {
|
||||
attributes[.font] = NSFont.systemFont(ofSize: fontSize)
|
||||
}
|
||||
}
|
||||
|
||||
public var textColor: NSColor = .textColor {
|
||||
didSet {
|
||||
attributes[.foregroundColor] = textColor
|
||||
}
|
||||
}
|
||||
|
||||
public var attributedStringValue: NSAttributedString {
|
||||
var newAttributes = attributes
|
||||
let isVertical: Bool = !(direction == .horizontal)
|
||||
newAttributes[.verticalGlyphForm] = isVertical
|
||||
let lineHeight: CGFloat = isVertical ? fontSize * 0.8 : fontSize * 1.3
|
||||
let newStyle: NSMutableParagraphStyle = newAttributes[.paragraphStyle] as! NSMutableParagraphStyle
|
||||
newStyle.maximumLineHeight = lineHeight
|
||||
newStyle.minimumLineHeight = lineHeight
|
||||
newAttributes[.paragraphStyle] = newStyle
|
||||
let attributedText = NSMutableAttributedString(string: text ?? "", attributes: newAttributes)
|
||||
return attributedText
|
||||
}
|
||||
|
||||
public var backgroundColor: NSColor = .controlBackgroundColor
|
||||
|
||||
public var attributes: [NSAttributedString.Key: Any] = [
|
||||
.verticalGlyphForm: true,
|
||||
.font: NSFont.systemFont(ofSize: NSFont.systemFontSize),
|
||||
.foregroundColor: NSColor.textColor,
|
||||
.paragraphStyle: {
|
||||
let paragraphStyle = NSMutableParagraphStyle()
|
||||
paragraphStyle.alignment = .left
|
||||
return paragraphStyle
|
||||
}(),
|
||||
]
|
||||
public var text: String? { didSet { ctFrame = nil } }
|
||||
private var ctFrame: CTFrame?
|
||||
private(set) var currentRect: NSRect?
|
||||
|
||||
override public func draw(_ rect: CGRect) {
|
||||
let context = NSGraphicsContext.current?.cgContext
|
||||
guard let context = context else { return }
|
||||
let setter = CTFramesetterCreateWithAttributedString(attributedStringValue)
|
||||
let path = CGPath(rect: rect, transform: nil)
|
||||
let theCTFrameProgression: CTFrameProgression = {
|
||||
switch direction {
|
||||
case .horizontal: return CTFrameProgression.topToBottom
|
||||
case .vertical: return CTFrameProgression.rightToLeft
|
||||
case .verticalReversed: return CTFrameProgression.leftToRight
|
||||
}
|
||||
}()
|
||||
let frameAttrs: CFDictionary =
|
||||
[
|
||||
kCTFrameProgressionAttributeName: theCTFrameProgression.rawValue
|
||||
] as CFDictionary
|
||||
let newFrame = CTFramesetterCreateFrame(setter, CFRangeMake(0, 0), path, frameAttrs)
|
||||
ctFrame = newFrame
|
||||
backgroundColor.setFill()
|
||||
let bgPath: NSBezierPath = .init(roundedRect: rect, xRadius: 0, yRadius: 0)
|
||||
bgPath.fill()
|
||||
currentRect = rect
|
||||
CTFrameDraw(newFrame, context)
|
||||
}
|
||||
}
|
|
@ -32,6 +32,7 @@
|
|||
5B54E743283A7D89001ECBDC /* lmCoreNS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B54E742283A7D89001ECBDC /* lmCoreNS.swift */; };
|
||||
5B5948CE289CC04500C85824 /* LMInstantiator_DateTimeExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B5948CD289CC04500C85824 /* LMInstantiator_DateTimeExtension.swift */; };
|
||||
5B5E535227EF261400C6AA1E /* IME.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B5E535127EF261400C6AA1E /* IME.swift */; };
|
||||
5B5F8AEB28C86AAD007C11F1 /* NSAttributedTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B5F8AEA28C86AAD007C11F1 /* NSAttributedTextView.swift */; };
|
||||
5B62A32927AE77D100A19448 /* FSEventStreamHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B62A32827AE77D100A19448 /* FSEventStreamHelper.swift */; };
|
||||
5B62A33627AE795800A19448 /* mgrPrefs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B62A33527AE795800A19448 /* mgrPrefs.swift */; };
|
||||
5B62A33D27AE7CC100A19448 /* ctlAboutWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B62A33C27AE7CC100A19448 /* ctlAboutWindow.swift */; };
|
||||
|
@ -246,6 +247,7 @@
|
|||
5B54E742283A7D89001ECBDC /* lmCoreNS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = lmCoreNS.swift; sourceTree = "<group>"; };
|
||||
5B5948CD289CC04500C85824 /* LMInstantiator_DateTimeExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LMInstantiator_DateTimeExtension.swift; sourceTree = "<group>"; };
|
||||
5B5E535127EF261400C6AA1E /* IME.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = IME.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
|
||||
5B5F8AEA28C86AAD007C11F1 /* NSAttributedTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSAttributedTextView.swift; sourceTree = "<group>"; };
|
||||
5B62A32827AE77D100A19448 /* FSEventStreamHelper.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = FSEventStreamHelper.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
|
||||
5B62A33527AE795800A19448 /* mgrPrefs.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = mgrPrefs.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
|
||||
5B62A33C27AE7CC100A19448 /* ctlAboutWindow.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = ctlAboutWindow.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
|
||||
|
@ -463,11 +465,20 @@
|
|||
path = SubLMs;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
5B5F8AEC28C86AB3007C11F1 /* NSAttributedTextView */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
5B5F8AEA28C86AAD007C11F1 /* NSAttributedTextView.swift */,
|
||||
);
|
||||
path = NSAttributedTextView;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
5B62A30127AE732800A19448 /* 3rdParty */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
5B84579B2871AD2200C93B01 /* HotenkaChineseConverter */,
|
||||
5B949BD72816DC4400D87B5D /* LineReader */,
|
||||
5B5F8AEC28C86AB3007C11F1 /* NSAttributedTextView */,
|
||||
5BA58644289BCFAC0077D02F /* Qwertyyb */,
|
||||
5B20430528BEE2F300BFC6FD /* Sandbox */,
|
||||
5BA9FCEA27FED652002DE248 /* SindreSorhus */,
|
||||
|
@ -1211,6 +1222,7 @@
|
|||
5B887F302826AEA400B6651E /* lmCoreEX.swift in Sources */,
|
||||
5BA9FD4627FEF3C9002DE248 /* Container.swift in Sources */,
|
||||
5B2170E5289FACAD00BE7304 /* 6_Node.swift in Sources */,
|
||||
5B5F8AEB28C86AAD007C11F1 /* NSAttributedTextView.swift in Sources */,
|
||||
5B949BD92816DC5400D87B5D /* LineReader.swift in Sources */,
|
||||
5BA9FD1027FEDB6B002DE248 /* suiPrefPaneKeyboard.swift in Sources */,
|
||||
5B3133BF280B229700A4A505 /* KeyHandler_States.swift in Sources */,
|
||||
|
|
Loading…
Reference in New Issue