WorkflowView.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / WF / Common / AuthoringOM / Design / WorkflowView.cs / 1305376 / WorkflowView.cs

                            namespace System.Workflow.ComponentModel.Design 
{
 	using System;
	using System.IO;
	using System.Data; 
	using System.Drawing;
 	using System.Security; 
	using System.Resources; 
 	using System.Reflection;
 	using System.Diagnostics; 
	using System.Collections;
 	using System.Windows.Forms;
	using System.ComponentModel;
	using System.Drawing.Design; 
	using System.Drawing.Imaging;
 	using System.Drawing.Printing; 
	using System.Drawing.Drawing2D; 
    using System.Workflow.Interop;
    using System.Collections.Generic; 
 	using System.Windows.Forms.Design;
 	using System.Security.Permissions;
	using System.ComponentModel.Design;
 	using System.Runtime.InteropServices; 
    using System.Collections.ObjectModel;
    ///What did I change in this file 
	///1. Eliminated the layout manager and introduced classes for WorkflowLayout and PrintPreviewLayout 
	///2. Eliminated the event syncing of PageSetupData change. We call performlayout on the current designer service whenever the pagesetupdata changes
 
	/// Designer Features:
 	/// Selection on click and thru drag rectangle		
	/// Reconfigurable background						
 	/// Scrolling										 
 	/// Ensure Visible functionality					
	/// Accessibility									 
 	/// Zoom											 
	/// Rehostable			
	/// Extensible 
	/// Small memory footprint
 	/// Ability to move around objects using drag drop	
	/// Ability to drop the objects using drag drop		
 	/// Printing support								 
 	/// Theme support
	/// Magnifier 
 	/// AutoScroll 
	/// AutoExpand
	/// USE THIS FOR PERFORMANCE TEST: Debug.WriteLine("******Root drawing: " + Convert.ToString((DateTime.Now.Ticks - ticks) / 10000) + "ms"); 
	///
 	/// Here are some details about the coordinate system,
	///
 	/// Screen CoOrdinate System: Starts at 0,0 of the screen 
 	///	Client CoOrdinate System: Starts at 0,0 of the control
	/// Logical CoOrdinate System: The workflowview supports zooming and scroll, we want to hide this 
 	/// complexity from the activity writter and hence whenever we get a coordinate we translate it based 
	/// scroll position, zoom level and layout. This helps us to sheild the activity designers from complexity
	/// of zooming, scaling and layouting. The designer writters deal with one coordinate system which is unscaled and 
	/// starts at 0,0
 	///
	///
 
 	[ToolboxItem(false)]
 	[ActivityDesignerTheme(typeof(AmbientTheme), Xml = WorkflowView.ThemeXml)] 
	public class WorkflowView : UserControl, IServiceProvider, IMessageFilter 
 	{
		#region Theme Initializer XML 
		internal const string ThemeXml =
				"";
		#endregion 

		#region Members Variables
		private	enum TabButtonIds		{ MultiPage = 1, Zoom, Pan}
 
 		//Designer Hookup
		private IServiceProvider				serviceProvider = null; 
 		 
 		private ActivityDesigner				rootDesigner = null;
		 
 		//Zoom
		private float							zoomLevel = 1.0f;
		private int								shadowDepth = WorkflowTheme.CurrentTheme.AmbientTheme.ShadowDepth;
 
		//MessageFilters
        private List stockMessageFilters = new List(); 
        private List customMessageFilters = new List(); 

 		// 

 		private Bitmap							viewPortBitmap = null;

 		//Misc. 
		private WorkflowToolTip					workflowToolTip = null;
 
 		private CommandSet						commandSet = null; 
		private DynamicAction					fitAllAction = null;
 
		//print
		private int								prePreviewZoom = 100;
 		private Point							prePreviewScroll = Point.Empty;
		private WorkflowPrintDocument			printDocument = null; 

 		//Active layout 
 		private WorkflowLayout					activeLayout = null; 
		private WorkflowLayout					defaultLayout = null;
 
 		//One time callable delegates
		private EventHandler					layoutEventHandler = null;
        private EventHandler                    ensureVisibleEventHandler = null;
 
		private Stack				messageHitTestContexts = new Stack();
 
		private HScrollBar						hScrollBar; 
 		private VScrollBar						vScrollBar;
 
        private TabControl                      toolContainer;
        private EventHandler                    idleEventListeners;
        private EventHandler                    idleEventHandler;
 
        private bool                            dragDropInProgress;
		#endregion 
 
        #region Events
        public event EventHandler ZoomChanged; 
        public event EventHandler RootDesignerChanged;
        #endregion

        #region Constructor and Dispose 
        public WorkflowView() : this(new DesignSurface())
 		{ 
 		} 

		public WorkflowView(IServiceProvider serviceProvider) 
 		{
			Debug.Assert(serviceProvider != null);
			if (serviceProvider == null)
				throw new ArgumentNullException("serviceProvider"); 

 			SuspendLayout(); 
			AllowDrop = true; 
 			AutoScroll = false;
 			HScroll = false; 
			VScroll = false;
 			SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint | ControlStyles.Opaque | ControlStyles.AllPaintingInWmPaint | ControlStyles.Selectable | ControlStyles.EnableNotifyMessage, true);

			this.serviceProvider = serviceProvider; 

			//*****Promote the services which are accessed from other components 
			IServiceContainer serviceContainer = GetService(typeof(IServiceContainer)) as IServiceContainer; 
 			if (serviceContainer != null)
			{ 
 				//Remove any existing designer service if there is any
 				serviceContainer.RemoveService(typeof(WorkflowView));
				serviceContainer.AddService(typeof(WorkflowView), this);
            } 

            //set the UI Service to be used by themes 
            IUIService uiService = this.serviceProvider.GetService(typeof(IUIService)) as IUIService; 
            if(uiService != null)
                WorkflowTheme.UIService = uiService; 

 			//Make sure that we add scrollbars
			EnsureScrollBars(new HScrollBar(), new VScrollBar());
 
			//Initialize the tooltip shown
			this.workflowToolTip = new WorkflowToolTip(this); 
 
            //[....] the global theme change event, which is fired by the theme infrastructure for theme change
            WorkflowTheme.ThemeChanged += new EventHandler(OnThemeChange); 

            //Create the core message filters
            PopulateMessageFilters(true);
 
            //Set the root designer, note that the dynamic action is dependent on the DynamicActionMessageFilter pushed
            //when the root is set. 
            RootDesigner = ActivityDesigner.GetSafeRootDesigner(this); 
            this.fitAllAction = CreateDynamicAction();
 
 			//If the active layout is still null then we will set the default layout as active layout
			if (this.activeLayout == null || this.defaultLayout == null)
 				ActiveLayout = DefaultLayout = new WorkflowRootLayout(this.serviceProvider);
 
            //Create the local command set and update all the commands once
 			IMenuCommandService menuCommandService = GetService(typeof(IMenuCommandService)) as IMenuCommandService; 
			if (menuCommandService != null) 
 			{
				this.commandSet = new CommandSet(this); 
				this.commandSet.UpdatePanCommands(true);
			}

            //Subscribe to selection change 
            ISelectionService selectionService = GetService(typeof(ISelectionService)) as ISelectionService;
            if (selectionService != null) 
                selectionService.SelectionChanged += new EventHandler(OnSelectionChanged); 

            //In case of non VS case we need to pumpin the Keyboard messages, the user control sets 
            //focus to the child controls by default which is a problem so we need to trap the
            //messages by adding application level message filter, in case of VS this is not required and
            //the message filter is never called.
            Application.AddMessageFilter(this); 

            //We make sure that during the construction we dont do perform layouts on idle event 
            ResumeLayout(true); 
        }
 
 		protected override void Dispose(bool disposing)
		{
 			//Remove the proffered services
 			if (disposing) 
			{
                try 
                { 
                    SuspendLayout();
 
                    Application.RemoveMessageFilter(this);

                    if (this.layoutEventHandler != null)
                    { 
                        Idle -= this.layoutEventHandler;
                        this.layoutEventHandler = null; 
                    } 

                    if (this.ensureVisibleEventHandler != null) 
                    {
                        Idle -= this.ensureVisibleEventHandler;
                        this.ensureVisibleEventHandler = null;
                    } 

                    if (this.idleEventHandler != null) 
                    { 
                        this.idleEventListeners = null;
 
                        Form host = TopLevelControl as Form;
                        if (!Application.MessageLoop || (host != null && host.Modal))
                            WorkflowTimer.Default.Unsubscribe(this.idleEventHandler);
                        else 
                            Application.Idle -= this.idleEventHandler;
                        this.idleEventHandler = null; 
                    } 

                    ISelectionService selectionService = GetService(typeof(ISelectionService)) as ISelectionService; 
                    if (selectionService != null)
                        selectionService.SelectionChanged -= new EventHandler(OnSelectionChanged);

                    //Unsubscribe the theme change 
                    WorkflowTheme.ThemeChanged -= new EventHandler(OnThemeChange);
 
                    //Remove the dynamic action 
                    if (this.fitAllAction != null)
                    { 
                        this.fitAllAction.Dispose();
                        this.fitAllAction = null;
                    }
 
                    if (this.workflowToolTip != null)
                    { 
                        ((IDisposable)this.workflowToolTip).Dispose(); 
                        this.workflowToolTip = null;
                    } 

                    DisposeMessageFilters(false);
                    DisposeMessageFilters(true);
 
                    //Dispose the layouts
                    this.activeLayout = null; 
                    if (this.defaultLayout != null) 
                    {
                        this.defaultLayout.Dispose(); 
                        this.defaultLayout = null;
                    }

                    //Destroy other resources 
                    if (this.viewPortBitmap != null)
                    { 
                        this.viewPortBitmap.Dispose(); 
                        this.viewPortBitmap = null;
                    } 

                    if (this.commandSet != null)
                    {
                        this.commandSet.Dispose(); 
                        this.commandSet = null;
                    } 
 
                    HScrollBar.ValueChanged -= new EventHandler(OnScroll);
                    VScrollBar.ValueChanged -= new EventHandler(OnScroll); 

                    if (this.toolContainer != null)
                    {
                        Controls.Remove(this.toolContainer); 
                        this.toolContainer.TabStrip.Tabs.Clear();
                        this.toolContainer.Dispose(); 
                        this.toolContainer = null; 
                    }
 
                    IServiceContainer serviceContainer = GetService(typeof(IServiceContainer)) as IServiceContainer;
                    if (serviceContainer != null)
                    {
                        serviceContainer.RemoveService(typeof(WorkflowView)); 
                    }
                } 
                finally 
                {
                    ResumeLayout(false); 
                }
 			}

			base.Dispose( disposing ); 
		}
		#endregion 
 
 		#region Public Properties
		public int Zoom 
 		{
 			get
			{
 				return Convert.ToInt32(this.zoomLevel * 100); 
			}
 
			set 
			{
 				if (Zoom == value) 
					return;

 				if (value < AmbientTheme.MinZoom || value > AmbientTheme.MaxZoom)
 					throw new NotSupportedException(DR.GetString(DR.ZoomLevelException2, AmbientTheme.MinZoom, AmbientTheme.MaxZoom)); 

				ScrollBar hScrollBar = HScrollBar; 
 				ScrollBar vScrollBar = VScrollBar; 

                if (hScrollBar != null && vScrollBar != null) 
                {
                    PointF oldRelativeCenter = Point.Empty;
                    Point oldCenter = new Point(ScrollPosition.X, ScrollPosition.Y);
                    oldRelativeCenter = new PointF((float)oldCenter.X / (float)hScrollBar.Maximum, (float)oldCenter.Y / (float)vScrollBar.Maximum); 

                    //recalculate the zoom and scroll range 
                    this.zoomLevel = (float)value / 100.0f; 
                    UpdateScrollRange();
 
                    //center the view again
                    Point newCenter = new Point((int)((float)hScrollBar.Maximum * oldRelativeCenter.X), (int)((float)vScrollBar.Maximum * oldRelativeCenter.Y));
                    ScrollPosition = new Point(newCenter.X, newCenter.Y);
 
                    if (this.rootDesigner != null)
                        this.rootDesigner.Location = this.activeLayout.RootDesignerAlignment; 
 
                    InvalidateClientRectangle(Rectangle.Empty);
 
                    //

                    this.activeLayout.Update(null, WorkflowLayout.LayoutUpdateReason.ZoomChanged);
 
                    //force command refresh
                    //this is to workarond VS not refreshing Zoom drop down when doing area zoom-in 
                    IUIService uis = GetService(typeof(IUIService)) as IUIService; 
                    if (uis != null)
                        uis.SetUIDirty(); 

                    //We need to update the zoom commands when the zoom is updated
                    if (this.commandSet != null)
                        this.commandSet.UpdateZoomCommands(true); 

                    OnZoomChanged(); 
                } 
			}
		} 

		public ActivityDesigner RootDesigner
 		{
			get 
 			{
 				return this.rootDesigner; 
			} 

 			set 
			{
				if (this.rootDesigner == value)
					return;
 
                DisposeMessageFilters(false);
 
 				this.rootDesigner = value; 

				if (this.rootDesigner != null) 
 				{
                    PopulateMessageFilters(false);
                    ActiveLayout = DefaultLayout = this.rootDesigner.SupportedLayout;
 				} 

                OnRootDesignerChanged(); 
 
				base.PerformLayout();
 			} 
		}

		public int ShadowDepth
		{ 
 			get
			{ 
 				return this.shadowDepth; 
 			}
 
			set
 			{
				if (value < AmbientTheme.MinShadowDepth || value > AmbientTheme.MaxShadowDepth)
					throw new NotSupportedException(DR.GetString(DR.ShadowDepthException, AmbientTheme.MinShadowDepth, AmbientTheme.MaxShadowDepth)); 

				if (this.shadowDepth == value) 
 					return; 

				this.shadowDepth = value; 
 				InvalidateClientRectangle(Rectangle.Empty);
 			}
		}
 
 		public Rectangle ViewPortRectangle
		{ 
			get 
			{
 				return new Rectangle(ScrollPosition, ViewPortSize); 
			}
 		}

 		public Size ViewPortSize 
		{
 			get 
			{ 
				Size viewPortSize = ClientSize;
                if (HScrollBar.Visible) 
                    viewPortSize.Height = Math.Max(0, viewPortSize.Height - HScrollBar.Height);
                if (VScrollBar.Visible)
                    viewPortSize.Width = Math.Max(0, viewPortSize.Width - VScrollBar.Width);
				return viewPortSize; 
 			}
		} 
 
 		public Point ScrollPosition
 		{ 
			get
 			{
				return new Point(HScrollBar.Value, VScrollBar.Value);
			} 

			set 
 			{ 
				ScrollBar hScrollBar = HScrollBar;
 				if (hScrollBar != null) 
 				{
					value.X = Math.Min(value.X, hScrollBar.Maximum - hScrollBar.LargeChange + 1);
 					value.X = Math.Max(value.X, hScrollBar.Minimum);
					hScrollBar.Value = value.X; 
				}
 
				ScrollBar vScrollBar = VScrollBar; 
 				if (vScrollBar != null)
				{ 
 					value.Y = Math.Min(value.Y, vScrollBar.Maximum - vScrollBar.LargeChange + 1);
 					value.Y = Math.Max(value.Y, vScrollBar.Minimum);
					vScrollBar.Value = value.Y;
 				} 
			}
		} 
 
		public bool PrintPreviewMode
 		{ 
			get
 			{
 				return (this.activeLayout == ((WorkflowPrintDocument)PrintDocument).PrintPreviewLayout);
			} 

 			set 
			{ 
				if (PrintPreviewMode == value)
					return; 

 				if (value && PrinterSettings.InstalledPrinters.Count == 0)
				{
                    DesignerHelpers.ShowError(this, DR.GetString(DR.ThereIsNoPrinterInstalledErrorMessage)); 
 					value = false;
 				} 
 
                ActiveLayout = (value) ? ((WorkflowPrintDocument)PrintDocument).PrintPreviewLayout : DefaultLayout;
 
                if (this.commandSet != null)
					this.commandSet.UpdatePageLayoutCommands(true);

 				if (PrintPreviewMode) 
				{
					this.prePreviewZoom = Zoom; 
					this.prePreviewScroll = ScrollPosition; 
 					Zoom = 40;
				} 
 				else
 				{
					Zoom = this.prePreviewZoom;
 					ScrollPosition = this.prePreviewScroll; 
				}
			} 
		} 

 		public PrintDocument PrintDocument 
		{
 			get
 			{
				if (this.printDocument == null) 
 					this.printDocument = new WorkflowPrintDocument(this);
 
				return this.printDocument; 
			}
		} 

 		public event EventHandler Idle
		{
 			add 
 			{
                //Add the listener to our list 
                this.idleEventListeners += value; 

                if (this.idleEventHandler == null) 
                {
                    this.idleEventHandler = new EventHandler(OnWorkflowIdle);

                    Form host = TopLevelControl as Form; 
                    if (!Application.MessageLoop || (host != null && host.Modal))
                        WorkflowTimer.Default.Subscribe(100, this.idleEventHandler); 
                    else 
                        Application.Idle += this.idleEventHandler;
                } 
			}

 			remove
			{ 
                this.idleEventListeners -= value;
 
                if (this.idleEventHandler != null && this.idleEventListeners == null) 
                {
                    Form host = TopLevelControl as Form; 
                    if (host != null && host.Modal)
                        WorkflowTimer.Default.Unsubscribe(this.idleEventHandler);
                    else
                        Application.Idle -= this.idleEventHandler; 

                    this.idleEventHandler = null; 
                } 
			}
		} 

 		public HScrollBar HScrollBar
		{
 			get 
 			{
				return this.hScrollBar; 
 			} 
		}
 
		public VScrollBar VScrollBar
		{
 			get
			{ 
 				return this.vScrollBar;
 			} 
        } 

        public bool EnableFitToScreen 
        {
            get
            {
                return (this.fitAllAction != null); 
            }
 
            set 
            {
                if (EnableFitToScreen == value) 
                    return;

                if (value)
                { 
                    if (this.fitAllAction == null)
                        this.fitAllAction = CreateDynamicAction(); 
                } 
                else
                { 
                    if (this.fitAllAction != null)
                    {
                        this.fitAllAction.Dispose();
                        this.fitAllAction = null; 
                    }
                } 
 
                InvalidateClientRectangle(Rectangle.Empty);
            } 
        }
		#endregion

 		#region Protected Properties 
		#endregion
 
		#region Private Properties 
        internal bool DragDropInProgress
        { 
            get
            {
                return this.dragDropInProgress;
            } 
        }
 
        internal bool ShowToolContainer 
        {
            get 
            {
                return (this.toolContainer != null);
            }
 
            set
            { 
                if (ShowToolContainer == value) 
                    return;
 
                try
                {
                    SuspendLayout();
 
                    if (value)
                    { 
                        this.toolContainer = new TabControl(DockStyle.Right, AnchorAlignment.Far); 
                        Controls.Add(this.toolContainer);
                        EnsureScrollBars(this.hScrollBar, this.toolContainer.ScrollBar as VScrollBar); 

                        string[,] tabButtonInfo = new string[/*Caption Resource ID*/,/*Bitmap Resource ID*/ ] { { "MultipageLayoutCaption", "MultipageLayout" }, { "ZoomCaption", "Zoom" }, { "PanCaption", "AutoPan" } };
                        for (int i = 0; i < tabButtonInfo.GetLength(0); i++)
                        { 
                            Bitmap tabImage = DR.GetImage(tabButtonInfo[i, 1]) as Bitmap;
                            string buttonCaption = DR.GetString(tabButtonInfo[i, 0]); 
                            this.toolContainer.TabStrip.Tabs.Add(new ItemInfo(i + 1, tabImage, buttonCaption)); 
                        }
 
                        this.toolContainer.TabStrip.TabChange += new SelectionChangeEventHandler(OnTabChange);
                        if (this.commandSet != null)
                        {
                            this.commandSet.UpdatePageLayoutCommands(true); 
                            this.commandSet.UpdateZoomCommands(true);
                            this.commandSet.UpdatePanCommands(true); 
                        } 
                    }
                    else 
                    {
                        this.toolContainer.TabStrip.TabChange -= new SelectionChangeEventHandler(OnTabChange);
                        this.toolContainer.TabStrip.Tabs.Clear();
 
                        Controls.Remove(this.toolContainer);
                        this.toolContainer.Dispose(); 
                        this.toolContainer = null; 

                        EnsureScrollBars(this.hScrollBar, new VScrollBar()); 
                    }
                }
                finally
                { 
                    ResumeLayout(true);
                } 
            } 
        }
 
        internal HitTestInfo MessageHitTestContext
		{
 			get
			{ 
 				return this.messageHitTestContexts.Peek();
 			} 
		} 

 		internal WorkflowLayout ActiveLayout 
		{
			get
			{
 				return this.activeLayout; 
			}
 
 			set 
 			{
				Debug.Assert(value != null); 
 				if (value == null)
					throw new ArgumentNullException("Layout cannot be null!");

				Cursor cursor = Cursor.Current; 
				try
 				{ 
					Cursor.Current = Cursors.WaitCursor; 
 					
 					this.activeLayout = value; 
					if (this.activeLayout != ((WorkflowPrintDocument)PrintDocument).PrintPreviewLayout)
 						DefaultLayout = this.activeLayout;

					base.PerformLayout(); 
					if (this.commandSet != null)
						this.commandSet.UpdatePageLayoutCommands(true); 
 				} 
				finally
 				{ 
 					Cursor.Current = cursor;
				}
 			}
		} 

		private WorkflowLayout DefaultLayout 
		{ 
 			get
			{ 
 				if (this.defaultLayout == null)
 					this.defaultLayout = new WorkflowRootLayout(this);
				return this.defaultLayout;
 			} 

			set 
			{ 
				if (value == null)
 					throw new ArgumentNullException(DR.GetString(DR.Error_WorkflowLayoutNull)); 

				if (this.defaultLayout == value)
 					return;
 
 				if (this.defaultLayout != null)
					this.defaultLayout.Dispose(); 
 
 				this.defaultLayout = value;
			} 
		}

		private float ScaleZoomFactor
 		{ 
			get
 			{ 
 				return (this.zoomLevel * this.activeLayout.Scaling); 
			}
 		} 
		#endregion

		#region Public Methods
		public void AddDesignerMessageFilter(WorkflowDesignerMessageFilter designerMessageFilter) 
 		{
			if (designerMessageFilter == null) 
 				throw new ArgumentNullException("designerMessageFilter"); 

 			if (Capture) 
				Capture = false;

 			this.customMessageFilters.Insert(0, designerMessageFilter);
			designerMessageFilter.SetParentView(this); 
		}
 
		public void RemoveDesignerMessageFilter(WorkflowDesignerMessageFilter designerMessageFilter) 
 		{
			if (designerMessageFilter == null) 
 				throw new ArgumentNullException("designerMessageFilter");

 			if (this.customMessageFilters.Contains(designerMessageFilter))
			{ 
 				if (Capture)
					Capture = false; 
 
                this.customMessageFilters.Remove(designerMessageFilter);
				((IDisposable)designerMessageFilter).Dispose(); 
			}
 		}

		public void ShowInPlaceToolTip(string toolTipText, Rectangle toolTipRectangle) 
 		{
 			if (toolTipText == null) 
				throw new ArgumentNullException("toolTipText"); 

 			if (toolTipRectangle.IsEmpty) 
				throw new ArgumentException(SR.GetString(SR.Error_EmptyToolTipRectangle));

			this.workflowToolTip.SetText(toolTipText, toolTipRectangle);
		} 

 		public void ShowInfoTip(string text) 
		{ 
 			if (text == null)
 				throw new ArgumentNullException("text"); 

			this.workflowToolTip.SetText(String.Empty, text);
 		}
 
		public void ShowInfoTip(string title, string text)
		{ 
			if (title == null) 
 				throw new ArgumentNullException("title");
 
			if (text == null)
 				throw new ArgumentNullException("text");

 			this.workflowToolTip.SetText(title, text); 
		}
 
 		public void EnsureVisible(object selectableObject) 
		{
			if (selectableObject == null) 
				throw new ArgumentNullException("selectableObject");

 			// make sure that all the parents are expanded
			Activity activity = selectableObject as Activity; 
 			while (activity != null)
 			{ 
				ActivityDesigner activityDesigner = ActivityDesigner.GetDesigner(activity); 
 				CompositeActivityDesigner parentDesigner = activityDesigner.ParentDesigner;
				if (parentDesigner != null) 
				{
					if (activityDesigner != null)
 						parentDesigner.EnsureVisibleContainedDesigner(activityDesigner);
					activity = parentDesigner.Activity; 
 				}
 				else 
				{ 
 					activity = null;
				} 
			}

			//this is to handle the case when we call ensure visible of a scope which currently has
 			//activity from the secondary flow selected. instead we should always switch to the main flow 
			activity = selectableObject as Activity;
 			if (activity != null) 
 			{ 
				CompositeActivityDesigner compositeDesigner = ActivityDesigner.GetDesigner(activity) as CompositeActivityDesigner;
 				if (compositeDesigner != null) 
					compositeDesigner.EnsureVisibleContainedDesigner(compositeDesigner);
			}

			PerformLayout(false); 

            if (this.ensureVisibleEventHandler == null) 
            { 
                this.ensureVisibleEventHandler = new EventHandler(OnEnsureVisible);
                Idle += this.ensureVisibleEventHandler; 
            }
 		}

		public void PerformLayout(bool immediateUpdate) 
 		{
 			if (immediateUpdate) 
			{ 
 				if (this.layoutEventHandler != null)
				{ 
					Idle -= this.layoutEventHandler;
					this.layoutEventHandler = null;
 				}
				base.PerformLayout();//invalidate rectangle really cares for the this.layoutEventHandler being null 
 			}
 			else if (this.layoutEventHandler == null) 
			{ 
 				this.layoutEventHandler = new EventHandler(OnPerformLayout);
				Idle += this.layoutEventHandler; 
			}
		}

        public void SaveViewState(Stream viewState) 
        {
            if (viewState == null) 
                throw new ArgumentNullException("viewState"); 

            IDesignerHost designerHost = (IDesignerHost)GetService(typeof(IDesignerHost)); 
            if (designerHost == null)
                throw new Exception(SR.GetString(SR.General_MissingService, typeof(IDesignerHost).FullName));

            BinaryWriter writer = new BinaryWriter(viewState); 

            // write workflow properties 
            writer.Write(this.PrintPreviewMode); 
            writer.Write(this.Zoom);
 
            // write components
            DesignerHelpers.SerializeDesignerStates(designerHost, writer);

            // write scroll position 
            writer.Write(this.ScrollPosition.X);
            writer.Write(this.ScrollPosition.Y); 
        } 

        public void LoadViewState(Stream viewState) 
        {
            if (viewState == null)
                throw new ArgumentNullException("viewState");
 
            bool outdated = false;
            Point scrollPosition = new Point(0, 0); 
 
            IDesignerHost designerHost = (IDesignerHost)GetService(typeof(IDesignerHost));
            if (designerHost == null) 
                throw new Exception(SR.GetString(SR.General_MissingService, typeof(IDesignerHost).FullName));

            viewState.Position = 0;
 
            BinaryReader reader = new BinaryReader(viewState);
 
            // read workflow properties 
            this.PrintPreviewMode = reader.ReadBoolean();
            this.Zoom = reader.ReadInt32(); 
            try
            {
                // get activities
                outdated = DesignerHelpers.DeserializeDesignerStates(designerHost, reader); 

                // we will apply the scrolling only if if there is perfect match 
                // between the components in the workflow and the persisted data. 
                // It might be different if files were updated outside of VS, or if
                // VS crashes. 
                if (!outdated)
                {
                    scrollPosition.X = reader.ReadInt32();
                    scrollPosition.Y = reader.ReadInt32(); 
                }
            } 
            finally 
            {
                // flush the layout to apply the new settings, this will set the scrollers extents 
                base.PerformLayout();
                this.ScrollPosition = scrollPosition;
            }
        } 

        ///  
        /// Changes zoom level on the design surface such that the entire workflow is displayed in the view 
        /// 
        public void FitToScreenSize() 
        {
            if (HScrollBar.Maximum > ViewPortSize.Width || VScrollBar.Maximum > ViewPortSize.Height)
            {
                int newZoom = (int)(100.0f / ActiveLayout.Scaling * Math.Min((float)ViewPortSize.Width / (float)ActiveLayout.Extent.Width, (float)ViewPortSize.Height / (float)ActiveLayout.Extent.Height)); 
                Zoom = Math.Min(Math.Max(newZoom, AmbientTheme.MinZoom), AmbientTheme.MaxZoom);
            } 
        } 

        ///  
        /// Sets the zoom level to 100% so that the workflow size is restored to actial workflow size
        /// 
        public void FitToWorkflowSize()
        { 
            if (Zoom != 100)
                Zoom = 100; 
        } 

        ///  
        /// Saves workflow as image to a file based on the format specified
        /// 
        /// Path to file where to save the image
        /// Format in which to save the image 
        public void SaveWorkflowImage(string imageFile, ImageFormat imageFormat)
        { 
            if (imageFile == null) 
                throw new ArgumentNullException("imageFile");
 
            if (imageFormat == null)
                throw new ArgumentNullException("imageFormat");

            Bitmap workflowBitmap = TakeWorkflowSnapShot(); 
            if (workflowBitmap != null)
            { 
                workflowBitmap.Save(imageFile, imageFormat); 
                workflowBitmap.Dispose();
            } 
        }

        /// 
        /// Saves workflow as image to a stream based on encoding specified 
        /// 
        /// Stream where to save the workflow 
        /// Format in which to save the image 
        public void SaveWorkflowImage(Stream stream, ImageFormat imageFormat)
        { 
            if (stream == null)
                throw new ArgumentNullException("stream");

            if (imageFormat == null) 
                throw new ArgumentNullException("imageFormat");
 
            Bitmap workflowBitmap = TakeWorkflowSnapShot(); 
            if (workflowBitmap != null)
            { 
                workflowBitmap.Save(stream, imageFormat);
                workflowBitmap.Dispose();
            }
        } 

        ///  
        /// Stores the workflow image to clipboard. 
        /// 
        public void SaveWorkflowImageToClipboard() 
        {
            Bitmap workflowBitmap = TakeWorkflowSnapShot();
            if (workflowBitmap != null)
            { 
                Clipboard.SetDataObject(workflowBitmap, true);
                workflowBitmap.Dispose(); 
            } 
        }
        #endregion 

 		#region Protected Methods

		#region Overridden Methods handling UI events 
 		#region Drawing
 		protected override void OnPaint(PaintEventArgs e) 
		{ 
 			base.OnPaint(e);
 
			//We set the highest quality interpolation so that we do not loose the image quality
			GraphicsContainer graphicsState = e.Graphics.BeginContainer();
			e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
 			e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; 
			e.Graphics.CompositingQuality = CompositingQuality.HighQuality;
 
            bool takeWorkflowSnapShot = (this.viewPortBitmap == null || this.viewPortBitmap.Size != ViewPortSize); 
            if (takeWorkflowSnapShot)
            { 
                if (this.viewPortBitmap != null)
                    this.viewPortBitmap.Dispose();
                this.viewPortBitmap = new Bitmap(Math.Max(1, ViewPortSize.Width), Math.Max(1, ViewPortSize.Height), e.Graphics);
            } 

 			//Create viewport information and take the workflow snapshot before passing on the information to the active layout 
 			ViewPortData viewPortData = new ViewPortData(); 
			viewPortData.LogicalViewPort = ClientRectangleToLogical(new Rectangle(Point.Empty, ViewPortSize));
 			viewPortData.MemoryBitmap = this.viewPortBitmap; 
			viewPortData.Scaling = new SizeF(ScaleZoomFactor, ScaleZoomFactor);
			viewPortData.Translation = ScrollPosition;
			viewPortData.ShadowDepth = new Size(this.shadowDepth, this.shadowDepth);
 			viewPortData.ViewPortSize = ViewPortSize; 

			//capture the workflow onto in-memory bitmap 
            if (this.layoutEventHandler == null || takeWorkflowSnapShot) 
                WorkflowView.TakeWorkflowSnapShot(this, viewPortData);
 
 			//copy workflow from the bitmap onto corresponding pages on the screen
 			try
			{
 				this.activeLayout.OnPaintWorkflow(e, viewPortData); 
			}
			catch (Exception ex) 
			{ 
 				//If a layout throws an exception then we will not draw the layout
				// 
 				Debug.WriteLine(ex);
 			}

			//If any of the message filters throws an exception we continue to draw 
 			using (WorkflowMessageDispatchData dispatchData = new WorkflowMessageDispatchData(this, EventArgs.Empty))
			{ 
				foreach (WorkflowDesignerMessageFilter filter in dispatchData.Filters) 
				{
 					try 
					{
 						if (((IWorkflowDesignerMessageSink)filter).OnPaintWorkflowAdornments(e, ViewPortRectangle))
 							break;
					} 
 					catch (Exception ex)
					{ 
						//Ignore the filter throwing the exception and continue to function 
						Debug.WriteLine(ex);
 					} 
				}
 			}

 			e.Graphics.EndContainer(graphicsState); 

            e.Graphics.FillRectangle(SystemBrushes.Control, new Rectangle(Width - SystemInformation.VerticalScrollBarWidth, Height - SystemInformation.HorizontalScrollBarHeight, SystemInformation.VerticalScrollBarWidth, SystemInformation.HorizontalScrollBarHeight)); 
        } 

        protected virtual void OnZoomChanged() 
        {
            if (this.ZoomChanged != null)
                this.ZoomChanged(this, EventArgs.Empty);
        } 

        protected virtual void OnRootDesignerChanged() 
        { 
            if (this.RootDesignerChanged != null)
                this.RootDesignerChanged(this, EventArgs.Empty); 
        }
		#endregion

 		#region Mouse Events 
		protected override void OnMouseDown(MouseEventArgs e)
		{ 
			base.OnMouseDown(e); 

 			using (WorkflowMessageDispatchData dispatchData = new WorkflowMessageDispatchData(this, e)) 
			{
 				foreach (WorkflowDesignerMessageFilter filter in dispatchData.Filters)
 				{
					if (((IWorkflowDesignerMessageSink)filter).OnMouseDown(e)) 
 						break;
				} 
			} 
		}
 
 		protected override void OnMouseMove(MouseEventArgs e)
		{
 			base.OnMouseMove(e);
 
 			using (WorkflowMessageDispatchData dispatchData = new WorkflowMessageDispatchData(this, e))
			{ 
 				foreach (WorkflowDesignerMessageFilter filter in dispatchData.Filters) 
				{
					if (((IWorkflowDesignerMessageSink)filter).OnMouseMove(e)) 
						break;
 				}
			}
 		} 

 		protected override void OnMouseUp(MouseEventArgs e) 
		{ 
 			base.OnMouseUp(e);
 
			using (WorkflowMessageDispatchData dispatchData = new WorkflowMessageDispatchData(this, e))
			{
				foreach (WorkflowDesignerMessageFilter filter in dispatchData.Filters)
 				{ 
					if (((IWorkflowDesignerMessageSink)filter).OnMouseUp(e))
 						break; 
 				} 
			}
 		} 

		protected override void OnMouseDoubleClick(MouseEventArgs e)
		{
			base.OnMouseDoubleClick(e); 

 			using (WorkflowMessageDispatchData dispatchData = new WorkflowMessageDispatchData(this, e)) 
			{ 
 				foreach (WorkflowDesignerMessageFilter filter in dispatchData.Filters)
 				{ 
					if (((IWorkflowDesignerMessageSink)filter).OnMouseDoubleClick(e))
 						break;
				}
			} 
		}
 
 		protected override void OnMouseEnter(EventArgs e) 
		{
 			base.OnMouseEnter(e); 

 			Point clientPoint = PointToClient(Control.MousePosition);
			MouseEventArgs eventArgs = new MouseEventArgs(Control.MouseButtons, 1, clientPoint.X, clientPoint.Y, 0);
 
 			using (WorkflowMessageDispatchData dispatchData = new WorkflowMessageDispatchData(this, eventArgs))
			{ 
				foreach (WorkflowDesignerMessageFilter filter in dispatchData.Filters) 
				{
 					if (((IWorkflowDesignerMessageSink)filter).OnMouseEnter(eventArgs)) 
						break;
 				}
 			}
		} 

 		protected override void OnMouseHover(EventArgs e) 
		{ 
			base.OnMouseHover(e);
 
			Point clientPoint = PointToClient(Control.MousePosition);
 			MouseEventArgs eventArgs = new MouseEventArgs(Control.MouseButtons, 1, clientPoint.X, clientPoint.Y, 0);

			using (WorkflowMessageDispatchData dispatchData = new WorkflowMessageDispatchData(this, eventArgs)) 
 			{
 				foreach (WorkflowDesignerMessageFilter filter in dispatchData.Filters) 
				{ 
 					if (((IWorkflowDesignerMessageSink)filter).OnMouseHover(eventArgs))
						break; 
				}
			}
 		}
 
		protected override void OnMouseLeave(EventArgs e)
 		{ 
 			base.OnMouseLeave(e); 

			using (WorkflowMessageDispatchData dispatchData = new WorkflowMessageDispatchData(this, EventArgs.Empty)) 
 			{
				foreach (WorkflowDesignerMessageFilter filter in dispatchData.Filters)
				{
					if (((IWorkflowDesignerMessageSink)filter).OnMouseLeave()) 
 						break;
				} 
 			} 
 		}
 
		protected override void OnMouseCaptureChanged(EventArgs e)
 		{
			base.OnMouseCaptureChanged(e);
 
			using (WorkflowMessageDispatchData dispatchData = new WorkflowMessageDispatchData(this, EventArgs.Empty))
			{ 
 				foreach (WorkflowDesignerMessageFilter filter in dispatchData.Filters) 
				{
 					if (((IWorkflowDesignerMessageSink)filter).OnMouseCaptureChanged()) 
 						break;
				}
 			}
		} 

		protected override void OnMouseWheel(MouseEventArgs e) 
		{ 
 			base.OnMouseWheel(e);
 
			using (WorkflowMessageDispatchData dispatchData = new WorkflowMessageDispatchData(this, e))
 			{
 				foreach (WorkflowDesignerMessageFilter filter in dispatchData.Filters)
				{ 
 					if (((IWorkflowDesignerMessageSink)filter).OnMouseWheel(e))
						break; 
				} 
			}
 		} 
		#endregion

 		#region Keyboard Events
 		protected override void OnKeyDown(KeyEventArgs e) 
		{
 			using (WorkflowMessageDispatchData dispatchData = new WorkflowMessageDispatchData(this, e)) 
			{ 
				foreach (WorkflowDesignerMessageFilter filter in dispatchData.Filters)
				{ 
 					if (((IWorkflowDesignerMessageSink)filter).OnKeyDown(e))
						break;
 				}
 			} 

			if (!e.Handled) 
 				base.OnKeyDown(e); 
		}
 
		protected override void OnKeyUp(KeyEventArgs e)
		{
 			using (WorkflowMessageDispatchData dispatchData = new WorkflowMessageDispatchData(this, e))
			{ 
 				foreach (WorkflowDesignerMessageFilter filter in dispatchData.Filters)
 				{ 
					if (((IWorkflowDesignerMessageSink)filter).OnKeyUp(e)) 
 						break;
				} 
			}

			if (!e.Handled)
 				base.OnKeyUp(e); 
		}
 		#endregion 
 
 		#region Layouting Events
		protected override void OnLayout(LayoutEventArgs levent) 
 		{
			base.OnLayout(levent);

			ScrollBar hScrollBar = HScrollBar; 
			ScrollBar vScrollBar = VScrollBar;
 
            if (Controls.Contains(hScrollBar)) 
                hScrollBar.Bounds = new Rectangle(0, Math.Max(0, Height - SystemInformation.HorizontalScrollBarHeight), Math.Max(Width - ((vScrollBar.Visible) ? SystemInformation.VerticalScrollBarWidth : 0), 0), SystemInformation.HorizontalScrollBarHeight);
 
 			if (Controls.Contains(vScrollBar))
                vScrollBar.Bounds = new Rectangle(Math.Max(0, Width - SystemInformation.VerticalScrollBarWidth), 0, SystemInformation.VerticalScrollBarWidth, Math.Max(Height - ((hScrollBar.Visible) ? SystemInformation.HorizontalScrollBarHeight : 0), 0));

            if (this.toolContainer != null) 
            {
                this.toolContainer.Location = new Point(Width - this.toolContainer.Width, 0); 
                this.toolContainer.Height = Height - ((hScrollBar.Visible) ? hScrollBar.Height :0); 
            }
 
			using (WorkflowMessageDispatchData dispatchData = new WorkflowMessageDispatchData(this, levent))
 			{
 				foreach (WorkflowDesignerMessageFilter filter in dispatchData.Filters)
					((IWorkflowDesignerMessageSink)filter).OnLayout(levent); 
 			}
 
			//Layout the designers 
			using (Graphics graphics = CreateGraphics())
			{ 
 				this.activeLayout.Update(graphics, WorkflowLayout.LayoutUpdateReason.LayoutChanged);

				if (this.rootDesigner != null)
 					this.rootDesigner.Location = this.activeLayout.RootDesignerAlignment; 
 			}
 
			//Update the scroll range and redraw 
 			UpdateScrollRange();
			InvalidateClientRectangle(Rectangle.Empty); 
		}
		#endregion

 		#region DragDrop Events 
		protected override void OnDragEnter(DragEventArgs dragEventArgs)
 		{ 
 			base.OnDragEnter(dragEventArgs); 

            this.dragDropInProgress = true; 

			using (WorkflowMessageDispatchData dispatchData = new WorkflowMessageDispatchData(this, dragEventArgs))
 			{
				foreach (WorkflowDesignerMessageFilter filter in dispatchData.Filters) 
				{
					if (((IWorkflowDesignerMessageSink)filter).OnDragEnter(dragEventArgs)) 
 						break; 
				}
 			} 
 		}

		protected override void OnDragOver(DragEventArgs dragEventArgs)
 		{ 
			base.OnDragOver(dragEventArgs);
 
			using (WorkflowMessageDispatchData dispatchData = new WorkflowMessageDispatchData(this, dragEventArgs)) 
			{
 				foreach (WorkflowDesignerMessageFilter filter in dispatchData.Filters) 
				{
 					if (((IWorkflowDesignerMessageSink)filter).OnDragOver(dragEventArgs))
 						break;
				} 
 			}
		} 
 
		protected override void OnDragLeave(EventArgs e)
		{ 
 			base.OnDragLeave(e);

			using (WorkflowMessageDispatchData dispatchData = new WorkflowMessageDispatchData(this, EventArgs.Empty))
 			{ 
 				foreach (WorkflowDesignerMessageFilter filter in dispatchData.Filters)
				{ 
 					if (((IWorkflowDesignerMessageSink)filter).OnDragLeave()) 
						break;
				} 
			}

            this.dragDropInProgress = false;
        } 

 		protected override void OnDragDrop(DragEventArgs dragEventArgs) 
		{ 
 			base.OnDragDrop(dragEventArgs);
 
 			using (WorkflowMessageDispatchData dispatchData = new WorkflowMessageDispatchData(this, dragEventArgs))
			{
 				foreach (WorkflowDesignerMessageFilter filter in dispatchData.Filters)
				{ 
					if (((IWorkflowDesignerMessageSink)filter).OnDragDrop(dragEventArgs))
						break; 
 				} 
			}
 
            this.dragDropInProgress = false;
        }

 		protected override void OnGiveFeedback(GiveFeedbackEventArgs gfbevent) 
 		{
			base.OnGiveFeedback(gfbevent); 
 
 			using (WorkflowMessageDispatchData dispatchData = new WorkflowMessageDispatchData(this, gfbevent))
			{ 
				foreach (WorkflowDesignerMessageFilter filter in dispatchData.Filters)
				{
 					if (((IWorkflowDesignerMessageSink)filter).OnGiveFeedback(gfbevent))
						break; 
 				}
 			} 
		} 

 		protected override void OnQueryContinueDrag(QueryContinueDragEventArgs qcdevent) 
		{
			base.OnQueryContinueDrag(qcdevent);

			using (WorkflowMessageDispatchData dispatchData = new WorkflowMessageDispatchData(this, qcdevent)) 
 			{
				foreach (WorkflowDesignerMessageFilter filter in dispatchData.Filters) 
 				{ 
 					if (((IWorkflowDesignerMessageSink)filter).OnQueryContinueDrag(qcdevent))
						break; 
 				}
			}
		}
		#endregion 

 		#region General Events 
		//Handle context menus here reason being it can come from mouse r button click 
 		//or shift+F10, or there might be other keys too
 		//We need to handle the WndProc and not the OnNotifyMessage because we need to set 
		//the m.Result to handled (IntPtr.Zero) and dont let the base class see the message at all
 		//see WinOE #787 "The keyboard "key" to launch the context menu launches the menu at 0,0"
		[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
		[UIPermission(SecurityAction.Assert, Window = UIPermissionWindow.AllWindows)] 
		protected override void WndProc(ref Message m)
 		{ 
			using (WorkflowMessageDispatchData dispatchData = new WorkflowMessageDispatchData(this, EventArgs.Empty)) 
 			{
 				foreach (WorkflowDesignerMessageFilter filter in dispatchData.Filters) 
				{
 					if (((IWorkflowDesignerMessageSink)filter).ProcessMessage(m))
						break;
				} 

				const int WM_CONTEXTMENU = 0x007B; 
 				if (m.Msg == WM_CONTEXTMENU) 
				{
 					int LParam = (int)m.LParam; 
 					Point location = (LParam != -1) ? new Point(LParam) : Control.MousePosition;

					foreach (WorkflowDesignerMessageFilter filter in dispatchData.Filters)
 					{ 
						if (((IWorkflowDesignerMessageSink)filter).OnShowContextMenu(location))
							break; 
					} 

 					//mark the message handled 
					m.Result = IntPtr.Zero;
 					//dont pass the message to the base but return immediatly
 					return;
				} 
 			}
 
			if (this.workflowToolTip != null && m.Msg == NativeMethods.WM_NOTIFY) 
				this.workflowToolTip.RelayParentNotify(ref m);
 
			try
 			{
				if (m.Result == IntPtr.Zero)
 					base.WndProc(ref m); 
 			}
			catch (Exception e) 
 			{ 
                if (e != CheckoutException.Canceled)
                    DesignerHelpers.ShowError(this, e); 
			}
		}

		protected override void OnControlAdded(ControlEventArgs e) 
 		{
			if (e.Control != VScrollBar && e.Control != HScrollBar && e.Control != this.toolContainer) 
 				throw new InvalidOperationException(SR.GetString(SR.Error_InsertingChildControls)); 
 		}
 
		protected override AccessibleObject CreateAccessibilityInstance()
 		{
			return new WorkflowViewAccessibleObject(this);
		} 
		#endregion
 
 		#endregion 

		#endregion 

 		#region Private Methods
        private void OnWorkflowIdle(object sender, EventArgs e)
        { 
            if (this.idleEventListeners != null)
                this.idleEventListeners(this, e); 
        } 

 		private void UpdateLayout() 
		{
 			if (this.layoutEventHandler != null)
			{
				PerformLayout(true); 
				InvalidateClientRectangle(Rectangle.Empty);
 			} 
		} 

 		internal void OnCommandKey(KeyEventArgs e) 
 		{
			this.OnKeyDown(e);
            this.OnKeyUp(e);
 		} 

		private void OnSelectionChanged(object sender, EventArgs e) 
		{ 
			if (this.commandSet != null)
 				this.commandSet.UpdateCommandSet(); 

			//Make sure that the ensure visible also works when the component is selected
 			//from property browser dropdown
 			//Make sure that when there is a selection change using the property browser 
			//drop down we make sure that the designer associated with component selected by the user in the dropdown
 			//is made visible. 
			//To enable this functionality please note that selection change is not a good event as it will get 
			//fired in multiple cases, instead we should add a event in extended ui service which will do this and move
			//the following code in the event handler of that event 
 			//Ref Bug#3925

            if (RootDesigner != null && RootDesigner.Activity != null)
            { 
                ISelectionService selectionService = GetService(typeof(ISelectionService)) as ISelectionService;
                if (selectionService != null && selectionService.GetComponentSelected(RootDesigner.Activity)) 
                { 
                    IHelpService helpService = GetService(typeof(IHelpService)) as IHelpService;
                    if (helpService != null) 
                        helpService.AddContextAttribute("Keyword", RootDesigner.Activity.GetType().FullName, HelpKeywordType.F1Keyword);
                }
            }
		} 

 		private void OnPerformLayout(object sender, EventArgs e) 
 		{ 
			if (this.layoutEventHandler != null)
 			{ 
				Idle -= this.layoutEventHandler;
				this.layoutEventHandler = null;

				base.PerformLayout(); 
 			}
		} 
 
        //Gets the snapshot of the entire workflow
        private Bitmap TakeWorkflowSnapShot() 
        {
            Bitmap bitmap = null;
            ActivityDesigner rootDesigner = RootDesigner;
            if (rootDesigner != null) 
            {
                using (Graphics graphics = CreateGraphics()) 
                { 
                    ViewPortData viewPortData = new ViewPortData();
                    viewPortData.LogicalViewPort = new Rectangle(Point.Empty, new Size(rootDesigner.Bounds.Width + 2 * DefaultWorkflowLayout.Separator.Width, rootDesigner.Bounds.Height + 2 * DefaultWorkflowLayout.Separator.Height)); 
                    viewPortData.MemoryBitmap = new Bitmap(viewPortData.LogicalViewPort.Width, viewPortData.LogicalViewPort.Height, graphics);
                    viewPortData.Scaling = new SizeF(1, 1);
                    viewPortData.Translation = Point.Empty;
                    viewPortData.ShadowDepth = new Size(0, 0); 
                    viewPortData.ViewPortSize = viewPortData.LogicalViewPort.Size;
                    TakeWorkflowSnapShot(this, viewPortData); 
                    bitmap = viewPortData.MemoryBitmap; 
                }
            } 

            return bitmap;
        }
 
 		//This function will give snapshot of what is drawn on the screen at any point of time
 		//It will scale and translate the designers and drawing based on the viewport data 
		//We need this function in OnPaint and taking snapshot of magnifier bitmap 
 		//At the end of this function; the ViewPortData.MemoryBitmap will contain the bitmap of the
		//workflow to be drawn as per layout 
		internal static void TakeWorkflowSnapShot(WorkflowView workflowView, ViewPortData viewPortData)
		{
 			//Get the drawing canvas
			Bitmap memoryBitmap = viewPortData.MemoryBitmap; 
 			Debug.Assert(memoryBitmap != null);
 
 			using (Graphics viewPortGraphics = Graphics.FromImage(memoryBitmap)) 
			{
 				//We set the highest quality interpolation so that we do not loose the image quality 
				viewPortGraphics.SmoothingMode = SmoothingMode.HighQuality;
				viewPortGraphics.InterpolationMode = InterpolationMode.HighQualityBicubic;

                using (PaintEventArgs eventArgs = new PaintEventArgs(viewPortGraphics, viewPortData.LogicalViewPort)) 
                {
                    workflowView.ActiveLayout.OnPaint(eventArgs, viewPortData); 
                } 

				//Create the scaling matrix 
 				Matrix transformationMatrix = new Matrix();
				transformationMatrix.Scale(viewPortData.Scaling.Width, viewPortData.Scaling.Height, MatrixOrder.Prepend);

 				//When we draw on the viewport we draw in scaled and translated. 
 				//So that we minimize the calls to DrawImage
				//Make sure that we scale down the logical view port origin in order to take care of scaling factor 
 				//Before we select the transform factor we make sure that logicalviewport origin is scaled down 
				Point[] logicalViewPortOrigin = new Point[] { viewPortData.LogicalViewPort.Location };
				transformationMatrix.TransformPoints(logicalViewPortOrigin); 

				//For performance improvement and to eliminate one extra DrawImage...we draw the designers on the viewport
 				//bitmap with visual depth consideration
				transformationMatrix.Translate(-logicalViewPortOrigin[0].X + viewPortData.ShadowDepth.Width, -logicalViewPortOrigin[0].Y + viewPortData.ShadowDepth.Height, MatrixOrder.Append); 

 				//Select the transform into viewport graphics. 
 				//Viewport bitmap has the scaled and translated designers which we then map to 
				//the actual graphics based on page layout
 				viewPortGraphics.Transform = transformationMatrix; 

				//Draw the designers on bitmap
				if (workflowView.RootDesigner != null)
				{ 
 					using (Region clipRegion = new Region())
					using (GraphicsPath designerPath = ActivityDesignerPaint.GetDesignerPath(workflowView.RootDesigner, false)) 
 					{ 
 						Region oldRegion = viewPortGraphics.Clip;
 
						//First draw the grid and rectangle with the designer clip region
 						clipRegion.MakeEmpty();
						clipRegion.Union(designerPath);
						viewPortGraphics.Clip = clipRegion; 
						AmbientTheme ambientTheme = WorkflowTheme.CurrentTheme.AmbientTheme;
 						viewPortGraphics.FillRectangle(ambientTheme.BackgroundBrush, workflowView.RootDesigner.Bounds); 
						if (ambientTheme.ShowGrid) 
 							ActivityDesignerPaint.DrawGrid(viewPortGraphics, workflowView.RootDesigner.Bounds);
 						viewPortGraphics.Clip = oldRegion; 

						//Then draw the root with clip region extended
 						try
						{ 
                            using (PaintEventArgs paintEventArgs = new PaintEventArgs(viewPortGraphics, viewPortData.LogicalViewPort))
                            { 
                                ((IWorkflowDesignerMessageSink)workflowView.RootDesigner).OnPaint(paintEventArgs, viewPortData.LogicalViewPort); 
                            }
						} 
						catch (Exception e)
 						{
							//Eat the exception thrown in draw
 							Debug.WriteLine(e); 
 						}
					} 
 				} 

				//Draw all the filters 


                using (PaintEventArgs paintArgs = new PaintEventArgs(viewPortGraphics, workflowView.RootDesigner.Bounds))
                { 
				    using (WorkflowMessageDispatchData dispatchData = new WorkflowMessageDispatchData(workflowView, EventArgs.Empty))
				    { 
                        foreach (WorkflowDesignerMessageFilter filter in dispatchData.Filters) 
                        {
                            try 
                            {
                                if (((IWorkflowDesignerMessageSink)filter).OnPaint(paintArgs, viewPortData.LogicalViewPort))
                                    break;
                            } 
                            catch (Exception e)
                            { 
                                Debug.WriteLine(e); 
                            }
                        } 
                    }
 				}

				viewPortGraphics.Transform = new Matrix(); 

 				//Now that we have a bitmap which is bit offseted based visual depth we need to take copy of it 
 				//This is done so as to avoid expensive DrawImage call, what I am assuming here is that time it 
				//will take to create a new bitmap from an existing one is less expensive in terms of speed than space
 				//As you just need to copy bitmap bits in memory than to perform expesive Image Drawing operation 
				if (!viewPortData.ShadowDepth.IsEmpty)
				{
					Bitmap temporaryBitmap = new Bitmap(memoryBitmap);
 
 					//THEMETODO: WE JUST NEED TO GRAYSCALE THIS, RATHER THAN DRAWING A SHADOW
					//Now that we have taken a copy we will draw over the existing bitmap so that we can make it as shadow bitmap 
 					using (Brush shadowDepthBrush = new SolidBrush(Color.FromArgb(220, Color.White))) 
                        viewPortGraphics.FillRectangle(shadowDepthBrush, new Rectangle(Point.Empty, new Size(memoryBitmap.Size.Width - viewPortData.ShadowDepth.Width - 1, memoryBitmap.Size.Height - viewPortData.ShadowDepth.Height - 1)));
 
 					//Now make sure that we draw the image from the temporary bitmap with white color set as transparent
					//so that we achive the 3D effect
 					//Make sure that we take into consideration the transparency key
					ImageAttributes transparentColorKey = new ImageAttributes(); 
					transparentColorKey.SetColorKey(viewPortData.TransparentColor, viewPortData.TransparentColor, ColorAdjustType.Default);
					transparentColorKey.SetColorKey(viewPortData.TransparentColor, viewPortData.TransparentColor, ColorAdjustType.Bitmap); 
 					viewPortGraphics.DrawImage(temporaryBitmap, new Rectangle(-viewPortData.ShadowDepth.Width, -viewPortData.ShadowDepth.Height, memoryBitmap.Width, memoryBitmap.Height), 0, 0, memoryBitmap.Width, memoryBitmap.Height, GraphicsUnit.Pixel, transparentColorKey); 

					//Now dispose the temporary bitmap 
 					temporaryBitmap.Dispose();
 				}
			}
 		} 

		internal void OnThemeChange(object sender, EventArgs e) 
		{ 
			ShadowDepth = WorkflowTheme.CurrentTheme.AmbientTheme.ShadowDepth;
 
 			using (WorkflowMessageDispatchData dispatchData = new WorkflowMessageDispatchData(this, EventArgs.Empty))
			{
 				foreach (WorkflowDesignerMessageFilter filter in dispatchData.Filters)
 				{ 
					try
 					{ 
						((IWorkflowDesignerMessageSink)filter).OnThemeChange(); 
					}
					catch (Exception ex) 
 					{
						Debug.WriteLine(ex);
 					}
 				} 
			}
 
 			base.PerformLayout(); 
		}
 
		private void OnEnsureVisible(object sender, EventArgs e)
		{
            if (this.ensureVisibleEventHandler != null)
            { 
                Idle -= this.ensureVisibleEventHandler;
                this.ensureVisibleEventHandler = null; 
            } 

            ISelectionService selectionService = (ISelectionService)GetService(typeof(ISelectionService)); 
            if (selectionService != null && selectionService.SelectionCount > 0)
            {
                //We do not want to regenerate a layout event in ensure visible
                ArrayList selectedComponents = new ArrayList(selectionService.GetSelectedComponents()); 
                for (int i = selectedComponents.Count - 1; i >= 0; i--)
                { 
                    Rectangle rectangleToMakeVisible = Rectangle.Empty; 
                    if (selectedComponents[i] is Activity)
                    { 
                        ActivityDesigner activityDesigner = ActivityDesigner.GetDesigner(selectedComponents[i] as Activity);
                        if (activityDesigner != null)
                        {
                            rectangleToMakeVisible = activityDesigner.Bounds; 
                            rectangleToMakeVisible.Inflate(WorkflowTheme.CurrentTheme.AmbientTheme.SelectionSize);
                            rectangleToMakeVisible.Inflate(WorkflowTheme.CurrentTheme.AmbientTheme.SelectionSize); 
                        } 
                    }
                    else if (selectedComponents[i] is HitTestInfo) 
                    {
                        rectangleToMakeVisible = ((HitTestInfo)selectedComponents[i]).Bounds;
                    }
 
                    if (!rectangleToMakeVisible.IsEmpty)
                        EnsureVisible(rectangleToMakeVisible); 
                } 
            }
        } 

        private void EnsureVisible(Rectangle rect)
        {
            Rectangle clientRectangle = ClientRectangleToLogical(new Rectangle(Point.Empty, ViewPortSize)); 

            if (!clientRectangle.Contains(rect.Location) || !clientRectangle.Contains(new Point(rect.Right, rect.Bottom))) 
            { 
                Size scrollDelta = new Size();
                if (!clientRectangle.Contains(new Point(rect.Left, clientRectangle.Top)) || !clientRectangle.Contains(new Point(rect.Right, clientRectangle.Top))) 
                {
                    if (rect.Width > clientRectangle.Width)
                        scrollDelta.Width = (rect.Left + rect.Width / 2) - (clientRectangle.Left + clientRectangle.Width / 2);
                    else if (rect.Left < clientRectangle.Left) 
                        scrollDelta.Width = (rect.Left - clientRectangle.Left);
                    else 
                        scrollDelta.Width = (rect.Right - clientRectangle.Right); 
                }
 
                if (!clientRectangle.Contains(new Point(clientRectangle.Left, rect.Top)) || !clientRectangle.Contains(new Point(clientRectangle.Left, rect.Bottom)))
                {
                    if ((rect.Top < clientRectangle.Top) || (rect.Height > clientRectangle.Height))
                        scrollDelta.Height = (rect.Top - clientRectangle.Top); 
                    else
                        scrollDelta.Height = rect.Bottom - clientRectangle.Bottom; 
                } 

                scrollDelta = LogicalSizeToClient(scrollDelta); 
                Point scrollPosition = ScrollPosition;
                ScrollPosition = new Point(scrollPosition.X + scrollDelta.Width, scrollPosition.Y + scrollDelta.Height);
            }
        } 

 		private void OnScroll(object sender, EventArgs e) 
		{ 
 			//Lets speedup the scrolling logic
 			InvalidateClientRectangle(Rectangle.Empty); 

            ScrollBar scrollBar = sender as ScrollBar;
            if (scrollBar != null)
            { 
                using (WorkflowMessageDispatchData dispatchData = new WorkflowMessageDispatchData(this, e))
                { 
                    foreach (WorkflowDesignerMessageFilter filter in dispatchData.Filters) 
                    {
                        try 
                        {
                            ((IWorkflowDesignerMessageSink)filter).OnScroll(scrollBar, scrollBar.Value);
                        }
                        catch (Exception ex) 
                        {
                            Debug.WriteLine(ex); 
                        } 
                    }
                } 
            }
        }

		private void UpdateScrollRange() 
 		{
			if (ViewPortSize.Width < 0 || ViewPortSize.Height < 0) 
				return; 

			Size currentSize = ViewPortSize; 
 			Size maximumScrollSize = LogicalSizeToClient(this.activeLayout.Extent);
			Size largeChangeSize = new Size(Math.Min(maximumScrollSize.Width, currentSize.Width), Math.Min(maximumScrollSize.Height, currentSize.Height));

 			if (hScrollBar.Maximum != maximumScrollSize.Width) 
 				hScrollBar.Maximum = maximumScrollSize.Width;
			if (vScrollBar.Maximum != maximumScrollSize.Height) 
 				vScrollBar.Maximum = maximumScrollSize.Height; 

			if (hScrollBar.LargeChange != largeChangeSize.Width) 
			{
				hScrollBar.SmallChange = largeChangeSize.Width / 15;
 				hScrollBar.LargeChange = largeChangeSize.Width + 1;
			} 
 			if (vScrollBar.LargeChange != largeChangeSize.Height)
 			{ 
				vScrollBar.SmallChange = largeChangeSize.Height / 15; 
 				vScrollBar.LargeChange = largeChangeSize.Height + 1;
			} 

			int xMaxScrollPos = maximumScrollSize.Width - hScrollBar.LargeChange;
			xMaxScrollPos = (xMaxScrollPos < 0) ? 0 : xMaxScrollPos;
 			if (hScrollBar.Value > xMaxScrollPos) 
				hScrollBar.Value = xMaxScrollPos;
 
 			int yMaxScrollPos = maximumScrollSize.Height - vScrollBar.LargeChange; 
 			yMaxScrollPos = (yMaxScrollPos < 0) ? 0 : yMaxScrollPos;
			if (vScrollBar.Value > yMaxScrollPos) 
 				vScrollBar.Value = yMaxScrollPos;

			RefreshDynamicAction();
 
            bool hScrollBarVisible = hScrollBar.Visible;
            if (Controls.Contains(hScrollBar)) 
                hScrollBar.Visible = (hScrollBar.Maximum > currentSize.Width); 

            bool vScrollBarVisible = vScrollBar.Visible; 
            if (Controls.Contains(vScrollBar))
                vScrollBar.Visible = (vScrollBar.Maximum > currentSize.Height);

            if (hScrollBarVisible != hScrollBar.Visible || vScrollBar.Visible != vScrollBarVisible) 
            {
                base.PerformLayout(); 
                Refresh(); 
            }
        } 

		private DynamicAction CreateDynamicAction()
		{
 			DynamicAction fitAllAction = new DynamicAction(); 
			fitAllAction.ButtonSize = DynamicAction.ButtonSizes.Large;
 			fitAllAction.Doc----gnment = DesignerContentAlignment.BottomRight; 
 			fitAllAction.DockMargin = new Size(5, 5); 

			ActionButton fitallButton = new ActionButton(new Image[] { DR.GetImage(DR.FitToScreen) as Bitmap }); 
 			fitallButton.StateChanged += new EventHandler(OnFitToScreen);
			fitAllAction.Buttons.Add(fitallButton);

			return fitAllAction; 
		}
 
 		private void RefreshDynamicAction() 
		{
 			DynamicActionMessageFilter dynamicActionFilter = GetService(typeof(DynamicActionMessageFilter)) as DynamicActionMessageFilter; 
 			if (dynamicActionFilter == null || this.fitAllAction == null)
				return;

 			if (HScrollBar.Maximum > ViewPortSize.Width || VScrollBar.Maximum > ViewPortSize.Height) 
			{
				//This means we need to show the zoomin icon 
                this.fitAllAction.Buttons[0].Description = DR.GetString(DR.FitToScreenDescription); 
				this.fitAllAction.Buttons[0].StateImages = new Bitmap[] { DR.GetImage(DR.FitToScreen) as Bitmap };
 				dynamicActionFilter.AddAction(this.fitAllAction); 
			}
 			else if (Zoom != 100)
 			{
				//We need to show zoomout icon 
                this.fitAllAction.Buttons[0].Description = DR.GetString(DR.FitToWorkflowDescription);
 				this.fitAllAction.Buttons[0].StateImages = new Bitmap[] { DR.GetImage(DR.FitToWorkflow) as Bitmap }; 
				dynamicActionFilter.AddAction(this.fitAllAction); 
			}
			else 
 			{
				//In neither case we remove the action
 				dynamicActionFilter.RemoveAction(this.fitAllAction);
 				this.fitAllAction.Buttons[0].State = ActionButton.States.Normal; 
			}
 		} 
 
		private void OnFitToScreen(object sender, EventArgs e)
		{ 
			ActionButton fitallButton = sender as ActionButton;
 			if (fitallButton == null || fitallButton.State != ActionButton.States.Pressed)
				return;
 
 			if (HScrollBar.Maximum > ViewPortSize.Width || VScrollBar.Maximum > ViewPortSize.Height)
                FitToScreenSize(); 
            else if (Zoom != 100) 
                FitToWorkflowSize();
 		} 

		private void OnTabChange(object sender, TabSelectionChangeEventArgs e)
 		{
			if (e.CurrentItem.Identifier == (int)TabButtonIds.MultiPage || 
					e.CurrentItem.Identifier == (int)TabButtonIds.Zoom ||
					e.CurrentItem.Identifier == (int)TabButtonIds.Pan) 
 			{ 
				Rectangle buttonRect = e.SelectedTabBounds;
 				CommandID menuID = null; 

 				if (e.CurrentItem.Identifier == (int)TabButtonIds.MultiPage)
					menuID = WorkflowMenuCommands.PageLayoutMenu;
 				else if (e.CurrentItem.Identifier == (int)TabButtonIds.Zoom) 
					menuID = WorkflowMenuCommands.ZoomMenu;
				else 
					menuID = WorkflowMenuCommands.PanMenu; 

 				IMenuCommandService menuCommandService = (IMenuCommandService)GetService(typeof(IMenuCommandService)); 
				if (menuCommandService != null)
 					menuCommandService.ShowContextMenu(menuID, buttonRect.Right, buttonRect.Top);
 			}
		} 

 		private void EnsureScrollBars(HScrollBar newHorizScrollBar, VScrollBar newVertScrollBar) 
		{ 
            try
            { 
                SuspendLayout();

                if (this.hScrollBar != newHorizScrollBar)
                { 
                    if (this.hScrollBar != null)
                    { 
                        this.hScrollBar.ValueChanged -= new EventHandler(OnScroll); 
                        if (Controls.Contains(this.hScrollBar))
                            Controls.Remove(this.hScrollBar); 
                    }

                    this.hScrollBar = newHorizScrollBar;
                    if (this.hScrollBar.Parent == null) 
                    {
                        this.hScrollBar.TabStop = false; 
                        Controls.Add(this.hScrollBar); 
                    }
                } 

                if (this.vScrollBar != newVertScrollBar)
                {
                    if (this.vScrollBar != null) 
                    {
                        this.vScrollBar.ValueChanged -= new EventHandler(OnScroll); 
                        if (Controls.Contains(this.vScrollBar)) 
                            Controls.Remove(this.vScrollBar);
                    } 

                    this.vScrollBar = newVertScrollBar;
                    if (this.vScrollBar.Parent == null)
                    { 
                        this.vScrollBar.TabStop = false;
                        Controls.Add(this.vScrollBar); 
                    } 
                }
 
                this.hScrollBar.ValueChanged += new EventHandler(OnScroll);
                this.vScrollBar.ValueChanged += new EventHandler(OnScroll);
            }
            finally 
            {
                ResumeLayout(true); 
            } 
		}
 
        private void PopulateMessageFilters(bool stockFilters)
        {
            IList filters = (stockFilters) ? this.stockMessageFilters : this.customMessageFilters;
            Debug.Assert(filters.Count == 0); 

            if (stockFilters) 
            { 
                filters.Add(new GlyphManager());
                filters.Add(new WindowManager()); 
            }
            else
            {
                Debug.Assert(this.rootDesigner != null); 

                if (Capture) 
                    Capture = false; 

                IList customFilters = ((IWorkflowRootDesigner)this.rootDesigner).MessageFilters; 
                foreach (WorkflowDesignerMessageFilter filter in customFilters)
                    filters.Add(filter);
            }
 
            foreach (WorkflowDesignerMessageFilter filter in filters)
                filter.SetParentView(this); 
        } 

        private void DisposeMessageFilters(bool stockFilters) 
        {
            List filters = (stockFilters) ? this.stockMessageFilters : this.customMessageFilters;

            //We dispose all the message filters, this is done by copying because some of the 
            //message filters might remove other dependent messagefilters
            ArrayList clonedFilterList = new ArrayList(filters.ToArray()); 
            foreach (WorkflowDesignerMessageFilter filter in clonedFilterList) 
                ((IDisposable)filter).Dispose();
            filters.Clear(); 
        }
        #endregion

		#region Coordinate Transformation Functions 
 		public void InvalidateClientRectangle(Rectangle clientRectangle)
		{ 
 			if (this.layoutEventHandler == null) 
 			{
				if (!clientRectangle.IsEmpty) 
 				{
					//Inflate the invalidated rectangle. When zoom factor is less than 1; there is a loss of precision
					clientRectangle.Inflate(1, 1);
					base.Invalidate(clientRectangle); 
 				}
				else 
 				{ 
 					base.Invalidate();
				} 
 			}
		}

		public void InvalidateLogicalRectangle(Rectangle logicalRectangle) 
		{
 			InvalidateClientRectangle(LogicalRectangleToClient(logicalRectangle)); 
		} 

 		public Point LogicalPointToScreen(Point logicalPoint) 
 		{
			return PointToScreen(LogicalPointToClient(logicalPoint));
 		}
 
		public Point ScreenPointToLogical(Point screenPoint)
		{ 
			return ClientPointToLogical(PointToClient(screenPoint)); 
 		}
 
		public Point LogicalPointToClient(Point logicalPoint)
 		{
 			return LogicalPointToClient(logicalPoint, true);
		} 

 		public Point ClientPointToLogical(Point clientPoint) 
		{ 
			return ClientPointToLogical(clientPoint, true);
		} 

 		public Size LogicalSizeToClient(Size logicalSize)
		{
 			Point[] points = new Point[] { new Point(logicalSize) }; 

 			//Scale the point 
			Matrix scalingMatrix = new Matrix(); 
 			scalingMatrix.Scale(ScaleZoomFactor, ScaleZoomFactor);
			scalingMatrix.TransformPoints(points); 
			return new Size(points[0]);
		}

 		public Size ClientSizeToLogical(Size clientSize) 
		{
 			//Scale the size, size scaling does not require translate 
 			Point[] points = new Point[] { new Point(clientSize) }; 
			Matrix scalingMatrix = new Matrix();
 			scalingMatrix.Scale(ScaleZoomFactor, ScaleZoomFactor); 
			scalingMatrix.Invert();
			scalingMatrix.TransformPoints(points);
			scalingMatrix.Invert();
 			return new Size(points[0]); 
		}
 
 		public Rectangle LogicalRectangleToClient(Rectangle rectangle) 
 		{
            Debug.Assert(this.activeLayout != null, "active layout should not be null"); 
            Rectangle clientViewPort = (this.activeLayout != null) ? this.activeLayout.MapOutRectangleFromLayout(rectangle) : rectangle;
			//
 
 
			return new Rectangle(LogicalPointToClient(clientViewPort.Location, false), LogicalSizeToClient(clientViewPort.Size));
		} 
 
 		public Rectangle ClientRectangleToLogical(Rectangle rectangle)
		{ 
 			//We translate the client viewport to logical view port.
 			//To do this we first get the view port rectangle scale it down
			//then translate it to area of page we would be viewing
 			Rectangle scaledLogicalViewPort = new Rectangle(ClientPointToLogical(rectangle.Location, false), ClientSizeToLogical(rectangle.Size)); 
			return this.activeLayout.MapInRectangleToLayout(scaledLogicalViewPort);
		} 
 
		internal bool IsClientPointInActiveLayout(Point clientPoint)
 		{ 
			Point logicalPoint = ClientPointToLogical(clientPoint, false);
 			return this.activeLayout.IsCoOrdInLayout(logicalPoint);
 		}
 
		/*
 		* Client scale is when we transform the coordinate based on zoom and translate it based on scrolling position and layout 
		* Logical scale is when we transform the coordinate and map it to a flat coordinate system which goes from 0,0 to m,n 
		* We also consider the ActiveLayout to transform the coordinates.
		*/ 
 		private Point LogicalPointToClient(Point point, bool mapToLayout)
		{
 			if (mapToLayout)
 				point = this.activeLayout.MapOutCoOrdFromLayout(point); 

			//Scale the point 
 			Matrix scalingMatrix = new Matrix(); 
			scalingMatrix.Scale(ScaleZoomFactor, ScaleZoomFactor);
			Point[] points = new Point[] { point }; 
			scalingMatrix.TransformPoints(points);

 			//Translate the point
			Matrix translateMatrix = new Matrix(); 
 			translateMatrix.Translate(-ScrollPosition.X, -ScrollPosition.Y);
 			translateMatrix.TransformPoints(points); 
			return points[0]; 
 		}
 
		private Point ClientPointToLogical(Point point, bool mapToLayout)
		{
			Point[] points = new Point[] { point };
 
 			//Translate the point
			Matrix translateMatrix = new Matrix(); 
 			translateMatrix.Translate(ScrollPosition.X, ScrollPosition.Y); 
 			translateMatrix.TransformPoints(points);
 
			//Scale down the point
 			Matrix scalingMatrix = new Matrix();
			scalingMatrix.Scale(ScaleZoomFactor, ScaleZoomFactor);
			scalingMatrix.Invert(); 
			scalingMatrix.TransformPoints(points);
 			scalingMatrix.Invert(); 
			if (!mapToLayout) 
 				return points[0];
 			else 
				return this.activeLayout.MapInCoOrdToLayout(points[0]);
 		}
		#endregion
 
		#region IServiceProvider Implemetation
		object IServiceProvider.GetService(Type serviceType) 
 		{ 
			return GetService(serviceType);
 		} 

 		protected override object GetService(Type serviceType)
		{
 			object retVal = null; 

            if (serviceType == typeof(CommandID)) 
                retVal = new CommandID(new Guid("5f1c3c8d-60f1-4b98-b85b-8679f97e8eac"), 0); 
            else
				retVal = this.serviceProvider.GetService(serviceType); 

            return retVal;
		}
		#endregion 

 		#region Class WorkflowMessageDispatchData 
		private sealed class WorkflowMessageDispatchData : IDisposable 
 		{
 			private WorkflowView workflowView; 
            private HitTestInfo messageContext = null;

			public WorkflowMessageDispatchData(WorkflowView workflowView, EventArgs e)
 			{ 
				this.workflowView = workflowView;
 
				if (this.workflowView.RootDesigner != null && this.workflowView.stockMessageFilters.Count > 0) 
				{
 					Point clientPoint = Point.Empty; 
					if (e is MouseEventArgs || e is DragEventArgs)
 					{
 						if (e is MouseEventArgs)
						{ 
 							clientPoint = new Point(((MouseEventArgs)e).X, ((MouseEventArgs)e).Y);
						} 
						else if (e is DragEventArgs) 
						{
 							clientPoint = this.workflowView.PointToClient(new Point(((DragEventArgs)e).X, ((DragEventArgs)e).Y)); 
							this.workflowView.UpdateLayout();
 						}

 						Point logicalPoint = this.workflowView.ClientPointToLogical(clientPoint); 
						HitTestInfo hitTestInfo = this.workflowView.RootDesigner.HitTest(logicalPoint);
                        this.messageContext = (hitTestInfo != null) ? hitTestInfo : HitTestInfo.Nowhere; 
                        this.workflowView.messageHitTestContexts.Push(this.messageContext); 
 					}
				} 
			}

			void IDisposable.Dispose()
 			{ 
                if (this.workflowView != null && this.messageContext != null)
                { 
                    HitTestInfo hittestInfo = this.workflowView.messageHitTestContexts.Pop(); 
                    if (hittestInfo != this.messageContext)
                        Debug.Assert(false, "WorkflowView poped wrong message context"); 
                }
			}

 			public ReadOnlyCollection Filters 
 			{
				get 
 				{ 
                    //We recreate a new list everytime as in some of the messages dispatched, we there can
                    //be additional filters which might be added 
                    List mergedFilterList = new List();
                    mergedFilterList.AddRange(this.workflowView.customMessageFilters);
                    mergedFilterList.AddRange(this.workflowView.stockMessageFilters);
                    return mergedFilterList.AsReadOnly(); 
				}
			} 
		} 
 		#endregion
 
        #region IMessageFilter Implementation
        [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
        bool IMessageFilter.PreFilterMessage(ref Message m)
        { 
            bool handled = false;
            if (m.Msg == NativeMethods.WM_KEYDOWN || m.Msg == NativeMethods.WM_SYSKEYDOWN || 
                m.Msg == NativeMethods.WM_KEYUP || m.Msg == NativeMethods.WM_SYSKEYUP) 
            {
                Control control = Control.FromHandle(m.HWnd); 
                if (control != null && (control == this || Controls.Contains(control)))
                {
                    KeyEventArgs eventArgs = new KeyEventArgs((Keys)(unchecked((int)(long)m.WParam)) | ModifierKeys);
                    if (m.Msg == NativeMethods.WM_KEYDOWN || m.Msg == NativeMethods.WM_SYSKEYDOWN) 
                        OnKeyDown(eventArgs);
                    else 
                        OnKeyUp(eventArgs); 

                    handled = eventArgs.Handled; 
                }
            }

            return handled; 
        }
        #endregion 
    } 

    #region Class WorkflowViewAccessibleObject 
    public class WorkflowViewAccessibleObject : Control.ControlAccessibleObject
    {
        private WorkflowView workflowView;
 
        public WorkflowViewAccessibleObject(WorkflowView workflowView)
            : base(workflowView) 
        { 
            if (workflowView == null)
                throw new ArgumentNullException("workflowView"); 
            this.workflowView = workflowView;
        }

        public override Rectangle Bounds 
        {
            get 
            { 
                return new Rectangle(this.workflowView.PointToScreen(Point.Empty), this.workflowView.ViewPortSize);
            } 
        }

        public override string DefaultAction
        { 
            get
            { 
                return DR.GetString(DR.AccessibleAction); 
            }
        } 

        public override string Description
        {
            get 
            {
                return DR.GetString(DR.WorkflowViewAccessibleDescription); 
            } 
        }
 
        public override string Help
        {
            get
            { 
                return DR.GetString(DR.WorkflowViewAccessibleHelp);
            } 
        } 

        public override string Name 
        {
            get
            {
                return DR.GetString(DR.WorkflowViewAccessibleName); 
            }
 
            set 
            {
            } 
        }

        public override AccessibleRole Role
        { 
            get
            { 
                return AccessibleRole.Diagram; 
            }
        } 

        public override AccessibleObject GetChild(int index)
        {
            return (this.workflowView.RootDesigner != null && index == 0) ? this.workflowView.RootDesigner.AccessibilityObject : base.GetChild(index); 
        }
 
        public override int GetChildCount() 
        {
            return (this.workflowView.RootDesigner != null) ? 1 : -1; 
        }

        public override AccessibleObject Navigate(AccessibleNavigation navdir)
        { 
            if (navdir == AccessibleNavigation.FirstChild || navdir == AccessibleNavigation.LastChild)
                return GetChild(0); 
            else 
                return base.Navigate(navdir);
        } 
    }
    #endregion

	#region WorkflowTimer 
 	internal sealed class WorkflowTimer : IDisposable
 	{ 
		private static WorkflowTimer workflowTimer; 

 		private const int TimerInterval = 50; 
		private Timer timer = null;
		private List elapsedEvents = new List();

		internal static WorkflowTimer Default 
 		{
			get 
 			{ 
 				if (WorkflowTimer.workflowTimer == null)
					WorkflowTimer.workflowTimer = new WorkflowTimer(); 
 				return WorkflowTimer.workflowTimer;
			}
		}
 
		private WorkflowTimer()
 		{ 
			this.timer = new Timer(); 
 			this.timer.Interval = WorkflowTimer.TimerInterval;
 			this.timer.Tick += new EventHandler(OnTimer); 
			this.timer.Stop();
 		}

        ~WorkflowTimer() 
        {
            Dispose(false); 
        } 

        public void Dispose() 
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        } 

        private void Dispose(bool disposing) 
        { 
            if (this.timer != null)
			{ 
				if (this.timer.Enabled)
					this.timer.Stop();

 				this.timer.Dispose(); 
				this.timer = null;
 			} 
 		} 

		internal void Subscribe(int elapsedInterval, EventHandler elapsedEventHandler) 
 		{
			this.elapsedEvents.Add(new ElapsedEventUnit(elapsedInterval / WorkflowTimer.TimerInterval, elapsedEventHandler));
			if (!this.timer.Enabled)
				this.timer.Start(); 
 		}
 
		internal void Unsubscribe(EventHandler elapsedEventHandler) 
 		{
 			List removableElapsedEvents = new List(); 
			foreach (ElapsedEventUnit elapsedEvent in this.elapsedEvents)
 			{
				if (elapsedEvent.elapsedEventHandler == elapsedEventHandler)
					removableElapsedEvents.Add(elapsedEvent); 
			}
 
 			foreach (ElapsedEventUnit elapsedEvent in removableElapsedEvents) 
				this.elapsedEvents.Remove(elapsedEvent);
 
 			if (this.elapsedEvents.Count == 0 && this.timer.Enabled)
 				this.timer.Stop();
		}
 
 		private void OnTimer(object sender, EventArgs e)
		{ 
			List clonedList = new List(this.elapsedEvents); 
			foreach (ElapsedEventUnit elapsedEvent in clonedList)
 			{ 
				elapsedEvent.elapsedTime += 1;
 				if (elapsedEvent.elapsedInterval <= elapsedEvent.elapsedTime)
 				{
					elapsedEvent.elapsedTime = 0; 
 					elapsedEvent.elapsedEventHandler(this, EventArgs.Empty);
				} 
			} 
		}
 
 		private sealed class ElapsedEventUnit
		{
 			internal EventHandler	elapsedEventHandler;
 			internal int			elapsedInterval; 
			internal int			elapsedTime;
 
 			internal ElapsedEventUnit(int interval, EventHandler eventHandler) 
			{
				this.elapsedInterval = interval; 
				this.elapsedEventHandler = eventHandler;
 			}
		}
 	} 
 	#endregion
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
namespace System.Workflow.ComponentModel.Design 
{
 	using System;
	using System.IO;
	using System.Data; 
	using System.Drawing;
 	using System.Security; 
	using System.Resources; 
 	using System.Reflection;
 	using System.Diagnostics; 
	using System.Collections;
 	using System.Windows.Forms;
	using System.ComponentModel;
	using System.Drawing.Design; 
	using System.Drawing.Imaging;
 	using System.Drawing.Printing; 
	using System.Drawing.Drawing2D; 
    using System.Workflow.Interop;
    using System.Collections.Generic; 
 	using System.Windows.Forms.Design;
 	using System.Security.Permissions;
	using System.ComponentModel.Design;
 	using System.Runtime.InteropServices; 
    using System.Collections.ObjectModel;
    ///What did I change in this file 
	///1. Eliminated the layout manager and introduced classes for WorkflowLayout and PrintPreviewLayout 
	///2. Eliminated the event syncing of PageSetupData change. We call performlayout on the current designer service whenever the pagesetupdata changes
 
	/// Designer Features:
 	/// Selection on click and thru drag rectangle		
	/// Reconfigurable background						
 	/// Scrolling										 
 	/// Ensure Visible functionality					
	/// Accessibility									 
 	/// Zoom											 
	/// Rehostable			
	/// Extensible 
	/// Small memory footprint
 	/// Ability to move around objects using drag drop	
	/// Ability to drop the objects using drag drop		
 	/// Printing support								 
 	/// Theme support
	/// Magnifier 
 	/// AutoScroll 
	/// AutoExpand
	/// USE THIS FOR PERFORMANCE TEST: Debug.WriteLine("******Root drawing: " + Convert.ToString((DateTime.Now.Ticks - ticks) / 10000) + "ms"); 
	///
 	/// Here are some details about the coordinate system,
	///
 	/// Screen CoOrdinate System: Starts at 0,0 of the screen 
 	///	Client CoOrdinate System: Starts at 0,0 of the control
	/// Logical CoOrdinate System: The workflowview supports zooming and scroll, we want to hide this 
 	/// complexity from the activity writter and hence whenever we get a coordinate we translate it based 
	/// scroll position, zoom level and layout. This helps us to sheild the activity designers from complexity
	/// of zooming, scaling and layouting. The designer writters deal with one coordinate system which is unscaled and 
	/// starts at 0,0
 	///
	///
 
 	[ToolboxItem(false)]
 	[ActivityDesignerTheme(typeof(AmbientTheme), Xml = WorkflowView.ThemeXml)] 
	public class WorkflowView : UserControl, IServiceProvider, IMessageFilter 
 	{
		#region Theme Initializer XML 
		internal const string ThemeXml =
				"";
		#endregion 

		#region Members Variables
		private	enum TabButtonIds		{ MultiPage = 1, Zoom, Pan}
 
 		//Designer Hookup
		private IServiceProvider				serviceProvider = null; 
 		 
 		private ActivityDesigner				rootDesigner = null;
		 
 		//Zoom
		private float							zoomLevel = 1.0f;
		private int								shadowDepth = WorkflowTheme.CurrentTheme.AmbientTheme.ShadowDepth;
 
		//MessageFilters
        private List stockMessageFilters = new List(); 
        private List customMessageFilters = new List(); 

 		// 

 		private Bitmap							viewPortBitmap = null;

 		//Misc. 
		private WorkflowToolTip					workflowToolTip = null;
 
 		private CommandSet						commandSet = null; 
		private DynamicAction					fitAllAction = null;
 
		//print
		private int								prePreviewZoom = 100;
 		private Point							prePreviewScroll = Point.Empty;
		private WorkflowPrintDocument			printDocument = null; 

 		//Active layout 
 		private WorkflowLayout					activeLayout = null; 
		private WorkflowLayout					defaultLayout = null;
 
 		//One time callable delegates
		private EventHandler					layoutEventHandler = null;
        private EventHandler                    ensureVisibleEventHandler = null;
 
		private Stack				messageHitTestContexts = new Stack();
 
		private HScrollBar						hScrollBar; 
 		private VScrollBar						vScrollBar;
 
        private TabControl                      toolContainer;
        private EventHandler                    idleEventListeners;
        private EventHandler                    idleEventHandler;
 
        private bool                            dragDropInProgress;
		#endregion 
 
        #region Events
        public event EventHandler ZoomChanged; 
        public event EventHandler RootDesignerChanged;
        #endregion

        #region Constructor and Dispose 
        public WorkflowView() : this(new DesignSurface())
 		{ 
 		} 

		public WorkflowView(IServiceProvider serviceProvider) 
 		{
			Debug.Assert(serviceProvider != null);
			if (serviceProvider == null)
				throw new ArgumentNullException("serviceProvider"); 

 			SuspendLayout(); 
			AllowDrop = true; 
 			AutoScroll = false;
 			HScroll = false; 
			VScroll = false;
 			SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint | ControlStyles.Opaque | ControlStyles.AllPaintingInWmPaint | ControlStyles.Selectable | ControlStyles.EnableNotifyMessage, true);

			this.serviceProvider = serviceProvider; 

			//*****Promote the services which are accessed from other components 
			IServiceContainer serviceContainer = GetService(typeof(IServiceContainer)) as IServiceContainer; 
 			if (serviceContainer != null)
			{ 
 				//Remove any existing designer service if there is any
 				serviceContainer.RemoveService(typeof(WorkflowView));
				serviceContainer.AddService(typeof(WorkflowView), this);
            } 

            //set the UI Service to be used by themes 
            IUIService uiService = this.serviceProvider.GetService(typeof(IUIService)) as IUIService; 
            if(uiService != null)
                WorkflowTheme.UIService = uiService; 

 			//Make sure that we add scrollbars
			EnsureScrollBars(new HScrollBar(), new VScrollBar());
 
			//Initialize the tooltip shown
			this.workflowToolTip = new WorkflowToolTip(this); 
 
            //[....] the global theme change event, which is fired by the theme infrastructure for theme change
            WorkflowTheme.ThemeChanged += new EventHandler(OnThemeChange); 

            //Create the core message filters
            PopulateMessageFilters(true);
 
            //Set the root designer, note that the dynamic action is dependent on the DynamicActionMessageFilter pushed
            //when the root is set. 
            RootDesigner = ActivityDesigner.GetSafeRootDesigner(this); 
            this.fitAllAction = CreateDynamicAction();
 
 			//If the active layout is still null then we will set the default layout as active layout
			if (this.activeLayout == null || this.defaultLayout == null)
 				ActiveLayout = DefaultLayout = new WorkflowRootLayout(this.serviceProvider);
 
            //Create the local command set and update all the commands once
 			IMenuCommandService menuCommandService = GetService(typeof(IMenuCommandService)) as IMenuCommandService; 
			if (menuCommandService != null) 
 			{
				this.commandSet = new CommandSet(this); 
				this.commandSet.UpdatePanCommands(true);
			}

            //Subscribe to selection change 
            ISelectionService selectionService = GetService(typeof(ISelectionService)) as ISelectionService;
            if (selectionService != null) 
                selectionService.SelectionChanged += new EventHandler(OnSelectionChanged); 

            //In case of non VS case we need to pumpin the Keyboard messages, the user control sets 
            //focus to the child controls by default which is a problem so we need to trap the
            //messages by adding application level message filter, in case of VS this is not required and
            //the message filter is never called.
            Application.AddMessageFilter(this); 

            //We make sure that during the construction we dont do perform layouts on idle event 
            ResumeLayout(true); 
        }
 
 		protected override void Dispose(bool disposing)
		{
 			//Remove the proffered services
 			if (disposing) 
			{
                try 
                { 
                    SuspendLayout();
 
                    Application.RemoveMessageFilter(this);

                    if (this.layoutEventHandler != null)
                    { 
                        Idle -= this.layoutEventHandler;
                        this.layoutEventHandler = null; 
                    } 

                    if (this.ensureVisibleEventHandler != null) 
                    {
                        Idle -= this.ensureVisibleEventHandler;
                        this.ensureVisibleEventHandler = null;
                    } 

                    if (this.idleEventHandler != null) 
                    { 
                        this.idleEventListeners = null;
 
                        Form host = TopLevelControl as Form;
                        if (!Application.MessageLoop || (host != null && host.Modal))
                            WorkflowTimer.Default.Unsubscribe(this.idleEventHandler);
                        else 
                            Application.Idle -= this.idleEventHandler;
                        this.idleEventHandler = null; 
                    } 

                    ISelectionService selectionService = GetService(typeof(ISelectionService)) as ISelectionService; 
                    if (selectionService != null)
                        selectionService.SelectionChanged -= new EventHandler(OnSelectionChanged);

                    //Unsubscribe the theme change 
                    WorkflowTheme.ThemeChanged -= new EventHandler(OnThemeChange);
 
                    //Remove the dynamic action 
                    if (this.fitAllAction != null)
                    { 
                        this.fitAllAction.Dispose();
                        this.fitAllAction = null;
                    }
 
                    if (this.workflowToolTip != null)
                    { 
                        ((IDisposable)this.workflowToolTip).Dispose(); 
                        this.workflowToolTip = null;
                    } 

                    DisposeMessageFilters(false);
                    DisposeMessageFilters(true);
 
                    //Dispose the layouts
                    this.activeLayout = null; 
                    if (this.defaultLayout != null) 
                    {
                        this.defaultLayout.Dispose(); 
                        this.defaultLayout = null;
                    }

                    //Destroy other resources 
                    if (this.viewPortBitmap != null)
                    { 
                        this.viewPortBitmap.Dispose(); 
                        this.viewPortBitmap = null;
                    } 

                    if (this.commandSet != null)
                    {
                        this.commandSet.Dispose(); 
                        this.commandSet = null;
                    } 
 
                    HScrollBar.ValueChanged -= new EventHandler(OnScroll);
                    VScrollBar.ValueChanged -= new EventHandler(OnScroll); 

                    if (this.toolContainer != null)
                    {
                        Controls.Remove(this.toolContainer); 
                        this.toolContainer.TabStrip.Tabs.Clear();
                        this.toolContainer.Dispose(); 
                        this.toolContainer = null; 
                    }
 
                    IServiceContainer serviceContainer = GetService(typeof(IServiceContainer)) as IServiceContainer;
                    if (serviceContainer != null)
                    {
                        serviceContainer.RemoveService(typeof(WorkflowView)); 
                    }
                } 
                finally 
                {
                    ResumeLayout(false); 
                }
 			}

			base.Dispose( disposing ); 
		}
		#endregion 
 
 		#region Public Properties
		public int Zoom 
 		{
 			get
			{
 				return Convert.ToInt32(this.zoomLevel * 100); 
			}
 
			set 
			{
 				if (Zoom == value) 
					return;

 				if (value < AmbientTheme.MinZoom || value > AmbientTheme.MaxZoom)
 					throw new NotSupportedException(DR.GetString(DR.ZoomLevelException2, AmbientTheme.MinZoom, AmbientTheme.MaxZoom)); 

				ScrollBar hScrollBar = HScrollBar; 
 				ScrollBar vScrollBar = VScrollBar; 

                if (hScrollBar != null && vScrollBar != null) 
                {
                    PointF oldRelativeCenter = Point.Empty;
                    Point oldCenter = new Point(ScrollPosition.X, ScrollPosition.Y);
                    oldRelativeCenter = new PointF((float)oldCenter.X / (float)hScrollBar.Maximum, (float)oldCenter.Y / (float)vScrollBar.Maximum); 

                    //recalculate the zoom and scroll range 
                    this.zoomLevel = (float)value / 100.0f; 
                    UpdateScrollRange();
 
                    //center the view again
                    Point newCenter = new Point((int)((float)hScrollBar.Maximum * oldRelativeCenter.X), (int)((float)vScrollBar.Maximum * oldRelativeCenter.Y));
                    ScrollPosition = new Point(newCenter.X, newCenter.Y);
 
                    if (this.rootDesigner != null)
                        this.rootDesigner.Location = this.activeLayout.RootDesignerAlignment; 
 
                    InvalidateClientRectangle(Rectangle.Empty);
 
                    //

                    this.activeLayout.Update(null, WorkflowLayout.LayoutUpdateReason.ZoomChanged);
 
                    //force command refresh
                    //this is to workarond VS not refreshing Zoom drop down when doing area zoom-in 
                    IUIService uis = GetService(typeof(IUIService)) as IUIService; 
                    if (uis != null)
                        uis.SetUIDirty(); 

                    //We need to update the zoom commands when the zoom is updated
                    if (this.commandSet != null)
                        this.commandSet.UpdateZoomCommands(true); 

                    OnZoomChanged(); 
                } 
			}
		} 

		public ActivityDesigner RootDesigner
 		{
			get 
 			{
 				return this.rootDesigner; 
			} 

 			set 
			{
				if (this.rootDesigner == value)
					return;
 
                DisposeMessageFilters(false);
 
 				this.rootDesigner = value; 

				if (this.rootDesigner != null) 
 				{
                    PopulateMessageFilters(false);
                    ActiveLayout = DefaultLayout = this.rootDesigner.SupportedLayout;
 				} 

                OnRootDesignerChanged(); 
 
				base.PerformLayout();
 			} 
		}

		public int ShadowDepth
		{ 
 			get
			{ 
 				return this.shadowDepth; 
 			}
 
			set
 			{
				if (value < AmbientTheme.MinShadowDepth || value > AmbientTheme.MaxShadowDepth)
					throw new NotSupportedException(DR.GetString(DR.ShadowDepthException, AmbientTheme.MinShadowDepth, AmbientTheme.MaxShadowDepth)); 

				if (this.shadowDepth == value) 
 					return; 

				this.shadowDepth = value; 
 				InvalidateClientRectangle(Rectangle.Empty);
 			}
		}
 
 		public Rectangle ViewPortRectangle
		{ 
			get 
			{
 				return new Rectangle(ScrollPosition, ViewPortSize); 
			}
 		}

 		public Size ViewPortSize 
		{
 			get 
			{ 
				Size viewPortSize = ClientSize;
                if (HScrollBar.Visible) 
                    viewPortSize.Height = Math.Max(0, viewPortSize.Height - HScrollBar.Height);
                if (VScrollBar.Visible)
                    viewPortSize.Width = Math.Max(0, viewPortSize.Width - VScrollBar.Width);
				return viewPortSize; 
 			}
		} 
 
 		public Point ScrollPosition
 		{ 
			get
 			{
				return new Point(HScrollBar.Value, VScrollBar.Value);
			} 

			set 
 			{ 
				ScrollBar hScrollBar = HScrollBar;
 				if (hScrollBar != null) 
 				{
					value.X = Math.Min(value.X, hScrollBar.Maximum - hScrollBar.LargeChange + 1);
 					value.X = Math.Max(value.X, hScrollBar.Minimum);
					hScrollBar.Value = value.X; 
				}
 
				ScrollBar vScrollBar = VScrollBar; 
 				if (vScrollBar != null)
				{ 
 					value.Y = Math.Min(value.Y, vScrollBar.Maximum - vScrollBar.LargeChange + 1);
 					value.Y = Math.Max(value.Y, vScrollBar.Minimum);
					vScrollBar.Value = value.Y;
 				} 
			}
		} 
 
		public bool PrintPreviewMode
 		{ 
			get
 			{
 				return (this.activeLayout == ((WorkflowPrintDocument)PrintDocument).PrintPreviewLayout);
			} 

 			set 
			{ 
				if (PrintPreviewMode == value)
					return; 

 				if (value && PrinterSettings.InstalledPrinters.Count == 0)
				{
                    DesignerHelpers.ShowError(this, DR.GetString(DR.ThereIsNoPrinterInstalledErrorMessage)); 
 					value = false;
 				} 
 
                ActiveLayout = (value) ? ((WorkflowPrintDocument)PrintDocument).PrintPreviewLayout : DefaultLayout;
 
                if (this.commandSet != null)
					this.commandSet.UpdatePageLayoutCommands(true);

 				if (PrintPreviewMode) 
				{
					this.prePreviewZoom = Zoom; 
					this.prePreviewScroll = ScrollPosition; 
 					Zoom = 40;
				} 
 				else
 				{
					Zoom = this.prePreviewZoom;
 					ScrollPosition = this.prePreviewScroll; 
				}
			} 
		} 

 		public PrintDocument PrintDocument 
		{
 			get
 			{
				if (this.printDocument == null) 
 					this.printDocument = new WorkflowPrintDocument(this);
 
				return this.printDocument; 
			}
		} 

 		public event EventHandler Idle
		{
 			add 
 			{
                //Add the listener to our list 
                this.idleEventListeners += value; 

                if (this.idleEventHandler == null) 
                {
                    this.idleEventHandler = new EventHandler(OnWorkflowIdle);

                    Form host = TopLevelControl as Form; 
                    if (!Application.MessageLoop || (host != null && host.Modal))
                        WorkflowTimer.Default.Subscribe(100, this.idleEventHandler); 
                    else 
                        Application.Idle += this.idleEventHandler;
                } 
			}

 			remove
			{ 
                this.idleEventListeners -= value;
 
                if (this.idleEventHandler != null && this.idleEventListeners == null) 
                {
                    Form host = TopLevelControl as Form; 
                    if (host != null && host.Modal)
                        WorkflowTimer.Default.Unsubscribe(this.idleEventHandler);
                    else
                        Application.Idle -= this.idleEventHandler; 

                    this.idleEventHandler = null; 
                } 
			}
		} 

 		public HScrollBar HScrollBar
		{
 			get 
 			{
				return this.hScrollBar; 
 			} 
		}
 
		public VScrollBar VScrollBar
		{
 			get
			{ 
 				return this.vScrollBar;
 			} 
        } 

        public bool EnableFitToScreen 
        {
            get
            {
                return (this.fitAllAction != null); 
            }
 
            set 
            {
                if (EnableFitToScreen == value) 
                    return;

                if (value)
                { 
                    if (this.fitAllAction == null)
                        this.fitAllAction = CreateDynamicAction(); 
                } 
                else
                { 
                    if (this.fitAllAction != null)
                    {
                        this.fitAllAction.Dispose();
                        this.fitAllAction = null; 
                    }
                } 
 
                InvalidateClientRectangle(Rectangle.Empty);
            } 
        }
		#endregion

 		#region Protected Properties 
		#endregion
 
		#region Private Properties 
        internal bool DragDropInProgress
        { 
            get
            {
                return this.dragDropInProgress;
            } 
        }
 
        internal bool ShowToolContainer 
        {
            get 
            {
                return (this.toolContainer != null);
            }
 
            set
            { 
                if (ShowToolContainer == value) 
                    return;
 
                try
                {
                    SuspendLayout();
 
                    if (value)
                    { 
                        this.toolContainer = new TabControl(DockStyle.Right, AnchorAlignment.Far); 
                        Controls.Add(this.toolContainer);
                        EnsureScrollBars(this.hScrollBar, this.toolContainer.ScrollBar as VScrollBar); 

                        string[,] tabButtonInfo = new string[/*Caption Resource ID*/,/*Bitmap Resource ID*/ ] { { "MultipageLayoutCaption", "MultipageLayout" }, { "ZoomCaption", "Zoom" }, { "PanCaption", "AutoPan" } };
                        for (int i = 0; i < tabButtonInfo.GetLength(0); i++)
                        { 
                            Bitmap tabImage = DR.GetImage(tabButtonInfo[i, 1]) as Bitmap;
                            string buttonCaption = DR.GetString(tabButtonInfo[i, 0]); 
                            this.toolContainer.TabStrip.Tabs.Add(new ItemInfo(i + 1, tabImage, buttonCaption)); 
                        }
 
                        this.toolContainer.TabStrip.TabChange += new SelectionChangeEventHandler(OnTabChange);
                        if (this.commandSet != null)
                        {
                            this.commandSet.UpdatePageLayoutCommands(true); 
                            this.commandSet.UpdateZoomCommands(true);
                            this.commandSet.UpdatePanCommands(true); 
                        } 
                    }
                    else 
                    {
                        this.toolContainer.TabStrip.TabChange -= new SelectionChangeEventHandler(OnTabChange);
                        this.toolContainer.TabStrip.Tabs.Clear();
 
                        Controls.Remove(this.toolContainer);
                        this.toolContainer.Dispose(); 
                        this.toolContainer = null; 

                        EnsureScrollBars(this.hScrollBar, new VScrollBar()); 
                    }
                }
                finally
                { 
                    ResumeLayout(true);
                } 
            } 
        }
 
        internal HitTestInfo MessageHitTestContext
		{
 			get
			{ 
 				return this.messageHitTestContexts.Peek();
 			} 
		} 

 		internal WorkflowLayout ActiveLayout 
		{
			get
			{
 				return this.activeLayout; 
			}
 
 			set 
 			{
				Debug.Assert(value != null); 
 				if (value == null)
					throw new ArgumentNullException("Layout cannot be null!");

				Cursor cursor = Cursor.Current; 
				try
 				{ 
					Cursor.Current = Cursors.WaitCursor; 
 					
 					this.activeLayout = value; 
					if (this.activeLayout != ((WorkflowPrintDocument)PrintDocument).PrintPreviewLayout)
 						DefaultLayout = this.activeLayout;

					base.PerformLayout(); 
					if (this.commandSet != null)
						this.commandSet.UpdatePageLayoutCommands(true); 
 				} 
				finally
 				{ 
 					Cursor.Current = cursor;
				}
 			}
		} 

		private WorkflowLayout DefaultLayout 
		{ 
 			get
			{ 
 				if (this.defaultLayout == null)
 					this.defaultLayout = new WorkflowRootLayout(this);
				return this.defaultLayout;
 			} 

			set 
			{ 
				if (value == null)
 					throw new ArgumentNullException(DR.GetString(DR.Error_WorkflowLayoutNull)); 

				if (this.defaultLayout == value)
 					return;
 
 				if (this.defaultLayout != null)
					this.defaultLayout.Dispose(); 
 
 				this.defaultLayout = value;
			} 
		}

		private float ScaleZoomFactor
 		{ 
			get
 			{ 
 				return (this.zoomLevel * this.activeLayout.Scaling); 
			}
 		} 
		#endregion

		#region Public Methods
		public void AddDesignerMessageFilter(WorkflowDesignerMessageFilter designerMessageFilter) 
 		{
			if (designerMessageFilter == null) 
 				throw new ArgumentNullException("designerMessageFilter"); 

 			if (Capture) 
				Capture = false;

 			this.customMessageFilters.Insert(0, designerMessageFilter);
			designerMessageFilter.SetParentView(this); 
		}
 
		public void RemoveDesignerMessageFilter(WorkflowDesignerMessageFilter designerMessageFilter) 
 		{
			if (designerMessageFilter == null) 
 				throw new ArgumentNullException("designerMessageFilter");

 			if (this.customMessageFilters.Contains(designerMessageFilter))
			{ 
 				if (Capture)
					Capture = false; 
 
                this.customMessageFilters.Remove(designerMessageFilter);
				((IDisposable)designerMessageFilter).Dispose(); 
			}
 		}

		public void ShowInPlaceToolTip(string toolTipText, Rectangle toolTipRectangle) 
 		{
 			if (toolTipText == null) 
				throw new ArgumentNullException("toolTipText"); 

 			if (toolTipRectangle.IsEmpty) 
				throw new ArgumentException(SR.GetString(SR.Error_EmptyToolTipRectangle));

			this.workflowToolTip.SetText(toolTipText, toolTipRectangle);
		} 

 		public void ShowInfoTip(string text) 
		{ 
 			if (text == null)
 				throw new ArgumentNullException("text"); 

			this.workflowToolTip.SetText(String.Empty, text);
 		}
 
		public void ShowInfoTip(string title, string text)
		{ 
			if (title == null) 
 				throw new ArgumentNullException("title");
 
			if (text == null)
 				throw new ArgumentNullException("text");

 			this.workflowToolTip.SetText(title, text); 
		}
 
 		public void EnsureVisible(object selectableObject) 
		{
			if (selectableObject == null) 
				throw new ArgumentNullException("selectableObject");

 			// make sure that all the parents are expanded
			Activity activity = selectableObject as Activity; 
 			while (activity != null)
 			{ 
				ActivityDesigner activityDesigner = ActivityDesigner.GetDesigner(activity); 
 				CompositeActivityDesigner parentDesigner = activityDesigner.ParentDesigner;
				if (parentDesigner != null) 
				{
					if (activityDesigner != null)
 						parentDesigner.EnsureVisibleContainedDesigner(activityDesigner);
					activity = parentDesigner.Activity; 
 				}
 				else 
				{ 
 					activity = null;
				} 
			}

			//this is to handle the case when we call ensure visible of a scope which currently has
 			//activity from the secondary flow selected. instead we should always switch to the main flow 
			activity = selectableObject as Activity;
 			if (activity != null) 
 			{ 
				CompositeActivityDesigner compositeDesigner = ActivityDesigner.GetDesigner(activity) as CompositeActivityDesigner;
 				if (compositeDesigner != null) 
					compositeDesigner.EnsureVisibleContainedDesigner(compositeDesigner);
			}

			PerformLayout(false); 

            if (this.ensureVisibleEventHandler == null) 
            { 
                this.ensureVisibleEventHandler = new EventHandler(OnEnsureVisible);
                Idle += this.ensureVisibleEventHandler; 
            }
 		}

		public void PerformLayout(bool immediateUpdate) 
 		{
 			if (immediateUpdate) 
			{ 
 				if (this.layoutEventHandler != null)
				{ 
					Idle -= this.layoutEventHandler;
					this.layoutEventHandler = null;
 				}
				base.PerformLayout();//invalidate rectangle really cares for the this.layoutEventHandler being null 
 			}
 			else if (this.layoutEventHandler == null) 
			{ 
 				this.layoutEventHandler = new EventHandler(OnPerformLayout);
				Idle += this.layoutEventHandler; 
			}
		}

        public void SaveViewState(Stream viewState) 
        {
            if (viewState == null) 
                throw new ArgumentNullException("viewState"); 

            IDesignerHost designerHost = (IDesignerHost)GetService(typeof(IDesignerHost)); 
            if (designerHost == null)
                throw new Exception(SR.GetString(SR.General_MissingService, typeof(IDesignerHost).FullName));

            BinaryWriter writer = new BinaryWriter(viewState); 

            // write workflow properties 
            writer.Write(this.PrintPreviewMode); 
            writer.Write(this.Zoom);
 
            // write components
            DesignerHelpers.SerializeDesignerStates(designerHost, writer);

            // write scroll position 
            writer.Write(this.ScrollPosition.X);
            writer.Write(this.ScrollPosition.Y); 
        } 

        public void LoadViewState(Stream viewState) 
        {
            if (viewState == null)
                throw new ArgumentNullException("viewState");
 
            bool outdated = false;
            Point scrollPosition = new Point(0, 0); 
 
            IDesignerHost designerHost = (IDesignerHost)GetService(typeof(IDesignerHost));
            if (designerHost == null) 
                throw new Exception(SR.GetString(SR.General_MissingService, typeof(IDesignerHost).FullName));

            viewState.Position = 0;
 
            BinaryReader reader = new BinaryReader(viewState);
 
            // read workflow properties 
            this.PrintPreviewMode = reader.ReadBoolean();
            this.Zoom = reader.ReadInt32(); 
            try
            {
                // get activities
                outdated = DesignerHelpers.DeserializeDesignerStates(designerHost, reader); 

                // we will apply the scrolling only if if there is perfect match 
                // between the components in the workflow and the persisted data. 
                // It might be different if files were updated outside of VS, or if
                // VS crashes. 
                if (!outdated)
                {
                    scrollPosition.X = reader.ReadInt32();
                    scrollPosition.Y = reader.ReadInt32(); 
                }
            } 
            finally 
            {
                // flush the layout to apply the new settings, this will set the scrollers extents 
                base.PerformLayout();
                this.ScrollPosition = scrollPosition;
            }
        } 

        ///  
        /// Changes zoom level on the design surface such that the entire workflow is displayed in the view 
        /// 
        public void FitToScreenSize() 
        {
            if (HScrollBar.Maximum > ViewPortSize.Width || VScrollBar.Maximum > ViewPortSize.Height)
            {
                int newZoom = (int)(100.0f / ActiveLayout.Scaling * Math.Min((float)ViewPortSize.Width / (float)ActiveLayout.Extent.Width, (float)ViewPortSize.Height / (float)ActiveLayout.Extent.Height)); 
                Zoom = Math.Min(Math.Max(newZoom, AmbientTheme.MinZoom), AmbientTheme.MaxZoom);
            } 
        } 

        ///  
        /// Sets the zoom level to 100% so that the workflow size is restored to actial workflow size
        /// 
        public void FitToWorkflowSize()
        { 
            if (Zoom != 100)
                Zoom = 100; 
        } 

        ///  
        /// Saves workflow as image to a file based on the format specified
        /// 
        /// Path to file where to save the image
        /// Format in which to save the image 
        public void SaveWorkflowImage(string imageFile, ImageFormat imageFormat)
        { 
            if (imageFile == null) 
                throw new ArgumentNullException("imageFile");
 
            if (imageFormat == null)
                throw new ArgumentNullException("imageFormat");

            Bitmap workflowBitmap = TakeWorkflowSnapShot(); 
            if (workflowBitmap != null)
            { 
                workflowBitmap.Save(imageFile, imageFormat); 
                workflowBitmap.Dispose();
            } 
        }

        /// 
        /// Saves workflow as image to a stream based on encoding specified 
        /// 
        /// Stream where to save the workflow 
        /// Format in which to save the image 
        public void SaveWorkflowImage(Stream stream, ImageFormat imageFormat)
        { 
            if (stream == null)
                throw new ArgumentNullException("stream");

            if (imageFormat == null) 
                throw new ArgumentNullException("imageFormat");
 
            Bitmap workflowBitmap = TakeWorkflowSnapShot(); 
            if (workflowBitmap != null)
            { 
                workflowBitmap.Save(stream, imageFormat);
                workflowBitmap.Dispose();
            }
        } 

        ///  
        /// Stores the workflow image to clipboard. 
        /// 
        public void SaveWorkflowImageToClipboard() 
        {
            Bitmap workflowBitmap = TakeWorkflowSnapShot();
            if (workflowBitmap != null)
            { 
                Clipboard.SetDataObject(workflowBitmap, true);
                workflowBitmap.Dispose(); 
            } 
        }
        #endregion 

 		#region Protected Methods

		#region Overridden Methods handling UI events 
 		#region Drawing
 		protected override void OnPaint(PaintEventArgs e) 
		{ 
 			base.OnPaint(e);
 
			//We set the highest quality interpolation so that we do not loose the image quality
			GraphicsContainer graphicsState = e.Graphics.BeginContainer();
			e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
 			e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; 
			e.Graphics.CompositingQuality = CompositingQuality.HighQuality;
 
            bool takeWorkflowSnapShot = (this.viewPortBitmap == null || this.viewPortBitmap.Size != ViewPortSize); 
            if (takeWorkflowSnapShot)
            { 
                if (this.viewPortBitmap != null)
                    this.viewPortBitmap.Dispose();
                this.viewPortBitmap = new Bitmap(Math.Max(1, ViewPortSize.Width), Math.Max(1, ViewPortSize.Height), e.Graphics);
            } 

 			//Create viewport information and take the workflow snapshot before passing on the information to the active layout 
 			ViewPortData viewPortData = new ViewPortData(); 
			viewPortData.LogicalViewPort = ClientRectangleToLogical(new Rectangle(Point.Empty, ViewPortSize));
 			viewPortData.MemoryBitmap = this.viewPortBitmap; 
			viewPortData.Scaling = new SizeF(ScaleZoomFactor, ScaleZoomFactor);
			viewPortData.Translation = ScrollPosition;
			viewPortData.ShadowDepth = new Size(this.shadowDepth, this.shadowDepth);
 			viewPortData.ViewPortSize = ViewPortSize; 

			//capture the workflow onto in-memory bitmap 
            if (this.layoutEventHandler == null || takeWorkflowSnapShot) 
                WorkflowView.TakeWorkflowSnapShot(this, viewPortData);
 
 			//copy workflow from the bitmap onto corresponding pages on the screen
 			try
			{
 				this.activeLayout.OnPaintWorkflow(e, viewPortData); 
			}
			catch (Exception ex) 
			{ 
 				//If a layout throws an exception then we will not draw the layout
				// 
 				Debug.WriteLine(ex);
 			}

			//If any of the message filters throws an exception we continue to draw 
 			using (WorkflowMessageDispatchData dispatchData = new WorkflowMessageDispatchData(this, EventArgs.Empty))
			{ 
				foreach (WorkflowDesignerMessageFilter filter in dispatchData.Filters) 
				{
 					try 
					{
 						if (((IWorkflowDesignerMessageSink)filter).OnPaintWorkflowAdornments(e, ViewPortRectangle))
 							break;
					} 
 					catch (Exception ex)
					{ 
						//Ignore the filter throwing the exception and continue to function 
						Debug.WriteLine(ex);
 					} 
				}
 			}

 			e.Graphics.EndContainer(graphicsState); 

            e.Graphics.FillRectangle(SystemBrushes.Control, new Rectangle(Width - SystemInformation.VerticalScrollBarWidth, Height - SystemInformation.HorizontalScrollBarHeight, SystemInformation.VerticalScrollBarWidth, SystemInformation.HorizontalScrollBarHeight)); 
        } 

        protected virtual void OnZoomChanged() 
        {
            if (this.ZoomChanged != null)
                this.ZoomChanged(this, EventArgs.Empty);
        } 

        protected virtual void OnRootDesignerChanged() 
        { 
            if (this.RootDesignerChanged != null)
                this.RootDesignerChanged(this, EventArgs.Empty); 
        }
		#endregion

 		#region Mouse Events 
		protected override void OnMouseDown(MouseEventArgs e)
		{ 
			base.OnMouseDown(e); 

 			using (WorkflowMessageDispatchData dispatchData = new WorkflowMessageDispatchData(this, e)) 
			{
 				foreach (WorkflowDesignerMessageFilter filter in dispatchData.Filters)
 				{
					if (((IWorkflowDesignerMessageSink)filter).OnMouseDown(e)) 
 						break;
				} 
			} 
		}
 
 		protected override void OnMouseMove(MouseEventArgs e)
		{
 			base.OnMouseMove(e);
 
 			using (WorkflowMessageDispatchData dispatchData = new WorkflowMessageDispatchData(this, e))
			{ 
 				foreach (WorkflowDesignerMessageFilter filter in dispatchData.Filters) 
				{
					if (((IWorkflowDesignerMessageSink)filter).OnMouseMove(e)) 
						break;
 				}
			}
 		} 

 		protected override void OnMouseUp(MouseEventArgs e) 
		{ 
 			base.OnMouseUp(e);
 
			using (WorkflowMessageDispatchData dispatchData = new WorkflowMessageDispatchData(this, e))
			{
				foreach (WorkflowDesignerMessageFilter filter in dispatchData.Filters)
 				{ 
					if (((IWorkflowDesignerMessageSink)filter).OnMouseUp(e))
 						break; 
 				} 
			}
 		} 

		protected override void OnMouseDoubleClick(MouseEventArgs e)
		{
			base.OnMouseDoubleClick(e); 

 			using (WorkflowMessageDispatchData dispatchData = new WorkflowMessageDispatchData(this, e)) 
			{ 
 				foreach (WorkflowDesignerMessageFilter filter in dispatchData.Filters)
 				{ 
					if (((IWorkflowDesignerMessageSink)filter).OnMouseDoubleClick(e))
 						break;
				}
			} 
		}
 
 		protected override void OnMouseEnter(EventArgs e) 
		{
 			base.OnMouseEnter(e); 

 			Point clientPoint = PointToClient(Control.MousePosition);
			MouseEventArgs eventArgs = new MouseEventArgs(Control.MouseButtons, 1, clientPoint.X, clientPoint.Y, 0);
 
 			using (WorkflowMessageDispatchData dispatchData = new WorkflowMessageDispatchData(this, eventArgs))
			{ 
				foreach (WorkflowDesignerMessageFilter filter in dispatchData.Filters) 
				{
 					if (((IWorkflowDesignerMessageSink)filter).OnMouseEnter(eventArgs)) 
						break;
 				}
 			}
		} 

 		protected override void OnMouseHover(EventArgs e) 
		{ 
			base.OnMouseHover(e);
 
			Point clientPoint = PointToClient(Control.MousePosition);
 			MouseEventArgs eventArgs = new MouseEventArgs(Control.MouseButtons, 1, clientPoint.X, clientPoint.Y, 0);

			using (WorkflowMessageDispatchData dispatchData = new WorkflowMessageDispatchData(this, eventArgs)) 
 			{
 				foreach (WorkflowDesignerMessageFilter filter in dispatchData.Filters) 
				{ 
 					if (((IWorkflowDesignerMessageSink)filter).OnMouseHover(eventArgs))
						break; 
				}
			}
 		}
 
		protected override void OnMouseLeave(EventArgs e)
 		{ 
 			base.OnMouseLeave(e); 

			using (WorkflowMessageDispatchData dispatchData = new WorkflowMessageDispatchData(this, EventArgs.Empty)) 
 			{
				foreach (WorkflowDesignerMessageFilter filter in dispatchData.Filters)
				{
					if (((IWorkflowDesignerMessageSink)filter).OnMouseLeave()) 
 						break;
				} 
 			} 
 		}
 
		protected override void OnMouseCaptureChanged(EventArgs e)
 		{
			base.OnMouseCaptureChanged(e);
 
			using (WorkflowMessageDispatchData dispatchData = new WorkflowMessageDispatchData(this, EventArgs.Empty))
			{ 
 				foreach (WorkflowDesignerMessageFilter filter in dispatchData.Filters) 
				{
 					if (((IWorkflowDesignerMessageSink)filter).OnMouseCaptureChanged()) 
 						break;
				}
 			}
		} 

		protected override void OnMouseWheel(MouseEventArgs e) 
		{ 
 			base.OnMouseWheel(e);
 
			using (WorkflowMessageDispatchData dispatchData = new WorkflowMessageDispatchData(this, e))
 			{
 				foreach (WorkflowDesignerMessageFilter filter in dispatchData.Filters)
				{ 
 					if (((IWorkflowDesignerMessageSink)filter).OnMouseWheel(e))
						break; 
				} 
			}
 		} 
		#endregion

 		#region Keyboard Events
 		protected override void OnKeyDown(KeyEventArgs e) 
		{
 			using (WorkflowMessageDispatchData dispatchData = new WorkflowMessageDispatchData(this, e)) 
			{ 
				foreach (WorkflowDesignerMessageFilter filter in dispatchData.Filters)
				{ 
 					if (((IWorkflowDesignerMessageSink)filter).OnKeyDown(e))
						break;
 				}
 			} 

			if (!e.Handled) 
 				base.OnKeyDown(e); 
		}
 
		protected override void OnKeyUp(KeyEventArgs e)
		{
 			using (WorkflowMessageDispatchData dispatchData = new WorkflowMessageDispatchData(this, e))
			{ 
 				foreach (WorkflowDesignerMessageFilter filter in dispatchData.Filters)
 				{ 
					if (((IWorkflowDesignerMessageSink)filter).OnKeyUp(e)) 
 						break;
				} 
			}

			if (!e.Handled)
 				base.OnKeyUp(e); 
		}
 		#endregion 
 
 		#region Layouting Events
		protected override void OnLayout(LayoutEventArgs levent) 
 		{
			base.OnLayout(levent);

			ScrollBar hScrollBar = HScrollBar; 
			ScrollBar vScrollBar = VScrollBar;
 
            if (Controls.Contains(hScrollBar)) 
                hScrollBar.Bounds = new Rectangle(0, Math.Max(0, Height - SystemInformation.HorizontalScrollBarHeight), Math.Max(Width - ((vScrollBar.Visible) ? SystemInformation.VerticalScrollBarWidth : 0), 0), SystemInformation.HorizontalScrollBarHeight);
 
 			if (Controls.Contains(vScrollBar))
                vScrollBar.Bounds = new Rectangle(Math.Max(0, Width - SystemInformation.VerticalScrollBarWidth), 0, SystemInformation.VerticalScrollBarWidth, Math.Max(Height - ((hScrollBar.Visible) ? SystemInformation.HorizontalScrollBarHeight : 0), 0));

            if (this.toolContainer != null) 
            {
                this.toolContainer.Location = new Point(Width - this.toolContainer.Width, 0); 
                this.toolContainer.Height = Height - ((hScrollBar.Visible) ? hScrollBar.Height :0); 
            }
 
			using (WorkflowMessageDispatchData dispatchData = new WorkflowMessageDispatchData(this, levent))
 			{
 				foreach (WorkflowDesignerMessageFilter filter in dispatchData.Filters)
					((IWorkflowDesignerMessageSink)filter).OnLayout(levent); 
 			}
 
			//Layout the designers 
			using (Graphics graphics = CreateGraphics())
			{ 
 				this.activeLayout.Update(graphics, WorkflowLayout.LayoutUpdateReason.LayoutChanged);

				if (this.rootDesigner != null)
 					this.rootDesigner.Location = this.activeLayout.RootDesignerAlignment; 
 			}
 
			//Update the scroll range and redraw 
 			UpdateScrollRange();
			InvalidateClientRectangle(Rectangle.Empty); 
		}
		#endregion

 		#region DragDrop Events 
		protected override void OnDragEnter(DragEventArgs dragEventArgs)
 		{ 
 			base.OnDragEnter(dragEventArgs); 

            this.dragDropInProgress = true; 

			using (WorkflowMessageDispatchData dispatchData = new WorkflowMessageDispatchData(this, dragEventArgs))
 			{
				foreach (WorkflowDesignerMessageFilter filter in dispatchData.Filters) 
				{
					if (((IWorkflowDesignerMessageSink)filter).OnDragEnter(dragEventArgs)) 
 						break; 
				}
 			} 
 		}

		protected override void OnDragOver(DragEventArgs dragEventArgs)
 		{ 
			base.OnDragOver(dragEventArgs);
 
			using (WorkflowMessageDispatchData dispatchData = new WorkflowMessageDispatchData(this, dragEventArgs)) 
			{
 				foreach (WorkflowDesignerMessageFilter filter in dispatchData.Filters) 
				{
 					if (((IWorkflowDesignerMessageSink)filter).OnDragOver(dragEventArgs))
 						break;
				} 
 			}
		} 
 
		protected override void OnDragLeave(EventArgs e)
		{ 
 			base.OnDragLeave(e);

			using (WorkflowMessageDispatchData dispatchData = new WorkflowMessageDispatchData(this, EventArgs.Empty))
 			{ 
 				foreach (WorkflowDesignerMessageFilter filter in dispatchData.Filters)
				{ 
 					if (((IWorkflowDesignerMessageSink)filter).OnDragLeave()) 
						break;
				} 
			}

            this.dragDropInProgress = false;
        } 

 		protected override void OnDragDrop(DragEventArgs dragEventArgs) 
		{ 
 			base.OnDragDrop(dragEventArgs);
 
 			using (WorkflowMessageDispatchData dispatchData = new WorkflowMessageDispatchData(this, dragEventArgs))
			{
 				foreach (WorkflowDesignerMessageFilter filter in dispatchData.Filters)
				{ 
					if (((IWorkflowDesignerMessageSink)filter).OnDragDrop(dragEventArgs))
						break; 
 				} 
			}
 
            this.dragDropInProgress = false;
        }

 		protected override void OnGiveFeedback(GiveFeedbackEventArgs gfbevent) 
 		{
			base.OnGiveFeedback(gfbevent); 
 
 			using (WorkflowMessageDispatchData dispatchData = new WorkflowMessageDispatchData(this, gfbevent))
			{ 
				foreach (WorkflowDesignerMessageFilter filter in dispatchData.Filters)
				{
 					if (((IWorkflowDesignerMessageSink)filter).OnGiveFeedback(gfbevent))
						break; 
 				}
 			} 
		} 

 		protected override void OnQueryContinueDrag(QueryContinueDragEventArgs qcdevent) 
		{
			base.OnQueryContinueDrag(qcdevent);

			using (WorkflowMessageDispatchData dispatchData = new WorkflowMessageDispatchData(this, qcdevent)) 
 			{
				foreach (WorkflowDesignerMessageFilter filter in dispatchData.Filters) 
 				{ 
 					if (((IWorkflowDesignerMessageSink)filter).OnQueryContinueDrag(qcdevent))
						break; 
 				}
			}
		}
		#endregion 

 		#region General Events 
		//Handle context menus here reason being it can come from mouse r button click 
 		//or shift+F10, or there might be other keys too
 		//We need to handle the WndProc and not the OnNotifyMessage because we need to set 
		//the m.Result to handled (IntPtr.Zero) and dont let the base class see the message at all
 		//see WinOE #787 "The keyboard "key" to launch the context menu launches the menu at 0,0"
		[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
		[UIPermission(SecurityAction.Assert, Window = UIPermissionWindow.AllWindows)] 
		protected override void WndProc(ref Message m)
 		{ 
			using (WorkflowMessageDispatchData dispatchData = new WorkflowMessageDispatchData(this, EventArgs.Empty)) 
 			{
 				foreach (WorkflowDesignerMessageFilter filter in dispatchData.Filters) 
				{
 					if (((IWorkflowDesignerMessageSink)filter).ProcessMessage(m))
						break;
				} 

				const int WM_CONTEXTMENU = 0x007B; 
 				if (m.Msg == WM_CONTEXTMENU) 
				{
 					int LParam = (int)m.LParam; 
 					Point location = (LParam != -1) ? new Point(LParam) : Control.MousePosition;

					foreach (WorkflowDesignerMessageFilter filter in dispatchData.Filters)
 					{ 
						if (((IWorkflowDesignerMessageSink)filter).OnShowContextMenu(location))
							break; 
					} 

 					//mark the message handled 
					m.Result = IntPtr.Zero;
 					//dont pass the message to the base but return immediatly
 					return;
				} 
 			}
 
			if (this.workflowToolTip != null && m.Msg == NativeMethods.WM_NOTIFY) 
				this.workflowToolTip.RelayParentNotify(ref m);
 
			try
 			{
				if (m.Result == IntPtr.Zero)
 					base.WndProc(ref m); 
 			}
			catch (Exception e) 
 			{ 
                if (e != CheckoutException.Canceled)
                    DesignerHelpers.ShowError(this, e); 
			}
		}

		protected override void OnControlAdded(ControlEventArgs e) 
 		{
			if (e.Control != VScrollBar && e.Control != HScrollBar && e.Control != this.toolContainer) 
 				throw new InvalidOperationException(SR.GetString(SR.Error_InsertingChildControls)); 
 		}
 
		protected override AccessibleObject CreateAccessibilityInstance()
 		{
			return new WorkflowViewAccessibleObject(this);
		} 
		#endregion
 
 		#endregion 

		#endregion 

 		#region Private Methods
        private void OnWorkflowIdle(object sender, EventArgs e)
        { 
            if (this.idleEventListeners != null)
                this.idleEventListeners(this, e); 
        } 

 		private void UpdateLayout() 
		{
 			if (this.layoutEventHandler != null)
			{
				PerformLayout(true); 
				InvalidateClientRectangle(Rectangle.Empty);
 			} 
		} 

 		internal void OnCommandKey(KeyEventArgs e) 
 		{
			this.OnKeyDown(e);
            this.OnKeyUp(e);
 		} 

		private void OnSelectionChanged(object sender, EventArgs e) 
		{ 
			if (this.commandSet != null)
 				this.commandSet.UpdateCommandSet(); 

			//Make sure that the ensure visible also works when the component is selected
 			//from property browser dropdown
 			//Make sure that when there is a selection change using the property browser 
			//drop down we make sure that the designer associated with component selected by the user in the dropdown
 			//is made visible. 
			//To enable this functionality please note that selection change is not a good event as it will get 
			//fired in multiple cases, instead we should add a event in extended ui service which will do this and move
			//the following code in the event handler of that event 
 			//Ref Bug#3925

            if (RootDesigner != null && RootDesigner.Activity != null)
            { 
                ISelectionService selectionService = GetService(typeof(ISelectionService)) as ISelectionService;
                if (selectionService != null && selectionService.GetComponentSelected(RootDesigner.Activity)) 
                { 
                    IHelpService helpService = GetService(typeof(IHelpService)) as IHelpService;
                    if (helpService != null) 
                        helpService.AddContextAttribute("Keyword", RootDesigner.Activity.GetType().FullName, HelpKeywordType.F1Keyword);
                }
            }
		} 

 		private void OnPerformLayout(object sender, EventArgs e) 
 		{ 
			if (this.layoutEventHandler != null)
 			{ 
				Idle -= this.layoutEventHandler;
				this.layoutEventHandler = null;

				base.PerformLayout(); 
 			}
		} 
 
        //Gets the snapshot of the entire workflow
        private Bitmap TakeWorkflowSnapShot() 
        {
            Bitmap bitmap = null;
            ActivityDesigner rootDesigner = RootDesigner;
            if (rootDesigner != null) 
            {
                using (Graphics graphics = CreateGraphics()) 
                { 
                    ViewPortData viewPortData = new ViewPortData();
                    viewPortData.LogicalViewPort = new Rectangle(Point.Empty, new Size(rootDesigner.Bounds.Width + 2 * DefaultWorkflowLayout.Separator.Width, rootDesigner.Bounds.Height + 2 * DefaultWorkflowLayout.Separator.Height)); 
                    viewPortData.MemoryBitmap = new Bitmap(viewPortData.LogicalViewPort.Width, viewPortData.LogicalViewPort.Height, graphics);
                    viewPortData.Scaling = new SizeF(1, 1);
                    viewPortData.Translation = Point.Empty;
                    viewPortData.ShadowDepth = new Size(0, 0); 
                    viewPortData.ViewPortSize = viewPortData.LogicalViewPort.Size;
                    TakeWorkflowSnapShot(this, viewPortData); 
                    bitmap = viewPortData.MemoryBitmap; 
                }
            } 

            return bitmap;
        }
 
 		//This function will give snapshot of what is drawn on the screen at any point of time
 		//It will scale and translate the designers and drawing based on the viewport data 
		//We need this function in OnPaint and taking snapshot of magnifier bitmap 
 		//At the end of this function; the ViewPortData.MemoryBitmap will contain the bitmap of the
		//workflow to be drawn as per layout 
		internal static void TakeWorkflowSnapShot(WorkflowView workflowView, ViewPortData viewPortData)
		{
 			//Get the drawing canvas
			Bitmap memoryBitmap = viewPortData.MemoryBitmap; 
 			Debug.Assert(memoryBitmap != null);
 
 			using (Graphics viewPortGraphics = Graphics.FromImage(memoryBitmap)) 
			{
 				//We set the highest quality interpolation so that we do not loose the image quality 
				viewPortGraphics.SmoothingMode = SmoothingMode.HighQuality;
				viewPortGraphics.InterpolationMode = InterpolationMode.HighQualityBicubic;

                using (PaintEventArgs eventArgs = new PaintEventArgs(viewPortGraphics, viewPortData.LogicalViewPort)) 
                {
                    workflowView.ActiveLayout.OnPaint(eventArgs, viewPortData); 
                } 

				//Create the scaling matrix 
 				Matrix transformationMatrix = new Matrix();
				transformationMatrix.Scale(viewPortData.Scaling.Width, viewPortData.Scaling.Height, MatrixOrder.Prepend);

 				//When we draw on the viewport we draw in scaled and translated. 
 				//So that we minimize the calls to DrawImage
				//Make sure that we scale down the logical view port origin in order to take care of scaling factor 
 				//Before we select the transform factor we make sure that logicalviewport origin is scaled down 
				Point[] logicalViewPortOrigin = new Point[] { viewPortData.LogicalViewPort.Location };
				transformationMatrix.TransformPoints(logicalViewPortOrigin); 

				//For performance improvement and to eliminate one extra DrawImage...we draw the designers on the viewport
 				//bitmap with visual depth consideration
				transformationMatrix.Translate(-logicalViewPortOrigin[0].X + viewPortData.ShadowDepth.Width, -logicalViewPortOrigin[0].Y + viewPortData.ShadowDepth.Height, MatrixOrder.Append); 

 				//Select the transform into viewport graphics. 
 				//Viewport bitmap has the scaled and translated designers which we then map to 
				//the actual graphics based on page layout
 				viewPortGraphics.Transform = transformationMatrix; 

				//Draw the designers on bitmap
				if (workflowView.RootDesigner != null)
				{ 
 					using (Region clipRegion = new Region())
					using (GraphicsPath designerPath = ActivityDesignerPaint.GetDesignerPath(workflowView.RootDesigner, false)) 
 					{ 
 						Region oldRegion = viewPortGraphics.Clip;
 
						//First draw the grid and rectangle with the designer clip region
 						clipRegion.MakeEmpty();
						clipRegion.Union(designerPath);
						viewPortGraphics.Clip = clipRegion; 
						AmbientTheme ambientTheme = WorkflowTheme.CurrentTheme.AmbientTheme;
 						viewPortGraphics.FillRectangle(ambientTheme.BackgroundBrush, workflowView.RootDesigner.Bounds); 
						if (ambientTheme.ShowGrid) 
 							ActivityDesignerPaint.DrawGrid(viewPortGraphics, workflowView.RootDesigner.Bounds);
 						viewPortGraphics.Clip = oldRegion; 

						//Then draw the root with clip region extended
 						try
						{ 
                            using (PaintEventArgs paintEventArgs = new PaintEventArgs(viewPortGraphics, viewPortData.LogicalViewPort))
                            { 
                                ((IWorkflowDesignerMessageSink)workflowView.RootDesigner).OnPaint(paintEventArgs, viewPortData.LogicalViewPort); 
                            }
						} 
						catch (Exception e)
 						{
							//Eat the exception thrown in draw
 							Debug.WriteLine(e); 
 						}
					} 
 				} 

				//Draw all the filters 


                using (PaintEventArgs paintArgs = new PaintEventArgs(viewPortGraphics, workflowView.RootDesigner.Bounds))
                { 
				    using (WorkflowMessageDispatchData dispatchData = new WorkflowMessageDispatchData(workflowView, EventArgs.Empty))
				    { 
                        foreach (WorkflowDesignerMessageFilter filter in dispatchData.Filters) 
                        {
                            try 
                            {
                                if (((IWorkflowDesignerMessageSink)filter).OnPaint(paintArgs, viewPortData.LogicalViewPort))
                                    break;
                            } 
                            catch (Exception e)
                            { 
                                Debug.WriteLine(e); 
                            }
                        } 
                    }
 				}

				viewPortGraphics.Transform = new Matrix(); 

 				//Now that we have a bitmap which is bit offseted based visual depth we need to take copy of it 
 				//This is done so as to avoid expensive DrawImage call, what I am assuming here is that time it 
				//will take to create a new bitmap from an existing one is less expensive in terms of speed than space
 				//As you just need to copy bitmap bits in memory than to perform expesive Image Drawing operation 
				if (!viewPortData.ShadowDepth.IsEmpty)
				{
					Bitmap temporaryBitmap = new Bitmap(memoryBitmap);
 
 					//THEMETODO: WE JUST NEED TO GRAYSCALE THIS, RATHER THAN DRAWING A SHADOW
					//Now that we have taken a copy we will draw over the existing bitmap so that we can make it as shadow bitmap 
 					using (Brush shadowDepthBrush = new SolidBrush(Color.FromArgb(220, Color.White))) 
                        viewPortGraphics.FillRectangle(shadowDepthBrush, new Rectangle(Point.Empty, new Size(memoryBitmap.Size.Width - viewPortData.ShadowDepth.Width - 1, memoryBitmap.Size.Height - viewPortData.ShadowDepth.Height - 1)));
 
 					//Now make sure that we draw the image from the temporary bitmap with white color set as transparent
					//so that we achive the 3D effect
 					//Make sure that we take into consideration the transparency key
					ImageAttributes transparentColorKey = new ImageAttributes(); 
					transparentColorKey.SetColorKey(viewPortData.TransparentColor, viewPortData.TransparentColor, ColorAdjustType.Default);
					transparentColorKey.SetColorKey(viewPortData.TransparentColor, viewPortData.TransparentColor, ColorAdjustType.Bitmap); 
 					viewPortGraphics.DrawImage(temporaryBitmap, new Rectangle(-viewPortData.ShadowDepth.Width, -viewPortData.ShadowDepth.Height, memoryBitmap.Width, memoryBitmap.Height), 0, 0, memoryBitmap.Width, memoryBitmap.Height, GraphicsUnit.Pixel, transparentColorKey); 

					//Now dispose the temporary bitmap 
 					temporaryBitmap.Dispose();
 				}
			}
 		} 

		internal void OnThemeChange(object sender, EventArgs e) 
		{ 
			ShadowDepth = WorkflowTheme.CurrentTheme.AmbientTheme.ShadowDepth;
 
 			using (WorkflowMessageDispatchData dispatchData = new WorkflowMessageDispatchData(this, EventArgs.Empty))
			{
 				foreach (WorkflowDesignerMessageFilter filter in dispatchData.Filters)
 				{ 
					try
 					{ 
						((IWorkflowDesignerMessageSink)filter).OnThemeChange(); 
					}
					catch (Exception ex) 
 					{
						Debug.WriteLine(ex);
 					}
 				} 
			}
 
 			base.PerformLayout(); 
		}
 
		private void OnEnsureVisible(object sender, EventArgs e)
		{
            if (this.ensureVisibleEventHandler != null)
            { 
                Idle -= this.ensureVisibleEventHandler;
                this.ensureVisibleEventHandler = null; 
            } 

            ISelectionService selectionService = (ISelectionService)GetService(typeof(ISelectionService)); 
            if (selectionService != null && selectionService.SelectionCount > 0)
            {
                //We do not want to regenerate a layout event in ensure visible
                ArrayList selectedComponents = new ArrayList(selectionService.GetSelectedComponents()); 
                for (int i = selectedComponents.Count - 1; i >= 0; i--)
                { 
                    Rectangle rectangleToMakeVisible = Rectangle.Empty; 
                    if (selectedComponents[i] is Activity)
                    { 
                        ActivityDesigner activityDesigner = ActivityDesigner.GetDesigner(selectedComponents[i] as Activity);
                        if (activityDesigner != null)
                        {
                            rectangleToMakeVisible = activityDesigner.Bounds; 
                            rectangleToMakeVisible.Inflate(WorkflowTheme.CurrentTheme.AmbientTheme.SelectionSize);
                            rectangleToMakeVisible.Inflate(WorkflowTheme.CurrentTheme.AmbientTheme.SelectionSize); 
                        } 
                    }
                    else if (selectedComponents[i] is HitTestInfo) 
                    {
                        rectangleToMakeVisible = ((HitTestInfo)selectedComponents[i]).Bounds;
                    }
 
                    if (!rectangleToMakeVisible.IsEmpty)
                        EnsureVisible(rectangleToMakeVisible); 
                } 
            }
        } 

        private void EnsureVisible(Rectangle rect)
        {
            Rectangle clientRectangle = ClientRectangleToLogical(new Rectangle(Point.Empty, ViewPortSize)); 

            if (!clientRectangle.Contains(rect.Location) || !clientRectangle.Contains(new Point(rect.Right, rect.Bottom))) 
            { 
                Size scrollDelta = new Size();
                if (!clientRectangle.Contains(new Point(rect.Left, clientRectangle.Top)) || !clientRectangle.Contains(new Point(rect.Right, clientRectangle.Top))) 
                {
                    if (rect.Width > clientRectangle.Width)
                        scrollDelta.Width = (rect.Left + rect.Width / 2) - (clientRectangle.Left + clientRectangle.Width / 2);
                    else if (rect.Left < clientRectangle.Left) 
                        scrollDelta.Width = (rect.Left - clientRectangle.Left);
                    else 
                        scrollDelta.Width = (rect.Right - clientRectangle.Right); 
                }
 
                if (!clientRectangle.Contains(new Point(clientRectangle.Left, rect.Top)) || !clientRectangle.Contains(new Point(clientRectangle.Left, rect.Bottom)))
                {
                    if ((rect.Top < clientRectangle.Top) || (rect.Height > clientRectangle.Height))
                        scrollDelta.Height = (rect.Top - clientRectangle.Top); 
                    else
                        scrollDelta.Height = rect.Bottom - clientRectangle.Bottom; 
                } 

                scrollDelta = LogicalSizeToClient(scrollDelta); 
                Point scrollPosition = ScrollPosition;
                ScrollPosition = new Point(scrollPosition.X + scrollDelta.Width, scrollPosition.Y + scrollDelta.Height);
            }
        } 

 		private void OnScroll(object sender, EventArgs e) 
		{ 
 			//Lets speedup the scrolling logic
 			InvalidateClientRectangle(Rectangle.Empty); 

            ScrollBar scrollBar = sender as ScrollBar;
            if (scrollBar != null)
            { 
                using (WorkflowMessageDispatchData dispatchData = new WorkflowMessageDispatchData(this, e))
                { 
                    foreach (WorkflowDesignerMessageFilter filter in dispatchData.Filters) 
                    {
                        try 
                        {
                            ((IWorkflowDesignerMessageSink)filter).OnScroll(scrollBar, scrollBar.Value);
                        }
                        catch (Exception ex) 
                        {
                            Debug.WriteLine(ex); 
                        } 
                    }
                } 
            }
        }

		private void UpdateScrollRange() 
 		{
			if (ViewPortSize.Width < 0 || ViewPortSize.Height < 0) 
				return; 

			Size currentSize = ViewPortSize; 
 			Size maximumScrollSize = LogicalSizeToClient(this.activeLayout.Extent);
			Size largeChangeSize = new Size(Math.Min(maximumScrollSize.Width, currentSize.Width), Math.Min(maximumScrollSize.Height, currentSize.Height));

 			if (hScrollBar.Maximum != maximumScrollSize.Width) 
 				hScrollBar.Maximum = maximumScrollSize.Width;
			if (vScrollBar.Maximum != maximumScrollSize.Height) 
 				vScrollBar.Maximum = maximumScrollSize.Height; 

			if (hScrollBar.LargeChange != largeChangeSize.Width) 
			{
				hScrollBar.SmallChange = largeChangeSize.Width / 15;
 				hScrollBar.LargeChange = largeChangeSize.Width + 1;
			} 
 			if (vScrollBar.LargeChange != largeChangeSize.Height)
 			{ 
				vScrollBar.SmallChange = largeChangeSize.Height / 15; 
 				vScrollBar.LargeChange = largeChangeSize.Height + 1;
			} 

			int xMaxScrollPos = maximumScrollSize.Width - hScrollBar.LargeChange;
			xMaxScrollPos = (xMaxScrollPos < 0) ? 0 : xMaxScrollPos;
 			if (hScrollBar.Value > xMaxScrollPos) 
				hScrollBar.Value = xMaxScrollPos;
 
 			int yMaxScrollPos = maximumScrollSize.Height - vScrollBar.LargeChange; 
 			yMaxScrollPos = (yMaxScrollPos < 0) ? 0 : yMaxScrollPos;
			if (vScrollBar.Value > yMaxScrollPos) 
 				vScrollBar.Value = yMaxScrollPos;

			RefreshDynamicAction();
 
            bool hScrollBarVisible = hScrollBar.Visible;
            if (Controls.Contains(hScrollBar)) 
                hScrollBar.Visible = (hScrollBar.Maximum > currentSize.Width); 

            bool vScrollBarVisible = vScrollBar.Visible; 
            if (Controls.Contains(vScrollBar))
                vScrollBar.Visible = (vScrollBar.Maximum > currentSize.Height);

            if (hScrollBarVisible != hScrollBar.Visible || vScrollBar.Visible != vScrollBarVisible) 
            {
                base.PerformLayout(); 
                Refresh(); 
            }
        } 

		private DynamicAction CreateDynamicAction()
		{
 			DynamicAction fitAllAction = new DynamicAction(); 
			fitAllAction.ButtonSize = DynamicAction.ButtonSizes.Large;
 			fitAllAction.Doc----gnment = DesignerContentAlignment.BottomRight; 
 			fitAllAction.DockMargin = new Size(5, 5); 

			ActionButton fitallButton = new ActionButton(new Image[] { DR.GetImage(DR.FitToScreen) as Bitmap }); 
 			fitallButton.StateChanged += new EventHandler(OnFitToScreen);
			fitAllAction.Buttons.Add(fitallButton);

			return fitAllAction; 
		}
 
 		private void RefreshDynamicAction() 
		{
 			DynamicActionMessageFilter dynamicActionFilter = GetService(typeof(DynamicActionMessageFilter)) as DynamicActionMessageFilter; 
 			if (dynamicActionFilter == null || this.fitAllAction == null)
				return;

 			if (HScrollBar.Maximum > ViewPortSize.Width || VScrollBar.Maximum > ViewPortSize.Height) 
			{
				//This means we need to show the zoomin icon 
                this.fitAllAction.Buttons[0].Description = DR.GetString(DR.FitToScreenDescription); 
				this.fitAllAction.Buttons[0].StateImages = new Bitmap[] { DR.GetImage(DR.FitToScreen) as Bitmap };
 				dynamicActionFilter.AddAction(this.fitAllAction); 
			}
 			else if (Zoom != 100)
 			{
				//We need to show zoomout icon 
                this.fitAllAction.Buttons[0].Description = DR.GetString(DR.FitToWorkflowDescription);
 				this.fitAllAction.Buttons[0].StateImages = new Bitmap[] { DR.GetImage(DR.FitToWorkflow) as Bitmap }; 
				dynamicActionFilter.AddAction(this.fitAllAction); 
			}
			else 
 			{
				//In neither case we remove the action
 				dynamicActionFilter.RemoveAction(this.fitAllAction);
 				this.fitAllAction.Buttons[0].State = ActionButton.States.Normal; 
			}
 		} 
 
		private void OnFitToScreen(object sender, EventArgs e)
		{ 
			ActionButton fitallButton = sender as ActionButton;
 			if (fitallButton == null || fitallButton.State != ActionButton.States.Pressed)
				return;
 
 			if (HScrollBar.Maximum > ViewPortSize.Width || VScrollBar.Maximum > ViewPortSize.Height)
                FitToScreenSize(); 
            else if (Zoom != 100) 
                FitToWorkflowSize();
 		} 

		private void OnTabChange(object sender, TabSelectionChangeEventArgs e)
 		{
			if (e.CurrentItem.Identifier == (int)TabButtonIds.MultiPage || 
					e.CurrentItem.Identifier == (int)TabButtonIds.Zoom ||
					e.CurrentItem.Identifier == (int)TabButtonIds.Pan) 
 			{ 
				Rectangle buttonRect = e.SelectedTabBounds;
 				CommandID menuID = null; 

 				if (e.CurrentItem.Identifier == (int)TabButtonIds.MultiPage)
					menuID = WorkflowMenuCommands.PageLayoutMenu;
 				else if (e.CurrentItem.Identifier == (int)TabButtonIds.Zoom) 
					menuID = WorkflowMenuCommands.ZoomMenu;
				else 
					menuID = WorkflowMenuCommands.PanMenu; 

 				IMenuCommandService menuCommandService = (IMenuCommandService)GetService(typeof(IMenuCommandService)); 
				if (menuCommandService != null)
 					menuCommandService.ShowContextMenu(menuID, buttonRect.Right, buttonRect.Top);
 			}
		} 

 		private void EnsureScrollBars(HScrollBar newHorizScrollBar, VScrollBar newVertScrollBar) 
		{ 
            try
            { 
                SuspendLayout();

                if (this.hScrollBar != newHorizScrollBar)
                { 
                    if (this.hScrollBar != null)
                    { 
                        this.hScrollBar.ValueChanged -= new EventHandler(OnScroll); 
                        if (Controls.Contains(this.hScrollBar))
                            Controls.Remove(this.hScrollBar); 
                    }

                    this.hScrollBar = newHorizScrollBar;
                    if (this.hScrollBar.Parent == null) 
                    {
                        this.hScrollBar.TabStop = false; 
                        Controls.Add(this.hScrollBar); 
                    }
                } 

                if (this.vScrollBar != newVertScrollBar)
                {
                    if (this.vScrollBar != null) 
                    {
                        this.vScrollBar.ValueChanged -= new EventHandler(OnScroll); 
                        if (Controls.Contains(this.vScrollBar)) 
                            Controls.Remove(this.vScrollBar);
                    } 

                    this.vScrollBar = newVertScrollBar;
                    if (this.vScrollBar.Parent == null)
                    { 
                        this.vScrollBar.TabStop = false;
                        Controls.Add(this.vScrollBar); 
                    } 
                }
 
                this.hScrollBar.ValueChanged += new EventHandler(OnScroll);
                this.vScrollBar.ValueChanged += new EventHandler(OnScroll);
            }
            finally 
            {
                ResumeLayout(true); 
            } 
		}
 
        private void PopulateMessageFilters(bool stockFilters)
        {
            IList filters = (stockFilters) ? this.stockMessageFilters : this.customMessageFilters;
            Debug.Assert(filters.Count == 0); 

            if (stockFilters) 
            { 
                filters.Add(new GlyphManager());
                filters.Add(new WindowManager()); 
            }
            else
            {
                Debug.Assert(this.rootDesigner != null); 

                if (Capture) 
                    Capture = false; 

                IList customFilters = ((IWorkflowRootDesigner)this.rootDesigner).MessageFilters; 
                foreach (WorkflowDesignerMessageFilter filter in customFilters)
                    filters.Add(filter);
            }
 
            foreach (WorkflowDesignerMessageFilter filter in filters)
                filter.SetParentView(this); 
        } 

        private void DisposeMessageFilters(bool stockFilters) 
        {
            List filters = (stockFilters) ? this.stockMessageFilters : this.customMessageFilters;

            //We dispose all the message filters, this is done by copying because some of the 
            //message filters might remove other dependent messagefilters
            ArrayList clonedFilterList = new ArrayList(filters.ToArray()); 
            foreach (WorkflowDesignerMessageFilter filter in clonedFilterList) 
                ((IDisposable)filter).Dispose();
            filters.Clear(); 
        }
        #endregion

		#region Coordinate Transformation Functions 
 		public void InvalidateClientRectangle(Rectangle clientRectangle)
		{ 
 			if (this.layoutEventHandler == null) 
 			{
				if (!clientRectangle.IsEmpty) 
 				{
					//Inflate the invalidated rectangle. When zoom factor is less than 1; there is a loss of precision
					clientRectangle.Inflate(1, 1);
					base.Invalidate(clientRectangle); 
 				}
				else 
 				{ 
 					base.Invalidate();
				} 
 			}
		}

		public void InvalidateLogicalRectangle(Rectangle logicalRectangle) 
		{
 			InvalidateClientRectangle(LogicalRectangleToClient(logicalRectangle)); 
		} 

 		public Point LogicalPointToScreen(Point logicalPoint) 
 		{
			return PointToScreen(LogicalPointToClient(logicalPoint));
 		}
 
		public Point ScreenPointToLogical(Point screenPoint)
		{ 
			return ClientPointToLogical(PointToClient(screenPoint)); 
 		}
 
		public Point LogicalPointToClient(Point logicalPoint)
 		{
 			return LogicalPointToClient(logicalPoint, true);
		} 

 		public Point ClientPointToLogical(Point clientPoint) 
		{ 
			return ClientPointToLogical(clientPoint, true);
		} 

 		public Size LogicalSizeToClient(Size logicalSize)
		{
 			Point[] points = new Point[] { new Point(logicalSize) }; 

 			//Scale the point 
			Matrix scalingMatrix = new Matrix(); 
 			scalingMatrix.Scale(ScaleZoomFactor, ScaleZoomFactor);
			scalingMatrix.TransformPoints(points); 
			return new Size(points[0]);
		}

 		public Size ClientSizeToLogical(Size clientSize) 
		{
 			//Scale the size, size scaling does not require translate 
 			Point[] points = new Point[] { new Point(clientSize) }; 
			Matrix scalingMatrix = new Matrix();
 			scalingMatrix.Scale(ScaleZoomFactor, ScaleZoomFactor); 
			scalingMatrix.Invert();
			scalingMatrix.TransformPoints(points);
			scalingMatrix.Invert();
 			return new Size(points[0]); 
		}
 
 		public Rectangle LogicalRectangleToClient(Rectangle rectangle) 
 		{
            Debug.Assert(this.activeLayout != null, "active layout should not be null"); 
            Rectangle clientViewPort = (this.activeLayout != null) ? this.activeLayout.MapOutRectangleFromLayout(rectangle) : rectangle;
			//
 
 
			return new Rectangle(LogicalPointToClient(clientViewPort.Location, false), LogicalSizeToClient(clientViewPort.Size));
		} 
 
 		public Rectangle ClientRectangleToLogical(Rectangle rectangle)
		{ 
 			//We translate the client viewport to logical view port.
 			//To do this we first get the view port rectangle scale it down
			//then translate it to area of page we would be viewing
 			Rectangle scaledLogicalViewPort = new Rectangle(ClientPointToLogical(rectangle.Location, false), ClientSizeToLogical(rectangle.Size)); 
			return this.activeLayout.MapInRectangleToLayout(scaledLogicalViewPort);
		} 
 
		internal bool IsClientPointInActiveLayout(Point clientPoint)
 		{ 
			Point logicalPoint = ClientPointToLogical(clientPoint, false);
 			return this.activeLayout.IsCoOrdInLayout(logicalPoint);
 		}
 
		/*
 		* Client scale is when we transform the coordinate based on zoom and translate it based on scrolling position and layout 
		* Logical scale is when we transform the coordinate and map it to a flat coordinate system which goes from 0,0 to m,n 
		* We also consider the ActiveLayout to transform the coordinates.
		*/ 
 		private Point LogicalPointToClient(Point point, bool mapToLayout)
		{
 			if (mapToLayout)
 				point = this.activeLayout.MapOutCoOrdFromLayout(point); 

			//Scale the point 
 			Matrix scalingMatrix = new Matrix(); 
			scalingMatrix.Scale(ScaleZoomFactor, ScaleZoomFactor);
			Point[] points = new Point[] { point }; 
			scalingMatrix.TransformPoints(points);

 			//Translate the point
			Matrix translateMatrix = new Matrix(); 
 			translateMatrix.Translate(-ScrollPosition.X, -ScrollPosition.Y);
 			translateMatrix.TransformPoints(points); 
			return points[0]; 
 		}
 
		private Point ClientPointToLogical(Point point, bool mapToLayout)
		{
			Point[] points = new Point[] { point };
 
 			//Translate the point
			Matrix translateMatrix = new Matrix(); 
 			translateMatrix.Translate(ScrollPosition.X, ScrollPosition.Y); 
 			translateMatrix.TransformPoints(points);
 
			//Scale down the point
 			Matrix scalingMatrix = new Matrix();
			scalingMatrix.Scale(ScaleZoomFactor, ScaleZoomFactor);
			scalingMatrix.Invert(); 
			scalingMatrix.TransformPoints(points);
 			scalingMatrix.Invert(); 
			if (!mapToLayout) 
 				return points[0];
 			else 
				return this.activeLayout.MapInCoOrdToLayout(points[0]);
 		}
		#endregion
 
		#region IServiceProvider Implemetation
		object IServiceProvider.GetService(Type serviceType) 
 		{ 
			return GetService(serviceType);
 		} 

 		protected override object GetService(Type serviceType)
		{
 			object retVal = null; 

            if (serviceType == typeof(CommandID)) 
                retVal = new CommandID(new Guid("5f1c3c8d-60f1-4b98-b85b-8679f97e8eac"), 0); 
            else
				retVal = this.serviceProvider.GetService(serviceType); 

            return retVal;
		}
		#endregion 

 		#region Class WorkflowMessageDispatchData 
		private sealed class WorkflowMessageDispatchData : IDisposable 
 		{
 			private WorkflowView workflowView; 
            private HitTestInfo messageContext = null;

			public WorkflowMessageDispatchData(WorkflowView workflowView, EventArgs e)
 			{ 
				this.workflowView = workflowView;
 
				if (this.workflowView.RootDesigner != null && this.workflowView.stockMessageFilters.Count > 0) 
				{
 					Point clientPoint = Point.Empty; 
					if (e is MouseEventArgs || e is DragEventArgs)
 					{
 						if (e is MouseEventArgs)
						{ 
 							clientPoint = new Point(((MouseEventArgs)e).X, ((MouseEventArgs)e).Y);
						} 
						else if (e is DragEventArgs) 
						{
 							clientPoint = this.workflowView.PointToClient(new Point(((DragEventArgs)e).X, ((DragEventArgs)e).Y)); 
							this.workflowView.UpdateLayout();
 						}

 						Point logicalPoint = this.workflowView.ClientPointToLogical(clientPoint); 
						HitTestInfo hitTestInfo = this.workflowView.RootDesigner.HitTest(logicalPoint);
                        this.messageContext = (hitTestInfo != null) ? hitTestInfo : HitTestInfo.Nowhere; 
                        this.workflowView.messageHitTestContexts.Push(this.messageContext); 
 					}
				} 
			}

			void IDisposable.Dispose()
 			{ 
                if (this.workflowView != null && this.messageContext != null)
                { 
                    HitTestInfo hittestInfo = this.workflowView.messageHitTestContexts.Pop(); 
                    if (hittestInfo != this.messageContext)
                        Debug.Assert(false, "WorkflowView poped wrong message context"); 
                }
			}

 			public ReadOnlyCollection Filters 
 			{
				get 
 				{ 
                    //We recreate a new list everytime as in some of the messages dispatched, we there can
                    //be additional filters which might be added 
                    List mergedFilterList = new List();
                    mergedFilterList.AddRange(this.workflowView.customMessageFilters);
                    mergedFilterList.AddRange(this.workflowView.stockMessageFilters);
                    return mergedFilterList.AsReadOnly(); 
				}
			} 
		} 
 		#endregion
 
        #region IMessageFilter Implementation
        [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
        bool IMessageFilter.PreFilterMessage(ref Message m)
        { 
            bool handled = false;
            if (m.Msg == NativeMethods.WM_KEYDOWN || m.Msg == NativeMethods.WM_SYSKEYDOWN || 
                m.Msg == NativeMethods.WM_KEYUP || m.Msg == NativeMethods.WM_SYSKEYUP) 
            {
                Control control = Control.FromHandle(m.HWnd); 
                if (control != null && (control == this || Controls.Contains(control)))
                {
                    KeyEventArgs eventArgs = new KeyEventArgs((Keys)(unchecked((int)(long)m.WParam)) | ModifierKeys);
                    if (m.Msg == NativeMethods.WM_KEYDOWN || m.Msg == NativeMethods.WM_SYSKEYDOWN) 
                        OnKeyDown(eventArgs);
                    else 
                        OnKeyUp(eventArgs); 

                    handled = eventArgs.Handled; 
                }
            }

            return handled; 
        }
        #endregion 
    } 

    #region Class WorkflowViewAccessibleObject 
    public class WorkflowViewAccessibleObject : Control.ControlAccessibleObject
    {
        private WorkflowView workflowView;
 
        public WorkflowViewAccessibleObject(WorkflowView workflowView)
            : base(workflowView) 
        { 
            if (workflowView == null)
                throw new ArgumentNullException("workflowView"); 
            this.workflowView = workflowView;
        }

        public override Rectangle Bounds 
        {
            get 
            { 
                return new Rectangle(this.workflowView.PointToScreen(Point.Empty), this.workflowView.ViewPortSize);
            } 
        }

        public override string DefaultAction
        { 
            get
            { 
                return DR.GetString(DR.AccessibleAction); 
            }
        } 

        public override string Description
        {
            get 
            {
                return DR.GetString(DR.WorkflowViewAccessibleDescription); 
            } 
        }
 
        public override string Help
        {
            get
            { 
                return DR.GetString(DR.WorkflowViewAccessibleHelp);
            } 
        } 

        public override string Name 
        {
            get
            {
                return DR.GetString(DR.WorkflowViewAccessibleName); 
            }
 
            set 
            {
            } 
        }

        public override AccessibleRole Role
        { 
            get
            { 
                return AccessibleRole.Diagram; 
            }
        } 

        public override AccessibleObject GetChild(int index)
        {
            return (this.workflowView.RootDesigner != null && index == 0) ? this.workflowView.RootDesigner.AccessibilityObject : base.GetChild(index); 
        }
 
        public override int GetChildCount() 
        {
            return (this.workflowView.RootDesigner != null) ? 1 : -1; 
        }

        public override AccessibleObject Navigate(AccessibleNavigation navdir)
        { 
            if (navdir == AccessibleNavigation.FirstChild || navdir == AccessibleNavigation.LastChild)
                return GetChild(0); 
            else 
                return base.Navigate(navdir);
        } 
    }
    #endregion

	#region WorkflowTimer 
 	internal sealed class WorkflowTimer : IDisposable
 	{ 
		private static WorkflowTimer workflowTimer; 

 		private const int TimerInterval = 50; 
		private Timer timer = null;
		private List elapsedEvents = new List();

		internal static WorkflowTimer Default 
 		{
			get 
 			{ 
 				if (WorkflowTimer.workflowTimer == null)
					WorkflowTimer.workflowTimer = new WorkflowTimer(); 
 				return WorkflowTimer.workflowTimer;
			}
		}
 
		private WorkflowTimer()
 		{ 
			this.timer = new Timer(); 
 			this.timer.Interval = WorkflowTimer.TimerInterval;
 			this.timer.Tick += new EventHandler(OnTimer); 
			this.timer.Stop();
 		}

        ~WorkflowTimer() 
        {
            Dispose(false); 
        } 

        public void Dispose() 
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        } 

        private void Dispose(bool disposing) 
        { 
            if (this.timer != null)
			{ 
				if (this.timer.Enabled)
					this.timer.Stop();

 				this.timer.Dispose(); 
				this.timer = null;
 			} 
 		} 

		internal void Subscribe(int elapsedInterval, EventHandler elapsedEventHandler) 
 		{
			this.elapsedEvents.Add(new ElapsedEventUnit(elapsedInterval / WorkflowTimer.TimerInterval, elapsedEventHandler));
			if (!this.timer.Enabled)
				this.timer.Start(); 
 		}
 
		internal void Unsubscribe(EventHandler elapsedEventHandler) 
 		{
 			List removableElapsedEvents = new List(); 
			foreach (ElapsedEventUnit elapsedEvent in this.elapsedEvents)
 			{
				if (elapsedEvent.elapsedEventHandler == elapsedEventHandler)
					removableElapsedEvents.Add(elapsedEvent); 
			}
 
 			foreach (ElapsedEventUnit elapsedEvent in removableElapsedEvents) 
				this.elapsedEvents.Remove(elapsedEvent);
 
 			if (this.elapsedEvents.Count == 0 && this.timer.Enabled)
 				this.timer.Stop();
		}
 
 		private void OnTimer(object sender, EventArgs e)
		{ 
			List clonedList = new List(this.elapsedEvents); 
			foreach (ElapsedEventUnit elapsedEvent in clonedList)
 			{ 
				elapsedEvent.elapsedTime += 1;
 				if (elapsedEvent.elapsedInterval <= elapsedEvent.elapsedTime)
 				{
					elapsedEvent.elapsedTime = 0; 
 					elapsedEvent.elapsedEventHandler(this, EventArgs.Empty);
				} 
			} 
		}
 
 		private sealed class ElapsedEventUnit
		{
 			internal EventHandler	elapsedEventHandler;
 			internal int			elapsedInterval; 
			internal int			elapsedTime;
 
 			internal ElapsedEventUnit(int interval, EventHandler eventHandler) 
			{
				this.elapsedInterval = interval; 
				this.elapsedEventHandler = eventHandler;
 			}
		}
 	} 
 	#endregion
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK