Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
UIElement.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 
4 using System;
5 using System.Collections.Generic;
6 using System.Diagnostics;
7 using System.Linq;
8 using System.Reflection;
9 
10 using SiliconStudio.Core;
11 using SiliconStudio.Core.Mathematics;
12 using SiliconStudio.Paradox.Games;
13 using SiliconStudio.Paradox.UI.Events;
14 
15 namespace SiliconStudio.Paradox.UI
16 {
17  /// <summary>
18  /// Provides a base class for all the User Interface elements in Paradox applications.
19  /// </summary>
20  [DebuggerDisplay("UIElement: {Name}")]
21  public abstract class UIElement : IUIElementUpdate
22  {
23  #region Dependency Properties
24 
25  /// <summary>
26  /// The key to the height dependency property.
27  /// </summary>
28  public readonly static PropertyKey<float> DefaultWidthPropertyKey = new PropertyKey<float>("DefaultWidthKey", typeof(UIElement), DefaultValueMetadata.Static(0f), ValidateValueMetadata.New<float>(DefaultSizeValidator), ObjectInvalidationMetadata.New<float>(DefaultSizeInvalidation));
29  /// <summary>
30  /// The key to the height dependency property.
31  /// </summary>
32  public readonly static PropertyKey<float> DefaultHeightPropertyKey = new PropertyKey<float>("DefaultHeightKey", typeof(UIElement), DefaultValueMetadata.Static(0f), ValidateValueMetadata.New<float>(DefaultSizeValidator), ObjectInvalidationMetadata.New<float>(DefaultSizeInvalidation));
33  /// <summary>
34  /// The key to the height dependency property.
35  /// </summary>
36  public readonly static PropertyKey<float> DefaultDepthPropertyKey = new PropertyKey<float>("DefaultDepthKey", typeof(UIElement), DefaultValueMetadata.Static(0f), ValidateValueMetadata.New<float>(DefaultSizeValidator), ObjectInvalidationMetadata.New<float>(DefaultSizeInvalidation));
37  /// <summary>
38  /// The key to the name dependency property.
39  /// </summary>
40  public readonly static PropertyKey<string> NamePropertyKey = new PropertyKey<string>("NameKey", typeof(UIElement), DefaultValueMetadata.Static<string>(null), ObjectInvalidationMetadata.New<string>(NameInvalidationCallback));
41  /// <summary>
42  /// The key to the parent dependency property.
43  /// </summary>
44  private readonly static PropertyKey<UIElement> parentPropertyKey = new PropertyKey<UIElement>("ParentKey", typeof(UIElement), DefaultValueMetadata.Static<UIElement>(null));
45  /// <summary>
46  /// The key to the VisualParent dependency property.
47  /// </summary>
48  private readonly static PropertyKey<UIElement> visualParentPropertyKey = new PropertyKey<UIElement>("ParentKey", typeof(UIElement), DefaultValueMetadata.Static<UIElement>(null));
49  /// <summary>
50  /// The key to the Background color dependency property.
51  /// </summary>
52  private readonly static PropertyKey<Color> backgroundColorPropertyKey = new PropertyKey<Color>("backgroundColorKey", typeof(Color), DefaultValueMetadata.Static(new Color(0,0,0,0)));
53 
54  private static void DefaultSizeInvalidation(object propertyOwner, PropertyKey<float> propertyKey, float propertyOldValue)
55  {
56  var element = (UIElement)propertyOwner;
57  element.InvalidateMeasure();
58  }
59 
60  #endregion
61 
62  #region Routed Events
63 
64  private static readonly RoutedEvent<TouchEventArgs> previewTouchDownEvent = EventManager.RegisterRoutedEvent<TouchEventArgs>(
65  "PreviewTouchDown",
66  RoutingStrategy.Tunnel,
67  typeof(UIElement));
68 
69  private static readonly RoutedEvent<TouchEventArgs> previewTouchMoveEvent = EventManager.RegisterRoutedEvent<TouchEventArgs>(
70  "PreviewTouchMove",
71  RoutingStrategy.Tunnel,
72  typeof(UIElement));
73 
74  private static readonly RoutedEvent<TouchEventArgs> previewTouchUpEvent = EventManager.RegisterRoutedEvent<TouchEventArgs>(
75  "PreviewTouchUp",
76  RoutingStrategy.Tunnel,
77  typeof(UIElement));
78 
79  private static readonly RoutedEvent<TouchEventArgs> touchDownEvent = EventManager.RegisterRoutedEvent<TouchEventArgs>(
80  "TouchDown",
81  RoutingStrategy.Bubble,
82  typeof(UIElement));
83 
84  private static readonly RoutedEvent<TouchEventArgs> touchEnterEvent = EventManager.RegisterRoutedEvent<TouchEventArgs>(
85  "TouchEnter",
86  RoutingStrategy.Direct,
87  typeof(UIElement));
88 
89  private static readonly RoutedEvent<TouchEventArgs> touchLeaveEvent = EventManager.RegisterRoutedEvent<TouchEventArgs>(
90  "TouchLeave",
91  RoutingStrategy.Direct,
92  typeof(UIElement));
93 
94  private static readonly RoutedEvent<TouchEventArgs> touchMoveEvent = EventManager.RegisterRoutedEvent<TouchEventArgs>(
95  "TouchMove",
96  RoutingStrategy.Bubble,
97  typeof(UIElement));
98 
99  private static readonly RoutedEvent<TouchEventArgs> touchUpEvent = EventManager.RegisterRoutedEvent<TouchEventArgs>(
100  "TouchUp",
101  RoutingStrategy.Bubble,
102  typeof(UIElement));
103 
104  private static readonly RoutedEvent<KeyEventArgs> keyPressedEvent = EventManager.RegisterRoutedEvent<KeyEventArgs>(
105  "KeyPressed",
106  RoutingStrategy.Bubble,
107  typeof(UIElement));
108 
109  private static readonly RoutedEvent<KeyEventArgs> keyDownEvent = EventManager.RegisterRoutedEvent<KeyEventArgs>(
110  "KeyDown",
111  RoutingStrategy.Bubble,
112  typeof(UIElement));
113 
114  private static readonly RoutedEvent<KeyEventArgs> keyReleasedEvent = EventManager.RegisterRoutedEvent<KeyEventArgs>(
115  "KeyReleased",
116  RoutingStrategy.Bubble,
117  typeof(UIElement));
118 
119  #endregion
120 
121  private static uint uiElementCount;
122  private Visibility visibility = Visibility.Visible;
123  private float opacity = 1.0f;
124  private bool isEnabled = true;
125  private bool isHierarchyEnabled = true;
126  private float width = float.NaN;
127  private float height = float.NaN;
128  private float depth = float.NaN;
129  private HorizontalAlignment horizontalAlignment = HorizontalAlignment.Stretch;
130  private VerticalAlignment verticalAlignment = VerticalAlignment.Stretch;
131  private DepthAlignment depthAlignment = DepthAlignment.Back;
132  private float maximumWidth = float.PositiveInfinity;
133  private float maximumHeight = float.PositiveInfinity;
134  private float maximumDepth = float.PositiveInfinity;
135  private float minimumWidth;
136  private float minimumHeight;
137  private float minimumDepth;
138  private Matrix localMatrix = Matrix.Identity;
139  private MouseOverState mouseOverState;
140 
141  // Cached element renderer
142  internal Renderers.ElementRenderer ElementRenderer;
143 
144  internal bool HierarchyDisablePicking;
145  internal Vector3 RenderSizeInternal;
146  internal Matrix WorldMatrixInternal;
147  internal protected Thickness MarginInternal = Thickness.UniformCuboid(0f);
148 
149  protected bool ArrangeChanged;
150  protected bool LocalMatrixChanged;
151 
152  private Vector3 previousProvidedMeasureSize = new Vector3(-1,-1,-1);
153  private Vector3 previousProvidedArrangeSize = new Vector3(-1,-1,-1);
154  private bool previousIsParentCollapsed;
155 
156  private static Queue<List<RoutedEventHandlerInfo>> routedEventHandlerInfoListPool = new Queue<List<RoutedEventHandlerInfo>>();
157 
158  static UIElement()
159  {
160  // register the class handlers
161  EventManager.RegisterClassHandler(typeof(UIElement), previewTouchDownEvent, PreviewTouchDownClassHandler);
162  EventManager.RegisterClassHandler(typeof(UIElement), previewTouchMoveEvent, PreviewTouchMoveClassHandler);
163  EventManager.RegisterClassHandler(typeof(UIElement), previewTouchUpEvent, PreviewTouchUpClassHandler);
164  EventManager.RegisterClassHandler(typeof(UIElement), touchDownEvent, TouchDownClassHandler);
165  EventManager.RegisterClassHandler(typeof(UIElement), touchEnterEvent, TouchEnterClassHandler);
166  EventManager.RegisterClassHandler(typeof(UIElement), touchLeaveEvent, TouchLeaveClassHandler);
167  EventManager.RegisterClassHandler(typeof(UIElement), touchMoveEvent, TouchMoveClassHandler);
168  EventManager.RegisterClassHandler(typeof(UIElement), touchUpEvent, TouchUpClassHandler);
169  EventManager.RegisterClassHandler(typeof(UIElement), keyPressedEvent, KeyPressedClassHandler);
170  EventManager.RegisterClassHandler(typeof(UIElement), keyDownEvent, KeyDownClassHandler);
171  EventManager.RegisterClassHandler(typeof(UIElement), keyReleasedEvent, KeyReleasedClassHandler);
172  }
173 
174  /// <summary>
175  /// Create an instance of a UIElement
176  /// </summary>
177  protected UIElement()
178  {
179  ID = ++uiElementCount;
180  DependencyProperties = new PropertyContainer(this);
181  VisualChildrenCollection = new UIElementCollection();
182  DrawLayerNumber = 1; // one layer for BackgroundColor/Clipping
183  }
184 
185  /// <summary>
186  /// The <see cref="UIElement"/> that currently has the focus.
187  /// </summary>
188  internal static UIElement FocusedElement { get; set; }
189 
190  /// <summary>
191  /// A unique ID defining the UI element.
192  /// </summary>
193  public uint ID { get; private set; }
194 
195  /// <summary>
196  /// List of the dependency properties attached to the object.
197  /// </summary>
199 
200  /// <summary>
201  /// Gets the size that this element computed during the measure pass of the layout process.
202  /// </summary>
203  /// <remarks>This value does not contain possible <see cref="Margin"/></remarks>
204  public Vector3 DesiredSize { get; private set; }
205 
206  /// <summary>
207  /// Gets the size that this element computed during the measure pass of the layout process.
208  /// </summary>
209  /// <remarks>This value contains possible <see cref="Margin"/></remarks>
210  public Vector3 DesiredSizeWithMargins { get; private set; }
211 
212  /// <summary>
213  /// Gets a value indicating whether the computed size and position of child elements in this element's layout are valid.
214  /// </summary>
215  public bool IsArrangeValid { get; private set; }
216 
217  /// <summary>
218  /// Gets a value indicating whether the current size returned by layout measure is valid.
219  /// </summary>
220  public bool IsMeasureValid { get; private set; }
221 
222  /// <summary>
223  /// Gets a value indicating whether the <see cref="UIElement"/> is currently touched by the user.
224  /// </summary>
225  public bool IsTouched { get; internal set; }
226 
227  /// <summary>
228  /// The world matrix of the UIElement.
229  /// The origin of the element is the center of the object's bounding box defined by <see cref="RenderSize"/>.
230  /// </summary>
231  public Matrix WorldMatrix
232  {
233  get { return WorldMatrixInternal; }
234  private set { WorldMatrixInternal = value; }
235  }
236 
237  /// <summary>
238  /// The final depth bias value of the element resulting from the parent/children z order update.
239  /// </summary>
240  internal int DepthBias { get; private set; }
241 
242  /// <summary>
243  /// The maximum depth bias value among the children of the element resulting from the parent/children z order update.
244  /// </summary>
245  internal int MaxChildrenDepthBias { get; private set; }
246 
247  /// <summary>
248  /// The number of layers used to draw this element.
249  /// This value has to be modified by the user when he redefines the default element renderer,
250  /// so that <see cref="DepthBias"/> values of the relatives keeps enough spaces to draw the different layers.
251  /// </summary>
252  public int DrawLayerNumber { get; set; }
253 
254  /// <summary>
255  /// The instance of <see cref="UISystem"/> managing this <see cref="UIElement"/>.
256  /// </summary>
257  internal protected UISystem UISystem { get; set; }
258 
259  internal bool ForceNextMeasure = true;
260  internal bool ForceNextArrange = true;
261 
262  /// <summary>
263  /// The ratio between the element real size on the screen and the element virtual size.
264  /// </summary>
265  internal protected Vector2 RealSizeVirtualResolutionRatio
266  {
267  get { return UISystem.BackBufferVirtualResolutionRatio; } // TODO should we take in account the world matrix here? -> may generate to many font size in case of zoom animations
268  }
269 
270  /// <summary>
271  /// The visual children of this element.
272  /// </summary>
273  /// <remarks>If the class is inherited it is the responsibility of the descendant class to correctly update this collection</remarks>
274  internal protected UIElementCollection VisualChildrenCollection { get; private set; }
275 
276  /// <summary>
277  /// Invalidates the arrange state (layout) for the element.
278  /// </summary>
279  protected internal void InvalidateArrange()
280  {
281  ForceArrange(); // force arrange on top hierarchy
282 
283  PropagateArrangeInvalidationToChildren(); // propagate weak invalidation on children
284  }
285 
286  private void PropagateArrangeInvalidationToChildren()
287  {
288  foreach (var child in VisualChildrenCollection)
289  {
290  if (child.IsArrangeValid)
291  {
292  child.IsArrangeValid = false;
293  child.PropagateArrangeInvalidationToChildren();
294  }
295  }
296  }
297 
298  private void ForceArrange()
299  {
300  if(ForceNextArrange) // no need to propagate arrange force if it's already done
301  return;
302 
303  IsArrangeValid = false;
304  ForceNextArrange = true;
305 
306  if(VisualParent != null)
307  VisualParent.ForceArrange();
308  }
309 
310  /// <summary>
311  /// Invalidates the measurement state (layout) for the element.
312  /// </summary>
313  protected internal void InvalidateMeasure()
314  {
315  ForceMeasure(); // force measure on top hierarchy
316 
317  PropagateMeasureInvalidationToChildren(); // propagate weak invalidation on children
318  }
319 
320  private void PropagateMeasureInvalidationToChildren()
321  {
322  foreach (var child in VisualChildrenCollection)
323  {
324  if (child.IsMeasureValid)
325  {
326  child.IsMeasureValid = false;
327  child.IsArrangeValid = false;
328  child.PropagateMeasureInvalidationToChildren();
329  }
330  }
331  }
332 
333  private void ForceMeasure()
334  {
335  if (ForceNextMeasure && ForceNextArrange) // no need to propagate arrange force if it's already done
336  return;
337 
338  ForceNextMeasure = true;
339  ForceNextArrange = true;
340 
341  IsMeasureValid = false;
342  IsArrangeValid = false;
343 
344  if (VisualParent != null)
345  VisualParent.ForceMeasure();
346  }
347 
348  private static void NameInvalidationCallback(object propertyOwner, PropertyKey<string> propertyKey, string propertyOldValue)
349  {
350  var element = (UIElement)propertyOwner;
351  element.OnNameChanged();
352  }
353 
354  /// <summary>
355  /// This method is call when the name of the UIElement changes.
356  /// This method can be overridden in inherited classes to perform class specific actions on <see cref="Name"/> changes.
357  /// </summary>
358  protected virtual void OnNameChanged()
359  {
360  }
361 
362  /// <summary>
363  /// Indicate if the UIElement can be hit by the user.
364  /// If this property is true, the UI system performs hit test on the UIElement.
365  /// </summary>
366  public bool CanBeHitByUser { get; set; }
367 
368  /// <summary>
369  /// This property can be set to <value>true</value> to disable all touch events on the element's children.
370  /// </summary>
371  public bool PreventChildrenFromBeingHit { get; set; }
372 
373  /// <summary>
374  /// Gets or sets a value indicating whether this element is enabled in the user interface (UI).
375  /// </summary>
376  public virtual bool IsEnabled
377  {
378  get { return isEnabled; }
379  set
380  {
381  isEnabled = value;
382 
383  MouseOverState = MouseOverState.MouseOverNone;
384  }
385  }
386 
387  /// <summary>
388  /// Gets the value indicating whether this element and all its upper hierarchy are enabled or not.
389  /// </summary>
390  public bool IsHierarchyEnabled
391  {
392  get { return isHierarchyEnabled; }
393  }
394 
395  /// <summary>
396  /// Gets a value indicating whether this element is visible in the user interface (UI).
397  /// </summary>
398  public bool IsVisible
399  {
400  get { return Visibility == Visibility.Visible; }
401  }
402 
403  /// <summary>
404  /// Gets a value indicating whether this element takes some place in the user interface.
405  /// </summary>
406  public bool IsCollapsed
407  {
408  get { return Visibility == Visibility.Collapsed; }
409  }
410 
411  /// <summary>
412  /// Gets or sets the opacity factor applied to the entire UIElement when it is rendered in the user interface (UI). This is a dependency property.
413  /// </summary>
414  /// <remarks>Value is clamped between [0,1].</remarks>
415  public float Opacity
416  {
417  get { return opacity; }
418  set { opacity = Math.Max(0, Math.Min(1, value)); }
419  }
420 
421  /// <summary>
422  /// Gets or sets the user interface (UI) visibility of this element. This is a dependency property.
423  /// </summary>
424  public Visibility Visibility
425  {
426  get { return visibility; }
427  set
428  {
429  if(value == visibility)
430  return;
431 
432  visibility = value;
433  InvalidateMeasure();
434  }
435  }
436 
437  /// <summary>
438  /// Gets the current state of the mouse over the UI element.
439  /// </summary>
440  /// <remarks>Only elements that can be clicked by user can have the <cref>MouseOverState.MouseOverElement</cref> value.
441  /// That is element that have <see cref="CanBeHitByUser"/> set to <value>true</value></remarks>
443  {
444  get { return mouseOverState; }
445  internal set
446  {
447  var oldValue = mouseOverState;
448  if(oldValue == value)
449  return;
450 
451  mouseOverState = value;
452 
453  var handler = MouseOverStateChanged;
454  if (handler != null)
455  handler(this, new PropertyChangedArgs<MouseOverState> { NewValue = value, OldValue = oldValue });
456  }
457  }
458 
459  /// <summary>
460  /// Gets or sets the default height of this element. This is a dependency property.
461  /// </summary>
462  /// <exception cref="ArgumentOutOfRangeException">The value has to be a finite positive real number.</exception>
463  public float DefaultHeight
464  {
465  get { return DependencyProperties.Get(DefaultHeightPropertyKey); }
466  set { DependencyProperties.Set(DefaultHeightPropertyKey, value); }
467  }
468 
469  /// <summary>
470  /// Gets or sets the default width of this element. This is a dependency property.
471  /// </summary>
472  /// <exception cref="ArgumentOutOfRangeException">The value has to be a finite positive real number.</exception>
473  public float DefaultWidth
474  {
475  get { return DependencyProperties.Get(DefaultWidthPropertyKey); }
476  set { DependencyProperties.Set(DefaultWidthPropertyKey, value); }
477  }
478 
479  /// <summary>
480  /// Gets or sets the default width of this element. This is a dependency property.
481  /// </summary>
482  /// <exception cref="ArgumentOutOfRangeException">The value has to be a finite positive real number.</exception>
483  public float DefaultDepth
484  {
485  get { return DependencyProperties.Get(DefaultDepthPropertyKey); }
486  set { DependencyProperties.Set(DefaultDepthPropertyKey, value); }
487  }
488 
489  private static void DefaultSizeValidator(ref float size)
490  {
491  if (size < 0 || float.IsInfinity(size) || float.IsNaN(size))
492  throw new ArgumentOutOfRangeException("size");
493  }
494 
495  /// <summary>
496  /// Gets or sets the user suggested height of this element. This is a dependency property.
497  /// </summary>
498  /// <exception cref="ArgumentOutOfRangeException">The value has to be positive and finite or undefined.</exception>
499  public float Height
500  {
501  get { return height; }
502  set
503  {
504  if (value < 0 || float.IsInfinity(value))
505  throw new ArgumentOutOfRangeException("value");
506 
507  height = value;
508  InvalidateMeasure();
509  }
510  }
511 
512  /// <summary>
513  /// Gets or sets the user suggested width of this element. This is a dependency property.
514  /// </summary>
515  /// <exception cref="ArgumentOutOfRangeException">The value has to be positive and finite or undefined.</exception>
516  public float Width
517  {
518  get { return width; }
519  set
520  {
521  if (value < 0 || float.IsInfinity(value))
522  throw new ArgumentOutOfRangeException("value");
523 
524  width = value;
525  InvalidateMeasure();
526  }
527  }
528 
529  /// <summary>
530  /// Gets or sets the user suggested width of this element. This is a dependency property.
531  /// </summary>
532  /// <exception cref="ArgumentOutOfRangeException">The value has to be positive and finite or undefined.</exception>
533  public float Depth
534  {
535  get { return depth; }
536  set
537  {
538  if (value < 0 || float.IsInfinity(value))
539  throw new ArgumentOutOfRangeException("value");
540 
541  depth = value;
542  InvalidateMeasure();
543  }
544  }
545 
546  /// <summary>
547  /// Gets or sets the size of the element. Same as setting separately <see cref="Width"/>, <see cref="Height"/>, and <see cref="Depth"/>
548  /// </summary>
549  public Vector3 Size
550  {
551  get { return new Vector3(Width, Height, Depth); }
552  set
553  {
554  Width = value.X;
555  Height = value.Y;
556  Depth = value.Z;
557  InvalidateMeasure();
558  }
559  }
560 
561  /// <summary>
562  /// Set one component of the size of the element.
563  /// </summary>
564  /// <param name="dimensionIndex">Index indicating which component to set</param>
565  /// <param name="value">The value to give to the size</param>
566  internal void SetSize(int dimensionIndex, float value)
567  {
568  if (dimensionIndex == 0)
569  Width = value;
570  else if (dimensionIndex == 1)
571  Height = value;
572  else
573  Depth = value;
574 
575  InvalidateMeasure();
576  }
577 
578  /// <summary>
579  /// Gets or sets the minimum width of this element. This is a dependency property.
580  /// </summary>
581  /// <exception cref="ArgumentOutOfRangeException">The value has to be positive and finite.</exception>
582  public float MinimumWidth
583  {
584  get { return minimumWidth; }
585  set
586  {
587  if (value < 0 || float.IsNaN(value) || float.IsInfinity(value))
588  throw new ArgumentOutOfRangeException("value");
589  minimumWidth = value;
590  InvalidateMeasure();
591  }
592  }
593 
594  /// <summary>
595  /// Gets or sets the minimum height of this element. This is a dependency property.
596  /// </summary>
597  /// <exception cref="ArgumentOutOfRangeException">The value has to be positive and finite.</exception>
598  public float MinimumHeight
599  {
600  get { return minimumHeight; }
601  set
602  {
603  if (value < 0 || float.IsNaN(value) || float.IsInfinity(value))
604  throw new ArgumentOutOfRangeException("value");
605  minimumHeight = value;
606  InvalidateMeasure();
607  }
608  }
609 
610  /// <summary>
611  /// Gets or sets the minimum height of this element. This is a dependency property.
612  /// </summary>
613  /// <exception cref="ArgumentOutOfRangeException">The value has to be positive and finite.</exception>
614  public float MinimumDepth
615  {
616  get { return minimumDepth; }
617  set
618  {
619  if (value < 0 || float.IsNaN(value) || float.IsInfinity(value))
620  throw new ArgumentOutOfRangeException("value");
621  minimumDepth = value;
622  InvalidateMeasure();
623  }
624  }
625 
626  /// <summary>
627  /// Gets or sets a value indicating whether to clip the content of this element (or content coming from the child elements of this element)
628  /// to fit into the size of the containing element. This is a dependency property.
629  /// </summary>
630  /// <exception cref="ArgumentOutOfRangeException">The value has to be positive and finite.</exception>
631  public bool ClipToBounds { get; set; }
632 
633  /// <summary>
634  /// Gets or sets the maximum width of this element. This is a dependency property.
635  /// </summary>
636  /// <exception cref="ArgumentOutOfRangeException">The value has to be positive.</exception>
637  public float MaximumWidth
638  {
639  get { return maximumWidth; }
640  set
641  {
642  if (value < 0 || float.IsNaN(value))
643  throw new ArgumentOutOfRangeException("value");
644  maximumWidth = value;
645  InvalidateMeasure();
646  }
647  }
648 
649  /// <summary>
650  /// Gets or sets the maximum height of this element. This is a dependency property.
651  /// </summary>
652  /// <exception cref="ArgumentOutOfRangeException">The value has to be positive.</exception>
653  public float MaximumHeight
654  {
655  get { return maximumHeight; }
656  set
657  {
658  if (value < 0 || float.IsNaN(value))
659  throw new ArgumentOutOfRangeException("value");
660  maximumHeight = value;
661  InvalidateMeasure();
662  }
663  }
664 
665  /// <summary>
666  /// Gets or sets the maximum height of this element. This is a dependency property.
667  /// </summary>
668  /// <exception cref="ArgumentOutOfRangeException">The value has to be positive.</exception>
669  public float MaximumDepth
670  {
671  get { return maximumDepth; }
672  set
673  {
674  if (value < 0 || float.IsNaN(value))
675  throw new ArgumentOutOfRangeException("value");
676  maximumDepth = value;
677  InvalidateMeasure();
678  }
679  }
680 
681  /// <summary>
682  /// Gets or sets the vertical alignment of this element. This is a dependency property.
683  /// </summary>
685  {
686  get { return horizontalAlignment; }
687  set
688  {
689  horizontalAlignment = value;
690  InvalidateArrange();
691  }
692  }
693 
694  /// <summary>
695  /// Gets or sets the vertical alignment of this element. This is a dependency property.
696  /// </summary>
698  {
699  get { return verticalAlignment; }
700  set
701  {
702  verticalAlignment = value;
703  InvalidateArrange();
704  }
705  }
706 
707  /// <summary>
708  /// Gets or sets the depth alignment of this element. This is a dependency property.
709  /// </summary>
711  {
712  get { return depthAlignment; }
713  set
714  {
715  depthAlignment = value;
716  InvalidateArrange();
717  }
718  }
719 
720  /// <summary>
721  /// Gets or sets the name of this element. This is a dependency property.
722  /// </summary>
723  public string Name
724  {
725  get { return DependencyProperties.Get(NamePropertyKey); }
726  set { DependencyProperties.Set(NamePropertyKey, value); }
727  }
728 
729  /// <summary>
730  /// Gets the logical parent of this element. This is a dependency property.
731  /// </summary>
732  public UIElement Parent
733  {
734  get { return DependencyProperties.Get(parentPropertyKey); }
735  protected set { DependencyProperties.Set(parentPropertyKey, value); }
736  }
737 
738  /// <summary>
739  /// Gets the visual parent of this element. This is a dependency property.
740  /// </summary>
741  public UIElement VisualParent
742  {
743  get { return DependencyProperties.Get(visualParentPropertyKey); }
744  protected set { DependencyProperties.Set(visualParentPropertyKey, value); }
745  }
746 
747  /// <summary>
748  /// Get a enumerable to the visual children of the <see cref="UIElement"/>.
749  /// </summary>
750  /// <remarks>Inherited classes are in charge of overriding this method to return their children.</remarks>
751  public IEnumerable<UIElement> VisualChildren
752  {
753  get { return VisualChildrenCollection; }
754  }
755 
756  /// <summary>
757  /// The list of the children of the element that can be hit by the user.
758  /// </summary>
759  protected internal virtual List<UIElement> HitableChildren
760  {
761  get { return VisualChildrenCollection.UnderlyingList; }
762  }
763 
764  /// <summary>
765  /// Gets or sets the margins of this element. This is a dependency property.
766  /// </summary>
767  public Thickness Margin
768  {
769  get { return MarginInternal; }
770  set
771  {
772  MarginInternal = value;
773  InvalidateMeasure();
774  }
775  }
776 
777  /// <summary>
778  /// Gets or sets the LocalMatrix of this element. This is a dependency property.
779  /// </summary>
780  /// <remarks>The local transform is not taken is account during the layering. The transformation is purely for rendering effects.</remarks>
781  public Matrix LocalMatrix
782  {
783  get { return localMatrix; }
784  set
785  {
786  localMatrix = value;
787  LocalMatrixChanged = true;
788  }
789  }
790 
791  /// <summary>
792  /// The opacity used to render element.
793  /// </summary>
794  public float RenderOpacity { get; private set; }
795 
796  /// <summary>
797  /// Gets (or sets, but see Remarks) the final render size of this element.
798  /// </summary>
799  public Vector3 RenderSize
800  {
801  get { return RenderSizeInternal; }
802  private set { RenderSizeInternal = value; }
803  }
804 
805  /// <summary>
806  /// The rendering offsets caused by the UIElement margins and alignments.
807  /// </summary>
808  public Vector3 RenderOffsets { get; private set; }
809 
810  /// <summary>
811  /// Gets the rendered width of this element.
812  /// </summary>
813  public float ActualWidth
814  {
815  get { return RenderSize.X; }
816  }
817 
818  /// <summary>
819  /// Gets the rendered height of this element.
820  /// </summary>
821  public float ActualHeight
822  {
823  get { return RenderSize.Y; }
824  }
825  /// <summary>
826  /// Gets the rendered depth of this element.
827  /// </summary>
828  public float ActualDepth
829  {
830  get { return RenderSize.Z; }
831  }
832 
833  /// <summary>
834  /// The background color of the element.
835  /// </summary>
836  public Color BackgroundColor
837  {
838  get { return DependencyProperties.Get(backgroundColorPropertyKey); }
839  set { DependencyProperties.Set(backgroundColorPropertyKey, value); }
840  }
841 
842  private unsafe bool Vector3BinaryEqual(ref Vector3 left, ref Vector3 right)
843  {
844  fixed (Vector3* pVector3Left = &left)
845  fixed (Vector3* pVector3Right = &right)
846  {
847  var pLeft = (int*)pVector3Left;
848  var pRight = (int*)pVector3Right;
849 
850  return pLeft[0] == pRight[0] && pLeft[1] == pRight[1] && pLeft[2] == pRight[2];
851  }
852  }
853 
854  /// <summary>
855  /// Updates the <see cref="DesiredSize"/> of a <see cref="UIElement"/>.
856  /// Parent elements call this method from their own implementations to form a recursive layout update.
857  /// Calling this method constitutes the first pass (the "Measure" pass) of a layout update.
858  /// </summary>
859  /// <param name="availableSizeWithMargins">The available space that a parent element can allocate a child element with its margins.
860  /// A child element can request a larger space than what is available; the provided size might be accommodated if scrolling is possible in the content model for the current element.</param>
861  public void Measure(Vector3 availableSizeWithMargins)
862  {
863  if (!ForceNextMeasure && Vector3BinaryEqual(ref availableSizeWithMargins, ref previousProvidedMeasureSize))
864  {
865  IsMeasureValid = true;
866  ValidateChildrenMeasure();
867  return;
868  }
869 
870  ForceNextMeasure = false;
871  IsMeasureValid = true;
872  IsArrangeValid = false;
873  previousProvidedMeasureSize = availableSizeWithMargins;
874 
875  // avoid useless computation if the element is collapsed
876  if (IsCollapsed)
877  {
878  DesiredSize = DesiredSizeWithMargins = Vector3.Zero;
879  return;
880  }
881 
882  // variable containing the temporary desired size
883  var desiredSize = new Vector3(Width, Height, Depth);
884 
885  // override the size if not set by the user
886  if (float.IsNaN(desiredSize.X) || float.IsNaN(desiredSize.Y) || float.IsNaN(desiredSize.Z))
887  {
888  // either the width, height or the depth of the UIElement is not fixed
889  // -> compute the desired size of the children to determine it
890 
891  // removes the size required for the margins in the available size
892  var availableSizeWithoutMargins = CalculateSizeWithoutThickness(ref availableSizeWithMargins, ref MarginInternal);
893 
894  // trunk the available size for the element between the maximum and minimum width/height of the UIElement
895  availableSizeWithoutMargins = new Vector3(
896  Math.Max(MinimumWidth, Math.Min(MaximumWidth, !float.IsNaN(desiredSize.X)? desiredSize.X: availableSizeWithoutMargins.X)),
897  Math.Max(MinimumHeight, Math.Min(MaximumHeight, !float.IsNaN(desiredSize.Y) ? desiredSize.Y : availableSizeWithoutMargins.Y)),
898  Math.Max(MinimumDepth, Math.Min(MaximumDepth, !float.IsNaN(desiredSize.Z) ? desiredSize.Z : availableSizeWithoutMargins.Z)));
899 
900  // compute the desired size for the children
901  var childrenDesiredSize = MeasureOverride(availableSizeWithoutMargins);
902 
903  // replace the undetermined size by the desired size for the children
904  if (float.IsNaN(desiredSize.X))
905  desiredSize.X = childrenDesiredSize.X;
906  if (float.IsNaN(desiredSize.Y))
907  desiredSize.Y = childrenDesiredSize.Y;
908  if (float.IsNaN(desiredSize.Z))
909  desiredSize.Z = childrenDesiredSize.Z;
910 
911  // override the element size by the default size if still unspecified
912  if (float.IsNaN(desiredSize.X))
913  desiredSize.X = DefaultWidth;
914  if (float.IsNaN(desiredSize.Y))
915  desiredSize.Y = DefaultHeight;
916  if (float.IsNaN(desiredSize.Z))
917  desiredSize.Z = DefaultDepth;
918  }
919 
920  // trunk the desired size between the maximum and minimum width/height of the UIElement
921  desiredSize = new Vector3(
922  Math.Max(MinimumWidth, Math.Min(MaximumWidth, desiredSize.X)),
923  Math.Max(MinimumHeight, Math.Min(MaximumHeight, desiredSize.Y)),
924  Math.Max(MinimumDepth, Math.Min(MaximumDepth, desiredSize.Z)));
925 
926  // compute the desired size with margin
927  var desiredSizeWithMargins = CalculateSizeWithThickness(ref desiredSize, ref MarginInternal);
928 
929  // update Element state variables
930  DesiredSize = desiredSize;
931  DesiredSizeWithMargins = desiredSizeWithMargins;
932  }
933 
934  private void ValidateChildrenMeasure()
935  {
936  foreach (var child in VisualChildrenCollection)
937  {
938  if (!child.IsMeasureValid)
939  {
940  child.IsMeasureValid = true;
941  child.ValidateChildrenMeasure();
942  }
943  }
944  }
945 
946  /// <summary>
947  /// When overridden in a derived class, measures the size in layout required for possible child elements and determines a size for the <see cref="UIElement"/>-derived class.
948  /// </summary>
949  /// <param name="availableSizeWithoutMargins">The available size that this element can give to child elements.
950  /// Infinity can be specified as a value to indicate that the element will size to whatever content is available.</param>
951  /// <returns>The size desired by the children</returns>
952  protected virtual Vector3 MeasureOverride(Vector3 availableSizeWithoutMargins)
953  {
954  return Vector3.Zero;
955  }
956 
957  /// <summary>
958  /// Positions child elements and determines the size of the UIElement.
959  /// This method constitutes the second pass of a layout update.
960  /// </summary>
961  /// <param name="finalSizeWithMargins">The final size that the parent computes for the child element with the margins.</param>
962  /// <param name="isParentCollapsed">Boolean indicating if one of the parents of the element is currently collapsed.</param>
963  public void Arrange(Vector3 finalSizeWithMargins, bool isParentCollapsed)
964  {
965  if (!ForceNextArrange && Vector3BinaryEqual(ref finalSizeWithMargins, ref previousProvidedArrangeSize) && isParentCollapsed == previousIsParentCollapsed)
966  {
967  IsArrangeValid = true;
968  ValidateChildrenArrange();
969  return;
970  }
971 
972  ForceNextArrange = false;
973  IsArrangeValid = true;
974  ArrangeChanged = true;
975  previousIsParentCollapsed = isParentCollapsed;
976  previousProvidedArrangeSize = finalSizeWithMargins;
977 
978  // special to avoid useless computation if the element is collapsed
979  if (IsCollapsed || isParentCollapsed)
980  {
981  CollapseOverride();
982  return;
983  }
984 
985  // initialize the element size with the user suggested size (maybe NaN if not set)
986  var elementSize = new Vector3(Width, Height, Depth);
987 
988  // stretch the element if the user size is unspecified and alignment constraints requires it
989  var finalSizeWithoutMargins = CalculateSizeWithoutThickness(ref finalSizeWithMargins, ref MarginInternal);
990  if (float.IsNaN(elementSize.X) && HorizontalAlignment == HorizontalAlignment.Stretch)
991  elementSize.X = finalSizeWithoutMargins.X;
992  if (float.IsNaN(elementSize.Y) && VerticalAlignment == VerticalAlignment.Stretch)
993  elementSize.Y = finalSizeWithoutMargins.Y;
994  if (float.IsNaN(elementSize.Z) && DepthAlignment == DepthAlignment.Stretch)
995  elementSize.Z = finalSizeWithoutMargins.Z;
996 
997  // override the element size by the desired size if still unspecified
998  if (float.IsNaN(elementSize.X))
999  elementSize.X = Math.Min(DesiredSize.X, finalSizeWithoutMargins.X);
1000  if (float.IsNaN(elementSize.Y))
1001  elementSize.Y = Math.Min(DesiredSize.Y, finalSizeWithoutMargins.Y);
1002  if (float.IsNaN(elementSize.Z))
1003  elementSize.Z = Math.Min(DesiredSize.Z, finalSizeWithoutMargins.Z);
1004 
1005  // trunk the element size between the maximum and minimum width/height of the UIElement
1006  elementSize = new Vector3(
1007  Math.Max(MinimumWidth, Math.Min(MaximumWidth, elementSize.X)),
1008  Math.Max(MinimumHeight, Math.Min(MaximumHeight, elementSize.Y)),
1009  Math.Max(MinimumDepth, Math.Min(MaximumDepth, elementSize.Z)));
1010 
1011  // let ArrangeOverride decide of the final taken size
1012  elementSize = ArrangeOverride(elementSize);
1013 
1014  // compute the rendering offsets
1015  var renderOffsets = CalculateAdjustmentOffsets(ref MarginInternal, ref finalSizeWithMargins, ref elementSize);
1016 
1017  // update UIElement internal variables
1018  RenderSize = elementSize;
1019  RenderOffsets = renderOffsets;
1020  }
1021 
1022  private void ValidateChildrenArrange()
1023  {
1024  foreach (var child in VisualChildrenCollection)
1025  {
1026  if (!child.IsArrangeValid)
1027  {
1028  child.IsArrangeValid = true;
1029  child.ValidateChildrenArrange();
1030  }
1031  }
1032  }
1033 
1034  /// <summary>
1035  /// When overridden in a derived class, positions possible child elements and determines a size for a <see cref="UIElement"/> derived class.
1036  /// </summary>
1037  /// <param name="finalSizeWithoutMargins">The final area within the parent that this element should use to arrange itself and its children.</param>
1038  /// <returns>The actual size used.</returns>
1039  protected virtual Vector3 ArrangeOverride(Vector3 finalSizeWithoutMargins)
1040  {
1041  return finalSizeWithoutMargins;
1042  }
1043 
1044  /// <summary>
1045  /// When overridden in a derived class, collapse possible child elements and derived class.
1046  /// </summary>
1047  protected virtual void CollapseOverride()
1048  {
1049  DesiredSize = Vector3.Zero;
1050  DesiredSizeWithMargins = Vector3.Zero;
1051  RenderSize = Vector3.Zero;
1052  RenderOffsets = Vector3.Zero;
1053 
1054  foreach (var child in VisualChildrenCollection)
1055  PropagateCollapseToChild(child);
1056  }
1057 
1058  /// <summary>
1059  /// Propagate the collapsing to a child element <paramref name="element"/>.
1060  /// </summary>
1061  /// <param name="element">A child element to which propagate the collapse.</param>
1062  /// <exception cref="InvalidOperationException"><paramref name="element"/> is not a child of this element.</exception>
1063  protected void PropagateCollapseToChild(UIElement element)
1064  {
1065  if (element.VisualParent != this)
1066  throw new InvalidOperationException("Element is not a child of this element.");
1067 
1068  element.InvalidateMeasure();
1069  element.CollapseOverride();
1070  }
1071 
1072  /// <summary>
1073  /// Finds an element that has the provided identifier name in the element children.
1074  /// </summary>
1075  /// <param name="name">The name of the requested element.</param>
1076  /// <returns>The requested element. This can be null if no matching element was found.</returns>
1077  /// <remarks>If several elements with the same name exist return the first found</remarks>
1078  public UIElement FindName(string name)
1079  {
1080  if (Name == name)
1081  return this;
1082 
1083  return VisualChildren.Select(child => child.FindName(name)).FirstOrDefault(elt => elt != null);
1084  }
1085 
1086  /// <summary>
1087  /// Provides an accessor that simplifies access to the NameScope registration method.
1088  /// </summary>
1089  /// <param name="name">Name to use for the specified name-object mapping.</param>
1090  /// <param name="scopedElement">Object for the mapping.</param>
1091  protected void RegisterName(string name, UIElement scopedElement)
1092  {
1093  throw new NotImplementedException();
1094  }
1095 
1096  /// <summary>
1097  /// Set the parent to a child.
1098  /// </summary>
1099  /// <param name="child">The child to which set the parent.</param>
1100  /// <param name="parent">The parent of the child.</param>
1101  protected static void SetParent(UIElement child, UIElement parent)
1102  {
1103  if (parent != null && child.Parent != null && parent != child.Parent)
1104  throw new InvalidOperationException("The UI element 'Name="+child.Name+"' has already as parent the element 'Name="+child.Parent.Name+"'.");
1105 
1106  child.Parent = parent;
1107  }
1108 
1109  /// <summary>
1110  /// Set the visual parent to a child.
1111  /// </summary>
1112  /// <param name="child">The child to which set the visual parent.</param>
1113  /// <param name="parent">The parent of the child.</param>
1114  protected static void SetVisualParent(UIElement child, UIElement parent)
1115  {
1116  if (child == null) throw new ArgumentNullException("child");
1117  if (parent != null && child.VisualParent != null && parent != child.VisualParent)
1118  throw new InvalidOperationException("The UI element 'Name=" + child.Name + "' has already as visual parent the element 'Name=" + child.VisualParent.Name + "'.");
1119 
1120  if (child.VisualParent != null)
1121  child.VisualParent.VisualChildrenCollection.Remove(child);
1122 
1123  child.VisualParent = parent;
1124 
1125  if (parent != null)
1126  {
1127  parent.VisualChildrenCollection.Add(child);
1128  ((IUIElementUpdate)child).UpdateUISystemReference(parent.UISystem);
1129  }
1130  }
1131 
1132  /// <summary>
1133  /// Calculate the intersection of the UI element and the ray.
1134  /// </summary>
1135  /// <param name="ray">The ray in world space coordinate</param>
1136  /// <param name="intersectionPoint">The intersection point in world space coordinate</param>
1137  /// <returns><value>true</value> if the two elements intersects, <value>false</value> otherwise</returns>
1138  internal protected virtual bool Intersects(ref Ray ray, out Vector3 intersectionPoint)
1139  {
1140  // does ray intersect element Oxy face?
1141  var intersects = Collision.RayIntersectsRectangle(ref ray, ref WorldMatrixInternal, ref RenderSizeInternal, 2, out intersectionPoint);
1142 
1143  // if element has depth also test other faces
1144  if (ActualDepth > MathUtil.ZeroTolerance)
1145  {
1146  Vector3 intersection;
1147  if (Collision.RayIntersectsRectangle(ref ray, ref WorldMatrixInternal, ref RenderSizeInternal, 0, out intersection))
1148  {
1149  intersects = true;
1150  if (intersection.Z > intersectionPoint.Z)
1151  intersectionPoint = intersection;
1152  }
1153  if (Collision.RayIntersectsRectangle(ref ray, ref WorldMatrixInternal, ref RenderSizeInternal, 1, out intersection))
1154  {
1155  intersects = true;
1156  if (intersection.Z > intersectionPoint.Z)
1157  intersectionPoint = intersection;
1158  }
1159  }
1160 
1161  return intersects;
1162  }
1163 
1164  #region Implementation of the IUIElementUpdate interface
1165 
1166  void IUIElementUpdate.Update(GameTime time)
1167  {
1168  if(!IsEnabled)
1169  return;
1170 
1171  Update(time);
1172 
1173  foreach (var child in VisualChildrenCollection)
1174  ((IUIElementUpdate)child).Update(time);
1175  }
1176 
1177  void IUIElementUpdate.UpdateWorldMatrix(ref Matrix parentWorldMatrix, bool parentWorldChanged)
1178  {
1179  UpdateWorldMatrix(ref parentWorldMatrix, parentWorldChanged);
1180  }
1181 
1182  void IUIElementUpdate.UpdateElementState(int elementBias)
1183  {
1184  var parent = VisualParent;
1185  var parentRenderOpacity = 1f;
1186  var parentIsHierarchyEnabled = true;
1187  var parentHierarchyDisablePicking = false;
1188 
1189  if (parent != null)
1190  {
1191  parentRenderOpacity = parent.RenderOpacity;
1192  parentIsHierarchyEnabled = parent.IsHierarchyEnabled;
1193  parentHierarchyDisablePicking = parent.HierarchyDisablePicking;
1194  }
1195 
1196  RenderOpacity = parentRenderOpacity * Opacity;
1197  isHierarchyEnabled = parentIsHierarchyEnabled && isEnabled;
1198  HierarchyDisablePicking = parentHierarchyDisablePicking || PreventChildrenFromBeingHit;
1199  DepthBias = elementBias;
1200 
1201  var currentElementDepthBias = DepthBias + DrawLayerNumber;
1202 
1203  foreach (var visualChild in VisualChildrenCollection)
1204  {
1205  ((IUIElementUpdate)visualChild).UpdateElementState(currentElementDepthBias);
1206 
1207  currentElementDepthBias = visualChild.MaxChildrenDepthBias + (visualChild.ClipToBounds ? visualChild.DrawLayerNumber : 0);
1208  }
1209 
1210  MaxChildrenDepthBias = currentElementDepthBias;
1211  }
1212 
1213  void IUIElementUpdate.UpdateUISystemReference(UISystem system)
1214  {
1215  OnUISystemChanged(system);
1216  foreach (var children in VisualChildrenCollection)
1217  ((IUIElementUpdate)children).UpdateUISystemReference(system);
1218  }
1219 
1220  #endregion
1221 
1222  /// <summary>
1223  /// Method called by <see cref="IUIElementUpdate.Update"/>.
1224  /// This method can be overridden by inherited classes to perform time-based actions.
1225  /// This method is not in charge to recursively call the update on children elements, this is automatically done.
1226  /// </summary>
1227  /// <param name="time">The current time of the game</param>
1228  protected virtual void Update(GameTime time)
1229  {
1230  }
1231 
1232  /// <summary>
1233  /// Method called by <see cref="IUIElementUpdate.UpdateWorldMatrix"/>.
1234  /// Parents are in charge of recursively calling this function on their children.
1235  /// </summary>
1236  /// <param name="parentWorldMatrix">The world matrix of the parent.</param>
1237  /// <param name="parentWorldChanged">Boolean indicating if the world matrix provided by the parent changed</param>
1238  protected virtual void UpdateWorldMatrix(ref Matrix parentWorldMatrix, bool parentWorldChanged)
1239  {
1240  if (parentWorldChanged || LocalMatrixChanged || ArrangeChanged)
1241  {
1242  var localMatrixCopy = localMatrix;
1243 
1244  // include rendering offsets into the local matrix.
1245  localMatrixCopy.TranslationVector += RenderOffsets + RenderSize / 2;
1246 
1247  // calculate the world matrix of UIelement
1248  Matrix worldMatrix;
1249  Matrix.Multiply(ref localMatrixCopy, ref parentWorldMatrix, out worldMatrix);
1250  WorldMatrix = worldMatrix;
1251 
1252  LocalMatrixChanged = false;
1253  ArrangeChanged = false;
1254  }
1255  }
1256 
1257  /// <summary>
1258  /// Function called when the <see cref="UISystem"/> in charge of the <see cref="UIElement"/> changed.
1259  /// This function can be override in children classes.
1260  /// </summary>
1261  /// <param name="system">The new UI system in charge of the element.</param>
1262  protected virtual void OnUISystemChanged(UISystem system)
1263  {
1264  UISystem = system;
1265  }
1266 
1267  /// <summary>
1268  /// Add the thickness values into the size calculation of a UI element.
1269  /// </summary>
1270  /// <param name="sizeWithoutMargins">The size without the thickness included</param>
1271  /// <param name="thickness">The thickness to add to the space</param>
1272  /// <returns>The size with the margins included</returns>
1273  protected static Vector3 CalculateSizeWithThickness(ref Vector3 sizeWithoutMargins, ref Thickness thickness)
1274  {
1275  var negativeThickness = -thickness;
1276  return CalculateSizeWithoutThickness(ref sizeWithoutMargins, ref negativeThickness);
1277  }
1278 
1279  /// <summary>
1280  /// Remove the thickness values into the size calculation of a UI element.
1281  /// </summary>
1282  /// <param name="sizeWithMargins">The size with the thickness included</param>
1283  /// <param name="thickness">The thickness to remove in the space</param>
1284  /// <returns>The size with the margins not included</returns>
1285  protected static Vector3 CalculateSizeWithoutThickness(ref Vector3 sizeWithMargins, ref Thickness thickness)
1286  {
1287  return new Vector3(
1288  Math.Max(0, sizeWithMargins.X - thickness.Left - thickness.Right),
1289  Math.Max(0, sizeWithMargins.Y - thickness.Top - thickness.Bottom),
1290  Math.Max(0, sizeWithMargins.Z - thickness.Front - thickness.Back));
1291  }
1292 
1293  /// <summary>
1294  /// Computes the (X,Y,Z) offsets to position correctly the UI element given the total provided space to it.
1295  /// </summary>
1296  /// <param name="thickness">The thickness around the element to position.</param>
1297  /// <param name="providedSpace">The total space given to the child element by the parent</param>
1298  /// <param name="usedSpaceWithoutThickness">The space used by the child element without the thickness included in it.</param>
1299  /// <returns>The offsets</returns>
1300  protected Vector3 CalculateAdjustmentOffsets(ref Thickness thickness, ref Vector3 providedSpace, ref Vector3 usedSpaceWithoutThickness)
1301  {
1302  // compute the size of the element with the thickness included
1303  var usedSpaceWithThickness = CalculateSizeWithThickness(ref usedSpaceWithoutThickness, ref thickness);
1304 
1305  // set offset for left and stretch alignments
1306  var offsets = new Vector3(thickness.Left, thickness.Top, thickness.Back);
1307 
1308  // align the element horizontally
1309  switch (HorizontalAlignment)
1310  {
1311  case HorizontalAlignment.Center:
1312  offsets.X += (providedSpace.X - usedSpaceWithThickness.X) / 2;
1313  break;
1314  case HorizontalAlignment.Right:
1315  offsets.X += providedSpace.X - usedSpaceWithThickness.X;
1316  break;
1317  }
1318 
1319  // align the element vertically
1320  switch (VerticalAlignment)
1321  {
1322  case VerticalAlignment.Center:
1323  offsets.Y += (providedSpace.Y - usedSpaceWithThickness.Y) / 2;
1324  break;
1325  case VerticalAlignment.Bottom:
1326  offsets.Y += providedSpace.Y - usedSpaceWithThickness.Y;
1327  break;
1328  }
1329 
1330  // align the element vertically
1331  switch (DepthAlignment)
1332  {
1333  case DepthAlignment.Center:
1334  offsets.Z += (providedSpace.Z - usedSpaceWithThickness.Z) / 2;
1335  break;
1336  case DepthAlignment.Front:
1337  offsets.Z += providedSpace.Z - usedSpaceWithThickness.Z;
1338  break;
1339  }
1340 
1341  return offsets;
1342  }
1343 
1344  internal void PropagateRoutedEvent(RoutedEventArgs e)
1345  {
1346  var routedEvent = e.RoutedEvent;
1347 
1348  // propagate first if tunneling
1349  if (routedEvent.RoutingStrategy == RoutingStrategy.Tunnel && VisualParent != null)
1350  VisualParent.PropagateRoutedEvent(e);
1351 
1352  // Trigger the class handler
1353  var classHandler = EventManager.GetClassHandler(GetType(), routedEvent);
1354  if (classHandler != null && (classHandler.HandledEventToo || !e.Handled))
1355  classHandler.Invoke(this, e);
1356 
1357  // Trigger instance handlers
1358  if (eventsToHandlers.ContainsKey(routedEvent))
1359  {
1360  // get a list of handler from the pool where we can copy the handler to trigger
1361  if (routedEventHandlerInfoListPool.Count == 0)
1362  routedEventHandlerInfoListPool.Enqueue(new List<RoutedEventHandlerInfo>());
1363  var pooledList = routedEventHandlerInfoListPool.Dequeue();
1364 
1365  // copy the RoutedEventHandlerEventInfo list into a list of the pool in order to be able to modify the handler list in the handler itself
1366  pooledList.AddRange(eventsToHandlers[routedEvent]);
1367 
1368  // iterate on the pooled list to invoke handlers
1369  foreach (var handlerInfo in pooledList)
1370  {
1371  if (handlerInfo.HandledEventToo || !e.Handled)
1372  handlerInfo.Invoke(this, e);
1373  }
1374 
1375  // add the pooled list back to the pool.
1376  pooledList.Clear(); // avoid to keep dead references
1377  routedEventHandlerInfoListPool.Enqueue(pooledList);
1378  }
1379 
1380  // propagate afterwards if bubbling
1381  if (routedEvent.RoutingStrategy == RoutingStrategy.Bubble && VisualParent != null)
1382  VisualParent.PropagateRoutedEvent(e);
1383  }
1384 
1385  /// <summary>
1386  /// Raises a specific routed event. The <see cref="RoutedEvent"/> to be raised is identified within the <see cref="RoutedEventArgs"/> instance
1387  /// that is provided (as the <see cref="RoutedEvent"/> property of that event data).
1388  /// </summary>
1389  /// <param name="e">A <see cref="RoutedEventArgs"/> that contains the event data and also identifies the event to raise.</param>
1390  /// <exception cref="ArgumentNullException"><paramref name="e"/> is null.</exception>
1391  /// <exception cref="InvalidOperationException">The type of the routed event argument <paramref name="e"/> does not match the event handler second argument type.</exception>
1393  {
1394  if (e == null)
1395  throw new ArgumentNullException("e");
1396 
1397  if (e.RoutedEvent == null)
1398  return;
1399 
1400  if(!e.RoutedEvent.HandlerSecondArgumentType.GetTypeInfo().IsAssignableFrom(e.GetType().GetTypeInfo()))
1401  throw new InvalidOperationException("The type of second parameter of the handler (" + e.RoutedEvent.HandlerSecondArgumentType
1402  + ") is not assignable from the parameter 'e' type (" + e.GetType() + ").");
1403 
1404  var sourceWasNull = e.Source == null;
1405  if (sourceWasNull) // set the source to default if needed
1406  e.Source = this;
1407 
1408  e.StartEventRouting();
1409 
1410  PropagateRoutedEvent(e);
1411 
1412  e.EndEventRouting();
1413 
1414  if (sourceWasNull) // reset the source if it was not explicitly set (event might be reused again for other sources)
1415  e.Source = null;
1416  }
1417 
1418  /// <summary>
1419  /// Adds a routed event handler for a specified routed event, adding the handler to the handler collection on the current element.
1420  /// Specify handledEventsToo as true to have the provided handler be invoked for routed event that had already been marked as handled by another element along the event route.
1421  /// </summary>
1422  /// <param name="routedEvent">An identifier for the routed event to be handled.</param>
1423  /// <param name="handler">A reference to the handler implementation.</param>
1424  /// <param name="handledEventsToo">true to register the handler such that it is invoked even when the routed event is marked handled in its event data;
1425  /// false to register the handler with the default condition that it will not be invoked if the routed event is already marked handled.</param>
1426  /// <exception cref="ArgumentNullException">Provided handler or routed event is null.</exception>
1427  public void AddHandler<T>(RoutedEvent<T> routedEvent, EventHandler<T> handler, bool handledEventsToo = false) where T : RoutedEventArgs
1428  {
1429  if (routedEvent == null) throw new ArgumentNullException("routedEvent");
1430  if (handler == null) throw new ArgumentNullException("handler");
1431 
1432  if(!eventsToHandlers.ContainsKey(routedEvent))
1433  eventsToHandlers[routedEvent] = new List<RoutedEventHandlerInfo>();
1434 
1435  eventsToHandlers[routedEvent].Add(new RoutedEventHandlerInfo<T>(handler, handledEventsToo));
1436  }
1437 
1438  /// <summary>
1439  /// Removes the specified routed event handler from this element.
1440  /// </summary>
1441  /// <param name="routedEvent">The identifier of the routed event for which the handler is attached.</param>
1442  /// <param name="handler">The specific handler implementation to remove from the event handler collection on this element.</param>
1443  /// <exception cref="ArgumentNullException">Provided handler or routed event is null.</exception>
1444  public void RemoveHandler<T>(RoutedEvent<T> routedEvent, EventHandler<T> handler) where T : RoutedEventArgs
1445  {
1446  if (routedEvent == null) throw new ArgumentNullException("routedEvent");
1447  if (handler == null) throw new ArgumentNullException("handler");
1448 
1449  if(!eventsToHandlers.ContainsKey(routedEvent))
1450  return;
1451 
1452  eventsToHandlers[routedEvent].Remove(new RoutedEventHandlerInfo<T>(handler));
1453  }
1454 
1455  private readonly Dictionary<RoutedEvent, List<RoutedEventHandlerInfo>> eventsToHandlers = new Dictionary<RoutedEvent, List<RoutedEventHandlerInfo>>();
1456 
1457  #region Events
1458 
1459  /// <summary>
1460  /// Occurs when the value of the <see cref="MouseOverState"/> property changed.
1461  /// </summary>
1462  /// <remarks>This event is not a routed event</remarks>
1463  public event PropertyChangedHandler<MouseOverState> MouseOverStateChanged;
1464 
1465  /// <summary>
1466  /// Occurs when the user starts touching the <see cref="UIElement"/>. That is when he moves its finger down from the element.
1467  /// </summary>
1468  /// <remarks>A click event is tunneling</remarks>
1469  public event EventHandler<TouchEventArgs> PreviewTouchDown
1470  {
1471  add { AddHandler(previewTouchDownEvent, value); }
1472  remove { RemoveHandler(previewTouchDownEvent, value); }
1473  }
1474 
1475  /// <summary>
1476  /// Occurs when the user moves its finger on the <see cref="UIElement"/>.
1477  /// That is when his finger was already on the element and moved from its previous position.
1478  /// </summary>
1479  /// <remarks>A click event is tunneling</remarks>
1480  public event EventHandler<TouchEventArgs> PreviewTouchMove
1481  {
1482  add { AddHandler(previewTouchMoveEvent, value); }
1483  remove { RemoveHandler(previewTouchMoveEvent, value); }
1484  }
1485 
1486  /// <summary>
1487  /// Occurs when the user stops touching the <see cref="UIElement"/>. That is when he moves its finger up from the element.
1488  /// </summary>
1489  /// <remarks>A click event is tunneling</remarks>
1490  public event EventHandler<TouchEventArgs> PreviewTouchUp
1491  {
1492  add { AddHandler(previewTouchUpEvent, value); }
1493  remove { RemoveHandler(previewTouchUpEvent, value); }
1494  }
1495 
1496  /// <summary>
1497  /// Occurs when the user starts touching the <see cref="UIElement"/>. That is when he moves its finger down from the element.
1498  /// </summary>
1499  /// <remarks>A click event is bubbling</remarks>
1500  public event EventHandler<TouchEventArgs> TouchDown
1501  {
1502  add { AddHandler(touchDownEvent, value); }
1503  remove { RemoveHandler(touchDownEvent, value); }
1504  }
1505 
1506  /// <summary>
1507  /// Occurs when the user enters its finger into <see cref="UIElement"/>.
1508  /// That is when his finger was on the screen outside of the element and moved inside the element.
1509  /// </summary>
1510  /// <remarks>A click event is bubbling</remarks>
1511  public event EventHandler<TouchEventArgs> TouchEnter
1512  {
1513  add { AddHandler(touchEnterEvent, value); }
1514  remove { RemoveHandler(touchEnterEvent, value); }
1515  }
1516 
1517  /// <summary>
1518  /// Occurs when the user leaves its finger from the <see cref="UIElement"/>.
1519  /// That is when his finger was inside of the element and moved on the screen outside of the element.
1520  /// </summary>
1521  /// <remarks>A click event is bubbling</remarks>
1522  public event EventHandler<TouchEventArgs> TouchLeave
1523  {
1524  add { AddHandler(touchLeaveEvent, value); }
1525  remove { RemoveHandler(touchLeaveEvent, value); }
1526  }
1527 
1528  /// <summary>
1529  /// Occurs when the user move its finger inside the <see cref="UIElement"/>.
1530  /// That is when his finger was already on the element and moved from its previous position.
1531  /// </summary>
1532  /// <remarks>A click event is bubbling</remarks>
1533  public event EventHandler<TouchEventArgs> TouchMove
1534  {
1535  add { AddHandler(touchMoveEvent, value); }
1536  remove { RemoveHandler(touchMoveEvent, value); }
1537  }
1538 
1539  /// <summary>
1540  /// Occurs when the user stops touching the <see cref="UIElement"/>. That is when he moves its finger up from the element.
1541  /// </summary>
1542  /// <remarks>A click event is bubbling</remarks>
1543  public event EventHandler<TouchEventArgs> TouchUp
1544  {
1545  add { AddHandler(touchUpEvent, value); }
1546  remove { RemoveHandler(touchUpEvent, value); }
1547  }
1548 
1549  /// <summary>
1550  /// Occurs when the element has the focus and the user press a key on the keyboard.
1551  /// </summary>
1552  /// <remarks>A key pressed event is bubbling</remarks>
1553  internal event EventHandler<KeyEventArgs> KeyPressed
1554  {
1555  add { AddHandler(keyPressedEvent, value); }
1556  remove { RemoveHandler(keyPressedEvent, value); }
1557  }
1558 
1559  /// <summary>
1560  /// Occurs when the element has the focus and the user maintains a key pressed on the keyboard.
1561  /// </summary>
1562  /// <remarks>A key down event is bubbling</remarks>
1563  internal event EventHandler<KeyEventArgs> KeyDown
1564  {
1565  add { AddHandler(keyDownEvent, value); }
1566  remove { RemoveHandler(keyDownEvent, value); }
1567  }
1568 
1569  /// <summary>
1570  /// Occurs when the element has the focus and the user release a key on the keyboard.
1571  /// </summary>
1572  /// <remarks>A key released event is bubbling</remarks>
1573  internal event EventHandler<KeyEventArgs> KeyReleased
1574  {
1575  add { AddHandler(keyReleasedEvent, value); }
1576  remove { RemoveHandler(keyReleasedEvent, value); }
1577  }
1578 
1579  #endregion
1580 
1581  #region Internal Event Raiser
1582 
1583  internal void RaiseTouchDownEvent(TouchEventArgs touchArgs)
1584  {
1585  touchArgs.RoutedEvent = previewTouchDownEvent;
1586  RaiseEvent(touchArgs);
1587 
1588  touchArgs.RoutedEvent = touchDownEvent;
1589  RaiseEvent(touchArgs);
1590  }
1591 
1592  internal void RaiseTouchEnterEvent(TouchEventArgs touchArgs)
1593  {
1594  touchArgs.RoutedEvent = touchEnterEvent;
1595  RaiseEvent(touchArgs);
1596  }
1597 
1598  internal void RaiseTouchLeaveEvent(TouchEventArgs touchArgs)
1599  {
1600  touchArgs.RoutedEvent = touchLeaveEvent;
1601  RaiseEvent(touchArgs);
1602  }
1603 
1604  internal void RaiseTouchMoveEvent(TouchEventArgs touchArgs)
1605  {
1606  touchArgs.RoutedEvent = previewTouchMoveEvent;
1607  RaiseEvent(touchArgs);
1608 
1609  touchArgs.RoutedEvent = touchMoveEvent;
1610  RaiseEvent(touchArgs);
1611  }
1612 
1613  internal void RaiseTouchUpEvent(TouchEventArgs touchArgs)
1614  {
1615  touchArgs.RoutedEvent = previewTouchUpEvent;
1616  RaiseEvent(touchArgs);
1617 
1618  touchArgs.RoutedEvent = touchUpEvent;
1619  RaiseEvent(touchArgs);
1620  }
1621 
1622  internal void RaiseKeyPressedEvent(KeyEventArgs keyEventArgs)
1623  {
1624  keyEventArgs.RoutedEvent = keyPressedEvent;
1625  RaiseEvent(keyEventArgs);
1626  }
1627 
1628  internal void RaiseKeyDownEvent(KeyEventArgs keyEventArgs)
1629  {
1630  keyEventArgs.RoutedEvent = keyDownEvent;
1631  RaiseEvent(keyEventArgs);
1632  }
1633 
1634  internal void RaiseKeyReleasedEvent(KeyEventArgs keyEventArgs)
1635  {
1636  keyEventArgs.RoutedEvent = keyReleasedEvent;
1637  RaiseEvent(keyEventArgs);
1638  }
1639 
1640  #endregion
1641 
1642  #region Class Event Handlers
1643 
1644  private static void PreviewTouchDownClassHandler(object sender, TouchEventArgs args)
1645  {
1646  var uiElementSender = (UIElement)sender;
1647  if(uiElementSender.IsHierarchyEnabled)
1648  uiElementSender.OnPreviewTouchDown(args);
1649  }
1650 
1651  /// <summary>
1652  /// The class handler of the event <see cref="PreviewTouchDown"/>.
1653  /// This method can be overridden in inherited classes to perform actions common to all instances of a class.
1654  /// </summary>
1655  /// <param name="args">The arguments of the event</param>
1656  protected virtual void OnPreviewTouchDown(TouchEventArgs args)
1657  {
1658  IsTouched = true;
1659  }
1660 
1661  private static void PreviewTouchMoveClassHandler(object sender, TouchEventArgs args)
1662  {
1663  var uiElementSender = (UIElement)sender;
1664  if (uiElementSender.IsHierarchyEnabled)
1665  uiElementSender.OnPreviewTouchMove(args);
1666  }
1667 
1668  /// <summary>
1669  /// The class handler of the event <see cref="PreviewTouchMove"/>.
1670  /// This method can be overridden in inherited classes to perform actions common to all instances of a class.
1671  /// </summary>
1672  /// <param name="args">The arguments of the event</param>
1673  protected virtual void OnPreviewTouchMove(TouchEventArgs args)
1674  {
1675  }
1676 
1677  private static void PreviewTouchUpClassHandler(object sender, TouchEventArgs args)
1678  {
1679  var uiElementSender = (UIElement)sender;
1680  if (uiElementSender.IsHierarchyEnabled)
1681  uiElementSender.OnPreviewTouchUp(args);
1682  }
1683 
1684  /// <summary>
1685  /// The class handler of the event <see cref="PreviewTouchUp"/>.
1686  /// This method can be overridden in inherited classes to perform actions common to all instances of a class.
1687  /// </summary>
1688  /// <param name="args">The arguments of the event</param>
1689  protected virtual void OnPreviewTouchUp(TouchEventArgs args)
1690  {
1691  IsTouched = false;
1692  }
1693 
1694  private static void TouchDownClassHandler(object sender, TouchEventArgs args)
1695  {
1696  var uiElementSender = (UIElement)sender;
1697  if (uiElementSender.IsHierarchyEnabled)
1698  uiElementSender.OnTouchDown(args);
1699  }
1700 
1701  /// <summary>
1702  /// The class handler of the event <see cref="TouchDown"/>.
1703  /// This method can be overridden in inherited classes to perform actions common to all instances of a class.
1704  /// </summary>
1705  /// <param name="args">The arguments of the event</param>
1706  protected virtual void OnTouchDown(TouchEventArgs args)
1707  {
1708  }
1709 
1710  private static void TouchEnterClassHandler(object sender, TouchEventArgs args)
1711  {
1712  var uiElementSender = (UIElement)sender;
1713  if (uiElementSender.IsHierarchyEnabled)
1714  uiElementSender.OnTouchEnter(args);
1715  }
1716 
1717  /// <summary>
1718  /// The class handler of the event <see cref="TouchEnter"/>.
1719  /// This method can be overridden in inherited classes to perform actions common to all instances of a class.
1720  /// </summary>
1721  /// <param name="args">The arguments of the event</param>
1722  protected virtual void OnTouchEnter(TouchEventArgs args)
1723  {
1724  IsTouched = true;
1725  }
1726 
1727  private static void TouchLeaveClassHandler(object sender, TouchEventArgs args)
1728  {
1729  var uiElementSender = (UIElement)sender;
1730  if (uiElementSender.IsHierarchyEnabled)
1731  uiElementSender.OnTouchLeave(args);
1732  }
1733 
1734  /// <summary>
1735  /// The class handler of the event <see cref="TouchLeave"/>.
1736  /// This method can be overridden in inherited classes to perform actions common to all instances of a class.
1737  /// </summary>
1738  /// <param name="args">The arguments of the event</param>
1739  protected virtual void OnTouchLeave(TouchEventArgs args)
1740  {
1741  IsTouched = false;
1742  }
1743 
1744  private static void TouchMoveClassHandler(object sender, TouchEventArgs args)
1745  {
1746  var uiElementSender = (UIElement)sender;
1747  if (uiElementSender.IsHierarchyEnabled)
1748  uiElementSender.OnTouchMove(args);
1749  }
1750 
1751  /// <summary>
1752  /// The class handler of the event <see cref="TouchMove"/>.
1753  /// This method can be overridden in inherited classes to perform actions common to all instances of a class.
1754  /// </summary>
1755  /// <param name="args">The arguments of the event</param>
1756  protected virtual void OnTouchMove(TouchEventArgs args)
1757  {
1758  }
1759 
1760  private static void TouchUpClassHandler(object sender, TouchEventArgs args)
1761  {
1762  var uiElementSender = (UIElement)sender;
1763  if (uiElementSender.IsHierarchyEnabled)
1764  uiElementSender.OnTouchUp(args);
1765  }
1766 
1767  /// <summary>
1768  /// The class handler of the event <see cref="TouchUp"/>.
1769  /// This method can be overridden in inherited classes to perform actions common to all instances of a class.
1770  /// </summary>
1771  /// <param name="args">The arguments of the event</param>
1772  protected virtual void OnTouchUp(TouchEventArgs args)
1773  {
1774  }
1775 
1776  private static void KeyPressedClassHandler(object sender, KeyEventArgs args)
1777  {
1778  var uiElementSender = (UIElement)sender;
1779  if (uiElementSender.IsHierarchyEnabled)
1780  uiElementSender.OnKeyPressed(args);
1781  }
1782 
1783  /// <summary>
1784  /// The class handler of the event <see cref="KeyPressed"/>.
1785  /// This method can be overridden in inherited classes to perform actions common to all instances of a class.
1786  /// </summary>
1787  /// <param name="args">The arguments of the event</param>
1788  internal virtual void OnKeyPressed(KeyEventArgs args)
1789  {
1790  }
1791 
1792  private static void KeyDownClassHandler(object sender, KeyEventArgs args)
1793  {
1794  var uiElementSender = (UIElement)sender;
1795  if (uiElementSender.IsHierarchyEnabled)
1796  uiElementSender.OnKeyDown(args);
1797  }
1798 
1799  /// <summary>
1800  /// The class handler of the event <see cref="KeyDown"/>.
1801  /// This method can be overridden in inherited classes to perform actions common to all instances of a class.
1802  /// </summary>
1803  /// <param name="args">The arguments of the event</param>
1804  internal virtual void OnKeyDown(KeyEventArgs args)
1805  {
1806  }
1807 
1808  private static void KeyReleasedClassHandler(object sender, KeyEventArgs args)
1809  {
1810  var uiElementSender = (UIElement)sender;
1811  if (uiElementSender.IsHierarchyEnabled)
1812  uiElementSender.OnKeyReleased(args);
1813  }
1814 
1815  /// <summary>
1816  /// The class handler of the event <see cref="KeyReleased"/>.
1817  /// This method can be overridden in inherited classes to perform actions common to all instances of a class.
1818  /// </summary>
1819  /// <param name="args">The arguments of the event</param>
1820  internal virtual void OnKeyReleased(KeyEventArgs args)
1821  {
1822  }
1823 
1824  #endregion
1825  }
1826 }
MouseOverState
Describe the possible states of the mouse over an UI element.
Provides a base class for all the User Interface elements in Paradox applications.
Definition: UIElement.cs:21
static Vector3 CalculateSizeWithoutThickness(ref Vector3 sizeWithMargins, ref Thickness thickness)
Remove the thickness values into the size calculation of a UI element.
Definition: UIElement.cs:1285
virtual void Update(GameTime time)
Method called by IUIElementUpdate.Update. This method can be overridden by inherited classes to perfo...
Definition: UIElement.cs:1228
Represents a two dimensional mathematical vector.
Definition: Vector2.cs:42
static void SetVisualParent(UIElement child, UIElement parent)
Set the visual parent to a child.
Definition: UIElement.cs:1114
bool Handled
Gets or sets a value that indicates the present state of the event handling for a routed event as it ...
void Arrange(Vector3 finalSizeWithMargins, bool isParentCollapsed)
Positions child elements and determines the size of the UIElement. This method constitutes the second...
Definition: UIElement.cs:963
static Vector3 CalculateSizeWithThickness(ref Vector3 sizeWithoutMargins, ref Thickness thickness)
Add the thickness values into the size calculation of a UI element.
Definition: UIElement.cs:1273
VerticalAlignment
Describes how a child element is vertically positioned or stretched within a parent's layout slot...
Interface for the update of the UIElements.
virtual Vector3 ArrangeOverride(Vector3 finalSizeWithoutMargins)
When overridden in a derived class, positions possible child elements and determines a size for a UIE...
Definition: UIElement.cs:1039
virtual void OnPreviewTouchUp(TouchEventArgs args)
The class handler of the event PreviewTouchUp. This method can be overridden in inherited classes to ...
Definition: UIElement.cs:1689
virtual bool Intersects(ref Ray ray, out Vector3 intersectionPoint)
Calculate the intersection of the UI element and the ray.
Definition: UIElement.cs:1138
UIElement VisualParent
Gets the visual parent of this element. This is a dependency property.
Definition: UIElement.cs:742
virtual void OnPreviewTouchMove(TouchEventArgs args)
The class handler of the event PreviewTouchMove. This method can be overridden in inherited classes t...
Definition: UIElement.cs:1673
virtual void OnPreviewTouchDown(TouchEventArgs args)
The class handler of the event PreviewTouchDown. This method can be overridden in inherited classes t...
Definition: UIElement.cs:1656
UIElement()
Create an instance of a UIElement
Definition: UIElement.cs:177
Represents a container that can hold properties, lightweight to embed (lazy initialized).
Contains state information and event data associated with a routed event.
const float ZeroTolerance
The value for which all absolute numbers smaller than are considered equal to zero.
Definition: MathUtil.cs:38
Represents a three dimensional mathematical vector.
Definition: Vector3.cs:42
virtual Vector3 MeasureOverride(Vector3 availableSizeWithoutMargins)
When overridden in a derived class, measures the size in layout required for possible child elements ...
Definition: UIElement.cs:952
Visibility
Specifies the display state of an element.
Definition: Visibility.cs:8
static bool RayIntersectsRectangle(ref Ray ray, ref Matrix rectangleWorldMatrix, ref Vector3 rectangleSize, int normalAxis, out Vector3 intersectionPoint)
Determines whether there is an intersection between a Ray and a rectangle (2D).
Definition: Collision.cs:683
void RegisterName(string name, UIElement scopedElement)
Provides an accessor that simplifies access to the NameScope registration method. ...
Definition: UIElement.cs:1091
PropertyChangedHandler< MouseOverState > MouseOverStateChanged
Occurs when the value of the MouseOverState property changed.
Definition: UIElement.cs:1463
DepthAlignment
Describes how a child element is positioned in depth or stretched within a parent's layout slot...
Describes the thickness of a frame around a cuboid. Six float values describe the Left...
Definition: Thickness.cs:12
virtual void OnUISystemChanged(UISystem system)
Function called when the UISystem in charge of the UIElement changed. This function can be override i...
Definition: UIElement.cs:1262
static void SetParent(UIElement child, UIElement parent)
Set the parent to a child.
Definition: UIElement.cs:1101
HorizontalAlignment
Indicates where an element should be displayed on the horizontal axis relative to the allocated layou...
virtual void OnTouchDown(TouchEventArgs args)
The class handler of the event TouchDown. This method can be overridden in inherited classes to perfo...
Definition: UIElement.cs:1706
RoutedEvent RoutedEvent
Gets or sets the RoutedEvent associated with this RoutedEventArgs instance.
string Name
Gets or sets the name of this element. This is a dependency property.
Definition: UIElement.cs:724
Contains static methods to help in determining intersections, containment, etc.
Definition: Collision.cs:60
Base class for UI element renderers
virtual void OnNameChanged()
This method is call when the name of the UIElement changes. This method can be overridden in inherite...
Definition: UIElement.cs:358
UIElement Parent
Gets the logical parent of this element. This is a dependency property.
Definition: UIElement.cs:733
Current timing used for variable-step (real time) or fixed-step (game time) games.
Definition: GameTime.cs:31
SiliconStudio.Core.Mathematics.Color Color
Definition: ColorPicker.cs:14
virtual void UpdateWorldMatrix(ref Matrix parentWorldMatrix, bool parentWorldChanged)
Method called by IUIElementUpdate.UpdateWorldMatrix. Parents are in charge of recursively calling thi...
Definition: UIElement.cs:1238
void PropagateCollapseToChild(UIElement element)
Propagate the collapsing to a child element element .
Definition: UIElement.cs:1063
Represents a 32-bit color (4 bytes) in the form of RGBA (in byte order: R, G, B, A).
Definition: Color.cs:16
Represents a three dimensional line based on a point in space and a direction.
Definition: Ray.cs:42
virtual void OnTouchUp(TouchEventArgs args)
The class handler of the event TouchUp. This method can be overridden in inherited classes to perform...
Definition: UIElement.cs:1772
virtual void OnTouchEnter(TouchEventArgs args)
The class handler of the event TouchEnter. This method can be overridden in inherited classes to perf...
Definition: UIElement.cs:1722
Provides data for touch input events.
UIElement FindName(string name)
Finds an element that has the provided identifier name in the element children.
Definition: UIElement.cs:1078
Interface of the UI system.
Definition: UISystem.cs:20
virtual void OnTouchLeave(TouchEventArgs args)
The class handler of the event TouchLeave. This method can be overridden in inherited classes to perf...
Definition: UIElement.cs:1739
Represents and identifies a routed event and declares its characteristics.
Definition: RoutedEvent.cs:10
void Measure(Vector3 availableSizeWithMargins)
Updates the DesiredSize of a UIElement. Parent elements call this method from their own implementatio...
Definition: UIElement.cs:861
SiliconStudio.Core.Mathematics.Vector3 Vector3
_In_ size_t _In_ size_t size
Definition: DirectXTexP.h:175
A class that represents a tag propety.
Definition: PropertyKey.cs:17
A routed event typed with the RoutedEventArgs it triggers.
Definition: RoutedEvent.cs:38
Vector3 CalculateAdjustmentOffsets(ref Thickness thickness, ref Vector3 providedSpace, ref Vector3 usedSpaceWithoutThickness)
Computes the (X,Y,Z) offsets to position correctly the UI element given the total provided space to i...
Definition: UIElement.cs:1300
virtual void OnTouchMove(TouchEventArgs args)
The class handler of the event TouchMove. This method can be overridden in inherited classes to perfo...
Definition: UIElement.cs:1756
RoutingStrategy
Indicates the routing strategy of a routed event.
PropertyContainer DependencyProperties
List of the dependency properties attached to the object.
Definition: UIElement.cs:198
virtual void CollapseOverride()
When overridden in a derived class, collapse possible child elements and derived class.
Definition: UIElement.cs:1047
void RaiseEvent(RoutedEventArgs e)
Raises a specific routed event. The RoutedEvent to be raised is identified within the RoutedEventArgs...
Definition: UIElement.cs:1392
Represents a 4x4 mathematical matrix.
Definition: Matrix.cs:47