Browse Source

REPORT-60163 公式编辑器优化2.0

1.添加了输入提示;
2.优化了搜索框;
3.优化了出错提示以及添加了关闭前检测。
feature/x
Hoky 3 years ago
parent
commit
1c33d91f1a
  1. 17
      designer-base/src/main/java/com/fr/design/dialog/BasicPane.java
  2. 16
      designer-base/src/main/java/com/fr/design/dialog/UIDialog.java
  3. 76
      designer-base/src/main/java/com/fr/design/formula/FormulaChecker.java
  4. 293
      designer-base/src/main/java/com/fr/design/formula/FormulaPane.java
  5. 9
      designer-base/src/main/java/com/fr/design/formula/FormulaPaneWhenReserveFormula.java
  6. 48
      designer-base/src/main/java/com/fr/design/formula/exception/FormulaExceptionTipsProcessor.java
  7. 31
      designer-base/src/main/java/com/fr/design/formula/exception/function/FormulaCheckConstants.java
  8. 74
      designer-base/src/main/java/com/fr/design/formula/exception/function/FormulaCheckWrongFunction.java
  9. 103
      designer-base/src/main/java/com/fr/design/formula/exception/function/MismatchedCharFunction.java
  10. 139
      designer-base/src/main/java/com/fr/design/formula/exception/function/MismatchedTokenFunction.java
  11. 43
      designer-base/src/main/java/com/fr/design/formula/exception/function/NoViableAltForCharFunction.java
  12. 40
      designer-base/src/main/java/com/fr/design/formula/exception/function/NoViableAltFunction.java
  13. 1003
      designer-base/src/main/java/com/fr/design/gui/autocomplete/FormulaAutoCompletePopupWindow.java
  14. 22
      designer-base/src/main/java/com/fr/design/gui/autocomplete/FormulaCompletion.java
  15. 1311
      designer-base/src/main/java/com/fr/design/gui/autocomplete/FormulaPaneAutoCompletion.java
  16. 28
      designer-base/src/main/java/com/fr/design/gui/autocomplete/ParameterizedCompletionContext.java
  17. BIN
      designer-base/src/main/resources/com/fr/design/images/m_file/formula.png
  18. BIN
      designer-base/src/main/resources/com/fr/design/images/m_file/param.png

17
designer-base/src/main/java/com/fr/design/dialog/BasicPane.java

@ -8,9 +8,14 @@ import com.fr.design.i18n.Toolkit;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.stable.core.PropertyChangeAdapter;
import javax.swing.*;
import javax.swing.JPanel;
import javax.swing.event.DocumentEvent;
import java.awt.*;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Window;
@Open
public abstract class BasicPane extends JPanel {
@ -262,6 +267,10 @@ public abstract class BasicPane extends JPanel {
public void checkValid() throws Exception {
}
public boolean confirmContinueBeforeDoOK() {
return true;
}
public static class NamePane extends BasicPane {
private UITextField nameTextField;
private UILabel Name;
@ -390,6 +399,10 @@ public abstract class BasicPane extends JPanel {
BasicPane.this.checkValid();
}
public boolean confirmContinueBeforeDoOK() {
return BasicPane.this.confirmContinueBeforeDoOK();
}
}
private class UnsizedDialog extends UIDialog {

16
designer-base/src/main/java/com/fr/design/dialog/UIDialog.java

@ -33,6 +33,7 @@ public abstract class UIDialog extends JDialog {
private BasicPane pane;
private java.util.List<DialogActionListener> listeners = new ArrayList<DialogActionListener>();
private boolean isDoOKSucceed;
private boolean needExceptionCheck = true;
public UIDialog(Frame parent) {
@ -151,6 +152,10 @@ public abstract class UIDialog extends JDialog {
});
}
public void setNeedExceptionCheck(boolean needExceptionCheck) {
this.needExceptionCheck = needExceptionCheck;
}
/**
* 添加监听器
@ -172,14 +177,21 @@ public abstract class UIDialog extends JDialog {
* 确定操作
*/
public void doOK() {
//由于checkValid不可以加入自定义的弹窗以及操作,添加一个接口
if (!confirmContinueBeforeDoOK()) {
return;
}
try {
checkValid();
} catch (Exception exp) {
if (needExceptionCheck) {
FineJOptionPane.showMessageDialog(
this,
exp.getMessage(),
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Tool_Tips"),
JOptionPane.WARNING_MESSAGE);
}
return;
}
@ -253,6 +265,10 @@ public abstract class UIDialog extends JDialog {
*/
public abstract void checkValid() throws Exception;
public boolean confirmContinueBeforeDoOK() {
return true;
}
public void setButtonEnabled(boolean b) {
this.okButton.setEnabled(b);
}

76
designer-base/src/main/java/com/fr/design/formula/FormulaChecker.java

@ -1,91 +1,43 @@
package com.fr.design.formula;
import com.fr.design.formula.exception.FormulaExceptionTipsProcessor;
import com.fr.design.i18n.Toolkit;
import com.fr.log.FineLoggerFactory;
import com.fr.parser.FRLexer;
import com.fr.parser.FRParser;
import com.fr.script.checker.FunctionCheckerDispatcher;
import com.fr.script.checker.exception.ConditionCheckWrongException;
import com.fr.script.checker.exception.FunctionCheckWrongException;
import com.fr.script.rules.FunctionParameterType;
import com.fr.script.rules.FunctionRule;
import com.fr.stable.StringUtils;
import com.fr.script.checker.result.FormulaCheckResult;
import com.fr.script.checker.result.FormulaCoordinates;
import com.fr.stable.script.Expression;
import com.fr.stable.script.Node;
import com.fr.third.antlr.TokenStreamRecognitionException;
import java.io.StringReader;
import java.util.List;
/**
* @author Hoky
* @date 2021/9/28
*/
public class FormulaChecker {
private static final String VALID_FORMULA = Toolkit.i18nText("Fine-Design_Basic_FormulaD_Valid_Formula");
private static final String INVALID_FORMULA = Toolkit.i18nText("Fine-Design_Basic_FormulaD_Invalid_Formula");
public static final String COLON = ":";
public static final String VALID_FORMULA = Toolkit.i18nText("Fine-Design_Basic_FormulaD_Valid_Formula");
public static final String INVALID_FORMULA = Toolkit.i18nText("Fine-Design_Basic_FormulaD_Invalid_Formula");
private static FormulaExceptionTipsProcessor processor = FormulaExceptionTipsProcessor.getProcessor();
public static String check(String formulaText) throws FormulaCheckerException {
public static FormulaCheckResult check(String formulaText) {
//过滤一些空格等符号
StringReader in = new StringReader(formulaText);
FRLexer lexer = new FRLexer(in);
FRParser parser = new FRParser(lexer);
try {
Expression expression = parser.parse();
Node node = expression.getConditionalExpression();
boolean valid = FunctionCheckerDispatcher.getInstance().getFunctionChecker(node).checkFunction(node);
if (valid) {
return VALID_FORMULA;
} else {
throw new FormulaCheckerException(INVALID_FORMULA);
}
} catch (ConditionCheckWrongException cce) {
String functionName = cce.getFunctionName();
throw new FormulaCheckerException(functionName + Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Condition_Tips") + COLON);
} catch (FunctionCheckWrongException ce) {
List<FunctionRule> rules = ce.getRules();
String functionName = ce.getFunctionName();
StringBuilder errorMsg = new StringBuilder(functionName + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Error_Tips") + COLON);
for (int i = 0; i < rules.size(); i++) {
errorMsg.append("(");
if (rules.get(i).getParameterList().isEmpty()) {
errorMsg.append(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_No_Param"));
}
for (FunctionParameterType functionParameterType : rules.get(i).getParameterList()) {
errorMsg.append(getTypeString(functionParameterType)).append(",");
}
if (",".equals(errorMsg.charAt(errorMsg.length() - 1) + "")) {
errorMsg.deleteCharAt(errorMsg.length() - 1);
}
errorMsg.append(")");
if (i != rules.size() - 1) {
errorMsg.append(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Or"));
}
}
throw new FormulaCheckerException(errorMsg.toString());
boolean valid = FunctionCheckerDispatcher.getInstance().getFunctionChecker(node).checkFunction(formulaText, node);
return new FormulaCheckResult(valid, valid ? VALID_FORMULA : INVALID_FORMULA, FormulaCoordinates.INVALID);
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
throw new FormulaCheckerException(INVALID_FORMULA);
// alex:继续往下面走,expression为null时告知不合法公式
if (e instanceof TokenStreamRecognitionException) {
return processor.getExceptionTips(((TokenStreamRecognitionException) e).recog);
}
return processor.getExceptionTips(e);
}
private static String getTypeString(FunctionParameterType type) {
switch (type) {
case NUMBER:
return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Number");
case STRING:
return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_String");
case ANY:
return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Any");
case DATE:
return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Date");
case BOOLEAN:
return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Boolean");
case ARRAY:
return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Array");
}
return StringUtils.EMPTY;
}
}

293
designer-base/src/main/java/com/fr/design/formula/FormulaPane.java

@ -16,7 +16,13 @@ import com.fr.design.dialog.BasicPane;
import com.fr.design.dialog.DialogActionAdapter;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.gui.autocomplete.CompletionCellRenderer;
import com.fr.design.gui.autocomplete.CompletionProvider;
import com.fr.design.gui.autocomplete.DefaultCompletionProvider;
import com.fr.design.gui.autocomplete.FormulaCompletion;
import com.fr.design.gui.autocomplete.FormulaPaneAutoCompletion;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.icheckbox.UICheckBox;
import com.fr.design.gui.icontainer.UIScrollPane;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.ilist.QuickList;
@ -43,6 +49,7 @@ import com.fr.parser.SheetIntervalLiteral;
import com.fr.report.core.namespace.SimpleCellValueNameSpace;
import com.fr.script.Calculator;
import com.fr.script.ScriptConstants;
import com.fr.script.checker.result.FormulaCheckResult;
import com.fr.stable.EncodeConstants;
import com.fr.stable.EssentialUtils;
import com.fr.stable.ParameterProvider;
@ -65,6 +72,7 @@ import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.event.ListSelectionEvent;
@ -82,6 +90,8 @@ import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
@ -112,17 +122,27 @@ import java.util.Set;
* @since 2012-3-29下午1:50:53
*/
public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
public static final String VALID_FORMULA = Toolkit.i18nText("Fine-Design_Basic_FormulaD_Valid_Formula");
public static final String INVALID_FORMULA = Toolkit.i18nText("Fine-Design_Basic_FormulaD_Invalid_Formula");
private final static String CONFIRM_DIALOG_TITLE = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Confirm");
public static final int DEFUAL_FOMULA_LENGTH = 103;
public static final String ELLIPSIS = "...";
public static final int KEY_CODE_A = 64;
public static final int KEY_CODE_Z = 91;
public static final String CHECK_RESULT = Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Result");
public static final String CONTINUE = Toolkit.i18nText("Fine-Design_Basic_Formula_Continue");
public static final String CAL_RESULT = Toolkit.i18nText("Fine-Design_Basic_Formula_Cal_Result");
public static final String NEWLINE = "\n";
public static final String ERROR_POSITION = Toolkit.i18nText("Fine-Design_Basic_Formula_Error_Position");
public static final String FORMULA_ICON = "/com/fr/design/images/m_file/formula.png";
public static final String PARAM_ICON = "/com/fr/design/images/m_file/param.png";
public static final int KEY_CODE_$ = 515;
private VariableTreeAndDescriptionArea variableTreeAndDescriptionArea;
private RSyntaxTextArea formulaTextArea;
private UITextField keyWordTextField = new UITextField(18);
private int currentPosition = 0;
private int beginPosition = 0;
private int insertPosition = 0;
protected static UICheckBox autoCompletionCheck;
protected static UICheckBox checkBeforeColse;
private JList tipsList;
protected DefaultListModel listModel = new DefaultListModel();
private int ifHasBeenWriten = 0;
@ -131,6 +151,9 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
private DefaultListModel functionNameModel;
private JList functionNameList;
private UITableEditorPane<ParameterProvider> editor4CalPane;
private FormulaPaneAutoCompletion autoCompletion;
private static DefaultCompletionProvider COMPLETION_PROVIDER = null;
private static final Map<String, String> PARAM_PREFIX_MAP = new HashMap<>();
public FormulaPane() {
initComponents();
@ -139,6 +162,21 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
private void initFormulaTextAreaKeyListener() {
formulaTextArea.addKeyListener(this);
formulaTextArea.addKeyListener(new KeyAdapter() {
//用来判断一下是不是组合键
@Override
public void keyTyped(KeyEvent e) {
if (inKeyCodeRange(e) && autoCompletionCheck.isSelected()) {
autoCompletion.doCompletion();
}
}
private boolean inKeyCodeRange(KeyEvent e) {
//|| e.getExtendedKeyCode() ==
return (e.getExtendedKeyCode() > KEY_CODE_A && e.getExtendedKeyCode() < KEY_CODE_Z);
}
@Override
public void keyReleased(KeyEvent e) {
formulaTextArea.setForeground(Color.black);
String text = formulaTextArea.getText();
@ -150,6 +188,9 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
insertPosition = 0;
formulaTextArea.setText(text);
}
if (e.getExtendedKeyCode() == KEY_CODE_$) {
autoCompletion.doCompletion();
}
}
});
}
@ -174,7 +215,9 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
beginPosition = getBeginPosition();
insertPosition = beginPosition;
firstStepToFindTips(beginPosition);
fixFunctionNameList();
if (tipsList.getSelectedValue() != null) {
fixFunctionNameList(tipsList.getSelectedValue().toString());
}
}
}
});
@ -204,7 +247,9 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
String toFind = keyWordTextField.getText();
search(toFind, false);
fixFunctionNameList();
if (tipsList.getSelectedValue() != null) {
fixFunctionNameList(tipsList.getSelectedValue().toString());
}
e.consume();
}
}
@ -213,28 +258,26 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
private void initTipsPane() {
// tipsPane
JPanel tipsPane = new JPanel(new BorderLayout(4, 4));
this.add(tipsPane, BorderLayout.EAST);
JPanel searchPane = new JPanel(new BorderLayout(4, 4));
JPanel searchPane = new JPanel(new BorderLayout(4, 1));
this.add(searchPane, BorderLayout.NORTH);
searchPane.add(keyWordTextField, BorderLayout.CENTER);
UIButton searchButton = new UIButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaPane_Search"));
UILabel formulaLabel = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaD_Input_Formula_In_The_Text_Area_Below") + ":"
+ " ");
formulaLabel.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
searchPane.add(searchButton, BorderLayout.EAST);
tipsPane.add(searchPane, BorderLayout.NORTH);
searchPane.add(formulaLabel, BorderLayout.WEST);
initKeyWordTextFieldKeyListener();
tipsList = new JList(listModel);
tipsList.addMouseListener(new DoubleClick());
UIScrollPane tipsScrollPane = new UIScrollPane(tipsList);
tipsScrollPane.setPreferredSize(new Dimension(170, 75));
tipsScrollPane.setBorder(new UIRoundedBorder(UIConstants.LINE_COLOR, 1, UIConstants.ARC));
tipsPane.add(tipsScrollPane, BorderLayout.CENTER);
searchButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
searchButton.addActionListener(e -> {
String toFind = keyWordTextField.getText();
search(toFind, false);
popTips();
formulaTextArea.requestFocusInWindow();
fixFunctionNameList();
if (tipsList.getSelectedValue() != null) {
fixFunctionNameList(tipsList.getSelectedValue().toString());
}
});
}
@ -254,18 +297,13 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
private void initTextPane() {
// text
JPanel textPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
this.add(textPane, BorderLayout.CENTER);
JPanel checkBoxandbuttonPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane();
UILabel formulaLabel = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaD_Input_Formula_In_The_Text_Area_Below") + ":"
+ " ");
formulaLabel.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
JPanel checkBoxandbuttonPane = FRGUIPaneFactory.createX_AXISBoxInnerContainer_S_Pane();
initFormulaTextArea();
UIScrollPane formulaTextAreaScrollPane = new UIScrollPane(formulaTextArea);
formulaTextAreaScrollPane.setBorder(null);
textPane.add(formulaLabel, BorderLayout.NORTH);
textPane.add(formulaTextAreaScrollPane, BorderLayout.CENTER);
textPane.add(checkBoxandbuttonPane, BorderLayout.SOUTH);
@ -275,19 +313,105 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
checkValidButton.addActionListener(checkValidActionListener);
calButton.addActionListener(calculateActionListener);
//靠左流式布局
JPanel checkBoxPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane();
checkBoxPane.setPreferredSize(new Dimension(450, 30));
checkBoxandbuttonPane.add(checkBoxPane, BorderLayout.WEST);
checkBoxandbuttonPane.add(checkValidButton, BorderLayout.EAST);
checkBoxandbuttonPane.add(calButton, BorderLayout.EAST);
//靠右流式布局
JPanel buttonPane = FRGUIPaneFactory.createRightFlowInnerContainer_S_Pane();
buttonPane.add(checkValidButton, BorderLayout.EAST);
buttonPane.add(calButton, BorderLayout.EAST);
checkBoxandbuttonPane.add(buttonPane, BorderLayout.EAST);
if (autoCompletionCheck == null) {
autoCompletionCheck = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_AutoCompletion"));
autoCompletionCheck.setSelected(true);
}
if (checkBeforeColse == null) {
checkBeforeColse = new UICheckBox(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Before_Closed"));
checkBeforeColse.setSelected(true);
}
checkBoxPane.add(autoCompletionCheck, BorderLayout.WEST);
checkBoxPane.add(checkBeforeColse, BorderLayout.WEST);
extendCheckBoxPane(checkBoxPane);
ParameterTableModel model = new ParameterTableModel(0);
editor4CalPane = new UITableEditorPane<>(model);
formulaTextArea.addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent e) {
// 获得焦点时 安装
if (autoCompletion == null && autoCompletionCheck.isSelected()) {
CompletionProvider provider = createCompletionProvider();
autoCompletion = new FormulaPaneAutoCompletion(provider);
autoCompletion.setListCellRenderer(new CompletionCellRenderer());
autoCompletion.install(formulaTextArea);
autoCompletion.installVariableTree(variableTreeAndDescriptionArea);
}
}
@Override
public void focusLost(FocusEvent e) {
// 失去焦点时 卸载
uninstallAutoCompletion();
}
});
}
private CompletionProvider createCompletionProvider() {
if (COMPLETION_PROVIDER == null) {
COMPLETION_PROVIDER = new DefaultCompletionProvider();
NameAndDescription[] nameAndDescriptions = FunctionConstants.ALL.getDescriptions();
for (NameAndDescription nameAndDescription : nameAndDescriptions) {
COMPLETION_PROVIDER.addCompletion(new FormulaCompletion(COMPLETION_PROVIDER, nameAndDescription.getName(), BaseUtils.readIcon(FORMULA_ICON)));
}
VariableResolver variableResolver = VariableResolver.DEFAULT;
List<String> allParameters = new ArrayList<>();
allParameters.addAll(Arrays.asList(variableResolver.resolveCurReportVariables()));
allParameters.addAll(Arrays.asList(variableResolver.resolveColumnNames()));
allParameters.addAll(Arrays.asList(variableResolver.resolveGlobalParameterVariables()));
allParameters.addAll(Arrays.asList(variableResolver.resolveReportParameterVariables()));
allParameters.addAll(Arrays.asList(variableResolver.resolveTableDataParameterVariables()));
//先把参数前缀拿出来
for (String parameter : allParameters) {
String paramWithoutPre;
if (parameter.startsWith("$$")) {
paramWithoutPre = parameter.substring(2);
PARAM_PREFIX_MAP.put(paramWithoutPre, "$$");
} else if (parameter.startsWith("$")) {
paramWithoutPre = parameter.substring(1);
PARAM_PREFIX_MAP.put(paramWithoutPre, "$");
} else {
paramWithoutPre = parameter;
PARAM_PREFIX_MAP.put(paramWithoutPre, StringUtils.EMPTY);
}
COMPLETION_PROVIDER.addCompletion(new FormulaCompletion(COMPLETION_PROVIDER, paramWithoutPre, BaseUtils.readIcon(PARAM_ICON)));
}
COMPLETION_PROVIDER.addCompletion(new FormulaCompletion(COMPLETION_PROVIDER, "$$$", BaseUtils.readIcon(PARAM_ICON)));
return COMPLETION_PROVIDER;
}
return COMPLETION_PROVIDER;
}
public static boolean containsParam(String param) {
return PARAM_PREFIX_MAP.containsKey(param);
}
public static String getParamPrefix(String param) {
return PARAM_PREFIX_MAP.getOrDefault(param, StringUtils.EMPTY);
}
private void uninstallAutoCompletion() {
if (autoCompletion != null) {
autoCompletion.uninstall();
autoCompletion = null;
}
}
protected void extendCheckBoxPane(JPanel checkBoxPane) {
// do nothing
}
@ -341,7 +465,9 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
private void singleClickActuator(String currentLineContent) {
refreshDescriptionTextArea(currentLineContent);
formulaTextArea.requestFocusInWindow();
fixFunctionNameList();
if (tipsList.getSelectedValue() != null) {
fixFunctionNameList(tipsList.getSelectedValue().toString());
}
}
private void doubleClickActuator(String currentLineContent) {
@ -405,14 +531,15 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
beginPosition = getBeginPosition();
insertPosition = beginPosition;
firstStepToFindTips(beginPosition);
fixFunctionNameList();
if (tipsList.getSelectedValue() != null) {
fixFunctionNameList(tipsList.getSelectedValue().toString());
}
ifHasBeenWriten = 1;
}
}
}
private void fixFunctionNameList() {
if (tipsList.getSelectedValue() != null) {
private void fixFunctionNameList(String functionName) {
int signOfContinue = 1;
int indexOfFunction = 0;
for (int i = 0; i < functionTypeListModel.size(); i++) {
@ -421,7 +548,6 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
NameAndDescription[] nads = functionType.getDescriptions();
if (signOfContinue == 1) {
functionNameModel.removeAllElements();
String functionName = ((String) tipsList.getSelectedValue());
for (int k = 0; k < nads.length; k++) {
functionNameModel.addElement(nads[k]);
if (functionName.equals(nads[k].getName()))//若相等,找出显示的函数的index,setSelectedIndex()
@ -442,8 +568,6 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
functionNameList.ensureIndexIsVisible(indexOfFunction);
}
}
private int getBeginPosition() {
int i = currentPosition;
String textArea = formulaTextArea.getText();
@ -492,9 +616,17 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
// do nothing
}
private void popTips() {
JPopupMenu popupMenu = new JPopupMenu();
JScrollPane tipsScrollPane = new JScrollPane(tipsList);
popupMenu.add(tipsScrollPane);
tipsScrollPane.setPreferredSize(new Dimension(240, 146));
tipsScrollPane.setBorder(new UIRoundedBorder(UIConstants.LINE_COLOR, 1, UIConstants.ARC));
popupMenu.show(keyWordTextField, 0, 23);
}
protected void search(String keyWord, boolean findDescription) {
listModel.removeAllElements();
keyWord = removeAllSpace(keyWord);
if (keyWord.length() != 0) {
NameAndDescription[] descriptions = FunctionConstants.ALL.getDescriptions();
@ -610,7 +742,9 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
beginPosition = getBeginPosition();
insertPosition = beginPosition;
firstStepToFindTips(beginPosition);
fixFunctionNameList();
if (tipsList.getSelectedValue() != null) {
fixFunctionNameList(tipsList.getSelectedValue().toString());
}
ifHasBeenWriten = 1;
} else {
this.formulaTextArea.setText(content);
@ -618,7 +752,9 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
beginPosition = getBeginPosition();
insertPosition = beginPosition;
firstStepToFindTips(beginPosition);
fixFunctionNameList();
if (tipsList.getSelectedValue() != null) {
fixFunctionNameList(tipsList.getSelectedValue().toString());
}
ifHasBeenWriten = 1;
}
}
@ -650,17 +786,12 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
public void actionPerformed(ActionEvent evt) {
// Execute Formula default cell element.
String formulaText = formulaTextArea.getText().trim();
String formulaValidMessage;
try {
formulaValidMessage = FormulaChecker.check(formulaText);
showMessageDialog(formulaValidMessage + ".");
} catch (FormulaCheckerException e) {
formulaValidMessage = e.getMessage();
showMessageDialog(formulaValidMessage + ".", false);
}
FormulaCheckResult checkResult = FormulaChecker.check(formulaText);
confirmCheckResult(checkResult);
}
};
private final ActionListener calculateActionListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
@ -671,20 +802,10 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
return;
}
String formulaValidMessage;
boolean formulaValid;
try {
formulaValidMessage = FormulaChecker.check(formulaText);
formulaValid = true;
} catch (FormulaCheckerException formulaCheckerException) {
formulaValidMessage = formulaCheckerException.getMessage();
formulaValid = false;
}
String messageTips;
if (ComparatorUtils.equals(formulaValidMessage, INVALID_FORMULA)) {
messageTips = INVALID_FORMULA;
} else {
messageTips = ComparatorUtils.equals(formulaValidMessage, VALID_FORMULA) ? "" : formulaValidMessage + "\n";
FormulaCheckResult checkResult = FormulaChecker.check(formulaText);
if (checkResult.isValid()) {
messageTips = checkResult.getTips() + NEWLINE;
Map<String, Object> paramsMap = setParamsIfExist(formulaText);
Calculator calculator = Calculator.createCalculator();
ParameterMapNameSpace parameterMapNameSpace = ParameterMapNameSpace.create(paramsMap);
@ -704,19 +825,42 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
String objectToString = EssentialUtils.objectToString(value);
String result = objectToString.length() > DEFUAL_FOMULA_LENGTH ?
objectToString.substring(0, DEFUAL_FOMULA_LENGTH - ELLIPSIS.length()) + ELLIPSIS : objectToString;
messageTips = messageTips +
Toolkit.i18nText("Fine-Design_Basic_Formula_Cal_Result") + ":" + result;
messageTips = messageTips + CAL_RESULT + ":" + result;
FineLoggerFactory.getLogger().info("value:{}", value);
} catch (UtilEvalError utilEvalError) {
FineLoggerFactory.getLogger().error("", utilEvalError);
FineLoggerFactory.getLogger().error(utilEvalError.getMessage(), utilEvalError);
}
} else {
messageTips = checkResult.getTips();
}
if (checkResult.isValid()) {
showMessageDialog(messageTips, checkResult.isValid());
} else {
confirmCheckResult(checkResult);
}
showMessageDialog(messageTips, formulaValid);
}
};
private void showMessageDialog(String message) {
showMessageDialog(message, true);
private boolean confirmCheckResult(FormulaCheckResult checkResult) {
if (checkResult.isValid()) {
showMessageDialog(checkResult.getTips(), checkResult.isValid());
} else {
int confirmDialog = FineJOptionPane.showConfirmDialog(
FormulaPane.this,
checkResult.getTips() + ", " + ERROR_POSITION + ":" + (checkResult.getFormulaCoordinates().getColumns()) + ".",
CONFIRM_DIALOG_TITLE,
JOptionPane.YES_NO_OPTION,
JOptionPane.WARNING_MESSAGE,
null,
new String[]{CHECK_RESULT, CONTINUE},
CHECK_RESULT);
if (confirmDialog == 0) {
formulaTextArea.setCaretPosition(checkResult.getFormulaCoordinates().getColumns());
formulaTextArea.requestFocus();
return false;
}
}
return true;
}
private void showMessageDialog(String message, boolean formulaValid) {
@ -750,6 +894,18 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
return null;
}
@Override
public boolean confirmContinueBeforeDoOK() {
if (checkBeforeColse.isSelected()) {
String formula = formulaTextArea.getText().trim();
FormulaCheckResult checkResult = FormulaChecker.check(formula);
if (!checkResult.isValid()) {
return confirmCheckResult(checkResult);
}
}
return true;
}
private Map<String, Object> setParamsIfExist(String formulaText) {
Map<String, Object> parameterMap = new HashMap<>();
try {
@ -990,7 +1146,8 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
private void initDescriptionTextArea() {
// Description
descriptionTextArea = new UITextArea(16, 27);
descriptionTextArea = new UITextArea();
descriptionTextArea.setPreferredSize(new Dimension(350, 200));
UIScrollPane desScrollPane = new UIScrollPane(descriptionTextArea);
desScrollPane.setBorder(null);
@ -1191,6 +1348,10 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
}
};
public void refreshText(String line) {
refreshDescriptionTextArea(line);
}
public void populate(VariableResolver variableResolver) {
// varibale tree.
DefaultTreeModel variableModel = (DefaultTreeModel) variablesTree.getModel();
@ -1326,12 +1487,12 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
buffer.append(name.toUpperCase());
buffer.append("\"");
buffer.append("|");
buffer.append("\n");
buffer.append(NEWLINE);
buffer.append("\"");
buffer.append(name.toLowerCase());
buffer.append("\"");
buffer.append("|");
buffer.append("\n");
buffer.append(NEWLINE);
}
FineLoggerFactory.getLogger().debug(buffer.toString());
}

9
designer-base/src/main/java/com/fr/design/formula/FormulaPaneWhenReserveFormula.java

@ -3,11 +3,10 @@ package com.fr.design.formula;
import com.fr.base.BaseFormula;
import com.fr.design.gui.icheckbox.UICheckBox;
import javax.swing.*;
import javax.swing.JPanel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.BorderLayout;
/**
* @author richie
@ -41,8 +40,8 @@ public class FormulaPaneWhenReserveFormula extends FormulaPane {
reserveCheckBox4Write = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Write_Save_Formula"));
reserveCheckBox4Write.setSelected(false);
checkBoxPane.add(reserveCheckBox4Result, BorderLayout.CENTER);
checkBoxPane.add(reserveCheckBox4Write, BorderLayout.SOUTH);
checkBoxPane.add(reserveCheckBox4Result, BorderLayout.WEST);
checkBoxPane.add(reserveCheckBox4Write, BorderLayout.WEST);
}
@Override

48
designer-base/src/main/java/com/fr/design/formula/exception/FormulaExceptionTipsProcessor.java

@ -0,0 +1,48 @@
package com.fr.design.formula.exception;
import com.fr.design.formula.FormulaChecker;
import com.fr.design.formula.exception.function.FormulaCheckWrongFunction;
import com.fr.design.formula.exception.function.MismatchedCharFunction;
import com.fr.design.formula.exception.function.MismatchedTokenFunction;
import com.fr.design.formula.exception.function.NoViableAltForCharFunction;
import com.fr.design.formula.exception.function.NoViableAltFunction;
import com.fr.script.checker.exception.FunctionCheckWrongException;
import com.fr.script.checker.result.FormulaCheckResult;
import com.fr.script.checker.result.FormulaCoordinates;
import com.fr.third.antlr.MismatchedCharException;
import com.fr.third.antlr.MismatchedTokenException;
import com.fr.third.antlr.NoViableAltException;
import com.fr.third.antlr.NoViableAltForCharException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
/**
* @author Hoky
* @date 2021/10/26
*/
public class FormulaExceptionTipsProcessor {
private static final Map<Class, Function<Exception, FormulaCheckResult>> EXCEPTION_TIPS = new ConcurrentHashMap<>();
private static final FormulaExceptionTipsProcessor PROCESSOR = new FormulaExceptionTipsProcessor();
static {
EXCEPTION_TIPS.put(FunctionCheckWrongException.class, FormulaCheckWrongFunction.getFunction());
EXCEPTION_TIPS.put(MismatchedCharException.class, MismatchedCharFunction.getFunction());
EXCEPTION_TIPS.put(MismatchedTokenException.class, MismatchedTokenFunction.getFunction());
EXCEPTION_TIPS.put(NoViableAltException.class, NoViableAltFunction.getFunction());
EXCEPTION_TIPS.put(NoViableAltForCharException.class, NoViableAltForCharFunction.getFunction());
}
public FormulaCheckResult getExceptionTips(Exception e) {
return EXCEPTION_TIPS.getOrDefault(e.getClass(),
e1 -> new FormulaCheckResult(false, FormulaChecker.INVALID_FORMULA, FormulaCoordinates.INVALID))
.apply(e);
}
public static FormulaExceptionTipsProcessor getProcessor() {
return PROCESSOR;
}
}

31
designer-base/src/main/java/com/fr/design/formula/exception/function/FormulaCheckConstants.java

@ -0,0 +1,31 @@
package com.fr.design.formula.exception.function;
import com.fr.design.i18n.Toolkit;
/**
* @author Hoky
* @date 2021/10/28
*/
public class FormulaCheckConstants {
public final static String EXPECTING = Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Expecting") + ": ";
public final static String FOUND = Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Found");
public final static String EXPECTING_ANYTHING = Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Expecting_Anything");
public final static String GOT_IT_ANYWAY = Toolkit.i18nText("Fine-Design_Basic_Formula_Check_GotItAnyway");
public final static String TOKEN = Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Token");
public final static String IN_RANGE = Toolkit.i18nText("Fine-Design_Basic_Formula_Check_In_Range");
public final static String CHECK_NOT = Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Not");
public final static String ONE_OF = Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ONE_OF");
public final static String UNEXPECTED_TOKEN = Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Unexpected_Token");
public final static String UNEXPECTED_CHAR = Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Unexpected_Char");
public final static String UNEXPECTED_END_OF_SUBTREE = Toolkit.i18nText("Fine-Design_Basic_Formula_Check_End_Of_Subtree");
public final static String UNEXPECTED_AST_NODE = Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Unexpected_AST_Node");
public final static String MISMATCHED_TOKEN = Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Mismatched_Token");
public final static String MISMATCHED_CHAR = Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Mismatched_Char");
public final static String MISMATCHED_EOF = Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Mismatched_EOF");
public static final String COLON = ":";
public static final String LEFT = "(";
public static final String COMMON = ",";
public static final String RIGHT = ")";
public static final String BLANK = " ";
public static final String SINGLE_QUOTES = "'";
}

74
designer-base/src/main/java/com/fr/design/formula/exception/function/FormulaCheckWrongFunction.java

@ -0,0 +1,74 @@
package com.fr.design.formula.exception.function;
import com.fr.design.i18n.Toolkit;
import com.fr.script.checker.exception.FunctionCheckWrongException;
import com.fr.script.checker.result.FormulaCheckResult;
import com.fr.script.checker.result.FormulaCoordinates;
import com.fr.script.rules.FunctionParameterType;
import com.fr.script.rules.FunctionRule;
import com.fr.stable.StringUtils;
import java.util.List;
import java.util.function.Function;
/**
* @author Hoky
* @date 2021/10/26
*/
public class FormulaCheckWrongFunction implements Function<Exception, FormulaCheckResult> {
private final static FormulaCheckWrongFunction FUNCTION = new FormulaCheckWrongFunction();
@Override
public FormulaCheckResult apply(Exception e) {
if (e instanceof FunctionCheckWrongException) {
FunctionCheckWrongException ce = (FunctionCheckWrongException) e;
List<FunctionRule> rules = ce.getRules();
String functionName = ce.getFunctionName();
StringBuilder errorMsg = new StringBuilder(functionName + Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Error_Tips") + FormulaCheckConstants.COLON);
for (int i = 0; i < rules.size(); i++) {
errorMsg.append(FormulaCheckConstants.LEFT);
if (rules.get(i).getParameterList().isEmpty()) {
errorMsg.append(Toolkit.i18nText("Fine-Design_Basic_Formula_No_Param"));
}
for (FunctionParameterType functionParameterType : rules.get(i).getParameterList()) {
errorMsg.append(getTypeString(functionParameterType)).append(FormulaCheckConstants.COMMON);
}
if (FormulaCheckConstants.COMMON.equals(errorMsg.charAt(errorMsg.length() - 1) + StringUtils.EMPTY)) {
errorMsg.deleteCharAt(errorMsg.length() - 1);
}
errorMsg.append(FormulaCheckConstants.RIGHT);
if (i != rules.size() - 1) {
errorMsg.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Or"));
}
}
return new FormulaCheckResult(false, errorMsg.toString(), new FormulaCoordinates(1, indexPosition(ce.getFormulaText(), ce.getNode().toString())));
}
return new FormulaCheckResult(false, StringUtils.EMPTY, new FormulaCoordinates(-1, -1));
}
private static String getTypeString(FunctionParameterType type) {
switch (type) {
case NUMBER:
return Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Number");
case STRING:
return Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_String");
case ANY:
return Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Any");
case DATE:
return Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Date");
case BOOLEAN:
return Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Boolean");
case ARRAY:
return Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Array");
}
return StringUtils.EMPTY;
}
public static Function<Exception, FormulaCheckResult> getFunction() {
return FUNCTION;
}
private int indexPosition(String formulaText, String invalidFormula) {
return formulaText.indexOf(invalidFormula);
}
}

103
designer-base/src/main/java/com/fr/design/formula/exception/function/MismatchedCharFunction.java

@ -0,0 +1,103 @@
package com.fr.design.formula.exception.function;
import com.fr.design.formula.FormulaChecker;
import com.fr.script.checker.result.FormulaCheckResult;
import com.fr.script.checker.result.FormulaCoordinates;
import com.fr.third.antlr.MismatchedCharException;
import java.util.function.Function;
/**
* @author Hoky
* @date 2021/10/28
*/
public class MismatchedCharFunction implements Function<Exception, FormulaCheckResult> {
private final static MismatchedCharFunction FUNCTION = new MismatchedCharFunction();
@Override
public FormulaCheckResult apply(Exception e) {
if (e instanceof MismatchedCharException) {
MismatchedCharException charException = (MismatchedCharException) e;
FormulaCoordinates formulaCoordinates = new FormulaCoordinates(charException.line, charException.column - 1);
return new FormulaCheckResult(false, getMessage(charException), formulaCoordinates);
}
return new FormulaCheckResult(false, FormulaChecker.INVALID_FORMULA, FormulaCoordinates.INVALID);
}
public static Function<Exception, FormulaCheckResult> getFunction() {
return FUNCTION;
}
private String getMessage(MismatchedCharException charException) {
StringBuffer sb = new StringBuffer();
switch (charException.mismatchType) {
case 1:
sb.append(FormulaCheckConstants.EXPECTING);
appendCharName(sb, charException.expecting);
sb.append(FormulaCheckConstants.COMMON)
.append(FormulaCheckConstants.BLANK)
.append(FormulaCheckConstants.FOUND);
appendCharName(sb, charException.foundChar);
break;
case 2:
sb.append(FormulaCheckConstants.EXPECTING_ANYTHING)
.append(FormulaCheckConstants.BLANK)
.append(FormulaCheckConstants.SINGLE_QUOTES);
appendCharName(sb, charException.expecting);
sb.append("';").append(FormulaCheckConstants.GOT_IT_ANYWAY);
break;
case 3:
case 4:
sb.append(FormulaCheckConstants.EXPECTING).append(FormulaCheckConstants.TOKEN);
if (charException.mismatchType == 4) {
sb.append(FormulaCheckConstants.CHECK_NOT);
}
sb.append(FormulaCheckConstants.IN_RANGE).append(": ");
appendCharName(sb, charException.expecting);
sb.append("..");
appendCharName(sb, charException.upper);
sb.append(", ").append(FormulaCheckConstants.FOUND);
appendCharName(sb, charException.foundChar);
break;
case 5:
case 6:
sb.append(FormulaCheckConstants.EXPECTING)
.append(charException.mismatchType == 6 ? FormulaCheckConstants.CHECK_NOT : FormulaCheckConstants.BLANK)
.append(FormulaCheckConstants.ONE_OF).append(" (");
int[] elems = charException.set.toArray();
for (int i = 0; i < elems.length; ++i) {
appendCharName(sb, elems[i]);
}
sb.append("), ").append(FormulaCheckConstants.FOUND);
appendCharName(sb, charException.foundChar);
break;
default:
sb.append(FormulaCheckConstants.MISMATCHED_CHAR);
}
return sb.toString();
}
private void appendCharName(StringBuffer sb, int c) {
switch (c) {
case 9:
sb.append("'\\t'");
break;
case 10:
sb.append("'\\n'");
break;
case 13:
sb.append("'\\r'");
break;
case 65535:
sb.append(FormulaCheckConstants.MISMATCHED_EOF);
break;
default:
sb.append((char) c);
}
}
}

139
designer-base/src/main/java/com/fr/design/formula/exception/function/MismatchedTokenFunction.java

@ -0,0 +1,139 @@
package com.fr.design.formula.exception.function;
import com.fr.design.formula.FormulaChecker;
import com.fr.log.FineLoggerFactory;
import com.fr.script.checker.result.FormulaCheckResult;
import com.fr.script.checker.result.FormulaCoordinates;
import com.fr.stable.StringUtils;
import com.fr.third.antlr.MismatchedTokenException;
import java.lang.reflect.Field;
import java.util.function.Function;
/**
* @author Hoky
* @date 2021/10/28
*/
public class MismatchedTokenFunction implements Function<Exception, FormulaCheckResult> {
private final static MismatchedTokenFunction FUNCTION = new MismatchedTokenFunction();
public static final String NULL_STRING = "null";
@Override
public FormulaCheckResult apply(Exception e) {
if (e instanceof MismatchedTokenException) {
MismatchedTokenException charException = (MismatchedTokenException) e;
FormulaCoordinates formulaCoordinates = new FormulaCoordinates(charException.line, charException.column - 1);
return new FormulaCheckResult(false, getMessage(charException), formulaCoordinates);
}
return new FormulaCheckResult(false, FormulaChecker.INVALID_FORMULA, FormulaCoordinates.INVALID);
}
public static Function<Exception, FormulaCheckResult> getFunction() {
return FUNCTION;
}
public String getMessage(MismatchedTokenException exception) {
StringBuilder sb = new StringBuilder();
Object fieldValue = getFieldValue(exception, "tokenText");
String tokenText = fieldValue == null ? NULL_STRING : fieldValue.toString();
switch (exception.mismatchType) {
case 1:
sb.append(FormulaCheckConstants.EXPECTING)
.append(tokenName(exception.expecting, exception))
.append(", ")
.append(FormulaCheckConstants.FOUND)
.append(FormulaCheckConstants.BLANK + FormulaCheckConstants.SINGLE_QUOTES)
.append(tokenText).append("'");
break;
case 2:
sb.append(FormulaCheckConstants.EXPECTING_ANYTHING)
.append(tokenName(exception.expecting, exception))
.append("; ")
.append(FormulaCheckConstants.GOT_IT_ANYWAY);
break;
case 3:
sb.append(FormulaCheckConstants.EXPECTING)
.append(FormulaCheckConstants.TOKEN)
.append(FormulaCheckConstants.IN_RANGE)
.append(": ")
.append(tokenName(exception.expecting, exception))
.append("..")
.append(tokenName(exception.upper, exception))
.append(", ").append(FormulaCheckConstants.FOUND)
.append("'").append(tokenText).append("'");
break;
case 4:
sb.append(FormulaCheckConstants.EXPECTING)
.append(FormulaCheckConstants.TOKEN)
.append(FormulaCheckConstants.CHECK_NOT)
.append(FormulaCheckConstants.IN_RANGE)
.append(": ")
.append(tokenName(exception.expecting, exception))
.append("..")
.append(tokenName(exception.upper, exception))
.append(",").
append(FormulaCheckConstants.FOUND)
.append(" '")
.append(tokenText)
.append("'");
break;
case 5:
case 6:
sb.append(FormulaCheckConstants.EXPECTING)
.append(exception.mismatchType == 6 ? FormulaCheckConstants.CHECK_NOT : FormulaCheckConstants.BLANK)
.append(FormulaCheckConstants.ONE_OF).append("(");
int[] elms = exception.set.toArray();
for (int i = 0; i < elms.length; ++i) {
sb.append(' ');
sb.append(tokenName(elms[i], exception));
}
sb.append("),")
.append(FormulaCheckConstants.FOUND)
.append("'")
.append(tokenText)
.append("'");
break;
default:
sb.append(FormulaCheckConstants.MISMATCHED_TOKEN);
}
return sb.toString();
}
private String tokenName(int tokenType, MismatchedTokenException exception) {
if (tokenType == 0) {
return "<Set of tokens>";
} else {
String[] tokenNames = (String[]) getFieldValue(exception, "tokenNames");
return tokenType >= 0 && tokenType < tokenNames.length ? translateToken(tokenNames[tokenType]) : "<" + tokenType + ">";
}
}
private String translateToken(String token) {
switch (token) {
case ("RPAREN"):
return ")";
case ("LPAREN"):
return "(";
case ("COMMA"):
return ",";
case ("COLON"):
return ":";
default:
return token;
}
}
private Object getFieldValue(Object object, String fieldName) {
try {
Field field = object.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
return field.get(object);
} catch (Exception e) {
FineLoggerFactory.getLogger().warn(e.getMessage(), e);
return StringUtils.EMPTY;
}
}
}

43
designer-base/src/main/java/com/fr/design/formula/exception/function/NoViableAltForCharFunction.java

@ -0,0 +1,43 @@
package com.fr.design.formula.exception.function;
import com.fr.design.formula.FormulaChecker;
import com.fr.script.checker.result.FormulaCheckResult;
import com.fr.script.checker.result.FormulaCoordinates;
import com.fr.third.antlr.NoViableAltForCharException;
import java.util.function.Function;
/**
* @author Hoky
* @date 2021/10/28
*/
public class NoViableAltForCharFunction implements Function<Exception, FormulaCheckResult> {
private final static NoViableAltForCharFunction FUNCTION = new NoViableAltForCharFunction();
@Override
public FormulaCheckResult apply(Exception e) {
if (e instanceof NoViableAltForCharException) {
NoViableAltForCharException charException = (NoViableAltForCharException) e;
FormulaCoordinates formulaCoordinates = new FormulaCoordinates(charException.line, charException.column - 1);
return new FormulaCheckResult(false, getMessage(charException), formulaCoordinates);
}
return new FormulaCheckResult(false, FormulaChecker.INVALID_FORMULA, FormulaCoordinates.INVALID);
}
public static Function<Exception, FormulaCheckResult> getFunction() {
return FUNCTION;
}
public String getMessage(NoViableAltForCharException exception) {
String mesg = FormulaCheckConstants.UNEXPECTED_CHAR + ": ";
if (exception.foundChar >= ' ' && exception.foundChar <= '~') {
mesg = mesg + '\'';
mesg = mesg + exception.foundChar;
mesg = mesg + '\'';
} else {
mesg = mesg + exception.foundChar + "(0x" + Integer.toHexString(exception.foundChar).toUpperCase() + ")";
}
return mesg;
}
}

40
designer-base/src/main/java/com/fr/design/formula/exception/function/NoViableAltFunction.java

@ -0,0 +1,40 @@
package com.fr.design.formula.exception.function;
import com.fr.design.formula.FormulaChecker;
import com.fr.script.checker.result.FormulaCheckResult;
import com.fr.script.checker.result.FormulaCoordinates;
import com.fr.third.antlr.NoViableAltException;
import com.fr.third.antlr.TreeParser;
import java.util.function.Function;
/**
* @author Hoky
* @date 2021/10/28
*/
public class NoViableAltFunction implements Function<Exception, FormulaCheckResult> {
private final static NoViableAltFunction FUNCTION = new NoViableAltFunction();
@Override
public FormulaCheckResult apply(Exception e) {
if (e instanceof NoViableAltException) {
NoViableAltException altException = (NoViableAltException) e;
FormulaCoordinates formulaCoordinates = new FormulaCoordinates(altException.line, altException.column - 1);
return new FormulaCheckResult(false, getMessage(altException), formulaCoordinates);
}
return new FormulaCheckResult(false, FormulaChecker.INVALID_FORMULA, FormulaCoordinates.INVALID);
}
public static Function<Exception, FormulaCheckResult> getFunction() {
return FUNCTION;
}
public String getMessage(NoViableAltException exception) {
if (exception.token != null) {
return FormulaCheckConstants.UNEXPECTED_TOKEN + ": " + exception.token.getText();
} else {
return exception.node == TreeParser.ASTNULL ? FormulaCheckConstants.UNEXPECTED_END_OF_SUBTREE :
FormulaCheckConstants.UNEXPECTED_AST_NODE + ": " + exception.node.toString();
}
}
}

1003
designer-base/src/main/java/com/fr/design/gui/autocomplete/FormulaAutoCompletePopupWindow.java

File diff suppressed because it is too large Load Diff

22
designer-base/src/main/java/com/fr/design/gui/autocomplete/FormulaCompletion.java

@ -0,0 +1,22 @@
package com.fr.design.gui.autocomplete;
import javax.swing.Icon;
/**
* @author Hoky
* @date 2021/11/5
*/
public class FormulaCompletion extends BasicCompletion {
private Icon icon;
public FormulaCompletion(CompletionProvider provider, String replacementText, Icon icon) {
super(provider, replacementText);
this.icon = icon;
}
@Override
public Icon getIcon() {
return icon;
}
}

1311
designer-base/src/main/java/com/fr/design/gui/autocomplete/FormulaPaneAutoCompletion.java

File diff suppressed because it is too large Load Diff

28
designer-base/src/main/java/com/fr/design/gui/autocomplete/ParameterizedCompletionContext.java

@ -16,16 +16,34 @@ import com.fr.design.gui.syntax.ui.rsyntaxtextarea.RSyntaxTextArea;
import com.fr.design.gui.syntax.ui.rtextarea.ChangeableHighlightPainter;
import com.fr.log.FineLoggerFactory;
import javax.swing.*;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.*;
import javax.swing.text.AbstractDocument;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultEditorKit;
import javax.swing.text.Document;
import javax.swing.text.Highlighter;
import javax.swing.text.Highlighter.Highlight;
import javax.swing.text.Highlighter.HighlightPainter;
import java.awt.*;
import java.awt.event.*;
import javax.swing.text.JTextComponent;
import javax.swing.text.Position;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;
@ -41,7 +59,7 @@ import java.util.List;
* @author Robert Futrell
* @version 1.0
*/
class ParameterizedCompletionContext {
public class ParameterizedCompletionContext {
/**
* The parent window.

BIN
designer-base/src/main/resources/com/fr/design/images/m_file/formula.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 B

BIN
designer-base/src/main/resources/com/fr/design/images/m_file/param.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 383 B

Loading…
Cancel
Save