mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-10-14 19:27:04 -04:00
V, H and Space pick the Select and Hand tools (#281)
The quick toolbar's tooltips read "Select (V)" and "Hand (H)", but nothing listened for either key. V now selects, H picks the Hand, and holding Space pans with the Hand until it is released, as in Acrobat. They are plain letters, so not while a text field, a form field, a dialog or the palette has the keyboard, and not with a modifier held. The shortcuts dialog lists them (reusing the translated tooltips) and the view.hand-tool parity entry cites the new test. Claude-Session: https://claude.ai/code/session_01NH3itd85jPuM6wNjgcGfEH Co-authored-by: wstock <[email protected]> Co-authored-by: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
4 files changed
+84
-2
No files matched your search
@@ -1031,6 +1031,8 @@ pub fn show(app: &mut PdfCraftApp, ctx: &egui::Context) {
|
||||
("⇧⌘+ / ⇧⌘−", tl!("Rotate view")),
|
||||
("Home / End", tl!("First / last page")),
|
||||
("← / →, ⌘← / ⌘→", tl!("Previous / next page")),
|
||||
("V", tl!("Select (V)")),
|
||||
("H / Space (hold)", tl!("Hand (H)")),
|
||||
("Delete", tl!("Delete selected pages (Organize)")),
|
||||
("⌘A", tl!("Select all pages (Organize)")),
|
||||
] {
|
||||
|
||||
@@ -330,6 +330,8 @@ pub struct PdfCraftApp {
|
||||
pub left_open: bool,
|
||||
pub right: Option<RightPanel>,
|
||||
pub quick_tool: QuickTool,
|
||||
/// The tool to go back to when Space, held for a temporary Hand, is released.
|
||||
space_hand: Option<QuickTool>,
|
||||
/// Comment author, per-tool colours and widths, pin.
|
||||
pub comment_prefs: comments::CommentPrefs,
|
||||
/// Resolved colours, including the current OS theme when following the system.
|
||||
@@ -558,6 +560,7 @@ impl PdfCraftApp {
|
||||
left_open: true,
|
||||
right: None,
|
||||
quick_tool: QuickTool::Select,
|
||||
space_hand: None,
|
||||
comment_prefs: Default::default(),
|
||||
theme: ThemeKind::Light,
|
||||
theme_preference: ThemePreference::Light,
|
||||
@@ -1366,11 +1369,46 @@ impl PdfCraftApp {
|
||||
{
|
||||
self.views[i].select_all();
|
||||
}
|
||||
self.tool_keys(i, ctx);
|
||||
canvas::shortcuts(&mut self.views[i], ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PdfCraftApp {
|
||||
/// The quick tools' keys, as in Acrobat: V selects, H pans, and holding Space pans until it
|
||||
/// is released. Plain letters, so not while a text field, a form field, a dialog or the
|
||||
/// palette has the keyboard.
|
||||
fn tool_keys(&mut self, i: usize, ctx: &egui::Context) {
|
||||
use egui::Key;
|
||||
let free = self.dialog.is_none() && !self.palette_open && !ctx.egui_wants_keyboard_input() && self.views[i].forms.focus.is_none();
|
||||
let (plain, space) = ctx.input(|input| (input.modifiers.is_none(), input.key_down(Key::Space)));
|
||||
if let Some(previous) = self.space_hand
|
||||
&& !space
|
||||
{
|
||||
self.space_hand = None;
|
||||
if self.quick_tool == QuickTool::Hand {
|
||||
self.quick_tool = previous;
|
||||
}
|
||||
}
|
||||
if !free || !plain {
|
||||
return;
|
||||
}
|
||||
if ctx.input(|input| input.key_pressed(Key::V)) {
|
||||
self.quick_tool = QuickTool::Select;
|
||||
self.space_hand = None;
|
||||
}
|
||||
if ctx.input(|input| input.key_pressed(Key::H)) {
|
||||
self.quick_tool = QuickTool::Hand;
|
||||
self.space_hand = None;
|
||||
}
|
||||
if space && self.space_hand.is_none() && self.quick_tool != QuickTool::Hand {
|
||||
self.space_hand = Some(self.quick_tool);
|
||||
self.quick_tool = QuickTool::Hand;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl eframe::App for PdfCraftApp {
|
||||
fn save(&mut self, storage: &mut dyn eframe::Storage) {
|
||||
storage.set_string("pdfcraft", self.persist());
|
||||
|
||||
@@ -472,6 +472,48 @@ fn arrow_and_page_keys_move_through_a_scrolling_document() {
|
||||
assert_eq!(press(&mut h, Key::PageDown, 1), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn v_h_and_space_pick_the_quick_tools() {
|
||||
// The toolbar's tooltips promise "Select (V)" and "Hand (H)", but the keys did nothing.
|
||||
use egui::{Key, Modifiers};
|
||||
use pdfcraft_ui_egui::QuickTool;
|
||||
let mut h = harness();
|
||||
h.state_mut().active = Some(0);
|
||||
h.run_steps(2);
|
||||
let press = |h: &mut Harness<'static, PdfCraftApp>, key| {
|
||||
h.key_press(key);
|
||||
h.run_steps(2);
|
||||
h.state().quick_tool
|
||||
};
|
||||
assert_eq!(press(&mut h, Key::H), QuickTool::Hand);
|
||||
assert_eq!(press(&mut h, Key::V), QuickTool::Select);
|
||||
// V leaves any other tool too, as the toolbar button does.
|
||||
h.state_mut().quick_tool = QuickTool::Crop;
|
||||
assert_eq!(press(&mut h, Key::V), QuickTool::Select);
|
||||
// Holding Space pans with the Hand for as long as it is held, then gives the tool back.
|
||||
h.state_mut().quick_tool = QuickTool::Crop;
|
||||
h.key_down(Key::Space);
|
||||
h.run_steps(4);
|
||||
assert_eq!(h.state().quick_tool, QuickTool::Hand, "Space held");
|
||||
h.key_up(Key::Space);
|
||||
h.run_steps(2);
|
||||
assert_eq!(h.state().quick_tool, QuickTool::Crop, "Space released");
|
||||
// With a modifier the letters are someone else's shortcut.
|
||||
h.key_press_modifiers(Modifiers::SHIFT, Key::H);
|
||||
h.run_steps(2);
|
||||
assert_eq!(h.state().quick_tool, QuickTool::Crop);
|
||||
// They are letters to a text field: typing in the find bar keeps the tool.
|
||||
h.state_mut().quick_tool = QuickTool::Select;
|
||||
h.state_mut().views[0].open_find();
|
||||
h.run_steps(4);
|
||||
assert_eq!(press(&mut h, Key::H), QuickTool::Select, "typing H in the find bar");
|
||||
h.key_down(Key::Space);
|
||||
h.run_steps(2);
|
||||
h.key_up(Key::Space);
|
||||
h.run_steps(2);
|
||||
assert_eq!(h.state().quick_tool, QuickTool::Select, "typing a space in the find bar");
|
||||
}
|
||||
|
||||
/// Like [`fixture`], with each page's size given.
|
||||
fn sized_fixture(sizes: &[(u32, u32)]) -> Vec<u8> {
|
||||
let n = sizes.len();
|
||||
|
||||
@@ -1034,8 +1034,8 @@ milestone = "M3"
|
||||
status = "shipped"
|
||||
commands = []
|
||||
tools = []
|
||||
evidence = ["crates/ui-egui/tests/view.rs::the_hand_tool_pans_by_dragging"]
|
||||
notes = "drag to pan; Grab/Grabbing cursors"
|
||||
evidence = ["crates/ui-egui/tests/view.rs::the_hand_tool_pans_by_dragging", "crates/ui-egui/tests/viewer.rs::v_h_and_space_pick_the_quick_tools"]
|
||||
notes = "drag to pan; Grab/Grabbing cursors; H picks it, V goes back to Select, Space held pans temporarily"
|
||||
|
||||
[[feature]]
|
||||
id = "view.rotate-view"
|
||||
|
||||
Reference in new issue
Block a user