Доработан winui

This commit is contained in:
2026-02-01 09:26:13 +03:00
parent 584df249f6
commit e8b4cb9881
26 changed files with 1842 additions and 2373 deletions

View File

@@ -13,21 +13,6 @@ using System.Runtime.CompilerServices;
namespace Lattice.UI;
/// <summary>
/// Представляет кастомный контрол вкладок с поддержкой всех позиций размещения панели вкладок.
/// Реализует интерфейс <see cref="IDockLeafControl"/> для интеграции с системой докинга.
/// </summary>
/// <remarks>
/// <para>
/// Контрол обеспечивает отображение коллекции вкладок с возможностью навигации между ними,
/// закрытия вкладок и изменения порядка. Поддерживает все четыре позиции размещения панели
/// вкладок: сверху, снизу, слева и справа.
/// </para>
/// <para>
/// Контрол автоматически синхронизирует свое состояние с моделью данных <see cref="DockLeaf"/>
/// и обеспечивает двустороннюю привязку данных через механизм INotifyPropertyChanged.
/// </para>
/// </remarks>
public sealed class LatticeTabControl : Control, IDockLeafControl, IDisposable
{
private readonly PropertyChangedEventHandler _modelPropertyChangedHandler;
@@ -44,9 +29,6 @@ public sealed class LatticeTabControl : Control, IDockLeafControl, IDisposable
private bool _showCloseButtons = true;
private bool _canReorderTabs = true;
/// <summary>
/// Инициализирует новый экземпляр класса <see cref="LatticeTabControl"/>.
/// </summary>
public LatticeTabControl()
{
this.DefaultStyleKey = typeof(LatticeTabControl);
@@ -54,7 +36,6 @@ public sealed class LatticeTabControl : Control, IDockLeafControl, IDisposable
this.DataContextChanged += OnDataContextChanged;
}
/// <inheritdoc/>
public IDockElement? Model
{
get => _model;
@@ -68,7 +49,6 @@ public sealed class LatticeTabControl : Control, IDockLeafControl, IDisposable
}
}
/// <inheritdoc/>
public LayoutManager? LayoutManager
{
get => _layoutManager;
@@ -80,7 +60,6 @@ public sealed class LatticeTabControl : Control, IDockLeafControl, IDisposable
}
}
/// <inheritdoc/>
public IDockContextManager? ContextManager
{
get => _contextManager;
@@ -92,7 +71,6 @@ public sealed class LatticeTabControl : Control, IDockLeafControl, IDisposable
}
}
/// <inheritdoc/>
public bool IsSelected
{
get => _isSelected;
@@ -104,7 +82,6 @@ public sealed class LatticeTabControl : Control, IDockLeafControl, IDisposable
}
}
/// <inheritdoc/>
public bool IsActive
{
get => _isActive;
@@ -116,7 +93,9 @@ public sealed class LatticeTabControl : Control, IDockLeafControl, IDisposable
}
}
/// <inheritdoc/>
public bool CanDrag => true;
public bool CanDrop => true;
public TabPlacement TabPlacement
{
get => _tabPlacement;
@@ -131,7 +110,6 @@ public sealed class LatticeTabControl : Control, IDockLeafControl, IDisposable
}
}
/// <inheritdoc/>
public bool ShowCloseButtons
{
get => _showCloseButtons;
@@ -146,7 +124,6 @@ public sealed class LatticeTabControl : Control, IDockLeafControl, IDisposable
}
}
/// <inheritdoc/>
public bool CanReorderTabs
{
get => _canReorderTabs;
@@ -160,7 +137,6 @@ public sealed class LatticeTabControl : Control, IDockLeafControl, IDisposable
}
}
/// <inheritdoc/>
public IDockContent? ActiveContent
{
get => _model?.ActiveContent;
@@ -173,19 +149,14 @@ public sealed class LatticeTabControl : Control, IDockLeafControl, IDisposable
}
}
/// <inheritdoc/>
public object? PrepareDragData() => Model;
public bool HandleDrop(object data, DockPosition position) => false;
public event EventHandler<ActiveContentChangedEventArgs>? ActiveContentChanged;
/// <inheritdoc/>
public event EventHandler<ContentClosingEventArgs>? ContentClosing;
/// <inheritdoc/>
public event EventHandler<TabsReorderedEventArgs>? TabsReordered;
/// <inheritdoc/>
public event PropertyChangedEventHandler? PropertyChanged;
/// <inheritdoc/>
protected override void OnApplyTemplate()
{
base.OnApplyTemplate();
@@ -203,17 +174,11 @@ public sealed class LatticeTabControl : Control, IDockLeafControl, IDisposable
UpdateTabHeaders();
}
/// <summary>
/// Обрабатывает изменение контекста данных контрола.
/// </summary>
private void OnDataContextChanged(FrameworkElement sender, DataContextChangedEventArgs args)
{
Model = args.NewValue as DockLeaf;
}
/// <summary>
/// Присоединяет модель данных к контролу.
/// </summary>
private void AttachModel()
{
if (_model != null)
@@ -232,9 +197,6 @@ public sealed class LatticeTabControl : Control, IDockLeafControl, IDisposable
}
}
/// <summary>
/// Отсоединяет модель данных от контрола.
/// </summary>
private void DetachModel()
{
if (_model != null)
@@ -250,9 +212,6 @@ public sealed class LatticeTabControl : Control, IDockLeafControl, IDisposable
}
}
/// <summary>
/// Обрабатывает изменения свойств модели данных.
/// </summary>
private void OnModelPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
@@ -274,17 +233,11 @@ public sealed class LatticeTabControl : Control, IDockLeafControl, IDisposable
}
}
/// <summary>
/// Обрабатывает изменения коллекции вкладок.
/// </summary>
private void OnChildrenCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
UpdateTabHeaders();
}
/// <summary>
/// Обновляет положение панели вкладок.
/// </summary>
private void UpdateTabPlacement()
{
if (_rootGrid == null || _model == null) return;
@@ -322,10 +275,6 @@ public sealed class LatticeTabControl : Control, IDockLeafControl, IDisposable
UpdateElementPositions();
}
/// <summary>
/// Обновляет ориентацию списка заголовков вкладок.
/// </summary>
/// <param name="orientation">Новая ориентация списка.</param>
private void UpdateHeaderListOrientation(Orientation orientation)
{
if (_tabHeaderList?.ItemsPanelRoot is StackPanel stackPanel)
@@ -334,9 +283,6 @@ public sealed class LatticeTabControl : Control, IDockLeafControl, IDisposable
}
}
/// <summary>
/// Обновляет позиции элементов в сетке.
/// </summary>
private void UpdateElementPositions()
{
if (_rootGrid == null || _tabHeaderList == null || _contentControl == null) return;
@@ -373,9 +319,6 @@ public sealed class LatticeTabControl : Control, IDockLeafControl, IDisposable
}
}
/// <summary>
/// Обновляет заголовки вкладок.
/// </summary>
private void UpdateTabHeaders()
{
if (_tabHeaderList == null || _model == null) return;
@@ -391,11 +334,6 @@ public sealed class LatticeTabControl : Control, IDockLeafControl, IDisposable
UpdateSelectedTab();
}
/// <summary>
/// Создает элемент заголовка вкладки.
/// </summary>
/// <param name="content">Содержимое вкладки.</param>
/// <returns>Созданный элемент заголовка.</returns>
private ListBoxItem CreateTabHeaderItem(IDockContent content)
{
var item = new ListBoxItem
@@ -411,18 +349,12 @@ public sealed class LatticeTabControl : Control, IDockLeafControl, IDisposable
if (e.GetCurrentPoint(item).Properties.IsLeftButtonPressed)
{
ActiveContent = content;
e.Handled = true;
}
};
return item;
}
/// <summary>
/// Создает содержимое заголовка вкладки.
/// </summary>
/// <param name="content">Содержимое вкладки.</param>
/// <returns>Созданное содержимое заголовка.</returns>
private UIElement CreateTabHeaderContent(IDockContent content)
{
var grid = new Grid();
@@ -455,7 +387,6 @@ public sealed class LatticeTabControl : Control, IDockLeafControl, IDisposable
closeButton.Click += (sender, e) =>
{
CloseContent(content);
e.Handled = true;
};
Grid.SetColumn(closeButton, 1);
@@ -465,9 +396,6 @@ public sealed class LatticeTabControl : Control, IDockLeafControl, IDisposable
return grid;
}
/// <summary>
/// Обновляет выбранную вкладку.
/// </summary>
private void UpdateSelectedTab()
{
if (_tabHeaderList == null || _model == null) return;
@@ -486,9 +414,6 @@ public sealed class LatticeTabControl : Control, IDockLeafControl, IDisposable
}
}
/// <summary>
/// Обрабатывает изменение выбора вкладки.
/// </summary>
private void OnTabSelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (_tabHeaderList?.SelectedItem is ListBoxItem selectedItem &&
@@ -505,7 +430,6 @@ public sealed class LatticeTabControl : Control, IDockLeafControl, IDisposable
}
}
/// <inheritdoc/>
public void AddContent(IDockContent content)
{
if (_model != null && !_model.Children.Contains(content))
@@ -515,7 +439,6 @@ public sealed class LatticeTabControl : Control, IDockLeafControl, IDisposable
}
}
/// <inheritdoc/>
public void RemoveContent(IDockContent content)
{
if (_model != null && _model.Children.Contains(content))
@@ -525,7 +448,6 @@ public sealed class LatticeTabControl : Control, IDockLeafControl, IDisposable
}
}
/// <inheritdoc/>
public bool CloseContent(IDockContent content)
{
var args = new ContentClosingEventArgs(content);
@@ -540,7 +462,6 @@ public sealed class LatticeTabControl : Control, IDockLeafControl, IDisposable
return false;
}
/// <inheritdoc/>
public void CloseAllExcept(IDockContent exceptContent)
{
if (_model == null) return;
@@ -555,7 +476,6 @@ public sealed class LatticeTabControl : Control, IDockLeafControl, IDisposable
}
}
/// <inheritdoc/>
public void CloseAll()
{
if (_model == null) return;
@@ -567,23 +487,17 @@ public sealed class LatticeTabControl : Control, IDockLeafControl, IDisposable
}
}
/// <inheritdoc/>
public void Refresh()
{
UpdateTabHeaders();
UpdateTabPlacement();
}
/// <inheritdoc/>
public void ApplyTheme(IDockTheme theme)
{
if (theme != null)
{
// TODO: Реализовать применение темы к стилям контрола
}
// TODO: Реализовать применение темы
}
/// <inheritdoc/>
public void OnModelPropertyChanged(string propertyName)
{
if (_model != null)
@@ -592,15 +506,11 @@ public sealed class LatticeTabControl : Control, IDockLeafControl, IDisposable
}
}
/// <summary>
/// Вызывает событие изменения свойства.
/// </summary>
private void OnPropertyChanged([CallerMemberName] string? propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
/// <inheritdoc/>
public void Dispose()
{
if (!_disposed)