Click here to Skip to main content
15,885,278 members
Articles / Multimedia / GDI+

Internal Supply Chain, Visibility via 200 plus 3D Chart Reports - Part II

Rate me:
Please Sign up or sign in to vote.
5.00/5 (15 votes)
8 Oct 2009CPOL4 min read 53.7K   5.3K   46  
This article focuses on internal supply chain management systems visibility via chart reports, and provides assessment apparatus to manage and monitor activities spawned during business processes, hence paves the way for timely and precise business decisions.
//==============================================================================
//  File:		VerticalTabControl.cs
//
//  Namespace:	System.Windows.Forms.DataVisualization.Charting.Utilities.SampleMain
//
//	Classes:	VerticalTabControl, VerticalTabPage, VerticalTabPageCollection
//
//  Purpose:	Custom tab control which supports vertical tap pages buttons 
//				mode. 
//
//==============================================================================
// Copyright � Microsoft Corporation, all rights reserved
//==============================================================================

using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.ComponentModel;
using System.Collections;
using System.Windows.Forms;

namespace System.Windows.Forms.DataVisualization.Charting.Utilities.SampleMain
{
	/// <summary>
	/// This class represents a custom vertical tab control that is used by docking windows.
	/// <seealso cref="DockingWindow"/>
	/// <seealso cref="VerticalTabPage"/>
	/// <seealso cref="VerticalTabPageButton"/>
	/// </summary>
	/// <remarks>A <b>VerticalTabControl</b> object displays one or more tab pages via its 
	/// <see cref="VerticalTabPageCollection"/>.<para>This class is exposed as the 
	/// <see cref="DockingWindow.TabControl"/> property of the <see cref="DockingWindow"/> class.
	/// </para></remarks>
	public class VerticalTabControl : UserControl
	{
		#region Fields

		/// <summary>
		/// Control tab pages collection.
		/// </summary>
		private	VerticalTabPageCollection	tabPages = null;

		/// <summary>
		/// Selected tab page or null.
		/// </summary>
		private	VerticalTabPage				selectedTabPage = null;

		/// <summary>
		/// Indicates that tab control is vertical
		/// </summary>
		private bool						vertical = true;

		/// <summary>
		/// Tab buttons offset from the left and right side.
		/// </summary>
		private int							buttonOffset = 7;

		/// <summary>
		/// Tab button text spacing
		/// </summary>
		private Rectangle					buttonTextSpacing = new Rectangle(12, 4, 12, 4);

		/// <summary>
		/// List of images used to draw on the tab pages buttons.
		/// </summary>
		private	ImageList					imageList = null;

		/// <summary>
		/// Control used to draw a horizontal splitter line
		/// </summary>
		private	Label						tabSplitterLine = null;

		/// <summary>
		/// Color of the box border.
		/// </summary>
		private Color	borderColor = Color.Black;

		/// <summary>
		/// Box border size.
		/// </summary>
		private	int		borderSize = 1;

		/// <summary>
		/// Background image horizontal offset;
		/// </summary>
		public	int		BackImageOffsetX = 0;

		/// <summary>
		/// Background image vertical offset;
		/// </summary>
		public	int		BackImageOffsetY = 0;

		#endregion

		#region Constructor

		/// <summary>
		/// Default constructor.
		/// </summary>
		public VerticalTabControl()
		{
			// Create tab pages collection
			this.tabPages = new VerticalTabPageCollection(this);

			// Initialize splitter line control
			tabSplitterLine = new Label();
			tabSplitterLine.Text = String.Empty;
			tabSplitterLine.Visible = false;
			tabSplitterLine.BorderStyle = BorderStyle.FixedSingle;
			this.Controls.Add(tabSplitterLine);

			this.SetStyle(ControlStyles.ResizeRedraw, true);
		}

		#endregion

		#region Properties

		/// <summary>
		/// Border color of the box.
		/// </summary>
		[
		Category("Appearance"),
		DefaultValue(typeof(Color), "Black"),
		Description("Border color of the box."),
		]
		public Color BorderColor
		{
			set
			{
				this.borderColor = value;
				this.Invalidate();
			}
			get
			{
				return this.borderColor;
			}
		}

		/// <summary>
		/// Border size of the box.
		/// </summary>
		[
		Category("Appearance"),
		DefaultValue(1),
		Description("Border size of the box."),
		]
		public int BorderSize
		{
			set
			{
				this.borderSize = value;
				this.Invalidate();
			}
			get
			{
				return this.borderSize;
			}
		}

		/// <summary>
		/// Gets the number of non-hidden tab pages in the control.
		/// </summary>
		/// <value>The number of non-hidden tab pages in the control.</value>
		[
		Category("Misc"),
		DefaultValue(0),
		Description("Gets the number of non-hidden tab pages in the control."),
		]
		public int VisibleTabPagesCount
		{
			get
			{
				int count = 0;
				foreach(VerticalTabPage tabPage in this.TabPages)
				{
					if(!tabPage.Hidden)
					{
						++count;
					}
				}
				return count;
			}
		}

		/// <summary>
		/// Gets the control's tab pages collection.
		/// <seealso cref="VerticalTabPageCollection"/>
		/// <seealso cref="VerticalTabPage"/>
		/// </summary>
		/// <value>The control's <see cref="VerticalTabPageCollection"/> object.</value>
		[
		Category("Misc"),
		DefaultValue(""),
		Description("Gets control tab pages collection."),
		]
		public VerticalTabPageCollection TabPages
		{
			get
			{
				return tabPages;
			}
		}

		/// <summary>
		/// Gets or sets the vertical style of the tab control.
		/// </summary>
		/// <value>If <b>true</b> the control is displayed vertically, if <b>false</b> it 
		/// is not.</value>
		[
		Category("Appearance"),
		DefaultValue(""),
		Description("Gets or sets the vertical style of the tab control."),
		]
		public bool Vertical
		{
			get
			{
				return vertical;
			}
			set
			{
				if(vertical != value)
				{
					vertical = value;
					OnVerticalChanged();
				}
			}
		}

		/// <summary>
		/// Gets or sets the control's image list, which is used for the vertical tab page 
		/// buttons.
		/// <seealso cref="ImageList"/>
		/// <seealso cref="VerticalTabPage.ImageIndex"/>
		/// </summary>
		/// <value>The control's <see cref="ImageList"/> object.</value>
		[
		Category("Appearance"),
		DefaultValue(""),
		Description("Gets or sets the control's image list."),
		]
		public ImageList ImageList
		{
			get
			{
				return imageList;
			}
			set
			{
				imageList = value;
			}
		}

		/// <summary>
		/// Gets or sets the index of the selected tab page.
		/// <seealso cref="VerticalTabPage"/>
		/// </summary>
		/// <value>The  index of the selected tab page.</value>
		[
		Category("Misc"),
		DefaultValue(""),
		Description("Gets or sets the index of the selected tab page."),
		]
		public int SelectedIndex
		{
			get
			{
				// Get index of selected tab page
				if(selectedTabPage != null)
				{
					return selectedTabPage.Index;
				}
				return -1;
			}
			set
			{
				// Select tab page using index
				if(value < this.TabPages.Count && value >= 0)
				{
					this.SelectedTab = this.TabPages[value];
				}
				else
				{
					this.SelectedTab = null;
				}
			}
		}

		/// <summary>
		/// Gets or sets the selected tab page.
		/// <seealso cref="VerticalTabPage"/>
		/// </summary>
		/// <value>The selected <see cref="VerticalTabPage"/> object of the control.</value>
		[
		Category("Misc"),
		DefaultValue(""),
		Description("Sets or gets selected tab page."),
		]
		public VerticalTabPage SelectedTab
		{
			get
			{
				return selectedTabPage;
			}
			set
			{
				if(value == null || this.Contains(value))
				{
					// Hidden tabs cannot be selected
					if(this.VisibleTabPagesCount == 0)
					{
						value = null;
					}
					else if(value != null && value.Hidden)
					{
						// Try to find non-hidden tab page next to current
						int index = value.Index + 1;
						while(value.Hidden && index < this.TabPages.Count)
						{
							value = this.TabPages[index++];
						}

						// Try to find non-hidden tab page prev. to current
						index = value.Index - 1;
						while(value.Hidden && index >= 0)
						{
							value = this.TabPages[index--];
						}

					}

					selectedTabPage = value;
					OnSelectedTabPageChanged();
				}
			}
		}

		#endregion

		#region Methods

		/// <summary>
		/// Called when the control is resized.
		/// <seealso cref="EventArgs"/>
		/// </summary>
		/// <param name="e">Event arguments.</param>
		protected override void OnResize(EventArgs e)
		{
			// Call base class
			base.OnResize(e);

			// Resize horizontal splitter line 
			if(!this.Vertical)
			{
				//this.tabSplitterLine.Visible = (this.VisibleTabPagesCount > 1) ? true : false;
				this.tabSplitterLine.Location = new Point(0, this.ClientRectangle.Bottom - GetButtonHeight());
				this.tabSplitterLine.Size = new Size(this.Width, 1);
				tabSplitterLine.SendToBack();
			}

			// Reposition buttons in horizontal style
			if(!this.Vertical)
			{
				this.SuspendLayout();
				ResizeHorizontalTabPages();
				this.ResumeLayout();
			}
		}

		/// <summary>
		/// Called when the tab pages are changed. 
		/// </summary>
		internal void OnTabPagesChanged()
		{
			ReorderTabButtons();
		}

		/// <summary>
		/// Called when the vertical style of the tab control is changed.
		/// </summary>
		protected virtual void OnVerticalChanged()
		{
			// Hide/Show horizontal splitter line 
			//this.tabSplitterLine.Visible = !this.Vertical;

			// Reorder tabs
			ReorderTabButtons();
		}

		/// <summary>
		/// Called when the selected tab page is changed.
		/// </summary>
		protected virtual void OnSelectedTabPageChanged()
		{
			ReorderTabButtons();

			// Fire event
			if(this.SelectedIndexChanged != null)
			{
				this.SelectedIndexChanged(this, new EventArgs());
			}
		}

		/// <summary>
		/// Sets tab buttons order, visibility and docking style.
		/// </summary>
		private void ReorderTabButtons()
		{
			this.SuspendLayout();

			// Hide paneles of all tab pages except of selected one
			bool	beforeSelectedTab = true;
			int		childControlIndex = this.TabPages.Count - 1;
			int		tabIndex = 0;
			foreach(VerticalTabPage tabPage in this.TabPages)
			{
				// Set button orientation 
				tabPage.TabButton.Vertical = this.Vertical;

				// Set buttons docking and child order for vertical tabs
				if(this.Vertical)
				{
					// Hide button if there is only one
//					if(this.VisibleTabPagesCount == 1)
//					{
//						tabPage.TabButton.Visible = false;
//					}
//					else
					{
						tabPage.TabButton.Visible = (tabPage.Hidden) ? false : true;
					}


					// Set button height
					tabPage.TabButton.Height = GetButtonHeight();

					// Dock buttons to Top or Bottom
					tabPage.TabButton.Dock = (beforeSelectedTab) ? DockStyle.Top : DockStyle.Bottom;

					// Set button child index
					this.Controls.SetChildIndex(tabPage.TabButton, childControlIndex);
				}

                if(tabPage == this.SelectedTab)
				{
					// Rest of the buttons should be docked to the bottom
					beforeSelectedTab = false;
					childControlIndex = 0;

					// Set selected style of the button
					tabPage.TabButton.SelectedTab = true;

					// Make sure the previous button has no separator line
					if(tabIndex > 0)
					{
						this.TabPages[tabIndex - 1].TabButton.SeparatorLine = false;
					}
				}
				else
				{
					// Hide non selected tab panels
					tabPage.Visible = false;

					// Set non-selected style of the button
					tabPage.TabButton.SelectedTab = false;
					tabPage.TabButton.SeparatorLine = true;
				}

				// Get next child index 
				if(beforeSelectedTab)
				{
					--childControlIndex;
				}
				else
				{
					++childControlIndex;
				}

				// Show selected tab panel
				if(this.SelectedTab != null)
				{
					// Make sure panel is on the top of the Z order
					this.SelectedTab.BringToFront();

					// set fill docking style
					if(this.Vertical)
					{
						this.SelectedTab.Dock = DockStyle.Fill;
					}

					// Show selected tab panel
					this.SelectedTab.Visible = true;
				}

				++tabIndex;
			}

			// Make sure all buttons fit in horizontal mode
			if(!this.Vertical)
			{
				ResizeHorizontalTabPages();
			}

			this.ResumeLayout();
		}

		/// <summary>
		/// Returns the height of the tab page button.
		/// </summary>
		/// <returns>The tab button's height.</returns>
		/// <remarks>The height of button is the same for all vertical tab pages.
		/// </remarks>
		public int GetButtonHeight()
		{
			int	height = 0;
			if(this.TabPages.Count > 0)
			{
				// Get text size
				Graphics graphics = this.CreateGraphics();
				SizeF	textSize = graphics.MeasureString(this.TabPages[0].TabButton.Text, this.TabPages[0].TabButton.Font);
				height = (int)textSize.Height;
				graphics.Dispose();

				// Get image size
				if(this.TabPages[0].TabButton.Image != null)
				{
					height = Math.Max(height, this.TabPages[0].TabButton.Image.Height);
				}

				// Add extra spacing
				height += buttonTextSpacing.Y + buttonTextSpacing.Height;
			}
			return height;
		}

		/// <summary>
		/// Sets tab page button and panel position for non-vertical tab control.
		/// </summary>
		internal void ResizeHorizontalTabPages()
		{
			//************************************************************
			//** Reposition all tab page panel controls.
			//************************************************************
			Rectangle	panelPosition = this.ClientRectangle;
			panelPosition.Inflate(-1, -1);
			if(this.VisibleTabPagesCount >= 1)
			{
				int tabButtonsHeight = GetButtonHeight() + 1;
				panelPosition.Height -= tabButtonsHeight;
				panelPosition.Y += tabButtonsHeight;
			}
			foreach(VerticalTabPage tabPage in this.TabPages)
			{
				tabPage.Dock = DockStyle.None;
				tabPage.Location = panelPosition.Location;
				tabPage.Size = panelPosition.Size;
			}

			//************************************************************
			//** Calculate positions for all buttons.
			//************************************************************

			// Create an arry of rectangles
			Rectangle[]	buttonPos = new Rectangle[this.TabPages.Count];

			// Calculate position of each button
			int	tabIndex = 0;
			int	currentX = this.buttonOffset;
			foreach(VerticalTabPage tabPage in this.TabPages)
			{
				if(!tabPage.Hidden)
				{
					buttonPos[tabIndex] = new Rectangle(0, 0, 0, 0);

					// Hide all buttons if only one tap page in control
//					if(this.VisibleTabPagesCount == 1)
//					{
//						tabPage.TabButton.Visible = false;
//					}
//					else
					{
						tabPage.TabButton.Visible = (tabPage.Hidden) ? false : true;
					}

					// Get left button coordinate using previous page button
					buttonPos[tabIndex].X = currentX;

					// Set button Top and Height
					buttonPos[tabIndex].Y = (tabPage == this.SelectedTab) ? 1 : 1;
					buttonPos[tabIndex].Height = GetButtonHeight();

					// Set button width
					Graphics graphics = this.CreateGraphics();
					SizeF	textSize = graphics.MeasureString(tabPage.TabButton.Text, tabPage.TabButton.Font);
					buttonPos[tabIndex].Width = (int)textSize.Width + buttonTextSpacing.X + buttonTextSpacing.Width;
					graphics.Dispose();

					// Add image width
					if(tabPage.TabButton.Image != null)
					{
						buttonPos[tabIndex].Width += tabPage.TabButton.Image.Width + 3;
					}

					// Move current X coordinate
					currentX = buttonPos[tabIndex].Right - 1;
				}

				// Increase index
				++tabIndex;
			}

			//************************************************************
			//** Adjust buttons position if total width is too big.
			//************************************************************

			// Calculate max width for all buttons
			int maxX = this.ClientRectangle.Width - 2 * this.buttonOffset;

			// Check if buttons width adjustment is required
			bool	adjustmentRequired = false;
			foreach(Rectangle rect in buttonPos)
			{
				if(rect.Right > maxX)
				{
					adjustmentRequired = true;
					break;
				}
			}

			// Make the adjustment
			if(adjustmentRequired)
			{
				// Calculate new button width
				int newWidth = maxX / this.TabPages.Count - this.TabPages.Count;
				if(newWidth < 10)
				{
					newWidth = 10;
				}

				// Set new width
				currentX = this.buttonOffset;
				for(int rectIndex = 0; rectIndex < buttonPos.Length; rectIndex++)
				{
					buttonPos[rectIndex].X = currentX;
					buttonPos[rectIndex].Width = newWidth;
					currentX = buttonPos[rectIndex].Right + 1;
				}
			}

			//************************************************************
			//** Set buttons position.
			//************************************************************
			tabIndex = 0;
			foreach(VerticalTabPage tabPage in this.TabPages)
			{
				if(tabPage.TabButton.Dock != DockStyle.None)
				{
					tabPage.TabButton.Dock = DockStyle.None;
				}
				tabPage.TabButton.Location = buttonPos[tabIndex].Location;
				tabPage.TabButton.Size = buttonPos[tabIndex].Size;
				tabPage.SendToBack();

				// Increase index
				++tabIndex;
			}

		}

		#endregion

		#region Overriden painting methods

		protected override void OnPaintBackground( PaintEventArgs e )
		{
			int height = this.GetButtonHeight() + 1;
			if(this.BackgroundImage != null)
			{
				e.Graphics.Clear(this.BackColor);

				// Draw image in the background of the tab controls.
				// Image must be aligne to the bottom-right corner of the tabs area.
				Rectangle destRect = new Rectangle(
					this.Right - this.BackgroundImage.Width + this.BackImageOffsetX,
					0,
					this.BackgroundImage.Width,
					height);
				ImageAttributes imageAttributes = new ImageAttributes();
				e.Graphics.DrawImage(
					this.BackgroundImage, 
					destRect, 
					0, 
					this.BackImageOffsetY, 
					this.BackgroundImage.Width, 
					height,
					GraphicsUnit.Pixel,
					imageAttributes);
			}
			else
			{
				base.OnPaintBackground( e );
			}

			// Border rectangle
			height -= 1;
			Rectangle rectBorder = new Rectangle(0, height, this.Width - 1, this.Height - height - 1);

			// Draw simple border
			using(Pen pen = new Pen(BorderColor, BorderSize))
			{
				e.Graphics.DrawRectangle(pen, rectBorder);
			}
		}

		protected override void OnPaint( PaintEventArgs e )
		{
			base.OnPaint(e);
		}

		#endregion

		#region Events

		/// <summary>
		/// Event that occurs when selected index is changed in the tab control.
		/// </summary>
		public event EventHandler SelectedIndexChanged;

		/// <summary>
		/// The tab page button's dragging started event.
		/// </summary>
		public event EventHandler TabPageButtonStartDragging;

		/// <summary>
		/// Tab page button dragging started event.
		/// </summary>
		/// <param name="sender">Event sender.</param>
		/// <param name="e">Event arguments.</param>
		internal void OnTabPageButtonStartDragging(object sender, EventArgs e)
		{
			// Fire TabPageButtonStartDragging event
			if(this.TabPageButtonStartDragging != null)
			{
				this.TabPageButtonStartDragging(sender, e);
			}
		}

		#endregion
	}

	/// <summary>
	/// This class represents a vertical tab page.
	/// <seealso cref="VerticalTabControl"/>
	/// <seealso cref="VerticalTabPageButton"/>
	/// <seealso cref="VerticalTabPageCollection"/>
	/// <seealso cref="DockingWindow"/>
	/// </summary>
	/// <remarks>One or more vertical tab pages can be displayed by the vertical tab control of a 
	/// docking window.<para>A vertical tab page displays a tab page button that has an image and 
	/// some text.
	/// </para>
	/// <para>These pages are stored in the <see cref="VerticalTabPageCollection"/> object property 
	/// of a vertical tab control.</para>
	/// <para>You can use the inherited properties to set panel-specific properties 
	/// (e.g. text, etc.).</para></remarks>
	public class VerticalTabPage : Panel
	{
		#region Fields

		/// <summary>
		/// Tab control this page belongs to.
		/// </summary>
		internal VerticalTabControl		tabControl = null;

		/// <summary>
		/// Tab page button.
		/// </summary>
		internal	VerticalTabPageButton	tabButton = null;

		/// <summary>
		/// Indicates that tab page is hidden.
		/// </summary>
		private bool					hidden = false;

		#endregion

		#region Constructor

		/// <summary>
		/// Default constructor.
		/// </summary>
		public VerticalTabPage()
		{
			Initialize("TabName");
		}

		/// <summary>
		/// Default constructor that takes the text to be displayed on the tab.
		/// <seealso cref="VerticalTabControl"/>
		/// </summary>
		/// <param name="text">Text to be displayed on the tab.</param>
		public VerticalTabPage(string text)
		{
			Initialize(text);
		}

		/// <summary>
		/// Initialize tab control page.
		/// </summary>
		/// <param name="text">Text to be displayed on the tab.</param>
		private void Initialize(string text)
		{
			// Set button text
			this.Text = text;

			// Initialize Panel properties
			this.Visible = false;
			this.Dock = DockStyle.Fill;
			this.DockPadding.Left = 5;
			this.DockPadding.Right = 2;
			this.DockPadding.Top = 5;
			this.DockPadding.Bottom = 2;

			// Change control style
			//this.SetStyle(ControlStyles.ResizeRedraw, true);
			
			// Create tab page button
			tabButton = new VerticalTabPageButton();
			tabButton.Text = text;
			tabButton.Dock = DockStyle.Top;
			tabButton.FlatStyle = FlatStyle.Standard;
			tabButton.ImageAlign = ContentAlignment.MiddleLeft;
			tabButton.TextAlign = ContentAlignment.MiddleLeft;

			// Hookup to the button events
			tabButton.DragOver += new DragEventHandler(OnButtonDragOver);
			tabButton.MouseDown += new MouseEventHandler(OnButtonMouseDown);
			tabButton.Click += new EventHandler(OnButtonMouseClick);
			tabButton.StartDragging += new EventHandler(OnButtonStartDragging);
		}

		#endregion

		#region Properties

		/// <summary>
		/// Gets or sets the tab page's hidden flag.
		/// <seealso cref="VerticalTabControl"/>
		/// </summary>
		/// <value>If <b>true</b> the tab page is hidden, if <b>false</b> it is not.</value>
		[
		Category("Appearance"),
		DefaultValue(false),
		Description("Gets or sets the tab page's hidden flag."),
		]
		public bool Hidden
		{
			get
			{
				return hidden;
			}
			set
			{
				if(hidden != value)
				{
					hidden = value;
					OnHiddenChanged();
				}
			}
		}

		/// <summary>
		/// Gets or sets the index of the image to be drawn on the tab button.
		/// <seealso cref="VerticalTabControl"/>
		/// </summary>
		/// <value>Index of the tab button's image.</value>
		[
		Category("Misc."),
		DefaultValue(""),
		Description("Gets or sets the index of the image to be drawn on the tab button."),
		]
		public int ImageIndex
		{
			get
			{
				return this.TabButton.ImageIndex;
			}
			set
			{
				// Set image list of the button
				if(this.tabControl != null)
				{
					if(this.TabButton.ImageList != this.tabControl.ImageList)
					{
						this.TabButton.ImageList = this.tabControl.ImageList;
					}
				}

				// Set image index
				this.TabButton.ImageIndex = value;
			}
		}

		/// <summary>
		/// Gets the tab page's button control.
		/// <seealso cref="VerticalTabPageButton"/>
		/// <seealso cref="VerticalTabControl"/>
		/// </summary>
		/// <value>The tab page's <see cref="VerticalTabPageButton"/> object.</value>
		[
		Category("Misc."),
		DefaultValue(""),
		Description("Gets the tab page's button control."),
		]
		public VerticalTabPageButton TabButton
		{
			get
			{
				return tabButton;
			}
		}

		/// <summary>
		/// Gets the index of the page in the tab control's vertical tab page collection.
		/// <seealso cref="VerticalTabControl"/>
		/// <seealso cref="VerticalTabPageCollection"/>
		/// </summary>
		/// <value>The index of the tab page.</value>
		[
		Category("Misc."),
		DefaultValue(""),
		Description("Gets the index of the tab page in the collection."),
		]
		public int Index
		{
			get
			{
				if(this.tabControl != null)
				{
					// Find index of this tab page
					int	tabPageIndex = 0;
					foreach(VerticalTabPage tabPage in this.tabControl.TabPages)
					{
						if(tabPage == this)
						{
							return tabPageIndex;
						}
						++tabPageIndex;
					}
				}
				return -1;
			}
		}


		#endregion

		#region Methods

		private void OnButtonDragOver(object sender, DragEventArgs e)
		{
			if(this.tabControl != null && this != tabControl.SelectedTab)
			{
				// Change selected tab control
				tabControl.SelectedTab = this;
				this.Invalidate();
				this.Update();
			}
		}

		/// <summary>
		/// Mouse button was pressed inside tab page button.
		/// </summary>
		/// <param name="sender">Event sender.</param>
		/// <param name="e">Event arguments</param>
		private void OnButtonMouseDown(object sender, MouseEventArgs e)
		{
			if(this.tabControl != null && !this.tabControl.Vertical)
			{
				// Change selected tab control
				tabControl.SelectedTab = this;
			}
		}

		/// <summary>
		/// Mouse button was pressed inside tab page button.
		/// </summary>
		/// <param name="sender">Event sender.</param>
		/// <param name="e">Event arguments</param>
		private void OnButtonMouseClick(object sender, EventArgs e)
		{
			if(this.tabControl != null && this.tabControl.Vertical)
			{
				// Change selected tab control
				tabControl.SelectedTab = this;
			}
		}
		
		/// <summary>
		/// Event is called when button was dragged with the mouse.
		/// </summary>
		/// <param name="sender">Event sender.</param>
		/// <param name="e">Event arguments</param>
		private void OnButtonStartDragging(object sender, EventArgs e)
		{
			if(this.tabControl != null)
			{
				// Notify tab control
				tabControl.OnTabPageButtonStartDragging(sender, e);
			}
		}
		
		/// <summary>
		/// Called after the controls text is changed.
		/// </summary>
		/// <param name="e">Event arguments.</param>
		protected override void OnTextChanged(EventArgs e)
		{
			// Update button text
			if(this.TabButton != null)
			{
				this.TabButton.Text = this.Text;
			}
		}

		/// <summary>
		/// Called after the  controls hidden flag is changed.
		/// </summary>
		protected void OnHiddenChanged()
		{
			// Change visibility of the tab button
			this.TabButton.Visible = !this.Hidden;

			// Check if control reference is not null
			if(this.tabControl != null)
			{
				// Hidden tab page can't be selected
				if(this.tabControl.SelectedTab == this)
				{
					int newIndex = this.Index;
					if(newIndex >= this.tabControl.TabPages.Count)
					{
						newIndex = this.tabControl.TabPages.Count - 1;
					}
					this.tabControl.SelectedIndex = newIndex;
				}

				// If there is only one tab page in control - select it
				if(this.tabControl.SelectedTab == null)
				{
					this.tabControl.SelectedTab = this;
				}

				// Notify tab control about the changes
				this.tabControl.OnTabPagesChanged();
			}
		}

		#endregion

	}

	/// <summary>
	/// This class represents a collection of tab pages that belong to a vertical tab control.
	/// <seealso cref="VerticalTabControl"/>
	/// <seealso cref="VerticalTabPage"/>
	/// </summary>
	/// <remarks><b>VerticalTabPageCollection</b> is exposed as the 
	/// <see cref="VerticalTabControl.TabPages"/> property of the <see cref="VerticalTabControl"/> 
	/// class.<para>A vertical tab control can display one or more tab pages.</para></remarks>
	public class VerticalTabPageCollection : CollectionBase
	{
		#region Fields

		/// <summary>
		/// Reference to the owner tab control.
		/// </summary>
		private	VerticalTabControl	tabControl = null;

		#endregion

		#region Constructor and initialization

		/// <summary>
		/// Default public constructor is not accessible.
		/// </summary>
		private VerticalTabPageCollection()
		{
		}

		/// <summary>
		/// The constructor, which takes the vertical tab control owner of this object.
		/// <seealso cref="VerticalTabControl"/>
		/// <seealso cref="VerticalTabPage"/>
		/// </summary>
		/// <param name="tabControl">Owner of the collection.</param>
		public VerticalTabPageCollection(VerticalTabControl tabControl)
		{
			this.tabControl = tabControl;
		}

		#endregion

		#region Indexer

		/// <summary>
		/// Strongly typed indexer of the collection.
		/// <seealso cref="VerticalTabControl"/>
		/// <seealso cref="VerticalTabPage"/>
		/// </summary>
		public VerticalTabPage this[int index] 
		{
			get 
			{ 
				return (VerticalTabPage)this.List[index]; 
			} 

			set 
			{ 
				this.List[index] = value;
			}
		}

		#endregion

		#region Add and Insert methods

		/// <summary>
		/// Adds the specified <b>VerticalTabPage</b> object to the end of the collection.
		/// <seealso cref="Insert"/>
		/// <seealso cref="Remove"/>
		/// <seealso cref="SetTabIndex"/>
		/// <seealso cref="VerticalTabControl"/>
		/// <seealso cref="VerticalTabPage"/>
		/// </summary>
		/// <param name="tabPage">Tab page object.</param>
		/// <returns>Index of the added object.</returns>
		public int Add(VerticalTabPage tabPage)
		{
			return this.List.Add(tabPage);
		}

		/// <summary>
		/// Adds a new <b>VerticalTabPage</b> object to the end of the collection, 
		/// taking the tab page's text.
		/// <seealso cref="Insert"/>
		/// <seealso cref="SetTabIndex"/>
		/// <seealso cref="Remove"/>
		/// <seealso cref="VerticalTabControl"/>
		/// <seealso cref="VerticalTabPage"/>
		/// </summary>
		/// <param name="text">Tab page's text.</param>
		/// <returns>Newly created object.</returns>
		public VerticalTabPage Add(string text)
		{
			VerticalTabPage tabPage = new VerticalTabPage(text);
			this.List.Add(tabPage);
			return tabPage;
		}

		/// <summary>
		/// Inserts the specified <b>VerticalTabPage</b> object into the collection.
		/// <seealso cref="Add"/>
		/// <seealso cref="Remove"/>
		/// <seealso cref="SetTabIndex"/>
		/// <seealso cref="VerticalTabControl"/>
		/// <seealso cref="VerticalTabPage"/>
		/// </summary>
		/// <param name="index">Index where the tab page will be inserted.</param>
		/// <param name="tabPage">Tab page object.</param>
		public void Insert(int index, VerticalTabPage tabPage)
		{
			this.List.Insert(index, tabPage);
		}

		/// <summary>
		/// Changes the index of the tab page in the collection.
		/// <seealso cref="Add"/>
		/// <seealso cref="Remove"/>
		/// <seealso cref="VerticalTabControl"/>
		/// <seealso cref="VerticalTabPage"/>
		/// </summary>
		/// <param name="tabPage">Tab page object.</param>
		/// <param name="index">New index of the tab page.</param>
		public void SetTabIndex(VerticalTabPage tabPage, int index)
		{
			// Check if tab page exsists in the collection
			if(this.List.Contains(tabPage))
			{
				// Remove item from the list without notifications
				this.InnerList.Remove(tabPage);

				// Check insert index
				if(index > this.Count)
				{
					index = this.Count;
				}

				// Insert item into the list without notifications
				this.InnerList.Insert(index, tabPage);

				// Notify control that tab pages where changed
				this.tabControl.OnTabPagesChanged();
			}
		}

		/// <summary>
		/// Inserts a new tab page into the collection.
		/// <seealso cref="Add"/>
		/// <seealso cref="Remove"/>
		/// <seealso cref="SetTabIndex"/>
		/// <seealso cref="VerticalTabControl"/>
		/// <seealso cref="VerticalTabPage"/>
		/// </summary>
		/// <param name="index">Index where the tab page will be inserted.</param>
		/// <param name="text">Tab page's text.</param>
		public void Insert(int index, string text)
		{
			VerticalTabPage tabPage = new VerticalTabPage(text);
			this.List.Insert(index, tabPage);
		}

		/// <summary>
		/// Removes the specified tab page from the collection.
		/// <seealso cref="Add"/>
		/// <seealso cref="Insert"/>
		/// <seealso cref="SetTabIndex"/>
		/// <seealso cref="VerticalTabControl"/>
		/// <seealso cref="VerticalTabPage"/>
		/// </summary>
		/// <param name="tabPage">Tab page to remove.</param>
		public void Remove(VerticalTabPage tabPage)
		{
			this.List.Remove(tabPage);
		}

		#endregion

		#region Items Inserting and Removing Notification methods

		/// <summary>
		/// Called before an item is inserted into the collection.
		/// </summary>
		/// <param name="index">Index where the item is being inserted.</param>
		/// <param name="value">Inserted object.</param>
		protected override void OnInsert(int index, object value)
		{
			VerticalTabPage	tabPage = (VerticalTabPage)value;

			// Set referense to the tab control
			tabPage.tabControl = this.tabControl;

			// Set referense to the tab control image list
			if(this.tabControl.ImageList != null)
			{
				tabPage.TabButton.ImageList = this.tabControl.ImageList;
			}

			// Set button orientation
			tabPage.TabButton.Vertical = this.tabControl.Vertical;

			// Add panel and button controls as child controls of the TabControl
			if(!this.tabControl.Contains(tabPage))
			{
				this.tabControl.Controls.Add(tabPage.TabButton);
				this.tabControl.Controls.Add(tabPage);
			}
		}

		/// <summary>
		/// Called before an item is removed from the collection.
		/// </summary>
		/// <param name="index">Index of the item to be removed.</param>
		/// <param name="value">Object to be removed.</param>
		protected override void OnRemove(int index, object value)
		{
			VerticalTabPage	tabPage = (VerticalTabPage)value;

			// Remove panel and button controls from child controls of the TabControl
			if(this.tabControl.Contains(tabPage))
			{
				this.tabControl.Controls.Remove(tabPage.TabButton);
				this.tabControl.Controls.Remove(tabPage);
			}
		}

		/// <summary>
		/// Called before all items are removed from the collection.
		/// </summary>
		protected override void OnClear()
		{
			for(int tabIndex = 0; tabIndex < this.List.Count; tabIndex++)
			{
				OnRemove(tabIndex, this.List[tabIndex]);
			}
		}

		/// <summary>
		/// Called after a new item is inserted into the collection.
		/// </summary>
		/// <param name="index">Index of the inserted item.</param>
		/// <param name="value">Object that was inserted.</param>
		protected override void OnInsertComplete(int index, object value)
		{
			VerticalTabPage	tabPage = (VerticalTabPage)value;

			// Set selected item
			if(this.tabControl.SelectedTab == null)
			{
				this.tabControl.SelectedTab = tabPage;
			}

			// Notify control that tab pages where changed
			this.tabControl.OnTabPagesChanged();
		}

		/// <summary>
		/// Called after an item is removed from the collection.
		/// </summary>
		/// <param name="index">Index of the removed item.</param>
		/// <param name="value">Object that was removed.</param>
		protected override void OnRemoveComplete(int index, object value)
		{
			VerticalTabPage	tabPage = (VerticalTabPage)value;

			// Check if selected tab page should be updated
			if(this.tabControl.SelectedTab == tabPage)
			{
				int newIndex = index;
				if(newIndex >= this.tabControl.TabPages.Count)
				{
					newIndex = this.tabControl.TabPages.Count - 1;
				}
				this.tabControl.SelectedIndex = newIndex;
			}

			// Notify control that tab pages where changed
			this.tabControl.OnTabPagesChanged();
		}

		/// <summary>
		/// Called after all items are removed from the collection.
		/// </summary>
		protected override void OnClearComplete()
		{
			// Clear selected index
			this.tabControl.SelectedTab = null;

			// Notify control that tab pages where changed
			this.tabControl.OnTabPagesChanged();
		}

		#endregion
	}

	/// <summary>
	/// Helper class that draws horizontally tiled image .
	/// </summary>
	public class TiledPictureBox : PictureBox
	{
		#region Constructor

		/// <summary>
		/// Default constructor.
		/// </summary>
		public TiledPictureBox()
		{
			// Change control style
			this.SetStyle(ControlStyles.ResizeRedraw, true);
		}

		#endregion

		#region Overriden painting methods

		protected override void OnPaintBackground( PaintEventArgs e )
		{
			if(this.Image != null)
			{
				using( Bitmap bitmap = new Bitmap(e.ClipRectangle.Width, e.ClipRectangle.Height) )
				{
					using( Graphics graphics = Graphics.FromImage(bitmap) )
					{
						ImageAttributes imageAttributes = new ImageAttributes();
						for(int curentX = 0; curentX < e.ClipRectangle.Width; curentX += this.Image.Width)
						{
							graphics.DrawImage(
								this.Image, 
								new Rectangle(curentX, 0, this.Image.Width, e.ClipRectangle.Height), 
								0, e.ClipRectangle.Y, this.Image.Width, e.ClipRectangle.Height,
								GraphicsUnit.Pixel,
								imageAttributes);
						}

						e.Graphics.DrawImage(
							bitmap,
							e.ClipRectangle, 
							0, 0, bitmap.Width, bitmap.Height,
							GraphicsUnit.Pixel,
							imageAttributes);
					}
				}
			}
		}

		protected override void OnPaint( PaintEventArgs e )
		{
		}

		#endregion
	}

	/// <summary>
	/// Helper class that adds background image to the label.
	/// </summary>
	public class LabelWithBackImage : Label
	{
		#region Constructor

		/// <summary>
		/// Default constructor.
		/// </summary>
		public LabelWithBackImage()
		{
			// Change control style
			this.SetStyle(ControlStyles.ResizeRedraw, true);
		}

		#endregion

		#region Overriden painting methods

		internal	Image	BackImage = null;

		protected override void OnPaintBackground( PaintEventArgs e )
		{
			base.OnPaintBackground( e );
		}

		protected override void OnPaint( PaintEventArgs e )
		{
			// Clear background
			e.Graphics.Clear(this.BackColor);

			// Draw back image
			if(this.BackImage != null)
			{
				int imageLeft = this.Right - this.BackImage.Width - this.Left;
				Rectangle	dest = e.ClipRectangle;
				if(dest.X < imageLeft)
				{
					dest.Width -= imageLeft - dest.X;
					dest.X = imageLeft;
				}
				ImageAttributes imageAttributes = new ImageAttributes();
				e.Graphics.DrawImage(
					this.BackImage,
					dest, 
					dest.X - imageLeft, 
					e.ClipRectangle.Y + this.Top, 
					dest.Width, dest.Height,
					GraphicsUnit.Pixel,
					imageAttributes);
			}

			// Get text position
			Rectangle	textRect = new Rectangle(this.ClientRectangle.Location, this.ClientRectangle.Size);
			textRect.X += 5;
			textRect.Width -= 10;

			// Draw text
			StringFormat format = new StringFormat();
			format.LineAlignment = StringAlignment.Center;
			format.Alignment = StringAlignment.Near;
			format.Trimming = StringTrimming.EllipsisCharacter;
			format.FormatFlags = StringFormatFlags.LineLimit;
			using( SolidBrush brush = new SolidBrush( this.ForeColor ) )
			{
				e.Graphics.DrawString(this.Text, this.Font, brush, textRect, format);
			}

			format.Dispose();
		}

		#endregion
	}

}

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 Code Project Open License (CPOL)


Written By
Software Developer
Pakistan Pakistan
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.
This is a Organisation

33 members

Comments and Discussions