From f6ecfc995f8eceaa1fe2c8d5a849f9fccb06ae9a Mon Sep 17 00:00:00 2001 From: Mika Kuns Date: Thu, 25 Jun 2026 16:36:09 +0200 Subject: [PATCH] feat(ui): drag-reorder Mission Control panes by their header --- .../MissionControlView.axaml.cs | 40 ++++++++++++++++++- .../MissionControl/MonitorPaneView.axaml | 4 +- .../MissionControl/MonitorPaneView.axaml.cs | 18 +++++++++ 3 files changed, 60 insertions(+), 2 deletions(-) diff --git a/src/ClaudeDo.Ui/Views/MissionControl/MissionControlView.axaml.cs b/src/ClaudeDo.Ui/Views/MissionControl/MissionControlView.axaml.cs index 74ba752..1e3f706 100644 --- a/src/ClaudeDo.Ui/Views/MissionControl/MissionControlView.axaml.cs +++ b/src/ClaudeDo.Ui/Views/MissionControl/MissionControlView.axaml.cs @@ -1,8 +1,46 @@ +using System.Linq; using Avalonia.Controls; +using Avalonia.Input; +using Avalonia.Interactivity; +using Avalonia.VisualTree; +using ClaudeDo.Ui.ViewModels; +using ClaudeDo.Ui.ViewModels.Islands; namespace ClaudeDo.Ui.Views.MissionControl; public partial class MissionControlView : UserControl { - public MissionControlView() => InitializeComponent(); + // Shared with MonitorPaneView (the drag source). + public static readonly DataFormat PaneFormat = + DataFormat.CreateStringApplicationFormat("claudedo-monitor-pane"); + + public MissionControlView() + { + InitializeComponent(); + AddHandler(DragDrop.DragOverEvent, OnPaneDragOver); + AddHandler(DragDrop.DropEvent, OnPaneDrop); + } + + private void OnPaneDragOver(object? sender, DragEventArgs e) + { + e.DragEffects = (e.DataTransfer?.Contains(PaneFormat) ?? false) + ? DragDropEffects.Move + : DragDropEffects.None; + } + + private void OnPaneDrop(object? sender, DragEventArgs e) + { + if (DataContext is not MissionControlViewModel vm) return; + var draggedId = e.DataTransfer?.TryGetValue(PaneFormat); + if (string.IsNullOrEmpty(draggedId)) return; + if (e.Source is not Avalonia.Visual src) return; + + var targetPane = src.FindAncestorOfType(); + if (targetPane?.DataContext is not TaskMonitorViewModel target) return; + + var dragged = vm.Monitors.FirstOrDefault(m => m.SubscribedTaskId == draggedId); + if (dragged is null) return; + + vm.MoveMonitor(dragged, target); + } } diff --git a/src/ClaudeDo.Ui/Views/MissionControl/MonitorPaneView.axaml b/src/ClaudeDo.Ui/Views/MissionControl/MonitorPaneView.axaml index b448efc..df2ab48 100644 --- a/src/ClaudeDo.Ui/Views/MissionControl/MonitorPaneView.axaml +++ b/src/ClaudeDo.Ui/Views/MissionControl/MonitorPaneView.axaml @@ -6,6 +6,7 @@ x:DataType="vm:TaskMonitorViewModel" x:Class="ClaudeDo.Ui.Views.MissionControl.MonitorPaneView"> + BorderThickness="0,0,0,1" Padding="6,3" + PointerPressed="OnHeaderPressed">