mirror of
https://github.com/storytold/lightcraft.git
synced 2026-10-26 02:59:17 -06:00
Merge PR #289
This commit is contained in:
@@ -29,6 +29,8 @@ pub mod widgets;
|
||||
#[cfg(test)]
|
||||
mod tests_curve;
|
||||
#[cfg(test)]
|
||||
mod tests_filmstrip;
|
||||
#[cfg(test)]
|
||||
mod tests_grid;
|
||||
#[cfg(test)]
|
||||
mod tests_library_problem;
|
||||
|
||||
@@ -1493,6 +1493,12 @@ fn eye_overlay(app: &mut LightcraftApp, ui: &mut egui::Ui, resp: &egui::Response
|
||||
|
||||
// ------------------------------------------------------------------------ filmstrip
|
||||
|
||||
/// A filmstrip cell's file-name label: names longer than 14 characters are cut to 13 and an
|
||||
/// ellipsis. Counts characters, not bytes, so a CJK name is never cut inside a character (#266).
|
||||
fn film_label(name: &str) -> String {
|
||||
if name.chars().nth(14).is_some() { format!("{}…", name.chars().take(13).collect::<String>()) } else { name.to_string() }
|
||||
}
|
||||
|
||||
pub(crate) fn filmstrip(app: &mut LightcraftApp, ui: &mut egui::Ui, r: Rect) {
|
||||
let t = Tokens::get(ui.ctx());
|
||||
ui.painter().rect_filled(r, 0.0, t.canvas);
|
||||
@@ -1536,8 +1542,7 @@ pub(crate) fn filmstrip(app: &mut LightcraftApp, ui: &mut egui::Ui, r: Rect) {
|
||||
let names = app.ui.settings.film_names;
|
||||
if let Some(ph) = app.session.catalog.photo(*id).filter(|_| names) {
|
||||
let name = ph.file_name.rsplit_once('.').map(|(n, _)| n).unwrap_or(&ph.file_name);
|
||||
let short: String = if name.len() > 14 { format!("{}…", &name[..13]) } else { name.to_string() };
|
||||
p.text(pos2(cr.left() + 8.0, cr.top() + 10.0), Align2::LEFT_CENTER, short, t.font(10.0), t.text_dim);
|
||||
p.text(pos2(cr.left() + 8.0, cr.top() + 10.0), Align2::LEFT_CENTER, film_label(name), t.font(10.0), t.text_dim);
|
||||
p.text(pos2(cr.right() - 8.0, cr.top() + 10.0), Align2::RIGHT_CENTER, &ph.format, t.semibold(8.5), t.text_dim);
|
||||
}
|
||||
let img_area = Rect::from_min_max(cr.min + vec2(10.0, 22.0), cr.max - vec2(10.0, 8.0));
|
||||
@@ -1648,3 +1653,20 @@ fn straighten_overlay(app: &mut LightcraftApp, ui: &mut egui::Ui, resp: &egui::R
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::film_label;
|
||||
|
||||
#[test]
|
||||
fn film_labels_cut_on_characters_not_bytes() {
|
||||
// the name from #266: byte 13 falls inside '限'
|
||||
assert_eq!(film_label("202407層三限定訂閱圖(4)"), "202407層三限定訂閱圖…");
|
||||
assert_eq!(film_label("写真"), "写真");
|
||||
// exactly 14 characters (42 bytes) is shown whole
|
||||
assert_eq!(film_label("一二三四五六七八九十一二三四"), "一二三四五六七八九十一二三四");
|
||||
assert_eq!(film_label("IMG_20240712_153012"), "IMG_20240712_…");
|
||||
assert_eq!(film_label("DSC_0001"), "DSC_0001");
|
||||
assert_eq!(film_label(""), "");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
//! Headless test of the filmstrip's file-name labels (#266): a name with multi-byte (CJK)
|
||||
//! characters is drawn without panicking.
|
||||
|
||||
use std::time::Duration;
|
||||
|
||||
use lightcraft_catalog::Op;
|
||||
use serde_json::json;
|
||||
|
||||
use crate::headless::Headless;
|
||||
use crate::{LightcraftApp, Services};
|
||||
|
||||
const T: Duration = Duration::from_secs(20);
|
||||
const SETTLE: Duration = Duration::from_secs(120);
|
||||
|
||||
#[test]
|
||||
fn filmstrip_shows_a_cjk_file_name() {
|
||||
let mut session = lightcraft_engine::Session::with_demo();
|
||||
let first = session.visible_cloned()[0];
|
||||
let source = session.catalog.photo(first).expect("demo photo").source.clone();
|
||||
// the name from #266: cutting it at byte 13 lands inside '限'
|
||||
session.catalog.apply(Op::SetFile { id: first, file_name: "202407層三限定訂閱圖(4).jpg".into(), source }).unwrap();
|
||||
let app = LightcraftApp::new(session, Services { png: None, ..Default::default() });
|
||||
let mut h = Headless::new(app, [1200.0, 800.0], 1.0);
|
||||
let r = h.request("ui.set", json!({"view": "detail"}), T);
|
||||
assert_eq!(r["ok"], true, "{r}");
|
||||
h.settle(SETTLE);
|
||||
assert!(h.app.ui.settings.film_names);
|
||||
let film = format!("film:{}", first.0);
|
||||
assert!(h.app.widgets.iter().any(|(w, _)| *w == film), "{film} drawn in the filmstrip");
|
||||
}
|
||||
Reference in New Issue
Block a user