GraphControl: refactoring and optimizations (#831)

* GraphControl cleaning

* replace textbox value after submission

* rebase

* rebase

* rebase

* Add filters

* rebase!

* rebase
This commit is contained in:
Rudy Huyn
2019-12-13 16:33:08 -08:00
committed by Eric Wong
parent da38b5a015
commit 534139d67d
33 changed files with 1169 additions and 1393 deletions

View File

@@ -0,0 +1,85 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#include "pch.h"
#include "Equation.h"
using namespace Platform;
using namespace Platform::Collections;
using namespace std;
using namespace Windows::Foundation::Collections;
using namespace Windows::UI;
using namespace Windows::UI::ViewManagement;
using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Media;
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:";
Equation::Equation()
{
}
String ^ Equation::GetRequest()
{
wstringstream ss;
wstring expr{ Expression->Data() };
// Check for unicode characters of less than, less than or equal to, greater than and greater than or equal to.
if (expr.find(L">&#x3E;<") != wstring::npos || expr.find(L">&#x3C;<") != wstring::npos || expr.find(L">&#x2265;<") != wstring::npos
|| expr.find(L">&#x2264;<") != wstring::npos)
{
ss << L"<mrow><mi>plotIneq2D</mi><mfenced separators=\"\">"s;
}
else if (expr.find(L">=<") != wstring::npos)
{
ss << L"<mrow><mi>plotEq2d</mi><mfenced separators=\"\">";
}
else
{
ss << L"<mrow><mi>plot2d</mi><mfenced separators=\"\">";
}
ss << GetExpression() << L"</mfenced></mrow>";
return ref new String(ss.str().c_str());
}
wstring Equation::GetExpression()
{
wstring mathML = Expression->Data();
size_t mathPrefix = 0;
while ((mathPrefix = mathML.find(s_mathPrefix, mathPrefix)) != std::string::npos)
{
mathML.replace(mathPrefix, s_mathPrefix.length(), L"");
mathPrefix += s_mathPrefix.length();
}
return mathML;
}
Color Equation::LineColor::get()
{
return m_LineColor;
}
void Equation::LineColor::set(Color value)
{
if (m_LineColor.R != value.R || m_LineColor.G != value.G || m_LineColor.B != value.B || m_LineColor.A != value.A)
{
m_LineColor = value;
RaisePropertyChanged(L"LineColor");
}
}
Platform::String ^ Equation::LineColorPropertyName::get()
{
return Platform::StringReference(L"LineColor");
}
bool Equation::IsGraphableEquation()
{
return !Expression->IsEmpty() && IsLineEnabled && !HasGraphError;
}
}

View File

@@ -0,0 +1,41 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#pragma once
#include "Utils.h"
#include <string>
namespace GraphControl
{
[Windows::UI::Xaml::Data::Bindable] public ref class Equation sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
{
public:
Equation();
OBSERVABLE_OBJECT();
OBSERVABLE_NAMED_PROPERTY_RW(Platform::String ^, Expression);
OBSERVABLE_NAMED_PROPERTY_RW(bool, IsLineEnabled);
OBSERVABLE_NAMED_PROPERTY_RW(bool, IsValidated);
OBSERVABLE_NAMED_PROPERTY_RW(bool, HasGraphError);
property Windows::UI::Color LineColor
{
Windows::UI::Color get();
void set(Windows::UI::Color value);
}
static property Platform::String
^ LineColorPropertyName { Platform::String ^ get(); }
public : Platform::String
^ GetRequest();
bool IsGraphableEquation();
private:
std::wstring GetExpression();
private:
Windows::UI::Color m_LineColor;
};
}

View File

@@ -0,0 +1,179 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#pragma once
#include "Equation.h"
namespace GraphControl
{
delegate void EquationChangedEventHandler(Equation ^ sender);
delegate void VisibilityChangedEventHandler(Equation ^ sender);
public
ref class EquationCollection sealed : public Windows::Foundation::Collections::IObservableVector<GraphControl::Equation ^>
{
public:
virtual ~EquationCollection()
{
}
#pragma region IIterable
virtual Windows::Foundation::Collections::IIterator< GraphControl::Equation^ >^ First()
{
return m_vector->First();
}
#pragma endregion
#pragma region IVector
virtual property unsigned int Size
{
unsigned int get()
{
return m_vector->Size;
}
}
virtual void Append(GraphControl::Equation ^ value)
{
m_vector->Append(value);
m_tokens.emplace_back(
value->PropertyChanged += ref new Windows::UI::Xaml::Data::PropertyChangedEventHandler(this, &EquationCollection::OnEquationPropertyChanged));
}
virtual void Clear()
{
auto numEqs = m_vector->Size;
for (auto i = 0u; i < numEqs; i++)
{
m_vector->GetAt(i)->PropertyChanged -= m_tokens[i];
}
m_vector->Clear();
m_tokens.clear();
}
virtual GraphControl::Equation
^ GetAt(unsigned int index) { return m_vector->GetAt(index); }
virtual unsigned int GetMany(unsigned int startIndex, Platform::WriteOnlyArray<GraphControl::Equation ^> ^ items)
{
return m_vector->GetMany(startIndex, items);
}
virtual Windows::Foundation::Collections::IVectorView< GraphControl::Equation^ >^ GetView()
{
return m_vector->GetView();
}
virtual Platform::Boolean IndexOf(GraphControl::Equation^ value, unsigned int *index)
{
return m_vector->IndexOf(value, index);
}
virtual void InsertAt(unsigned int index, GraphControl::Equation ^ value)
{
m_vector->InsertAt(index, value);
m_tokens.insert(
m_tokens.begin() + index,
value->PropertyChanged += ref new Windows::UI::Xaml::Data::PropertyChangedEventHandler(this, &EquationCollection::OnEquationPropertyChanged));
}
virtual void RemoveAt(unsigned int index)
{
m_vector->GetAt(index)->PropertyChanged -= m_tokens[index];
m_vector->RemoveAt(index);
m_tokens.erase(m_tokens.begin() + index);
}
virtual void RemoveAtEnd()
{
auto size = m_vector->Size;
if (size > 0)
{
m_vector->GetAt(size - 1)->PropertyChanged -= *m_tokens.rbegin();
m_tokens.erase(m_tokens.end() - 1);
}
m_vector->RemoveAtEnd();
}
virtual void ReplaceAll(const Platform::Array<GraphControl::Equation ^> ^ items)
{
auto size = m_vector->Size;
for (auto i = 0u; i < size; i++)
{
m_vector->GetAt(i)->PropertyChanged -= m_tokens[i];
}
size = items->Length;
m_tokens.resize(size);
for (auto i = 0u; i < size; i++)
{
m_tokens[i] = items[i]->PropertyChanged +=
ref new Windows::UI::Xaml::Data::PropertyChangedEventHandler(this, &EquationCollection::OnEquationPropertyChanged);
}
m_vector->ReplaceAll(items);
}
virtual void SetAt(unsigned int index, GraphControl::Equation ^ value)
{
m_vector->GetAt(index)->PropertyChanged -= m_tokens[index];
m_vector->SetAt(index, value);
m_tokens[index] = value->PropertyChanged +=
ref new Windows::UI::Xaml::Data::PropertyChangedEventHandler(this, &EquationCollection::OnEquationPropertyChanged);
}
#pragma endregion
#pragma region IObservableVector
virtual event Windows::Foundation::Collections::VectorChangedEventHandler< GraphControl::Equation^ >^ VectorChanged
{
Windows::Foundation::EventRegistrationToken add(Windows::Foundation::Collections::VectorChangedEventHandler< GraphControl::Equation^ >^ handler)
{
return m_vector->VectorChanged += handler;
}
void remove(Windows::Foundation::EventRegistrationToken token)
{
m_vector->VectorChanged -= token;
}
}
#pragma endregion
internal:
EquationCollection() :
m_vector(ref new Platform::Collections::Vector< GraphControl::Equation^ >())
{
}
event EquationChangedEventHandler ^ EquationChanged;
event EquationChangedEventHandler ^ EquationStyleChanged;
event EquationChangedEventHandler ^ EquationLineEnabledChanged;
private:
void OnEquationPropertyChanged(Object^ sender, Windows::UI::Xaml::Data::PropertyChangedEventArgs ^ args)
{
auto equation = static_cast<Equation ^>(sender);
auto propertyName = args->PropertyName;
if (propertyName == GraphControl::Equation::LineColorPropertyName)
{
EquationStyleChanged(equation);
}
else if (propertyName == GraphControl::Equation::ExpressionPropertyName)
{
EquationChanged(equation);
}
else if (propertyName == GraphControl::Equation::IsLineEnabledPropertyName)
{
EquationLineEnabledChanged(equation);
}
}
private:
Platform::Collections::Vector<GraphControl::Equation ^> ^ m_vector;
std::vector<Windows::Foundation::EventRegistrationToken> m_tokens;
};
}

View File

@@ -0,0 +1,70 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#include "pch.h"
#include "KeyGraphFeaturesInfo.h"
#include "../../CalcViewModel/GraphingCalculatorEnums.h"
using namespace Platform;
using namespace Platform::Collections;
using namespace std;
using namespace Windows::Foundation::Collections;
using namespace Windows::UI;
using namespace Windows::UI::ViewManagement;
using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Media;
using namespace GraphControl;
using namespace Graphing;
IObservableVector<String ^> ^ KeyGraphFeaturesInfo::ConvertWStringVector(vector<wstring> inVector)
{
auto outVector = ref new Vector<String ^>();
for (auto v : inVector)
{
outVector->Append(ref new String(v.c_str()));
}
return outVector;
}
IObservableMap<String ^, String ^> ^ KeyGraphFeaturesInfo::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;
}
KeyGraphFeaturesInfo ^ KeyGraphFeaturesInfo::Create(IGraphFunctionAnalysisData data)
{
auto res = ref new KeyGraphFeaturesInfo();
res->XIntercept = ref new String(data.Zeros.c_str());
res->YIntercept = ref new String(data.YIntercept.c_str());
res->Domain = ref new String(data.Domain.c_str());
res->Range = ref new String(data.Range.c_str());
res->Parity = data.Parity;
res->PeriodicityDirection = data.PeriodicityDirection;
res->PeriodicityExpression = ref new String(data.PeriodicityExpression.c_str());
res->Minima = ConvertWStringVector(data.Minima);
res->Maxima = ConvertWStringVector(data.Maxima);
res->InflectionPoints = ConvertWStringVector(data.InflectionPoints);
res->Monotonicity = ConvertWStringIntMap(data.MonotoneIntervals);
res->VerticalAsymptotes = ConvertWStringVector(data.VerticalAsymptotes);
res->HorizontalAsymptotes = ConvertWStringVector(data.HorizontalAsymptotes);
res->ObliqueAsymptotes = ConvertWStringVector(data.ObliqueAsymptotes);
res->TooComplexFeatures = data.TooComplexFeatures;
res->AnalysisError = CalculatorApp::AnalysisErrorType::NoError;
return res;
}
KeyGraphFeaturesInfo ^ KeyGraphFeaturesInfo::Create(CalculatorApp::AnalysisErrorType type)
{
auto res = ref new KeyGraphFeaturesInfo();
res->AnalysisError = type;
return res;
}

View File

@@ -0,0 +1,51 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#pragma once
#include "Utils.h"
namespace Graphing
{
struct IGraphFunctionAnalysisData;
}
namespace CalculatorApp
{
enum AnalysisErrorType;
}
namespace GraphControl
{
public
ref class KeyGraphFeaturesInfo sealed
{
public:
PROPERTY_R(Platform::String ^, XIntercept);
PROPERTY_R(Platform::String ^, YIntercept);
PROPERTY_R(int, Parity);
PROPERTY_R(int, PeriodicityDirection);
PROPERTY_R(Platform::String ^, PeriodicityExpression);
PROPERTY_R(Windows::Foundation::Collections::IVector<Platform::String ^> ^, Minima);
PROPERTY_R(Windows::Foundation::Collections::IVector<Platform::String ^> ^, Maxima);
PROPERTY_R(Platform::String ^, Domain);
PROPERTY_R(Platform::String ^, Range);
PROPERTY_R(Windows::Foundation::Collections::IVector<Platform::String ^> ^, InflectionPoints);
PROPERTY_R(SINGLE_ARG(Windows::Foundation::Collections::IObservableMap<Platform::String ^, Platform::String ^> ^), Monotonicity);
PROPERTY_R(Windows::Foundation::Collections::IVector<Platform::String ^> ^, VerticalAsymptotes);
PROPERTY_R(Windows::Foundation::Collections::IVector<Platform::String ^> ^, HorizontalAsymptotes);
PROPERTY_R(Windows::Foundation::Collections::IVector<Platform::String ^> ^, ObliqueAsymptotes);
PROPERTY_R(int, TooComplexFeatures);
PROPERTY_R(int, AnalysisError);
internal:
static KeyGraphFeaturesInfo ^ Create(Graphing::IGraphFunctionAnalysisData data);
static KeyGraphFeaturesInfo ^ Create(CalculatorApp::AnalysisErrorType type);
private:
static Windows::Foundation::Collections::IObservableVector<Platform::String ^> ^ ConvertWStringVector(std::vector<std::wstring> inVector);
static Windows::Foundation::Collections::
IObservableMap<Platform::String ^, Platform::String ^> ^ ConvertWStringIntMap(std::map<std::wstring, int> inMap);
};
}