307 lines
8.2 KiB
C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using DevComponents.DotNetBar;
using C1.Win.C1SpellChecker;
namespace Volian.Controls.Library
{
// Our custom Spell Checker dialog
public partial class VlnSpellCheckDlg : DevComponents.DotNetBar.Office2007Form, ISpellDialog
{
private C1SpellChecker _Spell;
private ISpellCheckableEditor _Editor;
private CharRangeList _Errors;
private int _ErrorCount;
private int _ErrorIndex = -1; // current error index
private bool _AutoSuggest = true;
private string _NoSuggestionsText = "(no suggestions)";
Dictionary<string, string> _changeAll = new Dictionary<string, string>();
/// <summary>
/// Gets the <see cref="CharRange"/> object that represents the error currently
/// displayed in the dialog.
/// </summary>
public CharRange CurrentError
{
get { return _Errors[_ErrorIndex]; }
}
public bool DidCorrectSpelling = false; // B2015-024 have Spell Checker text changes be in editorial mode (not assign a change bar but keep existing change bar)
public VlnSpellCheckDlg()
{
InitializeComponent();
}
/// <summary>
/// Initializes the dialog to use the given parameters.
/// </summary>
/// <param name="spell"><see cref="C1SpellChecker"/> to use for spelling.</param>
/// <param name="editor"><see cref="ISpellCheckableEditor"/> that contains the text to spell-check.</param>
/// <param name="errors"><see cref="CharRangeList"/> that contains the initial error list.</param>
public void Initialize(C1SpellChecker spell, ISpellCheckableEditor editor, CharRangeList errors)
{
_Spell = spell;
_Editor = editor;
_Errors = errors;
if (_Errors == null)
{
_Errors = _Spell.CheckText(_Editor.Text);
}
_ErrorCount += _Errors.Count;
btnAddToDictionary.Visible = _Spell.UserDictionary.Enabled;
}
/// <summary>
/// Gets the total number of errors detected in the control.
/// </summary>
public int ErrorCount
{
get { return _ErrorCount; }
}
/// <summary>
/// Gets or sets the index of the current error into the <see cref="Errors"/> list.
/// </summary>
public int ErrorIndex
{
get { return _ErrorIndex; }
set
{
_ErrorIndex = value;
UpdateCurrentError();
}
}
private void UpdateEditor(string replacement)
{
DidCorrectSpelling = true;
// save starting point to continue checking from here
int start = CurrentError.Start;
if (replacement.Length == 0)
{
// if replacement is empty, expand over spaces and commas
CharRange delete = CharRange.ExpandOverWhitespace(_Editor.Text, CurrentError);
_Editor.Select(delete.Start, delete.Text.Length);
}
// replace word in text and re-check
_Editor.SelectedText = replacement;
_Errors = _Spell.CheckText(_Editor.Text, start);
// update index
ErrorIndex = ErrorIndex; // originally 0;
}
/// <summary>
/// Raises the <see cref="Form.Load"/> event.
/// </summary>
/// <param name="e"><see cref="EventArgs"/> that contains the event data.</param>
protected override void OnLoad(EventArgs e)
{
// fire load event
base.OnLoad(e);
//AddHandle();
// show first error (after firing load event)
ErrorIndex = 0;
}
// added for debugging - comment out when not using
//public void AddHandle()
//{
// if (!Handles.Contains(this.Handle))
// {
// GC.Collect();
// Handles.Add(this.Handle);
// Console.WriteLine("Handles {0}, RTB Count Created {1}, RTB Count Not Disposed = {2} ", Handles.Count,StepRTB.CountCreated,StepRTB.CountNotDisposed);
// }
//}
//private static List<IntPtr> Handles = new List<IntPtr>();
private bool _Initializing = false;
private string _OrgWord;
// update dialog to show current error
private void UpdateCurrentError()
{
// design time
if (DesignMode || _Errors == null)
{
return;
}
// finished with this batch of errors
if (ErrorIndex >= _Errors.Count)
{
// check whether the editor has more text to check
while (_Editor.HasMoreText())
{
_Errors = _Spell.CheckText(_Editor.Text);
if (_Errors.Count > 0)
{
_ErrorCount += _Errors.Count;
ErrorIndex = 0;
return;
}
}
// editor has no more text...
DialogResult = DialogResult.OK;
return;
}
// update current error
CharRange err = CurrentError;
// select word in editor
_Editor.Select(err.Start, err.Text.Length);
// honor 'change all' list
if (_changeAll.ContainsKey(err.Text))
{
txbBadWord.Text = _changeAll[err.Text];
btnChange_Click(this, EventArgs.Empty);
return;
}
_Initializing = true;
// show bad word, new text
txbBadWord.Text = _OrgWord = err.Text;
// repeated word?
if (err.Duplicate)
{
// adjust dialog
lblNotInDictionary.Text = "Duplicate Word";
btnIgnoreAll.Enabled = false;
btnAddToDictionary.Enabled = false;
btnRemove.Enabled = true;
// no suggestions
lbSuggestList.Items.Clear();
}
else
{
// adjust dialog
lblNotInDictionary.Text = "Not In Dictionary";
btnIgnoreAll.Enabled = true;
btnAddToDictionary.Enabled = true;
btnRemove.Enabled = false;
SetupSuggestions(err.Text);
}
// focus to new word
_AutoSuggest = false;
txbBadWord.SelectAll();
txbBadWord.Focus();
_AutoSuggest = true;
AcceptButton = btnIgnore;
// show 'Add' button only if user dictionary is enabled
btnAddToDictionary.Visible = _Spell.UserDictionary.Enabled;
// all ready, fire ErrorDisplayed event
//OnErrorDisplayed(EventArgs.Empty);
}
private void SetupSuggestions(string badWord)
{
// show suggestions
_Initializing = true;
string[] suggestions = _Spell.GetSuggestions(badWord);
lbSuggestList.Items.Clear();
if (suggestions.Length > 0)
{
lbSuggestList.Items.AddRange(suggestions);
lbSuggestList.SelectedIndex = -1;
lbSuggestList.Enabled = true;
}
else
{
lbSuggestList.Items.Add(_NoSuggestionsText);
lbSuggestList.SelectedIndex = -1;
lbSuggestList.Enabled = false;
}
_Initializing = false;
}
private void txbBadWord_TextChanged(object sender, EventArgs e)
{
btnChange.Enabled = (_OrgWord != txbBadWord.Text);
btnChangeAll.Enabled = btnChange.Enabled && lblNotInDictionary.Text == "Not In Dictionary";
btnAddToDictionary.Enabled = _Spell.UserDictionary.Enabled && !InDictionary(txbBadWord.Text);
if (_AutoSuggest && !_Initializing)
{
SetupSuggestions(txbBadWord.Text);
}
}
private bool InDictionary(string word)
{
if (_Spell.MainDictionary.Contains(word))
return true;
if (_Spell.CustomDictionary != null && _Spell.CustomDictionary.Contains(word))
return true;
if (_Spell.UserDictionary != null && _Spell.UserDictionary.Contains(word))
return true;
return false;
}
private void btnChange_Click(object sender, EventArgs e)
{
UpdateEditor(txbBadWord.Text);
}
private void btnChangeAll_Click(object sender, EventArgs e)
{
_changeAll[CurrentError.Text] = txbBadWord.Text;
UpdateEditor(txbBadWord.Text);
}
private void btnIgnore_Click(object sender, EventArgs e)
{
ErrorIndex++;
}
private void btnIgnoreAll_Click(object sender, EventArgs e)
{
//Console.WriteLine("handle: {0}", this.Handle);
_Spell.IgnoreList.Add(CurrentError.Text);
_Errors = _Spell.CheckText(_Editor.Text, CurrentError.Start);
UpdateCurrentError();
}
private void btnAddToDictionary_Click(object sender, EventArgs e)
{
_Spell.UserDictionary.AddWord(CurrentError.Text);
_Errors = _Spell.CheckText(_Editor.Text, CurrentError.Start);
ErrorIndex = 0;
}
private void lbSuggestList_SelectedIndexChanged(object sender, EventArgs e)
{
_AutoSuggest = false;
if (!_Initializing && lbSuggestList.Text != _NoSuggestionsText)
txbBadWord.Text = lbSuggestList.Text;
_AutoSuggest = true;
}
// double-click selects word for suggestion list and changes mis-spelled word
private void lbSuggestList_DoubleClick(object sender, EventArgs e)
{
if (txbBadWord.Text == lbSuggestList.Text)
{
UpdateEditor(txbBadWord.Text);
}
}
private void btnRemove_Click(object sender, EventArgs e)
{
UpdateEditor("");
}
}
}