JDialog Modal Window Iterations

I am developing a spell checking program that grabs its text from an Oracle Form. I need to make the spellchecker window modal so that a user can only press the "spell check" button once and not return to the main program until the spell check app has completed.

The spell check window is created once and changes each time a mispelled word is enountered. If I use setModal(true) then I must set the window to be visible/invisible between words causing the spell check window to blink. Otherwise the spell check window only stops at the last mispelled word. To get around this I have taken modal off and placed the window in a thread and stopped it between words. I included a window listener to request focus back to the spell check window in case it is deactivated or another window is clicked. But this still allows a tenacious user to click on the background form or spell check button while the spell check window is obtaining the focus (rapid multiple clicks will eventually select functions behind the spell check window).

What I need is a modal window that does not blink and waits for a command with each word.

publicvoid spellingError(SpellCheckEvent event){

spellEvent = event;

String badword = spellEvent.getInvalidWord();

//Highlight the mispelled word

txtSpellCheck.requestFocus();

txtSpellCheck.setCaretPosition(spellEvent.getWordContextPosition());

txtSpellCheck.moveCaretPosition(spellEvent.getWordContextPosition() + badword.length());

DefaultListModel m =new DefaultListModel();

//Get the Suggestions

List suggestions = event.getSuggestions();

//Test word for all Caps

char[] testWord = badword.toCharArray();

boolean capWord =true;

for (int i = 0; i < testWord.length && capWord; i++)

capWord = capWord && Character.isUpperCase(badword.charAt(i));

boolean cap =

(!spellCheck.getConfiguration().getBoolean(Configuration.SPELL_IGNOREUPPERCASE) && capWord);

//If mispelled word is all Caps, Capitalize the Suggestions

if (cap){

Iterator iterator = suggestions.iterator();

while (iterator.hasNext()){

Word word = (Word)iterator.next();

String suggestion = word.getWord();

word.setWord(suggestion.toUpperCase());

}

}

//Add Suggestions to the List

for (int i = 0; i < suggestions.size(); i++){

m.addElement(suggestions.get(i));

}

lstSuggestions.setModel(m);

lblBadWord.setText("Mispelled Word: " + event.getInvalidWord());

if (m.size() > 0){

lstSuggestions.setSelectedIndex(0);

txtWord.setText(((Word)m.get(0)).getWord());

}else{

txtWord.setText(event.getInvalidWord());

}

if (spellErrors == 1) this.setVisible(true);

//Stops application between Spelling Errors

synchronized (this){

try{

this.wait();

}catch (InterruptedException e){

}

}

}

/**

* Handles all button actions

* Parses by Action Command to execute corresponding Action

* @param e

*/

publicvoid actionPerformed(ActionEvent e){

try{

if (IGNORE_CMD.equals(e.getActionCommand())){

spellEvent.ignoreWord(false);

}elseif (IGNOREALL_CMD.equals(e.getActionCommand())){

spellEvent.ignoreWord(true);

}elseif (REPLACE_CMD.equals(e.getActionCommand())){

spellEvent.replaceWord(txtWord.getText(),false);

this.spellCorrection(spellEvent);

}elseif (REPLACEALL_CMD.equals(e.getActionCommand())){

spellEvent.replaceWord(txtWord.getText(),true);

this.spellCorrection(spellEvent);

}elseif (ADD_CMD.equals(e.getActionCommand())){

String inField = txtWord.getText();

Object selObj = lstSuggestions.getSelectedValue();

String selected = (selObj ==null ?"" : selObj.toString());

String addString = (inField.equals(selected) ? spellEvent.getInvalidWord() : inField);

top =false;

int n =

JOptionPane.showConfirmDialog(this, messages.getString(ADDWORD_1) +" '" + addString +

"' " + messages.getString(ADDWORD_2),

messages.getString(ADDWORD_3), JOptionPane.YES_NO_OPTION);

top =true;

this.requestFocus();

if (n == JOptionPane.YES_OPTION){

spellEvent.addToDictionary(addString);

}else{

return;

}

this.requestFocus();

}elseif (CANCEL_CMD.equals(e.getActionCommand())){

spellEvent.cancel();

this.dispose();

}elseif (DONE_CMD.equals(e.getActionCommand())){

callback.setLwtext(txtSpellCheck.getText());

spellEvent.cancel();

this.dispose();

}

//Resumes application

synchronized (this){

this.notify();

this.repaint();

}

fireActionEvent(e);

}catch (IllegalStateException state){

//Closes Application, writes changes if the DONE button was pressed

btnChange.setEnabled(false);

btnChangeAll.setEnabled(false);

btnIgnore.setEnabled(false);

btnIgnoreAll.setEnabled(false);

btnAdd.setEnabled(false);

lstSuggestions.setEnabled(false);

txtWord.setEnabled(false);

if (DONE_CMD.equals(e.getActionCommand())){

callback.setLwtext(txtSpellCheck.getText());

this.dispose();

}elseif (CANCEL_CMD.equals(e.getActionCommand())){

this.dispose();

}

}

}

[9114 byte] By [thebigredbuttona] at [2007-11-26 14:52:45]
# 1
Sorry forgot to mention we are running java 1.3 (sorry)
thebigredbuttona at 2007-7-8 8:40:59 > top of Java-index,Desktop,Core GUI APIs...
# 2

> The spell check window is created once and changes each time a

> mispelled word is enountered. If I use setModal(true) then I must set

> the window to be visible/invisible between words causing the spell check window to blink

I really don't understand the process you are trying to describe here and the code you posted doesn't help.

I don't see your problem. Here is a simple find/replace dialog (that can be made modal by adding the setModal(true) method in the showReplace() method).

http://forum.java.sun.com/thread.jspa?forumID=57&threadID=583655

You hit the find button and it highlights the text. Then you either use the replace button or the find button to continue.

I don't see how your process is any different you find a missssspelt word and then don't continue until the user enters a new spelling and then hits the replace button. I don't see the problem in making the window modal.

If you need further help then you need to create a [url http://homepage1.nifty.com/algafield/sscce.html]Short, Self Contained, Compilable and Executable, Example Program[/url] (SSCCE) that demonstrates the incorrect behaviour, because I can't guess exactly what you are doing based on the information provided.

And don't forget to use the [url http://forum.java.sun.com/help.jspa?sec=formatting]Code Formatting Tags[/url] so the code retains its original formatting.

camickra at 2007-7-8 8:40:59 > top of Java-index,Desktop,Core GUI APIs...
# 3

What you want to do is to put your spell checking code in a separate thread. From the event dispatching thread, start up another thread which executes the spell checking code, then display your modal dialog. The first thread blocks until the dialog is made invisible. When a misspelled word is encountered in the spell checking thread, update the dialog box by using EventQueue.invokeLater():

EventQueue.invokeLater(new Runnable() {

public void run() {

... update the dialog box ...

}

});

And when you are done spell checking, use the same technique to hide the dialog box:

EventQueue.invokeLater(new Runnable() {

public void run() {

dialogBox.setVisible(false);

}

});

That will unblock your original thread. At that point the spell checking thread can terminate.

Hope that helps...

Geoff

glevnera at 2007-7-8 8:40:59 > top of Java-index,Desktop,Core GUI APIs...
# 4

Thanks for the info, it sounds like this will work but I am not completely sure that I understand where to place this event code. I can move the Spell Check Listener to be interfaced in another class if need be. I am attaching the complete code that I have currently. If you could please give me a little more insight into where I should place these threads, listeners, and event queues I would greatly appreciate it.

This spell checker is based on Jazzy Spell Checker.

This class is just a gui form thrown together for testing, this will be replaced by a Oracle Form.

package spellchecker;

import java.awt.BorderLayout;

import java.awt.Dimension;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import java.awt.event.WindowAdapter;

import java.awt.event.WindowEvent;

import javax.swing.JButton;

import javax.swing.JFrame;

import oracle.forms.ui.VTextArea;

public class SpellBox extends JFrame {

private BorderLayout borderLayout1 = new BorderLayout();

private JButton btnSpellCheck = new JButton();

private VTextArea txtSpellCheck = new VTextArea();

private SpellCheckThis checkit = new SpellCheckThis();

public SpellBox() {

setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

addWindowListener(new WindowAdapter() {

public void windowClosed(WindowEvent e) {

System.exit(0);

}

});

try {

jbInit();

} catch (Exception e) {

e.printStackTrace();

}

}

public static void main(String[] args) {

SpellBox app = new SpellBox();

System.out.println("Showing form");

app.setVisible(true);

}

private void jbInit() throws Exception {

this.setSize(new Dimension(642, 334));

this.setLayout(borderLayout1);

this.setResizable(false);

this.setLocation(350, 350);

btnSpellCheck.setText("Spell Check That Thang!");

this.add(btnSpellCheck, BorderLayout.NORTH);

this.getContentPane().add(txtSpellCheck, BorderLayout.CENTER);

btnSpellCheck.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent e) {

checkit.spellCheck(txtSpellCheck);

}

});

}

}

This class will become an implimentation class for an Oracle Form

package spellchecker;

import com.swabunga.spell.engine.SpellDictionary;

import com.swabunga.spell.engine.SpellDictionaryHashMap;

import com.swabunga.spell.event.SpellCheckEvent;

import com.swabunga.spell.event.SpellCheckListener;

import com.swabunga.spell.event.SpellChecker;

import com.swabunga.spell.event.StringWordTokenizer;

import java.awt.Color;

import java.awt.Cursor;

import java.awt.FontMetrics;

import java.awt.Graphics;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import java.awt.event.TextEvent;

import java.awt.event.TextListener;

import java.io.File;

import java.util.StringTokenizer;

import javax.swing.JFrame;

import javax.swing.JOptionPane;

import javax.swing.text.Highlighter;

import jregex.MatchIterator;

import jregex.MatchResult;

import jregex.Matcher;

import jregex.Pattern;

import oracle.ewt.ColorScheme;

import oracle.ewt.lwAWT.LWComponent;

import oracle.ewt.lwAWT.lwText.LWTextArea;

import oracle.ewt.lwAWT.lwText.LWTextComponent;

import oracle.ewt.lwAWT.lwText.SelectionEvent;

import oracle.ewt.lwAWT.lwText.SelectionListener;

import oracle.ewt.painter.PaintContext;

import oracle.ewt.painter.Painter;

import oracle.ewt.painter.TextPainter;

import oracle.forms.handler.TextAreaItem;

import oracle.forms.properties.FormAction;

import oracle.forms.ui.VTextArea;

import oracle.graphics.vgs.ui.Text;

public class SpellCheckThis {

public LWTextArea lwtext = null;

public SpellCheckFrame spellPane = null;

public SpellCheckThis call = this;

public SpellCheckThis() {

}

public void spellCheck(VTextArea txtSpellCheck) {

lwtext = (LWTextArea)txtSpellCheck.getComponent(0);

Thread t = new Thread() {

public void run() {

try {

spellPane = new SpellCheckFrame(lwtext.getText(), call);

if (!spellPane.getErrors())

JOptionPane.showMessageDialog(null, "No Errors Found", "Velocity Spell Check",

JOptionPane.INFORMATION_MESSAGE);

} catch (Exception ex) {

ex.printStackTrace();

}

}

};

t.start();

}

public void setLwtext(String text) {

this.lwtext.setText(text);

}

}

And finally, this is currently the class that does all the displaying and spell checking.

package spellchecker;

import com.swabunga.spell.engine.Configuration;

import com.swabunga.spell.engine.SpellDictionary;

import com.swabunga.spell.engine.SpellDictionaryHashMap;

import com.swabunga.spell.engine.Word;

import com.swabunga.spell.event.SpellCheckEvent;

import com.swabunga.spell.event.SpellCheckListener;

import com.swabunga.spell.event.SpellChecker;

import com.swabunga.spell.event.StringWordTokenizer;

import java.awt.BorderLayout;

import java.awt.Color;

import java.awt.Dimension;

import java.awt.FlowLayout;

import java.awt.Font;

import java.awt.Rectangle;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import java.awt.event.WindowEvent;

import java.io.File;

import java.util.Iterator;

import java.util.List;

import java.util.Locale;

import java.util.ResourceBundle;

import java.util.StringTokenizer;

import javax.swing.BorderFactory;

import javax.swing.DefaultListModel;

import javax.swing.JButton;

import javax.swing.JDialog;

import javax.swing.JFrame;

import javax.swing.JLabel;

import javax.swing.JList;

import javax.swing.JOptionPane;

import javax.swing.JPanel;

import javax.swing.JScrollPane;

import javax.swing.JTextArea;

import javax.swing.JTextField;

import javax.swing.ListSelectionModel;

import javax.swing.border.BevelBorder;

import javax.swing.event.EventListenerList;

import javax.swing.event.ListSelectionEvent;

import javax.swing.event.ListSelectionListener;

import jregex.MatchIterator;

import jregex.MatchResult;

import jregex.Matcher;

import jregex.Pattern;

import nl.jj.swingx.gui.modal.InputBlocker;

public class SpellCheckFrame extends JDialog implements ActionListener, ListSelectionListener, SpellCheckListener {

private static final String dictFile = "english.0";

// private static final File dictFile = new File(VRCFile._LibDir(), "english.0");

public static final String IGNORE_CMD = "IGNORE";

public static final String IGNOREALL_CMD = "IGNOREALL";

public static final String ADD_CMD = "ADD";

public static final String REPLACE_CMD = "REPLACE";

public static final String REPLACEALL_CMD = "REPLACEALL";

public static final String CANCEL_CMD = "CANCEL";

public static final String DONE_CMD = "DONE";

public static final String ADDWORD_1 = "ADDWORD_1";

public static final String ADDWORD_2 = "ADDWORD_2";

public static final String ADDWORD_3 = "ADDWORD_3";

private boolean errors = false;

private boolean top = true;

private int spellErrors = 0;

private BorderLayout borderLayout1 = new BorderLayout();

private JPanel pnlWord = new JPanel();

private JPanel pnlOptions = new JPanel();

private JPanel pnlSuggestions = new JPanel();

private JLabel lblBadWord = new JLabel();

private JButton btnChange = new JButton();

private JButton btnChangeAll = new JButton();

private JButton btnIgnore = new JButton();

private JButton btnIgnoreAll = new JButton();

private JButton btnAdd = new JButton();

private JButton btnCancel = new JButton();

private JLabel lblSuggestions = new JLabel();

private JList lstSuggestions = new JList();

private SpellCheckEvent spellEvent = null;

private SpellCheckThis callback;

// private VSpellChecker callback;

private JTextArea txtSpellCheck = new JTextArea();

private JTextField txtWord = new JTextField();

private FlowLayout flowLayout1 = new FlowLayout();

private FlowLayout flowLayout2 = new FlowLayout();

private FlowLayout flowLayout3 = new FlowLayout();

private JButton btnDone = new JButton();

private JScrollPane scrollList = null;

private JScrollPane scrollPanel = null;

protected ResourceBundle messages;

protected EventListenerList listenerList = new EventListenerList();

public SpellChecker spellCheck = null;

/**

* Opens the Velocity Spell Check Interface and checks the spelling of the text passed to it

* @param text

* @param callback

*/

public SpellCheckFrame(String text, SpellCheckThis callback) {

txtSpellCheck.setText(text);

this.setModal(true);

//Set the Rows for the JTextArea for Scrolling

StringTokenizer tok = new StringTokenizer(text, "\n");

txtSpellCheck.setRows(tok.countTokens());

//Create backward connection to calling class

this.callback = callback;

try {

jbInit();

} catch (Exception e) {

}

//Set up the Dictionaries and start the Spell Check

messages = ResourceBundle.getBundle("com.swabunga.spell.swing.messages", Locale.getDefault());

try {

SpellDictionary dictionary =

new SpellDictionaryHashMap(new File("C:/java/Jazzy/english.0/" + dictFile));

//SpellDictionary dictionary =

//new SpellDictionaryHashMap(dictFile);

spellCheck = new SpellChecker(dictionary);

spellCheck.setCache();

spellCheck.setUserDictionary(dictionary);

spellCheck.addSpellCheckListener(this);

spellCheck.getConfiguration().setBoolean(Configuration.SPELL_IGNOREUPPERCASE, false);

spellCheck.checkSpelling(new StringWordTokenizer(txtSpellCheck.getText()));

} catch (Exception e) {

e.printStackTrace();

}

}

private void jbInit() throws Exception {

//Set Up JDialog

this.getContentPane().setLayout(borderLayout1);

this.setBackground(new Color(198, 198, 198));

this.setSize(new Dimension(550, 460));

this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

this.setTitle("Velocity Spell Check");

this.setResizable(false);

//this.addWindowListener(new WindowAdapter() {

// public void windowDeactivated(WindowEvent e) {

//this_windowDeactivated(e);

// }

//});

//Create North Panel

pnlWord.setBackground(new Color(231, 231, 231));

pnlWord.setBounds(new Rectangle(0, 0, 395, 100));

pnlWord.setSize(new Dimension(400, 57));

pnlWord.setLayout(flowLayout1);

pnlWord.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));

pnlWord.setMinimumSize(new Dimension(395, 57));

pnlWord.setMaximumSize(new Dimension(400, 57));

pnlWord.setPreferredSize(new Dimension(395, 220));

txtSpellCheck.setLineWrap(true);

txtSpellCheck.setCaret(new SelectionCaret());

txtSpellCheck.setPreferredSize(new Dimension(525, 180));

txtSpellCheck.setSize(new Dimension(525, 180));

txtSpellCheck.setMinimumSize(new Dimension(525, 180));

txtSpellCheck.setMaximumSize(new Dimension(525, 180));

scrollPanel = new JScrollPane(txtSpellCheck);

scrollPanel.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);

scrollPanel.setAutoscrolls(true);

scrollPanel.setPreferredSize(new Dimension(534, 180));

scrollPanel.setSize(new Dimension(534, 180));

scrollPanel.setMaximumSize(new Dimension(534, 180));

scrollPanel.setMinimumSize(new Dimension(534, 180));

lblBadWord.setText("Mispelled Word: ");

lblBadWord.setFont(new Font("Tahoma", 1, 13));

lblBadWord.setPreferredSize(new Dimension(210, 18));

lblBadWord.setSize(new Dimension(210, 18));

lblBadWord.setMinimumSize(new Dimension(210, 18));

lblBadWord.setMaximumSize(new Dimension(210, 18));

txtWord.setPreferredSize(new Dimension(319, 22));

txtWord.setSize(new Dimension(319, 22));

txtWord.setMinimumSize(new Dimension(319, 22));

txtWord.setMaximumSize(new Dimension(319, 22));

txtWord.setBorder(BorderFactory.createLineBorder(Color.black, 1));

pnlWord.add(scrollPanel, null);

pnlWord.add(lblBadWord, null);

pnlWord.add(txtWord, null);

//Create Center Panel

pnlSuggestions.setBackground(new Color(231, 231, 231));

pnlSuggestions.setLayout(flowLayout2);

pnlSuggestions.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));

pnlSuggestions.setPreferredSize(new Dimension(254, 199));

pnlSuggestions.setSize(new Dimension(254, 199));

pnlSuggestions.setMinimumSize(new Dimension(254, 199));

pnlSuggestions.setMaximumSize(new Dimension(254, 199));

lblSuggestions.setText("Suggestions:");

lblSuggestions.setFont(new Font("Tahoma", 1, 13));

lblSuggestions.setPreferredSize(new Dimension(391, 18));

lblSuggestions.setSize(new Dimension(391, 18));

lblSuggestions.setMinimumSize(new Dimension(391, 18));

lblSuggestions.setMaximumSize(new Dimension(391, 18));

lstSuggestions.setValueIsAdjusting(true);

lstSuggestions.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

lstSuggestions.setBorder(BorderFactory.createLineBorder(Color.black, 1));

lstSuggestions.setVisibleRowCount(100);

lstSuggestions.addListSelectionListener(new ListSelectionListener() {

public void valueChanged(ListSelectionEvent e) {

lstSuggestions_valueChanged(e);

}

});

scrollList = new JScrollPane(lstSuggestions);

scrollList.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);

scrollList.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

scrollList.setPreferredSize(new Dimension(391, 174));

scrollList.setSize(new Dimension(391, 174));

scrollList.setMinimumSize(new Dimension(391, 174));

scrollList.setMaximumSize(new Dimension(391, 174));

pnlSuggestions.add(lblSuggestions);

pnlSuggestions.add(scrollList);

//Create East Panel

pnlOptions.setBackground(new Color(198, 198, 198));

pnlOptions.setLayout(flowLayout3);

pnlOptions.setPreferredSize(new Dimension(143, 199));

pnlOptions.setMinimumSize(new Dimension(143, 199));

pnlOptions.setMaximumSize(new Dimension(143, 199));

btnChange.setText("Change");

btnChange.setActionCommand("REPLACE");

btnChange.setPreferredSize(new Dimension(133, 24));

btnChange.setMinimumSize(new Dimension(133, 24));

btnChange.setMaximumSize(new Dimension(133, 24));

btnChange.addActionListener(this);

btnChangeAll.setText("Change All");

btnChangeAll.setActionCommand("REPLACEALL");

btnChangeAll.setPreferredSize(new Dimension(133, 24));

btnChangeAll.setMaximumSize(new Dimension(133, 24));

btnChangeAll.setMinimumSize(new Dimension(133, 24));

btnChangeAll.addActionListener(this);

btnIgnore.setText("Ignore");

btnIgnore.setActionCommand("IGNORE");

btnIgnore.setPreferredSize(new Dimension(133, 24));

btnIgnore.setMaximumSize(new Dimension(133, 24));

btnIgnore.setMinimumSize(new Dimension(133, 24));

btnIgnore.addActionListener(this);

btnIgnoreAll.setText("Ignore All");

btnIgnoreAll.setActionCommand("IGNOREALL");

btnIgnoreAll.setPreferredSize(new Dimension(133, 24));

btnIgnoreAll.setMaximumSize(new Dimension(133, 24));

btnIgnoreAll.setMinimumSize(new Dimension(133, 24));

btnIgnoreAll.addActionListener(this);

btnAdd.setText("Add To Dictionary");

btnAdd.setActionCommand("ADD");

btnAdd.setPreferredSize(new Dimension(133, 24));

btnAdd.setMaximumSize(new Dimension(133, 24));

btnAdd.setMinimumSize(new Dimension(133, 24));

btnAdd.addActionListener(this);

btnCancel.setText("Cancel");

btnCancel.setActionCommand("CANCEL");

btnCancel.setPreferredSize(new Dimension(133, 24));

btnCancel.setMaximumSize(new Dimension(133, 24));

btnCancel.setMinimumSize(new Dimension(133, 24));

btnCancel.addActionListener(this);

btnDone.setText("Done");

btnDone.setActionCommand("DONE");

btnDone.setSize(new Dimension(133, 24));

btnDone.setPreferredSize(new Dimension(133, 24));

btnDone.setMaximumSize(new Dimension(133, 24));

btnDone.setMinimumSize(new Dimension(133, 24));

btnDone.addActionListener(this);

pnlOptions.add(btnChange, null);

pnlOptions.add(btnChangeAll, null);

pnlOptions.add(btnIgnore, null);

pnlOptions.add(btnIgnoreAll, null);

pnlOptions.add(btnAdd, null);

pnlOptions.add(btnCancel, null);

pnlOptions.add(btnDone, null);

//Add Panels to JDialog

this.getContentPane().add(pnlWord, BorderLayout.NORTH);

this.getContentPane().add(pnlSuggestions, BorderLayout.CENTER);

this.getContentPane().add(pnlOptions, BorderLayout.EAST);

}

public void valueChanged(ListSelectionEvent e) {

lstSuggestions_valueChanged(e);

}

private void lstSuggestions_valueChanged(ListSelectionEvent e) {

//Refresh value of the replacing word when selection changes

if ((!e.getValueIsAdjusting()) && (lstSuggestions.getSelectedValue() != null)) {

this.txtWord.setText(lstSuggestions.getSelectedValue().toString());

}

}

public void addActionListener(ActionListener l) {

//Register an action listener

listenerList.add(ActionListener.class, l);

}

public void removeActionListener(ActionListener l) {

//Deregister an action listener

listenerList.remove(ActionListener.class, l);

}

/**

* Called when the Spell Event encounters a mispelled word

* Sets the Mispelled Word and Suggestion List

* @param event

*/

public void spellingError(SpellCheckEvent event) {

spellErrors++;

spellEvent = event;

errors = true;

String badword = spellEvent.getInvalidWord();

//Highlight the mispelled word

txtSpellCheck.requestFocus();

txtSpellCheck.setCaretPosition(0);

txtSpellCheck.setCaretPosition(spellEvent.getWordContextPosition());

txtSpellCheck.moveCaretPosition(spellEvent.getWordContextPosition() + badword.length());

DefaultListModel m = new DefaultListModel();

//Get the Suggestions

List suggestions = event.getSuggestions();

//Test word for all Caps

char[] testWord = badword.toCharArray();

boolean capWord = true;

for (int i = 0; i < testWord.length && capWord; i++)

capWord = capWord && Character.isUpperCase(badword.charAt(i));

boolean cap =

(!spellCheck.getConfiguration().getBoolean(Configuration.SPELL_IGNOREUPPERCASE) && capWord);

//If mispelled word is all Caps, Capitalize the Suggestions

if (cap) {

Iterator iterator = suggestions.iterator();

while (iterator.hasNext()) {

Word word = (Word)iterator.next();

String suggestion = word.getWord();

word.setWord(suggestion.toUpperCase());

}

}

//Add Suggestions to the List

for (int i = 0; i < suggestions.size(); i++) {

m.addElement(suggestions.get(i));

}

lstSuggestions.setModel(m);

lblBadWord.setText("Mispelled Word: " + event.getInvalidWord());

if (m.size() > 0) {

lstSuggestions.setSelectedIndex(0);

txtWord.setText(((Word)m.get(0)).getWord());

} else {

txtWord.setText(event.getInvalidWord());

}

if (spellErrors == 1)this.setVisible(true);

//Stops application between Spelling Errors

synchronized (this) {

try {

this.wait();

} catch (InterruptedException e) {

}

}

}

/**

* Handles all button actions

* Parses by Action Command to execute corresponding Action

* @param e

*/

public void actionPerformed(ActionEvent e) {

try {

if (IGNORE_CMD.equals(e.getActionCommand())) {

spellEvent.ignoreWord(false);

} else if (IGNOREALL_CMD.equals(e.getActionCommand())) {

spellEvent.ignoreWord(true);

} else if (REPLACE_CMD.equals(e.getActionCommand())) {

spellEvent.replaceWord(txtWord.getText(), false);

this.spellCorrection(spellEvent);

} else if (REPLACEALL_CMD.equals(e.getActionCommand())) {

spellEvent.replaceWord(txtWord.getText(), true);

this.spellCorrection(spellEvent);

} else if (ADD_CMD.equals(e.getActionCommand())) {

String inField = txtWord.getText();

Object selObj = lstSuggestions.getSelectedValue();

String selected = (selObj == null ? "" : selObj.toString());

String addString = (inField.equals(selected) ? spellEvent.getInvalidWord() : inField);

top = false;

int n = JOptionPane.showConfirmDialog(this, messages.getString(ADDWORD_1) + " '" + addString +

"' " + messages.getString(ADDWORD_2),

messages.getString(ADDWORD_3), JOptionPane.YES_NO_OPTION);

top = true;

this.requestFocus();

if (n == JOptionPane.YES_OPTION) {

spellEvent.addToDictionary(addString);

} else {

return;

}

this.requestFocus();

} else if (CANCEL_CMD.equals(e.getActionCommand())) {

spellEvent.cancel();

this.dispose();

} else if (DONE_CMD.equals(e.getActionCommand())) {

callback.setLwtext(txtSpellCheck.getText());

spellEvent.cancel();

this.dispose();

}

//Resumes application

synchronized (this) {

this.notify();

}

fireActionEvent(e);

} catch (IllegalStateException state) {

//Closes Application, writes changes if the DONE button was pressed

btnChange.setEnabled(false);

btnChangeAll.setEnabled(false);

btnIgnore.setEnabled(false);

btnIgnoreAll.setEnabled(false);

btnAdd.setEnabled(false);

lstSuggestions.setEnabled(false);

txtWord.setEnabled(false);

if (DONE_CMD.equals(e.getActionCommand())) {

callback.setLwtext(txtSpellCheck.getText());

this.dispose();

} else if (CANCEL_CMD.equals(e.getActionCommand())) {

this.dispose();

}

}

}

protected void fireActionEvent(ActionEvent e) {

// Guaranteed to return a non-null array

Object[] listeners = listenerList.getListenerList();

// Process the listeners last to first, notifying

// those that are interested in this event

for (int i = listeners.length - 2; i >= 0; i -= 2) {

System.out.println(listeners[i].toString());

if (listeners[i] == ActionListener.class) {

((ActionListener)listeners[i + 1]).actionPerformed(e);

}

}

}

/**

* Replaces mispelled word with correct word

* Replaces one word or all words depending on button pressed

* @param event

*/

public void spellCorrection(SpellCheckEvent event) {

String word = event.getInvalidWord();

String correctWord = event.getReplaceWord();

if (event.getAction() == event.REPLACE) {

Pattern p = new Pattern("\\b" + word + "\\b");

Matcher m = p.matcher(txtSpellCheck.getText());

MatchIterator mi = m.findAll();

MatchResult mr = mi.nextMatch();

txtSpellCheck.replaceRange(correctWord, mr.start(), mr.end());

} else if (event.getAction() == event.REPLACEALL) {

txtSpellCheck.setText(new Pattern("\\b" + word + "\\b").replacer(correctWord)

.replace(txtSpellCheck.getText()));

}

// In java 1.4 we could have done this:

//if (event.getAction() == event.REPLACE){

//lwtext.setText(lwtext.getText().replaceFirst("\\b" + word + "\\b", correctWord));

//}else if (event.getAction() == event.REPLACEALL){

//lwtext.setText(lwtext.getText().replaceAll("\\b" + word + "\\b", correctWord));

//}

}

private void this_windowDeactivated(WindowEvent e) {

//Keeps Spell Check Window on top until closed

if (top)

SpellCheckFrame.this.requestFocus();

}

public boolean getErrors() {

return errors;

}

}

thebigredbuttona at 2007-7-8 8:40:59 > top of Java-index,Desktop,Core GUI APIs...
# 5

Yow, that is a lot of code and I don't feel much like reading it! After thinking about it some more, however, I realized that for a spell checker, which is presumably not very compute intensive, you don't even need to worry about creating a second thread.

All you need to do is create a modal dialog box whose various action listeners do the work when the user clicks on a button. To give the user feedback, just update the contents of the dialog box: don't hide it, and don't create a new one. If he clicked on a Next Word button, for example, update the dialog box to show the next misspelled word. When you are done -- there are no more misspelled words, or the user clicked on Done, for example -- just call setVisible(false) to hide the dialog box.

Then to use the spell checker, all the app needs to do is create an instance of your dialog box and show it using setVisible(true). When the spell checker is done and hides itself, execution will continue at the next line.

Hope that's clearer...

Geoff

glevnera at 2007-7-8 8:40:59 > top of Java-index,Desktop,Core GUI APIs...
# 6

Thanks, I don't really feel like reading it much anymore either! Thanks for the advice, the problems I had with the modal was that it was processing to the end and skipping all the words. Part of the problem is how the Jazzy engine works. It fires a new spell event each time and waits for an action, then moves on to the next. The event is great at capturing all the info but doesn't have a function to "move to the next". My next attempt will be to try and capture the events in a collection and iterate though them my own way.

Thanks for the quick responses.

Joe

thebigredbuttona at 2007-7-8 8:40:59 > top of Java-index,Desktop,Core GUI APIs...
# 7

I have found a way that works, I just hope that it will work in Oracle Forms too! For any interested, I used a JModalFrame (part of the modalwindow project on java.net). I changed the JDialog above to a Jpanel and added it to the JModal Frame. This did the trick.

Thanks to all that helped!!

Joe

thebigredbuttona at 2007-7-8 8:40:59 > top of Java-index,Desktop,Core GUI APIs...