/// <summary>Prevents re-entrant calls to UpdateUI. Yes this is the best way to do it /cry</summary> protected override void UpdateUIInternal() { m_edit_match.Text = Pattern.Expr; m_edit_eqv_regex.Text = Pattern.RegexString; m_edit_replace.Text = Pattern.Replace; m_radio_substring.Checked = Pattern.PatnType == EPattern.Substring; m_radio_wildcard.Checked = Pattern.PatnType == EPattern.Wildcard; m_radio_regex.Checked = Pattern.PatnType == EPattern.RegularExpression; m_check_ignore_case.Checked = Pattern.IgnoreCase; m_btn_add.ToolTip(m_tt, IsNew ? "Add this new pattern" : "Save changes to this pattern"); m_btn_add.ImageKey = IsNew ? "add" : "save"; m_btn_add.Enabled = CommitEnabled; // Show/Hide the eqv regex m_table.Height = m_table.PreferredSize.Height; m_split_subs.Top = m_table.Bottom; m_split_subs.Height = m_split_subs.Parent.Height - m_split_subs.Top - 3; // Highlight the match/replace fields if in error var ex0 = Pattern.ValidateExpr(); string tt0 = ex0 == null ? "The pattern used to identify rows to transform.\r\n" + (Pattern.PatnType == EPattern.RegularExpression ? "Capture groups are defined using the usual regular expression syntax for capture groups e.g. (.*),(<tag>?.*),etc\r\n" : "Create capture groups using '{' and '}', e.g. {one},{2},{tag},etc\r\n") : "Invalid match pattern - " + ex0.Message; var ex1 = Pattern.ValidateReplace(); string tt1 = ex1 == null ? "The template for the transformed result.\r\nUse the capture groups (syntax: {1} or {tag}) created in the Match field" : "Invalid replace template - " + ex1.Message; m_lbl_match.ToolTip(m_tt, tt0); m_edit_match.ToolTip(m_tt, tt0); m_lbl_replace.ToolTip(m_tt, tt1); m_edit_replace.ToolTip(m_tt, tt1); m_edit_match.BackColor = Misc.FieldBkColor(ex0 == null); m_edit_replace.BackColor = Misc.FieldBkColor(ex1 == null); // Apply the transform to the test text if not in error if (ex0 == null && ex1 == null) { string[] lines = m_edit_test.Lines; // Preserve the current carot position using (m_edit_test.SelectionScope()) { // Reset the highlighting m_edit_test.SelectAll(); m_edit_test.SelectionBackColor = Color.White; // Apply the transform to each line in the test text m_edit_result.Clear(); for (int i = 0, iend = lines.Length; i != iend; ++i) { m_edit_result.Select(m_edit_result.TextLength, 0); if (i != 0) { m_edit_result.SelectedText = Environment.NewLine; } if (!Pattern.IsMatch(lines[i])) { m_edit_result.SelectedText = lines[i]; } else { int starti = m_edit_test.GetFirstCharIndexFromLine(i); int startj = m_edit_result.TextLength; List <Transform.Capture> src_caps, dst_caps; string result = Pattern.Txfm(lines[i], out src_caps, out dst_caps); m_edit_result.SelectedText = result; // Highlight the capture groups in the test text and the result int j = 0; foreach (var s in src_caps) { m_edit_test.Select(starti + s.Span.Begi, s.Span.Sizei); m_edit_test.SelectionBackColor = Constants.BkColors[j++ % Constants.BkColors.Length]; } j = 0; foreach (var s in dst_caps) { m_edit_result.Select(startj + s.Span.Begi, s.Span.Sizei); m_edit_result.SelectionBackColor = Constants.BkColors[j++ % Constants.BkColors.Length]; } } } } // Updates the caps data based on the line that the cursor's in var line_index = m_edit_test.GetLineFromCharIndex(m_edit_test.SelectionStart); var line = line_index >= 0 && line_index < lines.Length ? lines[line_index] : string.Empty; var groups = new Dictionary <string, string>(); foreach (var name in Pattern.CaptureGroupNames) { groups[name] = string.Empty; } foreach (var cap in Pattern.CaptureGroups(line)) { groups[cap.Key] = cap.Value; } m_caps = groups.ToList(); } m_grid_subs.RowCount = m_caps.Count; m_grid_subs.Refresh(); }