Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
Panel.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 using System;
4 using System.Collections.Generic;
5 using System.Collections.Specialized;
6 using System.Diagnostics;
7 
8 using SiliconStudio.Core;
9 using SiliconStudio.Core.Collections;
10 using SiliconStudio.Core.Mathematics;
11 using SiliconStudio.Paradox.UI.Controls;
12 
13 namespace SiliconStudio.Paradox.UI.Panels
14 {
15  /// <summary>
16  /// Provides a base class for all Panel elements. Use Panel elements to position and arrange child objects Paradox applications.
17  /// </summary>
18  [DebuggerDisplay("Panel - Name={Name}")]
19  public abstract class Panel : UIElement, IScrollAnchorInfo
20  {
21  /// <summary>
22  /// The key to the ZIndex dependency property.
23  /// </summary>
24  public readonly static PropertyKey<int> ZIndexPropertyKey = new PropertyKey<int>("ZIndexKey", typeof(Panel), DefaultValueMetadata.Static(0), ObjectInvalidationMetadata.New<int>(PanelZSortedChildInvalidator));
25 
26  /// <summary>
27  /// The key to the PanelArrangeMatrix dependency property. This property can be used by panels to arrange they children as they want.
28  /// </summary>
29  protected readonly static PropertyKey<Matrix> PanelArrangeMatrixPropertyKey = new PropertyKey<Matrix>("PanelArrangeMatrixKey", typeof(Panel), DefaultValueMetadata.Static(Matrix.Identity), ObjectInvalidationMetadata.New<Matrix>(InvalidateArrangeMatrix));
30 
31  private static void InvalidateArrangeMatrix(object propertyOwner, PropertyKey<Matrix> propertyKey, Matrix propertyOldValue)
32  {
33  var element = (UIElement)propertyOwner;
34  var parentPanel = element.VisualParent as Panel;
35 
36  if(parentPanel!=null) // if the element is not added to a panel yet, the invalidation will occur during the add of the child
37  parentPanel.childrenWithArrangeMatrixInvalidated.Add(element);
38  }
39 
40  private readonly bool[] shouldAnchor = new bool[3];
41 
42  /// <summary>
43  /// A comparer sorting the <see cref="Panel"/> children by increasing Z-Index.
44  /// </summary>
45  protected class PanelChildrenComparer : Comparer<UIElement>
46  {
47  public override int Compare(UIElement x, UIElement y)
48  {
49  if (x == y)
50  return 0;
51 
52  if (x == null)
53  return 1;
54 
55  if (y == null)
56  return -1;
57 
58  return x.DependencyProperties.Get(ZIndexPropertyKey) - y.DependencyProperties.Get(ZIndexPropertyKey);
59  }
60  }
61  /// <summary>
62  /// A instance of <see cref="PanelChildrenComparer"/> that can be used to sort panels children by increasing Z-Indices.
63  /// </summary>
64  protected readonly static PanelChildrenComparer PanelChildrenSorter = new PanelChildrenComparer();
65 
66  private readonly HashSet<UIElement> childrenWithArrangeMatrixInvalidated = new HashSet<UIElement>();
67  private Matrix[] childrenArrangeWorldMatrix = new Matrix[2];
68 
69  /// <summary>
70  /// Gets the <see cref="UIElementCollection"/> of child elements of this Panel.
71  /// </summary>
72  public UIElementCollection Children { get; private set; }
73 
74  /// <summary>
75  /// Invalidation callback that sort panel children back after a modification of a child ZIndex.
76  /// </summary>
77  /// <param name="element">The element which had is ZIndex modified</param>
78  /// <param name="key">The key of the modified property</param>
79  /// <param name="oldValue">The value of the property before modification</param>
80  private static void PanelZSortedChildInvalidator(object element, PropertyKey<int> key, int oldValue)
81  {
82  var uiElement = (UIElement)element;
83  var parentAsPanel = uiElement.VisualParent as Panel;
84 
85  if(parentAsPanel == null)
86  return;
87 
88  parentAsPanel.VisualChildrenCollection.Sort(PanelChildrenSorter);
89  }
90 
91  /// <summary>
92  /// Creates a new empty Panel.
93  /// </summary>
94  protected Panel()
95  {
96  // activate anchoring by default
97  for (int i = 0; i < shouldAnchor.Length; i++)
98  shouldAnchor[i] = true;
99 
100  Children = new UIElementCollection();
101  Children.CollectionChanged += LogicalChildrenChanged;
102  }
103 
104  /// <summary>
105  /// Action to take when the Children collection is modified.
106  /// </summary>
107  /// <param name="sender">Sender of the event</param>
108  /// <param name="trackingCollectionChangedEventArgs">Argument indicating what changed in the collection</param>
109  protected void LogicalChildrenChanged(object sender, TrackingCollectionChangedEventArgs trackingCollectionChangedEventArgs)
110  {
111  var modifiedElement = (UIElement)trackingCollectionChangedEventArgs.Item;
112  var elementIndex = trackingCollectionChangedEventArgs.Index;
113  switch (trackingCollectionChangedEventArgs.Action)
114  {
115  case NotifyCollectionChangedAction.Add:
116  OnLogicalChildAdded(modifiedElement, elementIndex);
117  break;
118  case NotifyCollectionChangedAction.Remove:
119  OnLogicalChildRemoved(modifiedElement, elementIndex);
120  break;
121  default:
122  throw new NotImplementedException();
123  }
124  InvalidateMeasure();
125  }
126 
127  /// <summary>
128  /// Action to perform when a logical child is removed.
129  /// </summary>
130  /// <param name="oldElement">The element that has been removed</param>
131  /// <param name="index">The index of the child removed in the collection</param>
132  protected virtual void OnLogicalChildRemoved(UIElement oldElement, int index)
133  {
134  if (oldElement.Parent == null)
135  throw new UIInternalException("The parent of the removed children UIElement not null");
136  SetParent(oldElement, null);
137  SetVisualParent(oldElement, null);
138  }
139 
140  /// <summary>
141  /// Action to perform when a logical child is added.
142  /// </summary>
143  /// <param name="newElement">The element that has been added</param>
144  /// <param name="index">The index in the collection where the child has been added</param>
145  protected virtual void OnLogicalChildAdded(UIElement newElement, int index)
146  {
147  if (newElement == null)
148  throw new InvalidOperationException("Cannot add a null UIElement to the children list.");
149  SetParent(newElement, this);
150  SetVisualParent(newElement, this);
151  VisualChildrenCollection.Sort(PanelChildrenSorter);
152  if(Children.Count > childrenArrangeWorldMatrix.Length)
153  childrenArrangeWorldMatrix = new Matrix[2*Children.Count];
154  }
155 
156  protected override void UpdateWorldMatrix(ref Matrix parentWorldMatrix, bool parentWorldChanged)
157  {
158  var shouldUpdateAllChridrenMatrix = parentWorldChanged || ArrangeChanged || LocalMatrixChanged;
159 
160  base.UpdateWorldMatrix(ref parentWorldMatrix, parentWorldChanged);
161 
162  var childIndex = 0;
163  foreach (var child in VisualChildrenCollection)
164  {
165  var shouldUpdateChildWorldMatrix = shouldUpdateAllChridrenMatrix || childrenWithArrangeMatrixInvalidated.Contains(child);
166  {
167  var childMatrix = child.DependencyProperties.Get(PanelArrangeMatrixPropertyKey);
168  Matrix.Multiply(ref childMatrix, ref WorldMatrixInternal, out childrenArrangeWorldMatrix[childIndex]);
169  }
170 
171  ((IUIElementUpdate)child).UpdateWorldMatrix(ref childrenArrangeWorldMatrix[childIndex], shouldUpdateChildWorldMatrix);
172 
173  ++childIndex;
174  }
175  childrenWithArrangeMatrixInvalidated.Clear();
176  }
177 
178  /// <summary>
179  /// Change the anchoring activation state of the given direction.
180  /// </summary>
181  /// <param name="direction">The direction in which activate or deactivate the anchoring</param>
182  /// <param name="enable"><value>true</value> to enable anchoring, <value>false</value> to disable the anchoring</param>
183  public void ActivateAnchoring(Orientation direction, bool enable)
184  {
185  shouldAnchor[(int)direction] = enable;
186  }
187 
188  public virtual bool ShouldAnchor(Orientation direction)
189  {
190  return shouldAnchor[(int)direction];
191  }
192 
193  public virtual Vector2 GetSurroudingAnchorDistances(Orientation direction, float position)
194  {
195  var maxPosition = RenderSize[(int)direction];
196  var validPosition = Math.Max(0, Math.Min(position, maxPosition));
197 
198  return new Vector2(-validPosition, maxPosition - validPosition);
199  }
200 
201  public ScrollViewer ScrollOwner { get; set; }
202  }
203 }
Provides a base class for all the User Interface elements in Paradox applications.
Definition: UIElement.cs:21
SiliconStudio.Paradox.Games.Mathematics.Vector2 Vector2
A comparer sorting the Panel children by increasing Z-Index.
Definition: Panel.cs:45
Represents a two dimensional mathematical vector.
Definition: Vector2.cs:42
void LogicalChildrenChanged(object sender, TrackingCollectionChangedEventArgs trackingCollectionChangedEventArgs)
Action to take when the Children collection is modified.
Definition: Panel.cs:109
The exception that is thrown when an internal error happened in the UI System. That is an error that ...
Orientation
Defines the different orientations that a control or layout can have.
Definition: Orientation.cs:8
Interface for the update of the UIElements.
Panel()
Creates a new empty Panel.
Definition: Panel.cs:94
_In_ size_t _In_ DXGI_FORMAT _In_ size_t _In_ float size_t y
Definition: DirectXTexP.h:191
virtual void OnLogicalChildAdded(UIElement newElement, int index)
Action to perform when a logical child is added.
Definition: Panel.cs:145
virtual Vector2 GetSurroudingAnchorDistances(Orientation direction, float position)
Get the distances to the previous and next anchors in the provided direction and from given position...
Definition: Panel.cs:193
Interface providing anchor information to its ScrollViewer.
void ActivateAnchoring(Orientation direction, bool enable)
Change the anchoring activation state of the given direction.
Definition: Panel.cs:183
UIElement Parent
Gets the logical parent of this element. This is a dependency property.
Definition: UIElement.cs:733
switch(inFormat)
object Item
Gets the added or removed item (if dictionary, value only).
override int Compare(UIElement x, UIElement y)
Definition: Panel.cs:47
NotifyCollectionChangedAction Action
Gets the type of action performed. Allowed values are NotifyCollectionChangedAction.Add and NotifyCollectionChangedAction.Remove.
virtual bool ShouldAnchor(Orientation direction)
Indicate whether the ScrollViewer managing this element should snap scrolling to anchors in the provi...
Definition: Panel.cs:188
virtual void OnLogicalChildRemoved(UIElement oldElement, int index)
Action to perform when a logical child is removed.
Definition: Panel.cs:132
Represents a scroll viewer. A scroll viewer element has an infinite virtual size defined by its Scrol...
Definition: ScrollViewer.cs:19
A class that represents a tag propety.
Definition: PropertyKey.cs:17
object Get(PropertyKey propertyKey)
Gets the specified tag value.
PropertyContainer DependencyProperties
List of the dependency properties attached to the object.
Definition: UIElement.cs:198
override void UpdateWorldMatrix(ref Matrix parentWorldMatrix, bool parentWorldChanged)
Method called by IUIElementUpdate.UpdateWorldMatrix. Parents are in charge of recursively calling thi...
Definition: Panel.cs:156
Provides a base class for all Panel elements. Use Panel elements to position and arrange child object...
Definition: Panel.cs:19
Represents a 4x4 mathematical matrix.
Definition: Matrix.cs:47