mirror of
https://gitlab.com/cleanflash/installer.git
synced 2026-08-13 02:41:38 +08:00
Add text fixes
This commit is contained in:
@@ -79,7 +79,8 @@ impl FontManager {
|
||||
}
|
||||
}
|
||||
|
||||
/// Draw multiline text, splitting on '\n'. Returns total height drawn.
|
||||
/// Draw multiline text, splitting on '\n' and word-wrapping at `max_width`
|
||||
/// (if > 0). Returns total height drawn.
|
||||
pub fn draw_text_multiline(
|
||||
&self,
|
||||
renderer: &mut Renderer,
|
||||
@@ -89,18 +90,90 @@ impl FontManager {
|
||||
size: f32,
|
||||
color: u32,
|
||||
line_spacing: f32,
|
||||
max_width: f32,
|
||||
) -> f32 {
|
||||
let scaled = self.regular.as_scaled(size);
|
||||
let line_height = scaled.height() + line_spacing;
|
||||
let mut cy = y as f32;
|
||||
|
||||
for line in text.split('\n') {
|
||||
self.draw_text(renderer, x, cy as i32, line, size, color);
|
||||
cy += line_height;
|
||||
if max_width > 0.0 {
|
||||
let wrapped = self.word_wrap(line, size, max_width);
|
||||
for wl in &wrapped {
|
||||
self.draw_text(renderer, x, cy as i32, wl, size, color);
|
||||
cy += line_height;
|
||||
}
|
||||
} else {
|
||||
self.draw_text(renderer, x, cy as i32, line, size, color);
|
||||
cy += line_height;
|
||||
}
|
||||
}
|
||||
|
||||
cy - y as f32
|
||||
}
|
||||
|
||||
/// Measure the total height of multiline text with word-wrapping.
|
||||
pub fn measure_text_multiline(&self, text: &str, size: f32, line_spacing: f32, max_width: f32) -> (f32, f32) {
|
||||
let scaled = self.regular.as_scaled(size);
|
||||
let line_height = scaled.height() + line_spacing;
|
||||
let mut total_lines = 0usize;
|
||||
let mut overall_max_w: f32 = 0.0;
|
||||
|
||||
for line in text.split('\n') {
|
||||
if max_width > 0.0 {
|
||||
let wrapped = self.word_wrap(line, size, max_width);
|
||||
for wl in &wrapped {
|
||||
let (lw, _) = self.measure_text(wl, size);
|
||||
if lw > overall_max_w {
|
||||
overall_max_w = lw;
|
||||
}
|
||||
}
|
||||
total_lines += wrapped.len();
|
||||
} else {
|
||||
let (lw, _) = self.measure_text(line, size);
|
||||
if lw > overall_max_w {
|
||||
overall_max_w = lw;
|
||||
}
|
||||
total_lines += 1;
|
||||
}
|
||||
}
|
||||
|
||||
(overall_max_w, line_height * total_lines as f32)
|
||||
}
|
||||
|
||||
/// Word-wrap a single line to fit within `max_width` pixels.
|
||||
fn word_wrap(&self, line: &str, size: f32, max_width: f32) -> Vec<String> {
|
||||
if line.is_empty() {
|
||||
return vec![String::new()];
|
||||
}
|
||||
|
||||
let mut result = Vec::new();
|
||||
let mut current = String::new();
|
||||
let mut current_w: f32 = 0.0;
|
||||
let space_w = self.measure_text(" ", size).0;
|
||||
|
||||
for word in line.split_whitespace() {
|
||||
let (ww, _) = self.measure_text(word, size);
|
||||
|
||||
if current.is_empty() {
|
||||
// First word on this line — always add even if too wide.
|
||||
current = word.to_string();
|
||||
current_w = ww;
|
||||
} else if current_w + space_w + ww <= max_width {
|
||||
current.push(' ');
|
||||
current.push_str(word);
|
||||
current_w += space_w + ww;
|
||||
} else {
|
||||
// Wrap.
|
||||
result.push(current);
|
||||
current = word.to_string();
|
||||
current_w = ww;
|
||||
}
|
||||
}
|
||||
|
||||
result.push(current);
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ use super::Rect;
|
||||
use crate::font::FontManager;
|
||||
use crate::renderer::Renderer;
|
||||
|
||||
/// Simple static label for drawing text.
|
||||
/// Simple static label for drawing text with optional word-wrapping.
|
||||
pub struct Label {
|
||||
pub rect: Rect,
|
||||
pub text: String,
|
||||
@@ -10,6 +10,8 @@ pub struct Label {
|
||||
pub font_size: f32,
|
||||
pub line_spacing: f32,
|
||||
pub visible: bool,
|
||||
/// If > 0, text is word-wrapped to this pixel width.
|
||||
pub max_width: f32,
|
||||
}
|
||||
|
||||
impl Label {
|
||||
@@ -21,6 +23,7 @@ impl Label {
|
||||
font_size,
|
||||
line_spacing: 2.0,
|
||||
visible: true,
|
||||
max_width: 0.0,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +39,7 @@ impl Label {
|
||||
self.font_size,
|
||||
self.color,
|
||||
self.line_spacing,
|
||||
self.max_width,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -44,10 +48,13 @@ impl Label {
|
||||
if !self.visible || !mouse_released {
|
||||
return false;
|
||||
}
|
||||
let (tw, _th) = fonts.measure_text(&self.text, self.font_size);
|
||||
let lines = self.text.lines().count().max(1);
|
||||
let approx_h = (self.font_size * lines as f32 + 2.0 * lines as f32) as i32;
|
||||
let r = Rect::new(self.rect.x, self.rect.y, tw as i32 + 5, approx_h);
|
||||
let (tw, th) = fonts.measure_text_multiline(
|
||||
&self.text,
|
||||
self.font_size,
|
||||
self.line_spacing,
|
||||
self.max_width,
|
||||
);
|
||||
let r = Rect::new(self.rect.x, self.rect.y, tw as i32 + 5, th as i32);
|
||||
r.contains(mx, my)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user