Добавьте файлы проекта.
This commit is contained in:
89
QWERTYkez.WordProcessor/Builders/CellProps.cs
Normal file
89
QWERTYkez.WordProcessor/Builders/CellProps.cs
Normal file
@@ -0,0 +1,89 @@
|
||||
namespace QWERTYkez.WordProcessor.Builders;
|
||||
|
||||
public readonly struct CellProps(double? width = null!)
|
||||
{
|
||||
public double? Width { get; init; } = width;
|
||||
public TableVerticalAlignmentValues? VerticalAlignment { get; init; } = default;
|
||||
public MergedCell? Merge { get; init; } = default;
|
||||
|
||||
|
||||
#pragma warning disable IDE1006 // Стили именования
|
||||
public static CellProps V_H_ { get; } = new() { Merge = MergedCell.V_H_ };
|
||||
public static CellProps H_ { get; } = new() { Merge = MergedCell.H_ };
|
||||
public static CellProps V_ { get; } = new() { Merge = MergedCell.V_ };
|
||||
public static CellProps _V_H { get; } = new() { Merge = MergedCell._V_H };
|
||||
public static CellProps _H { get; } = new() { Merge = MergedCell._H };
|
||||
public static CellProps _V { get; } = new() { Merge = MergedCell._V };
|
||||
public static CellProps _VH_ { get; } = new() { Merge = MergedCell._VH_ };
|
||||
public static CellProps V__H { get; } = new() { Merge = MergedCell.V__H };
|
||||
#pragma warning restore IDE1006 // Стили именования
|
||||
|
||||
|
||||
internal bool TryExtract(out List<OpenXmlElement> list)
|
||||
{
|
||||
list =
|
||||
[
|
||||
new TableCellVerticalAlignment() { Val = VerticalAlignment ?? TableVerticalAlignmentValues.Center },
|
||||
new TableCellMargin()
|
||||
{
|
||||
TopMargin = new TopMargin() { Width = "0" },
|
||||
BottomMargin = new BottomMargin() { Width = "0" },
|
||||
LeftMargin = new LeftMargin() { Width = "0" },
|
||||
RightMargin = new RightMargin() { Width = "0" }
|
||||
}
|
||||
];
|
||||
|
||||
if (Width.HasValue)
|
||||
list.Add(new TableCellWidth()
|
||||
{
|
||||
Type = TableWidthUnitValues.Dxa,
|
||||
Width = ((uint)(Width.Value * 567d)).ToString() // 1 см = 567 DXA
|
||||
});
|
||||
|
||||
if (Merge.HasValue)
|
||||
{
|
||||
switch (Merge.Value)
|
||||
{
|
||||
case MergedCell.V_H_:
|
||||
list.Add(new HorizontalMerge() { Val = MergedCellValues.Restart });
|
||||
list.Add(new VerticalMerge() { Val = MergedCellValues.Restart });
|
||||
break;
|
||||
case MergedCell.H_:
|
||||
list.Add(new HorizontalMerge() { Val = MergedCellValues.Restart }); break;
|
||||
case MergedCell.V_:
|
||||
list.Add(new VerticalMerge() { Val = MergedCellValues.Restart }); break;
|
||||
case MergedCell._V_H:
|
||||
list.Add(new HorizontalMerge() { Val = MergedCellValues.Continue });
|
||||
list.Add(new VerticalMerge() { Val = MergedCellValues.Continue });
|
||||
break;
|
||||
case MergedCell._H:
|
||||
list.Add(new HorizontalMerge() { Val = MergedCellValues.Continue }); break;
|
||||
case MergedCell._V:
|
||||
list.Add(new VerticalMerge() { Val = MergedCellValues.Continue }); break;
|
||||
case MergedCell._VH_:
|
||||
list.Add(new HorizontalMerge() { Val = MergedCellValues.Restart });
|
||||
list.Add(new VerticalMerge() { Val = MergedCellValues.Continue });
|
||||
break;
|
||||
case MergedCell.V__H:
|
||||
list.Add(new HorizontalMerge() { Val = MergedCellValues.Continue });
|
||||
list.Add(new VerticalMerge() { Val = MergedCellValues.Restart });
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return list.Count > 0;
|
||||
}
|
||||
}
|
||||
public enum MergedCell
|
||||
{
|
||||
V_H_,
|
||||
H_,
|
||||
V_,
|
||||
|
||||
_V_H,
|
||||
_H,
|
||||
_V,
|
||||
|
||||
_VH_,
|
||||
V__H,
|
||||
}
|
||||
162
QWERTYkez.WordProcessor/Builders/FontProps.cs
Normal file
162
QWERTYkez.WordProcessor/Builders/FontProps.cs
Normal file
@@ -0,0 +1,162 @@
|
||||
using MathStyle = DocumentFormat.OpenXml.Math.Style;
|
||||
using MathStyleValues = DocumentFormat.OpenXml.Math.StyleValues;
|
||||
|
||||
namespace QWERTYkez.WordProcessor.Builders;
|
||||
|
||||
public record FontProps
|
||||
{
|
||||
public FontProps(double? size = null) => Size = size ?? 12;
|
||||
|
||||
public string? FontFamily { get; init; }
|
||||
|
||||
public double? Size
|
||||
{
|
||||
get => _SizeD.HasValue ? _SizeD.Value / 2d : null;
|
||||
init => _SizeD = value.HasValue ? (uint?)(value.Value * 2) : null;
|
||||
}
|
||||
uint? _SizeD;
|
||||
|
||||
public bool IsItalic { get; init; } = false;
|
||||
|
||||
public bool IsBold { get; init; } = false;
|
||||
|
||||
public UnderlineValues? Underline { get; init; }
|
||||
|
||||
public VerticalPositionValues? SubSup { get; init; }
|
||||
|
||||
public string? Color { get; init; }
|
||||
|
||||
|
||||
public bool TryExtract(out List<OpenXmlElement> list)
|
||||
{
|
||||
list = [];
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(FontFamily))
|
||||
list.Add(new RunFonts { Ascii = FontFamily, HighAnsi = FontFamily });
|
||||
|
||||
if (_SizeD is not null)
|
||||
list.Add(new FontSize { Val = _SizeD.Value.ToString() });
|
||||
|
||||
if (IsBold)
|
||||
list.Add(new Bold());
|
||||
|
||||
if (IsItalic)
|
||||
list.Add(new Italic());
|
||||
|
||||
if (Underline is not null)
|
||||
list.Add(new Underline { Val = Underline });
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(Color))
|
||||
list.Add(new Color { Val = Color });
|
||||
|
||||
if (SubSup is not null)
|
||||
list.Add(new VerticalTextAlignment { Val = SubSup });
|
||||
|
||||
return list.Count > 0;
|
||||
}
|
||||
public bool TryExtractWithoutFamily(out List<OpenXmlElement> list)
|
||||
{
|
||||
list = [];
|
||||
|
||||
if (_SizeD is not null)
|
||||
list.Add(new FontSize { Val = _SizeD.Value.ToString() });
|
||||
|
||||
if (IsBold)
|
||||
list.Add(new Bold());
|
||||
|
||||
if (IsItalic)
|
||||
list.Add(new Italic());
|
||||
|
||||
if (Underline is not null)
|
||||
list.Add(new Underline { Val = Underline });
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(Color))
|
||||
list.Add(new Color { Val = Color });
|
||||
|
||||
if (SubSup is not null)
|
||||
list.Add(new VerticalTextAlignment { Val = SubSup });
|
||||
|
||||
return list.Count > 0;
|
||||
}
|
||||
public bool TrySupExtract(out List<OpenXmlElement> list)
|
||||
{
|
||||
list = [];
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(FontFamily))
|
||||
list.Add(new RunFonts { Ascii = FontFamily, HighAnsi = FontFamily });
|
||||
|
||||
if (_SizeD is not null)
|
||||
list.Add(new FontSize { Val = _SizeD.Value.ToString() });
|
||||
|
||||
if (IsBold)
|
||||
list.Add(new Bold());
|
||||
|
||||
if (IsItalic)
|
||||
list.Add(new Italic());
|
||||
|
||||
if (Underline is not null)
|
||||
list.Add(new Underline { Val = Underline });
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(Color))
|
||||
list.Add(new Color { Val = Color });
|
||||
|
||||
list.Add(new VerticalTextAlignment { Val = VerticalPositionValues.Superscript });
|
||||
|
||||
return list.Count > 0;
|
||||
}
|
||||
public bool TrySubExtract(out List<OpenXmlElement> list)
|
||||
{
|
||||
list = [];
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(FontFamily))
|
||||
list.Add(new RunFonts { Ascii = FontFamily, HighAnsi = FontFamily });
|
||||
|
||||
if (_SizeD is not null)
|
||||
list.Add(new FontSize { Val = _SizeD.Value.ToString() });
|
||||
|
||||
if (IsBold)
|
||||
list.Add(new Bold());
|
||||
|
||||
if (IsItalic)
|
||||
list.Add(new Italic());
|
||||
|
||||
if (Underline is not null)
|
||||
list.Add(new Underline { Val = Underline });
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(Color))
|
||||
list.Add(new Color { Val = Color });
|
||||
|
||||
list.Add(new VerticalTextAlignment { Val = VerticalPositionValues.Subscript });
|
||||
|
||||
return list.Count > 0;
|
||||
}
|
||||
|
||||
public bool TryExtractForMath(out List<OpenXmlElement> list)
|
||||
{
|
||||
list = [];
|
||||
|
||||
// Для математики используем только элемент Style
|
||||
if (IsBold)
|
||||
list.Add(new MathStyle { Val = MathStyleValues.BoldItalic });
|
||||
else list.Add(new MathStyle { Val = MathStyleValues.Italic });
|
||||
// Обычное начертание можно не добавлять, так как по умолчанию и так обычное
|
||||
// (но если нужно явно сбросить, можно добавить Style { Val = StyleValues.Plain })
|
||||
|
||||
return list.Count > 0;
|
||||
}
|
||||
|
||||
// Фабричные методы для создания FontProps
|
||||
public static FontProps Default => new();
|
||||
|
||||
public static FontProps WithFont(string fontFamily, double? size = null) =>
|
||||
new(size) { FontFamily = fontFamily };
|
||||
|
||||
public static FontProps WithSize(double size) =>
|
||||
new(size);
|
||||
|
||||
public static FontProps WithStyle(bool bold = false, bool italic = false) =>
|
||||
new() { IsBold = bold, IsItalic = italic };
|
||||
|
||||
public static FontProps WithColor(string hexColor) =>
|
||||
new() { Color = hexColor };
|
||||
}
|
||||
357
QWERTYkez.WordProcessor/Builders/FormulaHelper.cs
Normal file
357
QWERTYkez.WordProcessor/Builders/FormulaHelper.cs
Normal file
@@ -0,0 +1,357 @@
|
||||
using Base = DocumentFormat.OpenXml.Math.Base;
|
||||
using ControlProperties = DocumentFormat.OpenXml.Math.ControlProperties;
|
||||
using Degree = DocumentFormat.OpenXml.Math.Degree;
|
||||
using Denominator = DocumentFormat.OpenXml.Math.Denominator;
|
||||
using Fraction = DocumentFormat.OpenXml.Math.Fraction;
|
||||
using FractionProperties = DocumentFormat.OpenXml.Math.FractionProperties;
|
||||
using HideDegree = DocumentFormat.OpenXml.Math.HideDegree;
|
||||
using MathRun = DocumentFormat.OpenXml.Math.Run;
|
||||
using MathRunProperties = DocumentFormat.OpenXml.Math.RunProperties;
|
||||
using MathText = DocumentFormat.OpenXml.Math.Text;
|
||||
using Numerator = DocumentFormat.OpenXml.Math.Numerator;
|
||||
using Radical = DocumentFormat.OpenXml.Math.Radical;
|
||||
using RadicalProperties = DocumentFormat.OpenXml.Math.RadicalProperties;
|
||||
using SubArgument = DocumentFormat.OpenXml.Math.SubArgument;
|
||||
using Subscript = DocumentFormat.OpenXml.Math.Subscript;
|
||||
using SubSuperscript = DocumentFormat.OpenXml.Math.SubSuperscript;
|
||||
using SuperArgument = DocumentFormat.OpenXml.Math.SuperArgument;
|
||||
using Superscript = DocumentFormat.OpenXml.Math.Superscript;
|
||||
|
||||
namespace QWERTYkez.WordProcessor.Builders;
|
||||
|
||||
internal static class FormulaHelper
|
||||
{
|
||||
// Вспомогательный метод для создания MathRun с форматированием
|
||||
public static MathRun CreateMathRun(FontProps? font)
|
||||
{
|
||||
var mathRun = new MathRun();
|
||||
|
||||
// 1. Математический стиль (полужирный/курсив) – добавляем первым
|
||||
if (font is not null && font.TryExtractForMath(out var mathStyleElements))
|
||||
{
|
||||
var mathPr = new MathRunProperties(mathStyleElements);
|
||||
mathRun.AppendChild(mathPr);
|
||||
}
|
||||
|
||||
// 2. Wordprocessing: цвет, размер, подчёркивание (без семейства шрифта)
|
||||
var wordPr = new RunProperties();
|
||||
if (font is not null && font.TryExtractWithoutFamily(out var wordElements))
|
||||
{
|
||||
foreach (var elem in wordElements)
|
||||
wordPr.AppendChild(elem.CloneNode(true));
|
||||
}
|
||||
mathRun.AppendChild(wordPr);
|
||||
|
||||
return mathRun;
|
||||
}
|
||||
|
||||
public static void AddText(OpenXmlElement parent, string text, FontProps? font)
|
||||
{
|
||||
if (parent is MathRun mathRun)
|
||||
{
|
||||
mathRun.AppendChild(new MathText(text));
|
||||
}
|
||||
else
|
||||
{
|
||||
var run = CreateMathRun(font);
|
||||
run.AppendChild(new MathText(text));
|
||||
parent.AppendChild(run);
|
||||
}
|
||||
}
|
||||
|
||||
public static Fraction CreateFraction(
|
||||
Action<IFormula> numeratorBuilder,
|
||||
Action<IFormula> denominatorBuilder,
|
||||
IFormula builder)
|
||||
{
|
||||
var fraction = new Fraction();
|
||||
var font = builder.BaseFont;
|
||||
|
||||
// Добавляем свойства дроби с форматированием (для черты дроби)
|
||||
var fPr = new FractionProperties();
|
||||
if (font.TryExtractWithoutFamily(out var wordElements))
|
||||
{
|
||||
var ctrlPr = new ControlProperties();
|
||||
var rPr = new RunProperties();
|
||||
foreach (var elem in wordElements)
|
||||
rPr.AppendChild(elem.CloneNode(true));
|
||||
rPr.AppendChild(new RunFonts { Ascii = "Cambria Math", HighAnsi = "Cambria Math" });
|
||||
ctrlPr.AppendChild(rPr);
|
||||
fPr.AppendChild(ctrlPr);
|
||||
}
|
||||
fraction.AppendChild(fPr);
|
||||
|
||||
// Числитель
|
||||
var numeratorElem = new Numerator();
|
||||
fraction.AppendChild(numeratorElem);
|
||||
builder.PushContext(numeratorElem);
|
||||
numeratorBuilder(builder);
|
||||
builder.PopContext();
|
||||
|
||||
// Знаменатель
|
||||
var denominatorElem = new Denominator();
|
||||
fraction.AppendChild(denominatorElem);
|
||||
builder.PushContext(denominatorElem);
|
||||
denominatorBuilder(builder);
|
||||
builder.PopContext();
|
||||
|
||||
return fraction;
|
||||
}
|
||||
|
||||
public static Radical CreateRadical(
|
||||
Action<IFormula> radicandBuilder,
|
||||
Action<IFormula>? degreeBuilder,
|
||||
IFormula builder)
|
||||
{
|
||||
var radical = new Radical();
|
||||
var font = builder.BaseFont;
|
||||
|
||||
var radPr = new RadicalProperties();
|
||||
|
||||
// Цвет, размер и подчёркивание для знака корня (ControlProperties)
|
||||
if (font is not null && font.TryExtractWithoutFamily(out var wordElements))
|
||||
{
|
||||
var ctrlPr = new ControlProperties();
|
||||
var rPr = new RunProperties();
|
||||
foreach (var elem in wordElements)
|
||||
rPr.AppendChild(elem.CloneNode(true));
|
||||
rPr.AppendChild(new RunFonts { Ascii = "Cambria Math", HighAnsi = "Cambria Math" });
|
||||
ctrlPr.AppendChild(rPr);
|
||||
radPr.AppendChild(ctrlPr);
|
||||
}
|
||||
|
||||
// Если степень не задана, скрываем её
|
||||
if (degreeBuilder is null)
|
||||
{
|
||||
radPr.HideDegree = new HideDegree { Val = DocumentFormat.OpenXml.Math.BooleanValues.One };
|
||||
}
|
||||
|
||||
// Добавляем свойства радикала (с цветом)
|
||||
radical.AppendChild(radPr);
|
||||
|
||||
// Степень (если есть)
|
||||
if (degreeBuilder is not null)
|
||||
{
|
||||
var degree = new Degree();
|
||||
radical.AppendChild(degree);
|
||||
builder.PushContext(degree);
|
||||
degreeBuilder(builder);
|
||||
builder.PopContext();
|
||||
}
|
||||
|
||||
// Подкоренное выражение
|
||||
var radicand = new Base();
|
||||
radical.AppendChild(radicand);
|
||||
builder.PushContext(radicand);
|
||||
radicandBuilder(builder);
|
||||
builder.PopContext();
|
||||
|
||||
return radical;
|
||||
}
|
||||
|
||||
public static void AddIntegral(
|
||||
OpenXmlElement currentContext,
|
||||
Action<IFormula> functionBuilder,
|
||||
Action<IFormula> differentialBuilder,
|
||||
Action<IFormula>? lowerLimitBuilder,
|
||||
Action<IFormula>? upperLimitBuilder,
|
||||
IFormula builder)
|
||||
{
|
||||
var font = builder.BaseFont;
|
||||
|
||||
if (lowerLimitBuilder is null && upperLimitBuilder is null)
|
||||
{
|
||||
var integralRun = CreateMathRun(font);
|
||||
integralRun.AppendChild(new MathText("∫"));
|
||||
currentContext.AppendChild(integralRun);
|
||||
|
||||
var funcRun = CreateMathRun(font);
|
||||
currentContext.AppendChild(funcRun);
|
||||
builder.PushContext(funcRun);
|
||||
functionBuilder(builder);
|
||||
builder.PopContext();
|
||||
|
||||
var diffRun = CreateMathRun(font);
|
||||
currentContext.AppendChild(diffRun);
|
||||
builder.PushContext(diffRun);
|
||||
differentialBuilder(builder);
|
||||
builder.PopContext();
|
||||
}
|
||||
else
|
||||
{
|
||||
var integralWithLimits = new SubSuperscript();
|
||||
currentContext.AppendChild(integralWithLimits);
|
||||
|
||||
var baseElem = new Base();
|
||||
var integralRun = CreateMathRun(font);
|
||||
integralRun.AppendChild(new MathText("∫"));
|
||||
baseElem.AppendChild(integralRun);
|
||||
integralWithLimits.AppendChild(baseElem);
|
||||
|
||||
if (lowerLimitBuilder is not null)
|
||||
{
|
||||
var subArg = new SubArgument();
|
||||
integralWithLimits.AppendChild(subArg);
|
||||
builder.PushContext(subArg);
|
||||
lowerLimitBuilder(builder);
|
||||
builder.PopContext();
|
||||
}
|
||||
if (upperLimitBuilder is not null)
|
||||
{
|
||||
var superArg = new SuperArgument();
|
||||
integralWithLimits.AppendChild(superArg);
|
||||
builder.PushContext(superArg);
|
||||
upperLimitBuilder(builder);
|
||||
builder.PopContext();
|
||||
}
|
||||
|
||||
var funcRun = CreateMathRun(font);
|
||||
currentContext.AppendChild(funcRun);
|
||||
builder.PushContext(funcRun);
|
||||
functionBuilder(builder);
|
||||
builder.PopContext();
|
||||
|
||||
var diffRun = CreateMathRun(font);
|
||||
currentContext.AppendChild(diffRun);
|
||||
builder.PushContext(diffRun);
|
||||
differentialBuilder(builder);
|
||||
builder.PopContext();
|
||||
}
|
||||
}
|
||||
|
||||
public static void AddSum(
|
||||
OpenXmlElement currentContext,
|
||||
Action<IFormula> expressionBuilder,
|
||||
Action<IFormula>? lowerLimitBuilder,
|
||||
Action<IFormula>? upperLimitBuilder,
|
||||
IFormula builder)
|
||||
{
|
||||
var font = builder.BaseFont;
|
||||
|
||||
if (lowerLimitBuilder is null && upperLimitBuilder is null)
|
||||
{
|
||||
var sumRun = CreateMathRun(font);
|
||||
sumRun.AppendChild(new MathText("∑"));
|
||||
currentContext.AppendChild(sumRun);
|
||||
|
||||
var exprRun = CreateMathRun(font);
|
||||
currentContext.AppendChild(exprRun);
|
||||
builder.PushContext(exprRun);
|
||||
expressionBuilder(builder);
|
||||
builder.PopContext();
|
||||
}
|
||||
else
|
||||
{
|
||||
var sumWithLimits = new SubSuperscript();
|
||||
currentContext.AppendChild(sumWithLimits);
|
||||
|
||||
var baseElem = new Base();
|
||||
var sumRun = CreateMathRun(font);
|
||||
sumRun.AppendChild(new MathText("∑"));
|
||||
baseElem.AppendChild(sumRun);
|
||||
sumWithLimits.AppendChild(baseElem);
|
||||
|
||||
if (lowerLimitBuilder is not null)
|
||||
{
|
||||
var subArg = new SubArgument();
|
||||
sumWithLimits.AppendChild(subArg);
|
||||
builder.PushContext(subArg);
|
||||
lowerLimitBuilder(builder);
|
||||
builder.PopContext();
|
||||
}
|
||||
if (upperLimitBuilder is not null)
|
||||
{
|
||||
var superArg = new SuperArgument();
|
||||
sumWithLimits.AppendChild(superArg);
|
||||
builder.PushContext(superArg);
|
||||
upperLimitBuilder(builder);
|
||||
builder.PopContext();
|
||||
}
|
||||
|
||||
var exprRun = CreateMathRun(font);
|
||||
currentContext.AppendChild(exprRun);
|
||||
builder.PushContext(exprRun);
|
||||
expressionBuilder(builder);
|
||||
builder.PopContext();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>Создаёт степень.</summary>
|
||||
public static Superscript CreateSuperscript(
|
||||
Action<IFormula> baseBuilder,
|
||||
Action<IFormula> supBuilder,
|
||||
IFormula builder)
|
||||
{
|
||||
var superscript = new Superscript();
|
||||
|
||||
// Основание
|
||||
var baseElem = new Base();
|
||||
superscript.AppendChild(baseElem);
|
||||
builder.PushContext(baseElem);
|
||||
baseBuilder(builder);
|
||||
builder.PopContext();
|
||||
|
||||
// Показатель
|
||||
var superArg = new SuperArgument();
|
||||
superscript.AppendChild(superArg);
|
||||
builder.PushContext(superArg);
|
||||
supBuilder(builder);
|
||||
builder.PopContext();
|
||||
|
||||
return superscript;
|
||||
}
|
||||
|
||||
/// <summary>Создаёт нижний индекс.</summary>
|
||||
public static Subscript CreateSubscript(
|
||||
Action<IFormula> baseBuilder,
|
||||
Action<IFormula> subBuilder,
|
||||
IFormula builder)
|
||||
{
|
||||
var subscript = new Subscript();
|
||||
|
||||
var baseElem = new Base();
|
||||
subscript.AppendChild(baseElem);
|
||||
builder.PushContext(baseElem);
|
||||
baseBuilder(builder);
|
||||
builder.PopContext();
|
||||
|
||||
var subArg = new SubArgument();
|
||||
subscript.AppendChild(subArg);
|
||||
builder.PushContext(subArg);
|
||||
subBuilder(builder);
|
||||
builder.PopContext();
|
||||
|
||||
return subscript;
|
||||
}
|
||||
|
||||
/// <summary>Создаёт одновременные нижний и верхний индексы.</summary>
|
||||
public static SubSuperscript CreateSubSuperscript(
|
||||
Action<IFormula> baseBuilder,
|
||||
Action<IFormula> subBuilder,
|
||||
Action<IFormula> supBuilder,
|
||||
IFormula builder)
|
||||
{
|
||||
var subSup = new SubSuperscript();
|
||||
|
||||
var baseElem = new Base();
|
||||
subSup.AppendChild(baseElem);
|
||||
builder.PushContext(baseElem);
|
||||
baseBuilder(builder);
|
||||
builder.PopContext();
|
||||
|
||||
var subArg = new SubArgument();
|
||||
subSup.AppendChild(subArg);
|
||||
builder.PushContext(subArg);
|
||||
subBuilder(builder);
|
||||
builder.PopContext();
|
||||
|
||||
var superArg = new SuperArgument();
|
||||
subSup.AppendChild(superArg);
|
||||
builder.PushContext(superArg);
|
||||
supBuilder(builder);
|
||||
builder.PopContext();
|
||||
|
||||
return subSup;
|
||||
}
|
||||
}
|
||||
315
QWERTYkez.WordProcessor/Builders/Interfaces.cs
Normal file
315
QWERTYkez.WordProcessor/Builders/Interfaces.cs
Normal file
@@ -0,0 +1,315 @@
|
||||
namespace QWERTYkez.WordProcessor.Builders;
|
||||
|
||||
public interface ITable
|
||||
{
|
||||
/// <summary>Базовый шрифт, используемый по умолчанию для содержимого таблицы.</summary>
|
||||
FontProps BaseFont { get; }
|
||||
|
||||
/// <summary>Добавляет строку в таблицу, настраиваемую с помощью <paramref name="configure"/>.</summary>
|
||||
/// <param name="configure">Делегат для конфигурации строки через <see cref="IRow"/>.</param>
|
||||
/// <returns>Тот же экземпляр <see cref="ITable"/> для цепочки вызовов.</returns>
|
||||
ITable AddRow(Action<IRow> configure);
|
||||
|
||||
/// <summary>Добавляет строку с указанной высотой, настраиваемую с помощью <paramref name="configure"/>.</summary>
|
||||
/// <param name="height">Высота строки в сантиметрах.</param>
|
||||
/// <param name="configure">Делегат для конфигурации строки через <see cref="IRow"/>.</param>
|
||||
/// <returns>Тот же экземпляр <see cref="ITable"/> для цепочки вызовов.</returns>
|
||||
ITable AddRow(double height, Action<IRow> configure);
|
||||
|
||||
/// <summary>Добавляет строку с ячейками, содержащими заданные тексты, используя указанный шрифт.</summary>
|
||||
/// <param name="font">Шрифт для всех ячеек строки.</param>
|
||||
/// <param name="cellTexts">Массив текстов для ячеек.</param>
|
||||
/// <returns>Тот же экземпляр <see cref="ITable"/> для цепочки вызовов.</returns>
|
||||
ITable AddRowWithCells(FontProps font, params string[] cellTexts);
|
||||
|
||||
/// <summary>Добавляет строку с ячейками, содержащими заданные тексты, используя базовый шрифт таблицы.</summary>
|
||||
/// <param name="cellTexts">Массив текстов для ячеек.</param>
|
||||
/// <returns>Тот же экземпляр <see cref="ITable"/> для цепочки вызовов.</returns>
|
||||
ITable AddRowWithCells(params string[] cellTexts);
|
||||
|
||||
/// <summary>Задаёт свойства таблицы: ширину и стиль границ, выравнивание.</summary>
|
||||
/// <param name="borderWidth">Ширина границ в пунктах (1/8 pt). По умолчанию 8.</param>
|
||||
/// <param name="borderValues">Стиль границ. По умолчанию <see cref="BorderValues.Single"/>.</param>
|
||||
/// <param name="tableAlignment">Выравнивание таблицы на странице. По умолчанию <see cref="TableRowAlignmentValues.Center"/>.</param>
|
||||
/// <returns>Тот же экземпляр <see cref="ITable"/> для цепочки вызовов.</returns>
|
||||
ITable Properties(uint borderWidth = 8, BorderValues? borderValues = null, TableRowAlignmentValues? tableAlignment = null);
|
||||
|
||||
/// <summary>Создаёт объект <see cref="Table"/> на основе выполненных настроек.</summary>
|
||||
/// <returns>Готовый объект <see cref="Table"/> для вставки в документ.</returns>
|
||||
internal Table Build();
|
||||
}
|
||||
|
||||
public interface IRow
|
||||
{
|
||||
/// <summary>Базовый шрифт, используемый по умолчанию для содержимого строки.</summary>
|
||||
FontProps BaseFont { get; }
|
||||
|
||||
/// <summary>Добавляет ячейку, настраиваемую с помощью <paramref name="configure"/>.</summary>
|
||||
/// <param name="configure">Делегат для конфигурации ячейки через <see cref="ICell"/>.</param>
|
||||
/// <returns>Тот же экземпляр <see cref="IRow"/> для цепочки вызовов.</returns>
|
||||
IRow AddCell(Action<ICell> configure);
|
||||
|
||||
/// <summary>Добавляет ячейку с заданными свойствами (без текста).</summary>
|
||||
/// <param name="cellProps">Свойства ячейки (ширина, объединение, вертикальное выравнивание).</param>
|
||||
/// <returns>Тот же экземпляр <see cref="IRow"/> для цепочки вызовов.</returns>
|
||||
IRow AddCell(CellProps cellProps);
|
||||
|
||||
/// <summary>Добавляет ячейку с заданными свойствами и текстом (используется базовый шрифт).</summary>
|
||||
/// <param name="cellProps">Свойства ячейки.</param>
|
||||
/// <param name="text">Текст ячейки.</param>
|
||||
/// <returns>Тот же экземпляр <see cref="IRow"/> для цепочки вызовов.</returns>
|
||||
IRow AddCell(CellProps cellProps, string text);
|
||||
|
||||
/// <summary>Добавляет ячейку с заданными свойствами, текстом и указанным шрифтом.</summary>
|
||||
/// <param name="cellProps">Свойства ячейки.</param>
|
||||
/// <param name="text">Текст ячейки.</param>
|
||||
/// <param name="font">Шрифт для текста. Если <see langword="null"/>, используется базовый шрифт.</param>
|
||||
/// <returns>Тот же экземпляр <see cref="IRow"/> для цепочки вызовов.</returns>
|
||||
IRow AddCell(CellProps cellProps, string text, FontProps font);
|
||||
|
||||
/// <summary>Добавляет ячейку с простым текстом (используется базовый шрифт).</summary>
|
||||
/// <param name="text">Текст ячейки.</param>
|
||||
/// <returns>Тот же экземпляр <see cref="IRow"/> для цепочки вызовов.</returns>
|
||||
IRow AddCell(string text);
|
||||
|
||||
/// <summary>Добавляет ячейку с простым текстом и указанным шрифтом.</summary>
|
||||
/// <param name="text">Текст ячейки.</param>
|
||||
/// <param name="font">Шрифт для текста. Если <see langword="null"/>, используется базовый шрифт.</param>
|
||||
/// <returns>Тот же экземпляр <see cref="IRow"/> для цепочки вызовов.</returns>
|
||||
IRow AddCell(string text, FontProps font);
|
||||
|
||||
/// <summary>Добавляет ячейку, содержащую один абзац, построенный с помощью <paramref name="configure"/>.</summary>
|
||||
/// <param name="configure">Делегат для конфигурации абзаца через <see cref="IParagraph"/>.</param>
|
||||
/// <returns>Тот же экземпляр <see cref="IRow"/> для цепочки вызовов.</returns>
|
||||
IRow AddCellWithPara(Action<IParagraph> configure);
|
||||
|
||||
/// <summary>Добавляет ячейку с указанными свойствами, содержащую один абзац, построенный с помощью <paramref name="configure"/>.</summary>
|
||||
/// <param name="cellProps">Свойства ячейки.</param>
|
||||
/// <param name="configure">Делегат для конфигурации абзаца через <see cref="IParagraph"/>.</param>
|
||||
/// <returns>Тот же экземпляр <see cref="IRow"/> для цепочки вызовов.</returns>
|
||||
IRow AddCellWithPara(CellProps cellProps, Action<IParagraph> configure);
|
||||
|
||||
/// <summary>Устанавливает точную высоту строки (свойство Exact).</summary>
|
||||
/// <param name="heightInCm">Высота в сантиметрах.</param>
|
||||
/// <returns>Тот же экземпляр <see cref="IRow"/> для цепочки вызовов.</returns>
|
||||
IRow SetExactHeight(double heightInCm);
|
||||
|
||||
/// <summary>Устанавливает минимальную высоту строки (свойство AtLeast).</summary>
|
||||
/// <param name="heightInCm">Высота в сантиметрах.</param>
|
||||
/// <returns>Тот же экземпляр <see cref="IRow"/> для цепочки вызовов.</returns>
|
||||
IRow SetHeight(double heightInCm);
|
||||
|
||||
/// <summary>Позволяет напрямую настроить свойства строки <see cref="TableRowProperties"/>.</summary>
|
||||
/// <param name="configure">Делегат для настройки свойств.</param>
|
||||
/// <returns>Тот же экземпляр <see cref="IRow"/> для цепочки вызовов.</returns>
|
||||
IRow SetProperties(Action<TableRowProperties> configure);
|
||||
|
||||
/// <summary>Создаёт объект <see cref="TableRow"/> на основе выполненных настроек.</summary>
|
||||
/// <returns>Готовый объект <see cref="TableRow"/> для вставки в таблицу.</returns>
|
||||
internal TableRow Build();
|
||||
}
|
||||
|
||||
public interface ICell
|
||||
{
|
||||
/// <summary>Базовый шрифт, используемый по умолчанию для содержимого ячейки.</summary>
|
||||
FontProps BaseFont { get; }
|
||||
|
||||
/// <summary>Добавляет в ячейку абзац, содержащий математическую формулу.</summary>
|
||||
/// <param name="configure">Делегат для конфигурации формулы через <see cref="IFormula"/>.</param>
|
||||
/// <returns>Тот же экземпляр <see cref="ICell"/> для цепочки вызовов.</returns>
|
||||
ICell AddFormula(Action<IFormula> configure);
|
||||
|
||||
/// <summary>Добавляет в ячейку абзац, построенный с помощью <paramref name="configure"/>.</summary>
|
||||
/// <param name="configure">Делегат для конфигурации абзаца через <see cref="IParagraph"/>.</param>
|
||||
/// <returns>Тот же экземпляр <see cref="ICell"/> для цепочки вызовов.</returns>
|
||||
ICell AddParagraph(Action<IParagraph> configure);
|
||||
|
||||
/// <summary>Добавляет в ячейку абзац, состоящий из нескольких строк текста (разделённых переносами).</summary>
|
||||
/// <param name="lines">Массив строк, каждая строка будет размещена на новой строке абзаца.</param>
|
||||
/// <returns>Тот же экземпляр <see cref="ICell"/> для цепочки вызовов.</returns>
|
||||
ICell AddParagraph(params string[] lines);
|
||||
|
||||
/// <summary>Добавляет в ячейку абзац с указанным текстом и опциональным шрифтом.</summary>
|
||||
/// <param name="text">Текст абзаца.</param>
|
||||
/// <param name="font">Шрифт для текста. Если <see langword="null"/>, используется базовый шрифт.</param>
|
||||
/// <returns>Тот же экземпляр <see cref="ICell"/> для цепочки вызовов.</returns>
|
||||
ICell AddParagraph(string text, FontProps? font = null);
|
||||
|
||||
/// <summary>Устанавливает свойства ячейки (ширина, объединение, вертикальное выравнивание).</summary>
|
||||
/// <param name="props">Свойства ячейки.</param>
|
||||
/// <returns>Тот же экземпляр <see cref="ICell"/> для цепочки вызовов.</returns>
|
||||
ICell SetCellProps(CellProps props);
|
||||
|
||||
/// <summary>Создаёт объект <see cref="TableCell"/> на основе выполненных настроек.</summary>
|
||||
/// <returns>Готовый объект <see cref="TableCell"/> для вставки в строку.</returns>
|
||||
internal TableCell Build();
|
||||
}
|
||||
|
||||
public interface IText
|
||||
{
|
||||
/// <summary>Базовый шрифт, используемый по умолчанию для содержимого текстового блока.</summary>
|
||||
FontProps BaseFont { get; }
|
||||
|
||||
/// <summary>Добавляет в документ абзац, содержащий математическую формулу.</summary>
|
||||
/// <param name="configure">Делегат для конфигурации формулы через <see cref="IFormula"/>.</param>
|
||||
/// <returns>Тот же экземпляр <see cref="IText"/> для цепочки вызовов.</returns>
|
||||
IText AddFormula(Action<IFormula> configure);
|
||||
|
||||
/// <summary>Добавляет абзац, построенный с помощью <paramref name="configure"/>.</summary>
|
||||
/// <param name="configure">Делегат для конфигурации абзаца через <see cref="IParagraph"/>.</param>
|
||||
/// <returns>Тот же экземпляр <see cref="IText"/> для цепочки вызовов.</returns>
|
||||
IText AddParagraph(Action<IParagraph> configure);
|
||||
|
||||
/// <summary>Добавляет абзац, состоящий из нескольких строк текста (разделённых переносами).</summary>
|
||||
/// <param name="lines">Массив строк, каждая строка будет размещена на новой строке абзаца.</param>
|
||||
/// <returns>Тот же экземпляр <see cref="IText"/> для цепочки вызовов.</returns>
|
||||
IText AddParagraph(params string[] lines);
|
||||
|
||||
/// <summary>Добавляет абзац с указанным текстом и опциональным шрифтом.</summary>
|
||||
/// <param name="text">Текст абзаца.</param>
|
||||
/// <param name="font">Шрифт для текста. Если <see langword="null"/>, используется базовый шрифт.</param>
|
||||
/// <returns>Тот же экземпляр <see cref="IText"/> для цепочки вызовов.</returns>
|
||||
IText AddParagraph(string text, FontProps? font = null);
|
||||
|
||||
/// <summary>Создаёт список абзацев <see cref="Paragraph"/> на основе выполненных настроек.</summary>
|
||||
/// <returns>Список готовых абзацев для вставки в документ.</returns>
|
||||
internal List<Paragraph> Build();
|
||||
}
|
||||
|
||||
public interface IParagraph
|
||||
{
|
||||
/// <summary>Базовый шрифт, используемый по умолчанию для содержимого абзаца.</summary>
|
||||
FontProps BaseFont { get; }
|
||||
|
||||
/// <summary>Добавляет в абзац математическую формулу (внутри отдельного <see cref="Run"/>).</summary>
|
||||
/// <param name="configure">Делегат для конфигурации формулы через <see cref="IFormula"/>.</param>
|
||||
/// <returns>Тот же экземпляр <see cref="IParagraph"/> для цепочки вызовов.</returns>
|
||||
IParagraph AddFormula(Action<IFormula> configure);
|
||||
|
||||
/// <summary>Добавляет в абзац математическую формулу (внутри отдельного <see cref="Run"/>) и разрыв строки (<see cref="DocumentFormat.OpenXml.Wordprocessing.Break"/>) в текущий абзац.</summary>
|
||||
/// <param name="configure">Делегат для конфигурации формулы через <see cref="IFormula"/>.</param>
|
||||
/// <returns>Тот же экземпляр <see cref="IParagraph"/> для цепочки вызовов.</returns>
|
||||
IParagraph AddFormulaBreak(Action<IFormula> configure);
|
||||
|
||||
/// <summary>Добавляет разрыв строки (<see cref="DocumentFormat.OpenXml.Wordprocessing.Break"/>) в текущий абзац.</summary>
|
||||
/// <returns>Тот же экземпляр <see cref="IParagraph"/> для цепочки вызовов.</returns>
|
||||
IParagraph Break();
|
||||
|
||||
/// <summary>Добавляет разрыв строки (<see cref="DocumentFormat.OpenXml.Wordprocessing.Break"/>) в текущий абзац.</summary>
|
||||
/// <returns>Тот же экземпляр <see cref="IParagraph"/> для цепочки вызовов.</returns>
|
||||
IParagraph BreakPage();
|
||||
|
||||
/// <summary>Добавляет текстовый фрагмент (<see cref="Run"/>) с указанным текстом и опциональным шрифтом.</summary>
|
||||
/// <param name="text">Текст фрагмента.</param>
|
||||
/// <param name="font">Шрифт для текста. Если <see langword="null"/>, используется базовый шрифт.</param>
|
||||
/// <returns>Тот же экземпляр <see cref="IParagraph"/> для цепочки вызовов.</returns>
|
||||
IParagraph AddRun(string text, FontProps? font = null);
|
||||
|
||||
/// <summary>Добавляет текстовый фрагмент (<see cref="Run"/>) с указанным текстом и опциональным шрифтом и разрыв строки (<see cref="DocumentFormat.OpenXml.Wordprocessing.Break"/>) в текущий абзац.</summary>
|
||||
/// <param name="text">Текст фрагмента.</param>
|
||||
/// <param name="font">Шрифт для текста. Если <see langword="null"/>, используется базовый шрифт.</param>
|
||||
/// <returns>Тот же экземпляр <see cref="IParagraph"/> для цепочки вызовов.</returns>
|
||||
IParagraph AddRunBreak(string text, FontProps? font = null);
|
||||
|
||||
/// <summary>Добавляет текстовый фрагмент с полным контролем над свойствами <see cref="RunProperties"/>.</summary>
|
||||
/// <param name="text">Текст фрагмента.</param>
|
||||
/// <param name="configure">Делегат для настройки свойств фрагмента.</param>
|
||||
/// <returns>Тот же экземпляр <see cref="IParagraph"/> для цепочки вызовов.</returns>
|
||||
IParagraph AddRunWithCustomProps(string text, Action<RunProperties> configure);
|
||||
|
||||
/// <summary>Добавляет текстовый фрагмент, отформатированный как нижний индекс (<see cref="VerticalPositionValues.Subscript"/>).</summary>
|
||||
/// <param name="text">Текст фрагмента.</param>
|
||||
/// <param name="font">Базовый шрифт (свойства <see cref="SubSup"/> будут переопределены).</param>
|
||||
/// <returns>Тот же экземпляр <see cref="IParagraph"/> для цепочки вызовов.</returns>
|
||||
IParagraph AddSubRun(string text, FontProps? font = null);
|
||||
|
||||
/// <summary>Добавляет текстовый фрагмент, отформатированный как верхний индекс (<see cref="VerticalPositionValues.Superscript"/>).</summary>
|
||||
/// <param name="text">Текст фрагмента.</param>
|
||||
/// <param name="font">Базовый шрифт (свойства <see cref="SubSup"/> будут переопределены).</param>
|
||||
/// <returns>Тот же экземпляр <see cref="IParagraph"/> для цепочки вызовов.</returns>
|
||||
IParagraph AddSupRun(string text, FontProps? font = null);
|
||||
|
||||
/// <summary>Устанавливает выравнивание абзаца.</summary>
|
||||
/// <param name="alignment">Тип выравнивания (лево, право, центр, по ширине).</param>
|
||||
/// <returns>Тот же экземпляр <see cref="IParagraph"/> для цепочки вызовов.</returns>
|
||||
IParagraph SetAlignment(JustificationValues alignment);
|
||||
|
||||
/// <summary>Создаёт объект <see cref="Paragraph"/> на основе выполненных настроек.</summary>
|
||||
/// <returns>Готовый объект <see cref="Paragraph"/>.</returns>
|
||||
internal Paragraph Build();
|
||||
}
|
||||
|
||||
public interface IFormula
|
||||
{
|
||||
FontProps BaseFont { get; }
|
||||
|
||||
IFormula Text(string text);
|
||||
|
||||
|
||||
IFormula Division(string numerator, string denominator);
|
||||
IFormula Division(string numerator, Action<IFormula> denominator);
|
||||
IFormula Division(Action<IFormula> numerator, string denominator);
|
||||
IFormula Division(Action<IFormula> numerator, Action<IFormula> denominator);
|
||||
|
||||
|
||||
IFormula Sup(string baseText, string supText);
|
||||
IFormula Sup(string baseText, Action<IFormula> supText);
|
||||
IFormula Sup(Action<IFormula> baseText, string supText);
|
||||
IFormula Sup(Action<IFormula> baseText, Action<IFormula> supText);
|
||||
|
||||
|
||||
IFormula Sub(string baseText, string subText);
|
||||
IFormula Sub(string baseText, Action<IFormula> subText);
|
||||
IFormula Sub(Action<IFormula> baseText, string subText);
|
||||
IFormula Sub(Action<IFormula> baseText, Action<IFormula> subText);
|
||||
|
||||
|
||||
IFormula SubSup(string baseText, string subText, string supText);
|
||||
IFormula SubSup(string baseText, string subText, Action<IFormula> supText);
|
||||
IFormula SubSup(string baseText, Action<IFormula> subText, string supText);
|
||||
IFormula SubSup(string baseText, Action<IFormula> subText, Action<IFormula> supText);
|
||||
IFormula SubSup(Action<IFormula> baseText, string subText, string supText);
|
||||
IFormula SubSup(Action<IFormula> baseText, string subText, Action<IFormula> supText);
|
||||
IFormula SubSup(Action<IFormula> baseText, Action<IFormula> subText, string supText);
|
||||
IFormula SubSup(Action<IFormula> baseText, Action<IFormula> subText, Action<IFormula> supText);
|
||||
|
||||
|
||||
IFormula Root(string radicand);
|
||||
IFormula Root(Action<IFormula> radicand);
|
||||
IFormula Root(string radicand, string degree);
|
||||
IFormula Root(string radicand, Action<IFormula> degree);
|
||||
IFormula Root(Action<IFormula> radicand, string degree);
|
||||
IFormula Root(Action<IFormula> radicand, Action<IFormula> degree);
|
||||
|
||||
|
||||
IFormula Integral(string function, string differential, string? lowerLimit = null, string? upperLimit = null);
|
||||
IFormula Integral(string function, string differential, string? lowerLimit = null, Action<IFormula>? upperLimit = null);
|
||||
IFormula Integral(string function, string differential, Action<IFormula>? lowerLimit = null, string? upperLimit = null);
|
||||
IFormula Integral(string function, string differential, Action<IFormula>? lowerLimit = null, Action<IFormula>? upperLimit = null);
|
||||
IFormula Integral(string function, Action<IFormula> differential, string? lowerLimit = null, string? upperLimit = null);
|
||||
IFormula Integral(string function, Action<IFormula> differential, string? lowerLimit = null, Action<IFormula>? upperLimit = null);
|
||||
IFormula Integral(string function, Action<IFormula> differential, Action<IFormula>? lowerLimit = null, string? upperLimit = null);
|
||||
IFormula Integral(string function, Action<IFormula> differential, Action<IFormula>? lowerLimit = null, Action<IFormula>? upperLimit = null);
|
||||
IFormula Integral(Action<IFormula> function, string differential, string? lowerLimit = null, string? upperLimit = null);
|
||||
IFormula Integral(Action<IFormula> function, string differential, string? lowerLimit = null, Action<IFormula>? upperLimit = null);
|
||||
IFormula Integral(Action<IFormula> function, string differential, Action<IFormula>? lowerLimit = null, string? upperLimit = null);
|
||||
IFormula Integral(Action<IFormula> function, string differential, Action<IFormula>? lowerLimit = null, Action<IFormula>? upperLimit = null);
|
||||
IFormula Integral(Action<IFormula> function, Action<IFormula> differential, string? lowerLimit = null, string? upperLimit = null);
|
||||
IFormula Integral(Action<IFormula> function, Action<IFormula> differential, string? lowerLimit = null, Action<IFormula>? upperLimit = null);
|
||||
IFormula Integral(Action<IFormula> function, Action<IFormula> differential, Action<IFormula>? lowerLimit = null, string? upperLimit = null);
|
||||
IFormula Integral(Action<IFormula> function, Action<IFormula> differential, Action<IFormula>? lowerLimit = null, Action<IFormula>? upperLimit = null);
|
||||
|
||||
|
||||
IFormula Sum(string expression, string? lowerLimit = null, string? upperLimit = null);
|
||||
IFormula Sum(string expression, string? lowerLimit = null, Action<IFormula>? upperLimit = null);
|
||||
IFormula Sum(string expression, Action<IFormula>? lowerLimit = null, string? upperLimit = null);
|
||||
IFormula Sum(string expression, Action<IFormula>? lowerLimit = null, Action<IFormula>? upperLimit = null);
|
||||
IFormula Sum(Action<IFormula> expression, string? lowerLimit = null, string? upperLimit = null);
|
||||
IFormula Sum(Action<IFormula> expression, string? lowerLimit = null, Action<IFormula>? upperLimit = null);
|
||||
IFormula Sum(Action<IFormula> expression, Action<IFormula>? lowerLimit = null, string? upperLimit = null);
|
||||
IFormula Sum(Action<IFormula> expression, Action<IFormula>? lowerLimit = null, Action<IFormula>? upperLimit = null);
|
||||
|
||||
|
||||
internal void PushContext(OpenXmlElement element);
|
||||
internal void PopContext();
|
||||
}
|
||||
431
QWERTYkez.WordProcessor/Builders/ParagraphBuilderBase.cs
Normal file
431
QWERTYkez.WordProcessor/Builders/ParagraphBuilderBase.cs
Normal file
@@ -0,0 +1,431 @@
|
||||
namespace QWERTYkez.WordProcessor.Builders;
|
||||
|
||||
abstract class ParagraphBuilderBase : IParagraph, IFormula
|
||||
{
|
||||
public FontProps BaseFont { get; internal set; }
|
||||
|
||||
// Конструктор для установки базового шрифта
|
||||
protected ParagraphBuilderBase(FontProps? baseFont = null)
|
||||
{
|
||||
BaseFont = baseFont is not null && baseFont.SubSup.HasValue
|
||||
? baseFont with { SubSup = null }
|
||||
: baseFont ?? new FontProps();
|
||||
}
|
||||
|
||||
|
||||
internal FontProps GetEffectiveFont(FontProps? overrideFont) => overrideFont ?? BaseFont;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
protected Paragraph _paragraph = null!;
|
||||
protected List<Run> _runs = null!;
|
||||
|
||||
internal IParagraph ParagraphBuilder => CreateParagraphBuilder();
|
||||
protected virtual IParagraph CreateParagraphBuilder()
|
||||
{
|
||||
_paragraph = new Paragraph
|
||||
{
|
||||
ParagraphProperties = new ParagraphProperties(
|
||||
new Justification { Val = JustificationValues.Center },
|
||||
new SpacingBetweenLines
|
||||
{
|
||||
After = "0",
|
||||
Before = "0",
|
||||
LineRule = LineSpacingRuleValues.Auto
|
||||
},
|
||||
new Indentation
|
||||
{
|
||||
Left = "0",
|
||||
Right = "0",
|
||||
FirstLine = "0",
|
||||
Hanging = "0"
|
||||
}
|
||||
)
|
||||
};
|
||||
_runs = [];
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
Paragraph IParagraph.Build()
|
||||
{
|
||||
foreach (var run in _runs)
|
||||
{
|
||||
_paragraph.AppendChild(run);
|
||||
}
|
||||
return _paragraph;
|
||||
}
|
||||
|
||||
// Настройка выравнивания
|
||||
public IParagraph SetAlignment(JustificationValues alignment)
|
||||
{
|
||||
var props = _paragraph.ParagraphProperties;
|
||||
props?.Justification = new Justification { Val = alignment };
|
||||
return this;
|
||||
}
|
||||
|
||||
// Добавление текста
|
||||
public IParagraph AddRun(string text, FontProps? font = null)
|
||||
{
|
||||
// Заменяем обычные пробелы на неразрывные для сохранения видимости
|
||||
string processedText = text.Replace(' ', '\u00A0');
|
||||
|
||||
var effectiveFont = GetEffectiveFont(font);
|
||||
Run run;
|
||||
|
||||
if (effectiveFont.TryExtract(out var elements))
|
||||
{
|
||||
run = new Run(new RunProperties(elements), new Text(processedText));
|
||||
}
|
||||
else
|
||||
{
|
||||
run = new Run(new Text(processedText));
|
||||
}
|
||||
|
||||
_runs.Add(run);
|
||||
return this;
|
||||
}
|
||||
|
||||
// Добавление текста
|
||||
public IParagraph AddRunBreak(string text, FontProps? font = null)
|
||||
{
|
||||
// Заменяем обычные пробелы на неразрывные для сохранения видимости
|
||||
string processedText = text.Replace(' ', '\u00A0');
|
||||
|
||||
var effectiveFont = GetEffectiveFont(font);
|
||||
Run run;
|
||||
|
||||
if (effectiveFont.TryExtract(out var elements))
|
||||
{
|
||||
run = new Run(new RunProperties(elements), new Text(processedText));
|
||||
}
|
||||
else
|
||||
{
|
||||
run = new Run(new Text(processedText));
|
||||
}
|
||||
|
||||
_runs.Add(run);
|
||||
|
||||
_runs.Add(new Run(new Break()));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
// Добавление текста
|
||||
public IParagraph AddSupRun(string text, FontProps? font = null)
|
||||
{
|
||||
var effectiveFont = GetEffectiveFont(font);
|
||||
Run run;
|
||||
|
||||
if (effectiveFont.TrySupExtract(out var elements))
|
||||
{
|
||||
run = new Run(new RunProperties(elements), new Text(text));
|
||||
}
|
||||
else
|
||||
{
|
||||
run = new Run(new Text(text));
|
||||
}
|
||||
|
||||
_runs.Add(run);
|
||||
return this;
|
||||
}
|
||||
|
||||
// Добавление текста
|
||||
public IParagraph AddSubRun(string text, FontProps? font = null)
|
||||
{
|
||||
var effectiveFont = GetEffectiveFont(font);
|
||||
Run run;
|
||||
|
||||
if (effectiveFont.TrySubExtract(out var elements))
|
||||
{
|
||||
run = new Run(new RunProperties(elements), new Text(text));
|
||||
}
|
||||
else
|
||||
{
|
||||
run = new Run(new Text(text));
|
||||
}
|
||||
|
||||
_runs.Add(run);
|
||||
return this;
|
||||
}
|
||||
|
||||
public IParagraph AddRunWithCustomProps(string text, Action<RunProperties> configure)
|
||||
{
|
||||
var props = new RunProperties();
|
||||
configure(props);
|
||||
_runs.Add(new Run(props, new Text(text)));
|
||||
return this;
|
||||
}
|
||||
|
||||
// Добавление разрыва строки
|
||||
public IParagraph Break()
|
||||
{
|
||||
_runs.Add(new Run(new Break()));
|
||||
return this;
|
||||
}
|
||||
|
||||
// Добавление разрыва строки
|
||||
public IParagraph BreakPage()
|
||||
{
|
||||
_runs.Add(new Run(new Break() { Type = BreakValues.Page }));
|
||||
return this;
|
||||
}
|
||||
|
||||
// Метод AddFormula для IParagraphBuilder
|
||||
IParagraph IParagraph.AddFormula(Action<IFormula> configure)
|
||||
{
|
||||
var math = new OfficeMath();
|
||||
try
|
||||
{
|
||||
_mathContextStack.Push(math);
|
||||
configure(this);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_mathContextStack.Pop();
|
||||
}
|
||||
|
||||
var run = new Run(); // без RunProperties
|
||||
run.AppendChild(math);
|
||||
_runs.Add(run);
|
||||
return this;
|
||||
}
|
||||
|
||||
// Метод AddFormula для IParagraphBuilder
|
||||
IParagraph IParagraph.AddFormulaBreak(Action<IFormula> configure)
|
||||
{
|
||||
var math = new OfficeMath();
|
||||
try
|
||||
{
|
||||
_mathContextStack.Push(math);
|
||||
configure(this);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_mathContextStack.Pop();
|
||||
}
|
||||
|
||||
var run = new Run(); // без RunProperties
|
||||
run.AppendChild(math);
|
||||
_runs.Add(run);
|
||||
_runs.Add(new Run(new Break()));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Стек для вложенных математических конструкций
|
||||
private readonly Stack<OpenXmlElement> _mathContextStack = new();
|
||||
bool TryGetCurrentMathContext(out OpenXmlElement element)
|
||||
{
|
||||
if (_mathContextStack.Count > 0)
|
||||
{
|
||||
element = _mathContextStack.Peek();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
element = null!;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Вспомогательные методы для стека (используются FormulaHelper)
|
||||
void IFormula.PushContext(OpenXmlElement element) => _mathContextStack.Push(element);
|
||||
void IFormula.PopContext() => _mathContextStack.Pop();
|
||||
|
||||
|
||||
// Реализация IFormulaBuilder
|
||||
public IFormula Text(string text)
|
||||
{
|
||||
if (TryGetCurrentMathContext(out var element))
|
||||
FormulaHelper.AddText(element, text, BaseFont);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
// Division
|
||||
public IFormula Division(string numerator, string denominator) =>
|
||||
Division(ToAction(numerator), ToAction(denominator));
|
||||
public IFormula Division(string numerator, Action<IFormula> denominator) =>
|
||||
Division(ToAction(numerator), denominator);
|
||||
public IFormula Division(Action<IFormula> numerator, string denominator) =>
|
||||
Division(numerator, ToAction(denominator));
|
||||
public IFormula Division(Action<IFormula> numerator, Action<IFormula> denominator)
|
||||
{
|
||||
var fraction = FormulaHelper.CreateFraction(numerator, denominator, this);
|
||||
if (TryGetCurrentMathContext(out var element))
|
||||
element.AppendChild(fraction);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
// Sup
|
||||
public IFormula Sup(string baseText, string supText) =>
|
||||
Sup(ToAction(baseText), ToAction(supText));
|
||||
public IFormula Sup(string baseText, Action<IFormula> supText) =>
|
||||
Sup(ToAction(baseText), supText);
|
||||
public IFormula Sup(Action<IFormula> baseText, string supText) =>
|
||||
Sup(baseText, ToAction(supText));
|
||||
public IFormula Sup(Action<IFormula> baseText, Action<IFormula> supText)
|
||||
{
|
||||
var superscript = FormulaHelper.CreateSuperscript(baseText, supText, this);
|
||||
if (TryGetCurrentMathContext(out var element))
|
||||
element.AppendChild(superscript);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
// Sub
|
||||
public IFormula Sub(string baseText, string subText) =>
|
||||
Sub(ToAction(baseText), ToAction(subText));
|
||||
public IFormula Sub(string baseText, Action<IFormula> subText) =>
|
||||
Sub(ToAction(baseText), subText);
|
||||
public IFormula Sub(Action<IFormula> baseText, string subText) =>
|
||||
Sub(baseText, ToAction(subText));
|
||||
public IFormula Sub(Action<IFormula> baseText, Action<IFormula> subText)
|
||||
{
|
||||
var subscript = FormulaHelper.CreateSubscript(baseText, subText, this);
|
||||
if (TryGetCurrentMathContext(out var element))
|
||||
element.AppendChild(subscript);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
// SubSup
|
||||
public IFormula SubSup(string baseText, string subText, string supText) =>
|
||||
SubSup(ToAction(baseText), ToAction(subText), ToAction(supText));
|
||||
public IFormula SubSup(string baseText, string subText, Action<IFormula> supText) =>
|
||||
SubSup(ToAction(baseText), ToAction(subText), supText);
|
||||
public IFormula SubSup(string baseText, Action<IFormula> subText, string supText) =>
|
||||
SubSup(ToAction(baseText), subText, ToAction(supText));
|
||||
public IFormula SubSup(string baseText, Action<IFormula> subText, Action<IFormula> supText) =>
|
||||
SubSup(ToAction(baseText), subText, supText);
|
||||
public IFormula SubSup(Action<IFormula> baseText, string subText, string supText) =>
|
||||
SubSup(baseText, ToAction(subText), ToAction(supText));
|
||||
public IFormula SubSup(Action<IFormula> baseText, string subText, Action<IFormula> supText) =>
|
||||
SubSup(baseText, ToAction(subText), supText);
|
||||
public IFormula SubSup(Action<IFormula> baseText, Action<IFormula> subText, string supText) =>
|
||||
SubSup(baseText, subText, ToAction(supText));
|
||||
public IFormula SubSup(Action<IFormula> baseText, Action<IFormula> subText, Action<IFormula> supText)
|
||||
{
|
||||
var subSup = FormulaHelper.CreateSubSuperscript(baseText, subText, supText, this);
|
||||
if (TryGetCurrentMathContext(out var element))
|
||||
element.AppendChild(subSup);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
// Root
|
||||
public IFormula Root(string radicand) => Root(ToAction(radicand));
|
||||
public IFormula Root(Action<IFormula> radicand)
|
||||
{
|
||||
var radical = FormulaHelper.CreateRadical(radicand, null, this);
|
||||
if (TryGetCurrentMathContext(out var element))
|
||||
element.AppendChild(radical);
|
||||
return this;
|
||||
}
|
||||
public IFormula Root(string radicand, string degree) =>
|
||||
Root(ToAction(radicand), ToAction(degree));
|
||||
public IFormula Root(string radicand, Action<IFormula> degree) =>
|
||||
Root(ToAction(radicand), degree);
|
||||
public IFormula Root(Action<IFormula> radicand, string degree) =>
|
||||
Root(radicand, ToAction(degree));
|
||||
public IFormula Root(Action<IFormula> radicand, Action<IFormula> degree)
|
||||
{
|
||||
var radical = FormulaHelper.CreateRadical(radicand, degree, this);
|
||||
if (TryGetCurrentMathContext(out var element))
|
||||
element.AppendChild(radical);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
private void AddIntegralCore(
|
||||
Action<IFormula> function,
|
||||
Action<IFormula> differential,
|
||||
Action<IFormula>? lowerLimit,
|
||||
Action<IFormula>? upperLimit)
|
||||
{
|
||||
if (TryGetCurrentMathContext(out var element))
|
||||
FormulaHelper.AddIntegral(element, function, differential, lowerLimit, upperLimit, this);
|
||||
}
|
||||
|
||||
public IFormula Integral(string function, string differential, string? lowerLimit = null, string? upperLimit = null) =>
|
||||
Integral(ToAction(function), ToAction(differential), ToNullableAction(lowerLimit), ToNullableAction(upperLimit));
|
||||
public IFormula Integral(string function, string differential, string? lowerLimit = null, Action<IFormula>? upperLimit = null) =>
|
||||
Integral(ToAction(function), ToAction(differential), ToNullableAction(lowerLimit), upperLimit);
|
||||
public IFormula Integral(string function, string differential, Action<IFormula>? lowerLimit = null, string? upperLimit = null) =>
|
||||
Integral(ToAction(function), ToAction(differential), lowerLimit, ToNullableAction(upperLimit));
|
||||
public IFormula Integral(string function, string differential, Action<IFormula>? lowerLimit = null, Action<IFormula>? upperLimit = null) =>
|
||||
Integral(ToAction(function), ToAction(differential), lowerLimit, upperLimit);
|
||||
public IFormula Integral(string function, Action<IFormula> differential, string? lowerLimit = null, string? upperLimit = null) =>
|
||||
Integral(ToAction(function), differential, ToNullableAction(lowerLimit), ToNullableAction(upperLimit));
|
||||
public IFormula Integral(string function, Action<IFormula> differential, string? lowerLimit = null, Action<IFormula>? upperLimit = null) =>
|
||||
Integral(ToAction(function), differential, ToNullableAction(lowerLimit), upperLimit);
|
||||
public IFormula Integral(string function, Action<IFormula> differential, Action<IFormula>? lowerLimit = null, string? upperLimit = null) =>
|
||||
Integral(ToAction(function), differential, lowerLimit, ToNullableAction(upperLimit));
|
||||
public IFormula Integral(string function, Action<IFormula> differential, Action<IFormula>? lowerLimit = null, Action<IFormula>? upperLimit = null) =>
|
||||
Integral(ToAction(function), differential, lowerLimit, upperLimit);
|
||||
public IFormula Integral(Action<IFormula> function, string differential, string? lowerLimit = null, string? upperLimit = null) =>
|
||||
Integral(function, ToAction(differential), ToNullableAction(lowerLimit), ToNullableAction(upperLimit));
|
||||
public IFormula Integral(Action<IFormula> function, string differential, string? lowerLimit = null, Action<IFormula>? upperLimit = null) =>
|
||||
Integral(function, ToAction(differential), ToNullableAction(lowerLimit), upperLimit);
|
||||
public IFormula Integral(Action<IFormula> function, string differential, Action<IFormula>? lowerLimit = null, string? upperLimit = null) =>
|
||||
Integral(function, ToAction(differential), lowerLimit, ToNullableAction(upperLimit));
|
||||
public IFormula Integral(Action<IFormula> function, string differential, Action<IFormula>? lowerLimit = null, Action<IFormula>? upperLimit = null) =>
|
||||
Integral(function, ToAction(differential), lowerLimit, upperLimit);
|
||||
public IFormula Integral(Action<IFormula> function, Action<IFormula> differential, string? lowerLimit = null, string? upperLimit = null) =>
|
||||
Integral(function, differential, ToNullableAction(lowerLimit), ToNullableAction(upperLimit));
|
||||
public IFormula Integral(Action<IFormula> function, Action<IFormula> differential, string? lowerLimit = null, Action<IFormula>? upperLimit = null) =>
|
||||
Integral(function, differential, ToNullableAction(lowerLimit), upperLimit);
|
||||
public IFormula Integral(Action<IFormula> function, Action<IFormula> differential, Action<IFormula>? lowerLimit = null, string? upperLimit = null) =>
|
||||
Integral(function, differential, lowerLimit, ToNullableAction(upperLimit));
|
||||
public IFormula Integral(Action<IFormula> function, Action<IFormula> differential, Action<IFormula>? lowerLimit = null, Action<IFormula>? upperLimit = null)
|
||||
{
|
||||
AddIntegralCore(function, differential, lowerLimit, upperLimit);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
// Sum
|
||||
private void AddSumCore(
|
||||
Action<IFormula> expression,
|
||||
Action<IFormula>? lowerLimit,
|
||||
Action<IFormula>? upperLimit)
|
||||
{
|
||||
if (TryGetCurrentMathContext(out var element))
|
||||
FormulaHelper.AddSum(element, expression, lowerLimit, upperLimit, this);
|
||||
}
|
||||
|
||||
public IFormula Sum(string expression, string? lowerLimit = null, string? upperLimit = null) =>
|
||||
Sum(ToAction(expression), ToNullableAction(lowerLimit), ToNullableAction(upperLimit));
|
||||
public IFormula Sum(string expression, string? lowerLimit = null, Action<IFormula>? upperLimit = null) =>
|
||||
Sum(ToAction(expression), ToNullableAction(lowerLimit), upperLimit);
|
||||
public IFormula Sum(string expression, Action<IFormula>? lowerLimit = null, string? upperLimit = null) =>
|
||||
Sum(ToAction(expression), lowerLimit, ToNullableAction(upperLimit));
|
||||
public IFormula Sum(string expression, Action<IFormula>? lowerLimit = null, Action<IFormula>? upperLimit = null) =>
|
||||
Sum(ToAction(expression), lowerLimit, upperLimit);
|
||||
public IFormula Sum(Action<IFormula> expression, string? lowerLimit = null, string? upperLimit = null) =>
|
||||
Sum(expression, ToNullableAction(lowerLimit), ToNullableAction(upperLimit));
|
||||
public IFormula Sum(Action<IFormula> expression, string? lowerLimit = null, Action<IFormula>? upperLimit = null) =>
|
||||
Sum(expression, ToNullableAction(lowerLimit), upperLimit);
|
||||
public IFormula Sum(Action<IFormula> expression, Action<IFormula>? lowerLimit = null, string? upperLimit = null) =>
|
||||
Sum(expression, lowerLimit, ToNullableAction(upperLimit));
|
||||
public IFormula Sum(Action<IFormula> expression, Action<IFormula>? lowerLimit = null, Action<IFormula>? upperLimit = null)
|
||||
{
|
||||
AddSumCore(expression, lowerLimit, upperLimit);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Вспомогательный метод для преобразования строки в делегат
|
||||
private static Action<IFormula>? ToNullableAction(string? text) => text is null ? null : (b => b.Text(text));
|
||||
private static Action<IFormula> ToAction(string text) => b => b.Text(text);
|
||||
}
|
||||
328
QWERTYkez.WordProcessor/Builders/TableBuilder.cs
Normal file
328
QWERTYkez.WordProcessor/Builders/TableBuilder.cs
Normal file
@@ -0,0 +1,328 @@
|
||||
namespace QWERTYkez.WordProcessor.Builders;
|
||||
|
||||
internal sealed class TableBuilder : ParagraphBuilderBase, ITable, IRow, ICell
|
||||
{
|
||||
private readonly Table _table = new();
|
||||
|
||||
internal TableBuilder(FontProps? baseFont) : base(baseFont)
|
||||
{
|
||||
}
|
||||
|
||||
internal static TableBuilder Create(FontProps? baseFont = null) => new(baseFont);
|
||||
|
||||
|
||||
// Метод завершения сборки
|
||||
public Table Build() => _table;
|
||||
|
||||
// Публичные методы настройки таблицы
|
||||
public ITable Properties(
|
||||
uint borderWidth = 8,
|
||||
BorderValues? borderValues = null,
|
||||
TableRowAlignmentValues? tableAlignment = null)
|
||||
{
|
||||
var borderType = borderValues ?? BorderValues.Single;
|
||||
var alignment = tableAlignment ?? TableRowAlignmentValues.Center;
|
||||
|
||||
_table.AppendChild(new TableProperties(
|
||||
new TableBorders(
|
||||
new TopBorder() { Val = borderType, Size = borderWidth },
|
||||
new BottomBorder() { Val = borderType, Size = borderWidth },
|
||||
new LeftBorder() { Val = borderType, Size = borderWidth },
|
||||
new RightBorder() { Val = borderType, Size = borderWidth },
|
||||
new InsideHorizontalBorder() { Val = borderType, Size = borderWidth },
|
||||
new InsideVerticalBorder() { Val = borderType, Size = borderWidth }
|
||||
),
|
||||
new TableJustification { Val = alignment },
|
||||
new TableLayout() { Type = TableLayoutValues.Autofit }
|
||||
));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
// Добавление строк с использованием IRowBuilder
|
||||
public ITable AddRow(Action<IRow> configure)
|
||||
{
|
||||
var IRowBuilder = RowBuilder;
|
||||
configure(this);
|
||||
_table.AppendChild(IRowBuilder.Build());
|
||||
return this;
|
||||
}
|
||||
|
||||
public ITable AddRow(double height, Action<IRow> configure)
|
||||
{
|
||||
var IRowBuilder = RowBuilder.SetHeight(height);
|
||||
configure(this);
|
||||
_table.AppendChild(IRowBuilder.Build());
|
||||
return this;
|
||||
}
|
||||
|
||||
// Быстрые методы для добавления строк с ячейками
|
||||
public ITable AddRowWithCells(params string[] cellTexts)
|
||||
{
|
||||
AddRow(row =>
|
||||
{
|
||||
foreach (var text in cellTexts)
|
||||
{
|
||||
row.AddCell(text);
|
||||
}
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
public ITable AddRowWithCells(FontProps font, params string[] cellTexts)
|
||||
{
|
||||
AddRow(row =>
|
||||
{
|
||||
foreach (var text in cellTexts)
|
||||
{
|
||||
row.AddCell(text, font);
|
||||
}
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private TableRow _row = null!;
|
||||
internal IRow RowBuilder
|
||||
{
|
||||
get
|
||||
{
|
||||
_row = new();
|
||||
return this;
|
||||
}
|
||||
}
|
||||
TableRow IRow.Build() => _row;
|
||||
|
||||
|
||||
// Настройка высоты строки (исправленный метод)
|
||||
public IRow SetHeight(double heightInCm)
|
||||
{
|
||||
var height = new TableRowHeight
|
||||
{
|
||||
Val = (UInt32Value)(uint)(heightInCm * 567), // 1 см = 567 DXA
|
||||
HeightType = HeightRuleValues.AtLeast
|
||||
};
|
||||
|
||||
// Убедимся, что TableRowProperties существует
|
||||
if (_row.TableRowProperties is null)
|
||||
{
|
||||
_row.TableRowProperties = new TableRowProperties();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Удалим существующий TableRowHeight, если он есть
|
||||
var existingHeight = _row.TableRowProperties.Elements<TableRowHeight>().FirstOrDefault();
|
||||
existingHeight?.Remove();
|
||||
}
|
||||
|
||||
// Добавляем TableRowHeight как дочерний элемент
|
||||
_row.TableRowProperties.AppendChild(height);
|
||||
return this;
|
||||
}
|
||||
|
||||
public IRow SetExactHeight(double heightInCm)
|
||||
{
|
||||
var height = new TableRowHeight
|
||||
{
|
||||
Val = (UInt32Value)(uint)(heightInCm * 567),
|
||||
HeightType = HeightRuleValues.Exact
|
||||
};
|
||||
|
||||
// Убедимся, что TableRowProperties существует
|
||||
if (_row.TableRowProperties is null)
|
||||
{
|
||||
_row.TableRowProperties = new TableRowProperties();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Удалим существующий TableRowHeight, если он есть
|
||||
var existingHeight = _row.TableRowProperties.Elements<TableRowHeight>().FirstOrDefault();
|
||||
existingHeight?.Remove();
|
||||
}
|
||||
|
||||
// Добавляем TableRowHeight как дочерний элемент
|
||||
_row.TableRowProperties.AppendChild(height);
|
||||
return this;
|
||||
}
|
||||
|
||||
// Добавление ячеек
|
||||
public IRow AddCell(Action<ICell> configure)
|
||||
{
|
||||
var cellBuilder = CellBuilder;
|
||||
configure(this);
|
||||
_row.AppendChild(cellBuilder.Build());
|
||||
return this;
|
||||
}
|
||||
|
||||
public IRow AddCell(string text)
|
||||
{
|
||||
var cellBuilder = CellBuilder;
|
||||
cellBuilder.AddParagraph(p => p.AddRun(text));
|
||||
_row.AppendChild(cellBuilder.Build());
|
||||
return this;
|
||||
}
|
||||
|
||||
public IRow AddCell(string text, FontProps font)
|
||||
{
|
||||
var cellBuilder = CellBuilder;
|
||||
|
||||
if (font is not null)
|
||||
cellBuilder.AddParagraph(p => p.AddRun(text, font));
|
||||
else cellBuilder.AddParagraph(p => p.AddRun(text));
|
||||
|
||||
_row.AppendChild(cellBuilder.Build());
|
||||
return this;
|
||||
}
|
||||
|
||||
public IRow AddCell(CellProps cellProps, string text, FontProps font)
|
||||
{
|
||||
var cellBuilder = CellBuilder.SetCellProps(cellProps);
|
||||
|
||||
if (font is not null)
|
||||
cellBuilder.AddParagraph(p => p.AddRun(text, font));
|
||||
else cellBuilder.AddParagraph(p => p.AddRun(text));
|
||||
|
||||
_row.AppendChild(cellBuilder.Build());
|
||||
return this;
|
||||
}
|
||||
|
||||
public IRow AddCell(CellProps cellProps, string text)
|
||||
{
|
||||
var cellBuilder = CellBuilder.SetCellProps(cellProps);
|
||||
cellBuilder.AddParagraph(p => p.AddRun(text));
|
||||
_row.AppendChild(cellBuilder.Build());
|
||||
return this;
|
||||
}
|
||||
|
||||
public IRow AddCell(CellProps cellProps)
|
||||
{
|
||||
var cellBuilder = CellBuilder.SetCellProps(cellProps);
|
||||
_row.AppendChild(cellBuilder.Build());
|
||||
return this;
|
||||
}
|
||||
|
||||
// Метод для установки произвольных свойств строки
|
||||
public IRow SetProperties(Action<TableRowProperties> configure)
|
||||
{
|
||||
_row.TableRowProperties ??= new TableRowProperties();
|
||||
configure(_row.TableRowProperties);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public IRow AddCellWithPara(Action<IParagraph> configure)
|
||||
{
|
||||
var cellBuilder = CellBuilder;
|
||||
cellBuilder.AddParagraph(configure);
|
||||
_row.AppendChild(cellBuilder.Build());
|
||||
return this;
|
||||
}
|
||||
public IRow AddCellWithPara(CellProps cellProps, Action<IParagraph> configure)
|
||||
{
|
||||
var cellBuilder = CellBuilder.SetCellProps(cellProps);
|
||||
cellBuilder.AddParagraph(configure);
|
||||
_row.AppendChild(cellBuilder.Build());
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private TableCell _cell = null!;
|
||||
private List<Paragraph> _paragraphs = null!;
|
||||
internal ICell CellBuilder
|
||||
{
|
||||
get
|
||||
{
|
||||
_cell = new();
|
||||
_paragraphs = [];
|
||||
return this;
|
||||
}
|
||||
}
|
||||
TableCell ICell.Build()
|
||||
{
|
||||
foreach (var paragraph in _paragraphs)
|
||||
{
|
||||
_cell.AppendChild(paragraph);
|
||||
}
|
||||
return _cell;
|
||||
}
|
||||
|
||||
// Установка свойств ячейки
|
||||
public ICell SetCellProps(CellProps props)
|
||||
{
|
||||
if (props.TryExtract(out var elements))
|
||||
{
|
||||
_cell.TableCellProperties = new TableCellProperties(elements);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
// Добавление параграфов
|
||||
public ICell AddParagraph(Action<IParagraph> configure)
|
||||
{
|
||||
var paraBuilder = ParagraphBuilder;
|
||||
configure(paraBuilder);
|
||||
_paragraphs.Add(paraBuilder.Build());
|
||||
return this;
|
||||
}
|
||||
|
||||
public ICell AddParagraph(string text, FontProps? font = null)
|
||||
{
|
||||
var paraBuilder = ParagraphBuilder;
|
||||
|
||||
if (font is not null)
|
||||
{
|
||||
paraBuilder.AddRun(text, font);
|
||||
}
|
||||
else
|
||||
{
|
||||
paraBuilder.AddRun(text);
|
||||
}
|
||||
|
||||
_paragraphs.Add(paraBuilder.Build());
|
||||
return this;
|
||||
}
|
||||
|
||||
public ICell AddParagraph(params string[] lines)
|
||||
{
|
||||
var paraBuilder = ParagraphBuilder;
|
||||
if (lines.Length > 0)
|
||||
{
|
||||
paraBuilder.AddRun(lines[0]);
|
||||
for (int i = 1; i < lines.Length; i++)
|
||||
{
|
||||
paraBuilder.Break();
|
||||
paraBuilder.AddRun(lines[i]);
|
||||
}
|
||||
}
|
||||
_paragraphs.Add(paraBuilder.Build());
|
||||
return this;
|
||||
}
|
||||
|
||||
// Метод AddFormula для ICellBuilder
|
||||
ICell ICell.AddFormula(Action<IFormula> configure)
|
||||
{
|
||||
var paraBuilder = ParagraphBuilder;
|
||||
paraBuilder.AddFormula(configure);
|
||||
_paragraphs.Add(paraBuilder.Build());
|
||||
return this;
|
||||
}
|
||||
}
|
||||
110
QWERTYkez.WordProcessor/Builders/TextBuilder.cs
Normal file
110
QWERTYkez.WordProcessor/Builders/TextBuilder.cs
Normal file
@@ -0,0 +1,110 @@
|
||||
namespace QWERTYkez.WordProcessor.Builders;
|
||||
|
||||
internal sealed class TextBuilder : ParagraphBuilderBase, IText
|
||||
{
|
||||
private readonly ParagraphProperties? _baseParagraphProperties;
|
||||
|
||||
internal TextBuilder(FontProps? baseFont, ParagraphProperties? baseParagraphProperties = null) : base(baseFont)
|
||||
{
|
||||
_baseParagraphProperties = baseParagraphProperties?.CloneNode(true) as ParagraphProperties;
|
||||
}
|
||||
|
||||
internal static TextBuilder Create(FontProps? baseFont = null, ParagraphProperties? baseParagraphProperties = null) =>
|
||||
new(baseFont, baseParagraphProperties);
|
||||
|
||||
|
||||
|
||||
|
||||
// Переопределяем создание параграфа
|
||||
protected override IParagraph CreateParagraphBuilder()
|
||||
{
|
||||
_paragraph = new Paragraph();
|
||||
|
||||
if (_baseParagraphProperties is not null)
|
||||
{
|
||||
_paragraph.ParagraphProperties = _baseParagraphProperties.CloneNode(true) as ParagraphProperties;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Используем стандартные свойства (как в базовом классе)
|
||||
_paragraph.ParagraphProperties = new ParagraphProperties(
|
||||
new Justification { Val = JustificationValues.Center },
|
||||
new SpacingBetweenLines
|
||||
{
|
||||
After = "0",
|
||||
Before = "0",
|
||||
LineRule = LineSpacingRuleValues.Auto
|
||||
},
|
||||
new Indentation
|
||||
{
|
||||
Left = "0",
|
||||
Right = "0",
|
||||
FirstLine = "0",
|
||||
Hanging = "0"
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
_runs = [];
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private readonly List<Paragraph> _paragraphs = [];
|
||||
public List<Paragraph> Build() => _paragraphs;
|
||||
|
||||
IText IText.AddFormula(Action<IFormula> configure)
|
||||
{
|
||||
var paraBuilder = ParagraphBuilder;
|
||||
paraBuilder.AddFormula(configure);
|
||||
_paragraphs.Add(paraBuilder.Build());
|
||||
return this;
|
||||
}
|
||||
|
||||
// Добавление параграфов
|
||||
public IText AddParagraph(Action<IParagraph> configure)
|
||||
{
|
||||
var paraBuilder = ParagraphBuilder;
|
||||
configure(paraBuilder);
|
||||
_paragraphs.Add(paraBuilder.Build());
|
||||
return this;
|
||||
}
|
||||
|
||||
public IText AddParagraph(string text, FontProps? font = null)
|
||||
{
|
||||
var paraBuilder = ParagraphBuilder;
|
||||
|
||||
if (font is not null)
|
||||
{
|
||||
paraBuilder.AddRun(text, font);
|
||||
}
|
||||
else
|
||||
{
|
||||
paraBuilder.AddRun(text);
|
||||
}
|
||||
|
||||
_paragraphs.Add(paraBuilder.Build());
|
||||
return this;
|
||||
}
|
||||
|
||||
public IText AddParagraph(params string[] lines)
|
||||
{
|
||||
var paraBuilder = ParagraphBuilder;
|
||||
if (lines.Length > 0)
|
||||
{
|
||||
paraBuilder.AddRun(lines[0]);
|
||||
for (int i = 1; i < lines.Length; i++)
|
||||
{
|
||||
paraBuilder.Break();
|
||||
paraBuilder.AddRun(lines[i]);
|
||||
}
|
||||
}
|
||||
_paragraphs.Add(paraBuilder.Build());
|
||||
return this;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user