feat(clipboard): PASTESPEC pastes in a chosen format

PASTESPEC offers the formats on the clipboard: Objects and Block for
objects copied in the application (the PASTECLIP and PASTEBLOCK paths),
and Text for the system clipboard's text, placed as multi-line text in
the current text style with its lines as paragraphs.

Refs #645

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Hakan SevenandClaude Opus 5.5 committed 2026-10-13 15:06:58 +03:00
1 parent 4ffae00199
commit b1d4c9bd9b
29 files changed
+242 -1

No files matched your search

+30
View File
@@ -95,6 +95,23 @@ impl OpenCADStudio {
}
}
/// PASTESPEC with the formats on hand: the copied objects, and `text`
/// from the system clipboard once it has been read.
pub(in crate::app) fn paste_special_command(
&self,
i: usize,
text: Option<&str>,
) -> Box<dyn CadCommand> {
let document = &self.tabs[i].scene.document;
let defaults = crate::scene::creation_style::current_text_defaults(document);
Box::new(crate::modules::draw::clipboard::pastespec::PasteSpecCommand::new(
!self.clipboard.is_empty(),
text,
defaults.style_name,
defaults.height,
))
}
pub(super) fn dispatch_blocks(&mut self, cmd: &str, i: usize) -> Option<Task<Message>> {
match cmd {
// ── BASE — drawing insertion base point ───────────────────────
@@ -284,6 +301,19 @@ impl OpenCADStudio {
}
}
// PASTESPEC — offer the copied objects now; the system clipboard's
// text joins the formats once read (Message::PasteSpecial).
"PASTESPEC" => {
let command = self.paste_special_command(i, None);
let started = self.start_count_command(i, command);
#[cfg(target_arch = "wasm32")]
let read = Task::perform(crate::sys::read_clipboard_text(), Message::PasteSpecial);
#[cfg(not(target_arch = "wasm32"))]
let read = iced::clipboard::read_text()
.map(|result| Message::PasteSpecial(result.ok().map(|text| (*text).clone())));
return Some(Task::batch([started, read]));
}
// PASTEORIG — paste at the entities' original coordinates (no pick).
"PASTEORIG" => {
if self.clipboard.is_empty() {