Omaha #3453 Inline spell check capability
Change-Id: I0af5f892a6231fe4e861e66906304101b909b9ed Former-commit-id: faaf3b70a4a283f3131923abc722741152c5a632
This commit is contained in:
parent
1f7d7daab2
commit
46e50907cf
3 changed files with 366 additions and 3 deletions
|
@ -2,16 +2,20 @@ Manifest-Version: 1.0
|
|||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: Spellchecker Plug-in
|
||||
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-Vendor: RAYTHEON
|
||||
Require-Bundle: org.eclipse.ui,
|
||||
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-ActivationPolicy: lazy
|
||||
Import-Package: org.eclipse.jdt.ui,
|
||||
org.eclipse.jface.text,
|
||||
org.eclipse.jface.text.contentassist,
|
||||
org.eclipse.jface.text.source,
|
||||
org.eclipse.ui.editors.text,
|
||||
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