4
4
/// Represents a single row/column in a Terminal.Gui rendering surface (e.g. <see cref="LineCanvas"/> and
5
5
/// <see cref="ConsoleDriver"/>).
6
6
/// </summary>
7
- public record struct Cell ( )
7
+ public record struct Cell ( Attribute ? Attribute = null , bool IsDirty = false , Rune Rune = default )
8
8
{
9
-
10
9
/// <summary>The attributes to use when drawing the Glyph.</summary>
11
- public Attribute ? Attribute { get ; set ; } = null ;
10
+ public Attribute ? Attribute { get ; set ; } = Attribute ;
12
11
13
12
/// <summary>
14
13
/// Gets or sets a value indicating whether this <see cref="T:Terminal.Gui.Cell"/> has been modified since the
15
14
/// last time it was drawn.
16
15
/// </summary>
17
- public bool IsDirty { get ; set ; } = false ;
16
+ public bool IsDirty { get ; set ; } = IsDirty ;
18
17
19
- private Rune _rune = default ;
18
+ private Rune _rune = Rune ;
20
19
21
20
/// <summary>The character to display. If <see cref="Rune"/> is <see langword="null"/>, then <see cref="Rune"/> is ignored.</summary>
22
21
public Rune Rune
@@ -29,6 +28,8 @@ public Rune Rune
29
28
}
30
29
}
31
30
31
+ private List < Rune > _combiningMarks ;
32
+
32
33
/// <summary>
33
34
/// The combining marks for <see cref="Rune"/> that when combined makes this Cell a combining sequence. If
34
35
/// <see cref="CombiningMarks"/> empty, then <see cref="CombiningMarks"/> is ignored.
@@ -37,8 +38,153 @@ public Rune Rune
37
38
/// Only valid in the rare case where <see cref="Rune"/> is a combining sequence that could not be normalized to a
38
39
/// single Rune.
39
40
/// </remarks>
40
- internal List < Rune > CombiningMarks { get ; } = new ( ) ;
41
+ internal List < Rune > CombiningMarks
42
+ {
43
+ get => _combiningMarks ?? [ ] ;
44
+ private set => _combiningMarks = value ?? [ ] ;
45
+ }
41
46
42
47
/// <inheritdoc/>
43
48
public override string ToString ( ) { return $ "[{ Rune } , { Attribute } ]"; }
49
+
50
+ /// <summary>Converts the string into a <see cref="List{Cell}"/>.</summary>
51
+ /// <param name="str">The string to convert.</param>
52
+ /// <param name="attribute">The <see cref="Gui.ColorScheme"/> to use.</param>
53
+ /// <returns></returns>
54
+ public static List < Cell > ToCellList ( string str , Attribute ? attribute = null )
55
+ {
56
+ List < Cell > cells = new ( ) ;
57
+
58
+ foreach ( Rune rune in str . EnumerateRunes ( ) )
59
+ {
60
+ cells . Add ( new ( ) { Rune = rune , Attribute = attribute } ) ;
61
+ }
62
+
63
+ return cells ;
64
+ }
65
+
66
+ /// <summary>
67
+ /// Splits a string into a List that will contain a <see cref="List{Cell}"/> for each line.
68
+ /// </summary>
69
+ /// <param name="content">The string content.</param>
70
+ /// <param name="attribute">The color scheme.</param>
71
+ /// <returns>A <see cref="List{Cell}"/> for each line.</returns>
72
+ public static List < List < Cell > > StringToLinesOfCells ( string content , Attribute ? attribute = null )
73
+ {
74
+ List < Cell > cells = content . EnumerateRunes ( )
75
+ . Select ( x => new Cell { Rune = x , Attribute = attribute } )
76
+ . ToList ( ) ;
77
+
78
+ return SplitNewLines ( cells ) ;
79
+ }
80
+
81
+ /// <summary>Converts a <see cref="Cell"/> generic collection into a string.</summary>
82
+ /// <param name="cells">The enumerable cell to convert.</param>
83
+ /// <returns></returns>
84
+ public static string ToString ( IEnumerable < Cell > cells )
85
+ {
86
+ var str = string . Empty ;
87
+
88
+ foreach ( Cell cell in cells )
89
+ {
90
+ str += cell . Rune . ToString ( ) ;
91
+ }
92
+
93
+ return str ;
94
+ }
95
+
96
+ /// <summary>Converts a <see cref="List{Cell}"/> generic collection into a string.</summary>
97
+ /// <param name="cellsList">The enumerable cell to convert.</param>
98
+ /// <returns></returns>
99
+ public static string ToString ( List < List < Cell > > cellsList )
100
+ {
101
+ var str = string . Empty ;
102
+
103
+ for ( var i = 0 ; i < cellsList . Count ; i ++ )
104
+ {
105
+ IEnumerable < Cell > cellList = cellsList [ i ] ;
106
+ str += ToString ( cellList ) ;
107
+
108
+ if ( i + 1 < cellsList . Count )
109
+ {
110
+ str += Environment . NewLine ;
111
+ }
112
+ }
113
+
114
+ return str ;
115
+ }
116
+
117
+ // Turns the string into cells, this does not split the contents on a newline if it is present.
118
+
119
+ internal static List < Cell > StringToCells ( string str , Attribute ? attribute = null )
120
+ {
121
+ List < Cell > cells = [ ] ;
122
+
123
+ foreach ( Rune rune in str . ToRunes ( ) )
124
+ {
125
+ cells . Add ( new ( ) { Rune = rune , Attribute = attribute } ) ;
126
+ }
127
+
128
+ return cells ;
129
+ }
130
+
131
+ internal static List < Cell > ToCells ( IEnumerable < Rune > runes , Attribute ? attribute = null )
132
+ {
133
+ List < Cell > cells = new ( ) ;
134
+
135
+ foreach ( Rune rune in runes )
136
+ {
137
+ cells . Add ( new ( ) { Rune = rune , Attribute = attribute } ) ;
138
+ }
139
+
140
+ return cells ;
141
+ }
142
+
143
+ private static List < List < Cell > > SplitNewLines ( List < Cell > cells )
144
+ {
145
+ List < List < Cell > > lines = [ ] ;
146
+ int start = 0 , i = 0 ;
147
+ var hasCR = false ;
148
+
149
+ // ASCII code 13 = Carriage Return.
150
+ // ASCII code 10 = Line Feed.
151
+ for ( ; i < cells . Count ; i ++ )
152
+ {
153
+ if ( cells [ i ] . Rune . Value == 13 )
154
+ {
155
+ hasCR = true ;
156
+
157
+ continue ;
158
+ }
159
+
160
+ if ( cells [ i ] . Rune . Value == 10 )
161
+ {
162
+ if ( i - start > 0 )
163
+ {
164
+ lines . Add ( cells . GetRange ( start , hasCR ? i - 1 - start : i - start ) ) ;
165
+ }
166
+ else
167
+ {
168
+ lines . Add ( StringToCells ( string . Empty ) ) ;
169
+ }
170
+
171
+ start = i + 1 ;
172
+ hasCR = false ;
173
+ }
174
+ }
175
+
176
+ if ( i - start >= 0 )
177
+ {
178
+ lines . Add ( cells . GetRange ( start , i - start ) ) ;
179
+ }
180
+
181
+ return lines ;
182
+ }
183
+
184
+ /// <summary>
185
+ /// Splits a rune cell list into a List that will contain a <see cref="List{Cell}"/> for each line.
186
+ /// </summary>
187
+ /// <param name="cells">The cells list.</param>
188
+ /// <returns></returns>
189
+ public static List < List < Cell > > ToCells ( List < Cell > cells ) { return SplitNewLines ( cells ) ; }
44
190
}
0 commit comments