Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
GridCells.cs
1using System;
2using System.Collections.Generic;
3using System.Threading.Tasks;
4using Waher.Script;
5
7{
11 public class GridCells : ICellLayout
12 {
13 private readonly List<GridPadding> elements = new List<GridPadding>();
14 private readonly Variables session;
15 private readonly int nrColumns;
16 private readonly float[] rights;
17 private readonly float[] widths;
18 private readonly List<float> bottoms;
19 private readonly List<float> heights;
20 private int x = 0;
21 private int y = 0;
22
28 public GridCells(Variables Session, int NrColumns)
29 {
30 this.session = Session;
31 this.nrColumns = NrColumns;
32 this.rights = new float[this.nrColumns];
33 this.widths = new float[this.nrColumns];
34 this.bottoms = new List<float>();
35 this.heights = new List<float>();
36 }
37
38 private GridPadding GetElement(int X, int Y)
39 {
40 if (X < 0 || X >= this.nrColumns)
41 return null;
42
43 if (Y < 0)
44 return null;
45
46 int i = Y * this.nrColumns + X;
47 if (i >= this.elements.Count)
48 return null;
49
50 return this.elements[i];
51 }
52
53 private void IncPos()
54 {
55 this.x++;
56 if (this.x >= this.nrColumns)
57 {
58 this.x = 0;
59 this.y++;
60 }
61 }
62
63 private float GetRight(int x)
64 {
65 if (x < 0)
66 return 0;
67 else if (x >= this.nrColumns)
68 throw new InvalidOperationException("Cell does not fit in grid.");
69 else
70 return this.rights[x];
71 }
72
73 private float GetBottom(int y)
74 {
75 if (y < 0)
76 return 0;
77
78 int c = this.bottoms.Count;
79 while (c <= y)
80 {
81 this.heights.Add(0);
82
83 if (c == 0)
84 this.bottoms.Add(0);
85 else
86 this.bottoms.Add(this.bottoms[c - 1]);
87
88 c++;
89 }
90
91 return this.bottoms[y];
92 }
93
98 public async Task Add(ILayoutElement Element)
99 {
100 CellSpan Span;
101
102 if (Element is Cell Cell)
103 Span = await Cell.CalcSpan(this.session);
104 else
105 Span.ColSpan = Span.RowSpan = 1;
106
107 while (!(this.GetElement(this.x, this.y) is null))
108 this.IncPos();
109
110 this.SetElement(this.x, this.y, Span.ColSpan, Span.RowSpan, Element);
111
112 int X2 = this.x + Span.ColSpan - 1;
113 if (X2 >= this.nrColumns)
114 X2 = this.nrColumns - 1;
115
116 float? f = Element.Width;
117 if (f.HasValue && Span.ColSpan == 1 && f.Value > this.widths[this.x])
118 this.widths[this.x] = f.Value;
119
120 float Right = this.GetRight(this.x - 1) + (f ?? 0);
121 float Right2 = this.GetRight(X2);
122 float Diff = Right - Right2;
123
124 while (Diff > 0)
125 {
126 this.rights[X2] += Diff;
127
128 if (++X2 >= this.nrColumns)
129 break;
130
131 Right2 = this.GetRight(X2);
132 Right += this.widths[X2];
133 Diff = Right - Right2;
134 }
135
136 int Y2 = this.y + Span.RowSpan - 1;
137
138 f = Element.Height;
139
140 float Bottom = this.GetBottom(this.y - 1) + (f ?? 0);
141 float Bottom2 = this.GetBottom(Y2);
142 int c = this.bottoms.Count;
143
144 if (f.HasValue && Span.RowSpan == 1 && f.Value > this.heights[this.y])
145 this.heights[this.y] = f.Value;
146
147 Diff = Bottom - Bottom2;
148
149 while (Diff > 0)
150 {
151 this.bottoms[Y2] += Diff;
152
153 if (++Y2 >= c)
154 break;
155
156 Bottom2 = this.GetBottom(Y2);
157 Bottom += this.heights[Y2];
158 Diff = Bottom - Bottom2;
159 }
160
161 this.x += Span.ColSpan;
162 if (this.x >= this.nrColumns)
163 {
164 this.x = 0;
165 this.y++;
166 }
167 }
168
172 public void Flush()
173 {
174 }
175
176 private void SetElement(int X, int Y, int ColSpan, int RowSpan, ILayoutElement Element)
177 {
178 GridPadding P = new GridPadding(Element, 0, 0, X, Y, ColSpan, RowSpan);
179
180 if (ColSpan > 1 || RowSpan > 1)
181 {
182 int i;
183 bool First = true;
184
185 for (; RowSpan > 0; RowSpan--)
186 {
187 for (i = 0; i < ColSpan; i++)
188 {
189 if (!this.SetElement(X + i, Y, P))
190 throw new InvalidOperationException("Cell does not fit in grid.");
191
192 if (First)
193 {
194 First = false;
195 P = new GridPadding(null, 0, 0, 0, 0, 0, 0);
196 }
197 }
198
199 Y++;
200 }
201 }
202 else
203 {
204 if (!this.SetElement(X, Y, P))
205 throw new InvalidOperationException("Cell does not fit in grid.");
206 }
207 }
208
209 private bool SetElement(int X, int Y, GridPadding Element)
210 {
211 if (X < 0 || X >= this.nrColumns)
212 return false;
213
214 if (Y < 0)
215 return false;
216
217 int i = Y * this.nrColumns + X;
218 int c = this.elements.Count;
219
220 while (i > c)
221 {
222 this.elements.Add(null);
223 c++;
224 }
225
226 if (i == c)
227 {
228 this.elements.Add(Element);
229 return true;
230 }
231 else
232 {
233 if (this.elements[i] is null)
234 {
235 this.elements[i] = Element;
236 return true;
237 }
238 else
239 return false;
240 }
241 }
242
246 public float TotWidth => this.GetRight(this.nrColumns - 1);
247
251 public float TotHeight => this.GetBottom(this.bottoms.Count - 1);
252
258 {
259 ILayoutElement Element;
260
261 foreach (GridPadding P in this.elements)
262 {
263 Element = P.Element;
264
265 if (!(Element is null))
266 {
267 Element.MeasurePositions(State);
268 P.OffsetX -= Element.Left ?? 0;
269 P.OffsetY -= Element.Top ?? 0;
270 }
271 }
272 }
273
278 public void Distribute(bool SetPosition)
279 {
280 foreach (GridPadding P in this.elements)
281 {
282 if (!(P.Element is null))
283 {
284 int X = P.X;
285 int Y = P.Y;
286 float Left = this.GetRight(X - 1);
287 float Top = this.GetBottom(Y - 1);
288 float Right = this.GetRight(X + P.ColSpan - 1);
289 float Bottom = this.GetBottom(Y + P.RowSpan - 1);
290 float MaxWidth = Right - Left;
291 float MaxHeight = Bottom - Top;
292
293 P.Distribute(MaxWidth, MaxHeight, this.session, SetPosition);
294 }
295 }
296 }
297
302 public Padding[] Align()
303 {
304 List<Padding> Result = new List<Padding>();
305
306 foreach (GridPadding P in this.elements)
307 {
308 if (!(P.Element is null))
309 {
310 int X = P.X;
311 int Y = P.Y;
312 float Left = this.GetRight(X - 1);
313 float Top = this.GetBottom(Y - 1);
314
315 P.OffsetX += Left;
316 P.OffsetY += Top;
317 Result.Add(P);
318 }
319 }
320
321 return Result.ToArray();
322 }
323 }
324}
Defines a cell in a grid.
Definition: Cell.cs:61
async Task< CellSpan > CalcSpan(Variables Session)
Calculates the span of the cell.
Definition: Cell.cs:265
async Task Add(ILayoutElement Element)
Adds a cell to the layout.
Definition: GridCells.cs:98
Padding[] Align()
Aligns cells and returns an array of padded cells.
Definition: GridCells.cs:302
GridCells(Variables Session, int NrColumns)
Lays out cells in a grid.
Definition: GridCells.cs:28
void MeasurePositions(DrawingState State)
Measures layout entities and defines unassigned properties, related to positions.
Definition: GridCells.cs:257
float TotWidth
Total width of layout
Definition: GridCells.cs:246
void Flush()
Flushes any waiting elements int he layout pipeline.
Definition: GridCells.cs:172
void Distribute(bool SetPosition)
Distributes cells in layout.
Definition: GridCells.cs:278
float TotHeight
Total height of layout
Definition: GridCells.cs:251
Provides padding for a layout element in a grid.
Definition: GridPadding.cs:7
Provides padding for a layout element in a group contruct.
Definition: Padding.cs:11
Task Distribute(float? MaxWidth, float? MaxHeight, Variables Session, bool SetPosition)
Aligns a measured cell
Definition: Padding.cs:73
ILayoutElement Element
Embedded element
Definition: Padding.cs:36
Collection of variables.
Definition: Variables.cs:25
Basic interface for cell layout objects.
Definition: ICellLayout.cs:9
Base interface for all layout elements.
void MeasurePositions(DrawingState State)
Measures layout entities and defines unassigned properties, related to positions.
Contains information about a cells span in a grid.
Definition: CellSpan.cs:7