360 lines
14 KiB
C#
360 lines
14 KiB
C#
using Lattice.UI.Docking.Abstractions;
|
||
using System.ComponentModel;
|
||
using System.Runtime.CompilerServices;
|
||
|
||
namespace Lattice.UI.Docking.Commands;
|
||
|
||
/// <summary>
|
||
/// Предоставляет базовую реализацию команды док-системы.
|
||
/// Реализует интерфейс <see cref="IDockCommand"/> и <see cref="INotifyPropertyChanged"/>
|
||
/// для поддержки уведомлений об изменении свойств.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// Этот класс предоставляет общую логику для команд, включая управление состоянием
|
||
/// возможности выполнения, уведомление об изменениях и реализацию интерфейса ICommand.
|
||
/// </remarks>
|
||
public abstract class DockCommandBase : IDockCommand, INotifyPropertyChanged
|
||
{
|
||
/// <summary>
|
||
/// Происходит при изменении возможности выполнения команды.
|
||
/// </summary>
|
||
public event EventHandler? CanExecuteChanged;
|
||
|
||
/// <summary>
|
||
/// Происходит при изменении значения свойства.
|
||
/// </summary>
|
||
public event PropertyChangedEventHandler? PropertyChanged;
|
||
|
||
private bool _canExecute = true;
|
||
|
||
/// <summary>
|
||
/// Получает уникальный идентификатор команды.
|
||
/// </summary>
|
||
/// <value>
|
||
/// Строковый идентификатор команды. Должен быть уникальным в пределах системы.
|
||
/// </value>
|
||
public abstract string Id { get; }
|
||
|
||
/// <summary>
|
||
/// Получает отображаемое имя команды.
|
||
/// </summary>
|
||
/// <value>
|
||
/// Имя команды, отображаемое в пользовательском интерфейсе.
|
||
/// </value>
|
||
public abstract string Name { get; }
|
||
|
||
/// <summary>
|
||
/// Получает описание команды.
|
||
/// </summary>
|
||
/// <value>
|
||
/// Текстовое описание функциональности команды.
|
||
/// Реализация по умолчанию возвращает пустую строку.
|
||
/// </value>
|
||
public virtual string Description => string.Empty;
|
||
|
||
/// <summary>
|
||
/// Получает идентификатор ресурса для иконки команды.
|
||
/// </summary>
|
||
/// <value>
|
||
/// Имя ресурса иконки или путь к файлу иконки.
|
||
/// Реализация по умолчанию возвращает пустую строку.
|
||
/// </value>
|
||
public virtual string Icon => string.Empty;
|
||
|
||
/// <summary>
|
||
/// Получает комбинацию клавиш для быстрого вызова команды.
|
||
/// </summary>
|
||
/// <value>
|
||
/// Строковое представление горячей клавиши.
|
||
/// Реализация по умолчанию возвращает пустую строку.
|
||
/// </value>
|
||
public virtual string Shortcut => string.Empty;
|
||
|
||
/// <summary>
|
||
/// Получает или задает значение, указывающее, можно ли выполнить команду.
|
||
/// </summary>
|
||
/// <value>
|
||
/// true, если команду можно выполнить; в противном случае false.
|
||
/// </value>
|
||
/// <remarks>
|
||
/// При изменении этого свойства генерируется событие <see cref="CanExecuteChanged"/>.
|
||
/// </remarks>
|
||
protected bool CanExecuteValue
|
||
{
|
||
get => _canExecute;
|
||
set
|
||
{
|
||
if (_canExecute != value)
|
||
{
|
||
_canExecute = value;
|
||
OnCanExecuteChanged();
|
||
OnPropertyChanged();
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Определяет, можно ли выполнить команду в текущем контексте.
|
||
/// </summary>
|
||
/// <param name="parameter">Параметр команды.</param>
|
||
/// <returns>
|
||
/// true, если команду можно выполнить; в противном случае false.
|
||
/// </returns>
|
||
/// <remarks>
|
||
/// Реализация по умолчанию возвращает значение свойства <see cref="CanExecuteValue"/>.
|
||
/// </remarks>
|
||
public virtual bool CanExecute(object? parameter)
|
||
{
|
||
return _canExecute;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Выполняет команду.
|
||
/// </summary>
|
||
/// <param name="parameter">Параметр команды.</param>
|
||
/// <remarks>
|
||
/// Этот метод должен быть реализован в производных классах.
|
||
/// </remarks>
|
||
public abstract void Execute(object? parameter);
|
||
|
||
/// <summary>
|
||
/// Вызывает событие изменения возможности выполнения команды.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// Этот метод может быть переопределен в производных классах для добавления
|
||
/// дополнительной логики перед вызовом события.
|
||
/// </remarks>
|
||
protected virtual void OnCanExecuteChanged()
|
||
{
|
||
CanExecuteChanged?.Invoke(this, EventArgs.Empty);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Вызывает событие <see cref="PropertyChanged"/>.
|
||
/// </summary>
|
||
/// <param name="propertyName">
|
||
/// Имя изменившегося свойства. Если не указано, определяется автоматически.
|
||
/// </param>
|
||
protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
|
||
{
|
||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Предоставляет команду для закрытия контента (вкладки).
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// Команда закрывает активную вкладку в указанном контроле листа.
|
||
/// </remarks>
|
||
public class CloseContentCommand : DockCommandBase
|
||
{
|
||
/// <summary>
|
||
/// Получает уникальный идентификатор команды.
|
||
/// </summary>
|
||
/// <value>
|
||
/// Идентификатор "CloseContent".
|
||
/// </value>
|
||
public override string Id => "CloseContent";
|
||
|
||
/// <summary>
|
||
/// Получает отображаемое имя команды.
|
||
/// </summary>
|
||
/// <value>
|
||
/// Имя "Close".
|
||
/// </value>
|
||
public override string Name => "Close";
|
||
|
||
/// <summary>
|
||
/// Получает описание команды.
|
||
/// </summary>
|
||
/// <value>
|
||
/// Описание "Close the current tab".
|
||
/// </value>
|
||
public override string Description => "Close the current tab";
|
||
|
||
/// <summary>
|
||
/// Получает идентификатор ресурса для иконки команды.
|
||
/// </summary>
|
||
/// <value>
|
||
/// Идентификатор "Close".
|
||
/// </value>
|
||
public override string Icon => "Close";
|
||
|
||
/// <summary>
|
||
/// Получает комбинацию клавиш для быстрого вызова команды.
|
||
/// </summary>
|
||
/// <value>
|
||
/// Горячая клавиша "Ctrl+F4".
|
||
/// </value>
|
||
public override string Shortcut => "Ctrl+F4";
|
||
|
||
/// <summary>
|
||
/// Определяет, можно ли выполнить команду в текущем контексте.
|
||
/// </summary>
|
||
/// <param name="parameter">Параметр команды.</param>
|
||
/// <returns>
|
||
/// true, если команду можно выполнить; в противном случае false.
|
||
/// </returns>
|
||
/// <remarks>
|
||
/// Команда доступна только если параметр является контролом листа
|
||
/// и содержит активный контент.
|
||
/// </remarks>
|
||
public override bool CanExecute(object? parameter)
|
||
{
|
||
return parameter is Abstractions.IDockLeafControl leafControl &&
|
||
leafControl.ActiveContent != null;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Выполняет команду закрытия контента.
|
||
/// </summary>
|
||
/// <param name="parameter">Параметр команды. Ожидается <see cref="Abstractions.IDockLeafControl"/>.</param>
|
||
/// <remarks>
|
||
/// Команда закрывает активную вкладку в указанном контроле листа.
|
||
/// </remarks>
|
||
public override void Execute(object? parameter)
|
||
{
|
||
if (parameter is Abstractions.IDockLeafControl leafControl &&
|
||
leafControl.ActiveContent != null)
|
||
{
|
||
leafControl.CloseContent(leafControl.ActiveContent);
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Предоставляет команду для создания плавающего окна из элемента.
|
||
/// </summary>
|
||
public class FloatWindowCommand : DockCommandBase
|
||
{
|
||
/// <summary>
|
||
/// Получает уникальный идентификатор команды.
|
||
/// </summary>
|
||
/// <value>
|
||
/// Идентификатор "FloatWindow".
|
||
/// </value>
|
||
public override string Id => "FloatWindow";
|
||
|
||
/// <summary>
|
||
/// Получает отображаемое имя команды.
|
||
/// </summary>
|
||
/// <value>
|
||
/// Имя "Float".
|
||
/// </value>
|
||
public override string Name => "Float";
|
||
|
||
/// <summary>
|
||
/// Получает описание команды.
|
||
/// </summary>
|
||
/// <value>
|
||
/// Описание "Float the window as a separate window".
|
||
/// </value>
|
||
public override string Description => "Float the window as a separate window";
|
||
|
||
/// <summary>
|
||
/// Получает идентификатор ресурса для иконки команды.
|
||
/// </summary>
|
||
/// <value>
|
||
/// Идентификатор "Float".
|
||
/// </value>
|
||
public override string Icon => "Float";
|
||
|
||
/// <summary>
|
||
/// Определяет, можно ли выполнить команду в текущем контексте.
|
||
/// </summary>
|
||
/// <param name="parameter">Параметр команды.</param>
|
||
/// <returns>
|
||
/// true, если команду можно выполнить; в противном случае false.
|
||
/// </returns>
|
||
/// <remarks>
|
||
/// Команда доступна только если параметр является элементом док-системы,
|
||
/// который может быть преобразован в плавающее окно.
|
||
/// </remarks>
|
||
public override bool CanExecute(object? parameter)
|
||
{
|
||
return parameter is Core.Docking.Abstractions.IDockElement;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Выполняет команду создания плавающего окна.
|
||
/// </summary>
|
||
/// <param name="parameter">Параметр команды. Ожидается <see cref="Core.Docking.Abstractions.IDockElement"/>.</param>
|
||
/// <remarks>
|
||
/// Реализация зависит от конкретного UI и должна быть предоставлена в производных классах.
|
||
/// Базовая реализация не выполняет никаких действий.
|
||
/// </remarks>
|
||
public override void Execute(object? parameter)
|
||
{
|
||
// Реализация зависит от конкретного UI
|
||
// В базовом классе метод не выполняет никаких действий
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Предоставляет команду для закрепления плавающего окна.
|
||
/// </summary>
|
||
public class DockWindowCommand : DockCommandBase
|
||
{
|
||
/// <summary>
|
||
/// Получает уникальный идентификатор команды.
|
||
/// </summary>
|
||
/// <value>
|
||
/// Идентификатор "DockWindow".
|
||
/// </value>
|
||
public override string Id => "DockWindow";
|
||
|
||
/// <summary>
|
||
/// Получает отображаемое имя команды.
|
||
/// </summary>
|
||
/// <value>
|
||
/// Имя "Dock".
|
||
/// </value>
|
||
public override string Name => "Dock";
|
||
|
||
/// <summary>
|
||
/// Получает описание команды.
|
||
/// </summary>
|
||
/// <value>
|
||
/// Описание "Dock the window to the main window".
|
||
/// </value>
|
||
public override string Description => "Dock the window to the main window";
|
||
|
||
/// <summary>
|
||
/// Получает идентификатор ресурса для иконки команды.
|
||
/// </summary>
|
||
/// <value>
|
||
/// Идентификатор "Dock".
|
||
/// </value>
|
||
public override string Icon => "Dock";
|
||
|
||
/// <summary>
|
||
/// Определяет, можно ли выполнить команду в текущем контексте.
|
||
/// </summary>
|
||
/// <param name="parameter">Параметр команды.</param>
|
||
/// <returns>
|
||
/// true, если команду можно выполнить; в противном случае false.
|
||
/// </returns>
|
||
/// <remarks>
|
||
/// Команда доступна только если параметр является плавающим окном,
|
||
/// которое может быть закреплено в основном окне.
|
||
/// </remarks>
|
||
public override bool CanExecute(object? parameter)
|
||
{
|
||
return parameter is Abstractions.IFloatingWindowControl;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Выполняет команду закрепления окна.
|
||
/// </summary>
|
||
/// <param name="parameter">Параметр команды. Ожидается <see cref="Abstractions.IFloatingWindowControl"/>.</param>
|
||
/// <remarks>
|
||
/// Реализация зависит от конкретного UI и должна быть предоставлена в производных классах.
|
||
/// Базовая реализация не выполняет никаких действий.
|
||
/// </remarks>
|
||
public override void Execute(object? parameter)
|
||
{
|
||
// Реализация зависит от конкретного UI
|
||
// В базовом классе метод не выполняет никаких действий
|
||
}
|
||
} |