mirror of
https://github.com/storytold/deckcraft.git
synced 2026-10-25 19:17:06 -06:00
Pasted shapes get the next automatic name instead of keeping the original's (fixes #1290)
This commit is contained in:
@@ -358,7 +358,15 @@ fn paste(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
let mut shapes = clip.shapes.clone();
|
||||
reid("edit.paste", doc, &mut shapes)?;
|
||||
remap_media(&mut shapes, &media);
|
||||
for sh in &mut shapes {
|
||||
let taken = super::current_shapes(doc, sel).map_or(0, Vec::len);
|
||||
for (k, sh) in shapes.iter_mut().enumerate() {
|
||||
// An automatic name ("Rectangle 3") counts on from this slide, as a new shape would;
|
||||
// a name the user typed stays.
|
||||
let base = super::insert::auto_name_base(sh);
|
||||
let numbered = sh.name.strip_prefix(base.as_str()).and_then(|r| r.strip_prefix(' '));
|
||||
if numbered.is_some_and(|d| !d.is_empty() && d.bytes().all(|b| b.is_ascii_digit())) {
|
||||
sh.name = format!("{base} {}", taken + k + 1);
|
||||
}
|
||||
if let Some(x) = sh.xfrm.as_mut() {
|
||||
x.x += off;
|
||||
x.y += off;
|
||||
|
||||
@@ -149,25 +149,30 @@ fn default_rect(s: &Session, w: f64, h: f64) -> Xfrm {
|
||||
Xfrm::new((size.width - w) / 2.0, (size.height - h) / 2.0, w, h)
|
||||
}
|
||||
|
||||
/// The word an automatic shape name starts with ("Rectangle" in "Rectangle 3").
|
||||
pub(crate) fn auto_name_base(shape: &Shape) -> String {
|
||||
match &shape.kind {
|
||||
ShapeKind::Picture { .. } => "Picture".to_string(),
|
||||
ShapeKind::Table(_) => "Table".to_string(),
|
||||
ShapeKind::Chart(_) => "Chart".to_string(),
|
||||
ShapeKind::Media(m) if m.video => "Video".to_string(),
|
||||
ShapeKind::Media(_) => "Audio".to_string(),
|
||||
ShapeKind::Model3d { .. } => "3D Model".to_string(),
|
||||
_ if shape.text_box => "TextBox".to_string(),
|
||||
_ => shape
|
||||
.geom
|
||||
.preset_name()
|
||||
.and_then(deckcraft_geom::preset::info)
|
||||
.map(|i| i.label.split(':').next().unwrap_or(i.label).trim().to_string())
|
||||
.unwrap_or_else(|| "Shape".into()),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn add_shape(s: &mut Session, cmd: &str, mut shape: Shape, select: bool) -> Result<ShapeId> {
|
||||
s.edit(|doc, sel| {
|
||||
shape.id = ShapeId(doc.alloc_id().ok_or_else(|| bad(cmd, NO_ID_SPACE))?);
|
||||
if shape.name.is_empty() {
|
||||
let base = match &shape.kind {
|
||||
ShapeKind::Picture { .. } => "Picture".to_string(),
|
||||
ShapeKind::Table(_) => "Table".to_string(),
|
||||
ShapeKind::Chart(_) => "Chart".to_string(),
|
||||
ShapeKind::Media(m) if m.video => "Video".to_string(),
|
||||
ShapeKind::Media(_) => "Audio".to_string(),
|
||||
ShapeKind::Model3d { .. } => "3D Model".to_string(),
|
||||
_ if shape.text_box => "TextBox".to_string(),
|
||||
_ => shape
|
||||
.geom
|
||||
.preset_name()
|
||||
.and_then(deckcraft_geom::preset::info)
|
||||
.map(|i| i.label.split(':').next().unwrap_or(i.label).trim().to_string())
|
||||
.unwrap_or_else(|| "Shape".into()),
|
||||
};
|
||||
let base = auto_name_base(&shape);
|
||||
let n = super::current_shapes(doc, sel).map(|v| v.len()).unwrap_or(0) + 1;
|
||||
shape.name = format!("{base} {n}");
|
||||
}
|
||||
|
||||
@@ -210,6 +210,29 @@ fn clipboard_copy_paste_shapes_and_slides() {
|
||||
assert!(s.doc().unwrap().doc.validate().is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pasted_shapes_get_the_next_automatic_name() {
|
||||
let mut s = session();
|
||||
let names = |s: &Session| s.doc().unwrap().current_slide().unwrap().shapes.iter().map(|x| x.name.clone()).collect::<Vec<_>>();
|
||||
let before = names(&s).len();
|
||||
s.execute("shape.insert", &json!({"preset": "rect", "rect": [10, 10, 50, 50]})).unwrap();
|
||||
let auto = names(&s)[before].clone();
|
||||
s.execute("edit.copy", &json!({})).unwrap();
|
||||
s.execute("edit.paste", &json!({})).unwrap();
|
||||
s.execute("edit.paste", &json!({})).unwrap();
|
||||
let all = names(&s);
|
||||
let base = auto.rsplit_once(' ').unwrap().0;
|
||||
assert_eq!(all[before + 1], format!("{base} {}", before + 2));
|
||||
assert_eq!(all[before + 2], format!("{base} {}", before + 3));
|
||||
|
||||
// A name the user chose is not an automatic one and stays on the copy.
|
||||
let id = s.doc().unwrap().selection.shapes[0].0;
|
||||
s.execute("shape.rename", &json!({"id": id, "name": "Hero"})).unwrap();
|
||||
s.execute("edit.copy", &json!({})).unwrap();
|
||||
s.execute("edit.paste", &json!({})).unwrap();
|
||||
assert_eq!(names(&s).last().unwrap(), "Hero");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bold_copy_is_html_and_pages_html_pastes_bold() {
|
||||
let mut s = session();
|
||||
|
||||
Reference in New Issue
Block a user