Resolving field resizing crashes.
This commit is contained in:
@@ -10,7 +10,7 @@ import SwiftUI
|
|||||||
|
|
||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
|
|
||||||
class MTLabel : NSTextField {
|
public class MTLabel : NSTextField {
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
super.init(frame: .zero)
|
super.init(frame: .zero)
|
||||||
|
|||||||
@@ -48,27 +48,24 @@ public enum MTTextAlignment : UInt {
|
|||||||
*/
|
*/
|
||||||
@IBDesignable
|
@IBDesignable
|
||||||
public class MTMathUILabel : MTView {
|
public class MTMathUILabel : MTView {
|
||||||
|
|
||||||
private var _mathList:MTMathList?
|
|
||||||
|
|
||||||
/** The `MTMathList` to render. Setting this will remove any
|
/** The `MTMathList` to render. Setting this will remove any
|
||||||
`latex` that has already been set. If `latex` has been set, this will
|
`latex` that has already been set. If `latex` has been set, this will
|
||||||
return the parsed `MTMathList` if the `latex` parses successfully. Use this
|
return the parsed `MTMathList` if the `latex` parses successfully. Use this
|
||||||
setting if the `MTMathList` has been programmatically constructed, otherwise it
|
setting if the `MTMathList` has been programmatically constructed, otherwise it
|
||||||
is preferred to use `latex`.
|
is preferred to use `latex`.
|
||||||
*/
|
*/
|
||||||
var mathList:MTMathList? {
|
public var mathList:MTMathList? {
|
||||||
set {
|
set {
|
||||||
_mathList = newValue
|
_mathList = newValue
|
||||||
error = nil
|
_error = nil
|
||||||
_latex = MTMathListBuilder.mathListToString(newValue)
|
_latex = MTMathListBuilder.mathListToString(newValue)
|
||||||
self.invalidateIntrinsicContentSize()
|
self.invalidateIntrinsicContentSize()
|
||||||
self.setNeedsLayout()
|
self.setNeedsLayout()
|
||||||
}
|
}
|
||||||
get { _mathList }
|
get { _mathList }
|
||||||
}
|
}
|
||||||
|
private var _mathList:MTMathList?
|
||||||
private var _latex:String=""
|
|
||||||
|
|
||||||
/** The latex string to be displayed. Setting this will remove any `mathList` that
|
/** The latex string to be displayed. Setting this will remove any `mathList` that
|
||||||
has been set. If latex has not been set, this will return the latex output for the
|
has been set. If latex has not been set, this will return the latex output for the
|
||||||
@@ -78,12 +75,12 @@ public class MTMathUILabel : MTView {
|
|||||||
public var latex:String {
|
public var latex:String {
|
||||||
set {
|
set {
|
||||||
_latex = newValue
|
_latex = newValue
|
||||||
self.error = nil
|
_error = nil
|
||||||
var error : NSError? = nil
|
var error : NSError? = nil
|
||||||
_mathList = MTMathListBuilder.build(fromString: newValue, error: &error)
|
_mathList = MTMathListBuilder.build(fromString: newValue, error: &error)
|
||||||
if error != nil {
|
if error != nil {
|
||||||
_mathList = nil
|
_mathList = nil
|
||||||
self.error = error
|
_error = error
|
||||||
self.errorLabel?.text = error!.localizedDescription
|
self.errorLabel?.text = error!.localizedDescription
|
||||||
self.errorLabel?.frame = self.bounds
|
self.errorLabel?.frame = self.bounds
|
||||||
self.errorLabel?.isHidden = !self.displayErrorInline
|
self.errorLabel?.isHidden = !self.displayErrorInline
|
||||||
@@ -95,84 +92,108 @@ public class MTMathUILabel : MTView {
|
|||||||
}
|
}
|
||||||
get { _latex }
|
get { _latex }
|
||||||
}
|
}
|
||||||
|
private var _latex = ""
|
||||||
|
|
||||||
/** This contains any error that occurred when parsing the latex. */
|
/** This contains any error that occurred when parsing the latex. */
|
||||||
public var error:NSError?
|
public var error:NSError? { _error }
|
||||||
|
private var _error:NSError?
|
||||||
|
|
||||||
/** If true, if there is an error it displays the error message inline. Default true. */
|
/** If true, if there is an error it displays the error message inline. Default true. */
|
||||||
public var displayErrorInline = true
|
public var displayErrorInline = true
|
||||||
|
|
||||||
/** The MTFont to use for rendering. */
|
/** The MTFont to use for rendering. */
|
||||||
var font = MTFontManager.fontManager.defaultFont {
|
public var font:MTFont? {
|
||||||
didSet {
|
set {
|
||||||
|
guard newValue != nil else { return }
|
||||||
|
_font = newValue
|
||||||
self.invalidateIntrinsicContentSize()
|
self.invalidateIntrinsicContentSize()
|
||||||
self.setNeedsLayout()
|
self.setNeedsLayout()
|
||||||
}
|
}
|
||||||
|
get { _font }
|
||||||
}
|
}
|
||||||
|
private var _font:MTFont?
|
||||||
|
|
||||||
/** Convenience method to just set the size of the font without changing the fontface. */
|
/** Convenience method to just set the size of the font without changing the fontface. */
|
||||||
@IBInspectable
|
@IBInspectable
|
||||||
public var fontSize = MTFontManager.fontManager.kDefaultFontSize {
|
public var fontSize:CGFloat {
|
||||||
didSet {
|
set {
|
||||||
self.font = font?.copy(withSize: fontSize)
|
_fontSize = newValue
|
||||||
|
let font = font?.copy(withSize: newValue)
|
||||||
|
self.font = font // also forces an update
|
||||||
}
|
}
|
||||||
|
get { _fontSize }
|
||||||
}
|
}
|
||||||
|
private var _fontSize:CGFloat=0
|
||||||
|
|
||||||
/** This sets the text color of the rendered math formula. The default color is black. */
|
/** This sets the text color of the rendered math formula. The default color is black. */
|
||||||
@IBInspectable
|
@IBInspectable
|
||||||
public var textColor:MTColor? = MTColor.black {
|
public var textColor:MTColor? {
|
||||||
didSet {
|
set {
|
||||||
self.displayList?.textColor = textColor
|
guard newValue != nil else { return }
|
||||||
|
_textColor = newValue
|
||||||
|
self.displayList?.textColor = newValue
|
||||||
self.setNeedsDisplay()
|
self.setNeedsDisplay()
|
||||||
}
|
}
|
||||||
|
get { _textColor }
|
||||||
}
|
}
|
||||||
|
private var _textColor:MTColor?
|
||||||
|
|
||||||
/** The minimum distance from the margin of the view to the rendered math. This value is
|
/** The minimum distance from the margin of the view to the rendered math. This value is
|
||||||
`UIEdgeInsetsZero` by default. This is useful if you need some padding between the math and
|
`UIEdgeInsetsZero` by default. This is useful if you need some padding between the math and
|
||||||
the border/background color. sizeThatFits: will have its returned size increased by these insets.
|
the border/background color. sizeThatFits: will have its returned size increased by these insets.
|
||||||
*/
|
*/
|
||||||
@IBInspectable
|
@IBInspectable
|
||||||
public var contentInsets = MTEdgeInsetsZero {
|
public var contentInsets:MTEdgeInsets {
|
||||||
didSet {
|
set {
|
||||||
|
_contentInsets = newValue
|
||||||
self.invalidateIntrinsicContentSize()
|
self.invalidateIntrinsicContentSize()
|
||||||
self.setNeedsLayout()
|
self.setNeedsLayout()
|
||||||
}
|
}
|
||||||
|
get { _contentInsets }
|
||||||
}
|
}
|
||||||
|
private var _contentInsets = MTEdgeInsetsZero
|
||||||
|
|
||||||
/** The Label mode for the label. The default mode is Display */
|
/** The Label mode for the label. The default mode is Display */
|
||||||
public var labelMode = MTMathUILabelMode.display {
|
public var labelMode:MTMathUILabelMode {
|
||||||
didSet {
|
set {
|
||||||
|
_labelMode = newValue
|
||||||
self.invalidateIntrinsicContentSize()
|
self.invalidateIntrinsicContentSize()
|
||||||
self.setNeedsLayout()
|
self.setNeedsLayout()
|
||||||
}
|
}
|
||||||
|
get { _labelMode }
|
||||||
}
|
}
|
||||||
|
private var _labelMode = MTMathUILabelMode.display
|
||||||
|
|
||||||
/** Horizontal alignment for the text. The default is align left. */
|
/** Horizontal alignment for the text. The default is align left. */
|
||||||
public var textAlignment = MTTextAlignment.left {
|
public var textAlignment:MTTextAlignment {
|
||||||
didSet {
|
set {
|
||||||
|
_textAlignment = newValue
|
||||||
self.invalidateIntrinsicContentSize()
|
self.invalidateIntrinsicContentSize()
|
||||||
self.setNeedsLayout()
|
self.setNeedsLayout()
|
||||||
}
|
}
|
||||||
|
get { _textAlignment }
|
||||||
}
|
}
|
||||||
|
private var _textAlignment = MTTextAlignment.left
|
||||||
|
|
||||||
/** The internal display of the MTMathUILabel. This is for advanced use only. */
|
/** The internal display of the MTMathUILabel. This is for advanced use only. */
|
||||||
var displayList: MTMathListDisplay? = nil
|
public var displayList: MTMathListDisplay? { _displayList }
|
||||||
|
private var _displayList:MTMathListDisplay?
|
||||||
|
|
||||||
public var currentStyle:MTLineStyle {
|
public var currentStyle:MTLineStyle {
|
||||||
switch labelMode {
|
switch _labelMode {
|
||||||
case .display: return .display
|
case .display: return .display
|
||||||
case .text: return .text
|
case .text: return .text
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var errorLabel: MTLabel?
|
public var errorLabel: MTLabel?
|
||||||
|
|
||||||
override init(frame: CGRect) {
|
public override init(frame: CGRect) {
|
||||||
super.init(frame: frame)
|
super.init(frame: frame)
|
||||||
self.initCommon()
|
self.initCommon()
|
||||||
}
|
}
|
||||||
|
|
||||||
required init?(coder: NSCoder) {
|
public required init?(coder: NSCoder) {
|
||||||
super.init(coder: coder)
|
super.init(coder: coder)
|
||||||
self.initCommon()
|
self.initCommon()
|
||||||
}
|
}
|
||||||
@@ -183,32 +204,33 @@ public class MTMathUILabel : MTView {
|
|||||||
#else
|
#else
|
||||||
self.layer.isGeometryFlipped = true
|
self.layer.isGeometryFlipped = true
|
||||||
#endif
|
#endif
|
||||||
fontSize = 20
|
_fontSize = 20
|
||||||
contentInsets = MTEdgeInsetsZero
|
_contentInsets = MTEdgeInsetsZero
|
||||||
labelMode = .display
|
_labelMode = .display
|
||||||
let font = MTFontManager.fontManager.defaultFont
|
let font = MTFontManager.fontManager.defaultFont
|
||||||
self.font = font
|
self.font = font
|
||||||
textAlignment = .left
|
_textAlignment = .left
|
||||||
displayList = nil
|
_displayList = nil
|
||||||
displayErrorInline = true
|
displayErrorInline = true
|
||||||
self.backgroundColor = MTColor.clear
|
self.backgroundColor = MTColor.clear
|
||||||
|
|
||||||
textColor = MTColor.black
|
_textColor = MTColor.black
|
||||||
errorLabel = MTLabel()
|
let label = MTLabel()
|
||||||
|
self.errorLabel = label
|
||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
errorLabel?.layer?.isGeometryFlipped = true
|
label.layer?.isGeometryFlipped = true
|
||||||
#else
|
#else
|
||||||
errorLabel?.layer.isGeometryFlipped = true
|
label.layer.isGeometryFlipped = true
|
||||||
#endif
|
#endif
|
||||||
errorLabel?.isHidden = true
|
label.isHidden = true
|
||||||
errorLabel?.textColor = MTColor.red
|
label.textColor = MTColor.red
|
||||||
self.addSubview(errorLabel!)
|
self.addSubview(label)
|
||||||
}
|
}
|
||||||
|
|
||||||
override public func draw(_ dirtyRect: MTRect) {
|
override public func draw(_ dirtyRect: MTRect) {
|
||||||
super.draw(dirtyRect)
|
super.draw(dirtyRect)
|
||||||
if self.mathList == nil { return }
|
if self.mathList == nil { return }
|
||||||
|
|
||||||
// drawing code
|
// drawing code
|
||||||
let context = MTGraphicsGetCurrentContext()!
|
let context = MTGraphicsGetCurrentContext()!
|
||||||
context.saveGState()
|
context.saveGState()
|
||||||
@@ -222,29 +244,25 @@ public class MTMathUILabel : MTView {
|
|||||||
|
|
||||||
func _layoutSubviews() {
|
func _layoutSubviews() {
|
||||||
if mathList != nil {
|
if mathList != nil {
|
||||||
displayList = MTTypesetter.createLineForMathList(mathList, font: font, style: currentStyle)
|
_displayList = MTTypesetter.createLineForMathList(mathList, font: font, style: currentStyle)
|
||||||
displayList?.textColor = textColor
|
_displayList!.textColor = textColor
|
||||||
var textX = CGFloat(0)
|
var textX = CGFloat(0)
|
||||||
switch self.textAlignment {
|
switch self.textAlignment {
|
||||||
case .left:
|
case .left: textX = contentInsets.left
|
||||||
textX = self.contentInsets.left
|
case .center: textX = (bounds.size.width - contentInsets.left - contentInsets.right - _displayList!.width) / 2 + contentInsets.left
|
||||||
case .center:
|
case .right: textX = bounds.size.width - _displayList!.width - contentInsets.right
|
||||||
textX = (bounds.size.width - contentInsets.left - contentInsets.right - displayList!.width) / 2 +
|
|
||||||
contentInsets.left
|
|
||||||
case .right:
|
|
||||||
textX = bounds.size.width - displayList!.width - contentInsets.right
|
|
||||||
}
|
}
|
||||||
let availableHeight = bounds.size.height - contentInsets.bottom - contentInsets.top
|
let availableHeight = bounds.size.height - contentInsets.bottom - contentInsets.top
|
||||||
|
|
||||||
// center things vertically
|
// center things vertically
|
||||||
var height = displayList!.ascent + displayList!.descent
|
var height = _displayList!.ascent + _displayList!.descent
|
||||||
if height < fontSize/2 {
|
if height < fontSize/2 {
|
||||||
height = fontSize/2 // set height to half the font size
|
height = fontSize/2 // set height to half the font size
|
||||||
}
|
}
|
||||||
let textY = (availableHeight - height) / 2 + displayList!.descent + contentInsets.bottom
|
let textY = (availableHeight - height) / 2 + _displayList!.descent + contentInsets.bottom
|
||||||
displayList?.position = CGPointMake(textX, textY)
|
_displayList!.position = CGPointMake(textX, textY)
|
||||||
} else {
|
} else {
|
||||||
displayList = nil
|
_displayList = nil
|
||||||
}
|
}
|
||||||
errorLabel?.frame = self.bounds
|
errorLabel?.frame = self.bounds
|
||||||
self.setNeedsDisplay()
|
self.setNeedsDisplay()
|
||||||
@@ -253,8 +271,8 @@ public class MTMathUILabel : MTView {
|
|||||||
func _sizeThatFits(_ size:CGSize) -> CGSize {
|
func _sizeThatFits(_ size:CGSize) -> CGSize {
|
||||||
var size = size
|
var size = size
|
||||||
var displayList:MTMathListDisplay? = nil
|
var displayList:MTMathListDisplay? = nil
|
||||||
if mathList != nil {
|
if _mathList != nil {
|
||||||
displayList = MTTypesetter.createLineForMathList(mathList, font: font, style: currentStyle)
|
displayList = MTTypesetter.createLineForMathList(_mathList, font: font, style: currentStyle)
|
||||||
}
|
}
|
||||||
size.width = displayList!.width + contentInsets.left + contentInsets.right
|
size.width = displayList!.width + contentInsets.left + contentInsets.right
|
||||||
size.height = displayList!.ascent + displayList!.descent + contentInsets.top + contentInsets.bottom
|
size.height = displayList!.ascent + displayList!.descent + contentInsets.top + contentInsets.bottom
|
||||||
|
|||||||
Reference in New Issue
Block a user