|
|
|
@ -2,69 +2,36 @@ package com.fr.design.formula;
|
|
|
|
|
|
|
|
|
|
import com.fr.base.BaseFormula; |
|
|
|
|
import com.fr.base.BaseUtils; |
|
|
|
|
import com.fr.base.Parameter; |
|
|
|
|
import com.fr.base.ParameterMapNameSpace; |
|
|
|
|
import com.fr.base.TableDataNameSpace; |
|
|
|
|
import com.fr.base.io.IOFile; |
|
|
|
|
import com.fr.data.TableDataSource; |
|
|
|
|
import com.fr.base.FRContext; |
|
|
|
|
import com.fr.design.actions.UpdateAction; |
|
|
|
|
import com.fr.design.border.UIRoundedBorder; |
|
|
|
|
import com.fr.design.constants.UIConstants; |
|
|
|
|
import com.fr.design.dialog.BasicDialog; |
|
|
|
|
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.ibutton.UIButton; |
|
|
|
|
import com.fr.design.gui.icontainer.UIScrollPane; |
|
|
|
|
import com.fr.design.gui.ilable.UILabel; |
|
|
|
|
import com.fr.design.gui.ilist.QuickList; |
|
|
|
|
import com.fr.design.gui.itableeditorpane.ParameterTableModel; |
|
|
|
|
import com.fr.design.gui.itableeditorpane.UITableEditorPane; |
|
|
|
|
import com.fr.design.gui.itextarea.UITextArea; |
|
|
|
|
import com.fr.design.gui.itextfield.UITextField; |
|
|
|
|
import com.fr.design.gui.syntax.ui.rsyntaxtextarea.RSyntaxTextArea; |
|
|
|
|
import com.fr.design.gui.syntax.ui.rsyntaxtextarea.SyntaxConstants; |
|
|
|
|
import com.fr.design.i18n.Toolkit; |
|
|
|
|
import com.fr.design.layout.FRGUIPaneFactory; |
|
|
|
|
import com.fr.design.mainframe.DesignerContext; |
|
|
|
|
import com.fr.design.mainframe.JTemplate; |
|
|
|
|
import com.fr.design.parameter.ParameterInputPane; |
|
|
|
|
import com.fr.design.utils.gui.GUICoreUtils; |
|
|
|
|
import com.fr.general.ComparatorUtils; |
|
|
|
|
import com.fr.general.FArray; |
|
|
|
|
import com.fr.log.FineLoggerFactory; |
|
|
|
|
import com.fr.parser.ArrayExpression; |
|
|
|
|
import com.fr.parser.BlockIntervalLiteral; |
|
|
|
|
import com.fr.parser.ColumnRowRangeInPage; |
|
|
|
|
import com.fr.parser.FRLexer; |
|
|
|
|
import com.fr.parser.FRParser; |
|
|
|
|
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.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.EncodeConstants; |
|
|
|
|
import com.fr.stable.EssentialUtils; |
|
|
|
|
import com.fr.stable.ParameterProvider; |
|
|
|
|
import com.fr.stable.ProductConstants; |
|
|
|
|
import com.fr.stable.StringUtils; |
|
|
|
|
import com.fr.stable.UtilEvalError; |
|
|
|
|
import com.fr.stable.script.ColumnRowRange; |
|
|
|
|
import com.fr.stable.script.Expression; |
|
|
|
|
import com.fr.stable.script.Node; |
|
|
|
|
import com.fr.stable.script.Tiny; |
|
|
|
|
import com.fr.stable.script.TinyHunter; |
|
|
|
|
|
|
|
|
|
import javax.swing.BorderFactory; |
|
|
|
|
import javax.swing.DefaultListCellRenderer; |
|
|
|
|
import javax.swing.DefaultListModel; |
|
|
|
|
import javax.swing.Icon; |
|
|
|
|
import javax.swing.JComponent; |
|
|
|
|
import javax.swing.JFrame; |
|
|
|
|
import javax.swing.JList; |
|
|
|
|
import javax.swing.JOptionPane; |
|
|
|
|
import javax.swing.JPanel; |
|
|
|
@ -98,14 +65,7 @@ import java.io.InputStream;
|
|
|
|
|
import java.io.InputStreamReader; |
|
|
|
|
import java.io.Reader; |
|
|
|
|
import java.io.StringReader; |
|
|
|
|
import java.util.ArrayList; |
|
|
|
|
import java.util.Collections; |
|
|
|
|
import java.util.Comparator; |
|
|
|
|
import java.util.HashMap; |
|
|
|
|
import java.util.HashSet; |
|
|
|
|
import java.util.List; |
|
|
|
|
import java.util.Map; |
|
|
|
|
import java.util.Set; |
|
|
|
|
import java.util.Locale; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* 公式编辑面板 |
|
|
|
@ -115,24 +75,19 @@ import java.util.Set;
|
|
|
|
|
*/ |
|
|
|
|
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"); |
|
|
|
|
public static final int DEFUAL_FOMULA_LENGTH = 103; |
|
|
|
|
public static final String ELLIPSIS = "..."; |
|
|
|
|
private VariableTreeAndDescriptionArea variableTreeAndDescriptionArea; |
|
|
|
|
private RSyntaxTextArea formulaTextArea; |
|
|
|
|
private UITextField keyWordTextField = new UITextField(18); |
|
|
|
|
private int currentPosition = 0; |
|
|
|
|
private int beginPosition = 0; |
|
|
|
|
private int insertPosition = 0; |
|
|
|
|
private JList tipsList; |
|
|
|
|
protected VariableTreeAndDescriptionArea variableTreeAndDescriptionArea; |
|
|
|
|
protected RSyntaxTextArea formulaTextArea; |
|
|
|
|
protected UITextField keyWordTextField = new UITextField(18); |
|
|
|
|
protected int currentPosition = 0; |
|
|
|
|
protected int beginPosition = 0; |
|
|
|
|
protected int insertPosition = 0; |
|
|
|
|
protected JList tipsList; |
|
|
|
|
protected DefaultListModel listModel = new DefaultListModel(); |
|
|
|
|
private int ifHasBeenWriten = 0; |
|
|
|
|
private DefaultListModel functionTypeListModel = new DefaultListModel(); |
|
|
|
|
private QuickList functionTypeList; |
|
|
|
|
private DefaultListModel functionNameModel; |
|
|
|
|
private JList functionNameList; |
|
|
|
|
private UITableEditorPane<ParameterProvider> editor4CalPane; |
|
|
|
|
protected int ifHasBeenWriten = 0; |
|
|
|
|
protected DefaultListModel functionTypeListModel = new DefaultListModel(); |
|
|
|
|
protected QuickList functionTypeList; |
|
|
|
|
protected DefaultListModel functionNameModel; |
|
|
|
|
protected JList functionNameList; |
|
|
|
|
|
|
|
|
|
public FormulaPane() { |
|
|
|
|
initComponents(); |
|
|
|
@ -193,12 +148,10 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
|
|
|
|
|
keyWordTextField.addKeyListener(new KeyListener() { |
|
|
|
|
@Override |
|
|
|
|
public void keyTyped(KeyEvent e) { |
|
|
|
|
//do nothing
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public void keyReleased(KeyEvent e) { |
|
|
|
|
//do nothing
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@ -243,20 +196,7 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
|
|
|
|
|
|
|
|
|
|
protected void initComponents() { |
|
|
|
|
this.setLayout(new BorderLayout(4, 4)); |
|
|
|
|
|
|
|
|
|
initTextPane(); |
|
|
|
|
initTipsPane(); |
|
|
|
|
initVariableTreeAndDescriptionArea(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void initVariableTreeAndDescriptionArea() { |
|
|
|
|
variableTreeAndDescriptionArea = new VariableTreeAndDescriptionArea(); |
|
|
|
|
this.add(variableTreeAndDescriptionArea, BorderLayout.SOUTH); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void initTextPane() { |
|
|
|
|
// text
|
|
|
|
|
|
|
|
|
|
JPanel textPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
|
|
|
|
this.add(textPane, BorderLayout.CENTER); |
|
|
|
|
JPanel checkBoxandbuttonPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); |
|
|
|
@ -271,29 +211,26 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
|
|
|
|
|
textPane.add(formulaTextAreaScrollPane, BorderLayout.CENTER); |
|
|
|
|
textPane.add(checkBoxandbuttonPane, BorderLayout.SOUTH); |
|
|
|
|
|
|
|
|
|
initTipsPane(); |
|
|
|
|
|
|
|
|
|
UIButton checkValidButton = new UIButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaD_Check_Valid")); |
|
|
|
|
UIButton calButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Formula_Cal_Button")); |
|
|
|
|
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); |
|
|
|
|
extendCheckBoxPane(checkBoxPane); |
|
|
|
|
|
|
|
|
|
ParameterTableModel model = new ParameterTableModel(0); |
|
|
|
|
editor4CalPane = new UITableEditorPane<>(model); |
|
|
|
|
variableTreeAndDescriptionArea = new VariableTreeAndDescriptionArea(); |
|
|
|
|
this.add(variableTreeAndDescriptionArea, BorderLayout.SOUTH); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected void extendCheckBoxPane(JPanel checkBoxPane) { |
|
|
|
|
// do nothing
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void configFormulaArea() { |
|
|
|
|
protected void configFormulaArea() { |
|
|
|
|
formulaTextArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_FORMULA); |
|
|
|
|
formulaTextArea.setAnimateBracketMatching(true); |
|
|
|
|
formulaTextArea.setAntiAliasingEnabled(true); |
|
|
|
@ -308,68 +245,43 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public class DoubleClick extends MouseAdapter { |
|
|
|
|
String singlePressContent; |
|
|
|
|
|
|
|
|
|
String doublePressContent; |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public void mousePressed(MouseEvent e) { |
|
|
|
|
public void mouseClicked(MouseEvent e) { |
|
|
|
|
int index = tipsList.getSelectedIndex(); |
|
|
|
|
if (index != -1) { |
|
|
|
|
if (e.getClickCount() == 1) { |
|
|
|
|
singlePressContent = (String) listModel.getElementAt(index); |
|
|
|
|
} else if (e.getClickCount() == 2) { |
|
|
|
|
doublePressContent = (String) listModel.getElementAt(index); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public void mouseReleased(MouseEvent e) { |
|
|
|
|
int index = tipsList.getSelectedIndex(); |
|
|
|
|
if (index != -1) { |
|
|
|
|
if (e.getClickCount() == 1) { |
|
|
|
|
if (ComparatorUtils.equals((String) listModel.getElementAt(index), singlePressContent)) { |
|
|
|
|
singleClickActuator(singlePressContent); |
|
|
|
|
String currentLineContent = (String) listModel.getElementAt(index); |
|
|
|
|
if (e.getClickCount() == 2) { |
|
|
|
|
if (ifHasBeenWriten == 0) { |
|
|
|
|
formulaTextArea.setForeground(Color.black); |
|
|
|
|
formulaTextArea.setText(""); |
|
|
|
|
} |
|
|
|
|
} else if (e.getClickCount() == 2) { |
|
|
|
|
if (ComparatorUtils.equals((String) listModel.getElementAt(index), doublePressContent)) { |
|
|
|
|
doubleClickActuator(doublePressContent); |
|
|
|
|
formulaTextArea.setForeground(Color.black); |
|
|
|
|
currentPosition = formulaTextArea.getCaretPosition(); |
|
|
|
|
String output = currentLineContent + "()"; |
|
|
|
|
String textAll = formulaTextArea.getText(); |
|
|
|
|
String textReplaced; |
|
|
|
|
int position = 0; |
|
|
|
|
if (insertPosition <= currentPosition) { |
|
|
|
|
textReplaced = textAll.substring(0, insertPosition) + output + textAll.substring(currentPosition); |
|
|
|
|
position = insertPosition + output.length() - 1; |
|
|
|
|
} else { |
|
|
|
|
textReplaced = textAll.substring(0, currentPosition) + output + textAll.substring(insertPosition); |
|
|
|
|
position = currentPosition + output.length() - 1; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void singleClickActuator(String currentLineContent) { |
|
|
|
|
refreshDescriptionTextArea(currentLineContent); |
|
|
|
|
formulaTextArea.requestFocusInWindow(); |
|
|
|
|
fixFunctionNameList(); |
|
|
|
|
} |
|
|
|
|
formulaTextArea.setText(textReplaced); |
|
|
|
|
formulaTextArea.requestFocusInWindow(); |
|
|
|
|
formulaTextArea.setCaretPosition(position); |
|
|
|
|
insertPosition = position; |
|
|
|
|
ifHasBeenWriten = 1; |
|
|
|
|
listModel.removeAllElements(); |
|
|
|
|
} else if (e.getClickCount() == 1) { |
|
|
|
|
refreshDescriptionTextArea(currentLineContent); |
|
|
|
|
|
|
|
|
|
private void doubleClickActuator(String currentLineContent) { |
|
|
|
|
if (ifHasBeenWriten == 0) { |
|
|
|
|
formulaTextArea.setForeground(Color.black); |
|
|
|
|
formulaTextArea.setText(""); |
|
|
|
|
} |
|
|
|
|
formulaTextArea.setForeground(Color.black); |
|
|
|
|
currentPosition = formulaTextArea.getCaretPosition(); |
|
|
|
|
String output = currentLineContent + "()"; |
|
|
|
|
String textAll = formulaTextArea.getText(); |
|
|
|
|
String textReplaced; |
|
|
|
|
int position = 0; |
|
|
|
|
if (insertPosition <= currentPosition) { |
|
|
|
|
textReplaced = textAll.substring(0, insertPosition) + output + textAll.substring(currentPosition); |
|
|
|
|
position = insertPosition + output.length() - 1; |
|
|
|
|
} else { |
|
|
|
|
textReplaced = textAll.substring(0, currentPosition) + output + textAll.substring(insertPosition); |
|
|
|
|
position = currentPosition + output.length() - 1; |
|
|
|
|
formulaTextArea.requestFocusInWindow(); |
|
|
|
|
fixFunctionNameList(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
formulaTextArea.setText(textReplaced); |
|
|
|
|
formulaTextArea.requestFocusInWindow(); |
|
|
|
|
formulaTextArea.setCaretPosition(position); |
|
|
|
|
insertPosition = position; |
|
|
|
|
ifHasBeenWriten = 1; |
|
|
|
|
listModel.removeAllElements(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -413,7 +325,7 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void fixFunctionNameList() { |
|
|
|
|
protected void fixFunctionNameList() { |
|
|
|
|
if (tipsList.getSelectedValue() != null) { |
|
|
|
|
int signOfContinue = 1; |
|
|
|
|
int indexOfFunction = 0; |
|
|
|
@ -446,7 +358,7 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private int getBeginPosition() { |
|
|
|
|
protected int getBeginPosition() { |
|
|
|
|
int i = currentPosition; |
|
|
|
|
String textArea = formulaTextArea.getText(); |
|
|
|
|
for (; i > 0; i--) { |
|
|
|
@ -461,7 +373,7 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
|
|
|
|
|
return i; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void firstStepToFindTips(int theBeginPosition) { |
|
|
|
|
protected void firstStepToFindTips(int theBeginPosition) { |
|
|
|
|
String textArea = formulaTextArea.getText(); |
|
|
|
|
|
|
|
|
|
if (currentPosition > 0 && theBeginPosition < currentPosition) { |
|
|
|
@ -491,7 +403,6 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public void keyTyped(KeyEvent e) { |
|
|
|
|
// do nothing
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected void search(String keyWord, boolean findDescription) { |
|
|
|
@ -501,19 +412,14 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
|
|
|
|
|
if (keyWord.length() != 0) { |
|
|
|
|
NameAndDescription[] descriptions = FunctionConstants.ALL.getDescriptions(); |
|
|
|
|
int lengthOfDes = descriptions.length; |
|
|
|
|
List<String> list = new ArrayList<>(); |
|
|
|
|
for (int i = 0; i < lengthOfDes; i++) { |
|
|
|
|
NameAndDescription and = descriptions[i]; |
|
|
|
|
|
|
|
|
|
String functionName = and.searchResult(keyWord, findDescription); |
|
|
|
|
if (StringUtils.isNotBlank(functionName)) { |
|
|
|
|
list.add(functionName); |
|
|
|
|
listModel.addElement(functionName); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
Collections.sort(list, new SimilarComparator(keyWord)); |
|
|
|
|
for (String name : list) { |
|
|
|
|
listModel.addElement(name); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!listModel.isEmpty()) { |
|
|
|
|
tipsList.setSelectedIndex(0); |
|
|
|
@ -549,7 +455,7 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
|
|
|
|
|
/** |
|
|
|
|
* Apply text. |
|
|
|
|
*/ |
|
|
|
|
private void applyText(String text) { |
|
|
|
|
public void applyText(String text) { |
|
|
|
|
if (text == null || text.length() <= 0) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
@ -647,234 +553,45 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// check valid
|
|
|
|
|
private final ActionListener checkValidActionListener = new ActionListener() { |
|
|
|
|
protected ActionListener checkValidActionListener = new ActionListener() { |
|
|
|
|
|
|
|
|
|
public void actionPerformed(ActionEvent evt) { |
|
|
|
|
// Execute Formula default cell element.
|
|
|
|
|
String formulaText = formulaTextArea.getText().trim(); |
|
|
|
|
String formulaValidMessage = getFormulaValidMessage(formulaText); |
|
|
|
|
FineJOptionPane.showMessageDialog( |
|
|
|
|
FormulaPane.this, |
|
|
|
|
formulaValidMessage + ".", |
|
|
|
|
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Tool_Tips"), |
|
|
|
|
JOptionPane.INFORMATION_MESSAGE); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
private static String getFormulaValidMessage(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(); |
|
|
|
|
return FunctionCheckerDispatcher.getInstance() |
|
|
|
|
.getFunctionChecker(node) |
|
|
|
|
.checkFunction(node) ? VALID_FORMULA : INVALID_FORMULA; |
|
|
|
|
} catch (ConditionCheckWrongException cce) { |
|
|
|
|
String functionName = cce.getFunctionName(); |
|
|
|
|
StringBuilder errorMsg = new StringBuilder(functionName + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Condition_Tips") + ":"); |
|
|
|
|
return errorMsg.toString(); |
|
|
|
|
} 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") + ":"); |
|
|
|
|
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")); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return errorMsg.toString(); |
|
|
|
|
} catch (Exception e) { |
|
|
|
|
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
|
|
|
|
return INVALID_FORMULA; |
|
|
|
|
// alex:继续往下面走,expression为null时告知不合法公式
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (formulaText != null && formulaText.length() > 0) { |
|
|
|
|
StringReader in = new StringReader(formulaText); |
|
|
|
|
|
|
|
|
|
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 ""; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private final ActionListener calculateActionListener = new ActionListener() { |
|
|
|
|
@Override |
|
|
|
|
public void actionPerformed(ActionEvent e) { |
|
|
|
|
String formulaText = formulaTextArea.getText().trim(); |
|
|
|
|
String formulaValidMessage = getFormulaValidMessage(formulaText); |
|
|
|
|
String unSupportFormula = containsUnsupportedSimulationFormulas(formulaText); |
|
|
|
|
if (unSupportFormula != null) { |
|
|
|
|
FineJOptionPane.showMessageDialog( |
|
|
|
|
FormulaPane.this, |
|
|
|
|
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Unsupported_Formulas") + ":" + unSupportFormula, |
|
|
|
|
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Tool_Tips"), |
|
|
|
|
JOptionPane.INFORMATION_MESSAGE); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
String messageTips; |
|
|
|
|
if (formulaValidMessage.equals(INVALID_FORMULA)) { |
|
|
|
|
messageTips = INVALID_FORMULA; |
|
|
|
|
} else { |
|
|
|
|
messageTips = formulaValidMessage.equals(VALID_FORMULA) ? "" : formulaValidMessage + "\n"; |
|
|
|
|
Map<String, Object> paramsMap = setParamsIfExist(formulaText); |
|
|
|
|
Calculator calculator = Calculator.createCalculator(); |
|
|
|
|
ParameterMapNameSpace parameterMapNameSpace = ParameterMapNameSpace.create(paramsMap); |
|
|
|
|
calculator.pushNameSpace(parameterMapNameSpace); |
|
|
|
|
|
|
|
|
|
JTemplate<?, ?> currentEditingTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); |
|
|
|
|
if (currentEditingTemplate != null) { |
|
|
|
|
IOFile file = (IOFile) currentEditingTemplate.getTarget(); |
|
|
|
|
calculator.setAttribute(TableDataSource.KEY, file); |
|
|
|
|
calculator.pushNameSpace(TableDataNameSpace.getInstance()); |
|
|
|
|
calculator.pushNameSpace(SimpleCellValueNameSpace.getInstance()); |
|
|
|
|
} |
|
|
|
|
FRLexer lexer = new FRLexer(in); |
|
|
|
|
FRParser parser = new FRParser(lexer); |
|
|
|
|
|
|
|
|
|
BaseFormula baseFormula = BaseFormula.createFormulaBuilder().build(formulaText); |
|
|
|
|
Expression expression = null; |
|
|
|
|
try { |
|
|
|
|
Object value = calculator.evalValue(baseFormula); |
|
|
|
|
String objectToString = EssentialUtils.objectToString(value); |
|
|
|
|
String result = objectToString.length() > DEFUAL_FOMULA_LENGTH ? |
|
|
|
|
objectToString.substring(0, DEFUAL_FOMULA_LENGTH - ELLIPSIS.length()) + ELLIPSIS : objectToString; |
|
|
|
|
messageTips = messageTips + |
|
|
|
|
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Cal_Result") + ":" + result; |
|
|
|
|
FineLoggerFactory.getLogger().info("value:{}", value); |
|
|
|
|
} catch (UtilEvalError utilEvalError) { |
|
|
|
|
FineLoggerFactory.getLogger().error("", utilEvalError); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
FineJOptionPane.showMessageDialog( |
|
|
|
|
FormulaPane.this, |
|
|
|
|
messageTips, |
|
|
|
|
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Tool_Tips"), |
|
|
|
|
JOptionPane.INFORMATION_MESSAGE); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
private String containsUnsupportedSimulationFormulas(String formulaText) { |
|
|
|
|
try { |
|
|
|
|
Expression expression = Calculator.createCalculator().parse(formulaText); |
|
|
|
|
UnsupportedFormulaScanner scanner = new UnsupportedFormulaScanner(); |
|
|
|
|
if (!scanner.travelFormula(expression.getConditionalExpression())) { |
|
|
|
|
return scanner.getUnSupportFormula(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
UnsupportedSimulationFormulaHunter unsupportedSimulationFormulaHunter = new UnsupportedSimulationFormulaHunter(); |
|
|
|
|
expression.traversal4Tiny(unsupportedSimulationFormulaHunter); |
|
|
|
|
return unsupportedSimulationFormulaHunter.isSupported() ? null : unsupportedSimulationFormulaHunter.getUnSupportFormula(); |
|
|
|
|
} catch (Exception e) { |
|
|
|
|
FineLoggerFactory.getLogger().error("", e); |
|
|
|
|
} |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private Map<String, Object> setParamsIfExist(String formulaText) { |
|
|
|
|
Map<String, Object> parameterMap = new HashMap<>(); |
|
|
|
|
try { |
|
|
|
|
Calculator calculator = Calculator.createCalculator(); |
|
|
|
|
Expression expression = calculator.parse(formulaText); |
|
|
|
|
ParameterCellHunter parameterCellHunter = new ParameterCellHunter(); |
|
|
|
|
expression.traversal4Tiny(parameterCellHunter); |
|
|
|
|
Parameter[] parameters = parameterCellHunter.getParameterBooty(); |
|
|
|
|
|
|
|
|
|
if (parameters.length < 1 && editor4CalPane.update().size() < 1) { |
|
|
|
|
return parameterMap; |
|
|
|
|
} |
|
|
|
|
ParameterInputPane pPane = new ParameterInputPane(parameters); |
|
|
|
|
pPane.showSmallWindow(new JFrame(), new DialogActionAdapter() { |
|
|
|
|
@Override |
|
|
|
|
public void doOk() { |
|
|
|
|
parameterMap.putAll(pPane.update()); |
|
|
|
|
expression = parser.parse(); |
|
|
|
|
} catch (Exception e) { |
|
|
|
|
FRContext.getLogger().error(e.getMessage(), e); |
|
|
|
|
// alex:继续往下面走,expression为null时告知不合法公式
|
|
|
|
|
} |
|
|
|
|
}).setVisible(true); |
|
|
|
|
//过滤出数组参数,如:[1,2]
|
|
|
|
|
for (Map.Entry<String, Object> entry : parameterMap.entrySet()) { |
|
|
|
|
if (entry.getValue().toString().startsWith("[") && entry.getValue().toString().endsWith("]")) { |
|
|
|
|
Expression parse = calculator.parse(entry.getValue()); |
|
|
|
|
ArrayExpression arrayExpression = (ArrayExpression) parse.getConditionalExpression(); |
|
|
|
|
FArray<Node> fArray = new FArray<>(arrayExpression.getArrays()); |
|
|
|
|
parameterMap.put(entry.getKey(), fArray); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} catch (Exception e) { |
|
|
|
|
FineLoggerFactory.getLogger().error("", e); |
|
|
|
|
} |
|
|
|
|
return parameterMap; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private static class ParameterCellHunter extends TinyHunter { |
|
|
|
|
|
|
|
|
|
private final Set<Parameter> parameterList = new HashSet<>(); |
|
|
|
|
|
|
|
|
|
Parameter[] getParameterBooty() { |
|
|
|
|
return parameterList.toArray(new Parameter[0]); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void hunter4Tiny(Tiny tiny) { |
|
|
|
|
String statement = tiny.getStatement(); |
|
|
|
|
if (StringUtils.isNotBlank(statement) && statement.startsWith(ScriptConstants.DETAIL_TAG)) { |
|
|
|
|
parameterList.add(new Parameter(statement.substring(1))); |
|
|
|
|
} else if (tiny.getClass() == ColumnRowRange.class || |
|
|
|
|
tiny.getClass() == SheetIntervalLiteral.class || tiny.getClass() == BlockIntervalLiteral.class) { |
|
|
|
|
parameterList.add(new Parameter(tiny.toString())); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private static class UnsupportedSimulationFormulaHunter extends TinyHunter { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private boolean supported = true; |
|
|
|
|
|
|
|
|
|
private String unSupportFormula; |
|
|
|
|
|
|
|
|
|
public boolean isSupported() { |
|
|
|
|
return supported; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public String getUnSupportFormula() { |
|
|
|
|
return unSupportFormula; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void hunter4Tiny(Tiny tiny) { |
|
|
|
|
if (tiny.getClass() == ColumnRowRangeInPage.class) { |
|
|
|
|
supported = false; |
|
|
|
|
unSupportFormula = tiny.toString(); |
|
|
|
|
JOptionPane.showMessageDialog( |
|
|
|
|
FormulaPane.this, |
|
|
|
|
/* |
|
|
|
|
* alex:仅仅只需要根据expression是否为null作合法性判断 |
|
|
|
|
* 不需要eval |
|
|
|
|
* TODO 但有个问题,有些函数的参数个数是有规定的,何以判别之 |
|
|
|
|
*/ |
|
|
|
|
(expression != null ? com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaD_Valid_Formula") : com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaD_Invalid_Formula")) + ".", ProductConstants.PRODUCT_NAME, |
|
|
|
|
JOptionPane.INFORMATION_MESSAGE); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
public class VariableTreeAndDescriptionArea extends JPanel { |
|
|
|
|
|
|
|
|
|
private JTree variablesTree; |
|
|
|
|
private UITextArea descriptionTextArea; |
|
|
|
|
|
|
|
|
|
VariableTreeAndDescriptionArea() { |
|
|
|
|
public VariableTreeAndDescriptionArea() { |
|
|
|
|
this.initComponents(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -1053,31 +770,31 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
|
|
|
|
|
private void initVariablesTreeSelectionListener() { |
|
|
|
|
variablesTree.addTreeSelectionListener(new TreeSelectionListener() { |
|
|
|
|
public void valueChanged(TreeSelectionEvent e) { |
|
|
|
|
DefaultMutableTreeNode selectedTreeNode = (DefaultMutableTreeNode) variablesTree.getLastSelectedPathComponent(); |
|
|
|
|
Object selectedValue = selectedTreeNode.getUserObject(); |
|
|
|
|
Object selectedParentValue = ((DefaultMutableTreeNode) selectedTreeNode.getParent()).getUserObject(); |
|
|
|
|
|
|
|
|
|
Object selectedValue = ((DefaultMutableTreeNode) variablesTree.getLastSelectedPathComponent()).getUserObject(); |
|
|
|
|
if (selectedValue == null) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (selectedValue instanceof TextUserObject) { |
|
|
|
|
//有公式说明的条件:1.属于TextUserObject 2.parent是系统参数
|
|
|
|
|
if (ComparatorUtils.equals(((TextFolderUserObject) selectedParentValue).getText(), |
|
|
|
|
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaPane_Variables"))) { |
|
|
|
|
descriptionTextArea.setText(com.fr.design.i18n.Toolkit.i18nText(FormulaConstants.getValueByKey(((TextUserObject) selectedValue).getText()))); |
|
|
|
|
StringBuilder desBuf = new StringBuilder(); |
|
|
|
|
try { |
|
|
|
|
String path; |
|
|
|
|
Locale locale = FRContext.getLocale(); |
|
|
|
|
if (locale.equals(Locale.CHINA)) { |
|
|
|
|
path = "/com/fr/design/insert/formula/variable/cn/"; |
|
|
|
|
} else { |
|
|
|
|
descriptionTextArea.setText(StringUtils.EMPTY); |
|
|
|
|
path = "/com/fr/design/insert/formula/variable/en/"; |
|
|
|
|
} |
|
|
|
|
} else if (selectedValue instanceof TextFolderUserObject) { |
|
|
|
|
descriptionTextArea.setText(StringUtils.EMPTY); |
|
|
|
|
if (selectedValue instanceof TextUserObject) { |
|
|
|
|
desBuf = getText((TextUserObject) selectedValue, path); |
|
|
|
|
} |
|
|
|
|
} catch (IOException exp) { |
|
|
|
|
FineLoggerFactory.getLogger().error(exp.getMessage(), exp); |
|
|
|
|
} |
|
|
|
|
descriptionTextArea.setText(desBuf.toString()); |
|
|
|
|
descriptionTextArea.moveCaretPosition(0); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void initVariablesTree() { |
|
|
|
|
// vairable.
|
|
|
|
|
variablesTree = new JTree(); |
|
|
|
@ -1097,15 +814,13 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
|
|
|
|
|
|
|
|
|
|
private void initComponents() { |
|
|
|
|
this.setLayout(new BorderLayout(4, 4)); |
|
|
|
|
initVariablesTree(); |
|
|
|
|
initFunctionPane(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void initFunctionPane() { |
|
|
|
|
// Function
|
|
|
|
|
JPanel functionPane = new JPanel(new BorderLayout(4, 4)); |
|
|
|
|
this.add(functionPane, BorderLayout.WEST); |
|
|
|
|
initFunctionTypeList(functionPane); |
|
|
|
|
initFunctionNameList(functionPane); |
|
|
|
|
initVariablesTree(); |
|
|
|
|
// 选择:
|
|
|
|
|
functionTypeList.setSelectedIndex(0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -1250,42 +965,13 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public static class SimilarComparator implements Comparator<String> { |
|
|
|
|
|
|
|
|
|
private String searchKey; |
|
|
|
|
|
|
|
|
|
public SimilarComparator(String searchKey) { |
|
|
|
|
this.searchKey = searchKey.toLowerCase(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* 把以关键词开头的和不以关键词开头的分别按照字母表顺序排序 |
|
|
|
|
* |
|
|
|
|
* @param o1 待比较对象1 |
|
|
|
|
* @param o2 待比较对象2 |
|
|
|
|
* @return 比较结果,1表示 o1 > o2, -1表示 o1 < o2, 0表示 o1 = o2 |
|
|
|
|
*/ |
|
|
|
|
@Override |
|
|
|
|
public int compare(String o1, String o2) { |
|
|
|
|
int result; |
|
|
|
|
boolean o1StartWith = o1.toLowerCase().startsWith(searchKey); |
|
|
|
|
boolean o2StartWith = o2.toLowerCase().startsWith(searchKey); |
|
|
|
|
if (o1StartWith) { |
|
|
|
|
result = o2StartWith ? o1.compareTo(o2) : -1; |
|
|
|
|
} else { |
|
|
|
|
result = o2StartWith ? 1 : o1.compareTo(o2); |
|
|
|
|
} |
|
|
|
|
return result; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public static class TextFolderUserObject { |
|
|
|
|
|
|
|
|
|
private String text; |
|
|
|
|
private Icon icon; |
|
|
|
|
private String[] subNodes = new String[0]; |
|
|
|
|
|
|
|
|
|
TextFolderUserObject(String text, Icon icon, String[] subNodes) { |
|
|
|
|
public TextFolderUserObject(String text, Icon icon, String[] subNodes) { |
|
|
|
|
this.text = text; |
|
|
|
|
this.icon = icon; |
|
|
|
|
this.subNodes = subNodes; |
|
|
|
@ -1312,11 +998,11 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
|
|
|
|
|
|
|
|
|
|
public static class TextUserObject { |
|
|
|
|
|
|
|
|
|
TextUserObject(String text) { |
|
|
|
|
public TextUserObject(String text) { |
|
|
|
|
this(text, text); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TextUserObject(String text, String displayText) { |
|
|
|
|
public TextUserObject(String text, String displayText) { |
|
|
|
|
this.text = text; |
|
|
|
|
this.displayText = displayText; |
|
|
|
|
} |
|
|
|
@ -1325,7 +1011,7 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
|
|
|
|
|
return this.text; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
String getDisplayText() { |
|
|
|
|
public String getDisplayText() { |
|
|
|
|
return this.displayText; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -1350,6 +1036,6 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
|
|
|
|
|
buffer.append("|"); |
|
|
|
|
buffer.append("\n"); |
|
|
|
|
} |
|
|
|
|
FineLoggerFactory.getLogger().debug(buffer.toString()); |
|
|
|
|
FRContext.getLogger().debug(buffer.toString()); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|