mirror of
https://github.com/storytold/designcraft.git
synced 2026-11-14 14:22:39 +00:00
Place: Escape drops the current loaded image and loads the next (place.skip)
This commit is contained in:
1 parent
7f0c2818f2
commit
91f78b2db9
4 files changed
+48
-3
No files matched your search
@@ -425,6 +425,13 @@ fn advance_place_cursor(s: &mut Session) {
|
||||
}
|
||||
}
|
||||
|
||||
/// Drop the current loaded image without placing it and move to the next; the last one ends placing.
|
||||
pub(super) fn place_skip(s: &mut Session, _p: &Value) -> Result<Value> {
|
||||
validate_place_cursor(s, "place.skip")?;
|
||||
advance_place_cursor(s);
|
||||
Ok(json!({"remaining": loaded_count(s)}))
|
||||
}
|
||||
|
||||
/// Validate bounded grid dimensions and a finite nonnegative gutter.
|
||||
fn grid_dimensions(p: &Value, command: &str, default_columns: usize, default_rows: usize) -> Result<(usize, usize, f64)> {
|
||||
let dimension = |key, default| -> Result<usize> {
|
||||
@@ -651,6 +658,32 @@ pub(super) mod image_place_tests {
|
||||
}
|
||||
}
|
||||
|
||||
fn test_png(shade: u8) -> String {
|
||||
let png = designcraft_render::Rendered { width: 4, height: 4, pixels: vec![shade; 4 * 4 * 4] }.to_png();
|
||||
crate::cmd::base64_encode(&png)
|
||||
}
|
||||
|
||||
fn loaded_names(s: &Session) -> Vec<String> {
|
||||
let d = &s.doc().unwrap().doc;
|
||||
s.loaded.iter().chain(s.loaded_queue.iter()).map(|g| d.assets[&g.asset].name.clone()).collect()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn skip_drops_the_current_image_and_the_last_one_ends_placing() {
|
||||
let mut s = Session::new();
|
||||
s.execute("file.new", &json!({})).unwrap();
|
||||
let files: Vec<_> = (0..3).map(|i| json!({"base64": test_png(i as u8), "name": format!("{i}.png")})).collect();
|
||||
s.execute("place.load", &json!({"files": files})).unwrap();
|
||||
assert_eq!(s.execute("place.skip", &json!({})).unwrap()["remaining"], 2);
|
||||
assert_eq!(loaded_names(&s), ["1.png", "2.png"]);
|
||||
s.execute("place.skip", &json!({})).unwrap();
|
||||
assert_eq!(s.tool_id(), "placeGun");
|
||||
s.execute("place.skip", &json!({})).unwrap();
|
||||
assert!(s.loaded.is_none());
|
||||
assert_eq!(s.tool_id(), "selection");
|
||||
assert!(s.execute("place.skip", &json!({})).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn consecutive_path_placements_create_distinct_graphics() {
|
||||
let images = [image_file_with_color(30).unwrap(), image_file_with_color(31).unwrap(), image_file_with_color(32).unwrap()];
|
||||
|
||||
@@ -3,7 +3,7 @@ use super::EngineError;
|
||||
use super::bytes::{base64_encode, to_bytes, to_bytes_with_preview, with_document_extension};
|
||||
use super::new::{file_new, file_sample, save_preset};
|
||||
use super::open::{file_open, file_open_bytes, file_open_recent, has_recent, recent_entry};
|
||||
use super::place::{file_place, place_contact_sheet, place_drop, place_grid, place_load, read_source};
|
||||
use super::place::{file_place, place_contact_sheet, place_drop, place_grid, place_load, place_skip, read_source};
|
||||
use super::save::{FolderAccess, can_revert, file_revert, file_save, recovery_dir};
|
||||
use super::snippets::{snippet_export, snippet_place};
|
||||
use super::{CommandSpec, PRESETS, Value, always, bad, cmd, has_doc, json, ok, str_param};
|
||||
@@ -160,7 +160,8 @@ pub fn specs() -> Vec<CommandSpec> {
|
||||
has_doc,
|
||||
place_contact_sheet
|
||||
),
|
||||
cmd!(noundo "place.cancel", "Cancel Image Placement", [], None, "{}", has_doc, |s, _| {
|
||||
cmd!(noundo "place.skip", "Skip Loaded Image", [], None, "{} — drops the current loaded image without placing it and loads the next; the last one ends placing", has_doc, place_skip),
|
||||
cmd!(noundo "place.cancel", "Cancel Image Placement", [], None, "{} — clears every loaded image", has_doc, |s, _| {
|
||||
s.loaded = None;
|
||||
s.loaded_queue.clear();
|
||||
s.set_tool("selection");
|
||||
|
||||
@@ -173,9 +173,10 @@ impl Tool for PlaceGun {
|
||||
}
|
||||
fn key(&mut self, _cx: &ToolContext, key: crate::ToolKey, _mods: Mods) -> Vec<Action> {
|
||||
use crate::ToolKey;
|
||||
// Escape drops the current image and loads the next; `place.cancel` clears them all.
|
||||
if key == ToolKey::Escape {
|
||||
self.start = None;
|
||||
return vec![Action::Exec("place.cancel".into(), json!({}))];
|
||||
return vec![Action::Exec("place.skip".into(), json!({}))];
|
||||
}
|
||||
// During a drag the arrow keys change the grid, and are handled even when it is already
|
||||
// at its limit, so they don't go on to nudge the selection.
|
||||
|
||||
@@ -2527,6 +2527,16 @@ fn place_gun_grid_arrow_keys_are_handled_during_a_drag() {
|
||||
assert!(t.key(&cx, ToolKey::Delete, Mods::default()).is_empty());
|
||||
}
|
||||
|
||||
/// Escape drops only the current loaded image; `place.cancel` clears them all.
|
||||
#[test]
|
||||
fn place_gun_escape_skips_the_current_image() {
|
||||
let d = Document::new(&NewDocument::default());
|
||||
let (s, c, l) = (Selection::default(), Cache::new(), CanvasLayout::new(&d, false));
|
||||
let cx = ctx(&d, &s, &c, &l);
|
||||
let mut t = create("placeGun");
|
||||
assert_eq!(t.key(&cx, ToolKey::Escape, Mods::default()), vec![Action::Exec("place.skip".into(), serde_json::json!({}))]);
|
||||
}
|
||||
|
||||
/// A place-cursor grid drag too thin for its cells shows and places the single frame an ordinary
|
||||
/// drag would; one with room shows its cells and places the grid.
|
||||
#[test]
|
||||
|
||||
Reference in new issue
Block a user