using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Windows.Forms;
using VEPROMS.CSLA.Library;
using System.Drawing;
using System.Text.RegularExpressions;
namespace Volian.Controls.Library
{
	public partial class StepPanel : Panel
	{
		#region Fields
		private static readonly log4net.ILog _MyLog = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
		/// 
		/// Procedure Item Info - Top ItemInfo
		/// 
		private ItemInfo _MyProcedureItemInfo;
		/// 
		/// This is not correct.  There should be a dictionary of Section Layouts
		/// 
		private StepSectionLayoutData _MyStepSectionLayoutData;
		/// 
		/// Lookup Table to convert ItemInfo.ItemID to StepItem
		/// 
		internal Dictionary _LookupStepItems;
		public StepItem FindItem(ItemInfo itemInfo)
		{
			if (itemInfo == null) return null;
			if (!_LookupStepItems.ContainsKey(itemInfo.ItemID)) return null;
			return _LookupStepItems[itemInfo.ItemID];
		}
		/// 
		/// Currently selected RichTextBox
		/// 
		private StepRTB _SelectedStepRTB = null;
		/// 
		/// Currently selected ItemInfo
		/// 
		internal ItemInfo _SelectedItemInfo;
		private int _ItemMoving = 0;
		private StepPanelSettings _MyStepPanelSettings;
		private int _MaxRNO = -1; // TODO: Need to calculate MaxRNO on a section basis rather than for a panel
		private Font _MyFont = null;
		private Font _ProcFont = new Font("Arial", 12, FontStyle.Bold);
		private Font _SectFont = new Font("Arial", 10, FontStyle.Bold);
		private Font _StepFont = new Font("Arial", 10);
		private Color _ActiveColor = Color.SkyBlue;
#if (DEBUG)
		private Color _InactiveColor = Color.Linen;
		private Color _TabColor = Color.Beige;
		private Color _PanelColor = Color.LightGray;
#else
		private Color _InactiveColor = Color.White;
		private Color _TabColor = Color.White;
		private Color _PanelColor = Color.White;
#endif
		// Whether panel is in view or edit mode.  Toggled from steprtb
		// or set based on approval/multi-user (these two will be done
		// later.
		public E_ViewMode PanelViewEditMode = E_ViewMode.Edit;
		internal string _LastAdjust="";
		private bool _ShowLines = true;
		private Graphics _MyGraphics = null;
		private int _DPI = 0;
		#endregion
		#region Item Events
		/// 
		/// Occurs when the user clicks tab of a StepItem
		/// 
		public event StepPanelEvent ItemClick;
		/// 
		/// Checks to see if the 'ItemClick' event is handled and launches it
		/// 
		/// 
		/// 
		internal void OnItemClick(object sender, StepPanelEventArgs args)
		{
		  if (ItemClick != null) ItemClick(sender, args);
		}
		private bool ItemSelectionChangeShown = false; // This keeps OnItemSelectedChanged from being called twice when an item is selected.
		/// 
		/// Occurs when the selected StepItem changes
		/// 
		public event ItemSelectedChangedEvent ItemSelectedChanged;
		/// 
		/// Checks to see if the 'ItemSelectedChanged' event is handled and launches it
		/// 
		/// 
		/// 
		internal void OnItemSelectedChanged(object sender, ItemSelectedChangedEventArgs args)
		{
			ItemSelectionChangeShown = true;//Remember that you have run already
			//vlnStackTrace.ShowStack(string.Format("OnItemSelectedChanged {0}",args.MyItemInfo.ItemID));
			if (ItemSelectedChanged != null) ItemSelectedChanged(sender, args);
		}
		/// 
		/// Occurs when the user clicks on the Attachment Expander
		/// 
		public event StepPanelAttachmentEvent AttachmentClicked;
		/// 
		/// Checks to see if the 'AttachmentClicked' event is handled and launches it
		/// 
		/// 
		/// 
		internal void OnAttachmentClicked(object sender, StepPanelAttachmentEventArgs args)
		{
			if (AttachmentClicked != null) AttachmentClicked(sender, args);
			else MessageBox.Show(args.MyStepItem.MyItemInfo.MyContent.MyEntry.MyDocument.DocumentTitle, "Unhandled Attachment Click", MessageBoxButtons.OK, MessageBoxIcon.Information);
		}
		// Edit/View mode change
		public event StepPanelModeChangeEvent ModeChange;
		internal void OnModeChange(object sender, StepRTBModeChangeEventArgs args)
		{
			PanelViewEditMode = args.ViewMode;
			ModeChange(sender, args);
		}
		// various selections from steptabribbon that need to filter up to frmveproms
		// such as 'global search', 'bookmarks'
		public event StepPanelTabDisplayEvent TabDisplay;
		internal void OnTabDisplay(object sender, StepPanelTabDisplayEventArgs args)
		{
			TabDisplay(sender, args);
		}
		// close section, if deleting word doc section
		public event StepPanelWordSectionCloseEvent WordSectionClose;
		internal void OnWordSectionClose(object sender, WordSectionEventArgs args)
		{
			WordSectionClose(sender, args);
		}
		// if section deleted, have event to flag in other UI panels
		public event StepPanelWordSectionDeletedEvent WordSectionDeleted;
		internal void OnWordSectionDeleted(object sender, WordSectionEventArgs args)
		{
			WordSectionDeleted(sender, args);
		}
		#endregion
		#region Link Events
		/// 
		/// Occurs when the user moves onto or off of a Link
		/// 
		public event StepPanelLinkEvent LinkActiveChanged;
		/// 
		/// Checks to see if the 'LinkActiveChanged' event is handled and launches it
		/// 
		/// 
		/// 
		internal void OnLinkActiveChanged(object sender, StepPanelLinkEventArgs args)
		{
			if (LinkActiveChanged != null) LinkActiveChanged(sender, args);
			else MessageBox.Show(args.LinkInfoText, "Unhandled Link Active Changed", MessageBoxButtons.OK, MessageBoxIcon.Information);
		}
		/// 
		/// Occurs when the user chooses to Insert a Transition
		/// 
		public event StepPanelLinkEvent LinkInsertTran;
		/// 
		/// Checks to see if the 'LinkInsertTran' event is handled and launches it
		/// 
		/// 
		/// 
		internal void OnLinkInsertTran(object sender, StepPanelLinkEventArgs args)
		{
			if (LinkInsertTran != null) LinkInsertTran(sender, args);
			else MessageBox.Show(args.LinkInfoText, "Unhandled Link Insert Tran", MessageBoxButtons.OK, MessageBoxIcon.Information);
		}
		/// 
		/// Occurs when the user chooses to Insert an RO
		/// 
		public event StepPanelLinkEvent LinkInsertRO;
		/// 
		/// Checks to see if the 'LinkInsertRO' event is handled and launches it
		/// 
		/// 
		/// 
		internal void OnLinkInsertRO(object sender, StepPanelLinkEventArgs args)
		{
			if (LinkInsertRO != null) LinkInsertRO(sender, args);
			else MessageBox.Show(args.LinkInfoText, "Unhandled Link Insert RO", MessageBoxButtons.OK, MessageBoxIcon.Information);
		}
		/// 
		/// Occurs when the user clicks a Link
		/// 
		public event StepPanelLinkEvent LinkClicked;
		/// 
		/// Checks to see if the 'LinkClicked' event is handled and launches it
		/// 
		/// 
		/// 
		internal void OnLinkClicked(object sender, StepPanelLinkEventArgs args)
		{
			if (LinkClicked != null) LinkClicked(sender, args);
			else MessageBox.Show(args.LinkInfoText, "Unhandled Link Click", MessageBoxButtons.OK, MessageBoxIcon.Information);
		}
		/// 
		/// Occurs when the user chooses to modify a Transition
		/// 
		public event StepPanelLinkEvent LinkModifyTran;
		/// 
		/// Checks to see if the 'LinkModifyTran' event is handled and launches it
		/// 
		/// 
		/// 
		internal void OnLinkModifyTran(object sender, StepPanelLinkEventArgs args)
		{
			if (LinkModifyTran != null) LinkModifyTran(sender, args);
			else MessageBox.Show(args.LinkInfoText, "Unhandled Link Modify Tran", MessageBoxButtons.OK, MessageBoxIcon.Information);
		}
		/// 
		/// Occurs when the user chooses to modify an RO
		/// 
		public event StepPanelLinkEvent LinkModifyRO;
		/// 
		/// Checks to see if the 'LinkModifyRO' event is handled and launches it
		/// 
		/// 
		/// 
		internal void OnLinkModifyRO(object sender, StepPanelLinkEventArgs args)
		{
			if (LinkModifyRO != null) LinkModifyRO(sender, args);
			else MessageBox.Show(args.LinkInfoText, "Unhandled Link Modify RO", MessageBoxButtons.OK, MessageBoxIcon.Information);
		}
		#endregion
		#region Constructors
		public StepPanel()
		{
			InitializeComponent();
			this.BackColorChanged += new EventHandler(StepPanel_BackColorChanged);
#if(DEBUG)
			this.Paint += new PaintEventHandler(StepPanel_Paint);
			this.DoubleClick += new EventHandler(StepPanel_DoubleClick); // Toggles Vertical lines on and off
#else
			this.BackColor = Color.White;
#endif
			this.AutoScroll = true;
		}
		public StepPanel(IContainer container)
		{
			container.Add(this);
			InitializeComponent();
			this.BackColorChanged += new EventHandler(StepPanel_BackColorChanged);
#if(DEBUG)
			this.Paint += new PaintEventHandler(StepPanel_Paint); // Toggles Vertical lines on and off
			this.DoubleClick += new EventHandler(StepPanel_DoubleClick);
#else
			this.BackColor = Color.White;
#endif
			this.AutoScroll = true;
		}
		void StepPanel_BackColorChanged(object sender, EventArgs e)
		{
			// Walk through controls & set colors
			InactiveColor = PanelColor = BackColor;
			foreach (Control ctrl in Controls)
			{
				if (ctrl.GetType() == typeof(StepItem))
				{
					StepItem rtb = (StepItem)ctrl;
					rtb.BackColor = BackColor;
				}
			}
		}
		#endregion
		#region Private Methods
		/// 
		/// Expands an Item and It's Parents as need to display an item
		/// 
		/// Item to Expand
		private void ExpandAsNeeded(ItemInfo myItemInfo)
		{
			int id = myItemInfo.ItemID;
			if (!_LookupStepItems.ContainsKey(id)) // If the item is not currently displayed
				ExpandAsNeeded((ItemInfo)myItemInfo.ActiveParent); // Expand it's parent
			if (_LookupStepItems.ContainsKey(id)) // Expanding Parent should have added it to _LookupStepItems
			{
				StepItem itm = _LookupStepItems[id];
				ItemInfo ii = myItemInfo.ActiveParent as ItemInfo;
				if (itm.Visible == false && ii != null)
					ExpandAsNeeded((ItemInfo)myItemInfo.ActiveParent);
				itm.AutoExpand(); // Expand it if it should expand
			}
		}
		#endregion
		#region Properties
		public StepTabPanel MyStepTabPanel
		{ get { return Parent as StepTabPanel; } }
		/// 
		/// Procedure Item Info - Top ItemInfo
		/// Get and Set - Set stes-up all of the 
		/// 
		public ItemInfo MyProcedureItemInfo
		{
			get { return _MyProcedureItemInfo; }
			set
			{
				//// TIMING: DisplayItem.TimeIt("pMyItem Start");
				_MyProcedureItemInfo = value;
				if(value != null)
					_MyStepSectionLayoutData = _MyProcedureItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.StepSectionLayoutData;
				//// TIMING: DisplayItem.TimeIt("pMyItem Layout");
				//this.Layout += new LayoutEventHandler(DisplayPanel_Layout);
				//this.Scroll += new ScrollEventHandler(DisplayPanel_Scroll);
				//// TIMING: DisplayItem.TimeIt("pMyItem Scroll");
				Controls.Clear();
				_LookupStepItems = new Dictionary();
				//// TIMING: DisplayItem.TimeIt("pMyItem Clear");
				//SuspendLayout();
				StepItem tmpStepItem = new StepItem(_MyProcedureItemInfo, this, null, ChildRelation.None, false);
				//ResumeLayout();
				//// TIMING: DisplayItem.TimeIt("pMyItem End");
			}
		}
		public void Reset()
		{
			ItemInfo parent = SelectedItemInfo.ActiveParent as ItemInfo;
			if (parent != null) ItemInfo.ResetParts(parent.ItemID);  // Force data to reload
			// The following line actually reloads the procedure item
			MyProcedureItemInfo = MyProcedureItemInfo;		// see get/set above. - Load Procedure and Sections
			// The following line expands the items needed to display SelectedItemInfo
			ExpandAsNeeded(SelectedItemInfo);
		}
		/// 
		/// Get or Set currently selected RichTextBox (StepRTB)
		/// 
		public StepRTB SelectedStepRTB
		{
			get { return _SelectedStepRTB; }
			set 
			{
				StepRTB lastRTB = _SelectedStepRTB;
				if(value != null)
					value.BackColor = ActiveColor; // Set the active color
				if (_SelectedStepRTB == value) return; // Same - No Change
				if (_SelectedStepRTB != null)
				{
					_SelectedStepRTB.BackColor = InactiveColor;
					_SelectedStepRTB.SaveText(); // Save any changes to the text
					_SelectedStepRTB.SaveConfig();		// This may be redundant
					_SelectedStepRTB.RTBFillIn(false);
					_SelectedStepRTB.ViewRTB = true;
				}
				_SelectedStepRTB = value;
				if (value != null)
				{
					_SelectedStepRTB.ViewRTB =  PanelViewEditMode == E_ViewMode.View;
					_SelectedStepRTB.RTBFillIn(PanelViewEditMode != E_ViewMode.View);
					if (_SelectedItemInfo.ItemID != value.MyItemInfo.ItemID)
						SelectedItemInfo = value.MyItemInfo;
				}
				//vlnStackTrace.ShowStack("_DisplayRTB = {0}", _DisplayRTB.MyItem.ItemID);// Show StackTrace
			}
		}
		/// 
		/// Gets or Sets the SelectedItemInfo
		/// Activates and Expands as necessary
		/// 
		public ItemInfo SelectedItemInfo
		{
			get { return _SelectedItemInfo; }
			set
			{
				//vlnStackTrace.ShowStack("SelectedItemInfo {0} => {1}",_SelectedItemInfo, value);
				_SelectedItemInfo = value;
				int id = value.ItemID;
				ExpandAsNeeded(value);
				// reset the entire step panel if the item isn't found.
				if (!_LookupStepItems.ContainsKey(id)) Reset();
				StepItem itm = _LookupStepItems[id];
				ItemSelectionChangeShown = false;//OnItemSelectedChanged has not run yet.
				itm.ItemSelect();
				if (!ItemSelectionChangeShown) OnItemSelectedChanged(this, new ItemSelectedChangedEventArgs(itm));
				//vlnStackTrace.ShowStack("_ItemSelected = {0}", _ItemSelected.ItemID);// Show StackTrace
			}
		}
		private bool _DisplayItemChanging = false;
		public bool DisplayItemChanging
		{
			get { return _DisplayItemChanging; }
			set { _DisplayItemChanging = value; }
		}
		/// 
		/// Returns the SelectedStepItem
		/// 
		public StepItem SelectedStepItem
		{
			get { return (_SelectedItemInfo != null) ? _LookupStepItems[_SelectedItemInfo.ItemID] : null; }
		}
		/// 
		/// Displays the selected StepItem
		/// 
		public void ItemShow()
		{
			if (_SelectedItemInfo != null)
			{
				SelectedStepItem.ItemShow();
				OnItemSelectedChanged(this, new ItemSelectedChangedEventArgs(SelectedStepItem));
			}
		}
		public new void MouseWheel(MouseEventArgs e)
		{
			base.OnMouseWheel(e);
		}
		/// 
		/// Used to track movement other than scrolling
		/// 0 - Indicates no other movement
		/// > 0 - Indicates that other movement is happening
		/// 
		public int ItemMoving
		{
			get { return _ItemMoving; }
			set { _ItemMoving = value; }
		}
		/// 
		/// Lazy loaded StepPanelSettings
		/// 
	public StepPanelSettings MyStepPanelSettings
	{
		get 
		{
			if (_MyStepPanelSettings == null) _MyStepPanelSettings = new StepPanelSettings(this);
			return _MyStepPanelSettings;
		}
		set { _MyStepPanelSettings = value;}
	}
		/// 
		/// Gets or Sets the font for the Panel
		/// 
		public Font MyFont
		{
			get { return _MyFont; }
			set { _ProcFont = _SectFont = _StepFont = _MyFont = value; }
		}
		/// 
		/// Gets or sets the font for the Procedure Text
		/// 
		public Font ProcFont
		{
			get { return _ProcFont; }
			set { _ProcFont = value; }
		}
		/// 
		/// Gets or sets the font for the Section Text
		/// 
		public Font SectFont
		{
			get { return _SectFont; }
			set { _SectFont = value; }
		}
		/// 
		/// Gets or sets the Step Font
		/// 
		public Font StepFont
		{
			get { return _StepFont; }
			set { _StepFont = value; }
		}
		/// 
		/// Gets or Sets the Active Color for the Panel
		/// 
		public Color ActiveColor
		{
			get { return _ActiveColor; }
			set { _ActiveColor = value; }
		}
		/// 
		/// Gets or sets the InActive Color for the Panel
		/// 
		public Color InactiveColor
		{
			get { return _InactiveColor; }
			set { _InactiveColor = value; }
		}
		/// 
		/// Gets or sets the Tab Color
		/// 
		public Color TabColor
		{
			get { return _TabColor; }
			set { _TabColor = value; }
		}
		/// 
		/// Gets or sets the Panel Color
		/// 
		public Color PanelColor
		{
			get { return _PanelColor; }
			set { _PanelColor = value;
			BackColor = value;
		}
		}
		#endregion
		#region DisplayConversions
		/// 
		/// gets a Graphic object for the panel
		/// 
		public Graphics MyGraphics
		{
			get
			{
				if (_MyGraphics == null)
					_MyGraphics = CreateGraphics();
				return _MyGraphics;
			}
		}
		/// 
		/// Gets the DPI setting for the current graphics setting
		/// 
		internal int DPI
		{
			get 
			{
				if (_DPI == 0)
					_DPI = Convert.ToInt32(MyGraphics.DpiX);
				return _DPI; 
			}
		}
		/// 
		/// Converts an integer value from Twips to Pixels
		/// 
		/// 
		/// 
		public int ToDisplay(int value)
		{
			//return (DPI * value) / 864;
			return (DPI * value) / 72;
		}
		/// 
		/// Converts an integer? value from Twips to Pixels
		/// 
		/// 
		/// 
		public int ToDisplay(int? value)
		{
			return ToDisplay((int)value);
		}
		/// 
		/// Converts an string value from Twips to Pixels
		/// 
		/// 
		/// 
		public int ToDisplay(string value)
		{
			return ToDisplay(Convert.ToInt32(value));
		}
		/// 
		/// Converts a value from a list in a string from Twips to Pixels
		/// 
		/// 
		/// 
		public int ToDisplay(string value,int i)
		{
			string s = value.Split(",".ToCharArray())[i];
			return ToDisplay(s);
		}
		#endregion
		#region Debug Methods
		/// 
		/// Gets or sets ShowLines so that vertical lines are shown for debugging purposes
		/// 
		public bool ShowLines
		{
			get { return _ShowLines; }
			set { _ShowLines = value; }
		}
		/// 
		/// Draw a vertical line
		/// 
		/// 
		/// 
		private void VerticalLine(Graphics g, int x)
		{
			Pen bluePen = new Pen(Color.CornflowerBlue,1);
			g.DrawLine(bluePen, x, 0, x, this.Height);
		}
		/// 
		/// Toggle the vertical lines on and off
		/// 
		/// 
		/// 
		private void StepPanel_DoubleClick(object sender, EventArgs e)
		{
			ShowLines = !ShowLines;
			Refresh();
		}
		private void StepPanel_Paint(object sender, PaintEventArgs e)
		{
			if (ShowLines)
			{
				//int fifth = Height / 5;
				//Rectangle r1 = new Rectangle(0, 0, Width, Height - fifth);
				////Brush b = new System.Drawing.Drawing2D.LinearGradientBrush(r1, Color.FromArgb(128, 0, 32), Color.FromArgb(96, 0, 16), 90);
				//Brush b = new System.Drawing.Drawing2D.LinearGradientBrush(r1, Color.FromArgb(255,128, 0, 32), Color.FromArgb(255,96, 0, 16),System.Drawing.Drawing2D.LinearGradientMode.Vertical);
				//e.Graphics.FillRectangle(b, r1);
				//r1 = new Rectangle(0, Height - fifth, Width, fifth);
				//b = new System.Drawing.Drawing2D.LinearGradientBrush(r1, Color.FromArgb(255,96, 0, 16), Color.FromArgb(255,128, 0, 32), 90);
				//e.Graphics.FillRectangle(b, r1);
				//VerticalLine(e.Graphics, 60);
				//VerticalLine(e.Graphics, 102);
				//VerticalLine(e.Graphics, 415);
			}
		}
		/// 
		/// Output all of the StepItem controls to the log
		/// 
		private void ListControls()
		{
			// Walk through the controls and find the next control for each
			if(_MyLog.IsInfoEnabled)_MyLog.InfoFormat("'Item','Next'");
			foreach (Control control in Controls)
				if (control.GetType() == typeof(StepItem))
				{
					StepItem rtb = (StepItem)control;
					StepItem nxt = rtb.NextDownStepItem;
					if(_MyLog.IsInfoEnabled)_MyLog.InfoFormat("{0},{1}", rtb.MyID, nxt == null ? 0 : nxt.MyID);
				}
		}
		#endregion
		#region Cursor Movement Methods
		/// 
		/// Finds the Displayed 'top' child for a given item. Used for down arrow.
		/// 
		/// ItemInfo
		/// 
		private ItemInfo TopPart(ItemInfo ii)
		{
			ExpandAsNeeded(ii);
			if (ii.Cautions != null) return TopPart(ii.Cautions[0]);
			if (ii.Notes != null) return TopPart(ii.Notes[0]);
			return (ii);
		}
		/// 
		/// Finds the Displayed 'bottom' child for a given item. Used for up arrow.
		/// 
		/// ItemInfo
		/// 
		private ItemInfo BottomPart(ItemInfo ii)
		{
			ExpandAsNeeded(ii);
			if (ii.RNOs != null && ii.RNOLevel >= ii.ColumnMode) return BottomPart(ii.RNOs[0]);
			if (ii.Sections != null) return BottomPart(ii.Sections[0].LastSibling);
			if (ii.Steps != null) return BottomPart(ii.Steps[0].LastSibling);
			if (ii.Tables != null) return BottomPart(ii.Tables[0].LastSibling);
			return ii;
		}
		/// 
		/// Supports cursor movement between richtext boxes, including arrow keys/page up,down/
		/// ctrl Home,End
		/// 
		/// StepRTB
		/// Point
		/// E_ArrowKeys
		public void CursorMovement(StepRTB rtb, Point position, E_ArrowKeys arrow)
		{
			ItemInfo ii = null;
			switch (arrow)
			{
				case E_ArrowKeys.Up:
				case E_ArrowKeys.CtrlUp:
					ii = ArrowUp(rtb.MyItemInfo);
					if (ii != null) SelectedStepRTB = _LookupStepItems[ii.ItemID].MyStepRTB;
					break;
				case E_ArrowKeys.Down:
				case E_ArrowKeys.CtrlDown:
					ii = ArrowDown(rtb.MyItemInfo);
					if (ii != null) SelectedStepRTB = _LookupStepItems[ii.ItemID].MyStepRTB;
					break;
				case E_ArrowKeys.Right:
				case E_ArrowKeys.CtrlRight:
					if (rtb.MyItemInfo.RNOs != null)
						SelectedStepRTB = _LookupStepItems[rtb.MyItemInfo.RNOs[0].ItemID].MyStepRTB;
					break;
				case E_ArrowKeys.Left:
				case E_ArrowKeys.CtrlLeft:
					if (!rtb.MyItemInfo.IsProcedure)
						SelectedStepRTB = _LookupStepItems[rtb.MyItemInfo.MyParent.ItemID].MyStepRTB;
					break;
				default:
					break;
			}
		}
		private ItemInfo ArrowUp(ItemInfo ii)
		{
			// if on RNO, check display mode (1 column/2 column, etc) and how deep RNO is before going to
			// parents substeps.
			if (ii.IsRNO && ii.MyParent.Steps != null && ii.RNOLevel >= ii.ColumnMode) return BottomPart(ii.MyParent.Steps[0].LastSibling);
			// If on top note and parent has cautions - go to bottom caution
			if (ii.IsNoteStructure && ii.MyParent != null && ii.MyParent.Cautions != null) return BottomPart(ii.MyParent.Cautions[0].LastSibling);
			if (ii.IsCautionStructure || ii.IsNoteStructure)
			{
				if (ii.MyParent.MyPrevious != null) return BottomPart(ii.MyParent.MyPrevious);
				return ii.MyParent.MyParent;
			}
			// If has note, BottomPart of last sibling of the note
			if (ii.Notes != null) return BottomPart(ii.Notes[0].LastSibling);
			// If has caution, BottomPart of last sibling of the caution
			if (ii.Cautions != null) return BottomPart(ii.Cautions[0].LastSibling);
			// If previous sibling, BottomPart of previous sibling
            if (ii.MyPrevious != null && ii.IsProcedure == false) return BottomPart(ii.MyPrevious);
			// Go to parent until at procedure
			if (!ii.IsProcedure) return (ii.MyParent);
			return null;
		}
		private ItemInfo ArrowDown(ItemInfo ii)
		{
			return ArrowDown(ii, true, true);
		}
		private ItemInfo ArrowDown(ItemInfo ii, bool lookAtSub, bool lookAtRNO)
		{
			if (ii.IsSection || ii.IsProcedure)
			{
				if (lookAtSub && ii.Sections != null) return TopPart(ii.Sections[0]);
				if (lookAtSub && ii.Steps != null) return TopPart(ii.Steps[0]);
				if (ii.IsSection && ii.NextItems != null) return TopPart(ii.NextItems[0]);
			}
			else
			{
				// Subitems - go to top part of subitem  
				// (the lookAtSub prevented looping within a substep group at same level)
				if (lookAtSub && ii.Steps != null) return TopPart(ii.Steps[0]);
				if (lookAtSub && ii.Tables != null) return TopPart(ii.Tables[0]);
				// RNOs: Use PMode (column)
				if (lookAtRNO && ii.RNOs != null && ii.RNOLevel >= ii.ColumnMode) return TopPart(ii.RNOs[0]);
				// Nextsibling - go to top part of sibling
				// TODO: RHM - NextItems was not null when it should have been after delete of a note below a caution
				if (ii.NextItems != null && ii.NextItemCount > 0) return TopPart(ii.NextItems[0]);
				// If on caution, if parent has note - go to note
				if (ii.IsCautionStructureFirstSib && ii.MyParent.Notes != null) return ii.MyParent.Notes[0];
				// If on caution, if parent !has note or if on note go to parent
				if ((ii.IsCautionStructureFirstSib && ii.MyParent.Notes == null) || ii.IsNoteStructureFirstSib) return ii.MyParent;
				// Recursively call with parent until at procedure
				if (!ii.IsProcedure) return (ArrowDown(ii.MyParent, false, ii.MyParent.RNOLevel==ii.RNOLevel));
			}
			return null;
		}
		internal void StepCursorKeys(StepRTB rtb, KeyEventArgs keyargs)
		{
			ItemInfo ii = rtb.MyItemInfo;
			if (ii.IsSection || ii.IsProcedure) return;
			while (!ii.IsHigh)
			{
				ii = ii.MyParent;
			}
			switch (keyargs.KeyCode)
			{
				// for home/end, control key must be pressed too, but this is checked
				// before here.
				case Keys.Home:
					ii = ii.FirstSibling;
					break;
				case Keys.End:
					ii = ii.LastSibling;
					break;
				case Keys.PageDown:
					ii = ii.NextItems == null ? null : ii.NextItems[0];
					break;
				case Keys.PageUp:
					ii = ii.MyPrevious;
					break;
			}
			if (ii == null) return;
			SelectedStepRTB = _LookupStepItems[ii.ItemID].MyStepRTB;
		}
		#endregion
	}
	[TypeConverter(typeof(ExpandableObjectConverter))]
	public partial class StepPanelSettings
	{
		private static readonly log4net.ILog _MyLog = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
		public StepPanelSettings(StepPanel panel)
		{
			_MyStepPanel = panel;
		}
		public StepPanelSettings()
		{
		}
		private StepPanel _MyStepPanel; 
		[Browsable(false)]
		public StepPanel MyStepPanel
		{
			get { return _MyStepPanel; }
			set { _MyStepPanel = value; }
		}
		private float _CircleXOffset = -4;
		[Category("Circle")]
		[DisplayName("Circle Horizontal Offset")]
		public float CircleXOffset
		{
			get { return _CircleXOffset; }
			set { _CircleXOffset = value; if (_MyStepPanel != null) _MyStepPanel.Refresh(); }
		}
		private float _CircleYOffset = -13;
		[Category("Circle")]
		[DisplayName("Circle Vertical Offset")]
		public float CircleYOffset
		{
			get { return _CircleYOffset; }
			set { _CircleYOffset = value; if (_MyStepPanel != null) _MyStepPanel.Refresh(); }
		}
		private Font _CircleFont = new Font("Arial Unicode MS", 23);
		[Category("Circle")]
		[DisplayName("Circle Font")]
		public Font CircleFont
		{
			get { return _CircleFont; }
			set { _CircleFont = value; if(_MyStepPanel != null) _MyStepPanel.Refresh(); }
		}
		private Color _CircleColor = Color.Black;
		[Category("Circle")]
		[DisplayName("Circle Color")]
		public Color CircleColor
		{
			get { return _CircleColor; }
			set { _CircleColor = value; if (_MyStepPanel != null) _MyStepPanel.Refresh(); }
		}
		private int _CircleDiameter = 25;
		[Category("Circle")]
		[DisplayName("Circle Diameter")]
		public int CircleDiameter
		{
			get { return _CircleDiameter; }
			set { _CircleDiameter = value; if (_MyStepPanel != null) _MyStepPanel.Refresh(); }
		}
		private int _CircleWeight = 2;
		[Category("Circle")]
		[DisplayName("Circle Pen Weight")]
		public int CircleWeight
		{
			get { return _CircleWeight; }
			set { _CircleWeight = value; if (_MyStepPanel != null) _MyStepPanel.Refresh(); }
		}
		private float _NumberLocationX = 20F;
		[Category("Number")]
		[DisplayName("Number Location X")]
		public float NumberLocationX
		{
			get { return _NumberLocationX; }
			set { _NumberLocationX = value; if (_MyStepPanel != null) _MyStepPanel.Refresh(); }
		}
		private float _NumberLocationY = 4;
		[Category("Number")]
		[DisplayName("Number Location Y")]
		public float NumberLocationY
		{
			get { return _NumberLocationY; }
			set { _NumberLocationY = value; if (_MyStepPanel != null) _MyStepPanel.Refresh(); }
		}
		private SizeF _NumberSize = new SizeF(200F, 23F);
		[Category("Number")]
		[DisplayName("Number Size")]
		public SizeF NumberSize
		{
			get { return _NumberSize; }
			set { _NumberSize = value;  if (_MyStepPanel != null) _MyStepPanel.Refresh(); }
		}
		private int _TableWidthAdjust = 4;
		[Category("Table")]
		[DisplayName("Table Width Adjust")]
		public int TableWidthAdjust
		{
			get { return _TableWidthAdjust; }
			set { _TableWidthAdjust = value; if (_MyStepPanel != null) _MyStepPanel.Refresh(); }
		}
		private int _CheckOffWeight = 1;
		[Category("CheckOff")]
		[DisplayName("CheckOff Pen Weight")]
		public int CheckOffWeight
		{
			get { return _CheckOffWeight; }
			set { _CheckOffWeight = value; if (_MyStepPanel != null) _MyStepPanel.Refresh(); }
		}
		private Color _CheckOffColor = Color.Black;
		[Category("CheckOff")]
		[DisplayName("CheckOff Color")]
		public Color CheckOffColor
		{
			get { return _CheckOffColor; }
			set { _CheckOffColor = value; if (_MyStepPanel != null) _MyStepPanel.Refresh(); }
		}
		private int _CheckOffSize =12;
		[Category("CheckOff")]
		[DisplayName("CheckOff Size")]
		public int CheckOffSize
		{
			get { return _CheckOffSize; }
			set { _CheckOffSize = value; if (_MyStepPanel != null) _MyStepPanel.Refresh(); }
		}
		private int _CheckOffX =0;
		[Category("CheckOff")]
		[DisplayName("CheckOff X")]
		public int CheckOffX
		{
			get { return _CheckOffX; }
			set { _CheckOffX = value; if (_MyStepPanel != null) _MyStepPanel.Refresh(); }
		}
		private int _CheckOffY =5;
		[Category("CheckOff")]
		[DisplayName("CheckOff Y")]
		public int CheckOffY
		{
			get { return _CheckOffY; }
			set { _CheckOffY = value; if (_MyStepPanel != null) _MyStepPanel.Refresh(); }
		}
	
		private int _ChangeBarWeight = 1;
		[Category("ChangeBar")]
		[DisplayName("ChangeBar Pen Weight")]
		public int ChangeBarWeight
		{
			get { return _ChangeBarWeight; }
			set { _ChangeBarWeight = value; if (_MyStepPanel != null) _MyStepPanel.Refresh(); }
		}
		private Color _ChangeBarColor = Color.Black;
		[Category("ChangeBar")]
		[DisplayName("ChangeBar Color")]
		public Color ChangeBarColor
		{
			get { return _ChangeBarColor; }
			set { _ChangeBarColor = value; if (_MyStepPanel != null) _MyStepPanel.Refresh(); }
		}
	}
	public partial class StepPanelEventArgs
	{
		private StepItem _MyStepItem;
		public StepItem MyStepItem
		{
			get { return _MyStepItem; }
			set { _MyStepItem = value; }
		}
		private MouseEventArgs _MyMouseEventArgs;
		public MouseEventArgs MyMouseEventArgs
		{
			get { return _MyMouseEventArgs; }
			set { _MyMouseEventArgs = value; }
		}
		public StepPanelEventArgs(StepItem myStepItem, MouseEventArgs myMouseEventArgs)
		{
			_MyStepItem = myStepItem;
			_MyMouseEventArgs = myMouseEventArgs;
		}
	}
	public partial class ItemSelectedChangedEventArgs
	{
		private ItemInfo _MyItemInfo;
		public ItemInfo MyItemInfo
		{
			get { return _MyItemInfo; }
			set { _MyItemInfo = value; }
		}
		private StepItem _MyStepItem = null;
		public StepItem MyStepItem
		{
			get { return _MyStepItem; }
			set { _MyStepItem = value; }
		}
		public ItemSelectedChangedEventArgs(ItemInfo myItemInfo)
		{
			_MyItemInfo = myItemInfo;
		}
		public ItemSelectedChangedEventArgs(StepItem myStepItem)
		{
			_MyItemInfo = myStepItem.MyItemInfo;
			_MyStepItem = myStepItem;
		}
	}
	public partial class StepPanelAttachmentEventArgs
	{
		private StepItem _MyStepItem;
		public StepItem MyStepItem
		{
			get { return _MyStepItem; }
			set { _MyStepItem = value; }
		}
		public StepPanelAttachmentEventArgs(StepItem myStepItem)
		{
			_MyStepItem = myStepItem;
		}
	}
	
	public partial class StepPanelLinkEventArgs : EventArgs
	{
		private static readonly log4net.ILog _MyLog = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
		private StepItem _LinkedStepItem;
		public StepItem LinkedStepItem
		{
			get { return _LinkedStepItem; }
			//set { _LinkedStepItem = value; }
		}
		private string _LinkInfoText;
		public string LinkInfoText
		{
			get { return _LinkInfoText; }
		}
		private LinkText _MyLinkText;
		public LinkText MyLinkText
		{
			get { return _MyLinkText;}
		}
		public StepPanelLinkEventArgs(StepItem linkedStepItem, string linkInfoText)
		{
			_LinkedStepItem = linkedStepItem;
			_LinkInfoText = linkInfoText;
			_MyLinkText = new LinkText(_LinkInfoText);
			//if(_MyLog.IsInfoEnabled)_MyLog.InfoFormat("\r\n LinkInfo '{0}'\r\n", linkInfo.LinkText);
		}
	}
	public partial class StepPanelTabDisplayEventArgs : EventArgs
	{
		private string _PanelTabName;
		public string PanelTabName
		{
			get { return _PanelTabName; }
		}
		public StepPanelTabDisplayEventArgs(string panelTabname)
		{
			_PanelTabName = panelTabname;
		}
	}
	public partial class WordSectionEventArgs : EventArgs
	{
		private SectionInfo _MySectionInfo;
		public SectionInfo MySectionInfo
		{
			get { return _MySectionInfo; }
		}
		public WordSectionEventArgs(SectionInfo mySectionInfo)
		{
			_MySectionInfo = mySectionInfo;
		}
	}
	public delegate void StepPanelEvent(object sender, StepPanelEventArgs args);
	public delegate void ItemSelectedChangedEvent(object sender, ItemSelectedChangedEventArgs args);
	public delegate void StepPanelLinkEvent(object sender, StepPanelLinkEventArgs args);
	public delegate void StepPanelAttachmentEvent(object sender, StepPanelAttachmentEventArgs args);
	public delegate void StepRTBLinkEvent(object sender, StepPanelLinkEventArgs args);
	public delegate void StepPanelModeChangeEvent(object sender, StepRTBModeChangeEventArgs args);
	public delegate void StepPanelTabDisplayEvent(object sender, StepPanelTabDisplayEventArgs args);
	public delegate void StepPanelWordSectionCloseEvent(object sender, WordSectionEventArgs args);
	public delegate void StepPanelWordSectionDeletedEvent(object sender, WordSectionEventArgs args);
}