Package com.inet.jortho

Source Code of com.inet.jortho.AutoSpellChecker

/*
*  JOrtho
*
*  Copyright (C) 2005-2008 by i-net software
*
*  This program is free software; you can redistribute it and/or
*  modify it under the terms of the GNU General Public License as
*  published by the Free Software Foundation; either version 2 of the
*  License, or (at your option) any later version.
*
*  This program 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
*  General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with this program; if not, write to the Free Software
*  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
*  USA.
*  Created on 05.11.2005
*/
package com.inet.jortho;

import java.awt.EventQueue;
import java.util.Locale;

import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.AbstractDocument;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.Element;
import javax.swing.text.Highlighter;
import javax.swing.text.JTextComponent;
import javax.swing.text.Highlighter.Highlight;

/**
* This class check a <code>JTextComponent</code> automatically (in the background) for orthography. Spell error are
* highlighted with a red zigzag line.
*
* @author Volker Berlin
*/
class AutoSpellChecker implements DocumentListener, LanguageChangeListener {
  private static final RedZigZagPainter painter = new RedZigZagPainter();

  /**
   * Remove the AutoSpellChecker from the given JTextComponent.
   *
   * @param text
   *            the JTextComponent
   */
  static void disable(final JTextComponent text) {
    final AbstractDocument doc = (AbstractDocument) text.getDocument();
    for (final DocumentListener listener : doc.getDocumentListeners()) {
      if (listener instanceof AutoSpellChecker) {
        final AutoSpellChecker autoSpell = (AutoSpellChecker) listener;
        doc.removeDocumentListener(autoSpell);
        AutoSpellChecker.removeHighlights(text);
      }
    }
  }

  /**
   * Refresh the highlighting. This can be useful if the dictionary was modify.
   *
   * @param text
   *            the JTextComponent
   */
  static void refresh(final JTextComponent text) {
    final AbstractDocument doc = (AbstractDocument) text.getDocument();
    for (final DocumentListener listener : doc.getDocumentListeners()) {
      if (listener instanceof AutoSpellChecker) {
        final AutoSpellChecker autoSpell = (AutoSpellChecker) listener;
        autoSpell.checkAll();
      }
    }
  }

  private static void removeHighlights(final JTextComponent text) {
    final Highlighter highlighter = text.getHighlighter();
    for (final Highlight highlight : highlighter.getHighlights()) {
      if (highlight.getPainter() == painter) {
        highlighter.removeHighlight(highlight);
      }
    }
  }

  private Dictionary dictionary;
  private final JTextComponent jText;
  private Locale locale;
  private final SpellCheckerOptions options;

  public AutoSpellChecker(final JTextComponent text, final SpellCheckerOptions options) {
    jText = text;
    this.options = options == null ? SpellChecker.getOptions() : options;
    jText.getDocument().addDocumentListener(this);
    SpellChecker.addLanguageChangeLister(this);
    dictionary = SpellChecker.getCurrentDictionary();
    locale = SpellChecker.getCurrentLocale();
    checkAll();
  }

  /*====================================================================
   *
   * Methods of interface DocumentListener
   *
   *===================================================================*/
  /**
   * {@inheritDoc}
   */
  public void changedUpdate(final DocumentEvent ev) {
    //Nothing
  }

  /**
  //     * Check the completely text. Because this can consume many times with large Documents that this will do in a thread
   * in the background step by step.
   */
  private void checkAll() {
    if (jText == null) {
      //the needed objects does not exists
      return;
    }
    if (dictionary == null) {
      AutoSpellChecker.removeHighlights(jText);
      return;
    }
    final Thread thread = new Thread(new Runnable() {
      public void run() {
        final Document document = jText.getDocument();
        for (int i = 0; i < document.getLength();) {
          try {
            final Element element = ((AbstractDocument) document).getParagraphElement(i);
            i = element.getEndOffset();
            checkElement(element);
          }
          catch (final java.lang.Exception ex) {
            return;
          }
        }
      }
    }, "JOrtho checkall");
    thread.setPriority(Thread.NORM_PRIORITY - 1);
    thread.setDaemon(true);
    thread.start();
  }

  /**
   * Check the spelling of the text of an element.
   *
   * @param element
   *            the to checking Element
   */
  private void checkElement(final javax.swing.text.Element element) {
    try {
      if(! EventQueue.isDispatchThread()){
        try {
                  EventQueue.invokeAndWait(new Runnable() {
                    public void run() {
                      checkElement(element);
                      return;
                    }
                  });
                }
                catch (Exception e) {
                  e.printStackTrace();
                }
      }
      final int i = element.getStartOffset();
      final int l = ((AbstractDocument) jText.getDocument()).getLength();
      final int j = Math.min(element.getEndOffset(), l);
      if (i >= j) {
        return;
      }
      // prevent a NPE if the dictionary is currently not loaded.
      final Dictionary dic = dictionary;
      final Locale loc = locale;
      if (dic == null || loc == null) {
        return;
      }
      final Tokenizer tok = new Tokenizer(jText, dic, loc, i, j, options);
      String word;
      final Highlighter highlighter = jText.getHighlighter();
      while ((word = tok.nextInvalidWord()) != null) {
        final int wordOffset = tok.getWordOffset();
        highlighter.addHighlight(wordOffset, wordOffset + word.length(), painter);
      }
    }
    catch (final BadLocationException e) {
      e.printStackTrace();
    }
  }

  private void removeHighlighters(final javax.swing.text.Element element) {
      {
        final int i = element.getStartOffset();
        final int j = element.getEndOffset();
        final Highlighter highlighter = jText.getHighlighter();
        final Highlight[] highlights = highlighter.getHighlights();
        for (int k = highlights.length; --k >= 0;) {
          final Highlight highlight = highlights[k];
          final int hlStartOffset = highlight.getStartOffset();
          final int hlEndOffset = highlight.getEndOffset();
          if ((i <= hlStartOffset && hlStartOffset <= j) || (i <= hlEndOffset && hlEndOffset <= j)) {
            if (highlight.getPainter() == painter) {
              highlighter.removeHighlight(highlight);
            }
          }
        }
      }
    }

  /**
   * Check the Elements on the given position.
   */
  private void checkElements(int offset, final int length) {
    final int end = offset + length;
    final Document document = jText.getDocument();
    Element element;
    do {
      try {
        // We need to use a ParagraphElement because a CharacterElement produce problems with formating in a word
        element = ((AbstractDocument) document).getParagraphElement(offset);
      }
      catch (final java.lang.Exception ex) {
        return;
      }
      removeHighlighters(element);
      checkElement(element);
      offset = element.getEndOffset();
    } while (offset <= end && offset < document.getLength());
  }

  /**
   * {@inheritDoc}
   */
  public void insertUpdate(final DocumentEvent ev) {
    checkElements(ev.getOffset(), ev.getLength());
  }

  /**
   * {@inheritDoc}
   */
  public void languageChanged(final LanguageChangeEvent ev) {
    dictionary = SpellChecker.getCurrentDictionary();
    locale = SpellChecker.getCurrentLocale();
    checkAll();
  }

  /**
   * {@inheritDoc}
   */
  public void removeUpdate(final DocumentEvent ev) {
    checkElements(ev.getOffset(), 0);
  }
}
TOP

Related Classes of com.inet.jortho.AutoSpellChecker

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.