Add display model
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
import CoreGraphics
|
||||
import Foundation
|
||||
|
||||
extension Math {
|
||||
final class DisplayLargeOperator: DisplayNode {
|
||||
var upperLimit: DisplayList?
|
||||
var lowerLimit: DisplayList?
|
||||
var nucleus: DisplayNode?
|
||||
|
||||
var limitShift: CGFloat = 0
|
||||
var upperLimitGap: CGFloat = 0 { didSet { updateUpperLimitPosition() } }
|
||||
var lowerLimitGap: CGFloat = 0 { didSet { updateLowerLimitPosition() } }
|
||||
var extraPadding: CGFloat = 0
|
||||
|
||||
init(nucleus: DisplayNode?, upperLimit: DisplayList?, lowerLimit: DisplayList?, limitShift: CGFloat, extraPadding: CGFloat) {
|
||||
self.upperLimit = upperLimit
|
||||
self.lowerLimit = lowerLimit
|
||||
self.nucleus = nucleus
|
||||
self.limitShift = limitShift
|
||||
self.extraPadding = extraPadding
|
||||
super.init()
|
||||
|
||||
var maxWidth = max(nucleus?.width ?? 0, upperLimit?.width ?? 0)
|
||||
maxWidth = max(maxWidth, lowerLimit?.width ?? 0)
|
||||
width = maxWidth
|
||||
}
|
||||
|
||||
override var ascent: CGFloat {
|
||||
get {
|
||||
guard let nucleus else { return 0 }
|
||||
if let upperLimit {
|
||||
return nucleus.ascent + extraPadding + upperLimit.ascent + upperLimitGap + upperLimit.descent
|
||||
}
|
||||
return nucleus.ascent
|
||||
}
|
||||
set { super.ascent = newValue }
|
||||
}
|
||||
|
||||
override var descent: CGFloat {
|
||||
get {
|
||||
guard let nucleus else { return 0 }
|
||||
if let lowerLimit {
|
||||
return nucleus.descent + extraPadding + lowerLimitGap + lowerLimit.descent + lowerLimit.ascent
|
||||
}
|
||||
return nucleus.descent
|
||||
}
|
||||
set { super.descent = newValue }
|
||||
}
|
||||
|
||||
override var position: CGPoint {
|
||||
didSet {
|
||||
updateLowerLimitPosition()
|
||||
updateUpperLimitPosition()
|
||||
updateNucleusPosition()
|
||||
}
|
||||
}
|
||||
|
||||
private func updateLowerLimitPosition() {
|
||||
guard let lowerLimit, let nucleus else { return }
|
||||
lowerLimit.position = CGPoint(
|
||||
x: position.x - limitShift + (width - lowerLimit.width) / 2,
|
||||
y: position.y - nucleus.descent - lowerLimitGap - lowerLimit.ascent
|
||||
)
|
||||
}
|
||||
|
||||
private func updateUpperLimitPosition() {
|
||||
guard let upperLimit, let nucleus else { return }
|
||||
upperLimit.position = CGPoint(
|
||||
x: position.x + limitShift + (width - upperLimit.width) / 2,
|
||||
y: position.y + nucleus.ascent + upperLimitGap + upperLimit.descent
|
||||
)
|
||||
}
|
||||
|
||||
private func updateNucleusPosition() {
|
||||
guard let nucleus else { return }
|
||||
nucleus.position = CGPoint(x: position.x + (width - nucleus.width) / 2, y: position.y)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user