Omaha #4959: GFE formatter launcher word wrap calls to python now happen off UI thread.
Change-Id: I9cc2c1c88a9dd554aa4a557f7658f5012671b357 Former-commit-id: 3f703cfef74d24af9f5b75500f28fae532130812
This commit is contained in:
parent
c0aa08888e
commit
5d75e31d00
3 changed files with 162 additions and 73 deletions
|
@ -174,6 +174,7 @@ import com.raytheon.viz.ui.simulatedtime.SimulatedTimeOperations;
|
|||
* 08/10/2015 4721 randerso Changed getNNNid() to use the productID field (not textdbPil)
|
||||
* Aug 31, 2015 4749 njensen Changed setCloseCallback to addCloseCallback
|
||||
* 09/15/2015 4858 dgilling Disable store/transmit in DRT mode.
|
||||
* 10/14/2015 4959 dgilling Support new function signature for wordWrap.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -2961,7 +2962,7 @@ public class ProductEditorComp extends Composite implements
|
|||
while ((curLine <= lastLine) && (curLine < styledText.getLineCount())) {
|
||||
int lineOff = styledText.getOffsetAtLine(curLine);
|
||||
// word wrap a block, and find out how the text length changed.
|
||||
indices = textComp.wordWrap(styledText, lineOff, wrapColumn);
|
||||
indices = textComp.wordWrap(lineOff, wrapColumn);
|
||||
int firstIdx = indices[0];
|
||||
int lastIdx = indices[1];
|
||||
int newLen = indices[2];
|
||||
|
|
|
@ -56,8 +56,6 @@ import org.eclipse.swt.widgets.Display;
|
|||
import org.eclipse.swt.widgets.Event;
|
||||
import org.eclipse.swt.widgets.Listener;
|
||||
|
||||
import com.raytheon.uf.common.dataplugin.gfe.python.GfePyIncludeUtil;
|
||||
import com.raytheon.uf.common.python.PythonScript;
|
||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||
import com.raytheon.uf.common.status.ProductEditorLogger;
|
||||
import com.raytheon.uf.common.status.UFStatus;
|
||||
|
@ -70,7 +68,7 @@ import com.raytheon.viz.gfe.textformatter.TextFmtParserUtil;
|
|||
|
||||
/**
|
||||
* Composite containing the product editor.
|
||||
*
|
||||
*
|
||||
* <pre>
|
||||
* SOFTWARE HISTORY
|
||||
* Date Ticket# Engineer Description
|
||||
|
@ -91,12 +89,14 @@ import com.raytheon.viz.gfe.textformatter.TextFmtParserUtil;
|
|||
* editing of framing codes.
|
||||
* 07/02/2015 13753 lshi Update times for products in Product Editor
|
||||
* 08/06/2015 13753 lshi use isSystemTextChange instead of isUpdateTime
|
||||
*
|
||||
* 14 OCT 2015 4959 dgilling Use WordWrapperPythonExecutor to get
|
||||
* python calls off UI thread.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* @author lvenable
|
||||
* @version 1.0
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
public class StyledTextComp extends Composite {
|
||||
|
@ -129,11 +129,28 @@ public class StyledTextComp extends Composite {
|
|||
|
||||
private static final String PRODUCT_PARSE_ERROR = "An unhandled exception was encountered trying to parse your text product. Please cancel and run your formatter again.";
|
||||
|
||||
private static final String NORM_SEP = "^\\s*$";
|
||||
|
||||
private static final String FUNNY_SEP = "^(\\s*)\\*(\\s*)";
|
||||
|
||||
private static final String NWS_SEP = "^\\..*\\.{3}";
|
||||
|
||||
private static final String PARA_SEP_STRING = "(" + NORM_SEP + ")|("
|
||||
+ FUNNY_SEP + ")|(" + NWS_SEP + ")";
|
||||
|
||||
private static final Pattern PARA_SEP_PATTERN = Pattern
|
||||
.compile(PARA_SEP_STRING);
|
||||
|
||||
private static final Pattern FUNNY_SEP_PATTERN = Pattern.compile(FUNNY_SEP,
|
||||
Pattern.MULTILINE);
|
||||
|
||||
/**
|
||||
* Parent composite.
|
||||
*/
|
||||
private final ProductEditorComp parent;
|
||||
|
||||
private final WordWrapPythonExecutor wrapper;
|
||||
|
||||
/**
|
||||
* Styled text editor.
|
||||
*/
|
||||
|
@ -166,8 +183,6 @@ public class StyledTextComp extends Composite {
|
|||
|
||||
private boolean dirty = false;
|
||||
|
||||
private PythonScript python = null;
|
||||
|
||||
protected Color bgColor;
|
||||
|
||||
protected Color fgColor;
|
||||
|
@ -182,15 +197,6 @@ public class StyledTextComp extends Composite {
|
|||
|
||||
private final ProductEditorLogger peLog;
|
||||
|
||||
private static final String NORM_SEP = "^\\s*$";
|
||||
|
||||
private static final String FUNNY_SEP = "^(\\s*)\\*(\\s*)";
|
||||
|
||||
private static final String NWS_SEP = "^\\..*\\.{3}";
|
||||
|
||||
private static final String PARA_SEP_STRING = "(" + NORM_SEP + ")|("
|
||||
+ FUNNY_SEP + ")|(" + NWS_SEP + ")";
|
||||
|
||||
public boolean isAutoWrapMode() {
|
||||
return autoWrapMode;
|
||||
}
|
||||
|
@ -201,7 +207,7 @@ public class StyledTextComp extends Composite {
|
|||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
*
|
||||
* @param parent
|
||||
* Parent composite.
|
||||
* @param wrapMode
|
||||
|
@ -214,6 +220,7 @@ public class StyledTextComp extends Composite {
|
|||
this.parent = parent;
|
||||
this.wrapColumn = wrapColumn;
|
||||
this.autoWrapMode = wrapMode;
|
||||
this.wrapper = new WordWrapPythonExecutor();
|
||||
|
||||
this.peLog = new ProductEditorLogger(parent.getProductName());
|
||||
|
||||
|
@ -250,30 +257,15 @@ public class StyledTextComp extends Composite {
|
|||
this.addDisposeListener(new DisposeListener() {
|
||||
@Override
|
||||
public void widgetDisposed(DisposeEvent arg0) {
|
||||
wrapper.dispose();
|
||||
textFont.dispose();
|
||||
bgColor.dispose();
|
||||
fgColor.dispose();
|
||||
frameColor.dispose();
|
||||
insertColor.dispose();
|
||||
lockColor.dispose();
|
||||
if (python != null) {
|
||||
python.dispose();
|
||||
python = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
List<String> preEvals = new ArrayList<String>();
|
||||
preEvals.add("import textwrap");
|
||||
try {
|
||||
python = new PythonScript(
|
||||
GfePyIncludeUtil.getCommonGfeIncludePath(), this.getClass()
|
||||
.getClassLoader(), preEvals);
|
||||
} catch (JepException je) {
|
||||
if (python != null) {
|
||||
python.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -323,7 +315,7 @@ public class StyledTextComp extends Composite {
|
|||
|
||||
/**
|
||||
* Get the StyledText editor.
|
||||
*
|
||||
*
|
||||
* @return The StyledText editor.
|
||||
*/
|
||||
public StyledText getTextEditorST() {
|
||||
|
@ -332,7 +324,7 @@ public class StyledTextComp extends Composite {
|
|||
|
||||
/**
|
||||
* Set the product text.
|
||||
*
|
||||
*
|
||||
* @param text
|
||||
* The product text.
|
||||
*/
|
||||
|
@ -502,7 +494,7 @@ public class StyledTextComp extends Composite {
|
|||
|
||||
/**
|
||||
* Parse the product text string.
|
||||
*
|
||||
*
|
||||
* @param productText
|
||||
* Complete product text.
|
||||
* @throws JepException
|
||||
|
@ -598,7 +590,7 @@ public class StyledTextComp extends Composite {
|
|||
|
||||
/**
|
||||
* Replacement of the text in the given range with new text.
|
||||
*
|
||||
*
|
||||
* @param tip
|
||||
* the range of text to be replaced
|
||||
* @param text
|
||||
|
@ -707,7 +699,7 @@ public class StyledTextComp extends Composite {
|
|||
* A verify event occurs after the user has done something to modify the
|
||||
* text (typically typed a key), but before the text is modified. The doit
|
||||
* field in the verify event indicates whether or not to modify the text.
|
||||
*
|
||||
*
|
||||
* @param event
|
||||
* Verify event that was fired.
|
||||
*/
|
||||
|
@ -797,7 +789,7 @@ public class StyledTextComp extends Composite {
|
|||
/**
|
||||
* Check if there is selected text and if there is locked text in the
|
||||
* selected text.
|
||||
*
|
||||
*
|
||||
* @return True if there is selected text that contains locked text.
|
||||
*/
|
||||
private boolean selectionHasLockedText() {
|
||||
|
@ -811,12 +803,12 @@ public class StyledTextComp extends Composite {
|
|||
|
||||
/**
|
||||
* Check if there is locked text in the specified range of text.
|
||||
*
|
||||
*
|
||||
* @param offset
|
||||
* The starting point of the locked text search.
|
||||
* @param length
|
||||
* The length of the search.
|
||||
*
|
||||
*
|
||||
* @return Whether or not there is text in the range that contains locked
|
||||
* text.
|
||||
*/
|
||||
|
@ -834,7 +826,7 @@ public class StyledTextComp extends Composite {
|
|||
|
||||
/**
|
||||
* Check if the key being pressed is a "non-edit" key.
|
||||
*
|
||||
*
|
||||
* @param event
|
||||
* Verify event.
|
||||
* @return True if the key is an arrow or "non-edit" key.
|
||||
|
@ -868,7 +860,7 @@ public class StyledTextComp extends Composite {
|
|||
|
||||
/**
|
||||
* Handle the mouse down event.
|
||||
*
|
||||
*
|
||||
* @param e
|
||||
* Event fired.
|
||||
*/
|
||||
|
@ -983,7 +975,7 @@ public class StyledTextComp extends Composite {
|
|||
/**
|
||||
* Checks if the system is editing, e.g. updating the issue time every
|
||||
* minute, vs a user typing text in the text area
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private boolean isSystemTextChange() {
|
||||
|
@ -1103,7 +1095,7 @@ public class StyledTextComp extends Composite {
|
|||
eventCursor = event.start + event.length;
|
||||
}
|
||||
|
||||
wordWrap(textEditorST, eventCursor, wrapColumn);
|
||||
wordWrap(eventCursor, wrapColumn);
|
||||
|
||||
if (cursorOffset != eventCursor) {
|
||||
// restore cursor position for programmatic changes
|
||||
|
@ -1139,7 +1131,7 @@ public class StyledTextComp extends Composite {
|
|||
|
||||
/**
|
||||
* Getter for the column at which wrap and auto-wrap will wrap the text.
|
||||
*
|
||||
*
|
||||
* @return the column number
|
||||
*/
|
||||
public int getWrapColumn() {
|
||||
|
@ -1148,7 +1140,7 @@ public class StyledTextComp extends Composite {
|
|||
|
||||
/**
|
||||
* Getter for the column at which wrap and auto-wrap will wrap the text.
|
||||
*
|
||||
*
|
||||
* @param wrapColumn
|
||||
* the column number
|
||||
*/
|
||||
|
@ -1187,7 +1179,7 @@ public class StyledTextComp extends Composite {
|
|||
/**
|
||||
* Query the prefs for setting. If it does not exist, use colorDft as its
|
||||
* value. Create an SWT Color for display from the value and return it.
|
||||
*
|
||||
*
|
||||
* @param prefs
|
||||
* A preference store which might have config values.
|
||||
* @param display
|
||||
|
@ -1210,7 +1202,7 @@ public class StyledTextComp extends Composite {
|
|||
|
||||
/**
|
||||
* Send a PROBLEM message if color1 is exactly equal to color2.
|
||||
*
|
||||
*
|
||||
* @param color1
|
||||
* the first color
|
||||
* @param color2
|
||||
|
@ -1237,7 +1229,7 @@ public class StyledTextComp extends Composite {
|
|||
* <p>
|
||||
* The getter name is different to avoid confusion with the getFgColor()
|
||||
* method of Control.
|
||||
*
|
||||
*
|
||||
* @return the foreground Color
|
||||
*/
|
||||
public Color getFgndColor() {
|
||||
|
@ -1248,7 +1240,7 @@ public class StyledTextComp extends Composite {
|
|||
* Get the framed text color of the StyledTextComp. This is the actual
|
||||
* color, not a copy. It will be disposed when the StyledTextComp is, and
|
||||
* should not be disposed before then.
|
||||
*
|
||||
*
|
||||
* @return the frameColor
|
||||
*/
|
||||
public Color getFrameColor() {
|
||||
|
@ -1259,7 +1251,7 @@ public class StyledTextComp extends Composite {
|
|||
* Get the insert color of the StyledTextComp. This is the actual color, not
|
||||
* a copy. It will be disposed when the StyledTextComp is, and should not be
|
||||
* disposed before then.
|
||||
*
|
||||
*
|
||||
* @return the insertColor
|
||||
*/
|
||||
public Color getInsertColor() {
|
||||
|
@ -1270,7 +1262,7 @@ public class StyledTextComp extends Composite {
|
|||
* Get the locked text color of the StyledTextComp. This is the actual
|
||||
* color, not a copy. It will be disposed when the StyledTextComp is, and
|
||||
* should not be disposed before then.
|
||||
*
|
||||
*
|
||||
* @return the lockColor
|
||||
*/
|
||||
public Color getLockColor() {
|
||||
|
@ -1280,9 +1272,7 @@ public class StyledTextComp extends Composite {
|
|||
/**
|
||||
* Word wrap the text in the block around cursorIndex. Adjust the cursor
|
||||
* position to account for inserted or deleted whitespace.
|
||||
*
|
||||
* @param st
|
||||
* The StyledText in which word wrap is to be performed
|
||||
*
|
||||
* @param cursorIndex
|
||||
* The cursor index
|
||||
* @param width
|
||||
|
@ -1294,15 +1284,11 @@ public class StyledTextComp extends Composite {
|
|||
* <li>The length of the replacement text</li>
|
||||
* </ol>
|
||||
*/
|
||||
public int[] wordWrap(StyledText st, int cursorIndex, int width) {
|
||||
public int[] wordWrap(int cursorIndex, int width) {
|
||||
StyledText st = getTextEditorST();
|
||||
|
||||
final Pattern PARA_SEP_PATTERN = Pattern.compile(PARA_SEP_STRING);
|
||||
final Matcher PARA_MATCHER = PARA_SEP_PATTERN.matcher("");
|
||||
|
||||
final Pattern FUNNY_SEP_PATTERN = Pattern.compile(FUNNY_SEP,
|
||||
Pattern.MULTILINE);
|
||||
final Matcher FUNNY_SEP_MATCHER = FUNNY_SEP_PATTERN.matcher("");
|
||||
|
||||
final String NL = st.getLineDelimiter();
|
||||
|
||||
String line;
|
||||
|
@ -1428,11 +1414,8 @@ public class StyledTextComp extends Composite {
|
|||
preArgs.put("text", pre);
|
||||
|
||||
try {
|
||||
python.instantiatePythonClass("_wrapper", "textwrap.TextWrapper",
|
||||
args);
|
||||
pre = (String) python.execute("fill", "_wrapper", preArgs);
|
||||
|
||||
} catch (JepException e) {
|
||||
pre = wrapper.callWordWrapPython(args, preArgs);
|
||||
} catch (Exception e) {
|
||||
statusHandler.error("Python error wrapping text preceding cursor:",
|
||||
e);
|
||||
}
|
||||
|
@ -1455,10 +1438,8 @@ public class StyledTextComp extends Composite {
|
|||
postArgs.put("text", post);
|
||||
|
||||
try {
|
||||
python.instantiatePythonClass("_wrapper", "textwrap.TextWrapper",
|
||||
args);
|
||||
post = (String) python.execute("fill", "_wrapper", postArgs);
|
||||
} catch (JepException e) {
|
||||
post = wrapper.callWordWrapPython(args, postArgs);
|
||||
} catch (Exception e) {
|
||||
statusHandler.error("Python error wrapping text after cursor:", e);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
/**
|
||||
* 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.viz.gfe.dialogs.formatterlauncher;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import com.raytheon.uf.common.dataplugin.gfe.python.GfePyIncludeUtil;
|
||||
import com.raytheon.uf.common.python.PythonScript;
|
||||
|
||||
/**
|
||||
* Executor service for running GFE's python-based word wrapping code.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Oct 14, 2015 #4959 dgilling Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author dgilling
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public final class WordWrapPythonExecutor {
|
||||
|
||||
private final ExecutorService execService;
|
||||
|
||||
private PythonScript python;
|
||||
|
||||
public WordWrapPythonExecutor() {
|
||||
this.execService = Executors.newSingleThreadExecutor();
|
||||
}
|
||||
|
||||
public synchronized String callWordWrapPython(
|
||||
final Map<String, Object> classArgs,
|
||||
final Map<String, Object> methodArgs) throws InterruptedException,
|
||||
ExecutionException {
|
||||
Callable<String> wordWrapTask = new Callable<String>() {
|
||||
|
||||
@Override
|
||||
public String call() throws Exception {
|
||||
if (python == null) {
|
||||
List<String> preEvals = Arrays.asList("import textwrap");
|
||||
python = new PythonScript(
|
||||
GfePyIncludeUtil.getCommonGfeIncludePath(),
|
||||
getClass().getClassLoader(), preEvals);
|
||||
}
|
||||
|
||||
python.instantiatePythonClass("_wrapper",
|
||||
"textwrap.TextWrapper", classArgs);
|
||||
return (String) python.execute("fill", "_wrapper", methodArgs);
|
||||
}
|
||||
};
|
||||
|
||||
Future<String> result = execService.submit(wordWrapTask);
|
||||
return result.get();
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
/*
|
||||
* Have to create a Runnable to dispose the PythonScript instance to
|
||||
* avoid thread access issues.
|
||||
*/
|
||||
Runnable disposeTask = new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (python != null) {
|
||||
python.close();
|
||||
python = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
execService.submit(disposeTask);
|
||||
|
||||
if (execService != null) {
|
||||
execService.shutdown();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue