Документация проекта отображения.
This commit is contained in:
@@ -5,13 +5,26 @@ using Image = System.Drawing.Image;
|
||||
|
||||
namespace Pf2eViewer.EntityTreeViewer;
|
||||
|
||||
/// <summary>
|
||||
/// Элемент управления для отображения строки поля сущности.
|
||||
/// </summary>
|
||||
internal class EntityTreeViewerControlRow
|
||||
{
|
||||
/// <summary>
|
||||
/// Элемент управления, которому принадлежит эта строка.
|
||||
/// </summary>
|
||||
public readonly EntityTreeViewerControl ParentControl;
|
||||
|
||||
/// <summary>
|
||||
/// Отображаемая строка поля сущности.
|
||||
/// </summary>
|
||||
public readonly StructureField Item;
|
||||
|
||||
// Local fields
|
||||
#region "Поля строки"
|
||||
|
||||
/// <summary>
|
||||
/// Кэш изображения строки.
|
||||
/// </summary>
|
||||
public Image Cache
|
||||
{
|
||||
get
|
||||
@@ -26,6 +39,9 @@ internal class EntityTreeViewerControlRow
|
||||
}
|
||||
private Image? _cache;
|
||||
|
||||
/// <summary>
|
||||
/// Кэш изображения строки при наведении.
|
||||
/// </summary>
|
||||
public Image HoveredCache
|
||||
{
|
||||
get
|
||||
@@ -40,6 +56,9 @@ internal class EntityTreeViewerControlRow
|
||||
}
|
||||
private Image? _hoveredCache;
|
||||
|
||||
/// <summary>
|
||||
/// Список типов лестницы.
|
||||
/// </summary>
|
||||
public List<LadderType> Ladder
|
||||
{
|
||||
get => _ladder;
|
||||
@@ -51,6 +70,9 @@ internal class EntityTreeViewerControlRow
|
||||
}
|
||||
private List<LadderType> _ladder = [];
|
||||
|
||||
/// <summary>
|
||||
/// Проверяет, находится ли курсор над строкой.
|
||||
/// </summary>
|
||||
public bool Hovered
|
||||
{
|
||||
get => _hovered;
|
||||
@@ -65,59 +87,103 @@ internal class EntityTreeViewerControlRow
|
||||
}
|
||||
private bool _hovered = false;
|
||||
|
||||
/// <summary>
|
||||
/// Индекс строки в представлении.
|
||||
/// </summary>
|
||||
public int ViewIndex { get; set; } // = -1;
|
||||
|
||||
/// <summary>
|
||||
/// Кнопка раскрытия/сворачивания.
|
||||
/// </summary>
|
||||
public IconButton? Button { get; set; } = null;
|
||||
|
||||
// Inherited fields
|
||||
#endregion
|
||||
|
||||
#region "Поля для рендеринга"
|
||||
|
||||
/// <inheritdoc cref="EntityTreeViewerControl.Font"/>
|
||||
public Font Font
|
||||
{
|
||||
get => ParentControl.Font;
|
||||
set => ParentControl.Font = value;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="EntityTreeViewerControl.ForeColor"/>
|
||||
public Color ForeColor
|
||||
{
|
||||
get => ParentControl.ForeColor;
|
||||
set => ParentControl.ForeColor = value;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="EntityTreeViewerControl.BackColor"/>
|
||||
public Color BackColor
|
||||
{
|
||||
get => ParentControl.BackColor;
|
||||
set => ParentControl.BackColor = value;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="EntityTreeViewerControl.HoverColor"/>
|
||||
public Color HoverColor
|
||||
{
|
||||
get => ParentControl.HoverColor;
|
||||
set => ParentControl.HoverColor = value;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="EntityTreeViewerControl.ItemHeight"/>
|
||||
public int ItemHeight
|
||||
{
|
||||
get => ParentControl.ItemHeight;
|
||||
set => ParentControl.ItemHeight = value;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="EntityTreeViewerControl.DepthSize"/>
|
||||
public int DepthSize
|
||||
{
|
||||
get => ParentControl.DepthSize;
|
||||
set => ParentControl.DepthSize = value;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="EntityTreeViewerControl.ButtonSize"/>
|
||||
public int ButtonSize
|
||||
{
|
||||
get => ParentControl.ButtonSize;
|
||||
set => ParentControl.ButtonSize = value;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="EntityTreeViewerControl.TypeFontSize"/>
|
||||
public float TypeFontSize
|
||||
{
|
||||
get => ParentControl.TypeFontSize;
|
||||
set => ParentControl.TypeFontSize = value;
|
||||
}
|
||||
|
||||
// ValueText functions
|
||||
#endregion
|
||||
|
||||
#region "Вычисляемые поля"
|
||||
|
||||
/// <summary>
|
||||
/// Ширина строки.
|
||||
/// </summary>
|
||||
public int Width => ParentControl.ContentWidth;
|
||||
|
||||
/// <summary>
|
||||
/// Высота строки.
|
||||
/// </summary>
|
||||
public int Height => ItemHeight;
|
||||
|
||||
/// <summary>
|
||||
/// Флаг наличия кнопки.
|
||||
/// </summary>
|
||||
public bool HasButton => Item.FieldType == StructureFieldType.Complex;
|
||||
|
||||
/// <summary>
|
||||
/// Глубина отображения строки.
|
||||
/// </summary>
|
||||
public int Depth => Item.Depth;
|
||||
|
||||
/// <summary>
|
||||
/// Ширина имени в строке.
|
||||
/// </summary>
|
||||
public int NameWidth
|
||||
{
|
||||
get
|
||||
@@ -127,6 +193,9 @@ internal class EntityTreeViewerControlRow
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Строковое представление типа поля.
|
||||
/// </summary>
|
||||
public string TypeText
|
||||
{
|
||||
get
|
||||
@@ -140,10 +209,19 @@ internal class EntityTreeViewerControlRow
|
||||
}
|
||||
}
|
||||
|
||||
// public Font TypeFont => new(Font.FontFamily, TypeFontSize, FontStyle.Italic);
|
||||
/// <summary>
|
||||
/// Шрифт для отображения типа поля.
|
||||
/// </summary>
|
||||
public Font TypeFont => new(Font.FontFamily, TypeFontSize);
|
||||
|
||||
/// <summary>
|
||||
/// Строковое представление значения поля.
|
||||
/// </summary>
|
||||
public string ValueText => Item.GetValueString();
|
||||
|
||||
/// <summary>
|
||||
/// Шрифт для отображения значения поля.
|
||||
/// </summary>
|
||||
public Font ValueFont =>
|
||||
new(
|
||||
Font.FontFamily,
|
||||
@@ -151,16 +229,31 @@ internal class EntityTreeViewerControlRow
|
||||
Item.FieldType == StructureFieldType.Complex ? FontStyle.Italic : FontStyle.Regular
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Прямоугольник, занимаемый строкой в представлении.
|
||||
/// </summary>
|
||||
public RectangleF Target => new(0, ViewIndex * Height, Width, Height);
|
||||
|
||||
/// <summary>
|
||||
/// Прямоугольник, занимаемый строкой в родительском представлении.
|
||||
/// </summary>
|
||||
public RectangleF RealTarget =>
|
||||
new(0, ViewIndex * Height - ParentControl.VerticalScroll.Value, Width, Height);
|
||||
|
||||
// Simple fields
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Список данных для рендеринга строк.
|
||||
/// </summary>
|
||||
private readonly List<StringRenderData> _renderData = [];
|
||||
|
||||
// Main methods
|
||||
#region "Основные методы"
|
||||
|
||||
/// <summary>
|
||||
/// Создание элемента управления строки поля сущности.
|
||||
/// </summary>
|
||||
/// <param name="parent">Родительский элемент управления.</param>
|
||||
/// <param name="item">Строка поля структуры объекта.</param>
|
||||
public EntityTreeViewerControlRow(EntityTreeViewerControl parent, StructureField item)
|
||||
{
|
||||
ParentControl = parent;
|
||||
@@ -171,6 +264,9 @@ internal class EntityTreeViewerControlRow
|
||||
UpdateButton();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Применение свойств к элементу управления.
|
||||
/// </summary>
|
||||
private void ApplyItem()
|
||||
{
|
||||
_renderData.Clear();
|
||||
@@ -200,12 +296,20 @@ internal class EntityTreeViewerControlRow
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Обновление кэша изображения строки.
|
||||
/// </summary>
|
||||
public void UpdateCache()
|
||||
{
|
||||
Cache = RenderCache(BackColor);
|
||||
HoveredCache = RenderCache(HoverColor);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Создание кэша изображения строки.
|
||||
/// </summary>
|
||||
/// <param name="backColor">Цвет заднего фона.</param>
|
||||
/// <returns>Кеш изображения строки.</returns>
|
||||
private Image RenderCache(Color backColor)
|
||||
{
|
||||
Image cache = new Bitmap(Width, Height);
|
||||
@@ -220,6 +324,10 @@ internal class EntityTreeViewerControlRow
|
||||
return cache;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Запрос на перерисовку строки.
|
||||
/// </summary>
|
||||
/// <param name="g">Графический объект.</param>
|
||||
public void Invalidate(Graphics? g = null)
|
||||
{
|
||||
g ??= Graphics.FromImage(ParentControl.ContentImage);
|
||||
@@ -229,8 +337,13 @@ internal class EntityTreeViewerControlRow
|
||||
UpdateButton();
|
||||
}
|
||||
|
||||
// Button
|
||||
#endregion
|
||||
|
||||
#region "Кнопка"
|
||||
|
||||
/// <summary>
|
||||
/// Обновление кнопки раскрытия/сворачивания.
|
||||
/// </summary>
|
||||
public void UpdateButton()
|
||||
{
|
||||
if (Button is null)
|
||||
@@ -250,6 +363,11 @@ internal class EntityTreeViewerControlRow
|
||||
Button.Visible = Item.Visible;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Событие нажатия кнопки раскрытия/сворачивания.
|
||||
/// </summary>
|
||||
/// <param name="sender">Источник события.</param>
|
||||
/// <param name="e">Событие нажатие кнопки</param>
|
||||
private void Button_Click(object? sender, EventArgs e)
|
||||
{
|
||||
if (Item is StructureFieldComplex complex)
|
||||
@@ -259,8 +377,14 @@ internal class EntityTreeViewerControlRow
|
||||
}
|
||||
}
|
||||
|
||||
// Render
|
||||
#endregion
|
||||
|
||||
#region "Отрисовка"
|
||||
|
||||
/// <summary>
|
||||
/// Отрисовка лестницы.
|
||||
/// </summary>
|
||||
/// <param name="g">Графический объект.</param>
|
||||
private void RenderLadder(Graphics g)
|
||||
{
|
||||
int n = Depth;
|
||||
@@ -301,6 +425,10 @@ internal class EntityTreeViewerControlRow
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Отрисовка содержимого строки.
|
||||
/// </summary>
|
||||
/// <param name="g">Графический объект.</param>
|
||||
private void RenderContent(Graphics g)
|
||||
{
|
||||
float[] xs =
|
||||
@@ -326,13 +454,28 @@ internal class EntityTreeViewerControlRow
|
||||
}
|
||||
}
|
||||
|
||||
// Helper functions
|
||||
#endregion
|
||||
|
||||
#region Функции-помощники в отрисовке
|
||||
|
||||
/// <summary>
|
||||
/// Смешивание цвета с цветом текста.
|
||||
/// </summary>
|
||||
/// <param name="color">Цвет оттенка.</param>
|
||||
/// <param name="rate">Степень смешения.</param>
|
||||
/// <returns>Смешенный цвет.</returns>
|
||||
private Color BlendColor(Color color, double rate = 0.5)
|
||||
{
|
||||
return BlendColor(ForeColor, color, rate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Смешивание цветов.
|
||||
/// </summary>
|
||||
/// <param name="color1">Первый смешиваемый цвет.</param>
|
||||
/// <param name="color2">Второй смешиваемый цвет.</param>
|
||||
/// <param name="rate">Степень смешения.</param>
|
||||
/// <returns>Смешенный цвет.</returns>
|
||||
private Color BlendColor(Color color1, Color color2, double rate)
|
||||
{
|
||||
return Color.FromArgb(
|
||||
@@ -345,6 +488,10 @@ internal class EntityTreeViewerControlRow
|
||||
int Mix(int a, int b) => Convert.ToInt32(Math.Round(a * rate + b * (1 - rate)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение цвета текста по типу значения поля.
|
||||
/// </summary>
|
||||
/// <returns>Цвет текста.</returns>
|
||||
public Color GetValueColor()
|
||||
{
|
||||
return Item switch
|
||||
@@ -363,19 +510,59 @@ internal class EntityTreeViewerControlRow
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Класс для хранения данных рендеринга строки.
|
||||
/// </summary>
|
||||
/// <param name="text">Текст отображаемой строки.</param>
|
||||
/// <param name="font">Шрифт отображаемой строки.</param>
|
||||
/// <param name="color">Цвет отображаемой строки.</param>
|
||||
private class StringRenderData(string text, Font font, Color color)
|
||||
{
|
||||
/// <summary>
|
||||
/// Текст отображаемой строки.
|
||||
/// </summary>
|
||||
public string Text { get; } = text;
|
||||
|
||||
/// <summary>
|
||||
/// Шрифт отображаемой строки.
|
||||
/// </summary>
|
||||
public Font Font { get; } = font;
|
||||
|
||||
/// <summary>
|
||||
/// Цвет отображаемой строки.
|
||||
/// </summary>
|
||||
public Color Color { get; } = color;
|
||||
|
||||
/// <summary>
|
||||
/// Левый край отображаемой строки.
|
||||
/// </summary>
|
||||
public float Left { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Ширина отображаемой строки.
|
||||
/// </summary>
|
||||
public float Width { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Высота отображаемой строки.
|
||||
/// </summary>
|
||||
public float Height { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Прямоугольник, занимаемый строкой.
|
||||
/// </summary>
|
||||
public RectangleF Rect => new(Left, 0, Width, Height);
|
||||
|
||||
private string Fit(Graphics g, RectangleF rect)
|
||||
/// <summary>
|
||||
/// Уместить строку в занимаемый прямоугольник.
|
||||
/// </summary>
|
||||
/// <param name="g">Элемент графики.</param>
|
||||
/// <param name="rect">Занимаемый прямоугольник</param>
|
||||
/// <param name="filler">Строка, на которую будет заканчиваться значнеие при переполнении.</param>
|
||||
/// <returns></returns>
|
||||
private string Fit(Graphics g, RectangleF rect, string filler = "…")
|
||||
{
|
||||
if (Text.Length == 0 || g.MeasureString(Text, Font).Width <= rect.Width)
|
||||
{
|
||||
@@ -386,16 +573,20 @@ internal class EntityTreeViewerControlRow
|
||||
|
||||
int i = txt.Length;
|
||||
|
||||
while (g.MeasureString(txt + "...", Font).Width > rect.Width)
|
||||
while (g.MeasureString(txt + filler, Font).Width > rect.Width)
|
||||
{
|
||||
txt = txt[..--i];
|
||||
if (i == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
return txt + "...";
|
||||
return txt + filler;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Отрисовка строки.
|
||||
/// </summary>
|
||||
/// <param name="g">Элемент графики.</param>
|
||||
public void Draw(Graphics g)
|
||||
{
|
||||
g.DrawString(
|
||||
|
||||
Reference in New Issue
Block a user