From 11d435770eb69f116334a48bfe0d729c8c685c71 Mon Sep 17 00:00:00 2001 From: leyoda Date: Fri, 24 Apr 2026 08:29:07 +0200 Subject: [PATCH] =?UTF-8?q?yoda:=20add=20=E2=86=91=E2=86=93=20buttons=20ne?= =?UTF-8?q?xt=20to=20drag=20handle=20in=20toolbar=20editor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. 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. --- src/app.rs | 48 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/src/app.rs b/src/app.rs index 868fad7..1dbf6e6 100644 --- a/src/app.rs +++ b/src/app.rs @@ -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();