//------------------------------------------------------------------------------
// C# ConsoleView Control
// Copyright (C) 2011 Cores Co., Ltd. Japan
//------------------------------------------------------------------------------
// $Id: Caret.cs 88 2011-04-05 11:03:57Z nagasima $
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Drawing;

namespace ConsoleView
{
	public class Caret
	{
		[Serializable, StructLayout(LayoutKind.Sequential)]
		struct POINT
		{
			public int X, Y;
		}

		[DllImport("user32.dll")]
		private static extern bool CreateCaret(IntPtr hWnd, IntPtr hbm, int cx, int cy);
		[DllImport("user32.dll")]
		private static extern bool DestroyCaret();
		[DllImport("user32.dll")]
		private static extern bool SetCaretPos(int x, int y);
		[DllImport("user32.dll")]
		private static extern bool GetCaretPos(out POINT lpPoint);
		[DllImport("user32.dll")]
		private static extern bool ShowCaret(IntPtr hWnd);
		[DllImport("user32.dll")]
		private static extern bool HideCaret(IntPtr hWnd);
		[DllImport("user32.dll")]
		private static extern int GetCaretBlinkTime();
		[DllImport("user32.dll")]
		private static extern bool SetCaretBlinkTime(int uMSeconds);

		private Control m_Control;
		private bool m_Created;
		private Rectangle m_Bounds;
		private bool m_Visible;

		public Caret(Control control)
		{
			m_Control = control;
		}

		public bool Visible
		{
			get { return m_Visible; }
			set
			{
				m_Visible = value;
				if (m_Control == null || !m_Control.IsHandleCreated)
					return;
				if (!m_Created)
					CreateCaret();
				if (m_Visible)
					ShowCaret(m_Control.Handle);
				else
					HideCaret(m_Control.Handle);
			}
		}

		public int BlinkTime
		{
			get { return GetCaretBlinkTime(); }
			set { SetCaretBlinkTime(value); }
		}

		public Size Size
		{
			get { return m_Bounds.Size; }
			set
			{
				m_Bounds.Size = value;
				if (m_Control == null || !m_Control.IsHandleCreated)
					return;
				CreateCaret();
			}
		}

		public Point Location
		{
			get
			{
				if (m_Control != null && m_Control.IsHandleCreated && m_Created)
				{
					POINT result;
					GetCaretPos(out result);
					m_Bounds.Location = new Point(result.X, result.Y);
				}
				return m_Bounds.Location;
			}
			set
			{
				m_Bounds.Location = value;
				if (m_Control == null || !m_Control.IsHandleCreated)
					return;
				if (!m_Created)
					CreateCaret();
				SetCaretPos(m_Bounds.Left, m_Bounds.Top);
				//throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
			}
		}

		public Rectangle Bounds
		{
			get { return m_Bounds; }
			set { Size = value.Size; Location = value.Location; }
		}

		private void CreateCaret()
		{
			if (m_Created)
				DestroyCaret();
			m_Created = CreateCaret(m_Control.Handle, IntPtr.Zero, m_Bounds.Width, m_Bounds.Height);
			if (m_Visible)
				ShowCaret(m_Control.Handle);
		}

		public void OnGotFocus()
		{
			CreateCaret();
			SetCaretPos(m_Bounds.Left, m_Bounds.Top);
		}

		public void OnLostFocus()
		{
			if (m_Created)
				DestroyCaret();
		}
	}
}
