571 lines
19 KiB
C++
571 lines
19 KiB
C++
#include "stdafx.h"
|
|
|
|
#include "ccl/rslang/RSGenerator.h"
|
|
#include "xtr/dialog/CstDataPage.h"
|
|
|
|
#include "resource.h"
|
|
|
|
#include "xtr/ExteorOptions.h"
|
|
#include "xtr/cclDescriptor.h"
|
|
#include "xtr/xtrDesign.h"
|
|
|
|
#include "xtr/ui/UIHelper.h"
|
|
#include "xtr/ui/HelpHandler.h"
|
|
#include "xtr/ui/KeyboardHandler.h"
|
|
|
|
#include "xtr/dialog/EditConstituenta.h"
|
|
|
|
namespace xtr::dialog {
|
|
|
|
using ccl::semantic::ParsingStatus;
|
|
using ccl::semantic::CstType;
|
|
using ccl::rslang::TokenID;
|
|
using ccl::rslang::ValueClass;
|
|
using ui::Keyboard;
|
|
|
|
#pragma warning( push )
|
|
#pragma warning( disable : 26440 26436 26454 )
|
|
|
|
BEGIN_MESSAGE_MAP(CstDataPage, CPropertyPage)
|
|
ON_WM_DESTROY()
|
|
|
|
ON_EN_SETFOCUS(IXTRC_NAME, &ThisClass::OnSetfocusName)
|
|
ON_EN_KILLFOCUS(IXTRC_EXPRESSION, &ThisClass::OnKillfocusExpression)
|
|
ON_EN_CHANGE(IXTRC_EXPRESSION, &ThisClass::OnChangeExpression)
|
|
ON_EN_CHANGE(IXTRC_INTERPRETATION, &ThisClass::OnChangeInterpretation)
|
|
ON_EN_CHANGE(IXTRC_COMMENT_KS, &ThisClass::OnChangeComment)
|
|
ON_EN_CHANGE(IXTRC_NAME, &ThisClass::OnChangeName)
|
|
ON_EN_CHANGE(IXTRC_TERM, &ThisClass::OnChangeTerm)
|
|
ON_CBN_SELCHANGE(IXTRC_NAME_CB, &ThisClass::OnSelchangeName)
|
|
|
|
ON_BN_CLICKED(IXTRC_ALLOW_EDIT, &ThisClass::OnAllowEdit)
|
|
ON_BN_CLICKED(IXTRC_PREV, &ThisClass::OnPrev)
|
|
ON_BN_CLICKED(IXTRC_NEXT, &ThisClass::OnNext)
|
|
ON_BN_CLICKED(IXTRC_INPUT_HELP, &ThisClass::OnHelpInput)
|
|
ON_BN_CLICKED(IXTRC_ANALYSE, &ThisClass::OnAnalyse)
|
|
ON_BN_CLICKED(IXTRC_CALCULATE, &ThisClass::OnCalculate)
|
|
ON_BN_CLICKED(IXTRC_SHOW_SSYNTAX, &ThisClass::OnSimpleSyntax)
|
|
|
|
ON_COMMAND_EX(IXTRC_BOOLEAN, &ThisClass::OnInsertBtn)
|
|
ON_COMMAND_EX(IXTRC_BOOL, &ThisClass::OnInsertBtn)
|
|
ON_COMMAND_EX(IXTRC_PR_S, &ThisClass::OnInsertBtn)
|
|
ON_COMMAND_EX(IXTRC_PR_L, &ThisClass::OnInsertBtn)
|
|
ON_COMMAND_EX(IXTRC_FILTER, &ThisClass::OnInsertBtn)
|
|
ON_COMMAND_EX(IXTRC_CARD, &ThisClass::OnInsertBtn)
|
|
ON_COMMAND_EX(IXTRC_DEBOOL, &ThisClass::OnInsertBtn)
|
|
ON_COMMAND_EX(IXTRC_RED, &ThisClass::OnInsertBtn)
|
|
ON_COMMAND_EX(IXTRC_CARTPROD, &ThisClass::OnInsertBtn)
|
|
ON_COMMAND_EX(IXTRC_NEGATION, &ThisClass::OnInsertBtn)
|
|
ON_COMMAND_EX(IXTRC_UNION, &ThisClass::OnInsertBtn)
|
|
ON_COMMAND_EX(IXTRC_INTERSECT, &ThisClass::OnInsertBtn)
|
|
ON_COMMAND_EX(IXTRC_OR, &ThisClass::OnInsertBtn)
|
|
ON_COMMAND_EX(IXTRC_BELONG, &ThisClass::OnInsertBtn)
|
|
ON_COMMAND_EX(IXTRC_IMPLICATION, &ThisClass::OnInsertBtn)
|
|
ON_COMMAND_EX(IXTRC_INEQ, &ThisClass::OnInsertBtn)
|
|
ON_COMMAND_EX(IXTRC_NULLSET, &ThisClass::OnInsertBtn)
|
|
ON_COMMAND_EX(IXTRC_QUANTEXIST, &ThisClass::OnInsertBtn)
|
|
ON_COMMAND_EX(IXTRC_QUANTUNIVERSAL, &ThisClass::OnInsertBtn)
|
|
ON_COMMAND_EX(IXTRC_LOGIC_EQUAL, &ThisClass::OnInsertBtn)
|
|
ON_COMMAND_EX(IXTRC_EQUAL, &ThisClass::OnInsertBtn)
|
|
ON_COMMAND_EX(IXTRC_LOGIC_AND, &ThisClass::OnInsertBtn)
|
|
ON_COMMAND_EX(IXTRC_SET_MINUS, &ThisClass::OnInsertBtn)
|
|
ON_COMMAND_EX(IXTRC_NOTELEMENT, &ThisClass::OnInsertBtn)
|
|
ON_COMMAND_EX(IXTRC_SUBSET, &ThisClass::OnInsertBtn)
|
|
ON_COMMAND_EX(IXTRC_NOTSUBSET, &ThisClass::OnInsertBtn)
|
|
ON_COMMAND_EX(IXTRC_SUBSET_OR_EQ, &ThisClass::OnInsertBtn)
|
|
ON_COMMAND_EX(IXTRC_DOUBLEPAR, &ThisClass::OnInsertBtn)
|
|
ON_COMMAND_EX(IXTRC_DOUBLESQR, &ThisClass::OnInsertBtn)
|
|
ON_COMMAND_EX(IXTRC_GREATER_OR_EQ, &ThisClass::OnInsertBtn)
|
|
ON_COMMAND_EX(IXTRC_LESSER_OR_EQ, &ThisClass::OnInsertBtn)
|
|
ON_COMMAND_EX(IXTRC_SET_SYMMINUS, &ThisClass::OnInsertBtn)
|
|
|
|
ON_COMMAND_EX(IXTRC_RS_RECURSIVE, &ThisClass::OnInsertBtn)
|
|
ON_COMMAND_EX(IXTRC_RS_DECLARATIVE, &ThisClass::OnInsertBtn)
|
|
ON_COMMAND_EX(IXTRC_RS_IMPERATIVE, &ThisClass::OnInsertBtn)
|
|
END_MESSAGE_MAP()
|
|
|
|
#pragma warning( pop )
|
|
|
|
CstDataPage::CstDataPage(EditConstituentaDlg& parent)
|
|
: CPropertyPage(IXTRD_CST_EDIT_DATA), parent(parent) {}
|
|
|
|
BOOL CstDataPage::OnInitDialog() {
|
|
CPropertyPage::OnInitDialog();
|
|
|
|
InitControls();
|
|
InitCstNameList();
|
|
UpdateData(FALSE);
|
|
return TRUE;
|
|
}
|
|
|
|
void CstDataPage::InitControls() {
|
|
static constexpr auto PROPERTI_DROPPED_WIDTH = 820U;
|
|
|
|
Keyboard::Instance().RegisterIndicator(&languageIndicator);
|
|
|
|
expressionCtrl.InitRE(Keyboard::Layout::MATH, TRUE, TRUE);
|
|
typificationCtrl.InitRE(Keyboard::Layout::MATH, TRUE, FALSE);
|
|
definitionCtrl.InitRE(Keyboard::Layout::RUS, FALSE, TRUE);
|
|
termCtrl.InitRE(Keyboard::Layout::RUS, FALSE, TRUE);
|
|
|
|
conventionCtrl.SetAutoURLDetect();
|
|
conventionCtrl.InitRE(Keyboard::Layout::RUS);
|
|
|
|
logCtrl.SetAutoURLDetect();
|
|
logCtrl.InitRE();
|
|
|
|
namePicker.SetDroppedWidth(PROPERTI_DROPPED_WIDTH);
|
|
|
|
cstNameCtrl.SetFont(&XTROptions::App().fontMath);
|
|
logCtrl.SetFont(&XTROptions::App().fontTooltip);
|
|
definitionCtrl.SetFont(&XTROptions::App().fontText);
|
|
termCtrl.SetFont(&XTROptions::App().fontText);
|
|
conventionCtrl.SetFont(&XTROptions::App().fontMathComment);
|
|
languageIndicator.SetFont(&XTROptions::App().fontTooltip);
|
|
namePicker.SetFont(&XTROptions::App().fontText);
|
|
|
|
if (!parent.editor->IsModel()) {
|
|
GetDlgItem(IXTRC_CALCULATE)->ShowWindow(FALSE);
|
|
}
|
|
}
|
|
|
|
void CstDataPage::DoDataExchange(CDataExchange* pDX) {
|
|
CPropertyPage::DoDataExchange(pDX);
|
|
|
|
::DDX_Control(pDX, IXTRC_NAME, cstNameCtrl);
|
|
::DDX_Control(pDX, IXTRC_NAME_CB, namePicker);
|
|
::DDX_Control(pDX, IXTRC_ALLOW_EDIT, allowEditCtrl);
|
|
::DDX_Control(pDX, IXTRC_CALCULATE, evaluateBtn);
|
|
::DDX_Control(pDX, IXTRC_EXPRESSION, expressionCtrl);
|
|
::DDX_Control(pDX, IXTRC_INTERPRETATION, definitionCtrl);
|
|
::DDX_Control(pDX, IXTRC_TERM, termCtrl);
|
|
::DDX_Control(pDX, IXTRC_COMMENT_KS, conventionCtrl);
|
|
::DDX_Control(pDX, IXTRC_TYPIFICATION, typificationCtrl);
|
|
::DDX_Control(pDX, IXTRC_SYNTAX, logCtrl);
|
|
::DDX_Control(pDX, IXTRC_LANGUAGE, languageIndicator);
|
|
|
|
const auto& core = parent.editor->Core();
|
|
const auto& cst = core.GetRS(parent.activeUID);
|
|
if (!pDX->m_bSaveAndValidate) {
|
|
const auto isInherited = parent.editor->IsModel() ? FALSE : parent.editor->Schema().Mods().IsTracking(parent.activeUID);
|
|
|
|
LoadDataFrom(parent.activeUID);
|
|
|
|
allowEditCtrl.ShowWindow(isInherited);
|
|
|
|
expressionCtrl.Init(core, parent.activeUID);
|
|
expressionCtrl.SetReadOnly(isInherited);
|
|
|
|
termCtrl.Initialize(term, *parent.editor, !XTROptions::Text().editReference, FALSE);
|
|
termCtrl.SetReadOnly(!allowEdit);
|
|
definitionCtrl.Initialize(definition, *parent.editor, !XTROptions::Text().editReference);
|
|
definitionCtrl.SetReadOnly(!allowEdit);
|
|
|
|
if (ccl::semantic::IsBaseNotion(cst.type)) {
|
|
GetDlgItem(IXTRC_COMMENT_STATIC)->SetWindowTextW(mfc::LoadSID(IXTRS_CONVENTION));
|
|
} else {
|
|
GetDlgItem(IXTRC_COMMENT_STATIC)->SetWindowTextW(mfc::LoadSID(IXTRS_COMMENT));
|
|
}
|
|
conventionCtrl.SetReadOnly(!allowEdit);
|
|
|
|
InitCstNameList();
|
|
}
|
|
|
|
auto sellectedName = mfc::ToMFC(cst.alias);
|
|
::DDX_Check(pDX, IXTRC_ALLOW_EDIT, allowEdit);
|
|
::DDX_Text(pDX, IXTRC_EXPRESSION, expression);
|
|
::DDX_Text(pDX, IXTRC_TYPIFICATION, typification);
|
|
::DDX_Text(pDX, IXTRC_COMMENT_KS, convention);
|
|
::DDX_Text(pDX, IXTRC_NAME, cstName);
|
|
::DDX_CBString(pDX, IXTRC_NAME_CB, sellectedName);
|
|
|
|
if (!pDX->m_bSaveAndValidate) {
|
|
UpdateFormat();
|
|
} else {
|
|
SaveDataFor(parent.activeUID);
|
|
InitCstNameList();
|
|
}
|
|
UpdateStatusBar();
|
|
ClearSyntaxWindow();
|
|
}
|
|
|
|
void CstDataPage::LoadDataFrom(const EntityUID target) {
|
|
allowEdit = TRUE;
|
|
if (!parent.editor->IsModel()) {
|
|
if (parent.editor->Schema().Mods().IsTracking(target)) {
|
|
allowEdit = parent.editor->Schema().Mods()(target)->allowEdit;
|
|
}
|
|
}
|
|
const auto& rsCst = parent.editor->GetRS(target);
|
|
const auto& textCst = parent.editor->GetText(target);
|
|
|
|
cstName = mfc::ToMFC(rsCst.alias);
|
|
expression = mfc::ToMFC(rsCst.definition);
|
|
convention = mfc::ToMFC(rsCst.convention);
|
|
|
|
typification = info::Label(parent.editor->GetParse(target).TypePtr());
|
|
parseStatus = parent.editor->GetParse(target).status;
|
|
valueStatus = parent.editor->GetParse(target).valueClass;
|
|
|
|
definition = mfc::ToMFC(textCst.definition.Raw());
|
|
term = mfc::ToMFC(textCst.term.Text().Raw());
|
|
}
|
|
|
|
void CstDataPage::SaveDataFor(const EntityUID uid) {
|
|
auto expr = mfc::ToSTL(expressionCtrl.Text());
|
|
// Note: dont use ::DDX_Text value because of line breakes are doubled ('\r\n')
|
|
auto stlComment = mfc::ToSTL(conventionCtrl.Text());
|
|
auto definitionRef = ui::TrimText(definitionCtrl.GetRefStr());
|
|
auto termRef = ui::TrimText(termCtrl.GetRefStr());
|
|
|
|
if (!parent.editor->IsModel() && parent.editor->Schema().Mods().IsTracking(uid)) {
|
|
parent.editor->EditSchema().Mods()(uid)->allowEdit = allowEdit;
|
|
}
|
|
parent.editor->SetAliasFor(uid, mfc::ToSTL(cstName));
|
|
parent.editor->SetExpressionFor(uid, expr);
|
|
parent.editor->SetConventionFor(uid, stlComment);
|
|
parent.editor->SetDefinitionFor(uid, mfc::ToSTL(definitionRef));
|
|
parent.editor->SetTermFor(uid, mfc::ToSTL(termRef));
|
|
}
|
|
|
|
BOOL CstDataPage::PreTranslateMessage(MSG* pMsg) {
|
|
if (pMsg->message == WM_KEYDOWN) {
|
|
if (pMsg->wParam == VK_ESCAPE) {
|
|
OnCancel();
|
|
return TRUE;
|
|
} else if (pMsg->wParam == VK_F1) {
|
|
ui::HelpHandler::RunHelp(parent.editor->IsModel() ? ui::HelpID::editData : ui::HelpID::editCst);
|
|
return TRUE;
|
|
}
|
|
}
|
|
return CPropertyPage::PreTranslateMessage(pMsg);
|
|
}
|
|
|
|
void CstDataPage::OnSetfocusName() { // NOLINT(readability-convert-member-functions-to-static)
|
|
Keyboard::Instance().SetLayout(Keyboard::Layout::ENG);
|
|
}
|
|
|
|
void CstDataPage::OnKillfocusExpression() {
|
|
if (GetFocus() == nullptr ||
|
|
(GetFocus() != GetDlgItem(IXTRC_ANALYSE) &&
|
|
!GetFocus()->IsKindOf(RUNTIME_CLASS(CButton)))) {
|
|
RunAutocheck();
|
|
}
|
|
}
|
|
|
|
void CstDataPage::OnDestroy() {
|
|
Keyboard::Instance().UnregisterIndicator(&languageIndicator);
|
|
CPropertyPage::OnDestroy();
|
|
}
|
|
|
|
void CstDataPage::OnCancel() {
|
|
CPropertyPage::OnCancel();
|
|
EndDialog(IDCANCEL);
|
|
}
|
|
|
|
BOOL CstDataPage::OnApply() {
|
|
if (!CPropertyPage::OnApply()) {
|
|
return FALSE;
|
|
} else {
|
|
if (parent.GetActivePage() == this) {
|
|
RunAutocheck();
|
|
UpdateData(FALSE);
|
|
}
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
void CstDataPage::OnOK() {
|
|
if (parent.GetActivePage() == this) {
|
|
UpdateData(TRUE);
|
|
SetModified(FALSE);
|
|
}
|
|
CPropertyPage::OnOK();
|
|
}
|
|
|
|
void CstDataPage::OnSelchangeName() {
|
|
const auto index = namePicker.GetCurSel();
|
|
assert(index != mfc::noItems);
|
|
|
|
OnApply();
|
|
|
|
CString name{};
|
|
namePicker.GetLBText(index, name);
|
|
name = mfc::FirstWordOf(name);
|
|
|
|
parent.activeUID = parent.editor->Core().FindAlias(mfc::ToSTL(name)).value();
|
|
UpdateData(FALSE);
|
|
}
|
|
|
|
void CstDataPage::OnChangeExpression() {
|
|
if (expressionCtrl.Text() != expression) {
|
|
OnChange();
|
|
UpdateStatus(ParsingStatus::UNKNOWN, ValueClass::invalid);
|
|
}
|
|
}
|
|
|
|
void CstDataPage::OnAllowEdit() {
|
|
UpdateData();
|
|
UpdateData(FALSE);
|
|
}
|
|
|
|
void CstDataPage::OnChange() {
|
|
SetModified();
|
|
}
|
|
|
|
void CstDataPage::OnChangeInterpretation() {
|
|
if (GetFocus() != nullptr && *GetFocus() == definitionCtrl) {
|
|
OnChange();
|
|
}
|
|
}
|
|
|
|
void CstDataPage::OnChangeTerm() {
|
|
if (GetFocus() != nullptr && *GetFocus() == termCtrl) {
|
|
OnChange();
|
|
}
|
|
}
|
|
|
|
void CstDataPage::OnChangeComment() {
|
|
if (GetFocus() != nullptr && *GetFocus() == conventionCtrl) {
|
|
OnChange();
|
|
}
|
|
}
|
|
|
|
void CstDataPage::OnChangeName() {
|
|
if (GetFocus() != nullptr && *GetFocus() == cstNameCtrl) {
|
|
OnChange();
|
|
}
|
|
}
|
|
|
|
void CstDataPage::OnPrev() {
|
|
UpdateData(TRUE);
|
|
parent.StepPrev();
|
|
UpdateData(FALSE);
|
|
}
|
|
|
|
void CstDataPage::OnNext() {
|
|
UpdateData(TRUE);
|
|
parent.StepNext();
|
|
UpdateData(FALSE);
|
|
}
|
|
|
|
void CstDataPage::OnHelpInput() { // NOLINT(readability-convert-member-functions-to-static)
|
|
ui::HelpHandler::RunHelp(ui::HelpID::rslanguage);
|
|
}
|
|
|
|
BOOL CstDataPage::OnInsertBtn(uint32_t command) {
|
|
switch(command) {
|
|
case IXTRC_EQUAL: expressionCtrl.InputToken(TokenID::EQUAL); break;
|
|
case IXTRC_INEQ: expressionCtrl.InputToken(TokenID::NOTEQUAL); break;
|
|
case IXTRC_LESSER_OR_EQ: expressionCtrl.InputToken(TokenID::LESSER_OR_EQ); break;
|
|
case IXTRC_GREATER_OR_EQ: expressionCtrl.InputToken(TokenID::GREATER_OR_EQ); break;
|
|
|
|
case IXTRC_QUANTUNIVERSAL: expressionCtrl.InputToken(TokenID::FORALL); break;
|
|
case IXTRC_QUANTEXIST: expressionCtrl.InputToken(TokenID::EXISTS); break;
|
|
case IXTRC_LOGIC_AND: expressionCtrl.InputToken(TokenID::AND); break;
|
|
case IXTRC_OR: expressionCtrl.InputToken(TokenID::OR); break;
|
|
case IXTRC_NEGATION: expressionCtrl.InputToken(TokenID::NOT); break;
|
|
case IXTRC_IMPLICATION: expressionCtrl.InputToken(TokenID::IMPLICATION);break;
|
|
case IXTRC_LOGIC_EQUAL: expressionCtrl.InputToken(TokenID::EQUIVALENT); break;
|
|
|
|
case IXTRC_NULLSET: expressionCtrl.InputToken(TokenID::LIT_EMPTYSET); break;
|
|
case IXTRC_UNION: expressionCtrl.InputToken(TokenID::UNION); break;
|
|
case IXTRC_SET_MINUS: expressionCtrl.InputToken(TokenID::SET_MINUS); break;
|
|
case IXTRC_SET_SYMMINUS: expressionCtrl.InputToken(TokenID::SYMMINUS); break;
|
|
case IXTRC_INTERSECT: expressionCtrl.InputToken(TokenID::INTERSECTION); break;
|
|
case IXTRC_BELONG: expressionCtrl.InputToken(TokenID::IN); break;
|
|
case IXTRC_NOTELEMENT: expressionCtrl.InputToken(TokenID::NOTIN); break;
|
|
case IXTRC_SUBSET: expressionCtrl.InputToken(TokenID::SUBSET); break;
|
|
case IXTRC_NOTSUBSET: expressionCtrl.InputToken(TokenID::NOTSUBSET); break;
|
|
case IXTRC_SUBSET_OR_EQ: expressionCtrl.InputToken(TokenID::SUBSET_OR_EQ); break;
|
|
|
|
case IXTRC_BOOLEAN: expressionCtrl.InputToken(TokenID::BOOLEAN); break;
|
|
case IXTRC_PR_S: expressionCtrl.InputToken(TokenID::SMALLPR); break;
|
|
case IXTRC_PR_L: expressionCtrl.InputToken(TokenID::BIGPR); break;
|
|
case IXTRC_FILTER: expressionCtrl.InputToken(TokenID::FILTER); break;
|
|
case IXTRC_CARD: expressionCtrl.InputToken(TokenID::CARD); break;
|
|
case IXTRC_CARTPROD: expressionCtrl.InputToken(TokenID::DECART); break;
|
|
|
|
case IXTRC_BOOL: expressionCtrl.InputToken(TokenID::BOOL); break;
|
|
case IXTRC_DEBOOL: expressionCtrl.InputToken(TokenID::DEBOOL); break;
|
|
case IXTRC_RED: expressionCtrl.InputToken(TokenID::REDUCE); break;
|
|
case IXTRC_RS_DECLARATIVE: expressionCtrl.InputToken(TokenID::DECLARATIVE); break;
|
|
case IXTRC_RS_RECURSIVE: expressionCtrl.InputToken(TokenID::RECURSIVE); break;
|
|
case IXTRC_RS_IMPERATIVE: expressionCtrl.InputToken(TokenID::IMPERATIVE); break;
|
|
|
|
case IXTRC_DOUBLEPAR: expressionCtrl.InputParenthesis(); break;
|
|
case IXTRC_DOUBLESQR: expressionCtrl.InputBrackets(); break;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
void CstDataPage::OnAnalyse() {
|
|
const auto& cst = parent.editor->GetRS(parent.activeUID);
|
|
const auto definitionText = mfc::ToSTL(expressionCtrl.Text());
|
|
|
|
auto analyser = parent.editor->Core().RSLang().MakeAuditor();
|
|
const ccl::rslang::ExpressionType* type{ nullptr };
|
|
|
|
const auto typeOK = analyser->CheckConstituenta(cst.alias, definitionText, cst.type);
|
|
if (typeOK) {
|
|
type = &analyser->GetType();
|
|
}
|
|
|
|
if (!typeOK) {
|
|
UpdateStatus(ParsingStatus::INCORRECT, ValueClass::invalid);
|
|
} else {
|
|
if (!analyser->CheckValue()) {
|
|
UpdateStatus(ParsingStatus::VERIFIED, ValueClass::invalid);
|
|
} else {
|
|
UpdateStatus(ParsingStatus::VERIFIED, analyser->GetValueClass());
|
|
}
|
|
}
|
|
|
|
if (!empty(analyser->Errors().All())) {
|
|
auto errorPosition = std::max(static_cast<long>(analyser->Errors().FirstErrorPos() - analyser->prefixLen), 0L);
|
|
auto* re = reinterpret_cast<ui::TextEdit*>(GetDlgItem(IXTRC_EXPRESSION));
|
|
re->SetFocus();
|
|
re->SetSel(errorPosition, errorPosition);
|
|
}
|
|
|
|
typificationCtrl.SetWindowTextW(info::Label(type));
|
|
auto log = info::DescriptionOf(*analyser, XTROptions::ParseRSL().showAST);
|
|
logCtrl.SetWindowTextW(log);
|
|
}
|
|
|
|
void CstDataPage::OnCalculate() {
|
|
if (ccl::semantic::IsBaseNotion(parent.editor->GetRS(parent.activeUID).type)) {
|
|
return;
|
|
}
|
|
if (parseStatus != ParsingStatus::VERIFIED) {
|
|
OnAnalyse();
|
|
return;
|
|
}
|
|
if (!OnApply()) {
|
|
return;
|
|
}
|
|
BeginWaitCursor();
|
|
|
|
const auto& cst = parent.editor->GetRS(parent.activeUID);
|
|
const auto expr = mfc::ToSTL(expressionCtrl.Text());
|
|
const auto fullExpr = ccl::rslang::Generator::GlobalDefinition(
|
|
cst.alias,
|
|
expr,
|
|
cst.type == CstType::structured
|
|
);
|
|
const auto basePos = static_cast<StrPos>(ssize(fullExpr) - ssize(expr));
|
|
|
|
ccl::rslang::Interpreter calculator{
|
|
parent.editor->Core().RSLang(),
|
|
parent.editor->Core().RSLang().ASTContext(),
|
|
parent.editor->Model().Calculations().Context()
|
|
};
|
|
const auto calcResult = calculator.Evaluate(fullExpr, ccl::rslang::Syntax::MATH);
|
|
if (!calcResult.has_value()) {
|
|
auto errorPosition = std::max(static_cast<long>(calculator.Errors().FirstErrorPos() - basePos), 0L);
|
|
auto* re = reinterpret_cast<ui::TextEdit*>(GetDlgItem(IXTRC_EXPRESSION));
|
|
re->SetFocus();
|
|
re->SetSel(errorPosition, errorPosition);
|
|
}
|
|
|
|
parent.editor->EditModel().Calculations().Calculate(parent.activeUID);
|
|
|
|
EndWaitCursor();
|
|
|
|
UpdateData(FALSE);
|
|
logCtrl.SetWindowTextW(info::DescriptionOf(calculator, calcResult, XTROptions::ParseRSL().showAST));
|
|
}
|
|
|
|
void CstDataPage::OnSimpleSyntax() {
|
|
const auto definitionText = mfc::ToSTL(expressionCtrl.Text());
|
|
const auto asciiExpr = ccl::rslang::ConvertTo(definitionText, ccl::rslang::Syntax::ASCII);
|
|
logCtrl.SetWindowTextW(mfc::ToMFC(asciiExpr));
|
|
}
|
|
|
|
void CstDataPage::SetModified(BOOL bChanged) {
|
|
isModified = bChanged;
|
|
CPropertyPage::SetModified(bChanged);
|
|
}
|
|
|
|
BOOL CstDataPage::IsModified() const noexcept {
|
|
return isModified;
|
|
}
|
|
|
|
void CstDataPage::UpdateStatus(const ParsingStatus status, const ValueClass vclass) {
|
|
parseStatus = status;
|
|
valueStatus = vclass;
|
|
UpdateStatusBar();
|
|
}
|
|
|
|
void CstDataPage::UpdateStatusBar() {
|
|
auto color = design::clrBlack;
|
|
const auto isCalculable = ccl::semantic::IsCalculable(parent.editor->GetRS(parent.activeUID).type);
|
|
evaluateBtn.EnableWindow(isCalculable && parseStatus == ParsingStatus::VERIFIED);
|
|
if (parseStatus != ParsingStatus::VERIFIED) {
|
|
color = design::Color(parseStatus);
|
|
} else if (!isCalculable || !parent.editor->IsModel()) {
|
|
color = design::Color(valueStatus);
|
|
} else if (isModified) {
|
|
color = design::clrYellow;
|
|
} else {
|
|
color = design::Color(parent.editor->Model().Calculations()(parent.activeUID));
|
|
}
|
|
|
|
auto* statusRE = reinterpret_cast<CRichEditCtrl*>(GetDlgItem(IXTRC_EXP_STATUS));
|
|
statusRE->SetBackgroundColor(FALSE, color);
|
|
}
|
|
|
|
void CstDataPage::ClearSyntaxWindow() {
|
|
logCtrl.SetWindowTextW({});
|
|
}
|
|
|
|
void CstDataPage::RunAutocheck() {
|
|
if (parseStatus != ParsingStatus::VERIFIED && XTROptions::ParseRSL().autoCheck) {
|
|
ExpressAnalyse();
|
|
}
|
|
}
|
|
|
|
void CstDataPage::UpdateFormat() {
|
|
expressionCtrl.UpdateFormat();
|
|
typificationCtrl.UpdateFormat();
|
|
definitionCtrl.UpdateFormat();
|
|
termCtrl.UpdateFormat();
|
|
}
|
|
|
|
void CstDataPage::InitCstNameList() {
|
|
namePicker.SetRedraw(FALSE);
|
|
|
|
const auto sel = namePicker.GetCurSel();
|
|
namePicker.ResetContent();
|
|
|
|
for (const auto uid : parent.editor->List()) {
|
|
const auto& cst = parent.editor->GetText(uid);
|
|
auto str = mfc::ToMFC(cst.alias);
|
|
str += LR"( - )";
|
|
if (!std::empty(cst.term.Nominal())) {
|
|
str += mfc::ToMFC(cst.term.Nominal());
|
|
} else {
|
|
str += mfc::ToMFC(cst.definition.Str());
|
|
}
|
|
str.Replace(L"\n", L" ");
|
|
namePicker.AddString(str);
|
|
}
|
|
namePicker.SetCurSel(sel);
|
|
namePicker.SetRedraw(TRUE);
|
|
}
|
|
|
|
void CstDataPage::ExpressAnalyse() {
|
|
const auto& cst = parent.editor->GetRS(parent.activeUID);
|
|
const auto definitionText = mfc::ToSTL(expressionCtrl.Text());
|
|
auto analyser = parent.editor->Core().RSLang().MakeAuditor();
|
|
if (!analyser->CheckConstituenta(cst.alias, definitionText, cst.type)) {
|
|
UpdateStatus(ParsingStatus::INCORRECT, ValueClass::invalid);
|
|
} else if (!analyser->CheckValue()) {
|
|
UpdateStatus(ParsingStatus::VERIFIED, ValueClass::invalid);
|
|
} else {
|
|
UpdateStatus(ParsingStatus::VERIFIED, analyser->GetValueClass());
|
|
}
|
|
logCtrl.SetWindowTextW(CString{});
|
|
}
|
|
|
|
} // namespace xtr::dialog
|