#712: share eyedropper previews and translate the sampling hint

This commit is contained in:
Kristian Myram committed 2026-10-30 02:17:34 +01:00
1 parent e509710227
commit 6da89b6ea8
2 files changed
+25 -23

No files matched your search

+8
View File
@@ -163,6 +163,7 @@ pub(crate) fn tr_args(text: &str, args: &[&dyn Display]) -> String {
/// Japanese: the same rows, in the same order, as the Chinese catalogs below.
const JAPANESE: &[(&str, &str)] = &[
("Click to sample color", "クリックして色をサンプル"),
("Appearance Settings…", "外観設定…"),
("Add to favorites", "お気に入りに追加"),
("Remove from favorites", "お気に入りから削除"),
@@ -904,6 +905,7 @@ const JAPANESE: &[(&str, &str)] = &[
];
const SIMPLIFIED_CHINESE: &[(&str, &str)] = &[
("Click to sample color", "单击以取样颜色"),
("Appearance Settings…", "外观设置…"),
("Add to favorites", "添加到收藏"),
("Remove from favorites", "从收藏中移除"),
@@ -1644,6 +1646,7 @@ const SIMPLIFIED_CHINESE: &[(&str, &str)] = &[
];
const TRADITIONAL_CHINESE: &[(&str, &str)] = &[
("Click to sample color", "按一下以取樣顏色"),
("Appearance Settings…", "外觀設定…"),
("Add to favorites", "加入最愛"),
("Remove from favorites", "從最愛移除"),
@@ -2332,6 +2335,7 @@ const TRADITIONAL_CHINESE: &[(&str, &str)] = &[
/// Ukrainian (uk): original translations of the same interface rows as the Chinese catalogs.
/// Technical names, key names and substituted project content keep their original spelling.
const UKRAINIAN: &[(&str, &str)] = &[
("Click to sample color", "Клацніть, щоб узяти зразок кольору"),
("Appearance Settings…", "Налаштування вигляду…"),
("Add to favorites", "Додати до вибраного"),
("Remove from favorites", "Видалити з вибраного"),
@@ -2906,6 +2910,7 @@ const UKRAINIAN: &[(&str, &str)] = &[
// Brazilian Portuguese.
const PORTUGUESE: &[(&str, &str)] = &[
("Click to sample color", "Clique para obter uma amostra de cor"),
(" OK ", " OK "),
(" Delete ", " Excluir "),
(" Open Auto-Save ", " Abrir salvamento automático "),
@@ -3357,6 +3362,7 @@ const PORTUGUESE: &[(&str, &str)] = &[
/// Czech (cs): original translations covering every row in the Chinese panel catalogs.
const CZECH: &[(&str, &str)] = &[
("Click to sample color", "Kliknutím naberete barvu"),
(" OK ", " OK "),
(" Delete ", " Odstranit "),
(" Open Auto-Save ", " Otevřít automatickou zálohu "),
@@ -3911,6 +3917,7 @@ const CZECH: &[(&str, &str)] = &[
/// order. Terms follow the Spanish menu catalog (composición, material de archivo, cola de procesamiento,
/// ajuste preestablecido, método abreviado). Written from the English source.
const SPANISH: &[(&str, &str)] = &[
("Click to sample color", "Haz clic para tomar una muestra de color"),
("Copy Source Path", "Copiar ruta de origen"),
("Appearance Settings…", "Ajustes de apariencia…"),
("Add to favorites", "Añadir a favoritos"),
@@ -4467,6 +4474,7 @@ const SPANISH: &[(&str, &str)] = &[
/// Georgian (ka): every row of the Chinese catalogs, in the same order (the tests keep them in step).
const GEORGIAN: &[(&str, &str)] = &[
("Click to sample color", "დააწკაპუნეთ ფერის ნიმუშის ასაღებად"),
("Appearance Settings…", "იერსახის პარამეტრები…"),
("Add to favorites", "რჩეულებში დამატება"),
("Remove from favorites", "რჩეულებიდან ამოშლა"),
@@ -119,6 +119,21 @@ fn fx_pick_session(
ControlFlow::Continue(point_preview)
}
/// Shared hint chip and sampled-color swatch for text and popup eyedroppers.
fn color_pick_preview(app: &EffectcraftApp, painter: &egui::Painter, map: &crate::panels::viewer::ViewerMap, hint: &str, pointer: Option<egui::Pos2>) {
let chip = Rect::from_min_size(map.area.min + vec2(10.0, 10.0), vec2(220.0, 22.0));
painter.rect_filled(chip, 11.0, Color32::from_black_alpha(180));
painter.text(chip.center(), Align2::CENTER_CENTER, hint, Tokens::ui(11.5), app.tokens.text);
if let Some(pos) = pointer
&& let Some(img) = &app.viewer_image
&& let Some(sample) = fw::sample_frame(img, crate::panels::viewer_tools::shown_region(painter.ctx(), map.comp), map.to_comp(pos))
{
let swatch = Rect::from_min_size(pos + vec2(14.0, 14.0), vec2(26.0, 18.0));
painter.rect_filled(swatch, 2.0, Color32::from_rgb((sample[0] * 255.0) as u8, (sample[1] * 255.0) as u8, (sample[2] * 255.0) as u8));
painter.rect_stroke(swatch, 2.0, Stroke::new(1.0, Color32::WHITE), egui::StrokeKind::Outside);
}
}
/// An armed text-colour pick: sample the shown frame on click, Esc cancels.
fn text_color_pick(
app: &mut EffectcraftApp,
@@ -128,7 +143,6 @@ fn text_color_pick(
ectx: &EvalCtx,
actions: &mut Actions,
) {
let t = app.tokens;
let ctx = ui.ctx().clone();
let Some(pick) = app.ui.text_color_pick.clone() else {
return;
@@ -140,20 +154,11 @@ fn text_color_pick(
app.viewer_pixels();
let resp = ui.interact(map.area, egui::Id::unique("viewer-text-color-pick"), Sense::click());
app.auto.add("viewer.textColorPick", map.area, &pick.field);
let chip = Rect::from_min_size(map.area.min + vec2(10.0, 10.0), vec2(220.0, 22.0));
painter.rect_filled(chip, 11.0, Color32::from_black_alpha(180));
painter.text(chip.center(), Align2::CENTER_CENTER, crate::i18n::tr_args("Click to sample text {}", &[&pick.field]), Tokens::ui(11.5), t.text);
color_pick_preview(app, painter, map, &crate::i18n::tr_args("Click to sample text {}", &[&pick.field]), resp.hover_pos());
if let Some(pos) = resp.hover_pos() {
ctx.set_cursor_icon(egui::CursorIcon::Crosshair);
let c = map.to_comp(pos);
app.pointer_comp = Some([c[0] as f32, c[1] as f32]);
if let Some(img) = &app.viewer_image
&& let Some(s) = fw::sample_frame(img, crate::panels::viewer_tools::shown_region(&ctx, map.comp), c)
{
let sw = Rect::from_min_size(pos + vec2(14.0, 14.0), vec2(26.0, 18.0));
painter.rect_filled(sw, 2.0, Color32::from_rgb((s[0] * 255.0) as u8, (s[1] * 255.0) as u8, (s[2] * 255.0) as u8));
painter.rect_stroke(sw, 2.0, Stroke::new(1.0, Color32::WHITE), egui::StrokeKind::Outside);
}
}
if resp.clicked()
&& let Some(pos) = resp.interact_pointer_pos()
@@ -180,7 +185,6 @@ fn text_color_pick(
/// the pointer, and the next press on it samples the frame into the picker. The press is read from
/// the pointer, since a modal dialog over the viewer takes its clicks.
fn popup_eyedropper(app: &mut EffectcraftApp, ui: &mut egui::Ui, painter: &egui::Painter, map: &crate::panels::viewer::ViewerMap) {
let t = app.tokens;
let ctx = ui.ctx().clone();
if !crate::color_picker::eyedropper_armed(&ctx) {
return;
@@ -190,17 +194,7 @@ fn popup_eyedropper(app: &mut EffectcraftApp, ui: &mut egui::Ui, painter: &egui:
app.auto.add("viewer.colorPickerEyedropper", map.area, "Sample color");
ctx.set_cursor_icon(egui::CursorIcon::Crosshair);
app.viewer_pixels();
let chip = Rect::from_min_size(map.area.min + vec2(10.0, 10.0), vec2(220.0, 22.0));
painter.rect_filled(chip, 11.0, Color32::from_black_alpha(180));
painter.text(chip.center(), Align2::CENTER_CENTER, "Click to sample color", Tokens::ui(11.5), t.text);
if let Some(hp) = crate::color_picker::eyedropper_point(&ctx)
&& let Some(img) = &app.viewer_image
&& let Some(s) = fw::sample_frame(img, crate::panels::viewer_tools::shown_region(&ctx, map.comp), map.to_comp(hp))
{
let sw = Rect::from_min_size(hp + vec2(14.0, 14.0), vec2(26.0, 18.0));
painter.rect_filled(sw, 2.0, Color32::from_rgb((s[0] * 255.0) as u8, (s[1] * 255.0) as u8, (s[2] * 255.0) as u8));
painter.rect_stroke(sw, 2.0, Stroke::new(1.0, Color32::WHITE), egui::StrokeKind::Outside);
}
color_pick_preview(app, painter, map, crate::i18n::tr("Click to sample color"), crate::color_picker::eyedropper_point(&ctx));
if let Some(pos) = crate::color_picker::sample_press(&ctx)
&& let Some(img) = &app.viewer_image
&& let Some(s) = fw::sample_frame(img, crate::panels::viewer_tools::shown_region(&ctx, map.comp), map.to_comp(pos))