85 lines
2.5 KiB
Swift
85 lines
2.5 KiB
Swift
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)
|
|
}
|
|
}
|
|
}
|