Power System Platform  2026w10a-beta
Loading...
Searching...
No Matches
MathExpressionForm.cpp
1/*
2 * Copyright (C) 2017 Thales Lima Oliveira <thales@ufu.br>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17
18#include "../elements/controlElement/MathExpression.h"
19#include "MathExpressionForm.h"
20
21#define ERROR_INDICATOR 10
22
23MathExpressionForm::MathExpressionForm(wxWindow* parent, MathExpression* mathExpr) : MathExpressionFormBase(parent)
24{
25 m_parent = parent;
26 m_mathExpr = mathExpr;
27
28 // Variables string.
29 wxString variables = "";
30 for(unsigned int i = 0; i < m_mathExpr->GetVariables().size(); ++i) {
31 variables += m_mathExpr->GetVariables()[i] + " ";
32 }
33 variables.RemoveLast();
34
35 // Variables text ctrl.
36 wxFont variablesFont = m_textCtrlVariables->GetFont();
37 variablesFont.SetWeight(wxFONTWEIGHT_BOLD);
38 m_textCtrlVariables->SetFont(variablesFont);
39 m_textCtrlVariables->SetForegroundColour(wxColour(160, 0, 0));
40 m_textCtrlVariables->SetValue(variables);
41
42 m_stcMathExpr->SetText(m_mathExpr->GetMathExpression());
43
44 m_staticTextCheckStatus->SetLabel(_("No checks performed."));
45 SetSintaxHighlights();
46 m_stcMathExpr->SetTabWidth(3);
47
48 // Error indicator
49 m_stcMathExpr->IndicatorSetUnder(ERROR_INDICATOR, true);
50 m_stcMathExpr->IndicatorSetStyle(ERROR_INDICATOR, wxSTC_INDIC_ROUNDBOX);
51 m_stcMathExpr->IndicatorSetAlpha(ERROR_INDICATOR, 200);
52 m_stcMathExpr->IndicatorSetUnder(ERROR_INDICATOR, true);
53 m_stcMathExpr->IndicatorSetForeground(ERROR_INDICATOR, wxColor(255, 85, 0));
54 m_stcMathExpr->SetIndicatorCurrent(ERROR_INDICATOR);
55
56 // Parser error messages to translation.
57 m_translatedErrorMsg.clear();
58 m_translatedErrorMsg.push_back(_("Syntax error"));
59 m_translatedErrorMsg.push_back(_("Mismatched parenthesis"));
60 m_translatedErrorMsg.push_back(_("Missing ')'"));
61 m_translatedErrorMsg.push_back(_("Empty parentheses"));
62 m_translatedErrorMsg.push_back(_("Syntax error: Operator expected"));
63 m_translatedErrorMsg.push_back(_("Not enough memory"));
64 m_translatedErrorMsg.push_back(_("An unexpected error occurred"));
65 m_translatedErrorMsg.push_back(_("Syntax error in input variables"));
66 m_translatedErrorMsg.push_back(_("Illegal number of parameters to function"));
67 m_translatedErrorMsg.push_back(_("Syntax error: Premature end of string"));
68 m_translatedErrorMsg.push_back(_("Syntax error: Expecting ( after function"));
69 m_translatedErrorMsg.push_back(_("Syntax error: Unknown identifier"));
70 m_translatedErrorMsg.push_back(_("No function has been parsed yet"));
71}
72
73MathExpressionForm::~MathExpressionForm() {}
74
75void MathExpressionForm::OnCheckButtonClick(wxCommandEvent& event) { CheckMathExpression(); }
76
77void MathExpressionForm::OnOKButtonClick(wxCommandEvent& event)
78{
79 if(ValidateData()) EndModal(wxID_OK);
80}
81
82bool MathExpressionForm::ValidateData()
83{
84 if(!CheckMathExpression()) {
85 wxMessageDialog msg(this, _("There is an error on math expression."), _("Error"), wxOK | wxCENTRE | wxICON_ERROR);
86 msg.ShowModal();
87 return false;
88 }
89 wxString rawVariables = m_textCtrlVariables->GetValue();
90 wxString var = "";
91 std::vector<wxString> variables;
92 for(unsigned int i = 0; i < rawVariables.length(); ++i) {
93 if(rawVariables[i] == ' ') {
94 variables.push_back(var);
95 var = "";
96 } else if((i + 1) == static_cast<unsigned int>(rawVariables.length())) {
97 var += rawVariables[i];
98 variables.push_back(var);
99 } else {
100 var += rawVariables[i];
101 }
102 }
103
104 int diff = static_cast<int>(variables.size()) - static_cast<int>(m_mathExpr->GetVariables().size());
105
106 if(diff < 0) {
107 diff = std::abs(diff);
108 for(int i = 0; i < diff; ++i) { m_mathExpr->RemoveInNode(); }
109 } else if(diff > 0) {
110 for(int i = 0; i < diff; ++i) { m_mathExpr->AddInNode(); }
111 }
112 m_mathExpr->SetVariables(variables);
113 m_mathExpr->SetMathExpression(m_stcMathExpr->GetValue());
114 m_mathExpr->UpdatePoints();
115 return true;
116}
117
118void MathExpressionForm::SetSintaxHighlights()
119{
120 wxString variables = m_textCtrlVariables->GetValue();
121
122 m_stcMathExpr->StyleClearAll();
123 m_stcMathExpr->SetLexer(wxSTC_LEX_DMAP);
124 m_stcMathExpr->StyleSetForeground(wxSTC_DMAP_OPERATOR, wxColour(180, 0, 255));
125 m_stcMathExpr->StyleSetForeground(wxSTC_DMAP_WORD, wxColour(10, 0, 255));
126 m_stcMathExpr->StyleSetForeground(wxSTC_DMAP_WORD2, wxColour(160, 0, 0));
127 // m_stcMathExpr->StyleSetForeground(wxSTC_DMAP_WORD3, wxColour(0, 150, 0));
128 m_stcMathExpr->StyleSetForeground(wxSTC_DMAP_NUMBER, wxColour(0, 150, 0));
129
130 m_stcMathExpr->StyleSetBold(wxSTC_DMAP_WORD, true);
131 m_stcMathExpr->StyleSetBold(wxSTC_DMAP_WORD2, true);
132 m_stcMathExpr->StyleSetBold(wxSTC_DMAP_WORD3, true);
133
134 m_stcMathExpr->SetKeyWords(
135 0, wxT("abs acos acosh arg asin asinh atan atan2 atanh cbrt conj ceil cos cosh cot csc eval exp exp2 floor "
136 "hypot if imag int log log2 log10 max min polar pow real sec sin sinh sqrt tan tanh trunc"));
137 m_stcMathExpr->SetKeyWords(1, wxT("time step switch ") + variables);
138 m_stcMathExpr->SetKeyWords(2, wxT("true false open closed pi e"));
139}
140
141void MathExpressionForm::OnTextUpdate(wxCommandEvent& event) { SetSintaxHighlights(); }
142
143std::string MathExpressionForm::GetVariablesToParse()
144{
145 wxString variables = wxT("time,step,switch,") + m_textCtrlVariables->GetValue();
146 for(unsigned int i = 0; i < variables.length(); ++i) {
147 if(variables[i] == ' ') variables[i] = ',';
148 }
149 return static_cast<std::string>(variables);
150}
151
152void MathExpressionForm::OnLeftClickDown(wxMouseEvent& event)
153{
154 m_stcMathExpr->IndicatorClearRange(0, m_stcMathExpr->GetValue().length());
155 event.Skip();
156}
157
158bool MathExpressionForm::CheckMathExpression()
159{
160 bool success = true;
161 m_stcMathExpr->IndicatorClearRange(0, m_stcMathExpr->GetValue().length());
162 int currentLang = wxLocale::GetSystemLanguage();
163 wxLocale newLocale(wxLANGUAGE_ENGLISH_US);
164 MathExprParser parser = m_mathExpr->GetParser();
165 int parserRes = parser.Parse(static_cast<std::string>(m_stcMathExpr->GetValue()), GetVariablesToParse());
166 if(parserRes != -1) {
167 m_staticTextCheckStatus->SetLabel(m_translatedErrorMsg[parser.GetParseErrorType()]);
168 m_staticTextCheckStatus->SetForegroundColour(wxColor(255, 0, 0));
169 m_stcMathExpr->IndicatorFillRange(parserRes, 1);
170 success = false;
171 } else {
172 m_staticTextCheckStatus->SetLabel(_("The math expression is correct."));
173 m_staticTextCheckStatus->SetForegroundColour(wxColor(0, 128, 0));
174 }
175 wxLocale oldLocale(currentLang);
176 Layout();
177 return success;
178}
A generic math expression block that can perform math and conditional operations with the inputs.