diff --git a/src/Editor/Ghost.Editor/Themes/DockingDictionary.xaml b/src/Editor/Ghost.Editor/Themes/DockingDictionary.xaml index 13dd43f..fb4c973 100644 --- a/src/Editor/Ghost.Editor/Themes/DockingDictionary.xaml +++ b/src/Editor/Ghost.Editor/Themes/DockingDictionary.xaml @@ -7,6 +7,7 @@ + \ No newline at end of file diff --git a/src/Editor/Ghost.Editor/View/Controls/Docking/DockDocument.xaml b/src/Editor/Ghost.Editor/View/Controls/Docking/DockDocument.xaml new file mode 100644 index 0000000..2693a12 --- /dev/null +++ b/src/Editor/Ghost.Editor/View/Controls/Docking/DockDocument.xaml @@ -0,0 +1,21 @@ + + + + diff --git a/src/Editor/Ghost.Editor/View/Controls/Docking/DockGroup.cs b/src/Editor/Ghost.Editor/View/Controls/Docking/DockGroup.cs index c769f63..279c740 100644 --- a/src/Editor/Ghost.Editor/View/Controls/Docking/DockGroup.cs +++ b/src/Editor/Ghost.Editor/View/Controls/Docking/DockGroup.cs @@ -115,70 +115,41 @@ public partial class DockGroup : DockContainer var selectedDoc = _tabView.SelectedItem is TabViewItem selectedItem ? selectedItem.Tag as DockDocument : null; - // Remove tabs that are no longer in Children - for (int i = _tabView.TabItems.Count - 1; i >= 0; i--) + // Detach all existing tabs + foreach (var item in _tabView.TabItems) { - if (_tabView.TabItems[i] is TabViewItem tabItem && tabItem.Tag is DockDocument doc) + if (item is TabViewItem tabItem) { - if (!Children.Contains(doc)) - { - tabItem.ClearValue(ContentControl.ContentProperty); - tabItem.Content = null; - _tabView.TabItems.RemoveAt(i); - } + tabItem.Content = null; } } + _tabView.TabItems.Clear(); TabViewItem? newSelectedItem = null; - // Add tabs that are in Children but not in TabItems, and ensure correct order - for (int i = 0; i < Children.Count; i++) + foreach (var child in Children) { - if (Children[i] is DockDocument doc) + if (child is DockDocument doc) { - TabViewItem? existingTab = null; - for (int j = 0; j < _tabView.TabItems.Count; j++) + var tabItem = new TabViewItem { - if (_tabView.TabItems[j] is TabViewItem tabItem && tabItem.Tag == doc) - { - existingTab = tabItem; - // Fix order if necessary - if (j != i) - { - _tabView.TabItems.RemoveAt(j); - _tabView.TabItems.Insert(i, existingTab); - } - break; - } - } + Tag = doc + }; - if (existingTab == null) + tabItem.SetBinding(TabViewItem.HeaderProperty, new Microsoft.UI.Xaml.Data.Binding { - existingTab = new TabViewItem - { - Tag = doc - }; + Source = doc, + Path = new PropertyPath(nameof(DockDocument.Title)), + Mode = Microsoft.UI.Xaml.Data.BindingMode.OneWay + }); - existingTab.SetBinding(TabViewItem.HeaderProperty, new Binding - { - Source = doc, - Path = new PropertyPath(nameof(DockDocument.Title)), - Mode = BindingMode.OneWay - }); + tabItem.Content = doc; - existingTab.SetBinding(ContentControl.ContentProperty, new Binding - { - Source = doc, - Path = new PropertyPath(nameof(DockDocument.Content)), - Mode = BindingMode.OneWay - }); - - _tabView.TabItems.Insert(i, existingTab); - } + _tabView.TabItems.Add(tabItem); if (doc == selectedDoc) { - newSelectedItem = existingTab; + newSelectedItem = tabItem; } } } diff --git a/src/Editor/Ghost.Editor/View/Controls/Docking/DockPanel.cs b/src/Editor/Ghost.Editor/View/Controls/Docking/DockPanel.cs index 69f0bdc..0b007e3 100644 --- a/src/Editor/Ghost.Editor/View/Controls/Docking/DockPanel.cs +++ b/src/Editor/Ghost.Editor/View/Controls/Docking/DockPanel.cs @@ -1,6 +1,6 @@ -using CommunityToolkit.WinUI.Controls; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; +using CommunityToolkit.WinUI.Controls; namespace Ghost.Editor.View.Controls.Docking; @@ -8,10 +8,10 @@ namespace Ghost.Editor.View.Controls.Docking; /// A container that can host multiple dock modules with splitters. /// [TemplatePart(Name = PART_GRID, Type = typeof(Grid))] -public partial class DockPanel : DockContainer +public class DockPanel : DockContainer { private const string PART_GRID = "PART_Grid"; - private const double SPLITTER_THICKNESS = 1; + private const double SPLITTER_THICKNESS = 4; public static readonly DependencyProperty OrientationProperty = DependencyProperty.Register( nameof(Orientation), typeof(Orientation), typeof(DockPanel), new PropertyMetadata(Orientation.Horizontal, OnOrientationChanged)); @@ -74,123 +74,44 @@ public partial class DockPanel : DockContainer { if (_grid == null) return; - // Remove splitters and children that are no longer in the collection - for (int i = _grid.Children.Count - 1; i >= 0; i--) - { - var child = _grid.Children[i]; - if (child is GridSplitter) - { - _grid.Children.RemoveAt(i); - } - else if (child is DockModule module && !Children.Contains(module)) - { - _grid.Children.RemoveAt(i); - } - } + _grid.Children.Clear(); + _grid.RowDefinitions.Clear(); + _grid.ColumnDefinitions.Clear(); - if (Children.Count == 0) - { - _grid.RowDefinitions.Clear(); - _grid.ColumnDefinitions.Clear(); - return; - } + if (Children.Count == 0) return; if (Orientation == Orientation.Horizontal) { - _grid.RowDefinitions.Clear(); - - int requiredColumns = (Children.Count * 2) - 1; - while (_grid.ColumnDefinitions.Count > requiredColumns) + for (int i = 0; i < Children.Count; i++) { - _grid.ColumnDefinitions.RemoveAt(_grid.ColumnDefinitions.Count - 1); - } - - for (var i = 0; i < Children.Count; i++) - { - int columnIndex = i * 2; - if (columnIndex >= _grid.ColumnDefinitions.Count) - { - _grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) }); - } - else - { - _grid.ColumnDefinitions[columnIndex].Width = new GridLength(1, GridUnitType.Star); - } - + _grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) }); var child = Children[i]; - if (!_grid.Children.Contains(child)) - { - _grid.Children.Add(child); - } - - Grid.SetColumn(child, columnIndex); - Grid.SetRow(child, 0); + Grid.SetColumn(child, i * 2); + _grid.Children.Add(child); if (i < Children.Count - 1) { - int splitterIndex = i * 2 + 1; - if (splitterIndex >= _grid.ColumnDefinitions.Count) - { - _grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto }); - } - else - { - _grid.ColumnDefinitions[splitterIndex].Width = GridLength.Auto; - } - + _grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto }); var splitter = new GridSplitter { ResizeDirection = GridSplitter.GridResizeDirection.Columns, Width = SPLITTER_THICKNESS }; - Grid.SetColumn(splitter, splitterIndex); - Grid.SetRow(splitter, 0); + Grid.SetColumn(splitter, i * 2 + 1); _grid.Children.Add(splitter); } } } else { - _grid.ColumnDefinitions.Clear(); - - int requiredRows = (Children.Count * 2) - 1; - while (_grid.RowDefinitions.Count > requiredRows) + for (int i = 0; i < Children.Count; i++) { - _grid.RowDefinitions.RemoveAt(_grid.RowDefinitions.Count - 1); - } - - for (var i = 0; i < Children.Count; i++) - { - int rowIndex = i * 2; - if (rowIndex >= _grid.RowDefinitions.Count) - { - _grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) }); - } - else - { - _grid.RowDefinitions[rowIndex].Height = new GridLength(1, GridUnitType.Star); - } - + _grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) }); var child = Children[i]; - if (!_grid.Children.Contains(child)) - { - _grid.Children.Add(child); - } - - Grid.SetRow(child, rowIndex); - Grid.SetColumn(child, 0); + Grid.SetRow(child, i * 2); + _grid.Children.Add(child); if (i < Children.Count - 1) { - int splitterIndex = i * 2 + 1; - if (splitterIndex >= _grid.RowDefinitions.Count) - { - _grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); - } - else - { - _grid.RowDefinitions[splitterIndex].Height = GridLength.Auto; - } - + _grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); var splitter = new GridSplitter { ResizeDirection = GridSplitter.GridResizeDirection.Rows, Height = SPLITTER_THICKNESS }; - Grid.SetRow(splitter, splitterIndex); - Grid.SetColumn(splitter, 0); + Grid.SetRow(splitter, i * 2 + 1); _grid.Children.Add(splitter); } } diff --git a/src/Editor/Ghost.Editor/View/Controls/ProjectBrowser.xaml b/src/Editor/Ghost.Editor/View/Controls/ProjectBrowser.xaml index 3a3e305..959502a 100644 --- a/src/Editor/Ghost.Editor/View/Controls/ProjectBrowser.xaml +++ b/src/Editor/Ghost.Editor/View/Controls/ProjectBrowser.xaml @@ -152,7 +152,6 @@ diff --git a/src/Editor/Ghost.Editor/View/Controls/ProjectBrowser.xaml.cs b/src/Editor/Ghost.Editor/View/Controls/ProjectBrowser.xaml.cs index 7eb931d..4563234 100644 --- a/src/Editor/Ghost.Editor/View/Controls/ProjectBrowser.xaml.cs +++ b/src/Editor/Ghost.Editor/View/Controls/ProjectBrowser.xaml.cs @@ -17,9 +17,6 @@ internal sealed partial class ProjectBrowser : UserControl private readonly IInspectorService _inspectorService; private bool _isUpdatingSelection = false; - private double _savedHorizontalOffset; - private double _savedVerticalOffset; - private ScrollViewer? _filesScrollViewer; public ProjectBrowserViewModel ViewModel { @@ -52,43 +49,12 @@ internal sealed partial class ProjectBrowser : UserControl private void ProjectBrowser_Loaded(object sender, RoutedEventArgs e) { _inspectorService.OnSelectionChanged += _inspectorService_OnSelectionChanged; - PART_FilesView.UpdateLayout(); - - DispatcherQueue.TryEnqueue(Microsoft.UI.Dispatching.DispatcherQueuePriority.Low, () => - { - if (_filesScrollViewer == null) - { - _filesScrollViewer = FindVisualChild(PART_FilesView); - } - - if (_filesScrollViewer != null) - { - // Sometimes resetting the ItemsSource helps clear corrupted virtualization state - var itemsSource = PART_FilesView.ItemsSource; - PART_FilesView.ItemsSource = null; - PART_FilesView.ItemsSource = itemsSource; - - PART_FilesView.UpdateLayout(); - _filesScrollViewer.ChangeView(_savedHorizontalOffset, _savedVerticalOffset, null, true); - } - }); } private void ProjectBrowser_Unloaded(object sender, RoutedEventArgs e) { _inspectorService.OnSelectionChanged -= _inspectorService_OnSelectionChanged; - if (_filesScrollViewer == null) - { - _filesScrollViewer = FindVisualChild(PART_FilesView); - } - - if (_filesScrollViewer != null) - { - _savedHorizontalOffset = _filesScrollViewer.HorizontalOffset; - _savedVerticalOffset = _filesScrollViewer.VerticalOffset; - } - if (LastFocused == this) { LastFocused = null; @@ -104,26 +70,6 @@ internal sealed partial class ProjectBrowser : UserControl } } - private static T? FindVisualChild(DependencyObject parent) where T : DependencyObject - { - for (int i = 0; i < Microsoft.UI.Xaml.Media.VisualTreeHelper.GetChildrenCount(parent); i++) - { - var child = Microsoft.UI.Xaml.Media.VisualTreeHelper.GetChild(parent, i); - if (child is T t) - { - return t; - } - - var result = FindVisualChild(child); - if (result != null) - { - return result; - } - } - - return null; - } - private void PART_DirectoriesView_SelectionChanged(TreeView sender, TreeViewSelectionChangedEventArgs args) { if (_isUpdatingSelection)