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); + } }