/* Jazzy - a Java library for Spell Checking Copyright (C) 2001 Mindaugas Idzelis Full text of license can be found in LICENSE.txt This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ package com.swabunga.spell.swing; import java.awt.Component; import java.awt.Dialog; import java.awt.Frame; import java.awt.Window; import java.io.File; import java.io.IOException; import java.util.Locale; import java.util.ResourceBundle; import javax.swing.JEditorPane; import javax.swing.SwingUtilities; import javax.swing.text.Document; import javax.swing.text.EditorKit; import javax.swing.text.JTextComponent; import javax.swing.text.StyledEditorKit; import com.swabunga.spell.engine.SpellDictionary; import com.swabunga.spell.engine.SpellDictionaryCachedDichoDisk; import com.swabunga.spell.engine.SpellDictionaryHashMap; import com.swabunga.spell.event.DocumentWordTokenizer; import com.swabunga.spell.event.SpellCheckEvent; import com.swabunga.spell.event.SpellCheckListener; import com.swabunga.spell.event.SpellChecker; import com.swabunga.spell.swing.autospell.AutoSpellCheckHandler; import com.swabunga.spell.swing.autospell.AutoSpellEditorKit; /** * This class spellchecks a JTextComponent throwing up a Dialog everytime it encounters a misspelled word. * * @author Robert Gustavsson (robert@lindesign.se) */ public class JTextComponentSpellChecker implements SpellCheckListener { // private static final String COMPLETED="COMPLETED"; private String dialogTitle = null; private SpellChecker spellCheck = null; private JSpellDialog dlg = null; private JTextComponent textComp = null; private ResourceBundle messages; private SpellDictionary mainDict = null; private AutoSpellCheckHandler markHandler; // Constructor public JTextComponentSpellChecker(SpellDictionary dict) { this(dict, null, null); } // Convinient Constructors, for those lazy guys. public JTextComponentSpellChecker(String dictFile) throws IOException { this(dictFile, null); } public JTextComponentSpellChecker(String dictFile, String title) throws IOException { this(new SpellDictionaryHashMap(new File(dictFile)), null, title); } public JTextComponentSpellChecker(String dictFile, String phoneticFile, String title) throws IOException { this(new SpellDictionaryHashMap(new File(dictFile), new File(phoneticFile)), null, title); } public JTextComponentSpellChecker(SpellDictionary dict, SpellDictionary userDict, String title) { spellCheck = new SpellChecker(dict); mainDict = dict; spellCheck.setCache(); if (userDict != null) { spellCheck.setUserDictionary(userDict); } spellCheck.addSpellCheckListener(this); dialogTitle = title; messages = ResourceBundle.getBundle("com.swabunga.spell.swing.messages", Locale.getDefault()); markHandler = new AutoSpellCheckHandler(spellCheck, messages); } // MEMBER METHODS /** * Set user dictionary (used when a word is added) */ public void setUserDictionary(SpellDictionary dictionary) { if (spellCheck != null) { spellCheck.setUserDictionary(dictionary); } } private void setupDialog(JTextComponent textComp) { Component comp = SwingUtilities.getRoot(textComp); // Probably the most common situation efter the first time. if (dlg != null && dlg.getOwner() == comp) { return; } if (comp != null && comp instanceof Window) { if (comp instanceof Frame) { dlg = new JSpellDialog((Frame) comp, dialogTitle, true); } if (comp instanceof Dialog) { dlg = new JSpellDialog((Dialog) comp, dialogTitle, true); } // Put the dialog in the middle of it's parent. if (dlg != null) { Window win = (Window) comp; int x = (int) (win.getLocation().getX() + win.getWidth() / 2 - dlg.getWidth() / 2); int y = (int) (win.getLocation().getY() + win.getHeight() / 2 - dlg.getHeight() / 2); dlg.setLocation(x, y); } } else { dlg = new JSpellDialog((Frame) null, dialogTitle, true); } } /** * This method is called to check the spelling of a JTextComponent. * * @param textComp * The JTextComponent to spellcheck. * @return Either SpellChecker.SPELLCHECK_OK, SpellChecker.SPELLCHECK_CANCEL or the number of errors found. The number of errors are * those that are found BEFORE any corrections are made. */ public synchronized int spellCheck(JTextComponent textComp) { setupDialog(textComp); this.textComp = textComp; DocumentWordTokenizer tokenizer = new DocumentWordTokenizer(textComp.getDocument()); int exitStatus = spellCheck.checkSpelling(tokenizer); textComp.requestFocusInWindow(); textComp.setCaretPosition(0); this.textComp = null; try { if (mainDict instanceof SpellDictionaryCachedDichoDisk) { ((SpellDictionaryCachedDichoDisk) mainDict).saveCache(); } } catch (IOException ex) { System.err.println(ex.getMessage()); } return exitStatus; } /** * * @param pane */ public void startAutoSpellCheck(JEditorPane pane) { Document doc = pane.getDocument(); pane.setEditorKit(new AutoSpellEditorKit((StyledEditorKit) pane.getEditorKit())); pane.setDocument(doc); markHandler.addJEditorPane(pane); } /** * * @param pane */ public void stopAutoSpellCheck(JEditorPane pane) { EditorKit kit; Document doc; if (pane.getEditorKit() instanceof com.swabunga.spell.swing.autospell.AutoSpellEditorKit) { doc = pane.getDocument(); kit = ((com.swabunga.spell.swing.autospell.AutoSpellEditorKit) pane.getEditorKit()).getStyledEditorKit(); pane.setEditorKit(kit); pane.setDocument(doc); } markHandler.removeJEditorPane(pane); } /** * */ @Override public void spellingError(SpellCheckEvent event) { // java.util.List suggestions = event.getSuggestions(); event.getSuggestions(); int start = event.getWordContextPosition(); int end = start + event.getInvalidWord().length(); // Mark the invalid word in TextComponent textComp.requestFocusInWindow(); textComp.setCaretPosition(0); textComp.setCaretPosition(start); textComp.moveCaretPosition(end); dlg.show(event); } }