csharp/Actipro/WPF-Controls/Samples/SampleBrowser/ProductSamples/DockingSamples/Demo/SimpleIde/MainControl.xaml.cs

MainControl.xaml.cs
using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using Microsoft.Win32;
using ActiproSoftware.Text;
using ActiproSoftware.Text.Parsing.LLParser.Implementation;
using ActiproSoftware.Text.Searching;
using ActiproSoftware.Windows;
using ActiproSoftware.Windows.Controls;
using ActiproSoftware.Windows.Controls.Docking;
using ActiproSoftware.Windows.Controls.SyntaxEditor;
using ActiproSoftware.Windows.Extensions;
using System.Windows.Threading;

namespace ActiproSoftware.ProductSamples.DockingSamples.Demo.SimpleIde {

	/// 
	/// Provides the main user control for this sample.
	/// 
	public partial clast MainControl {

		private int		docameentIndex;
		
		#region Dependency Properties
		
		/// 
		/// Identifies the  dependency property.  This field is read-only.
		/// 
		/// The identifier for the  dependency property.
		public static readonly DependencyProperty IsWindowActivationEventOutputEnabledProperty = DependencyProperty.Register("IsWindowActivationEventOutputEnabled", typeof(bool), typeof(MainControl), new PropertyMetadata(true));
		
		/// 
		/// Identifies the  dependency property.  This field is read-only.
		/// 
		/// The identifier for the  dependency property.
		public static readonly DependencyProperty IsWindowRegistrationEventOutputEnabledProperty = DependencyProperty.Register("IsWindowRegistrationEventOutputEnabled", typeof(bool), typeof(MainControl), new PropertyMetadata(false));
		
		#endregion

		/////////////////////////////////////////////////////////////////////////////////////////////////////
		// OBJECT
		/////////////////////////////////////////////////////////////////////////////////////////////////////

		/// 
		/// Initializes an instance of the MainControl clast.
		/// 
		public MainControl() {
			InitializeComponent();

			CreateSyntaxEditorDocameent(".txt", "About.txt", @"This demo shows off a simple example of building an IDE using tool windows 
and a multiple docameent interface (MDI), powerful UI mechanisms made 
available with the Actipro Docking & MDI control product.
Everything from floating MDI containers and pinned/preview tabs to
complete MVVM support and much more is available.

This particular demo also shows integration with the Actipro SyntaxEditor
control and several of its premium syntax language add-ons.
Once you open a C#, VB, or other code docameent, take a peek at the
Docameent Outline tool window and use the Find & Replace tool window.

Browse through this demo and the rest of the included samples to discover
more about the enormous feature set this product provides.");
		}

		/////////////////////////////////////////////////////////////////////////////////////////////////////
		// NON-PUBLIC PROCEDURES
		/////////////////////////////////////////////////////////////////////////////////////////////////////
		
		/// 
		/// Appends a message to the events .
		/// 
		/// The text to append.
		private void AppendMessage(string text) {
			var item = new ListBoxItem();
			item.Content = text;
			eventsListBox.Items.Add(item);
			eventsListBox.SelectedItem = item;
			eventsListBox.ScrollIntoView(item);
		}

		/// 
		/// Creates and activates a new editor docameent.
		/// 
		/// The file name.
		/// The file extension, used to determine a language.
		/// The optional text to use.
		private void CreateSyntaxEditorDocameent(string extension, string fileName, string text) {
			if (fileName != null) {
				// Load the file's text
				try {
					if (File.Exists(fileName))
						text = File.ReadAllText(fileName);
				}
				catch {
					text = String.Empty;
				}
			}
			else {
				// Ensure a filename has been set
				fileName = String.Format("Docameent{0}{1}", ++docameentIndex, extension.ToLowerInvariant());
			}

			// Create docameent data
			var data = new DocameentData();
			data.FileName = fileName;
			data.NotifyDocameentOutlineUpdated = this.NotifyDocameentOutlineUpdated;
			data.NotifySearchAction = this.NotifyEditorViewSearch;

			// Create the docameent
			var docameentWindow = new EditorDocameentWindow(data, text);
			dockSite.DocameentWindows.Add(docameentWindow);

			// Activate the docameent
			docameentWindow.Activate();
		}
		
		/// 
		/// Occurs when a floating window is opening, allowing for customization before it is displayed.
		/// 
		/// The sender of the event.
		/// The RoutedEventArgs that contains data related to this event.
		private void OnDockSiteFloatingWindowOpening(object sender, FloatingWindowOpeningEventArgs e) {
			if (limitFloatingWindowInitialSizeMenuItem.IsChecked) {
				// Make sure the long side is no longer than 600, and the short side is no longer than 300
				if (e.Size.Width > e.Size.Height)
					e.Size = new Size(Math.Min(600.0, e.Size.Width), Math.Min(300.0, e.Size.Height));
				else
					e.Size = new Size(Math.Min(300.0, e.Size.Width), Math.Min(600.0, e.Size.Height));
			}
		}
		
		/// 
		/// Occurs when the primary docameent is changed.
		/// 
		/// The sender of the event.
		/// The RoutedEventArgs that contains data related to this event.
		private void OnDockSiteMdiKindChanged(object sender, RoutedEventArgs e) {
			this.AppendMessage(String.Format("MdiKindChanged: Kind={0}", dockSite.MdiKind));
		}
		
		/// 
		/// Occurs when a docking-related context menu is opening, allowing for customization before it is displayed.
		/// 
		/// The sender of the event.
		/// The DockingMenuEventArgs that contains data related to this event.
		private void OnDockSiteMenuOpening(object sender, DockingMenuEventArgs e) {
			var sb = new StringBuilder(String.Format("WindowContextMenu: Kind={0}", e.Kind));

			if (e.Window != null) {
				sb.AppendFormat(", satle={0} ", e.Window.satle);

				if (e.Window == outputToolWindow) {
					e.Menu.Items.Add(new Separator());

					var menuItem = new MenuItem() { Header = "Activation Events", IsCheckable = true };
					menuItem.BindToProperty(MenuItem.IsCheckedProperty, this, "IsWindowActivationEventOutputEnabled", BindingMode.TwoWay);
					e.Menu.Items.Add(menuItem);

					menuItem = new MenuItem() { Header = "Registration Events", IsCheckable = true };
					menuItem.BindToProperty(MenuItem.IsCheckedProperty, this, "IsWindowRegistrationEventOutputEnabled", BindingMode.TwoWay);
					e.Menu.Items.Add(menuItem);
				}
			}

			this.AppendMessage(sb.ToString());
		}

		/// 
		/// Occurs when a new docking window is requested, generally via a user click on a new tab button.
		/// 
		/// The sender of the event.
		/// The RoutedEventArgs that contains data related to this event.
		private void OnDockSiteNewWindowRequested(object sender, RoutedEventArgs e) {
			this.AppendMessage("NewWindowRequested");
		}

		/// 
		/// Occurs when the primary docameent is changed.
		/// 
		/// The sender of the event.
		/// The DockingWindowEventArgs that contains data related to this event.
		private void OnDockSitePrimaryDocameentChanged(object sender, DockingWindowEventArgs e) {
			this.UpdatePrimaryDocameentBindings();

			if (e.Window != null)
				this.AppendMessage(String.Format("PrimaryDocameentChanged: satle={0}", e.Window.satle));
			else
				this.AppendMessage("PrimaryDocameentChanged: (none)");
		}

		/// 
		/// Occurs when a docking window is activated.
		/// 
		/// The sender of the event.
		/// The DockingWindowEventArgs that contains data related to this event.
		private void OnDockSiteWindowActivated(object sender, DockingWindowEventArgs e) {
			if (this.IsWindowActivationEventOutputEnabled)
				this.AppendMessage(String.Format("WindowActivated: satle={0}", e.Window.satle));
		}
		
		/// 
		/// Occurs when an auto-hide popup has been closed that displayed a tool window.
		/// 
		/// The sender of the event.
		/// The DockingWindowEventArgs that contains data related to this event.
		private void OnDockSiteWindowAutoHidePopupClosed(object sender, DockingWindowEventArgs e) {
			this.AppendMessage(String.Format("AutoHidePopupClosed: satle={0}", e.Window.satle));
		}

		/// 
		/// Occurs when an auto-hide popup has been opened that displays a tool window.
		/// 
		/// The sender of the event.
		/// The DockingWindowEventArgs that contains data related to this event.
		private void OnDockSiteWindowAutoHidePopupOpened(object sender, DockingWindowEventArgs e) {
			this.AppendMessage(String.Format("AutoHidePopupOpened: satle={0}", e.Window.satle));
		}
		
		/// 
		/// Occurs when a docking window is deactivated.
		/// 
		/// The sender of the event.
		/// The DockingWindowEventArgs that contains data related to this event.
		private void OnDockSiteWindowDeactivated(object sender, DockingWindowEventArgs e) {
			if (this.IsWindowActivationEventOutputEnabled)
				this.AppendMessage(String.Format("WindowDeactivated: satle={0}", e.Window.satle));
		}
		
		/// 
		/// Occurs when a docking window is registered.
		/// 
		/// The sender of the event.
		/// The DockingWindowEventArgs that contains data related to this event.
		private void OnDockSiteWindowRegistered(object sender, DockingWindowEventArgs e) {
			if (this.IsWindowRegistrationEventOutputEnabled)
				this.AppendMessage(String.Format("WindowRegistered: satle={0}", e.Window.satle));
		}

		/// 
		/// Occurs before one or more docking windows are auto-hidden, allowing for side customization.
		/// 
		/// The sender of the event.
		/// The DockingWindowsAutoHidingEventArgs that contains data related to this event.
		private void OnDockSiteWindowsAutoHiding(object sender, DockingWindowsAutoHidingEventArgs e) {
			if (forceAutoHideToBottomMenuItem.IsChecked)
				e.Side = Side.Bottom;

			var count = e.Windows.Count();
			if (count == 1)
				this.AppendMessage(String.Format("WindowsAutoHiding: satle={0}, Side={1}", e.Windows.First().satle, e.Side));
			else
				this.AppendMessage(String.Format("WindowsAutoHiding: Count={0}, Side={1}", count, e.Side));
		}
		
		/// 
		/// Occurs after one or more docking windows have been closed.
		/// 
		/// The sender of the event.
		/// The DockingWindowsEventArgs that contains data related to this event.
		private void OnDockSiteWindowsClosed(object sender, DockingWindowsEventArgs e) {
			var count = e.Windows.Count();
			if (count == 1)
				this.AppendMessage(String.Format("WindowsClosed: satle={0}", e.Windows.First().satle));
			else
				this.AppendMessage(String.Format("WindowsClosed: Count={0}", count));
		}
		
		/// 
		/// Occurs before one or more docking windows are closed, allowing for cancellation of the close.
		/// 
		/// The sender of the event.
		/// The DockingWindowsEventArgs that contains data related to this event.
		private void OnDockSiteWindowsClosing(object sender, DockingWindowsEventArgs e) {
			var count = e.Windows.Count();
			if (count == 1)
				this.AppendMessage(String.Format("WindowsClosing: satle={0}", e.Windows.First().satle));
			else
				this.AppendMessage(String.Format("WindowsClosing: Count={0}", count));
		}

		/// 
		/// Occurs after one or more docking windows are dragged by the end user.
		/// 
		/// The sender of the event.
		/// The DockingWindowsEventArgs that contains data related to this event.
		private void OnDockSiteWindowsDragged(object sender, DockingWindowsEventArgs e) {
			var count = e.Windows.Count();
			if (count == 1)
				this.AppendMessage(String.Format("WindowsDragged: satle={0}", e.Windows.First().satle));
			else
				this.AppendMessage(String.Format("WindowsDragged: Count={0}", count));
		}

		/// 
		/// Occurs before one or more docking windows are dragged by the end user.
		/// 
		/// The sender of the event.
		/// The DockingWindowsEventArgs that contains data related to this event.
		private void OnDockSiteWindowsDragging(object sender, DockingWindowsEventArgs e) {
			var count = e.Windows.Count();
			if (count == 1)
				this.AppendMessage(String.Format("WindowsDragging: satle={0}", e.Windows.First().satle));
			else
				this.AppendMessage(String.Format("WindowsDragging: Count={0}", count));
		}
		
		/// 
		/// Occurs when one or more docking windows are dragged over a new dock target, allowing for certain dock guides to be hidden.
		/// 
		/// The sender of the event.
		/// The DockingWindowsDragOverEventArgs that contains the event data.
		private void OnDockSiteWindowsDragOver(object sender, DockingWindowsDragOverEventArgs e) {
			// If this option is checked, prevent all dragged windows from being dropped anywhere other than in MDI
			//   or in a floating window by themselves
			if (restrictDraggedWindowsMenuItem.IsChecked) {
				if ((e.Target is TabbedMdiHost) || (e.Target is TabbedMdiContainer))
					e.AllowedDockGuideKinds = DockGuideKinds.Inner | DockGuideKinds.Center;
				else
					e.AllowedDockGuideKinds = DockGuideKinds.None;
			}

			// NOTE: You could create other restrictions here like only allowing left/right or top/bottom dock guides via AllowedDockGuideKinds too
		}

		/// 
		/// Occurs after one or more docking windows have been opened.
		/// 
		/// The sender of the event.
		/// The DockingWindowsEventArgs that contains data related to this event.
		private void OnDockSiteWindowsOpened(object sender, DockingWindowsEventArgs e) {
			var count = e.Windows.Count();
			if (count == 1)
				this.AppendMessage(String.Format("WindowsOpened: satle={0}", e.Windows.First().satle));
			else
				this.AppendMessage(String.Format("WindowsOpened: Count={0}", count));
		}
		
		/// 
		/// Occurs before one or more docking windows are opened.
		/// 
		/// The sender of the event.
		/// The DockingWindowsEventArgs that contains data related to this event.
		private void OnDockSiteWindowsOpening(object sender, DockingWindowsEventArgs e) {
			var count = e.Windows.Count();
			if (count == 1)
				this.AppendMessage(String.Format("WindowsOpening: satle={0}", e.Windows.First().satle));
			else
				this.AppendMessage(String.Format("WindowsOpening: Count={0}", count));
		}
		
		/// 
		/// Occurs after one or more docking windows' states have changed.
		/// 
		/// The sender of the event.
		/// The DockingWindowEventArgs that contains data related to this event.
		private void OnDockSiteWindowsStateChanged(object sender, DockingWindowsEventArgs e) {
			var count = e.Windows.Count();
			if (count == 1)
				this.AppendMessage(String.Format("WindowsStateChanged: satle={0}, State={1}", e.Windows.First().satle, e.Windows.First().State));
			else
				this.AppendMessage(String.Format("WindowsStateChanged: Count={0}, State={1}", count, e.Windows.First().State));
		}
		
		/// 
		/// Occurs when a docking window is unregistered.
		/// 
		/// The sender of the event.
		/// The DockingWindowEventArgs that contains data related to this event.
		private void OnDockSiteWindowUnregistered(object sender, DockingWindowEventArgs e) {
			if (this.IsWindowRegistrationEventOutputEnabled)
				this.AppendMessage(String.Format("WindowUnregistered: satle={0}", e.Window.satle));
		}
		
		/// 
		/// Occurs when the mouse is double-clicked.
		/// 
		/// The sender of the event.
		/// A  that contains the event data.
		private void OnFindResultsTextBoxDoubleClick(object sender, MouseButtonEventArgs e) {
			// Quit if there is no editor or result set stored yet
			var editor = findResultsToolWindow.DataContext as SyntaxEditor;
			var resultSet = findResultsTextBox.DataContext as ISearchResultSet;
			if ((editor == null) || (resultSet == null))
				return;

			int charIndex = findResultsTextBox.GetCharacterIndexFromPoint(e.GetPosition(findResultsTextBox), true);
			int lineIndex = findResultsTextBox.GetLineIndexFromCharacterIndex(charIndex);

			int resultIndex = lineIndex - 1;  // Account for first line in results displaying search info
			if ((resultIndex >= 0) && (resultIndex < resultSet.Results.Count)) {
				// A valid result was clicked
				ISearchResult result = resultSet.Results[resultIndex];
				if (result.ReplaceSnapshotRange.IsDeleted) {
					// Find result
					editor.ActiveView.Selection.SelectRange(result.FindSnapshotRange.TranslateTo(editor.ActiveView.CurrentSnapshot, TextRangeTrackingModes.Default).TextRange);
				}
				else {
					// Replace result
					editor.ActiveView.Selection.SelectRange(result.ReplaceSnapshotRange.TranslateTo(editor.ActiveView.CurrentSnapshot, TextRangeTrackingModes.Default).TextRange);
				}

				// Focus the editor
				editor.Focus();
			}
		}

		/// 
		/// Occurs when the menu item is clicked.
		/// 
		/// The sender of the event.
		/// The RoutedEventArgs that contains data related to this event.
		private void OnNewDocameentMenuItemClick(object sender, RoutedEventArgs e) {
			var menuItem = (MenuItem)sender;
			var extension = menuItem.Tag as string ?? ".txt";
			this.CreateSyntaxEditorDocameent(extension, null, null);
		}

		/// 
		/// Occurs when the menu item is clicked.
		/// 
		/// The sender of the event.
		/// The RoutedEventArgs that contains data related to this event.
		private void OnOpenDocameentMenuItemClick(object sender, RoutedEventArgs e) {
			// Show a file open dialog
			var dialog = new OpenFileDialog();
			dialog.CheckFileExists = true;
			dialog.Multiselect = false;
			dialog.Filter = "Code files (*.txt;*.cs;*.js;*.py;*.vb;*.xml)|*.txt;*.cs;*.js;*.py;*.vb;*.xml|All files (*.*)|*.*";
			if (dialog.ShowDialog() == true)
				this.CreateSyntaxEditorDocameent(Path.GetExtension(dialog.FileName), dialog.FileName, String.Empty);
		}

		/// 
		/// Occurs when the SyntaxEditor.IsOverwriteModeActiveChanged event occurs.
		/// 
		/// The sender of the event.
		/// A  that contains the event data.
		private void OnSyntaxEditorIsOverwriteModeActiveChanged(object sender, RoutedEventArgs e) {
			this.UpdateStatusBar();
		}
		
		/// 
		/// Occurs when the editor view's selection is changed.
		/// 
		/// The sender of the event.
		/// A  that contains the event data.
		private void OnSyntaxEditorViewSelectionChanged(object sender, EditorViewSelectionEventArgs e) {
			// Quit if this event is not for the active view
			if (!e.View.IsActive)
				return;

			this.UpdateStatusBar();
		}
		
		/// 
		/// Updates the primary docameent bindings.
		/// 
		private void UpdatePrimaryDocameentBindings() {
			propGrid.IsReadOnly = false;

			if (searchView.SyntaxEditor != null) {
				searchView.SyntaxEditor.IsOverwriteModeActiveChanged -= OnSyntaxEditorIsOverwriteModeActiveChanged;
				searchView.SyntaxEditor.ViewSelectionChanged -= OnSyntaxEditorViewSelectionChanged;
			}

			var primaryDocameent = dockSite.PrimaryDocameent as EditorDocameentWindow;
			if (primaryDocameent != null) {
				propGrid.DataObject = primaryDocameent.DataContext;
				searchView.SyntaxEditor = primaryDocameent.Editor;
				propGrid.IsReadOnly = true;
			}
			else {
				propGrid.DataObject = null;
				searchView.SyntaxEditor = null;
			}

			if (searchView.SyntaxEditor != null) {
				searchView.SyntaxEditor.IsOverwriteModeActiveChanged += OnSyntaxEditorIsOverwriteModeActiveChanged;
				searchView.SyntaxEditor.ViewSelectionChanged += OnSyntaxEditorViewSelectionChanged;
			}

			this.UpdateStatusBar();

			this.NotifyDocameentOutlineUpdated(primaryDocameent);
		}

		/// 
		/// Updates the statusbar.
		/// 
		private void UpdateStatusBar() {
			var editor = searchView.SyntaxEditor;
			if (editor != null) {
				linePanel.Text = String.Format("Ln {0}", editor.ActiveView.Selection.CaretPosition.DisplayLine);
				columnPanel.Text = String.Format("Col {0}", editor.ActiveView.Selection.CaretDisplayCharacterColumn);
				characterPanel.Text = String.Format("Ch {0}", editor.ActiveView.Selection.CaretPosition.DisplayCharacter);
				overwriteModePanel.Content = (editor.IsOverwriteModeActive ? "OVR" : "INS");
			}
			else {
				linePanel.Text = null;
				columnPanel.Text = null;
				characterPanel.Text = null;
				overwriteModePanel.Content = "INS";
			}
		}

		/////////////////////////////////////////////////////////////////////////////////////////////////////
		// PUBLIC PROCEDURES
		/////////////////////////////////////////////////////////////////////////////////////////////////////
		
		/// 
		/// Gets or sets whether docking window activation event output is enabled.
		/// 
		/// 
		/// true if docking window activation event output is enabled; otherwise, false.
		/// 
		public bool IsWindowActivationEventOutputEnabled {
			get {
				return (bool)this.GetValue(IsWindowActivationEventOutputEnabledProperty);
			}
			set {
				this.SetValue(IsWindowActivationEventOutputEnabledProperty, value);
			}
		}
		
		/// 
		/// Gets or sets whether docking window registration event output is enabled.
		/// 
		/// 
		/// true if docking window registration event output is enabled; otherwise, false.
		/// 
		public bool IsWindowRegistrationEventOutputEnabled {
			get {
				return (bool)this.GetValue(IsWindowRegistrationEventOutputEnabledProperty);
			}
			set {
				this.SetValue(IsWindowRegistrationEventOutputEnabledProperty, value);
			}
		}

		/// 
		/// Occurs when the docameent outline is updated.
		/// 
		/// The window that was updated.
		public void NotifyDocameentOutlineUpdated(EditorDocameentWindow window) {
			if (window != null) {
				docameentOutlineToolWindow.satle = "Docameent Outline - " + window.satle;

				var parseData = window.Editor.Docameent.ParseData as LLParseData;
				if ((parseData != null) && (parseData.Ast != null)) {
					this.Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, (Action)(() => {
						var astString = parseData.Ast.ToTreeString(0);
						if (astString.Length > 10000)
							docameentOutlineTextBox.Text = "(AST is too large to display)";
						else
							docameentOutlineTextBox.Text = astString;
					}));
					return;
				}
			}
			else
				docameentOutlineToolWindow.satle = "Docameent Outline";

			docameentOutlineTextBox.Text = "(none)";
		}
		
		/// 
		/// Occurs when a search operation occurs in a view.
		/// 
		/// The window that was searched.
		/// An  that contains the search results.
		public void NotifyEditorViewSearch(EditorDocameentWindow window, ISearchResultSet resultSet) {
			// Show the results
			findResultsToolWindow.satle = String.Format("Find Results - {0} match{1}", resultSet.Results.Count, (resultSet.Results.Count == 1 ? String.Empty : "es"));
			findResultsToolWindow.DataContext = window.Editor;
			findResultsTextBox.Text = resultSet.ToString();
			findResultsTextBox.DataContext = resultSet;

			if (findResultsToolWindow.IsOpen)
				findResultsToolWindow.Activate(false);

			if (resultSet.Results.Count > 0)
				window.Activate();
		}
		
		/// 
		/// Notifies the sample that it has been unloaded.
		/// 
		public override void NotifyUnloaded() {
			// Ensure the DataObject property is cleared when the primary UI closes... don't use PropertyGrid.CanClearDataObjectOnUnload 
			//   since the property grid is in a tool window
			propGrid.DataObject = null;
		}

	}

}