yoda: direct drag-drop reorder on the toolbar itself
User feedback: going through Settings to reorder is too indirect. Now each toolbar button is wrapped in dnd_source + dnd_destination so the user can grab an icon in the live toolbar and drop it onto another icon to reorder in-place. The underlying icon button keeps firing its on_press for quick clicks (dnd_source only starts a drag past the default 8 px motion threshold), so regular clicks continue to run the associated Action — no mode-switch needed. Settings retains the ↑↓/add/remove UI as a fallback (discoverability + keyboard-friendly) and for the same drag-drop if the user prefers working from the panel. The config model (Vec<ToolbarAction> + ToolbarReorder message) is already shared, so both paths mutate the same state.
This commit is contained in:
parent
11d435770e
commit
af843d204d
1 changed files with 25 additions and 6 deletions
31
src/app.rs
31
src/app.rs
|
|
@ -6807,25 +6807,44 @@ impl Application for App {
|
|||
|
||||
// Yoda phase 3: Dolphin-style quick actions toolbar. Items are
|
||||
// rendered from self.config.toolbar (Vec<ToolbarAction>) — the user
|
||||
// picks the set AND the order via drag-drop in Settings. Dispatch
|
||||
// goes through Action::message so keybinding and toolbar share the
|
||||
// same code path.
|
||||
// picks the set AND the order via direct drag-drop on the toolbar.
|
||||
// Short click = action (shared Action::message dispatch); drag past
|
||||
// the default 8px threshold = reorder (ToolbarReorder message).
|
||||
if !self.config.toolbar.is_empty() {
|
||||
use cosmic::iced::clipboard::dnd::DndAction as DndAct;
|
||||
let clipboard_has = self.clipboard_has_content();
|
||||
let buttons: Vec<Element<_>> = self
|
||||
.config
|
||||
.toolbar
|
||||
.iter()
|
||||
.map(|a| {
|
||||
let (icon, label, msg) = toolbar_action_ui(*a);
|
||||
let enabled = !matches!(a, ToolbarAction::Paste) || clipboard_has;
|
||||
let action = *a;
|
||||
let (icon, label, msg) = toolbar_action_ui(action);
|
||||
let enabled = !matches!(action, ToolbarAction::Paste) || clipboard_has;
|
||||
let btn = widget::button::icon(widget::icon::from_name(icon).size(16));
|
||||
let btn = if enabled { btn.on_press(msg) } else { btn };
|
||||
widget::tooltip(
|
||||
let tooltip = widget::tooltip(
|
||||
btn,
|
||||
widget::text::body(label),
|
||||
widget::tooltip::Position::Bottom,
|
||||
);
|
||||
let source = widget::dnd_source::<Message, ToolbarActionPayload>(tooltip)
|
||||
.drag_content(move || ToolbarActionPayload(action.to_u8()));
|
||||
widget::dnd_destination(
|
||||
source,
|
||||
vec![std::borrow::Cow::Borrowed(TOOLBAR_MIME)],
|
||||
)
|
||||
.data_received_for::<ToolbarActionPayload>(
|
||||
move |payload: Option<ToolbarActionPayload>| {
|
||||
match payload.and_then(|p| ToolbarAction::from_u8(p.0)) {
|
||||
Some(src) if src != action => {
|
||||
Message::ToolbarReorder { src, target: action }
|
||||
}
|
||||
_ => Message::ToolbarReorder { src: action, target: action },
|
||||
}
|
||||
},
|
||||
)
|
||||
.action(DndAct::Move)
|
||||
.into()
|
||||
})
|
||||
.collect();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue