[UI] add line wrapping functionality
This commit is contained in:
130
README.md
130
README.md
@@ -114,18 +114,34 @@ struct MathView: UIViewRepresentable {
|
||||
var fontSize: CGFloat = 30
|
||||
var labelMode: MTMathUILabelMode = .text
|
||||
var insets: MTEdgeInsets = MTEdgeInsets()
|
||||
|
||||
|
||||
func makeUIView(context: Context) -> MTMathUILabel {
|
||||
let view = MTMathUILabel()
|
||||
view.setContentHuggingPriority(.required, for: .vertical)
|
||||
view.setContentCompressionResistancePriority(.required, for: .vertical)
|
||||
return view
|
||||
}
|
||||
|
||||
func updateUIView(_ view: MTMathUILabel, context: Context) {
|
||||
view.latex = equation
|
||||
view.font = MTFontManager().font(withName: font.rawValue, size: fontSize)
|
||||
let font = MTFontManager().font(withName: font.rawValue, size: fontSize)
|
||||
font?.fallbackFont = UIFont.systemFont(ofSize: fontSize)
|
||||
view.font = font
|
||||
view.textAlignment = textAlignment
|
||||
view.labelMode = labelMode
|
||||
view.textColor = MTColor(Color.primary)
|
||||
view.contentInsets = insets
|
||||
view.invalidateIntrinsicContentSize()
|
||||
}
|
||||
|
||||
func sizeThatFits(_ proposal: ProposedViewSize, uiView: MTMathUILabel, context: Context) -> CGSize? {
|
||||
// Enable line wrapping by passing proposed width to the label
|
||||
if let width = proposal.width, width.isFinite, width > 0 {
|
||||
uiView.preferredMaxLayoutWidth = width
|
||||
let size = uiView.sizeThatFits(CGSize(width: width, height: .greatestFiniteMagnitude))
|
||||
return size
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -143,23 +159,127 @@ struct MathView: NSViewRepresentable {
|
||||
var fontSize: CGFloat = 30
|
||||
var labelMode: MTMathUILabelMode = .text
|
||||
var insets: MTEdgeInsets = MTEdgeInsets()
|
||||
|
||||
|
||||
func makeNSView(context: Context) -> MTMathUILabel {
|
||||
let view = MTMathUILabel()
|
||||
view.setContentHuggingPriority(.required, for: .vertical)
|
||||
view.setContentCompressionResistancePriority(.required, for: .vertical)
|
||||
return view
|
||||
}
|
||||
|
||||
|
||||
func updateNSView(_ view: MTMathUILabel, context: Context) {
|
||||
view.latex = equation
|
||||
view.font = MTFontManager().font(withName: font.rawValue, size: fontSize)
|
||||
let font = MTFontManager().font(withName: font.rawValue, size: fontSize)
|
||||
font?.fallbackFont = NSFont.systemFont(ofSize: fontSize)
|
||||
view.font = font
|
||||
view.textAlignment = textAlignment
|
||||
view.labelMode = labelMode
|
||||
view.textColor = MTColor(Color.primary)
|
||||
view.contentInsets = insets
|
||||
view.invalidateIntrinsicContentSize()
|
||||
}
|
||||
|
||||
func sizeThatFits(_ proposal: ProposedViewSize, nsView: MTMathUILabel, context: Context) -> CGSize? {
|
||||
// Enable line wrapping by passing proposed width to the label
|
||||
if let width = proposal.width, width.isFinite, width > 0 {
|
||||
nsView.preferredMaxLayoutWidth = width
|
||||
let size = nsView.sizeThatFits(CGSize(width: width, height: .greatestFiniteMagnitude))
|
||||
return size
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Automatic Line Wrapping
|
||||
|
||||
`SwiftMath` supports automatic line wrapping for text and simple math expressions. When the content exceeds the available width, it will wrap at word boundaries to fit within the constrained space.
|
||||
|
||||
#### Using Line Wrapping with UIKit/AppKit
|
||||
|
||||
For direct `MTMathUILabel` usage, set the `preferredMaxLayoutWidth` property:
|
||||
|
||||
```swift
|
||||
let label = MTMathUILabel()
|
||||
label.latex = "\\(\\text{Remember the conversion: 1 km equals 1000 meters.}\\)"
|
||||
label.font = MTFontManager.fontManager.defaultFont
|
||||
label.labelMode = .text
|
||||
|
||||
// Enable line wrapping by setting a maximum width
|
||||
label.preferredMaxLayoutWidth = 300
|
||||
```
|
||||
|
||||
You can also use `sizeThatFits` to calculate the size with a width constraint:
|
||||
|
||||
```swift
|
||||
let constrainedSize = label.sizeThatFits(CGSize(width: 300, height: .greatestFiniteMagnitude))
|
||||
```
|
||||
|
||||
#### Using Line Wrapping with SwiftUI
|
||||
|
||||
The `MathView` examples above include `sizeThatFits()` which automatically enables line wrapping when SwiftUI proposes a width constraint. No additional configuration is needed:
|
||||
|
||||
```swift
|
||||
VStack(alignment: .leading, spacing: 8) {
|
||||
MathView(
|
||||
equation: "\\(\\text{Remember the conversion: 1 km equals 1000 meters.}\\)",
|
||||
fontSize: 17,
|
||||
labelMode: .text
|
||||
)
|
||||
}
|
||||
.frame(maxWidth: 300) // The text will wrap to fit within 300pt
|
||||
```
|
||||
|
||||
#### Line Wrapping Behavior
|
||||
|
||||
- **Works for**: Text content (`\text{...}`), mixed text with simple math, and simple equations
|
||||
- **Breaks at**: Word boundaries (spaces)
|
||||
- **Preserves**: Complex math layout (fractions, superscripts, matrices remain on single lines)
|
||||
- **Respects**: Unicode text including CJK characters with proper word boundaries
|
||||
|
||||
#### Examples
|
||||
|
||||
**Simple text wrapping:**
|
||||
```swift
|
||||
// Long text will wrap to multiple lines
|
||||
label.latex = "\\(\\text{The quadratic formula is used to solve equations of the form } ax^2 + bx + c = 0\\)"
|
||||
label.preferredMaxLayoutWidth = 250
|
||||
```
|
||||
|
||||
**Simple equation with operators:**
|
||||
```swift
|
||||
// Long equations can break between operators if too long
|
||||
label.latex = "\\(5 + 10 + 15 + 20 + 25 + 30\\)"
|
||||
label.preferredMaxLayoutWidth = 150
|
||||
// Will wrap: "5 + 10 + 15 + 20 +"
|
||||
// "25 + 30"
|
||||
```
|
||||
|
||||
**Mixed text and math:**
|
||||
```swift
|
||||
// Text wraps but math expressions stay intact
|
||||
label.latex = "\\(\\text{Result: } 5 \\times 1000 = 5000 \\text{ meters}\\)"
|
||||
label.preferredMaxLayoutWidth = 200
|
||||
// Will wrap at spaces between text and operators
|
||||
```
|
||||
|
||||
**Multiple lines in SwiftUI:**
|
||||
```swift
|
||||
ScrollView {
|
||||
VStack(alignment: .leading, spacing: 12) {
|
||||
ForEach(steps) { step in
|
||||
MathView(
|
||||
equation: step.description,
|
||||
fontSize: 17,
|
||||
labelMode: .text
|
||||
)
|
||||
}
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
// Each MathView will automatically wrap based on available width
|
||||
```
|
||||
|
||||
### Included Features
|
||||
This is a list of formula types that the library currently supports:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user