Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
Path.cs
1using System.Collections.Generic;
2using System.Threading.Tasks;
3using System.Xml;
4using SkiaSharp;
10
12{
17 {
18 private ISegment[] segments;
19 private StringAttribute head;
20 private StringAttribute tail;
21 private StringAttribute shapeFill;
22
28 public Path(Layout2DDocument Document, ILayoutElement Parent)
29 : base(Document, Parent)
30 {
31 }
32
36 public override string LocalName => "Path";
37
42 {
43 get => this.head;
44 set => this.head = value;
45 }
46
51 {
52 get => this.tail;
53 set => this.tail = value;
54 }
55
60 {
61 get => this.shapeFill;
62 set => this.shapeFill = value;
63 }
64
69 public override async Task FromXml(XmlElement Input)
70 {
71 await base.FromXml(Input);
72
73 this.head = new StringAttribute(Input, "head", this.Document);
74 this.tail = new StringAttribute(Input, "tail", this.Document);
75 this.shapeFill = new StringAttribute(Input, "shapeFill", this.Document);
76
77 this.segments = this.GetSegments();
78 }
79
80 private ISegment[] GetSegments()
81 {
82 List<ISegment> Segments = null;
83
84 if (this.HasChildren)
85 {
86 foreach (ILayoutElement Child in this.Children)
87 {
88 if (Child is ISegment Segment)
89 {
90 if (Segments is null)
91 Segments = new List<ISegment>();
92
93 Segments.Add(Segment);
94 }
95 else
96 throw new LayoutSyntaxException("Not a segment type: " + Child.Namespace + "#" + Child.LocalName);
97 }
98 }
99
100 return Segments?.ToArray();
101 }
102
107 public override void ExportAttributes(XmlWriter Output)
108 {
109 base.ExportAttributes(Output);
110
111 this.head?.Export(Output);
112 this.tail?.Export(Output);
113 this.shapeFill?.Export(Output);
114 }
115
122 public override ILayoutElement Create(Layout2DDocument Document, ILayoutElement Parent)
123 {
124 return new Path(Document, Parent);
125 }
126
131 public override void CopyContents(ILayoutElement Destination)
132 {
133 base.CopyContents(Destination);
134
135 if (Destination is Path Dest)
136 {
137 Dest.head = this.head?.CopyIfNotPreset(Destination.Document);
138 Dest.tail = this.tail?.CopyIfNotPreset(Destination.Document);
139 Dest.shapeFill = this.shapeFill?.CopyIfNotPreset(Destination.Document);
140
141 Dest.segments = Dest.GetSegments();
142 }
143 }
144
150 public override async Task DoMeasureDimensions(DrawingState State)
151 {
152 await base.DoMeasureDimensions(State);
153
154 PathState PathState = new PathState(this, null, false, false);
155
156 EvaluationResult<string> RefId = await this.head.TryEvaluate(State.Session);
157 if (RefId.Ok &&
158 this.Document.TryGetElement(RefId.Result, out ILayoutElement Element) &&
159 Element is Shape Shape)
160 {
161 this.headElement = Shape;
162 }
163
164 RefId = await this.tail.TryEvaluate(State.Session);
165 if (RefId.Ok &&
166 this.Document.TryGetElement(RefId.Result, out Element) &&
167 Element is Shape Shape2)
168 {
169 this.tailElement = Shape2;
170 }
171
172 RefId = await this.shapeFill.TryEvaluate(State.Session);
173 if (RefId.Ok &&
174 this.Document.TryGetElement(RefId.Result, out Element) &&
175 Element is Background Background)
176 {
177 this.shapeFiller = Background;
178 }
179
180 if (!(this.segments is null))
181 {
182 foreach (ISegment Segment in this.segments)
183 await Segment.Measure(State, PathState);
184 }
185 }
186
187 private Shape headElement;
188 private Shape tailElement;
189 private Background shapeFiller;
190
195 public override async Task Draw(DrawingState State)
196 {
197 SKPaint Fill = await this.TryGetFill(State);
198 SKPaint Pen = await this.TryGetPen(State);
199
200 bool CalcStart = !(this.tailElement is null);
201 bool CalcEnd = !(this.headElement is null);
202
203 if (!(this.segments is null))
204 {
205 using (SKPath Path = new SKPath())
206 {
207 PathState PathState = new PathState(this, Path, CalcStart, CalcEnd);
208
209 await this.Draw(State, PathState, Path);
210
212
213 if (!(Fill is null))
214 State.Canvas.DrawPath(Path, Fill);
215
216 if (!(Pen is null))
217 State.Canvas.DrawPath(Path, Pen);
218 }
219 }
220
221 if (CalcStart || CalcEnd)
222 {
223 if (!(this.shapeFiller is null))
224 Fill = this.shapeFiller.Paint;
225
226 this.tailElement?.DrawTail(State, this, Pen, Fill);
227 this.headElement?.DrawHead(State, this, Pen, Fill);
228 }
229
230 await base.Draw(State);
231 }
232
238 public async Task Measure(DrawingState State, PathState PathState)
239 {
240 if (!(this.segments is null))
241 {
242 foreach (ISegment Segment in this.segments)
243 await Segment .Measure(State, PathState);
244 }
245
246 this.hasStart = false;
247 this.hasEnd = false;
248 }
249
256 public async Task Draw(DrawingState State, PathState PathState, SKPath Path)
257 {
258 if (!(this.segments is null))
259 {
260 bool CalcStart = PathState.CalcStart;
261
262 foreach (ISegment Segment in this.segments)
263 {
264 if (Segment.IsVisible)
265 {
266 await Segment .Draw(State, PathState, Path);
267
268 if (CalcStart &&
269 Segment is IDirectedElement DirectedElement &&
270 DirectedElement.TryGetStart(out this.startX, out this.startY, out this.startDirection))
271 {
272 CalcStart = false;
273 this.hasStart = true;
274 }
275 }
276 }
277
278 if (PathState.CalcEnd)
279 {
280 int i = this.segments.Length;
281
282 while (i-- > 0)
283 {
284 if (this.segments[i] is IDirectedElement DirectedElement &&
285 DirectedElement.TryGetEnd(out this.endX, out this.endY, out this.endDirection))
286 {
287 this.hasEnd = true;
288 break;
289 }
290 }
291 }
292 }
293 }
294
295 private float startX;
296 private float startY;
297 private float startDirection;
298 private bool hasStart;
299 private float endX;
300 private float endY;
301 private float endDirection;
302 private bool hasEnd;
303
311 public bool TryGetStart(out float X, out float Y, out float Direction)
312 {
313 if (this.hasStart)
314 {
315 X = this.startX;
316 Y = this.startY;
317 Direction = this.startDirection;
318
319 return true;
320 }
321 else
322 {
323 X = Y = Direction = 0;
324 return false;
325 }
326 }
327
335 public bool TryGetEnd(out float X, out float Y, out float Direction)
336 {
337 if (this.hasEnd)
338 {
339 X = this.endX;
340 Y = this.endY;
341 Direction = this.endDirection;
342
343 return true;
344 }
345 else
346 {
347 X = Y = Direction = 0;
348 return false;
349 }
350 }
351
356 public override void ExportStateAttributes(XmlWriter Output)
357 {
358 base.ExportStateAttributes(Output);
359
360 this.head?.ExportState(Output);
361 this.tail?.ExportState(Output);
362 this.shapeFill?.ExportState(Output);
363 }
364
365 }
366}
Contains a 2D layout document.
void Export(XmlWriter Output)
Exports the attribute.
Definition: Attribute.cs:187
void ExportState(XmlWriter Output)
Exports the state of the attribute.
Definition: Attribute.cs:199
static async Task< EvaluationResult< T > > TryEvaluate(Attribute< T > Attribute, Variables Session)
Tries to evaluate the attribute value.
Definition: Attribute.cs:256
StringAttribute CopyIfNotPreset(Layout2DDocument ForDocument)
Copies the attribute object if undefined, or defined by an expression. Returns a reference to itself,...
Abstract base class for backgrounds.
Definition: Background.cs:10
SKCanvas Canvas
Current drawing canvas.
Variables Session
Current session.
Definition: DrawingState.cs:91
Abstract base class for figures
Definition: Figure.cs:14
async Task< SKPaint > TryGetPen(DrawingState State)
Tries to get the pen associated with the element, if one is defined.
Definition: Figure.cs:111
async Task< SKPaint > TryGetFill(DrawingState State)
Tries to get the filling of the figure, if one is defined.
Definition: Figure.cs:130
override async Task DoMeasureDimensions(DrawingState State)
Measures layout entities and defines unassigned properties, related to dimensions.
Definition: Path.cs:150
async Task Draw(DrawingState State, PathState PathState, SKPath Path)
Draws the segments of the path.
Definition: Path.cs:256
override void CopyContents(ILayoutElement Destination)
Copies contents (attributes and children) to the destination element.
Definition: Path.cs:131
override async Task Draw(DrawingState State)
Draws layout entities.
Definition: Path.cs:195
override string LocalName
Local name of type of element.
Definition: Path.cs:36
override void ExportAttributes(XmlWriter Output)
Exports attributes to XML.
Definition: Path.cs:107
StringAttribute HeadAttribute
Head
Definition: Path.cs:42
override async Task FromXml(XmlElement Input)
Populates the element (including children) with information from its XML definition.
Definition: Path.cs:69
bool TryGetEnd(out float X, out float Y, out float Direction)
Tries to get end position and terminating direction.
Definition: Path.cs:335
async Task Measure(DrawingState State, PathState PathState)
Measures layout entities and defines unassigned properties.
Definition: Path.cs:238
override void ExportStateAttributes(XmlWriter Output)
Exports the local attributes of the current element.
Definition: Path.cs:356
bool TryGetStart(out float X, out float Y, out float Direction)
Tries to get start position and initial direction.
Definition: Path.cs:311
StringAttribute TailAttribute
Tail
Definition: Path.cs:51
override ILayoutElement Create(Layout2DDocument Document, ILayoutElement Parent)
Creates a new instance of the layout element.
Definition: Path.cs:122
StringAttribute ShapeFillAttribute
Shape Fill
Definition: Path.cs:60
Path(Layout2DDocument Document, ILayoutElement Parent)
A path
Definition: Path.cs:28
bool CalcStart
If start position and angle are to be calculated.
Definition: PathState.cs:61
bool CalcEnd
If end position and angle are to be calculated.
Definition: PathState.cs:66
void FlushSpline()
Closes an ongoing spline curve (if one open).
Definition: PathState.cs:288
Layout2DDocument Document
Layout document.
Defines a shape for use elsewhere in the layout.
Definition: Shape.cs:11
Task DrawTail(DrawingState State, IDirectedElement DirectedElement, SKPaint DefaultPen, SKPaint DefaultFill)
Draws shape as a tail
Definition: Shape.cs:98
Task DrawHead(DrawingState State, IDirectedElement DirectedElement, SKPaint DefaultPen, SKPaint DefaultFill)
Draws shape as a head
Definition: Shape.cs:114
Task Measure(DrawingState State, PathState PathState)
Measures layout entities and defines unassigned properties, related to dimensions.
Task Draw(DrawingState State, PathState PathState, SKPath Path)
Draws layout entities.
Interface for directed elements.
bool TryGetStart(out float X, out float Y, out float Direction)
Tries to get start position and initial direction.
bool TryGetEnd(out float X, out float Y, out float Direction)
Tries to get end position and terminating direction.
Base interface for all layout elements.
bool IsVisible
If the element is visible or not.
string LocalName
Local name of type of element.
string Namespace
Namespace of type of element.
Layout2DDocument Document
Layout document.