diff options
Diffstat (limited to 'ShiftOS.Frontend/GUI')
| -rw-r--r-- | ShiftOS.Frontend/GUI/Button.cs | 50 | ||||
| -rw-r--r-- | ShiftOS.Frontend/GUI/Control.cs | 218 | ||||
| -rw-r--r-- | ShiftOS.Frontend/GUI/ItemGroup.cs | 64 | ||||
| -rw-r--r-- | ShiftOS.Frontend/GUI/PictureBox.cs | 146 | ||||
| -rw-r--r-- | ShiftOS.Frontend/GUI/ProgressBar.cs | 57 | ||||
| -rw-r--r-- | ShiftOS.Frontend/GUI/TextControl.cs | 16 | ||||
| -rw-r--r-- | ShiftOS.Frontend/GUI/TextInput.cs | 46 |
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); + + } + } +} |
