Resolving field resizing crashes.

This commit is contained in:
Michael Griebling
2023-01-18 09:02:28 -05:00
parent 2dd0fac5a8
commit 13a8a9097c
2 changed files with 76 additions and 58 deletions

View File

@@ -10,7 +10,7 @@ import SwiftUI
#if os(macOS)
class MTLabel : NSTextField {
public class MTLabel : NSTextField {
init() {
super.init(frame: .zero)

View File

@@ -48,27 +48,24 @@ public enum MTTextAlignment : UInt {
*/
@IBDesignable
public class MTMathUILabel : MTView {
private var _mathList:MTMathList?
/** The `MTMathList` to render. Setting this will remove any
`latex` that has already been set. If `latex` has been set, this will
return the parsed `MTMathList` if the `latex` parses successfully. Use this
setting if the `MTMathList` has been programmatically constructed, otherwise it
is preferred to use `latex`.
*/
var mathList:MTMathList? {
public var mathList:MTMathList? {
set {
_mathList = newValue
error = nil
_error = nil
_latex = MTMathListBuilder.mathListToString(newValue)
self.invalidateIntrinsicContentSize()
self.setNeedsLayout()
}
get { _mathList }
}
private var _latex:String=""
private var _mathList:MTMathList?
/** 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
@@ -78,12 +75,12 @@ public class MTMathUILabel : MTView {
public var latex:String {
set {
_latex = newValue
self.error = nil
_error = nil
var error : NSError? = nil
_mathList = MTMathListBuilder.build(fromString: newValue, error: &error)
if error != nil {
_mathList = nil
self.error = error
_error = error
self.errorLabel?.text = error!.localizedDescription
self.errorLabel?.frame = self.bounds
self.errorLabel?.isHidden = !self.displayErrorInline
@@ -95,84 +92,108 @@ public class MTMathUILabel : MTView {
}
get { _latex }
}
private var _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. */
public var displayErrorInline = true
/** The MTFont to use for rendering. */
var font = MTFontManager.fontManager.defaultFont {
didSet {
public var font:MTFont? {
set {
guard newValue != nil else { return }
_font = newValue
self.invalidateIntrinsicContentSize()
self.setNeedsLayout()
}
get { _font }
}
private var _font:MTFont?
/** Convenience method to just set the size of the font without changing the fontface. */
@IBInspectable
public var fontSize = MTFontManager.fontManager.kDefaultFontSize {
didSet {
self.font = font?.copy(withSize: fontSize)
public var fontSize:CGFloat {
set {
_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. */
@IBInspectable
public var textColor:MTColor? = MTColor.black {
didSet {
self.displayList?.textColor = textColor
public var textColor:MTColor? {
set {
guard newValue != nil else { return }
_textColor = newValue
self.displayList?.textColor = newValue
self.setNeedsDisplay()
}
get { _textColor }
}
private var _textColor:MTColor?
/** 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
the border/background color. sizeThatFits: will have its returned size increased by these insets.
*/
@IBInspectable
public var contentInsets = MTEdgeInsetsZero {
didSet {
public var contentInsets:MTEdgeInsets {
set {
_contentInsets = newValue
self.invalidateIntrinsicContentSize()
self.setNeedsLayout()
}
get { _contentInsets }
}
private var _contentInsets = MTEdgeInsetsZero
/** The Label mode for the label. The default mode is Display */
public var labelMode = MTMathUILabelMode.display {
didSet {
public var labelMode:MTMathUILabelMode {
set {
_labelMode = newValue
self.invalidateIntrinsicContentSize()
self.setNeedsLayout()
}
get { _labelMode }
}
private var _labelMode = MTMathUILabelMode.display
/** Horizontal alignment for the text. The default is align left. */
public var textAlignment = MTTextAlignment.left {
didSet {
public var textAlignment:MTTextAlignment {
set {
_textAlignment = newValue
self.invalidateIntrinsicContentSize()
self.setNeedsLayout()
}
get { _textAlignment }
}
private var _textAlignment = MTTextAlignment.left
/** 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 {
switch labelMode {
switch _labelMode {
case .display: return .display
case .text: return .text
}
}
var errorLabel: MTLabel?
public var errorLabel: MTLabel?
override init(frame: CGRect) {
public override init(frame: CGRect) {
super.init(frame: frame)
self.initCommon()
}
required init?(coder: NSCoder) {
public required init?(coder: NSCoder) {
super.init(coder: coder)
self.initCommon()
}
@@ -183,32 +204,33 @@ public class MTMathUILabel : MTView {
#else
self.layer.isGeometryFlipped = true
#endif
fontSize = 20
contentInsets = MTEdgeInsetsZero
labelMode = .display
_fontSize = 20
_contentInsets = MTEdgeInsetsZero
_labelMode = .display
let font = MTFontManager.fontManager.defaultFont
self.font = font
textAlignment = .left
displayList = nil
_textAlignment = .left
_displayList = nil
displayErrorInline = true
self.backgroundColor = MTColor.clear
textColor = MTColor.black
errorLabel = MTLabel()
_textColor = MTColor.black
let label = MTLabel()
self.errorLabel = label
#if os(macOS)
errorLabel?.layer?.isGeometryFlipped = true
label.layer?.isGeometryFlipped = true
#else
errorLabel?.layer.isGeometryFlipped = true
label.layer.isGeometryFlipped = true
#endif
errorLabel?.isHidden = true
errorLabel?.textColor = MTColor.red
self.addSubview(errorLabel!)
label.isHidden = true
label.textColor = MTColor.red
self.addSubview(label)
}
override public func draw(_ dirtyRect: MTRect) {
super.draw(dirtyRect)
if self.mathList == nil { return }
// drawing code
let context = MTGraphicsGetCurrentContext()!
context.saveGState()
@@ -222,29 +244,25 @@ public class MTMathUILabel : MTView {
func _layoutSubviews() {
if mathList != nil {
displayList = MTTypesetter.createLineForMathList(mathList, font: font, style: currentStyle)
displayList?.textColor = textColor
_displayList = MTTypesetter.createLineForMathList(mathList, font: font, style: currentStyle)
_displayList!.textColor = textColor
var textX = CGFloat(0)
switch self.textAlignment {
case .left:
textX = self.contentInsets.left
case .center:
textX = (bounds.size.width - contentInsets.left - contentInsets.right - displayList!.width) / 2 +
contentInsets.left
case .right:
textX = bounds.size.width - displayList!.width - contentInsets.right
case .left: textX = contentInsets.left
case .center: 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
// center things vertically
var height = displayList!.ascent + displayList!.descent
var height = _displayList!.ascent + _displayList!.descent
if height < fontSize/2 {
height = fontSize/2 // set height to half the font size
}
let textY = (availableHeight - height) / 2 + displayList!.descent + contentInsets.bottom
displayList?.position = CGPointMake(textX, textY)
let textY = (availableHeight - height) / 2 + _displayList!.descent + contentInsets.bottom
_displayList!.position = CGPointMake(textX, textY)
} else {
displayList = nil
_displayList = nil
}
errorLabel?.frame = self.bounds
self.setNeedsDisplay()
@@ -253,8 +271,8 @@ public class MTMathUILabel : MTView {
func _sizeThatFits(_ size:CGSize) -> CGSize {
var size = size
var displayList:MTMathListDisplay? = nil
if mathList != nil {
displayList = MTTypesetter.createLineForMathList(mathList, font: font, style: currentStyle)
if _mathList != nil {
displayList = MTTypesetter.createLineForMathList(_mathList, font: font, style: currentStyle)
}
size.width = displayList!.width + contentInsets.left + contentInsets.right
size.height = displayList!.ascent + displayList!.descent + contentInsets.top + contentInsets.bottom