fix(ui): refine command line and clipboard
- preserve command history colors after reopening - remove collapsed command bar residue and split the unsaved prompt - read system text when the drawing clipboard is empty Refs #467 Refs #468 Refs #470
This commit is contained in:
parent
d1f9055901
commit
9cf0c9f945
14 changed files with 245 additions and 40 deletions
|
|
@ -193,7 +193,7 @@ impl OpenCADStudio {
|
|||
|
||||
"PASTECLIP" => {
|
||||
if self.clipboard.is_empty() {
|
||||
self.command_line.push_error(crate::t!("Clipboard is empty.").as_ref());
|
||||
return Some(self.read_system_clipboard_for_paste());
|
||||
} else {
|
||||
let wires = self.tabs[i].scene.wires_for_entities(&self.clipboard);
|
||||
let base = self.clipboard_base;
|
||||
|
|
|
|||
|
|
@ -1586,10 +1586,11 @@ pub enum Message {
|
|||
crate::scene::text::web_font::Script,
|
||||
Result<(), String>,
|
||||
),
|
||||
/// Ctrl+V. Routed by `update`: into the open text/MText editor (via an async
|
||||
/// system-clipboard read, which is the only paste path that works on the
|
||||
/// web) or, with no editor open, the entity paste command.
|
||||
/// Ctrl+V. Routed by `update` into an open text editor, the drawing-object
|
||||
/// clipboard, or the system text clipboard.
|
||||
PasteShortcut,
|
||||
/// Completion of a system text clipboard read requested by PASTECLIP.
|
||||
SystemClipboardPaste(SystemClipboardText),
|
||||
/// Ctrl/Cmd+A — select all layer rows when the Layer Manager is open, or all
|
||||
/// drawing objects otherwise (#236).
|
||||
SelectAllShortcut,
|
||||
|
|
@ -2791,6 +2792,15 @@ pub enum Message {
|
|||
),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum SystemClipboardText {
|
||||
Text(String),
|
||||
EmptyOrUnsupported,
|
||||
Unavailable,
|
||||
Occupied,
|
||||
ConversionFailed,
|
||||
}
|
||||
|
||||
impl OpenCADStudio {
|
||||
/// Install the Start-page video list, decoding each thumbnail's JPEG into
|
||||
/// an image Handle exactly once (a fresh Handle per view frame would
|
||||
|
|
|
|||
|
|
@ -1259,7 +1259,44 @@ pub(super) fn on_tab_close(&mut self, idx: usize) -> Task<Message> {
|
|||
#[cfg(not(target_arch = "wasm32"))]
|
||||
return Task::none();
|
||||
}
|
||||
Task::done(Message::Command("PASTECLIP".to_string()))
|
||||
if self.clipboard.is_empty() {
|
||||
self.read_system_clipboard_for_paste()
|
||||
} else {
|
||||
Task::done(Message::Command("PASTECLIP".to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
pub(in crate::app) fn read_system_clipboard_for_paste(&self) -> Task<Message> {
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
{
|
||||
Task::perform(crate::sys::read_clipboard_text(), |text| {
|
||||
Message::SystemClipboardPaste(match text {
|
||||
Some(text) if !text.is_empty() => {
|
||||
crate::app::SystemClipboardText::Text(text)
|
||||
}
|
||||
_ => crate::app::SystemClipboardText::EmptyOrUnsupported,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
{
|
||||
iced::clipboard::read_text().map(|result| {
|
||||
use crate::app::SystemClipboardText as Text;
|
||||
use iced::clipboard::Error;
|
||||
|
||||
let result = match result {
|
||||
Ok(text) if !text.is_empty() => Text::Text((*text).clone()),
|
||||
Ok(_) | Err(Error::ContentNotAvailable) => Text::EmptyOrUnsupported,
|
||||
Err(Error::ClipboardUnavailable) | Err(Error::Unknown { .. }) => {
|
||||
Text::Unavailable
|
||||
}
|
||||
Err(Error::ClipboardOccupied) => Text::Occupied,
|
||||
Err(Error::ConversionFailure) => Text::ConversionFailed,
|
||||
};
|
||||
Message::SystemClipboardPaste(result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn on_qselect_open(&mut self) -> Task<Message> {
|
||||
|
|
|
|||
|
|
@ -3585,10 +3585,44 @@ impl OpenCADStudio {
|
|||
// Ctrl+V. The MText editor and (on the web) the TEXT editor read the
|
||||
// system clipboard asynchronously — the only paste path that works
|
||||
// in the browser, where the synchronous clipboard the iced
|
||||
// text_input expects is empty. With no editor open it falls through
|
||||
// to the entity paste command.
|
||||
// text_input expects is empty. With no editor open, drawing objects
|
||||
// take priority and system text is used when that clipboard is empty.
|
||||
Message::PasteShortcut => self.on_paste_shortcut(),
|
||||
|
||||
Message::SystemClipboardPaste(result) => {
|
||||
use super::SystemClipboardText as Text;
|
||||
|
||||
match result {
|
||||
Text::Text(text) => {
|
||||
let flat = text.replace(['\r', '\n'], " ").to_uppercase();
|
||||
self.command_line.input.push_str(&flat);
|
||||
self.command_line.autocomplete_cursor = None;
|
||||
self.focus_cmd_input()
|
||||
}
|
||||
Text::EmptyOrUnsupported => {
|
||||
self.command_line.push_error(
|
||||
crate::tr!("clipboard-no-supported-content").as_ref(),
|
||||
);
|
||||
Task::none()
|
||||
}
|
||||
Text::Unavailable => {
|
||||
self.command_line
|
||||
.push_error(crate::tr!("clipboard-unavailable").as_ref());
|
||||
Task::none()
|
||||
}
|
||||
Text::Occupied => {
|
||||
self.command_line
|
||||
.push_error(crate::tr!("clipboard-occupied").as_ref());
|
||||
Task::none()
|
||||
}
|
||||
Text::ConversionFailed => {
|
||||
self.command_line
|
||||
.push_error(crate::tr!("clipboard-conversion-failed").as_ref());
|
||||
Task::none()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Message::SelectAllShortcut => {
|
||||
let i = self.active_tab;
|
||||
if self.mtext_editor.as_ref().is_some_and(|e| e.show_preview) {
|
||||
|
|
|
|||
|
|
@ -1475,14 +1475,13 @@ fn unsaved_changes_dialog_window(
|
|||
name: &str,
|
||||
sizing: crate::ui::modal::ModalSizing,
|
||||
) -> Element<'static, Message> {
|
||||
let body_text = t!(
|
||||
"Do you want to save changes to \"%{name}\"?",
|
||||
name = name
|
||||
);
|
||||
|
||||
container(
|
||||
column![
|
||||
text(body_text).size(13),
|
||||
text(name.to_owned()).size(14),
|
||||
iced::widget::Space::new().height(4),
|
||||
text(crate::tr!("modal-unsaved-save-prompt"))
|
||||
.size(12)
|
||||
.style(dialog_muted_text_style),
|
||||
iced::widget::Space::new().height(20),
|
||||
row![
|
||||
dialog_button(t!("Save"), Message::UnsavedDialogSave, button::primary),
|
||||
|
|
|
|||
Loading…
Reference in a new issue