fix(ui): Double-clicking the Fill or Stroke box opens the Color Picker
In InDesign a double-click on the Tools panel's Fill or Stroke box opens the Color Picker; DesignCraft opened the Swatches panel. It now opens the Color Picker for that box, with the selection's colour (the selected text's when text is selected). The Stroke box also reports its name to screen readers. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
d020b4e85d
commit
03d8b1e61b
|
|
@ -132,6 +132,7 @@ Newest first.
|
|||
- **2026-10-12** · Window close and application/menu Quit ask about unsaved documents; later Cancel keeps every tab open, including earlier Don't Save choices. Approvals are rechecked after edits. Cancelable macOS Dock Quit remains open (#544). No readiness percentage change.
|
||||
- **2026-10-12** · Each running app keeps recovery data in its own locked folder; current folder and lock ownership are checked before writes and cleanup. Failed isolation disables recovery with a warning instead of sharing document IDs. No readiness percentage change.
|
||||
- **2026-10-12** · Native engine saves and exports replace files atomically; failed writes retain the original, private staging preserves Unix permissions, and valid long filenames work. Desktop Services and CLI raster exports remain separate follow-ups. No readiness percentage change.
|
||||
- **2026-10-12** · Double-clicking the Fill or Stroke box in the Tools panel opens the Color Picker with the selection's colour, as in InDesign (it opened the Swatches panel). No readiness percentage change.
|
||||
- **2026-10-12** · Words in capitals hyphenate like capitalized words (FERRUM COM-MODI), as in InDesign; Hyphenate Capitalized Words off keeps them whole. No readiness percentage change.
|
||||
- **2026-10-11** · `transform.move {copy}`, Edit › Duplicate and Step and Repeat return the copies' ids, so a script can go on with them. No readiness percentage change.
|
||||
- **2026-10-11** · `object.fill` and `object.stroke` refuse a swatch name the document doesn't have (it painted nothing) and suggest the name meant (`Paper` → `[Paper]`). No readiness percentage change.
|
||||
|
|
|
|||
|
|
@ -272,16 +272,31 @@ fn fill_stroke_proxy(app: &mut DesignApp, ui: &mut egui::Ui, width: f32) {
|
|||
crate::rtl::label(ui, fill_tip);
|
||||
});
|
||||
fresp.widget_info(|| egui::WidgetInfo::labeled(egui::WidgetType::Button, true, fill_tip));
|
||||
let stroke_tip = crate::i18n::tr(&app.ui.language, "Stroke (X)");
|
||||
let sresp = ui.interact(stroke_r.translate(vec2(0.0, 0.0)), ui.id().with("proxy_stroke"), Sense::click()).on_hover_ui(|ui| {
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Stroke (X)"));
|
||||
crate::rtl::label(ui, stroke_tip);
|
||||
});
|
||||
sresp.widget_info(|| egui::WidgetInfo::labeled(egui::WidgetType::Button, true, stroke_tip));
|
||||
if fresp.clicked() || sresp.clicked() {
|
||||
let front =
|
||||
if stroke_front { !fresp.clicked() } else { sresp.clicked() && !fill_r.contains(sresp.interact_pointer_pos().unwrap_or_default()) };
|
||||
ui.data_mut(|d| d.insert_temp(stroke_front_id, front));
|
||||
}
|
||||
// A double-click opens the Color Picker for that box (as InDesign's), with the selection's
|
||||
// colour: the selected text's when text is selected.
|
||||
if fresp.double_clicked() || sresp.double_clicked() {
|
||||
let _ = app.run("window.panel", json!({"panel": "swatches"}));
|
||||
let on_fill = fresp.double_clicked() && (!stroke_front || !sresp.double_clicked());
|
||||
let stroke = !on_fill;
|
||||
let text = crate::panels::text_attrs(app).filter(|_| app.session.active().is_some_and(|d| d.selection.text.is_some()));
|
||||
let current = match text {
|
||||
Some(a) => a["chars"][if stroke { "stroke" } else { "fill" }].as_str().unwrap_or("[None]").to_string(),
|
||||
None if stroke => stroke_sw.clone(),
|
||||
None => fill_sw.clone(),
|
||||
};
|
||||
let rgb = doc.as_ref().and_then(|d| d.resolve_color(¤t, 1.0)).map_or([0.0; 3], |c| c.to_rgb());
|
||||
let byte = |v: f32| (v.clamp(0.0, 1.0) * 255.0).round() as u8;
|
||||
let hex = format!("#{:02x}{:02x}{:02x}", byte(rgb[0]), byte(rgb[1]), byte(rgb[2]));
|
||||
app.ui.dialog = Some(crate::dialogs::Dialog::new("colorPicker", json!({"target": if stroke { "stroke" } else { "fill" }, "hex": hex})));
|
||||
}
|
||||
ui.add_space(3.0);
|
||||
// Formatting affects container / text.
|
||||
|
|
@ -472,6 +487,36 @@ mod tests {
|
|||
assert!(!h.state().app.ui.tools_double_column);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn double_clicking_the_fill_box_opens_the_color_picker_with_the_selections_colour() {
|
||||
let mut app = app(false);
|
||||
app.run("file.new", serde_json::json!({})).unwrap();
|
||||
let id = app.run("frame.create", serde_json::json!({"rect": [72, 72, 200, 200]})).unwrap()["id"].clone();
|
||||
app.run("object.color", serde_json::json!({"color": "#456daf", "ids": [id]})).unwrap();
|
||||
app.run("selection.set", serde_json::json!({"ids": [id]})).unwrap();
|
||||
// Frames 1 ms apart, so two clicks make a double-click.
|
||||
let mut h = egui_kittest::Harness::builder().with_size(vec2(1400.0, 900.0)).with_step_dt(0.001).build_ui_state(
|
||||
|ui, app: &mut crate::DesignApp| {
|
||||
let ctx = ui.ctx().clone();
|
||||
app.logic(&ctx);
|
||||
app.ui(ui);
|
||||
},
|
||||
app,
|
||||
);
|
||||
h.run_steps(6);
|
||||
let at = h.get_by_label(FILL).rect().center();
|
||||
h.hover_at(at);
|
||||
h.step();
|
||||
for pressed in [true, false, true, false] {
|
||||
h.event(egui::Event::PointerButton { pos: at, button: egui::PointerButton::Primary, pressed, modifiers: Default::default() });
|
||||
h.step();
|
||||
}
|
||||
h.run_steps(3);
|
||||
let d = h.state().ui.dialog.clone().expect("the Color Picker opened");
|
||||
assert_eq!(d.id, "colorPicker");
|
||||
assert_eq!((d.fields["target"].as_str(), d.fields["hex"].as_str()), (Some("fill"), Some("#456daf")), "{:?}", d.fields);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_tall_window_keeps_one_column_and_does_not_scroll() {
|
||||
let mut h = test_window::open(app(false), vec2(1400.0, 900.0));
|
||||
|
|
|
|||
Loading…
Reference in New Issue