using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Text.RegularExpressions;
using VEPROMS.CSLA.Library;
using JR.Utils.GUI.Forms;
namespace Volian.Controls.Library
{
	
	public partial class ImageItem : EditItem
	{
		#region IEditItem
		// set this for the imageitem so that other code (menuing/ribbons/treeview, etc) will continue to work. Include the MyItemInfo
		public override StepRTB MyStepRTB		
		{
			get { return _MyStepRTB; }
		}
		public override int TableWidth
		{ 
			get 
			{
				return (int)_MyPictureBox.Width + ImageMargin;
			}
		}
		/// 
		/// The left edge of the Tab
		/// 
		public override int ItemLeft
		{
			get { return Left + lblTab.Left; }
			set { Left = value - lblTab.Left; }
		}
		/// 
		/// The Location of the Tab
		/// 
		public override Point ItemLocation
		{
			get { return new Point(Location.X + lblTab.Left, Location.Y); }
			set { Location = new Point(value.X - lblTab.Left, value.Y); }
		}
		/// 
		/// Width of the Tab and Image
		/// 
		public override int ItemWidth
		{
			get { return Width - lblTab.Left; }
			set
			{
				Width = ImageMargin + value + lblTab.Left;
			}
		}
		/// 
		/// Width of the PictureBox
		/// 
		public override int ContentWidth
		{
			get { return _MyPictureBox.Width; }
			set
			{
				Width = value + lblTab.Left + lblTab.Width;
			}
		}
		public override int BorderWidth { get { return (_MyPictureBox.Width - _MyPictureBox.ClientRectangle.Width); } }
		/// 
		/// Location of the PictureBox
		/// 
		public override Point ContentLocation
		{
			get { return new Point(Location.X + _MyPictureBox.Left, Location.Y); }
			set { Location = new Point(value.X - _MyPictureBox.Left, value.Y); }
		}
		/// 
		/// Left edge of the PictureBox
		/// 
		public override int ContentLeft
		{
			get { return Left + _MyPictureBox.Left; }
		}
	
		override public void AdjustTableWidthAndLocation()
		{
			Width = Width;
			Height = Height;
			ItemLocation = TableLocation(MyStepSectionLayoutData, ItemWidth);
		}
		override public void SetToolTip(string tip)
		{
			DevComponents.DotNetBar.SuperTooltipInfo tpi = new DevComponents.DotNetBar.SuperTooltipInfo("", "", tip, null, null, DevComponents.DotNetBar.eTooltipColor.Lemon);
			_MyToolTip.MinimumTooltipSize = new Size(0, 24);
			_MyToolTip.TooltipDuration = 3;
			_MyToolTip.SetSuperTooltip(MyPictureBox, tpi);
		}
		public override void RefreshContent()
		{
			IdentifyMe(false);
			RefreshDisplay(false);
			SetExpandAndExpander(MyItemInfo);
		}
		public override void RefreshOrdinal()
		{
			TabFormat = null;
		}
		public override void HandleResize() {}
		public override void MatchExpanded() {}
		/// 
		/// Sets the focus to this ImageItem
		/// 
		public override void ItemSelect()
		{
			if (!_MyPictureBox.Disposing)
			{
				_MyPictureBox.Focus();
			}
			else
			{
				_MyLog.WarnFormat("Attempt to give Focus to Disposed Object {0}", MyID);
			}
			ScrollToCenter();
		}
		/// 
		/// Sets the focus to this ImageItem
		/// 
		public override void ItemShow()
		{
			_MyPictureBox.Focus();
			ScrollToCenter();
		}
		public override void SetActive()
		{
			this.BackColor = MyStepPanel.ActiveColor;
		}
		public override void SetText()
		{
			LastMethodsPush("SetText");
			if (MyItemInfo != null)
			{
				IdentifyMe(false);
			}
			LastMethodsPop();
		}
		public override void SetExpandAndExpander(ItemInfo itemInfo)
		{
			CanExpand = false;
		}
		public override void SaveCurrentAndContents()
		{
			SaveContents();
		}
		public override void RefreshDisplay(bool activeMode)
		{
			if (MyItemInfo.MyContent.MyImage == null) return;  // new figure
			FileName = MyItemInfo.MyContent.MyImage.FileName;
			InsType = FileName.ToUpper() == "PASTE.JPG" ? E_ImageSource.Clipboard : E_ImageSource.File;
			System.Drawing.Image img = byteArrayToImage(MyItemInfo.MyContent.MyImage.Data);
			MyPictureBox.Image = img;
			MyPictureBox.Visible = true;
			ImageConfig ic = new ImageConfig(MyItemInfo.MyContent.MyImage);
			if (ic != null && ic.Image_Height != 0)
			{
				_origCfgWd = ic.Image_Width * MyStepPanel.DPI / 72;
				_origCfgHt = ic.Image_Height * MyStepPanel.DPI / 72;
			}
			SetWidthsAndHeights(img);
			//need this to trigger update of steptabribbonbuttons:
			MyStepPanel.MyStepTabPanel.MyStepTabRibbon.SetButtonAndMenuEnabling(true);
		}
		public override void ToggleEditView(E_ViewMode vwMode) {}
		public override string TabFormat
		{
			get { return null; }
			set { ;}
		}
		public override bool Expanded
		{
			get { return true; }
			set { ; }
		}
		public override bool CanExpand
		{
			get { return false; }
			set { ; }
		}
		public override int TabLeft { get { return lblTab.Left; } set { lblTab.Left = value; } }	//taken from griditem
		public override Font TabFont { get { return MyStepRTB.Font; } set { ; } }
		public override string TabText { get { return lblTab.Text; } }
		public override Point TabLocation { get { return lblTab.Location; } }
		public override Font ContentFont { get { return MyStepRTB.Font; } set { /*MyStepRTB.Font = value*/; } }
		public override float ContentTop { get { return MyPictureBox.Top; } }
		public override DialogResult ReplaceText(string rpltxt, string fndstr, bool caseSensitive, bool matchWholeWord, bool reverse, bool prompt, IWin32Window fndrpldlg)
		{
			return DialogResult.OK;
		}
		public override bool FindText(string str, bool caseSensitive, bool matchWholeWord, bool reverse)
		{
			return false;
		}
		public override void PositionToEnd()
		{
			return;
		}
		public override void PositionToStart()
		{
			return;
		}
		public override string SelectedTextForFind
		{
			get { return null; }
		}
		public override bool SpellCheckNext()
		{
			return true;
		}
		public override bool Empty
		{
			get
			{
				return _MyPictureBox.Image == null;
			}
			set { _MyPictureBox.Image = null; }
		}
		public override void RefreshTab()
		{
			TabFormat = null;
		}
		public override void SetupHeader(ItemInfo itemInfo) { }
		public override void ShowExpanded() { }
		#endregion
		#region Properties
		public enum E_ImageSource : int
		{
			None = 0, Clipboard = 1, File = 2, RoFigure = 3
		}
		public System.Windows.Forms.PictureBox MyPictureBox
		{
			get { return _MyPictureBox; }
		}
		private string FileName = null;
		private static int _ImageMargin = 18;
		/// 
		/// Margin between the EditItem and the ImageItem.  Appears on the Right.
		/// Will allow space to draw a Change Bar on the right side of the EditItem.
		/// 
		public static int ImageMargin
		{
			get { return _ImageMargin; }
			set { _ImageMargin = value; }
		}
		private bool _IsDirty = false;
		private int _origCfgHt = 0;	// keep track if original size was stored in cfg
		private int _origCfgWd = 0;
		private bool _pastedNew = false;   // need this for flagging newly pasted image (may need to clear cfg)
		#endregion
		#region Constructors
		public ImageItem()
		{
			InitializeComponent();
		}
		// the following displays for existing images
		public ImageItem(ItemInfo itemInfo, StepPanel myStepPanel, EditItem myParentEditItem, ChildRelation myChildRelation, bool expand)
		{
			InitializeComponent();
			MyItemInfo = itemInfo;
			SetupEditItem(itemInfo, myStepPanel, myParentEditItem, myChildRelation, expand, null, false);
			if (MyItemInfo.MyContent.MyImage != null && MyItemInfo.MyContent.MyImage.Data != null)  // this is figure/image (not RO)
			{
				FileName = MyItemInfo.MyContent.MyImage.FileName;
				InsType = FileName.ToUpper() == "PASTE.JPG" ? E_ImageSource.Clipboard : E_ImageSource.File;
				System.Drawing.Image img = byteArrayToImage(MyItemInfo.MyContent.MyImage.Data);
				MyPictureBox.Image = img;
				MyPictureBox.Visible = true;
				ImageConfig ic = new ImageConfig(MyItemInfo.MyContent.MyImage);
				if (ic != null && ic.Image_Height != 0)		// embedded image (not RO)
				{
					_origCfgWd = ic.Image_Width * MyStepPanel.DPI / 72;
					_origCfgHt = ic.Image_Height * MyStepPanel.DPI / 72;
				}
				SetWidthsAndHeights(img);
			}
			else
			{
				// get ro image data from link within the steprtb:
				HandleRoImage();
				DisplayText vlntxt = new DisplayText(MyItemInfo, E_EditPrintMode.Edit, E_ViewMode.View, false, E_FieldToEdit.Text, true, null, null, false);
				MyStepRTB.OrigDisplayText = vlntxt;
				InsType = E_ImageSource.RoFigure;
			}
			AdjustTableWidthAndLocation();
			AddEventHandlers();
			MyStepRTB.RemoveEventHandlers();
			MyStepRTB.Visible = false;
		}
		private int _newSizeWd = 0;
		private int _newSizeHt = 0;
		public void SizeImage(int wd, int ht)
		{
			MyPictureBox.Width = wd;
			MyPictureBox.Height = ht;
			MyPictureBox.SizeMode = PictureBoxSizeMode.Zoom;
			this.Width = MyPictureBox.Width + ImageMargin;
			this.Height = MyPictureBox.Height + 10;
			_newSizeWd = wd / (MyStepPanel.DPI / 72);
			_newSizeHt = ht / (MyStepPanel.DPI / 72);
			if (!MyItemInfo.FormatStepData.StepEditData.TypeMenu.MenuItem.ToUpper().Contains("AER")) ItemLocation = TableLocation(MyStepSectionLayoutData, ItemWidth);
			_IsDirty = true;
		}
		private void SetWidthsAndHeights(System.Drawing.Image img)
		{
			int wd = img.Width * MyStepPanel.DPI / 72; // converts from screen resolution's DPI to image's points (72/inch)
			int ht = img.Height * MyStepPanel.DPI / 72;
			if (MyItemInfo.MyContent.MyImage != null)   // image is null if creating new.
			{
				ImageConfig ic = new ImageConfig(MyItemInfo.MyContent.MyImage);
				if (!_pastedNew && ic != null && ic.Image_Height != 0)
				{
					wd = ic.Image_Width * MyStepPanel.DPI / 72;
					ht = ic.Image_Height * MyStepPanel.DPI / 72;
				}
			}
			MyPictureBox.Visible = true;
			MyPictureBox.Width = wd;
			MyPictureBox.Height = ht;
			MyPictureBox.SizeMode = PictureBoxSizeMode.Zoom;		// as resize matches width/height.
			this.Width = MyPictureBox.Width + ImageMargin;
			this.Height = MyPictureBox.Height + 10;
		}
		// the following gets called for 'NEW' images
		private E_ImageSource InsType = E_ImageSource.None;
		public ImageItem(ItemInfo itemInfo, StepPanel myStepPanel, EditItem myParentEditItem, ChildRelation myChildRelation, bool expand, EditItem nextEditItem, ImageItem.E_ImageSource insType)
		{
			InitializeComponent();
			MyItemInfo = itemInfo;
			if (MyItemInfo.MyContent.MyImage != null && MyItemInfo.MyContent.MyImage.Data != null)  // this is figure/image (not RO)
			{
				SetupEditItem(itemInfo, myStepPanel, myParentEditItem, myChildRelation, expand, nextEditItem, false);
				FileName = MyItemInfo.MyContent.MyImage.FileName;
				InsType = FileName.ToUpper() == "PASTE.JPG" ? E_ImageSource.Clipboard : E_ImageSource.File;
				System.Drawing.Image img = byteArrayToImage(MyItemInfo.MyContent.MyImage.Data);
				MyPictureBox.Image = img;
				MyPictureBox.Visible = true;
				ImageConfig ic = new ImageConfig(MyItemInfo.MyContent.MyImage);
				if (ic != null && ic.Image_Height != 0)		// embedded image (not RO)
				{
					_origCfgWd = ic.Image_Width * MyStepPanel.DPI / 72;
					_origCfgHt = ic.Image_Height * MyStepPanel.DPI / 72;
				}
				SetWidthsAndHeights(img);
			}
			else if (MyItemInfo.MyContent.Text != null && MyItemInfo.MyContent.Text.ToUpper().Contains("RO"))
			{
				SetupEditItem(itemInfo, myStepPanel, myParentEditItem, myChildRelation, expand, nextEditItem, false);
				// get ro image data from link within the steprtb:
				HandleRoImage();
				DisplayText vlntxt = new DisplayText(MyItemInfo, E_EditPrintMode.Edit, E_ViewMode.View, false, E_FieldToEdit.Text, true, null, null, false);
				MyStepRTB.OrigDisplayText = vlntxt;
				InsType = E_ImageSource.RoFigure;
			}
			else
			{
				InsType = insType;
				FileName = null;
				//InitializeComponent();
				SetupEditItem(itemInfo, myStepPanel, myParentEditItem, myChildRelation, expand, nextEditItem, false);
				MyPictureBox.Width = 100;
				MyPictureBox.Height = 100;
				this.Width = 100 + ImageMargin;
				this.Height = 100;
				if (insType == ImageItem.E_ImageSource.File)
				{
					ImageFileDialog();
				}
				else if (insType == ImageItem.E_ImageSource.Clipboard)
				{
					// see if there is an image in clipboard and if so, insert it:
					System.Drawing.Image img = Clipboard.GetImage();
					if (img != null)
					{
						MyPictureBox.Image = img;
						SetWidthsAndHeights(img);
						string ext = GetImageFormatExtension(img);
						FileName = "paste." + ext;
						_IsDirty = true;
					}
				}
				else  // this is an Ro image - use displaytext and steprtb to get image data
				{
					DisplayText vlntxt = new DisplayText(MyItemInfo, E_EditPrintMode.Edit, E_ViewMode.View, false, E_FieldToEdit.Text, true, null, null, false);
					MyStepRTB.OrigDisplayText = vlntxt;
				}
			}
			AdjustTableWidthAndLocation();
			this.Controls.Add(this._MyPictureBox);
			AddEventHandlers();
			MyStepRTB.RemoveEventHandlers();
			MyStepRTB.Visible = false;
		}
		private void ImageFileDialog()
		{
			OpenFileDialog openFileDialog1 = new OpenFileDialog();
			openFileDialog1.InitialDirectory = "c:\\";
			openFileDialog1.Filter = "Image files (*.jpg;*.tif;*.bmp;*.png)|*.jpg;*.tif;*.bmp;*.png|All files (*.*)|*.*";
			openFileDialog1.FilterIndex = 0;
			openFileDialog1.RestoreDirectory = true;
			if (openFileDialog1.ShowDialog() == DialogResult.OK)
			{
				try
				{
					// check that it is an image
					System.Drawing.Image img = System.Drawing.Image.FromFile(openFileDialog1.FileName);
					if (img != null)
						{
							FileName = openFileDialog1.FileName;
							MyPictureBox.Image = img;
							SetWidthsAndHeights(img);
							_IsDirty = true;
						}
				}
				catch (Exception ex)
				{
					FlexibleMessageBox.Show("Could not create image, check file type.", "Error on Image File Selection");
					return;
				}
			}
		}
		//public static System.Drawing.Imaging.ImageFormat GetImageFormat(this System.Drawing.Image img)
		//{
		//	if (img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Jpeg))
		//		return System.Drawing.Imaging.ImageFormat.Jpeg;
		//	if (img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Bmp))
		//		return System.Drawing.Imaging.ImageFormat.Bmp;
		//	if (img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Png))
		//		return System.Drawing.Imaging.ImageFormat.Png;
		//	if (img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Emf))
		//		return System.Drawing.Imaging.ImageFormat.Emf;
		//	if (img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Exif))
		//		return System.Drawing.Imaging.ImageFormat.Exif;
		//	if (img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Gif))
		//		return System.Drawing.Imaging.ImageFormat.Gif;
		//	if (img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Icon))
		//		return System.Drawing.Imaging.ImageFormat.Icon;
		//	if (img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.MemoryBmp))
		//		return System.Drawing.Imaging.ImageFormat.MemoryBmp;
		//	if (img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Tiff))
		//		return System.Drawing.Imaging.ImageFormat.Tiff;
		//	else
		//		return System.Drawing.Imaging.ImageFormat.Wmf;
		//}
		private static string GetImageFormatExtension(System.Drawing.Image img)
		{
			return ("jpg");	// seems that this is the only one that works.
			/*
			if (img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Jpeg))
				return "jpg";
			if (img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Bmp))
				return "bmp";
			if (img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Png))
				return "png";
			if (img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Emf))
				return "emf";
			if (img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Gif))
				return "gif";
			if (img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Icon))
				return "ico";
			if (img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Tiff))
				return "tif";
			else
				return "wmf";
			 */
		}
		#endregion
		#region RO_Images
		public void HandleRoImage()
		{
			string imageText = null;
			ProcedureInfo proc = MyItemInfo.MyProcedure;
			DocVersionInfo dvi = proc.MyDocVersion;
			ROFstInfo rofst = dvi.DocVersionAssociations[0].MyROFst;
			ROFSTLookup lookup = rofst.GetROFSTLookup(dvi);
			string linkInfoText = MyItemInfo.MyContent.Text.Replace(@"\u8209?", "-");
			int ind = linkInfoText.IndexOf("[END>");		// found cases where the ro figure had 2 links stored within content->text (BGE data)
			if (ind > 0)
			{
				int indx = linkInfoText.IndexOf("[END>", ind + 3);
				if (indx > -1)
				{
					// link is duplicated (bad data), but handle it:
					linkInfoText = linkInfoText.Substring(0, linkInfoText.IndexOf(@"\v ", ind + 3));
				}
			} 
			linkInfoText = linkInfoText.Replace(@"\v ", "");
			Match m = Regex.Match(linkInfoText, @"(.*)[#]Link:([A-Za-z]*):(.*)");
			string val = null;
			if (m.Length > 0) // if m.lengh is zero, then no match was found - no RO was entered in the figure substep
			{
				if (m.Groups.Count < 4)
				{
					val = string.Format("{0}\n{1}\n{2}n{3}",
					linkInfoText.Substring(0, linkInfoText.Length - 16),
					linkInfoText.Substring(linkInfoText.Length - 16, 8),
					linkInfoText.Substring(linkInfoText.Length - 8, 4),
					linkInfoText.Substring(linkInfoText.Length - 4, 4));
					val = val.Replace(@"\u8209?", "-").Replace(@"\u9586?", @"\"); // replace dash and backslash symbols with dash and backslash characters
				}
				else
				{
					string[] subs = m.Groups[3].Value.Split(" ".ToCharArray());
					val = lookup.GetRoValue(subs[1]);
					if (val == null || val == "?") val = lookup.GetRoValue(subs[1].Substring(0, 12));
					if (val == "?")
					{
						// Do 'empty' image box.
							//_MyLog.WarnFormat("\r\nMissing Referenced Object {0} in {1}", subs[1], itemInfo.ShortPath);
					}
				}
			}
			GC.Collect(); // memory garbage collection (Regex memory bug)
			if (val != null && val != "?")
			{
				string imgname = null;
				int W = 0;
				int H = 0;
				string[] vals = val.Split("\n".ToCharArray());
				W = (int)(Int32.Parse(vals[3], System.Globalization.NumberStyles.AllowHexSpecifier) * MyItemInfo.FormatStepData.Font.CharsToTwips);
				int lines = Int32.Parse(vals[2], System.Globalization.NumberStyles.AllowHexSpecifier);
				H = lines * 12;
				try
				{
					imgname = vals[0];
					ROImageInfo roImage = ROImageInfo.GetByROFstID_FileName(rofst.ROFstID, vals[0]);
					if (roImage != null)
						imageText = val;
					else
					{
						roImage = rofst.GetROImageByFilename(vals[0], MyItemInfo);// need code to go and get an ROImaage if it exists
						if (roImage != null)
							imageText = val;
					}
					AddROImageToScreen(W, H, imageText);
				}
				catch (Exception ex)
				{
					string msg = string.Format("Could not display image {0}.", imgname);
					FlexibleMessageBox.Show(msg);
				}
			}
		}
		
		public bool ThumbnailCallback()
		{
			return false;
		}
		public void AddROImageToScreen(int w, int h, string imageText)
		{
			string[] vals = imageText.Split("\n".ToCharArray());
			ProcedureInfo proc = MyItemInfo.MyProcedure;
			DocVersionInfo dvi = proc.ActiveParent as DocVersionInfo;
			ROFstInfo rofst = dvi.DocVersionAssociations[0].MyROFst;
			ROImageInfo roImageInfo = ROImageInfo.GetByROFstID_FileName(rofst.ROFstID, vals[0]);
			if (roImageInfo == null) roImageInfo = rofst.GetROImageByFilename(vals[0], MyItemInfo);
			if (roImageInfo != null)
			{
				System.Drawing.Image.GetThumbnailImageAbort myCallback =
					new System.Drawing.Image.GetThumbnailImageAbort(ThumbnailCallback);
				ROImageConfig rc = new ROImageConfig(roImageInfo);
				int size = Convert.ToInt32(rc.Image_Size);
				byte[] cnt = roImageInfo.Content;
				byte[] dcnt = ROImageInfo.Decompress(cnt, size);
				MemoryStream ms = new MemoryStream(dcnt);
				System.Drawing.Image img2 = System.Drawing.Image.FromStream(ms);
				// if there is config data that saves the resize of the image, use it, otherwise use what was passed in:
				StepConfig sc = new StepConfig(MyItemInfo as StepInfo);
				SizeF sizef = new Size(1, 1);
				if (sc.Step_ImageHeight == null || sc.Step_ImageHeight == 0)
				{
					sizef = new SizeF((img2.Width / img2.HorizontalResolution),
										(img2.Height / img2.VerticalResolution));
					float fscale = Math.Min(w / sizef.Width, h / sizef.Height);
					sizef.Width *= fscale;
					sizef.Height *= fscale;
				}
				else
				{
					sizef = new Size(sc.Step_ImageWidth, sc.Step_ImageHeight);
				}
				System.Drawing.Image img = img2.GetThumbnailImage((int)sizef.Width, (int)sizef.Height, myCallback, IntPtr.Zero);
				MyPictureBox.Image = img;
				SetWidthsAndHeights(img);
			}
		}
		#endregion
		#region EventHandlers
		private void ImageItem_Enter(object sender, EventArgs e)
		{
			if (MyStepPanel.DisplayItemChanging) return;
			SetMenu("OpenContextMenu");
			MyStepPanel.SelectedEditItem = this;
		}
		private void AddEventHandlers()
		{
			// Always be sure to add the same event handlers to RemoveEventHandlers
			MyItemInfo.MyContent.Changed += new VEPROMS.CSLA.Library.ContentInfoEvent(MyContent_Changed);
			this.Enter += new System.EventHandler(ImageItem_Enter);
			this.MyPictureBox.Enter += new System.EventHandler(ImageItem_Enter);
			this.Click += new EventHandler(ImageItem_Click);
			this.MyPictureBox.Click += new EventHandler(ImageItem_Click);
			this.MyPictureBox.PreviewKeyDown += new PreviewKeyDownEventHandler(ImageItem_PreviewKeyDown);	//note that PictureBox does not have cursorkey events
			this.MyPictureBox.KeyDown += new KeyEventHandler(ImageItem_KeyDown);
			this.MyStepRTB.RoInsert += new StepRTBRoEvent(MyStepRTB_RoInsert);
			this.MyStepRTB.DoSaveContents += new StepRTBEvent(MyStepRTB_DoSaveContents);   // for storing RO data
			this.MyPictureBox.Resize += MyPictureBox_Resize;
			this.MyPictureBox.MouseDown += MyPictureBox_MouseDown;
		}
		void MyPictureBox_MouseDown(object sender, MouseEventArgs e)
		{
			SetMenu("OpenContextMenu");
		}
		void MyPictureBox_Resize(object sender, EventArgs e)
		{
			if (this.Height != _MyPictureBox.Height + _MyPictureBox.Top + 7)  // add in 7 to make it look good // + 10)
			{
				LastMethodsPush(string.Format("MyPictureBox_Resize {0}", _MyPictureBox.Height));
				this.Height = _MyPictureBox.Height + _MyPictureBox.Top + 7;
				LastMethodsPop();
			}
		}
		private void RemoveEventHandlers()
		{
			// Always be sure to add the same event handlers to RemoveEventHandlers
			MyItemInfo.MyContent.Changed -= new VEPROMS.CSLA.Library.ContentInfoEvent(MyContent_Changed);
			this.Enter -= new System.EventHandler(ImageItem_Enter);
			this.MyPictureBox.Enter -= new System.EventHandler(ImageItem_Enter);
			this.Click -= new EventHandler(ImageItem_Click);
			this.MyPictureBox.Click -= new EventHandler(ImageItem_Click);
			this.MyPictureBox.PreviewKeyDown -= new PreviewKeyDownEventHandler(ImageItem_PreviewKeyDown);
			this.MyPictureBox.KeyDown -= new KeyEventHandler(ImageItem_KeyDown);
			this.MyStepRTB.RoInsert -= new StepRTBRoEvent(MyStepRTB_RoInsert);
			this.MyStepRTB.DoSaveContents -= new StepRTBEvent(MyStepRTB_DoSaveContents);
			this.MyPictureBox.Resize -= MyPictureBox_Resize;
			this.MyPictureBox.MouseDown -= MyPictureBox_MouseDown;
		}
		void ImageItem_Click(object sender, EventArgs e)
		{
			if (MyStepPanel.DisplayItemChanging) return;
			MyStepPanel.SelectedEditItem = this;
		}
		// the PictureBox does not have cursor key event support - did this by previewing keydowns and 
		// if the key is arrow up/down, do associated cursormovement through the StepPanel
		void ImageItem_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
		{
			switch (e.KeyCode)
			{
				case Keys.Up:
					MyStepPanel.CursorMovement(this, new Point(0, 0), E_ArrowKeys.Up);
					break;
				case Keys.Down:
					MyStepPanel.CursorMovement(this, new Point(0, 0), E_ArrowKeys.Down);
					break;
			}
		}
		void ImageItem_KeyDown(object sender, KeyEventArgs e)
		{
			if (e.Control)
			{
				switch (e.KeyCode)
				{
					case Keys.V:			// handle paste of an image
						if (MyStepPanel.VwMode == E_ViewMode.View)
						{
							e.Handled = true;
							return;
						}
						if (InsType == E_ImageSource.RoFigure && MyItemInfo.MyContent.MyImage == null)		// on an RO image
						{
							FlexibleMessageBox.Show("Cannot replace an existing RO figure/image. Use the Step Properties panel/RO tab.", "Warning, no paste/replace for RO images.");
							e.Handled = true;
							return;
						}
						PasteImage();
						e.Handled = true;
						return;
				}
			}
		}
		public void PasteImage()
		{
			bool setdata = false;
			System.Drawing.Image img = Clipboard.GetImage();
			if (img == null) // let user know there is no valid data in clipboard:
			{
				FlexibleMessageBox.Show(this, "The clipboard does not contain image data.", "Cannot paste.", MessageBoxButtons.OK);
				return;
			}
			if (MyItemInfo.MyContent.MyImage != null && img != null)	// see if there already is an image and if so - ask if user wants to replace.
			{
				if (FlexibleMessageBox.Show(this, "Do you want to replace the existing image?", "Confirm Image Replace", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question) == DialogResult.Yes)
				{
						setdata = true;
				}
			}
			else if (MyItemInfo.MyContent.ContentRoUsageCount > 0 && img != null)
			{
				FlexibleMessageBox.Show("Cannot replace an existing RO figure/image. Use the Step Properties panel/RO tab.", "Warning, no paste/replace for RO images.");
				return;
			}
			else if (img != null)			// no existing image, be sure there is valid data in clipboard
				setdata = true;
			if (setdata)
			{
				_IsDirty = true;
				_pastedNew = true;
				MyPictureBox.Image = img;
				SetWidthsAndHeights(img);
				string ext = GetImageFormatExtension(img);
				FileName = "paste." + ext;
			}
		}
		void MyStepRTB_RoInsert(object sender, StepRTBRoEventArgs args)
		{
			int sel = MyStepRTB.SelectionStart + args.ValText.Length;
			_IsDirty = true;
			InsType = E_ImageSource.RoFigure;
			MyStepRTB.UpdateStepRtb(args.LinkText, args.ValText);
			HandleRoImage();
		}
		void MyStepRTB_DoSaveContents(object sender, EventArgs args)
		{
			_IsDirty = true;
			InsType = E_ImageSource.RoFigure;
			SaveCurrentAndContents();
			HandleRoImage();
		}	
		#endregion
		#region ContextMenu
		void SetMenu(string contentMenu)
		{
			if (contentMenu == null)
				MyStepPanel.MyStepTabPanel.MyStepTabRibbon.ClearContextMenu();
			else if (contentMenu == "OpenContextMenu")
				MyStepPanel.MyStepTabPanel.MyStepTabRibbon.SetContextMenuImage(this);
		}
		#endregion
		#region Methods
		public override void SetFocus()
		{
			MyPictureBox.Focus();
		}
		public override void SaveContents()
		{
			MyStepRTB.Visible = false;
			if (!_IsDirty) return;
			if (InsType != E_ImageSource.None && InsType != E_ImageSource.RoFigure)
			{
				SaveImage();
			}
			else if (InsType == E_ImageSource.RoFigure)
			{
				DisplayText vlntxt = new DisplayText(MyItemInfo, E_EditPrintMode.Edit, E_ViewMode.View, false, E_FieldToEdit.Text, true, null, null, false);
				if (MyStepRTB.OrigDisplayText == null)
				{
					MyStepRTB.OrigDisplayText = vlntxt;
				}
				if (MyStepRTB.Text == "")
				{
					MyStepRTB.AddRtfText(vlntxt.StartText);
				}
				bool success = MyStepRTB.OrigDisplayText.Save((RichTextBox)MyStepRTB);
				if (success && _newSizeHt != 0)
				{
					StepConfig sc = new StepConfig(MyItemInfo as StepInfo);
					sc.Step_ImageWidth = (int)(_newSizeWd / (MyStepPanel.DPI / 72f));
					sc.Step_ImageHeight = (int)(_newSizeHt / (MyStepPanel.DPI / 72f));
					using (Item item = MyItemInfo.Get())
					{
						item.MyContent.Config = sc.ToString();
						item.Save();
					}
				}
			}
			_IsDirty = false;
		}
		public void SaveImage()
		{
			try
			{
				using (Item _MyItem = MyItemInfo.Get())
				{
					byte[] imgToByte = imageToByteArray(MyPictureBox.Image, FileName);
					if (imgToByte == null) return;
					int origLen = imgToByte.Length;
					bool compressed = false;
					// if file is a tif or bmp see if compressing it saves space and if so, save the
					// compressed data with a flag in config, the size needed to decompress, to show it is compressed.
					if (FileName.ToUpper().EndsWith(".TIFF") || FileName.ToUpper().EndsWith(".TIF") || FileName.ToUpper().EndsWith(".BMP"))
					{
						byte[] cmp = ROImageInfo.Compress(imgToByte);
						if (origLen > cmp.Length)
						{
							imgToByte = cmp;
							compressed = true;
						}
					}
					ImageConfig imgCfg = null;
					if (_pastedNew && compressed)
					{
						imgCfg = new ImageConfig();
						imgCfg.Image_DataSize = origLen;
						_MyItem.MyContent.MyImage.Config = imgCfg.ToString();
					}
					else if (_newSizeHt != 0)
					{
						if (MyItemInfo.MyContent.MyImage == null && imgCfg == null)
							imgCfg = new ImageConfig();
						else if (imgCfg == null)
							imgCfg = new ImageConfig(MyItemInfo.MyContent.MyImage);
						// B2017-155 Round the value by adding .51F
						imgCfg.Image_Width = (int)(.51F + _newSizeWd / (MyStepPanel.DPI / 72f));
						imgCfg.Image_Height = (int)(.51F + _newSizeHt / (MyStepPanel.DPI / 72f));
						if (compressed) imgCfg.Image_DataSize = origLen;
						_MyItem.MyContent.MyImage.Config = imgCfg.ToString();
					}
					else if (compressed)
					{
						if (MyItemInfo.MyContent.MyImage == null && imgCfg == null)
							imgCfg = new ImageConfig();
						else if (imgCfg == null)
							imgCfg = new ImageConfig(MyItemInfo.MyContent.MyImage);
							imgCfg.Image_DataSize = origLen;
							_MyItem.MyContent.MyImage.Config = imgCfg.ToString();
					}
					_MyItem.MyContent.MyImage.Data = imgToByte;
					_MyItem.MyContent.MyImage.FileName = FileName;
					_MyItem.MyContent.MyImage.ImageType = 1;
					_MyItem.MyContent.MyImage.DTS = DateTime.Now;
					_MyItem.MyContent.MyImage.UserID = Volian.Base.Library.VlnSettings.UserID;
					_MyItem.MyContent.DTS = DateTime.Now;
					_MyItem.MyContent.UserID = Volian.Base.Library.VlnSettings.UserID;
					_MyItem.Save();
					}
					StepConfig sc = MyItemInfo.MyConfig as StepConfig;
					// if the plant has the change id option, the change id was entered when the program started.
					// this should be saved for every piece of edited data.  Note that the set of config
					// item Step_MultipleChangeID has the save built in to it.
					if (MyItemInfo.ActiveFormat.PlantFormat.FormatData.ProcData.ChangeBarData.ChangeIds
							&& !this.MyStepPanel.MyStepTabPanel.MyDisplayTabControl.EditorialChange)
					{
						if (sc == null) sc = new StepConfig();
						sc.Step_ChangeID = this.MyStepPanel.MyStepTabPanel.MyDisplayTabControl.ChgId;
					}
					// We saved changes. Reset the change bar override.
					// IF there is a step config remove the change bar override by setting the CBOverride value to null
					// This fixes a problem reported by Farly where if the change bar or overridden to be off, the next
					// time a change was made, the change bar remained turned off.
					if (sc != null)
						sc.Step_CBOverride = null; // clear the change bar override
					MyStepRTB.ClearUndo();
			}
			catch (Exception ex)
			{
				FlexibleMessageBox.Show("The image could not be saved.", "Image Save", MessageBoxButtons.OK, MessageBoxIcon.Information);
				return;
			}
			_newSizeHt = 0;
			_newSizeWd = 0;
		}
		public static byte[] imageToByteArray(System.Drawing.Image imageIn, string fname)
		{
			// get filename's extension to map to imageformat:
			string ext = fname.Substring(fname.LastIndexOf(".") + 1).ToUpper();
			System.Drawing.Imaging.ImageFormat ifmt = System.Drawing.Imaging.ImageFormat.Gif;
			switch (ext)
			{
				case ("JPG"):
					ifmt = System.Drawing.Imaging.ImageFormat.Jpeg;
					break;
				case ("TIF"):
				case ("TIFF"):
					ifmt = System.Drawing.Imaging.ImageFormat.Tiff;
					break;
				case ("WMF"):
					ifmt = System.Drawing.Imaging.ImageFormat.Wmf;
					break;
				case ("BMP"):
					ifmt = System.Drawing.Imaging.ImageFormat.Bmp;
					break;
				case ("EMF"):
					ifmt = System.Drawing.Imaging.ImageFormat.Emf;
					break;
				case ("GIF"):
					ifmt = System.Drawing.Imaging.ImageFormat.Gif;
					break;
				case ("ICO"):
					ifmt = System.Drawing.Imaging.ImageFormat.Icon;
					break;
				case ("PNG"):
					ifmt = System.Drawing.Imaging.ImageFormat.Png;
					break;
				default:
					FlexibleMessageBox.Show("Invalid File Type");
					return null;
			}
			MemoryStream ms = new MemoryStream();
			imageIn.Save(ms, ifmt); 
			return ms.ToArray();
		}
		public System.Drawing.Image byteArrayToImage(byte[] byteArrayIn)
		{
			// if there is config data, DataSize, then decompress the data:
			ImageConfig imgCfg = new ImageConfig(MyItemInfo.MyContent.MyImage);
			if (imgCfg.Image_DataSize > 0) byteArrayIn = ROImageInfo.Decompress(byteArrayIn, imgCfg.Image_DataSize);
			MemoryStream ms = new MemoryStream(byteArrayIn);
			System.Drawing.Image returnImage = System.Drawing.Image.FromStream(ms);
			return returnImage;
		}
		// the following is used if an image is being inserted using Before/after from steptabribbon:
		public static void AddImageIfNeeded(ItemInfo newItemInfo)
		{
			string filename = null;
			System.Drawing.Image img = Clipboard.GetImage();
			if (img != null)
			{
				// Ask user if they want to use the clipboard image.
				DialogResult dr = FlexibleMessageBox.Show("Clipboard has an image, use this (select Yes) or select a file (select No)?", "Insert Image Before/After", MessageBoxButtons.YesNo);
				if (dr == DialogResult.Yes)
				{
					string ext = ImageItem.GetImageFormatExtension(img);
					filename = "paste." + ext;
				}
				else
					img = null;
			}
			if (img == null)
			{
				OpenFileDialog openFileDialog1 = new OpenFileDialog();
				openFileDialog1.InitialDirectory = "c:\\";
				openFileDialog1.Filter = "Image files (*.jpg;*.tif;*.bmp;*.png)|*.jpg;*.tif;*.bmp;*.png|All files (*.*)|*.*";
				openFileDialog1.FilterIndex = 0;
				openFileDialog1.RestoreDirectory = true;
				DialogResult dr = openFileDialog1.ShowDialog();
				if (dr == DialogResult.OK)
				{
					// check that it is an image
					try
					{
						img = System.Drawing.Image.FromFile(openFileDialog1.FileName);
					}
					catch (Exception ex)
					{
						img = null;
					}
					if (img != null) filename = openFileDialog1.FileName;
				}
				if (filename == null)
				{
					if (dr != DialogResult.Cancel)
					{
						string msg = string.Format("Could not display image {0}.", openFileDialog1.FileName);
						FlexibleMessageBox.Show(msg);
					}
					return;   // user must have exited out or entered a bad filename.
				}
			}
			byte[] imgToByte = imageToByteArray(img, filename);
			int origLen = imgToByte.Length;
			bool compressed = false;
			// if file is a tif or bmp see if compressing it saves space and if so, save the
			// compressed data with a flag in config, the size needed to decompress, to show it is compressed.
			if (filename.ToUpper().EndsWith(".TIFF") || filename.ToUpper().EndsWith(".TIF") || filename.ToUpper().EndsWith(".BMP"))
			{
				byte[] cmp = ROImageInfo.Compress(imgToByte);
				if (origLen > cmp.Length)
				{
					imgToByte = cmp;
					compressed = true;
				}
			}
			using (Item _MyItem = newItemInfo.Get())
			{
				ImageConfig imgCfg = null;
				if (compressed)
				{
					imgCfg = new ImageConfig();
					imgCfg.Image_DataSize = origLen;
					_MyItem.MyContent.MyImage.Config = imgCfg.ToString();
				}
				_MyItem.MyContent.MyImage.Data = imgToByte;
				_MyItem.MyContent.MyImage.FileName = filename;
				_MyItem.MyContent.MyImage.ImageType = 1;
				_MyItem.MyContent.MyImage.DTS = DateTime.Now;
				_MyItem.MyContent.MyImage.UserID = Volian.Base.Library.VlnSettings.UserID;
				_MyItem.MyContent.DTS = DateTime.Now;
				_MyItem.MyContent.UserID = Volian.Base.Library.VlnSettings.UserID;
				_MyItem.Save();
			}
		}
		public override void IdentifyMe(bool highlight)
		{
			if (highlight)
				this.BackColor = Color.Gray;
			else
			{
				if (MyPictureBox.Focused || this.Focused) // If active Set BackColor to the active color
					this.BackColor = MyStepPanel.ActiveColor;
				else  // note that the 'inactive' color is actually MyStepPanel.PanelColor
					this.BackColor = MyItemInfo.ItemAnnotationCount == 0 ? MyStepPanel.PanelColor : MyStepPanel.AnnotationColor;
			}
		}
		#endregion
	}
}