www.pudn.com > cad-draw.zip > Canvas.cs, change:2007-12-29,size:27209b


using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Drawing; 
using System.Data; 
using System.Text; 
using System.Windows.Forms; 
 
namespace Canvas 
{ 
	public struct CanvasWrapper : ICanvas 
	{ 
		CanvasCtrl m_canvas;  
		Graphics m_graphics; 
		Rectangle m_rect; 
		public CanvasWrapper(CanvasCtrl canvas) 
		{ 
			m_canvas = canvas; 
			m_graphics = null; 
			m_rect = new Rectangle(); 
		} 
		public CanvasWrapper(CanvasCtrl canvas, Graphics graphics, Rectangle clientrect) 
		{ 
			m_canvas = canvas; 
			m_graphics = graphics; 
			m_rect = clientrect; 
		} 
		public IModel Model 
		{ 
			get { return m_canvas.Model; } 
		} 
		public CanvasCtrl CanvasCtrl 
		{ 
			get { return m_canvas; } 
		} 
		public void Dispose() 
		{ 
			m_graphics = null; 
		} 
		#region ICanvas Members 
		public IModel DataModel 
		{ 
			get { return m_canvas.Model; } 
		} 
		public UnitPoint ScreenTopLeftToUnitPoint() 
		{ 
			return m_canvas.ScreenTopLeftToUnitPoint(); 
		} 
		public UnitPoint ScreenBottomRightToUnitPoint() 
		{ 
			return m_canvas.ScreenBottomRightToUnitPoint(); 
		} 
		public PointF ToScreen(UnitPoint unitpoint) 
		{ 
			return m_canvas.ToScreen(unitpoint); 
		} 
		public float ToScreen(double unitvalue) 
		{ 
			return m_canvas.ToScreen(unitvalue); 
		} 
		public double ToUnit(float screenvalue) 
		{ 
			return m_canvas.ToUnit(screenvalue); 
		} 
		public UnitPoint ToUnit(PointF screenpoint) 
		{ 
			return m_canvas.ToUnit(screenpoint); 
		} 
		public Graphics Graphics 
		{ 
			get { return m_graphics; } 
		} 
		public Rectangle ClientRectangle 
		{ 
			get { return m_rect; } 
			set { m_rect = value; } 
		} 
		public Pen CreatePen(Color color, float unitWidth) 
		{ 
			return m_canvas.CreatePen(color, unitWidth); 
		} 
		public void DrawLine(ICanvas canvas, Pen pen, UnitPoint p1, UnitPoint p2) 
		{ 
			m_canvas.DrawLine(canvas, pen, p1, p2); 
		} 
		public void DrawArc(ICanvas canvas, Pen pen, UnitPoint center, float radius, float beginangle, float angle) 
		{ 
			m_canvas.DrawArc(canvas, pen, center, radius, beginangle, angle); 
		} 
		public void Invalidate() 
		{ 
			m_canvas.DoInvalidate(false); 
		} 
		public IDrawObject CurrentObject 
		{ 
			get { return m_canvas.NewObject; } 
		} 
		#endregion 
	} 
	public partial class CanvasCtrl : UserControl 
	{ 
		enum eCommandType 
		{ 
			select, 
			pan, 
			move, 
			draw, 
			edit, 
			editNode, 
		} 
 
		ICanvasOwner		m_owner; 
		CursorCollection	m_cursors = new CursorCollection(); 
		IModel				m_model; 
		MoveHelper			m_moveHelper = null; 
		NodeMoveHelper		m_nodeMoveHelper = null; 
		CanvasWrapper		m_canvaswrapper; 
		eCommandType		m_commandType = eCommandType.select; 
		bool				m_runningSnaps = true; 
		Type[]				m_runningSnapTypes = null; 
		PointF				m_mousedownPoint; 
		IDrawObject			m_newObject = null; 
		IEditTool			m_editTool = null; 
		SelectionRectangle	m_selection = null; 
		string				m_drawObjectId = string.Empty; 
		string				m_editToolId = string.Empty; 
		Bitmap				m_staticImage = null; 
		bool				m_staticDirty = true; 
		ISnapPoint			m_snappoint = null; 
		 
		public Type[] RunningSnaps 
		{ 
			get { return m_runningSnapTypes; } 
			set { m_runningSnapTypes = value; } 
		} 
		public bool RunningSnapsEnabled 
		{ 
			get { return m_runningSnaps; } 
			set { m_runningSnaps = value; } 
		} 
 
		System.Drawing.Drawing2D.SmoothingMode	m_smoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighSpeed; 
		public System.Drawing.Drawing2D.SmoothingMode SmoothingMode 
		{ 
			get { return m_smoothingMode; } 
			set { m_smoothingMode = value;} 
		} 
 
		public IModel Model 
		{ 
			get { return m_model; } 
			set { m_model = value; } 
		} 
		public CanvasCtrl(ICanvasOwner owner, IModel datamodel) 
		{ 
			m_canvaswrapper = new CanvasWrapper(this); 
			m_owner = owner; 
			m_model = datamodel; 
 
			InitializeComponent(); 
			this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint, true); 
			this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); 
 
			m_commandType = eCommandType.select; 
			m_cursors.AddCursor(eCommandType.select, Cursors.Arrow); 
			m_cursors.AddCursor(eCommandType.draw, Cursors.Cross); 
			m_cursors.AddCursor(eCommandType.pan, "hmove.cur"); 
			m_cursors.AddCursor(eCommandType.move, Cursors.SizeAll); 
			m_cursors.AddCursor(eCommandType.edit, Cursors.Cross); 
			UpdateCursor(); 
 
			m_moveHelper = new MoveHelper(this); 
			m_nodeMoveHelper = new NodeMoveHelper(m_canvaswrapper); 
		} 
		public UnitPoint GetMousePoint() 
		{ 
			Point point = this.PointToClient(Control.MousePosition); 
			return ToUnit(point); 
		} 
		public void SetCenter(UnitPoint unitPoint) 
		{ 
			PointF point = ToScreen(unitPoint); 
			m_lastCenterPoint = unitPoint; 
			SetCenterScreen(point, false); 
		} 
		public void SetCenter() 
		{ 
			Point point = this.PointToClient(Control.MousePosition); 
			SetCenterScreen(point, true); 
		} 
		public UnitPoint GetCenter() 
		{ 
			return ToUnit(new PointF(this.ClientRectangle.Width/2, this.ClientRectangle.Height/2)); 
		} 
		protected  void SetCenterScreen(PointF screenPoint, bool setCursor) 
		{ 
			float centerX = ClientRectangle.Width / 2; 
			m_panOffset.X += centerX - screenPoint.X; 
			 
			float centerY = ClientRectangle.Height / 2; 
			m_panOffset.Y += centerY - screenPoint.Y; 
 
			if (setCursor) 
				Cursor.Position = this.PointToScreen(new Point((int)centerX, (int)centerY)); 
			DoInvalidate(true); 
		} 
		protected override void OnPaint(PaintEventArgs e) 
		{ 
			CommonTools.Tracing.StartTrack(Program.TracePaint); 
			ClearPens(); 
			e.Graphics.SmoothingMode = m_smoothingMode; 
			CanvasWrapper dc = new CanvasWrapper(this, e.Graphics, ClientRectangle); 
			Rectangle cliprectangle = e.ClipRectangle; 
			if (m_staticImage == null) 
			{ 
				cliprectangle = ClientRectangle; 
				m_staticImage = new Bitmap(ClientRectangle.Width, ClientRectangle.Height); 
				m_staticDirty = true; 
			} 
			RectangleF r = ScreenUtils.ToUnitNormalized(dc, cliprectangle); 
			if (float.IsNaN(r.Width) || float.IsInfinity(r.Width)) 
			{ 
				r = ScreenUtils.ToUnitNormalized(dc, cliprectangle); 
			} 
			if (m_staticDirty) 
			{ 
				m_staticDirty = false; 
				CanvasWrapper dcStatic = new CanvasWrapper(this, Graphics.FromImage(m_staticImage), ClientRectangle); 
				dcStatic.Graphics.SmoothingMode = m_smoothingMode; 
				m_model.BackgroundLayer.Draw(dcStatic, r); 
				if (m_model.GridLayer.Enabled) 
					m_model.GridLayer.Draw(dcStatic, r); 
 
				PointF nullPoint = ToScreen(new UnitPoint(0, 0)); 
				dcStatic.Graphics.DrawLine(Pens.Blue, nullPoint.X - 10, nullPoint.Y, nullPoint.X + 10, nullPoint.Y); 
				dcStatic.Graphics.DrawLine(Pens.Blue, nullPoint.X, nullPoint.Y - 10, nullPoint.X, nullPoint.Y + 10); 
 
				ICanvasLayer[] layers = m_model.Layers; 
				for (int layerindex = layers.Length - 1; layerindex >= 0; layerindex--) 
				{ 
					if (layers[layerindex] != m_model.ActiveLayer && layers[layerindex].Visible) 
						layers[layerindex].Draw(dcStatic, r); 
				} 
				if (m_model.ActiveLayer != null) 
					m_model.ActiveLayer.Draw(dcStatic, r); 
 
				dcStatic.Dispose(); 
			} 
			e.Graphics.DrawImage(m_staticImage, cliprectangle, cliprectangle, GraphicsUnit.Pixel); 
			 
			foreach (IDrawObject drawobject in m_model.SelectedObjects) 
				drawobject.Draw(dc, r); 
 
			if (m_newObject != null) 
				m_newObject.Draw(dc, r); 
			 
			if (m_snappoint != null) 
				m_snappoint.Draw(dc); 
			 
			if (m_selection != null) 
			{ 
				m_selection.Reset(); 
				m_selection.SetMousePoint(e.Graphics, this.PointToClient(Control.MousePosition)); 
			} 
			if (m_moveHelper.IsEmpty == false) 
				m_moveHelper.DrawObjects(dc, r); 
 
			if (m_nodeMoveHelper.IsEmpty == false) 
				m_nodeMoveHelper.DrawObjects(dc, r); 
			dc.Dispose(); 
			ClearPens(); 
			CommonTools.Tracing.EndTrack(Program.TracePaint, "OnPaint complete"); 
		} 
		void RepaintStatic(Rectangle r) 
		{ 
			if (m_staticImage == null) 
				return; 
			Graphics dc = Graphics.FromHwnd(Handle); 
			if (r.X < 0) r.X = 0; 
			if (r.X > m_staticImage.Width) r.X = 0; 
			if (r.Y < 0) r.Y = 0; 
			if (r.Y > m_staticImage.Height) r.Y = 0; 
			 
			if (r.Width > m_staticImage.Width || r.Width < 0) 
				r.Width = m_staticImage.Width; 
			if (r.Height > m_staticImage.Height || r.Height < 0) 
				r.Height = m_staticImage.Height; 
			dc.DrawImage(m_staticImage, r, r, GraphicsUnit.Pixel); 
			dc.Dispose(); 
		} 
		void RepaintSnappoint(ISnapPoint snappoint) 
		{ 
			if (snappoint == null) 
				return; 
			CanvasWrapper dc = new CanvasWrapper(this, Graphics.FromHwnd(Handle), ClientRectangle); 
			snappoint.Draw(dc); 
			dc.Graphics.Dispose(); 
			dc.Dispose(); 
		} 
		void RepaintObject(IDrawObject obj) 
		{ 
			if (obj == null) 
				return; 
			CanvasWrapper dc = new CanvasWrapper(this, Graphics.FromHwnd(Handle), ClientRectangle); 
			RectangleF invalidaterect = ScreenUtils.ConvertRect(ScreenUtils.ToScreenNormalized(dc, obj.GetBoundingRect(dc))); 
			obj.Draw(dc, invalidaterect); 
			dc.Graphics.Dispose(); 
			dc.Dispose(); 
		} 
		public void DoInvalidate(bool dostatic, RectangleF rect) 
		{ 
			if (dostatic) 
				m_staticDirty = true; 
			Invalidate(ScreenUtils.ConvertRect(rect)); 
		} 
		public void DoInvalidate(bool dostatic) 
		{ 
			if (dostatic) 
				m_staticDirty = true; 
			Invalidate(); 
		} 
		public IDrawObject NewObject 
		{ 
			get { return m_newObject; } 
		} 
		protected void HandleSelection(List<IDrawObject> selected) 
		{ 
			bool add = Control.ModifierKeys == Keys.Shift; 
			bool toggle = Control.ModifierKeys == Keys.Control; 
			bool invalidate = false; 
			bool anyoldsel = false; 
			int selcount = 0; 
			if (selected != null) 
				selcount = selected.Count; 
			foreach(IDrawObject obj in m_model.SelectedObjects) 
			{ 
				anyoldsel = true; 
				break; 
			} 
			if (toggle && selcount > 0) 
			{ 
				invalidate = true; 
				foreach (IDrawObject obj in selected) 
				{ 
					if (m_model.IsSelected(obj)) 
						m_model.RemoveSelectedObject(obj); 
					else 
						m_model.AddSelectedObject(obj); 
				} 
			} 
			if (add && selcount > 0) 
			{ 
				invalidate = true; 
				foreach (IDrawObject obj in selected) 
					m_model.AddSelectedObject(obj); 
			} 
			if (add == false && toggle == false && selcount > 0) 
			{ 
				invalidate = true; 
				m_model.ClearSelectedObjects(); 
				foreach (IDrawObject obj in selected) 
					m_model.AddSelectedObject(obj); 
			} 
			if (add == false && toggle == false && selcount == 0 && anyoldsel) 
			{ 
				invalidate = true; 
				m_model.ClearSelectedObjects(); 
			} 
 
			if (invalidate) 
				DoInvalidate(false); 
		} 
		void FinishNodeEdit() 
		{ 
			m_commandType = eCommandType.select; 
			m_snappoint = null; 
		} 
		protected virtual void HandleMouseDownWhenDrawing(UnitPoint mouseunitpoint, ISnapPoint snappoint) 
		{ 
			if (m_commandType == eCommandType.draw) 
			{ 
				if (m_newObject == null) 
				{ 
					m_newObject = m_model.CreateObject(m_drawObjectId, mouseunitpoint, snappoint); 
					DoInvalidate(false, m_newObject.GetBoundingRect(m_canvaswrapper)); 
				} 
				else 
				{ 
					if (m_newObject != null) 
					{ 
						eDrawObjectMouseDown result = m_newObject.OnMouseDown(m_canvaswrapper, mouseunitpoint, snappoint); 
						switch (result) 
						{ 
							case eDrawObjectMouseDown.Done: 
								m_model.AddObject(m_model.ActiveLayer, m_newObject); 
								m_newObject = null; 
								DoInvalidate(true); 
								break; 
							case eDrawObjectMouseDown.DoneRepeat: 
								m_model.AddObject(m_model.ActiveLayer, m_newObject); 
								m_newObject = m_model.CreateObject(m_newObject.Id, m_newObject.RepeatStartingPoint, null); 
								DoInvalidate(true); 
								break; 
							case eDrawObjectMouseDown.Continue: 
								break; 
						} 
					} 
				} 
			} 
		} 
		protected override void OnMouseDown(MouseEventArgs e) 
		{ 
			m_mousedownPoint = new PointF(e.X, e.Y); // used when panning 
			m_dragOffset = new PointF(0,0); 
 
			UnitPoint mousepoint = ToUnit(m_mousedownPoint); 
			if (m_snappoint != null) 
				mousepoint = m_snappoint.SnapPoint; 
			 
			if (m_commandType == eCommandType.editNode) 
			{ 
				bool handled = false; 
				if (m_nodeMoveHelper.HandleMouseDown(mousepoint, ref handled)) 
				{ 
					FinishNodeEdit(); 
					base.OnMouseDown(e); 
					return; 
				} 
			} 
			if (m_commandType == eCommandType.select) 
			{ 
				bool handled = false; 
				if (m_nodeMoveHelper.HandleMouseDown(mousepoint, ref handled)) 
				{ 
					m_commandType = eCommandType.editNode; 
					m_snappoint = null; 
					base.OnMouseDown(e); 
					return; 
				} 
				m_selection = new SelectionRectangle(m_mousedownPoint); 
			} 
			if (m_commandType == eCommandType.move) 
			{ 
				m_moveHelper.HandleMouseDownForMove(mousepoint, m_snappoint); 
			} 
			if (m_commandType == eCommandType.draw) 
			{ 
				HandleMouseDownWhenDrawing(mousepoint, null); 
				DoInvalidate(true); 
			} 
			if (m_commandType == eCommandType.edit) 
			{ 
				if (m_editTool == null) 
					m_editTool = m_model.GetEditTool(m_editToolId); 
				if (m_editTool != null) 
				{ 
					if (m_editTool.SupportSelection) 
						m_selection = new SelectionRectangle(m_mousedownPoint); 
 
					eDrawObjectMouseDown mouseresult = m_editTool.OnMouseDown(m_canvaswrapper, mousepoint, m_snappoint); 
					/* 
					if (mouseresult == eDrawObjectMouseDown.Continue) 
					{ 
						if (m_editTool.SupportSelection) 
							m_selection = new SelectionRectangle(m_mousedownPoint); 
					} 
					 * */ 
					if (mouseresult == eDrawObjectMouseDown.Done) 
					{ 
						m_editTool.Finished(); 
						m_editTool = m_model.GetEditTool(m_editToolId); // continue with new tool 
						//m_editTool = null; 
						 
						if (m_editTool.SupportSelection) 
							m_selection = new SelectionRectangle(m_mousedownPoint); 
					} 
				} 
				DoInvalidate(true); 
				UpdateCursor(); 
			} 
			base.OnMouseDown(e); 
		} 
		protected override void OnMouseUp(MouseEventArgs e) 
		{ 
			base.OnMouseUp(e); 
 
			if (m_commandType == eCommandType.pan) 
			{ 
				m_panOffset.X += m_dragOffset.X; 
				m_panOffset.Y += m_dragOffset.Y; 
				m_dragOffset = new PointF(0, 0); 
			} 
 
			List<IDrawObject> hitlist = null; 
			Rectangle screenSelRect = Rectangle.Empty; 
			if (m_selection != null) 
			{ 
				screenSelRect = m_selection.ScreenRect(); 
				RectangleF selectionRect = m_selection.Selection(m_canvaswrapper); 
				if (selectionRect != RectangleF.Empty) 
				{ 
					// is any selection rectangle. use it for selection 
					hitlist = m_model.GetHitObjects(m_canvaswrapper, selectionRect, m_selection.AnyPoint()); 
					DoInvalidate(true); 
				} 
				else 
				{ 
					// else use mouse point 
					UnitPoint mousepoint = ToUnit(new PointF(e.X, e.Y)); 
					hitlist = m_model.GetHitObjects(m_canvaswrapper, mousepoint); 
				} 
				m_selection = null; 
			} 
			if (m_commandType == eCommandType.select) 
			{ 
				if (hitlist != null) 
					HandleSelection(hitlist); 
			} 
			if (m_commandType == eCommandType.edit && m_editTool != null) 
			{ 
				UnitPoint mousepoint = ToUnit(m_mousedownPoint); 
				if (m_snappoint != null) 
					mousepoint = m_snappoint.SnapPoint; 
				if (screenSelRect != Rectangle.Empty) 
					m_editTool.SetHitObjects(mousepoint, hitlist); 
				m_editTool.OnMouseUp(m_canvaswrapper, mousepoint, m_snappoint); 
			} 
			if (m_commandType == eCommandType.draw && m_newObject != null) 
			{ 
				UnitPoint mousepoint = ToUnit(m_mousedownPoint); 
				if (m_snappoint != null) 
					mousepoint = m_snappoint.SnapPoint; 
				m_newObject.OnMouseUp(m_canvaswrapper, mousepoint, m_snappoint); 
			} 
		} 
		protected override void OnMouseMove(MouseEventArgs e) 
		{ 
			base.OnMouseMove(e); 
			if (m_selection != null) 
			{ 
				Graphics dc = Graphics.FromHwnd(Handle); 
				m_selection.SetMousePoint(dc, new PointF(e.X, e.Y)); 
				dc.Dispose(); 
				return; 
			} 
 
			if (m_commandType == eCommandType.pan && e.Button == MouseButtons.Left) 
			{ 
				m_dragOffset.X = -(m_mousedownPoint.X - e.X); 
				m_dragOffset.Y = -(m_mousedownPoint.Y - e.Y); 
				m_lastCenterPoint = CenterPointUnit(); 
				DoInvalidate(true); 
			} 
			UnitPoint mousepoint; 
			UnitPoint unitpoint = ToUnit(new PointF(e.X, e.Y)); 
			if (m_commandType == eCommandType.draw || m_commandType == eCommandType.move || m_nodeMoveHelper.IsEmpty == false) 
			{ 
				Rectangle invalidaterect = Rectangle.Empty; 
				ISnapPoint newsnap = null; 
				mousepoint = GetMousePoint(); 
				if (RunningSnapsEnabled) 
					newsnap = m_model.SnapPoint(m_canvaswrapper, mousepoint, m_runningSnapTypes, null); 
				if (newsnap == null) 
					newsnap = m_model.GridLayer.SnapPoint(m_canvaswrapper, mousepoint, null); 
				if ((m_snappoint != null) && ((newsnap == null) || (newsnap.SnapPoint != m_snappoint.SnapPoint) || m_snappoint.GetType() != newsnap.GetType())) 
				{ 
					invalidaterect = ScreenUtils.ConvertRect(ScreenUtils.ToScreenNormalized(m_canvaswrapper, m_snappoint.BoundingRect)); 
					invalidaterect.Inflate(2, 2); 
					RepaintStatic(invalidaterect); // remove old snappoint 
					m_snappoint = newsnap; 
				} 
				if (m_commandType == eCommandType.move) 
					Invalidate(invalidaterect); 
 
				if (m_snappoint == null) 
					m_snappoint = newsnap; 
			} 
			m_owner.SetPositionInfo(unitpoint); 
			m_owner.SetSnapInfo(m_snappoint); 
 
 
			//UnitPoint mousepoint; 
			if (m_snappoint != null) 
				mousepoint = m_snappoint.SnapPoint; 
			else 
				mousepoint = GetMousePoint(); 
 
			if (m_newObject != null) 
			{ 
				Rectangle invalidaterect = ScreenUtils.ConvertRect(ScreenUtils.ToScreenNormalized(m_canvaswrapper, m_newObject.GetBoundingRect(m_canvaswrapper))); 
				invalidaterect.Inflate(2, 2); 
				RepaintStatic(invalidaterect); 
 
				m_newObject.OnMouseMove(m_canvaswrapper, mousepoint); 
				RepaintObject(m_newObject); 
			} 
			if (m_snappoint != null) 
				RepaintSnappoint(m_snappoint); 
 
			if (m_moveHelper.HandleMouseMoveForMove(mousepoint)) 
				Refresh(); //Invalidate(); 
 
			RectangleF rNoderect = m_nodeMoveHelper.HandleMouseMoveForNode(mousepoint); 
			if (rNoderect != RectangleF.Empty) 
			{ 
				Rectangle invalidaterect = ScreenUtils.ConvertRect(ScreenUtils.ToScreenNormalized(m_canvaswrapper, rNoderect)); 
				RepaintStatic(invalidaterect); 
 
				CanvasWrapper dc = new CanvasWrapper(this, Graphics.FromHwnd(Handle), ClientRectangle); 
				dc.Graphics.Clip = new Region(ClientRectangle); 
				//m_nodeMoveHelper.DrawOriginalObjects(dc, rNoderect); 
				m_nodeMoveHelper.DrawObjects(dc, rNoderect); 
				if (m_snappoint != null) 
					RepaintSnappoint(m_snappoint); 
 
				dc.Graphics.Dispose(); 
				dc.Dispose(); 
			} 
		} 
		protected override void OnMouseWheel(MouseEventArgs e) 
		{ 
			UnitPoint p = GetMousePoint(); 
			float wheeldeltatick = 120; 
			float zoomdelta = (1.25f * (Math.Abs(e.Delta) / wheeldeltatick)); 
			if (e.Delta < 0) 
				m_model.Zoom = m_model.Zoom / zoomdelta; 
			else 
				m_model.Zoom = m_model.Zoom * zoomdelta; 
			SetCenterScreen(ToScreen(p), true); 
			DoInvalidate(true); 
			base.OnMouseWheel(e); 
		} 
		protected override void OnResize(EventArgs e) 
		{ 
			base.OnResize(e); 
 
			if (m_lastCenterPoint != UnitPoint.Empty && Width != 0) 
				SetCenterScreen(ToScreen(m_lastCenterPoint), false); 
			m_lastCenterPoint = CenterPointUnit(); 
			m_staticImage = null; 
			DoInvalidate(true); 
		} 
 
		UnitPoint m_lastCenterPoint; 
		PointF m_panOffset = new PointF(25, -25); 
		PointF m_dragOffset = new PointF(0, 0); 
		float m_screenResolution = 96; 
 
		PointF Translate(UnitPoint point) 
		{ 
			return point.Point; 
		} 
		float ScreenHeight() 
		{ 
			return (float)(ToUnit(this.ClientRectangle.Height) / m_model.Zoom); 
		} 
 
		#region ICanvas 
		public UnitPoint CenterPointUnit() 
		{ 
			UnitPoint p1 = ScreenTopLeftToUnitPoint(); 
			UnitPoint p2 = ScreenBottomRightToUnitPoint(); 
			UnitPoint center = new UnitPoint(); 
			center.X = (p1.X + p2.X) / 2; 
			center.Y = (p1.Y + p2.Y) / 2; 
			return center; 
		} 
		public UnitPoint ScreenTopLeftToUnitPoint() 
		{ 
			return ToUnit(new PointF(0, 0)); 
		} 
		public UnitPoint ScreenBottomRightToUnitPoint() 
		{ 
			return ToUnit(new PointF(this.ClientRectangle.Width, this.ClientRectangle.Height)); 
		} 
		public PointF ToScreen(UnitPoint point) 
		{ 
			PointF transformedPoint = Translate(point); 
			transformedPoint.Y = ScreenHeight() - transformedPoint.Y; 
			transformedPoint.Y *= m_screenResolution * m_model.Zoom; 
			transformedPoint.X *= m_screenResolution * m_model.Zoom; 
 
			transformedPoint.X += m_panOffset.X + m_dragOffset.X; 
			transformedPoint.Y += m_panOffset.Y + m_dragOffset.Y; 
			return transformedPoint; 
		} 
		public float ToScreen(double value) 
		{ 
			return (float)(value * m_screenResolution * m_model.Zoom); 
		} 
		public double ToUnit(float screenvalue) 
		{ 
			return (double)screenvalue / (double)(m_screenResolution * m_model.Zoom); 
		} 
		public UnitPoint ToUnit(PointF screenpoint) 
		{ 
			float panoffsetX = m_panOffset.X + m_dragOffset.X; 
			float panoffsetY = m_panOffset.Y + m_dragOffset.Y; 
			float xpos = (screenpoint.X - panoffsetX) / (m_screenResolution * m_model.Zoom); 
			float ypos = ScreenHeight() - ((screenpoint.Y - panoffsetY)) / (m_screenResolution * m_model.Zoom); 
			return new UnitPoint(xpos, ypos); 
		} 
		public Pen CreatePen(Color color, float unitWidth) 
		{ 
			return GetPen(color, ToScreen(unitWidth)); 
		} 
		public void DrawLine(ICanvas canvas, Pen pen, UnitPoint p1, UnitPoint p2) 
		{ 
			PointF tmpp1 = ToScreen(p1); 
			PointF tmpp2 = ToScreen(p2); 
			canvas.Graphics.DrawLine(pen, tmpp1, tmpp2); 
		} 
		public void DrawArc(ICanvas canvas, Pen pen, UnitPoint center, float radius, float startAngle, float sweepAngle) 
		{ 
			PointF p1 = ToScreen(center); 
			radius = (float)Math.Round(ToScreen(radius)); 
			RectangleF r = new RectangleF(p1, new SizeF()); 
			r.Inflate(radius, radius); 
			if (radius > 0 && radius < 1e8f ) 
				canvas.Graphics.DrawArc(pen, r, -startAngle, -sweepAngle); 
		} 
 
		#endregion 
 
		Dictionary<float, Dictionary<Color, Pen>> m_penCache = new Dictionary<float,Dictionary<Color,Pen>>(); 
		Pen GetPen(Color color, float width) 
		{ 
			if (m_penCache.ContainsKey(width) == false) 
				m_penCache[width] = new Dictionary<Color,Pen>(); 
			if (m_penCache[width].ContainsKey(color) == false) 
				m_penCache[width][color] = new Pen(color, width); 
			return m_penCache[width][color]; 
		} 
		void ClearPens() 
		{ 
			m_penCache.Clear(); 
		} 
		 
		void UpdateCursor() 
		{ 
			Cursor = m_cursors.GetCursor(m_commandType); 
		} 
 
		Dictionary<Keys, Type> m_QuickSnap = new Dictionary<Keys,Type>(); 
		public void AddQuickSnapType(Keys key, Type snaptype) 
		{ 
			m_QuickSnap.Add(key, snaptype); 
		} 
 
		public void CommandSelectDrawTool(string drawobjectid) 
		{ 
			CommandEscape(); 
			m_model.ClearSelectedObjects(); 
			m_commandType = eCommandType.draw; 
			m_drawObjectId = drawobjectid; 
			UpdateCursor(); 
		} 
		public void CommandEscape() 
		{ 
			bool dirty = (m_newObject != null) || (m_snappoint != null); 
			m_newObject = null; 
			m_snappoint = null; 
			if (m_editTool != null) 
				m_editTool.Finished(); 
			m_editTool	= null; 
			m_commandType = eCommandType.select; 
			m_moveHelper.HandleCancelMove(); 
			m_nodeMoveHelper.HandleCancelMove(); 
			DoInvalidate(dirty); 
			UpdateCursor(); 
		} 
		public void CommandPan() 
		{ 
			if (m_commandType == eCommandType.select || m_commandType == eCommandType.move) 
				m_commandType = eCommandType.pan; 
			UpdateCursor(); 
		} 
		public void CommandMove(bool handleImmediately) 
		{ 
			if (m_model.SelectedCount > 0) 
			{ 
				if (handleImmediately && m_commandType == eCommandType.move) 
					m_moveHelper.HandleMouseDownForMove(GetMousePoint(), m_snappoint); 
				m_commandType = eCommandType.move; 
				UpdateCursor(); 
			} 
		} 
		public void CommandDeleteSelected() 
		{ 
			m_model.DeleteObjects(m_model.SelectedObjects); 
			m_model.ClearSelectedObjects(); 
			DoInvalidate(true); 
			UpdateCursor(); 
		} 
		public void CommandEdit(string editid) 
		{ 
			CommandEscape(); 
			m_model.ClearSelectedObjects(); 
			m_commandType = eCommandType.edit; 
			m_editToolId = editid; 
			m_editTool = m_model.GetEditTool(m_editToolId); 
			UpdateCursor(); 
		} 
		void HandleQuickSnap(KeyEventArgs e) 
		{ 
			if (m_commandType == eCommandType.select || m_commandType == eCommandType.pan) 
				return; 
			ISnapPoint p = null; 
			UnitPoint mousepoint = GetMousePoint(); 
			if (m_QuickSnap.ContainsKey(e.KeyCode)) 
				p = m_model.SnapPoint(m_canvaswrapper, mousepoint, null, m_QuickSnap[e.KeyCode]); 
			if (p != null) 
			{ 
				if (m_commandType == eCommandType.draw) 
				{ 
					HandleMouseDownWhenDrawing(p.SnapPoint, p); 
					if (m_newObject != null) 
						m_newObject.OnMouseMove(m_canvaswrapper, GetMousePoint()); 
					DoInvalidate(true); 
					e.Handled = true; 
				} 
				if (m_commandType == eCommandType.move) 
				{ 
					m_moveHelper.HandleMouseDownForMove(p.SnapPoint, p); 
					e.Handled = true; 
				} 
				if (m_nodeMoveHelper.IsEmpty == false) 
				{ 
					bool handled = false; 
					m_nodeMoveHelper.HandleMouseDown(p.SnapPoint, ref handled); 
					FinishNodeEdit(); 
					e.Handled = true; 
				} 
				if (m_commandType == eCommandType.edit) 
				{ 
				} 
			} 
		} 
		protected override void OnKeyDown(KeyEventArgs e) 
		{ 
			HandleQuickSnap(e); 
 
			if (m_nodeMoveHelper.IsEmpty == false) 
			{ 
				m_nodeMoveHelper.OnKeyDown(m_canvaswrapper, e); 
				if (e.Handled) 
					return; 
			} 
			base.OnKeyDown(e); 
			if (e.Handled) 
			{ 
				UpdateCursor(); 
				return; 
			} 
			if (m_editTool != null) 
			{ 
				m_editTool.OnKeyDown(m_canvaswrapper, e); 
				if (e.Handled) 
					return; 
			} 
			if (m_newObject != null) 
			{ 
				m_newObject.OnKeyDown(m_canvaswrapper, e); 
				if (e.Handled) 
					return; 
			} 
			foreach (IDrawObject obj in m_model.SelectedObjects) 
			{ 
				obj.OnKeyDown(m_canvaswrapper, e); 
				if (e.Handled) 
					return; 
			} 
 
			if ((Control.ModifierKeys & Keys.Control) == Keys.Control) 
			{ 
				if (e.KeyCode == Keys.G) 
				{ 
					m_model.GridLayer.Enabled = !m_model.GridLayer.Enabled; 
					DoInvalidate(true); 
				} 
				if (e.KeyCode == Keys.S) 
				{ 
					RunningSnapsEnabled = !RunningSnapsEnabled; 
					if (!RunningSnapsEnabled) 
						m_snappoint = null; 
					DoInvalidate(false); 
				} 
				return; 
			} 
 
			if (e.KeyCode == Keys.Escape) 
			{ 
				CommandEscape(); 
			} 
			if (e.KeyCode == Keys.P) 
			{ 
				CommandPan(); 
			} 
			if (e.KeyCode == Keys.S) 
			{ 
				RunningSnapsEnabled = !RunningSnapsEnabled; 
				if (!RunningSnapsEnabled) 
					m_snappoint = null; 
				DoInvalidate(false); 
			} 
			if (e.KeyCode >= Keys.D1 && e.KeyCode <= Keys.D9) 
			{ 
				int layerindex = (int)e.KeyCode - (int)Keys.D1; 
				if (layerindex >=0 && layerindex < m_model.Layers.Length) 
				{ 
					m_model.ActiveLayer = m_model.Layers[layerindex]; 
					DoInvalidate(true); 
				} 
			} 
			if (e.KeyCode == Keys.Delete) 
			{ 
				CommandDeleteSelected(); 
			} 
			if (e.KeyCode == Keys.O) 
			{ 
				CommandEdit("linesmeet"); 
			} 
			UpdateCursor(); 
		} 
	} 
}