Click here to Skip to main content
15,886,362 members
Articles / Programming Languages / C#

C# Script: The Missing Puzzle Piece

Rate me:
Please Sign up or sign in to vote.
4.88/5 (184 votes)
6 Aug 2014MIT24 min read 1.3M   9.4K   531  
An article on a "scripting engine" for the C# language
using System;
using System.Drawing;
using System.Collections;
using System.Diagnostics;
using System.Windows.Forms;
using System.Drawing.Drawing2D;

namespace Scripting
{
	public class ProgressbarForm : System.Windows.Forms.Form
	{
		#region Public interface...
		public void Increment()
		{
			position++;
			if (position > maxPosition)
			{
				position = 0;
			}
			CalcUnits();
			
			using(Graphics g = CreateGraphics())
			{
				DrawProgressBar(g, true);
			}
		}

		public void UpdateProgress()
		{
			CalcUnits(); 
			using(Graphics g = CreateGraphics())
			{
				if (g != null)
				{
					DrawProgressBar(g, true);
				}
			}
		}
		public void Setup(int position, int maxPosition, int unitsInGrpup, int autoIncrementDelay) // -1 means no autoincrementing
		{
			this.position = position;	
			this.maxPosition = maxPosition;
			this.unitsInGrpup = unitsInGrpup;

			this.currCount = 0;
			this.extraPositions = 0;
			this.autoIncrementDelay = autoIncrementDelay;
			System.Diagnostics.Debug.Assert(maxPosition - unitsInGrpup >= unitsInGrpup);

			CalcUnits();
		}
		
		
		public int AutoIncrementDelay { set { autoIncrementDelay = value; UpdateProgress(); } get { return autoIncrementDelay; } }	
		public int Position { set { position = value; UpdateProgress(); } get { return position; } }	
		public int MaxPosition { set { maxPosition = value; UpdateProgress(); } get { return maxPosition; } }
		public int UnitsInGrpup { set { unitsInGrpup = value; UpdateProgress(); } get { return unitsInGrpup; }}
		#endregion

		//drawing and calculating rutines
		private void Init()
		{
			progressRectangle = ClientRectangle;
			progressRectangle.Inflate(-4, -4);
			unitsRectangle = progressRectangle;
			unitsRectangle.Inflate(-10, -2);
			
			RectangleF rcUnit0 = unitsRectangle;
			float unitWidth = (float)(unitsRectangle.Width / (maxPosition - unitsInGrpup + 1));
			rcUnit0.Width = unitWidth;
			
			float offset = ((float)(unitsRectangle.Width - ((maxPosition - unitsInGrpup + 1) * unitWidth))) / (float)2.0;
			rcUnit0.Offset(offset, 0);			//center units in clientRect
			rcUnit0.Inflate(-1, -4);			//shrink it a little
			
			unitRects.Clear();
	
			for (int i = 0; i < (maxPosition - unitsInGrpup + 1); i++)
			{	
				RectangleF rcUnit = rcUnit0;
				rcUnit.X += (float)i * (float)unitWidth;
				unitRects.Add(rcUnit);
			}

			if (autoIncrementDelay > 0)
			{
				timer1.Enabled = true;
				timer1.Interval = autoIncrementDelay;
			}
			else
			{
				timer1.Enabled = false;
			}
		}

		private void CalcUnits()
		{
			int maxUnits = maxPosition;
			if (position == 0)
			{
				currCount = -1;
				extraPositions = 0;
			}
			else
			{
				currCount = position - 1;
			
				if (currCount < unitsInGrpup)
				{
					extraPositions = currCount;
				}
				else
				{
					extraPositions = unitsInGrpup - 1;
					if (currCount > maxUnits - unitsInGrpup)
					{
						extraPositions -= unitsInGrpup - (maxUnits - currCount);
						currCount = maxUnits - unitsInGrpup;
					}
				}
			}
		}

		private void DrawProgressBar(Graphics g, bool unitsOnly)
		{
			Bitmap myBitmap = new Bitmap((int)ClientRectangle.Width, (int)ClientRectangle.Height, g);
			using(Graphics memSurface = Graphics.FromImage(myBitmap))
			{
				RectangleF rc = progressRectangle;
				if (!unitsOnly)
				{
					using (Brush blackBrush = new SolidBrush(Color.Black))
					{
						memSurface.FillRectangle(blackBrush, ClientRectangle);
					}
					using (Pen whitePan = new Pen(Color.White, 3))
					{
						using (GraphicsPath path = RoundRectangle(rc)) 
						{
							memSurface.DrawPath(whitePan, path);
						}					
					}

				}
				using (Brush darkBrush = new SolidBrush(Color.FromArgb(18, 1, 100)))
				{	
					rc.Inflate(-2, -2);
					using (GraphicsPath path = RoundRectangle(rc))
					{
						memSurface.FillPath(darkBrush, path);
					}
				}
				DrawUnits(memSurface);
			}
			g.DrawImage(myBitmap, 0, 0);
			myBitmap.Dispose();
		}

		private void DrawUnits(Graphics g)
		{
			int index = currCount;
			if (index != -1)
			{
				using (Brush unitBrush = CreateUnitBrash((RectangleF)unitRects[index]))
				{
					g.FillRectangle(unitBrush, (RectangleF)unitRects[index]);
					for (int i = extraPositions; i > 0; i--)
					{
						g.FillRectangle(unitBrush, (RectangleF)unitRects[index - i]);
					}
				}
			}
		}

		private Brush CreateUnitBrash(RectangleF rc)
		{
			bool useGradient = true; 
			if (useGradient)
			{
				using (GraphicsPath path = new GraphicsPath())
				{
					RectangleF rc1 = unitsRectangle;
					rc1.Offset(0, -10);	//shift "reflection spot" a bit up from the center
					rc1.Height += 10;
					path.AddRectangle(rc1);

					PathGradientBrush pthGrBrush = new PathGradientBrush(path);
					pthGrBrush.SurroundColors = new Color[]{Color.Green};
					pthGrBrush.CenterColor = Color.LawnGreen;
					pthGrBrush.FocusScales = new PointF(1.0f, 0.15f);
					return pthGrBrush;
				}

//				int unitVOffest = 2;
//				LinearGradientBrush linGrBrush = new LinearGradientBrush(
//					unitsRectangle,
//					Color.FromArgb(245, 255, 245),
//					Color.FromArgb(8,255,0), LinearGradientMode.Vertical);  
//				//linGrBrush.GammaCorrection = true;
//				return linGrBrush;
			}
			else
				return new SolidBrush(Color.FromArgb(8,255,0));	
		}

		private GraphicsPath RoundRectangle(RectangleF rc)
		{
			float radius = rc.Height / 2.0f;

			PointF point1 = new PointF(rc.X + radius, rc.Y);
			PointF point2 = new PointF(rc.X + rc.Width - radius, rc.Y);
			PointF point3 = new PointF(rc.X + rc.Width - radius, rc.Y + rc.Height);
			PointF point4 = new PointF(rc.X + radius, rc.Y + rc.Height);
						
			GraphicsPath myPath = new GraphicsPath();

			myPath.AddLine(point1, point2);
			myPath.AddArc(point2.X - radius, point2.Y, radius*2.0f, rc.Height, 270, 180);
			myPath.AddLine(point3, point4);
			myPath.AddArc(point4.X - radius, point1.Y, radius*2.0f, rc.Height, 90, 180);

			return myPath;
		}

		//internal progressbar data
		private int currCount;	
		private int extraPositions;	
		private RectangleF progressRectangle;
		private RectangleF unitsRectangle;

		private int position;	
		private int maxPosition;
		private int unitsInGrpup;
		private int autoIncrementDelay;
		private ArrayList unitRects;

		//form data and methods
		private System.Windows.Forms.Timer timer1;
		private System.ComponentModel.IContainer components;

		public ProgressbarForm(string title)
		{
			InitializeComponent();
			if (title != null)
			{
				this.Text = title;
			}
		}

		static public void ShowContinuous(string title)
		{
			using(ProgressbarForm dlg = new ProgressbarForm(title))
			{
				dlg.Setup(0, 20, 4, 70);
				dlg.ShowDialog();
			}
		}
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if(components != null)
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}
		#region Windows Form Designer generated code
		private void InitializeComponent()
		{
			this.components = new System.ComponentModel.Container();
			this.timer1 = new System.Windows.Forms.Timer(this.components);
			// 
			// timer1
			// 
			this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
			// 
			// ProgressbarForm
			// 
			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
			this.ClientSize = new System.Drawing.Size(258, 32);
			this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
			this.Name = "ProgressbarForm";
			this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
			this.Text = "Progressbar";
			this.Click += new System.EventHandler(this.ProgressbarForm_Click);
			this.Load += new System.EventHandler(this.ProgressbarForm_Load);
			this.Paint += new System.Windows.Forms.PaintEventHandler(this.ProgressbarForm_Paint);

		}
		#endregion
		
		private void ProgressbarForm_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
		{
			DrawProgressBar(e.Graphics, false);
		}

		private void ProgressbarForm_Load(object sender, System.EventArgs e)
		{
			unitRects = new ArrayList();
			Init();
		}

		private void timer1_Tick(object sender, System.EventArgs e)
		{
			Increment();
		}

		private void ProgressbarForm_Click(object sender, System.EventArgs e)
		{
			//timer1.Enabled = !timer1.Enabled; for testing only
		}
	}
	
	class Script
	{
		static public void Main(string[] args)
		{
			ProgressbarForm.ShowContinuous("Progress");
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The MIT License


Written By
Program Manager
Australia Australia
I was born in Ukraine. After completing the university degree worked there as a Research Chemist. Last 23 years I live in Australia where I've got my second qualification as a Software Engineer.

"I am the lucky one: I do enjoy what I am doing!"

Comments and Discussions