From 17ec2d0f69ca19d3a8cdfdb06d2f0b8645cb50bd Mon Sep 17 00:00:00 2001 From: Markus Ewald Date: Wed, 13 Feb 2019 11:57:01 +0000 Subject: [PATCH] The progress spinner can now also show a status message beneath it (optional) git-svn-id: file:///srv/devel/repo-conversion/nuwi@52 d2e56fa2-650e-0410-a79f-9358c0239efd --- Source/Controls/ProgressSpinner.cs | 83 ++++++++++++++++++++++++++---- 1 file changed, 73 insertions(+), 10 deletions(-) diff --git a/Source/Controls/ProgressSpinner.cs b/Source/Controls/ProgressSpinner.cs index 2502309..ee423bc 100644 --- a/Source/Controls/ProgressSpinner.cs +++ b/Source/Controls/ProgressSpinner.cs @@ -94,11 +94,22 @@ namespace Nuclex.Windows.Forms.Controls { } } + /// Font that is used to display the status text + public Font StatusFont { + get { return this.statusFont; } + set { this.statusFont = value; } + } + + /// Text that will be displayed as the control's status + public string StatusText { + get { return this.statusText; } + set { this.statusText = value; } + } + /// Called when the control is hidden or shown /// Not used protected override void OnVisibleChanged(EventArgs arguments) { base.OnVisibleChanged(arguments); - this.animationUpdateTimer.Enabled = this.spinnerRunning && Visible; } @@ -107,6 +118,7 @@ namespace Nuclex.Windows.Forms.Controls { protected override void OnPaint(PaintEventArgs arguments) { paintControlsBehindMe(arguments); paintAnimatedDots(arguments); + paintStatusMessage(arguments); } /// Forcefully redraws the controls below this one @@ -128,11 +140,11 @@ namespace Nuclex.Windows.Forms.Controls { if(Parent != null && this.BackColor == Color.Transparent) { using(var bmp = new Bitmap(Parent.Width, Parent.Height)) { Parent.Controls.Cast() - .Where(c => Parent.Controls.GetChildIndex(c) > Parent.Controls.GetChildIndex(this)) - .Where(c => c.Bounds.IntersectsWith(this.Bounds)) - .OrderByDescending(c => Parent.Controls.GetChildIndex(c)) - .ToList() - .ForEach(c => c.DrawToBitmap(bmp, c.Bounds)); + .Where(c => Parent.Controls.GetChildIndex(c) > Parent.Controls.GetChildIndex(this)) + .Where(c => c.Bounds.IntersectsWith(this.Bounds)) + .OrderByDescending(c => Parent.Controls.GetChildIndex(c)) + .ToList() + .ForEach(c => c.DrawToBitmap(bmp, c.Bounds)); arguments.Graphics.DrawImage(bmp, -Left, -Top); } @@ -152,9 +164,9 @@ namespace Nuclex.Windows.Forms.Controls { SmoothingMode prevousSmoothingMode = arguments.Graphics.SmoothingMode; arguments.Graphics.SmoothingMode = SmoothingMode.HighQuality; try { - int diameter = Math.Min(Width, Height); - PointF center = new PointF(diameter / 2.0f, diameter / 2.0f); + PointF center = new PointF(Width / 2.0f, (Height - this.statusFont.Height - 2) / 2.0f); + int diameter = Math.Min(Width, Height - this.statusFont.Height - 2); int bigRadius = diameter / 2 - DotRadius - (DotCount - 1) * ScaleFactor; // Draw the dots @@ -185,6 +197,52 @@ namespace Nuclex.Windows.Forms.Controls { } } + /// Draws the status message under the animated dots + /// Provides access to the drawing surface and tools + private void paintStatusMessage(PaintEventArgs arguments) { + if(!string.IsNullOrEmpty(this.statusText)) { + SizeF textRectangle = arguments.Graphics.MeasureString( + this.statusText, this.statusFont + ); + + var messageArea = new RectangleF( + (Width - textRectangle.Width) / 2.0f, + Height - this.statusFont.Height - 1.0f, + textRectangle.Width, + this.statusFont.Height + ); + + // Draw text with a white halo. This is a little bit ugly... + { + messageArea.Offset(-1.0f, 0.0f); + arguments.Graphics.DrawString( + this.statusText, this.statusFont, Brushes.White, messageArea + ); + + messageArea.Offset(2.0f, 0.0f); + arguments.Graphics.DrawString( + this.statusText, this.statusFont, Brushes.White, messageArea + ); + + messageArea.Offset(-1.0f, -1.0f); + arguments.Graphics.DrawString( + this.statusText, this.statusFont, Brushes.White, messageArea + ); + + messageArea.Offset(0.0f, 2.0f); + arguments.Graphics.DrawString( + this.statusText, this.statusFont, Brushes.White, messageArea + ); + + messageArea.Offset(0.0f, -1.0f); + arguments.Graphics.DrawString( + this.statusText, this.statusFont, this.dotFillBrush, messageArea + ); + } + } + } + + /// Called when the animation timer ticks to update the animation state /// Animation timer that has ticked /// Not used @@ -195,6 +253,11 @@ namespace Nuclex.Windows.Forms.Controls { /// Whether the spinner has been started private bool spinnerRunning; + /// Index of the currently leading dot + private int leadingDotIndex = 0; + /// Text that will be displayed under the control as the current status + private string statusText; + /// Color in which the dots will be filled private Color dotFillColor = Color.RoyalBlue; /// Color that will be used for the dots' outline @@ -203,8 +266,8 @@ namespace Nuclex.Windows.Forms.Controls { private Brush dotFillBrush; /// Brush used for the dots' outline private Pen dotOutlinePen; - /// Index of the currently leading dot - private int leadingDotIndex = 0; + /// Font that is used to display the status text + private Font statusFont = SystemFonts.SmallCaptionFont; }