Omaha #3453 Inline spell check capability
Change-Id: I0af5f892a6231fe4e861e66906304101b909b9ed Former-commit-id: faaf3b70a4a283f3131923abc722741152c5a632
This commit is contained in:
parent
c73dc25f13
commit
7dd3809c35
3 changed files with 366 additions and 3 deletions
|
@ -2,16 +2,20 @@ Manifest-Version: 1.0
|
||||||
Bundle-ManifestVersion: 2
|
Bundle-ManifestVersion: 2
|
||||||
Bundle-Name: Spellchecker Plug-in
|
Bundle-Name: Spellchecker Plug-in
|
||||||
Bundle-SymbolicName: com.raytheon.uf.viz.spellchecker
|
Bundle-SymbolicName: com.raytheon.uf.viz.spellchecker
|
||||||
Bundle-Version: 1.12.1174.qualifier
|
Bundle-Version: 1.14.0.qualifier
|
||||||
Bundle-Activator: com.raytheon.uf.viz.spellchecker.Activator
|
Bundle-Activator: com.raytheon.uf.viz.spellchecker.Activator
|
||||||
Bundle-Vendor: RAYTHEON
|
Bundle-Vendor: RAYTHEON
|
||||||
Require-Bundle: org.eclipse.ui,
|
Require-Bundle: org.eclipse.ui,
|
||||||
org.eclipse.core.runtime,
|
org.eclipse.core.runtime,
|
||||||
com.raytheon.viz.core;bundle-version="1.11.26"
|
com.raytheon.viz.core;bundle-version="1.11.26",
|
||||||
|
com.google.guava;bundle-version="11.0.2"
|
||||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
|
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
|
||||||
Bundle-ActivationPolicy: lazy
|
Bundle-ActivationPolicy: lazy
|
||||||
Import-Package: org.eclipse.jdt.ui,
|
Import-Package: org.eclipse.jdt.ui,
|
||||||
org.eclipse.jface.text,
|
org.eclipse.jface.text,
|
||||||
org.eclipse.jface.text.contentassist,
|
org.eclipse.jface.text.contentassist,
|
||||||
|
org.eclipse.jface.text.source,
|
||||||
|
org.eclipse.ui.editors.text,
|
||||||
org.eclipse.ui.texteditor.spelling
|
org.eclipse.ui.texteditor.spelling
|
||||||
Export-Package: com.raytheon.uf.viz.spellchecker.dialogs
|
Export-Package: com.raytheon.uf.viz.spellchecker.dialogs,
|
||||||
|
com.raytheon.uf.viz.spellchecker.text
|
||||||
|
|
|
@ -0,0 +1,100 @@
|
||||||
|
/**
|
||||||
|
* This software was developed and / or modified by Raytheon Company,
|
||||||
|
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
|
||||||
|
*
|
||||||
|
* U.S. EXPORT CONTROLLED TECHNICAL DATA
|
||||||
|
* This software product contains export-restricted data whose
|
||||||
|
* export/transfer/disclosure is restricted by U.S. law. Dissemination
|
||||||
|
* to non-U.S. persons whether in the United States or abroad requires
|
||||||
|
* an export license or other authorization.
|
||||||
|
*
|
||||||
|
* Contractor Name: Raytheon Company
|
||||||
|
* Contractor Address: 6825 Pine Street, Suite 340
|
||||||
|
* Mail Stop B8
|
||||||
|
* Omaha, NE 68106
|
||||||
|
* 402.291.0100
|
||||||
|
*
|
||||||
|
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||||
|
* further licensing information.
|
||||||
|
**/
|
||||||
|
package com.raytheon.uf.viz.spellchecker.jobs;
|
||||||
|
|
||||||
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
|
import org.eclipse.core.runtime.IStatus;
|
||||||
|
import org.eclipse.core.runtime.Platform;
|
||||||
|
import org.eclipse.core.runtime.Status;
|
||||||
|
import org.eclipse.core.runtime.content.IContentTypeManager;
|
||||||
|
import org.eclipse.core.runtime.jobs.Job;
|
||||||
|
import org.eclipse.jface.text.IDocument;
|
||||||
|
import org.eclipse.jface.text.IRegion;
|
||||||
|
import org.eclipse.ui.PlatformUI;
|
||||||
|
import org.eclipse.ui.editors.text.EditorsUI;
|
||||||
|
import org.eclipse.ui.texteditor.spelling.ISpellingProblemCollector;
|
||||||
|
import org.eclipse.ui.texteditor.spelling.SpellingContext;
|
||||||
|
import org.eclipse.ui.texteditor.spelling.SpellingService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Spelling job that will run through the entire text and add all the problems
|
||||||
|
* instead of one at a time.
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
*
|
||||||
|
* SOFTWARE HISTORY
|
||||||
|
*
|
||||||
|
* Date Ticket# Engineer Description
|
||||||
|
* ------------ ---------- ----------- --------------------------
|
||||||
|
* Jun 17, 2014 3453 rblum Initial creation
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @author rblum
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class EnhancedSpellCheckJob extends Job {
|
||||||
|
|
||||||
|
private IDocument document;
|
||||||
|
|
||||||
|
private IRegion[] region = new IRegion[1];
|
||||||
|
|
||||||
|
private ISpellingProblemCollector collector;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param name
|
||||||
|
*/
|
||||||
|
public EnhancedSpellCheckJob(String name) {
|
||||||
|
super(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDocument(IDocument document) {
|
||||||
|
this.document = document;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRegion(IRegion region) {
|
||||||
|
this.region[0] = region;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCollector(ISpellingProblemCollector collector) {
|
||||||
|
this.collector = collector;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected IStatus run(IProgressMonitor monitor) {
|
||||||
|
SpellingService service = (SpellingService) PlatformUI.getWorkbench()
|
||||||
|
.getService(SpellingService.class);
|
||||||
|
if (service == null) {
|
||||||
|
EditorsUI.getPreferenceStore().setValue(SpellingService.PREFERENCE_SPELLING_ENGINE,
|
||||||
|
"spellingEngine");
|
||||||
|
service = new SpellingService(EditorsUI.getPreferenceStore());
|
||||||
|
}
|
||||||
|
|
||||||
|
SpellingContext context = new SpellingContext();
|
||||||
|
context.setContentType(Platform.getContentTypeManager().getContentType(
|
||||||
|
IContentTypeManager.CT_TEXT));
|
||||||
|
synchronized (this) {
|
||||||
|
service.check(document, region, context, collector, monitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status.OK_STATUS;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,259 @@
|
||||||
|
/**
|
||||||
|
* This software was developed and / or modified by Raytheon Company,
|
||||||
|
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
|
||||||
|
*
|
||||||
|
* U.S. EXPORT CONTROLLED TECHNICAL DATA
|
||||||
|
* This software product contains export-restricted data whose
|
||||||
|
* export/transfer/disclosure is restricted by U.S. law. Dissemination
|
||||||
|
* to non-U.S. persons whether in the United States or abroad requires
|
||||||
|
* an export license or other authorization.
|
||||||
|
*
|
||||||
|
* Contractor Name: Raytheon Company
|
||||||
|
* Contractor Address: 6825 Pine Street, Suite 340
|
||||||
|
* Mail Stop B8
|
||||||
|
* Omaha, NE 68106
|
||||||
|
* 402.291.0100
|
||||||
|
*
|
||||||
|
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||||
|
* further licensing information.
|
||||||
|
**/
|
||||||
|
package com.raytheon.uf.viz.spellchecker.text;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.eclipse.jface.preference.IPreferenceStore;
|
||||||
|
import org.eclipse.jface.text.Document;
|
||||||
|
import org.eclipse.jface.text.ITextListener;
|
||||||
|
import org.eclipse.jface.text.Region;
|
||||||
|
import org.eclipse.jface.text.TextEvent;
|
||||||
|
import org.eclipse.jface.text.TextPresentation;
|
||||||
|
import org.eclipse.jface.text.TextViewer;
|
||||||
|
import org.eclipse.jface.text.contentassist.ICompletionProposal;
|
||||||
|
import org.eclipse.swt.SWT;
|
||||||
|
import org.eclipse.swt.custom.StyleRange;
|
||||||
|
import org.eclipse.swt.events.MenuAdapter;
|
||||||
|
import org.eclipse.swt.events.MenuEvent;
|
||||||
|
import org.eclipse.swt.events.MouseAdapter;
|
||||||
|
import org.eclipse.swt.events.MouseEvent;
|
||||||
|
import org.eclipse.swt.events.SelectionAdapter;
|
||||||
|
import org.eclipse.swt.events.SelectionEvent;
|
||||||
|
import org.eclipse.swt.graphics.Point;
|
||||||
|
import org.eclipse.swt.widgets.Composite;
|
||||||
|
import org.eclipse.swt.widgets.Display;
|
||||||
|
import org.eclipse.swt.widgets.Menu;
|
||||||
|
import org.eclipse.swt.widgets.MenuItem;
|
||||||
|
import org.eclipse.ui.editors.text.EditorsUI;
|
||||||
|
import org.eclipse.ui.texteditor.spelling.ISpellingProblemCollector;
|
||||||
|
import org.eclipse.ui.texteditor.spelling.SpellingProblem;
|
||||||
|
import org.eclipse.ui.texteditor.spelling.SpellingService;
|
||||||
|
|
||||||
|
import com.google.common.collect.BoundType;
|
||||||
|
import com.google.common.collect.Range;
|
||||||
|
import com.google.common.collect.Ranges;
|
||||||
|
import com.raytheon.uf.viz.core.VizApp;
|
||||||
|
import com.raytheon.uf.viz.spellchecker.jobs.EnhancedSpellCheckJob;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link TextViewer} that displays lines where text is misspelled.
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
*
|
||||||
|
* SOFTWARE HISTORY
|
||||||
|
*
|
||||||
|
* Date Ticket# Engineer Description
|
||||||
|
* ------------ ---------- ----------- --------------------------
|
||||||
|
* Jun 18, 2014 3453 rblum Initial creation
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @author rblum
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class SpellCheckTextViewer extends TextViewer implements
|
||||||
|
ISpellingProblemCollector {
|
||||||
|
|
||||||
|
private List<SpellingProblem> problems;
|
||||||
|
|
||||||
|
private IPreferenceStore store;
|
||||||
|
|
||||||
|
private volatile boolean checkingSpelling = false;
|
||||||
|
|
||||||
|
private Map<Range<Integer>, SpellingProblem> ranges;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param parent
|
||||||
|
* @param styles
|
||||||
|
*/
|
||||||
|
public SpellCheckTextViewer(Composite parent, int styles) {
|
||||||
|
super(parent, styles);
|
||||||
|
problems = new ArrayList<SpellingProblem>();
|
||||||
|
ranges = new HashMap<Range<Integer>, SpellingProblem>();
|
||||||
|
store = EditorsUI.getPreferenceStore();
|
||||||
|
setDocument(new Document());
|
||||||
|
ITextListener listener = new ITextListener() {
|
||||||
|
@Override
|
||||||
|
public void textChanged(TextEvent event) {
|
||||||
|
if (checkingSpelling == false) {
|
||||||
|
scheduleSpellJob(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
addTextListener(listener);
|
||||||
|
getTextWidget().addMouseListener(new MouseAdapter() {
|
||||||
|
@Override
|
||||||
|
public void mouseDown(MouseEvent e) {
|
||||||
|
int offset = -1;
|
||||||
|
if (e.button == 3) {
|
||||||
|
try {
|
||||||
|
offset = getTextWidget().getOffsetAtLocation(
|
||||||
|
new Point(e.x, e.y));
|
||||||
|
} catch (Exception exception) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SpellingProblem problem = getProblemInRange(offset);
|
||||||
|
final Menu menu = new Menu(getTextWidget());
|
||||||
|
if (store
|
||||||
|
.getBoolean(SpellingService.PREFERENCE_SPELLING_ENABLED) == false) {
|
||||||
|
MenuItem item = new MenuItem(menu, SWT.PUSH);
|
||||||
|
item.setText("Enable spell checking");
|
||||||
|
item.addSelectionListener(new SelectionAdapter() {
|
||||||
|
@Override
|
||||||
|
public void widgetSelected(SelectionEvent e) {
|
||||||
|
store.setValue(
|
||||||
|
SpellingService.PREFERENCE_SPELLING_ENABLED,
|
||||||
|
true);
|
||||||
|
scheduleSpellJob(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else if (problem != null) {
|
||||||
|
for (ICompletionProposal prop : problem.getProposals()) {
|
||||||
|
MenuItem item = new MenuItem(menu, SWT.PUSH);
|
||||||
|
item.setText(prop.getDisplayString());
|
||||||
|
item.setData(prop);
|
||||||
|
item.setImage(prop.getImage());
|
||||||
|
addSelectionAction(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
menu.addMenuListener(new MenuAdapter() {
|
||||||
|
@Override
|
||||||
|
public void menuHidden(MenuEvent e) {
|
||||||
|
// TODO, we might be leaking menus
|
||||||
|
// menu.dispose();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
menu.setVisible(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see
|
||||||
|
* org.eclipse.ui.texteditor.spelling.ISpellingProblemCollector#accept(org
|
||||||
|
* .eclipse.ui.texteditor.spelling.SpellingProblem)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void accept(SpellingProblem problem) {
|
||||||
|
problems.add(problem);
|
||||||
|
Range<Integer> range = Ranges.range(problem.getOffset(),
|
||||||
|
BoundType.CLOSED, problem.getOffset() + problem.getLength(),
|
||||||
|
BoundType.CLOSED);
|
||||||
|
ranges.put(range, problem);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see
|
||||||
|
* org.eclipse.ui.texteditor.spelling.ISpellingProblemCollector#beginCollecting
|
||||||
|
* ()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void beginCollecting() {
|
||||||
|
invalidateTextPresentation();
|
||||||
|
problems.clear();
|
||||||
|
ranges.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see
|
||||||
|
* org.eclipse.ui.texteditor.spelling.ISpellingProblemCollector#endCollecting
|
||||||
|
* ()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void endCollecting() {
|
||||||
|
VizApp.runAsync(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
TextPresentation presentation = new TextPresentation();
|
||||||
|
for (SpellingProblem problem : problems) {
|
||||||
|
StyleRange range = new StyleRange(problem.getOffset(),
|
||||||
|
problem.getLength(), Display.getCurrent()
|
||||||
|
.getSystemColor(SWT.COLOR_LIST_FOREGROUND),
|
||||||
|
Display.getCurrent().getSystemColor(
|
||||||
|
SWT.COLOR_LIST_BACKGROUND));
|
||||||
|
range.underline = true;
|
||||||
|
range.underlineColor = Display.getCurrent().getSystemColor(
|
||||||
|
SWT.COLOR_RED);
|
||||||
|
range.underlineStyle = SWT.UNDERLINE_SQUIGGLE;
|
||||||
|
presentation.addStyleRange(range);
|
||||||
|
changeTextPresentation(presentation, true);
|
||||||
|
}
|
||||||
|
checkingSpelling = false;
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private SpellingProblem getProblemInRange(int offset) {
|
||||||
|
SpellingProblem problem = null;
|
||||||
|
for (Range<Integer> range : ranges.keySet()) {
|
||||||
|
if (range.contains(offset)) {
|
||||||
|
problem = ranges.get(range);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return problem;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addSelectionAction(final MenuItem item) {
|
||||||
|
item.addSelectionListener(new SelectionAdapter() {
|
||||||
|
@Override
|
||||||
|
public void widgetSelected(SelectionEvent e) {
|
||||||
|
ICompletionProposal prop = (ICompletionProposal) item.getData();
|
||||||
|
prop.apply(getDocument());
|
||||||
|
refresh();
|
||||||
|
scheduleSpellJob(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void scheduleSpellJob(boolean entireDocument) {
|
||||||
|
if (store.getBoolean(SpellingService.PREFERENCE_SPELLING_ENABLED)) {
|
||||||
|
EnhancedSpellCheckJob job = new EnhancedSpellCheckJob(
|
||||||
|
"Checking spelling...");
|
||||||
|
job.setDocument(getDocument());
|
||||||
|
if (entireDocument) {
|
||||||
|
job.setRegion(new Region(0, getDocument().getLength()));
|
||||||
|
} else {
|
||||||
|
int lineIndex = getTextWidget().getLineAtOffset(
|
||||||
|
getTextWidget().getCaretOffset());
|
||||||
|
int lineOffset = getTextWidget().getOffsetAtLine(lineIndex);
|
||||||
|
int lineLength = getTextWidget().getLine(lineIndex).length();
|
||||||
|
|
||||||
|
job.setRegion(new Region(lineOffset, lineLength));
|
||||||
|
}
|
||||||
|
|
||||||
|
job.setCollector(SpellCheckTextViewer.this);
|
||||||
|
checkingSpelling = true;
|
||||||
|
job.schedule();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue