diff --git a/src/Beutl.Language/Strings.Designer.cs b/src/Beutl.Language/Strings.Designer.cs
index 1340fae21..64c422d99 100644
--- a/src/Beutl.Language/Strings.Designer.cs
+++ b/src/Beutl.Language/Strings.Designer.cs
@@ -2306,5 +2306,11 @@ public static string DockArea_TopRight {
return ResourceManager.GetString("DockArea_TopRight", resourceCulture);
}
}
+
+ public static string MoveTo {
+ get {
+ return ResourceManager.GetString("MoveTo", resourceCulture);
+ }
+ }
}
}
diff --git a/src/Beutl.Language/Strings.ja.resx b/src/Beutl.Language/Strings.ja.resx
index fc9276282..a1207a7ec 100644
--- a/src/Beutl.Language/Strings.ja.resx
+++ b/src/Beutl.Language/Strings.ja.resx
@@ -1249,4 +1249,7 @@ b-editorがダウンロードURLを管理します。
上 右
+
+ 移動
+
diff --git a/src/Beutl.Language/Strings.resx b/src/Beutl.Language/Strings.resx
index 9010c6ff8..efe80f63a 100644
--- a/src/Beutl.Language/Strings.resx
+++ b/src/Beutl.Language/Strings.resx
@@ -1249,4 +1249,7 @@ and b-editor maintains the download URL.
Top Right
+
+ Move to
+
diff --git a/src/Beutl/ViewModels/DockHostViewModel.cs b/src/Beutl/ViewModels/DockHostViewModel.cs
index 01691c889..135663e54 100644
--- a/src/Beutl/ViewModels/DockHostViewModel.cs
+++ b/src/Beutl/ViewModels/DockHostViewModel.cs
@@ -221,11 +221,19 @@ public void CloseToolTab(IToolContext item)
_logger.LogInformation("CloseToolTab {ToolName}", item.Extension.Name);
try
{
+ item.IsSelected.Value = false;
foreach (ReactiveCollection tools in GetNestedTools())
{
if (tools.FirstOrDefault(x => x.Context == item) is { } found)
{
+ int index = tools.IndexOf(found);
tools.Remove(found);
+ index = Math.Min(index, tools.Count - 1);
+ if (0 <= index && index < tools.Count)
+ {
+ tools[index].Context.IsSelected.Value = true;
+ }
+
break;
}
}
diff --git a/src/Beutl/Views/CustomSideBarButtonMenuFlyout.cs b/src/Beutl/Views/CustomSideBarButtonMenuFlyout.cs
new file mode 100644
index 000000000..a3534b18a
--- /dev/null
+++ b/src/Beutl/Views/CustomSideBarButtonMenuFlyout.cs
@@ -0,0 +1,105 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Controls.Templates;
+using Avalonia.Interactivity;
+using Avalonia.VisualTree;
+using Beutl.ViewModels;
+using ReDocking;
+
+namespace Beutl.Views;
+
+public class CustomSideBarButtonMenuFlyout : MenuFlyout
+{
+ private readonly ReDockHost _dockHost;
+
+ public CustomSideBarButtonMenuFlyout(ReDockHost dockHost)
+ {
+ _dockHost = dockHost;
+ var list = new List();
+
+ {
+ var moveMenu = new MenuItem();
+ moveMenu.Header = Strings.MoveTo;
+ moveMenu.ItemsSource = dockHost.DockAreas;
+ moveMenu.DataTemplates.Add(new FuncDataTemplate(_ => true,
+ o => new TextBlock
+ {
+ [!TextBlock.TextProperty] = o.GetObservable(DockArea.LocalizedNameProperty).ToBinding(),
+ }));
+
+ moveMenu.AddHandler(MenuItem.ClickEvent, OnMoveToSubItemClick);
+ list.Add(moveMenu);
+ }
+
+ {
+ var closeMenu = new MenuItem();
+ closeMenu.Header = Strings.Close;
+ closeMenu.AddHandler(MenuItem.ClickEvent, OnCloseClick);
+ list.Add(closeMenu);
+ }
+
+ if (dockHost.IsFloatingEnabled)
+ {
+ var displayMenu = new MenuItem();
+ displayMenu.Header = "Display mode";
+ displayMenu.ItemsSource = new List
+ {
+ new MenuItem { Header = "Docked", Tag = DockableDisplayMode.Docked },
+ new MenuItem { Header = "Floating", Tag = DockableDisplayMode.Floating },
+ };
+ displayMenu.AddHandler(MenuItem.ClickEvent, OnDisplayModeClick);
+ list.Add(displayMenu);
+ }
+
+ ItemsSource = list;
+ }
+
+ private void OnCloseClick(object? sender, RoutedEventArgs e)
+ {
+ if (Target is not SideBarButton button) return;
+ if (button is not { DataContext: ToolTabViewModel tabViewModel }) return;
+ if (button.FindAncestorOfType() is not { DataContext: EditViewModel viewModel }) return;
+
+ viewModel.CloseToolTab(tabViewModel.Context);
+ }
+
+ private void OnDisplayModeClick(object? sender, RoutedEventArgs e)
+ {
+ if (e.Source is MenuItem { Tag: DockableDisplayMode mode } &&
+ Target is SideBarButton button)
+ {
+ var args = new SideBarButtonDisplayModeChangedEventArgs(ReDockHost.ButtonDisplayModeChangedEvent, this)
+ {
+ DisplayMode = mode, Item = button.DataContext, Button = button
+ };
+ _dockHost.RaiseEvent(args);
+ }
+ }
+
+ private void OnMoveToSubItemClick(object? sender, RoutedEventArgs e)
+ {
+ if (e.Source is MenuItem { DataContext: DockArea area } &&
+ Target is SideBarButton button)
+ {
+ // Target
+ var oldSideBar = button.FindAncestorOfType();
+ var newSideBar = area.SideBar;
+ if (oldSideBar is null || newSideBar is null) return;
+ var oldLocation = button.DockLocation;
+ var newLocation = area.Location;
+ if (oldLocation is null || oldLocation == newLocation) return;
+
+ var args = new SideBarButtonMoveEventArgs(ReDockHost.ButtonMoveEvent, this)
+ {
+ Item = button.DataContext,
+ Button = button,
+ SourceSideBar = oldSideBar,
+ SourceLocation = oldLocation,
+ DestinationSideBar = newSideBar,
+ DestinationLocation = newLocation,
+ DestinationIndex = 0
+ };
+ _dockHost.RaiseEvent(args);
+ }
+ }
+}
diff --git a/src/Beutl/Views/EditView.axaml b/src/Beutl/Views/EditView.axaml
index f972c8cda..cd1d12f54 100644
--- a/src/Beutl/Views/EditView.axaml
+++ b/src/Beutl/Views/EditView.axaml
@@ -42,6 +42,7 @@
diff --git a/src/Beutl/Views/EditView.axaml.cs b/src/Beutl/Views/EditView.axaml.cs
index 91d8679eb..c8fd47764 100644
--- a/src/Beutl/Views/EditView.axaml.cs
+++ b/src/Beutl/Views/EditView.axaml.cs
@@ -55,7 +55,7 @@ private void OnSideBarButtonDisplayModeChanged(object? sender, SideBarButtonDisp
{
}
- private ReactiveCollection GetItemsSource(DockAreaLocation location)
+ internal ReactiveCollection GetItemsSource(DockAreaLocation location)
{
var sideBar = DockHost.DockAreas.FirstOrDefault(i => i.SideBar?.Location == location.LeftRight)?.SideBar;
@@ -156,4 +156,20 @@ private void OnSideBarButtonDrop(object? sender, SideBarButtonMoveEventArgs e)
e.Handled = true;
}
+
+ private void OnSideBarButtonFlyoutRequested(object? sender, SideBarButtonFlyoutRequestedEventArgs e)
+ {
+ e.Handled = true;
+ var flyout = new CustomSideBarButtonMenuFlyout(e.DockHost);
+ if (e.Button.DockLocation?.LeftRight == SideBarLocation.Left)
+ {
+ flyout.Placement = PlacementMode.Right;
+ }
+ else
+ {
+ flyout.Placement = PlacementMode.Left;
+ }
+
+ flyout.ShowAt(e.Button);
+ }
}