Skip to content

Commit

Permalink
Add overflow hint for text (#142)
Browse files Browse the repository at this point in the history
  • Loading branch information
filtsin authored Mar 16, 2023
1 parent 36dec6b commit 811a435
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 8 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/draw/input_text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ impl<'a> Drawable for InputText<'a> {
.min(self.params.radius.top_right);

let pos = Point::new(rect_point.x + padding.left, rect_point.y + padding.top);
let end_pos = Point::new(
dt.width() as f32 - self.params.padding.right - self.params.margin.right,
pos.y,
);

let password_text = if self.params.password {
Some("*".repeat(self.text.chars().count()))
Expand All @@ -89,6 +93,7 @@ impl<'a> Drawable for InputText<'a> {
text,
font_size,
pos,
end_pos,
FontColor::Single(color.as_source()),
&DrawOptions::new(),
);
Expand Down
6 changes: 5 additions & 1 deletion src/draw/list_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ where
}

let pos = Point::new(x_offset + icon_size_f32 + icon_spacing, y_offset);
let end_pos = Point::new(dt.width() as f32 - self.params.margin.right, y_offset);

let color = if i == selected_item {
self.params.selected_font_color
} else {
Expand Down Expand Up @@ -176,7 +178,8 @@ where
};

let font = &self.params.font;
font.draw(dt, item.name, font_size, pos, color, &draw_opts);
font.draw(dt, item.name, font_size, pos, end_pos, color, &draw_opts);

if i == selected_item && has_subname {
if let Some(subname) = item.subname {
font.draw(
Expand All @@ -187,6 +190,7 @@ where
pos.x + self.params.action_left_margin,
pos.y + entry_height + item_spacing,
),
Point::new(end_pos.x, pos.y + entry_height + item_spacing),
FontColor::Single(self.params.font_color.as_source()),
&draw_opts,
);
Expand Down
2 changes: 2 additions & 0 deletions src/font.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,14 @@ pub trait FontBackend: Sized {

fn font_by_path(path: &Path) -> Result<Self>;

#[allow(clippy::too_many_arguments)]
fn draw(
&self,
dt: &mut DrawTarget,
text: &str,
font_size: f32,
start_pos: Point,
end_pos: Point,
color: FontColor,
opts: &DrawOptions,
);
Expand Down
46 changes: 41 additions & 5 deletions src/font/fdue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ use std::path::{Path, PathBuf};

use anyhow::Context;
use fontconfig::{Fontconfig, Pattern};
use fontdue::layout::{CoordinateSystem, Layout, LayoutSettings, TextStyle, VerticalAlign};
use fontdue::layout::{
CoordinateSystem, Layout, LayoutSettings, TextStyle, VerticalAlign, WrapStyle,
};
use levenshtein::levenshtein;
use once_cell::sync::Lazy;
use raqote::{DrawOptions, Point, SolidSource};
Expand Down Expand Up @@ -109,15 +111,14 @@ impl FontBackend for Font {
let pat = Pattern::new(&FONTCONFIG_CACHE);
fontconfig::list_fonts(&pat, None)
.iter()
.filter_map(|pat| {
.find_map(|pat| {
let path = std::path::Path::new(pat.filename()?);
if !path.exists() {
return None;
}
let index = pat.face_index().and_then(index_to_u32);
Some(Font::from_path(path, index))
})
.next()
.expect("cannot find any font")
.expect("cannot load default font")
}
Expand Down Expand Up @@ -172,9 +173,10 @@ impl FontBackend for Font {
fn draw(
&self,
dt: &mut DrawTarget,
text: &str,
mut text: &str,
font_size: f32,
start_pos: Point,
end_pos: Point,
color: FontColor,
opts: &DrawOptions,
) {
Expand All @@ -185,13 +187,47 @@ impl FontBackend for Font {
x: start_pos.x,
y: start_pos.y,
max_height: Some(font_size),
max_width: Some(end_pos.x - start_pos.x),
vertical_align: VerticalAlign::Middle,
wrap_style: WrapStyle::Letter,
..LayoutSettings::default()
});

layout.append(&[&self.inner], &TextStyle::new(text, font_size, 0));

for (n, g) in layout.glyphs().iter().enumerate() {
let take_glyphs = match layout.lines() {
Some(vec) => {
// If layout return miltiple lines then we have text overflow, cut the text
// and layout again
match vec.get(1) {
Some(second_line) => second_line.glyph_start,
None => layout.glyphs().len(),
}
}
None => layout.glyphs().len(),
};

if take_glyphs != layout.glyphs().len() {
let overflow_text = "...";

// Try place ... in end of cutted text. Check strange case if width of window is too small
// even for overflow_text. No panic at all
let glyph_offset = if take_glyphs > overflow_text.len() {
take_glyphs - overflow_text.len()
} else {
take_glyphs
};

text = &text[0..layout.glyphs().get(glyph_offset).unwrap().byte_offset];
layout.clear();
layout.append(&[&self.inner], &TextStyle::new(text, font_size, 0));

if glyph_offset != take_glyphs {
layout.append(&[&self.inner], &TextStyle::new(overflow_text, font_size, 0));
}
}

for (n, g) in layout.glyphs().iter().take(take_glyphs).enumerate() {
let (_, b) = self.inner.rasterize_config(g.key);

assert!(g.width * g.height <= BUF_SIZE);
Expand Down

0 comments on commit 811a435

Please sign in to comment.