|
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Text.RegularExpressions;
using System.Runtime.InteropServices;
using RegexTester.UserControls;
using System.Threading;
using System.Diagnostics;
namespace RegexTester
{
/// <summary>
/// Add-in form.
/// </summary>
public partial class RegexTesterForm : Form
{
private RichTextBox regularExpressionRichTextBox;
private MessageDecorator messageControl;
private RegexTesterModel model;
private Thread updateThread;
private Stopwatch monitorWatch = new Stopwatch();
private Thread monitorThread;
/// <summary>
/// Make the form close on ESC.
/// </summary>
/// <param name="msg"></param>
/// <param name="keyData"></param>
/// <returns></returns>
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (msg.WParam.ToInt32() == (int)Keys.Escape)
{
DialogResult = DialogResult.Cancel;
this.Close();
}
return base.ProcessCmdKey(ref msg, keyData);
}
/// <summary>
/// C.tor.
/// </summary>
public RegexTesterForm()
{
InitializeComponent();
regularExpressionRichTextBox = new SyntaxHighlightRichTextBox();
regularExpressionRichTextBox.Multiline = true;
regularExpressionRichTextBox.BorderStyle = BorderStyle.None;
regularExpressionRichTextBox.Font = richTextBoxMatches.Font;
regularExpressionRichTextBox.DetectUrls = false;
regularExpressionRichTextBox.TextChanged += regexParameters_Changed;
regularExpressionRichTextBox.TabIndex = 1;
messageControl = new MessageDecorator { WrappedControl = regularExpressionRichTextBox };
showValidRegExTextBox.WrappedControl = messageControl;
showValidRegExTextBox.BorderWidth = 4;
checkBoxCompiled.CheckedChanged += regexParameters_Changed;
checkBoxCultureInvariant.CheckedChanged += regexParameters_Changed;
checkBoxECMAScript.CheckedChanged += regexParameters_Changed;
checkBoxExplicitCapture.CheckedChanged += regexParameters_Changed;
checkBoxIgnoreCase.CheckedChanged += regexParameters_Changed;
checkBoxIgnorePatternWhitespace.CheckedChanged += regexParameters_Changed;
checkBoxMultiLine.CheckedChanged += regexParameters_Changed;
checkBoxRightToLeft.CheckedChanged += regexParameters_Changed;
checkBoxSingleline.CheckedChanged += regexParameters_Changed;
model = new RegexTesterModel();
this.dataGridViewRegexs.Columns[0].DataPropertyName = "Name";
this.dataGridViewRegexs.Columns[1].DataPropertyName = "Regex";
this.dataGridViewRegexs.AutoGenerateColumns = false;
RefreshLoadedRegexsView();
updateThread = new Thread(UpdateFormThreadStart);
updateThread.Start();
monitorThread = new Thread(MonitorUpdateThreadStart);
monitorThread.Start();
Disposed += new EventHandler(RegexTesterForm_Disposed);
Shown += new EventHandler(RegexTesterForm_Shown);
}
private void RegexTesterForm_Shown(object sender, EventArgs e)
{
lock (testFormUpdateIndexLock)
{
TestFormUpdateIndex++;
}
}
private bool IsDisposed { get; set; }
private void RegexTesterForm_Disposed(object sender, EventArgs e)
{
IsDisposed = true;
}
private List<RegexInfo> CurrentRegexs { get; set; }
private bool IsRefreshingRegexView { get; set; }
private void RefreshLoadedRegexsView()
{
IsRefreshingRegexView = true;
CurrentRegexs = model.GetRegularExpressions().ToList();
this.dataGridViewRegexs.DataSource = CurrentRegexs;
IsRefreshingRegexView = false;
}
private object testFormUpdateIndexLock = new object();
private int TestFormUpdateIndex { get; set; }
private void UpdateFormThreadStart()
{
int maxIndex = -1;
while (!IsDisposed)
{
bool updated = false;
lock (testFormUpdateIndexLock)
{
if (TestFormUpdateIndex > maxIndex)
{
maxIndex = TestFormUpdateIndex;
updated = true;
}
}
if (updated)
{
monitorWatch.Start();
UpdateTestForm();
monitorWatch.Reset();
}
else
{
Thread.Sleep(100);
}
}
}
private void MonitorUpdateThreadStart()
{
while (!IsDisposed)
{
if (labelWarningEvaluationTime.Visible != monitorWatch.Elapsed.Seconds > 2)
{
CallGUIFromOtherThread(() => { labelWarningEvaluationTime.Visible = !labelWarningEvaluationTime.Visible; });
}
Thread.Sleep(100);
}
}
private void buttonResetEvaluation_Click(object sender, EventArgs e)
{
updateThread.Abort();
updateThread.Join();
ToMatch = "";
updateThread = new Thread(UpdateFormThreadStart);
updateThread.Start();
}
/// <summary>
/// Regular expression evaluated by form.
/// </summary>
public string RegularExpression
{
get { return regularExpressionRichTextBox.Text; }
set { regularExpressionRichTextBox.Text = value; }
}
public string ToMatch
{
get { return textBoxItemToMatch.Text; }
set { textBoxItemToMatch.Text = value; }
}
public string ReplacePattern
{
get { return textBoxReplacePattern.Text; }
set { textBoxReplacePattern.Text = value; }
}
public string ReplaceResult
{
get { return textBoxReplaceResult.Text; }
set { textBoxReplaceResult.Text = value; }
}
public RegexOptions Options
{
set
{
checkBoxCompiled.Checked = (value & RegexOptions.Compiled) == RegexOptions.Compiled;
checkBoxCultureInvariant.Checked = (value & RegexOptions.CultureInvariant) == RegexOptions.CultureInvariant;
checkBoxECMAScript.Checked = (value & RegexOptions.ECMAScript) == RegexOptions.ECMAScript;
checkBoxExplicitCapture.Checked = (value & RegexOptions.ExplicitCapture) == RegexOptions.ExplicitCapture;
checkBoxIgnoreCase.Checked = (value & RegexOptions.IgnoreCase) == RegexOptions.IgnoreCase;
checkBoxIgnorePatternWhitespace.Checked = (value & RegexOptions.IgnorePatternWhitespace) == RegexOptions.IgnorePatternWhitespace;
checkBoxMultiLine.Checked = (value & RegexOptions.Multiline) == RegexOptions.Multiline;
checkBoxRightToLeft.Checked = (value & RegexOptions.RightToLeft) == RegexOptions.RightToLeft;
checkBoxSingleline.Checked = (value & RegexOptions.Singleline) == RegexOptions.Singleline;
}
get
{
RegexOptions regexOptions = RegexOptions.None;
regexOptions |= checkBoxCompiled.Checked ? RegexOptions.Compiled : RegexOptions.None;
regexOptions |= checkBoxCultureInvariant.Checked ? RegexOptions.CultureInvariant : RegexOptions.None;
regexOptions |= checkBoxECMAScript.Checked ? RegexOptions.ECMAScript : RegexOptions.None;
regexOptions |= checkBoxExplicitCapture.Checked ? RegexOptions.ExplicitCapture : RegexOptions.None;
regexOptions |= checkBoxIgnoreCase.Checked ? RegexOptions.IgnoreCase : RegexOptions.None;
regexOptions |= checkBoxIgnorePatternWhitespace.Checked ? RegexOptions.IgnorePatternWhitespace : RegexOptions.None;
regexOptions |= checkBoxMultiLine.Checked ? RegexOptions.Multiline : RegexOptions.None;
regexOptions |= checkBoxRightToLeft.Checked ? RegexOptions.RightToLeft : RegexOptions.None;
regexOptions |= checkBoxSingleline.Checked ? RegexOptions.Singleline : RegexOptions.None;
return regexOptions;
}
}
private RegexInfo CurrentRegexInfo { get; set; }
private delegate void InvokeDelegate();
private void CallGUIFromOtherThread(Action a)
{
if (this.InvokeRequired)
{
this.Invoke(new InvokeDelegate(a));
}
else
{
a();
}
}
private void UpdateTestForm()
{
string regularExpressionText = null;
RegexOptions options = RegexOptions.None;
string replacePatternText = null;
string itemToMatchText = null;
CallGUIFromOtherThread(() =>
{
regularExpressionText = regularExpressionRichTextBox.Text;
options = Options;
replacePatternText = textBoxReplacePattern.Text;
itemToMatchText = textBoxItemToMatch.Text;
});
// Get regular expression
ParsedRegex parsedRegex = model.GetRegularExpression(regularExpressionText, options);
bool isValid = parsedRegex.Regex != null;
// Update validity of text box showing regular expression.
CallGUIFromOtherThread(() => { showValidRegExTextBox.IsValid = isValid; });
if (isValid)
{
string replaceValue = parsedRegex.Regex.Replace(itemToMatchText, replacePatternText);
CallGUIFromOtherThread(() =>
{
// Set replace value.
textBoxReplaceResult.Text = replaceValue;
// Clear error message.
messageControl.ResetMessage();
});
}
else
{
// Set error message.
CallGUIFromOtherThread(() => messageControl.SetMessage(parsedRegex.ParseError));
}
// Build result tree.
RegexResultTreeNode resultTree = model.BuildMatchTree(parsedRegex.Regex, itemToMatchText);
CallGUIFromOtherThread(() =>
{
// Reset result rich text field.
richTextBoxMatches.Clear();
// Visit regular expression tree.
resultTree.Accept(new RegexResultTreeToRichTextVisitor(richTextBoxMatches));
});
}
private void SetCurrentRegexInfo(RegexInfo current, bool clearMatch)
{
this.CurrentRegexInfo = current;
this.RegularExpression = current.Regex ?? "";
this.ReplacePattern = current.ReplacePattern ?? "";
this.Options = current.Options;
if (clearMatch)
{
this.ToMatch = "";
}
this.Text = "Test Regular Expressions";
if (current.Name != null)
{
this.Text += " - " + current.Name;
}
this.tabControlRegEx.SelectedTab = this.tabControlRegEx.TabPages[0];
}
private void regexParameters_Changed(object sender, EventArgs e)
{
lock (testFormUpdateIndexLock)
{
TestFormUpdateIndex++;
}
}
private void buttonOk_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.OK;
Close();
}
private void buttonCancel_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.Cancel;
Close();
}
private void buttonNew_Click(object sender, EventArgs e)
{
SetCurrentRegexInfo(new RegexInfo(), true);
}
private void buttonSave_Click(object sender, EventArgs e)
{
RegexInfo toFill = null;
if (CurrentRegexInfo != null && CurrentRegexInfo.Name != null)
{
toFill = CurrentRegexInfo;
}
else
{
SaveRegexForm saveForm = new SaveRegexForm();
if (saveForm.ShowDialog() == DialogResult.OK)
{
toFill = new RegexInfo
{
Name = saveForm.Name
};
CurrentRegexs.Add(toFill);
}
}
if (toFill != null)
{
toFill.Options = this.Options;
toFill.Regex = this.RegularExpression;
toFill.ReplacePattern = this.ReplacePattern;
model.SaveRegexs(CurrentRegexs);
SetCurrentRegexInfo(toFill, false);
}
RefreshLoadedRegexsView();
}
private void buttonDelete_Click(object sender, EventArgs e)
{
List<RegexInfo> newList = new List<RegexInfo>();
IDictionary<int, int> rowsToDelete = new Dictionary<int, int>();
foreach (DataGridViewRow r in dataGridViewRegexs.SelectedRows)
{
rowsToDelete.Add(r.Index, r.Index);
}
for (int i = 0; i < CurrentRegexs.Count; i++)
{
if (!rowsToDelete.ContainsKey(i))
{
newList.Add(CurrentRegexs[i]);
}
}
model.SaveRegexs(newList);
RefreshLoadedRegexsView();
}
private void dataGridViewRegexs_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
{
RegexInfo toLoad = CurrentRegexs[e.RowIndex];
SetCurrentRegexInfo(toLoad, true);
}
}
internal class RegexResultTreeToRichTextVisitor : IRegexResultTreeNodeVisitor
{
private RichTextBox richTextBox;
private Stack<Color> colorStack;
internal RegexResultTreeToRichTextVisitor(RichTextBox richTextBox)
{
this.richTextBox = richTextBox;
this.colorStack = new Stack<Color>();
}
public void Visit(RootNode node, bool beforeChildren)
{
}
public void Visit(MatchNode node, bool beforeChildren)
{
Font currentFont = richTextBox.SelectionFont;
Font boldFont = new Font(currentFont, FontStyle.Bold);
richTextBox.SelectionFont = boldFont;
if (beforeChildren)
{
colorStack.Push(richTextBox.SelectionColor);
richTextBox.SelectionColor = Color.Green;
}
richTextBox.AppendText(beforeChildren ? "[" : "]");
if (!beforeChildren)
{
richTextBox.SelectionColor = colorStack.Pop();
}
richTextBox.SelectionFont = currentFont;
}
public void Visit(GroupNode node, bool beforeChildren)
{
Font currentFont = richTextBox.SelectionFont;
Font boldFont = new Font(currentFont, FontStyle.Bold);
richTextBox.SelectionFont = boldFont;
if (beforeChildren)
{
colorStack.Push(richTextBox.SelectionColor);
richTextBox.SelectionColor = Color.Red;
}
richTextBox.AppendText(beforeChildren ? "(<" + node.GroupName + ">" : ")");
if (!beforeChildren)
{
richTextBox.SelectionColor = colorStack.Pop();
}
richTextBox.SelectionFont = currentFont;
}
public void Visit(LiteralNode node)
{
richTextBox.AppendText(node.Literal);
}
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
.NET developer. I wanted to be first an astronaut, then a jet pilot, but when I got a Commodore 64 for Christmas I never looked back. Also I would never have qualified for the first two things and everybody knows computer programmers get all the girls.