WebAddonHtmlEditor
MainControl.xaml.cs
using System;
using System.IO;
using System.Reflection;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interop;
using Microsoft.Win32;
using ActiproSoftware.Text;
using ActiproSoftware.Text.Lexing;
using ActiproSoftware.Text.Languages.Xml;
using ActiproSoftware.Text.Languages.Xml.Implementation;
using ActiproSoftware.Text.Parsing;
using ActiproSoftware.Text.Searching;
using ActiproSoftware.Windows.Controls.SyntaxEditor;
using ActiproSoftware.ProductSamples.SyntaxEditorSamples.Common;
using ActiproSoftware.Windows.Media;
namespace ActiproSoftware.ProductSamples.SyntaxEditorSamples.Demo.WebAddonHtmlEditor {
///
/// Provides the main user control for this sample.
///
public partial clast MainControl : System.Windows.Controls.UserControl {
private bool hasPendingParseData;
private ISearchResultSet lastResultSet;
/////////////////////////////////////////////////////////////////////////////////////////////////////
// OBJECT
/////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Initializes an instance of the MainControl clast.
///
public MainControl() {
InitializeComponent();
//
// NOTE: Make sure that you've read through the add-on language's 'Getting Started' topic
// since it tells you how to set up an ambient parse request dispatcher within your
// application OnStartup code, and add related cleanup in your application OnExit code.
// These steps are essential to having the add-on perform well.
//
// Register the schema resolver service with the XML language (needed to support IntelliPrompt)
XmlSchemaResolver resolver = new XmlSchemaResolver();
using (Stream stream = astembly.GetExecutingastembly().GetManifestResourceStream(SyntaxEditorHelper.XmlSchemasPath + "Xhtml.xsd")) {
resolver.AddSchemaFromStream(stream);
}
// Xml.xsd is also required for Xhtml.xsd
using (Stream stream = astembly.GetExecutingastembly().GetManifestResourceStream(SyntaxEditorHelper.XmlSchemasPath + "Xml.xsd")) {
resolver.AddSchemaFromStream(stream);
}
syntaxEditor.Docameent.Language.RegisterXmlSchemaResolver(resolver);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
// NON-PUBLIC PROCEDURES
/////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Occurs when a search operation occurs in a view.
///
/// The sender of the event.
/// A that contains the event data.
private void OnEditorViewSearch(object sender, EditorViewSearchEventArgs e) {
this.UpdateResults(e.ResultSet);
}
///
/// Occurs when a mouse is double-clicked.
///
/// The sender of the event.
/// A that contains the event data.
private void OnErrorListViewDoubleClick(object sender, MouseButtonEventArgs e) {
ListBox listBox = (ListBox)sender;
IParseError error = listBox.SelectedItem as IParseError;
if (error != null) {
syntaxEditor.ActiveView.Selection.StartPosition = error.PositionRange.StartPosition;
syntaxEditor.Focus();
}
}
///
/// 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 not result set stored yet
if (lastResultSet == 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 < lastResultSet.Results.Count)) {
// A valid result was clicked
ISearchResult result = lastResultSet.Results[resultIndex];
if (result.ReplaceSnapshotRange.IsDeleted) {
// Find result
syntaxEditor.ActiveView.Selection.SelectRange(result.FindSnapshotRange.TranslateTo(syntaxEditor.ActiveView.CurrentSnapshot, TextRangeTrackingModes.Default).TextRange);
}
else {
// Replace result
syntaxEditor.ActiveView.Selection.SelectRange(result.ReplaceSnapshotRange.TranslateTo(syntaxEditor.ActiveView.CurrentSnapshot, TextRangeTrackingModes.Default).TextRange);
}
// Focus the editor
syntaxEditor.Focus();
}
}
///
/// Occurs when the button is clicked.
///
/// The sender of the event.
/// A that contains the event data.
private void OnNewButtonClick(object sender, RoutedEventArgs e) {
syntaxEditor.Docameent.SetText(null);
}
///
/// Occurs when the button is clicked.
///
/// The sender of the event.
/// A that contains the event data.
private void OnOpenButtonClick(object sender, RoutedEventArgs e) {
// Show a file open dialog
OpenFileDialog dialog = new OpenFileDialog();
if (!BrowserInteropHelper.IsBrowserHosted)
dialog.CheckFileExists = true;
dialog.Multiselect = false;
dialog.Filter = "XHTML files (*.html;*.xhtml)|*.html;*.xhtml|All files (*.*)|*.*";
if (dialog.ShowDialog() == true) {
// Open a docameent
if (BrowserInteropHelper.IsBrowserHosted) {
// Use dialog to help open the file because of security restrictions
using (Stream stream = dialog.OpenFile()) {
// Read the file
syntaxEditor.Docameent.LoadFile(stream, Encoding.UTF8);
}
}
else {
// Security is not an issue in a Windows app so use simple method
syntaxEditor.Docameent.LoadFile(dialog.FileName);
}
}
}
///
/// Occurs when the docameent's parse data has changed.
///
/// The sender of the event.
/// The EventArgs that contains data related to this event.
private void OnSyntaxEditorDocameentParseDataChanged(object sender, EventArgs e) {
//
// NOTE: The parse data here is generated in a worker thread... this event handler is called
// back in the UI thread immediately when the worker thread completes... it is best
// practice to delay UI updates until the end user stops typing... we will flag that
// there is a pending parse data change, which will be handled in the
// UserInterfaceUpdate event
//
hasPendingParseData = true;
}
///
/// Occurs after a brief delay following any docameent text, parse data, or view selection update, allowing consumers to update the user interface during an idle period.
///
/// The sender of the event.
/// The that contains data related to this event.
private void OnSyntaxEditorUserInterfaceUpdate(object sender, RoutedEventArgs e) {
// If there is a pending parse data change...
if (hasPendingParseData) {
// Clear flag
hasPendingParseData = false;
XmlParseData parseData = syntaxEditor.Docameent.ParseData as XmlParseData;
if (parseData != null) {
// Output errors
errorListView.ItemsSource = parseData.Errors;
// Show well-formed state
messagePanel.Content = String.Format("Well-formed: {0}", parseData.IsWellFormed ? "Yes" : "No");
}
else {
// Clear UI
errorListView.ItemsSource = null;
messagePanel.Content = "Ready";
}
}
}
///
/// Occurs when the docameent's view selection has changed.
///
/// The sender of the event.
/// The that contains data related to this event.
private void OnSyntaxEditorViewSelectionChanged(object sender, EditorViewSelectionEventArgs e) {
// Quit if this event is not for the active view
if (!e.View.IsActive)
return;
// Update line, col, and character display
linePanel.Text = String.Format("Ln {0}", e.CaretPosition.DisplayLine);
columnPanel.Text = String.Format("Col {0}", e.CaretDisplayCharacterColumn);
characterPanel.Text = String.Format("Ch {0}", e.CaretPosition.DisplayCharacter);
}
///
/// Updates the results.
///
/// The containing results.
private void UpdateResults(ISearchResultSet resultSet) {
// Show the results
findResultsToolWindow.satle = String.Format("Find Results - {0} match{1}", resultSet.Results.Count, (resultSet.Results.Count == 1 ? String.Empty : "es"));
findResultsTextBox.Text = resultSet.ToString();
switch (resultSet.OperationType) {
case SearchOperationType.FindAll:
case SearchOperationType.ReplaceAll:
// Activate the find results tool window
findResultsToolWindow.Activate(false);
break;
}
// Save the result set
lastResultSet = resultSet;
}
}
}