aboutsummaryrefslogtreecommitdiff
path: root/ShiftOS.Frontend/GUI
diff options
context:
space:
mode:
Diffstat (limited to 'ShiftOS.Frontend/GUI')
-rw-r--r--ShiftOS.Frontend/GUI/Button.cs50
-rw-r--r--ShiftOS.Frontend/GUI/Control.cs218
-rw-r--r--ShiftOS.Frontend/GUI/ItemGroup.cs64
-rw-r--r--ShiftOS.Frontend/GUI/PictureBox.cs146
-rw-r--r--ShiftOS.Frontend/GUI/ProgressBar.cs57
-rw-r--r--ShiftOS.Frontend/GUI/TextControl.cs16
-rw-r--r--ShiftOS.Frontend/GUI/TextInput.cs46
7 files changed, 597 insertions, 0 deletions
diff --git a/ShiftOS.Frontend/GUI/Button.cs b/ShiftOS.Frontend/GUI/Button.cs
new file mode 100644
index 0000000..c2e41a3
--- /dev/null
+++ b/ShiftOS.Frontend/GUI/Button.cs
@@ -0,0 +1,50 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using ShiftOS.Engine;
+
+namespace ShiftOS.Frontend.GUI
+{
+ public class Button : TextControl
+ {
+ public Button()
+ {
+ TextAlign = TextAlign.MiddleCenter;
+ Text = "Click me!";
+ }
+
+ protected override void OnLayout()
+ {
+ if(AutoSize == true)
+ {
+ int borderwidth = SkinEngine.LoadedSkin.ButtonBorderWidth * 2;
+
+ using (var gfx = Graphics.FromImage(new Bitmap(1, 1)))
+ {
+ var measure = gfx.MeasureString(this.Text, this.Font);
+ Width = borderwidth + (int)measure.Width + 4;
+ Height = borderwidth + (int)measure.Height + 8;
+ }
+ }
+ base.OnLayout();
+ }
+
+ public override void Paint(Graphics gfx)
+ {
+ Color bgCol = SkinEngine.LoadedSkin.ButtonBackgroundColor;
+ Color fgCol = SkinEngine.LoadedSkin.ControlTextColor;
+ if (ContainsMouse)
+ bgCol = SkinEngine.LoadedSkin.ButtonHoverColor;
+ if (MouseLeftDown)
+ bgCol = SkinEngine.LoadedSkin.ButtonPressedColor;
+
+ gfx.Clear(bgCol);
+ gfx.DrawRectangle(new Pen(new SolidBrush(fgCol), SkinEngine.LoadedSkin.ButtonBorderWidth), new Rectangle(0, 0, Width, Height));
+ base.Paint(gfx);
+
+ }
+ }
+}
diff --git a/ShiftOS.Frontend/GUI/Control.cs b/ShiftOS.Frontend/GUI/Control.cs
index 975c69a..fcbd429 100644
--- a/ShiftOS.Frontend/GUI/Control.cs
+++ b/ShiftOS.Frontend/GUI/Control.cs
@@ -5,6 +5,11 @@ using System.Text;
using System.Threading.Tasks;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
+using System.Drawing;
+using ShiftOS.Frontend.GraphicsSubsystem;
+using System.Drawing.Imaging;
+using System.Drawing.Drawing2D;
+using Microsoft.Xna.Framework;
namespace ShiftOS.Frontend.GUI
{
@@ -21,6 +26,77 @@ namespace ShiftOS.Frontend.GUI
private bool _rightState = false;
private bool _middleState = false;
private bool _visible = true;
+ private DockStyle _dock = DockStyle.None;
+ private bool _focused = false;
+ private bool _autoSize = false;
+ private double _opacity = 1.0;
+
+ public double Opacity
+ {
+ get
+ {
+ return _opacity;
+ }
+ set
+ {
+ _opacity = (double)MathHelper.Clamp((float)value, 0, 1);
+ }
+ }
+
+ public bool AutoSize
+ {
+ get
+ {
+ return _autoSize;
+ }
+ set
+ {
+ _autoSize = value;
+ }
+ }
+
+ //Thank you, StackOverflow.
+ public static Bitmap ResizeImage(Image image, int width, int height)
+ {
+ var destRect = new System.Drawing.Rectangle(0, 0, width, height);
+ var destImage = new Bitmap(width, height);
+
+ destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);
+
+ using (var graphics = Graphics.FromImage(destImage))
+ {
+ graphics.CompositingMode = CompositingMode.SourceCopy;
+ graphics.CompositingQuality = CompositingQuality.HighQuality;
+ graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
+ graphics.SmoothingMode = SmoothingMode.HighQuality;
+ graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
+
+ using (var wrapMode = new ImageAttributes())
+ {
+ wrapMode.SetWrapMode(WrapMode.TileFlipXY);
+ graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode);
+ }
+ }
+
+ return destImage;
+ }
+
+ public DockStyle Dock
+ {
+ get
+ {
+ return _dock;
+ }
+ set
+ {
+ _dock = value;
+ }
+ }
+
+ public bool ContainsMouse
+ {
+ get { return _wasMouseInControl; }
+ }
public bool Visible
{
@@ -150,6 +226,11 @@ namespace ShiftOS.Frontend.GUI
return parentCoords;
}
+ public void ClearControls()
+ {
+ _children.Clear();
+ }
+
public Point PointToLocal(int x, int y)
{
return new GUI.Point(x - _x, y - _y);
@@ -168,13 +249,90 @@ namespace ShiftOS.Frontend.GUI
using (var cBmp = new System.Drawing.Bitmap(child.Width, child.Height))
{
child.Paint(System.Drawing.Graphics.FromImage(cBmp));
+ cBmp.SetOpacity((float)child.Opacity);
gfx.DrawImage(cBmp, new System.Drawing.Point(child.X, child.Y));
+
}
}
}
}
}
+ public void Layout()
+ {
+ //Dock style
+ if(_parent != null)
+ {
+ switch (_dock)
+ {
+ case DockStyle.Top:
+ X = 0;
+ Y = 0;
+ Width = _parent.Width;
+ break;
+ case DockStyle.Left:
+ X = 0;
+ Y = 0;
+ Height = _parent.Height;
+ break;
+ case DockStyle.Right:
+ Y = 0;
+ X = _parent.Width - Width;
+ Height = _parent.Height;
+ break;
+ case DockStyle.Bottom:
+ X = 0;
+ Y = _parent.Height - Height;
+ Width = _parent.Width;
+ break;
+ case DockStyle.Fill:
+ X = 0;
+ Y = 0;
+ Width = _parent.Width;
+ Height = _parent.Height;
+ break;
+ }
+ }
+ OnLayout();
+ foreach (var child in _children)
+ child.Layout();
+ }
+
+ protected virtual void OnLayout()
+ {
+ //do nothing
+ }
+
+ public bool IsFocusedControl
+ {
+ get
+ {
+ return UIManager.FocusedControl == this;
+ }
+ }
+
+ public bool ContainsFocusedControl
+ {
+ get
+ {
+ if (UIManager.FocusedControl == null)
+ return false;
+ else
+ {
+ bool contains = false;
+
+ var ctrl = UIManager.FocusedControl;
+ while(ctrl.Parent != null)
+ {
+ ctrl = ctrl.Parent;
+ if (ctrl == this)
+ contains = true;
+ }
+ return contains;
+ }
+ }
+ }
+
public virtual bool ProcessMouseState(MouseState state)
{
//If we aren't rendering the control, we aren't accepting input.
@@ -230,6 +388,10 @@ namespace ShiftOS.Frontend.GUI
{
fire = true;
}
+ if (_leftState == true && ld == false)
+ Click?.Invoke();
+ if (_leftState == false && ld == true)
+ UIManager.FocusedControl = this;
_leftState = ld;
_middleState = md;
_rightState = rd;
@@ -240,6 +402,10 @@ namespace ShiftOS.Frontend.GUI
}
else
{
+ _leftState = false;
+ _rightState = false;
+ _middleState = false;
+ MouseStateChanged();
//If the mouse was in local space before, fire MouseLeave
if(_wasMouseInControl == true)
{
@@ -251,9 +417,22 @@ namespace ShiftOS.Frontend.GUI
return false;
}
+ protected virtual void OnKeyEvent(KeyEvent e)
+ {
+
+ }
+
+ public void ProcessKeyEvent(KeyEvent e)
+ {
+ OnKeyEvent(e);
+ KeyEvent?.Invoke(e);
+ }
+
public event Action<Point> MouseMove;
public event Action MouseEnter;
public event Action MouseLeave;
+ public event Action Click;
+ public event Action<KeyEvent> KeyEvent;
}
public struct Point
@@ -268,4 +447,43 @@ namespace ShiftOS.Frontend.GUI
public int Y { get; set; }
}
+ public enum DockStyle
+ {
+ None,
+ Top,
+ Bottom,
+ Left,
+ Right,
+ Fill
+ }
+
+ //Thanks, StackOverflow.
+ public static class BitmapExtensions
+ {
+ public static Image SetOpacity(this Image image, float opacity)
+ {
+ var colorMatrix = new ColorMatrix();
+ colorMatrix.Matrix33 = opacity;
+ var imageAttributes = new ImageAttributes();
+ imageAttributes.SetColorMatrix(
+ colorMatrix,
+ ColorMatrixFlag.Default,
+ ColorAdjustType.Bitmap);
+ var output = new Bitmap(image.Width, image.Height);
+ using (var gfx = Graphics.FromImage(output))
+ {
+ gfx.SmoothingMode = SmoothingMode.AntiAlias;
+ gfx.DrawImage(
+ image,
+ new System.Drawing.Rectangle(0, 0, image.Width, image.Height),
+ 0,
+ 0,
+ image.Width,
+ image.Height,
+ GraphicsUnit.Pixel,
+ imageAttributes);
+ }
+ return output;
+ }
+ }
}
diff --git a/ShiftOS.Frontend/GUI/ItemGroup.cs b/ShiftOS.Frontend/GUI/ItemGroup.cs
new file mode 100644
index 0000000..e52a17f
--- /dev/null
+++ b/ShiftOS.Frontend/GUI/ItemGroup.cs
@@ -0,0 +1,64 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ShiftOS.Frontend.GUI
+{
+ public class ItemGroup : Control
+ {
+ private int _gap = 3;
+ private FlowDirection _flowDir = FlowDirection.LeftToRight;
+ private int _initialgap = 2;
+
+ protected override void OnLayout()
+ {
+ if (AutoSize)
+ {
+ int _highesty = _initialgap;
+ int _xx = _initialgap;
+ foreach(var ctrl in Children)
+ {
+ _xx += ctrl.Width + _gap;
+ if (_highesty < ctrl.Height + _initialgap + _gap)
+ _highesty = ctrl.Height + _initialgap + _gap;
+ }
+ Width = _xx;
+ Height = _highesty;
+ }
+
+ int _x = _initialgap;
+ int _y = _initialgap;
+ int _maxYForRow = 0;
+ foreach (var ctrl in Children)
+ {
+ if (_x + ctrl.Width + _gap > Width)
+ {
+ _x = _initialgap;
+ _y = _maxYForRow;
+ _maxYForRow = 0;
+ if (_maxYForRow < ctrl.Height + _gap)
+ _maxYForRow = ctrl.Height + _gap;
+ }
+ ctrl.X = _x;
+ ctrl.Y = _y;
+ ctrl.Dock = DockStyle.None;
+ ctrl.Layout();
+ _x += ctrl.Width + _gap;
+
+ if (_maxYForRow < ctrl.Height + _gap)
+ _maxYForRow = ctrl.Height + _gap;
+
+ }
+ }
+ }
+
+ public enum FlowDirection
+ {
+ LeftToRight,
+ TopDown,
+ RightToLeft,
+ BottomUp
+ }
+}
diff --git a/ShiftOS.Frontend/GUI/PictureBox.cs b/ShiftOS.Frontend/GUI/PictureBox.cs
new file mode 100644
index 0000000..2447416
--- /dev/null
+++ b/ShiftOS.Frontend/GUI/PictureBox.cs
@@ -0,0 +1,146 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using ShiftOS.Engine;
+using System.Drawing.Imaging;
+
+namespace ShiftOS.Frontend.GUI
+{
+ public class PictureBox : Control
+ {
+ private System.Drawing.Image img = null;
+ private ImageLayout _layout = ImageLayout.Fit;
+
+ public ImageLayout ImageLayout
+ {
+ get
+ {
+ return _layout;
+ }
+ set
+ {
+ _layout = value;
+ }
+ }
+
+ public System.Drawing.Image Image
+ {
+ get
+ {
+ return img;
+ }
+ set
+ {
+ if (img != null)
+ img.Dispose();
+ img = value;
+ }
+ }
+
+ protected override void OnLayout()
+ {
+ if (AutoSize)
+ {
+ Width = (img == null) ? 0 : img.Width;
+ Height = (img == null) ? 0 : img.Height;
+ }
+ }
+
+ public override void Paint(Graphics gfx)
+ {
+ if(img != null)
+ switch (_layout)
+ {
+ case ImageLayout.None:
+ //Just draw the image.
+ gfx.DrawImage(img, new PointF(0, 0));
+ break;
+ case ImageLayout.Stretch:
+ //Stretch the image, with no regard for aspect ratio.
+ var stretched = ResizeImage(img, Width, Height);
+ gfx.DrawImage(stretched, 0, 0);
+ break;
+ case ImageLayout.Fit:
+ //Resize image to fit the control but keep aspect ratio.
+ var fitted = FixedSize(img, Width, Height);
+ gfx.DrawImage(fitted, 0, 0);
+ break;
+ case ImageLayout.Tile:
+ //Keep original size but tile the image.
+
+ for(int x = 0; x < Width; x += img.Width)
+ {
+ for (int y = 0; y < Height; y += img.Height)
+ {
+ gfx.DrawImage(img, x, y);
+ }
+ }
+
+ break;
+ }
+ }
+
+ //Again, thanks StackOverflow
+ static Image FixedSize(Image imgPhoto, int Width, int Height)
+ {
+ int sourceWidth = imgPhoto.Width;
+ int sourceHeight = imgPhoto.Height;
+ int sourceX = 0;
+ int sourceY = 0;
+ int destX = 0;
+ int destY = 0;
+
+ float nPercent = 0;
+ float nPercentW = 0;
+ float nPercentH = 0;
+
+ nPercentW = ((float)Width / (float)sourceWidth);
+ nPercentH = ((float)Height / (float)sourceHeight);
+ if (nPercentH < nPercentW)
+ {
+ nPercent = nPercentH;
+ destX = System.Convert.ToInt16((Width -
+ (sourceWidth * nPercent)) / 2);
+ }
+ else
+ {
+ nPercent = nPercentW;
+ destY = System.Convert.ToInt16((Height -
+ (sourceHeight * nPercent)) / 2);
+ }
+
+ int destWidth = (int)(sourceWidth * nPercent);
+ int destHeight = (int)(sourceHeight * nPercent);
+
+ Bitmap bmPhoto = new Bitmap(Width, Height,
+ PixelFormat.Format24bppRgb);
+ bmPhoto.SetResolution(imgPhoto.HorizontalResolution,
+ imgPhoto.VerticalResolution);
+
+ Graphics grPhoto = Graphics.FromImage(bmPhoto);
+ grPhoto.Clear(SkinEngine.LoadedSkin.ControlColor);
+ grPhoto.InterpolationMode =
+ InterpolationMode.HighQualityBicubic;
+
+ grPhoto.DrawImage(imgPhoto,
+ new Rectangle(destX, destY, destWidth, destHeight),
+ new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight),
+ GraphicsUnit.Pixel);
+
+ grPhoto.Dispose();
+ return bmPhoto;
+ }
+ }
+
+ public enum ImageLayout
+ {
+ None,
+ Stretch,
+ Tile,
+ Fit,
+ }
+}
diff --git a/ShiftOS.Frontend/GUI/ProgressBar.cs b/ShiftOS.Frontend/GUI/ProgressBar.cs
new file mode 100644
index 0000000..f0dd626
--- /dev/null
+++ b/ShiftOS.Frontend/GUI/ProgressBar.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using static ShiftOS.Engine.SkinEngine;
+
+namespace ShiftOS.Frontend.GUI
+{
+ public class ProgressBar : Control
+ {
+ private int _maximum = 100;
+ private int _value = 0;
+
+ public int Maximum
+ {
+ get
+ {
+ return _maximum;
+ }
+ set
+ {
+ _maximum = value;
+ }
+ }
+
+ public int Value
+ {
+ get
+ {
+ return _value;
+ }
+ set
+ {
+ _value = value;
+ }
+ }
+
+ public override void Paint(Graphics gfx)
+ {
+ gfx.Clear(LoadedSkin.ProgressBarBackgroundColor);
+ int w = (int)linear(_value, 0, _maximum, 0, Width);
+ gfx.FillRectangle(new SolidBrush(LoadedSkin.ProgressColor), new Rectangle(0, 0, w, Height));
+ }
+
+ static public double linear(double x, double x0, double x1, double y0, double y1)
+ {
+ if ((x1 - x0) == 0)
+ {
+ return (y0 + y1) / 2;
+ }
+ return y0 + (x - x0) * (y1 - y0) / (x1 - x0);
+ }
+
+ }
+}
diff --git a/ShiftOS.Frontend/GUI/TextControl.cs b/ShiftOS.Frontend/GUI/TextControl.cs
index c8eb56b..79da213 100644
--- a/ShiftOS.Frontend/GUI/TextControl.cs
+++ b/ShiftOS.Frontend/GUI/TextControl.cs
@@ -13,6 +13,22 @@ namespace ShiftOS.Frontend.GUI
private TextAlign _textAlign = TextAlign.TopLeft;
private Font _font = new Font("Tahoma", 9f);
+ protected override void OnLayout()
+ {
+ if (AutoSize)
+ {
+ using (var bmp = new Bitmap(1, 1))
+ {
+ using(var gfx = Graphics.FromImage(bmp))
+ {
+ var measure = gfx.MeasureString(_text, _font);
+ Width = (int)measure.Width;
+ Height = (int)measure.Height;
+ }
+ }
+ }
+ }
+
public string Text
{
get { return _text; }
diff --git a/ShiftOS.Frontend/GUI/TextInput.cs b/ShiftOS.Frontend/GUI/TextInput.cs
new file mode 100644
index 0000000..fc142a0
--- /dev/null
+++ b/ShiftOS.Frontend/GUI/TextInput.cs
@@ -0,0 +1,46 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using ShiftOS.Frontend.GraphicsSubsystem;
+using static ShiftOS.Engine.SkinEngine;
+
+namespace ShiftOS.Frontend.GUI
+{
+ public class TextInput : Control
+ {
+ private string _label = "Type here!";
+ private string _text = "";
+ private int _index = 0;
+
+ protected override void OnKeyEvent(KeyEvent e)
+ {
+ if(e.Key == Microsoft.Xna.Framework.Input.Keys.Left)
+ {
+ if (_index > 0)
+ _index--;
+ }
+ if (e.Key == Microsoft.Xna.Framework.Input.Keys.Right)
+ if (_index < _text.Length)
+ _index++;
+ if (e.KeyChar != '\0')
+ _text.Insert(_index, e.KeyChar.ToString());
+ base.OnKeyEvent(e);
+ }
+
+ protected override void OnLayout()
+ {
+ base.OnLayout();
+ }
+
+ private int _textOffset = 0;
+
+ public override void Paint(Graphics gfx)
+ {
+ gfx.Clear(LoadedSkin.ControlColor);
+
+ }
+ }
+}