// GraficRuler.cs created with MonoDevelop
//
//    QuickStep: Acquire, view and identify spectra 
//    Copyright (C) 2012  Thomas Klose & Torsten Schache, Hiperscan GmbH Dresden, Germany
//
//    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 3 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, see <http://www.gnu.org/licenses/>.


using System;
using Cairo;

namespace HollyLibrary
{
	public enum RulerPosition
	{
		Top,
		Bottom,
		Left,
		Right,
	}
	
	public class GraficRuler : Gtk.DrawingArea
	{
		private RulerPosition ruler_position = RulerPosition.Left;
		
		private int first_slider_x = 0;
		private int first_slider_y = 0;
		
		private int second_slider_x = 0;
		private int second_slider_y = 0;
		
		private Cairo.Color background_color = new Cairo.Color(0.8, 0.8, 0.8, 1);
		private Cairo.Color activ_color = new Cairo.Color(1, 1, 1, 1);
		
		private int ruler_left__offset 		= 30;
		private int ruler_right__offset 	= 30;
		private int ruler_top__offset 		= 30;
		private int ruler_bottom__offset	= 30;
		
		public GraficRuler (RulerPosition rp, int length_in_mm) : base()
		{
			this.Step = 3;
			this.RulerLength = length_in_mm;
			this.CurrentRulerPosition = rp;
			
			if (rp == RulerPosition.Left || rp == RulerPosition.Right)
			{
				this.SetSizeRequest(55, length_in_mm * this.Step + this.RulerTopOffset + this.RulerBottomOffset);
				this.FirstSliderY = this.RulerTopOffset;
				this.SecondSliderY = this.RulerTopOffset + length_in_mm * this.Step;
				if(rp == RulerPosition.Left)
				{
					this.FirstSliderX = 40;
					this.SecondSliderX = 40;
				}
				else
				{
					this.FirstSliderX = 10;
					this.SecondSliderX = 10;
				}
			}
			else
			{
				this.SetSizeRequest(length_in_mm * this.Step + this.RulerLeftOffset + this.RulerTopOffset, 55);
				this.FirstSliderX = this.RulerLength;
				this.SecondSliderX = this.RulerLength + length_in_mm * this.Step;
				if(rp == RulerPosition.Top)
				{
					this.FirstSliderY = 40;
					this.SecondSliderY = 40;
				}
				else
				{
					this.FirstSliderY = 10;
					this.SecondSliderY = 10;
				}
			}
				
		}
		
		protected override bool OnExposeEvent (Gdk.EventExpose evnt)
		{
			Cairo.Context context = Gdk.CairoHelper.Create(evnt.Window);
			
			
			switch(this.CurrentRulerPosition)
			{
			case RulerPosition.Top:
				this.DrawTopBackgound(context);
				this.DrawTopRuler(context);
				break;
			case RulerPosition.Bottom:
				this.DrawBottomBackgound(context);
				this.DrawBottomRuler(context);
				break;
			case RulerPosition.Left:
				this.DrawLeftBackgound(context);
				this.DrawLeftRuler(context);
				break;
			case RulerPosition.Right:
				this.DrawRightBackgound(context);
				this.DrawRightRuler(context);
				break;
			}
			
			((IDisposable) context.Target).Dispose();                                      
        	((IDisposable) context).Dispose();

			return true;
		}
		
		private void DrawLeftBackgound(Cairo.Context context)
		{
			context.Color = this.BackgroundColor;
			context.Rectangle(0,0, 55, this.RulerLength * this.Step + this.RulerTopOffset + this.RulerBottomOffset);
			context.Fill();
		
			context.Color = this.ActiveColor;
			context.Rectangle(5, this.FirstSliderY, 50, this.SecondSliderY - this.FirstSliderY);
			context.Fill();
		}
		
		private void DrawLeftRuler(Cairo.Context context)
		{
			context.SetSourceRGBA(0, 0, 0, 1);
			context.LineWidth = 1;
			context.SelectFontFace("Courier new", FontSlant.Normal, FontWeight.Normal);
			context.SetFontSize(14);
			
			for(int i = 0; i <= this.RulerLength; i++)
			{
				if (i % 10 == 0)
				{
					context.MoveTo(25, i * this.Step + this.RulerTopOffset);
					context.LineTo(45, i * this.Step + this.RulerTopOffset);
					context.MoveTo(7, i * this.Step + this.RulerTopOffset + 4);
					context.ShowText((i / 10).ToString().PadLeft(2));
				}
				else
				{
					if (i % 5 == 0)
					{
						context.MoveTo(30, i * this.Step + this.RulerTopOffset);
						context.LineTo(45, i * this.Step + this.RulerTopOffset);
					}
					else
					{
						context.MoveTo(35, i * this.Step + this.RulerTopOffset);
						context.LineTo(45, i * this.Step + this.RulerTopOffset);
					}
				}
				context.StrokePreserve();
			}
		}
		
		private void DrawRightBackgound(Cairo.Context context)
		{
			context.Color = this.BackgroundColor;
			context.Rectangle(0,0, 55, this.RulerLength * this.Step + + this.RulerTopOffset + this.RulerBottomOffset);
			context.Fill();
		
			context.Color = this.ActiveColor;
			context.Rectangle(0, this.FirstSliderY, 50, this.SecondSliderY - this.FirstSliderY);
			context.Fill();
		}
		
		private void DrawRightRuler(Cairo.Context context)
		{
			context.SetSourceRGBA(0, 0, 0, 1);
			context.LineWidth = 1;
			context.SelectFontFace("Courier new", FontSlant.Normal, FontWeight.Normal);
			context.SetFontSize(14);
			
			for(int i = 0; i <= this.RulerLength; i++)
			{
				if (i % 10 == 0)
				{
					context.MoveTo(10, i * this.Step + this.RulerTopOffset);
					context.LineTo(30, i * this.Step + this.RulerTopOffset);
					context.MoveTo(32, i * this.Step + this.RulerTopOffset + 4);
					context.ShowText((i / 10).ToString().PadLeft(2));
				}
				else
				{
					if (i % 5 == 0)
					{
						context.MoveTo(10, i * this.Step + this.RulerTopOffset);
						context.LineTo(25, i * this.Step + this.RulerTopOffset);
					}
					else
					{
						context.MoveTo(10, i * this.Step + this.RulerTopOffset);
						context.LineTo(20, i * this.Step + this.RulerTopOffset);
					}
				}
				context.StrokePreserve();
			}
		}
		
		private void DrawTopBackgound(Cairo.Context context)
		{
			context.Color = this.BackgroundColor;
			context.Rectangle(0,0, this.RulerLength * this.Step + this.RulerLeftOffset + this.RulerRightOffset, 55);
			context.Fill();

			context.Color = this.ActiveColor;
			context.Rectangle(this.FirstSliderX, 5, this.SecondSliderX - this.FirstSliderX, 50);
			context.Fill();
		}
		
		private void DrawTopRuler(Cairo.Context context)
		{
			context.SetSourceRGBA(0, 0, 0, 1);
			context.LineWidth = 1;
			context.SelectFontFace("Courier new", FontSlant.Normal, FontWeight.Normal);
			context.SetFontSize(14);
			
			for(int i = 0; i <= this.RulerLength; i++)
			{
				if (i % 10 == 0)
				{
					context.MoveTo(i * this.Step + this.RulerLeftOffset, 45);
					context.LineTo(i * this.Step + this.RulerLeftOffset, 25);
					if (i / 10 < 10)
						context.MoveTo(i * this.Step + this.RulerLeftOffset - 12, 20);
					else
						context.MoveTo(i * this.Step + this.RulerLeftOffset - 8, 20);
					context.ShowText((i / 10).ToString().PadLeft(2));
				}
				else
				{
					if (i % 5 == 0)
					{
						context.MoveTo(i * this.Step + this.RulerLeftOffset, 45);
						context.LineTo(i * this.Step + this.RulerLeftOffset, 30);
					}
					else
					{
						context.MoveTo(i * this.Step + this.RulerLeftOffset, 45);
						context.LineTo(i * this.Step + this.RulerLeftOffset, 35);
					}
				}
				context.StrokePreserve();
			}
		}
		
		private void DrawBottomBackgound(Cairo.Context context)
		{
			context.Color = this.BackgroundColor;
			context.Rectangle(0,0, this.RulerLength * this.Step + this.RulerLeftOffset + this.RulerRightOffset, 55);
			context.Fill();

			context.Color = this.ActiveColor;
			context.Rectangle(this.FirstSliderX, 0, this.SecondSliderX - this.FirstSliderX, 50);
			context.Fill();
		}
		
		private void DrawBottomRuler(Cairo.Context context)
		{
			context.SetSourceRGBA(0, 0, 0, 1);
			context.LineWidth = 1;
			context.SelectFontFace("Courier new", FontSlant.Normal, FontWeight.Normal);
			context.SetFontSize(14);
			
			for(int i = 0; i <= this.RulerLength; i++)
			{
				if (i % 10 == 0)
				{
					context.MoveTo(i * this.Step + this.RulerLeftOffset, 10);
					context.LineTo(i * this.Step + this.RulerLeftOffset, 30);
					if (i / 10 < 10)
						context.MoveTo(i * this.Step + this.RulerLeftOffset - 12, 42);
					else
						context.MoveTo(i * this.Step + this.RulerLeftOffset - 8, 42);
					context.ShowText((i / 10).ToString().PadLeft(2));
				}
				else
				{
					if (i % 5 == 0)
					{
						context.MoveTo(i * this.Step + this.RulerLeftOffset, 10);
						context.LineTo(i * this.Step + this.RulerLeftOffset, 25);
					}
					else
					{
						context.MoveTo(i * this.Step + this.RulerLeftOffset, 10);
						context.LineTo(i * this.Step + this.RulerLeftOffset, 20);
					}
				}
				context.StrokePreserve();
			}
		}
		
		private void UpdateSize()
		{
			if (this.CurrentRulerPosition == RulerPosition.Left || this.CurrentRulerPosition == RulerPosition.Right)
				this.SetSizeRequest(55, this.RulerLength * this.Step + this.RulerTopOffset + this.RulerBottomOffset);
			else
				this.SetSizeRequest(this.RulerLength * this.Step + this.RulerLeftOffset + this.RulerTopOffset, 55);
			this.QueueDraw();
		}
		
		private void UpdateSliderPosition(int delta)
		{
			if (this.CurrentRulerPosition == RulerPosition.Left || this.CurrentRulerPosition == RulerPosition.Right)
			{
				this.FirstSliderY = this.FirstSliderY - this.RulerTopOffset  + delta;
				this.SecondSliderY = this.SecondSliderY - this.RulerTopOffset  + delta;
			}
			else
			{
				this.FirstSliderX = this.FirstSliderX - this.RulerLeftOffset  + delta;
				this.SecondSliderX = this.SecondSliderX -this.RulerLeftOffset  + delta;
			}
		}
		
		public RulerPosition CurrentRulerPosition
		{
			get{return this.ruler_position;}
			set
			{
				this.ruler_position = value;
				this.QueueDraw();
			}
		}
		
		public int FirstSliderX
		{
			get{return this.first_slider_x;}
			set
			{
				this.first_slider_x = value;
				this.QueueDraw();
			}		
		}
		
		public int FirstSliderY
		{
			get{return this.first_slider_y;}
			set
			{
				this.first_slider_y = value;
				this.QueueDraw();
			}		
		}
		
		public int SecondSliderX
		{
			get{return this.second_slider_x;}
			set
			{
				this.second_slider_x = value;
				this.QueueDraw();
			}		
		}
		
		public int SecondSliderY
		{
			get{return this.second_slider_y;}
			set
			{
				this.second_slider_y = value;
				this.QueueDraw();
			}		
		}
		
		public int RulerLeftOffset
		{
			get{return this.ruler_left__offset;}
			set
			{
				this.UpdateSliderPosition(value);
				this.ruler_left__offset = value;
				this.UpdateSize();
				
					
			}
		}
			
		public int RulerRightOffset
		{
			get{return this.ruler_right__offset;}
			set
			{
				this.ruler_right__offset = value;
				this.UpdateSize();
			}
		}
		
		public int RulerTopOffset
		{
			get{return this.ruler_top__offset;}
			set
			{
				this.UpdateSliderPosition(value);
				this.ruler_top__offset = value;
				this.UpdateSize();
			}
		}
		
		public int RulerBottomOffset
		{
			get{return this.ruler_bottom__offset;}
			set
			{
				this.ruler_bottom__offset = value;
				this.UpdateSize();
			}
		}
		
		public Cairo.Color BackgroundColor
		{
			get{return this.background_color;}
			set
			{
				this.background_color = value;
				this.QueueDraw();
			}
		}
		
		public Cairo.Color ActiveColor
		{
			get{return this.activ_color;}
			set
			{
				this.activ_color = value;
				this.QueueDraw();
			}
		}
		
		public int RulerLength{get;set;}
		private int Step{get;set;}
		
	}
}

