Key graph features (#704)

* Added IGraphAnalyzer

* Key Graph Features called and getting returned to the client. To do put all strings into the Equation object

* Updated UpdateKeyGraphFeatures to add function analysis data to all properties in Equation object

* Update KGF when variables are updated

* Key graph features ui started

* Added MathRichEditBox and started hooking up key graph features to the UI

* Updated EquationViewModel to include parity and periodicity

* Updated key graph features to update the EquationViewModel

* updated key graph features to display more values

* Key graph features populating uing MathRichEdit mode

* moved KeyGraphFeatures control to GraphingCalculator.xaml

* Use MathML formatting instead of MathRichEdit for strings passed back from the engine

* cleaned up project targeting and equation.h comments

* Updated equation edit box to populate for KeyGraphFeatures

* Fixed vcxproj files to have the correct targeting and certificates. KGF Title strings moved to x:Uid instead of the code behind

* Updated per PR feedback

* Update MathRichEditBox to detect if the string is a mathml string and use the appropriate set method to set the text

* fixed the issue where parity, periodicity and monotonicity could be set with an old value if the next one is empty

* KGF control UI adjustments and error handling

* Error control updates

* Error handling added when analysis fails

* fixed alignment on rich edit boxes

* Add monotonicity direction into the mathml string and only have 1 richeditbox

* Set hover state on KGF EquationEditBox to change button opacity and fixed spacing in Monotonicity RichEditBox

* remove sideload package certificate info VS added

* updated logic for setting error strings to be in the viewmodel

* Updated KeyGraphFeatures to populate dynamically using a ListView and TemplateSelector

* Update periodicity to not show if it isn't supported

* Fixed issue where y-intercept was using the x-intercept value

* Remove ItemsControl ItemsContainerStyle

* Updated per pr feedback. Fixed bug where analysis error would not reset

* Update MathRichEdit box to remove selection when focus is lost

* Updated mathrichedit to get LAF access for Dev, Release and Graphing projects

* Remove OnLostFocus in MathRichEdit, Change KGF ItemsControl back to ListView

* Clean up styles for KGF and ensure the match the comps

* Moved formatoptions logic to the Grapher constructor and reverted LineColor.Text resource that was mistakenly taken out

* Add copyright header to KGF Files

* fixed issue where asymptote values were not populating

* Disable KGF button when there is no equation. Fixed issue where equation populated in a new equationtextbox after the previous one was deleted

* Removed formatoptions testing lines used for debugging
This commit is contained in:
Stephanie Anderl 2019-11-12 13:46:11 -08:00 committed by GitHub
parent 626bdf0de5
commit 442ed6a861
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
48 changed files with 2931 additions and 476 deletions

View File

@ -45,7 +45,7 @@
<AppContainerApplication>true</AppContainerApplication>
<ApplicationType>Windows Store</ApplicationType>
<ApplicationTypeRevision>10.0</ApplicationTypeRevision>
<WindowsTargetPlatformVersion Condition="'$(WindowsTargetPlatformVersion)' == ''">10.0.18970.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion Condition="'$(WindowsTargetPlatformVersion)' == ''">10.0.19019.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformMinVersion>10.0.17134.0</WindowsTargetPlatformMinVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

View File

@ -42,7 +42,7 @@
<MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
<AppContainerApplication>true</AppContainerApplication>
<ApplicationType>Windows Store</ApplicationType>
<WindowsTargetPlatformVersion>10.0.18970.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion>10.0.19019.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformMinVersion>10.0.17134.0</WindowsTargetPlatformMinVersion>
<ApplicationTypeRevision>10.0</ApplicationTypeRevision>
</PropertyGroup>
@ -351,6 +351,7 @@
<ClInclude Include="DataLoaders\UnitConverterDataConstants.h" />
<ClInclude Include="DataLoaders\UnitConverterDataLoader.h" />
<ClInclude Include="DateCalculatorViewModel.h" />
<ClInclude Include="GraphingCalculatorEnums.h" />
<ClInclude Include="GraphingCalculator\EquationViewModel.h" />
<ClInclude Include="GraphingCalculator\GraphingCalculatorViewModel.h" />
<ClInclude Include="HistoryItemViewModel.h" />

View File

@ -220,6 +220,9 @@
<ClInclude Include="DataLoaders\CurrencyDataLoader.h">
<Filter>DataLoaders</Filter>
</ClInclude>
<ClInclude Include="GraphingCalculatorEnums.h">
<Filter>Common</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />

View File

@ -1,14 +1,324 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#include "pch.h"
#include "EquationViewModel.h"
#include "CalcViewModel\Common\LocalizationSettings.h"
#include "CalcViewModel\GraphingCalculatorEnums.h"
using namespace CalculatorApp::Common;
using namespace Graphing;
using namespace Platform;
using namespace Platform::Collections;
using namespace std;
using namespace Windows::UI;
using namespace Windows::UI::Xaml;
using namespace Windows::Foundation::Collections;
namespace CalculatorApp::ViewModel
{
EquationViewModel::EquationViewModel()
: m_LineColor{ nullptr }, m_KeyGraphFeaturesVisibility{ ::Visibility::Collapsed }
, m_Expression{ "" }
GridDisplayItems::GridDisplayItems()
: m_Expression{ "" }
, m_Direction{ "" }
{
}
KeyGraphFeaturesItem::KeyGraphFeaturesItem()
: m_Title{ "" }
, m_DisplayItems{ ref new Vector<String ^>() }
, m_GridItems{ ref new Vector<GridDisplayItems ^>() }
, m_IsText{ false }
{
}
EquationViewModel::EquationViewModel()
: m_LineColor{ nullptr }
, m_Expression{ "" }
, m_IsAnalysisUpdated{ false }
, m_Domain{ "" }
, m_Range{ "" }
, m_XIntercept{ "" }
, m_YIntercept{ "" }
, m_Parity{ -1 }
, m_PeriodicityDirection{ -1 }
, m_PeriodicityExpression{ "" }
, m_Minima{ ref new Vector<String ^>() }
, m_Maxima{ ref new Vector<String ^>() }
, m_InflectionPoints{ ref new Vector<String ^>() }
, m_Monotonicity{ ref new Map<String ^, String ^>() }
, m_VerticalAsymptotes{ ref new Vector<String ^>() }
, m_HorizontalAsymptotes{ ref new Vector<String ^>() }
, m_ObliqueAsymptotes{ ref new Vector<String ^>() }
, m_TooComplexFeatures{ -1 }
, m_AnalysisError{ 0 }
, m_AnalysisErrorVisible{ false }
, m_KeyGraphFeaturesItems{ ref new Vector<KeyGraphFeaturesItem ^>() }
, m_resourceLoader{ Windows::ApplicationModel::Resources::ResourceLoader::GetForCurrentView() }
{
}
void EquationViewModel::OnPropertyChanged(String ^ propertyName)
{
if (propertyName == L"IsAnalysisUpdated")
{
OnIsAnalysisUpdatedChanged();
}
}
void EquationViewModel::OnIsAnalysisUpdatedChanged()
{
if (IsAnalysisUpdated)
{
if (AnalysisError != 0)
{
AnalysisErrorVisible = true;
if (AnalysisError == static_cast<int>(AnalysisErrorType::AnalysisCouldNotBePerformed))
{
AnalysisErrorString = m_resourceLoader->GetString(L"KGFAnalysisCouldNotBePerformed");
}
else if (AnalysisError == static_cast<int>(AnalysisErrorType::AnalysisNotSupported))
{
AnalysisErrorString = m_resourceLoader->GetString(L"KGFAnalysisNotSupported");
}
return;
}
KeyGraphFeaturesItems->Clear();
SetKeyGraphFeaturesItems(m_resourceLoader->GetString(L"Domain"), Domain, m_resourceLoader->GetString(L"KGFDomainNone"));
SetKeyGraphFeaturesItems(m_resourceLoader->GetString(L"Range"), Range, m_resourceLoader->GetString(L"KGFRangeNone"));
SetKeyGraphFeaturesItems(m_resourceLoader->GetString(L"XIntercept"), XIntercept, m_resourceLoader->GetString(L"KGFXInterceptNone"));
SetKeyGraphFeaturesItems(m_resourceLoader->GetString(L"YIntercept"), YIntercept, m_resourceLoader->GetString(L"KGFYInterceptNone"));
SetKeyGraphFeaturesItems(m_resourceLoader->GetString(L"Minima"), Minima, m_resourceLoader->GetString(L"KGFMinimaNone"));
SetKeyGraphFeaturesItems(m_resourceLoader->GetString(L"Maxima"), Maxima, m_resourceLoader->GetString(L"KGFMaximaNone"));
SetKeyGraphFeaturesItems(
m_resourceLoader->GetString(L"InflectionPoints"), InflectionPoints, m_resourceLoader->GetString(L"KGFInflectionPointsNone"));
SetKeyGraphFeaturesItems(
m_resourceLoader->GetString(L"VerticalAsymptotes"), VerticalAsymptotes, m_resourceLoader->GetString(L"KGFVerticalAsymptotesNone"));
SetKeyGraphFeaturesItems(
m_resourceLoader->GetString(L"HorizontalAsymptotes"), HorizontalAsymptotes, m_resourceLoader->GetString(L"KGFHorizontalAsymptotesNone"));
SetKeyGraphFeaturesItems(
m_resourceLoader->GetString(L"ObliqueAsymptotes"), ObliqueAsymptotes, m_resourceLoader->GetString(L"KGFObliqueAsymptotesNone"));
SetParityStringProperty();
SetPeriodicityStringProperty();
SetMonotoncityStringProperty();
SetTooComplexFeaturesErrorProperty();
AnalysisErrorVisible = false;
IsAnalysisUpdated = false;
}
}
void EquationViewModel::SetKeyGraphFeaturesItems(String ^ title, String ^ expression, String ^ errorString)
{
KeyGraphFeaturesItem ^ item = ref new KeyGraphFeaturesItem();
item->Title = title;
if (expression != L"")
{
item->DisplayItems->Append(expression);
item->IsText = false;
}
else
{
item->DisplayItems->Append(errorString);
item->IsText = true;
}
KeyGraphFeaturesItems->Append(item);
}
void EquationViewModel::SetKeyGraphFeaturesItems(String ^ title, IObservableVector<String ^> ^ expressionVector, String ^ errorString)
{
KeyGraphFeaturesItem ^ item = ref new KeyGraphFeaturesItem();
item->Title = title;
if (expressionVector->Size != 0)
{
for (auto expression : expressionVector)
{
item->DisplayItems->Append(expression);
}
item->IsText = false;
}
else
{
item->DisplayItems->Append(errorString);
item->IsText = true;
}
KeyGraphFeaturesItems->Append(item);
}
void EquationViewModel::SetParityStringProperty()
{
KeyGraphFeaturesItem ^ parityItem = ref new KeyGraphFeaturesItem();
parityItem->Title = m_resourceLoader->GetString(L"Parity");
switch (Parity)
{
case 0:
parityItem->DisplayItems->Append(m_resourceLoader->GetString(L"KGFParityUnknown"));
break;
case 1:
parityItem->DisplayItems->Append(m_resourceLoader->GetString(L"KGFParityOdd"));
break;
case 2:
parityItem->DisplayItems->Append(m_resourceLoader->GetString(L"KGFParityEven"));
break;
case 3:
parityItem->DisplayItems->Append(m_resourceLoader->GetString(L"KGFParityNeither"));
break;
default:
parityItem->DisplayItems->Append(m_resourceLoader->GetString(L"KGFParityUnknown"));
}
parityItem->IsText = true;
KeyGraphFeaturesItems->Append(parityItem);
}
void EquationViewModel::SetPeriodicityStringProperty()
{
KeyGraphFeaturesItem ^ periodicityItem = ref new KeyGraphFeaturesItem();
periodicityItem->Title = m_resourceLoader->GetString(L"Periodicity");
switch (PeriodicityDirection)
{
case 0:
// Periodicity is not supported or is too complex to calculate.
// Return out of this function without adding periodicity to KeyGraphFeatureItems.
// SetTooComplexFeaturesErrorProperty will set the too complex error when periodicity is supported and unknown
return;
case 1:
if (PeriodicityExpression == L"")
{
periodicityItem->DisplayItems->Append(m_resourceLoader->GetString(L"KGFPeriodicityUnknown"));
periodicityItem->IsText = true;
}
else
{
periodicityItem->DisplayItems->Append(PeriodicityExpression);
periodicityItem->IsText = false;
}
break;
case 2:
periodicityItem->DisplayItems->Append(m_resourceLoader->GetString(L"KGFPeriodicityNotPeriodic"));
periodicityItem->IsText = false;
break;
default:
periodicityItem->DisplayItems->Append(m_resourceLoader->GetString(L"KGFPeriodicityError"));
periodicityItem->IsText = true;
}
KeyGraphFeaturesItems->Append(periodicityItem);
}
void EquationViewModel::SetMonotoncityStringProperty()
{
KeyGraphFeaturesItem ^ monotonicityItem = ref new KeyGraphFeaturesItem();
monotonicityItem->Title = m_resourceLoader->GetString(L"Monotonicity");
if (Monotonicity->Size != 0)
{
for (auto item : Monotonicity)
{
GridDisplayItems ^ gridItem = ref new GridDisplayItems();
gridItem->Expression = item->Key;
auto monotonicityType = item->Value->Data();
switch (*monotonicityType)
{
case '0':
gridItem->Direction = m_resourceLoader->GetString(L"KGFMonotonicityUnknown");
break;
case '1':
gridItem->Direction = m_resourceLoader->GetString(L"KGFMonotonicityIncreasing");
break;
case '2':
gridItem->Direction = m_resourceLoader->GetString(L"KGFMonotonicityDecreasing");
break;
case '3':
gridItem->Direction = m_resourceLoader->GetString(L"KGFMonotonicityConstant");
break;
default:
gridItem->Direction = m_resourceLoader->GetString(L"KGFMonotonicityError");
break;
}
monotonicityItem->GridItems->Append(gridItem);
}
monotonicityItem->IsText = false;
}
else
{
monotonicityItem->DisplayItems->Append(m_resourceLoader->GetString(L"KGFMonotonicityError"));
monotonicityItem->IsText = true;
}
KeyGraphFeaturesItems->Append(monotonicityItem);
}
void EquationViewModel::SetTooComplexFeaturesErrorProperty()
{
if (TooComplexFeatures <= 0)
{
return;
}
Platform::String ^ separator = ref new String(LocalizationSettings::GetInstance().GetListSeparator().c_str());
wstring error;
if ((TooComplexFeatures & KeyGraphFeaturesFlag::Domain) == KeyGraphFeaturesFlag::Domain)
{
error.append((m_resourceLoader->GetString(L"Domain") + separator + L" ")->Data());
}
if ((TooComplexFeatures & KeyGraphFeaturesFlag::Range) == KeyGraphFeaturesFlag::Range)
{
error.append((m_resourceLoader->GetString(L"Range") + separator + L" ")->Data());
}
if ((TooComplexFeatures & KeyGraphFeaturesFlag::Zeros) == KeyGraphFeaturesFlag::Zeros)
{
error.append((m_resourceLoader->GetString(L"XIntercept") + separator + L" ")->Data());
}
if ((TooComplexFeatures & KeyGraphFeaturesFlag::YIntercept) == KeyGraphFeaturesFlag::YIntercept)
{
error.append((m_resourceLoader->GetString(L"YIntercept") + separator + L" ")->Data());
}
if ((TooComplexFeatures & KeyGraphFeaturesFlag::Parity) == KeyGraphFeaturesFlag::Parity)
{
error.append((m_resourceLoader->GetString(L"Parity") + separator + L" ")->Data());
}
if ((TooComplexFeatures & KeyGraphFeaturesFlag::Periodicity) == KeyGraphFeaturesFlag::Periodicity)
{
error.append((m_resourceLoader->GetString(L"Periodicity") + separator + L" ")->Data());
}
if ((TooComplexFeatures & KeyGraphFeaturesFlag::Minima) == KeyGraphFeaturesFlag::Minima)
{
error.append((m_resourceLoader->GetString(L"Minima") + separator + L" ")->Data());
}
if ((TooComplexFeatures & KeyGraphFeaturesFlag::Maxima) == KeyGraphFeaturesFlag::Maxima)
{
error.append((m_resourceLoader->GetString(L"Maxima") + separator + L" ")->Data());
}
if ((TooComplexFeatures & KeyGraphFeaturesFlag::InflectionPoints) == KeyGraphFeaturesFlag::InflectionPoints)
{
error.append((m_resourceLoader->GetString(L"InflectionPoints") + separator + L" ")->Data());
}
if ((TooComplexFeatures & KeyGraphFeaturesFlag::VerticalAsymptotes) == KeyGraphFeaturesFlag::VerticalAsymptotes)
{
error.append((m_resourceLoader->GetString(L"VerticalAsymptotes") + separator + L" ")->Data());
}
if ((TooComplexFeatures & KeyGraphFeaturesFlag::HorizontalAsymptotes) == KeyGraphFeaturesFlag::HorizontalAsymptotes)
{
error.append((m_resourceLoader->GetString(L"HorizontalAsymptotes") + separator + L" ")->Data());
}
if ((TooComplexFeatures & KeyGraphFeaturesFlag::ObliqueAsymptotes) == KeyGraphFeaturesFlag::ObliqueAsymptotes)
{
error.append((m_resourceLoader->GetString(L"ObliqueAsymptotes") + separator + L" ")->Data());
}
if ((TooComplexFeatures & KeyGraphFeaturesFlag::MonotoneIntervals) == KeyGraphFeaturesFlag::MonotoneIntervals)
{
error.append((m_resourceLoader->GetString(L"Monotonicity") + separator + L" ")->Data());
}
KeyGraphFeaturesItem ^ tooComplexItem = ref new KeyGraphFeaturesItem();
tooComplexItem->DisplayItems->Append(m_resourceLoader->GetString(L"KGFTooComplexFeaturesError"));
tooComplexItem->DisplayItems->Append(ref new String(error.substr(0, (error.length() - (separator->Length() + 1))).c_str()));
tooComplexItem->IsText = true;
KeyGraphFeaturesItems->Append(tooComplexItem);
}
}

View File

@ -1,17 +1,96 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#pragma once
#include "../Common/Utils.h"
namespace CalculatorApp::ViewModel
{
public ref class EquationViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
public
ref class GridDisplayItems sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
{
public:
GridDisplayItems();
OBSERVABLE_OBJECT();
OBSERVABLE_PROPERTY_RW(Platform::String ^, Expression);
OBSERVABLE_PROPERTY_RW(Platform::String ^, Direction);
};
public
ref class KeyGraphFeaturesItem sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
{
public:
KeyGraphFeaturesItem();
OBSERVABLE_OBJECT();
OBSERVABLE_PROPERTY_RW(Platform::String ^, Title);
OBSERVABLE_PROPERTY_RW(Windows::Foundation::Collections::IObservableVector<Platform::String ^> ^, DisplayItems);
OBSERVABLE_PROPERTY_RW(Windows::Foundation::Collections::IObservableVector<GridDisplayItems ^> ^, GridItems);
OBSERVABLE_PROPERTY_RW(bool, IsText);
};
public
ref class EquationViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
{
public:
EquationViewModel();
OBSERVABLE_OBJECT();
OBSERVABLE_PROPERTY_RW(Platform::String^, Expression);
OBSERVABLE_OBJECT_CALLBACK(OnPropertyChanged);
OBSERVABLE_PROPERTY_RW(Platform::String ^, Expression);
OBSERVABLE_PROPERTY_RW(Windows::UI::Xaml::Media::SolidColorBrush ^, LineColor);
OBSERVABLE_PROPERTY_RW(Windows::UI::Xaml::Visibility, KeyGraphFeaturesVisibility);
// Key Graph Features
OBSERVABLE_PROPERTY_RW_ALWAYS_NOTIFY(bool, IsAnalysisUpdated);
OBSERVABLE_PROPERTY_RW(Platform::String ^, Domain);
OBSERVABLE_PROPERTY_RW(Platform::String ^, Range);
OBSERVABLE_PROPERTY_RW(Platform::String ^, XIntercept);
OBSERVABLE_PROPERTY_RW(Platform::String ^, YIntercept);
OBSERVABLE_PROPERTY_RW(int, Parity);
OBSERVABLE_PROPERTY_RW(int, PeriodicityDirection);
OBSERVABLE_PROPERTY_RW(Platform::String ^, PeriodicityExpression);
OBSERVABLE_PROPERTY_RW(Windows::Foundation::Collections::IObservableVector<Platform::String ^> ^, Minima);
OBSERVABLE_PROPERTY_RW(Windows::Foundation::Collections::IObservableVector<Platform::String ^> ^, Maxima);
OBSERVABLE_PROPERTY_RW(Windows::Foundation::Collections::IObservableVector<Platform::String ^> ^, InflectionPoints);
OBSERVABLE_PROPERTY_RW(Windows::Foundation::Collections::IObservableVector<Platform::String ^> ^, VerticalAsymptotes);
OBSERVABLE_PROPERTY_RW(Windows::Foundation::Collections::IObservableVector<Platform::String ^> ^, HorizontalAsymptotes);
OBSERVABLE_PROPERTY_RW(Windows::Foundation::Collections::IObservableVector<Platform::String ^> ^, ObliqueAsymptotes);
OBSERVABLE_PROPERTY_RW(int, TooComplexFeatures);
OBSERVABLE_PROPERTY_RW(int, AnalysisError);
OBSERVABLE_PROPERTY_R(Platform::String ^, AnalysisErrorString);
OBSERVABLE_PROPERTY_R(bool, AnalysisErrorVisible);
OBSERVABLE_PROPERTY_R(Windows::Foundation::Collections::IObservableVector<CalculatorApp::ViewModel::KeyGraphFeaturesItem ^> ^, KeyGraphFeaturesItems)
property Windows::Foundation::Collections::IObservableMap<Platform::String ^, Platform::String^> ^ Monotonicity
{
Windows::Foundation::Collections::IObservableMap<Platform::String ^, Platform::String^> ^ get()
{
return m_Monotonicity;
}
void set(Windows::Foundation::Collections::IObservableMap<Platform::String ^, Platform::String^> ^ value)
{
if (m_Monotonicity != value)
{
m_Monotonicity = value;
}
}
}
private:
void OnPropertyChanged(Platform::String ^ propertyName);
void SetParityStringProperty();
void SetPeriodicityStringProperty();
void SetKeyGraphFeaturesItems(Platform::String ^ title, Platform::String ^ expression, Platform::String ^ errorString);
void SetKeyGraphFeaturesItems(Platform::String ^ title, Windows::Foundation::Collections::IObservableVector<Platform::String ^> ^ expressionVector,
Platform::String ^ errorString);
void SetMonotoncityStringProperty();
void SetTooComplexFeaturesErrorProperty();
void OnIsAnalysisUpdatedChanged();
Windows::Foundation::Collections::IObservableMap<Platform::String ^, Platform::String ^> ^ m_Monotonicity;
Windows::ApplicationModel::Resources::ResourceLoader ^ m_resourceLoader;
};
}

View File

@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#include "pch.h"
#include "GraphingCalculatorViewModel.h"

View File

@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#pragma once
#include "../Common/Utils.h"
@ -5,28 +8,29 @@
namespace CalculatorApp::ViewModel
{
public value struct VariableChangedEventArgs sealed
public
value struct VariableChangedEventArgs sealed
{
Platform::String^ variableName;
Platform::String ^ variableName;
double newValue;
};
[Windows::UI::Xaml::Data::Bindable]
public ref class VariableViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
[Windows::UI::Xaml::Data::Bindable] public ref class VariableViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
{
public:
VariableViewModel(Platform::String^ name, double value) :
m_Name(name),
m_Value(value),
m_SliderSettingsVisible(false),
m_Min(0.0),
m_Step(0.1),
m_Max(2.0)
{ }
VariableViewModel(Platform::String ^ name, double value)
: m_Name(name)
, m_Value(value)
, m_SliderSettingsVisible(false)
, m_Min(0.0)
, m_Step(0.1)
, m_Max(2.0)
{
}
OBSERVABLE_OBJECT_CALLBACK(OnPropertyChanged);
OBSERVABLE_PROPERTY_R(Platform::String^, Name);
OBSERVABLE_PROPERTY_R(Platform::String ^, Name);
// TODO: Consider removing this work around and manually set the textbox text.
OBSERVABLE_PROPERTY_RW_ALWAYS_NOTIFY(double, Value);
@ -35,7 +39,7 @@ namespace CalculatorApp::ViewModel
OBSERVABLE_PROPERTY_RW_ALWAYS_NOTIFY(double, Max);
OBSERVABLE_PROPERTY_RW(bool, SliderSettingsVisible);
event Windows::Foundation::EventHandler<VariableChangedEventArgs>^ VariableUpdated;
event Windows::Foundation::EventHandler<VariableChangedEventArgs> ^ VariableUpdated;
void SetValue(double value)
{
@ -52,7 +56,7 @@ namespace CalculatorApp::ViewModel
}
private:
void OnPropertyChanged(Platform::String^ propertyName)
void OnPropertyChanged(Platform::String ^ propertyName)
{
if (propertyName == "Value")
{
@ -61,23 +65,23 @@ namespace CalculatorApp::ViewModel
}
};
[Windows::UI::Xaml::Data::Bindable]
public ref class GraphingCalculatorViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
[Windows::UI::Xaml::Data::Bindable] public ref class GraphingCalculatorViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
{
public:
GraphingCalculatorViewModel();
OBSERVABLE_OBJECT();
OBSERVABLE_PROPERTY_R(bool, IsDecimalEnabled);
OBSERVABLE_PROPERTY_R(Windows::Foundation::Collections::IObservableVector< EquationViewModel^ >^, Equations);
OBSERVABLE_PROPERTY_R(Windows::Foundation::Collections::IObservableVector< VariableViewModel^ >^, Variables);
OBSERVABLE_PROPERTY_R(Windows::Foundation::Collections::IObservableVector<EquationViewModel ^> ^, Equations);
OBSERVABLE_PROPERTY_R(Windows::Foundation::Collections::IObservableVector<VariableViewModel ^> ^, Variables);
COMMAND_FOR_METHOD(ButtonPressed, GraphingCalculatorViewModel::OnButtonPressed);
event Windows::Foundation::EventHandler<VariableChangedEventArgs>^ VariableUpdated;
event Windows::Foundation::EventHandler<VariableChangedEventArgs> ^ VariableUpdated;
void UpdateVariables(Windows::Foundation::Collections::IMap<Platform::String ^, double> ^ variables);
void UpdateVariables(Windows::Foundation::Collections::IMap<Platform::String^, double>^ variables);
private:
void OnButtonPressed(Platform::Object^ parameter);
void OnButtonPressed(Platform::Object ^ parameter);
};
}

View File

@ -0,0 +1,28 @@
#pragma once
namespace CalculatorApp
{
enum KeyGraphFeaturesFlag
{
Domain = 1,
Range = 2,
Parity = 4,
Periodicity = 8,
Zeros = 16,
YIntercept = 32,
Minima = 64,
Maxima = 128,
InflectionPoints = 256,
VerticalAsymptotes = 512,
HorizontalAsymptotes = 1024,
ObliqueAsymptotes = 2048,
MonotoneIntervals = 4096
};
enum AnalysisErrorType
{
NoError,
AnalysisCouldNotBePerformed,
AnalysisNotSupported
};
}

View File

@ -1140,6 +1140,244 @@
</Setter>
</Style>
<Style x:Name="EquationTextBoxButtonStyle" TargetType="Button">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="Transparent"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid x:Name="ButtonLayoutGrid"
Background="Transparent"
BorderBrush="{ThemeResource TextControlButtonBorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ButtonLayoutGrid" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="Transparent"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ButtonLayoutGrid" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlButtonBorderBrushPointerOver}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="GlyphElement" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{Binding Foreground, RelativeSource={RelativeSource TemplatedParent}}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ButtonLayoutGrid" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{Binding Background, RelativeSource={RelativeSource TemplatedParent}}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ButtonLayoutGrid" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlButtonBorderBrushPressed}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="GlyphElement" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemChromeWhiteColor}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation Duration="0"
Storyboard.TargetName="ButtonLayoutGrid"
Storyboard.TargetProperty="Opacity"
To="0"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<TextBlock x:Name="GlyphElement"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Foreground="{ThemeResource EquationBoxHoverButtonForegroundBrush}"
FontFamily="{TemplateBinding FontFamily}"
FontSize="12"
FontStyle="Normal"
AutomationProperties.AccessibilityView="Raw"
Text="{TemplateBinding Content}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="MathRichEdit_EquationTextBoxStyle" TargetType="Controls:MathRichEditBox">
<Setter Property="Foreground" Value="{ThemeResource TextControlForeground}"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="ContentLinkForegroundColor" Value="{ThemeResource ContentLinkForegroundColor}"/>
<Setter Property="ContentLinkBackgroundColor" Value="{ThemeResource ContentLinkBackgroundColor}"/>
<Setter Property="SelectionHighlightColor" Value="{ThemeResource TextControlSelectionHighlightColor}"/>
<Setter Property="BorderBrush" Value="{ThemeResource TextControlBorderBrush}"/>
<Setter Property="BorderThickness" Value="{ThemeResource TextControlBorderThemeThickness}"/>
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}"/>
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}"/>
<Setter Property="ScrollViewer.HorizontalScrollMode" Value="Auto"/>
<Setter Property="ScrollViewer.VerticalScrollMode" Value="Auto"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Hidden"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Hidden"/>
<Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="False"/>
<Setter Property="Padding" Value="{ThemeResource TextControlThemePadding}"/>
<Setter Property="UseSystemFocusVisuals" Value="{ThemeResource IsApplicationFocusVisualKindReveal}"/>
<Setter Property="ContextFlyout" Value="{StaticResource TextControlCommandBarContextFlyout}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Controls:MathRichEditBox">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HeaderContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlHeaderForegroundDisabled}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBackgroundDisabled}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBorderBrushDisabled}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlForegroundDisabled}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderTextContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlPlaceholderForegroundDisabled}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Normal"/>
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBorderBrushPointerOver}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="Transparent"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderTextContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlPlaceholderForegroundPointerOver}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlForegroundPointerOver}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Focused">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderTextContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlPlaceholderForegroundFocused}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="Transparent"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBorderBrushFocused}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlForegroundFocused}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement" Storyboard.TargetProperty="RequestedTheme">
<DiscreteObjectKeyFrame KeyTime="0" Value="Light"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter x:Name="HeaderContentPresenter"
Grid.Row="0"
Grid.Column="0"
Grid.ColumnSpan="4"
Margin="{ThemeResource RichEditBoxTopHeaderMargin}"
VerticalAlignment="Top"
Foreground="{ThemeResource TextControlHeaderForeground}"
FontWeight="Normal"
x:DeferLoadStrategy="Lazy"
Content="{TemplateBinding Header}"
ContentTemplate="{TemplateBinding HeaderTemplate}"
TextWrapping="Wrap"
Visibility="Collapsed"/>
<Border x:Name="BorderElement"
Grid.Row="1"
Grid.RowSpan="1"
Grid.Column="0"
Grid.ColumnSpan="4"
MinWidth="{ThemeResource TextControlThemeMinWidth}"
MinHeight="{ThemeResource TextControlThemeMinHeight}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Control.IsTemplateFocusTarget="True"
CornerRadius="{TemplateBinding CornerRadius}"/>
<ScrollViewer x:Name="ContentElement"
Grid.Row="1"
Grid.Column="0"
Margin="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}"
VerticalAlignment="Center"
AutomationProperties.AccessibilityView="Raw"
HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}"
IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}"
IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}"
IsTabStop="False"
IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}"
VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"
VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}"
ZoomMode="Disabled"/>
<TextBlock x:Name="PlaceholderTextContentPresenter"
Grid.Row="1"
Grid.Column="0"
Grid.ColumnSpan="4"
Margin="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}"
VerticalAlignment="Center"
Foreground="{ThemeResource TextControlPlaceholderForeground}"
IsHitTestVisible="False"
Text="{TemplateBinding PlaceholderText}"
TextAlignment="{TemplateBinding TextAlignment}"
TextWrapping="{TemplateBinding TextWrapping}"/>
<ContentPresenter x:Name="DescriptionPresenter"
Grid.Row="2"
Grid.Column="0"
Grid.ColumnSpan="4"
Foreground="{ThemeResource SystemControlDescriptionTextForegroundBrush}"
x:Load="False"
AutomationProperties.AccessibilityView="Raw"
Content="{TemplateBinding Description}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="EquationTextBoxStyle" TargetType="Controls:EquationTextBox">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0,1,1,1"/>
@ -1154,246 +1392,6 @@
<Setter.Value>
<ControlTemplate TargetType="Controls:EquationTextBox">
<Grid>
<Grid.Resources>
<Style x:Name="EquationTextBoxButtonStyle" TargetType="Button">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="Transparent"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid x:Name="ButtonLayoutGrid"
Background="Transparent"
BorderBrush="{ThemeResource TextControlButtonBorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ButtonLayoutGrid" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="Transparent"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ButtonLayoutGrid" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlButtonBorderBrushPointerOver}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="GlyphElement" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{Binding Foreground, RelativeSource={RelativeSource TemplatedParent}}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ButtonLayoutGrid" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{Binding Background, RelativeSource={RelativeSource TemplatedParent}}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ButtonLayoutGrid" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlButtonBorderBrushPressed}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="GlyphElement" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemChromeWhiteColor}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation Duration="0"
Storyboard.TargetName="ButtonLayoutGrid"
Storyboard.TargetProperty="Opacity"
To="0"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<TextBlock x:Name="GlyphElement"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Foreground="{ThemeResource EquationBoxHoverButtonForegroundBrush}"
FontFamily="{TemplateBinding FontFamily}"
FontSize="12"
FontStyle="Normal"
AutomationProperties.AccessibilityView="Raw"
Text="{TemplateBinding Content}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="EquationTextBoxStyle" TargetType="RichEditBox">
<Setter Property="Foreground" Value="{ThemeResource TextControlForeground}"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="ContentLinkForegroundColor" Value="{ThemeResource ContentLinkForegroundColor}"/>
<Setter Property="ContentLinkBackgroundColor" Value="{ThemeResource ContentLinkBackgroundColor}"/>
<Setter Property="SelectionHighlightColor" Value="{ThemeResource TextControlSelectionHighlightColor}"/>
<Setter Property="BorderBrush" Value="{ThemeResource TextControlBorderBrush}"/>
<Setter Property="BorderThickness" Value="{ThemeResource TextControlBorderThemeThickness}"/>
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}"/>
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}"/>
<Setter Property="ScrollViewer.HorizontalScrollMode" Value="Auto"/>
<Setter Property="ScrollViewer.VerticalScrollMode" Value="Auto"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Hidden"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Hidden"/>
<Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="False"/>
<Setter Property="Padding" Value="{ThemeResource TextControlThemePadding}"/>
<Setter Property="UseSystemFocusVisuals" Value="{ThemeResource IsApplicationFocusVisualKindReveal}"/>
<Setter Property="ContextFlyout" Value="{StaticResource TextControlCommandBarContextFlyout}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="RichEditBox">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HeaderContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlHeaderForegroundDisabled}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBackgroundDisabled}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBorderBrushDisabled}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlForegroundDisabled}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderTextContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlPlaceholderForegroundDisabled}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Normal"/>
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBorderBrushPointerOver}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="Transparent"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderTextContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlPlaceholderForegroundPointerOver}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlForegroundPointerOver}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Focused">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderTextContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlPlaceholderForegroundFocused}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="Transparent"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBorderBrushFocused}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlForegroundFocused}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement" Storyboard.TargetProperty="RequestedTheme">
<DiscreteObjectKeyFrame KeyTime="0" Value="Light"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter x:Name="HeaderContentPresenter"
Grid.Row="0"
Grid.Column="0"
Grid.ColumnSpan="4"
Margin="{ThemeResource RichEditBoxTopHeaderMargin}"
VerticalAlignment="Top"
Foreground="{ThemeResource TextControlHeaderForeground}"
FontWeight="Normal"
x:DeferLoadStrategy="Lazy"
Content="{TemplateBinding Header}"
ContentTemplate="{TemplateBinding HeaderTemplate}"
TextWrapping="Wrap"
Visibility="Collapsed"/>
<Border x:Name="BorderElement"
Grid.Row="1"
Grid.RowSpan="1"
Grid.Column="0"
Grid.ColumnSpan="4"
MinWidth="{ThemeResource TextControlThemeMinWidth}"
MinHeight="{ThemeResource TextControlThemeMinHeight}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Control.IsTemplateFocusTarget="True"
CornerRadius="{TemplateBinding CornerRadius}"/>
<ScrollViewer x:Name="ContentElement"
Grid.Row="1"
Grid.Column="0"
Margin="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}"
VerticalAlignment="Center"
AutomationProperties.AccessibilityView="Raw"
HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}"
IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}"
IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}"
IsTabStop="False"
IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}"
VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"
VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}"
ZoomMode="Disabled"/>
<TextBlock x:Name="PlaceholderTextContentPresenter"
Grid.Row="1"
Grid.Column="0"
Grid.ColumnSpan="4"
Margin="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}"
VerticalAlignment="Center"
Foreground="{ThemeResource TextControlPlaceholderForeground}"
IsHitTestVisible="False"
Text="{TemplateBinding PlaceholderText}"
TextAlignment="{TemplateBinding TextAlignment}"
TextWrapping="{TemplateBinding TextWrapping}"/>
<ContentPresenter x:Name="DescriptionPresenter"
Grid.Row="2"
Grid.Column="0"
Grid.ColumnSpan="4"
Foreground="{ThemeResource SystemControlDescriptionTextForegroundBrush}"
x:Load="False"
AutomationProperties.AccessibilityView="Raw"
Content="{TemplateBinding Description}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
@ -1479,7 +1477,6 @@
<VisualStateGroup x:Name="ButtonStates">
<VisualState x:Name="ButtonVisible">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="DeleteButton" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0">
@ -1521,19 +1518,19 @@
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<RichEditBox x:Name="EquationTextBox"
MinHeight="44"
Padding="{TemplateBinding Padding}"
VerticalAlignment="Stretch"
Style="{StaticResource EquationTextBoxStyle}"
BorderThickness="0"
FontFamily="{TemplateBinding FontFamily}"
FontSize="{TemplateBinding FontSize}"
FontWeight="{TemplateBinding FontWeight}"
AcceptsReturn="false"
InputScope="Text"
MaxLength="2048"
TextWrapping="NoWrap"/>
<Controls:MathRichEditBox x:Name="EquationTextBox"
MinHeight="44"
Padding="{TemplateBinding Padding}"
VerticalAlignment="Stretch"
Style="{StaticResource MathRichEdit_EquationTextBoxStyle}"
BorderThickness="0"
FontFamily="{TemplateBinding FontFamily}"
FontSize="{TemplateBinding FontSize}"
FontWeight="{TemplateBinding FontWeight}"
AcceptsReturn="false"
InputScope="Text"
MaxLength="2048"
TextWrapping="NoWrap"/>
<!-- TODO: Use brush overrides here instead of a new style, use a new style for the EquationButton above once that has more functionality -->
<Button x:Name="DeleteButton"
Grid.Column="3"
@ -1606,13 +1603,6 @@
Visibility="Collapsed"/>
</Grid>
</Border>
<ContentPresenter x:Name="KeyGraphFeaturesContentPresenter"
Grid.Row="1"
Grid.Column="0"
Grid.ColumnSpan="2"
AutomationProperties.AccessibilityView="Raw"
Content="{TemplateBinding KeyGraphFeaturesContent}"/>
</Grid>
</ControlTemplate>
</Setter.Value>

View File

@ -8,8 +8,8 @@
<MinimumVisualStudioVersion>15.0</MinimumVisualStudioVersion>
<AppContainerApplication>true</AppContainerApplication>
<ApplicationType>Windows Store</ApplicationType>
<WindowsTargetPlatformVersion Condition="'$(WindowsTargetPlatformVersion)' == ''">10.0.18970.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformMinVersion>10.0.18362.0</WindowsTargetPlatformMinVersion>
<WindowsTargetPlatformVersion Condition="'$(WindowsTargetPlatformVersion)' == ''">10.0.19019.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformMinVersion>10.0.17134.0</WindowsTargetPlatformMinVersion>
<!-- We want to manually control the MinVersion/MaxVersionTested in the manifest so turn of the replacement. -->
<AppxOSMinVersionReplaceManifestVersion>false</AppxOSMinVersionReplaceManifestVersion>
<AppxOSMaxVersionTestedReplaceManifestVersion>false</AppxOSMaxVersionTestedReplaceManifestVersion>
@ -234,6 +234,7 @@
</ClInclude>
<ClInclude Include="Common\AppLifecycleLogger.h" />
<ClInclude Include="Controls\CalculationResultAutomationPeer.h" />
<ClInclude Include="Controls\MathRichEditBox.h" />
<ClInclude Include="Controls\OverflowTextBlockAutomationPeer.h" />
<ClInclude Include="Common\AlwaysSelectedCollectionView.h" />
<ClInclude Include="Common\BindableBase.h" />
@ -258,6 +259,7 @@
<ClInclude Include="EquationStylePanelControl.xaml.h">
<DependentUpon>EquationStylePanelControl.xaml</DependentUpon>
</ClInclude>
<ClInclude Include="TemplateSelectors\KeyGraphFeaturesTemplateSelector.h" />
<ClInclude Include="Views\Calculator.xaml.h">
<DependentUpon>Views\Calculator.xaml</DependentUpon>
</ClInclude>
@ -288,6 +290,9 @@
<ClInclude Include="Views\GraphingCalculator\GraphingCalculator.xaml.h">
<DependentUpon>Views\GraphingCalculator\GraphingCalculator.xaml</DependentUpon>
</ClInclude>
<ClInclude Include="Views\GraphingCalculator\KeyGraphFeaturesPanel.xaml.h">
<DependentUpon>Views\GraphingCalculator\KeyGraphFeaturesPanel.xaml</DependentUpon>
</ClInclude>
<ClInclude Include="Views\HistoryList.xaml.h">
<DependentUpon>Views\HistoryList.xaml</DependentUpon>
</ClInclude>
@ -348,6 +353,7 @@
<Page Include="Views\DelighterUnitStyles.xaml" />
<Page Include="Views\GraphingCalculator\EquationInputArea.xaml" />
<Page Include="Views\GraphingCalculator\GraphingCalculator.xaml" />
<Page Include="Views\GraphingCalculator\KeyGraphFeaturesPanel.xaml" />
<Page Include="Views\HistoryList.xaml" />
<Page Include="Views\MainPage.xaml" />
<Page Include="Views\Memory.xaml" />
@ -379,6 +385,7 @@
</ClCompile>
<ClCompile Include="Common\AppLifecycleLogger.cpp" />
<ClCompile Include="Controls\CalculationResultAutomationPeer.cpp" />
<ClCompile Include="Controls\MathRichEditBox.cpp" />
<ClCompile Include="Controls\OverflowTextBlockAutomationPeer.cpp" />
<ClCompile Include="Common\BindableBase.cpp" />
<ClCompile Include="Controls\CalculationResult.cpp" />
@ -408,6 +415,7 @@
<ClCompile Include="EquationStylePanelControl.xaml.cpp">
<DependentUpon>EquationStylePanelControl.xaml</DependentUpon>
</ClCompile>
<ClCompile Include="TemplateSelectors\KeyGraphFeaturesTemplateSelector.cpp" />
<ClCompile Include="Views\Calculator.xaml.cpp">
<DependentUpon>Views\Calculator.xaml</DependentUpon>
</ClCompile>
@ -438,6 +446,9 @@
<ClCompile Include="Views\GraphingCalculator\GraphingCalculator.xaml.cpp">
<DependentUpon>Views\GraphingCalculator\GraphingCalculator.xaml</DependentUpon>
</ClCompile>
<ClCompile Include="Views\GraphingCalculator\KeyGraphFeaturesPanel.xaml.cpp">
<DependentUpon>Views\GraphingCalculator\KeyGraphFeaturesPanel.xaml</DependentUpon>
</ClCompile>
<ClCompile Include="Views\HistoryList.xaml.cpp">
<DependentUpon>Views\HistoryList.xaml</DependentUpon>
</ClCompile>
@ -850,4 +861,4 @@
<Error Condition="!Exists('..\..\packages\Microsoft.WindowsCalculator.PGO.1.0.2\build\native\Microsoft.WindowsCalculator.PGO.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.WindowsCalculator.PGO.1.0.2\build\native\Microsoft.WindowsCalculator.PGO.targets'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.UI.Xaml.2.1.190405004.2\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.UI.Xaml.2.1.190405004.2\build\native\Microsoft.UI.Xaml.targets'))" />
</Target>
</Project>
</Project>

View File

@ -307,6 +307,9 @@
<ClCompile Include="Controls\EquationTextBox.cpp">
<Filter>Controls</Filter>
</ClCompile>
<ClCompile Include="Controls\MathRichEditBox.cpp" />
<ClCompile Include="Views\GraphingCalculator\KeyGraphFeaturesPanel.xaml.cpp" />
<ClCompile Include="TemplateSelectors\KeyGraphFeaturesTemplateSelector.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="pch.h" />
@ -393,6 +396,9 @@
<ClInclude Include="Controls\EquationTextBox.h">
<Filter>Controls</Filter>
</ClInclude>
<ClInclude Include="Controls\MathRichEditBox.h" />
<ClInclude Include="Views\GraphingCalculator\KeyGraphFeaturesPanel.xaml.h" />
<ClInclude Include="TemplateSelectors\KeyGraphFeaturesTemplateSelector.h" />
</ItemGroup>
<ItemGroup>
<AppxManifest Include="Package.appxmanifest" />
@ -470,6 +476,7 @@
<Page Include="EquationStylePanelControl.xaml">
<Filter>Views\GraphingCalculator</Filter>
</Page>
<Page Include="Views\GraphingCalculator\KeyGraphFeaturesPanel.xaml" />
</ItemGroup>
<ItemGroup>
<PRIResource Include="Resources\en-US\CEngineStrings.resw">

View File

@ -20,13 +20,12 @@ using namespace Windows::UI::Xaml::Input;
using namespace Windows::UI::Xaml::Controls::Primitives;
DEPENDENCY_PROPERTY_INITIALIZATION(EquationTextBox, EquationColor);
DEPENDENCY_PROPERTY_INITIALIZATION(EquationTextBox, KeyGraphFeaturesContent);
DEPENDENCY_PROPERTY_INITIALIZATION(EquationTextBox, ColorChooserFlyout);
void EquationTextBox::OnApplyTemplate()
{
m_equationButton = dynamic_cast<Button ^>(GetTemplateChild("EquationButton"));
m_richEditBox = dynamic_cast<RichEditBox ^>(GetTemplateChild("EquationTextBox"));
m_richEditBox = dynamic_cast<MathRichEditBox ^>(GetTemplateChild("EquationTextBox"));
m_deleteButton = dynamic_cast<Button ^>(GetTemplateChild("DeleteButton"));
m_removeButton = dynamic_cast<Button ^>(GetTemplateChild("RemoveButton"));
m_functionButton = dynamic_cast<Button ^>(GetTemplateChild("FunctionButton"));
@ -34,7 +33,6 @@ void EquationTextBox::OnApplyTemplate()
if (m_richEditBox != nullptr)
{
m_richEditBox->Loaded += ref new RoutedEventHandler(this, &EquationTextBox::OnRichEditBoxLoaded);
m_richEditBox->GotFocus += ref new RoutedEventHandler(this, &EquationTextBox::OnRichEditBoxGotFocus);
m_richEditBox->LostFocus += ref new RoutedEventHandler(this, &EquationTextBox::OnRichEditBoxLostFocus);
m_richEditBox->TextChanged += ref new RoutedEventHandler(this, &EquationTextBox::OnRichEditBoxTextChanged);
@ -64,6 +62,7 @@ void EquationTextBox::OnApplyTemplate()
if (m_functionButton != nullptr)
{
m_functionButton->Click += ref new RoutedEventHandler(this, &EquationTextBox::OnFunctionButtonClicked);
m_functionButton->IsEnabled = false;
}
if (ColorChooserFlyout != nullptr)
@ -104,6 +103,10 @@ void EquationTextBox::OnKeyDown(KeyRoutedEventArgs ^ e)
if (e->Key == VirtualKey::Enter)
{
EquationSubmitted(this, ref new RoutedEventArgs());
if (m_functionButton && m_richEditBox->MathText != L"")
{
m_functionButton->IsEnabled = true;
}
}
}
@ -112,6 +115,10 @@ void EquationTextBox::OnLostFocus(RoutedEventArgs ^ e)
if (!m_richEditBox->ContextFlyout->IsOpen)
{
EquationSubmitted(this, ref new RoutedEventArgs());
if (m_functionButton && m_richEditBox->MathText != L"")
{
m_functionButton->IsEnabled = true;
}
}
}
@ -128,15 +135,6 @@ void EquationTextBox::OnColorFlyoutClosed(Object ^ sender, Object ^ e)
UpdateCommonVisualState();
}
void EquationTextBox::OnRichEditBoxLoaded(Object ^ sender, RoutedEventArgs ^ e)
{
LimitedAccessFeatures::TryUnlockFeature(
"com.microsoft.windows.richeditmath",
"H6wflFFz3gkOsAHtG/D9Tg==",
"8wekyb3d8bbwe has registered their use of com.microsoft.windows.richeditmath with Microsoft and agrees to the terms of use.");
m_richEditBox->TextDocument->SetMathMode(::RichEditMathMode::MathOnly);
}
void EquationTextBox::OnRichEditBoxTextChanged(Object ^ sender, RoutedEventArgs ^ e)
{
UpdateDeleteButtonVisualState();
@ -163,17 +161,32 @@ void EquationTextBox::OnDeleteButtonClicked(Object ^ sender, RoutedEventArgs ^ e
{
if (m_richEditBox != nullptr)
{
m_richEditBox->TextDocument->SetMath(L"");
m_richEditBox->MathText = L"";
if (m_functionButton)
{
m_functionButton->IsEnabled = false;
}
}
}
void EquationTextBox::OnEquationButtonClicked(Object ^ sender, RoutedEventArgs ^ e)
{
EquationButtonClicked(this, ref new RoutedEventArgs());
}
void EquationTextBox::OnRemoveButtonClicked(Object ^ sender, RoutedEventArgs ^ e)
{
if (m_richEditBox != nullptr)
{
m_richEditBox->MathText = L"";
}
RemoveButtonClicked(this, ref new RoutedEventArgs());
if (m_functionButton)
{
m_functionButton->IsEnabled = false;
}
}
void EquationTextBox::OnColorChooserButtonClicked(Object ^ sender, RoutedEventArgs ^ e)
@ -186,10 +199,7 @@ void EquationTextBox::OnColorChooserButtonClicked(Object ^ sender, RoutedEventAr
void EquationTextBox::OnFunctionButtonClicked(Object ^ sender, RoutedEventArgs ^ e)
{
auto equationViewModel = static_cast<EquationViewModel ^>(DataContext);
equationViewModel->KeyGraphFeaturesVisibility =
(equationViewModel->KeyGraphFeaturesVisibility == ::Visibility::Collapsed) ? ::Visibility::Visible : ::Visibility::Collapsed;
UpdateCommonVisualState();
KeyGraphFeaturesButtonClicked(this, ref new RoutedEventArgs());
}
void EquationTextBox::UpdateDeleteButtonVisualState()
@ -239,7 +249,7 @@ Platform::String ^ EquationTextBox::GetEquationText()
range->CharacterFormat->Underline = UnderlineType::None;
}
m_richEditBox->TextDocument->GetMath(&text);
text = m_richEditBox->MathText;
}
return text;
@ -249,7 +259,7 @@ void EquationTextBox::SetEquationText(Platform::String ^ equationText)
{
if (m_richEditBox != nullptr)
{
m_richEditBox->TextDocument->SetMath(equationText);
m_richEditBox->MathText = equationText;
}
}
@ -259,7 +269,7 @@ bool EquationTextBox::ShouldDeleteButtonBeVisible()
if (m_richEditBox != nullptr)
{
m_richEditBox->TextDocument->GetMath(&text);
text = m_richEditBox->MathText;
}
return (!text->IsEmpty() && m_isFocused);
}

View File

@ -5,6 +5,7 @@
#include "CalcViewModel/Common/Utils.h"
#include "CalcViewModel/GraphingCalculator/EquationViewModel.h"
#include "Calculator/Controls/MathRichEditBox.h"
namespace CalculatorApp
{
@ -19,11 +20,12 @@ namespace CalculatorApp
DEPENDENCY_PROPERTY_OWNER(EquationTextBox);
DEPENDENCY_PROPERTY(Windows::UI::Xaml::Media::SolidColorBrush^, EquationColor);
DEPENDENCY_PROPERTY(Windows::UI::Xaml::UIElement^, KeyGraphFeaturesContent);
DEPENDENCY_PROPERTY(Windows::UI::Xaml::Controls::Flyout^, ColorChooserFlyout);
event Windows::UI::Xaml::RoutedEventHandler ^ RemoveButtonClicked;
event Windows::UI::Xaml::RoutedEventHandler ^ KeyGraphFeaturesButtonClicked;
event Windows::UI::Xaml::RoutedEventHandler ^ EquationSubmitted;
event Windows::UI::Xaml::RoutedEventHandler ^ EquationButtonClicked;
Platform::String^ GetEquationText();
void SetEquationText(Platform::String^ equationText);
@ -42,10 +44,8 @@ namespace CalculatorApp
void UpdateDeleteButtonVisualState();
bool ShouldDeleteButtonBeVisible();
void OnRichEditBoxLoaded(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
void OnRichEditBoxGotFocus(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
void OnRichEditBoxLostFocus(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
void OnRichEditBoxLosingFocus(Windows::UI::Xaml::UIElement ^ sender, Windows::UI::Xaml::Input::LosingFocusEventArgs ^ e);
void OnRichEditBoxTextChanged(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
void OnDeleteButtonClicked(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
@ -57,7 +57,7 @@ namespace CalculatorApp
void OnColorFlyoutOpened(Platform::Object^ sender, Platform::Object^ e);
void OnColorFlyoutClosed(Platform::Object^ sender, Platform::Object^ e);
Windows::UI::Xaml::Controls::RichEditBox^ m_richEditBox;
CalculatorApp::Controls::MathRichEditBox^ m_richEditBox;
Windows::UI::Xaml::Controls::Button^ m_equationButton;
Windows::UI::Xaml::Controls::Button^ m_deleteButton;
Windows::UI::Xaml::Controls::Button^ m_removeButton;

View File

@ -0,0 +1,66 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#include "pch.h"
#include "MathRichEditBox.h"
using namespace Platform;
using namespace CalculatorApp;
using namespace CalculatorApp::Common;
using namespace CalculatorApp::Controls;
using namespace std;
using namespace Windows::ApplicationModel;
using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Controls;
using namespace Windows::Foundation::Collections;
DEPENDENCY_PROPERTY_INITIALIZATION(MathRichEditBox, MathText);
MathRichEditBox::MathRichEditBox()
{
static LimitedAccessFeatureStatus m_lafResultStatus;
String ^ packageName = Package::Current->Id->Name;
if (packageName == L"Microsoft.WindowsCalculator.Dev")
{
m_lafResultStatus = LimitedAccessFeatures::TryUnlockFeature(
"com.microsoft.windows.richeditmath",
"BeDD/jxKhz/yfVNA11t4uA==", // Microsoft.WindowsCalculator.Dev
"8wekyb3d8bbwe has registered their use of com.microsoft.windows.richeditmath with Microsoft and agrees to the terms of use.")->Status;
}
else if (packageName == L"Microsoft.WindowsCalculator")
{
m_lafResultStatus = LimitedAccessFeatures::TryUnlockFeature(
"com.microsoft.windows.richeditmath",
"pfanNuxnzo+mAkBQ3N/rGQ==", // Microsoft.WindowsCalculator
"8wekyb3d8bbwe has registered their use of com.microsoft.windows.richeditmath with Microsoft and agrees to the terms of use.")->Status;
}
else if (packageName == L"Microsoft.WindowsCalculator.Graphing")
{
m_lafResultStatus = LimitedAccessFeatures::TryUnlockFeature(
"com.microsoft.windows.richeditmath",
"H6wflFFz3gkOsAHtG/D9Tg==", // Microsoft.WindowsCalculator.Graphing
"8wekyb3d8bbwe has registered their use of com.microsoft.windows.richeditmath with Microsoft and agrees to the terms of use.")->Status;
}
TextDocument->SetMathMode(Windows::UI::Text::RichEditMathMode::MathOnly);
}
String ^ MathRichEditBox::GetMathTextProperty()
{
String ^ text;
this->TextDocument->GetMath(&text);
return text;
}
void MathRichEditBox::SetMathTextProperty(String ^ newValue)
{
bool readOnlyState = this->IsReadOnly;
this->IsReadOnly = false;
TextDocument->SetMath(newValue);
this->IsReadOnly = readOnlyState;
}

View File

@ -0,0 +1,49 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#pragma once
#include "CalcViewModel/Common/Utils.h"
namespace CalculatorApp
{
namespace Controls
{
public
ref class MathRichEditBox sealed : Windows::UI::Xaml::Controls::RichEditBox
{
public:
MathRichEditBox();
DEPENDENCY_PROPERTY_OWNER(MathRichEditBox);
static property Windows::UI::Xaml::DependencyProperty ^ MathTextProperty
{
Windows::UI::Xaml::DependencyProperty ^ get() {
return s_MathTextProperty;
}
}
property Platform::String ^ MathText
{
Platform::String ^ get()
{
return GetMathTextProperty();
}
void set(Platform::String^ value)
{
SetMathTextProperty(value);
}
}
private :
Platform::String ^ GetMathTextProperty();
void SetMathTextProperty(Platform::String ^ newValue);
static Windows::UI::Xaml::DependencyProperty ^ s_MathTextProperty;
static Windows::UI::Xaml::DependencyProperty ^ InitializeMathTextProperty()
{
return Utils::RegisterDependencyProperty<DependencyPropertiesOwner, Platform::String ^>(L"MathText");
}
};
}
}

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" xmlns:uap5="http://schemas.microsoft.com/appx/manifest/uap/windows10/5" IgnorableNamespaces="uap uap5 mp">
<Identity Name="Microsoft.WindowsCalculator.Graphing" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" Version="0.0.0.0" />
<Identity Name="Microsoft.WindowsCalculator.Graphing" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" Version="0.0.1.0" />
<mp:PhoneIdentity PhoneProductId="b58171c6-c70c-4266-a2e8-8f9c994f4456" PhonePublisherId="95d94207-0c7c-47ed-82db-d75c81153c35" />
<Properties>
<DisplayName>ms-resource:DevAppStoreName</DisplayName>

View File

@ -549,11 +549,11 @@
<value>%1, value %2</value>
<comment>{Locked="%1","%2"}. String used in automation name for each bit in bit flip. %1 will be replaced by the position of the bit (1st bit, 3rd bit), %2 by a binary value (1 or 0)</comment>
</data>
<data name="BitPosition" xml:space="preserve">
<data name="BitPosition" xml:space="preserve">
<value>%1 bit</value>
<comment>{Locked="%1"}. Sub-string used to indicate the position of a bit (e.g. 1st bit, 2nd bit...)</comment>
</data>
<data name="63" xml:space="preserve">
<data name="63" xml:space="preserve">
<value>63rd</value>
<comment>Sub-string used in automation name for 63 bit in bit flip</comment>
</data>
@ -3531,4 +3531,163 @@
<value>Line Color</value>
<comment>Label for the Line Color section of the style picker</comment>
</data>
<data name="KeyGraphFeaturesLabel.Text" xml:space="preserve">
<value>Key Graph Features</value>
<comment>Title for KeyGraphFeatures Control</comment>
</data>
<data name="KGFHorizontalAsymptotesNone" xml:space="preserve">
<value>The function does not have any horizontal asymptotes.</value>
<comment>Message displayed when the graph does not have any horizontal asymptotes</comment>
</data>
<data name="KGFInflectionPointsNone" xml:space="preserve">
<value>The function does not have any inflection points.</value>
<comment>Message displayed when the graph does not have any inflection points</comment>
</data>
<data name="KGFMaximaNone" xml:space="preserve">
<value>The function does not have any maxima points.</value>
<comment>Message displayed when the graph does not have any maxima</comment>
</data>
<data name="KGFMinimaNone" xml:space="preserve">
<value>The function does not have any minima points.</value>
<comment>Message displayed when the graph does not have any minima</comment>
</data>
<data name="KGFMonotonicityConstant" xml:space="preserve">
<value>Constant</value>
<comment>String describing constant monotonicity of a function</comment>
</data>
<data name="KGFMonotonicityDecreasing" xml:space="preserve">
<value>Decreasing</value>
<comment>String describing decreasing monotonicity of a function</comment>
</data>
<data name="KGFMonotonicityError" xml:space="preserve">
<value>Unable to determine the monotonicity of the function.</value>
<comment>Error displayed when monotonicity cannot be determined</comment>
</data>
<data name="KGFMonotonicityIncreasing" xml:space="preserve">
<value>Increasing</value>
<comment>String describing increasing monotonicity of a function</comment>
</data>
<data name="KGFMonotonicityUnknown" xml:space="preserve">
<value>The monotonicity of the function is unknown.</value>
<comment>Error displayed when monotonicity is unknown</comment>
</data>
<data name="KGFObliqueAsymptotesNone" xml:space="preserve">
<value>The function does not have any oblique aysmptotes.</value>
<comment>Message displayed when the graph does not have any oblique asymptotes</comment>
</data>
<data name="KGFParityError" xml:space="preserve">
<value>Unable to determine the parity of the function.</value>
<comment>Error displayed when parity is cannot be determined</comment>
</data>
<data name="KGFParityEven" xml:space="preserve">
<value>The function is even.</value>
<comment>Message displayed with the function parity is even</comment>
</data>
<data name="KGFParityNeither" xml:space="preserve">
<value>The function is neither even nor odd.</value>
<comment>Message displayed with the function parity is neither even nor odd</comment>
</data>
<data name="KGFParityOdd" xml:space="preserve">
<value>The function is odd.</value>
<comment>Message displayed with the function parity is odd</comment>
</data>
<data name="KGFParityUnknown" xml:space="preserve">
<value>The function parity is unknown.</value>
<comment>Error displayed when parity is unknown</comment>
</data>
<data name="KGFPeriodicityError" xml:space="preserve">
<value>Periodicity is not supported for this function.</value>
<comment>Error displayed when periodicity is not supported</comment>
</data>
<data name="KGFPeriodicityNotPeriodic" xml:space="preserve">
<value>The function is not periodic.</value>
<comment>Message displayed with the function periodicity is not periodic</comment>
</data>
<data name="KGFPeriodicityUnknown" xml:space="preserve">
<value>The function periodicity is unknown.</value>
<comment>Message displayed with the function periodicity is unknown</comment>
</data>
<data name="KGFTooComplexFeaturesError" xml:space="preserve">
<value>These features are too complex for Calculator to calculate:</value>
<comment>Error displayed when analysis features cannot be calculated</comment>
</data>
<data name="KGFVerticalAsymptotesNone" xml:space="preserve">
<value>The function does not have any vertical asymptotes.</value>
<comment>Message displayed when the graph does not have any vertical asymptotes</comment>
</data>
<data name="KGFXInterceptNone" xml:space="preserve">
<value>The function does not have any x-intercepts.</value>
<comment>Message displayed when the graph does not have any x-intercepts</comment>
</data>
<data name="KGFYInterceptNone" xml:space="preserve">
<value>The function does not have any y-intercepts.</value>
<comment>Message displayed when the graph does not have any y-intercepts</comment>
</data>
<data name="Domain" xml:space="preserve">
<value>Domain</value>
<comment>Title for KeyGraphFeatures Domain Property</comment>
</data>
<data name="HorizontalAsymptotes" xml:space="preserve">
<value>Horizontal Asymptotes</value>
<comment>Title for KeyGraphFeatures Horizontal Aysmptotes Property</comment>
</data>
<data name="InflectionPoints" xml:space="preserve">
<value>Inflection Points</value>
<comment>Title for KeyGraphFeatures Inflection Points Property</comment>
</data>
<data name="KGFAnalysisNotSupported" xml:space="preserve">
<value>Analysis is not supported for this function.</value>
<comment>Error displayed when graph analysis is not supported or had an error.</comment>
</data>
<data name="Maxima" xml:space="preserve">
<value>Maxima</value>
<comment>Title for KeyGraphFeatures Maxima Property</comment>
</data>
<data name="Minima" xml:space="preserve">
<value>Minima</value>
<comment>Title for KeyGraphFeatures Minima Property</comment>
</data>
<data name="Monotonicity" xml:space="preserve">
<value>Monotonicity</value>
<comment>Title for KeyGraphFeatures Monotonicity Property</comment>
</data>
<data name="ObliqueAsymptotes" xml:space="preserve">
<value>Oblique Asymptotes</value>
<comment>Title for KeyGraphFeatures Oblique Asymptotes Property</comment>
</data>
<data name="Parity" xml:space="preserve">
<value>Parity</value>
<comment>Title for KeyGraphFeatures Parity Property</comment>
</data>
<data name="Periodicity" xml:space="preserve">
<value>Period</value>
<comment>Title for KeyGraphFeatures Periodicity Property</comment>
</data>
<data name="Range" xml:space="preserve">
<value>Range</value>
<comment>Title for KeyGraphFeatures Range Property</comment>
</data>
<data name="VerticalAsymptotes" xml:space="preserve">
<value>Vertical Asymptotes</value>
<comment>Title for KeyGraphFeatures Vertical Asymptotes Property</comment>
</data>
<data name="XIntercept" xml:space="preserve">
<value>X Intercept</value>
<comment>Title for KeyGraphFeatures XIntercept Property</comment>
</data>
<data name="YIntercept" xml:space="preserve">
<value>Y Intercept</value>
<comment>Title for KeyGraphFeatures YIntercept Property</comment>
</data>
<data name="KGFAnalysisCouldNotBePerformed" xml:space="preserve">
<value>Analysis could not be performed for the function.</value>
</data>
<data name="KGFDomainNone" xml:space="preserve">
<value>Unable to calculate the domain for this function.</value>
<comment>Error displayed when Domain is not returned from the analyzer.</comment>
</data>
<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>
</root>

View File

@ -0,0 +1,36 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#include "pch.h"
#include "KeyGraphFeaturesTemplateSelector.h"
#include "CalcViewModel/GraphingCalculator/EquationViewModel.h"
using namespace CalculatorApp::ViewModel;
using namespace CalculatorApp::TemplateSelectors;
using namespace Platform;
using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Controls;
DataTemplate ^ KeyGraphFeaturesTemplateSelector::SelectTemplateCore(Object ^ item)
{
auto kgfItem = static_cast<KeyGraphFeaturesItem ^>(item);
if (!kgfItem->IsText)
{
if (kgfItem->DisplayItems->Size != 0)
{
return RichEditTemplate;
}
else if (kgfItem->GridItems->Size != 0)
{
return GridTemplate;
}
}
return TextBlockTemplate;
}
DataTemplate ^ KeyGraphFeaturesTemplateSelector::SelectTemplateCore(Object ^ item, DependencyObject ^ container)
{
return SelectTemplateCore(item);
}

View File

@ -0,0 +1,25 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#pragma once
namespace CalculatorApp
{
namespace TemplateSelectors
{
public
ref class KeyGraphFeaturesTemplateSelector sealed : Windows::UI::Xaml::Controls::DataTemplateSelector
{
public:
KeyGraphFeaturesTemplateSelector()
{
}
property Windows::UI::Xaml::DataTemplate ^ RichEditTemplate;
property Windows::UI::Xaml::DataTemplate ^ GridTemplate;
property Windows::UI::Xaml::DataTemplate ^ TextBlockTemplate;
Windows::UI::Xaml::DataTemplate ^ SelectTemplateCore(Platform::Object ^ item) override;
Windows::UI::Xaml::DataTemplate ^ SelectTemplateCore(Platform::Object ^ item, Windows::UI::Xaml::DependencyObject ^ container) override;
};
}
}

View File

@ -111,26 +111,42 @@
<SolidColorBrush x:Key="ButtonBackgroundPressed" Color="Transparent"/>
<SolidColorBrush x:Key="ButtonBackgroundDisabled" Color="Transparent"/>
<SolidColorBrush x:Key="ButtonForeground" Color="#99000000"/>
<SolidColorBrush x:Key="ButtonForegroundPointerOver" Color="{ThemeResource SystemAccentColor}" Opacity="0.8"/>
<SolidColorBrush x:Key="ButtonForegroundPressed" Color="{ThemeResource SystemAccentColor}" Opacity="1.0"/>
<SolidColorBrush x:Key="ButtonForegroundPointerOver"
Opacity="0.8"
Color="{ThemeResource SystemAccentColor}"/>
<SolidColorBrush x:Key="ButtonForegroundPressed"
Opacity="1.0"
Color="{ThemeResource SystemAccentColor}"/>
<SolidColorBrush x:Key="ButtonForegroundDisabled" Color="#33000000"/>
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast">
<SolidColorBrush x:Key="ButtonBackgroundPointerOver" Color="Transparent"/>
<SolidColorBrush x:Key="ButtonBackgroundPressed" Color="Transparent"/>
<SolidColorBrush x:Key="ButtonBackgroundDisabled" Color="Transparent"/>
<SolidColorBrush x:Key="ButtonForeground" Color="{ThemeResource SystemColorWindowTextColor}" Opacity="0.6"/>
<SolidColorBrush x:Key="ButtonForegroundPointerOver" Color="{ThemeResource SystemColorHighlightColor}" Opacity="0.8"/>
<SolidColorBrush x:Key="ButtonForegroundPressed" Color="{ThemeResource SystemColorHighlightColor}" Opacity="1.0"/>
<SolidColorBrush x:Key="ButtonForegroundDisabled" Color="{ThemeResource SystemColorGrayTextColor}" Opacity="0.2"/>
<SolidColorBrush x:Key="ButtonForeground"
Opacity="0.6"
Color="{ThemeResource SystemColorWindowTextColor}"/>
<SolidColorBrush x:Key="ButtonForegroundPointerOver"
Opacity="0.8"
Color="{ThemeResource SystemColorHighlightColor}"/>
<SolidColorBrush x:Key="ButtonForegroundPressed"
Opacity="1.0"
Color="{ThemeResource SystemColorHighlightColor}"/>
<SolidColorBrush x:Key="ButtonForegroundDisabled"
Opacity="0.2"
Color="{ThemeResource SystemColorGrayTextColor}"/>
</ResourceDictionary>
<ResourceDictionary x:Key="Dark">
<SolidColorBrush x:Key="ButtonBackgroundPointerOver" Color="Transparent"/>
<SolidColorBrush x:Key="ButtonBackgroundPressed" Color="Transparent"/>
<SolidColorBrush x:Key="ButtonBackgroundDisabled" Color="Transparent"/>
<SolidColorBrush x:Key="ButtonForeground" Color="#99FFFFFF"/>
<SolidColorBrush x:Key="ButtonForegroundPointerOver" Color="{ThemeResource SystemAccentColorLight1}" Opacity="0.8"/>
<SolidColorBrush x:Key="ButtonForegroundPressed" Color="{ThemeResource SystemAccentColorLight1}" Opacity="1.0"/>
<SolidColorBrush x:Key="ButtonForegroundPointerOver"
Opacity="0.8"
Color="{ThemeResource SystemAccentColorLight1}"/>
<SolidColorBrush x:Key="ButtonForegroundPressed"
Opacity="1.0"
Color="{ThemeResource SystemAccentColorLight1}"/>
<SolidColorBrush x:Key="ButtonForegroundDisabled" Color="#33FFFFFF"/>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
@ -149,41 +165,39 @@
Style="{StaticResource ResultsScrollerSnapped}"
AutomationProperties.AccessibilityView="Control">
<TextBlock x:Name="EditableToken"
AutomationProperties.AccessibilityView="Raw"
Text="{Binding DisplayValue, Mode=OneWay}"
Grid.Row="2"
Margin="4,0,4,0"
Padding="0"
HorizontalAlignment="Right"
VerticalAlignment="Stretch"
FontWeight="SemiBold"
Grid.Row="2"
HorizontalAlignment="Right"/>
AutomationProperties.AccessibilityView="Raw"
Text="{Binding DisplayValue, Mode=OneWay}"/>
</ScrollViewer>
<Border Background="{ThemeResource AppChromeAcrylicHostBackdropMediumLowBrush}"
Grid.Column="0">
<Border Grid.Column="0" Background="{ThemeResource AppChromeAcrylicHostBackdropMediumLowBrush}">
<Button x:Name="ScrollLeft"
x:Uid="scrollLeft"
Margin="0,3,0,0"
Style="{StaticResource AlwaysOnTopScrollButtonStyleS}"
MinWidth="{TemplateBinding ColumnWidth}"
MinHeight="{TemplateBinding ColumnHeight}"
Background="Transparent">
x:Uid="scrollLeft"
MinWidth="{TemplateBinding ColumnWidth}"
MinHeight="{TemplateBinding ColumnHeight}"
Margin="0,3,0,0"
Style="{StaticResource AlwaysOnTopScrollButtonStyleS}"
Background="Transparent">
<FontIcon FontFamily="{ThemeResource SymbolThemeFontFamily}"
FontSize="{TemplateBinding ScrollButtonFontSize}"
Glyph="&#xE26C;"/>
FontSize="{TemplateBinding ScrollButtonFontSize}"
Glyph="&#xE26C;"/>
</Button>
</Border>
<Border Background="{ThemeResource AppChromeAcrylicHostBackdropMediumLowBrush}"
Grid.Column="2">
<Border Grid.Column="2" Background="{ThemeResource AppChromeAcrylicHostBackdropMediumLowBrush}">
<Button x:Name="ScrollRight"
x:Uid="scrollRight"
Margin="0,3,0,0"
Style="{StaticResource AlwaysOnTopScrollButtonStyleS}"
MinWidth="{TemplateBinding ColumnWidth}"
MinHeight="{TemplateBinding ColumnHeight}"
Background="Transparent">
x:Uid="scrollRight"
MinWidth="{TemplateBinding ColumnWidth}"
MinHeight="{TemplateBinding ColumnHeight}"
Margin="0,3,0,0"
Style="{StaticResource AlwaysOnTopScrollButtonStyleS}"
Background="Transparent">
<FontIcon FontFamily="{ThemeResource SymbolThemeFontFamily}"
FontSize="{TemplateBinding ScrollButtonFontSize}"
Glyph="&#xE26B;"/>
FontSize="{TemplateBinding ScrollButtonFontSize}"
Glyph="&#xE26B;"/>
</Button>
</Border>
</Grid>
@ -192,7 +206,9 @@
</Setter>
</Style>
<Style x:Key="AlwaysOnTopStyleM" BasedOn="{StaticResource AlwaysOnTopStyleS}" TargetType="controls:OverflowTextBlock">
<Style x:Key="AlwaysOnTopStyleM"
BasedOn="{StaticResource AlwaysOnTopStyleS}"
TargetType="controls:OverflowTextBlock">
<Setter Property="ColumnWidth" Value="28"/>
<Setter Property="ColumnHeight" Value="280"/>
<Setter Property="ScrollButtonFontSize" Value="28"/>
@ -223,7 +239,7 @@
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Visibility" Value="Collapsed"/>
</Style>
<Style x:Key="AlwaysOnTopScrollButtonStyleS" TargetType="Button">
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Padding" Value="0,0,0,0"/>
@ -592,8 +608,8 @@
<controls:OverflowTextBlock x:Name="ExpressionText"
Grid.Row="1"
Margin="6,0,6,0"
Style="{StaticResource NormalStyle}"
VerticalAlignment="Bottom"
Style="{StaticResource NormalStyle}"
AutomationProperties.AutomationId="CalculatorExpression"
AutomationProperties.Name="{x:Bind Model.CalculationExpressionAutomationName, Mode=OneWay}"
IsTabStop="False"
@ -620,12 +636,12 @@
x:Uid="CalculatorAlwaysOnTopResults"
Grid.Row="2"
Margin="6,0,6,0"
HorizontalContentAlignment="Right"
AutomationProperties.AutomationId="CalculatorAlwaysOnTopResults"
AutomationProperties.HeadingLevel="Level1"
AutomationProperties.Name="{x:Bind Model.CalculationResultAutomationName, Mode=OneWay}"
TokensUpdated="{x:Bind Model.AreAlwaysOnTopResultsUpdated, Mode=OneWay}"
HorizontalContentAlignment="Right"
IsActive="True"
TokensUpdated="{x:Bind Model.AreAlwaysOnTopResultsUpdated, Mode=OneWay}"
UseSystemFocusVisuals="True"
Visibility="{x:Bind Model.IsAlwaysOnTop, Mode=OneWay}"/>
@ -644,18 +660,17 @@
TabIndex="7"
Visibility="{x:Bind Model.IsProgrammer, Mode=OneWay}"/>
<Grid x:Name="HistoryButtonParent"
Visibility="{x:Bind Model.IsAlwaysOnTop, Converter={StaticResource BooleanToVisibilityNegationConverter}, Mode=OneWay}">
<Grid x:Name="HistoryButtonParent" Visibility="{x:Bind Model.IsAlwaysOnTop, Converter={StaticResource BooleanToVisibilityNegationConverter}, Mode=OneWay}">
<Button x:Name="HistoryButton"
x:Uid="HistoryButton"
Grid.Row="0"
IsEnabled="{x:Bind Model.IsAlwaysOnTop, Converter={StaticResource BooleanNegationConverter}, Mode=OneWay}"
Style="{StaticResource HistoryButtonStyle}"
AutomationProperties.AutomationId="HistoryButton"
Command="{x:Bind HistoryButtonPressed, Mode=OneTime}"
Content="&#xe81c;"
ExitDisplayModeOnAccessKeyInvoked="False"
TabIndex="2">
x:Uid="HistoryButton"
Grid.Row="0"
Style="{StaticResource HistoryButtonStyle}"
AutomationProperties.AutomationId="HistoryButton"
Command="{x:Bind HistoryButtonPressed, Mode=OneTime}"
Content="&#xe81c;"
ExitDisplayModeOnAccessKeyInvoked="False"
IsEnabled="{x:Bind Model.IsAlwaysOnTop, Converter={StaticResource BooleanNegationConverter}, Mode=OneWay}"
TabIndex="2">
<FlyoutBase.AttachedFlyout>
<Flyout x:Name="HistoryFlyout"
AutomationProperties.AutomationId="HistoryFlyout"
@ -666,7 +681,7 @@
</FlyoutBase.AttachedFlyout>
</Button>
</Grid>
<!-- Scientific angle buttons -->
<local:CalculatorScientificAngleButtons x:Name="ScientificAngleButtons"
Grid.Row="3"
@ -680,8 +695,8 @@
x:Uid="MemoryPanel"
Grid.Row="4"
Margin="3,0,3,0"
Visibility="{x:Bind Model.IsAlwaysOnTop, Converter={StaticResource BooleanToVisibilityNegationConverter}, Mode=OneWay}"
AutomationProperties.HeadingLevel="Level1">
AutomationProperties.HeadingLevel="Level1"
Visibility="{x:Bind Model.IsAlwaysOnTop, Converter={StaticResource BooleanToVisibilityNegationConverter}, Mode=OneWay}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" MaxWidth="80"/>
<ColumnDefinition Width="1*" MaxWidth="80"/>

View File

@ -12,13 +12,16 @@
#include "Controls/CalculationResult.h"
#include "Controls/OverflowTextBlock.h"
#include "Controls/EquationTextBox.h"
#include "Controls/MathRichEditBox.h"
#include "CalcViewModel/HistoryViewModel.h"
#include "TemplateSelectors/KeyGraphFeaturesTemplateSelector.h"
#include "Views/CalculatorProgrammerDisplayPanel.xaml.h"
#include "Views/CalculatorProgrammerOperators.xaml.h"
#include "Views/CalculatorScientificAngleButtons.xaml.h"
#include "Views/HistoryList.xaml.h"
#include "Views/Memory.xaml.h"
#include "Views/OperatorsPanel.xaml.h"
#include "Views/GraphingCalculator/KeyGraphFeaturesPanel.xaml.h"
namespace CalculatorApp
{

View File

@ -10,24 +10,24 @@
d:DesignWidth="400"
mc:Ignorable="d">
<ListView x:Name="EquationInputList"
<ListView x:Name="EquationInputList"
VerticalContentAlignment="Top"
IsItemClickEnabled="False"
ItemsSource="{x:Bind Equations}"
SelectionMode="None">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="Margin" Value="0,0,0,2"/>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="Margin" Value="0,0,0,2"/>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate x:DataType="vm:EquationViewModel">
<controls:EquationTextBox x:Uid="EquationInputButton"
<ListView.ItemTemplate>
<DataTemplate x:DataType="vm:EquationViewModel">
<controls:EquationTextBox x:Uid="EquationInputButton"
Margin="0,0,3,0"
Style="{StaticResource EquationTextBoxStyle}"
EquationColor="{x:Bind LineColor, Mode=OneWay}"
@ -35,27 +35,22 @@
GotFocus="InputTextBox_GotFocus"
Loaded="EquationTextBoxLoaded"
LostFocus="InputTextBox_LostFocus"
RemoveButtonClicked="EquationTextBox_RemoveButtonClicked">
<controls:EquationTextBox.KeyGraphFeaturesContent>
<StackPanel x:Name="KeyGraphFeaturesGrid" Visibility="{x:Bind KeyGraphFeaturesVisibility, Mode=OneWay}">
<TextBlock Text="Key Graph Features"/>
<TextBlock Text="{x:Bind Expression, Mode=OneWay}"/>
</StackPanel>
</controls:EquationTextBox.KeyGraphFeaturesContent>
<controls:EquationTextBox.ColorChooserFlyout>
<Flyout x:Name="ColorChooserFlyout"
RemoveButtonClicked="EquationTextBox_RemoveButtonClicked"
KeyGraphFeaturesButtonClicked="EquationTextBox_KeyGraphFeaturesButtonClicked">
<controls:EquationTextBox.ColorChooserFlyout>
<Flyout x:Name="ColorChooserFlyout"
x:Uid="ColorChooserFlyout"
Placement="Bottom">
<local:EquationStylePanelControl SelectedColor="{x:Bind LineColor, Mode=TwoWay}"/>
</Flyout>
</controls:EquationTextBox.ColorChooserFlyout>
</controls:EquationTextBox>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.Footer>
<Button Margin="4"
<local:EquationStylePanelControl SelectedColor="{x:Bind LineColor, Mode=TwoWay}"/>
</Flyout>
</controls:EquationTextBox.ColorChooserFlyout>
</controls:EquationTextBox>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.Footer>
<Button Margin="4"
Click="AddEquationButton_Click"
Content="+"/>
</ListView.Footer>
</ListView>
</ListView.Footer>
</ListView>
</UserControl>

View File

@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#include "pch.h"
#include "EquationInputArea.xaml.h"
@ -33,7 +36,7 @@ EquationInputArea::EquationInputArea()
ref new TypedEventHandler<AccessibilitySettings ^, Object ^>(this, &EquationInputArea::OnHighContrastChanged);
ReloadAvailableColors(m_accessibilitySettings->HighContrast);
InitializeComponent();
}
@ -98,6 +101,18 @@ void EquationInputArea::EquationTextBox_RemoveButtonClicked(Object ^ sender, Rou
}
}
void EquationInputArea::EquationTextBox_KeyGraphFeaturesButtonClicked(Object ^ sender, RoutedEventArgs ^ e)
{
auto tb = static_cast<EquationTextBox ^>(sender);
auto eq = static_cast<EquationViewModel ^>(tb->DataContext);
EquationVM = eq;
KeyGraphFeaturesVisibilityChanged(this, ref new RoutedEventArgs());
}
void EquationInputArea::EquationTextBox_EquationButtonClicked(Object ^ sender, RoutedEventArgs ^ e)
{
}
void EquationInputArea::EquationTextBoxLoaded(Object ^ sender, RoutedEventArgs ^ e)
{
auto tb = static_cast<EquationTextBox ^>(sender);

View File

@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#pragma once
#include "Views/GraphingCalculator/EquationInputArea.g.h"
@ -6,6 +9,7 @@
#include "EquationStylePanelControl.xaml.h"
#include "CalcViewModel/Common/KeyboardShortcutManager.h"
#include "Controls/EquationTextBox.h"
#include "Converters/BooleanNegationConverter.h"
namespace CalculatorApp
{
@ -16,8 +20,10 @@ namespace CalculatorApp
OBSERVABLE_OBJECT_CALLBACK(OnPropertyChanged);
OBSERVABLE_PROPERTY_RW(Windows::Foundation::Collections::IObservableVector< ViewModel::EquationViewModel^ >^, Equations);
OBSERVABLE_PROPERTY_RW_ALWAYS_NOTIFY(ViewModel::EquationViewModel ^, EquationVM);
OBSERVABLE_PROPERTY_RW(Windows::Foundation::Collections::IObservableVector<Windows::UI::Xaml::Media::SolidColorBrush ^> ^, AvailableColors);
event Windows::UI::Xaml::RoutedEventHandler ^ KeyGraphFeaturesVisibilityChanged;
private:
void OnPropertyChanged(Platform::String^ propertyName);
@ -37,6 +43,8 @@ namespace CalculatorApp
Windows::UI::ViewManagement::AccessibilitySettings ^ m_accessibilitySettings;
int m_lastLineColorIndex;
void EquationTextBox_RemoveButtonClicked(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
void EquationTextBox_KeyGraphFeaturesButtonClicked(Platform::Object ^ sender, Windows::UI::Xaml::RoutedEventArgs ^ e);
void EquationTextBox_EquationButtonClicked(Platform::Object ^ sender, Windows::UI::Xaml::RoutedEventArgs ^ e);
void EquationTextBoxLoaded(Platform::Object ^ sender, Windows::UI::Xaml::RoutedEventArgs ^ e);
};
}

View File

@ -9,8 +9,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:CalculatorApp.ViewModel"
DataContextChanged="GraphingCalculator_DataContextChanged"
mc:Ignorable="d"
>
mc:Ignorable="d">
<UserControl.Resources>
<Style x:Key="ZoomRepeatButtonStyle" TargetType="RepeatButton">
@ -33,7 +32,7 @@
<converters:BooleanToVisibilityNegationConverter x:Name="BooleanToVisibilityNegationConverter"/>
</UserControl.Resources>
<Grid x:Name="RootGrid" >
<Grid x:Name="RootGrid">
<Grid.RowDefinitions>
<RowDefinition x:Name="RowHamburger" Height="{StaticResource HamburgerHeightGridLength}"/>
<RowDefinition/>
@ -48,39 +47,75 @@
Grid.Row="1"
Grid.Column="0">
<Grid Grid.Row="0" Margin="4,7,4,4">
<graphControl:Grapher Name="GraphingControl"
EquationsSource="{x:Bind ViewModel.Equations, Mode=OneWay}"
ForceProportionalAxes="True"
UseSystemFocusVisuals="True"
VariablesUpdated="GraphVariablesUpdated"
LostFocus="OnGraphLostFocus"
LosingFocus="OnLoosingFocus">
<graphControl:Grapher Name="GraphingControl"
EquationsSource="{x:Bind ViewModel.Equations, Mode=OneWay}"
ForceProportionalAxes="True"
LosingFocus="OnLoosingFocus"
LostFocus="OnGraphLostFocus"
UseSystemFocusVisuals="True"
VariablesUpdated="GraphVariablesUpdated">
<graphControl:Grapher.Background>
<SolidColorBrush Color="White"/>
</graphControl:Grapher.Background>
<graphControl:Grapher.EquationTemplate>
<DataTemplate x:DataType="vm:EquationViewModel">
<graphControl:Equation Expression="{x:Bind Expression, Mode=OneWay}" LineColor="{x:Bind LineColor, Mode=OneWay}"/>
<graphControl:Equation AnalysisError="{x:Bind AnalysisError, Mode=TwoWay}"
Domain="{x:Bind Domain, Mode=TwoWay}"
Expression="{x:Bind Expression, Mode=OneWay}"
HorizontalAsymptotes="{x:Bind HorizontalAsymptotes, Mode=TwoWay}"
InflectionPoints="{x:Bind InflectionPoints, Mode=TwoWay}"
IsAnalysisUpdated="{x:Bind IsAnalysisUpdated, Mode=TwoWay}"
LineColor="{x:Bind LineColor, Mode=OneWay}"
Maxima="{x:Bind Maxima, Mode=TwoWay}"
Minima="{x:Bind Minima, Mode=TwoWay}"
Monotonicity="{x:Bind Monotonicity, Mode=TwoWay}"
ObliqueAsymptotes="{x:Bind ObliqueAsymptotes, Mode=TwoWay}"
Parity="{x:Bind Parity, Mode=TwoWay}"
PeriodicityDirection="{x:Bind PeriodicityDirection, Mode=TwoWay}"
PeriodicityExpression="{x:Bind PeriodicityExpression, Mode=TwoWay}"
Range="{x:Bind Range, Mode=TwoWay}"
TooComplexFeatures="{x:Bind TooComplexFeatures, Mode=TwoWay}"
VerticalAsymptotes="{x:Bind VerticalAsymptotes, Mode=TwoWay}"
XIntercept="{x:Bind XIntercept, Mode=TwoWay}"
YIntercept="{x:Bind YIntercept, Mode=TwoWay}"/>
</DataTemplate>
</graphControl:Grapher.EquationTemplate>
</graphControl:Grapher>
<StackPanel Grid.Row="0" Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0,0,10,10">
<Button x:Name="ActiveTracing" Click="OnActiveTracingClick" MinWidth="40" MinHeight="40" Margin="0,0,10,0">
<StackPanel Grid.Row="0"
Margin="0,0,10,10"
HorizontalAlignment="Right"
VerticalAlignment="Top"
Orientation="Horizontal">
<Button x:Name="ActiveTracing"
MinWidth="40"
MinHeight="40"
Margin="0,0,10,0"
Click="OnActiveTracingClick">
<FontIcon FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE73F;"/>
</Button>
<Button x:Name="Share" Click="OnShareClick" MinWidth="40" MinHeight="40">
<Button x:Name="Share"
MinWidth="40"
MinHeight="40"
Click="OnShareClick">
<FontIcon FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE72D;"/>
</Button>
</StackPanel>
<Popup x:Name="TraceValuePopup" Grid.Row="0" RenderTransformOrigin="0,1">
<Popup x:Name="TraceValuePopup"
Grid.Row="0"
RenderTransformOrigin="0,1">
<Popup.RenderTransform>
<TranslateTransform x:Name="TraceValuePopupTransform" X="50" Y="150"/>
</Popup.RenderTransform>
<Grid Background="{StaticResource ToolTipBackground}" BorderBrush="{StaticResource ToolTipBorderBrush}" BorderThickness="3,3,3,3">
<TextBlock x:Name="TraceValue" Text="x=0,y=0" Margin="5,5,5,5" Foreground="{StaticResource ToolTipForeground}"/>
<Grid Background="{StaticResource ToolTipBackground}"
BorderBrush="{StaticResource ToolTipBorderBrush}"
BorderThickness="3,3,3,3">
<TextBlock x:Name="TraceValue"
Margin="5,5,5,5"
Foreground="{StaticResource ToolTipForeground}"
Text="x=0,y=0"/>
</Grid>
</Popup>
@ -392,20 +427,30 @@
<RowDefinition Height="3*"/>
</Grid.RowDefinitions>
<Grid>
<!-- Ideally the KeyGraphFeaturesPanel should be a frame so that navigation to and from the panel could be handled nicely -->
<local:KeyGraphFeaturesPanel x:Name="KeyGraphFeaturesControl"
Grid.RowSpan="2"
x:Load="{x:Bind IsKeyGraphFeaturesVisible, Mode=OneWay}"
KeyGraphFeaturesClosed="OnKeyGraphFeaturesClosed"
ViewModel="{x:Bind EquationInputAreaControl.EquationVM, Mode=OneWay}"
Visibility="{x:Bind IsKeyGraphFeaturesVisible, Mode=OneWay}"/>
<Grid x:Name="EquationInputAreaGrid" Visibility="{x:Bind IsKeyGraphFeaturesVisible, Converter={StaticResource BooleanToVisibilityNegationConverter}, Mode=OneWay}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<local:EquationInputArea Grid.Row="1"
<local:EquationInputArea x:Name="EquationInputAreaControl"
Grid.Row="1"
Margin="0,8,0,0"
Equations="{x:Bind ViewModel.Equations}"/>
Equations="{x:Bind ViewModel.Equations}"
KeyGraphFeaturesVisibilityChanged="OnEquationKeyGraphFeaturesVisibilityChanged"/>
</Grid>
<Grid x:Name="ButtonContainerGrid"
Grid.Row="1"
Margin="3,0,3,3"
UseLayoutRounding="False">
UseLayoutRounding="False"
Visibility="{x:Bind IsKeyGraphFeaturesVisible, Converter={StaticResource BooleanToVisibilityNegationConverter}, Mode=OneWay}">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>

View File

@ -1,9 +1,13 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#include "pch.h"
#include "CalcViewModel/Common/TraceLogger.h"
#include "GraphingCalculator.xaml.h"
#include "CalcViewModel/Common/KeyboardShortcutManager.h"
#include "Controls/CalculationResult.h"
#include "Calculator\Controls\EquationTextBox.h"
#include "Calculator\Views\GraphingCalculator\EquationInputArea.xaml.h"
using namespace CalculatorApp;
using namespace CalculatorApp::Common;
@ -311,3 +315,13 @@ void CalculatorApp::GraphingCalculator::OnLoosingFocus(Windows::UI::Xaml::UIElem
args->TryCancel();
}
}
void GraphingCalculator::OnEquationKeyGraphFeaturesVisibilityChanged(Object ^ sender, RoutedEventArgs ^ e)
{
IsKeyGraphFeaturesVisible = true;
}
void GraphingCalculator::OnKeyGraphFeaturesClosed(Object ^ sender, RoutedEventArgs ^ e)
{
IsKeyGraphFeaturesVisible = false;
}

View File

@ -1,8 +1,12 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#pragma once
#include "Views\GraphingCalculator\GraphingCalculator.g.h"
#include "CalcViewModel\GraphingCalculator\GraphingCalculatorViewModel.h"
#include "Views\NumberPad.xaml.h"
#include "Views\GraphingCalculator\KeyGraphFeaturesPanel.xaml.h"
namespace CalculatorApp
{
@ -18,6 +22,7 @@ namespace CalculatorApp
COMMAND_FOR_METHOD(ZoomOutButtonPressed, GraphingCalculator::OnZoomOutCommand);
COMMAND_FOR_METHOD(ZoomInButtonPressed, GraphingCalculator::OnZoomInCommand);
COMMAND_FOR_METHOD(ZoomResetButtonPressed, GraphingCalculator::OnZoomResetCommand);
OBSERVABLE_PROPERTY_RW(bool, IsKeyGraphFeaturesVisible);
property CalculatorApp::ViewModel::GraphingCalculatorViewModel^ ViewModel
{
@ -57,7 +62,8 @@ namespace CalculatorApp
void OnActiveTracingClick(Platform::Object ^ sender, Windows::UI::Xaml::RoutedEventArgs ^ e);
void OnGraphLostFocus(Platform::Object ^ sender, Windows::UI::Xaml::RoutedEventArgs ^ e);
void OnLoosingFocus(Windows::UI::Xaml::UIElement ^ sender, Windows::UI::Xaml::Input::LosingFocusEventArgs ^ args);
void OnEquationKeyGraphFeaturesVisibilityChanged(Platform::Object ^ sender, Windows::UI::Xaml::RoutedEventArgs ^ e);
void OnKeyGraphFeaturesClosed(Platform::Object ^ sender, Windows::UI::Xaml::RoutedEventArgs ^ e);
bool ActiveTracingOn;
};

View File

@ -0,0 +1,462 @@
<UserControl x:Class="CalculatorApp.KeyGraphFeaturesPanel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:CalculatorApp.Controls"
xmlns:converters="using:CalculatorApp.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:CalculatorApp"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ts="using:CalculatorApp.TemplateSelectors"
xmlns:vm="using:CalculatorApp.ViewModel"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
mc:Ignorable="d">
<UserControl.Resources>
<Style x:Key="KGF_EquationTextBoxStyle" TargetType="controls:EquationTextBox">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}"/>
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}"/>
<Setter Property="FontWeight" Value="Normal"/>
<Setter Property="Foreground" Value="{ThemeResource TextBoxForegroundThemeBrush}"/>
<Setter Property="Padding" Value="{ThemeResource TextControlThemePadding}"/>
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="Typography.StylisticSet20" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="controls:EquationTextBox">
<Grid>
<Grid.Resources>
<Style x:Key="KGF_EquationTextBoxStyle" TargetType="controls:MathRichEditBox">
<Setter Property="Foreground" Value="{ThemeResource TextControlForeground}"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="ContentLinkForegroundColor" Value="{ThemeResource ContentLinkForegroundColor}"/>
<Setter Property="ContentLinkBackgroundColor" Value="{ThemeResource ContentLinkBackgroundColor}"/>
<Setter Property="SelectionHighlightColor" Value="{ThemeResource TextControlSelectionHighlightColor}"/>
<Setter Property="BorderBrush" Value="{ThemeResource TextControlBorderBrush}"/>
<Setter Property="BorderThickness" Value="{ThemeResource TextControlBorderThemeThickness}"/>
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}"/>
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}"/>
<Setter Property="ScrollViewer.HorizontalScrollMode" Value="Auto"/>
<Setter Property="ScrollViewer.VerticalScrollMode" Value="Auto"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Hidden"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Hidden"/>
<Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="False"/>
<Setter Property="Padding" Value="{ThemeResource TextControlThemePadding}"/>
<Setter Property="UseSystemFocusVisuals" Value="{ThemeResource IsApplicationFocusVisualKindReveal}"/>
<Setter Property="ContextFlyout" Value="{StaticResource TextControlCommandBarContextFlyout}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="controls:MathRichEditBox">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Disabled"/>
<VisualState x:Name="Normal"/>
<VisualState x:Name="PointerOver"/>
<VisualState x:Name="Focused"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter x:Name="HeaderContentPresenter"
Grid.Row="0"
Grid.Column="0"
Grid.ColumnSpan="4"
Margin="{ThemeResource RichEditBoxTopHeaderMargin}"
Foreground="{ThemeResource TextControlHeaderForeground}"
FontWeight="Normal"
x:DeferLoadStrategy="Lazy"
Content="{TemplateBinding Header}"
ContentTemplate="{TemplateBinding HeaderTemplate}"
TextWrapping="Wrap"
Visibility="Collapsed"/>
<Border x:Name="BorderElement"
Grid.Row="1"
Grid.RowSpan="1"
Grid.Column="0"
Grid.ColumnSpan="4"
MinWidth="{ThemeResource TextControlThemeMinWidth}"
MinHeight="{ThemeResource TextControlThemeMinHeight}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="0"
Control.IsTemplateFocusTarget="True"
CornerRadius="{TemplateBinding CornerRadius}"/>
<ScrollViewer x:Name="ContentElement"
Grid.Row="1"
Grid.Column="0"
Margin="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}"
VerticalAlignment="Center"
AutomationProperties.AccessibilityView="Raw"
HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}"
IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}"
IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}"
IsTabStop="False"
IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}"
VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"
VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}"
ZoomMode="Disabled"/>
<TextBlock x:Name="PlaceholderTextContentPresenter"
Grid.Row="1"
Grid.Column="0"
Grid.ColumnSpan="4"
Margin="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}"
VerticalAlignment="Center"
Foreground="{ThemeResource TextControlPlaceholderForeground}"
IsHitTestVisible="False"
Text="{TemplateBinding PlaceholderText}"
TextAlignment="{TemplateBinding TextAlignment}"
TextWrapping="{TemplateBinding TextWrapping}"/>
<ContentPresenter x:Name="DescriptionPresenter"
Grid.Row="2"
Grid.Column="0"
Grid.ColumnSpan="4"
Background="Transparent"
Foreground="{ThemeResource SystemControlDescriptionTextForegroundBrush}"
x:Load="False"
AutomationProperties.AccessibilityView="Raw"
Content="{TemplateBinding Description}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition MinHeight="44"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Button x:Name="EquationButton"
MinWidth="44"
MinHeight="44"
VerticalAlignment="Stretch"
Background="{TemplateBinding EquationColor}"
Foreground="{StaticResource SystemChromeWhiteColor}"
BorderThickness="0">
<Button.Content>
<StackPanel Margin="5,0"
VerticalAlignment="Top"
Orientation="Horizontal">
<FontIcon VerticalAlignment="Center"
FontFamily="{ThemeResource SymbolThemeFontFamily}"
FontSize="16"
Glyph="&#xE72B;"/>
<TextBlock Margin="12,-4,0,0"
VerticalAlignment="Top"
FontFamily="{TemplateBinding FontFamily}"
FontSize="16"
Text="ƒₓ"/>
</StackPanel>
</Button.Content>
<Button.Resources>
<SolidColorBrush x:Name="ButtonBackgroundPointerOver"
Opacity="0.7"
Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=EquationColor.Color}"/>
<SolidColorBrush x:Name="ButtonForegroundPointerOver" Color="{ThemeResource SystemChromeWhiteColor}"/>
<SolidColorBrush x:Name="ButtonBorderBrushPointerOver" Color="Transparent"/>
</Button.Resources>
</Button>
<controls:MathRichEditBox x:Name="EquationTextBox"
Grid.Column="1"
MinHeight="44"
Padding="{TemplateBinding Padding}"
VerticalAlignment="Stretch"
Style="{StaticResource MathRichEdit_EquationTextBoxStyle}"
Background="Transparent"
BorderThickness="0"
FontFamily="{TemplateBinding FontFamily}"
FontSize="{TemplateBinding FontSize}"
FontWeight="{TemplateBinding FontWeight}"
AcceptsReturn="false"
InputScope="Text"
IsReadOnly="True"
MaxLength="2048"
TextWrapping="NoWrap"
UseSystemFocusVisuals="True"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="KGF_RichEditBoxStyle" TargetType="controls:MathRichEditBox">
<Setter Property="FontSize" Value="14"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="IsReadOnly" Value="True"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="IsEnabled" Value="True"/>
<Setter Property="Margin" Value="-8,0,0,0"/>
<Setter Property="UseSystemFocusVisuals" Value="True"/>
<Setter Property="TextWrapping" Value="NoWrap"/>
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="VerticalAlignment" Value="Stretch"/>
<Setter Property="Typography.StylisticSet20" Value="True"/>
<Setter Property="ScrollViewer.HorizontalScrollMode" Value="Disabled"/>
<Setter Property="ScrollViewer.VerticalScrollMode" Value="Disabled"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Disabled"/>
<Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="False"/>
<Setter Property="TextWrapping" Value="NoWrap"/>
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="VerticalAlignment" Value="Stretch"/>
<Setter Property="Typography.StylisticSet20" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="RichEditBox">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HeaderContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlForeground}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="Transparent"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBorderBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlForeground}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderTextContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlPlaceholderForegroundDisabled}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Normal"/>
<VisualState x:Name="PointerOver"/>
<VisualState x:Name="Focused"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter x:Name="HeaderContentPresenter"
Grid.Row="0"
Margin="{ThemeResource RichEditBoxTopHeaderMargin}"
Foreground="{ThemeResource TextControlHeaderForeground}"
FontWeight="Normal"
x:DeferLoadStrategy="Lazy"
Content="{TemplateBinding Header}"
ContentTemplate="{TemplateBinding HeaderTemplate}"
TextWrapping="Wrap"
Visibility="Collapsed"/>
<Border x:Name="BorderElement"
Grid.Row="1"
Grid.RowSpan="1"
MinWidth="{ThemeResource TextControlThemeMinWidth}"
MinHeight="{ThemeResource TextControlThemeMinHeight}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}"/>
<ScrollViewer x:Name="ContentElement"
Grid.Row="1"
Margin="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}"
VerticalAlignment="Center"
AutomationProperties.AccessibilityView="Raw"
HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}"
IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}"
IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}"
IsTabStop="False"
IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}"
VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"
VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}"
ZoomMode="Disabled"/>
<TextBlock x:Name="PlaceholderTextContentPresenter"
Grid.Row="1"
Margin="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}"
Foreground="{ThemeResource TextControlPlaceholderForeground}"
IsHitTestVisible="False"
Text="{TemplateBinding PlaceholderText}"
TextAlignment="{TemplateBinding TextAlignment}"
TextWrapping="{TemplateBinding TextWrapping}"/>
<ContentPresenter x:Name="DescriptionPresenter"
Grid.Row="2"
Foreground="{ThemeResource SystemControlDescriptionTextForegroundBrush}"
x:Load="False"
AutomationProperties.AccessibilityView="Raw"
Content="{TemplateBinding Description}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Name="KGF_TitleTextBlockStyle" TargetType="TextBlock">
<Setter Property="FontWeight" Value="Medium"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="TextWrapping" Value="WrapWholeWords"/>
<Setter Property="VerticalAlignment" Value="Bottom"/>
<Setter Property="AutomationProperties.HeadingLevel" Value="Level2"/>
</Style>
<Style x:Name="KGF_TextBlockStyle" TargetType="TextBlock">
<Setter Property="FontWeight" Value="Normal"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="TextWrapping" Value="WrapWholeWords"/>
</Style>
<Style x:Name="KGF_ListViewItemContainerStyle" TargetType="ListViewItem">
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="Width" Value="Auto"/>
<Setter Property="AutomationProperties.AccessibilityView" Value="Raw"/>
<Setter Property="Margin" Value="0,10"/>
</Style>
<DataTemplate x:Key="KGFRichEditDataTemplate" x:DataType="vm:KeyGraphFeaturesItem">
<StackPanel>
<TextBlock x:Name="TitleTextBlock"
Style="{StaticResource KGF_TitleTextBlockStyle}"
Text="{x:Bind Title, Mode=OneWay}"/>
<ItemsControl ItemsSource="{x:Bind DisplayItems, Mode=OneWay}" UseSystemFocusVisuals="True">
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="x:String">
<controls:MathRichEditBox HorizontalAlignment="Left"
HorizontalContentAlignment="Left"
Style="{StaticResource KGF_RichEditBoxStyle}"
MathText="{x:Bind}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="KGFGridDataTemplate" x:DataType="vm:KeyGraphFeaturesItem">
<StackPanel>
<TextBlock x:Name="TitleTextBlock"
Style="{StaticResource KGF_TitleTextBlockStyle}"
Text="{x:Bind Title, Mode=OneWay}"/>
<ItemsControl ItemsSource="{x:Bind GridItems, Mode=OneWay}" UseSystemFocusVisuals="True">
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="vm:GridDisplayItems">
<Grid VerticalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<controls:MathRichEditBox Grid.Column="0"
MinWidth="25"
VerticalAlignment="Center"
Style="{StaticResource KGF_RichEditBoxStyle}"
MathText="{x:Bind Expression}"/>
<TextBlock Grid.Column="1"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Style="{StaticResource KGF_TextBlockStyle}"
Text="{x:Bind Direction}"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="KGFTextBlockDataTemplate" x:DataType="vm:KeyGraphFeaturesItem">
<StackPanel>
<TextBlock x:Name="TitleTextBlock"
Style="{StaticResource KGF_TitleTextBlockStyle}"
Text="{x:Bind Title, Mode=OneWay}"/>
<ItemsControl ItemsSource="{x:Bind DisplayItems, Mode=OneWay}" UseSystemFocusVisuals="True">
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="x:String">
<TextBlock Style="{StaticResource KGF_TextBlockStyle}" Text="{x:Bind}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</DataTemplate>
<ts:KeyGraphFeaturesTemplateSelector x:Key="KGFTemplateSelector"
GridTemplate="{StaticResource KGFGridDataTemplate}"
RichEditTemplate="{StaticResource KGFRichEditDataTemplate}"
TextBlockTemplate="{StaticResource KGFTextBlockDataTemplate}"/>
<converters:BooleanToVisibilityNegationConverter x:Name="BooleanToVisibilityNegationConverter"/>
</UserControl.Resources>
<Grid Margin="0,7,0,0" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<controls:EquationTextBox x:Name="EquationInputTextBox"
x:Uid="EquationInputButton"
Grid.Row="0"
Margin="0,0,3,0"
Style="{StaticResource KGF_EquationTextBoxStyle}"
Background="Transparent"
BorderThickness="0"
DataContext="{x:Bind ViewModel, Mode=OneWay}"
EquationButtonClicked="EquationButtonClicked"
Loaded="EquationInputTextBox_Loaded"/>
<TextBlock x:Uid="KeyGraphFeaturesLabel"
Grid.Row="1"
Margin="12,20,10,0"
Style="{StaticResource KGF_TitleTextBlockStyle}"
FontSize="18"
AutomationProperties.HeadingLevel="Level1"/>
<ListView x:Name="KeyGraphFeaturesListView"
Grid.Row="2"
Margin="12,10,10,0"
Padding="0,0,0,12"
IsItemClickEnabled="False"
ItemContainerStyle="{StaticResource KGF_ListViewItemContainerStyle}"
ItemTemplateSelector="{StaticResource KGFTemplateSelector}"
ItemsSource="{x:Bind ViewModel.KeyGraphFeaturesItems}"
ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollMode="Auto"
SelectionMode="None"
Visibility="{x:Bind ViewModel.AnalysisErrorVisible, Converter={StaticResource BooleanToVisibilityNegationConverter}, Mode=OneWay}"/>
<TextBlock x:Name="AnalysisErrorTextBlock"
Grid.Row="2"
Margin="12,10,10,0"
Style="{StaticResource KGF_TextBlockStyle}"
FontWeight="Normal"
Text="{x:Bind ViewModel.AnalysisErrorString, Mode=OneWay}"
Visibility="{x:Bind ViewModel.AnalysisErrorVisible, Mode=OneWay}"/>
</Grid>
</UserControl>

View File

@ -0,0 +1,53 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#include "pch.h"
#include "KeyGraphFeaturesPanel.xaml.h"
#include "Controls/MathRichEditBox.h"
#include "CalcViewModel/GraphingCalculatorEnums.h"
using namespace CalculatorApp;
using namespace CalculatorApp::ViewModel;
using namespace Platform;
using namespace Windows::UI;
using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Controls;
KeyGraphFeaturesPanel::KeyGraphFeaturesPanel()
{
InitializeComponent();
}
void KeyGraphFeaturesPanel::OnPropertyChanged(String ^ propertyName)
{
if (propertyName == L"ViewModel")
{
if (ViewModel == nullptr)
{
return;
}
SetEquationTextBoxProperties();
}
}
void KeyGraphFeaturesPanel::EquationButtonClicked(Object ^ sender, RoutedEventArgs ^ e)
{
KeyGraphFeaturesClosed(this, ref new RoutedEventArgs());
}
void KeyGraphFeaturesPanel::EquationInputTextBox_Loaded(Object ^ sender, RoutedEventArgs ^ e)
{
if (ViewModel != nullptr)
{
SetEquationTextBoxProperties();
}
}
void KeyGraphFeaturesPanel::SetEquationTextBoxProperties()
{
EquationInputTextBox->SetEquationText(ViewModel->Expression);
EquationInputTextBox->EquationColor = ViewModel->LineColor;
}

View File

@ -0,0 +1,31 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#pragma once
#include "Views\GraphingCalculator\KeyGraphFeaturesPanel.g.h"
#include "CalcViewModel\GraphingCalculator\EquationViewModel.h"
#include "Controls/MathRichEditBox.h"
#include "Controls/EquationTextBox.h"
namespace CalculatorApp
{
public
ref class KeyGraphFeaturesPanel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
{
public:
KeyGraphFeaturesPanel();
OBSERVABLE_OBJECT_CALLBACK(OnPropertyChanged);
OBSERVABLE_PROPERTY_RW_ALWAYS_NOTIFY(CalculatorApp::ViewModel::EquationViewModel ^, ViewModel);
event Windows::UI::Xaml::RoutedEventHandler ^ KeyGraphFeaturesClosed;
private:
void OnPropertyChanged(Platform::String ^ propertyName);
void EquationButtonClicked(Platform::Object ^ sender, Windows::UI::Xaml::RoutedEventArgs ^ e);
void SetEquationTextBoxProperties();
void EquationInputTextBox_Loaded(Platform::Object ^ sender, Windows::UI::Xaml::RoutedEventArgs ^ e);
};
}

View File

@ -7,7 +7,7 @@
<MinimumVisualStudioVersion>15.0</MinimumVisualStudioVersion>
<AppContainerApplication>true</AppContainerApplication>
<ApplicationType>Windows Store</ApplicationType>
<WindowsTargetPlatformVersion Condition=" '$(WindowsTargetPlatformVersion)' == '' ">10.0.18970.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion Condition=" '$(WindowsTargetPlatformVersion)' == '' ">10.0.19019.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformMinVersion>10.0.17134.0</WindowsTargetPlatformMinVersion>
<ApplicationTypeRevision>10.0</ApplicationTypeRevision>
<UnitTestPlatformVersion Condition="'$(UnitTestPlatformVersion)' == ''">15.0</UnitTestPlatformVersion>

View File

@ -3,6 +3,7 @@
#include "pch.h"
#include "Equation.h"
using namespace winrt::Windows::Foundation::Collections;
using namespace Platform;
using namespace std;
@ -16,16 +17,84 @@ namespace GraphControl
// Remove mml: formatting specific to RichEditBox control, which is not understood by the graph engine.
static constexpr wstring_view s_mathPrefix = L"mml:";
DependencyProperty^ Equation::s_expressionProperty;
DependencyProperty ^ Equation::s_expressionProperty;
static constexpr auto s_propertyName_Expression = L"Expression";
DependencyProperty^ Equation::s_lineColorProperty;
DependencyProperty ^ Equation::s_lineColorProperty;
static constexpr auto s_propertyName_LineColor = L"LineColor";
DependencyProperty ^ Equation::s_isAnalysisUpdatedProperty;
static constexpr auto s_propertyName_IsAnalysisUpdated = L"IsAnalysisUpdated";
DependencyProperty ^ Equation::s_xInterceptProperty;
static constexpr auto s_propertyName_XIntercept = L"XIntercept";
DependencyProperty ^ Equation::s_yInterceptProperty;
static constexpr auto s_propertyName_YIntercept = L"YIntercept";
DependencyProperty ^ Equation::s_parityProperty;
static constexpr auto s_propertyName_Parity = L"Parity";
DependencyProperty ^ Equation::s_periodicityDirectionProperty;
static constexpr auto s_propertyName_PeriodicityDirection = L"PeriodicityDirection";
DependencyProperty ^ Equation::s_periodicityExpressionProperty;
static constexpr auto s_propertyName_PeriodicityExpression = L"PeriodicityExpression";
DependencyProperty ^ Equation::s_minimaProperty;
static constexpr auto s_propertyName_Minima = L"Minima";
DependencyProperty ^ Equation::s_maximaProperty;
static constexpr auto s_propertyName_Maxima = L"Maxima";
DependencyProperty ^ Equation::s_domainProperty;
static constexpr auto s_propertyName_Domain = L"Domain";
DependencyProperty ^ Equation::s_rangeProperty;
static constexpr auto s_propertyName_Range = L"Range";
DependencyProperty ^ Equation::s_inflectionPointsProperty;
static constexpr auto s_propertyName_InflectionPoints = L"InflectionPoints";
DependencyProperty ^ Equation::s_monotonicityProperty;
static constexpr auto s_propertyName_Monotonicity = L"Monotonicity";
DependencyProperty ^ Equation::s_verticalAsymptotesProperty;
static constexpr auto s_propertyName_VerticalAsymptotes = L"VerticalAsymptotes";
DependencyProperty ^ Equation::s_horizontalAsymptotesProperty;
static constexpr auto s_propertyName_HorizontalAsymptotes = L"HorizontalAsymptotes";
DependencyProperty ^ Equation::s_obliqueAsymptotesProperty;
static constexpr auto s_propertyName_ObliqueAsymptotes = L"ObliqueAsymptotes";
DependencyProperty ^ Equation::s_tooComplexFeaturesProperty;
static constexpr auto s_propertyName_TooComplexFeatures = L"TooComplexFeatures";
DependencyProperty ^ Equation::s_analysisErrorProperty;
static constexpr auto s_propertyName_AnalysisError = L"AnalysisError";
namespace EquationProperties
{
String^ Expression = StringReference(s_propertyName_Expression);
String^ LineColor = StringReference(s_propertyName_LineColor);
String ^ Expression = StringReference(s_propertyName_Expression);
String ^ LineColor = StringReference(s_propertyName_LineColor);
String ^ IsAnalysisUpdated = StringReference(s_propertyName_IsAnalysisUpdated);
String ^ XIntercept = StringReference(s_propertyName_XIntercept);
String ^ YIntercept = StringReference(s_propertyName_YIntercept);
String ^ Parity = StringReference(s_propertyName_Parity);
String ^ PeriodicityDirection = StringReference(s_propertyName_PeriodicityDirection);
String ^ PeriodicityExpression = StringReference(s_propertyName_PeriodicityExpression);
String ^ Minima = StringReference(s_propertyName_Minima);
String ^ Maxima = StringReference(s_propertyName_Maxima);
String ^ Domain = StringReference(s_propertyName_Domain);
String ^ Range = StringReference(s_propertyName_Range);
String ^ InflectionPoints = StringReference(s_propertyName_InflectionPoints);
String ^ Monotonicity = StringReference(s_propertyName_Monotonicity);
String ^ VerticalAsymptotes = StringReference(s_propertyName_VerticalAsymptotes);
String ^ HorizontalAsymptotes = StringReference(s_propertyName_HorizontalAsymptotes);
String ^ ObliqueAsymptotes = StringReference(s_propertyName_ObliqueAsymptotes);
String ^ TooComplexFeatures = StringReference(s_propertyName_TooComplexFeatures);
String ^ AnalysisError = StringReference(s_propertyName_AnalysisError);
}
void Equation::RegisterDependencyProperties()
@ -36,9 +105,7 @@ namespace GraphControl
EquationProperties::Expression,
String::typeid,
Equation::typeid,
ref new PropertyMetadata(
nullptr,
ref new PropertyChangedCallback(&Equation::OnCustomDependencyPropertyChanged)));
ref new PropertyMetadata(nullptr, ref new PropertyChangedCallback(&Equation::OnCustomDependencyPropertyChanged)));
}
if (!s_lineColorProperty)
@ -50,17 +117,167 @@ namespace GraphControl
EquationProperties::LineColor,
SolidColorBrush::typeid,
Equation::typeid,
ref new PropertyMetadata(
nullptr,
ref new PropertyChangedCallback(&Equation::OnCustomDependencyPropertyChanged)));
ref new PropertyMetadata(nullptr, ref new PropertyChangedCallback(&Equation::OnCustomDependencyPropertyChanged)));
}
if (!s_isAnalysisUpdatedProperty)
{
s_isAnalysisUpdatedProperty = DependencyProperty::Register(
EquationProperties::IsAnalysisUpdated,
bool ::typeid,
Equation::typeid,
ref new PropertyMetadata(nullptr, ref new PropertyChangedCallback(&Equation::OnCustomDependencyPropertyChanged)));
}
if (!s_xInterceptProperty)
{
s_xInterceptProperty = DependencyProperty::Register(
EquationProperties::XIntercept,
String::typeid,
Equation::typeid,
ref new PropertyMetadata(nullptr, ref new PropertyChangedCallback(&Equation::OnCustomDependencyPropertyChanged)));
}
if (!s_yInterceptProperty)
{
s_yInterceptProperty = DependencyProperty::Register(
EquationProperties::YIntercept,
String::typeid,
Equation::typeid,
ref new PropertyMetadata(nullptr, ref new PropertyChangedCallback(&Equation::OnCustomDependencyPropertyChanged)));
}
if (!s_parityProperty)
{
s_parityProperty = DependencyProperty::Register(
EquationProperties::Parity,
int ::typeid,
Equation::typeid,
ref new PropertyMetadata(nullptr, ref new PropertyChangedCallback(&Equation::OnCustomDependencyPropertyChanged)));
}
if (!s_periodicityDirectionProperty)
{
s_periodicityDirectionProperty = DependencyProperty::Register(
EquationProperties::PeriodicityDirection,
int ::typeid,
Equation::typeid,
ref new PropertyMetadata(nullptr, ref new PropertyChangedCallback(&Equation::OnCustomDependencyPropertyChanged)));
}
if (!s_periodicityExpressionProperty)
{
s_periodicityExpressionProperty = DependencyProperty::Register(
EquationProperties::PeriodicityExpression,
String::typeid,
Equation::typeid,
ref new PropertyMetadata(nullptr, ref new PropertyChangedCallback(&Equation::OnCustomDependencyPropertyChanged)));
}
if (!s_minimaProperty)
{
s_minimaProperty = DependencyProperty::Register(
EquationProperties::Minima,
IObservableVector<String ^>::typeid,
Equation::typeid,
ref new PropertyMetadata(nullptr, ref new PropertyChangedCallback(&Equation::OnCustomDependencyPropertyChanged)));
}
if (!s_maximaProperty)
{
s_maximaProperty = DependencyProperty::Register(
EquationProperties::Maxima,
IObservableVector<String ^>::typeid,
Equation::typeid,
ref new PropertyMetadata(nullptr, ref new PropertyChangedCallback(&Equation::OnCustomDependencyPropertyChanged)));
}
if (!s_domainProperty)
{
s_domainProperty = DependencyProperty::Register(
EquationProperties::Domain,
String::typeid,
Equation::typeid,
ref new PropertyMetadata(nullptr, ref new PropertyChangedCallback(&Equation::OnCustomDependencyPropertyChanged)));
}
if (!s_rangeProperty)
{
s_rangeProperty = DependencyProperty::Register(
EquationProperties::Range,
String::typeid,
Equation::typeid,
ref new PropertyMetadata(nullptr, ref new PropertyChangedCallback(&Equation::OnCustomDependencyPropertyChanged)));
}
if (!s_inflectionPointsProperty)
{
s_inflectionPointsProperty = DependencyProperty::Register(
EquationProperties::InflectionPoints,
IObservableVector<String ^>::typeid,
Equation::typeid,
ref new PropertyMetadata(nullptr, ref new PropertyChangedCallback(&Equation::OnCustomDependencyPropertyChanged)));
}
if (!s_monotonicityProperty)
{
s_monotonicityProperty = DependencyProperty::Register(
EquationProperties::Monotonicity,
IObservableMap<String ^, String ^>::typeid,
Equation::typeid,
ref new PropertyMetadata(nullptr, ref new PropertyChangedCallback(&Equation::OnCustomDependencyPropertyChanged)));
}
if (!s_verticalAsymptotesProperty)
{
s_verticalAsymptotesProperty = DependencyProperty::Register(
EquationProperties::VerticalAsymptotes,
IObservableVector<String ^>::typeid,
Equation::typeid,
ref new PropertyMetadata(nullptr, ref new PropertyChangedCallback(&Equation::OnCustomDependencyPropertyChanged)));
}
if (!s_horizontalAsymptotesProperty)
{
s_horizontalAsymptotesProperty = DependencyProperty::Register(
EquationProperties::HorizontalAsymptotes,
IObservableVector<String ^>::typeid,
Equation::typeid,
ref new PropertyMetadata(nullptr, ref new PropertyChangedCallback(&Equation::OnCustomDependencyPropertyChanged)));
}
if (!s_obliqueAsymptotesProperty)
{
s_obliqueAsymptotesProperty = DependencyProperty::Register(
EquationProperties::ObliqueAsymptotes,
IObservableVector<String ^>::typeid,
Equation::typeid,
ref new PropertyMetadata(nullptr, ref new PropertyChangedCallback(&Equation::OnCustomDependencyPropertyChanged)));
}
if (!s_tooComplexFeaturesProperty)
{
s_tooComplexFeaturesProperty = DependencyProperty::Register(
EquationProperties::TooComplexFeatures,
int ::typeid,
Equation::typeid,
ref new PropertyMetadata(nullptr, ref new PropertyChangedCallback(&Equation::OnCustomDependencyPropertyChanged)));
}
if (!s_analysisErrorProperty)
{
s_analysisErrorProperty = DependencyProperty::Register(
EquationProperties::AnalysisError,
int ::typeid,
Equation::typeid,
ref new PropertyMetadata(nullptr, ref new PropertyChangedCallback(&Equation::OnCustomDependencyPropertyChanged)));
}
}
void Equation::OnCustomDependencyPropertyChanged(DependencyObject^ obj, DependencyPropertyChangedEventArgs^ args)
void Equation::OnCustomDependencyPropertyChanged(DependencyObject ^ obj, DependencyPropertyChangedEventArgs ^ args)
{
if (auto eq = static_cast<Equation^>(obj))
if (auto eq = static_cast<Equation ^>(obj))
{
String^ propertyName = nullptr;
String ^ propertyName = nullptr;
if (args->Property == s_expressionProperty)
{
propertyName = EquationProperties::Expression;
@ -69,6 +286,74 @@ namespace GraphControl
{
propertyName = EquationProperties::LineColor;
}
else if (args->Property == s_isAnalysisUpdatedProperty)
{
propertyName = EquationProperties::IsAnalysisUpdated;
}
else if (args->Property == s_xInterceptProperty)
{
propertyName = EquationProperties::XIntercept;
}
else if (args->Property == s_yInterceptProperty)
{
propertyName = EquationProperties::YIntercept;
}
else if (args->Property == s_parityProperty)
{
propertyName = EquationProperties::Parity;
}
else if (args->Property == s_periodicityDirectionProperty)
{
propertyName = EquationProperties::PeriodicityDirection;
}
else if (args->Property == s_periodicityExpressionProperty)
{
propertyName = EquationProperties::PeriodicityExpression;
}
else if (args->Property == s_minimaProperty)
{
propertyName = EquationProperties::Minima;
}
else if (args->Property == s_maximaProperty)
{
propertyName = EquationProperties::Maxima;
}
else if (args->Property == s_domainProperty)
{
propertyName = EquationProperties::Domain;
}
else if (args->Property == s_rangeProperty)
{
propertyName = EquationProperties::Range;
}
else if (args->Property == s_inflectionPointsProperty)
{
propertyName = EquationProperties::InflectionPoints;
}
else if (args->Property == s_monotonicityProperty)
{
propertyName = EquationProperties::Monotonicity;
}
else if (args->Property == s_verticalAsymptotesProperty)
{
propertyName = EquationProperties::VerticalAsymptotes;
}
else if (args->Property == s_horizontalAsymptotesProperty)
{
propertyName = EquationProperties::HorizontalAsymptotes;
}
else if (args->Property == s_obliqueAsymptotesProperty)
{
propertyName = EquationProperties::ObliqueAsymptotes;
}
else if (args->Property == s_tooComplexFeaturesProperty)
{
propertyName = EquationProperties::TooComplexFeatures;
}
else if (args->Property == s_analysisErrorProperty)
{
propertyName = EquationProperties::AnalysisError;
}
eq->PropertyChanged(eq, propertyName);
}
@ -77,10 +362,7 @@ namespace GraphControl
wstring Equation::GetRequest()
{
wstringstream ss{};
ss << GetRequestHeader()
<< GetExpression()
<< GetLineColor()
<< L"</mfenced></mrow>";
ss << GetRequestHeader() << GetExpression() << GetLineColor() << L"</mfenced></mrow>";
return ss.str();
}

View File

@ -17,6 +17,7 @@ namespace GraphControl
[Windows::UI::Xaml::Data::Bindable] public ref class Equation sealed : public Windows::UI::Xaml::FrameworkElement
{
public:
Equation()
{
}
@ -60,17 +61,373 @@ namespace GraphControl
}
void set(Windows::UI::Xaml::Media::SolidColorBrush^ value)
{
if (value == nullptr || LineColor == nullptr || (value->Color.A != LineColor->Color.A) || (value->Color.R != LineColor->Color.R) || (value->Color.G != LineColor->Color.G)
|| (value->Color.B != LineColor->Color.B))
{
SetValue(s_lineColorProperty, value);
}
if (value == nullptr || LineColor == nullptr || (value->Color.A != LineColor->Color.A) || (value->Color.R != LineColor->Color.R)
|| (value->Color.G != LineColor->Color.G) || (value->Color.B != LineColor->Color.B))
SetValue(s_lineColorProperty, value);
}
}
#pragma endregion
internal:
event PropertyChangedEventHandler^ PropertyChanged;
#pragma region Key Graph Features
#pragma region bool IsAnalysisUpdated DependencyProperty
static property Windows::UI::Xaml::DependencyProperty^ IsAnalysisUpdatedProperty
{
Windows::UI::Xaml::DependencyProperty^ get()
{
return s_isAnalysisUpdatedProperty;
}
}
property bool IsAnalysisUpdated
{
bool get()
{
return static_cast<bool>(GetValue(s_isAnalysisUpdatedProperty));
}
void set(bool value)
{
SetValue(s_isAnalysisUpdatedProperty, value);
}
}
#pragma endregion
#pragma region Platform::String ^ XIntercept DependencyProperty
static property Windows::UI::Xaml::DependencyProperty^ XInterceptProperty
{
Windows::UI::Xaml::DependencyProperty^ get()
{
return s_xInterceptProperty;
}
}
property Platform::String^ XIntercept
{
Platform::String^ get()
{
return static_cast<Platform::String^>(GetValue(s_xInterceptProperty));
}
void set(Platform::String^ value)
{
SetValue(s_xInterceptProperty, value);
}
}
#pragma endregion
#pragma region Platform::String ^ YIntercept DependencyProperty
static property Windows::UI::Xaml::DependencyProperty^ YInterceptProperty
{
Windows::UI::Xaml::DependencyProperty^ get()
{
return s_yInterceptProperty;
}
}
property Platform::String^ YIntercept
{
Platform::String^ get()
{
return static_cast<Platform::String^>(GetValue(s_yInterceptProperty));
}
void set(Platform::String^ value)
{
SetValue(s_yInterceptProperty, value);
}
}
#pragma endregion
#pragma region int Parity DependencyProperty
static property Windows::UI::Xaml::DependencyProperty^ ParityProperty
{
Windows::UI::Xaml::DependencyProperty^ get()
{
return s_parityProperty;
}
}
property int Parity
{
int get()
{
return static_cast<int>(GetValue(s_parityProperty));
}
void set(int value)
{
SetValue(s_parityProperty, value);
}
}
#pragma endregion
#pragma region int Periodicity DependencyProperty
static property Windows::UI::Xaml::DependencyProperty^ PeriodicityDirectionProperty
{
Windows::UI::Xaml::DependencyProperty^ get()
{
return s_periodicityDirectionProperty;
}
}
property int PeriodicityDirection
{
int get()
{
return static_cast<int>(GetValue(s_periodicityDirectionProperty));
}
void set(int value)
{
SetValue(s_periodicityDirectionProperty, value);
}
}
#pragma endregion
#pragma region Platform::String ^ PeriodicityExpression DependencyProperty
static property Windows::UI::Xaml::DependencyProperty^ PeriodicityExpressionProperty
{
Windows::UI::Xaml::DependencyProperty^ get()
{
return s_periodicityExpressionProperty;
}
}
property Platform::String ^ PeriodicityExpression
{
Platform::String ^ get()
{
return static_cast<Platform::String ^>(GetValue(s_periodicityExpressionProperty));
}
void set(Platform::String ^ value)
{
SetValue(s_periodicityExpressionProperty, value);
}
}
#pragma endregion
#pragma region Windows::Foundation::Collections::IVector < Platform::String ^ > ^ Minima DependencyProperty
static property Windows::UI::Xaml::DependencyProperty^ MinimaProperty
{
Windows::UI::Xaml::DependencyProperty^ get()
{
return s_minimaProperty;
}
}
property Windows::Foundation::Collections::IVector<Platform::String^> ^ Minima
{
Windows::Foundation::Collections::IVector<Platform::String^> ^ get()
{
return static_cast<Windows::Foundation::Collections::IVector<Platform::String^> ^>(GetValue(s_minimaProperty));
}
void set(Windows::Foundation::Collections::IVector<Platform::String^> ^ value)
{
SetValue(s_minimaProperty, value);
}
}
#pragma endregion
#pragma region Windows::Foundation::Collections::IVector < Platform::String ^ > ^ Maxima DependencyProperty
static property Windows::UI::Xaml::DependencyProperty^ MaximaProperty
{
Windows::UI::Xaml::DependencyProperty^ get()
{
return s_maximaProperty;
}
}
property Windows::Foundation::Collections::IVector<Platform::String^> ^ Maxima
{
Windows::Foundation::Collections::IVector<Platform::String^> ^ get()
{
return static_cast<Windows::Foundation::Collections::IVector<Platform::String^> ^>(GetValue(s_maximaProperty));
}
void set(Windows::Foundation::Collections::IVector<Platform::String^> ^ value)
{
SetValue(s_maximaProperty, value);
}
}
#pragma endregion
#pragma region Platform::String ^ Domain DependencyProperty
static property Windows::UI::Xaml::DependencyProperty^ DomainProperty
{
Windows::UI::Xaml::DependencyProperty^ get()
{
return s_domainProperty;
}
}
property Platform::String^ Domain
{
Platform::String^ get()
{
return static_cast<Platform::String^>(GetValue(s_domainProperty));
}
void set(Platform::String^ value)
{
SetValue(s_domainProperty, value);
}
}
#pragma endregion
#pragma region Platform::String ^ Range DependencyProperty
static property Windows::UI::Xaml::DependencyProperty^ RangeProperty
{
Windows::UI::Xaml::DependencyProperty^ get()
{
return s_rangeProperty;
}
}
property Platform::String^ Range
{
Platform::String^ get()
{
return static_cast<Platform::String^>(GetValue(s_rangeProperty));
}
void set(Platform::String^ value)
{
SetValue(s_rangeProperty, value);
}
}
#pragma endregion
#pragma region Windows::Foundation::Collections::IVector < Platform::String ^ > ^ InflectionPoints DependencyProperty
static property Windows::UI::Xaml::DependencyProperty^ InflectionPointsProperty
{
Windows::UI::Xaml::DependencyProperty^ get()
{
return s_inflectionPointsProperty;
}
}
property Windows::Foundation::Collections::IVector<Platform::String^> ^ InflectionPoints
{
Windows::Foundation::Collections::IVector<Platform::String^> ^ get()
{
return static_cast<Windows::Foundation::Collections::IVector<Platform::String^> ^>(GetValue(s_inflectionPointsProperty));
}
void set(Windows::Foundation::Collections::IVector<Platform::String^> ^ value)
{
SetValue(s_inflectionPointsProperty, value);
}
}
#pragma endregion
#pragma region Windows::Foundation::Collections::IObservableMap < Platform::String ^, Platform::String ^ > ^ Monotonicity DependencyProperty
static property Windows::UI::Xaml::DependencyProperty^ MonotonicityProperty
{
Windows::UI::Xaml::DependencyProperty^ get()
{
return s_monotonicityProperty;
}
}
property Windows::Foundation::Collections::IObservableMap<Platform::String^, Platform::String ^> ^ Monotonicity
{
Windows::Foundation::Collections::IObservableMap<Platform::String^, Platform::String ^> ^ get()
{
return static_cast<Windows::Foundation::Collections::IObservableMap<Platform::String^, Platform::String ^> ^>(GetValue(s_monotonicityProperty));
}
void set(Windows::Foundation::Collections::IObservableMap<Platform::String^, Platform::String ^> ^ value)
{
SetValue(s_monotonicityProperty, value);
}
}
#pragma endregion
#pragma region Windows::Foundation::Collections::IVector < Platform::String ^ > ^ VerticalAsymptotes DependencyProperty
static property Windows::UI::Xaml::DependencyProperty^ VerticalAsymptotesProperty
{
Windows::UI::Xaml::DependencyProperty^ get()
{
return s_verticalAsymptotesProperty;
}
}
property Windows::Foundation::Collections::IVector<Platform::String^> ^ VerticalAsymptotes
{
Windows::Foundation::Collections::IVector<Platform::String^> ^ get()
{
return static_cast<Windows::Foundation::Collections::IVector<Platform::String^> ^>(GetValue(s_verticalAsymptotesProperty));
}
void set(Windows::Foundation::Collections::IVector<Platform::String^> ^ value)
{
SetValue(s_verticalAsymptotesProperty, value);
}
}
#pragma endregion
#pragma region Windows::Foundation::Collections::IVector < Platform::String ^ > ^ HorizontalAsymptotes DependencyProperty
static property Windows::UI::Xaml::DependencyProperty^ HorizontalAsymptotesProperty
{
Windows::UI::Xaml::DependencyProperty^ get()
{
return s_horizontalAsymptotesProperty;
}
}
property Windows::Foundation::Collections::IVector<Platform::String^> ^ HorizontalAsymptotes
{
Windows::Foundation::Collections::IVector<Platform::String^> ^ get()
{
return static_cast<Windows::Foundation::Collections::IVector<Platform::String^> ^>(GetValue(s_horizontalAsymptotesProperty));
}
void set(Windows::Foundation::Collections::IVector<Platform::String^> ^ value)
{
SetValue(s_horizontalAsymptotesProperty, value);
}
}
#pragma endregion
#pragma region Windows::Foundation::Collections::IVector < Platform::String ^ > ^ ObliqueAsymptotes DependencyProperty
static property Windows::UI::Xaml::DependencyProperty^ ObliqueAsymptotesProperty
{
Windows::UI::Xaml::DependencyProperty^ get()
{
return s_obliqueAsymptotesProperty;
}
}
property Windows::Foundation::Collections::IVector<Platform::String^> ^ ObliqueAsymptotes
{
Windows::Foundation::Collections::IVector<Platform::String^> ^ get()
{
return static_cast<Windows::Foundation::Collections::IVector<Platform::String^> ^>(GetValue(s_obliqueAsymptotesProperty));
}
void set(Windows::Foundation::Collections::IVector<Platform::String^> ^ value)
{
SetValue(s_obliqueAsymptotesProperty, value);
}
}
#pragma endregion
#pragma region int TooComplexFeatures DependencyProperty
static property Windows::UI::Xaml::DependencyProperty^ TooComplexFeaturesProperty
{
Windows::UI::Xaml::DependencyProperty^ get()
{
return s_tooComplexFeaturesProperty;
}
}
property int TooComplexFeatures
{
int get()
{
return static_cast<int>(GetValue(s_tooComplexFeaturesProperty));
}
void set(int value)
{
SetValue(s_tooComplexFeaturesProperty, value);
}
}
#pragma endregion
#pragma region int AnalysisError DependencyProperty
static property Windows::UI::Xaml::DependencyProperty ^ AnalysisErrorProperty
{
Windows::UI::Xaml::DependencyProperty ^ get()
{
return s_analysisErrorProperty;
}
}
property int AnalysisError
{
int get()
{
return static_cast<int>(GetValue(s_analysisErrorProperty));
}
void set(int value)
{
SetValue(s_analysisErrorProperty, value);
}
}
#pragma endregion
internal : event PropertyChangedEventHandler ^ PropertyChanged;
std::wstring GetRequest();
@ -84,5 +441,22 @@ namespace GraphControl
private:
static Windows::UI::Xaml::DependencyProperty ^ s_expressionProperty;
static Windows::UI::Xaml::DependencyProperty ^ s_lineColorProperty;
static Windows::UI::Xaml::DependencyProperty ^ s_isAnalysisUpdatedProperty;
static Windows::UI::Xaml::DependencyProperty ^ s_xInterceptProperty;
static Windows::UI::Xaml::DependencyProperty ^ s_yInterceptProperty;
static Windows::UI::Xaml::DependencyProperty ^ s_parityProperty;
static Windows::UI::Xaml::DependencyProperty ^ s_periodicityDirectionProperty;
static Windows::UI::Xaml::DependencyProperty ^ s_periodicityExpressionProperty;
static Windows::UI::Xaml::DependencyProperty ^ s_minimaProperty;
static Windows::UI::Xaml::DependencyProperty ^ s_maximaProperty;
static Windows::UI::Xaml::DependencyProperty ^ s_domainProperty;
static Windows::UI::Xaml::DependencyProperty ^ s_rangeProperty;
static Windows::UI::Xaml::DependencyProperty ^ s_inflectionPointsProperty;
static Windows::UI::Xaml::DependencyProperty ^ s_monotonicityProperty;
static Windows::UI::Xaml::DependencyProperty ^ s_verticalAsymptotesProperty;
static Windows::UI::Xaml::DependencyProperty ^ s_horizontalAsymptotesProperty;
static Windows::UI::Xaml::DependencyProperty ^ s_obliqueAsymptotesProperty;
static Windows::UI::Xaml::DependencyProperty ^ s_tooComplexFeaturesProperty;
static Windows::UI::Xaml::DependencyProperty ^ s_analysisErrorProperty;
};
}

View File

@ -8,6 +8,7 @@
namespace GraphControl
{
delegate void EquationChangedEventHandler();
delegate void VisibilityChangedEventHandler(Equation ^ sender);
public
ref class EquationCollection sealed : public Windows::Foundation::Collections::IObservableVector<GraphControl::Equation ^>
@ -151,16 +152,16 @@ public
private:
void OnEquationPropertyChanged(GraphControl::Equation ^, Platform::String ^ propertyName)
{
if (propertyName == L"LineColor")
if (propertyName == EquationProperties::LineColor)
{
EquationStyleChanged();
}
else
else if (propertyName == EquationProperties::Expression)
{
EquationChanged();
}
}
private:
Platform::Collections::Vector<GraphControl::Equation ^> ^ m_vector;
std::vector<Windows::Foundation::EventRegistrationToken> m_tokens;

View File

@ -3,6 +3,8 @@
#include "pch.h"
#include "Grapher.h"
#include "IBitmap.h"
#include "../../CalcViewModel/GraphingCalculatorEnums.h"
using namespace Graphing;
using namespace GraphControl;
@ -37,6 +39,9 @@ namespace
constexpr auto s_X = L"x";
constexpr auto s_Y = L"y";
constexpr auto s_getGraphOpeningTags = L"<math xmlns=\"http://www.w3.org/1998/Math/MathML\"><mrow><mi>show2d</mi><mfenced separators=\"\">";
constexpr auto s_getGraphClosingTags = L"</mfenced></mrow></math>";
// Helper function for converting a pointer position to a position that the graphing engine will understand.
// posX/posY are the pointer position elements and width,height are the dimensions of the graph surface.
// The graphing engine interprets x,y position between the range [-1, 1].
@ -61,6 +66,8 @@ namespace GraphControl
, m_Moving{ false }
{
m_solver->ParsingOptions().SetFormatType(FormatType::MathML);
m_solver->FormatOptions().SetFormatType(FormatType::MathML);
m_solver->FormatOptions().SetMathMLPrefix(wstring(L"mml"));
DefaultStyleKey = StringReference(s_defaultStyleKey);
@ -380,7 +387,7 @@ namespace GraphControl
if (!validEqs.empty())
{
wstringstream ss{};
ss << L"<math xmlns=\"http://www.w3.org/1998/Math/MathML\"><mrow><mi>show2d</mi><mfenced separators=\"\">";
ss << s_getGraphOpeningTags;
int numValidEquations = 0;
for (Equation ^ eq : validEqs)
@ -393,7 +400,7 @@ namespace GraphControl
ss << eq->GetRequest();
}
ss << L"</mfenced></mrow></math>";
ss << s_getGraphClosingTags;
wstring request = ss.str();
unique_ptr<IExpression> graphExpression;
@ -407,6 +414,7 @@ namespace GraphControl
m_renderMain->Graph = m_graph;
UpdateVariables();
UpdateKeyGraphFeatures();
}
}
}
@ -420,6 +428,7 @@ namespace GraphControl
m_renderMain->Graph = m_graph;
UpdateVariables();
UpdateKeyGraphFeatures();
}
}
}
@ -436,6 +445,105 @@ namespace GraphControl
}
}
shared_ptr<IGraph> Grapher::GetGraph(GraphControl::Equation ^ equation)
{
std::shared_ptr<Graphing::IGraph> graph = m_solver->CreateGrapher();
wstringstream ss{};
ss << s_getGraphOpeningTags;
ss << equation->GetRequest();
ss << s_getGraphClosingTags;
wstring request = ss.str();
unique_ptr<IExpression> graphExpression;
if (graphExpression = m_solver->ParseInput(request))
{
if (graph->TryInitialize(graphExpression.get()))
{
return graph;
}
}
return nullptr;
}
void Grapher::UpdateKeyGraphFeatures()
{
auto equations = GetValidEquations();
for (auto equation : equations)
{
equation->IsAnalysisUpdated = false;
if (auto graph = GetGraph(equation))
{
if (auto analyzer = graph->GetAnalyzer())
{
if (analyzer->CanFunctionAnalysisBePerformed())
{
if (S_OK
== analyzer->PerformFunctionAnalysis(
(Graphing::Analyzer::NativeAnalysisType)Graphing::Analyzer::PerformAnalysisType::PerformAnalysisType_All))
{
Graphing::IGraphFunctionAnalysisData functionAnalysisData = m_solver->Analyze(analyzer.get());
{
equation->XIntercept = ref new String(functionAnalysisData.Zeros.c_str());
equation->YIntercept = ref new String(functionAnalysisData.YIntercept.c_str());
equation->Domain = ref new String(functionAnalysisData.Domain.c_str());
equation->Range = ref new String(functionAnalysisData.Range.c_str());
equation->Parity = functionAnalysisData.Parity;
equation->PeriodicityDirection = functionAnalysisData.PeriodicityDirection;
equation->PeriodicityExpression = ref new String(functionAnalysisData.PeriodicityExpression.c_str());
equation->Minima = ConvertWStringVector(functionAnalysisData.Minima);
equation->Maxima = ConvertWStringVector(functionAnalysisData.Maxima);
equation->InflectionPoints = ConvertWStringVector(functionAnalysisData.InflectionPoints);
equation->Monotonicity = ConvertWStringIntMap(functionAnalysisData.MonotoneIntervals);
equation->VerticalAsymptotes = ConvertWStringVector(functionAnalysisData.VerticalAsymptotes);
equation->HorizontalAsymptotes = ConvertWStringVector(functionAnalysisData.HorizontalAsymptotes);
equation->ObliqueAsymptotes = ConvertWStringVector(functionAnalysisData.ObliqueAsymptotes);
equation->TooComplexFeatures = functionAnalysisData.TooComplexFeatures;
equation->AnalysisError = CalculatorApp::AnalysisErrorType::NoError;
equation->IsAnalysisUpdated = true;
continue;
}
}
}
else
{
equation->AnalysisError = CalculatorApp::AnalysisErrorType::AnalysisNotSupported;
equation->IsAnalysisUpdated = true;
continue;
}
}
}
equation->AnalysisError = CalculatorApp::AnalysisErrorType::AnalysisCouldNotBePerformed;
equation->IsAnalysisUpdated = true;
}
}
IObservableVector<String ^> ^ Grapher::ConvertWStringVector(vector<wstring> inVector)
{
Vector<String ^> ^ outVector = ref new Vector<String ^>();
for (auto v : inVector)
{
outVector->Append(ref new String(v.c_str()));
}
return outVector;
}
IObservableMap<String ^, String ^> ^ Grapher::ConvertWStringIntMap(map<wstring, int> inMap)
{
Map<String ^, String ^> ^ outMap = ref new Map<String ^, String ^>();
;
for (auto m : inMap)
{
outMap->Insert(ref new String(m.first.c_str()), m.second.ToString());
}
return outMap;
}
void Grapher::UpdateVariables()
{
auto updatedVariables = ref new Map<String ^, double>();

View File

@ -7,6 +7,7 @@
#include "DirectX/RenderMain.h"
#include "Equation.h"
#include "EquationCollection.h"
#include "IGraphAnalyzer.h"
#include "IMathSolver.h"
#include "Common.h"
@ -162,7 +163,7 @@ public
}
}
property Windows::Foundation::Point TraceLocation
property Windows::Foundation::Point TraceLocation
{
Windows::Foundation::Point get()
{
@ -170,7 +171,6 @@ public
}
}
property Windows::Foundation::Point ActiveTraceCursorPosition
{
Windows::Foundation::Point get()
@ -228,7 +228,9 @@ public
void UpdateGraphOptions(Graphing::IGraphingOptions& options, const std::vector<Equation ^>& validEqs);
std::vector<Equation ^> GetValidEquations();
void SetGraphArgs();
std::shared_ptr<Graphing::IGraph> GetGraph(GraphControl::Equation ^ equation);
void UpdateVariables();
void UpdateKeyGraphFeatures();
void OnForceProportionalAxesChanged(Windows::UI::Xaml::DependencyPropertyChangedEventArgs ^ args);
@ -247,6 +249,8 @@ public
void HandleTracingMovementTick(Object ^ sender, Object ^ e);
void HandleKey(bool keyDown, Windows::System::VirtualKey key);
Windows::Foundation::Collections::IObservableVector<Platform::String ^> ^ ConvertWStringVector(std::vector<std::wstring> inVector);
Windows::Foundation::Collections::IObservableMap<Platform::String ^, Platform::String ^> ^ ConvertWStringIntMap(std::map<std::wstring, int> inMap);
private:
DX::RenderMain ^ m_renderMain = nullptr;
@ -283,7 +287,7 @@ public
bool m_KeysPressed[5];
bool m_Moving;
Windows::UI::Xaml::DispatcherTimer ^ m_TracingTrackingTimer;
Windows::UI::Xaml::DispatcherTimer ^ m_TracingTrackingTimer;
public:
Windows::Storage::Streams::RandomAccessStreamReference ^ GetGraphBitmapStream();

View File

@ -42,8 +42,8 @@
<MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
<AppContainerApplication>true</AppContainerApplication>
<ApplicationType>Windows Store</ApplicationType>
<WindowsTargetPlatformVersion Condition="'$(WindowsTargetPlatformVersion)' == ''">10.0.18970.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformMinVersion>10.0.18362.0</WindowsTargetPlatformMinVersion>
<WindowsTargetPlatformVersion Condition="'$(WindowsTargetPlatformVersion)' == ''">10.0.19019.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformMinVersion>10.0.17134.0</WindowsTargetPlatformMinVersion>
<ApplicationTypeRevision>10.0</ApplicationTypeRevision>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

View File

@ -74,4 +74,10 @@
<ItemGroup>
<None Include="$(ProjectDir)\GraphingImplOverrides.props" />
</ItemGroup>
<ItemGroup>
<CopyFileToFolders Include="$(GraphingImplDll)" />
<CopyFileToFolders Include="$(GraphingEngineDll)" />
<CopyFileToFolders Include="$(GraphingImplDll)" />
<CopyFileToFolders Include="$(GraphingEngineDll)" />
</ItemGroup>
</Project>

View File

@ -2,7 +2,6 @@
#include <memory>
#include <string>
#ifndef GRAPHINGAPI
#ifdef GRAPHING_ENGINE_IMPL
#define GRAPHINGAPI __declspec(dllexport)

View File

@ -384,4 +384,189 @@ namespace Graphing
DashDotDot
};
}
namespace Analyzer {
// Graph Analyzer Messages
enum GraphAnalyzerMessage
{
// "No data"
GraphAnalyzerMessage_None = 0,
// "No zeros"
GraphAnalyzerMessage_NoZeros = 1,
// "No y-intercept"
GraphAnalyzerMessage_NoYIntercept = 2,
// "No minima"
GraphAnalyzerMessage_NoMinima = 3,
// "No maxima"
GraphAnalyzerMessage_NoMaxima = 4,
// "No inflection points"
GraphAnalyzerMessage_NoInflectionPoints = 5,
// "No vertical asymptotes"
GraphAnalyzerMessage_NoVerticalAsymptotes = 6,
// "No horizontal asymptotes"
GraphAnalyzerMessage_NoHorizontalAsymptotes = 7,
// "No oblique asymptotes"
GraphAnalyzerMessage_NoObliqueAsymptotes = 8,
// "Not able to calculate"
GraphAnalyzerMessage_NotAbleToCalculate = 9,
// "Not able to mark all graph features"
GraphAnalyzerMessage_NotAbleToMarkAllGraphFeatures = 10,
// These features are too complex for {APPLICATION_NAME} to calculate
GraphAnalyzerMessage_TheseFeaturesAreTooComplexToCalculate = 11,
// "This feature is too complex for {APPLICATION_NAME} to calculate"
GraphAnalyzerMessage_ThisFeatureIsTooComplexToCalculate = 12
};
// define which data should be filled into result object
enum AnalysisType
{
// fill domain data
AnalysisType_Domain = 0,
// fill range data
AnalysisType_Range = 1,
// fill parity data
AnalysisType_Parity = 2,
// fill zeros
AnalysisType_Zeros = 3,
// fill interception with y axis
AnalysisType_YIntercept = 4,
// fill minima
AnalysisType_Minima = 5,
// fill maxima
AnalysisType_Maxima = 6,
// fill inflection points
AnalysisType_InflectionPoints = 7,
// fill vertical asymptotes
AnalysisType_VerticalAsymptotes = 8,
// fill horizontal asymptotes
AnalysisType_HorizontalAsymptotes = 9,
// fill oblique asymptotes
AnalysisType_ObliqueAsymptotes = 10,
// fill monotonicity
AnalysisType_Monotonicity = 11,
// fill period
AnalysisType_Period = 12
};
// define which additional data should be calculated
enum class PerformAnalysisType
{
// Calculate nothing
//PerformAnalysisType_None = 0x0,
// Calculate domain data
PerformAnalysisType_Domain = 0x01,
// Calculate range data
PerformAnalysisType_Range = 0x02,
// Calculate parity data
PerformAnalysisType_Parity = 0x04,
// Calculate zeros and interception with y axis
PerformAnalysisType_InterceptionPointsWithXAndYAxis = 0x08,
// Calculate Extrema and inflection points
PerformAnalysisType_CriticalPoints = 0x10,
// Calculate asymptotes
PerformAnalysisType_Asymptotes = 0x20,
// Calculate monotonicity
PerformAnalysisType_Monotonicity = 0x40,
// Calculate period
PerformAnalysisType_Period = 0x80,
// Calculate all additional data
PerformAnalysisType_All = 0xFF
};
// function parity for function analysis
enum class FunctionParityType
{
// parity not calculated or not possible to calculate
FunctionParityType_Unknown = 0,
// parity is odd
FunctionParityType_Odd = 1,
// parity is even
FunctionParityType_Even = 2,
// function is not odd nor even
FunctionParityType_None = 3
};
// monotonicity direction for function analysis
enum class FunctionMonotonicityType
{
// unknown or not calculated
FunctionMonotonicityType_Unknown = 0,
// ascending monotonicity on interval
FunctionMonotonicityType_Ascending = 1,
// descending monotonicity on interval
FunctionMonotonicityType_Descending = 2,
// constant monotonicity on interval
FunctionMonotonicityType_Constant = 3
};
// asymptote description for function analysis
enum class AsymptoteType
{
// unknown or not calculated
AsymptoteType_Unknown = 0,
// when x goes to positive infinity
AsymptoteType_PositiveInfinity = 1,
// when x goes to negative infinity
AsymptoteType_NegativeInfinity = 2,
// when x goes to positive or negative infinity
AsymptoteType_AnyInfinity = 3
};
// function periodicity for function analysis
enum class FunctionPeriodicityType
{
// periodicity not calculated or not possible to calculate
FunctionPeriodicityType_Unknown = 0,
// parity is odd
FunctionPeriodicityType_Periodic = 1,
// parity is even
FunctionPeriodicityType_NotPeriodic = 2
};
}
}

View File

@ -4,8 +4,8 @@
namespace Graphing
{
struct IBitmap
struct IBitmap
{
virtual const std::vector<BYTE>& GetData() const = 0;
};
virtual const std::vector<BYTE>& GetData() const = 0;
};
}

View File

@ -1,6 +1,7 @@
#pragma once
#include "Common.h"
#include "IGraphAnalyzer.h"
#include "IGraphingOptions.h"
#include "IGraphRenderer.h"
#include "IEquation.h"
@ -16,12 +17,14 @@ namespace Graphing
virtual IGraphingOptions& GetOptions() = 0;
virtual std::vector<std::shared_ptr<IVariable>> GetVariables() = 0;
virtual std::vector<std::shared_ptr<Graphing::IVariable>> GetVariables() = 0;
virtual void SetArgValue(std::wstring variableName, double value) = 0;
virtual std::shared_ptr< Renderer::IGraphRenderer > GetRenderer() const = 0;
virtual std::shared_ptr<Renderer::IGraphRenderer> GetRenderer() const = 0;
virtual bool TryResetSelection() = 0;
virtual std::shared_ptr< Graphing::Analyzer::IGraphAnalyzer > GetAnalyzer() const = 0;
};
}

View File

@ -0,0 +1,21 @@
#pragma once
#include "Common.h"
#include "GraphingEnums.h"
#include <string>
#include <vector>
#include <map>
namespace Graphing::Analyzer
{
typedef unsigned int NativeAnalysisType; // PerformAnalysisType
struct IGraphAnalyzer : public NonCopyable, public NonMoveable
{
virtual ~IGraphAnalyzer() = default;
virtual bool CanFunctionAnalysisBePerformed() = 0;
virtual HRESULT PerformFunctionAnalysis(NativeAnalysisType analysisType) = 0;
virtual HRESULT GetAnalysisTypeCaption(const AnalysisType type, std::wstring& captionOut) const = 0;
virtual HRESULT GetMessage(const GraphAnalyzerMessage msg, std::wstring& msgOut) const = 0;
};
}

View File

@ -1,11 +1,15 @@
#pragma once
#include "Common.h"
#include "IBitmap.h"
struct ID2D1Factory;
struct ID2D1RenderTarget;
namespace Graphing
{
struct IBitmap;
}
namespace Graphing::Renderer
{
struct IGraphRenderer : public NonCopyable, public NonMoveable

View File

@ -2,10 +2,30 @@
#include "Common.h"
#include "IGraph.h"
#include "IGraphAnalyzer.h"
#include "GraphingEnums.h"
namespace Graphing
{
struct IGraphFunctionAnalysisData
{
std::wstring Domain;
std::wstring Range;
int Parity;
int PeriodicityDirection;
std::wstring PeriodicityExpression;
std::wstring Zeros;
std::wstring YIntercept;
std::vector<std::wstring> Minima;
std::vector<std::wstring> Maxima;
std::vector<std::wstring> InflectionPoints;
std::vector<std::wstring> VerticalAsymptotes;
std::vector<std::wstring> HorizontalAsymptotes;
std::vector<std::wstring> ObliqueAsymptotes;
std::map<std::wstring, int> MonotoneIntervals;
int TooComplexFeatures; // to-do: refactor to remove bitwise flag
};
struct IParsingOptions : public NonCopyable, public NonMoveable
{
virtual ~IParsingOptions() = default;
@ -23,6 +43,7 @@ namespace Graphing
virtual ~IFormatOptions() = default;
virtual void SetFormatType(FormatType type) = 0;
virtual void SetMathMLPrefix(const std::wstring& value) = 0;
};
struct IMathSolver : public NonCopyable, public NonMoveable
@ -41,5 +62,7 @@ namespace Graphing
virtual std::shared_ptr<Graphing::IGraph> CreateGrapher() = 0;
virtual std::wstring Serialize(const IExpression* expression) = 0;
virtual Graphing::IGraphFunctionAnalysisData Analyze(const Graphing::Analyzer::IGraphAnalyzer* analyzer) = 0;
};
}

View File

@ -42,8 +42,8 @@
<MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
<AppContainerApplication>true</AppContainerApplication>
<ApplicationType>Windows Store</ApplicationType>
<WindowsTargetPlatformVersion>10.0.18970.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformMinVersion>10.0.18362.0</WindowsTargetPlatformMinVersion>
<WindowsTargetPlatformVersion>10.0.19019.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformMinVersion>10.0.17134.0</WindowsTargetPlatformMinVersion>
<ApplicationTypeRevision>10.0</ApplicationTypeRevision>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
@ -270,6 +270,7 @@
<ClInclude Include="..\GraphingInterfaces\Common.h" />
<ClInclude Include="..\GraphingInterfaces\GraphingEnums.h" />
<ClInclude Include="..\GraphingInterfaces\IGraph.h" />
<ClInclude Include="..\GraphingInterfaces\IGraphAnalyzer.h" />
<ClInclude Include="..\GraphingInterfaces\IGraphingOptions.h" />
<ClInclude Include="..\GraphingInterfaces\IGraphRenderer.h" />
<ClInclude Include="..\GraphingInterfaces\IMathSolver.h" />

View File

@ -43,5 +43,10 @@
<ClInclude Include="..\GraphingInterfaces\IGraphRenderer.h">
<Filter>GraphingInterfaces</Filter>
</ClInclude>
<ClInclude Include="..\GraphingInterfaces\IEquation.h" />
<ClInclude Include="..\GraphingInterfaces\IEquationOptions.h" />
<ClInclude Include="..\GraphingInterfaces\IGraphAnalyzer.h">
<Filter>GraphingInterfaces</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -11,7 +11,8 @@ namespace MockGraphingImpl
{
public:
void SetFormatType(Graphing::FormatType type) override
{ }
{
}
};
class EvalOptions : public Graphing::IEvalOptions
@ -22,7 +23,12 @@ namespace MockGraphingImpl
{
public:
void SetFormatType(Graphing::FormatType type) override
{ }
{
}
void SetMathMLPrefix(const std::wstring& value) override
{
}
};
class MathSolver : public Graphing::IMathSolver
@ -63,6 +69,11 @@ namespace MockGraphingImpl
return std::wstring{};
}
Graphing::IGraphFunctionAnalysisData IMathSolver::Analyze(const Graphing::Analyzer::IGraphAnalyzer* analyzer)
{
return Graphing::IGraphFunctionAnalysisData{};
}
private:
MockGraphingImpl::ParsingOptions m_parsingOptions;
MockGraphingImpl::EvalOptions m_evalOptions;