/NuclearWinter/UI/Group.cs

# · C# · 308 lines · 254 code · 38 blank · 16 comment · 58 complexity · b7d20e6a657bbd82d94848f9ad09a6c1 MD5 · raw file

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using Microsoft.Xna.Framework;
  6. using NuclearWinter;
  7. using Microsoft.Xna.Framework.Input;
  8. using System.Diagnostics;
  9. namespace NuclearWinter.UI
  10. {
  11. /*
  12. * A widget to lay out a bunch of child widgets
  13. */
  14. public class Group: Widget
  15. {
  16. protected List<Widget> mlChildren;
  17. public void Clear()
  18. {
  19. mlChildren.RemoveAll( delegate(Widget _widget) { _widget.Parent = null; return true; } );
  20. UpdateContentSize();
  21. }
  22. public void AddChild( Widget _widget )
  23. {
  24. AddChild( _widget, mlChildren.Count );
  25. }
  26. public virtual void AddChild( Widget _widget, int _iIndex )
  27. {
  28. Debug.Assert( _widget.Parent == null );
  29. _widget.Parent = this;
  30. mlChildren.Insert( _iIndex, _widget );
  31. UpdateContentSize();
  32. }
  33. public Widget GetChild( int _iIndex )
  34. {
  35. return mlChildren[ _iIndex ];
  36. }
  37. public virtual void RemoveChild( Widget _widget )
  38. {
  39. Debug.Assert( _widget.Parent == this );
  40. _widget.Parent = null;
  41. mlChildren.Remove( _widget );
  42. UpdateContentSize();
  43. }
  44. //----------------------------------------------------------------------
  45. public bool AutoSize = false;
  46. public int Width {
  47. get { return ContentWidth; }
  48. set { ContentWidth = value; }
  49. }
  50. public int Height {
  51. get { return ContentHeight; }
  52. set { ContentHeight = value; }
  53. }
  54. //----------------------------------------------------------------------
  55. public Group( Screen _screen )
  56. : base( _screen )
  57. {
  58. mlChildren = new List<Widget>();
  59. }
  60. //----------------------------------------------------------------------
  61. internal override void UpdateContentSize()
  62. {
  63. if( AutoSize )
  64. {
  65. //ContentWidth = 0;
  66. ContentHeight = 0;
  67. foreach( Widget widget in mlChildren )
  68. {
  69. //ContentWidth = Math.Max( ContentWidth, fixedWidget.LayoutRect.Right );
  70. int iHeight = 0;
  71. if( widget.AnchoredRect.Top.HasValue )
  72. {
  73. if( widget.AnchoredRect.Bottom.HasValue )
  74. {
  75. iHeight = widget.AnchoredRect.Top.Value + widget.ContentHeight + widget.AnchoredRect.Bottom.Value;
  76. }
  77. else
  78. {
  79. iHeight = widget.AnchoredRect.Top.Value + widget.AnchoredRect.Height;
  80. }
  81. }
  82. ContentHeight = Math.Max( ContentHeight, iHeight ) + Padding.Vertical;
  83. }
  84. }
  85. base.UpdateContentSize();
  86. }
  87. //----------------------------------------------------------------------
  88. internal override void Update( float _fElapsedTime )
  89. {
  90. foreach( Widget widget in mlChildren )
  91. {
  92. widget.Update( _fElapsedTime );
  93. }
  94. base.Update( _fElapsedTime );
  95. }
  96. //----------------------------------------------------------------------
  97. internal override void DoLayout( Rectangle _rect )
  98. {
  99. base.DoLayout( _rect );
  100. LayoutChildren();
  101. UpdateContentSize();
  102. HitBox = LayoutRect;
  103. }
  104. //----------------------------------------------------------------------
  105. protected virtual void LayoutChildren()
  106. {
  107. foreach( Widget widget in mlChildren )
  108. {
  109. widget.DoLayout( LayoutRect );
  110. }
  111. }
  112. //----------------------------------------------------------------------
  113. public override Widget GetFirstFocusableDescendant( Direction _direction )
  114. {
  115. Widget firstChild = null;
  116. Widget focusableDescendant = null;
  117. foreach( Widget child in mlChildren )
  118. {
  119. switch( _direction )
  120. {
  121. case Direction.Up:
  122. if( ( firstChild == null || child.LayoutRect.Bottom > firstChild.LayoutRect.Bottom ) )
  123. {
  124. Widget childFocusableWidget = child.GetFirstFocusableDescendant( _direction );
  125. if( childFocusableWidget != null )
  126. {
  127. firstChild = child;
  128. focusableDescendant = childFocusableWidget;
  129. }
  130. }
  131. break;
  132. case Direction.Down:
  133. if( firstChild == null || child.LayoutRect.Top < firstChild.LayoutRect.Top )
  134. {
  135. Widget childFocusableWidget = child.GetFirstFocusableDescendant( _direction );
  136. if( childFocusableWidget != null )
  137. {
  138. firstChild = child;
  139. focusableDescendant = childFocusableWidget;
  140. }
  141. }
  142. break;
  143. case Direction.Left:
  144. if( firstChild == null || child.LayoutRect.Right > firstChild.LayoutRect.Right )
  145. {
  146. Widget childFocusableWidget = child.GetFirstFocusableDescendant( _direction );
  147. if( childFocusableWidget != null )
  148. {
  149. firstChild = child;
  150. focusableDescendant = childFocusableWidget;
  151. }
  152. }
  153. break;
  154. case Direction.Right:
  155. if( firstChild == null || child.LayoutRect.Left < firstChild.LayoutRect.Left )
  156. {
  157. Widget childFocusableWidget = child.GetFirstFocusableDescendant( _direction );
  158. if( childFocusableWidget != null )
  159. {
  160. firstChild = child;
  161. focusableDescendant = childFocusableWidget;
  162. }
  163. }
  164. break;
  165. }
  166. }
  167. return focusableDescendant;
  168. }
  169. //----------------------------------------------------------------------
  170. public override Widget GetSibling( Direction _direction, Widget _child )
  171. {
  172. Widget nearestSibling = null;
  173. Widget focusableSibling = null;
  174. Widget fixedChild = (Widget)_child;
  175. foreach( Widget child in mlChildren )
  176. {
  177. if( child == _child ) continue;
  178. switch( _direction )
  179. {
  180. case Direction.Up:
  181. if( child.LayoutRect.Bottom <= fixedChild.LayoutRect.Center.Y && ( nearestSibling == null || child.LayoutRect.Bottom > nearestSibling.LayoutRect.Bottom ) )
  182. {
  183. Widget childFocusableWidget = child.GetFirstFocusableDescendant( _direction );
  184. if( childFocusableWidget != null )
  185. {
  186. nearestSibling = child;
  187. focusableSibling = childFocusableWidget;
  188. }
  189. }
  190. break;
  191. case Direction.Down:
  192. if( child.LayoutRect.Top >= fixedChild.LayoutRect.Center.Y && ( nearestSibling == null || child.LayoutRect.Top < nearestSibling.LayoutRect.Top ) )
  193. {
  194. Widget childFocusableWidget = child.GetFirstFocusableDescendant( _direction );
  195. if( childFocusableWidget != null )
  196. {
  197. nearestSibling = child;
  198. focusableSibling = childFocusableWidget;
  199. }
  200. }
  201. break;
  202. case Direction.Left:
  203. if( child.LayoutRect.Right <= fixedChild.LayoutRect.Center.X && ( nearestSibling == null || child.LayoutRect.Right > nearestSibling.LayoutRect.Right ) )
  204. {
  205. Widget childFocusableWidget = child.GetFirstFocusableDescendant( _direction );
  206. if( childFocusableWidget != null )
  207. {
  208. nearestSibling = child;
  209. focusableSibling = childFocusableWidget;
  210. }
  211. }
  212. break;
  213. case Direction.Right:
  214. if( child.LayoutRect.Left >= fixedChild.LayoutRect.Center.X && ( nearestSibling == null || child.LayoutRect.Left < nearestSibling.LayoutRect.Left ) )
  215. {
  216. Widget childFocusableWidget = child.GetFirstFocusableDescendant( _direction );
  217. if( childFocusableWidget != null )
  218. {
  219. nearestSibling = child;
  220. focusableSibling = childFocusableWidget;
  221. }
  222. }
  223. break;
  224. }
  225. }
  226. if( focusableSibling == null )
  227. {
  228. return base.GetSibling( _direction, this );
  229. }
  230. return focusableSibling;
  231. }
  232. //----------------------------------------------------------------------
  233. public override Widget HitTest( Point _point )
  234. {
  235. if( HitBox.Contains( _point ) )
  236. {
  237. Widget hitWidget;
  238. for( int iChild = mlChildren.Count - 1; iChild >= 0; iChild-- )
  239. {
  240. Widget child = mlChildren[iChild];
  241. if( ( hitWidget = child.HitTest( _point ) ) != null )
  242. {
  243. return hitWidget;
  244. }
  245. }
  246. }
  247. return null;
  248. }
  249. //----------------------------------------------------------------------
  250. internal override bool OnPadButton( Buttons _button, bool _bIsDown )
  251. {
  252. foreach( Widget child in mlChildren )
  253. {
  254. if( child.OnPadButton( _button, _bIsDown ) )
  255. {
  256. return true;
  257. }
  258. }
  259. return false;
  260. }
  261. //----------------------------------------------------------------------
  262. internal override void Draw()
  263. {
  264. foreach( Widget child in mlChildren )
  265. {
  266. child.Draw();
  267. }
  268. }
  269. }
  270. }