diff --git a/ShiftOS.Frontend/Desktop/WindowManager.cs b/ShiftOS.Frontend/Desktop/WindowManager.cs index 2450986..1bceb93 100644 --- a/ShiftOS.Frontend/Desktop/WindowManager.cs +++ b/ShiftOS.Frontend/Desktop/WindowManager.cs @@ -87,6 +87,12 @@ namespace ShiftOS.Frontend.Desktop private string _text = "ShiftOS window"; private GUI.Control _hostedwindow = null; + public WindowBorder() + { + X = 720; + Y = 480; + } + public IShiftOSWindow ParentWindow { get @@ -99,6 +105,9 @@ namespace ShiftOS.Frontend.Desktop _hostedwindow = (GUI.Control)value; ClearControls(); AddControl(_hostedwindow); + Width = (LoadedSkin.LeftBorderWidth*2) + _hostedwindow.Width + LoadedSkin.RightBorderWidth; + Height = LoadedSkin.BottomBorderWidth + _hostedwindow.Height + (LoadedSkin.TitlebarHeight*2); + } } @@ -123,14 +132,50 @@ namespace ShiftOS.Frontend.Desktop UIManager.StopHandling(this); } - public override void Paint(Graphics gfx) + private int lastmousex, lastmousey = 0; + + protected override void OnLayout() + { + if (moving) + { + var screenpoint = PointToScreen(MouseX, MouseY); + this.X = lastmousex + screenpoint.X; + this.Y = lastmousey + screenpoint.Y; + } + int titlebarheight = Shiftorium.UpgradeInstalled("wm_titlebar") ? LoadedSkin.TitlebarHeight : 0; + int borderleft = Shiftorium.UpgradeInstalled("window_borders") ? LoadedSkin.LeftBorderWidth : 0; + int borderright = Shiftorium.UpgradeInstalled("window_borders") ? LoadedSkin.RightBorderWidth : 0; + int borderbottom = Shiftorium.UpgradeInstalled("window_borders") ? LoadedSkin.BottomBorderWidth : 0; + _hostedwindow.X = borderleft; + _hostedwindow.Y = titlebarheight; + } + + private bool moving = false; + + public override void MouseStateChanged() + { + if (Shiftorium.UpgradeInstalled("wm_titlebar")) + { + if(MouseY < LoadedSkin.TitlebarHeight) + { + var screenpoint = PointToScreen(MouseX, MouseY); + lastmousex = this.X - screenpoint.X; + lastmousey = this.Y - screenpoint.Y; + + moving = MouseLeftDown; + CaptureMouse = moving; + } + } + } + + protected override void OnPaint(Graphics gfx) { int titleheight = LoadedSkin.TitlebarHeight; int leftborderwidth = LoadedSkin.LeftBorderWidth; int rightborderwidth = LoadedSkin.RightBorderWidth; int bottomborderwidth = LoadedSkin.BottomBorderWidth; - if (Shiftorium.UpgradeInstalled("wm_titlebar") || true) + if (Shiftorium.UpgradeInstalled("wm_titlebar")) { var titlebarcolor = LoadedSkin.TitleBackgroundColor; var titlefont = LoadedSkin.TitleFont; @@ -138,7 +183,7 @@ namespace ShiftOS.Frontend.Desktop var titletextleft = LoadedSkin.TitleTextLeft; bool titletextcentered = LoadedSkin.TitleTextCentered; - var titlebarbg = GetImage("titlebar"); + var titlebarbg = GetImage("titlebar"); var titlebarlayout = GetImageLayout("titlebar"); var drawcorners = LoadedSkin.ShowTitleCorners; @@ -213,15 +258,41 @@ namespace ShiftOS.Frontend.Desktop var tbuttonpos = LoadedSkin.TitleButtonPosition; //Draw close button - if(Shiftorium.UpgradeInstalled("close_button") || true) + if(Shiftorium.UpgradeInstalled("close_button")) { var closebuttoncolor = LoadedSkin.CloseButtonColor; var closebuttonsize = LoadedSkin.CloseButtonSize; var closebuttonright = LoadedSkin.CloseButtonFromSide; + if (LoadedSkin.TitleButtonPosition == 0) + closebuttonright = new Point(Width - closebuttonsize.Width - closebuttonright.X, closebuttonright.Y); gfx.FillRectangle(new SolidBrush(closebuttoncolor), new Rectangle(closebuttonright, closebuttonsize)); } + //Draw maximize button + if (Shiftorium.UpgradeInstalled("maximize_button")) + { + var closebuttoncolor = LoadedSkin.MaximizeButtonColor; + var closebuttonsize = LoadedSkin.MaximizeButtonSize; + var closebuttonright = LoadedSkin.MaximizeButtonFromSide; + if (LoadedSkin.TitleButtonPosition == 0) + closebuttonright = new Point(Width - closebuttonsize.Width - closebuttonright.X, closebuttonright.Y); + + gfx.FillRectangle(new SolidBrush(closebuttoncolor), new Rectangle(closebuttonright, closebuttonsize)); + + } + //Draw minimize button + if (Shiftorium.UpgradeInstalled("minimize_button")) + { + var closebuttoncolor = LoadedSkin.MinimizeButtonColor; + var closebuttonsize = LoadedSkin.MinimizeButtonSize; + var closebuttonright = LoadedSkin.MinimizeButtonFromSide; + if (LoadedSkin.TitleButtonPosition == 0) + closebuttonright = new Point(Width - closebuttonsize.Width - closebuttonright.X, closebuttonright.Y); + + gfx.FillRectangle(new SolidBrush(closebuttoncolor), new Rectangle(closebuttonright, closebuttonsize)); + + } } else { @@ -230,30 +301,47 @@ namespace ShiftOS.Frontend.Desktop } + if (Shiftorium.UpgradeInstalled("window_borders")) + { + //Some variables we'll need... + int bottomlocy = Height - LoadedSkin.BottomBorderWidth; + int bottomlocx = leftborderwidth; + int bottomwidth = Width - bottomlocx - rightborderwidth; + int brightlocx = Width - rightborderwidth; + + var borderleftcolor = (ContainsFocusedControl || IsFocusedControl) ? LoadedSkin.BorderLeftBackground : LoadedSkin.BorderInactiveLeftBackground; + var borderrightcolor = (ContainsFocusedControl || IsFocusedControl) ? LoadedSkin.BorderRightBackground : LoadedSkin.BorderInactiveRightBackground; + var borderbottomcolor = (ContainsFocusedControl || IsFocusedControl) ? LoadedSkin.BorderBottomBackground : LoadedSkin.BorderInactiveBottomBackground; + var borderbleftcolor = (ContainsFocusedControl || IsFocusedControl) ? LoadedSkin.BorderBottomLeftBackground : LoadedSkin.BorderInactiveBottomLeftBackground; + var borderbrightcolor = (ContainsFocusedControl || IsFocusedControl) ? LoadedSkin.BorderBottomRightBackground : LoadedSkin.BorderInactiveBottomRightBackground; + + + //draw border corners + //BOTTOM LEFT + gfx.FillRectangle(new SolidBrush(borderbleftcolor), new Rectangle(0, bottomlocy, leftborderwidth, bottomborderwidth)); + + + //BOTTOM RIGHT + gfx.FillRectangle(new SolidBrush(borderbrightcolor), new Rectangle(brightlocx, bottomlocy, rightborderwidth, bottomborderwidth)); + + //BOTTOM + gfx.FillRectangle(new SolidBrush(borderbottomcolor), new Rectangle(bottomlocx, bottomlocy, bottomwidth, bottomborderwidth)); + + //LEFT + gfx.FillRectangle(new SolidBrush(borderleftcolor), new Rectangle(0, titleheight, leftborderwidth, Height - titleheight - bottomborderwidth)); + + //RIGHT + gfx.FillRectangle(new SolidBrush(borderrightcolor), new Rectangle(brightlocx, titleheight, rightborderwidth, Height - titleheight - bottomborderwidth)); + + + } + //So here's what we're gonna do now. //Now that we have a titlebar and window borders... //We're going to composite the hosted window //and draw it to the remaining area. - //First let's GET the window. - if(_hostedwindow != null) - { - var win = _hostedwindow; - //Now let's create a new bitmap to draw onto, the same size as the client area. - using(var bmp = new Bitmap(Width, Height - titleheight)) - { - //Now, let's create a graphics object. - using(var cgfx = Graphics.FromImage(bmp)) - { - //And composite... - win.Paint(cgfx); - - } - //Now draw the bitmap to our client area - gfx.DrawImage(bmp, 0, titleheight); - //We now have a full window. - } - } + //Painting of the canvas is done by the Paint() method. } } diff --git a/ShiftOS.Frontend/GUI/Button.cs b/ShiftOS.Frontend/GUI/Button.cs index c2e41a3..551d0d4 100644 --- a/ShiftOS.Frontend/GUI/Button.cs +++ b/ShiftOS.Frontend/GUI/Button.cs @@ -25,14 +25,13 @@ namespace ShiftOS.Frontend.GUI 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; + Width = borderwidth + (int)measure.Width + 16; + Height = borderwidth + (int)measure.Height + 12; } } - base.OnLayout(); } - public override void Paint(Graphics gfx) + protected override void OnPaint(Graphics gfx) { Color bgCol = SkinEngine.LoadedSkin.ButtonBackgroundColor; Color fgCol = SkinEngine.LoadedSkin.ControlTextColor; @@ -43,7 +42,7 @@ namespace ShiftOS.Frontend.GUI gfx.Clear(bgCol); gfx.DrawRectangle(new Pen(new SolidBrush(fgCol), SkinEngine.LoadedSkin.ButtonBorderWidth), new Rectangle(0, 0, Width, Height)); - base.Paint(gfx); + base.OnPaint(gfx); } } diff --git a/ShiftOS.Frontend/GUI/Control.cs b/ShiftOS.Frontend/GUI/Control.cs index fcbd429..90e7ba5 100644 --- a/ShiftOS.Frontend/GUI/Control.cs +++ b/ShiftOS.Frontend/GUI/Control.cs @@ -30,6 +30,63 @@ namespace ShiftOS.Frontend.GUI private bool _focused = false; private bool _autoSize = false; private double _opacity = 1.0; + private bool _invalidated = true; + private Bitmap _texCache = null; + private Anchor _anchor = null; + private int _mouseX = 0; + private int _mouseY = 0; + private bool _captureMouse = false; + + public bool CaptureMouse + { + get + { + return _captureMouse; + } + set + { + _captureMouse = value; + } + } + + public int MouseX + { + get + { + return _mouseX; + } + } + + public int MouseY + { + get + { + return _mouseY; + } + } + + + public Anchor Anchor + { + get + { + return _anchor; + } + set + { + _anchor = value; + Invalidate(); + } + } + + public void Invalidate() + { + _invalidated = true; + foreach(var child in _children) + { + child.Invalidate(); + } + } public double Opacity { @@ -39,7 +96,8 @@ namespace ShiftOS.Frontend.GUI } set { - _opacity = (double)MathHelper.Clamp((float)value, 0, 1); + _opacity = value; + Invalidate(); } } @@ -107,6 +165,7 @@ namespace ShiftOS.Frontend.GUI set { _visible = value; + Invalidate(); } } @@ -116,6 +175,7 @@ namespace ShiftOS.Frontend.GUI { ctrl._parent = this; _children.Add(ctrl); + Invalidate(); } } @@ -154,6 +214,7 @@ namespace ShiftOS.Frontend.GUI set { _x = value; + Invalidate(); } } @@ -166,6 +227,7 @@ namespace ShiftOS.Frontend.GUI set { _y = value; + Invalidate(); } } @@ -178,6 +240,7 @@ namespace ShiftOS.Frontend.GUI set { _w = value; + Invalidate(); } } @@ -190,6 +253,7 @@ namespace ShiftOS.Frontend.GUI set { _h = value; + Invalidate(); } } @@ -229,6 +293,7 @@ namespace ShiftOS.Frontend.GUI public void ClearControls() { _children.Clear(); + Invalidate(); } public Point PointToLocal(int x, int y) @@ -238,23 +303,56 @@ namespace ShiftOS.Frontend.GUI public virtual void MouseStateChanged() { } - public virtual void Paint(System.Drawing.Graphics gfx) + protected virtual void OnPaint(Graphics gfx) + { + + } + + public void InvalidateTopLevel() + { + var parent = this; + while (parent.Parent != null) + parent = parent.Parent; + parent.Invalidate(); + } + + public void Paint(System.Drawing.Graphics gfx) { if (_visible == true) { - if (_children.Count > 0) + if (_invalidated) { - foreach (var child in _children) + _texCache = new Bitmap(Width, Height); + using (var cGfx = Graphics.FromImage(_texCache)) { - using (var cBmp = new System.Drawing.Bitmap(child.Width, child.Height)) + OnPaint(cGfx); + } + _invalidated = false; + } + gfx.DrawImage(_texCache, 0, 0); + foreach (var child in _children) + { + if (child.Visible) + { + if (child._invalidated) { + var cBmp = new Bitmap(child.Width, child.Height); child.Paint(System.Drawing.Graphics.FromImage(cBmp)); cBmp.SetOpacity((float)child.Opacity); + child._invalidated = false; + child._texCache = cBmp; gfx.DrawImage(cBmp, new System.Drawing.Point(child.X, child.Y)); + + + } + else + { + gfx.DrawImage(child._texCache, child.X, child.Y); } } } + } } @@ -263,6 +361,11 @@ namespace ShiftOS.Frontend.GUI //Dock style if(_parent != null) { + if(_anchor != null) + { + + } + switch (_dock) { case DockStyle.Top: @@ -342,8 +445,10 @@ namespace ShiftOS.Frontend.GUI //Firstly, we get the mouse coordinates in the local space var coords = PointToLocal(state.Position.X, state.Position.Y); + _mouseX = coords.X; + _mouseY = coords.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) + 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); @@ -352,6 +457,7 @@ namespace ShiftOS.Frontend.GUI { _wasMouseInControl = true; MouseEnter?.Invoke(); + Invalidate(); } //Things are going to get a bit complicated. @@ -389,9 +495,17 @@ namespace ShiftOS.Frontend.GUI fire = true; } if (_leftState == true && ld == false) + { Click?.Invoke(); + Invalidate(); + } if (_leftState == false && ld == true) + { + var focused = UIManager.FocusedControl; UIManager.FocusedControl = this; + focused?.InvalidateTopLevel(); + InvalidateTopLevel(); + } _leftState = ld; _middleState = md; _rightState = rd; @@ -407,12 +521,36 @@ namespace ShiftOS.Frontend.GUI _middleState = false; MouseStateChanged(); //If the mouse was in local space before, fire MouseLeave - if(_wasMouseInControl == true) + if (_wasMouseInControl == true) { - _wasMouseInControl = false; - MouseLeave?.Invoke(); + if (CaptureMouse == true) + { + _wasMouseInControl = true; + int newX = MathHelper.Clamp(state.X, X, X + Width); + int newY = MathHelper.Clamp(state.Y, Y, Y + Height); + Mouse.SetPosition(newX, newY); + + } + else + { + _wasMouseInControl = false; + MouseLeave?.Invoke(); + Invalidate(); + } } } + if (CaptureMouse == true) + { + _mouseX = coords.X; + _mouseY = coords.Y; + Layout(); + _wasMouseInControl = true; + int newX = MathHelper.Clamp(state.X, X, X + Width); + int newY = MathHelper.Clamp(state.Y, Y, Y + Height); + Mouse.SetPosition(newX, newY); + return true; + } + //Mouse is not in the local space, don't do anything. return false; } @@ -486,4 +624,19 @@ namespace ShiftOS.Frontend.GUI return output; } } + + [Flags] + public enum AnchorStyle + { + Top, + Left, + Bottom, + Right + } + + public class Anchor + { + public AnchorStyle Style { get; set; } + public int Distance { get; set; } + } } diff --git a/ShiftOS.Frontend/GUI/PictureBox.cs b/ShiftOS.Frontend/GUI/PictureBox.cs index 2447416..9a234d4 100644 --- a/ShiftOS.Frontend/GUI/PictureBox.cs +++ b/ShiftOS.Frontend/GUI/PictureBox.cs @@ -50,7 +50,7 @@ namespace ShiftOS.Frontend.GUI } } - public override void Paint(Graphics gfx) + protected override void OnPaint(Graphics gfx) { if(img != null) switch (_layout) diff --git a/ShiftOS.Frontend/GUI/ProgressBar.cs b/ShiftOS.Frontend/GUI/ProgressBar.cs index f0dd626..e35dc27 100644 --- a/ShiftOS.Frontend/GUI/ProgressBar.cs +++ b/ShiftOS.Frontend/GUI/ProgressBar.cs @@ -37,7 +37,7 @@ namespace ShiftOS.Frontend.GUI } } - public override void Paint(Graphics gfx) + protected override void OnPaint(Graphics gfx) { gfx.Clear(LoadedSkin.ProgressBarBackgroundColor); int w = (int)linear(_value, 0, _maximum, 0, Width); diff --git a/ShiftOS.Frontend/GUI/TextControl.cs b/ShiftOS.Frontend/GUI/TextControl.cs index 79da213..37b9ca7 100644 --- a/ShiftOS.Frontend/GUI/TextControl.cs +++ b/ShiftOS.Frontend/GUI/TextControl.cs @@ -53,9 +53,9 @@ namespace ShiftOS.Frontend.GUI set { _textAlign = value; } } - public override void Paint(Graphics gfx) + protected override void OnPaint(Graphics gfx) { - var sMeasure = gfx.MeasureString(_text, _font); + var sMeasure = gfx.MeasureString(_text, _font, Width); PointF loc = new PointF(2, 2); float centerH = (Width - sMeasure.Width) / 2; float centerV = (Height - sMeasure.Height) / 2; diff --git a/ShiftOS.Frontend/GUI/TextInput.cs b/ShiftOS.Frontend/GUI/TextInput.cs index fc142a0..851f7d2 100644 --- a/ShiftOS.Frontend/GUI/TextInput.cs +++ b/ShiftOS.Frontend/GUI/TextInput.cs @@ -37,7 +37,7 @@ namespace ShiftOS.Frontend.GUI private int _textOffset = 0; - public override void Paint(Graphics gfx) + protected override void OnPaint(Graphics gfx) { gfx.Clear(LoadedSkin.ControlColor); diff --git a/ShiftOS.Frontend/GraphicsSubsystem/UIManager.cs b/ShiftOS.Frontend/GraphicsSubsystem/UIManager.cs index a688757..705fc5d 100644 --- a/ShiftOS.Frontend/GraphicsSubsystem/UIManager.cs +++ b/ShiftOS.Frontend/GraphicsSubsystem/UIManager.cs @@ -78,7 +78,7 @@ namespace ShiftOS.Frontend.GraphicsSubsystem public static void ProcessMouseState(MouseState state) { - foreach(var ctrl in topLevels) + foreach(var ctrl in topLevels.ToArray()) { ctrl.ProcessMouseState(state); } diff --git a/ShiftOS.Frontend/Infobox.cs b/ShiftOS.Frontend/Infobox.cs index 68c681d..53b4857 100644 --- a/ShiftOS.Frontend/Infobox.cs +++ b/ShiftOS.Frontend/Infobox.cs @@ -52,7 +52,11 @@ namespace ShiftOS.Frontend flyesno.Visible = false; txtinput.Visible = false; btnok.Visible = true; - btnok.Click += callback; + btnok.Click += () => + { + callback?.Invoke(); + AppearanceManager.Close(this); + }; } public void ShowYesNo(Action callback) @@ -64,10 +68,12 @@ namespace ShiftOS.Frontend btnyes.Click += () => { callback?.Invoke(true); + AppearanceManager.Close(this); }; btnno.Click += () => { callback?.Invoke(false); + AppearanceManager.Close(this); }; } @@ -118,7 +124,7 @@ namespace ShiftOS.Frontend // this.lbmessage.X = 85; this.lbmessage.Y = 19; - this.lbmessage.Width = 253; + this.lbmessage.Width = 213; this.lbmessage.Height = 94; this.lbmessage.Text = "label1"; this.lbmessage.TextAlign = TextAlign.MiddleLeft; @@ -144,6 +150,8 @@ namespace ShiftOS.Frontend // btnok // this.btnok.AutoSize = true; + this.btnok.X = 140; + this.btnok.Y = 140; this.btnok.Text = Localization.Parse("{GEN_OK}"); // // pbicon @@ -152,11 +160,13 @@ namespace ShiftOS.Frontend this.pbicon.Y = 19; this.pbicon.Width = 64; this.pbicon.Height = 64; + this.pbicon.Image = Properties.Resources.justthes; + this.pbicon.ImageLayout = ImageLayout.Stretch; // // Dialog // this.Width = 341; - this.Height = 127; + this.Height = 157; this.AddControl(pbicon); this.AddControl(btnok); this.AddControl(flyesno); diff --git a/ShiftOS.Frontend/ShiftOS.cs b/ShiftOS.Frontend/ShiftOS.cs index a2b1d67..396132c 100644 --- a/ShiftOS.Frontend/ShiftOS.cs +++ b/ShiftOS.Frontend/ShiftOS.cs @@ -73,6 +73,7 @@ namespace ShiftOS.Frontend justthes.Image = Properties.Resources.justthes; justthes.X = 15; justthes.Y = 15; + justthes.Opacity = 0.5; UIManager.AddTopLevel(justthes); _titleLabel = new GUI.TextControl(); diff --git a/ShiftOS_TheReturn/Shiftorium.cs b/ShiftOS_TheReturn/Shiftorium.cs index 0362566..e4c2a08 100644 --- a/ShiftOS_TheReturn/Shiftorium.cs +++ b/ShiftOS_TheReturn/Shiftorium.cs @@ -426,7 +426,7 @@ namespace ShiftOS.Engine try { if (SaveSystem.CurrentSave == null) - return false; + return true; if (SaveSystem.CurrentSave.StoriesExperienced == null) SaveSystem.CurrentSave.StoriesExperienced = new List();