aboutsummaryrefslogtreecommitdiff
path: root/ShiftOS.Frontend/GUI/Control.cs
diff options
context:
space:
mode:
authorMichael <[email protected]>2017-07-02 13:31:39 -0400
committerMichael <[email protected]>2017-07-02 13:31:39 -0400
commitdad09c9e7c1ff68a157836b636f13f25d27e050a (patch)
treec19c3648072a2ee8b04fa26ef2d875e9ba9857ca /ShiftOS.Frontend/GUI/Control.cs
parent345c1446863c3944bb08bfb3dfa25596b94e98db (diff)
downloadshiftos_thereturn-dad09c9e7c1ff68a157836b636f13f25d27e050a.tar.gz
shiftos_thereturn-dad09c9e7c1ff68a157836b636f13f25d27e050a.tar.bz2
shiftos_thereturn-dad09c9e7c1ff68a157836b636f13f25d27e050a.zip
Render text onscreen
Diffstat (limited to 'ShiftOS.Frontend/GUI/Control.cs')
-rw-r--r--ShiftOS.Frontend/GUI/Control.cs271
1 files changed, 271 insertions, 0 deletions
diff --git a/ShiftOS.Frontend/GUI/Control.cs b/ShiftOS.Frontend/GUI/Control.cs
new file mode 100644
index 0000000..975c69a
--- /dev/null
+++ b/ShiftOS.Frontend/GUI/Control.cs
@@ -0,0 +1,271 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.Xna.Framework.Graphics;
+using Microsoft.Xna.Framework.Input;
+
+namespace ShiftOS.Frontend.GUI
+{
+ public abstract class Control
+ {
+ private int _x = 0;
+ private int _y = 0;
+ private int _w = 0;
+ private int _h = 0;
+ private Control _parent = null;
+ private List<Control> _children = new List<Control>();
+ private bool _wasMouseInControl = false;
+ private bool _leftState = false;
+ private bool _rightState = false;
+ private bool _middleState = false;
+ private bool _visible = true;
+
+ public bool Visible
+ {
+ get
+ {
+ return _visible;
+ }
+ set
+ {
+ _visible = value;
+ }
+ }
+
+ public void AddControl(Control ctrl)
+ {
+ if (!_children.Contains(ctrl))
+ {
+ ctrl._parent = this;
+ _children.Add(ctrl);
+ }
+ }
+
+ public bool MouseLeftDown
+ {
+ get
+ {
+ return _leftState;
+ }
+ }
+
+ public bool MouseMiddleDown
+ {
+ get
+ {
+ return _middleState;
+ }
+ }
+
+ public bool MouseRightDown
+ {
+ get
+ {
+ return _rightState;
+ }
+ }
+
+
+
+ public int X
+ {
+ get
+ {
+ return _x;
+ }
+ set
+ {
+ _x = value;
+ }
+ }
+
+ public int Y
+ {
+ get
+ {
+ return _y;
+ }
+ set
+ {
+ _y = value;
+ }
+ }
+
+ public int Width
+ {
+ get
+ {
+ return _w;
+ }
+ set
+ {
+ _w = value;
+ }
+ }
+
+ public int Height
+ {
+ get
+ {
+ return _h;
+ }
+ set
+ {
+ _h = value;
+ }
+ }
+
+ public Control Parent
+ {
+ get
+ {
+ return _parent;
+ }
+ }
+
+ public Control[] Children
+ {
+ get
+ {
+ return _children.ToArray();
+ }
+ }
+
+ public Point PointToParent(int x, int y)
+ {
+ return new Point(x + _x, y + _y);
+ }
+
+ public Point PointToScreen(int x, int y)
+ {
+ var parentCoords = PointToParent(x, y);
+ Control parent = this._parent;
+ while(parent != null)
+ {
+ parentCoords = parent.PointToParent(parentCoords.X, parentCoords.Y);
+ parent = parent.Parent;
+ }
+ return parentCoords;
+ }
+
+ public Point PointToLocal(int x, int y)
+ {
+ return new GUI.Point(x - _x, y - _y);
+ }
+
+ public virtual void MouseStateChanged() { }
+
+ public virtual void Paint(System.Drawing.Graphics gfx)
+ {
+ if (_visible == true)
+ {
+ if (_children.Count > 0)
+ {
+ foreach (var child in _children)
+ {
+ using (var cBmp = new System.Drawing.Bitmap(child.Width, child.Height))
+ {
+ child.Paint(System.Drawing.Graphics.FromImage(cBmp));
+ gfx.DrawImage(cBmp, new System.Drawing.Point(child.X, child.Y));
+ }
+ }
+ }
+ }
+ }
+
+ public virtual bool ProcessMouseState(MouseState state)
+ {
+ //If we aren't rendering the control, we aren't accepting input.
+ if (_visible == false)
+ return false;
+
+
+ //Firstly, we get the mouse coordinates in the local space
+ var coords = PointToLocal(state.Position.X, state.Position.Y);
+ //Now we check if the mouse is within the bounds of the control
+ if(coords.X > 0 && coords.Y > 0 && coords.X <= _w && coords.Y <= _h)
+ {
+ //We're in the local space. Let's fire the MouseMove event.
+ MouseMove?.Invoke(coords);
+ //Also, if the mouse hasn't been in the local space last time it moved, fire MouseEnter.
+ if(_wasMouseInControl == false)
+ {
+ _wasMouseInControl = true;
+ MouseEnter?.Invoke();
+ }
+
+ //Things are going to get a bit complicated.
+ //Firstly, we need to find out if we have any children.
+ bool _requiresMoreWork = true;
+ if(_children.Count > 0)
+ {
+ //We do. We're going to iterate through them all and process the mouse state.
+ foreach(var control in _children)
+ {
+
+ //If the process method returns true, then we do not need to do anything else on our end.
+
+ //We need to first create a new mousestate object with the new coordinates
+
+ var nstate = new MouseState(coords.X, coords.Y, state.ScrollWheelValue, state.LeftButton, state.MiddleButton, state.RightButton, state.XButton1, state.XButton2);
+ //pass that state to the process method, and set the _requiresMoreWork value to the opposite of the return value
+ _requiresMoreWork = !control.ProcessMouseState(nstate);
+ //If it's false, break the loop.
+ if (_requiresMoreWork == false)
+ break;
+ }
+ }
+
+ //If we need to do more work...
+ if(_requiresMoreWork == true)
+ {
+ bool fire = false; //so we know to fire a MouseStateChanged method
+ //Let's get the state values of each button
+ bool ld = state.LeftButton == ButtonState.Pressed;
+ bool md = state.MiddleButton == ButtonState.Pressed;
+ bool rd = state.RightButton == ButtonState.Pressed;
+ if(ld != _leftState || md != _middleState || rd != _rightState)
+ {
+ fire = true;
+ }
+ _leftState = ld;
+ _middleState = md;
+ _rightState = rd;
+ if (fire)
+ MouseStateChanged();
+ }
+ return true;
+ }
+ else
+ {
+ //If the mouse was in local space before, fire MouseLeave
+ if(_wasMouseInControl == true)
+ {
+ _wasMouseInControl = false;
+ MouseLeave?.Invoke();
+ }
+ }
+ //Mouse is not in the local space, don't do anything.
+ return false;
+ }
+
+ public event Action<Point> MouseMove;
+ public event Action MouseEnter;
+ public event Action MouseLeave;
+ }
+
+ public struct Point
+ {
+ public Point(int x, int y)
+ {
+ X = x;
+ Y = y;
+ }
+
+ public int X { get; set; }
+ public int Y { get; set; }
+ }
+
+}