Skip to content

Commit 4fabb9d

Browse files
committed
Experimenting with Table support
1 parent 4fc0a99 commit 4fabb9d

20 files changed

Lines changed: 333 additions & 170 deletions

AvRichTextBox/AvRichTextBox.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@
2020

2121
<RepositoryUrl>https://github.com/cuikp/AvRichTextBox</RepositoryUrl>
2222
<RepositoryType>git</RepositoryType>
23-
<PackageReleaseNotes>ver 1.5.0: Can add direct content to RichTextBox in Xaml</PackageReleaseNotes>
23+
<PackageReleaseNotes>ver 1.5.1: prevented CR error at images, tab insertion enabled</PackageReleaseNotes>
2424

2525
<GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>
2626
<PackageOutputPath>D:\PROG\LocalNuget\AvRichTextBox</PackageOutputPath>
2727

28-
<Version>1.5.0</Version>
28+
<Version>1.5.1</Version>
2929
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
3030
<AssemblyVersion>1.0.0.0</AssemblyVersion>
3131

AvRichTextBox/Blocks/Paragraph.cs

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,6 @@ private void Inlines_CollectionChanged(object? sender, System.Collections.Specia
2121
foreach (IEditable ied in Inlines)
2222
ied.MyParagraphId = this.Id;
2323

24-
//if (e.NewItems != null)
25-
//{
26-
// foreach (IEditable ied in e.NewItems)
27-
// {
28-
// if (ied is EditableLineBreak elb)
29-
// {
30-
// int elbIdx = Inlines.IndexOf(elb);
31-
// Debug.WriteLine("ndex = " + elbIdx);
32-
// if (elbIdx == 0 || (Inlines[elbIdx - 1] is EditableRun erun && erun.Text != ""))
33-
// Inlines.Insert(elbIdx, new EditableRun(""));
34-
// }
35-
// }
36-
//}
37-
3824
}
3925

4026
public string ParToolTip => $"Background: {Background}\nLineSpacing: {LineSpacing}\nLineHeight: {LineHeight}";

AvRichTextBox/Blocks/Table.cs

Lines changed: 59 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,82 @@
11
using Avalonia.Controls;
2-
//using Avalonia.Media;
2+
using Avalonia.Layout;
3+
using Avalonia.Media;
34
using System.Collections.ObjectModel;
4-
//using System.ComponentModel;
5-
//using System.Runtime.CompilerServices;
5+
using System.Diagnostics;
66

77
namespace AvRichTextBox;
88

99
public partial class Table : Block
1010
{
11+
1112
public Thickness BorderThickness { get; set; } = new(1);
12-
public ObservableCollection<Border> Cells { get; set; } = [];
13+
public ObservableCollection<Cell> Cells { get; set; } = [];
1314
public ColumnDefinitions ColDefs { get; set; } = [];
1415
public RowDefinitions RowDefs { get; set; } = [];
16+
public double Height { get; set; } = 500;
17+
public double Width { get; set; } = 500;
18+
public HorizontalAlignment TableAlignment { get; set; } = HorizontalAlignment.Left;
19+
20+
public Table() { }
1521

22+
public Table(int cols, int rows)
23+
{
24+
double eqWidth = Width / cols;
25+
double eqHeight = Height / rows;
1626

17-
// public Table(int noCols, int noRows, double TableWidth)
18-
// {
19-
// double eqSpacedColWidth = 10D / (double)noCols;
27+
int cellno = 0;
2028

21-
// for (int rowno = 0; rowno < noRows; rowno++)
22-
// this.RowDefs.Add(new RowDefinition());
23-
// for (int colno = 0; colno < noCols; colno++)
24-
// this.ColDefs.Add(new ColumnDefinition(eqSpacedColWidth, GridUnitType.Star));
29+
for (int rowno = 0; rowno < rows; rowno++)
30+
{
31+
RowDefs.Add(new RowDefinition(eqHeight, GridUnitType.Pixel));
32+
33+
for (int colno = 0; colno < cols; colno++)
34+
{
35+
ColDefs.Add(new ColumnDefinition(eqWidth, GridUnitType.Pixel));
36+
Paragraph newPar = new();
37+
newPar.Inlines.Add(new EditableRun("col:" + colno));
38+
newPar.Inlines.Add(new EditableLineBreak());
39+
newPar.Inlines.Add(new EditableRun("row:" + rowno));
40+
41+
Cell newCell = new()
42+
{
43+
ColNo = colno,
44+
RowNo = rowno,
45+
BorderThickness = new(3),
46+
BorderBrush = Brushes.Red,
47+
CellContent = newPar
48+
};
49+
Cells.Add(newCell);
50+
cellno++;
51+
}
52+
}
2553

26-
// for (int rowno = 0; rowno < noRows; rowno++)
27-
// {
28-
// for (int colno = 0; colno < noCols; colno++)
29-
// {
30-
// Border cellborder = new() { BorderBrush = Brushes.Black, BorderThickness = new Thickness(0.5) };
31-
// SelectableTextBlock seltb = new() { GetText = "this is some text, with wrapping as well." };
32-
// seltb.Background = Brushes.White;
33-
// seltb.TextWrapping = TextWrapping.Wrap;
34-
// cellborder.Child = seltb;
35-
// Cells.Add(cellborder);
36-
// Grid.SetRow(cellborder, rowno);
37-
// Grid.SetColumn(cellborder, colno);
38-
// }
39-
// }
4054

4155

42-
// }
56+
}
4357

4458

59+
internal void InsertColumn(int idx)
60+
{
4561

62+
}
63+
64+
65+
}
66+
67+
68+
public class Cell
69+
{
70+
public Cell() { }
4671

72+
public Block CellContent { get; set; } = new Paragraph();
73+
public Thickness BorderThickness { get; set; } = new (1);
74+
public IBrush BorderBrush { get; set; } = null!;
75+
public int ColNo { get; set; }
76+
public int RowNo { get; set; }
4777

78+
public double Width { get; set; } = 100;
79+
public double Height { get; set; } = 60;
80+
4881
}
4982

AvRichTextBox/EditableBlocks/EditableParagraph/EditableParagraph.cs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
using Avalonia.Interactivity;
33
using Avalonia.Media;
44
using Avalonia.Threading;
5+
using DocumentFormat.OpenXml.ExtendedProperties;
6+
using DocumentFormat.OpenXml.Wordprocessing;
57

68
namespace AvRichTextBox;
79

@@ -23,12 +25,29 @@ public EditableParagraph()
2325

2426
//this.KeyDown += EditableParagraph_KeyDown;
2527

28+
2629
}
2730

31+
2832
private void EditableParagraph_Loaded(object? sender, RoutedEventArgs e)
2933
{
3034
UpdateInlines();
31-
35+
36+
if (this.DataContext is not Paragraph thisPar) return;
37+
38+
if (Inlines?.Count == 0)
39+
thisPar.Inlines.Add(new EditableRun(""));
40+
41+
List<int> lineBreakIndexes = Inlines.OfType<EditableLineBreak>().ToList().ConvertAll(elb => Inlines.IndexOf(elb));
42+
for (int idx = lineBreakIndexes.Count - 1; idx >= 0; idx--)
43+
{
44+
int elbIdx = lineBreakIndexes[idx];
45+
if (elbIdx == 0 || (Inlines[elbIdx - 1] is EditableRun erun && erun.Text != ""))
46+
thisPar.Inlines.Insert(elbIdx + 1, new EditableRun(""));
47+
}
48+
thisPar.UpdateEditableRunPositions();
49+
UpdateInlines();
50+
3251
}
3352

3453
public static readonly StyledProperty<bool> TextLayoutInfoStartRequestedProperty = AvaloniaProperty.Register<EditableParagraph, bool>(nameof(TextLayoutInfoStartRequested));
@@ -170,7 +189,6 @@ protected override void OnPointerReleased(PointerReleasedEventArgs e)
170189

171190
internal void UpdateInlines()
172191
{
173-
174192
if (((Paragraph)this.DataContext!).Inlines != null)
175193
this.Inlines = GetFormattedInlines();
176194

@@ -183,6 +201,7 @@ internal void UpdateInlines()
183201
this.InvalidateMeasure();
184202
this.InvalidateVisual();
185203

204+
186205
}
187206

188207
public int SelectionLength => SelectionEnd - SelectionStart;

AvRichTextBox/EditableBlocks/EditableParagraph/EditableParagraph_EventHandlers.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
using Avalonia;
2-
using System.Collections.Generic;
1+
using System.Collections.Generic;
32

43
namespace AvRichTextBox;
54

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
using Avalonia.Controls;
2+
using Avalonia.Interactivity;
3+
4+
namespace AvRichTextBox;
5+
6+
public class BindableGrid : Grid
7+
{
8+
public BindableGrid()
9+
{
10+
ColDefs.CollectionChanged += ColDefs_CollectionChanged;
11+
RowDefs.CollectionChanged += RowDefs_CollectionChanged;
12+
13+
this.Loaded += BindableGrid_Loaded;
14+
15+
}
16+
17+
private void BindableGrid_Loaded(object? sender, RoutedEventArgs e)
18+
{
19+
RowDefinitions = RowDefs;
20+
ColumnDefinitions = ColDefs;
21+
22+
this.UpdateLayout();
23+
}
24+
25+
public static readonly StyledProperty<RowDefinitions> RowDefsProperty = AvaloniaProperty.Register<BindableGrid, RowDefinitions>(nameof(RowDefs), defaultValue: new RowDefinitions());
26+
public static readonly StyledProperty<ColumnDefinitions> ColDefsProperty = AvaloniaProperty.Register<BindableGrid, ColumnDefinitions>(nameof(ColDefs), defaultValue: new ColumnDefinitions());
27+
public RowDefinitions RowDefs { get => GetValue(RowDefsProperty); set => SetValue(RowDefsProperty, value); }
28+
public ColumnDefinitions ColDefs { get => GetValue(ColDefsProperty); set => SetValue(ColDefsProperty, value); }
29+
30+
private void ColDefs_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
31+
{
32+
if (e.NewItems != null)
33+
foreach (ColumnDefinition cdef in e.NewItems)
34+
ColumnDefinitions.Add(cdef);
35+
if (e.OldItems != null)
36+
foreach (ColumnDefinition cdef in e.OldItems)
37+
ColumnDefinitions.Remove(cdef);
38+
}
39+
40+
private void RowDefs_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
41+
{
42+
if (e.NewItems != null)
43+
foreach (RowDefinition rdef in e.NewItems)
44+
RowDefinitions.Add(rdef);
45+
46+
if (e.OldItems != null)
47+
foreach (RowDefinition rdef in e.OldItems)
48+
RowDefinitions.Remove(rdef);
49+
}
50+
51+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using Avalonia.Controls;
2+
using Avalonia.Data;
3+
4+
namespace AvRichTextBox;
5+
6+
public class EditableCell : Border
7+
{
8+
public EditableCell()
9+
{
10+
11+
//this.Bind(Grid.RowProperty, new Binding("RowNo"));
12+
//this.Bind(Grid.ColumnProperty, new Binding("ColNo"));
13+
//this.Bind(HeightProperty, new Binding("Height"));
14+
//this.Bind(WidthProperty, new Binding("Width"));
15+
//this.Bind(BorderThicknessProperty, new Binding("BorderThickness"));
16+
//this.Bind(BorderBrushProperty, new Binding("BorderBrush"));
17+
}
18+
19+
}
20+
21+
Lines changed: 13 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,90 +1,33 @@
1-
using Avalonia;
2-
using Avalonia.Controls;
1+
using Avalonia.Controls;
32
using Avalonia.Interactivity;
43
using System.Collections.ObjectModel;
54

65
namespace AvRichTextBox;
76

8-
97
public partial class EditableTable : Grid, IEditableBlock
108
{
119
public bool IsEditable { get; set; } = true;
1210

13-
public static readonly StyledProperty<ObservableCollection<Border>> CellsProperty = AvaloniaProperty.Register<EditableTable, ObservableCollection<Border>>(nameof(Cells));
14-
public static readonly StyledProperty<ColumnDefinitions> ColDefsProperty = AvaloniaProperty.Register<EditableTable, ColumnDefinitions>(nameof(ColDefs));
15-
public static readonly StyledProperty<RowDefinitions> RowDefsProperty = AvaloniaProperty.Register<EditableTable, RowDefinitions>(nameof(RowDefs));
16-
17-
public ColumnDefinitions ColDefs
11+
public EditableTable()
1812
{
19-
get => GetValue(ColDefsProperty);
20-
set { SetValue(ColDefsProperty, value); }
13+
Loaded += EditableTable_Loaded;
2114
}
2215

23-
public RowDefinitions RowDefs
24-
{
25-
get => GetValue(RowDefsProperty);
26-
set { SetValue(RowDefsProperty, value); }
16+
private void EditableTable_Loaded(object? sender, RoutedEventArgs e)
17+
{
18+
this.UpdateLayout();
2719
}
2820

29-
public ObservableCollection<Border> Cells
21+
public static readonly StyledProperty<ObservableCollection<EditableCell>> CellsProperty = AvaloniaProperty.Register<EditableTable, ObservableCollection<EditableCell>>(nameof(Cells), defaultValue: []);
22+
public ObservableCollection<EditableCell> Cells { get => GetValue(CellsProperty); set => SetValue(CellsProperty, value); }
23+
24+
private void Cells_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
3025
{
31-
get => GetValue(CellsProperty);
32-
set => SetValue(CellsProperty, value);
26+
this.UpdateLayout();
3327
}
34-
35-
//public EditableTable()
36-
//{
37-
// this.Loaded += EditableTable_Loaded;
38-
39-
//}
40-
41-
//private void Cells_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
42-
//{
43-
// foreach (Border newCell in e.NewItems)
44-
// this.Children.Add(newCell);
45-
//}
46-
47-
//private void ColDefs_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
48-
//{
49-
// foreach (ColumnDefinition cdef in e.NewItems)
50-
// ColumnDefinitions.Add(cdef);
51-
// foreach (ColumnDefinition cdef in e.OldItems)
52-
// ColumnDefinitions.Remove(cdef);
53-
54-
//}
55-
56-
//private void RowDefs_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
57-
//{
58-
// foreach (RowDefinition rdef in e.NewItems)
59-
// RowDefinitions.Add(rdef);
60-
// foreach (RowDefinition rdef in e.OldItems)
61-
// RowDefinitions.Remove(rdef);
62-
63-
//}
64-
65-
//private void EditableTable_Loaded(object? sender, RoutedEventArgs e)
66-
//{
67-
// //ColDefs.CollectionChanged += ColDefs_CollectionChanged;
68-
// //RowDefs.CollectionChanged += RowDefs_CollectionChanged;
69-
// Cells.CollectionChanged += Cells_CollectionChanged;
70-
71-
// RowDefinitions = RowDefs;
72-
// ColumnDefinitions = ColDefs;
73-
74-
// foreach (Border b in Cells)
75-
// {
76-
// this.Children.Add(b);
77-
// //Debug.WriteLine(Grid.GetRow(b));
78-
// }
79-
80-
// //Debug.WriteLine("cellcount=" + Cells.Count);
81-
82-
// this.UpdateLayout();
83-
//}
84-
28+
8529
////public string GetText => string.Join("", ((Table)this.DataContext).Inlines.ToList().ConvertAll(edinline => edinline.InlineText));
8630

87-
88-
8931
}
9032

33+

AvRichTextBox/FlowDocument/FlowDocument.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ internal void SelectionEnd_Changed(TextRange selRange, int newEnd)
241241
internal void UpdateSelectedParagraphs()
242242
{
243243
SelectionParagraphs.Clear();
244-
SelectionParagraphs.AddRange(Blocks.Where(p => p.StartInDoc + p.BlockLength > Selection.Start && p.StartInDoc <= Selection.End).ToList().ConvertAll(bb => (Paragraph)bb));
244+
SelectionParagraphs.AddRange(Blocks.OfType<Paragraph>().Where(p => p.StartInDoc + p.BlockLength > Selection.Start && p.StartInDoc <= Selection.End).ToList());
245245
}
246246

247247
internal string GetText(TextRange tRange) => string.Join("", GetRangeInlines(tRange).ConvertAll(il => il.InlineText));

0 commit comments

Comments
 (0)