yoda: add ↑↓ buttons next to drag handle in toolbar editor

DnD source+destination wiring from 1cf17dc builds but the drag-drop
doesn't fire reliably in practice (suspected: either dnd_source's
shell.capture_event() on CursorMoved swallows events the destination
needs to see, or intra-window DnD has a Wayland-specific hiccup on the
current sctk/cosmic-comp pairing).

Adds two plain click-handled buttons per enabled row (↑ go-up-symbolic,
↓ go-down-symbolic, both disabled at list edges) so reorder is
functional regardless of DnD state. Backed by new messages
ToolbarMoveUp / ToolbarMoveDown that swap adjacent positions in the
Vec<ToolbarAction>.

The drag handle + DnD source/destination wrapping stays in place — if
DnD gets fixed upstream or on a future libcosmic it'll Just Work, and
the arrows remain as a keyboard-friendly fallback.
This commit is contained in:
Lionel DARNIS 2026-04-24 08:29:07 +02:00
parent 1cf17dcde8
commit 11d435770e

View file

@ -551,6 +551,10 @@ pub enum Message {
ToolbarAdd(ToolbarAction),
ToolbarRemove(ToolbarAction),
ToolbarReorder { src: ToolbarAction, target: ToolbarAction },
/// Move one step up (toward index 0) inside the enabled toolbar list.
ToolbarMoveUp(ToolbarAction),
/// Move one step down (toward the end) inside the enabled toolbar list.
ToolbarMoveDown(ToolbarAction),
ToolbarReset,
SetTypeToSearch(TypeToSearch),
SystemThemeModeChange,
@ -2416,12 +2420,27 @@ impl App {
.into()
};
let row_enabled = |action: ToolbarAction| -> Element<'_, Message> {
let row_enabled = |action: ToolbarAction, pos: usize, last: usize| -> Element<'_, Message> {
let (icon, label, _msg) = toolbar_action_ui(action);
let up_btn = widget::button::icon(widget::icon::from_name("go-up-symbolic").size(14));
let up_btn = if pos > 0 {
up_btn.on_press(Message::ToolbarMoveUp(action))
} else {
up_btn
};
let down_btn = widget::button::icon(widget::icon::from_name("go-down-symbolic").size(14));
let down_btn = if pos < last {
down_btn.on_press(Message::ToolbarMoveDown(action))
} else {
down_btn
};
let row_content: Element<_> = widget::row::with_children(vec![
drag_icon(14),
widget::icon::from_name(icon).size(16).into(),
widget::text::body(label).width(Length::Fill).into(),
up_btn.into(),
down_btn.into(),
widget::button::icon(widget::icon::from_name("list-remove-symbolic").size(14))
.on_press(Message::ToolbarRemove(action))
.into(),
@ -2476,8 +2495,9 @@ impl App {
section = section
.add(widget::text::body(fl!("toolbar-empty-hint")));
} else {
for a in enabled.iter().copied() {
section = section.add(row_enabled(a));
let last = enabled.len() - 1;
for (pos, a) in enabled.iter().copied().enumerate() {
section = section.add(row_enabled(a, pos, last));
}
}
@ -4615,6 +4635,28 @@ impl Application for App {
}
return Task::none();
}
Message::ToolbarMoveUp(action) => {
let mut tb = self.config.toolbar.clone();
if let Some(i) = tb.iter().position(|a| a == &action)
&& i > 0
{
tb.swap(i, i - 1);
config_set!(toolbar, tb);
return self.update_config();
}
return Task::none();
}
Message::ToolbarMoveDown(action) => {
let mut tb = self.config.toolbar.clone();
if let Some(i) = tb.iter().position(|a| a == &action)
&& i + 1 < tb.len()
{
tb.swap(i, i + 1);
config_set!(toolbar, tb);
return self.update_config();
}
return Task::none();
}
Message::ToolbarReset => {
config_set!(toolbar, default_toolbar());
return self.update_config();