forked from 1b-agent/opencadstudio-upstream
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:
1 parent
4ffae00199
commit
b1d4c9bd9b
29 files changed
+242
-1
No files matched your search
@@ -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() {
|
||||
|
||||
@@ -188,7 +188,7 @@ impl OpenCADStudio {
|
||||
}
|
||||
}
|
||||
|
||||
fn start_count_command(&mut self, i: usize, command: Box<dyn CadCommand>) -> Task<Message> {
|
||||
pub(in crate::app) fn start_count_command(&mut self, i: usize, command: Box<dyn CadCommand>) -> Task<Message> {
|
||||
self.reset_command_start_state(i);
|
||||
self.command_line.push_info(&command.prompt());
|
||||
self.tabs[i].active_cmd = Some(command);
|
||||
|
||||
@@ -2360,6 +2360,8 @@ pub enum Message {
|
||||
PasteShortcut,
|
||||
/// Which text input held focus when `PasteShortcut` arrived.
|
||||
PasteShortcutResolved(PasteFocus),
|
||||
/// Completion of the system text clipboard read PASTESPEC starts.
|
||||
PasteSpecial(Option<String>),
|
||||
/// Completion of a system text clipboard read requested by PASTECLIP.
|
||||
SystemClipboardPaste(SystemClipboardText),
|
||||
/// Web: completion of the clipboard-image read the paste fallback starts
|
||||
|
||||
@@ -6815,6 +6815,32 @@ impl OpenCADStudio {
|
||||
}
|
||||
}
|
||||
|
||||
Message::PasteSpecial(text) => {
|
||||
let i = self.active_tab;
|
||||
let waiting = self.tabs[i]
|
||||
.active_cmd
|
||||
.as_ref()
|
||||
.is_some_and(|command| command.name() == "PASTESPEC");
|
||||
if !waiting {
|
||||
return Task::none();
|
||||
}
|
||||
match text.filter(|text| !text.trim().is_empty()) {
|
||||
Some(text) => {
|
||||
// Same prompt, one more option: swap without echoing it.
|
||||
self.tabs[i].active_cmd = Some(self.paste_special_command(i, Some(&text)));
|
||||
self.push_ucs_to_cmd(i);
|
||||
Task::none()
|
||||
}
|
||||
None if self.clipboard.is_empty() => {
|
||||
self.tabs[i].active_cmd = None;
|
||||
self.command_line
|
||||
.push_error(crate::tr!("clipboard", "no-supported-content").as_ref());
|
||||
Task::none()
|
||||
}
|
||||
None => Task::none(),
|
||||
}
|
||||
}
|
||||
|
||||
Message::SystemClipboardPaste(result) => {
|
||||
use super::SystemClipboardText as Text;
|
||||
|
||||
|
||||
Reference in new issue
Block a user