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. 26
      designer-base/src/main/java/com/fr/design/dialog/UIDialog.java
  3. 78
      designer-base/src/main/java/com/fr/design/formula/FormulaChecker.java
  4. 341
      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.design.utils.gui.GUICoreUtils;
import com.fr.stable.core.PropertyChangeAdapter; import com.fr.stable.core.PropertyChangeAdapter;
import javax.swing.*; import javax.swing.JPanel;
import javax.swing.event.DocumentEvent; 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 @Open
public abstract class BasicPane extends JPanel { public abstract class BasicPane extends JPanel {
@ -262,6 +267,10 @@ public abstract class BasicPane extends JPanel {
public void checkValid() throws Exception { public void checkValid() throws Exception {
} }
public boolean confirmContinueBeforeDoOK() {
return true;
}
public static class NamePane extends BasicPane { public static class NamePane extends BasicPane {
private UITextField nameTextField; private UITextField nameTextField;
private UILabel Name; private UILabel Name;
@ -390,6 +399,10 @@ public abstract class BasicPane extends JPanel {
BasicPane.this.checkValid(); BasicPane.this.checkValid();
} }
public boolean confirmContinueBeforeDoOK() {
return BasicPane.this.confirmContinueBeforeDoOK();
}
} }
private class UnsizedDialog extends UIDialog { private class UnsizedDialog extends UIDialog {

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

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

@ -1,91 +1,43 @@
package com.fr.design.formula; package com.fr.design.formula;
import com.fr.design.formula.exception.FormulaExceptionTipsProcessor;
import com.fr.design.i18n.Toolkit; import com.fr.design.i18n.Toolkit;
import com.fr.log.FineLoggerFactory;
import com.fr.parser.FRLexer; import com.fr.parser.FRLexer;
import com.fr.parser.FRParser; import com.fr.parser.FRParser;
import com.fr.script.checker.FunctionCheckerDispatcher; import com.fr.script.checker.FunctionCheckerDispatcher;
import com.fr.script.checker.exception.ConditionCheckWrongException; import com.fr.script.checker.result.FormulaCheckResult;
import com.fr.script.checker.exception.FunctionCheckWrongException; 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 com.fr.stable.script.Expression; import com.fr.stable.script.Expression;
import com.fr.stable.script.Node; import com.fr.stable.script.Node;
import com.fr.third.antlr.TokenStreamRecognitionException;
import java.io.StringReader; import java.io.StringReader;
import java.util.List;
/** /**
* @author Hoky * @author Hoky
* @date 2021/9/28 * @date 2021/9/28
*/ */
public class FormulaChecker { public class FormulaChecker {
private static final String VALID_FORMULA = Toolkit.i18nText("Fine-Design_Basic_FormulaD_Valid_Formula"); public 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 INVALID_FORMULA = Toolkit.i18nText("Fine-Design_Basic_FormulaD_Invalid_Formula");
public static final String COLON = ":"; 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); StringReader in = new StringReader(formulaText);
FRLexer lexer = new FRLexer(in); FRLexer lexer = new FRLexer(in);
FRParser parser = new FRParser(lexer); FRParser parser = new FRParser(lexer);
try { try {
Expression expression = parser.parse(); Expression expression = parser.parse();
Node node = expression.getConditionalExpression(); Node node = expression.getConditionalExpression();
boolean valid = FunctionCheckerDispatcher.getInstance().getFunctionChecker(node).checkFunction(node); boolean valid = FunctionCheckerDispatcher.getInstance().getFunctionChecker(node).checkFunction(formulaText, node);
if (valid) { return new FormulaCheckResult(valid, valid ? VALID_FORMULA : INVALID_FORMULA, FormulaCoordinates.INVALID);
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());
} catch (Exception e) { } catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e); if (e instanceof TokenStreamRecognitionException) {
throw new FormulaCheckerException(INVALID_FORMULA); return processor.getExceptionTips(((TokenStreamRecognitionException) e).recog);
// alex:继续往下面走,expression为null时告知不合法公式 }
} 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;
} }
} }

341
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.DialogActionAdapter;
import com.fr.design.dialog.FineJOptionPane; import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.file.HistoryTemplateListCache; 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.ibutton.UIButton;
import com.fr.design.gui.icheckbox.UICheckBox;
import com.fr.design.gui.icontainer.UIScrollPane; import com.fr.design.gui.icontainer.UIScrollPane;
import com.fr.design.gui.ilable.UILabel; import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.ilist.QuickList; 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.report.core.namespace.SimpleCellValueNameSpace;
import com.fr.script.Calculator; import com.fr.script.Calculator;
import com.fr.script.ScriptConstants; import com.fr.script.ScriptConstants;
import com.fr.script.checker.result.FormulaCheckResult;
import com.fr.stable.EncodeConstants; import com.fr.stable.EncodeConstants;
import com.fr.stable.EssentialUtils; import com.fr.stable.EssentialUtils;
import com.fr.stable.ParameterProvider; import com.fr.stable.ParameterProvider;
@ -65,6 +72,7 @@ import javax.swing.JList;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.swing.JPopupMenu; import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTree; import javax.swing.JTree;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionEvent;
@ -82,6 +90,8 @@ import java.awt.Component;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyAdapter; import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import java.awt.event.KeyListener; import java.awt.event.KeyListener;
@ -112,17 +122,27 @@ import java.util.Set;
* @since 2012-3-29下午1:50:53 * @since 2012-3-29下午1:50:53
*/ */
public class FormulaPane extends BasicPane implements KeyListener, UIFormula { public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
private final static String CONFIRM_DIALOG_TITLE = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Confirm");
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");
public static final int DEFUAL_FOMULA_LENGTH = 103; public static final int DEFUAL_FOMULA_LENGTH = 103;
public static final String ELLIPSIS = "..."; 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 VariableTreeAndDescriptionArea variableTreeAndDescriptionArea;
private RSyntaxTextArea formulaTextArea; private RSyntaxTextArea formulaTextArea;
private UITextField keyWordTextField = new UITextField(18); private UITextField keyWordTextField = new UITextField(18);
private int currentPosition = 0; private int currentPosition = 0;
private int beginPosition = 0; private int beginPosition = 0;
private int insertPosition = 0; private int insertPosition = 0;
protected static UICheckBox autoCompletionCheck;
protected static UICheckBox checkBeforeColse;
private JList tipsList; private JList tipsList;
protected DefaultListModel listModel = new DefaultListModel(); protected DefaultListModel listModel = new DefaultListModel();
private int ifHasBeenWriten = 0; private int ifHasBeenWriten = 0;
@ -131,6 +151,9 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
private DefaultListModel functionNameModel; private DefaultListModel functionNameModel;
private JList functionNameList; private JList functionNameList;
private UITableEditorPane<ParameterProvider> editor4CalPane; 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() { public FormulaPane() {
initComponents(); initComponents();
@ -139,6 +162,21 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
private void initFormulaTextAreaKeyListener() { private void initFormulaTextAreaKeyListener() {
formulaTextArea.addKeyListener(this); formulaTextArea.addKeyListener(this);
formulaTextArea.addKeyListener(new KeyAdapter() { 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) { public void keyReleased(KeyEvent e) {
formulaTextArea.setForeground(Color.black); formulaTextArea.setForeground(Color.black);
String text = formulaTextArea.getText(); String text = formulaTextArea.getText();
@ -150,6 +188,9 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
insertPosition = 0; insertPosition = 0;
formulaTextArea.setText(text); formulaTextArea.setText(text);
} }
if (e.getExtendedKeyCode() == KEY_CODE_$) {
autoCompletion.doCompletion();
}
} }
}); });
} }
@ -174,7 +215,9 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
beginPosition = getBeginPosition(); beginPosition = getBeginPosition();
insertPosition = beginPosition; insertPosition = beginPosition;
firstStepToFindTips(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) { if (e.getKeyCode() == KeyEvent.VK_ENTER) {
String toFind = keyWordTextField.getText(); String toFind = keyWordTextField.getText();
search(toFind, false); search(toFind, false);
fixFunctionNameList(); if (tipsList.getSelectedValue() != null) {
fixFunctionNameList(tipsList.getSelectedValue().toString());
}
e.consume(); e.consume();
} }
} }
@ -213,28 +258,26 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
private void initTipsPane() { private void initTipsPane() {
// tipsPane // 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); searchPane.add(keyWordTextField, BorderLayout.CENTER);
UIButton searchButton = new UIButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaPane_Search")); 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); searchPane.add(searchButton, BorderLayout.EAST);
tipsPane.add(searchPane, BorderLayout.NORTH); searchPane.add(formulaLabel, BorderLayout.WEST);
initKeyWordTextFieldKeyListener(); initKeyWordTextFieldKeyListener();
tipsList = new JList(listModel); tipsList = new JList(listModel);
tipsList.addMouseListener(new DoubleClick()); tipsList.addMouseListener(new DoubleClick());
UIScrollPane tipsScrollPane = new UIScrollPane(tipsList); searchButton.addActionListener(e -> {
tipsScrollPane.setPreferredSize(new Dimension(170, 75)); String toFind = keyWordTextField.getText();
tipsScrollPane.setBorder(new UIRoundedBorder(UIConstants.LINE_COLOR, 1, UIConstants.ARC)); search(toFind, false);
tipsPane.add(tipsScrollPane, BorderLayout.CENTER); popTips();
searchButton.addActionListener(new ActionListener() { formulaTextArea.requestFocusInWindow();
@Override if (tipsList.getSelectedValue() != null) {
public void actionPerformed(ActionEvent e) { fixFunctionNameList(tipsList.getSelectedValue().toString());
String toFind = keyWordTextField.getText();
search(toFind, false);
formulaTextArea.requestFocusInWindow();
fixFunctionNameList();
} }
}); });
} }
@ -254,18 +297,13 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
private void initTextPane() { private void initTextPane() {
// text // text
JPanel textPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); JPanel textPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
this.add(textPane, BorderLayout.CENTER); this.add(textPane, BorderLayout.CENTER);
JPanel checkBoxandbuttonPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); JPanel checkBoxandbuttonPane = FRGUIPaneFactory.createX_AXISBoxInnerContainer_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));
initFormulaTextArea(); initFormulaTextArea();
UIScrollPane formulaTextAreaScrollPane = new UIScrollPane(formulaTextArea); UIScrollPane formulaTextAreaScrollPane = new UIScrollPane(formulaTextArea);
formulaTextAreaScrollPane.setBorder(null); formulaTextAreaScrollPane.setBorder(null);
textPane.add(formulaLabel, BorderLayout.NORTH);
textPane.add(formulaTextAreaScrollPane, BorderLayout.CENTER); textPane.add(formulaTextAreaScrollPane, BorderLayout.CENTER);
textPane.add(checkBoxandbuttonPane, BorderLayout.SOUTH); textPane.add(checkBoxandbuttonPane, BorderLayout.SOUTH);
@ -275,19 +313,105 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
checkValidButton.addActionListener(checkValidActionListener); checkValidButton.addActionListener(checkValidActionListener);
calButton.addActionListener(calculateActionListener); calButton.addActionListener(calculateActionListener);
//靠左流式布局
JPanel checkBoxPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); JPanel checkBoxPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane();
checkBoxPane.setPreferredSize(new Dimension(450, 30));
checkBoxandbuttonPane.add(checkBoxPane, BorderLayout.WEST); 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); extendCheckBoxPane(checkBoxPane);
ParameterTableModel model = new ParameterTableModel(0); ParameterTableModel model = new ParameterTableModel(0);
editor4CalPane = new UITableEditorPane<>(model); 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) { protected void extendCheckBoxPane(JPanel checkBoxPane) {
// do nothing // do nothing
} }
@ -341,7 +465,9 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
private void singleClickActuator(String currentLineContent) { private void singleClickActuator(String currentLineContent) {
refreshDescriptionTextArea(currentLineContent); refreshDescriptionTextArea(currentLineContent);
formulaTextArea.requestFocusInWindow(); formulaTextArea.requestFocusInWindow();
fixFunctionNameList(); if (tipsList.getSelectedValue() != null) {
fixFunctionNameList(tipsList.getSelectedValue().toString());
}
} }
private void doubleClickActuator(String currentLineContent) { private void doubleClickActuator(String currentLineContent) {
@ -405,43 +531,41 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
beginPosition = getBeginPosition(); beginPosition = getBeginPosition();
insertPosition = beginPosition; insertPosition = beginPosition;
firstStepToFindTips(beginPosition); firstStepToFindTips(beginPosition);
fixFunctionNameList(); if (tipsList.getSelectedValue() != null) {
fixFunctionNameList(tipsList.getSelectedValue().toString());
}
ifHasBeenWriten = 1; ifHasBeenWriten = 1;
} }
} }
} }
private void fixFunctionNameList() { private void fixFunctionNameList(String functionName) {
if (tipsList.getSelectedValue() != null) { int signOfContinue = 1;
int signOfContinue = 1; int indexOfFunction = 0;
int indexOfFunction = 0; for (int i = 0; i < functionTypeListModel.size(); i++) {
for (int i = 0; i < functionTypeListModel.size(); i++) { int signOfType = 0;
int signOfType = 0; FunctionGroup functionType = (FunctionGroup) functionTypeListModel.getElementAt(i);
FunctionGroup functionType = (FunctionGroup) functionTypeListModel.getElementAt(i); NameAndDescription[] nads = functionType.getDescriptions();
NameAndDescription[] nads = functionType.getDescriptions(); if (signOfContinue == 1) {
if (signOfContinue == 1) { functionNameModel.removeAllElements();
functionNameModel.removeAllElements(); for (int k = 0; k < nads.length; k++) {
String functionName = ((String) tipsList.getSelectedValue()); functionNameModel.addElement(nads[k]);
for (int k = 0; k < nads.length; k++) { if (functionName.equals(nads[k].getName()))//若相等,找出显示的函数的index,setSelectedIndex()
functionNameModel.addElement(nads[k]); {
if (functionName.equals(nads[k].getName()))//若相等,找出显示的函数的index,setSelectedIndex() signOfType = 1;
{ signOfContinue = 0;
signOfType = 1; indexOfFunction = k;
signOfContinue = 0;
indexOfFunction = k;
}
} }
}
if (signOfType == 1) { if (signOfType == 1) {
functionTypeList.setSelectedIndex(i); functionTypeList.setSelectedIndex(i);
signOfType = 0; signOfType = 0;
}
} }
} }
functionNameList.setSelectedIndex(indexOfFunction);
functionNameList.ensureIndexIsVisible(indexOfFunction);
} }
functionNameList.setSelectedIndex(indexOfFunction);
functionNameList.ensureIndexIsVisible(indexOfFunction);
} }
private int getBeginPosition() { private int getBeginPosition() {
@ -492,9 +616,17 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
// do nothing // 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) { protected void search(String keyWord, boolean findDescription) {
listModel.removeAllElements(); listModel.removeAllElements();
keyWord = removeAllSpace(keyWord); keyWord = removeAllSpace(keyWord);
if (keyWord.length() != 0) { if (keyWord.length() != 0) {
NameAndDescription[] descriptions = FunctionConstants.ALL.getDescriptions(); NameAndDescription[] descriptions = FunctionConstants.ALL.getDescriptions();
@ -610,7 +742,9 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
beginPosition = getBeginPosition(); beginPosition = getBeginPosition();
insertPosition = beginPosition; insertPosition = beginPosition;
firstStepToFindTips(beginPosition); firstStepToFindTips(beginPosition);
fixFunctionNameList(); if (tipsList.getSelectedValue() != null) {
fixFunctionNameList(tipsList.getSelectedValue().toString());
}
ifHasBeenWriten = 1; ifHasBeenWriten = 1;
} else { } else {
this.formulaTextArea.setText(content); this.formulaTextArea.setText(content);
@ -618,7 +752,9 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
beginPosition = getBeginPosition(); beginPosition = getBeginPosition();
insertPosition = beginPosition; insertPosition = beginPosition;
firstStepToFindTips(beginPosition); firstStepToFindTips(beginPosition);
fixFunctionNameList(); if (tipsList.getSelectedValue() != null) {
fixFunctionNameList(tipsList.getSelectedValue().toString());
}
ifHasBeenWriten = 1; ifHasBeenWriten = 1;
} }
} }
@ -650,17 +786,12 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
public void actionPerformed(ActionEvent evt) { public void actionPerformed(ActionEvent evt) {
// Execute Formula default cell element. // Execute Formula default cell element.
String formulaText = formulaTextArea.getText().trim(); String formulaText = formulaTextArea.getText().trim();
String formulaValidMessage; FormulaCheckResult checkResult = FormulaChecker.check(formulaText);
try { confirmCheckResult(checkResult);
formulaValidMessage = FormulaChecker.check(formulaText);
showMessageDialog(formulaValidMessage + ".");
} catch (FormulaCheckerException e) {
formulaValidMessage = e.getMessage();
showMessageDialog(formulaValidMessage + ".", false);
}
} }
}; };
private final ActionListener calculateActionListener = new ActionListener() { private final ActionListener calculateActionListener = new ActionListener() {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
@ -671,20 +802,10 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
return; return;
} }
String formulaValidMessage;
boolean formulaValid;
try {
formulaValidMessage = FormulaChecker.check(formulaText);
formulaValid = true;
} catch (FormulaCheckerException formulaCheckerException) {
formulaValidMessage = formulaCheckerException.getMessage();
formulaValid = false;
}
String messageTips; String messageTips;
if (ComparatorUtils.equals(formulaValidMessage, INVALID_FORMULA)) { FormulaCheckResult checkResult = FormulaChecker.check(formulaText);
messageTips = INVALID_FORMULA; if (checkResult.isValid()) {
} else { messageTips = checkResult.getTips() + NEWLINE;
messageTips = ComparatorUtils.equals(formulaValidMessage, VALID_FORMULA) ? "" : formulaValidMessage + "\n";
Map<String, Object> paramsMap = setParamsIfExist(formulaText); Map<String, Object> paramsMap = setParamsIfExist(formulaText);
Calculator calculator = Calculator.createCalculator(); Calculator calculator = Calculator.createCalculator();
ParameterMapNameSpace parameterMapNameSpace = ParameterMapNameSpace.create(paramsMap); ParameterMapNameSpace parameterMapNameSpace = ParameterMapNameSpace.create(paramsMap);
@ -704,19 +825,42 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
String objectToString = EssentialUtils.objectToString(value); String objectToString = EssentialUtils.objectToString(value);
String result = objectToString.length() > DEFUAL_FOMULA_LENGTH ? String result = objectToString.length() > DEFUAL_FOMULA_LENGTH ?
objectToString.substring(0, DEFUAL_FOMULA_LENGTH - ELLIPSIS.length()) + ELLIPSIS : objectToString; objectToString.substring(0, DEFUAL_FOMULA_LENGTH - ELLIPSIS.length()) + ELLIPSIS : objectToString;
messageTips = messageTips + messageTips = messageTips + CAL_RESULT + ":" + result;
Toolkit.i18nText("Fine-Design_Basic_Formula_Cal_Result") + ":" + result;
FineLoggerFactory.getLogger().info("value:{}", value); FineLoggerFactory.getLogger().info("value:{}", value);
} catch (UtilEvalError utilEvalError) { } 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) { private boolean confirmCheckResult(FormulaCheckResult checkResult) {
showMessageDialog(message, true); 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) { private void showMessageDialog(String message, boolean formulaValid) {
@ -750,6 +894,18 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
return null; 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) { private Map<String, Object> setParamsIfExist(String formulaText) {
Map<String, Object> parameterMap = new HashMap<>(); Map<String, Object> parameterMap = new HashMap<>();
try { try {
@ -990,7 +1146,8 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
private void initDescriptionTextArea() { private void initDescriptionTextArea() {
// Description // Description
descriptionTextArea = new UITextArea(16, 27); descriptionTextArea = new UITextArea();
descriptionTextArea.setPreferredSize(new Dimension(350, 200));
UIScrollPane desScrollPane = new UIScrollPane(descriptionTextArea); UIScrollPane desScrollPane = new UIScrollPane(descriptionTextArea);
desScrollPane.setBorder(null); 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) { public void populate(VariableResolver variableResolver) {
// varibale tree. // varibale tree.
DefaultTreeModel variableModel = (DefaultTreeModel) variablesTree.getModel(); DefaultTreeModel variableModel = (DefaultTreeModel) variablesTree.getModel();
@ -1326,12 +1487,12 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
buffer.append(name.toUpperCase()); buffer.append(name.toUpperCase());
buffer.append("\""); buffer.append("\"");
buffer.append("|"); buffer.append("|");
buffer.append("\n"); buffer.append(NEWLINE);
buffer.append("\""); buffer.append("\"");
buffer.append(name.toLowerCase()); buffer.append(name.toLowerCase());
buffer.append("\""); buffer.append("\"");
buffer.append("|"); buffer.append("|");
buffer.append("\n"); buffer.append(NEWLINE);
} }
FineLoggerFactory.getLogger().debug(buffer.toString()); 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.base.BaseFormula;
import com.fr.design.gui.icheckbox.UICheckBox; import com.fr.design.gui.icheckbox.UICheckBox;
import javax.swing.JPanel;
import javax.swing.*;
import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener; import javax.swing.event.ChangeListener;
import java.awt.*; import java.awt.BorderLayout;
/** /**
* @author richie * @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 = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Write_Save_Formula"));
reserveCheckBox4Write.setSelected(false); reserveCheckBox4Write.setSelected(false);
checkBoxPane.add(reserveCheckBox4Result, BorderLayout.CENTER); checkBoxPane.add(reserveCheckBox4Result, BorderLayout.WEST);
checkBoxPane.add(reserveCheckBox4Write, BorderLayout.SOUTH); checkBoxPane.add(reserveCheckBox4Write, BorderLayout.WEST);
} }
@Override @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.design.gui.syntax.ui.rtextarea.ChangeableHighlightPainter;
import com.fr.log.FineLoggerFactory; 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.CaretEvent;
import javax.swing.event.CaretListener; import javax.swing.event.CaretListener;
import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener; 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.Highlight;
import javax.swing.text.Highlighter.HighlightPainter; import javax.swing.text.Highlighter.HighlightPainter;
import java.awt.*; import javax.swing.text.JTextComponent;
import java.awt.event.*; 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.ArrayList;
import java.util.List; import java.util.List;
@ -41,7 +59,7 @@ import java.util.List;
* @author Robert Futrell * @author Robert Futrell
* @version 1.0 * @version 1.0
*/ */
class ParameterizedCompletionContext { public class ParameterizedCompletionContext {
/** /**
* The parent window. * 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