///|
/// Integration with crater layout engine
/// Uses character-based measurements (1 char = 1 unit width/height)
///|
/// Create a MeasureFunc for text that uses character width
pub fn text_measure_func(text : String) -> @node.MeasureFunc {
{
func: fn(
available_width : Double,
_available_height : Double,
) -> @node.IntrinsicSize {
let max_width = available_width.to_int()
// Calculate min-content (longest word)
let mut min_width = 0
let mut current_word = 0
for c in text {
if c == ' ' || c == '\n' {
if current_word > min_width {
min_width = current_word
}
current_word = 0
} else {
current_word = current_word + char_display_width(c)
}
}
if current_word > min_width {
min_width = current_word
}
// Calculate max-content (total width without wrapping)
let max_content = string_display_width(text)
// Calculate actual width and height based on wrapping
let actual_width = if max_width > 0 && max_content > max_width {
max_width
} else if max_content > 0 {
max_content
} else {
min_width
}
// Calculate height with wrapping
let height = if actual_width > 0 {
calculate_wrapped_height(text, actual_width)
} else {
1
}
{
min_width: min_width.to_double(),
max_width: max_content.to_double(),
min_height: 1.0,
max_height: height.to_double(),
}
},
}
}
///|
fn calculate_wrapped_height(text : String, max_width : Int) -> Int {
let mut lines = 1
let mut current_width = 0
for c in text {
if c == '\n' {
lines = lines + 1
current_width = 0
continue
}
let w = char_display_width(c)
if current_width + w > max_width {
lines = lines + 1
current_width = w
} else {
current_width = current_width + w
}
}
lines
}
///|
/// Compute layout using crater engine with character-based viewport
pub fn compute_layout(
node : @node.Node,
width : Int,
height : Int,
) -> @node.Layout {
let viewport = @types.Size::new(width.to_double(), height.to_double())
@crater.compute_layout(node, viewport)
}
///|
/// Border characters for box drawing
pub(all) struct BorderChars {
top_left : Char
top_right : Char
bottom_left : Char
bottom_right : Char
horizontal : Char
vertical : Char
}
///|
pub fn BorderChars::single() -> BorderChars {
{
top_left: '\u250C',
top_right: '\u2510',
bottom_left: '\u2514',
bottom_right: '\u2518',
horizontal: '\u2500',
vertical: '\u2502',
}
}
///|
pub fn BorderChars::double() -> BorderChars {
{
top_left: '\u2554',
top_right: '\u2557',
bottom_left: '\u255A',
bottom_right: '\u255D',
horizontal: '\u2550',
vertical: '\u2551',
}
}
///|
pub fn BorderChars::rounded() -> BorderChars {
{
top_left: '\u256D',
top_right: '\u256E',
bottom_left: '\u2570',
bottom_right: '\u256F',
horizontal: '\u2500',
vertical: '\u2502',
}
}
///|
pub fn BorderChars::ascii() -> BorderChars {
{
top_left: '+',
top_right: '+',
bottom_left: '+',
bottom_right: '+',
horizontal: '-',
vertical: '|',
}
}