Knowledgebase Home Page  >  RapidSpell Desktop .NET  >  Behavior Customization
Search the Knowledge Base
How can I implement Undo functionality in RapidSpell Dialog (RapidSpellGUI)? (C#, VB.NET)
https://keyoti.com/kb/Default.aspx?ToDo=view&questId=112&catId=62

Options

Print this page
Email this to a friend
By subclassing RapidSpellGUI, it is possible to modify standard behaviour and add new behavior.  In this example we add undo functionality to RapidSpellGUI and then use this new RapidSpellGUI with RapidSpellDialog.
 
 
Important note: this code is provided as-is, it should not be considered fully tested and is provided without any warranty.  If you plan to use it for production you must fully test it!
 
 
 
Step 1. add a new file to your project and paste this content
 
C#
 

using Keyoti.RapidSpell;

using System;

using System.Collections;

using System.Drawing;

using System.Windows.Forms;

class CustomUserInterfaceFormProvider : IUserInterfaceFormProvider

{

public IUserInterfaceForm CreateUserInterfaceForm(){ return new CustomGUI(); }

}

public class CustomGUI : RapidSpellGUI

{

Button undoButton = new Button();

RapidSpellChecker theCheckerEngine = null;

ArrayList stateHistory;

//retreives the CheckerEngine cast as RapidSpellChecker.

RapidSpellChecker RSCEngine

{

get

{

if(theCheckerEngine==null)

theCheckerEngine = (RapidSpellChecker) CheckerEngine;

return theCheckerEngine;

}

}

protected override void Dispose(bool disposing)

{

undoButton.Click -= new EventHandler(Undo);

base.Dispose(disposing);

}

 

/// <summary>

/// Called when starting a text box

/// </summary>

public override void Check()

{

//reset everything

theCheckerEngine = null;

stateHistory = new ArrayList();

undoButton.Enabled = false;

base.Check();

}

protected override void BuildGUI()

{

base.BuildGUI();

Size = new Size(Size.Width, Size.Height + 15);

undoButton.Text = "Undo";

undoButton.Location = new Point(225, 220);

undoButton.Size = this.defaultButtonSize;

undoButton.TabIndex=8;

undoButton.Click += new EventHandler(Undo);

undoButton.Enabled = false;

Controls.Add(undoButton);

}

 

protected override void Ignore()

{

OnStateChange(Action.Ignore);

base.Ignore();

}

protected override void IgnoreAll()

{

OnStateChange(Action.IgnoreAll);

base.IgnoreAll();

}

protected override void ChangeWord()

{

OnStateChange(Action.Change);

base.ChangeWord();

}

protected override void ChangeAll()

{

OnStateChange(Action.ChangeAll);

base.ChangeAll();

}

void OnStateChange(Action action)

{

stateHistory.Add(new State(

this.theTextComponent.Text,

action,

theBadWord.StartPosition,

theBadWord.GetWord(),

this.subFromPosition,

this.subToPosition,

this.wrapped

));

undoButton.Enabled = true;

}

void ApplyState(State state)

{

this.theTextComponent.Text = state.Text;

this.RSCEngine.Check (state.Text.Substring(

state.SubFromPosition, (state.SubToPosition-state.SubFromPosition)),

state.CurrentWordPointer );

this.wrapped = state.Wrapped;

this.subFromPosition = state.SubFromPosition;

this.subToPosition = state.SubToPosition;

}

protected virtual void Undo(object sender, EventArgs e)

{

//get the state before

State priorState = (State) stateHistory[stateHistory.Count-1];

if(priorState.LeaveAction == Action.IgnoreAll)

this.RSCEngine.IgnoreList.Remove(priorState.LeaveActionWord);

ApplyState(priorState);

this.Resume();

//remove the prior state

stateHistory.RemoveAt(stateHistory.Count-1);

if(stateHistory.Count==0)

undoButton.Enabled = false;

 

}

class State

{

/// <summary>

/// The text in the text box.

/// </summary>

public string Text;

/// <summary>

/// The action that caused this state to change.

/// </summary>

public Action LeaveAction;

/// <summary>

/// The word associated with the action (ie. the ignored/added word).

/// </summary>

public string LeaveActionWord;

/// <summary>

/// Where in the text the engine has reached.

/// </summary>

public int CurrentWordPointer;

/// <summary>

/// Where to spell checker will check to

/// </summary>

public int SubToPosition;

/// <summary>

/// Where to spell checker will check from

/// </summary>

public int SubFromPosition;

/// <summary>

/// Whether the check has wrapped

/// </summary>

public bool Wrapped;

public State(string text, Action leaveAction, int currentWordPointer, string leaveActionWord, int subFromPosition, int subToPosition, bool wrapped)

{

this.Text = text;

this.LeaveAction = leaveAction;

this.CurrentWordPointer = currentWordPointer;

this.LeaveActionWord = leaveActionWord;

this.SubFromPosition = subFromPosition;

this.SubToPosition = subToPosition;

this.Wrapped = wrapped;

}

}

enum Action

{

Ignore,

IgnoreAll,

Change,

ChangeAll

}

}

 

 

VB.NET

Imports Keyoti.RapidSpell

Imports System

Imports System.Collections

Imports System.Drawing

Imports System.Windows.Forms

_

Class CustomUserInterfaceFormProvider

Implements IUserInterfaceFormProvider

Public Function CreateUserInterfaceForm() As IUserInterfaceForm Implements IUserInterfaceFormProvider.CreateUserInterfaceForm

Return New CustomGUI

End Function 'CreateUserInterfaceForm

End Class 'CustomUserInterfaceFormProvider

_

Public Class CustomGUI

Inherits RapidSpellGUI

Private undoButton As New Button

Private theCheckerEngine As RapidSpellChecker = Nothing

Private stateHistory As ArrayList

'retreives the CheckerEngine cast as RapidSpellChecker.

ReadOnly Property RSCEngine() As RapidSpellChecker

Get

If theCheckerEngine Is Nothing Then

theCheckerEngine = CType(CheckerEngine, RapidSpellChecker)

End If

Return theCheckerEngine

End Get

End Property

 

Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)

RemoveHandler undoButton.Click, AddressOf Undo

MyBase.Dispose(disposing)

End Sub 'Dispose

 

 

'/ <summary>

'/ Called when starting a text box

'/ </summary>

Public Overloads Overrides Sub Check()

'reset everything

theCheckerEngine = Nothing

stateHistory = New ArrayList

undoButton.Enabled = False

MyBase.Check()

End Sub 'Check

 

 

Protected Overrides Sub BuildGUI()

MyBase.BuildGUI()

Size = New Size(Size.Width, Size.Height + 15)

undoButton.Text = "Undo"

undoButton.Location = New Point(225, 220)

undoButton.Size = Me.defaultButtonSize

undoButton.TabIndex = 8

AddHandler undoButton.Click, AddressOf Undo

undoButton.Enabled = False

Controls.Add(undoButton)

End Sub 'BuildGUI

 

 

Protected Overrides Sub Ignore()

OnStateChange(Action.Ignore)

MyBase.Ignore()

End Sub 'Ignore

 

Protected Overrides Sub IgnoreAll()

OnStateChange(Action.IgnoreAll)

MyBase.IgnoreAll()

End Sub 'IgnoreAll

 

Protected Overrides Sub ChangeWord()

OnStateChange(Action.Change)

MyBase.ChangeWord()

End Sub 'ChangeWord

 

Protected Overrides Sub ChangeAll()

OnStateChange(Action.ChangeAll)

MyBase.ChangeAll()

End Sub 'ChangeAll

 

Sub OnStateChange(ByVal action As Action)

stateHistory.Add(New State(Me.theTextComponent.Text, action, theBadWord.StartPosition, theBadWord.GetWord(), Me.subFromPosition, Me.subToPosition, Me.wrapped))

undoButton.Enabled = True

End Sub 'OnStateChange

 

Sub ApplyState(ByVal state As State)

Me.theTextComponent.Text = state.Text

Me.RSCEngine.Check(state.Text.Substring(state.SubFromPosition, state.SubToPosition - state.SubFromPosition), state.CurrentWordPointer)

Me.wrapped = state.Wrapped

Me.subFromPosition = state.SubFromPosition

Me.subToPosition = state.SubToPosition

End Sub 'ApplyState

 

Protected Overridable Sub Undo(ByVal sender As Object, ByVal e As EventArgs)

'get the state before

Dim priorState As State = CType(stateHistory((stateHistory.Count - 1)), State)

If priorState.LeaveAction = Action.IgnoreAll Then

Me.RSCEngine.IgnoreList.Remove(priorState.LeaveActionWord)

End If

ApplyState(priorState)

Me.Resume()

'remove the prior state

stateHistory.RemoveAt((stateHistory.Count - 1))

If stateHistory.Count = 0 Then

undoButton.Enabled = False

End If

End Sub 'Undo

_

Class State

'/ <summary>

'/ The text in the text box.

'/ </summary>

Public [Text] As String

'/ <summary>

'/ The action that caused this state to change.

'/ </summary>

Public LeaveAction As Action

'/ <summary>

'/ The word associated with the action (ie. the ignored/added word).

'/ </summary>

Public LeaveActionWord As String

'/ <summary>

'/ Where in the text the engine has reached.

'/ </summary>

Public CurrentWordPointer As Integer

'/ <summary>

'/ Where to spell checker will check to

'/ </summary>

Public SubToPosition As Integer

'/ <summary>

'/ Where to spell checker will check from

'/ </summary>

Public SubFromPosition As Integer

'/ <summary>

'/ Whether the check has wrapped

'/ </summary>

Public Wrapped As Boolean

 

Public Sub New(ByVal [text] As String, ByVal leaveAction As Action, ByVal currentWordPointer As Integer, ByVal leaveActionWord As String, ByVal subFromPosition As Integer, ByVal subToPosition As Integer, ByVal wrapped As Boolean)

Me.Text = [text]

Me.LeaveAction = leaveAction

Me.CurrentWordPointer = currentWordPointer

Me.LeaveActionWord = leaveActionWord

Me.SubFromPosition = subFromPosition

Me.SubToPosition = subToPosition

Me.Wrapped = wrapped

End Sub 'New

End Class 'State

_

Enum Action

Ignore

IgnoreAll

Change

ChangeAll

End Enum 'Action

End Class 'CustomGUI

 

this file includes a subclass of RapidSpellGUI which adds an undo button and methods to support it, it overrides the ignore/change actions to record an undo history.

 

Step 2. Use this with RapidSpellDialog by specifying a UserInterfaceFormProvider

C#

private void OnCheckSpellingClicked(object sender, System.EventArgs e) {

    //Make RapidSpellDialog use our custom user interface

    this.rapidSpellDialog1.UserInterfaceFormProvider = new CustomUserInterfaceFormProvider();

    this.rapidSpellDialog1.Check();

}

 

VB.NET

Private Sub CheckSpelling_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MenuItem2.Click

    'Make RapidSpellDialog use our custom user interface (as returned by CustomUserinterfaceFormProvider)

    Me.RapidSpellDialog1.UserInterfaceFormProvider = New CustomUserInterfaceFormProvider

    Me.RapidSpellDialog1.Check()

End Sub

 

To understand more about how this works we suggest you also see the CustomGUI example project, and the user guide section on custom user interfaces.

If you experience any problems with this code, or have questions - please email support@keyoti.com


Related Questions:

Attachments:

No attachments were found.