mirror of
https://github.com/storytold/designcraft.git
synced 2026-11-11 16:30:16 -06:00
Merge PR #1076: Tools: a tool group's flyout closes on Esc and on a click outside it, as InDesign's
This commit is contained in:
@@ -465,6 +465,7 @@ Newest first.
|
||||
- **2026-10-15** · A panel tab's context menu (and the end of its panel menu) has InDesign's Close, Close Tab Group, Minimize and Collapse to Icons, before Float Panel and Group with; `window.panel.closeGroup` and `window.collapseToIcons` are commands. No readiness percentage change.
|
||||
- **2026-10-15** · Window › Styles › Paragraph Styles (or Character Styles) opens InDesign's floating Character Styles | Paragraph Styles group, which stays open while other panels open; it was a flyout that the next panel replaced. No readiness percentage change.
|
||||
- 2026-10-15: Double-clicking the status bar's preflight count or its light shows the Preflight panel, as in InDesign.
|
||||
- 2026-10-15: A tool group's flyout closes on Esc and on a click anywhere outside it (a panel, the Fill swatch), as InDesign's; it only closed on a click on the canvas.
|
||||
- **2026-10-14** · The Type tool draws a new text frame over a locked empty frame, as InDesign does, instead of turning the locked frame into a text frame. No readiness percentage change.
|
||||
- **2026-10-14** · 100% black shows as pure black on screen by default, as InDesign's Appearance of Black does out of the box (Display All Blacks as Rich Black); Preferences › Appearance of Black › Display All Blacks Accurately still shows it as the dark grey it prints, and a saved choice is kept. No readiness percentage change.
|
||||
- **2026-10-14** · Pathfinder keeps the frontmost object, as InDesign does: a photo placed over shapes and intersected with them shows through the shapes (it was dropped, and the shapes kept their black fill); Add, Exclude Overlap and Minus Back take the front object's fill too, Subtract still keeps the back one. No readiness percentage change.
|
||||
|
||||
@@ -45,6 +45,7 @@ pub fn show(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
ui.add_space(2.0);
|
||||
let current = app.session.tool_id();
|
||||
let mut chosen: Option<&'static str> = None;
|
||||
let mut opened_now = false;
|
||||
// A slot is a group (its current tool shown, the others in its flyout) or, in two
|
||||
// columns, one tool of a group InDesign lays out tool by tool.
|
||||
let mut row_items: Vec<Option<(usize, Option<usize>)>> = Vec::new();
|
||||
@@ -118,6 +119,7 @@ pub fn show(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
|| (resp.is_pointer_button_down_on()
|
||||
&& ui.input(|i| i.pointer.press_start_time().is_some_and(|s| i.time - s > 0.35))))
|
||||
{
|
||||
opened_now |= app.ui.flyout != Some(gi);
|
||||
app.ui.flyout = Some(gi);
|
||||
}
|
||||
if app.ui.flyout == Some(gi) {
|
||||
@@ -157,6 +159,7 @@ pub fn show(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
t.text_dim,
|
||||
);
|
||||
}
|
||||
row.widget_info(|| egui::WidgetInfo::labeled(egui::WidgetType::Button, true, tl.label));
|
||||
if row.clicked() {
|
||||
chosen = Some(tl.id);
|
||||
}
|
||||
@@ -178,8 +181,18 @@ pub fn show(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
if let Some(id) = chosen {
|
||||
app.select_tool(id);
|
||||
}
|
||||
if app.ui.flyout.is_some() && ui.input(|i| i.pointer.any_click()) && chosen.is_none() && !ui.ctx().is_pointer_over_egui() {
|
||||
app.ui.flyout = None;
|
||||
// As InDesign's, an open flyout closes on Esc and on a click anywhere outside it (a
|
||||
// panel, a swatch, the canvas), not only on the canvas.
|
||||
if let Some(gi) = app.ui.flyout
|
||||
&& chosen.is_none()
|
||||
&& !opened_now
|
||||
{
|
||||
let area = ui.ctx().memory(|m| m.area_rect(egui::Id::new(("flyout", gi))));
|
||||
let outside = ui.input(|i| i.pointer.any_click() && i.pointer.interact_pos().is_some_and(|p| area.is_none_or(|a| !a.contains(p))));
|
||||
let esc = ui.input_mut(|i| i.consume_key(egui::Modifiers::NONE, egui::Key::Escape));
|
||||
if outside || esc {
|
||||
app.ui.flyout = None;
|
||||
}
|
||||
}
|
||||
ui.add_space(8.0);
|
||||
fill_stroke_proxy(app, ui, width, cols);
|
||||
@@ -618,6 +631,39 @@ mod tests {
|
||||
h.get_by_label(label).rect()
|
||||
}
|
||||
|
||||
/// As InDesign's: a tool group's flyout closes on Esc and on a click outside it (the fill
|
||||
/// swatch, a panel), not only on the canvas.
|
||||
#[test]
|
||||
fn a_tool_flyout_closes_on_escape_and_on_a_click_elsewhere() {
|
||||
use egui::{Event, Modifiers, PointerButton};
|
||||
use egui_kittest::kittest::Queryable;
|
||||
let app = crate::DesignApp::new(designcraft_engine::Session::new(), crate::Services::default());
|
||||
let mut h = crate::test_window::open(app, vec2(1400.0, 900.0));
|
||||
let open = |h: &mut egui_kittest::Harness<'static, crate::test_window::Window>| {
|
||||
let at = h.get_by_label("Rectangle Frame Tool (F)").rect().center();
|
||||
h.input_mut().events.push(Event::PointerMoved(at));
|
||||
for pressed in [true, false] {
|
||||
h.input_mut().events.push(Event::PointerButton { pos: at, button: PointerButton::Secondary, pressed, modifiers: Modifiers::NONE });
|
||||
}
|
||||
h.run_steps(3);
|
||||
assert!(h.state().app.ui.flyout.is_some(), "a right-click opens the flyout");
|
||||
let _ = h.get_by_label("Ellipse Frame Tool");
|
||||
};
|
||||
open(&mut h);
|
||||
h.key_press(egui::Key::Escape);
|
||||
h.run_steps(2);
|
||||
assert!(h.state().app.ui.flyout.is_none(), "Esc closes it");
|
||||
// A click on a panel closes it.
|
||||
open(&mut h);
|
||||
crate::test_window::click_at(&mut h, egui::pos2(1300.0, 700.0));
|
||||
assert!(h.state().app.ui.flyout.is_none(), "a click elsewhere closes it");
|
||||
// Choosing a tool in it closes it and selects the tool.
|
||||
open(&mut h);
|
||||
h.get_by_label("Ellipse Frame Tool").click();
|
||||
h.run_steps(3);
|
||||
assert_eq!((h.state().app.session.tool_id(), h.state().app.ui.flyout), ("ellipseFrame", None));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_short_window_reaches_every_tool() {
|
||||
for double in [false, true] {
|
||||
|
||||
Reference in New Issue
Block a user