OSDN Git Service

5727beee42d2d2c9c63c155e550e4ee1a74197f6
[neighbornote/NeighborNote.git] / src / com / swabunga / spell / swing / autospell / AutoSpellCheckHandler.java
1 /*\r
2 Jazzy - a Java library for Spell Checking\r
3 Copyright (C) 2001 Mindaugas Idzelis\r
4 Full text of license can be found in LICENSE.txt\r
5 \r
6 This library is free software; you can redistribute it and/or\r
7 modify it under the terms of the GNU Lesser General Public\r
8 License as published by the Free Software Foundation; either\r
9 version 2.1 of the License, or (at your option) any later version.\r
10 \r
11 This library is distributed in the hope that it will be useful,\r
12 but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
14 Lesser General Public License for more details.\r
15 \r
16 You should have received a copy of the GNU Lesser General Public\r
17 License along with this library; if not, write to the Free Software\r
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\r
19 */\r
20 package com.swabunga.spell.swing.autospell;\r
21 \r
22 import java.awt.Point;\r
23 import java.awt.event.ActionEvent;\r
24 import java.awt.event.ActionListener;\r
25 import java.awt.event.MouseAdapter;\r
26 import java.awt.event.MouseEvent;\r
27 import java.util.ResourceBundle;\r
28 \r
29 import javax.swing.JEditorPane;\r
30 import javax.swing.JMenuItem;\r
31 import javax.swing.JPopupMenu;\r
32 import javax.swing.SwingUtilities;\r
33 import javax.swing.event.DocumentEvent;\r
34 import javax.swing.event.DocumentListener;\r
35 import javax.swing.text.AttributeSet;\r
36 import javax.swing.text.Document;\r
37 import javax.swing.text.Element;\r
38 import javax.swing.text.Segment;\r
39 import javax.swing.text.SimpleAttributeSet;\r
40 import javax.swing.text.StyledDocument;\r
41 \r
42 import com.swabunga.spell.engine.Configuration;\r
43 import com.swabunga.spell.event.DocumentWordTokenizer;\r
44 import com.swabunga.spell.event.SpellChecker;\r
45 \r
46 /**\r
47  * This class handles the actual autospelling by implementing some listeners\r
48  * on the spellchecked JEditorPane and Document.\r
49  * \r
50  * @author Robert Gustavsson (robert@lindesign.se)\r
51  *\r
52  */\r
53 public class AutoSpellCheckHandler extends MouseAdapter implements DocumentListener, \r
54                                                                                                                                    AutoSpellConstants{\r
55 \r
56         private SpellChecker                    sCheck=null;\r
57         private final Configuration                     config = Configuration.getConfiguration();\r
58         private ResourceBundle                  messages=null;\r
59         \r
60         public AutoSpellCheckHandler(SpellChecker sc){\r
61                 sCheck=sc;\r
62         }\r
63         \r
64         public AutoSpellCheckHandler(SpellChecker sc, ResourceBundle rs){\r
65                 this(sc);\r
66                 messages=rs;\r
67         }\r
68         \r
69         public void addJEditorPane(JEditorPane pane){\r
70                 StyledDocument doc=(StyledDocument)pane.getDocument();\r
71                 markupSpelling(doc, 0, doc.getLength()-1);\r
72                 doc.addDocumentListener(this);\r
73                 pane.addMouseListener(this);\r
74         }\r
75         \r
76         public void removeJEditorPane(JEditorPane pane){\r
77                 Document doc=pane.getDocument();\r
78                 pane.removeMouseListener(this);\r
79                 doc.removeDocumentListener(this);\r
80         }\r
81         \r
82         private void markupSpelling(StyledDocument doc, int start, int end){\r
83                 int                                             wordStart=-1,\r
84                                                                 wordEnd=-1;\r
85                 String                                  word;\r
86                 DocumentWordTokenizer   docTok;\r
87                 @SuppressWarnings("unused")\r
88                 Segment                                 seg=new Segment();\r
89                 \r
90                 docTok=new DocumentWordTokenizer(doc);\r
91                 if(start>0){\r
92                         docTok.posStartFullWordFrom(start);\r
93                 }\r
94                 \r
95                 while(docTok.hasMoreWords() && docTok.getCurrentWordPosition()<=end){\r
96                         word=docTok.nextWord();\r
97                         wordStart=docTok.getCurrentWordPosition();\r
98                         \r
99                         // Mark non word parts (spaces) as correct\r
100                         if(wordEnd!=-1){\r
101                                 //System.out.println("Space:"+wordEnd+","+wordStart);\r
102                                 markAsCorrect(doc, wordEnd, wordStart);\r
103                         }\r
104                         wordEnd=docTok.getCurrentWordEnd();\r
105                         \r
106                         if(wordEnd>doc.getLength())\r
107                                 wordEnd=doc.getLength()-1;\r
108                         if(wordStart>=wordEnd)\r
109                                 continue;\r
110                         //System.out.println("Word:"+wordStart+","+wordEnd);\r
111                         if(sCheck.isCorrect(word) || sCheck.isIgnored(word)){\r
112                                 markAsCorrect(doc, wordStart, wordEnd);\r
113                         }else{\r
114                                 markAsMisspelled(doc, wordStart, wordEnd);\r
115                         }\r
116                 }\r
117                 // Mark the rest (if any) as correct.\r
118                 if(wordEnd<end && wordEnd!=-1){\r
119                         //System.out.println("End:"+wordEnd+","+end);\r
120                         markAsCorrect(doc, wordEnd, end);\r
121                 }\r
122         }\r
123         \r
124         private void markAsMisspelled(StyledDocument doc, int start, int end){\r
125                 SimpleAttributeSet attr;\r
126                 attr=new SimpleAttributeSet();\r
127                 attr.addAttribute(wordMisspelled, wordMisspelledTrue);\r
128                 doc.setCharacterAttributes(start, end-start, attr, false);\r
129         }\r
130         \r
131         private void markAsCorrect(StyledDocument doc, int start, int end){\r
132                 SimpleAttributeSet attr;\r
133                 attr=new SimpleAttributeSet(doc.getCharacterElement((start+end)/2).getAttributes());\r
134                 attr.removeAttribute(wordMisspelled);\r
135                 if(end>=start)\r
136                         doc.setCharacterAttributes(start, end-start, attr, true);\r
137         }\r
138         \r
139         private void handleDocumentChange(DocumentEvent evt){\r
140                 Element                 curElem,\r
141                                                 parElem;\r
142                 StyledDocument  doc;\r
143                 int                             start,\r
144                                                 end;\r
145                 \r
146                 if(evt.getDocument() instanceof StyledDocument){\r
147                         doc=(StyledDocument)evt.getDocument();\r
148                         curElem=doc.getCharacterElement(evt.getOffset());\r
149                         parElem=curElem.getParentElement();\r
150                         if(parElem!=null){\r
151                                 start=parElem.getStartOffset();\r
152                                 end=parElem.getEndOffset();\r
153                         }else{\r
154                                 start=curElem.getStartOffset();\r
155                                 end=curElem.getEndOffset();\r
156                         }\r
157                         //System.out.println("curElem: "+curElem.getStartOffset()+", "+curElem.getEndOffset());\r
158                         //System.out.println("parElem: "+parElem.getStartOffset()+", "+parElem.getEndOffset());\r
159                         //System.out.println("change: "+start+", "+end);\r
160                         markupSpelling(doc,start, end);\r
161                 }               \r
162         }\r
163         \r
164         @SuppressWarnings("unchecked")\r
165         private void showSuggestionPopup(JEditorPane pane, Point p){\r
166                 StyledDocument                  doc;\r
167                 JMenuItem                               item;\r
168                 AttributeSet                    attr;\r
169                 int                                     pos = pane.viewToModel(p);\r
170                 DocumentWordTokenizer   docTok;\r
171                 String                                  word;\r
172                 java.util.List                  suggestions;\r
173                 JPopupMenu                              popup;\r
174                 ReplaceListener                 repList;\r
175                 \r
176                 if (pos >= 0) {\r
177                         doc=(StyledDocument)pane.getDocument();\r
178                         attr=doc.getCharacterElement(pos).getAttributes();\r
179                         if(attr.containsAttribute(wordMisspelled, wordMisspelledTrue)){\r
180                                 docTok=new DocumentWordTokenizer(doc);\r
181                                 docTok.posStartFullWordFrom(pos);\r
182                                 word=docTok.nextWord();\r
183                                 suggestions=sCheck.getSuggestions(word, config.getInteger(Configuration.SPELL_THRESHOLD));\r
184                                 \r
185                                 popup=new JPopupMenu();\r
186                                 repList=new ReplaceListener(docTok);\r
187                                 for(int i=0;i<suggestions.size();i++) {\r
188                                         com.swabunga.spell.engine.Word w = (com.swabunga.spell.engine.Word) suggestions.get(i);\r
189                                         item = new JMenuItem(w.getWord());\r
190                                         item.setActionCommand(w.getWord());\r
191                                         item.addActionListener(repList);\r
192                                         popup.add(item);\r
193                                 }\r
194                                 popup.addSeparator();\r
195                                 item = new JMenuItem();\r
196                                 if(messages!=null)\r
197                                         item.setText(messages.getString("IGNOREALL"));\r
198                                 else\r
199                                         item.setText("Ignore All");\r
200                                 item.setActionCommand(word);\r
201                                 item.addActionListener(new IgnoreAllListener(doc));\r
202                                 popup.add(item);\r
203                                 item = new JMenuItem();\r
204                                 if(messages!=null)\r
205                                         item.setText(messages.getString("ADD"));\r
206                                 else\r
207                                         item.setText("Add word to wordlist");\r
208                                 item.setActionCommand(word);\r
209                                 item.addActionListener(new AddToDictListener(doc));\r
210                                 popup.add(item);\r
211                                 popup.show(pane, p.x, p.y);     \r
212                         }\r
213                 }\r
214         }\r
215         \r
216         // DocumentListener implementation\r
217         // ------------------------------------------------------------------\r
218         public void changedUpdate(DocumentEvent evt){\r
219         }\r
220         \r
221         public void insertUpdate(DocumentEvent evt){\r
222                 Runnable r=new SpellCheckChange(evt);\r
223                 SwingUtilities.invokeLater(r);\r
224         }\r
225         \r
226         public void removeUpdate(DocumentEvent evt){\r
227                 Runnable r=new SpellCheckChange(evt);\r
228                 SwingUtilities.invokeLater(r);\r
229         }\r
230         \r
231         // MouseListener implementation\r
232         // ------------------------------------------------------------------\r
233         @Override\r
234         public void mouseReleased(MouseEvent evt){\r
235                 JEditorPane pane;\r
236                 if(!(evt.getComponent() instanceof JEditorPane))\r
237                         return;\r
238                 \r
239                 if(evt.isPopupTrigger()){\r
240                         pane=(JEditorPane)evt.getComponent();\r
241                         if(pane.isEditable())\r
242                                 showSuggestionPopup(pane, new Point(evt.getX(), evt.getY()));\r
243                 }\r
244         }\r
245         \r
246         // INNER CLASSES\r
247         // ------------------------------------------------------------------\r
248         private class SpellCheckChange implements Runnable{\r
249         \r
250                 private final DocumentEvent evt;\r
251                 \r
252                 public SpellCheckChange(DocumentEvent evt){\r
253                         this.evt=evt;\r
254                 }\r
255                 \r
256                 public void run(){\r
257                         handleDocumentChange(evt);\r
258                 }\r
259                 \r
260         }\r
261         \r
262         private class ReplaceListener implements ActionListener{\r
263                 \r
264                 DocumentWordTokenizer   tok;\r
265                 \r
266                 public ReplaceListener(DocumentWordTokenizer tok){\r
267                         this.tok=tok;\r
268                 }\r
269                 \r
270                 public void actionPerformed(ActionEvent evt){\r
271                         tok.replaceWord(evt.getActionCommand());\r
272                 }\r
273         }\r
274         \r
275         private class AddToDictListener implements ActionListener{\r
276                 \r
277                 private final StyledDocument    doc;\r
278                 \r
279                 public AddToDictListener(StyledDocument doc){\r
280                         this.doc=doc;\r
281                 }\r
282                 \r
283                 public void actionPerformed(ActionEvent evt){\r
284                         sCheck.addToDictionary(evt.getActionCommand());\r
285                         Runnable r=new MarkUpSpellingAll(doc);\r
286                         SwingUtilities.invokeLater(r);\r
287                 }\r
288         }\r
289         \r
290         private class IgnoreAllListener implements ActionListener{\r
291                 \r
292                 private final StyledDocument    doc;\r
293                 \r
294                 public IgnoreAllListener(StyledDocument doc){\r
295                         this.doc=doc;\r
296                 }\r
297                 \r
298                 public void actionPerformed(ActionEvent evt){\r
299                         sCheck.ignoreAll(evt.getActionCommand());\r
300                         Runnable r=new MarkUpSpellingAll(doc);\r
301                         SwingUtilities.invokeLater(r);\r
302                 }\r
303         }\r
304         \r
305         private class MarkUpSpellingAll implements Runnable{\r
306                 \r
307                 private final StyledDocument doc;\r
308                 \r
309                 public MarkUpSpellingAll(StyledDocument doc){\r
310                         this.doc=doc;\r
311                 }\r
312                 \r
313                 public void run(){\r
314                         markupSpelling(doc,0,doc.getLength());\r
315                 }\r
316         }\r
317         \r
318 }