/******************************************************************************
 * ScreenCaptureTransparentForm.cs 
 * 
 * <Copyright and License> 
 * 
 * This file is part of GODS, a package for annotating medical images. 
 * 
 * Copyright (C) 2004 
 * Xuedong Chen 
 * Heri Mariwa 
 * Kimmy (Hsiang-ling) Lin 
 * Rui Yu 
 * 
 * This program is free software; you can redistribute it and/or 
 * modify it under the terms of the GNU General Public License 
 * as published by the Free Software Foundation; either version 2 
 * of the License, or (at your option) any later version. 
 * 
 * This program is distributed in the hope that it will be useful, 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
 * GNU General Public License for more details. 
 * 
 * You should have received a copy of the GNU General Public License 
 * along with this program; if not, write to the Free Software 
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
 *  
 * For further questions about this file, please send email to 
 * gods@cs.umb.edu or visit us at http://gods.sourceforge.net.  
 ******************************************************************************/

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

namespace GODS
{
	namespace ScreenCapture
	{
		public enum Shapes {square,rectangle};

		public interface ScreenCaptureRequester
		{
			void LoadCapturedImage(Bitmap img, Rectangle rect, Form captureForm);
		}

		/// <summary>
		/// ScreenCaputureTransparentForm is a canvas with captured screen image as 
		/// background and user can draw any shape on it, which confine the part to be
		/// be actually captured. 
		/// </summary>
		public class ScreenCaptureTransparentForm : System.Windows.Forms.Form
		{

			private bool mouseDown = false;
			private ScreenCaptureRequester scRequester =null;
			private float originX, originY;
			private Rectangle rect = new Rectangle(0,0,0,0);
			private Label label1;
			private Shapes shape=Shapes.square;

			private String hotkeyhelp="Enter: capture the selected area\n"+
				"Esc: quit capture\n" + 
				"+: contine current screen capture with same shape\n";  
			/// <summary>
			/// Required designer variable.
			/// </summary>
			private System.ComponentModel.Container components = null;

			public ScreenCaptureTransparentForm(ScreenCaptureRequester scRequester, Shapes shape)
			{
				//
				// Required for Windows Form Designer support
				//
				InitializeComponent();
				this.shape = shape;
				this.SetUpCaptureForm(scRequester);

			}

			/// <summary>
			/// Clean up any resources being used.
			/// </summary>
			protected override void Dispose( bool disposing )
			{
				if( disposing )
				{
					if(components != null)
					{
						components.Dispose();
					}
				}
				base.Dispose( disposing );
			}

			#region Windows Form Designer generated code
			/// <summary>
			/// Required method for Designer support - do not modify
			/// the contents of this method with the code editor.
			/// </summary>
			private void InitializeComponent()
			{
				this.label1 = new System.Windows.Forms.Label();
				this.SuspendLayout();
				// 
				// label1
				// 
				this.label1.Location = new System.Drawing.Point(8, 16);
				this.label1.Name = "label1";
				this.label1.TabIndex = 0;
				this.label1.Visible = false;
				// 
				// ScreenCaptureTransparentForm
				// 
				this.AutoScale = false;
				this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
				this.BackColor = System.Drawing.SystemColors.Control;
				this.ClientSize = new System.Drawing.Size(292, 273);
				this.ControlBox = false;
				this.Controls.Add(this.label1);
				this.Cursor = System.Windows.Forms.Cursors.Cross;
				this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
				this.MaximizeBox = false;
				this.MinimizeBox = false;
				this.Name = "ScreenCaptureTransparentForm";
				this.ShowInTaskbar = false;
				this.Text = "ScreenCaptureTransparentForm";
				this.TopMost = true;
				this.WindowState = System.Windows.Forms.FormWindowState.Maximized;
				this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.ScreenCaptureTransparentForm_MouseDown);
				this.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.Esc);
				this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.ScreenCaptureTransparentForm_MouseUp);
				this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.ScreenCaptureTransparentForm_MouseMove);
				this.ResumeLayout(false);

			}
			#endregion

			/// <summary>
			/// set up the background form and capture shape as well as
			/// a capture action requester which takes the captured image
			/// and process it 
			/// </summary>
			/// <param name="image"></param>
			/// <param name="sp"></param>
			/// <param name="mainF"></param>
			public void SetUpCaptureForm(ScreenCaptureRequester scRequester)
			{
				ScreenCapture sc = new ScreenCapture();
				this.BackgroundImage = sc.CaptureScreen();
				this.WindowState = FormWindowState.Maximized;
				this.scRequester = scRequester;
			}

			/// <summary>
			/// handle the keypress event
			/// </summary>
			/// <param name="sender"></param>
			/// <param name="e"></param>
			private void Esc(object sender, System.Windows.Forms.KeyPressEventArgs e)
			{
				switch(e.KeyChar)
				{
						// Counts the backspaces.
					case '+':
						continueCapture();
						break ;
						// Counts the ENTER keys.
					case '\r':
						captureSelected() ;
						this.Close();
						break ;
						// Counts the ESC keys.  
					case (char)27:
						abortCapture();
						break ;
						// Counts all other keys.
					default:
						break;
				}

			}
			/// <summary>
			/// continue the capture action based on same screen
			/// </summary>
			private void continueCapture()
			{
				captureSelected();
			}
			/// <summary>
			/// capture the selected part of image and hand it to passed in form
			/// </summary>
			private void captureSelected()
			{
				if(scRequester != null)
				{
					if(!(rect.Width==0 ||rect.Height ==0))
					{
						scRequester.LoadCapturedImage((Bitmap)this.BackgroundImage.Clone(), rect, this);
					}
				}
			}

			/// <summary>
			/// above the capture action
			/// </summary>
			private void abortCapture()
			{
				this.Close();
			}

			/// <summary>
			/// track the mouse down action and initialize the drawing
			/// </summary>
			/// <param name="sender"></param>
			/// <param name="e"></param>
			private void ScreenCaptureTransparentForm_MouseDown(object sender, MouseEventArgs e)
			{
			
				this.mouseDown = true;
				originX = Cursor.Position.X;
				originY = Cursor.Position.Y;
			
				this.label1.Visible = true;
				this.label1.Location = Cursor.Position;
				this.label1.Text = "Drag the mouse to select the capture area";
				this.label1.Size = new System.Drawing.Size(200,20);
				this.label1.BackColor= Color.Transparent;
				this.label1.ForeColor = Color.Red;
				this.label1.Refresh();
				this.label1.Show();

			}

			/// <summary>
			/// track the mouse up action which finish a drawing
			/// </summary>
			/// <param name="sender"></param>
			/// <param name="e"></param>
			private void ScreenCaptureTransparentForm_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
			{
				this.mouseDown = false;
				this.label1.Text=this.label1.Text +"\n"+hotkeyhelp;
				this.label1.Size = new System.Drawing.Size(300,60);

			}

			/// <summary>
			/// Handle the actual drawing event
			/// </summary>
			/// <param name="sender"></param>
			/// <param name="e"></param>
			private void ScreenCaptureTransparentForm_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
			{
				if(this.mouseDown)
				{
					Graphics g = this.CreateGraphics();
					g.DrawImage(this.BackgroundImage,this.ClientRectangle);
					Pen bluePen = new Pen(Color.Blue, 1);
					Pen greenPen = new Pen(Color.Green,1);
					// Create location and size of rectangle.
					float width = Cursor.Position.X - originX;
					float height = Cursor.Position.Y - originY;

					// Draw rectangle to screen.
					if(shape.Equals(Shapes.rectangle))
					{
						rect = new Rectangle((int)originX,(int)originY,(int)width,(int)height);	
					}
					else if(shape.Equals(Shapes.square))
					{
						int maxlength = (int)System.Math.Max(width,height);
						rect = new Rectangle((int)originX,(int)originY,maxlength,maxlength);
					}

					
					g.DrawRectangle(bluePen,rect);
					
					this.label1.Location = Cursor.Position;
					this.label1.Text= "Width = "+rect.Width +", Height = "+rect.Height; 
					this.label1.Size = new System.Drawing.Size(200,20);
					this.label1.BackColor= Color.Transparent;
					this.label1.ForeColor = Color.Red;
					this.label1.Refresh();
					this.label1.Show();	

				}
			}
		}
	}
}
