Improve error handling by displaying an error message (#1075)
* wire up error messages * more errors * fix crash on render error * Always show copy and cut * PR comments * Fix spelling
This commit is contained in:
parent
7b51b45906
commit
fc19ddcbcb
@ -11,6 +11,7 @@ using namespace Graphing;
|
||||
using namespace Platform;
|
||||
using namespace Platform::Collections;
|
||||
using namespace std;
|
||||
using namespace Windows::ApplicationModel::Resources;
|
||||
using namespace Windows::UI;
|
||||
using namespace Windows::UI::Xaml;
|
||||
using namespace Windows::Foundation::Collections;
|
||||
@ -36,7 +37,7 @@ namespace CalculatorApp::ViewModel
|
||||
: m_AnalysisErrorVisible{ false }
|
||||
, m_FunctionLabelIndex{ functionLabelIndex }
|
||||
, m_KeyGraphFeaturesItems{ ref new Vector<KeyGraphFeaturesItem ^>() }
|
||||
, m_resourceLoader{ Windows::ApplicationModel::Resources::ResourceLoader::GetForCurrentView() }
|
||||
, m_resourceLoader{ ::ResourceLoader::GetForCurrentView() }
|
||||
{
|
||||
if (equation == nullptr)
|
||||
{
|
||||
@ -72,11 +73,14 @@ namespace CalculatorApp::ViewModel
|
||||
AddKeyGraphFeature(m_resourceLoader->GetString(L"YIntercept"), graphEquation->YIntercept, m_resourceLoader->GetString(L"KGFYInterceptNone"));
|
||||
AddKeyGraphFeature(m_resourceLoader->GetString(L"Minima"), graphEquation->Minima, m_resourceLoader->GetString(L"KGFMinimaNone"));
|
||||
AddKeyGraphFeature(m_resourceLoader->GetString(L"Maxima"), graphEquation->Maxima, m_resourceLoader->GetString(L"KGFMaximaNone"));
|
||||
AddKeyGraphFeature(m_resourceLoader->GetString(L"InflectionPoints"), graphEquation->InflectionPoints, m_resourceLoader->GetString(L"KGFInflectionPointsNone"));
|
||||
AddKeyGraphFeature(
|
||||
m_resourceLoader->GetString(L"InflectionPoints"), graphEquation->InflectionPoints, m_resourceLoader->GetString(L"KGFInflectionPointsNone"));
|
||||
AddKeyGraphFeature(
|
||||
m_resourceLoader->GetString(L"VerticalAsymptotes"), graphEquation->VerticalAsymptotes, m_resourceLoader->GetString(L"KGFVerticalAsymptotesNone"));
|
||||
AddKeyGraphFeature(
|
||||
m_resourceLoader->GetString(L"HorizontalAsymptotes"), graphEquation->HorizontalAsymptotes, m_resourceLoader->GetString(L"KGFHorizontalAsymptotesNone"));
|
||||
m_resourceLoader->GetString(L"HorizontalAsymptotes"),
|
||||
graphEquation->HorizontalAsymptotes,
|
||||
m_resourceLoader->GetString(L"KGFHorizontalAsymptotesNone"));
|
||||
AddKeyGraphFeature(
|
||||
m_resourceLoader->GetString(L"ObliqueAsymptotes"), graphEquation->ObliqueAsymptotes, m_resourceLoader->GetString(L"KGFObliqueAsymptotesNone"));
|
||||
AddParityKeyGraphFeature(graphEquation);
|
||||
@ -299,4 +303,154 @@ namespace CalculatorApp::ViewModel
|
||||
|
||||
KeyGraphFeaturesItems->Append(tooComplexItem);
|
||||
}
|
||||
|
||||
String ^ EquationViewModel::EquationErrorText(ErrorType errorType, int errorCode)
|
||||
{
|
||||
auto resLoader = ResourceLoader::GetForCurrentView();
|
||||
if (errorType == ::ErrorType::Evaluation)
|
||||
{
|
||||
switch (static_cast<EvaluationErrorCode>(errorCode))
|
||||
{
|
||||
case (EvaluationErrorCode::Overflow):
|
||||
return resLoader->GetString(L"Overflow");
|
||||
break;
|
||||
case (EvaluationErrorCode::RequireRadiansMode):
|
||||
return resLoader->GetString(L"RequireRadiansMode");
|
||||
break;
|
||||
case (EvaluationErrorCode::TooComplexToSolve):
|
||||
return resLoader->GetString(L"TooComplexToSolve");
|
||||
break;
|
||||
case (EvaluationErrorCode::RequireDegreesMode):
|
||||
return resLoader->GetString(L"RequireDegreesMode");
|
||||
break;
|
||||
case (EvaluationErrorCode::FactorialInvalidArgument):
|
||||
case (EvaluationErrorCode::Factorial2InvalidArgument):
|
||||
return resLoader->GetString(L"FactorialInvalidArgument");
|
||||
break;
|
||||
case (EvaluationErrorCode::FactorialCannotPerformOnLargeNumber):
|
||||
return resLoader->GetString(L"FactorialCannotPerformOnLargeNumber");
|
||||
break;
|
||||
case (EvaluationErrorCode::ModuloCannotPerformOnFloat):
|
||||
return resLoader->GetString(L"ModuloCannotPerformOnFloat");
|
||||
break;
|
||||
case (EvaluationErrorCode::EquationTooComplexToSolve):
|
||||
case (EvaluationErrorCode::EquationTooComplexToSolveSymbolic):
|
||||
case (EvaluationErrorCode::EquationTooComplexToPlot):
|
||||
case (EvaluationErrorCode::InequalityTooComplexToSolve):
|
||||
case (EvaluationErrorCode::GE_TooComplexToSolve):
|
||||
return resLoader->GetString(L"TooComplexToSolve");
|
||||
break;
|
||||
case (EvaluationErrorCode::EquationHasNoSolution):
|
||||
case (EvaluationErrorCode::InequalityHasNoSolution):
|
||||
return resLoader->GetString(L"EquationHasNoSolution");
|
||||
break;
|
||||
case (EvaluationErrorCode::DivideByZero):
|
||||
return resLoader->GetString(L"DivideByZero");
|
||||
break;
|
||||
case (EvaluationErrorCode::MutuallyExclusiveConditions):
|
||||
return resLoader->GetString(L"MutuallyExclusiveConditions");
|
||||
break;
|
||||
case (EvaluationErrorCode::OutOfDomain):
|
||||
return resLoader->GetString(L"OutOfDomain");
|
||||
break;
|
||||
case (EvaluationErrorCode::GE_NotSupported):
|
||||
return resLoader->GetString(L"GE_NotSupported");
|
||||
break;
|
||||
default:
|
||||
return resLoader->GetString(L"GeneralError");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (errorType == ::ErrorType::Syntax)
|
||||
{
|
||||
switch (static_cast<SyntaxErrorCode>(errorCode))
|
||||
{
|
||||
case (SyntaxErrorCode::ParenthesisMismatch):
|
||||
return resLoader->GetString(L"ParenthesisMismatch");
|
||||
break;
|
||||
case (SyntaxErrorCode::UnmatchedParenthesis):
|
||||
return resLoader->GetString(L"UnmatchedParenthesis");
|
||||
break;
|
||||
case (SyntaxErrorCode::TooManyDecimalPoints):
|
||||
return resLoader->GetString(L"TooManyDecimalPoints");
|
||||
break;
|
||||
case (SyntaxErrorCode::DecimalPointWithoutDigits):
|
||||
return resLoader->GetString(L"DecimalPointWithoutDigits");
|
||||
break;
|
||||
case (SyntaxErrorCode::UnexpectedEndOfExpression):
|
||||
return resLoader->GetString(L"UnexpectedEndOfExpression");
|
||||
break;
|
||||
case (SyntaxErrorCode::UnexpectedToken):
|
||||
return resLoader->GetString(L"UnexpectedToken");
|
||||
break;
|
||||
case (SyntaxErrorCode::InvalidToken):
|
||||
return resLoader->GetString(L"InvalidToken");
|
||||
break;
|
||||
case (SyntaxErrorCode::TooManyEquals):
|
||||
return resLoader->GetString(L"TooManyEquals");
|
||||
break;
|
||||
case (SyntaxErrorCode::EqualWithoutGraphVariable):
|
||||
return resLoader->GetString(L"EqualWithoutGraphVariable");
|
||||
break;
|
||||
case (SyntaxErrorCode::InvalidEquationSyntax):
|
||||
case (SyntaxErrorCode::InvalidEquationFormat):
|
||||
return resLoader->GetString(L"InvalidEquationSyntax");
|
||||
break;
|
||||
case (SyntaxErrorCode::EmptyExpression):
|
||||
return resLoader->GetString(L"EmptyExpression");
|
||||
break;
|
||||
case (SyntaxErrorCode::EqualWithoutEquation):
|
||||
return resLoader->GetString(L"EqualWithoutEquation");
|
||||
break;
|
||||
case (SyntaxErrorCode::ExpectParenthesisAfterFunctionName):
|
||||
return resLoader->GetString(L"ExpectParenthesisAfterFunctionName");
|
||||
break;
|
||||
case (SyntaxErrorCode::IncorrectNumParameter):
|
||||
return resLoader->GetString(L"IncorrectNumParameter");
|
||||
break;
|
||||
case (SyntaxErrorCode::InvalidVariableNameFormat):
|
||||
return resLoader->GetString(L"InvalidVariableNameFormat");
|
||||
break;
|
||||
case (SyntaxErrorCode::BracketMismatch):
|
||||
return resLoader->GetString(L"BracketMismatch");
|
||||
break;
|
||||
case (SyntaxErrorCode::UnmatchedBracket):
|
||||
return resLoader->GetString(L"UnmatchedBracket");
|
||||
break;
|
||||
case (SyntaxErrorCode::CannotUseIInReal):
|
||||
return resLoader->GetString(L"CannotUseIInReal");
|
||||
break;
|
||||
case (SyntaxErrorCode::InvalidNumberDigit):
|
||||
return resLoader->GetString(L"InvalidNumberDigit");
|
||||
break;
|
||||
case (SyntaxErrorCode::InvalidNumberBase):
|
||||
return resLoader->GetString(L"InvalidNumberBase");
|
||||
break;
|
||||
case (SyntaxErrorCode::InvalidVariableSpecification):
|
||||
return resLoader->GetString(L"InvalidVariableSpecification");
|
||||
break;
|
||||
case (SyntaxErrorCode::ExpectingLogicalOperands):
|
||||
case (SyntaxErrorCode::ExpectingScalarOperands):
|
||||
return resLoader->GetString(L"ExpectingLogicalOperands");
|
||||
break;
|
||||
case (SyntaxErrorCode::CannotUseIndexVarInOpLimits):
|
||||
return resLoader->GetString(L"CannotUseIndexVarInOpLimits");
|
||||
break;
|
||||
case (SyntaxErrorCode::CannotUseIndexVarInLimPoint):
|
||||
return resLoader->GetString(L"Overflow");
|
||||
break;
|
||||
case (SyntaxErrorCode::CannotUseComplexInfinityInReal):
|
||||
return resLoader->GetString(L"CannotUseComplexInfinityInReal");
|
||||
break;
|
||||
case (SyntaxErrorCode::CannotUseIInInequalitySolving):
|
||||
return resLoader->GetString(L"CannotUseIInInequalitySolving");
|
||||
break;
|
||||
default:
|
||||
return resLoader->GetString(L"GeneralError");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return resLoader->GetString(L"GeneralError");
|
||||
}
|
||||
}
|
||||
|
@ -103,6 +103,8 @@ public
|
||||
|
||||
void PopulateKeyGraphFeatures(GraphControl::KeyGraphFeaturesInfo ^ info);
|
||||
|
||||
static Platform::String ^ EquationErrorText(GraphControl::ErrorType errorType, int errorCode);
|
||||
|
||||
private:
|
||||
void AddKeyGraphFeature(Platform::String ^ title, Platform::String ^ expression, Platform::String ^ errorString);
|
||||
void AddKeyGraphFeature(
|
||||
|
@ -27,6 +27,7 @@ DEPENDENCY_PROPERTY_INITIALIZATION(EquationTextBox, EquationButtonContentIndex);
|
||||
DEPENDENCY_PROPERTY_INITIALIZATION(EquationTextBox, HasError);
|
||||
DEPENDENCY_PROPERTY_INITIALIZATION(EquationTextBox, IsAddEquationMode);
|
||||
DEPENDENCY_PROPERTY_INITIALIZATION(EquationTextBox, MathEquation);
|
||||
DEPENDENCY_PROPERTY_INITIALIZATION(EquationTextBox, ErrorText);
|
||||
DEPENDENCY_PROPERTY_INITIALIZATION(EquationTextBox, IsEquationLineDisabled);
|
||||
|
||||
EquationTextBox::EquationTextBox()
|
||||
@ -432,12 +433,12 @@ void EquationTextBox::OnRichEditMenuOpened(Object ^ /*sender*/, Object ^ /*args*
|
||||
|
||||
if (m_richEditBox != nullptr && m_cutMenuItem != nullptr)
|
||||
{
|
||||
m_cutMenuItem->IsEnabled = m_richEditBox->TextDocument->CanCopy() && m_richEditBox->TextDocument->Selection->Length > 0;
|
||||
m_cutMenuItem->IsEnabled = m_richEditBox->TextDocument->CanCopy();
|
||||
}
|
||||
|
||||
if (m_richEditBox != nullptr && m_copyMenuItem != nullptr)
|
||||
{
|
||||
m_copyMenuItem->IsEnabled = m_richEditBox->TextDocument->CanCopy() && m_richEditBox->TextDocument->Selection->Length > 0;
|
||||
m_copyMenuItem->IsEnabled = m_richEditBox->TextDocument->CanCopy();
|
||||
}
|
||||
|
||||
if (m_richEditBox != nullptr && m_pasteMenuItem != nullptr)
|
||||
|
@ -25,6 +25,7 @@ namespace CalculatorApp
|
||||
DEPENDENCY_PROPERTY(Platform::String ^, MathEquation);
|
||||
DEPENDENCY_PROPERTY_WITH_CALLBACK(bool, HasError);
|
||||
DEPENDENCY_PROPERTY_WITH_CALLBACK(bool, IsAddEquationMode);
|
||||
DEPENDENCY_PROPERTY(Platform::String ^, ErrorText);
|
||||
DEPENDENCY_PROPERTY(bool, IsEquationLineDisabled);
|
||||
|
||||
PROPERTY_R(bool, HasFocus);
|
||||
|
@ -4105,6 +4105,162 @@
|
||||
<data name="KGFRangeNone" xml:space="preserve">
|
||||
<value>Unable to calculate the range for this function.</value>
|
||||
<comment>Error displayed when Range is not returned from the analyzer.</comment>
|
||||
</data>
|
||||
<data name="Overflow" xml:space="preserve">
|
||||
<value>Overflow (the number is too large)</value>
|
||||
<comment>Error that occurs during graphing when the number is too large. To see this error, assign a large number to variable a, then keep doing "a:=a*a" until it happens.</comment>
|
||||
</data>
|
||||
<data name="RequireRadiansMode" xml:space="preserve">
|
||||
<value>Radians mode is required to graph this equation.</value>
|
||||
<comment>Error that occurs during graphing when radians is required.</comment>
|
||||
</data>
|
||||
<data name="TooComplexToSolve" xml:space="preserve">
|
||||
<value>This function is too complex to graph</value>
|
||||
<comment>Error that occurs during graphing when the equation is too complex.</comment>
|
||||
</data>
|
||||
<data name="RequireDegreesMode" xml:space="preserve">
|
||||
<value>Degrees mode is required to graph this function</value>
|
||||
<comment>Error that occurs during graphing when degrees is required</comment>
|
||||
</data>
|
||||
<data name="FactorialInvalidArgument" xml:space="preserve">
|
||||
<value>The factorial function has an invalid argument</value>
|
||||
<comment>Error that occurs during graphing when a factorial function has an invalid argument.</comment>
|
||||
</data>
|
||||
<data name="FactorialCannotPerformOnLargeNumber" xml:space="preserve">
|
||||
<value>The factorial function has an argument that is too large to graph</value>
|
||||
<comment>Error that occurs during graphing when a factorial has a large n</comment>
|
||||
</data>
|
||||
<data name="ModuloCannotPerformOnFloat" xml:space="preserve">
|
||||
<value>Modulo can only be used with whole numbers</value>
|
||||
<comment>Error that occurs during graphing when modulo is used with a float.</comment>
|
||||
</data>
|
||||
<data name="EquationHasNoSolution" xml:space="preserve">
|
||||
<value>The equation has no solution</value>
|
||||
<comment>Error that occurs during graphing when the equation has no solution.</comment>
|
||||
</data>
|
||||
<data name="DivideByZero" xml:space="preserve">
|
||||
<value>Cannot divide by zero</value>
|
||||
<comment>Error that occurs during graphing when a divison by zero occurs.</comment>
|
||||
</data>
|
||||
<data name="MutuallyExclusiveConditions" xml:space="preserve">
|
||||
<value>The equation contains logical conditions that are mutually exclusive</value>
|
||||
<comment>Error that occurs during graphing when mutually exclusive conditions are used.</comment>
|
||||
</data>
|
||||
<data name="OutOfDomain" xml:space="preserve">
|
||||
<value>Equation is out of domain</value>
|
||||
<comment>Error that occurs during graphing when the equation is out of domain.</comment>
|
||||
</data>
|
||||
<data name="GE_NotSupported" xml:space="preserve">
|
||||
<value>Graphing this equation is not supported</value>
|
||||
<comment>Error that occurs during graphing when the equation is not supported.</comment>
|
||||
</data>
|
||||
<data name="ParenthesisMismatch" xml:space="preserve">
|
||||
<value>The equation is missing an opening parenthesis</value>
|
||||
<comment>Error that occurs during graphing when the equation is missing a (</comment>
|
||||
</data>
|
||||
<data name="UnmatchedParenthesis" xml:space="preserve">
|
||||
<value>The equation is missing a closing parenthesis</value>
|
||||
<comment>Error that occurs during graphing when the equation is missing a )</comment>
|
||||
</data>
|
||||
<data name="TooManyDecimalPoints" xml:space="preserve">
|
||||
<value>There are too many decimal points in a number</value>
|
||||
<comment>Error that occurs during graphing when a number has too many decimals. Ex: 1.2.3</comment>
|
||||
</data>
|
||||
<data name="DecimalPointWithoutDigits" xml:space="preserve">
|
||||
<value>A decimal point is missing digits</value>
|
||||
<comment>Error that occurs during graphing with a decimal point without digits</comment>
|
||||
</data>
|
||||
<data name="UnexpectedEndOfExpression" xml:space="preserve">
|
||||
<value>Unexpected end of expression</value>
|
||||
<comment>Error that occurs during graphing when the expression ends unexpectedly. Ex: 3-4*</comment>
|
||||
</data>
|
||||
<data name="UnexpectedToken" xml:space="preserve">
|
||||
<value>Unexpected characters in the expression</value>
|
||||
<comment>Error that occurs during graphing when there is an unexpected token.</comment>
|
||||
</data>
|
||||
<data name="InvalidToken" xml:space="preserve">
|
||||
<value>Invalid characters in the expression</value>
|
||||
<comment>Error that occurs during graphing when there is an invalid token.</comment>
|
||||
</data>
|
||||
<data name="TooManyEquals" xml:space="preserve">
|
||||
<value>There are too many equal signs</value>
|
||||
<comment>Error that occurs during graphing when there are too many equals.</comment>
|
||||
</data>
|
||||
<data name="EqualWithoutGraphVariable" xml:space="preserve">
|
||||
<value>The function must contain at least one x or y variable</value>
|
||||
<comment>Error that occurs during graphing when the equation is missing x or y.</comment>
|
||||
</data>
|
||||
<data name="InvalidEquationSyntax" xml:space="preserve">
|
||||
<value>Invalid expression</value>
|
||||
<comment>Error that occurs during graphing when an invalid syntax is used.</comment>
|
||||
</data>
|
||||
<data name="EmptyExpression" xml:space="preserve">
|
||||
<value>The expression is empty</value>
|
||||
<comment>Error that occurs during graphing when the expression is empty</comment>
|
||||
</data>
|
||||
<data name="EqualWithoutEquation" xml:space="preserve">
|
||||
<value>Equal was used without an equation</value>
|
||||
<comment>Error that occurs during graphing when equal is used without an equation. Ex: sin(x=y)</comment>
|
||||
</data>
|
||||
<data name="ExpectParenthesisAfterFunctionName" xml:space="preserve">
|
||||
<value>Parenthesis missing after function name</value>
|
||||
<comment>Error that occurs during graphing when parenthesis are missing after a function.</comment>
|
||||
</data>
|
||||
<data name="IncorrectNumParameter" xml:space="preserve">
|
||||
<value>A mathematical operation has the incorrect number of parameters</value>
|
||||
<comment>Error that occurs during graphing when a function has the wrong number of parameters</comment>
|
||||
</data>
|
||||
<data name="InvalidVariableNameFormat" xml:space="preserve">
|
||||
<value>A variable name is invalid</value>
|
||||
<comment>Error that occurs during graphing when a variable name is invalid.</comment>
|
||||
</data>
|
||||
<data name="BracketMismatch" xml:space="preserve">
|
||||
<value>The equation is missing an opening bracket</value>
|
||||
<comment>Error that occurs during graphing when a { is missing</comment>
|
||||
</data>
|
||||
<data name="UnmatchedBracket" xml:space="preserve">
|
||||
<value>The equation is missing a closing bracket</value>
|
||||
<comment>Error that occurs during graphing when a } is missing.</comment>
|
||||
</data>
|
||||
<data name="CannotUseIInReal" xml:space="preserve">
|
||||
<value>"i" and "I" cannot be used as variable names</value>
|
||||
<comment>Error that occurs during graphing when i or I is used.</comment>
|
||||
</data>
|
||||
<data name="GeneralError" xml:space="preserve">
|
||||
<value>The equation could not be graphed</value>
|
||||
<comment>General error that occurs during graphing.</comment>
|
||||
</data>
|
||||
<data name="InvalidNumberDigit" xml:space="preserve">
|
||||
<value>The digit could not be resolved for the given base</value>
|
||||
<comment>Error that occurs during graphing when trying to use bases incorrect. Ex: base(2,1020).</comment>
|
||||
</data>
|
||||
<data name="InvalidNumberBase" xml:space="preserve">
|
||||
<value>The base must be greater than 2 and less than 36</value>
|
||||
<comment>Error that occurs during graphing when the base is out of range.</comment>
|
||||
</data>
|
||||
<data name="InvalidVariableSpecification" xml:space="preserve">
|
||||
<value>A mathematical operation requires one of its paramaters to be a variable</value>
|
||||
<comment>Error that occurs during graphing when a function requires a variable in a particular position. Ex: 2nd argument of deriv.</comment>
|
||||
</data>
|
||||
<data name="ExpectingLogicalOperands" xml:space="preserve">
|
||||
<value>Equation is mixing logical and scalar operands</value>
|
||||
<comment>Error that occurs during graphing when operands are mixed. Such as true and 1.</comment>
|
||||
</data>
|
||||
<data name="CannotUseIndexVarInOpLimits" xml:space="preserve">
|
||||
<value>x or y cannot be used in the upper or lower limits</value>
|
||||
<comment>Error that occurs during graphing when x or y is used in integral upper limits.</comment>
|
||||
</data>
|
||||
<data name="CannotUseIndexVarInLimPoint" xml:space="preserve">
|
||||
<value>x or y cannot be used in the limit point</value>
|
||||
<comment>Error that occurs during graphing when x or y is used in the limit point.</comment>
|
||||
</data>
|
||||
<data name="CannotUseComplexInfinityInReal" xml:space="preserve">
|
||||
<value>Cannot use complex infinity</value>
|
||||
<comment>Error that occurs during graphing when complex infinity is used</comment>
|
||||
</data>
|
||||
<data name="CannotUseIInInequalitySolving" xml:space="preserve">
|
||||
<value>Cannot use complex numbers in inequalities</value>
|
||||
<comment>Error that occurs during graphing when complex numbers are used in inequalities.</comment>
|
||||
</data>
|
||||
<data name="equationAnalysisBack.[using:Windows.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
|
||||
<value>Back</value>
|
||||
|
@ -324,6 +324,7 @@
|
||||
<Setter Target="EquationBoxBorder.BorderThickness" Value="1"/>
|
||||
<Setter Target="EquationBoxBorder.BorderBrush" Value="{ThemeResource EquationBoxErrorBorderBrush}"/>
|
||||
<Setter Target="EquationBoxBorder.Background" Value="{ThemeResource EquationBoxErrorBackgroundBrush}"/>
|
||||
<Setter Target="RemoveButton.Visibility" Value="Visible"/>
|
||||
<Setter Target="ErrorIcon.Visibility" Value="Visible"/>
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
@ -344,7 +345,7 @@
|
||||
<Setter Target="ColorChooserButton.Visibility" Value="Collapsed"/>
|
||||
<Setter Target="FunctionButton.Visibility" Value="Collapsed"/>
|
||||
<Setter Target="RemoveButton.Visibility" Value="Visible"/>
|
||||
<Setter Target="ErrorIcon.Visibility" Value="Collapsed"/>
|
||||
<Setter Target="ErrorIcon.Visibility" Value="Visible"/>
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Disabled">
|
||||
@ -568,6 +569,7 @@
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<controls:MathRichEditBox x:Name="MathRichEditBox"
|
||||
x:Uid="mathRichEditBox"
|
||||
@ -698,7 +700,18 @@
|
||||
</ResourceDictionary>
|
||||
</ToggleButton.Resources>
|
||||
</ToggleButton>
|
||||
<Grid x:Name="RemoveButtonPanel" Grid.Column="3">
|
||||
<FontIcon x:Name="ErrorIcon"
|
||||
Grid.Column="3"
|
||||
MinWidth="28"
|
||||
VerticalAlignment="Stretch"
|
||||
Foreground="{ThemeResource ButtonForeground}"
|
||||
FontFamily="{ThemeResource SymbolThemeFontFamily}"
|
||||
FontSize="16"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
Glyph=""
|
||||
ToolTipService.ToolTip="{TemplateBinding ErrorText}"
|
||||
Visibility="Collapsed"/>
|
||||
<Grid x:Name="RemoveButtonPanel" Grid.Column="4">
|
||||
<Button x:Name="RemoveButton"
|
||||
x:Uid="removeButton"
|
||||
MinWidth="34"
|
||||
@ -737,7 +750,7 @@
|
||||
</Button>
|
||||
</Grid>
|
||||
<Button x:Name="DeleteButton"
|
||||
Grid.Column="3"
|
||||
Grid.Column="4"
|
||||
MinWidth="34"
|
||||
Margin="1,2"
|
||||
VerticalAlignment="Stretch"
|
||||
@ -774,16 +787,6 @@
|
||||
</ResourceDictionary>
|
||||
</Button.Resources>
|
||||
</Button>
|
||||
<FontIcon x:Name="ErrorIcon"
|
||||
Grid.Column="3"
|
||||
MinWidth="28"
|
||||
VerticalAlignment="Stretch"
|
||||
Foreground="{ThemeResource ButtonForeground}"
|
||||
FontFamily="{ThemeResource SymbolThemeFontFamily}"
|
||||
FontSize="16"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
Glyph=""
|
||||
Visibility="Collapsed"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
@ -823,7 +826,8 @@
|
||||
</ListView.ItemContainerStyle>
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:EquationViewModel">
|
||||
<controls:EquationTextBox x:Uid="EquationInputButton"
|
||||
<controls:EquationTextBox x:Name="EquationInputButton"
|
||||
x:Uid="EquationInputButton"
|
||||
Margin="1,0,1,2"
|
||||
Style="{StaticResource EquationTextBoxStyle}"
|
||||
DataContext="{x:Bind Mode=OneWay}"
|
||||
@ -833,6 +837,7 @@
|
||||
EquationColor="{x:Bind local:EquationInputArea.ToSolidColorBrush(LineColor), Mode=OneWay}"
|
||||
EquationFormatRequested="EquationTextBox_EquationFormatRequested"
|
||||
EquationSubmitted="EquationTextBox_Submitted"
|
||||
ErrorText="{x:Bind vm:EquationViewModel.EquationErrorText(GraphEquation.GraphErrorType, GraphEquation.GraphErrorCode), Mode=OneWay}"
|
||||
GotFocus="EquationTextBox_GotFocus"
|
||||
HasError="{x:Bind GraphEquation.HasGraphError, Mode=OneWay}"
|
||||
IsAddEquationMode="{x:Bind IsLastItemInList, Mode=OneWay}"
|
||||
|
@ -297,6 +297,8 @@ namespace GraphControl
|
||||
{
|
||||
optional<vector<shared_ptr<IEquation>>> initResult = nullopt;
|
||||
bool successful = false;
|
||||
m_errorCode = 0;
|
||||
m_errorType = 0;
|
||||
|
||||
if (m_renderMain && m_graph != nullptr)
|
||||
{
|
||||
@ -345,7 +347,7 @@ namespace GraphControl
|
||||
parsableEquation += s_getGraphClosingTags;
|
||||
|
||||
// Wire up the corresponding error to an error message in the UI at some point
|
||||
if (!(expr = m_solver->ParseInput(parsableEquation)))
|
||||
if (!(expr = m_solver->ParseInput(parsableEquation, m_errorCode, m_errorType)))
|
||||
{
|
||||
co_return false;
|
||||
}
|
||||
@ -356,7 +358,7 @@ namespace GraphControl
|
||||
request += s_getGraphClosingTags;
|
||||
}
|
||||
|
||||
if (graphExpression = m_solver->ParseInput(request))
|
||||
if (graphExpression = m_solver->ParseInput(request, m_errorCode, m_errorType))
|
||||
{
|
||||
initResult = TryInitializeGraph(keepCurrentView, graphExpression.get());
|
||||
|
||||
@ -386,8 +388,13 @@ namespace GraphControl
|
||||
// If we failed to render then we have already lost the previous graph
|
||||
shouldKeepPreviousGraph = false;
|
||||
initResult = nullopt;
|
||||
m_solver->HRErrorToErrorInfo(m_renderMain->GetRenderError(), m_errorCode, m_errorType);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_solver->HRErrorToErrorInfo(m_graph->GetInitializationError(), m_errorCode, m_errorType);
|
||||
}
|
||||
}
|
||||
|
||||
if (initResult == nullopt)
|
||||
@ -398,7 +405,7 @@ namespace GraphControl
|
||||
initResult = m_graph->TryInitialize();
|
||||
if (initResult != nullopt)
|
||||
{
|
||||
UpdateGraphOptions(m_graph->GetOptions(), validEqs);
|
||||
UpdateGraphOptions(m_graph->GetOptions(), vector<Equation^>());
|
||||
SetGraphArgs(m_graph);
|
||||
|
||||
m_renderMain->Graph = m_graph;
|
||||
@ -431,6 +438,8 @@ namespace GraphControl
|
||||
{
|
||||
if (!eq->IsValidated)
|
||||
{
|
||||
eq->GraphErrorType = static_cast<ErrorType>(m_errorType);
|
||||
eq->GraphErrorCode = m_errorCode;
|
||||
eq->HasGraphError = true;
|
||||
}
|
||||
}
|
||||
@ -457,7 +466,7 @@ namespace GraphControl
|
||||
request += equation->GetRequest()->Data();
|
||||
request += s_getGraphClosingTags;
|
||||
|
||||
if (unique_ptr<IExpression> graphExpression = m_solver->ParseInput(request))
|
||||
if (unique_ptr<IExpression> graphExpression = m_solver->ParseInput(request, m_errorCode, m_errorType))
|
||||
{
|
||||
if (graph->TryInitialize(graphExpression.get()))
|
||||
{
|
||||
@ -524,7 +533,7 @@ namespace GraphControl
|
||||
m_graph->SetArgValue(variableName->Data(), newValue);
|
||||
m_renderMain->GetCriticalSection().unlock();
|
||||
|
||||
m_renderMain->RunRenderPassAsync();
|
||||
m_renderMain->RunRenderPass();
|
||||
});
|
||||
|
||||
ThreadPool::RunAsync(workItemHandler, WorkItemPriority::High, WorkItemOptions::None);
|
||||
@ -549,7 +558,7 @@ namespace GraphControl
|
||||
auto lineColor = eq->LineColor;
|
||||
graphColors.emplace_back(lineColor.R, lineColor.G, lineColor.B, lineColor.A);
|
||||
|
||||
if (eq->IsSelected)
|
||||
if (eq->GraphedEquation != nullptr && !eq->HasGraphError && eq->IsSelected)
|
||||
{
|
||||
eq->GraphedEquation->TrySelectEquation();
|
||||
}
|
||||
@ -1001,7 +1010,7 @@ String ^ Grapher::ConvertToLinear(String ^ mmlString)
|
||||
{
|
||||
m_solver->FormatOptions().SetFormatType(FormatType::LinearInput);
|
||||
|
||||
auto expression = m_solver->ParseInput(mmlString->Data());
|
||||
auto expression = m_solver->ParseInput(mmlString->Data(), m_errorCode, m_errorType);
|
||||
auto linearExpression = m_solver->Serialize(expression.get());
|
||||
|
||||
m_solver->FormatOptions().SetFormatType(s_defaultFormatType);
|
||||
@ -1011,7 +1020,7 @@ String ^ Grapher::ConvertToLinear(String ^ mmlString)
|
||||
|
||||
String ^ Grapher::FormatMathML(String ^ mmlString)
|
||||
{
|
||||
auto expression = m_solver->ParseInput(mmlString->Data());
|
||||
auto expression = m_solver->ParseInput(mmlString->Data(), m_errorCode, m_errorType);
|
||||
auto formattedExpression = m_solver->Serialize(expression.get());
|
||||
return ref new String(formattedExpression.c_str());
|
||||
}
|
||||
|
@ -335,6 +335,8 @@ public
|
||||
bool m_Moving;
|
||||
Windows::UI::Xaml::DispatcherTimer ^ m_TracingTrackingTimer;
|
||||
Windows::UI::Core::CoreCursor ^ m_cachedCursor;
|
||||
int m_errorType;
|
||||
int m_errorCode;
|
||||
|
||||
public:
|
||||
Windows::Storage::Streams::RandomAccessStreamReference ^ GetGraphBitmapStream();
|
||||
|
@ -274,7 +274,9 @@ namespace GraphControl::DX
|
||||
pRenderTarget->BeginDraw();
|
||||
|
||||
bool hasMissingData = false;
|
||||
successful = SUCCEEDED(renderer->DrawD2D1(pFactory, pRenderTarget, hasMissingData));
|
||||
m_HResult = renderer->DrawD2D1(pFactory, pRenderTarget, hasMissingData);
|
||||
|
||||
successful = SUCCEEDED(m_HResult);
|
||||
|
||||
// We ignore D2DERR_RECREATE_TARGET here. This error indicates that the device
|
||||
// is lost. It will be handled during the next call to Present.
|
||||
@ -345,6 +347,11 @@ namespace GraphControl::DX
|
||||
return successful;
|
||||
}
|
||||
|
||||
HRESULT RenderMain::GetRenderError()
|
||||
{
|
||||
return m_HResult;
|
||||
}
|
||||
|
||||
void RenderMain::OnLoaded(Object ^ sender, RoutedEventArgs ^ e)
|
||||
{
|
||||
RunRenderPass();
|
||||
|
@ -61,6 +61,8 @@ namespace GraphControl::DX
|
||||
return m_isRenderPassSuccesful;
|
||||
}
|
||||
|
||||
HRESULT GetRenderError();
|
||||
|
||||
// Indicates if we are in active tracing mode (the tracing box is being used and controlled through keyboard input)
|
||||
property bool ActiveTracing
|
||||
{
|
||||
@ -189,5 +191,7 @@ namespace GraphControl::DX
|
||||
Windows::Foundation::IAsyncAction ^ m_renderPass = nullptr;
|
||||
|
||||
bool m_isRenderPassSuccesful;
|
||||
|
||||
HRESULT m_HResult;
|
||||
};
|
||||
}
|
||||
|
@ -7,6 +7,200 @@
|
||||
|
||||
namespace GraphControl
|
||||
{
|
||||
public enum class ErrorType
|
||||
{
|
||||
Evaluation,
|
||||
Syntax,
|
||||
Abort,
|
||||
};
|
||||
|
||||
public enum class EvaluationErrorCode
|
||||
{
|
||||
// Number is too large. To see this error, assign a large number to variable a, then keep doing "a:=a*a" until it happens
|
||||
Overflow = 2,
|
||||
|
||||
// doing trig in calculus and current mode is not Radians
|
||||
RequireRadiansMode = 3,
|
||||
|
||||
// This is actually abort code generated as time limit reached.
|
||||
TooComplexToSolve = 4,
|
||||
|
||||
// degree sign present and the current mode is not Degrees
|
||||
RequireDegreesMode = 5,
|
||||
|
||||
// n! and n is not an non-negative integer or m/2
|
||||
FactorialInvalidArgument = -1,
|
||||
|
||||
// n!! and n is not an non-negative integer or odd negative integers
|
||||
Factorial2InvalidArgument = -2,
|
||||
|
||||
// n! and n is too big
|
||||
FactorialCannotPerformOnLargeNumber = -3,
|
||||
|
||||
// x mod y, and one of them is not an integer
|
||||
ModuloCannotPerformOnFloat = -5,
|
||||
|
||||
// below are equation solving specific errors
|
||||
|
||||
// example1: sin(x)+x=2 example2: x^4-x^3-8x=9
|
||||
EquationTooComplexToSolveSymbolic = -7,
|
||||
|
||||
// example1: x-x=3 example2: x^2=-1
|
||||
EquationHasNoSolution = -8,
|
||||
|
||||
// only used for numeric solve where the algorithm doesn't converge
|
||||
EquationTooComplexToSolve = -9,
|
||||
|
||||
// used when equation cannot be ploted
|
||||
EquationTooComplexToPlot = -10,
|
||||
|
||||
// example1: 1/0
|
||||
DivideByZero = -15,
|
||||
|
||||
// the inequality is too complex for the engine to solve
|
||||
InequalityTooComplexToSolve = -41,
|
||||
|
||||
// the inequality has no solution
|
||||
InequalityHasNoSolution = -42,
|
||||
|
||||
// An exression contains logical conditions that are mutually exclusive
|
||||
MutuallyExclusiveConditions = -43,
|
||||
|
||||
// Arbitrary Precision Evaluation input is out of domain
|
||||
OutOfDomain = -101,
|
||||
|
||||
// Not supported.
|
||||
GE_NotSupported = -503,
|
||||
|
||||
// General error for graphing engine
|
||||
GE_GeneralError = -504,
|
||||
|
||||
// Failed to calculate
|
||||
GE_TooComplexToSolve = -506,
|
||||
};
|
||||
|
||||
public enum class SyntaxErrorCode
|
||||
{
|
||||
// found ) without matching (
|
||||
ParenthesisMismatch = 1,
|
||||
|
||||
// found ( without matching )
|
||||
UnmatchedParenthesis = 2,
|
||||
|
||||
// more than 1 decimal point in a number. Example: 7.3.2
|
||||
TooManyDecimalPoints = 3,
|
||||
|
||||
// decimal point on its own without any digits surrounding it. Example: 3+.+4
|
||||
DecimalPointWithoutDigits = 4,
|
||||
|
||||
// example: 3-4*
|
||||
UnexpectedEndOfExpression = 5,
|
||||
|
||||
// example: 3-*4
|
||||
UnexpectedToken = 6,
|
||||
|
||||
// example: [ (or many other special characters), another example: "3,5" (comma is invalid here)
|
||||
InvalidToken = 7,
|
||||
|
||||
// example: solve(x+3=8=x)
|
||||
TooManyEquals = 8,
|
||||
|
||||
// example: ploteq(4+83=9)
|
||||
EqualWithoutGraphVariable = 10,
|
||||
|
||||
// <para>example: ploteq(x+y) (expecting "=" in equation ploting)</para>
|
||||
// <para>example2: Solve(5*x+9) (expecting = in the equation solving)</para>
|
||||
InvalidEquationSyntax = 11,
|
||||
|
||||
// there is nothing in the expression
|
||||
EmptyExpression = 12,
|
||||
|
||||
// example: factor(x=3) (expecting solve(x=3)).
|
||||
EqualWithoutEquation = 14,
|
||||
|
||||
// example: solve( (x=3)*2 )
|
||||
InvalidEquationFormat = 15,
|
||||
|
||||
// This error only occurs when CasContext.ParsingOptions.AllowImplicitParentheses == false.
|
||||
// example: sin a (expecting sin(a))
|
||||
ExpectParenthesisAfterFunctionName = 25,
|
||||
|
||||
// example: root(a) (expecting 2 parameters)
|
||||
IncorrectNumParameter = 26,
|
||||
|
||||
// exmaple: "x_", "x_@", "x__1"
|
||||
InvalidVariableNameFormat = 32,
|
||||
|
||||
// found } without matching {
|
||||
BracketMismatch = 34,
|
||||
|
||||
// found { without matching }
|
||||
UnmatchedBracket = 35,
|
||||
|
||||
// syntax error in MathML format. Used only if CasContext.ParsingOptions.FormatType is MathML or MathMLNoWrapper
|
||||
InvalidMathMLFormat = 40,
|
||||
|
||||
// The input has an unknown MathML entity. Used only if CasContext.ParsingOptions.FormatType is MathML or MathMLNoWrapper
|
||||
UnknownMathMLEntity = 41,
|
||||
|
||||
// The input has an unknown MathML element. Used only if CasContext.ParsingOptions.FormatType is MathML or MathMLNoWrapper
|
||||
UnknownMathMLElement = 42,
|
||||
|
||||
// "i" and "I" cannot be used as variable names in real number field
|
||||
CannotUseIInReal = 48,
|
||||
|
||||
// General error
|
||||
GeneralError = 52,
|
||||
|
||||
// used in parsing numbers with arbitrary bases. example: base(2, 1020), base(16, 1AG)
|
||||
InvalidNumberDigit = 55,
|
||||
|
||||
// a valid number base must be an integer >=2 and <=36
|
||||
InvalidNumberBase = 56,
|
||||
|
||||
// some functions require a variable in certain argument position. e.g. 2nd argument of deriv, integral, limit, etc.
|
||||
// this error code is used if the argument at the position is not a variable
|
||||
InvalidVariableSpecification = 57,
|
||||
|
||||
// all operands of logical operators must be logical. example: "true and 1"
|
||||
ExpectingLogicalOperands = 58,
|
||||
|
||||
// all operands of a non-logical operator must not be logical. example: "sin(true)"
|
||||
ExpectingScalarOperands = 59,
|
||||
|
||||
// a list can contain logicals or scalars, but not both.
|
||||
CannotMixLogicalScalarInList = 60,
|
||||
|
||||
// in definite integral, seriesSum and seriesProduct, the index variable is used in the lower/upper limits.
|
||||
// example: integral(sin(x), x, 0, x)
|
||||
CannotUseIndexVarInOpLimits = 61,
|
||||
|
||||
// in limit, the index variable is used in the limit point
|
||||
// example: limit(sin(x), x, x-1)
|
||||
CannotUseIndexVarInLimPoint = 62,
|
||||
|
||||
/// ComplexInfinity cannot be used in real number field
|
||||
CannotUseComplexInfinityInReal = 72,
|
||||
|
||||
// complex numbers are not allowed in inequality solving
|
||||
CannotUseIInInequalitySolving = 123,
|
||||
|
||||
// Indicate a bug in the MathRichEdit serializer
|
||||
RichEditSerializationError = 201,
|
||||
|
||||
// can't initialize math zone in richedit, meaning it's the wrong version richedit dll, need reinstall
|
||||
RichEditInitialization = 202,
|
||||
|
||||
// indicate bug in either richedit or richedit wrapper
|
||||
RichEditInlineObjectStructure = 203,
|
||||
|
||||
// in a structure like integral, sum, product, one of the boxes is not filled
|
||||
RichEditMissingArgument = 204,
|
||||
|
||||
// errors in richedit wrapper that are not specifically handled for
|
||||
RichEditGeneralError = 210,
|
||||
};
|
||||
|
||||
[Windows::UI::Xaml::Data::Bindable] public ref class Equation sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
|
||||
{
|
||||
public:
|
||||
@ -18,6 +212,8 @@ namespace GraphControl
|
||||
OBSERVABLE_NAMED_PROPERTY_RW(bool, IsValidated);
|
||||
OBSERVABLE_NAMED_PROPERTY_RW(bool, HasGraphError);
|
||||
OBSERVABLE_NAMED_PROPERTY_RW(bool, IsSelected);
|
||||
OBSERVABLE_NAMED_PROPERTY_RW(ErrorType, GraphErrorType);
|
||||
OBSERVABLE_NAMED_PROPERTY_RW(int, GraphErrorCode);
|
||||
|
||||
property Windows::UI::Color LineColor
|
||||
{
|
||||
|
@ -29,6 +29,11 @@ namespace MockGraphingImpl
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
HRESULT GetInitializationError()
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
virtual Graphing::IGraphingOptions& GetOptions()
|
||||
{
|
||||
return m_graphingOptions;
|
||||
|
@ -115,7 +115,7 @@ namespace MockGraphingImpl
|
||||
return m_formatOptions;
|
||||
}
|
||||
|
||||
std::unique_ptr<Graphing::IExpression> ParseInput(const std::wstring& input) override
|
||||
std::unique_ptr<Graphing::IExpression> ParseInput(const std::wstring& input, int& errorCodeOut, int& errorTypeOut) override
|
||||
{
|
||||
if (input.empty())
|
||||
{
|
||||
@ -125,6 +125,10 @@ namespace MockGraphingImpl
|
||||
return std::make_unique<MockExpression>(MockExpression{});
|
||||
}
|
||||
|
||||
void HRErrorToErrorInfo(HRESULT hr, int& errorCodeOut, int& errorTypeOut)
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<Graphing::IGraph> CreateGrapher(const Graphing::IExpression* expression) override;
|
||||
|
||||
std::shared_ptr<Graphing::IGraph> CreateGrapher() override;
|
||||
|
@ -18,6 +18,8 @@ namespace Graphing
|
||||
|
||||
virtual std::optional<std::vector<std::shared_ptr<IEquation>>> TryInitialize(const IExpression* graphingExp = nullptr) = 0;
|
||||
|
||||
virtual HRESULT GetInitializationError() = 0;
|
||||
|
||||
virtual IGraphingOptions& GetOptions() = 0;
|
||||
|
||||
virtual std::vector<std::shared_ptr<Graphing::IVariable>> GetVariables() = 0;
|
||||
|
@ -64,9 +64,11 @@ namespace Graphing
|
||||
virtual IEvalOptions& EvalOptions() = 0;
|
||||
virtual IFormatOptions& FormatOptions() = 0;
|
||||
|
||||
virtual std::unique_ptr<IExpression> ParseInput(const std::wstring& input) = 0;
|
||||
virtual std::shared_ptr<IGraph> CreateGrapher(const IExpression* expression) = 0;
|
||||
virtual std::unique_ptr<IExpression> ParseInput(const std::wstring& input, int& errorCodeOut, int& errorTypeOut) = 0;
|
||||
|
||||
virtual void HRErrorToErrorInfo(HRESULT hr, int& errorCodeOut, int& errorTypeOut) = 0;
|
||||
|
||||
virtual std::shared_ptr<IGraph> CreateGrapher(const IExpression* expression) = 0;
|
||||
virtual std::shared_ptr<Graphing::IGraph> CreateGrapher() = 0;
|
||||
|
||||
virtual std::wstring Serialize(const IExpression* expression) = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user