Refactor Equation to be treated as a model and update Key Graph Features (#791)
* refactor code * update KGF * Rename some functions * Undo comment out of proj file * Pr feedback
This commit is contained in:
@@ -23,9 +23,6 @@ namespace GraphControl
|
||||
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";
|
||||
|
||||
@@ -78,7 +75,6 @@ namespace GraphControl
|
||||
{
|
||||
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);
|
||||
@@ -120,15 +116,6 @@ namespace GraphControl
|
||||
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(
|
||||
@@ -286,10 +273,6 @@ namespace GraphControl
|
||||
{
|
||||
propertyName = EquationProperties::LineColor;
|
||||
}
|
||||
else if (args->Property == s_isAnalysisUpdatedProperty)
|
||||
{
|
||||
propertyName = EquationProperties::IsAnalysisUpdated;
|
||||
}
|
||||
else if (args->Property == s_xInterceptProperty)
|
||||
{
|
||||
propertyName = EquationProperties::XIntercept;
|
||||
|
@@ -14,7 +14,7 @@ namespace GraphControl
|
||||
ref class Equation;
|
||||
delegate void PropertyChangedEventHandler(Equation ^ sender, Platform::String ^ propertyName);
|
||||
|
||||
[Windows::UI::Xaml::Data::Bindable] public ref class Equation sealed : public Windows::UI::Xaml::FrameworkElement
|
||||
[Windows::UI::Xaml::Data::Bindable] public ref class Equation sealed : public Windows::UI::Xaml::DependencyObject
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -70,26 +70,7 @@ namespace GraphControl
|
||||
|
||||
#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
|
||||
{
|
||||
@@ -441,7 +422,6 @@ 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;
|
||||
|
@@ -30,9 +30,7 @@ namespace
|
||||
constexpr auto s_defaultStyleKey = L"GraphControl.Grapher";
|
||||
constexpr auto s_templateKey_SwapChainPanel = L"GraphSurface";
|
||||
|
||||
constexpr auto s_propertyName_EquationTemplate = L"EquationTemplate";
|
||||
constexpr auto s_propertyName_Equations = L"Equations";
|
||||
constexpr auto s_propertyName_EquationsSource = L"EquationsSource";
|
||||
constexpr auto s_propertyName_Variables = L"Variables";
|
||||
constexpr auto s_propertyName_ForceProportionalAxes = L"ForceProportionalAxes";
|
||||
|
||||
@@ -54,9 +52,7 @@ namespace
|
||||
|
||||
namespace GraphControl
|
||||
{
|
||||
DependencyProperty ^ Grapher::s_equationTemplateProperty;
|
||||
DependencyProperty ^ Grapher::s_equationsProperty;
|
||||
DependencyProperty ^ Grapher::s_equationsSourceProperty;
|
||||
DependencyProperty ^ Grapher::s_variablesProperty;
|
||||
DependencyProperty ^ Grapher::s_forceProportionalAxesTemplateProperty;
|
||||
|
||||
@@ -160,24 +156,6 @@ namespace GraphControl
|
||||
ref new PropertyMetadata(nullptr, ref new PropertyChangedCallback(&Grapher::OnCustomDependencyPropertyChanged)));
|
||||
}
|
||||
|
||||
if (!s_equationsSourceProperty)
|
||||
{
|
||||
s_equationsSourceProperty = DependencyProperty::Register(
|
||||
StringReference(s_propertyName_EquationsSource),
|
||||
Object::typeid,
|
||||
Grapher::typeid,
|
||||
ref new PropertyMetadata(nullptr, ref new PropertyChangedCallback(&Grapher::OnCustomDependencyPropertyChanged)));
|
||||
}
|
||||
|
||||
if (!s_equationTemplateProperty)
|
||||
{
|
||||
s_equationTemplateProperty = DependencyProperty::Register(
|
||||
StringReference(s_propertyName_EquationTemplate),
|
||||
DataTemplate::typeid,
|
||||
Grapher::typeid,
|
||||
ref new PropertyMetadata(nullptr, ref new PropertyChangedCallback(&Grapher::OnCustomDependencyPropertyChanged)));
|
||||
}
|
||||
|
||||
if (!s_variablesProperty)
|
||||
{
|
||||
s_variablesProperty = DependencyProperty::Register(
|
||||
@@ -206,14 +184,6 @@ namespace GraphControl
|
||||
{
|
||||
self->OnEquationsChanged(args);
|
||||
}
|
||||
else if (args->Property == EquationsSourceProperty)
|
||||
{
|
||||
self->OnEquationsSourceChanged(args);
|
||||
}
|
||||
else if (args->Property == EquationTemplateProperty)
|
||||
{
|
||||
self->OnEquationTemplateChanged(args);
|
||||
}
|
||||
else if (args->Property == ForceProportionalAxesTemplateProperty)
|
||||
{
|
||||
self->OnForceProportionalAxesChanged(args);
|
||||
@@ -230,95 +200,10 @@ namespace GraphControl
|
||||
}
|
||||
}
|
||||
|
||||
void Grapher::OnEquationTemplateChanged(DependencyPropertyChangedEventArgs ^ args)
|
||||
{
|
||||
SyncEquationsWithItemsSource();
|
||||
}
|
||||
|
||||
void Grapher::OnEquationsSourceChanged(DependencyPropertyChangedEventArgs ^ args)
|
||||
{
|
||||
if (m_dataSource && m_tokenDataSourceChanged.Value != 0)
|
||||
{
|
||||
m_dataSource->DataSourceChanged -= m_tokenDataSourceChanged;
|
||||
}
|
||||
|
||||
m_dataSource = args->NewValue ? ref new InspectingDataSource(args->NewValue) : nullptr;
|
||||
if (m_dataSource)
|
||||
{
|
||||
m_tokenDataSourceChanged = m_dataSource->DataSourceChanged +=
|
||||
ref new TypedEventHandler<InspectingDataSource ^, DataSourceChangedEventArgs>(this, &Grapher::OnDataSourceChanged);
|
||||
}
|
||||
|
||||
SyncEquationsWithItemsSource();
|
||||
}
|
||||
|
||||
void Grapher::OnDataSourceChanged(InspectingDataSource ^ sender, DataSourceChangedEventArgs args)
|
||||
{
|
||||
switch (args.Action)
|
||||
{
|
||||
case DataSourceChangedAction::Insert:
|
||||
OnItemsAdded(args.NewStartingIndex, args.NewItemsCount);
|
||||
break;
|
||||
|
||||
case DataSourceChangedAction::Remove:
|
||||
OnItemsRemoved(args.OldStartingIndex, args.OldItemsCount);
|
||||
break;
|
||||
|
||||
case DataSourceChangedAction::Reset:
|
||||
SyncEquationsWithItemsSource();
|
||||
break;
|
||||
|
||||
case DataSourceChangedAction::Replace:
|
||||
OnItemsRemoved(args.OldStartingIndex, args.OldItemsCount);
|
||||
OnItemsAdded(args.NewStartingIndex, args.NewItemsCount);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Grapher::OnItemsAdded(int index, int count)
|
||||
{
|
||||
for (int i = index + count - 1; i >= index; i--)
|
||||
{
|
||||
auto eq = safe_cast<Equation ^>(EquationTemplate->LoadContent());
|
||||
eq->DataContext = m_dataSource->GetAt(i);
|
||||
|
||||
Equations->InsertAt(index, eq);
|
||||
}
|
||||
}
|
||||
|
||||
void Grapher::OnItemsRemoved(int index, int count)
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
Equations->RemoveAt(index);
|
||||
}
|
||||
}
|
||||
|
||||
void Grapher::SyncEquationsWithItemsSource()
|
||||
{
|
||||
Equations->Clear();
|
||||
if (m_dataSource)
|
||||
{
|
||||
auto size = m_dataSource->GetSize();
|
||||
for (auto i = 0u; i < size; i++)
|
||||
{
|
||||
auto eq = safe_cast<Equation ^>(EquationTemplate->LoadContent());
|
||||
eq->DataContext = m_dataSource->GetAt(i);
|
||||
|
||||
Equations->Append(eq);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Grapher::OnEquationsChanged(DependencyPropertyChangedEventArgs ^ args)
|
||||
{
|
||||
if (auto older = static_cast<EquationCollection ^>(args->OldValue))
|
||||
{
|
||||
if (m_tokenEquationsChanged.Value != 0)
|
||||
{
|
||||
older->VectorChanged -= m_tokenEquationsChanged;
|
||||
m_tokenEquationsChanged.Value = 0;
|
||||
}
|
||||
if (m_tokenEquationChanged.Value != 0)
|
||||
{
|
||||
older->EquationChanged -= m_tokenEquationChanged;
|
||||
@@ -334,8 +219,6 @@ namespace GraphControl
|
||||
|
||||
if (auto newer = static_cast<EquationCollection ^>(args->NewValue))
|
||||
{
|
||||
m_tokenEquationsChanged = newer->VectorChanged += ref new VectorChangedEventHandler<Equation ^>(this, &Grapher::OnEquationsVectorChanged);
|
||||
|
||||
m_tokenEquationChanged = newer->EquationChanged += ref new EquationChangedEventHandler(this, &Grapher::OnEquationChanged);
|
||||
|
||||
m_tokenEquationStyleChanged = newer->EquationStyleChanged += ref new EquationChangedEventHandler(this, &Grapher::OnEquationStyleChanged);
|
||||
@@ -344,22 +227,6 @@ namespace GraphControl
|
||||
UpdateGraph();
|
||||
}
|
||||
|
||||
void Grapher::OnEquationsVectorChanged(IObservableVector<Equation ^> ^ sender, IVectorChangedEventArgs ^ event)
|
||||
{
|
||||
if (event->CollectionChange == ::CollectionChange::ItemInserted || event->CollectionChange == ::CollectionChange::ItemChanged)
|
||||
{
|
||||
auto eq = sender->GetAt(event->Index);
|
||||
|
||||
// Don't update the graph unless the equations being added/modified is valid.
|
||||
if (eq->Expression->IsEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
UpdateGraph();
|
||||
}
|
||||
|
||||
void Grapher::OnEquationChanged()
|
||||
{
|
||||
UpdateGraph();
|
||||
@@ -378,6 +245,56 @@ namespace GraphControl
|
||||
}
|
||||
}
|
||||
|
||||
void Grapher::PlotGraph()
|
||||
{
|
||||
UpdateGraph();
|
||||
}
|
||||
|
||||
void Grapher::AnalyzeEquation(Equation ^ equation)
|
||||
{
|
||||
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;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
equation->AnalysisError = CalculatorApp::AnalysisErrorType::AnalysisNotSupported;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
equation->AnalysisError = CalculatorApp::AnalysisErrorType::AnalysisCouldNotBePerformed;
|
||||
}
|
||||
|
||||
void Grapher::UpdateGraph()
|
||||
{
|
||||
if (m_renderMain && m_graph != nullptr)
|
||||
@@ -414,7 +331,6 @@ namespace GraphControl
|
||||
m_renderMain->Graph = m_graph;
|
||||
|
||||
UpdateVariables();
|
||||
UpdateKeyGraphFeatures();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -428,7 +344,6 @@ namespace GraphControl
|
||||
m_renderMain->Graph = m_graph;
|
||||
|
||||
UpdateVariables();
|
||||
UpdateKeyGraphFeatures();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -467,59 +382,6 @@ namespace GraphControl
|
||||
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 ^>();
|
||||
|
@@ -3,7 +3,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "InspectingDataSource.h"
|
||||
#include "DirectX/RenderMain.h"
|
||||
#include "Equation.h"
|
||||
#include "EquationCollection.h"
|
||||
@@ -30,50 +29,6 @@ public
|
||||
|
||||
static void RegisterDependencyProperties();
|
||||
|
||||
#pragma region Windows::UI::Xaml::DataTemplate ^ EquationTemplate DependencyProperty
|
||||
static property Windows::UI::Xaml::DependencyProperty^ EquationTemplateProperty
|
||||
{
|
||||
Windows::UI::Xaml::DependencyProperty^ get()
|
||||
{
|
||||
return s_equationTemplateProperty;
|
||||
}
|
||||
}
|
||||
|
||||
property Windows::UI::Xaml::DataTemplate^ EquationTemplate
|
||||
{
|
||||
Windows::UI::Xaml::DataTemplate^ get()
|
||||
{
|
||||
return static_cast<Windows::UI::Xaml::DataTemplate^>(GetValue(s_equationTemplateProperty));
|
||||
}
|
||||
void set(Windows::UI::Xaml::DataTemplate^ value)
|
||||
{
|
||||
SetValue(s_equationTemplateProperty, value);
|
||||
}
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Platform::Object ^ EquationsSource DependencyProperty
|
||||
static property Windows::UI::Xaml::DependencyProperty^ EquationsSourceProperty
|
||||
{
|
||||
Windows::UI::Xaml::DependencyProperty^ get()
|
||||
{
|
||||
return s_equationsSourceProperty;
|
||||
}
|
||||
}
|
||||
|
||||
property Platform::Object^ EquationsSource
|
||||
{
|
||||
Platform::Object^ get()
|
||||
{
|
||||
return GetValue(s_equationsSourceProperty);
|
||||
}
|
||||
void set(Platform::Object^ value)
|
||||
{
|
||||
SetValue(s_equationsSourceProperty, value);
|
||||
}
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
#pragma region GraphControl::EquationCollection ^ Equations DependencyProperty
|
||||
static property Windows::UI::Xaml::DependencyProperty^ EquationsProperty
|
||||
{
|
||||
@@ -191,6 +146,8 @@ public
|
||||
event Windows::Foundation::EventHandler<Windows::Foundation::Collections::IMap<Platform::String ^, double> ^> ^ VariablesUpdated;
|
||||
void SetVariable(Platform::String ^ variableName, double newValue);
|
||||
Platform::String ^ ConvertToLinear(Platform::String ^ mmlString);
|
||||
void PlotGraph();
|
||||
void AnalyzeEquation(GraphControl::Equation ^ equation);
|
||||
|
||||
protected:
|
||||
#pragma region Control Overrides
|
||||
@@ -213,15 +170,7 @@ public
|
||||
static void OnCustomDependencyPropertyChanged(Windows::UI::Xaml::DependencyObject ^ obj, Windows::UI::Xaml::DependencyPropertyChangedEventArgs ^ args);
|
||||
void OnDependencyPropertyChanged(Windows::UI::Xaml::DependencyObject ^ obj, Windows::UI::Xaml::DependencyProperty ^ p);
|
||||
|
||||
void OnEquationTemplateChanged(Windows::UI::Xaml::DependencyPropertyChangedEventArgs ^ args);
|
||||
|
||||
void OnEquationsSourceChanged(Windows::UI::Xaml::DependencyPropertyChangedEventArgs ^ args);
|
||||
void OnDataSourceChanged(GraphControl::InspectingDataSource ^ sender, GraphControl::DataSourceChangedEventArgs args);
|
||||
|
||||
void OnEquationsChanged(Windows::UI::Xaml::DependencyPropertyChangedEventArgs ^ args);
|
||||
void OnEquationsVectorChanged(
|
||||
Windows::Foundation::Collections::IObservableVector<GraphControl::Equation ^> ^ sender,
|
||||
Windows::Foundation::Collections::IVectorChangedEventArgs ^ event);
|
||||
void OnEquationChanged();
|
||||
void OnEquationStyleChanged();
|
||||
|
||||
@@ -231,16 +180,11 @@ public
|
||||
void SetGraphArgs();
|
||||
std::shared_ptr<Graphing::IGraph> GetGraph(GraphControl::Equation ^ equation);
|
||||
void UpdateVariables();
|
||||
void UpdateKeyGraphFeatures();
|
||||
|
||||
void OnForceProportionalAxesChanged(Windows::UI::Xaml::DependencyPropertyChangedEventArgs ^ args);
|
||||
|
||||
void OnBackgroundColorChanged(const Windows::UI::Color& color);
|
||||
|
||||
void SyncEquationsWithItemsSource();
|
||||
void OnItemsAdded(int index, int count);
|
||||
void OnItemsRemoved(int index, int count);
|
||||
|
||||
void ScaleRange(double centerX, double centerY, double scale);
|
||||
|
||||
void OnCoreKeyDown(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Core::KeyEventArgs ^ e);
|
||||
@@ -259,7 +203,6 @@ public
|
||||
static Windows::UI::Xaml::DependencyProperty ^ s_equationTemplateProperty;
|
||||
|
||||
static Windows::UI::Xaml::DependencyProperty ^ s_equationsSourceProperty;
|
||||
InspectingDataSource ^ m_dataSource;
|
||||
Windows::Foundation::EventRegistrationToken m_tokenDataSourceChanged;
|
||||
|
||||
static Windows::UI::Xaml::DependencyProperty ^ s_equationsProperty;
|
||||
|
@@ -1,245 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
#include "InspectingDataSource.h"
|
||||
|
||||
using namespace Platform;
|
||||
using namespace Platform::Collections;
|
||||
using namespace std;
|
||||
using namespace Windows::Foundation::Collections;
|
||||
using namespace Windows::UI::Xaml::Interop;
|
||||
|
||||
namespace winrt
|
||||
{
|
||||
using namespace winrt::Windows::Foundation;
|
||||
using namespace winrt::Windows::Foundation::Collections;
|
||||
using namespace winrt::Windows::UI::Xaml::Interop;
|
||||
}
|
||||
|
||||
namespace GraphControl
|
||||
{
|
||||
InspectingDataSource::InspectingDataSource(Object^ source)
|
||||
{
|
||||
if (!source)
|
||||
{
|
||||
throw ref new InvalidArgumentException(L"Argument 'source' is null.");
|
||||
}
|
||||
|
||||
auto inspectable = from_cx<winrt::IInspectable>(source);
|
||||
if (auto vector = inspectable.try_as<winrt::IVector<winrt::IInspectable>>())
|
||||
{
|
||||
m_vector = vector;
|
||||
ListenToCollectionChanges();
|
||||
}
|
||||
else if (auto bindableVector = inspectable.try_as<winrt::IBindableVector>())
|
||||
{
|
||||
// The bindable interop interface are abi compatible with the corresponding
|
||||
// WinRT interfaces.
|
||||
|
||||
m_vector = reinterpret_cast<const winrt::IVector<winrt::IInspectable>&>(bindableVector);
|
||||
ListenToCollectionChanges();
|
||||
}
|
||||
else if (auto iterable = inspectable.try_as<winrt::IIterable<winrt::IInspectable>>())
|
||||
{
|
||||
m_vector = WrapIterable(iterable);
|
||||
}
|
||||
else if (auto bindableIterable = inspectable.try_as<winrt::IBindableIterable>())
|
||||
{
|
||||
m_vector = WrapIterable(reinterpret_cast<const winrt::IIterable<winrt::IInspectable> &>(bindableIterable));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw ref new InvalidArgumentException(L"Argument 'source' is not a supported vector.");
|
||||
}
|
||||
}
|
||||
|
||||
InspectingDataSource::~InspectingDataSource()
|
||||
{
|
||||
UnlistenToCollectionChanges();
|
||||
}
|
||||
|
||||
unsigned int InspectingDataSource::GetSize()
|
||||
{
|
||||
return m_vector.Size();
|
||||
}
|
||||
|
||||
Object^ InspectingDataSource::GetAt(unsigned int index)
|
||||
{
|
||||
return to_cx<Object>(m_vector.GetAt(index));
|
||||
}
|
||||
|
||||
optional<unsigned int> InspectingDataSource::IndexOf(Object^ value)
|
||||
{
|
||||
if ((m_vector != nullptr) && value)
|
||||
{
|
||||
uint32_t v;
|
||||
auto inspectable = from_cx<winrt::IInspectable>(value);
|
||||
if (m_vector.IndexOf(inspectable, v))
|
||||
{
|
||||
return v;
|
||||
}
|
||||
}
|
||||
return nullopt;
|
||||
}
|
||||
|
||||
winrt::IVector<winrt::IInspectable> InspectingDataSource::WrapIterable(const winrt::IIterable<winrt::IInspectable>& iterable)
|
||||
{
|
||||
auto vector = winrt::single_threaded_vector<winrt::IInspectable>();
|
||||
auto iterator = iterable.First();
|
||||
while (iterator.HasCurrent())
|
||||
{
|
||||
vector.Append(iterator.Current());
|
||||
iterator.MoveNext();
|
||||
}
|
||||
|
||||
return vector;
|
||||
}
|
||||
|
||||
void InspectingDataSource::UnlistenToCollectionChanges()
|
||||
{
|
||||
if (m_notifyCollectionChanged)
|
||||
{
|
||||
m_notifyCollectionChanged.CollectionChanged(m_eventToken);
|
||||
}
|
||||
else if (m_observableVector)
|
||||
{
|
||||
m_observableVector.VectorChanged(m_eventToken);
|
||||
}
|
||||
else if (m_bindableObservableVector)
|
||||
{
|
||||
m_bindableObservableVector.VectorChanged(m_eventToken);
|
||||
}
|
||||
}
|
||||
|
||||
void InspectingDataSource::ListenToCollectionChanges()
|
||||
{
|
||||
assert(m_vector);
|
||||
if (auto incc = m_vector.try_as<winrt::INotifyCollectionChanged>())
|
||||
{
|
||||
m_eventToken = incc.CollectionChanged([this](
|
||||
const winrt::IInspectable& sender,
|
||||
const winrt::NotifyCollectionChangedEventArgs& e)
|
||||
{
|
||||
OnCollectionChanged(sender, e);
|
||||
});
|
||||
|
||||
m_notifyCollectionChanged = incc;
|
||||
}
|
||||
else if (auto observableVector = m_vector.try_as<winrt::IObservableVector<winrt::IInspectable>>())
|
||||
{
|
||||
m_eventToken = observableVector.VectorChanged([this](
|
||||
const winrt::IObservableVector<winrt::IInspectable>& sender,
|
||||
const winrt::IVectorChangedEventArgs& e)
|
||||
{
|
||||
OnVectorChanged(sender, e);
|
||||
});
|
||||
|
||||
m_observableVector = observableVector;
|
||||
}
|
||||
else if (auto bindableObservableVector = m_vector.try_as<winrt::IBindableObservableVector>())
|
||||
{
|
||||
m_eventToken = bindableObservableVector.VectorChanged([this](
|
||||
winrt::IBindableObservableVector const& vector,
|
||||
winrt::IInspectable const& e)
|
||||
{
|
||||
OnBindableVectorChanged(vector, e);
|
||||
});
|
||||
|
||||
m_bindableObservableVector = bindableObservableVector;
|
||||
}
|
||||
}
|
||||
|
||||
void InspectingDataSource::OnCollectionChanged(
|
||||
const winrt::IInspectable& /*sender*/,
|
||||
const winrt::NotifyCollectionChangedEventArgs& e)
|
||||
{
|
||||
DataSourceChangedAction action;
|
||||
|
||||
switch (e.Action())
|
||||
{
|
||||
case winrt::NotifyCollectionChangedAction::Add:
|
||||
action = DataSourceChangedAction::Insert;
|
||||
break;
|
||||
case winrt::NotifyCollectionChangedAction::Remove:
|
||||
action = DataSourceChangedAction::Remove;
|
||||
break;
|
||||
case winrt::NotifyCollectionChangedAction::Replace:
|
||||
action = DataSourceChangedAction::Replace;
|
||||
break;
|
||||
case winrt::NotifyCollectionChangedAction::Reset:
|
||||
action = DataSourceChangedAction::Reset;
|
||||
break;
|
||||
case winrt::NotifyCollectionChangedAction::Move:
|
||||
throw ref new Exception(E_FAIL, L"Move operations are not supported. Use a combination of Add and Remove instead.");
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
|
||||
const auto& newItems = e.NewItems();
|
||||
const auto& oldItems = e.OldItems();
|
||||
|
||||
DataSourceChanged(this, DataSourceChangedEventArgs{
|
||||
action,
|
||||
e.OldStartingIndex(),
|
||||
oldItems ? static_cast<int>(oldItems.Size()) : 0,
|
||||
e.NewStartingIndex(),
|
||||
newItems ? static_cast<int>(newItems.Size()) : 0 });
|
||||
}
|
||||
|
||||
void InspectingDataSource::OnVectorChanged(
|
||||
const winrt::Collections::IObservableVector<winrt::IInspectable>& /*sender*/,
|
||||
const winrt::Collections::IVectorChangedEventArgs& e)
|
||||
{
|
||||
DataSourceChangedAction action;
|
||||
int oldStartingIndex = -1;
|
||||
int oldItemsCount = 0;
|
||||
int newStartingIndex = -1;
|
||||
int newItemsCount = 0;
|
||||
|
||||
// Note that the event args' Index property should NOT be accessed
|
||||
// in the Reset case, as the property accessor will throw an exception.
|
||||
switch (e.CollectionChange())
|
||||
{
|
||||
case winrt::CollectionChange::ItemInserted:
|
||||
action = DataSourceChangedAction::Insert;
|
||||
newStartingIndex = e.Index();
|
||||
newItemsCount = 1;
|
||||
break;
|
||||
case winrt::CollectionChange::ItemRemoved:
|
||||
action = DataSourceChangedAction::Remove;
|
||||
oldStartingIndex = e.Index();
|
||||
oldItemsCount = 1;
|
||||
break;
|
||||
case winrt::CollectionChange::ItemChanged:
|
||||
action = DataSourceChangedAction::Replace;
|
||||
oldStartingIndex = e.Index();
|
||||
oldItemsCount = 1;
|
||||
newStartingIndex = e.Index();
|
||||
newItemsCount = 1;
|
||||
break;
|
||||
case winrt::CollectionChange::Reset:
|
||||
action = DataSourceChangedAction::Reset;
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
|
||||
DataSourceChanged(this, DataSourceChangedEventArgs{
|
||||
action,
|
||||
oldStartingIndex,
|
||||
oldItemsCount,
|
||||
newStartingIndex,
|
||||
newItemsCount });
|
||||
}
|
||||
|
||||
void InspectingDataSource::OnBindableVectorChanged(
|
||||
winrt::IBindableObservableVector const& vector,
|
||||
winrt::IInspectable const& e)
|
||||
{
|
||||
OnVectorChanged(nullptr, e.as<winrt::IVectorChangedEventArgs>());
|
||||
}
|
||||
}
|
@@ -1,65 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace GraphControl
|
||||
{
|
||||
public enum class DataSourceChangedAction
|
||||
{
|
||||
Insert,
|
||||
Remove,
|
||||
Replace,
|
||||
Reset
|
||||
};
|
||||
|
||||
value struct DataSourceChangedEventArgs sealed
|
||||
{
|
||||
DataSourceChangedAction Action;
|
||||
int OldStartingIndex;
|
||||
int OldItemsCount;
|
||||
int NewStartingIndex;
|
||||
int NewItemsCount;
|
||||
};
|
||||
|
||||
ref class InspectingDataSource sealed
|
||||
{
|
||||
internal:
|
||||
InspectingDataSource(Platform::Object^ source);
|
||||
|
||||
event Windows::Foundation::TypedEventHandler<InspectingDataSource^, DataSourceChangedEventArgs>^ DataSourceChanged;
|
||||
|
||||
unsigned int GetSize();
|
||||
Platform::Object^ GetAt(unsigned int index);
|
||||
std::optional<unsigned int> IndexOf(Platform::Object^ value);
|
||||
|
||||
private:
|
||||
~InspectingDataSource();
|
||||
|
||||
static winrt::Windows::Foundation::Collections::IVector<winrt::Windows::Foundation::IInspectable>
|
||||
WrapIterable(const winrt::Windows::Foundation::Collections::IIterable<winrt::Windows::Foundation::IInspectable>& iterable);
|
||||
|
||||
void ListenToCollectionChanges();
|
||||
void UnlistenToCollectionChanges();
|
||||
|
||||
void OnCollectionChanged(
|
||||
const winrt::Windows::Foundation::IInspectable& sender,
|
||||
const winrt::Windows::UI::Xaml::Interop::NotifyCollectionChangedEventArgs& e);
|
||||
|
||||
void OnVectorChanged(
|
||||
const winrt::Windows::Foundation::Collections::IObservableVector<winrt::Windows::Foundation::IInspectable>& sender,
|
||||
const winrt::Windows::Foundation::Collections::IVectorChangedEventArgs& e);
|
||||
|
||||
void OnBindableVectorChanged(
|
||||
winrt::Windows::UI::Xaml::Interop::IBindableObservableVector const& vector,
|
||||
winrt::Windows::Foundation::IInspectable const& e);
|
||||
|
||||
private:
|
||||
winrt::Windows::Foundation::Collections::IVector<winrt::Windows::Foundation::IInspectable> m_vector;
|
||||
|
||||
winrt::Windows::UI::Xaml::Interop::INotifyCollectionChanged m_notifyCollectionChanged;
|
||||
winrt::Windows::Foundation::Collections::IObservableVector<winrt::Windows::Foundation::IInspectable> m_observableVector;
|
||||
winrt::Windows::UI::Xaml::Interop::IBindableObservableVector m_bindableObservableVector;
|
||||
winrt::event_token m_eventToken;
|
||||
};
|
||||
}
|
@@ -307,7 +307,6 @@
|
||||
<ClInclude Include="Control\Equation.h" />
|
||||
<ClInclude Include="Control\EquationCollection.h" />
|
||||
<ClInclude Include="Control\Grapher.h" />
|
||||
<ClInclude Include="Control\InspectingDataSource.h" />
|
||||
<ClInclude Include="DirectX\ActiveTracingPointRenderer.h" />
|
||||
<ClInclude Include="DirectX\DeviceResources.h" />
|
||||
<ClInclude Include="DirectX\DirectXHelper.h" />
|
||||
@@ -319,7 +318,6 @@
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Control\Equation.cpp" />
|
||||
<ClCompile Include="Control\Grapher.cpp" />
|
||||
<ClCompile Include="Control\InspectingDataSource.cpp" />
|
||||
<ClCompile Include="DirectX\ActiveTracingPointRenderer.cpp" />
|
||||
<ClCompile Include="DirectX\DeviceResources.cpp" />
|
||||
<ClCompile Include="DirectX\NearestPointRenderer.cpp" />
|
||||
|
@@ -25,9 +25,6 @@
|
||||
<ClCompile Include="Control\Grapher.cpp">
|
||||
<Filter>Control</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Control\InspectingDataSource.cpp">
|
||||
<Filter>Control</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DirectX\NearestPointRenderer.cpp">
|
||||
<Filter>DirectX</Filter>
|
||||
</ClCompile>
|
||||
@@ -56,9 +53,6 @@
|
||||
<ClInclude Include="Control\Grapher.h">
|
||||
<Filter>Control</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Control\InspectingDataSource.h">
|
||||
<Filter>Control</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DirectX\NearestPointRenderer.h">
|
||||
<Filter>DirectX</Filter>
|
||||
</ClInclude>
|
||||
|
Reference in New Issue
Block a user