PageRenderTime 28ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/Tags/0.1.3/BlackStar/Component.cs

#
C# | 853 lines | 631 code | 95 blank | 127 comment | 67 complexity | cc965096b468ab18b8c121c1cdd86295 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 Microsoft.Xna.Framework.Graphics;
  7. using Microsoft.Xna.Framework.Content;
  8. using Microsoft.Xna.Framework.Input;
  9. namespace BlackStar
  10. {
  11. public enum DockStyle : int
  12. {
  13. None = 0,
  14. Top = 1,
  15. Bottom = 2,
  16. Left = 3,
  17. Right = 4,
  18. Fill = 5
  19. }
  20. /// <summary>
  21. /// Reads Components from compiled content.
  22. /// </summary>
  23. public class ComponentContentReader : ContentTypeReader<Component>
  24. {
  25. protected override Component Read(ContentReader input, Component existingInstance)
  26. {
  27. Component result = new Component();
  28. result.ReadContent(input);
  29. return result;
  30. }
  31. }
  32. /// <summary>
  33. /// the base object that all GUI items descend from.
  34. /// </summary>
  35. public class Component : IComparable<Component>
  36. {
  37. #region Events
  38. public event ComponentMouseEvent MouseEnter;
  39. public event ComponentMouseEvent MouseExit;
  40. public event ComponentMouseEvent MouseUp;
  41. public event ComponentMouseEvent MouseDown;
  42. public event ComponentMouseEvent MouseClick;
  43. public event ComponentMouseEvent MouseDoubleClick;
  44. public event ComponentMouseEvent MouseScroll;
  45. public event ComponentEvent TextChanged;
  46. public event ComponentEvent Resized;
  47. public event ComponentEvent Enter;
  48. public event ComponentEvent Leave;
  49. public event ComponentKeyEvent KeyDown;
  50. public event ComponentKeyEvent KeyUp;
  51. #endregion
  52. #region Protected Variables
  53. protected string myText = string.Empty;
  54. protected string myFont = "Default";
  55. protected Color myFontColor = Color.Black;
  56. protected DockStyle myDock = DockStyle.None;
  57. protected bool myCanFocus = true;
  58. protected string myTabNext = string.Empty;
  59. protected string myTabPrev = string.Empty;
  60. protected Rectangle myDockSpace = Rectangle.Empty;
  61. protected bool myWriteToContent = true;
  62. /// <summary>
  63. /// Indicates if the last time the control updated, the mouse was over it.
  64. /// </summary>
  65. protected bool lastMouseOverMe = false;
  66. /// <summary>
  67. /// Used to disable the resizing code.
  68. /// </summary>
  69. protected bool layoutSuspended = true;
  70. /// <summary>
  71. /// A name for the component so that It can be found by
  72. /// name by the code using the GUI.
  73. /// </summary>
  74. protected string myName;
  75. /// <summary>
  76. /// Determines the order in which components are drawn. Lower values are
  77. /// drawn before higher values.
  78. /// </summary>
  79. protected int myDrawOrder = 0;
  80. /// <summary>
  81. /// The color used to draw the componet. Can be used to tint a skin, or
  82. /// make the control transparent by setting the alpha value of the color.
  83. /// </summary>
  84. protected Color myColor = Color.White;
  85. /// <summary>
  86. /// Determines if the control should be drawn or not. If visible is set to false,
  87. /// child components will also not be drawn.
  88. /// </summary>
  89. protected bool myVisible = true;
  90. protected string myCursor = "Default";
  91. protected internal int naturalOrder = 0;
  92. // the component's postion and size relative to its parent.
  93. protected internal Rectangle myRectangle = Rectangle.Empty;
  94. // how far child components are pushed in from the edge.
  95. protected Rectangle myPadding = Rectangle.Empty;
  96. // the components position relative to the screen.
  97. // protected Rectangle myAbsoluteRectangle = Rectangle.Empty;
  98. // the components interior space relative to the screen.
  99. protected internal Rectangle myInterior = Rectangle.Empty;
  100. protected bool myInheritColor = true;
  101. protected bool myInheritFont = true;
  102. protected bool myInheritFontColor = true;
  103. protected int myFontSize = 20;
  104. protected bool myInheritFontSize = true;
  105. #endregion
  106. // the serialized members region contains all the public members that
  107. // can be serialized. To keep editing the XML files related to components
  108. // relatively simple, We start with the name as the very first element.
  109. // all other elements are in alphabetical order.
  110. #region SerializedMembers
  111. /// <summary>
  112. /// A name to identify the component for use by the code that
  113. /// utilizes the GUI.
  114. /// </summary>
  115. public string Name
  116. {
  117. get { return myName; }
  118. set { myName = value; }
  119. }
  120. [ContentSerializer(Optional = true)]
  121. public bool CanFocus
  122. {
  123. get { return myCanFocus; }
  124. set { myCanFocus = value; }
  125. }
  126. [ContentSerializer(Optional = true)]
  127. public List<Component> Children = new List<Component>();
  128. /// <summary>
  129. /// The color that will be used to draw the component. If the component is skinned,
  130. /// setting the color can tint the skin. Setting the Alpha value of the color will
  131. /// affect the transparency of the control.
  132. /// </summary>
  133. [ContentSerializer(Optional = true)]
  134. public Color Color
  135. {
  136. get { return (myInheritColor && Parent != null) ? Parent.Color : myColor; }
  137. set { myColor = value; }
  138. }
  139. [ContentSerializer(Optional = true)]
  140. public string Cursor
  141. {
  142. get { return myCursor; }
  143. set { myCursor = value; }
  144. }
  145. [ContentSerializer(Optional = true)]
  146. public DockStyle Dock
  147. {
  148. get { return myDock; }
  149. set { myDock = value; }
  150. }
  151. [ContentSerializer(Optional = true)]
  152. public int DrawOrder
  153. {
  154. get { return myDrawOrder; }
  155. set { myDrawOrder = value; }
  156. }
  157. [ContentSerializer(Optional = true)]
  158. public string Font
  159. {
  160. get { return (myInheritFont && Parent != null) ? Parent.Font : myFont; }
  161. set { myFont = value; }
  162. }
  163. [ContentSerializer(Optional = true)]
  164. public Color FontColor
  165. {
  166. get { return (myInheritFontColor && Parent != null) ? Parent.FontColor : myFontColor; }
  167. set { myFontColor = value; }
  168. }
  169. [ContentSerializer(Optional = true)]
  170. public int FontSize
  171. {
  172. get { return (myInheritFontSize && Parent != null) ? Parent.FontSize : myFontSize; }
  173. set { myFontSize = value; }
  174. }
  175. [ContentSerializer(Optional = true)]
  176. public bool InheritColor
  177. {
  178. get { return myInheritColor; }
  179. set { myInheritColor = value; }
  180. }
  181. [ContentSerializer(Optional = true)]
  182. public bool InheritFont
  183. {
  184. get { return myInheritFont; }
  185. set { myInheritFont = value; }
  186. }
  187. [ContentSerializer(Optional = true)]
  188. public bool InheritFontColor
  189. {
  190. get { return myInheritFontColor; }
  191. set { myInheritFontColor = value; }
  192. }
  193. [ContentSerializer(Optional = true)]
  194. public bool InheritFontSize
  195. {
  196. get { return myInheritFontSize; }
  197. set { myInheritFontSize = value; }
  198. }
  199. [ContentSerializer(Optional = true)]
  200. public Rectangle Padding
  201. {
  202. get { return myPadding; }
  203. set { myPadding = value; UpdateRectangles(); }
  204. }
  205. public Rectangle Rectangle
  206. {
  207. get { return myRectangle; }
  208. set { myRectangle = value; UpdateRectangles(); }
  209. }
  210. [ContentSerializer(Optional = true)]
  211. public virtual string TabNext
  212. {
  213. get { return myTabNext; }
  214. set { myTabNext = value; }
  215. }
  216. [ContentSerializer(Optional = true)]
  217. public virtual string TabPrev
  218. {
  219. get { return myTabPrev; }
  220. set { myTabPrev = value; }
  221. }
  222. [ContentSerializer(Optional = true)]
  223. public virtual string Text
  224. {
  225. get { return myText; }
  226. set { SetText(value); }
  227. }
  228. protected virtual void SetText(string value)
  229. {
  230. if (myText != value)
  231. {
  232. myText = value;
  233. OnTextChanged();
  234. }
  235. }
  236. /// <summary>
  237. /// Determines if the component should be drawn. If Visible is false, the
  238. /// component and child components will not be drawn.
  239. /// </summary>
  240. [ContentSerializer(Optional = true)]
  241. public bool Visible
  242. {
  243. get { return myVisible; }
  244. set { myVisible = value; }
  245. }
  246. [ContentSerializerIgnore]
  247. public bool WriteToContent
  248. {
  249. get { return myWriteToContent; }
  250. set { myWriteToContent = value; }
  251. }
  252. #endregion
  253. #region Non Serialized Properties
  254. //public Rectangle Absolute { get { return myAbsoluteRectangle; } }
  255. public virtual Rectangle Interior { get { return myInterior; } }
  256. #endregion
  257. #region Content Members
  258. /// <summary>
  259. /// Loads the componets settings from compiled content.
  260. /// </summary>
  261. /// <param name="input">a content reader currently reading a component.</param>
  262. protected virtual internal void ReadContent(ContentReader input)
  263. {
  264. // suspend the layout until we are done loading.
  265. // this prevents the resize code from running before all the
  266. // size and location values are set.
  267. this.SuspendLayout();
  268. // Load all the properties of this component.
  269. this.Name = input.ReadString();
  270. this.Rectangle = input.ReadObject<Rectangle>();
  271. this.Padding = input.ReadObject<Rectangle>();
  272. this.Color = input.ReadColor();
  273. this.Visible = input.ReadBoolean();
  274. this.Cursor = input.ReadString();
  275. this.Text = input.ReadString();
  276. this.Font = input.ReadString();
  277. this.FontColor = input.ReadColor();
  278. this.Dock = (DockStyle)input.ReadInt32();
  279. this.InheritColor = input.ReadBoolean();
  280. this.InheritFont = input.ReadBoolean();
  281. this.InheritFontColor = input.ReadBoolean();
  282. this.myTabNext = input.ReadString();
  283. this.myTabPrev = input.ReadString();
  284. this.myDrawOrder = input.ReadInt32();
  285. // load child components.
  286. this.Children.AddRange(input.ReadObject<List<Component>>());
  287. int i = 0;
  288. foreach (Component c in this.Children)
  289. { c.naturalOrder = i; i++; }
  290. //this.Children = input.ReadObject<List<Component>>();
  291. // this will throw an exception if any of my children have the same name.
  292. this.CheckChildNames();
  293. // set the parent on child components.
  294. foreach (Component c in Children) { c.Parent = this; }
  295. // load any content required by this component.
  296. this.Load(input.ContentManager);
  297. }
  298. #endregion
  299. #region Rectangle Management
  300. protected virtual void UpdateRectangles()
  301. {
  302. // first get the dockspace left from the parent.
  303. if (Parent == null)
  304. {
  305. myDrawRectangle = myRectangle;
  306. return;
  307. }
  308. Rectangle parentDock = this.Parent.myDockSpace;
  309. switch (myDock)
  310. {
  311. case DockStyle.Top:
  312. myDrawRectangle.X = parentDock.X;
  313. myDrawRectangle.Y = parentDock.Y;
  314. myDrawRectangle.Width = parentDock.Width;
  315. myDrawRectangle.Height = myRectangle.Height;
  316. Parent.myDockSpace.Y += myRectangle.Height;
  317. Parent.myDockSpace.Height -= myRectangle.Height;
  318. break;
  319. case DockStyle.Bottom:
  320. myDrawRectangle.X = parentDock.X;
  321. myDrawRectangle.Y = parentDock.Bottom - myRectangle.Height;
  322. myDrawRectangle.Width = parentDock.Width;
  323. myDrawRectangle.Height = myRectangle.Height;
  324. Parent.myDockSpace.Height -= myRectangle.Height;
  325. break;
  326. case DockStyle.Left:
  327. myDrawRectangle.X = parentDock.X;
  328. myDrawRectangle.Y = parentDock.Y;
  329. myDrawRectangle.Width = myRectangle.Width;
  330. myDrawRectangle.Height = parentDock.Height;
  331. Parent.myDockSpace.X += myRectangle.Width;
  332. Parent.myDockSpace.Width -= myRectangle.Width;
  333. break;
  334. case DockStyle.Right:
  335. myDrawRectangle.X = parentDock.Right - myRectangle.Width;
  336. myDrawRectangle.Y = parentDock.Y;
  337. myDrawRectangle.Width = myRectangle.Width;
  338. myDrawRectangle.Height = parentDock.Height;
  339. Parent.myDockSpace.Width -= myRectangle.Width;
  340. break;
  341. case DockStyle.Fill:
  342. myDrawRectangle = parentDock;
  343. Parent.myDockSpace.Width = 0; // no space left.
  344. Parent.myDockSpace.Height = 0; // no space left.
  345. break;
  346. default:
  347. // the componet should be drawn at its stated location.
  348. myDrawRectangle.X = myRectangle.X + Parent.myDrawRectangle.X;
  349. myDrawRectangle.Y = myRectangle.Y + Parent.myDrawRectangle.Y;
  350. myDrawRectangle.Width = myRectangle.Width;
  351. myDrawRectangle.Height = myRectangle.Height;
  352. break;
  353. }
  354. // now update my dockspace.
  355. myDockSpace.X = myInterior.X = myDrawRectangle.X + myPadding.X;
  356. myDockSpace.Y = myInterior.Y = myDrawRectangle.Y + myPadding.Y;
  357. myDockSpace.Width = myInterior.Width = myDrawRectangle.Width - myPadding.X - myPadding.Width;
  358. myDockSpace.Height = myInterior.Height = myDrawRectangle.Height - myPadding.Y - myPadding.Height;
  359. }
  360. #endregion
  361. /// <summary>
  362. /// Provides the component and all its child components an opportunity to update.
  363. /// </summary>
  364. public virtual void Update(GameTime gameTime)
  365. {
  366. // not visible, nothing to do.
  367. if (!myVisible) return;
  368. bool mouseOver = this.IsMouseOver(gui.mouse.Location);
  369. if (mouseOver && !lastMouseOverMe)
  370. { DoMouseEnter(gui.mouse.getArgs()); OnMouseEnter(); }
  371. if (!mouseOver && lastMouseOverMe)
  372. { DoMouseExit(gui.mouse.getArgs()); OnMouseExit(); }
  373. UpdateComponents(gameTime);
  374. lastMouseOverMe = mouseOver;
  375. }
  376. /// <summary>
  377. /// Calls Update on all child components.
  378. /// </summary>
  379. protected virtual void UpdateComponents(GameTime gameTime)
  380. {
  381. // update all the child components.
  382. foreach (Component c in Children) { c.Update(gameTime); }
  383. }
  384. /// <summary>
  385. /// Checks to see if the mouse is over a child component.
  386. /// </summary>
  387. /// <returns>True if the mouse is over a child, otherwise false.</returns>
  388. protected internal bool IsMouseOverChild(Point p)
  389. {
  390. // the mouse can not be over a child component
  391. // if the parent is invisible.
  392. if (!myVisible) return false;
  393. // loop through each component.
  394. foreach (Component c in Children)
  395. //return true if the mouse is over that component.
  396. { if (c.IsMouseOver(p)) { return true; } }
  397. // if no child returned true, return false.
  398. return false;
  399. }
  400. /// <summary>
  401. /// Checks to see if the mous is over thi control.
  402. /// </summary>
  403. /// <returns>True if the mouse is over the control. False if it is not
  404. /// over this contorl, or it is over a child control.</returns>
  405. protected internal bool IsMouseOver(Point p)
  406. {
  407. // the mouse can not be over an invisible component.
  408. if (!myVisible) return false;
  409. // the mouse is not over this control if
  410. // it is over a child control.
  411. if (IsMouseOverChild(p)) { return false; }
  412. // check to see if the mouse is over this control.
  413. // notice that we use the absolute left and top. This
  414. // is because we want to know the controls screen position
  415. // because the mouse position is relative to the screen.
  416. return this.myDrawRectangle.Contains(p);
  417. }
  418. /// <summary>
  419. /// Changes the draw order so that this component is drawn last
  420. /// making it appear to be in front of overlapping components.
  421. /// </summary>
  422. public void BringToFront()
  423. {
  424. if (this.Parent != null)
  425. {
  426. Parent.BringToFront();
  427. Parent.NormalizeDrawOrder();
  428. this.DrawOrder = Parent.Children.Count;
  429. }
  430. }
  431. /// <summary>
  432. /// Changes the draw order so that this component is drawn first
  433. /// making it appear to be behind overlapping components.
  434. /// </summary>
  435. public void SendToBack()
  436. {
  437. if (this.Parent != null)
  438. {
  439. Parent.NormalizeDrawOrder();
  440. this.DrawOrder = 0;
  441. }
  442. }
  443. /// <summary>
  444. /// Sorts the components and renumbers their draw order to be sequential.
  445. /// </summary>
  446. protected void NormalizeDrawOrder()
  447. {
  448. Children.Sort();
  449. int i = 0;
  450. foreach (Component c in Children)
  451. {
  452. c.DrawOrder = i;
  453. i++;
  454. }
  455. }
  456. /// <summary>
  457. /// Stops this component and all child components from running
  458. /// any resizing code until ResumeLayout is called.
  459. /// </summary>
  460. public void SuspendLayout()
  461. {
  462. layoutSuspended = true;
  463. foreach (Component c in Children) { c.SuspendLayout(); }
  464. }
  465. /// <summary>
  466. /// Causes the componet and all child components to resume running
  467. /// resizing code.
  468. /// </summary>
  469. public void ResumeLayout()
  470. {
  471. layoutSuspended = false;
  472. foreach (Component c in Children) { c.ResumeLayout(); }
  473. Resize();
  474. }
  475. /// <summary>
  476. /// Draws the component on the screen. Also Draws all child components.
  477. /// </summary>
  478. public virtual void Draw()
  479. {
  480. if (!Visible) return;
  481. myGui.DrawRectangle(myDrawRectangle, this.Color, true);
  482. DrawComponents();
  483. }
  484. /// <summary>
  485. /// Draws all child components on the screen.
  486. /// </summary>
  487. protected virtual void DrawComponents()
  488. {
  489. Children.Sort(DrawAscend);
  490. foreach (Component c in Children) { c.Draw(); }
  491. }
  492. /// <summary>
  493. /// updates the size of the component and all child components.
  494. /// </summary>
  495. public virtual void Resize()
  496. {
  497. if (layoutSuspended) return;
  498. Children.Sort(NaturalOrder);
  499. UpdateRectangles();
  500. foreach (Component c in Children) { c.Resize(); }
  501. OnResize();
  502. }
  503. // This region contains code that caused the event to
  504. // be raised with the client code if an event handler
  505. // has been assigned.
  506. #region Event Triggers
  507. protected internal void OnCreate()
  508. {
  509. foreach (Component c in Children)
  510. { c.OnCreate(); }
  511. myGui.OnComponentCreated(this);
  512. }
  513. protected virtual void OnMouseEnter()
  514. { if (MouseEnter != null) MouseEnter(this, myGui.mouse.getArgs()); }
  515. protected virtual void OnMouseExit()
  516. { if (MouseExit != null) MouseExit(this, myGui.mouse.getArgs()); }
  517. protected virtual void OnMouseClick()
  518. { if (MouseClick != null) MouseClick(this, myGui.mouse.getArgs()); }
  519. protected virtual void OnMouseClick(MouseEventArgs e)
  520. { if (MouseClick != null) MouseClick(this, e); }
  521. protected virtual void OnMouseDoubleClick()
  522. { if (MouseClick != null) MouseDoubleClick(this, myGui.mouse.getArgs()); }
  523. protected virtual void OnMouseDoubleClick(MouseEventArgs e)
  524. { if (MouseClick != null) MouseDoubleClick(this, e); }
  525. protected virtual void OnMouseUp()
  526. { if (MouseUp != null) MouseUp(this, myGui.mouse.getArgs()); }
  527. protected virtual void OnMouseDown()
  528. { if (MouseDown != null) MouseDown(this, myGui.mouse.getArgs()); }
  529. protected virtual void OnMouseScroll()
  530. { if (MouseScroll != null) MouseScroll(this, myGui.mouse.getArgs()); }
  531. protected virtual void OnTextChanged()
  532. { if (this.TextChanged != null) TextChanged(this); }
  533. protected virtual void OnKeyUp(KeyEventArgs e)
  534. { if (KeyUp != null) KeyUp(this, e); }
  535. protected virtual void OnKeyDown(KeyEventArgs e)
  536. { if (KeyDown != null) KeyDown(this, e); }
  537. protected virtual void OnResize()
  538. { if (Resized != null) Resized(this); }
  539. protected virtual void OnEnter()
  540. { if (Enter != null) Enter(this); }
  541. protected virtual void OnLeave()
  542. { if (Leave != null) Leave(this); }
  543. #endregion
  544. public Component FindComponent(Point p)
  545. {
  546. if (!myVisible) return null;
  547. Children.Sort(Component.DrawDescend);
  548. Component r;
  549. foreach (Component c in Children)
  550. {
  551. r = c.FindComponent(p);
  552. if (r != null)
  553. {
  554. Children.Sort();
  555. return r;
  556. }
  557. }
  558. Children.Sort();
  559. if (myDrawRectangle.Contains(p)) { return this; } else { return null; }
  560. }
  561. public Component FindComponent(string name)
  562. {
  563. if (name == null || name == string.Empty) return null;
  564. int i = name.IndexOf("\\");
  565. string firstPart, secondPart;
  566. if (i == -1)
  567. { firstPart = name; secondPart = ""; }
  568. else
  569. {
  570. firstPart = name.Substring(0, i);
  571. secondPart = name.Substring(i + 1);
  572. }
  573. foreach (Component c in Children)
  574. {
  575. if (firstPart == "..")
  576. {
  577. if (secondPart == "")
  578. { return Parent; }
  579. else
  580. { return Parent.FindComponent(secondPart); }
  581. }
  582. if (c.Name == firstPart)
  583. {
  584. if (secondPart == "")
  585. { return c; }
  586. else
  587. { return c.FindComponent(secondPart); }
  588. }
  589. }
  590. return null;
  591. }
  592. /// <summary>
  593. /// What component this component is a child of. May be null if
  594. /// the component is not a child.
  595. /// </summary>
  596. [ContentSerializerIgnore]
  597. public Component Parent;
  598. /// <summary>
  599. /// The GUI that this object is a part of.
  600. /// </summary>
  601. protected GUI myGui;
  602. /// <summary>
  603. /// Tracks the GUI object that owns the component. The component uses
  604. /// the gui to load its content and draw itself.
  605. /// </summary>
  606. internal GUI gui
  607. {
  608. get { return myGui; }
  609. set
  610. {
  611. myGui = value;
  612. foreach (Component c in Children) { c.gui = value; }
  613. }
  614. }
  615. /// <summary>
  616. /// Used to load any conent need by the component.
  617. /// </summary>
  618. /// <param name="content">A ContentManager that can be used to load needed content.</param>
  619. public virtual void Load(ContentManager content) { }
  620. /// <summary>
  621. /// The screen area where the component will be drawn.
  622. /// </summary>
  623. protected internal Rectangle myDrawRectangle = Rectangle.Empty;
  624. /// <summary>
  625. /// The screen area where the component will be drawn.
  626. /// </summary>
  627. public Rectangle DrawRectangle
  628. { get { return myDrawRectangle; } }
  629. public void CheckChildNames()
  630. {
  631. List<string> names = new List<string>();
  632. foreach (Component c in Children)
  633. {
  634. if (names.Contains(c.Name))
  635. { throw new ApplicationException("'" + this.myName + "' has more than one child named '" + c.Name + "'."); }
  636. names.Add(c.Name);
  637. }
  638. foreach (Component c in Children) { c.CheckChildNames(); }
  639. }
  640. #region IComparable Implementation
  641. /// <summary>
  642. /// Used by IComparable so components can be sorted by draw order.
  643. /// </summary>
  644. /// <param name="other">the other component to compare against.</param>
  645. /// <returns>an indication of their relative draw orders.</returns>
  646. public int CompareTo(Component other)
  647. {
  648. return DrawOrder.CompareTo(other.DrawOrder);
  649. }
  650. public static Comparison<Component> DrawAscend =
  651. delegate(Component c1, Component c2)
  652. { return c1.DrawOrder.CompareTo(c2.DrawOrder); };
  653. public static Comparison<Component> DrawDescend =
  654. delegate(Component c1, Component c2)
  655. { return c2.DrawOrder.CompareTo(c1.DrawOrder); };
  656. public static Comparison<Component> NaturalOrder =
  657. delegate(Component c1, Component c2)
  658. { return c1.naturalOrder.CompareTo(c2.naturalOrder); };
  659. public bool HasFocus()
  660. {
  661. return (this.myGui.HasFocus == this);
  662. }
  663. #endregion
  664. // these memebers are called by the internal mouse and keyboard
  665. // events system. Components can override these to customize
  666. // the response to the event. They can raise an event to the
  667. // client code, react privately, muffle the event, pass
  668. // the event to their parent, or any combination of these.
  669. // The default action of the base component class is to
  670. // pass the event to the parent.
  671. #region DoEvent Members
  672. public virtual void DoKeyDown(KeyEventArgs e)
  673. {
  674. if (this.HasFocus())
  675. {
  676. if (e.Key == Keys.Tab)
  677. { DoTabNext(); }
  678. else if (e.Key == Keys.Tab && gui.keyboard.Shift)
  679. { DoTabPrev(); }
  680. else if (Parent != null)
  681. { Parent.DoKeyDown(e); }
  682. }
  683. }
  684. public virtual void DoKeyUp(KeyEventArgs e)
  685. { if (Parent != null) Parent.DoKeyUp(e); }
  686. public virtual void DoMouseClick(MouseEventArgs e)
  687. { if (Parent != null) Parent.DoMouseClick(e); }
  688. public virtual void DoMouseDoubleClick(MouseEventArgs e)
  689. { if (Parent != null) Parent.DoMouseDoubleClick(e); }
  690. public virtual void DoMouseDown(MouseEventArgs e)
  691. { if (Parent != null) Parent.DoMouseDown(e); }
  692. public virtual void DoMouseUp(MouseEventArgs e)
  693. { if (Parent != null) Parent.DoMouseUp(e); }
  694. public virtual void DoMouseMove(MouseEventArgs e)
  695. { if (Parent != null) Parent.DoMouseMove(e); }
  696. public virtual void DoMouseEnter(MouseEventArgs e)
  697. { if (Parent != null) Parent.DoMouseEnter(e); }
  698. public virtual void DoMouseExit(MouseEventArgs e)
  699. { if (Parent != null) Parent.DoMouseExit(e); }
  700. public virtual void DoMouseScroll(MouseEventArgs e)
  701. { if (Parent != null) Parent.DoMouseScroll(e); }
  702. public virtual void DoEnter()
  703. {
  704. if (this.CanFocus)
  705. { OnEnter(); }
  706. else if (Parent != null)
  707. { Parent.DoEnter(); }
  708. }
  709. public virtual void DoLeave()
  710. { if (this.HasFocus() && this.myCanFocus) OnLeave(); }
  711. public virtual void DoTabNext()
  712. {
  713. Component c = Parent.FindComponent(this.myTabNext);
  714. if (c != null) c.TakeFocus();
  715. }
  716. public virtual void DoTabPrev()
  717. {
  718. Component c = Parent.FindComponent(this.myTabPrev);
  719. if (c != null) c.TakeFocus();
  720. }
  721. public void TakeFocus()
  722. {
  723. this.BringToFront();
  724. myGui.HasFocus = this;
  725. }
  726. #endregion
  727. }
  728. }