mirror of
https://github.com/Microsoft/calculator.git
synced 2025-08-22 14:13:30 -07:00
- Initial commit for Graphing Calculator feature.
This commit is contained in:
parent
47a2741218
commit
a59a26519b
64 changed files with 5186 additions and 109 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -289,6 +289,7 @@ __pycache__/
|
|||
|
||||
# Calculator specific
|
||||
Generated Files/
|
||||
src/GraphControl/GraphingImplOverrides.props
|
||||
!/build/config/TRexDefs/**
|
||||
!src/Calculator/TemporaryKey.pfx
|
||||
!src/CalculatorUnitTests/CalculatorUnitTests_TemporaryKey.pfx
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
|
@ -42,6 +42,7 @@ namespace
|
|||
ApplicationViewModel::ApplicationViewModel() :
|
||||
m_CalculatorViewModel(nullptr),
|
||||
m_DateCalcViewModel(nullptr),
|
||||
m_GraphingCalcViewModel(nullptr),
|
||||
m_ConverterViewModel(nullptr),
|
||||
m_PreviousMode(ViewMode::None),
|
||||
m_mode(ViewMode::None),
|
||||
|
@ -132,6 +133,13 @@ void ApplicationViewModel::OnModeChanged()
|
|||
}
|
||||
m_CalculatorViewModel->SetCalculatorType(m_mode);
|
||||
}
|
||||
else if (NavCategory::IsGraphingCalculatorViewMode(m_mode))
|
||||
{
|
||||
if (!m_GraphingCalcViewModel)
|
||||
{
|
||||
m_GraphingCalcViewModel = ref new GraphingCalculatorViewModel();
|
||||
}
|
||||
}
|
||||
else if (NavCategory::IsDateCalculatorViewMode(m_mode))
|
||||
{
|
||||
TraceLogger::GetInstance().LogDateCalculatorModeViewed(m_mode, ApplicationView::GetApplicationViewIdForWindow(CoreWindow::GetForCurrentThread()));
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include "StandardCalculatorViewModel.h"
|
||||
#include "DateCalculatorViewModel.h"
|
||||
#include "GraphingCalculator/GraphingCalculatorViewModel.h"
|
||||
#include "UnitConverterViewModel.h"
|
||||
|
||||
namespace CalculatorApp
|
||||
|
@ -22,6 +23,7 @@ namespace CalculatorApp
|
|||
OBSERVABLE_OBJECT();
|
||||
OBSERVABLE_PROPERTY_RW(StandardCalculatorViewModel^, CalculatorViewModel);
|
||||
OBSERVABLE_PROPERTY_RW(DateCalculatorViewModel^, DateCalcViewModel);
|
||||
OBSERVABLE_PROPERTY_RW(GraphingCalculatorViewModel^, GraphingCalcViewModel);
|
||||
OBSERVABLE_PROPERTY_RW(UnitConverterViewModel^, ConverterViewModel);
|
||||
OBSERVABLE_PROPERTY_RW(CalculatorApp::Common::ViewMode, PreviousMode);
|
||||
OBSERVABLE_NAMED_PROPERTY_RW(Platform::String^, CategoryName);
|
||||
|
|
|
@ -350,6 +350,8 @@
|
|||
<ClInclude Include="DataLoaders\UnitConverterDataConstants.h" />
|
||||
<ClInclude Include="DataLoaders\UnitConverterDataLoader.h" />
|
||||
<ClInclude Include="DateCalculatorViewModel.h" />
|
||||
<ClInclude Include="GraphingCalculator\EquationViewModel.h" />
|
||||
<ClInclude Include="GraphingCalculator\GraphingCalculatorViewModel.h" />
|
||||
<ClInclude Include="HistoryItemViewModel.h" />
|
||||
<ClInclude Include="HistoryViewModel.h" />
|
||||
<ClInclude Include="MemoryItemViewModel.h" />
|
||||
|
@ -386,6 +388,8 @@
|
|||
<ClCompile Include="DataLoaders\CurrencyHttpClient.cpp" />
|
||||
<ClCompile Include="DataLoaders\UnitConverterDataLoader.cpp" />
|
||||
<ClCompile Include="DateCalculatorViewModel.cpp" />
|
||||
<ClCompile Include="GraphingCalculator\EquationViewModel.cpp" />
|
||||
<ClCompile Include="GraphingCalculator\GraphingCalculatorViewModel.cpp" />
|
||||
<ClCompile Include="HistoryItemViewModel.cpp" />
|
||||
<ClCompile Include="HistoryViewModel.cpp" />
|
||||
<ClCompile Include="MemoryItemViewModel.cpp" />
|
||||
|
|
|
@ -10,6 +10,9 @@
|
|||
<Filter Include="DataLoaders">
|
||||
<UniqueIdentifier>{0184f727-b8aa-4af8-a699-63f1b56e7853}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="GraphingCalculator">
|
||||
<UniqueIdentifier>{f7519cec-2ebd-432b-9d59-9647de131d50}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="pch.cpp" />
|
||||
|
@ -93,6 +96,12 @@
|
|||
<ClCompile Include="DataLoaders\UnitConverterDataLoader.cpp">
|
||||
<Filter>DataLoaders</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="GraphingCalculator\EquationViewModel.cpp">
|
||||
<Filter>GraphingCalculator</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="GraphingCalculator\GraphingCalculatorViewModel.cpp">
|
||||
<Filter>GraphingCalculator</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h" />
|
||||
|
@ -213,6 +222,12 @@
|
|||
<ClInclude Include="Common\TraceActivity.h">
|
||||
<Filter>Common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="GraphingCalculator\EquationViewModel.h">
|
||||
<Filter>GraphingCalculator</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="GraphingCalculator\GraphingCalculatorViewModel.h">
|
||||
<Filter>GraphingCalculator</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="DataLoaders\DefaultFromToCurrency.json">
|
||||
|
|
|
@ -62,10 +62,6 @@ namespace CalculatorApp
|
|||
IsStandardMode = (int) CM::Command::ModeBasic,
|
||||
None = (int) CM::Command::CommandNULL,
|
||||
IsProgrammerMode = (int) CM::Command::ModeProgrammer,
|
||||
DecButton = (int) CM::Command::CommandDec,
|
||||
OctButton = (int) CM::Command::CommandOct,
|
||||
HexButton = (int) CM::Command::CommandHex,
|
||||
BinButton = (int) CM::Command::CommandBin,
|
||||
And = (int) CM::Command::CommandAnd,
|
||||
Ror = (int) CM::Command::CommandROR,
|
||||
Rol = (int) CM::Command::CommandROL,
|
||||
|
@ -87,12 +83,21 @@ namespace CalculatorApp
|
|||
InvSinh = (int) CM::Command::CommandASINH,
|
||||
InvCosh = (int) CM::Command::CommandACOSH,
|
||||
InvTanh = (int) CM::Command::CommandATANH,
|
||||
Qword = (int) CM::Command::CommandQword,
|
||||
Dword = (int) CM::Command::CommandDword,
|
||||
Word = (int) CM::Command::CommandWord,
|
||||
Byte = (int) CM::Command::CommandByte,
|
||||
Cube = (int) CM::Command::CommandCUB,
|
||||
DMS = (int) CM::Command::CommandDMS,
|
||||
Hyp = (int)CM::Command::CommandHYP,
|
||||
HexButton = (int)CM::Command::CommandHex,
|
||||
DecButton = (int)CM::Command::CommandDec,
|
||||
OctButton = (int)CM::Command::CommandOct,
|
||||
BinButton = (int)CM::Command::CommandBin,
|
||||
Qword = (int)CM::Command::CommandQword,
|
||||
Dword = (int)CM::Command::CommandDword,
|
||||
Word = (int)CM::Command::CommandWord,
|
||||
Byte = (int)CM::Command::CommandByte,
|
||||
|
||||
Plot,
|
||||
X,
|
||||
Y,
|
||||
|
||||
BINSTART = (int) CM::Command::CommandBINEDITSTART,
|
||||
BINPOS0 = (int) CM::Command::CommandBINPOS0,
|
||||
|
@ -159,8 +164,7 @@ namespace CalculatorApp
|
|||
BINPOS61 = (int) CM::Command::CommandBINPOS61,
|
||||
BINPOS62 = (int) CM::Command::CommandBINPOS62,
|
||||
BINPOS63 = (int) CM::Command::CommandBINPOS63,
|
||||
BINEND = (int) CM::Command::CommandBINEDITEND,
|
||||
Hyp = (int) CM::Command::CommandHYP
|
||||
BINEND = (int) CM::Command::CommandBINEDITEND
|
||||
};
|
||||
|
||||
// This contains list of functions whose usage we are tracelogging
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
using namespace Concurrency;
|
||||
using namespace Platform;
|
||||
using namespace std;
|
||||
using namespace std::chrono;
|
||||
using namespace Windows::ApplicationModel::Resources;
|
||||
using namespace Windows::UI::Xaml;
|
||||
using namespace Windows::UI::Xaml::Controls;
|
||||
|
@ -70,7 +71,7 @@ namespace CalculatorApp
|
|||
}
|
||||
}
|
||||
|
||||
void LightUpButton(ButtonBase^ button)
|
||||
winrt::fire_and_forget LightUpButton(ButtonBase^ button)
|
||||
{
|
||||
// If the button is a toggle button then we don't need
|
||||
// to change the UI of the button
|
||||
|
@ -82,33 +83,15 @@ namespace CalculatorApp
|
|||
// The button will go into the visual Pressed state with this call
|
||||
VisualStateManager::GoToState(button, "Pressed", true);
|
||||
|
||||
// This timer will fire after lightUpTime and make the button
|
||||
// go back to the normal state.
|
||||
// This timer will only fire once after which it will be destroyed
|
||||
auto timer = ref new DispatcherTimer();
|
||||
TimeSpan lightUpTime{};
|
||||
lightUpTime.Duration = 500000L; // Half second (in 100-ns units)
|
||||
timer->Interval = lightUpTime;
|
||||
winrt::apartment_context uiThreadContext;
|
||||
|
||||
WeakReference timerWeakReference(timer);
|
||||
WeakReference buttonWeakReference(button);
|
||||
timer->Tick += ref new EventHandler<Object^>(
|
||||
[buttonWeakReference, timerWeakReference](Object^, Object^)
|
||||
{
|
||||
auto button = buttonWeakReference.Resolve<ButtonBase>();
|
||||
if (button)
|
||||
{
|
||||
VisualStateManager::GoToState(button, "Normal", true);
|
||||
}
|
||||
co_await winrt::resume_background();
|
||||
co_await winrt::resume_after(500ms);
|
||||
|
||||
// Cancel the timer after we're done so it only fires once
|
||||
auto timer = timerWeakReference.Resolve<DispatcherTimer>();
|
||||
if (timer)
|
||||
{
|
||||
timer->Stop();
|
||||
}
|
||||
});
|
||||
timer->Start();
|
||||
co_await uiThreadContext;
|
||||
|
||||
// Restore the normal state
|
||||
VisualStateManager::GoToState(button, "Normal", true);
|
||||
}
|
||||
|
||||
// Looks for the first button reference that it can resolve
|
||||
|
@ -457,9 +440,8 @@ void KeyboardShortcutManager::OnCharacterReceivedHandler(CoreWindow^ sender, Cha
|
|||
wchar_t character = static_cast<wchar_t>(args->KeyCode);
|
||||
auto buttons = s_CharacterForButtons.find(viewId)->second.equal_range(character);
|
||||
|
||||
RunFirstEnabledButtonCommand(buttons);
|
||||
|
||||
LightUpButtons(buttons);
|
||||
RunFirstEnabledButtonCommand(buttons);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -613,8 +595,6 @@ void KeyboardShortcutManager::OnKeyDownHandler(CoreWindow^ sender, KeyEventArgs^
|
|||
{
|
||||
if (currentHonorShortcuts->second)
|
||||
{
|
||||
RunFirstEnabledButtonCommand(buttons);
|
||||
|
||||
// Ctrl+C and Ctrl+V shifts focus to some button because of which enter doesn't work after copy/paste. So don't shift focus if Ctrl+C or Ctrl+V is pressed.
|
||||
// When drop down is open, pressing escape shifts focus to clear button. So dont's shift focus if drop down is open.
|
||||
// Ctrl+Insert is equivalent to Ctrl+C and Shift+Insert is equivalent to Ctrl+V
|
||||
|
@ -627,6 +607,8 @@ void KeyboardShortcutManager::OnKeyDownHandler(CoreWindow^ sender, KeyEventArgs^
|
|||
LightUpButtons(buttons);
|
||||
}
|
||||
}
|
||||
|
||||
RunFirstEnabledButtonCommand(buttons);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,14 +46,16 @@ static constexpr int DATA_ID = 13;
|
|||
static constexpr int PRESSURE_ID = 14;
|
||||
static constexpr int ANGLE_ID = 15;
|
||||
static constexpr int CURRENCY_ID = 16;
|
||||
static constexpr int GRAPHING_ID = 17;
|
||||
// ^^^ THESE CONSTANTS SHOULD NEVER CHANGE ^^^
|
||||
|
||||
// The order of items in this list determines the order of items in the menu.
|
||||
static constexpr array<const NavCategoryInitializer, 17> s_categoryManifest = {
|
||||
static constexpr array<const NavCategoryInitializer, 18> s_categoryManifest = {
|
||||
NavCategoryInitializer { ViewMode::Standard, STANDARD_ID, L"Standard", L"StandardMode", L"\uE8EF", CategoryGroupType::Calculator, MyVirtualKey::Number1, SUPPORTS_ALL },
|
||||
NavCategoryInitializer { ViewMode::Scientific, SCIENTIFIC_ID, L"Scientific", L"ScientificMode", L"\uF196", CategoryGroupType::Calculator, MyVirtualKey::Number2, SUPPORTS_ALL },
|
||||
NavCategoryInitializer { ViewMode::Programmer, PROGRAMMER_ID, L"Programmer", L"ProgrammerMode", L"\uECCE", CategoryGroupType::Calculator, MyVirtualKey::Number3, SUPPORTS_ALL },
|
||||
NavCategoryInitializer { ViewMode::Date, DATE_ID, L"Date", L"DateCalculationMode", L"\uE787", CategoryGroupType::Calculator, MyVirtualKey::Number4, SUPPORTS_ALL },
|
||||
NavCategoryInitializer { ViewMode::Graphing, GRAPHING_ID, L"Graphing", L"GraphingCalculatorMode", L"\uF770", CategoryGroupType::Calculator, MyVirtualKey::Number5, SUPPORTS_ALL },
|
||||
NavCategoryInitializer { ViewMode::Currency, CURRENCY_ID, L"Currency", L"CategoryName_Currency", L"\uEB0D", CategoryGroupType::Converter, MyVirtualKey::None, POSITIVE_ONLY },
|
||||
NavCategoryInitializer { ViewMode::Volume, VOLUME_ID, L"Volume", L"CategoryName_Volume", L"\uF1AA", CategoryGroupType::Converter, MyVirtualKey::None, POSITIVE_ONLY },
|
||||
NavCategoryInitializer { ViewMode::Length, LENGTH_ID, L"Length", L"CategoryName_Length", L"\uECC6", CategoryGroupType::Converter, MyVirtualKey::None, POSITIVE_ONLY },
|
||||
|
@ -121,9 +123,15 @@ bool NavCategory::IsValidViewMode(ViewMode mode)
|
|||
|
||||
bool NavCategory::IsCalculatorViewMode(ViewMode mode)
|
||||
{
|
||||
// Historically, Date Calculator is not a Calculator mode
|
||||
// even though it is in the Calculator category.
|
||||
return !IsDateCalculatorViewMode(mode) && IsModeInCategoryGroup(mode, CategoryGroupType::Calculator);
|
||||
// Historically, Calculator modes are Standard, Scientific, and Programmer.
|
||||
return !IsDateCalculatorViewMode(mode)
|
||||
&& !IsGraphingCalculatorViewMode(mode)
|
||||
&& IsModeInCategoryGroup(mode, CategoryGroupType::Calculator);
|
||||
}
|
||||
|
||||
bool NavCategory::IsGraphingCalculatorViewMode(ViewMode mode)
|
||||
{
|
||||
return mode == ViewMode::Graphing;
|
||||
}
|
||||
|
||||
bool NavCategory::IsDateCalculatorViewMode(ViewMode mode)
|
||||
|
|
|
@ -43,7 +43,8 @@ namespace CalculatorApp
|
|||
Data = 13,
|
||||
Pressure = 14,
|
||||
Angle = 15,
|
||||
Currency = 16
|
||||
Currency = 16,
|
||||
Graphing = 17
|
||||
};
|
||||
|
||||
public enum class CategoryGroupType
|
||||
|
@ -163,6 +164,7 @@ namespace CalculatorApp
|
|||
|
||||
static bool IsValidViewMode(ViewMode mode);
|
||||
static bool IsCalculatorViewMode(ViewMode mode);
|
||||
static bool IsGraphingCalculatorViewMode(ViewMode mode);
|
||||
static bool IsDateCalculatorViewMode(ViewMode mode);
|
||||
static bool IsConverterViewMode(ViewMode mode);
|
||||
|
||||
|
|
|
@ -15,11 +15,13 @@
|
|||
using namespace CalculatorApp;
|
||||
using namespace CalculatorApp::Common;
|
||||
using namespace concurrency;
|
||||
using namespace Graphing::Renderer;
|
||||
using namespace Platform;
|
||||
using namespace std;
|
||||
using namespace Utils;
|
||||
using namespace Windows::ApplicationModel::Resources;
|
||||
using namespace Windows::Storage::Streams;
|
||||
using namespace Windows::UI;
|
||||
using namespace Windows::UI::Core;
|
||||
using namespace Windows::UI::ViewManagement;
|
||||
using namespace Windows::UI::Xaml;
|
||||
|
@ -68,7 +70,7 @@ int Utils::GetWindowId()
|
|||
return windowId;
|
||||
}
|
||||
|
||||
void Utils::RunOnUIThreadNonblocking(std::function<void()>&& function, _In_ CoreDispatcher^ currentDispatcher)
|
||||
void Utils::RunOnUIThreadNonblocking(function<void()>&& function, _In_ CoreDispatcher^ currentDispatcher)
|
||||
{
|
||||
if (currentDispatcher != nullptr)
|
||||
{
|
||||
|
@ -91,7 +93,7 @@ wstring Utils::RemoveUnwantedCharsFromWstring(wstring input, wchar_t* unwantedCh
|
|||
{
|
||||
for (unsigned int i = 0; i < size; ++i)
|
||||
{
|
||||
input.erase(std::remove(input.begin(), input.end(), unwantedChars[i]), input.end());
|
||||
input.erase(remove(input.begin(), input.end(), unwantedChars[i]), input.end());
|
||||
}
|
||||
return input;
|
||||
}
|
||||
|
@ -225,3 +227,53 @@ task<String^> Utils::ReadFileFromFolder(IStorageFolder^ folder, String^ fileName
|
|||
String^ contents = co_await FileIO::ReadTextAsync(file);
|
||||
co_return contents;
|
||||
}
|
||||
|
||||
bool Utils::AreColorsEqual(const Color& color1, const Color& color2)
|
||||
{
|
||||
return ((color1.A == color2.A)
|
||||
&& (color1.R == color2.R)
|
||||
&& (color1.G == color2.G)
|
||||
&& (color1.B == color2.B));
|
||||
}
|
||||
|
||||
String^ Utils::Trim(String^ value)
|
||||
{
|
||||
if (!value)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
wstring trimmed = value->Data();
|
||||
Trim(trimmed);
|
||||
return ref new String(trimmed.c_str());
|
||||
}
|
||||
|
||||
void Utils::Trim(wstring& value)
|
||||
{
|
||||
TrimFront(value);
|
||||
TrimBack(value);
|
||||
}
|
||||
|
||||
void Utils::TrimFront(wstring& value)
|
||||
{
|
||||
value.erase(value.begin(), find_if(value.cbegin(), value.cend(), [](int ch){
|
||||
return !isspace(ch);
|
||||
}));
|
||||
}
|
||||
|
||||
void Utils::TrimBack(wstring& value)
|
||||
{
|
||||
value.erase(find_if(value.crbegin(), value.crend(), [](int ch) {
|
||||
return !isspace(ch);
|
||||
}).base(), value.end());
|
||||
}
|
||||
|
||||
bool operator==(const Color& color1, const Color& color2)
|
||||
{
|
||||
return equal_to<Color>()(color1, color2);
|
||||
}
|
||||
|
||||
bool operator!=(const Color& color1, const Color& color2)
|
||||
{
|
||||
return !(color1 == color2);
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "CalcManager/CalculatorVector.h"
|
||||
#include "CalcManager/ExpressionCommandInterface.h"
|
||||
#include "DelegateCommand.h"
|
||||
#include "GraphingInterfaces/GraphingEnums.h"
|
||||
|
||||
// Utility macros to make Models easier to write
|
||||
// generates a member variable called m_<n>
|
||||
|
@ -301,6 +302,15 @@ namespace Utils
|
|||
|
||||
concurrency::task<void> WriteFileToFolder(Windows::Storage::IStorageFolder^ folder, Platform::String^ fileName, Platform::String^ contents, Windows::Storage::CreationCollisionOption collisionOption);
|
||||
concurrency::task<Platform::String^> ReadFileFromFolder(Windows::Storage::IStorageFolder^ folder, Platform::String^ fileName);
|
||||
|
||||
bool AreColorsEqual(const Windows::UI::Color& color1, const Windows::UI::Color& color2);
|
||||
|
||||
Platform::String^ Trim(Platform::String^ value);
|
||||
void Trim(std::wstring& value);
|
||||
void TrimFront(std::wstring& value);
|
||||
void TrimBack(std::wstring& value);
|
||||
|
||||
|
||||
}
|
||||
|
||||
// This goes into the header to define the property, in the public: section of the class
|
||||
|
@ -421,3 +431,18 @@ namespace CalculatorApp
|
|||
return to;
|
||||
}
|
||||
}
|
||||
|
||||
// There's no standard definition of equality for Windows::UI::Color structs.
|
||||
// Define a template specialization for std::equal_to.
|
||||
template<>
|
||||
class std::equal_to<Windows::UI::Color>
|
||||
{
|
||||
public:
|
||||
bool operator()(const Windows::UI::Color& color1, const Windows::UI::Color& color2)
|
||||
{
|
||||
return Utils::AreColorsEqual(color1, color2);
|
||||
}
|
||||
};
|
||||
|
||||
bool operator==(const Windows::UI::Color& color1, const Windows::UI::Color& color2);
|
||||
bool operator!=(const Windows::UI::Color& color1, const Windows::UI::Color& color2);
|
||||
|
|
12
src/CalcViewModel/GraphingCalculator/EquationViewModel.cpp
Normal file
12
src/CalcViewModel/GraphingCalculator/EquationViewModel.cpp
Normal file
|
@ -0,0 +1,12 @@
|
|||
#include "pch.h"
|
||||
#include "EquationViewModel.h"
|
||||
|
||||
using namespace Windows::UI;
|
||||
|
||||
namespace CalculatorApp::ViewModel
|
||||
{
|
||||
EquationViewModel::EquationViewModel()
|
||||
: m_LineColor{ Colors::Transparent }
|
||||
{
|
||||
}
|
||||
}
|
16
src/CalcViewModel/GraphingCalculator/EquationViewModel.h
Normal file
16
src/CalcViewModel/GraphingCalculator/EquationViewModel.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
|
||||
#include "../Common/Utils.h"
|
||||
|
||||
namespace CalculatorApp::ViewModel
|
||||
{
|
||||
public ref class EquationViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
|
||||
{
|
||||
public:
|
||||
EquationViewModel();
|
||||
|
||||
OBSERVABLE_OBJECT();
|
||||
OBSERVABLE_PROPERTY_RW(Platform::String^, Expression);
|
||||
OBSERVABLE_PROPERTY_RW(Windows::UI::Color, LineColor);
|
||||
};
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
#include "pch.h"
|
||||
#include "GraphingCalculatorViewModel.h"
|
||||
|
||||
using namespace CalculatorApp::ViewModel;
|
||||
using namespace Platform::Collections;
|
||||
|
||||
namespace CalculatorApp::ViewModel
|
||||
{
|
||||
GraphingCalculatorViewModel::GraphingCalculatorViewModel()
|
||||
: m_IsDecimalEnabled{ true }
|
||||
, m_Equations{ ref new Vector< EquationViewModel^ >() }
|
||||
{
|
||||
}
|
||||
|
||||
void GraphingCalculatorViewModel::OnButtonPressed(Object^ parameter)
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
#pragma once
|
||||
|
||||
#include "../Common/Utils.h"
|
||||
#include "EquationViewModel.h"
|
||||
|
||||
namespace CalculatorApp::ViewModel
|
||||
{
|
||||
[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);
|
||||
|
||||
COMMAND_FOR_METHOD(ButtonPressed, GraphingCalculatorViewModel::OnButtonPressed);
|
||||
|
||||
private:
|
||||
void OnButtonPressed(Platform::Object^ parameter);
|
||||
};
|
||||
}
|
|
@ -16,6 +16,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CalcViewModel", "CalcViewMo
|
|||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CalculatorUnitTests", "CalculatorUnitTests\CalculatorUnitTests.vcxproj", "{D3BAED2C-4B07-4E1D-8807-9D6499450349}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MockGraphingImpl", "MockGraphingImpl\MockGraphingImpl.vcxproj", "{52E03A58-B378-4F50-8BFB-F659FB85E790}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GraphControl", "GraphControl\GraphControl.vcxproj", "{E727A92B-F149-492C-8117-C039A298719B}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|ARM = Debug|ARM
|
||||
|
@ -28,22 +32,6 @@ Global
|
|||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{311E866D-8B93-4609-A691-265941FEE101}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{311E866D-8B93-4609-A691-265941FEE101}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{311E866D-8B93-4609-A691-265941FEE101}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{311E866D-8B93-4609-A691-265941FEE101}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{311E866D-8B93-4609-A691-265941FEE101}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{311E866D-8B93-4609-A691-265941FEE101}.Debug|x64.Build.0 = Debug|x64
|
||||
{311E866D-8B93-4609-A691-265941FEE101}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{311E866D-8B93-4609-A691-265941FEE101}.Debug|x86.Build.0 = Debug|Win32
|
||||
{311E866D-8B93-4609-A691-265941FEE101}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{311E866D-8B93-4609-A691-265941FEE101}.Release|ARM.Build.0 = Release|ARM
|
||||
{311E866D-8B93-4609-A691-265941FEE101}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{311E866D-8B93-4609-A691-265941FEE101}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{311E866D-8B93-4609-A691-265941FEE101}.Release|x64.ActiveCfg = Release|x64
|
||||
{311E866D-8B93-4609-A691-265941FEE101}.Release|x64.Build.0 = Release|x64
|
||||
{311E866D-8B93-4609-A691-265941FEE101}.Release|x86.ActiveCfg = Release|Win32
|
||||
{311E866D-8B93-4609-A691-265941FEE101}.Release|x86.Build.0 = Release|Win32
|
||||
{9447424A-0E05-4911-BEB8-E0354405F39A}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{9447424A-0E05-4911-BEB8-E0354405F39A}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{9447424A-0E05-4911-BEB8-E0354405F39A}.Debug|ARM.Deploy.0 = Debug|ARM
|
||||
|
@ -68,6 +56,22 @@ Global
|
|||
{9447424A-0E05-4911-BEB8-E0354405F39A}.Release|x86.ActiveCfg = Release|Win32
|
||||
{9447424A-0E05-4911-BEB8-E0354405F39A}.Release|x86.Build.0 = Release|Win32
|
||||
{9447424A-0E05-4911-BEB8-E0354405F39A}.Release|x86.Deploy.0 = Release|Win32
|
||||
{311E866D-8B93-4609-A691-265941FEE101}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{311E866D-8B93-4609-A691-265941FEE101}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{311E866D-8B93-4609-A691-265941FEE101}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{311E866D-8B93-4609-A691-265941FEE101}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{311E866D-8B93-4609-A691-265941FEE101}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{311E866D-8B93-4609-A691-265941FEE101}.Debug|x64.Build.0 = Debug|x64
|
||||
{311E866D-8B93-4609-A691-265941FEE101}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{311E866D-8B93-4609-A691-265941FEE101}.Debug|x86.Build.0 = Debug|Win32
|
||||
{311E866D-8B93-4609-A691-265941FEE101}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{311E866D-8B93-4609-A691-265941FEE101}.Release|ARM.Build.0 = Release|ARM
|
||||
{311E866D-8B93-4609-A691-265941FEE101}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{311E866D-8B93-4609-A691-265941FEE101}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{311E866D-8B93-4609-A691-265941FEE101}.Release|x64.ActiveCfg = Release|x64
|
||||
{311E866D-8B93-4609-A691-265941FEE101}.Release|x64.Build.0 = Release|x64
|
||||
{311E866D-8B93-4609-A691-265941FEE101}.Release|x86.ActiveCfg = Release|Win32
|
||||
{311E866D-8B93-4609-A691-265941FEE101}.Release|x86.Build.0 = Release|Win32
|
||||
{90E9761D-9262-4773-942D-CAEAE75D7140}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{90E9761D-9262-4773-942D-CAEAE75D7140}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{90E9761D-9262-4773-942D-CAEAE75D7140}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
|
@ -100,6 +104,38 @@ Global
|
|||
{D3BAED2C-4B07-4E1D-8807-9D6499450349}.Release|x86.ActiveCfg = Release|Win32
|
||||
{D3BAED2C-4B07-4E1D-8807-9D6499450349}.Release|x86.Build.0 = Release|Win32
|
||||
{D3BAED2C-4B07-4E1D-8807-9D6499450349}.Release|x86.Deploy.0 = Release|Win32
|
||||
{52E03A58-B378-4F50-8BFB-F659FB85E790}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{52E03A58-B378-4F50-8BFB-F659FB85E790}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{52E03A58-B378-4F50-8BFB-F659FB85E790}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{52E03A58-B378-4F50-8BFB-F659FB85E790}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{52E03A58-B378-4F50-8BFB-F659FB85E790}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{52E03A58-B378-4F50-8BFB-F659FB85E790}.Debug|x64.Build.0 = Debug|x64
|
||||
{52E03A58-B378-4F50-8BFB-F659FB85E790}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{52E03A58-B378-4F50-8BFB-F659FB85E790}.Debug|x86.Build.0 = Debug|Win32
|
||||
{52E03A58-B378-4F50-8BFB-F659FB85E790}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{52E03A58-B378-4F50-8BFB-F659FB85E790}.Release|ARM.Build.0 = Release|ARM
|
||||
{52E03A58-B378-4F50-8BFB-F659FB85E790}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{52E03A58-B378-4F50-8BFB-F659FB85E790}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{52E03A58-B378-4F50-8BFB-F659FB85E790}.Release|x64.ActiveCfg = Release|x64
|
||||
{52E03A58-B378-4F50-8BFB-F659FB85E790}.Release|x64.Build.0 = Release|x64
|
||||
{52E03A58-B378-4F50-8BFB-F659FB85E790}.Release|x86.ActiveCfg = Release|Win32
|
||||
{52E03A58-B378-4F50-8BFB-F659FB85E790}.Release|x86.Build.0 = Release|Win32
|
||||
{E727A92B-F149-492C-8117-C039A298719B}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{E727A92B-F149-492C-8117-C039A298719B}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{E727A92B-F149-492C-8117-C039A298719B}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{E727A92B-F149-492C-8117-C039A298719B}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{E727A92B-F149-492C-8117-C039A298719B}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{E727A92B-F149-492C-8117-C039A298719B}.Debug|x64.Build.0 = Debug|x64
|
||||
{E727A92B-F149-492C-8117-C039A298719B}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{E727A92B-F149-492C-8117-C039A298719B}.Debug|x86.Build.0 = Debug|Win32
|
||||
{E727A92B-F149-492C-8117-C039A298719B}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{E727A92B-F149-492C-8117-C039A298719B}.Release|ARM.Build.0 = Release|ARM
|
||||
{E727A92B-F149-492C-8117-C039A298719B}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{E727A92B-F149-492C-8117-C039A298719B}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{E727A92B-F149-492C-8117-C039A298719B}.Release|x64.ActiveCfg = Release|x64
|
||||
{E727A92B-F149-492C-8117-C039A298719B}.Release|x64.Build.0 = Release|x64
|
||||
{E727A92B-F149-492C-8117-C039A298719B}.Release|x86.ActiveCfg = Release|Win32
|
||||
{E727A92B-F149-492C-8117-C039A298719B}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
|
@ -130,6 +130,9 @@
|
|||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup>
|
||||
<Import Project="$(SolutionDir)\GraphControl\GraphingImplOverrides.props" Condition="Exists('$(SolutionDir)\GraphControl\GraphingImplOverrides.props')" />
|
||||
</ImportGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
|
||||
<ClCompile>
|
||||
<AdditionalOptions>/bigobj /await /std:c++17 </AdditionalOptions>
|
||||
|
@ -281,6 +284,12 @@
|
|||
<ClInclude Include="Views\CalculatorStandardOperators.xaml.h">
|
||||
<DependentUpon>Views\CalculatorStandardOperators.xaml</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Views\GraphingCalculator\EquationInputArea.xaml.h">
|
||||
<DependentUpon>Views\GraphingCalculator\EquationInputArea.xaml</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Views\GraphingCalculator\GraphingCalculator.xaml.h">
|
||||
<DependentUpon>Views\GraphingCalculator\GraphingCalculator.xaml</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Views\HistoryList.xaml.h">
|
||||
<DependentUpon>Views\HistoryList.xaml</DependentUpon>
|
||||
</ClInclude>
|
||||
|
@ -336,6 +345,8 @@
|
|||
</Page>
|
||||
<Page Include="Views\CalculatorStandardOperators.xaml" />
|
||||
<Page Include="Views\DelighterUnitStyles.xaml" />
|
||||
<Page Include="Views\GraphingCalculator\EquationInputArea.xaml" />
|
||||
<Page Include="Views\GraphingCalculator\GraphingCalculator.xaml" />
|
||||
<Page Include="Views\HistoryList.xaml" />
|
||||
<Page Include="Views\MainPage.xaml" />
|
||||
<Page Include="Views\Memory.xaml" />
|
||||
|
@ -421,6 +432,12 @@
|
|||
<ClCompile Include="Views\CalculatorStandardOperators.xaml.cpp">
|
||||
<DependentUpon>Views\CalculatorStandardOperators.xaml</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Views\GraphingCalculator\EquationInputArea.xaml.cpp">
|
||||
<DependentUpon>Views\GraphingCalculator\EquationInputArea.xaml</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Views\GraphingCalculator\GraphingCalculator.xaml.cpp">
|
||||
<DependentUpon>Views\GraphingCalculator\GraphingCalculator.xaml</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Views\HistoryList.xaml.cpp">
|
||||
<DependentUpon>Views\HistoryList.xaml</DependentUpon>
|
||||
</ClCompile>
|
||||
|
@ -829,6 +846,9 @@
|
|||
<ProjectReference Include="..\CalcViewModel\CalcViewModel.vcxproj">
|
||||
<Project>{90e9761d-9262-4773-942d-caeae75d7140}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\GraphControl\GraphControl.vcxproj">
|
||||
<Project>{e727a92b-f149-492c-8117-c039a298719b}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<!-- Override MSBuild target to workaround VS bug with building using framework packages -->
|
||||
|
|
|
@ -218,6 +218,9 @@
|
|||
<Filter Include="Views\StateTriggers">
|
||||
<UniqueIdentifier>{0120c344-0bc0-4a1d-b82c-df7945f46189}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Views\GraphingCalculator">
|
||||
<UniqueIdentifier>{e23e2a6e-491b-4200-9bf7-d355a1ee695b}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ApplicationDefinition Include="App.xaml" />
|
||||
|
@ -480,6 +483,12 @@
|
|||
<Page Include="Views\OperatorsPanel.xaml">
|
||||
<Filter>Views</Filter>
|
||||
</Page>
|
||||
<Page Include="Views\GraphingCalculator\EquationInputArea.xaml">
|
||||
<Filter>Views\GraphingCalculator</Filter>
|
||||
</Page>
|
||||
<Page Include="Views\GraphingCalculator\GraphingCalculator.xaml">
|
||||
<Filter>Views\GraphingCalculator</Filter>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PRIResource Include="Resources\en-US\CEngineStrings.resw">
|
||||
|
|
|
@ -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.Dev" 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.0.0" />
|
||||
<mp:PhoneIdentity PhoneProductId="b58171c6-c70c-4266-a2e8-8f9c994f4456" PhonePublisherId="95d94207-0c7c-47ed-82db-d75c81153c35" />
|
||||
<Properties>
|
||||
<DisplayName>ms-resource:DevAppStoreName</DisplayName>
|
||||
|
|
|
@ -118,7 +118,7 @@
|
|||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="AppName" xml:space="preserve">
|
||||
<value>Calculator</value>
|
||||
<value>Graphing Calculator</value>
|
||||
<comment>{@Appx_ShortDisplayName@}{StringCategory="Feature Title"} This is the title of the official application when published through Windows Store.</comment>
|
||||
</data>
|
||||
<data name="DevAppName" xml:space="preserve">
|
||||
|
@ -1271,7 +1271,7 @@
|
|||
</data>
|
||||
<data name="equalButton.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||
<value>Equals</value>
|
||||
<comment>Screen reader prompt for the invert button on the scientific operator keypad</comment>
|
||||
<comment>Screen reader prompt for the equals button on the scientific operator keypad</comment>
|
||||
</data>
|
||||
<data name="shiftButton.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||
<value>Inverse Function</value>
|
||||
|
@ -3379,4 +3379,40 @@
|
|||
<value>Microsoft Services Agreement</value>
|
||||
<comment>Displayed on a link to the Microsoft Services Agreement in the about this app information</comment>
|
||||
</data>
|
||||
<data name="GraphingCalculatorModeText" xml:space="preserve">
|
||||
<value>Graphing</value>
|
||||
<comment>Name of the Graphing mode of the Calculator app. Displayed in the navigation menu.</comment>
|
||||
</data>
|
||||
<data name="graphingEqualButton.[using:CalculatorApp.Common]KeyboardShortcutManager.Character" xml:space="preserve">
|
||||
<value>=</value>
|
||||
<comment>{Locked}This is the character that should trigger this button. Note that it is a character and not a key, so it does not come from the Windows::System::VirtualKey enum.</comment>
|
||||
</data>
|
||||
<data name="graphingEqualButton.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||
<value>Equals</value>
|
||||
<comment>Screen reader prompt for the equal button on the graphing calculator operator keypad</comment>
|
||||
</data>
|
||||
<data name="plotButton.[using:CalculatorApp.Common]KeyboardShortcutManager.VirtualKey" xml:space="preserve">
|
||||
<value>Enter</value>
|
||||
<comment>{Locked}This is the value from the VirtualKey enum that maps to this button</comment>
|
||||
</data>
|
||||
<data name="plotButton.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||
<value>Plot</value>
|
||||
<comment>Screen reader prompt for the plot button on the graphing calculator operator keypad</comment>
|
||||
</data>
|
||||
<data name="xButton.[using:CalculatorApp.Common]KeyboardShortcutManager.VirtualKey" xml:space="preserve">
|
||||
<value>X</value>
|
||||
<comment>{Locked}This is the value that comes from the VirtualKey enum that represents the button. This value is not localized and must be one value that comes from the Windows::System::VirtualKey enum.</comment>
|
||||
</data>
|
||||
<data name="yButton.[using:CalculatorApp.Common]KeyboardShortcutManager.VirtualKey" xml:space="preserve">
|
||||
<value>Y</value>
|
||||
<comment>{Locked}This is the value that comes from the VirtualKey enum that represents the button. This value is not localized and must be one value that comes from the Windows::System::VirtualKey enum.</comment>
|
||||
</data>
|
||||
<data name="EquationInputAreaHeader.Text" xml:space="preserve">
|
||||
<value>Equations</value>
|
||||
<comment>The text that shows as the header for the equation input area in Graphing Calculator mode.</comment>
|
||||
</data>
|
||||
<data name="graphingPowerButton.[using:CalculatorApp.Common]KeyboardShortcutManager.Character" xml:space="preserve">
|
||||
<value>^</value>
|
||||
<comment>{Locked}This is the character that should trigger this button. Note that it is a character and not a key, so it does not come from the Windows::System::VirtualKey enum.</comment>
|
||||
</data>
|
||||
</root>
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
<UserControl x:Class="CalculatorApp.EquationInputArea"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:vm="using:CalculatorApp.ViewModel"
|
||||
d:DesignHeight="300"
|
||||
d:DesignWidth="400"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Grid Grid.Row="0" Margin="0,0,17,0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBlock x:Uid="EquationInputAreaHeader"
|
||||
Grid.Column="0"
|
||||
Style="{ThemeResource SubheaderTextBlockStyle}"
|
||||
FontSize="20"/>
|
||||
|
||||
<Button Grid.Column="1"
|
||||
Click="AddEquationButton_Click"
|
||||
Content="+"/>
|
||||
</Grid>
|
||||
|
||||
<ListView x:Name="EquationInputList"
|
||||
Grid.Row="2"
|
||||
Margin="0,4,0,0"
|
||||
IsItemClickEnabled="False"
|
||||
ItemsSource="{x:Bind Equations}"
|
||||
SelectionMode="None">
|
||||
|
||||
<ListView.Resources>
|
||||
<x:Double x:Key="ItemHeight">40</x:Double>
|
||||
</ListView.Resources>
|
||||
|
||||
<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,17,1"/>
|
||||
</Style>
|
||||
</ListView.ItemContainerStyle>
|
||||
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:EquationViewModel">
|
||||
<Grid Height="{StaticResource ItemHeight}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.Resources>
|
||||
<SolidColorBrush x:Key="LineColorBrush" Color="{x:Bind LineColor, Mode=OneWay}"/>
|
||||
</Grid.Resources>
|
||||
<Grid.Background>
|
||||
<StaticResource ResourceKey="LineColorBrush"/>
|
||||
</Grid.Background>
|
||||
|
||||
<Button Width="{StaticResource ItemHeight}"
|
||||
Height="{StaticResource ItemHeight}"
|
||||
Background="{StaticResource LineColorBrush}"/>
|
||||
|
||||
<Rectangle x:Name="InputBackplate"
|
||||
Grid.Column="1"
|
||||
Margin="0,2,3,2"
|
||||
Fill="White"/>
|
||||
|
||||
<TextBox Grid.Column="1"
|
||||
Margin="0,2,3,2"
|
||||
GotFocus="InputTextBox_GotFocus"
|
||||
KeyUp="InputTextBox_KeyUp"
|
||||
LostFocus="InputTextBox_LostFocus"/>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
</Grid>
|
||||
</UserControl>
|
|
@ -0,0 +1,108 @@
|
|||
#include "pch.h"
|
||||
#include "EquationInputArea.xaml.h"
|
||||
#include "CalcViewModel/Common/KeyboardShortcutManager.h"
|
||||
|
||||
using namespace CalculatorApp;
|
||||
using namespace CalculatorApp::Common;
|
||||
using namespace CalculatorApp::ViewModel;
|
||||
using namespace Platform;
|
||||
using namespace std;
|
||||
using namespace Windows::System;
|
||||
using namespace Windows::UI;
|
||||
using namespace Windows::UI::ViewManagement;
|
||||
using namespace Windows::UI::Xaml;
|
||||
using namespace Windows::UI::Xaml::Controls;
|
||||
using namespace Windows::UI::Xaml::Input;
|
||||
|
||||
namespace
|
||||
{
|
||||
const Color accentColor = (ref new UISettings())->GetColorValue(UIColorType::Accent);
|
||||
const Color lineColors[] = {
|
||||
accentColor,
|
||||
Colors::DarkOrange,
|
||||
Colors::MediumPurple,
|
||||
Colors::ForestGreen,
|
||||
Colors::BlueViolet,
|
||||
Colors::DarkRed,
|
||||
Colors::LightGoldenrodYellow,
|
||||
Colors::DarkOliveGreen
|
||||
};
|
||||
const size_t lineColorsSize = std::size(lineColors);
|
||||
|
||||
StringReference EquationsPropertyName(L"Equations");
|
||||
}
|
||||
|
||||
EquationInputArea::EquationInputArea()
|
||||
: m_lastLineColorIndex{ -1 }
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
void EquationInputArea::OnPropertyChanged(String^ propertyName)
|
||||
{
|
||||
if (propertyName == EquationsPropertyName)
|
||||
{
|
||||
OnEquationsPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void EquationInputArea::OnEquationsPropertyChanged()
|
||||
{
|
||||
if (Equations != nullptr && Equations->Size == 0)
|
||||
{
|
||||
AddNewEquation();
|
||||
|
||||
// For now, the first equation needs to be y = 0.
|
||||
// We can remove this when we can create empty graphs.
|
||||
if (EquationViewModel^ eqvm = Equations->GetAt(0))
|
||||
{
|
||||
eqvm->Expression = L"0";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EquationInputArea::AddEquationButton_Click(Object^ sender, RoutedEventArgs^ e)
|
||||
{
|
||||
AddNewEquation();
|
||||
}
|
||||
|
||||
void EquationInputArea::AddNewEquation()
|
||||
{
|
||||
auto eq = ref new EquationViewModel();
|
||||
eq->LineColor = GetNextLineColor();
|
||||
|
||||
Equations->Append(eq);
|
||||
EquationInputList->ScrollIntoView(eq);
|
||||
}
|
||||
|
||||
void EquationInputArea::InputTextBox_GotFocus(Object^ sender, RoutedEventArgs^ e)
|
||||
{
|
||||
KeyboardShortcutManager::HonorShortcuts(false);
|
||||
}
|
||||
|
||||
void EquationInputArea::InputTextBox_LostFocus(Object^ sender, RoutedEventArgs^ e)
|
||||
{
|
||||
KeyboardShortcutManager::HonorShortcuts(true);
|
||||
|
||||
auto tb = static_cast<TextBox^>(sender);
|
||||
auto eq = static_cast<EquationViewModel^>(tb->DataContext);
|
||||
tb->Text = eq->Expression;
|
||||
}
|
||||
|
||||
void EquationInputArea::InputTextBox_KeyUp(Object^ sender, KeyRoutedEventArgs^ e)
|
||||
{
|
||||
if (e->Key == VirtualKey::Enter)
|
||||
{
|
||||
auto tb = static_cast<TextBox^>(sender);
|
||||
auto eq = static_cast<EquationViewModel^>(tb->DataContext);
|
||||
eq->Expression = tb->Text;
|
||||
|
||||
e->Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
Color EquationInputArea::GetNextLineColor()
|
||||
{
|
||||
m_lastLineColorIndex = (m_lastLineColorIndex + 1) % lineColorsSize;
|
||||
return lineColors[m_lastLineColorIndex];
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
#pragma once
|
||||
|
||||
#include "Views/GraphingCalculator/EquationInputArea.g.h"
|
||||
#include "CalcViewModel/Common/Utils.h"
|
||||
#include "CalcViewModel/GraphingCalculator/EquationViewModel.h"
|
||||
|
||||
namespace CalculatorApp
|
||||
{
|
||||
public ref class EquationInputArea sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
|
||||
{
|
||||
public:
|
||||
EquationInputArea();
|
||||
|
||||
OBSERVABLE_OBJECT_CALLBACK(OnPropertyChanged);
|
||||
OBSERVABLE_PROPERTY_RW(Windows::Foundation::Collections::IObservableVector< ViewModel::EquationViewModel^ >^, Equations);
|
||||
|
||||
private:
|
||||
void OnPropertyChanged(Platform::String^ propertyName);
|
||||
void OnEquationsPropertyChanged();
|
||||
|
||||
void AddEquationButton_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
|
||||
void AddNewEquation();
|
||||
|
||||
void InputTextBox_GotFocus(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
|
||||
void InputTextBox_LostFocus(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
|
||||
void InputTextBox_KeyUp(Platform::Object^ sender, Windows::UI::Xaml::Input::KeyRoutedEventArgs^ e);
|
||||
|
||||
Windows::UI::Color GetNextLineColor();
|
||||
|
||||
private:
|
||||
int m_lastLineColorIndex;
|
||||
};
|
||||
}
|
242
src/Calculator/Views/GraphingCalculator/GraphingCalculator.xaml
Normal file
242
src/Calculator/Views/GraphingCalculator/GraphingCalculator.xaml
Normal file
|
@ -0,0 +1,242 @@
|
|||
<UserControl x:Class="CalculatorApp.GraphingCalculator"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="using:CalculatorApp.Controls"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:graphControl="using:GraphControl"
|
||||
xmlns:local="using:CalculatorApp"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:vm="using:CalculatorApp.ViewModel"
|
||||
DataContextChanged="GraphingCalculator_DataContextChanged"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Grid x:Name="RootGrid">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition x:Name="RowHamburger" Height="{StaticResource HamburgerHeightGridLength}"/>
|
||||
<RowDefinition/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="2*"/>
|
||||
<ColumnDefinition Width="1*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- Left portion of the screen -->
|
||||
<Grid x:Name="LeftGrid"
|
||||
Grid.Row="1"
|
||||
Grid.Column="0">
|
||||
|
||||
<graphControl:Grapher Grid.Row="0"
|
||||
Margin="4,7,4,4"
|
||||
EquationsSource="{x:Bind ViewModel.Equations, Mode=OneWay}"
|
||||
ForceProportionalAxes="True"
|
||||
UseSystemFocusVisuals="True">
|
||||
<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}"/>
|
||||
</DataTemplate>
|
||||
</graphControl:Grapher.EquationTemplate>
|
||||
</graphControl:Grapher>
|
||||
</Grid>
|
||||
|
||||
<!-- Right portion of the screen -->
|
||||
<Grid x:Name="RightGrid"
|
||||
Grid.Row="0"
|
||||
Grid.RowSpan="2"
|
||||
Grid.Column="1"
|
||||
Margin="4,0,4,0">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="5*"/>
|
||||
<RowDefinition Height="3*"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<local:EquationInputArea Grid.Row="0" Equations="{x:Bind ViewModel.Equations}"/>
|
||||
|
||||
<Grid x:Name="ButtonContainerGrid"
|
||||
Grid.Row="1"
|
||||
Margin="3,0,3,3"
|
||||
UseLayoutRounding="False">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition/>
|
||||
<RowDefinition/>
|
||||
<RowDefinition/>
|
||||
<RowDefinition/>
|
||||
<RowDefinition/>
|
||||
<RowDefinition/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<controls:CalculatorButton x:Name="XButton"
|
||||
x:Uid="xButton"
|
||||
Grid.Row="0"
|
||||
Grid.Column="0"
|
||||
Style="{StaticResource OperatorButtonStyle}"
|
||||
FontSize="16"
|
||||
ButtonId="X"
|
||||
Content="𝑥"
|
||||
FlowDirection="LeftToRight"/>
|
||||
<controls:CalculatorButton x:Name="YButton"
|
||||
x:Uid="yButton"
|
||||
Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
Style="{StaticResource OperatorButtonStyle}"
|
||||
FontSize="16"
|
||||
ButtonId="Y"
|
||||
Content="𝑦"
|
||||
FlowDirection="LeftToRight"/>
|
||||
<controls:CalculatorButton x:Name="PowerButton"
|
||||
x:Uid="graphingPowerButton"
|
||||
Grid.Row="0"
|
||||
Grid.Column="2"
|
||||
Style="{StaticResource OperatorButtonStyle}"
|
||||
ButtonId="XPowerY"
|
||||
Content="^"/>
|
||||
<controls:CalculatorButton x:Name="squareRootButton"
|
||||
x:Uid="squareRootButton"
|
||||
Grid.Row="0"
|
||||
Grid.Column="3"
|
||||
Style="{StaticResource SymbolOperatorButtonStyle}"
|
||||
FontFamily="{StaticResource SymbolThemeFontFamily}"
|
||||
ButtonId="Sqrt"
|
||||
Content=""/>
|
||||
|
||||
<!-- Display controls -->
|
||||
<controls:CalculatorButton x:Name="ClearButton"
|
||||
x:Uid="clearButton"
|
||||
Grid.Row="1"
|
||||
Grid.Column="2"
|
||||
Style="{StaticResource OperatorButtonStyle}"
|
||||
FontSize="16"
|
||||
ButtonId="Clear"
|
||||
Content="C"/>
|
||||
<controls:CalculatorButton x:Name="BackSpaceButton"
|
||||
x:Uid="backSpaceButton"
|
||||
Grid.Row="1"
|
||||
Grid.Column="3"
|
||||
Style="{StaticResource SymbolOperatorButtonStyle}"
|
||||
FontSize="16"
|
||||
ButtonId="Backspace"
|
||||
Content=""/>
|
||||
|
||||
<!-- Basic operators -->
|
||||
<controls:CalculatorButton x:Name="EqualButton"
|
||||
x:Uid="graphingEqualButton"
|
||||
Grid.Row="0"
|
||||
Grid.Column="4"
|
||||
Style="{StaticResource AccentCalcButtonStyle}"
|
||||
ButtonId="Equals"
|
||||
Content=""/>
|
||||
<controls:CalculatorButton x:Name="DivideButton"
|
||||
x:Uid="divideButton"
|
||||
Grid.Row="1"
|
||||
Grid.Column="4"
|
||||
Style="{StaticResource AccentCalcButtonStyle}"
|
||||
ButtonId="Divide"
|
||||
Content=""/>
|
||||
<controls:CalculatorButton x:Name="MultiplyButton"
|
||||
x:Uid="multiplyButton"
|
||||
Grid.Row="2"
|
||||
Grid.Column="4"
|
||||
Style="{StaticResource AccentCalcButtonStyle}"
|
||||
ButtonId="Multiply"
|
||||
Content=""/>
|
||||
<controls:CalculatorButton x:Name="MinusButton"
|
||||
x:Uid="minusButton"
|
||||
Grid.Row="3"
|
||||
Grid.Column="4"
|
||||
Style="{StaticResource AccentCalcButtonStyle}"
|
||||
ButtonId="Subtract"
|
||||
Content=""/>
|
||||
<controls:CalculatorButton x:Name="PlusButton"
|
||||
x:Uid="plusButton"
|
||||
Grid.Row="4"
|
||||
Grid.Column="4"
|
||||
Style="{StaticResource AccentCalcButtonStyle}"
|
||||
ButtonId="Add"
|
||||
Content=""/>
|
||||
|
||||
|
||||
<controls:CalculatorButton x:Name="logBase10Button"
|
||||
x:Uid="logBase10Button"
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
Style="{StaticResource OperatorButtonStyle}"
|
||||
ButtonId="LogBase10"
|
||||
Content="log"/>
|
||||
<controls:CalculatorButton x:Name="logBaseEButton"
|
||||
x:Uid="logBaseEButton"
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Style="{StaticResource OperatorButtonStyle}"
|
||||
ButtonId="LogBaseE"
|
||||
Content="ln"/>
|
||||
<controls:CalculatorButton x:Name="powerOf10Button"
|
||||
x:Uid="powerOf10Button"
|
||||
Grid.Row="2"
|
||||
Grid.Column="0"
|
||||
Style="{StaticResource SymbolOperatorButtonStyle}"
|
||||
AutomationProperties.AutomationId="powerOf10Button"
|
||||
ButtonId="TenPowerX"
|
||||
Content=""/>
|
||||
<controls:CalculatorButton x:Name="powerOfEButton"
|
||||
x:Uid="powerOfEButton"
|
||||
Grid.Row="3"
|
||||
Grid.Column="0"
|
||||
Style="{StaticResource SymbolOperatorButtonStyle}"
|
||||
ButtonId="EPowerX"
|
||||
Content=""/>
|
||||
<controls:CalculatorButton x:Name="piButton"
|
||||
x:Uid="piButton"
|
||||
Grid.Row="4"
|
||||
Grid.Column="0"
|
||||
Style="{StaticResource SymbolOperatorButtonStyle}"
|
||||
FontSize="14"
|
||||
ButtonId="Pi"
|
||||
Content=""/>
|
||||
|
||||
<controls:CalculatorButton x:Name="openParenthesisButton"
|
||||
x:Uid="openParenthesisButton"
|
||||
Grid.Row="5"
|
||||
Grid.Column="0"
|
||||
Style="{StaticResource ParenthesisCalcButtonStyle}"
|
||||
FontSize="19"
|
||||
ButtonId="OpenParenthesis"
|
||||
Content="("/>
|
||||
<controls:CalculatorButton x:Name="closeParenthesisButton"
|
||||
x:Uid="closeParenthesisButton"
|
||||
Grid.Row="5"
|
||||
Grid.Column="1"
|
||||
Style="{StaticResource OperatorButtonStyle}"
|
||||
FontSize="19"
|
||||
ButtonId="CloseParenthesis"
|
||||
Content=")"/>
|
||||
|
||||
<!-- The Numberpad -->
|
||||
<local:NumberPad x:Name="NumberPad"
|
||||
x:Uid="NumberPad"
|
||||
Grid.Row="2"
|
||||
Grid.RowSpan="4"
|
||||
Grid.Column="1"
|
||||
Grid.ColumnSpan="3"
|
||||
ButtonStyle="{StaticResource NumericButtonStyle24}"/>
|
||||
|
||||
<controls:CalculatorButton x:Name="PlotButton"
|
||||
x:Uid="plotButton"
|
||||
Grid.Row="5"
|
||||
Grid.Column="4"
|
||||
Style="{StaticResource AccentCalcButtonStyle}"
|
||||
FontFamily="{StaticResource SymbolThemeFontFamily}"
|
||||
ButtonId="Plot"
|
||||
Content=""/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</UserControl>
|
|
@ -0,0 +1,51 @@
|
|||
|
||||
#include "pch.h"
|
||||
#include "GraphingCalculator.xaml.h"
|
||||
#include "CalcViewModel/Common/KeyboardShortcutManager.h"
|
||||
#include "Controls/CalculationResult.h"
|
||||
|
||||
using namespace CalculatorApp;
|
||||
using namespace CalculatorApp::Common;
|
||||
using namespace CalculatorApp::Controls;
|
||||
using namespace CalculatorApp::ViewModel;
|
||||
using namespace concurrency;
|
||||
using namespace GraphControl;
|
||||
using namespace Platform;
|
||||
using namespace std::chrono;
|
||||
using namespace Utils;
|
||||
using namespace Windows::Foundation::Collections;
|
||||
using namespace Windows::Storage::Streams;
|
||||
using namespace Windows::System;
|
||||
using namespace Windows::UI::Xaml;
|
||||
using namespace Windows::UI::Xaml::Data;
|
||||
using namespace Windows::UI::Xaml::Input;
|
||||
using namespace Windows::UI::Xaml::Media;
|
||||
using namespace Windows::UI::Xaml::Media::Imaging;
|
||||
|
||||
constexpr auto sc_ViewModelPropertyName = L"ViewModel";
|
||||
|
||||
GraphingCalculator::GraphingCalculator()
|
||||
{
|
||||
Equation::RegisterDependencyProperties();
|
||||
Grapher::RegisterDependencyProperties();
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
void GraphingCalculator::GraphingCalculator_DataContextChanged(FrameworkElement^ sender, DataContextChangedEventArgs^ args)
|
||||
{
|
||||
ViewModel = dynamic_cast<GraphingCalculatorViewModel^>(args->NewValue);
|
||||
}
|
||||
|
||||
GraphingCalculatorViewModel^ GraphingCalculator::ViewModel::get()
|
||||
{
|
||||
return m_viewModel;
|
||||
}
|
||||
|
||||
void GraphingCalculator::ViewModel::set(GraphingCalculatorViewModel^ vm)
|
||||
{
|
||||
if (m_viewModel != vm)
|
||||
{
|
||||
m_viewModel = vm;
|
||||
RaisePropertyChanged(StringReference(sc_ViewModelPropertyName));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
#pragma once
|
||||
|
||||
#include "Views\GraphingCalculator\GraphingCalculator.g.h"
|
||||
#include "CalcViewModel/GraphingCalculator/GraphingCalculatorViewModel.h"
|
||||
#include "Views\NumberPad.xaml.h"
|
||||
|
||||
namespace CalculatorApp
|
||||
{
|
||||
public ref class GraphingCalculator sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
|
||||
{
|
||||
public:
|
||||
GraphingCalculator();
|
||||
|
||||
OBSERVABLE_OBJECT();
|
||||
|
||||
property CalculatorApp::ViewModel::GraphingCalculatorViewModel^ ViewModel
|
||||
{
|
||||
CalculatorApp::ViewModel::GraphingCalculatorViewModel^ get();
|
||||
void set(CalculatorApp::ViewModel::GraphingCalculatorViewModel^ vm);
|
||||
}
|
||||
|
||||
private:
|
||||
void GraphingCalculator_DataContextChanged(Windows::UI::Xaml::FrameworkElement^ sender, Windows::UI::Xaml::DataContextChangedEventArgs^ args);
|
||||
|
||||
private:
|
||||
CalculatorApp::ViewModel::GraphingCalculatorViewModel^ m_viewModel;
|
||||
};
|
||||
}
|
|
@ -154,6 +154,9 @@
|
|||
<Border x:Name="DateCalcHolder">
|
||||
<!-- PLACEHOLDER!!!! This is where the date calculator goes when it is delay loaded -->
|
||||
</Border>
|
||||
<Border x:Name="GraphingCalcHolder" Grid.Row="1">
|
||||
<!-- PLACEHOLDER!!!! This is where the graphing calculator goes when it is delay loaded -->
|
||||
</Border>
|
||||
<Border x:Name="ConverterHolder">
|
||||
<!-- PLACEHOLDER!!!! This is where the converter goes when it is delay loaded -->
|
||||
</Border>
|
||||
|
|
|
@ -167,6 +167,10 @@ void MainPage::OnAppPropertyChanged(_In_ Platform::Object^ sender, _In_ Windows:
|
|||
}
|
||||
EnsureDateCalculator();
|
||||
}
|
||||
else if (newValue == ViewMode::Graphing)
|
||||
{
|
||||
EnsureGraphingCalculator();
|
||||
}
|
||||
else if (NavCategory::IsConverterViewMode(newValue))
|
||||
{
|
||||
if (m_model->CalculatorViewModel)
|
||||
|
@ -196,9 +200,10 @@ void MainPage::OnAppPropertyChanged(_In_ Platform::Object^ sender, _In_ Windows:
|
|||
|
||||
void MainPage::ShowHideControls(ViewMode mode)
|
||||
{
|
||||
auto isCalcViewMode = NavCategory::IsCalculatorViewMode(mode);
|
||||
auto isDateCalcViewMode = NavCategory::IsDateCalculatorViewMode(mode);
|
||||
auto isConverterViewMode = NavCategory::IsConverterViewMode(mode);
|
||||
bool isCalcViewMode = NavCategory::IsCalculatorViewMode(mode);
|
||||
bool isDateCalcViewMode = NavCategory::IsDateCalculatorViewMode(mode);
|
||||
bool isGraphingCalcViewMode = NavCategory::IsGraphingCalculatorViewMode(mode);
|
||||
bool isConverterViewMode = NavCategory::IsConverterViewMode(mode);
|
||||
|
||||
if (m_calculator)
|
||||
{
|
||||
|
@ -212,6 +217,12 @@ void MainPage::ShowHideControls(ViewMode mode)
|
|||
m_dateCalculator->IsEnabled = isDateCalcViewMode;
|
||||
}
|
||||
|
||||
if (m_graphingCalculator)
|
||||
{
|
||||
m_graphingCalculator->Visibility = BooleanToVisibilityConverter::Convert(isGraphingCalcViewMode);
|
||||
m_graphingCalculator->IsEnabled = isGraphingCalcViewMode;
|
||||
}
|
||||
|
||||
if (m_converter)
|
||||
{
|
||||
m_converter->Visibility = BooleanToVisibilityConverter::Convert(isConverterViewMode);
|
||||
|
@ -239,7 +250,7 @@ void MainPage::UpdatePanelViewState()
|
|||
|
||||
void MainPage::OnPageLoaded(_In_ Object^, _In_ RoutedEventArgs^ args)
|
||||
{
|
||||
if (!m_converter && !m_calculator && !m_dateCalculator)
|
||||
if (!m_converter && !m_calculator && !m_dateCalculator && !m_graphingCalculator)
|
||||
{
|
||||
// We have just launched into our default mode (standard calc) so ensure calc is loaded
|
||||
EnsureCalculator();
|
||||
|
@ -292,6 +303,10 @@ void MainPage::SetDefaultFocus()
|
|||
{
|
||||
m_dateCalculator->SetDefaultFocus();
|
||||
}
|
||||
if (m_graphingCalculator != nullptr && m_graphingCalculator->Visibility == ::Visibility::Visible)
|
||||
{
|
||||
m_graphingCalculator->Focus(::FocusState::Programmatic);
|
||||
}
|
||||
if (m_converter != nullptr && m_converter->Visibility == ::Visibility::Visible)
|
||||
{
|
||||
m_converter->SetDefaultFocus();
|
||||
|
@ -354,6 +369,18 @@ void MainPage::EnsureDateCalculator()
|
|||
}
|
||||
}
|
||||
|
||||
void MainPage::EnsureGraphingCalculator()
|
||||
{
|
||||
if (!m_graphingCalculator)
|
||||
{
|
||||
m_graphingCalculator = ref new GraphingCalculator();
|
||||
m_graphingCalculator->Name = L"GraphingCalculator";
|
||||
m_graphingCalculator->DataContext = m_model->GraphingCalcViewModel;
|
||||
|
||||
GraphingCalcHolder->Child = m_graphingCalculator;
|
||||
}
|
||||
}
|
||||
|
||||
void MainPage::EnsureConverter()
|
||||
{
|
||||
if (!m_converter)
|
||||
|
@ -571,7 +598,7 @@ void MainPage::SetHeaderAutomationName()
|
|||
else
|
||||
{
|
||||
wstring full;
|
||||
if (NavCategory::IsCalculatorViewMode(mode))
|
||||
if (NavCategory::IsCalculatorViewMode(mode) || NavCategory::IsGraphingCalculatorViewMode(mode))
|
||||
{
|
||||
full = resProvider.GetResourceString(L"HeaderAutomationName_Calculator")->Data();
|
||||
}
|
||||
|
@ -581,6 +608,7 @@ void MainPage::SetHeaderAutomationName()
|
|||
}
|
||||
|
||||
string::size_type found = full.find(L"%1");
|
||||
assert(found != wstring::npos);
|
||||
wstring strMode = m_model->CategoryName->Data();
|
||||
full = full.replace(found, 2, strMode);
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
@ -6,6 +6,7 @@
|
|||
#include "Views/Calculator.xaml.h"
|
||||
#include "Views/MainPage.g.h"
|
||||
#include "Views/DateCalculator.xaml.h"
|
||||
#include "Views/GraphingCalculator/GraphingCalculator.xaml.h"
|
||||
#include "Views/UnitConverter.xaml.h"
|
||||
#include "CalcViewModel/ApplicationViewModel.h"
|
||||
#include "Views/TitleBar.xaml.h"
|
||||
|
@ -24,9 +25,9 @@ namespace CalculatorApp
|
|||
{
|
||||
public:
|
||||
MainPage();
|
||||
property CalculatorApp::ViewModel::ApplicationViewModel^ Model
|
||||
property ViewModel::ApplicationViewModel^ Model
|
||||
{
|
||||
CalculatorApp::ViewModel::ApplicationViewModel^ get(){
|
||||
ViewModel::ApplicationViewModel^ get(){
|
||||
return m_model;
|
||||
}
|
||||
}
|
||||
|
@ -36,7 +37,7 @@ namespace CalculatorApp
|
|||
void SetDefaultFocus();
|
||||
void SetHeaderAutomationName();
|
||||
|
||||
Windows::Foundation::Collections::IObservableVector<Platform::Object^>^ CreateUIElementsForCategories(_In_ Windows::Foundation::Collections::IObservableVector<CalculatorApp::Common::NavCategoryGroup^>^ categories);
|
||||
Windows::Foundation::Collections::IObservableVector<Platform::Object^>^ CreateUIElementsForCategories(_In_ Windows::Foundation::Collections::IObservableVector<Common::NavCategoryGroup^>^ categories);
|
||||
|
||||
protected:
|
||||
void OnNavigatedTo(_In_ Windows::UI::Xaml::Navigation::NavigationEventArgs^ e) override;
|
||||
|
@ -57,13 +58,13 @@ namespace CalculatorApp
|
|||
void OnAboutFlyoutOpened(_In_ Platform::Object^ sender, _In_ Platform::Object^ e);
|
||||
void OnAboutFlyoutClosed(_In_ Platform::Object^ sender, _In_ Platform::Object^ e);
|
||||
|
||||
Microsoft::UI::Xaml::Controls::NavigationViewItemHeader^ CreateNavViewHeaderFromGroup(CalculatorApp::Common::NavCategoryGroup^ group);
|
||||
Microsoft::UI::Xaml::Controls::NavigationViewItem^ CreateNavViewItemFromCategory(CalculatorApp::Common::NavCategory^ category);
|
||||
Microsoft::UI::Xaml::Controls::NavigationViewItemHeader^ CreateNavViewHeaderFromGroup(Common::NavCategoryGroup^ group);
|
||||
Microsoft::UI::Xaml::Controls::NavigationViewItem^ CreateNavViewItemFromCategory(Common::NavCategory^ category);
|
||||
|
||||
Windows::Foundation::EventRegistrationToken m_fullscreenFlyoutClosedToken;
|
||||
void OnFullscreenFlyoutClosed();
|
||||
|
||||
void ShowHideControls(CalculatorApp::Common::ViewMode mode);
|
||||
void ShowHideControls(Common::ViewMode mode);
|
||||
void UpdateViewState();
|
||||
void UpdatePanelViewState();
|
||||
|
||||
|
@ -73,21 +74,23 @@ namespace CalculatorApp
|
|||
void PinUnpinAppBarButtonOnClicked(_In_ Platform::Object^ sender, _In_ Windows::UI::Xaml::RoutedEventArgs^ e);
|
||||
|
||||
void EnsureCalculator();
|
||||
void EnsureConverter();
|
||||
void EnsureDateCalculator();
|
||||
void EnsureGraphingCalculator();
|
||||
void EnsureConverter();
|
||||
void ShowAboutPage();
|
||||
|
||||
void AnnounceCategoryName();
|
||||
|
||||
CalculatorApp::Calculator^ m_calculator;
|
||||
CalculatorApp::UnitConverter^ m_converter;
|
||||
CalculatorApp::DateCalculator^ m_dateCalculator;
|
||||
Calculator^ m_calculator;
|
||||
GraphingCalculator^ m_graphingCalculator;
|
||||
UnitConverter^ m_converter;
|
||||
DateCalculator^ m_dateCalculator;
|
||||
Windows::Foundation::EventRegistrationToken _windowSizeEventToken;
|
||||
Windows::Foundation::EventRegistrationToken m_hardwareButtonsBackPressedToken;
|
||||
Windows::Foundation::EventRegistrationToken m_colorValuesChangedToken;
|
||||
CalculatorApp::ViewModel::ApplicationViewModel^ m_model;
|
||||
ViewModel::ApplicationViewModel^ m_model;
|
||||
Windows::UI::ViewManagement::UISettings^ m_uiSettings;
|
||||
|
||||
std::unique_ptr<CalculatorApp::Common::TitleBarHelper> m_titleBarHelper;
|
||||
std::unique_ptr<Common::TitleBarHelper> m_titleBarHelper;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -97,7 +97,7 @@ namespace CalculatorUnitTests
|
|||
|
||||
// Boundary testing
|
||||
VERIFY_ARE_EQUAL(ViewMode::None, NavCategory::Deserialize(ref new Box<int>(-1)));
|
||||
VERIFY_ARE_EQUAL(ViewMode::None, NavCategory::Deserialize(ref new Box<int>(17)));
|
||||
VERIFY_ARE_EQUAL(ViewMode::None, NavCategory::Deserialize(ref new Box<int>(18)));
|
||||
}
|
||||
|
||||
void NavCategoryUnitTests::IsValidViewMode_AllValid()
|
||||
|
@ -106,6 +106,7 @@ namespace CalculatorUnitTests
|
|||
VERIFY_IS_TRUE(NavCategory::IsValidViewMode(ViewMode::Scientific));
|
||||
VERIFY_IS_TRUE(NavCategory::IsValidViewMode(ViewMode::Programmer));
|
||||
VERIFY_IS_TRUE(NavCategory::IsValidViewMode(ViewMode::Date));
|
||||
VERIFY_IS_TRUE(NavCategory::IsValidViewMode(ViewMode::Graphing));
|
||||
VERIFY_IS_TRUE(NavCategory::IsValidViewMode(ViewMode::Currency));
|
||||
VERIFY_IS_TRUE(NavCategory::IsValidViewMode(ViewMode::Volume));
|
||||
VERIFY_IS_TRUE(NavCategory::IsValidViewMode(ViewMode::Length));
|
||||
|
@ -125,9 +126,9 @@ namespace CalculatorUnitTests
|
|||
{
|
||||
VERIFY_IS_FALSE(NavCategory::IsValidViewMode(ViewMode::None));
|
||||
|
||||
// There are 17 total options so int 17 should be the first invalid
|
||||
VERIFY_IS_TRUE(NavCategory::IsValidViewMode(static_cast<ViewMode>(16)));
|
||||
VERIFY_IS_FALSE(NavCategory::IsValidViewMode(static_cast<ViewMode>(17)));
|
||||
// There are 18 total options so int 18 should be the first invalid
|
||||
VERIFY_IS_TRUE(NavCategory::IsValidViewMode(static_cast<ViewMode>(17)));
|
||||
VERIFY_IS_FALSE(NavCategory::IsValidViewMode(static_cast<ViewMode>(18)));
|
||||
|
||||
// Also verify the lower bound
|
||||
VERIFY_IS_TRUE(NavCategory::IsValidViewMode(static_cast<ViewMode>(0)));
|
||||
|
@ -141,6 +142,7 @@ namespace CalculatorUnitTests
|
|||
VERIFY_IS_TRUE(NavCategory::IsCalculatorViewMode(ViewMode::Programmer));
|
||||
|
||||
VERIFY_IS_FALSE(NavCategory::IsCalculatorViewMode(ViewMode::Date));
|
||||
VERIFY_IS_FALSE(NavCategory::IsCalculatorViewMode(ViewMode::Graphing));
|
||||
|
||||
VERIFY_IS_FALSE(NavCategory::IsCalculatorViewMode(ViewMode::Currency));
|
||||
VERIFY_IS_FALSE(NavCategory::IsCalculatorViewMode(ViewMode::Volume));
|
||||
|
@ -165,6 +167,8 @@ namespace CalculatorUnitTests
|
|||
|
||||
VERIFY_IS_TRUE(NavCategory::IsDateCalculatorViewMode(ViewMode::Date));
|
||||
|
||||
VERIFY_IS_FALSE(NavCategory::IsDateCalculatorViewMode(ViewMode::Graphing));
|
||||
|
||||
VERIFY_IS_FALSE(NavCategory::IsDateCalculatorViewMode(ViewMode::Currency));
|
||||
VERIFY_IS_FALSE(NavCategory::IsDateCalculatorViewMode(ViewMode::Volume));
|
||||
VERIFY_IS_FALSE(NavCategory::IsDateCalculatorViewMode(ViewMode::Length));
|
||||
|
@ -185,8 +189,8 @@ namespace CalculatorUnitTests
|
|||
VERIFY_IS_FALSE(NavCategory::IsConverterViewMode(ViewMode::Standard));
|
||||
VERIFY_IS_FALSE(NavCategory::IsConverterViewMode(ViewMode::Scientific));
|
||||
VERIFY_IS_FALSE(NavCategory::IsConverterViewMode(ViewMode::Programmer));
|
||||
|
||||
VERIFY_IS_FALSE(NavCategory::IsConverterViewMode(ViewMode::Date));
|
||||
VERIFY_IS_FALSE(NavCategory::IsConverterViewMode(ViewMode::Graphing));
|
||||
|
||||
VERIFY_IS_TRUE(NavCategory::IsConverterViewMode(ViewMode::Currency));
|
||||
VERIFY_IS_TRUE(NavCategory::IsConverterViewMode(ViewMode::Volume));
|
||||
|
@ -209,6 +213,7 @@ namespace CalculatorUnitTests
|
|||
VERIFY_ARE_EQUAL(StringReference(L"Scientific"), NavCategory::GetFriendlyName(ViewMode::Scientific));
|
||||
VERIFY_ARE_EQUAL(StringReference(L"Programmer"), NavCategory::GetFriendlyName(ViewMode::Programmer));
|
||||
VERIFY_ARE_EQUAL(StringReference(L"Date"), NavCategory::GetFriendlyName(ViewMode::Date));
|
||||
VERIFY_ARE_EQUAL(StringReference(L"Graphing"), NavCategory::GetFriendlyName(ViewMode::Graphing));
|
||||
VERIFY_ARE_EQUAL(StringReference(L"Currency"), NavCategory::GetFriendlyName(ViewMode::Currency));
|
||||
VERIFY_ARE_EQUAL(StringReference(L"Volume"), NavCategory::GetFriendlyName(ViewMode::Volume));
|
||||
VERIFY_ARE_EQUAL(StringReference(L"Length"), NavCategory::GetFriendlyName(ViewMode::Length));
|
||||
|
@ -232,6 +237,7 @@ namespace CalculatorUnitTests
|
|||
VERIFY_ARE_EQUAL(CategoryGroupType::Calculator, NavCategory::GetGroupType(ViewMode::Scientific));
|
||||
VERIFY_ARE_EQUAL(CategoryGroupType::Calculator, NavCategory::GetGroupType(ViewMode::Programmer));
|
||||
VERIFY_ARE_EQUAL(CategoryGroupType::Calculator, NavCategory::GetGroupType(ViewMode::Date));
|
||||
VERIFY_ARE_EQUAL(CategoryGroupType::Calculator, NavCategory::GetGroupType(ViewMode::Graphing));
|
||||
|
||||
VERIFY_ARE_EQUAL(CategoryGroupType::Converter, NavCategory::GetGroupType(ViewMode::Currency));
|
||||
VERIFY_ARE_EQUAL(CategoryGroupType::Converter, NavCategory::GetGroupType(ViewMode::Volume));
|
||||
|
@ -251,11 +257,12 @@ namespace CalculatorUnitTests
|
|||
void NavCategoryUnitTests::GetIndex()
|
||||
{
|
||||
// Index is the 0-based ordering of modes
|
||||
vector<ViewMode> orderedModes = {
|
||||
ViewMode orderedModes[] = {
|
||||
ViewMode::Standard,
|
||||
ViewMode::Scientific,
|
||||
ViewMode::Programmer,
|
||||
ViewMode::Date,
|
||||
ViewMode::Graphing,
|
||||
ViewMode::Currency,
|
||||
ViewMode::Volume,
|
||||
ViewMode::Length,
|
||||
|
@ -271,7 +278,8 @@ namespace CalculatorUnitTests
|
|||
ViewMode::Angle
|
||||
};
|
||||
|
||||
for (size_t index = 0; index < orderedModes.size(); index++)
|
||||
auto orderedModesSize = size(orderedModes);
|
||||
for (size_t index = 0; index < orderedModesSize; index++)
|
||||
{
|
||||
ViewMode mode = orderedModes[index];
|
||||
VERIFY_ARE_EQUAL(index, (size_t)NavCategory::GetIndex(mode));
|
||||
|
@ -283,11 +291,12 @@ namespace CalculatorUnitTests
|
|||
void NavCategoryUnitTests::GetPosition()
|
||||
{
|
||||
// Position is the 1-based ordering of modes
|
||||
vector<ViewMode> orderedModes = {
|
||||
ViewMode orderedModes[] = {
|
||||
ViewMode::Standard,
|
||||
ViewMode::Scientific,
|
||||
ViewMode::Programmer,
|
||||
ViewMode::Date,
|
||||
ViewMode::Graphing,
|
||||
ViewMode::Currency,
|
||||
ViewMode::Volume,
|
||||
ViewMode::Length,
|
||||
|
@ -303,7 +312,8 @@ namespace CalculatorUnitTests
|
|||
ViewMode::Angle
|
||||
};
|
||||
|
||||
for (size_t pos = 1; pos <= orderedModes.size(); pos++)
|
||||
auto orderedModesSize = size(orderedModes);
|
||||
for (size_t pos = 1; pos <= orderedModesSize; pos++)
|
||||
{
|
||||
ViewMode mode = orderedModes[pos - 1];
|
||||
VERIFY_ARE_EQUAL(pos, (size_t)NavCategory::GetPosition(mode));
|
||||
|
@ -327,6 +337,7 @@ namespace CalculatorUnitTests
|
|||
VERIFY_ARE_EQUAL(1, NavCategory::GetIndexInGroup(ViewMode::Scientific, CategoryGroupType::Calculator));
|
||||
VERIFY_ARE_EQUAL(2, NavCategory::GetIndexInGroup(ViewMode::Programmer, CategoryGroupType::Calculator));
|
||||
VERIFY_ARE_EQUAL(3, NavCategory::GetIndexInGroup(ViewMode::Date, CategoryGroupType::Calculator));
|
||||
VERIFY_ARE_EQUAL(4, NavCategory::GetIndexInGroup(ViewMode::Graphing, CategoryGroupType::Calculator));
|
||||
|
||||
VERIFY_ARE_EQUAL(0, NavCategory::GetIndexInGroup(ViewMode::Currency, CategoryGroupType::Converter));
|
||||
VERIFY_ARE_EQUAL(1, NavCategory::GetIndexInGroup(ViewMode::Volume, CategoryGroupType::Converter));
|
||||
|
@ -351,6 +362,8 @@ namespace CalculatorUnitTests
|
|||
VERIFY_ARE_EQUAL(ViewMode::Standard, NavCategory::GetViewModeForVirtualKey(MyVirtualKey::Number1));
|
||||
VERIFY_ARE_EQUAL(ViewMode::Scientific, NavCategory::GetViewModeForVirtualKey(MyVirtualKey::Number2));
|
||||
VERIFY_ARE_EQUAL(ViewMode::Programmer, NavCategory::GetViewModeForVirtualKey(MyVirtualKey::Number3));
|
||||
VERIFY_ARE_EQUAL(ViewMode::Date, NavCategory::GetViewModeForVirtualKey(MyVirtualKey::Number4));
|
||||
VERIFY_ARE_EQUAL(ViewMode::Graphing, NavCategory::GetViewModeForVirtualKey(MyVirtualKey::Number5));
|
||||
}
|
||||
|
||||
TEST_CLASS(NavCategoryGroupUnitTests)
|
||||
|
@ -380,29 +393,30 @@ namespace CalculatorUnitTests
|
|||
VERIFY_ARE_EQUAL(CategoryGroupType::Calculator, calculatorGroup->GroupType);
|
||||
|
||||
IObservableVector<NavCategory^>^ calculatorCategories = calculatorGroup->Categories;
|
||||
VERIFY_ARE_EQUAL(4, calculatorCategories->Size);
|
||||
VERIFY_ARE_EQUAL(5, calculatorCategories->Size);
|
||||
ValidateNavCategory(calculatorCategories, 0u, ViewMode::Standard, 1);
|
||||
ValidateNavCategory(calculatorCategories, 1u, ViewMode::Scientific, 2);
|
||||
ValidateNavCategory(calculatorCategories, 2u, ViewMode::Programmer, 3);
|
||||
ValidateNavCategory(calculatorCategories, 3u, ViewMode::Date, 4);
|
||||
ValidateNavCategory(calculatorCategories, 4u, ViewMode::Graphing, 5);
|
||||
|
||||
NavCategoryGroup^ converterGroup = menuOptions->GetAt(1);
|
||||
VERIFY_ARE_EQUAL(CategoryGroupType::Converter, converterGroup->GroupType);
|
||||
|
||||
IObservableVector<NavCategory^>^ converterCategories = converterGroup->Categories;
|
||||
VERIFY_ARE_EQUAL(13, converterCategories->Size);
|
||||
ValidateNavCategory(converterCategories, 0u, ViewMode::Currency, 5);
|
||||
ValidateNavCategory(converterCategories, 1u, ViewMode::Volume, 6);
|
||||
ValidateNavCategory(converterCategories, 2u, ViewMode::Length, 7);
|
||||
ValidateNavCategory(converterCategories, 3u, ViewMode::Weight, 8);
|
||||
ValidateNavCategory(converterCategories, 4u, ViewMode::Temperature, 9);
|
||||
ValidateNavCategory(converterCategories, 5u, ViewMode::Energy, 10);
|
||||
ValidateNavCategory(converterCategories, 6u, ViewMode::Area, 11);
|
||||
ValidateNavCategory(converterCategories, 7u, ViewMode::Speed, 12);
|
||||
ValidateNavCategory(converterCategories, 8u, ViewMode::Time, 13);
|
||||
ValidateNavCategory(converterCategories, 9u, ViewMode::Power, 14);
|
||||
ValidateNavCategory(converterCategories, 10u, ViewMode::Data, 15);
|
||||
ValidateNavCategory(converterCategories, 11u, ViewMode::Pressure, 16);
|
||||
ValidateNavCategory(converterCategories, 12u, ViewMode::Angle, 17);
|
||||
ValidateNavCategory(converterCategories, 0u, ViewMode::Currency, 6);
|
||||
ValidateNavCategory(converterCategories, 1u, ViewMode::Volume, 7);
|
||||
ValidateNavCategory(converterCategories, 2u, ViewMode::Length, 8);
|
||||
ValidateNavCategory(converterCategories, 3u, ViewMode::Weight, 9);
|
||||
ValidateNavCategory(converterCategories, 4u, ViewMode::Temperature, 10);
|
||||
ValidateNavCategory(converterCategories, 5u, ViewMode::Energy, 11);
|
||||
ValidateNavCategory(converterCategories, 6u, ViewMode::Area, 12);
|
||||
ValidateNavCategory(converterCategories, 7u, ViewMode::Speed, 13);
|
||||
ValidateNavCategory(converterCategories, 8u, ViewMode::Time, 14);
|
||||
ValidateNavCategory(converterCategories, 9u, ViewMode::Power, 15);
|
||||
ValidateNavCategory(converterCategories, 10u, ViewMode::Data, 16);
|
||||
ValidateNavCategory(converterCategories, 11u, ViewMode::Pressure, 17);
|
||||
ValidateNavCategory(converterCategories, 12u, ViewMode::Angle, 18);
|
||||
}
|
||||
}
|
||||
|
|
104
src/GraphControl/Control/Equation.cpp
Normal file
104
src/GraphControl/Control/Equation.cpp
Normal file
|
@ -0,0 +1,104 @@
|
|||
#include "pch.h"
|
||||
#include "Equation.h"
|
||||
|
||||
using namespace Platform;
|
||||
using namespace std;
|
||||
using namespace Windows::UI;
|
||||
using namespace Windows::UI::ViewManagement;
|
||||
using namespace Windows::UI::Xaml;
|
||||
|
||||
namespace GraphControl
|
||||
{
|
||||
DependencyProperty^ Equation::s_expressionProperty;
|
||||
static constexpr auto s_propertyName_Expression = L"Expression";
|
||||
|
||||
DependencyProperty^ Equation::s_lineColorProperty;
|
||||
static constexpr auto s_propertyName_LineColor = L"LineColor";
|
||||
|
||||
namespace EquationProperties
|
||||
{
|
||||
String^ Expression = StringReference(s_propertyName_Expression);
|
||||
String^ LineColor = StringReference(s_propertyName_LineColor);
|
||||
}
|
||||
|
||||
void Equation::RegisterDependencyProperties()
|
||||
{
|
||||
if (!s_expressionProperty)
|
||||
{
|
||||
s_expressionProperty = DependencyProperty::Register(
|
||||
EquationProperties::Expression,
|
||||
String::typeid,
|
||||
Equation::typeid,
|
||||
ref new PropertyMetadata(
|
||||
nullptr,
|
||||
ref new PropertyChangedCallback(&Equation::OnCustomDependencyPropertyChanged)));
|
||||
}
|
||||
|
||||
if (!s_lineColorProperty)
|
||||
{
|
||||
// Default line color should be the user's accent color
|
||||
auto uiSettings = ref new UISettings();
|
||||
Color accentColor = uiSettings->GetColorValue(UIColorType::Accent);
|
||||
|
||||
s_lineColorProperty = DependencyProperty::Register(
|
||||
EquationProperties::LineColor,
|
||||
Color::typeid,
|
||||
Equation::typeid,
|
||||
ref new PropertyMetadata(
|
||||
accentColor,
|
||||
ref new PropertyChangedCallback(&Equation::OnCustomDependencyPropertyChanged)));
|
||||
}
|
||||
}
|
||||
|
||||
void Equation::OnCustomDependencyPropertyChanged(DependencyObject^ obj, DependencyPropertyChangedEventArgs^ args)
|
||||
{
|
||||
if (auto eq = static_cast<Equation^>(obj))
|
||||
{
|
||||
String^ propertyName = nullptr;
|
||||
if (args->Property == s_expressionProperty)
|
||||
{
|
||||
propertyName = EquationProperties::Expression;
|
||||
}
|
||||
else if (args->Property == s_lineColorProperty)
|
||||
{
|
||||
propertyName = EquationProperties::LineColor;
|
||||
}
|
||||
|
||||
eq->PropertyChanged(eq, propertyName);
|
||||
}
|
||||
}
|
||||
|
||||
wstring Equation::GetRequest()
|
||||
{
|
||||
wstringstream ss{};
|
||||
ss << GetRequestHeader()
|
||||
<< GetExpression()
|
||||
<< GetLineColor()
|
||||
<< L")";
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
wstring Equation::GetRequestHeader()
|
||||
{
|
||||
wstring expr{ Expression->Data() };
|
||||
if (expr.find(L"=") != wstring::npos)
|
||||
{
|
||||
return L"plotEq2d("s;
|
||||
}
|
||||
else
|
||||
{
|
||||
return L"plot2d("s;
|
||||
}
|
||||
}
|
||||
|
||||
wstring Equation::GetExpression()
|
||||
{
|
||||
return Expression->Data();
|
||||
}
|
||||
|
||||
wstring Equation::GetLineColor()
|
||||
{
|
||||
return L""s;
|
||||
}
|
||||
}
|
80
src/GraphControl/Control/Equation.h
Normal file
80
src/GraphControl/Control/Equation.h
Normal file
|
@ -0,0 +1,80 @@
|
|||
#pragma once
|
||||
|
||||
namespace GraphControl
|
||||
{
|
||||
namespace EquationProperties
|
||||
{
|
||||
extern Platform::String^ Expression;
|
||||
extern Platform::String^ LineColor;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
public:
|
||||
Equation() {}
|
||||
|
||||
static void RegisterDependencyProperties();
|
||||
|
||||
#pragma region Platform::String^ Expression DependencyProperty
|
||||
static property Windows::UI::Xaml::DependencyProperty^ ExpressionProperty
|
||||
{
|
||||
Windows::UI::Xaml::DependencyProperty^ get()
|
||||
{
|
||||
return s_expressionProperty;
|
||||
}
|
||||
}
|
||||
property Platform::String^ Expression
|
||||
{
|
||||
Platform::String^ get()
|
||||
{
|
||||
return static_cast<Platform::String^>(GetValue(s_expressionProperty));
|
||||
}
|
||||
void set(Platform::String^ value)
|
||||
{
|
||||
SetValue(s_expressionProperty, value);
|
||||
}
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Windows::UI::Color LineColor DependencyProperty
|
||||
static property Windows::UI::Xaml::DependencyProperty^ LineColorProperty
|
||||
{
|
||||
Windows::UI::Xaml::DependencyProperty^ get()
|
||||
{
|
||||
return s_lineColorProperty;
|
||||
}
|
||||
}
|
||||
property Windows::UI::Color LineColor
|
||||
{
|
||||
Windows::UI::Color get()
|
||||
{
|
||||
return static_cast<Windows::UI::Color>(GetValue(s_lineColorProperty));
|
||||
}
|
||||
void set(Windows::UI::Color value)
|
||||
{
|
||||
SetValue(s_lineColorProperty, value);
|
||||
}
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
internal:
|
||||
event PropertyChangedEventHandler^ PropertyChanged;
|
||||
|
||||
std::wstring GetRequest();
|
||||
|
||||
private:
|
||||
static void OnCustomDependencyPropertyChanged(Windows::UI::Xaml::DependencyObject^ obj, Windows::UI::Xaml::DependencyPropertyChangedEventArgs^ args);
|
||||
|
||||
std::wstring GetRequestHeader();
|
||||
std::wstring GetExpression();
|
||||
std::wstring GetLineColor();
|
||||
|
||||
private:
|
||||
static Windows::UI::Xaml::DependencyProperty^ s_expressionProperty;
|
||||
static Windows::UI::Xaml::DependencyProperty^ s_lineColorProperty;
|
||||
};
|
||||
}
|
176
src/GraphControl/Control/EquationCollection.h
Normal file
176
src/GraphControl/Control/EquationCollection.h
Normal file
|
@ -0,0 +1,176 @@
|
|||
#pragma once
|
||||
|
||||
#include "Equation.h"
|
||||
|
||||
namespace GraphControl
|
||||
{
|
||||
delegate void EquationChangedEventHandler();
|
||||
|
||||
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 GraphControl::PropertyChangedEventHandler(this, &EquationCollection::OnEquationPropertyChanged)
|
||||
);
|
||||
|
||||
EquationChanged();
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
EquationChanged();
|
||||
}
|
||||
|
||||
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 PropertyChangedEventHandler(this, &EquationCollection::OnEquationPropertyChanged)
|
||||
);
|
||||
|
||||
EquationChanged();
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
EquationChanged();
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
EquationChanged();
|
||||
}
|
||||
|
||||
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 PropertyChangedEventHandler(this, &EquationCollection::OnEquationPropertyChanged);
|
||||
}
|
||||
|
||||
m_vector->ReplaceAll(items);
|
||||
|
||||
EquationChanged();
|
||||
}
|
||||
|
||||
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 PropertyChangedEventHandler(this, &EquationCollection::OnEquationPropertyChanged);
|
||||
|
||||
EquationChanged();
|
||||
}
|
||||
#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;
|
||||
|
||||
private:
|
||||
void OnEquationPropertyChanged(GraphControl::Equation^, Platform::String^ propertyName)
|
||||
{
|
||||
EquationChanged();
|
||||
}
|
||||
|
||||
private:
|
||||
Platform::Collections::Vector< GraphControl::Equation^ >^ m_vector;
|
||||
std::vector<Windows::Foundation::EventRegistrationToken> m_tokens;
|
||||
};
|
||||
}
|
392
src/GraphControl/Control/Grapher.cpp
Normal file
392
src/GraphControl/Control/Grapher.cpp
Normal file
|
@ -0,0 +1,392 @@
|
|||
#include "pch.h"
|
||||
#include "Grapher.h"
|
||||
|
||||
using namespace Graphing;
|
||||
using namespace GraphControl;
|
||||
using namespace GraphControl::DX;
|
||||
using namespace Platform;
|
||||
using namespace Platform::Collections;
|
||||
using namespace std;
|
||||
using namespace Windows::Foundation;
|
||||
using namespace Windows::Foundation::Collections;
|
||||
using namespace Windows::UI;
|
||||
using namespace Windows::UI::Input;
|
||||
using namespace Windows::UI::Xaml;
|
||||
using namespace Windows::UI::Xaml::Controls;
|
||||
using namespace Windows::UI::Xaml::Input;
|
||||
using namespace Windows::UI::Xaml::Media;
|
||||
|
||||
namespace GraphControl
|
||||
{
|
||||
constexpr auto s_defaultStyleKey = L"GraphControl.Grapher";
|
||||
constexpr auto s_templateKey_SwapChainPanel = L"GraphSurface";
|
||||
|
||||
DependencyProperty^ Grapher::s_equationTemplateProperty;
|
||||
constexpr auto s_propertyName_EquationTemplate = L"EquationTemplate";
|
||||
|
||||
DependencyProperty^ Grapher::s_equationsProperty;
|
||||
constexpr auto s_propertyName_Equations = L"Equations";
|
||||
|
||||
DependencyProperty^ Grapher::s_equationsSourceProperty;
|
||||
constexpr auto s_propertyName_EquationsSource = L"EquationsSource";
|
||||
|
||||
DependencyProperty^ Grapher::s_forceProportionalAxesTemplateProperty;
|
||||
constexpr auto s_propertyName_ForceProportionalAxes = L"ForceProportionalAxes";
|
||||
|
||||
Grapher::Grapher()
|
||||
: m_solver{ IMathSolver::CreateMathSolver() }
|
||||
, m_graph{ m_solver->CreateGrapher() }
|
||||
{
|
||||
m_solver->ParsingOptions().SetFormatType(FormatType::Linear);
|
||||
|
||||
DefaultStyleKey = StringReference(s_defaultStyleKey);
|
||||
|
||||
this->SetValue(EquationsProperty, ref new EquationCollection());
|
||||
|
||||
this->Loaded += ref new RoutedEventHandler(this, &Grapher::OnLoaded);
|
||||
this->Unloaded += ref new RoutedEventHandler(this, &Grapher::OnUnloaded);
|
||||
}
|
||||
|
||||
void Grapher::OnLoaded(Object^ sender, RoutedEventArgs^ args)
|
||||
{
|
||||
if (auto backgroundBrush = safe_cast<SolidColorBrush^>(this->Background))
|
||||
{
|
||||
m_tokenBackgroundColorChanged.Value =
|
||||
backgroundBrush->RegisterPropertyChangedCallback(SolidColorBrush::ColorProperty, ref new DependencyPropertyChangedCallback(this, &Grapher::OnDependencyPropertyChanged));
|
||||
|
||||
OnBackgroundColorChanged(backgroundBrush->Color);
|
||||
}
|
||||
}
|
||||
|
||||
void Grapher::OnUnloaded(Object^ sender, RoutedEventArgs^ args)
|
||||
{
|
||||
if (auto backgroundBrush = safe_cast<SolidColorBrush^>(this->Background))
|
||||
{
|
||||
this->UnregisterPropertyChangedCallback(BackgroundProperty, m_tokenBackgroundColorChanged.Value);
|
||||
}
|
||||
}
|
||||
|
||||
void Grapher::OnApplyTemplate()
|
||||
{
|
||||
auto swapChainPanel = dynamic_cast<SwapChainPanel^>(GetTemplateChild(StringReference(s_templateKey_SwapChainPanel)));
|
||||
if (swapChainPanel)
|
||||
{
|
||||
m_renderMain = ref new RenderMain(swapChainPanel);
|
||||
}
|
||||
|
||||
UpdateGraph();
|
||||
}
|
||||
|
||||
void Grapher::RegisterDependencyProperties()
|
||||
{
|
||||
if (!s_equationsProperty)
|
||||
{
|
||||
s_equationsProperty = DependencyProperty::Register(
|
||||
StringReference(s_propertyName_Equations),
|
||||
EquationCollection::typeid ,
|
||||
Grapher::typeid,
|
||||
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_forceProportionalAxesTemplateProperty)
|
||||
{
|
||||
s_forceProportionalAxesTemplateProperty = DependencyProperty::Register(
|
||||
StringReference(s_propertyName_ForceProportionalAxes),
|
||||
bool::typeid,
|
||||
Grapher::typeid,
|
||||
ref new PropertyMetadata(
|
||||
true,
|
||||
ref new PropertyChangedCallback(&Grapher::OnCustomDependencyPropertyChanged)));
|
||||
}
|
||||
}
|
||||
|
||||
void Grapher::OnCustomDependencyPropertyChanged(DependencyObject^ obj, DependencyPropertyChangedEventArgs^ args)
|
||||
{
|
||||
auto self = static_cast<Grapher^>(obj);
|
||||
if (self)
|
||||
{
|
||||
if (args->Property == EquationsProperty)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Grapher::OnDependencyPropertyChanged(DependencyObject^ obj, DependencyProperty^ p)
|
||||
{
|
||||
if (p == SolidColorBrush::ColorProperty)
|
||||
{
|
||||
auto brush = static_cast<SolidColorBrush^>(obj);
|
||||
OnBackgroundColorChanged(brush->Color);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
m_tokenEquationChanged.Value = 0;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
UpdateGraph();
|
||||
}
|
||||
|
||||
void Grapher::OnEquationsVectorChanged(IObservableVector<Equation^>^ sender, IVectorChangedEventArgs^ event)
|
||||
{
|
||||
UpdateGraph();
|
||||
}
|
||||
|
||||
void Grapher::OnEquationChanged()
|
||||
{
|
||||
UpdateGraph();
|
||||
}
|
||||
|
||||
void Grapher::UpdateGraph()
|
||||
{
|
||||
if (m_renderMain && m_graph != nullptr)
|
||||
{
|
||||
auto validEqs = GetValidEquations();
|
||||
if (!validEqs.empty())
|
||||
{
|
||||
|
||||
wstringstream ss{};
|
||||
ss << L"show2d(";
|
||||
|
||||
int numValidEquations = 0;
|
||||
for (Equation^ eq : validEqs)
|
||||
{
|
||||
if (numValidEquations++ > 0)
|
||||
{
|
||||
ss << L",";
|
||||
}
|
||||
|
||||
ss << eq->GetRequest();
|
||||
}
|
||||
|
||||
ss << L")";
|
||||
|
||||
wstring request = ss.str();
|
||||
if (auto graphExpression = m_solver->ParseInput(request))
|
||||
{
|
||||
if (m_graph->TryInitialize(graphExpression.get()))
|
||||
{
|
||||
UpdateGraphOptions(m_graph->GetOptions(), validEqs);
|
||||
|
||||
m_renderMain->Graph = m_graph;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Grapher::UpdateGraphOptions(IGraphingOptions& options, const vector<Equation^>& validEqs)
|
||||
{
|
||||
options.SetForceProportional(ForceProportionalAxes);
|
||||
|
||||
vector<Graphing::Color> graphColors;
|
||||
graphColors.reserve(validEqs.size());
|
||||
for (Equation^ eq : validEqs)
|
||||
{
|
||||
auto lineColor = eq->LineColor;
|
||||
graphColors.emplace_back(
|
||||
lineColor.R,
|
||||
lineColor.G,
|
||||
lineColor.B,
|
||||
lineColor.A);
|
||||
}
|
||||
options.SetGraphColors(graphColors);
|
||||
}
|
||||
|
||||
vector<Equation^> Grapher::GetValidEquations()
|
||||
{
|
||||
vector<Equation^> validEqs;
|
||||
|
||||
for (Equation^ eq : Equations)
|
||||
{
|
||||
if (!eq->Expression->IsEmpty())
|
||||
{
|
||||
validEqs.push_back(eq);
|
||||
}
|
||||
}
|
||||
|
||||
return validEqs;
|
||||
}
|
||||
|
||||
void Grapher::OnForceProportionalAxesChanged(DependencyPropertyChangedEventArgs^ args)
|
||||
{
|
||||
UpdateGraph();
|
||||
}
|
||||
|
||||
void Grapher::OnBackgroundColorChanged(const Windows::UI::Color& color)
|
||||
{
|
||||
if (m_renderMain)
|
||||
{
|
||||
m_renderMain->BackgroundColor = color;
|
||||
}
|
||||
}
|
||||
|
||||
void Grapher::OnPointerEntered(PointerRoutedEventArgs^ e)
|
||||
{
|
||||
if (m_renderMain)
|
||||
{
|
||||
OnPointerMoved(e);
|
||||
m_renderMain->DrawNearestPoint = true;
|
||||
|
||||
e->Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Grapher::OnPointerMoved(PointerRoutedEventArgs^ e)
|
||||
{
|
||||
if (m_renderMain)
|
||||
{
|
||||
PointerPoint^ currPoint = e->GetCurrentPoint(/* relativeTo */ this);
|
||||
m_renderMain->PointerLocation = currPoint->Position;
|
||||
|
||||
e->Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Grapher::OnPointerExited(PointerRoutedEventArgs^ e)
|
||||
{
|
||||
if (m_renderMain)
|
||||
{
|
||||
m_renderMain->DrawNearestPoint = false;
|
||||
e->Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
160
src/GraphControl/Control/Grapher.h
Normal file
160
src/GraphControl/Control/Grapher.h
Normal file
|
@ -0,0 +1,160 @@
|
|||
#pragma once
|
||||
|
||||
#include "InspectingDataSource.h"
|
||||
#include "DirectX/RenderMain.h"
|
||||
#include "Equation.h"
|
||||
#include "EquationCollection.h"
|
||||
#include "IMathSolver.h"
|
||||
|
||||
namespace GraphControl
|
||||
{
|
||||
[Windows::UI::Xaml::Markup::ContentPropertyAttribute(Name = L"Equations")]
|
||||
public ref class Grapher sealed : public Windows::UI::Xaml::Controls::Control
|
||||
{
|
||||
public:
|
||||
Grapher();
|
||||
|
||||
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
|
||||
{
|
||||
Windows::UI::Xaml::DependencyProperty^ get()
|
||||
{
|
||||
return s_equationsProperty;
|
||||
}
|
||||
}
|
||||
|
||||
property GraphControl::EquationCollection^ Equations
|
||||
{
|
||||
GraphControl::EquationCollection^ get()
|
||||
{
|
||||
return static_cast< GraphControl::EquationCollection^ >(GetValue(s_equationsProperty));
|
||||
}
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Windows::UI::Xaml::DataTemplate^ ForceProportionalAxes DependencyProperty
|
||||
static property Windows::UI::Xaml::DependencyProperty^ ForceProportionalAxesTemplateProperty
|
||||
{
|
||||
Windows::UI::Xaml::DependencyProperty^ get()
|
||||
{
|
||||
return s_forceProportionalAxesTemplateProperty;
|
||||
}
|
||||
}
|
||||
|
||||
property bool ForceProportionalAxes
|
||||
{
|
||||
bool get()
|
||||
{
|
||||
return static_cast<bool>(GetValue(s_forceProportionalAxesTemplateProperty));
|
||||
}
|
||||
void set(bool value)
|
||||
{
|
||||
SetValue(s_forceProportionalAxesTemplateProperty, value);
|
||||
}
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
protected:
|
||||
#pragma region Control Overrides
|
||||
void OnApplyTemplate() override;
|
||||
|
||||
void OnPointerEntered(Windows::UI::Xaml::Input::PointerRoutedEventArgs^ e) override;
|
||||
void OnPointerMoved(Windows::UI::Xaml::Input::PointerRoutedEventArgs^ e) override;
|
||||
void OnPointerExited(Windows::UI::Xaml::Input::PointerRoutedEventArgs^ e) override;
|
||||
#pragma endregion
|
||||
|
||||
private:
|
||||
void OnLoaded(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ args);
|
||||
void OnUnloaded(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ args);
|
||||
|
||||
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 OnEquationChanged();
|
||||
|
||||
void UpdateGraph();
|
||||
void UpdateGraphOptions(Graphing::IGraphingOptions& options, const std::vector<Equation^>& validEqs);
|
||||
std::vector<Equation^> GetValidEquations();
|
||||
|
||||
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);
|
||||
|
||||
private:
|
||||
DX::RenderMain^ m_renderMain = nullptr;
|
||||
|
||||
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;
|
||||
Windows::Foundation::EventRegistrationToken m_tokenEquationsChanged;
|
||||
Windows::Foundation::EventRegistrationToken m_tokenEquationChanged;
|
||||
|
||||
static Windows::UI::Xaml::DependencyProperty^ s_forceProportionalAxesTemplateProperty;
|
||||
|
||||
Windows::Foundation::EventRegistrationToken m_tokenBackgroundColorChanged;
|
||||
|
||||
const std::unique_ptr<Graphing::IMathSolver> m_solver;
|
||||
const std::shared_ptr<Graphing::IGraph> m_graph;
|
||||
void OnEquationsVectorChanged(Windows::Foundation::Collections::IObservableVector<GraphControl::Equation ^> ^sender, Windows::Foundation::Collections::IVectorChangedEventArgs ^event);
|
||||
};
|
||||
}
|
242
src/GraphControl/Control/InspectingDataSource.cpp
Normal file
242
src/GraphControl/Control/InspectingDataSource.cpp
Normal file
|
@ -0,0 +1,242 @@
|
|||
#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>());
|
||||
}
|
||||
}
|
62
src/GraphControl/Control/InspectingDataSource.h
Normal file
62
src/GraphControl/Control/InspectingDataSource.h
Normal file
|
@ -0,0 +1,62 @@
|
|||
#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;
|
||||
};
|
||||
}
|
659
src/GraphControl/DirectX/DeviceResources.cpp
Normal file
659
src/GraphControl/DirectX/DeviceResources.cpp
Normal file
|
@ -0,0 +1,659 @@
|
|||
#include "pch.h"
|
||||
#include "DeviceResources.h"
|
||||
#include "DirectXHelper.h"
|
||||
|
||||
using namespace D2D1;
|
||||
using namespace DirectX;
|
||||
using namespace Microsoft::WRL;
|
||||
using namespace std;
|
||||
using namespace Windows::Foundation;
|
||||
using namespace Windows::Graphics::Display;
|
||||
using namespace Windows::UI::Core;
|
||||
using namespace Windows::UI::Xaml::Controls;
|
||||
using namespace Platform;
|
||||
|
||||
namespace DisplayMetrics
|
||||
{
|
||||
// High resolution displays can require a lot of GPU and battery power to render.
|
||||
// High resolution phones, for example, may suffer from poor battery life if
|
||||
// games attempt to render at 60 frames per second at full fidelity.
|
||||
// The decision to render at full fidelity across all platforms and form factors
|
||||
// should be deliberate.
|
||||
static constexpr bool SupportHighResolutions = false;
|
||||
|
||||
// The default thresholds that define a "high resolution" display. If the thresholds
|
||||
// are exceeded and SupportHighResolutions is false, the dimensions will be scaled
|
||||
// by 50%.
|
||||
static constexpr float DpiThreshold = 192.0f; // 200% of standard desktop display.
|
||||
static constexpr float WidthThreshold = 1920.0f; // 1080p width.
|
||||
static constexpr float HeightThreshold = 1080.0f; // 1080p height.
|
||||
};
|
||||
|
||||
// Constants used to calculate screen rotations.
|
||||
namespace ScreenRotation
|
||||
{
|
||||
// 0-degree Z-rotation
|
||||
static constexpr XMFLOAT4X4 Rotation0(
|
||||
1.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 1.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 1.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 1.0f
|
||||
);
|
||||
|
||||
// 90-degree Z-rotation
|
||||
static constexpr XMFLOAT4X4 Rotation90(
|
||||
0.0f, 1.0f, 0.0f, 0.0f,
|
||||
-1.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 1.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 1.0f
|
||||
);
|
||||
|
||||
// 180-degree Z-rotation
|
||||
static constexpr XMFLOAT4X4 Rotation180(
|
||||
-1.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, -1.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 1.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 1.0f
|
||||
);
|
||||
|
||||
// 270-degree Z-rotation
|
||||
static constexpr XMFLOAT4X4 Rotation270(
|
||||
0.0f, -1.0f, 0.0f, 0.0f,
|
||||
1.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 1.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 1.0f
|
||||
);
|
||||
};
|
||||
|
||||
namespace GraphControl::DX
|
||||
{
|
||||
// Constructor for DeviceResources.
|
||||
DeviceResources::DeviceResources(SwapChainPanel^ panel) :
|
||||
m_screenViewport(),
|
||||
m_d3dFeatureLevel(D3D_FEATURE_LEVEL_9_1),
|
||||
m_d3dRenderTargetSize(),
|
||||
m_outputSize(),
|
||||
m_logicalSize(),
|
||||
m_nativeOrientation(DisplayOrientations::None),
|
||||
m_currentOrientation(DisplayOrientations::None),
|
||||
m_dpi(-1.0f),
|
||||
m_effectiveDpi(-1.0f),
|
||||
m_compositionScaleX(1.0f),
|
||||
m_compositionScaleY(1.0f),
|
||||
m_deviceNotify(nullptr)
|
||||
{
|
||||
CreateDeviceIndependentResources();
|
||||
CreateDeviceResources();
|
||||
SetSwapChainPanel(panel);
|
||||
}
|
||||
|
||||
// Configures resources that don't depend on the Direct3D device.
|
||||
void DeviceResources::CreateDeviceIndependentResources()
|
||||
{
|
||||
// Initialize Direct2D resources.
|
||||
D2D1_FACTORY_OPTIONS options;
|
||||
ZeroMemory(&options, sizeof(D2D1_FACTORY_OPTIONS));
|
||||
|
||||
#if defined(_DEBUG)
|
||||
// If the project is in a debug build, enable Direct2D debugging via SDK Layers.
|
||||
options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION;
|
||||
#endif
|
||||
|
||||
// Initialize the Direct2D Factory.
|
||||
DX::ThrowIfFailed(
|
||||
D2D1CreateFactory(
|
||||
D2D1_FACTORY_TYPE_SINGLE_THREADED,
|
||||
__uuidof(ID2D1Factory3),
|
||||
&options,
|
||||
&m_d2dFactory
|
||||
)
|
||||
);
|
||||
|
||||
// Initialize the DirectWrite Factory.
|
||||
DX::ThrowIfFailed(
|
||||
DWriteCreateFactory(
|
||||
DWRITE_FACTORY_TYPE_SHARED,
|
||||
__uuidof(IDWriteFactory3),
|
||||
&m_dwriteFactory
|
||||
)
|
||||
);
|
||||
|
||||
// Initialize the Windows Imaging Component (WIC) Factory.
|
||||
DX::ThrowIfFailed(
|
||||
CoCreateInstance(
|
||||
CLSID_WICImagingFactory2,
|
||||
nullptr,
|
||||
CLSCTX_INPROC_SERVER,
|
||||
IID_PPV_ARGS(&m_wicFactory)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Configures the Direct3D device, and stores handles to it and the device context.
|
||||
void DeviceResources::CreateDeviceResources()
|
||||
{
|
||||
// This flag adds support for surfaces with a different color channel ordering
|
||||
// than the API default. It is required for compatibility with Direct2D.
|
||||
UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
|
||||
|
||||
#if defined(_DEBUG)
|
||||
if (DX::SdkLayersAvailable())
|
||||
{
|
||||
// If the project is in a debug build, enable debugging via SDK Layers with this flag.
|
||||
creationFlags |= D3D11_CREATE_DEVICE_DEBUG;
|
||||
}
|
||||
#endif
|
||||
|
||||
// This array defines the set of DirectX hardware feature levels this app will support.
|
||||
// Note the ordering should be preserved.
|
||||
// Don't forget to declare your application's minimum required feature level in its
|
||||
// description. All applications are assumed to support 9.1 unless otherwise stated.
|
||||
static constexpr UINT featureLevelsSize = 9;
|
||||
static constexpr std::array<D3D_FEATURE_LEVEL, featureLevelsSize> featureLevels =
|
||||
{
|
||||
D3D_FEATURE_LEVEL_12_1,
|
||||
D3D_FEATURE_LEVEL_12_0,
|
||||
D3D_FEATURE_LEVEL_11_1,
|
||||
D3D_FEATURE_LEVEL_11_0,
|
||||
D3D_FEATURE_LEVEL_10_1,
|
||||
D3D_FEATURE_LEVEL_10_0,
|
||||
D3D_FEATURE_LEVEL_9_3,
|
||||
D3D_FEATURE_LEVEL_9_2,
|
||||
D3D_FEATURE_LEVEL_9_1
|
||||
};
|
||||
|
||||
// Create the Direct3D 11 API device object and a corresponding context.
|
||||
ComPtr<ID3D11Device> device;
|
||||
ComPtr<ID3D11DeviceContext> context;
|
||||
|
||||
HRESULT hr = D3D11CreateDevice(
|
||||
nullptr, // Specify nullptr to use the default adapter.
|
||||
D3D_DRIVER_TYPE_HARDWARE, // Create a device using the hardware graphics driver.
|
||||
0, // Should be 0 unless the driver is D3D_DRIVER_TYPE_SOFTWARE.
|
||||
creationFlags, // Set debug and Direct2D compatibility flags.
|
||||
&featureLevels[0], // List of feature levels this app can support.
|
||||
featureLevelsSize, // Size of the list above.
|
||||
D3D11_SDK_VERSION, // Always set this to D3D11_SDK_VERSION for Windows Store apps.
|
||||
&device, // Returns the Direct3D device created.
|
||||
&m_d3dFeatureLevel, // Returns feature level of device created.
|
||||
&context // Returns the device immediate context.
|
||||
);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
// If the initialization fails, fall back to the WARP device.
|
||||
// For more information on WARP, see:
|
||||
// https://go.microsoft.com/fwlink/?LinkId=286690
|
||||
DX::ThrowIfFailed(
|
||||
D3D11CreateDevice(
|
||||
nullptr,
|
||||
D3D_DRIVER_TYPE_WARP, // Create a WARP device instead of a hardware device.
|
||||
0,
|
||||
creationFlags,
|
||||
&featureLevels[0],
|
||||
featureLevelsSize,
|
||||
D3D11_SDK_VERSION,
|
||||
&device,
|
||||
&m_d3dFeatureLevel,
|
||||
&context
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Store pointers to the Direct3D 11.3 API device and immediate context.
|
||||
DX::ThrowIfFailed(
|
||||
device.As(&m_d3dDevice)
|
||||
);
|
||||
|
||||
DX::ThrowIfFailed(
|
||||
context.As(&m_d3dContext)
|
||||
);
|
||||
|
||||
// Create the Direct2D device object and a corresponding context.
|
||||
ComPtr<IDXGIDevice3> dxgiDevice;
|
||||
DX::ThrowIfFailed(
|
||||
m_d3dDevice.As(&dxgiDevice)
|
||||
);
|
||||
|
||||
DX::ThrowIfFailed(
|
||||
m_d2dFactory->CreateDevice(dxgiDevice.Get(), &m_d2dDevice)
|
||||
);
|
||||
|
||||
DX::ThrowIfFailed(
|
||||
m_d2dDevice->CreateDeviceContext(
|
||||
D2D1_DEVICE_CONTEXT_OPTIONS_NONE,
|
||||
&m_d2dContext
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// These resources need to be recreated every time the window size is changed.
|
||||
void DeviceResources::CreateWindowSizeDependentResources()
|
||||
{
|
||||
// Clear the previous window size specific context.
|
||||
static constexpr std::array<ID3D11RenderTargetView*, 1> nullViews = { nullptr };
|
||||
m_d3dContext->OMSetRenderTargets(static_cast<UINT>(nullViews.size()), &nullViews[0], nullptr);
|
||||
m_d3dRenderTargetView = nullptr;
|
||||
m_d2dContext->SetTarget(nullptr);
|
||||
m_d2dTargetBitmap = nullptr;
|
||||
m_d3dDepthStencilView = nullptr;
|
||||
m_d3dContext->Flush1(D3D11_CONTEXT_TYPE_ALL, nullptr);
|
||||
|
||||
UpdateRenderTargetSize();
|
||||
|
||||
m_d3dRenderTargetSize.Width = m_outputSize.Width;
|
||||
m_d3dRenderTargetSize.Height = m_outputSize.Height;
|
||||
|
||||
if (m_swapChain != nullptr)
|
||||
{
|
||||
// If the swap chain already exists, resize it.
|
||||
HRESULT hr = m_swapChain->ResizeBuffers(
|
||||
2, // Double-buffered swap chain.
|
||||
lround(m_d3dRenderTargetSize.Width),
|
||||
lround(m_d3dRenderTargetSize.Height),
|
||||
DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
0
|
||||
);
|
||||
|
||||
if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)
|
||||
{
|
||||
// If the device was removed for any reason, a new device and swap chain will need to be created.
|
||||
HandleDeviceLost();
|
||||
|
||||
// Everything is set up now. Do not continue execution of this method. HandleDeviceLost will reenter this method
|
||||
// and correctly set up the new device.
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
DX::ThrowIfFailed(hr);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise, create a new one using the same adapter as the existing Direct3D device.
|
||||
DXGI_SCALING scaling = DisplayMetrics::SupportHighResolutions ? DXGI_SCALING_NONE : DXGI_SCALING_STRETCH;
|
||||
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = { 0 };
|
||||
|
||||
swapChainDesc.Width = lround(m_d3dRenderTargetSize.Width); // Match the size of the window.
|
||||
swapChainDesc.Height = lround(m_d3dRenderTargetSize.Height);
|
||||
swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; // This is the most common swap chain format.
|
||||
swapChainDesc.Stereo = false;
|
||||
swapChainDesc.SampleDesc.Count = 1; // Don't use multi-sampling.
|
||||
swapChainDesc.SampleDesc.Quality = 0;
|
||||
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
swapChainDesc.BufferCount = 2; // Use double-buffering to minimize latency.
|
||||
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; // All Windows Store apps must use _FLIP_ SwapEffects.
|
||||
swapChainDesc.Flags = 0;
|
||||
swapChainDesc.Scaling = scaling;
|
||||
swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE;
|
||||
|
||||
// This sequence obtains the DXGI factory that was used to create the Direct3D device above.
|
||||
ComPtr<IDXGIDevice3> dxgiDevice;
|
||||
DX::ThrowIfFailed(
|
||||
m_d3dDevice.As(&dxgiDevice)
|
||||
);
|
||||
|
||||
ComPtr<IDXGIAdapter> dxgiAdapter;
|
||||
DX::ThrowIfFailed(
|
||||
dxgiDevice->GetAdapter(&dxgiAdapter)
|
||||
);
|
||||
|
||||
ComPtr<IDXGIFactory4> dxgiFactory;
|
||||
DX::ThrowIfFailed(
|
||||
dxgiAdapter->GetParent(IID_PPV_ARGS(&dxgiFactory))
|
||||
);
|
||||
|
||||
// When using XAML interop, the swap chain must be created for composition.
|
||||
ComPtr<IDXGISwapChain1> swapChain;
|
||||
DX::ThrowIfFailed(
|
||||
dxgiFactory->CreateSwapChainForComposition(
|
||||
m_d3dDevice.Get(),
|
||||
&swapChainDesc,
|
||||
nullptr,
|
||||
&swapChain
|
||||
)
|
||||
);
|
||||
|
||||
DX::ThrowIfFailed(
|
||||
swapChain.As(&m_swapChain)
|
||||
);
|
||||
|
||||
// Associate swap chain with SwapChainPanel
|
||||
// UI changes will need to be dispatched back to the UI thread
|
||||
m_swapChainPanel->Dispatcher->RunAsync(CoreDispatcherPriority::High, ref new DispatchedHandler([=]()
|
||||
{
|
||||
// Get backing native interface for SwapChainPanel
|
||||
ComPtr<ISwapChainPanelNative> panelNative;
|
||||
DX::ThrowIfFailed(
|
||||
reinterpret_cast<IUnknown*>(m_swapChainPanel)->QueryInterface(IID_PPV_ARGS(&panelNative))
|
||||
);
|
||||
|
||||
DX::ThrowIfFailed(
|
||||
panelNative->SetSwapChain(m_swapChain.Get())
|
||||
);
|
||||
}, CallbackContext::Any));
|
||||
|
||||
// Ensure that DXGI does not queue more than one frame at a time. This both reduces latency and
|
||||
// ensures that the application will only render after each VSync, minimizing power consumption.
|
||||
DX::ThrowIfFailed(
|
||||
dxgiDevice->SetMaximumFrameLatency(1)
|
||||
);
|
||||
}
|
||||
|
||||
// Set the proper orientation for the swap chain, and generate 2D and
|
||||
// 3D matrix transformations for rendering to the rotated swap chain.
|
||||
// Note the rotation angle for the 2D and 3D transforms are different.
|
||||
// This is due to the difference in coordinate spaces. Additionally,
|
||||
// the 3D matrix is specified explicitly to avoid rounding errors.
|
||||
|
||||
m_orientationTransform2D = Matrix3x2F::Identity();
|
||||
m_orientationTransform3D = ScreenRotation::Rotation0;
|
||||
|
||||
// Setup inverse scale on the swap chain
|
||||
DXGI_MATRIX_3X2_F inverseScale = { 0 };
|
||||
inverseScale._11 = 1.0f / m_effectiveCompositionScaleX;
|
||||
inverseScale._22 = 1.0f / m_effectiveCompositionScaleY;
|
||||
ComPtr<IDXGISwapChain2> spSwapChain2;
|
||||
DX::ThrowIfFailed(
|
||||
m_swapChain.As<IDXGISwapChain2>(&spSwapChain2)
|
||||
);
|
||||
|
||||
DX::ThrowIfFailed(
|
||||
spSwapChain2->SetMatrixTransform(&inverseScale)
|
||||
);
|
||||
|
||||
// Create a render target view of the swap chain back buffer.
|
||||
ComPtr<ID3D11Texture2D1> backBuffer;
|
||||
DX::ThrowIfFailed(
|
||||
m_swapChain->GetBuffer(0, IID_PPV_ARGS(&backBuffer))
|
||||
);
|
||||
|
||||
DX::ThrowIfFailed(
|
||||
m_d3dDevice->CreateRenderTargetView1(
|
||||
backBuffer.Get(),
|
||||
nullptr,
|
||||
&m_d3dRenderTargetView
|
||||
)
|
||||
);
|
||||
|
||||
// Create a depth stencil view for use with 3D rendering if needed.
|
||||
CD3D11_TEXTURE2D_DESC1 depthStencilDesc(
|
||||
DXGI_FORMAT_D24_UNORM_S8_UINT,
|
||||
lround(m_d3dRenderTargetSize.Width),
|
||||
lround(m_d3dRenderTargetSize.Height),
|
||||
1, // This depth stencil view has only one texture.
|
||||
1, // Use a single mipmap level.
|
||||
D3D11_BIND_DEPTH_STENCIL
|
||||
);
|
||||
|
||||
ComPtr<ID3D11Texture2D1> depthStencil;
|
||||
DX::ThrowIfFailed(
|
||||
m_d3dDevice->CreateTexture2D1(
|
||||
&depthStencilDesc,
|
||||
nullptr,
|
||||
&depthStencil
|
||||
)
|
||||
);
|
||||
|
||||
CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D);
|
||||
DX::ThrowIfFailed(
|
||||
m_d3dDevice->CreateDepthStencilView(
|
||||
depthStencil.Get(),
|
||||
&depthStencilViewDesc,
|
||||
&m_d3dDepthStencilView
|
||||
)
|
||||
);
|
||||
|
||||
// Set the 3D rendering viewport to target the entire window.
|
||||
m_screenViewport = CD3D11_VIEWPORT(
|
||||
0.0f,
|
||||
0.0f,
|
||||
m_d3dRenderTargetSize.Width,
|
||||
m_d3dRenderTargetSize.Height
|
||||
);
|
||||
|
||||
m_d3dContext->RSSetViewports(1, &m_screenViewport);
|
||||
|
||||
// Create a Direct2D target bitmap associated with the
|
||||
// swap chain back buffer and set it as the current target.
|
||||
D2D1_BITMAP_PROPERTIES1 bitmapProperties =
|
||||
D2D1::BitmapProperties1(
|
||||
D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW,
|
||||
D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED),
|
||||
m_dpi,
|
||||
m_dpi
|
||||
);
|
||||
|
||||
ComPtr<IDXGISurface2> dxgiBackBuffer;
|
||||
DX::ThrowIfFailed(
|
||||
m_swapChain->GetBuffer(0, IID_PPV_ARGS(&dxgiBackBuffer))
|
||||
);
|
||||
|
||||
DX::ThrowIfFailed(
|
||||
m_d2dContext->CreateBitmapFromDxgiSurface(
|
||||
dxgiBackBuffer.Get(),
|
||||
&bitmapProperties,
|
||||
&m_d2dTargetBitmap
|
||||
)
|
||||
);
|
||||
|
||||
m_d2dContext->SetTarget(m_d2dTargetBitmap.Get());
|
||||
m_d2dContext->SetDpi(m_effectiveDpi, m_effectiveDpi);
|
||||
|
||||
// Grayscale text anti-aliasing is recommended for all Windows Store apps.
|
||||
m_d2dContext->SetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE);
|
||||
}
|
||||
|
||||
// Determine the dimensions of the render target and whether it will be scaled down.
|
||||
void DeviceResources::UpdateRenderTargetSize()
|
||||
{
|
||||
m_effectiveDpi = m_dpi;
|
||||
m_effectiveCompositionScaleX = m_compositionScaleX;
|
||||
m_effectiveCompositionScaleY = m_compositionScaleY;
|
||||
|
||||
// To improve battery life on high resolution devices, render to a smaller render target
|
||||
// and allow the GPU to scale the output when it is presented.
|
||||
if (!DisplayMetrics::SupportHighResolutions && m_dpi > DisplayMetrics::DpiThreshold)
|
||||
{
|
||||
float width = DX::ConvertDipsToPixels(m_logicalSize.Width, m_dpi);
|
||||
float height = DX::ConvertDipsToPixels(m_logicalSize.Height, m_dpi);
|
||||
|
||||
// When the device is in portrait orientation, height > width. Compare the
|
||||
// larger dimension against the width threshold and the smaller dimension
|
||||
// against the height threshold.
|
||||
if (max(width, height) > DisplayMetrics::WidthThreshold && min(width, height) > DisplayMetrics::HeightThreshold)
|
||||
{
|
||||
// To scale the app we change the effective DPI. Logical size does not change.
|
||||
m_effectiveDpi /= 2.0f;
|
||||
m_effectiveCompositionScaleX /= 2.0f;
|
||||
m_effectiveCompositionScaleY /= 2.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate the necessary render target size in pixels.
|
||||
m_outputSize.Width = DX::ConvertDipsToPixels(m_logicalSize.Width, m_effectiveDpi);
|
||||
m_outputSize.Height = DX::ConvertDipsToPixels(m_logicalSize.Height, m_effectiveDpi);
|
||||
|
||||
// Prevent zero size DirectX content from being created.
|
||||
m_outputSize.Width = max(m_outputSize.Width, 1.0f);
|
||||
m_outputSize.Height = max(m_outputSize.Height, 1.0f);
|
||||
}
|
||||
|
||||
// This method is called when the XAML control is created (or re-created).
|
||||
void DeviceResources::SetSwapChainPanel(SwapChainPanel^ panel)
|
||||
{
|
||||
DisplayInformation^ currentDisplayInformation = DisplayInformation::GetForCurrentView();
|
||||
|
||||
m_swapChainPanel = panel;
|
||||
m_logicalSize = Windows::Foundation::Size(static_cast<float>(panel->ActualWidth), static_cast<float>(panel->ActualHeight));
|
||||
m_nativeOrientation = currentDisplayInformation->NativeOrientation;
|
||||
m_currentOrientation = currentDisplayInformation->CurrentOrientation;
|
||||
m_compositionScaleX = panel->CompositionScaleX;
|
||||
m_compositionScaleY = panel->CompositionScaleY;
|
||||
m_dpi = currentDisplayInformation->LogicalDpi;
|
||||
m_d2dContext->SetDpi(m_dpi, m_dpi);
|
||||
|
||||
CreateWindowSizeDependentResources();
|
||||
}
|
||||
|
||||
// This method is called in the event handler for the SizeChanged event.
|
||||
void DeviceResources::SetLogicalSize(Windows::Foundation::Size logicalSize)
|
||||
{
|
||||
if (m_logicalSize != logicalSize)
|
||||
{
|
||||
m_logicalSize = logicalSize;
|
||||
CreateWindowSizeDependentResources();
|
||||
}
|
||||
}
|
||||
|
||||
// This method is called in the event handler for the DpiChanged event.
|
||||
void DeviceResources::SetDpi(float dpi)
|
||||
{
|
||||
if (dpi != m_dpi)
|
||||
{
|
||||
m_dpi = dpi;
|
||||
m_d2dContext->SetDpi(m_dpi, m_dpi);
|
||||
CreateWindowSizeDependentResources();
|
||||
}
|
||||
}
|
||||
|
||||
// This method is called in the event handler for the OrientationChanged event.
|
||||
void DeviceResources::SetCurrentOrientation(DisplayOrientations currentOrientation)
|
||||
{
|
||||
if (m_currentOrientation != currentOrientation)
|
||||
{
|
||||
m_currentOrientation = currentOrientation;
|
||||
CreateWindowSizeDependentResources();
|
||||
}
|
||||
}
|
||||
|
||||
// This method is called in the event handler for the CompositionScaleChanged event.
|
||||
void DeviceResources::SetCompositionScale(float compositionScaleX, float compositionScaleY)
|
||||
{
|
||||
if (m_compositionScaleX != compositionScaleX ||
|
||||
m_compositionScaleY != compositionScaleY)
|
||||
{
|
||||
m_compositionScaleX = compositionScaleX;
|
||||
m_compositionScaleY = compositionScaleY;
|
||||
CreateWindowSizeDependentResources();
|
||||
}
|
||||
}
|
||||
|
||||
// This method is called in the event handler for the DisplayContentsInvalidated event.
|
||||
void DeviceResources::ValidateDevice()
|
||||
{
|
||||
// The D3D Device is no longer valid if the default adapter changed since the device
|
||||
// was created or if the device has been removed.
|
||||
|
||||
// First, get the information for the default adapter from when the device was created.
|
||||
|
||||
ComPtr<IDXGIDevice3> dxgiDevice;
|
||||
DX::ThrowIfFailed(m_d3dDevice.As(&dxgiDevice));
|
||||
|
||||
ComPtr<IDXGIAdapter> deviceAdapter;
|
||||
DX::ThrowIfFailed(dxgiDevice->GetAdapter(&deviceAdapter));
|
||||
|
||||
ComPtr<IDXGIFactory2> deviceFactory;
|
||||
DX::ThrowIfFailed(deviceAdapter->GetParent(IID_PPV_ARGS(&deviceFactory)));
|
||||
|
||||
ComPtr<IDXGIAdapter1> previousDefaultAdapter;
|
||||
DX::ThrowIfFailed(deviceFactory->EnumAdapters1(0, &previousDefaultAdapter));
|
||||
|
||||
DXGI_ADAPTER_DESC1 previousDesc;
|
||||
DX::ThrowIfFailed(previousDefaultAdapter->GetDesc1(&previousDesc));
|
||||
|
||||
// Next, get the information for the current default adapter.
|
||||
|
||||
ComPtr<IDXGIFactory4> currentFactory;
|
||||
DX::ThrowIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(¤tFactory)));
|
||||
|
||||
ComPtr<IDXGIAdapter1> currentDefaultAdapter;
|
||||
DX::ThrowIfFailed(currentFactory->EnumAdapters1(0, ¤tDefaultAdapter));
|
||||
|
||||
DXGI_ADAPTER_DESC1 currentDesc;
|
||||
DX::ThrowIfFailed(currentDefaultAdapter->GetDesc1(¤tDesc));
|
||||
|
||||
// If the adapter LUIDs don't match, or if the device reports that it has been removed,
|
||||
// a new D3D device must be created.
|
||||
|
||||
if (previousDesc.AdapterLuid.LowPart != currentDesc.AdapterLuid.LowPart ||
|
||||
previousDesc.AdapterLuid.HighPart != currentDesc.AdapterLuid.HighPart ||
|
||||
FAILED(m_d3dDevice->GetDeviceRemovedReason()))
|
||||
{
|
||||
// Release references to resources related to the old device.
|
||||
dxgiDevice = nullptr;
|
||||
deviceAdapter = nullptr;
|
||||
deviceFactory = nullptr;
|
||||
previousDefaultAdapter = nullptr;
|
||||
|
||||
// Create a new device and swap chain.
|
||||
HandleDeviceLost();
|
||||
}
|
||||
}
|
||||
|
||||
// Recreate all device resources and set them back to the current state.
|
||||
void DeviceResources::HandleDeviceLost()
|
||||
{
|
||||
m_swapChain = nullptr;
|
||||
|
||||
if (m_deviceNotify != nullptr)
|
||||
{
|
||||
m_deviceNotify->OnDeviceLost();
|
||||
}
|
||||
|
||||
CreateDeviceResources();
|
||||
m_d2dContext->SetDpi(m_dpi, m_dpi);
|
||||
CreateWindowSizeDependentResources();
|
||||
|
||||
if (m_deviceNotify != nullptr)
|
||||
{
|
||||
m_deviceNotify->OnDeviceRestored();
|
||||
}
|
||||
}
|
||||
|
||||
// Register our DeviceNotify to be informed on device lost and creation.
|
||||
void DeviceResources::RegisterDeviceNotify(DX::IDeviceNotify^ deviceNotify)
|
||||
{
|
||||
m_deviceNotify = deviceNotify;
|
||||
}
|
||||
|
||||
// Call this method when the app suspends. It provides a hint to the driver that the app
|
||||
// is entering an idle state and that temporary buffers can be reclaimed for use by other apps.
|
||||
void DeviceResources::Trim()
|
||||
{
|
||||
ComPtr<IDXGIDevice3> dxgiDevice;
|
||||
m_d3dDevice.As(&dxgiDevice);
|
||||
|
||||
dxgiDevice->Trim();
|
||||
}
|
||||
|
||||
// Present the contents of the swap chain to the screen.
|
||||
void DeviceResources::Present()
|
||||
{
|
||||
// The first argument instructs DXGI to block until VSync, putting the application
|
||||
// to sleep until the next VSync. This ensures we don't waste any cycles rendering
|
||||
// frames that will never be displayed to the screen.
|
||||
DXGI_PRESENT_PARAMETERS parameters = { 0 };
|
||||
HRESULT hr = m_swapChain->Present1(1, 0, ¶meters);
|
||||
|
||||
// Discard the contents of the render target.
|
||||
// This is a valid operation only when the existing contents will be entirely
|
||||
// overwritten. If dirty or scroll rects are used, this call should be modified.
|
||||
m_d3dContext->DiscardView1(m_d3dRenderTargetView.Get(), nullptr, 0);
|
||||
|
||||
// Discard the contents of the depth stencil.
|
||||
m_d3dContext->DiscardView1(m_d3dDepthStencilView.Get(), nullptr, 0);
|
||||
|
||||
// If the device was removed either by a disconnection or a driver upgrade, we
|
||||
// must recreate all device resources.
|
||||
if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)
|
||||
{
|
||||
HandleDeviceLost();
|
||||
}
|
||||
else
|
||||
{
|
||||
DX::ThrowIfFailed(hr);
|
||||
}
|
||||
}
|
||||
}
|
108
src/GraphControl/DirectX/DeviceResources.h
Normal file
108
src/GraphControl/DirectX/DeviceResources.h
Normal file
|
@ -0,0 +1,108 @@
|
|||
#pragma once
|
||||
|
||||
// Modified from the default template for Xaml and Direct3D 11 apps.
|
||||
|
||||
namespace GraphControl::DX
|
||||
{
|
||||
// Provides an interface for an application that owns DeviceResources to be notified of the device being lost or created.
|
||||
interface class IDeviceNotify
|
||||
{
|
||||
virtual void OnDeviceLost();
|
||||
virtual void OnDeviceRestored();
|
||||
};
|
||||
|
||||
// Controls all the DirectX device resources.
|
||||
class DeviceResources
|
||||
{
|
||||
public:
|
||||
DeviceResources(Windows::UI::Xaml::Controls::SwapChainPanel^ panel);
|
||||
void SetSwapChainPanel(Windows::UI::Xaml::Controls::SwapChainPanel^ panel);
|
||||
void SetLogicalSize(Windows::Foundation::Size logicalSize);
|
||||
void SetCurrentOrientation(Windows::Graphics::Display::DisplayOrientations currentOrientation);
|
||||
void SetDpi(float dpi);
|
||||
void SetCompositionScale(float compositionScaleX, float compositionScaleY);
|
||||
void ValidateDevice();
|
||||
void HandleDeviceLost();
|
||||
void RegisterDeviceNotify(IDeviceNotify^ deviceNotify);
|
||||
void Trim();
|
||||
void Present();
|
||||
|
||||
// The size of the render target, in pixels.
|
||||
Windows::Foundation::Size GetOutputSize() const { return m_outputSize; }
|
||||
|
||||
// The size of the render target, in dips.
|
||||
Windows::Foundation::Size GetLogicalSize() const { return m_logicalSize; }
|
||||
float GetDpi() const { return m_effectiveDpi; }
|
||||
|
||||
// D3D Accessors.
|
||||
ID3D11Device3* GetD3DDevice() const { return m_d3dDevice.Get(); }
|
||||
ID3D11DeviceContext3* GetD3DDeviceContext() const { return m_d3dContext.Get(); }
|
||||
IDXGISwapChain3* GetSwapChain() const { return m_swapChain.Get(); }
|
||||
D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; }
|
||||
ID3D11RenderTargetView1* GetBackBufferRenderTargetView() const { return m_d3dRenderTargetView.Get(); }
|
||||
ID3D11DepthStencilView* GetDepthStencilView() const { return m_d3dDepthStencilView.Get(); }
|
||||
D3D11_VIEWPORT GetScreenViewport() const { return m_screenViewport; }
|
||||
DirectX::XMFLOAT4X4 GetOrientationTransform3D() const { return m_orientationTransform3D; }
|
||||
|
||||
// D2D Accessors.
|
||||
ID2D1Factory3* GetD2DFactory() const { return m_d2dFactory.Get(); }
|
||||
ID2D1Device2* GetD2DDevice() const { return m_d2dDevice.Get(); }
|
||||
ID2D1DeviceContext2* GetD2DDeviceContext() const { return m_d2dContext.Get(); }
|
||||
ID2D1Bitmap1* GetD2DTargetBitmap() const { return m_d2dTargetBitmap.Get(); }
|
||||
IDWriteFactory3* GetDWriteFactory() const { return m_dwriteFactory.Get(); }
|
||||
IWICImagingFactory2* GetWicImagingFactory() const { return m_wicFactory.Get(); }
|
||||
D2D1::Matrix3x2F GetOrientationTransform2D() const { return m_orientationTransform2D; }
|
||||
|
||||
private:
|
||||
void CreateDeviceIndependentResources();
|
||||
void CreateDeviceResources();
|
||||
void CreateWindowSizeDependentResources();
|
||||
void UpdateRenderTargetSize();
|
||||
|
||||
// Direct3D objects.
|
||||
Microsoft::WRL::ComPtr<ID3D11Device3> m_d3dDevice;
|
||||
Microsoft::WRL::ComPtr<ID3D11DeviceContext3> m_d3dContext;
|
||||
Microsoft::WRL::ComPtr<IDXGISwapChain3> m_swapChain;
|
||||
|
||||
// Direct3D rendering objects. Required for 3D.
|
||||
Microsoft::WRL::ComPtr<ID3D11RenderTargetView1> m_d3dRenderTargetView;
|
||||
Microsoft::WRL::ComPtr<ID3D11DepthStencilView> m_d3dDepthStencilView;
|
||||
D3D11_VIEWPORT m_screenViewport;
|
||||
|
||||
// Direct2D drawing components.
|
||||
Microsoft::WRL::ComPtr<ID2D1Factory3> m_d2dFactory;
|
||||
Microsoft::WRL::ComPtr<ID2D1Device2> m_d2dDevice;
|
||||
Microsoft::WRL::ComPtr<ID2D1DeviceContext2> m_d2dContext;
|
||||
Microsoft::WRL::ComPtr<ID2D1Bitmap1> m_d2dTargetBitmap;
|
||||
|
||||
// DirectWrite drawing components.
|
||||
Microsoft::WRL::ComPtr<IDWriteFactory3> m_dwriteFactory;
|
||||
Microsoft::WRL::ComPtr<IWICImagingFactory2> m_wicFactory;
|
||||
|
||||
// Cached reference to the XAML panel.
|
||||
Windows::UI::Xaml::Controls::SwapChainPanel^ m_swapChainPanel;
|
||||
|
||||
// Cached device properties.
|
||||
D3D_FEATURE_LEVEL m_d3dFeatureLevel;
|
||||
Windows::Foundation::Size m_d3dRenderTargetSize;
|
||||
Windows::Foundation::Size m_outputSize;
|
||||
Windows::Foundation::Size m_logicalSize;
|
||||
Windows::Graphics::Display::DisplayOrientations m_nativeOrientation;
|
||||
Windows::Graphics::Display::DisplayOrientations m_currentOrientation;
|
||||
float m_dpi;
|
||||
float m_compositionScaleX;
|
||||
float m_compositionScaleY;
|
||||
|
||||
// Variables that take into account whether the app supports high resolution screens or not.
|
||||
float m_effectiveDpi;
|
||||
float m_effectiveCompositionScaleX;
|
||||
float m_effectiveCompositionScaleY;
|
||||
|
||||
// Transforms used for display orientation.
|
||||
D2D1::Matrix3x2F m_orientationTransform2D;
|
||||
DirectX::XMFLOAT4X4 m_orientationTransform3D;
|
||||
|
||||
// The IDeviceNotify can be held directly as it owns the DeviceResources.
|
||||
IDeviceNotify^ m_deviceNotify;
|
||||
};
|
||||
}
|
63
src/GraphControl/DirectX/DirectXHelper.h
Normal file
63
src/GraphControl/DirectX/DirectXHelper.h
Normal file
|
@ -0,0 +1,63 @@
|
|||
#pragma once
|
||||
|
||||
// Taken from the default template for Xaml and Direct3D 11 apps.
|
||||
|
||||
namespace GraphControl::DX
|
||||
{
|
||||
inline void ThrowIfFailed(HRESULT hr)
|
||||
{
|
||||
if (FAILED(hr))
|
||||
{
|
||||
// Set a breakpoint on this line to catch Win32 API errors.
|
||||
throw Platform::Exception::CreateException(hr);
|
||||
}
|
||||
}
|
||||
|
||||
// Function that reads from a binary file asynchronously.
|
||||
inline Concurrency::task<std::vector<byte>> ReadDataAsync(const std::wstring& filename)
|
||||
{
|
||||
using namespace Windows::Storage;
|
||||
using namespace Concurrency;
|
||||
|
||||
auto folder = Windows::ApplicationModel::Package::Current->InstalledLocation;
|
||||
|
||||
return create_task(folder->GetFileAsync(Platform::StringReference(filename.c_str()))).then([] (StorageFile^ file)
|
||||
{
|
||||
return FileIO::ReadBufferAsync(file);
|
||||
}).then([] (Streams::IBuffer^ fileBuffer) -> std::vector<byte>
|
||||
{
|
||||
std::vector<byte> returnBuffer;
|
||||
returnBuffer.resize(fileBuffer->Length);
|
||||
Streams::DataReader::FromBuffer(fileBuffer)->ReadBytes(Platform::ArrayReference<byte>(returnBuffer.data(), fileBuffer->Length));
|
||||
return returnBuffer;
|
||||
});
|
||||
}
|
||||
|
||||
// Converts a length in device-independent pixels (DIPs) to a length in physical pixels.
|
||||
inline float ConvertDipsToPixels(float dips, float dpi)
|
||||
{
|
||||
static const float dipsPerInch = 96.0f;
|
||||
return floorf(dips * dpi / dipsPerInch + 0.5f); // Round to nearest integer.
|
||||
}
|
||||
|
||||
#if defined(_DEBUG)
|
||||
// Check for SDK Layer support.
|
||||
inline bool SdkLayersAvailable()
|
||||
{
|
||||
HRESULT hr = D3D11CreateDevice(
|
||||
nullptr,
|
||||
D3D_DRIVER_TYPE_NULL, // There is no need to create a real hardware device.
|
||||
0,
|
||||
D3D11_CREATE_DEVICE_DEBUG, // Check for the SDK layers.
|
||||
nullptr, // Any feature level will do.
|
||||
0,
|
||||
D3D11_SDK_VERSION, // Always set this to D3D11_SDK_VERSION for Windows Store apps.
|
||||
nullptr, // No need to keep the D3D device reference.
|
||||
nullptr, // No need to know the feature level.
|
||||
nullptr // No need to keep the D3D device context reference.
|
||||
);
|
||||
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
#endif
|
||||
}
|
66
src/GraphControl/DirectX/NearestPointRenderer.cpp
Normal file
66
src/GraphControl/DirectX/NearestPointRenderer.cpp
Normal file
|
@ -0,0 +1,66 @@
|
|||
#include "pch.h"
|
||||
#include "NearestPointRenderer.h"
|
||||
#include "DirectXHelper.h"
|
||||
|
||||
using namespace D2D1;
|
||||
using namespace GraphControl::DX;
|
||||
using namespace std;
|
||||
using namespace Windows::Foundation;
|
||||
|
||||
namespace
|
||||
{
|
||||
const ColorF c_DefaultPointColor = ColorF::Black;
|
||||
constexpr float c_NearestPointRadius = 3;
|
||||
}
|
||||
|
||||
NearestPointRenderer::NearestPointRenderer(DeviceResources* deviceResources)
|
||||
: m_deviceResources{ deviceResources }
|
||||
, m_color{ c_DefaultPointColor }
|
||||
, m_ellipse{ D2D1_POINT_2F{ 0, 0 }, c_NearestPointRadius, c_NearestPointRadius }
|
||||
{
|
||||
CreateDeviceDependentResources();
|
||||
}
|
||||
|
||||
void NearestPointRenderer::CreateDeviceDependentResources()
|
||||
{
|
||||
CreateBrush();
|
||||
}
|
||||
|
||||
void NearestPointRenderer::ReleaseDeviceDependentResources()
|
||||
{
|
||||
m_brush.Reset();
|
||||
}
|
||||
|
||||
void NearestPointRenderer::Render(const Point& location)
|
||||
{
|
||||
if (ID2D1DeviceContext* context = m_deviceResources->GetD2DDeviceContext())
|
||||
{
|
||||
m_ellipse.point.x = location.X;
|
||||
m_ellipse.point.y = location.Y;
|
||||
|
||||
context->BeginDraw();
|
||||
context->FillEllipse(m_ellipse, m_brush.Get());
|
||||
|
||||
// Ignore D2DERR_RECREATE_TARGET here. This error indicates that the device
|
||||
// is lost. It will be handled during the next call to Present.
|
||||
HRESULT hr = context->EndDraw();
|
||||
if (hr != D2DERR_RECREATE_TARGET)
|
||||
{
|
||||
ThrowIfFailed(hr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NearestPointRenderer::SetColor(const ColorF& color)
|
||||
{
|
||||
m_color = color;
|
||||
CreateBrush();
|
||||
}
|
||||
|
||||
void NearestPointRenderer::CreateBrush()
|
||||
{
|
||||
m_brush.Reset();
|
||||
ThrowIfFailed(
|
||||
m_deviceResources->GetD2DDeviceContext()->CreateSolidColorBrush(m_color, &m_brush)
|
||||
);
|
||||
}
|
30
src/GraphControl/DirectX/NearestPointRenderer.h
Normal file
30
src/GraphControl/DirectX/NearestPointRenderer.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
#pragma once
|
||||
|
||||
namespace GraphControl::DX
|
||||
{
|
||||
class DeviceResources;
|
||||
|
||||
class NearestPointRenderer
|
||||
{
|
||||
public:
|
||||
NearestPointRenderer(DeviceResources* deviceResources);
|
||||
|
||||
void CreateDeviceDependentResources();
|
||||
void ReleaseDeviceDependentResources();
|
||||
void Render(const Windows::Foundation::Point& location);
|
||||
|
||||
void SetColor(const D2D1::ColorF& color);
|
||||
|
||||
private:
|
||||
void CreateBrush();
|
||||
|
||||
private:
|
||||
DeviceResources* const m_deviceResources;
|
||||
|
||||
D2D1::ColorF m_color;
|
||||
D2D1_ELLIPSE m_ellipse;
|
||||
|
||||
// Resources related to rendering.
|
||||
Microsoft::WRL::ComPtr<ID2D1SolidColorBrush> m_brush;
|
||||
};
|
||||
}
|
339
src/GraphControl/DirectX/RenderMain.cpp
Normal file
339
src/GraphControl/DirectX/RenderMain.cpp
Normal file
|
@ -0,0 +1,339 @@
|
|||
#include "pch.h"
|
||||
#include "RenderMain.h"
|
||||
#include "DirectXHelper.h"
|
||||
|
||||
using namespace Concurrency;
|
||||
using namespace Graphing;
|
||||
using namespace Platform;
|
||||
using namespace std;
|
||||
using namespace Windows::Foundation;
|
||||
using namespace Windows::Graphics::Display;
|
||||
using namespace Windows::System::Threading;
|
||||
using namespace Windows::UI::Core;
|
||||
using namespace Windows::UI::Xaml;
|
||||
using namespace Windows::UI::Xaml::Controls;
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr unsigned int s_RedChannelIndex = 0;
|
||||
constexpr unsigned int s_GreenChannelIndex = 1;
|
||||
constexpr unsigned int s_BlueChannelIndex = 2;
|
||||
constexpr unsigned int s_AlphaChannelIndex = 3;
|
||||
constexpr float s_MaxChannelValue = 255.0f;
|
||||
|
||||
constexpr float nearestPointRadius = 3;
|
||||
}
|
||||
|
||||
namespace GraphControl::DX
|
||||
{
|
||||
RenderMain::RenderMain(SwapChainPanel^ panel) :
|
||||
m_deviceResources{ panel },
|
||||
m_nearestPointRenderer{ &m_deviceResources },
|
||||
m_backgroundColor{ {} },
|
||||
m_swapChainPanel{ panel }
|
||||
{
|
||||
// Register to be notified if the Device is lost or recreated
|
||||
m_deviceResources.RegisterDeviceNotify(this);
|
||||
|
||||
RegisterEventHandlers();
|
||||
}
|
||||
|
||||
RenderMain::~RenderMain()
|
||||
{
|
||||
UnregisterEventHandlers();
|
||||
}
|
||||
|
||||
void RenderMain::Graph::set(shared_ptr< IGraph > graph)
|
||||
{
|
||||
m_graph = move(graph);
|
||||
|
||||
if (m_graph)
|
||||
{
|
||||
if (auto renderer = m_graph->GetRenderer())
|
||||
{
|
||||
float dpi = m_deviceResources.GetDpi();
|
||||
renderer->SetDpi(dpi, dpi);
|
||||
|
||||
renderer->SetGraphSize(
|
||||
static_cast<unsigned int>(m_swapChainPanel->ActualWidth),
|
||||
static_cast<unsigned int>(m_swapChainPanel->ActualHeight));
|
||||
}
|
||||
}
|
||||
|
||||
RunRenderPass();
|
||||
}
|
||||
|
||||
void RenderMain::BackgroundColor::set(Windows::UI::Color backgroundColor)
|
||||
{
|
||||
m_backgroundColor[s_RedChannelIndex] = static_cast<float>(backgroundColor.R) / s_MaxChannelValue;
|
||||
m_backgroundColor[s_GreenChannelIndex] = static_cast<float>(backgroundColor.G) / s_MaxChannelValue;
|
||||
m_backgroundColor[s_BlueChannelIndex] = static_cast<float>(backgroundColor.B) / s_MaxChannelValue;
|
||||
m_backgroundColor[s_AlphaChannelIndex] = static_cast<float>(backgroundColor.A) / s_MaxChannelValue;
|
||||
|
||||
RunRenderPass();
|
||||
}
|
||||
|
||||
void RenderMain::DrawNearestPoint::set(bool value)
|
||||
{
|
||||
if (m_drawNearestPoint != value)
|
||||
{
|
||||
m_drawNearestPoint = value;
|
||||
RunRenderPass();
|
||||
}
|
||||
}
|
||||
|
||||
void RenderMain::PointerLocation::set(Point location)
|
||||
{
|
||||
if (m_pointerLocation != location)
|
||||
{
|
||||
m_pointerLocation = location;
|
||||
RunRenderPass();
|
||||
}
|
||||
}
|
||||
|
||||
// Updates application state when the window size changes (e.g. device orientation change)
|
||||
void RenderMain::CreateWindowSizeDependentResources()
|
||||
{
|
||||
// TODO: Replace this with the sizedependent initialization of your app's content.
|
||||
RunRenderPass();
|
||||
}
|
||||
|
||||
void RenderMain::RunRenderPass()
|
||||
{
|
||||
if (Render())
|
||||
{
|
||||
m_deviceResources.Present();
|
||||
}
|
||||
}
|
||||
|
||||
// Renders the current frame according to the current application state.
|
||||
// Returns true if the frame was rendered and is ready to be displayed.
|
||||
bool RenderMain::Render()
|
||||
{
|
||||
bool successful = true;
|
||||
|
||||
// Must call BeginDraw before any draw commands.
|
||||
ID2D1Factory3 *pFactory = m_deviceResources.GetD2DFactory();
|
||||
ID2D1DeviceContext *pRenderTarget = m_deviceResources.GetD2DDeviceContext();
|
||||
|
||||
auto context = m_deviceResources.GetD3DDeviceContext();
|
||||
|
||||
// Clear the back buffer and set the background color.
|
||||
context->ClearRenderTargetView(m_deviceResources.GetBackBufferRenderTargetView(), m_backgroundColor);
|
||||
|
||||
if (m_graph)
|
||||
{
|
||||
if (auto renderer = m_graph->GetRenderer())
|
||||
{
|
||||
pRenderTarget->BeginDraw();
|
||||
|
||||
bool hasMissingData = false;
|
||||
successful = SUCCEEDED(renderer->DrawD2D1(pFactory, pRenderTarget, hasMissingData));
|
||||
|
||||
// We ignore D2DERR_RECREATE_TARGET here. This error indicates that the device
|
||||
// is lost. It will be handled during the next call to Present.
|
||||
HRESULT endDraw = pRenderTarget->EndDraw();
|
||||
if (endDraw != D2DERR_RECREATE_TARGET)
|
||||
{
|
||||
DX::ThrowIfFailed(endDraw);
|
||||
}
|
||||
|
||||
if (successful && m_drawNearestPoint)
|
||||
{
|
||||
int formulaId;
|
||||
Point nearestPointLocation;
|
||||
pair<float, float> nearestPointValue;
|
||||
renderer->GetClosePointData(
|
||||
m_pointerLocation.X, m_pointerLocation.Y,
|
||||
formulaId,
|
||||
nearestPointLocation.X, nearestPointLocation.Y,
|
||||
nearestPointValue.first, nearestPointValue.second);
|
||||
|
||||
if (!isnan(nearestPointLocation.X) && !isnan(nearestPointLocation.Y))
|
||||
{
|
||||
m_nearestPointRenderer.Render(nearestPointLocation);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return successful;
|
||||
}
|
||||
|
||||
void RenderMain::OnLoaded(Object^ sender, RoutedEventArgs^ e)
|
||||
{
|
||||
RunRenderPass();
|
||||
}
|
||||
|
||||
void RenderMain::RegisterEventHandlers()
|
||||
{
|
||||
UnregisterEventHandlers();
|
||||
|
||||
// Register event handlers for control lifecycle.
|
||||
m_coreWindow = Agile<CoreWindow>(Window::Current->CoreWindow);
|
||||
if (m_coreWindow != nullptr)
|
||||
{
|
||||
m_tokenVisibilityChanged =
|
||||
m_coreWindow->VisibilityChanged +=
|
||||
ref new TypedEventHandler<CoreWindow^, VisibilityChangedEventArgs^>(this, &RenderMain::OnVisibilityChanged);
|
||||
}
|
||||
|
||||
m_displayInformation = DisplayInformation::GetForCurrentView();
|
||||
if (m_displayInformation != nullptr)
|
||||
{
|
||||
m_tokenDpiChanged =
|
||||
m_displayInformation->DpiChanged +=
|
||||
ref new TypedEventHandler<DisplayInformation^, Object^>(this, &RenderMain::OnDpiChanged);
|
||||
|
||||
m_tokenOrientationChanged =
|
||||
m_displayInformation->OrientationChanged +=
|
||||
ref new TypedEventHandler<DisplayInformation^, Object^>(this, &RenderMain::OnOrientationChanged);
|
||||
}
|
||||
|
||||
m_tokenDisplayContentsInvalidated =
|
||||
DisplayInformation::DisplayContentsInvalidated +=
|
||||
ref new TypedEventHandler<DisplayInformation^, Object^>(this, &RenderMain::OnDisplayContentsInvalidated);
|
||||
|
||||
if (m_swapChainPanel != nullptr)
|
||||
{
|
||||
m_tokenLoaded =
|
||||
m_swapChainPanel->Loaded += ref new RoutedEventHandler(this, &RenderMain::OnLoaded);
|
||||
|
||||
m_tokenCompositionScaleChanged =
|
||||
m_swapChainPanel->CompositionScaleChanged +=
|
||||
ref new TypedEventHandler< SwapChainPanel^, Object^ >(this, &RenderMain::OnCompositionScaleChanged);
|
||||
|
||||
m_tokenSizeChanged =
|
||||
m_swapChainPanel->SizeChanged +=
|
||||
ref new SizeChangedEventHandler(this, &RenderMain::OnSizeChanged);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderMain::UnregisterEventHandlers()
|
||||
{
|
||||
if (m_coreWindow != nullptr)
|
||||
{
|
||||
if (m_tokenVisibilityChanged.Value != 0)
|
||||
{
|
||||
m_coreWindow->VisibilityChanged -= m_tokenVisibilityChanged;
|
||||
m_tokenVisibilityChanged.Value = 0;
|
||||
}
|
||||
m_coreWindow = nullptr;
|
||||
}
|
||||
|
||||
if (m_displayInformation != nullptr)
|
||||
{
|
||||
if (m_tokenDpiChanged.Value != 0)
|
||||
{
|
||||
m_displayInformation->DpiChanged -= m_tokenDpiChanged;
|
||||
m_tokenDpiChanged.Value = 0;
|
||||
}
|
||||
if (m_tokenOrientationChanged.Value != 0)
|
||||
{
|
||||
m_displayInformation->OrientationChanged -= m_tokenOrientationChanged;
|
||||
m_tokenOrientationChanged.Value = 0;
|
||||
}
|
||||
m_displayInformation = nullptr;
|
||||
}
|
||||
|
||||
if (m_tokenDisplayContentsInvalidated.Value != 0)
|
||||
{
|
||||
DisplayInformation::DisplayContentsInvalidated -= m_tokenDisplayContentsInvalidated;
|
||||
m_tokenDisplayContentsInvalidated.Value = 0;
|
||||
}
|
||||
|
||||
if (m_swapChainPanel != nullptr)
|
||||
{
|
||||
if (m_tokenLoaded.Value != 0)
|
||||
{
|
||||
m_swapChainPanel->Loaded -= m_tokenLoaded;
|
||||
m_tokenLoaded.Value = 0;
|
||||
}
|
||||
if (m_tokenCompositionScaleChanged.Value != 0)
|
||||
{
|
||||
m_swapChainPanel->CompositionScaleChanged -= m_tokenCompositionScaleChanged;
|
||||
m_tokenCompositionScaleChanged.Value = 0;
|
||||
}
|
||||
if (m_tokenSizeChanged.Value != 0)
|
||||
{
|
||||
m_swapChainPanel->SizeChanged -= m_tokenSizeChanged;
|
||||
m_tokenSizeChanged.Value = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RenderMain::OnVisibilityChanged(CoreWindow^ sender, VisibilityChangedEventArgs^ args)
|
||||
{
|
||||
if (args->Visible)
|
||||
{
|
||||
RunRenderPass();
|
||||
}
|
||||
}
|
||||
|
||||
void RenderMain::OnDpiChanged(DisplayInformation^ sender, Object^ args)
|
||||
{
|
||||
// Note: The value for LogicalDpi retrieved here may not match the effective DPI of the app
|
||||
// if it is being scaled for high resolution devices. Once the DPI is set on DeviceResources,
|
||||
// you should always retrieve it using the GetDpi method.
|
||||
// See DeviceResources.cpp for more details.
|
||||
m_deviceResources.SetDpi(sender->LogicalDpi);
|
||||
|
||||
if (m_graph)
|
||||
{
|
||||
if (auto renderer = m_graph->GetRenderer())
|
||||
{
|
||||
float dpi = m_deviceResources.GetDpi();
|
||||
renderer->SetDpi(dpi, dpi);
|
||||
}
|
||||
}
|
||||
|
||||
CreateWindowSizeDependentResources();
|
||||
}
|
||||
|
||||
void RenderMain::OnOrientationChanged(DisplayInformation^ sender, Object^ args)
|
||||
{
|
||||
m_deviceResources.SetCurrentOrientation(sender->CurrentOrientation);
|
||||
CreateWindowSizeDependentResources();
|
||||
}
|
||||
|
||||
void RenderMain::OnDisplayContentsInvalidated(DisplayInformation^ sender, Object^ args)
|
||||
{
|
||||
m_deviceResources.ValidateDevice();
|
||||
}
|
||||
|
||||
void RenderMain::OnCompositionScaleChanged(SwapChainPanel^ sender, Object^ args)
|
||||
{
|
||||
m_deviceResources.SetCompositionScale(sender->CompositionScaleX, sender->CompositionScaleY);
|
||||
CreateWindowSizeDependentResources();
|
||||
}
|
||||
|
||||
void RenderMain::OnSizeChanged(Object^ sender, SizeChangedEventArgs^ e)
|
||||
{
|
||||
m_deviceResources.SetLogicalSize(e->NewSize);
|
||||
|
||||
if (m_graph)
|
||||
{
|
||||
if (auto renderer = m_graph->GetRenderer())
|
||||
{
|
||||
const auto& newSize = e->NewSize;
|
||||
renderer->SetGraphSize(
|
||||
static_cast<unsigned int>(newSize.Width),
|
||||
static_cast<unsigned int>(newSize.Height));
|
||||
}
|
||||
}
|
||||
|
||||
CreateWindowSizeDependentResources();
|
||||
}
|
||||
|
||||
// Notifies renderers that device resources need to be released.
|
||||
void RenderMain::OnDeviceLost()
|
||||
{
|
||||
m_nearestPointRenderer.ReleaseDeviceDependentResources();
|
||||
}
|
||||
|
||||
// Notifies renderers that device resources may now be recreated.
|
||||
void RenderMain::OnDeviceRestored()
|
||||
{
|
||||
m_nearestPointRenderer.CreateDeviceDependentResources();
|
||||
}
|
||||
}
|
102
src/GraphControl/DirectX/RenderMain.h
Normal file
102
src/GraphControl/DirectX/RenderMain.h
Normal file
|
@ -0,0 +1,102 @@
|
|||
#pragma once
|
||||
|
||||
// Taken from the default template for Xaml and Direct3D 11 apps.
|
||||
|
||||
#include "DeviceResources.h"
|
||||
#include "NearestPointRenderer.h"
|
||||
#include "IGraph.h"
|
||||
|
||||
// Renders Direct2D and 3D content on the screen.
|
||||
namespace GraphControl::DX
|
||||
{
|
||||
ref class RenderMain sealed : public IDeviceNotify
|
||||
{
|
||||
public:
|
||||
virtual ~RenderMain();
|
||||
|
||||
// IDeviceNotify
|
||||
virtual void OnDeviceLost();
|
||||
virtual void OnDeviceRestored();
|
||||
|
||||
internal:
|
||||
RenderMain(Windows::UI::Xaml::Controls::SwapChainPanel^ panel);
|
||||
|
||||
property std::shared_ptr< Graphing::IGraph > Graph
|
||||
{
|
||||
void set(std::shared_ptr< Graphing::IGraph > graph);
|
||||
}
|
||||
|
||||
property Windows::UI::Color BackgroundColor
|
||||
{
|
||||
void set(Windows::UI::Color color);
|
||||
}
|
||||
|
||||
property bool DrawNearestPoint
|
||||
{
|
||||
void set(bool value);
|
||||
}
|
||||
|
||||
property Windows::Foundation::Point PointerLocation
|
||||
{
|
||||
void set(Windows::Foundation::Point location);
|
||||
}
|
||||
|
||||
void CreateWindowSizeDependentResources();
|
||||
|
||||
void RunRenderPass();
|
||||
|
||||
private:
|
||||
bool Render();
|
||||
|
||||
// Loaded/Unloaded
|
||||
void OnLoaded(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
|
||||
|
||||
// Dependent event registration
|
||||
void RegisterEventHandlers();
|
||||
void UnregisterEventHandlers();
|
||||
|
||||
// Window event handlers.
|
||||
void OnVisibilityChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::VisibilityChangedEventArgs^ args);
|
||||
|
||||
// DisplayInformation event handlers.
|
||||
void OnDpiChanged(Windows::Graphics::Display::DisplayInformation^ sender, Platform::Object^ args);
|
||||
void OnOrientationChanged(Windows::Graphics::Display::DisplayInformation^ sender, Platform::Object^ args);
|
||||
void OnDisplayContentsInvalidated(Windows::Graphics::Display::DisplayInformation^ sender, Platform::Object^ args);
|
||||
|
||||
// Other event handlers.
|
||||
void OnCompositionScaleChanged(Windows::UI::Xaml::Controls::SwapChainPanel^ sender, Object^ args);
|
||||
void OnSizeChanged(Platform::Object^ sender, Windows::UI::Xaml::SizeChangedEventArgs^ e);
|
||||
|
||||
private:
|
||||
DX::DeviceResources m_deviceResources;
|
||||
NearestPointRenderer m_nearestPointRenderer;
|
||||
|
||||
// Cached Graph object with Renderer property.
|
||||
std::shared_ptr< Graphing::IGraph > m_graph = nullptr;
|
||||
|
||||
// Track current input pointer position.
|
||||
bool m_drawNearestPoint = false;
|
||||
Windows::Foundation::Point m_pointerLocation;
|
||||
|
||||
float m_backgroundColor[4];
|
||||
|
||||
// The SwapChainPanel^ surface.
|
||||
Windows::UI::Xaml::Controls::SwapChainPanel^ m_swapChainPanel = nullptr;
|
||||
Windows::Foundation::EventRegistrationToken m_tokenLoaded;
|
||||
Windows::Foundation::EventRegistrationToken m_tokenCompositionScaleChanged;
|
||||
Windows::Foundation::EventRegistrationToken m_tokenSizeChanged;
|
||||
|
||||
// Cached references to event notifiers.
|
||||
Platform::Agile<Windows::UI::Core::CoreWindow> m_coreWindow = nullptr;
|
||||
Windows::Foundation::EventRegistrationToken m_tokenVisibilityChanged;
|
||||
|
||||
Windows::Graphics::Display::DisplayInformation^ m_displayInformation = nullptr;
|
||||
Windows::Foundation::EventRegistrationToken m_tokenDpiChanged;
|
||||
Windows::Foundation::EventRegistrationToken m_tokenOrientationChanged;
|
||||
Windows::Foundation::EventRegistrationToken m_tokenDisplayContentsInvalidated;
|
||||
|
||||
// Track our independent input on a background worker thread.
|
||||
Windows::Foundation::IAsyncAction^ m_inputLoopWorker = nullptr;
|
||||
Windows::UI::Core::CoreIndependentInputSource^ m_coreInput = nullptr;
|
||||
};
|
||||
}
|
346
src/GraphControl/GraphControl.vcxproj
Normal file
346
src/GraphControl/GraphControl.vcxproj
Normal file
|
@ -0,0 +1,346 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|ARM">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>ARM</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|ARM64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|ARM">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>ARM</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|ARM64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{e727a92b-f149-492c-8117-c039a298719b}</ProjectGuid>
|
||||
<Keyword>WindowsRuntimeComponent</Keyword>
|
||||
<RootNamespace>GraphControl</RootNamespace>
|
||||
<DefaultLanguage>en-US</DefaultLanguage>
|
||||
<MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
|
||||
<AppContainerApplication>true</AppContainerApplication>
|
||||
<ApplicationType>Windows Store</ApplicationType>
|
||||
<WindowsTargetPlatformVersion Condition="'$(WindowsTargetPlatformVersion)' == ''">10.0.17763.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformMinVersion>10.0.17134.0</WindowsTargetPlatformMinVersion>
|
||||
<ApplicationTypeRevision>10.0</ApplicationTypeRevision>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<GraphingInterfaceDir>$([MSBuild]::ValueOrDefault($(GraphingInterfaceDir), '$(SolutionDir)\GraphingInterfaces\'))</GraphingInterfaceDir>
|
||||
</PropertyGroup>
|
||||
<ImportGroup Condition="Exists('GraphingImplOverrides.props')">
|
||||
<Import Project="GraphingImplOverrides.props" />
|
||||
</ImportGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PreprocessorDefinitions>_WINRT_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<PrecompiledHeaderOutputFile>$(IntDir)pch.pch</PrecompiledHeaderOutputFile>
|
||||
<AdditionalUsingDirectories>$(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)</AdditionalUsingDirectories>
|
||||
<AdditionalOptions>/bigobj /await %(AdditionalOptions)</AdditionalOptions>
|
||||
<DisableSpecificWarnings>28204</DisableSpecificWarnings>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir);$(GraphingInterfaceDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<AdditionalLibraryDirectories>$(GraphingImplLibDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>$(GraphingImplLib);WindowsApp.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PreprocessorDefinitions>_WINRT_DLL;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<PrecompiledHeaderOutputFile>$(IntDir)pch.pch</PrecompiledHeaderOutputFile>
|
||||
<AdditionalUsingDirectories>$(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)</AdditionalUsingDirectories>
|
||||
<AdditionalOptions>/bigobj /await /d2CoroOptsWorkaround %(AdditionalOptions)</AdditionalOptions>
|
||||
<DisableSpecificWarnings>28204</DisableSpecificWarnings>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir);$(GraphingInterfaceDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<AdditionalDependencies>$(GraphingImplLib);WindowsApp.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(GraphingImplLibDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PreprocessorDefinitions>_WINRT_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<PrecompiledHeaderOutputFile>$(IntDir)pch.pch</PrecompiledHeaderOutputFile>
|
||||
<AdditionalUsingDirectories>$(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)</AdditionalUsingDirectories>
|
||||
<AdditionalOptions>/bigobj /await %(AdditionalOptions)</AdditionalOptions>
|
||||
<DisableSpecificWarnings>28204</DisableSpecificWarnings>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir);$(GraphingInterfaceDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<AdditionalDependencies>$(GraphingImplLib);WindowsApp.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(GraphingImplLibDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PreprocessorDefinitions>_WINRT_DLL;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<PrecompiledHeaderOutputFile>$(IntDir)pch.pch</PrecompiledHeaderOutputFile>
|
||||
<AdditionalUsingDirectories>$(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)</AdditionalUsingDirectories>
|
||||
<AdditionalOptions>/bigobj /await /d2CoroOptsWorkaround %(AdditionalOptions)</AdditionalOptions>
|
||||
<DisableSpecificWarnings>28204</DisableSpecificWarnings>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir);$(GraphingInterfaceDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<AdditionalDependencies>$(GraphingImplLib);WindowsApp.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(GraphingImplLibDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PreprocessorDefinitions>_WINRT_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<PrecompiledHeaderOutputFile>$(IntDir)pch.pch</PrecompiledHeaderOutputFile>
|
||||
<AdditionalUsingDirectories>$(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)</AdditionalUsingDirectories>
|
||||
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
|
||||
<DisableSpecificWarnings>28204</DisableSpecificWarnings>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir);$(GraphingInterfaceDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<AdditionalDependencies>$(GraphingImplLib);WindowsApp.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(GraphingImplLibDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PreprocessorDefinitions>_WINRT_DLL;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<PrecompiledHeaderOutputFile>$(IntDir)pch.pch</PrecompiledHeaderOutputFile>
|
||||
<AdditionalUsingDirectories>$(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)</AdditionalUsingDirectories>
|
||||
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
|
||||
<DisableSpecificWarnings>28204</DisableSpecificWarnings>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir);$(GraphingInterfaceDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<AdditionalDependencies>$(GraphingImplLib);WindowsApp.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(GraphingImplLibDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PreprocessorDefinitions>_WINRT_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<PrecompiledHeaderOutputFile>$(IntDir)pch.pch</PrecompiledHeaderOutputFile>
|
||||
<AdditionalUsingDirectories>$(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)</AdditionalUsingDirectories>
|
||||
<AdditionalOptions>/bigobj /await %(AdditionalOptions)</AdditionalOptions>
|
||||
<DisableSpecificWarnings>28204</DisableSpecificWarnings>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir);$(GraphingInterfaceDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<AdditionalDependencies>$(GraphingImplLib);WindowsApp.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(GraphingImplLibDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PreprocessorDefinitions>_WINRT_DLL;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<PrecompiledHeaderOutputFile>$(IntDir)pch.pch</PrecompiledHeaderOutputFile>
|
||||
<AdditionalUsingDirectories>$(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)</AdditionalUsingDirectories>
|
||||
<AdditionalOptions>/bigobj /await /d2CoroOptsWorkaround %(AdditionalOptions)</AdditionalOptions>
|
||||
<DisableSpecificWarnings>28204</DisableSpecificWarnings>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir);$(GraphingInterfaceDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<AdditionalDependencies>$(GraphingImplLib);WindowsApp.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(GraphingImplLibDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Control\Equation.h" />
|
||||
<ClInclude Include="Control\EquationCollection.h" />
|
||||
<ClInclude Include="Control\Grapher.h" />
|
||||
<ClInclude Include="Control\InspectingDataSource.h" />
|
||||
<ClInclude Include="DirectX\DeviceResources.h" />
|
||||
<ClInclude Include="DirectX\DirectXHelper.h" />
|
||||
<ClInclude Include="DirectX\NearestPointRenderer.h" />
|
||||
<ClInclude Include="DirectX\RenderMain.h" />
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="winrtHeaders.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Control\Equation.cpp" />
|
||||
<ClCompile Include="Control\Grapher.cpp" />
|
||||
<ClCompile Include="Control\InspectingDataSource.cpp" />
|
||||
<ClCompile Include="DirectX\DeviceResources.cpp" />
|
||||
<ClCompile Include="DirectX\NearestPointRenderer.cpp" />
|
||||
<ClCompile Include="DirectX\RenderMain.cpp" />
|
||||
<ClCompile Include="pch.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Include="Themes\generic.xaml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="$([MSBuild]::ValueOrDefault($(UseMockGraphingImpl), true))">
|
||||
<ProjectReference Include="$(SolutionDir)\MockGraphingImpl\MockGraphingImpl.vcxproj">
|
||||
<Project>{52E03A58-B378-4F50-8BFB-F659FB85E790}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets" />
|
||||
</Project>
|
68
src/GraphControl/GraphControl.vcxproj.filters
Normal file
68
src/GraphControl/GraphControl.vcxproj.filters
Normal file
|
@ -0,0 +1,68 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="DirectX">
|
||||
<UniqueIdentifier>{0d550f5f-db67-4160-8648-397c9bdc0307}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Themes">
|
||||
<UniqueIdentifier>{3d424f3b-ba30-440b-ac2b-8a2740506153}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Control">
|
||||
<UniqueIdentifier>{e8d91a71-6933-4fd8-b333-421085d13896}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="pch.cpp" />
|
||||
<ClCompile Include="DirectX\DeviceResources.cpp">
|
||||
<Filter>DirectX</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DirectX\RenderMain.cpp">
|
||||
<Filter>DirectX</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Control\Equation.cpp">
|
||||
<Filter>Control</Filter>
|
||||
</ClCompile>
|
||||
<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>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="DirectX\DeviceResources.h">
|
||||
<Filter>DirectX</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DirectX\DirectXHelper.h">
|
||||
<Filter>DirectX</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DirectX\RenderMain.h">
|
||||
<Filter>DirectX</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="winrtHeaders.h" />
|
||||
<ClInclude Include="Control\Equation.h">
|
||||
<Filter>Control</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Control\EquationCollection.h">
|
||||
<Filter>Control</Filter>
|
||||
</ClInclude>
|
||||
<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>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Include="Themes\generic.xaml">
|
||||
<Filter>Themes</Filter>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
</Project>
|
13
src/GraphControl/Themes/generic.xaml
Normal file
13
src/GraphControl/Themes/generic.xaml
Normal file
|
@ -0,0 +1,13 @@
|
|||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:GraphControl">
|
||||
<Style TargetType="local:Grapher">
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="local:Grapher">
|
||||
<SwapChainPanel x:Name="GraphSurface"/>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</ResourceDictionary>
|
1
src/GraphControl/pch.cpp
Normal file
1
src/GraphControl/pch.cpp
Normal file
|
@ -0,0 +1 @@
|
|||
#include "pch.h"
|
34
src/GraphControl/pch.h
Normal file
34
src/GraphControl/pch.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
#pragma once
|
||||
|
||||
//C4453: A '[WebHostHidden]' type should not be used on the published surface of a public type that is not '[WebHostHidden]'
|
||||
// This warning is disabled because the types in this app will not be published for use in javascript environment
|
||||
#pragma warning(disable:4453)
|
||||
|
||||
// Windows headers define a min/max macro.
|
||||
// Include the below #def to avoid this behavior.
|
||||
#define NOMINMAX
|
||||
|
||||
#include <collection.h>
|
||||
#include <ppltasks.h>
|
||||
#include <pplawait.h>
|
||||
#include <concrt.h>
|
||||
#include <future>
|
||||
#include <memory>
|
||||
#include <assert.h>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
// DirectX headers
|
||||
#include <d2d1_3.h>
|
||||
#include <d3d11_4.h>
|
||||
#include <dwrite_3.h>
|
||||
#include <DirectXColors.h>
|
||||
#include <wincodec.h>
|
||||
#include <wrl.h>
|
||||
#include <windows.ui.xaml.media.dxinterop.h>
|
||||
|
||||
// C++/WinRT
|
||||
#include "winrtHeaders.h"
|
||||
|
||||
#include "Control/Grapher.h"
|
24
src/GraphControl/winrtHeaders.h
Normal file
24
src/GraphControl/winrtHeaders.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
#pragma once
|
||||
|
||||
#include <winrt/base.h>
|
||||
#include <winrt/Windows.Foundation.h>
|
||||
#include <winrt/Windows.Foundation.Collections.h>
|
||||
#include <winrt/Windows.UI.Xaml.Interop.h>
|
||||
|
||||
template <typename T>
|
||||
T from_cx(Platform::Object^ from)
|
||||
{
|
||||
T to{ nullptr };
|
||||
|
||||
winrt::check_hresult(reinterpret_cast<::IUnknown*>(from)
|
||||
->QueryInterface(winrt::guid_of<T>(),
|
||||
reinterpret_cast<void**>(winrt::put_abi(to))));
|
||||
|
||||
return to;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T^ to_cx(winrt::Windows::Foundation::IUnknown const& from)
|
||||
{
|
||||
return safe_cast<T^>(reinterpret_cast<Platform::Object^>(winrt::get_abi(from)));
|
||||
}
|
96
src/GraphingInterfaces/Common.h
Normal file
96
src/GraphingInterfaces/Common.h
Normal file
|
@ -0,0 +1,96 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#ifndef GRAPHINGAPI
|
||||
#ifdef GRAPHING_ENGINE_IMPL
|
||||
#define GRAPHINGAPI __declspec(dllexport)
|
||||
#else
|
||||
#define GRAPHINGAPI __declspec(dllimport)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace Graphing
|
||||
{
|
||||
struct NonCopyable
|
||||
{
|
||||
NonCopyable() = default;
|
||||
virtual ~NonCopyable() = default;
|
||||
|
||||
NonCopyable(NonCopyable const&) = delete;
|
||||
NonCopyable& operator=(NonCopyable const&) = delete;
|
||||
};
|
||||
|
||||
struct NonMoveable
|
||||
{
|
||||
NonMoveable() = default;
|
||||
virtual ~NonMoveable() = default;
|
||||
|
||||
NonMoveable(NonMoveable&&) = delete;
|
||||
NonMoveable& operator=(NonMoveable&&) = delete;
|
||||
};
|
||||
|
||||
struct IExpression
|
||||
{
|
||||
virtual ~IExpression() = default;
|
||||
|
||||
virtual unsigned int GetExpressionID() const = 0;
|
||||
virtual bool IsEmptySet() const = 0;
|
||||
};
|
||||
|
||||
struct IExpressible
|
||||
{
|
||||
virtual ~IExpressible() = default;
|
||||
|
||||
virtual std::shared_ptr< IExpression > GetExpression() const = 0;
|
||||
};
|
||||
|
||||
class Color
|
||||
{
|
||||
private:
|
||||
// Each color channel is given an 8 bit space in a 32 bit uint32_t.
|
||||
// The format is (RRGGBBAA). As an example,
|
||||
// Red is FF0000FF (4,278,190,335)
|
||||
static constexpr uint8_t redChannelShift = 24;
|
||||
static constexpr uint8_t greenChannelShift = 16;
|
||||
static constexpr uint8_t blueChannelShift = 8;
|
||||
static constexpr uint8_t alphaChannelShift = 0;
|
||||
|
||||
public:
|
||||
uint8_t R;
|
||||
uint8_t G;
|
||||
uint8_t B;
|
||||
uint8_t A;
|
||||
|
||||
Color::Color(uint8_t r, uint8_t g, uint8_t b, uint8_t a) noexcept
|
||||
: R{ r }, G{ g }, B{ b }, A{ a }
|
||||
{}
|
||||
|
||||
Color::Color(uint8_t r, uint8_t g, uint8_t b) noexcept
|
||||
: Color{ r, g, b, 0xFF }
|
||||
{}
|
||||
|
||||
Color::Color() noexcept
|
||||
: Color{ 0, 0, 0 }
|
||||
{}
|
||||
|
||||
|
||||
explicit Color(uint32_t value) noexcept
|
||||
: Color{
|
||||
static_cast<uint8_t>(value >> redChannelShift),
|
||||
static_cast<uint8_t>(value >> greenChannelShift),
|
||||
static_cast<uint8_t>(value >> blueChannelShift),
|
||||
static_cast<uint8_t>(value >> alphaChannelShift)
|
||||
}
|
||||
{
|
||||
}
|
||||
|
||||
explicit operator uint32_t() const
|
||||
{
|
||||
return (A << alphaChannelShift)
|
||||
| (R << redChannelShift)
|
||||
| (G << greenChannelShift)
|
||||
| (B << blueChannelShift);
|
||||
}
|
||||
};
|
||||
}
|
387
src/GraphingInterfaces/GraphingEnums.h
Normal file
387
src/GraphingInterfaces/GraphingEnums.h
Normal file
|
@ -0,0 +1,387 @@
|
|||
#pragma once
|
||||
|
||||
namespace Graphing
|
||||
{
|
||||
enum class LocalizationType
|
||||
{
|
||||
Unknown,
|
||||
DecimalPointAndListComma,
|
||||
DecimalPointAndListSemicolon,
|
||||
DecimalCommaAndListSemicolon
|
||||
};
|
||||
|
||||
enum class EquationParsingMode
|
||||
{
|
||||
// Solving an equation. At least one equal sign is required
|
||||
SolveEquation,
|
||||
|
||||
// Graphing an equation. At least one equal sign is required
|
||||
GraphEquation,
|
||||
|
||||
// Not expecting an equation. No equal sign is allowed
|
||||
NonEquation,
|
||||
|
||||
// Accept zero or more equal signs
|
||||
DoNotCare
|
||||
};
|
||||
|
||||
enum class FormatType
|
||||
{
|
||||
// This format is not very human-readable, but best for machine processing and unit test.
|
||||
// The meaning of an expression is precise, there is no need for parentheses, and it's easy to parse.
|
||||
// While other serializers may contain little tweaks to make the UI component work as expected, this
|
||||
// format doesn't change often because no real UI uses it.
|
||||
// Example: Sum[1,Divide[2,x]]
|
||||
Formula,
|
||||
|
||||
// Similar to Formula, except the variables are in the format of Var(0), Var(1), ... instead of in their names.
|
||||
// Used in serialization only (CasContext.FormatOptions) but not in parsing (CasContext.ParsingOptions)
|
||||
// Example: Sum[1,Divide[2,Var(0)]]
|
||||
InvariantFormula,
|
||||
|
||||
// Similar to Formula, except the aggregates (grouping parentheses) are silently removed during serialization.
|
||||
// The primary usage for this format is in internal test cases.
|
||||
// When used in parsing, it's identical to Formula
|
||||
// Example: Sum[1,Divide[2,x]]
|
||||
FormulaWithoutAggregate,
|
||||
|
||||
// This format is the most human-readable one. Can be used in command line applications or application that accept
|
||||
// and displays linear syntax. Also, the RichEdit wrapper returns linear syntax and it should be parsed with Linear format type.
|
||||
// Example: 1+2/x
|
||||
Linear,
|
||||
|
||||
// This format is similar to linear format, but during serialization it uses ASCII characters only (except for variable
|
||||
// named specified by the user) and can round trip back to the linear parser.
|
||||
//
|
||||
// When used in parsing it's identical to Linear.
|
||||
LinearInput,
|
||||
|
||||
// The standard MathML format. Note that the math engine can only parse a subset of the syntax in the MathML specification.
|
||||
// Example: <math><mn>1</mn><mo>+</mo><mfrac><mn>2</mn><mi>x</mi></mfrac></math>
|
||||
MathML,
|
||||
|
||||
// Same as MathML, except this format type won't generate the root element <math> .
|
||||
// Used in serialization only (CasContext.FormatOptions) but not in parsing (CasContext.ParsingOptions)
|
||||
// Example: <mn>1</mn><mo>+</mo><mfrac><mn>2</mn><mi>x</mi></mfrac>
|
||||
MathMLNoWrapper,
|
||||
|
||||
// This format type is for the RichEdit wrapper to render math in RichEdit.
|
||||
//
|
||||
// Used in serialization only (CasContext.FormatOptions) but not in parsing (CasContext.ParsingOptions)
|
||||
// Example: 1 + \frac{2,x}
|
||||
MathRichEdit,
|
||||
|
||||
// This format type is for the RichEdit wrapper to render math in RichEdit.
|
||||
// It's same with MathRichEdit format with one exception: fractions are rendered
|
||||
// horizontally instead of vertically. This is a better choice if the display area
|
||||
// is confined with a small height.
|
||||
//
|
||||
// Used in serialization only (CasContext.FormatOptions) but not in parsing (CasContext.ParsingOptions)
|
||||
// Example: 1 + x/(2 a)
|
||||
InlineMathRichEdit,
|
||||
|
||||
// The most compact format. Uses binary data. Like Format, it guarantees round trip between parsing and serialization.
|
||||
Binary,
|
||||
|
||||
// Similar to Binary, except variableIds are used instead of variable name.
|
||||
InvariantBinary,
|
||||
|
||||
// This is the base-64 encoded Binary format
|
||||
Base64,
|
||||
|
||||
// This is the base-64 encoded InvariantBinary format.
|
||||
InvariantBase64,
|
||||
|
||||
// Latex format
|
||||
// Example: \frac{1}{2}
|
||||
Latex
|
||||
};
|
||||
|
||||
// Specify on what number field the evaluation should be performed: Real or Complex.
|
||||
enum class EvalNumberField
|
||||
{
|
||||
// This is invalid setting.
|
||||
Invalid,
|
||||
|
||||
// Evaluation should be performed on Real number field
|
||||
Real,
|
||||
|
||||
// Evaluation should be performed on Complex number field
|
||||
Complex
|
||||
};
|
||||
|
||||
// Specify the evaluation direction: Expand, Factor or Neutral (neither Expand nor Factor)
|
||||
enum class EvalExpandMode
|
||||
{
|
||||
// Neither Expand nor Factor
|
||||
Neutral,
|
||||
|
||||
// To expand during evaluation
|
||||
Expand,
|
||||
|
||||
// To factor during evaluation
|
||||
Factor
|
||||
};
|
||||
|
||||
// Specify the current trigonometry unit mode: Radians, Degrees, Grads. This has effect on these trig operators:
|
||||
// Sin Cos Tan Cot Sec Csc
|
||||
// ASin ACos ATan ACot ASec ACsc.
|
||||
// It has NO effect on hyperbolic trig operators (same behavior as Windows Calc), and any other operators.
|
||||
enum class EvalTrigUnitMode
|
||||
{
|
||||
// Invalid value.
|
||||
Invalid,
|
||||
|
||||
// Default trig unit. Period of sin is 2pi
|
||||
Radians,
|
||||
|
||||
// Degrees as trig unit. Period of sin is 360 degrees
|
||||
Degrees,
|
||||
|
||||
// Grads as trig unit. Period of sin is 400 grads
|
||||
Grads
|
||||
};
|
||||
|
||||
// Specifies the type of contextual action
|
||||
enum class ContextualActionType
|
||||
{
|
||||
// The input didn't generate any contextual action
|
||||
None,
|
||||
|
||||
// Solve equation
|
||||
SolveEquation,
|
||||
|
||||
// perform comparison
|
||||
Compare,
|
||||
|
||||
// Expand the expression
|
||||
Expand,
|
||||
|
||||
// Perform a 2D graphing
|
||||
Graph2D,
|
||||
|
||||
// Perform a 2D graphing on all items in the list
|
||||
ListGraph2D,
|
||||
|
||||
// Perform 2D graphing of the two functions on both side of the equal sign or inequality sign
|
||||
GraphBothSides2D,
|
||||
|
||||
// Perform a 3D graphing
|
||||
Graph3D,
|
||||
|
||||
// Perform 3D graphing of the two functions on both side of the equal sign or inequality sign
|
||||
GraphBothSides3D,
|
||||
|
||||
// Perform 2D inequality graphing
|
||||
GraphInequality,
|
||||
|
||||
// Perform assignment
|
||||
Assign,
|
||||
|
||||
// Factor the expression
|
||||
Factor,
|
||||
|
||||
// Compute the derivate of the expression
|
||||
Deriv,
|
||||
|
||||
// Compute the integral of the expression
|
||||
IndefiniteIntegral,
|
||||
|
||||
// Perform 2D graph
|
||||
Graph2DExpression,
|
||||
|
||||
// Perform 3D graph
|
||||
Graph3DExpression,
|
||||
|
||||
// solve the inequality
|
||||
SolveInequality,
|
||||
|
||||
// calculate/simplify the expression
|
||||
Calculate,
|
||||
|
||||
// round of the number
|
||||
Round,
|
||||
|
||||
// floor of the number
|
||||
Floor,
|
||||
|
||||
// ceiling of the number
|
||||
Ceiling,
|
||||
|
||||
// The bit mask for matrix related contextual action types. if (type & MatrixMask)!=0 then the type is matrix related
|
||||
MatrixMask,
|
||||
|
||||
// Compute the determinant of the matrix
|
||||
MatrixDeterminant,
|
||||
|
||||
// Compute the inverse of the matrix
|
||||
MatrixInverse,
|
||||
|
||||
// Compute the trace of the matrix
|
||||
MatrixTrace,
|
||||
|
||||
// Compute the transpose of the matrix
|
||||
MatrixTranspose,
|
||||
|
||||
// Compute the size of the matrix
|
||||
MatrixSize,
|
||||
|
||||
// Compute the reduce of the matrix
|
||||
MatrixReduce,
|
||||
|
||||
// The bit mask for list related contextual action types. if (type & ListMask)!=0 then the type is list related
|
||||
ListMask,
|
||||
|
||||
// Sort the list
|
||||
ListSort,
|
||||
|
||||
// Compute the mean of the list
|
||||
ListMean,
|
||||
|
||||
// Compute the median of the list
|
||||
ListMedian,
|
||||
|
||||
// Compute the mode of the list
|
||||
ListMode,
|
||||
|
||||
// Compute the LCM (least common multiplier) of the list
|
||||
ListLcm,
|
||||
|
||||
// Compute the GCF (greatest common factor) of the list
|
||||
ListGcf,
|
||||
|
||||
// Compute the sum of the list elements
|
||||
ListSum,
|
||||
|
||||
// Compute the product of the list elements
|
||||
ListProduct,
|
||||
|
||||
// Compute the max of the list elements
|
||||
ListMax,
|
||||
|
||||
// Compute the min of the list elements
|
||||
ListMin,
|
||||
|
||||
// Compute the variance of the list elements
|
||||
ListVariance,
|
||||
|
||||
// Compute the standard deviation of the list elements
|
||||
ListStdDev,
|
||||
|
||||
// Show complete (verbose) solution
|
||||
ShowVerboseSolution,
|
||||
|
||||
// bit mask of action type. Can be used to remove the Informational flag
|
||||
TypeMask, // mask to get the type
|
||||
|
||||
// A flag that can be added onto any type. This is informational only that explains what the straight input would do.
|
||||
// No action should be performed
|
||||
Informational
|
||||
};
|
||||
|
||||
enum class MathActionCategoryType
|
||||
{
|
||||
Unknown,
|
||||
Calculate,
|
||||
Solve,
|
||||
Integrate,
|
||||
Differentiate,
|
||||
Algebra,
|
||||
Matrix,
|
||||
List,
|
||||
Graph
|
||||
};
|
||||
|
||||
enum class StepSequenceType
|
||||
{
|
||||
None,
|
||||
Text,
|
||||
Expression,
|
||||
NewLine,
|
||||
NewStep,
|
||||
Conditional,
|
||||
Composite,
|
||||
Goto,
|
||||
Call,
|
||||
Return,
|
||||
Stop,
|
||||
Error,
|
||||
GotoTemp
|
||||
};
|
||||
|
||||
enum class FormatVerbosityMode
|
||||
{
|
||||
Verbose,
|
||||
Simple
|
||||
};
|
||||
|
||||
namespace Renderer
|
||||
{
|
||||
// Used to indicate what action should be performed to change the range.
|
||||
enum class ChangeRangeAction
|
||||
{
|
||||
// Zoom in on all axes by the predefined ratio
|
||||
ZoomIn,
|
||||
|
||||
// Zoom out on all axes by the predefined ratio
|
||||
ZoomOut,
|
||||
|
||||
// Zoom out on X axis only, leave the range of Y (and Z in 3D) unchanged
|
||||
WidenX,
|
||||
|
||||
// Zoom in on X axis only, leave the range of Y (and Z in 3D) unchanged
|
||||
ShrinkX,
|
||||
|
||||
// Zoom out on Y axis only, leave the range of X (and Z in 3D) unchanged
|
||||
WidenY,
|
||||
|
||||
// Zoom in on Y axis only, leave the range of X (and Z in 3D) unchanged
|
||||
ShrinkY,
|
||||
|
||||
// Zoom out on Z axis only, leave the range of X and Y unchanged. Apply to 3D graph only but not 2D graph.
|
||||
WidenZ,
|
||||
|
||||
// Zoom in on Z axis only, leave the range of X and Y unchanged. Apply to 3D graph only but not 2D graph.
|
||||
ShrinkZ,
|
||||
|
||||
// Move the view window of the graph towards the negative X axis.
|
||||
MoveNegativeX,
|
||||
|
||||
// Move the view window of the graph towards the positive X axis.
|
||||
MovePositiveX,
|
||||
|
||||
// Move the view window of the graph towards the negative Y axis.
|
||||
MoveNegativeY,
|
||||
|
||||
// Move the view window of the graph towards the positive Y axis.
|
||||
MovePositiveY,
|
||||
|
||||
// Move the view window of the graph towards the negative Z axis.
|
||||
MoveNegativeZ,
|
||||
|
||||
// Move the view window of the graph towards the positive Z axis.
|
||||
MovePositiveZ,
|
||||
|
||||
// Zoom in on all axes by the predefined ratio. The ratio is smaller than used in ZoomIn result in a smoother motion
|
||||
SmoothZoomIn,
|
||||
|
||||
// Zoom out on all axes by the predefined ratio. The ratio is smaller than used in ZoomIn result in a smoother motion
|
||||
SmoothZoomOut,
|
||||
|
||||
// Zoom in on all axes by the predefined ratio
|
||||
PinchZoomIn,
|
||||
|
||||
// Zoom out on all axes by the predefined ratio
|
||||
PinchZoomOut
|
||||
};
|
||||
|
||||
enum class LineStyle
|
||||
{
|
||||
Solid,
|
||||
Dot,
|
||||
Dash,
|
||||
DashDot,
|
||||
DashDotDot
|
||||
};
|
||||
}
|
||||
}
|
19
src/GraphingInterfaces/IGraph.h
Normal file
19
src/GraphingInterfaces/IGraph.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
#pragma once
|
||||
|
||||
#include "Common.h"
|
||||
#include "IGraphingOptions.h"
|
||||
#include "IGraphRenderer.h"
|
||||
|
||||
namespace Graphing
|
||||
{
|
||||
struct IGraph : public NonCopyable, public NonMoveable
|
||||
{
|
||||
virtual ~IGraph() = default;
|
||||
|
||||
virtual bool TryInitialize(const IExpression* graphingExp) = 0;
|
||||
|
||||
virtual IGraphingOptions& GetOptions() = 0;
|
||||
|
||||
virtual std::shared_ptr< Renderer::IGraphRenderer > GetRenderer() const = 0;
|
||||
};
|
||||
}
|
20
src/GraphingInterfaces/IGraphRenderer.h
Normal file
20
src/GraphingInterfaces/IGraphRenderer.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
#pragma once
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
struct ID2D1Factory;
|
||||
struct ID2D1RenderTarget;
|
||||
|
||||
namespace Graphing::Renderer
|
||||
{
|
||||
struct IGraphRenderer : public NonCopyable, public NonMoveable
|
||||
{
|
||||
virtual ~IGraphRenderer() = default;
|
||||
|
||||
virtual HRESULT SetGraphSize(unsigned int width, unsigned int height) = 0;
|
||||
virtual HRESULT SetDpi(float dpiX, float dpiY) = 0;
|
||||
|
||||
virtual HRESULT DrawD2D1(ID2D1Factory* pDirect2dFactory, ID2D1RenderTarget* pRenderTarget, bool& hasSomeMissingDataOut) = 0;
|
||||
virtual HRESULT GetClosePointData(float inScreenPointX, float inScreenPointY, int& formulaIdOut, float& xScreenPointOut, float& yScreenPointOut, float& xValueOut, float& yValueOut) = 0;
|
||||
};
|
||||
}
|
116
src/GraphingInterfaces/IGraphingOptions.h
Normal file
116
src/GraphingInterfaces/IGraphingOptions.h
Normal file
|
@ -0,0 +1,116 @@
|
|||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "Common.h"
|
||||
#include "GraphingEnums.h"
|
||||
|
||||
namespace Graphing
|
||||
{
|
||||
struct IGraphingOptions : public NonCopyable, public NonMoveable
|
||||
{
|
||||
virtual ~IGraphingOptions() = default;
|
||||
|
||||
virtual void ResetMarkKeyGraphFeaturesData() = 0;
|
||||
|
||||
virtual bool GetMarkZeros() const = 0;
|
||||
virtual void SetMarkZeros(bool value) = 0;
|
||||
|
||||
virtual bool GetMarkYIntercept() const = 0;
|
||||
virtual void SetMarkYIntercept(bool value) = 0;
|
||||
|
||||
virtual bool GetMarkMinima() const = 0;
|
||||
virtual void SetMarkMinima(bool value) = 0;
|
||||
|
||||
virtual bool GetMarkMaxima() const = 0;
|
||||
virtual void SetMarkMaxima(bool value) = 0;
|
||||
|
||||
virtual bool GetMarkInflectionPoints() const = 0;
|
||||
virtual void SetMarkInflectionPoints(bool value) = 0;
|
||||
|
||||
virtual bool GetMarkVerticalAsymptotes() const = 0;
|
||||
virtual void SetMarkVerticalAsymptotes(bool value) = 0;
|
||||
|
||||
virtual bool GetMarkHorizontalAsymptotes() const = 0;
|
||||
virtual void SetMarkHorizontalAsymptotes(bool value) = 0;
|
||||
|
||||
virtual bool GetMarkObliqueAsymptotes() const = 0;
|
||||
virtual void SetMarkObliqueAsymptotes(bool value) = 0;
|
||||
|
||||
virtual unsigned long long GetMaxExecutionTime() const = 0;
|
||||
virtual void SetMaxExecutionTime(unsigned long long value) = 0;
|
||||
virtual void ResetMaxExecutionTime() = 0;
|
||||
|
||||
virtual std::vector<Graphing::Color> GetGraphColors() const = 0;
|
||||
virtual bool SetGraphColors(const std::vector<Graphing::Color>& colors) = 0;
|
||||
virtual void ResetGraphColors() = 0;
|
||||
|
||||
virtual Graphing::Color GetBackColor() const = 0;
|
||||
virtual void SetBackColor(const Graphing::Color& value) = 0;
|
||||
virtual void ResetBackColor() = 0;
|
||||
|
||||
virtual Graphing::Color GetZerosColor() const = 0;
|
||||
virtual void SetZerosColor(const Graphing::Color& value) = 0;
|
||||
virtual void ResetZerosColor() = 0;
|
||||
|
||||
virtual Graphing::Color GetExtremaColor() const = 0;
|
||||
virtual void SetExtremaColor(const Graphing::Color& value) = 0;
|
||||
virtual void ResetExtremaColor() = 0;
|
||||
|
||||
virtual Graphing::Color GetInflectionPointsColor() const = 0;
|
||||
virtual void SetInflectionPointsColor(const Graphing::Color& value) = 0;
|
||||
virtual void ResetInflectionPointsColor() = 0;
|
||||
|
||||
virtual Graphing::Color GetAsymptotesColor() const = 0;
|
||||
virtual void SetAsymptotesColor(const Graphing::Color& value) = 0;
|
||||
virtual void ResetAsymptotesColor() = 0;
|
||||
|
||||
virtual Graphing::Color GetAxisColor() const = 0;
|
||||
virtual void SetAxisColor(const Graphing::Color& value) = 0;
|
||||
virtual void ResetAxisColor() = 0;
|
||||
|
||||
virtual Graphing::Color GetBoxColor() const = 0;
|
||||
virtual void SetBoxColor(const Graphing::Color& value) = 0;
|
||||
virtual void ResetBoxColor() = 0;
|
||||
|
||||
virtual Graphing::Color GetFontColor() const = 0;
|
||||
virtual void SetFontColor(const Graphing::Color& value) = 0;
|
||||
virtual void ResetFontColor() = 0;
|
||||
|
||||
virtual bool GetShowAxis() const = 0;
|
||||
virtual void SetShowAxis(bool value) = 0;
|
||||
virtual void ResetShowAxis() = 0;
|
||||
|
||||
virtual bool GetShowGrid() const = 0;
|
||||
virtual void SetShowGrid(bool value) = 0;
|
||||
virtual void ResetShowGrid() = 0;
|
||||
|
||||
virtual bool GetShowBox() const = 0;
|
||||
virtual void SetShowBox(bool value) = 0;
|
||||
virtual void ResetShowBox() = 0;
|
||||
|
||||
virtual bool GetForceProportional() const = 0;
|
||||
virtual void SetForceProportional(bool value) = 0;
|
||||
virtual void ResetForceProportional() = 0;
|
||||
|
||||
virtual std::wstring GetAliasX() const = 0;
|
||||
virtual void SetAliasX(const std::wstring& value) = 0;
|
||||
virtual void ResetAliasX() = 0;
|
||||
|
||||
virtual std::wstring GetAliasY() const = 0;
|
||||
virtual void SetAliasY(const std::wstring& value) = 0;
|
||||
virtual void ResetAliasY() = 0;
|
||||
|
||||
virtual Graphing::Renderer::LineStyle GetLineStyle() const = 0;
|
||||
virtual void SetLineStyle(Graphing::Renderer::LineStyle value) = 0;
|
||||
virtual void ResetLineStyle() = 0;
|
||||
|
||||
virtual std::pair<double, double> GetDefaultXRange() const = 0;
|
||||
virtual bool SetDefaultXRange(const std::pair<double, double>& minmax) = 0;
|
||||
virtual void ResetDefaultXRange() = 0;
|
||||
|
||||
virtual std::pair<double, double> GetDefaultYRange() const = 0;
|
||||
virtual bool SetDefaultYRange(const std::pair<double, double>& minmax) = 0;
|
||||
virtual void ResetDefaultYRange() = 0;
|
||||
};
|
||||
}
|
45
src/GraphingInterfaces/IMathSolver.h
Normal file
45
src/GraphingInterfaces/IMathSolver.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
#pragma once
|
||||
|
||||
#include "Common.h"
|
||||
#include "IGraph.h"
|
||||
#include "GraphingEnums.h"
|
||||
|
||||
namespace Graphing
|
||||
{
|
||||
struct IParsingOptions : public NonCopyable, public NonMoveable
|
||||
{
|
||||
virtual ~IParsingOptions() = default;
|
||||
|
||||
virtual void SetFormatType(FormatType type) = 0;
|
||||
};
|
||||
|
||||
struct IEvalOptions : public NonCopyable, public NonMoveable
|
||||
{
|
||||
virtual ~IEvalOptions() = default;
|
||||
};
|
||||
|
||||
struct IFormatOptions : public NonCopyable, public NonMoveable
|
||||
{
|
||||
virtual ~IFormatOptions() = default;
|
||||
|
||||
virtual void SetFormatType(FormatType type) = 0;
|
||||
};
|
||||
|
||||
struct IMathSolver : public NonCopyable, public NonMoveable
|
||||
{
|
||||
virtual ~IMathSolver() = default;
|
||||
|
||||
static GRAPHINGAPI std::unique_ptr<IMathSolver> CreateMathSolver();
|
||||
|
||||
virtual IParsingOptions& ParsingOptions() = 0;
|
||||
virtual IEvalOptions& EvalOptions() = 0;
|
||||
virtual IFormatOptions& FormatOptions() = 0;
|
||||
|
||||
virtual std::unique_ptr<IExpression> ParseInput(const std::wstring& input) = 0;
|
||||
virtual std::shared_ptr<IGraph> CreateGrapher(const IExpression* expression) = 0;
|
||||
|
||||
virtual std::shared_ptr<Graphing::IGraph> CreateGrapher() = 0;
|
||||
|
||||
virtual std::wstring Serialize(const IExpression* expression) = 0;
|
||||
};
|
||||
}
|
297
src/MockGraphingImpl/MockGraphingImpl.vcxproj
Normal file
297
src/MockGraphingImpl/MockGraphingImpl.vcxproj
Normal file
|
@ -0,0 +1,297 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|ARM">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>ARM</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|ARM64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|ARM">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>ARM</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|ARM64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{52e03a58-b378-4f50-8bfb-f659fb85e790}</ProjectGuid>
|
||||
<Keyword>DynamicLibrary</Keyword>
|
||||
<RootNamespace>MockGraphingImpl</RootNamespace>
|
||||
<DefaultLanguage>en-US</DefaultLanguage>
|
||||
<MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
|
||||
<AppContainerApplication>true</AppContainerApplication>
|
||||
<ApplicationType>Windows Store</ApplicationType>
|
||||
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformMinVersion>10.0.17763.0</WindowsTargetPlatformMinVersion>
|
||||
<ApplicationTypeRevision>10.0</ApplicationTypeRevision>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
<IgnoreImportLibrary>false</IgnoreImportLibrary>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
<IgnoreImportLibrary>false</IgnoreImportLibrary>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
<IgnoreImportLibrary>false</IgnoreImportLibrary>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
<IgnoreImportLibrary>false</IgnoreImportLibrary>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
<IgnoreImportLibrary>false</IgnoreImportLibrary>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
<IgnoreImportLibrary>false</IgnoreImportLibrary>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
<IgnoreImportLibrary>false</IgnoreImportLibrary>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
<IgnoreImportLibrary>false</IgnoreImportLibrary>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<CompileAsWinRT>false</CompileAsWinRT>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<AdditionalOptions>/DGRAPHING_ENGINE_IMPL %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)\..\;$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<CompileAsWinRT>false</CompileAsWinRT>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<AdditionalOptions>/DGRAPHING_ENGINE_IMPL %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)\..\;$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|arm'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<CompileAsWinRT>false</CompileAsWinRT>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<AdditionalOptions>/DGRAPHING_ENGINE_IMPL %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)\..\;$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|arm'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<CompileAsWinRT>false</CompileAsWinRT>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<AdditionalOptions>/DGRAPHING_ENGINE_IMPL %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)\..\;$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<CompileAsWinRT>false</CompileAsWinRT>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<AdditionalOptions>/DGRAPHING_ENGINE_IMPL %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)\..\;$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<CompileAsWinRT>false</CompileAsWinRT>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<AdditionalOptions>/DGRAPHING_ENGINE_IMPL %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)\..\;$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<CompileAsWinRT>false</CompileAsWinRT>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<AdditionalOptions>/DGRAPHING_ENGINE_IMPL %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)\..\;$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<CompileAsWinRT>false</CompileAsWinRT>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<AdditionalOptions>/DGRAPHING_ENGINE_IMPL %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)\..\;$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\GraphingInterfaces\Common.h" />
|
||||
<ClInclude Include="..\GraphingInterfaces\GraphingEnums.h" />
|
||||
<ClInclude Include="..\GraphingInterfaces\IGraph.h" />
|
||||
<ClInclude Include="..\GraphingInterfaces\IGraphingOptions.h" />
|
||||
<ClInclude Include="..\GraphingInterfaces\IGraphRenderer.h" />
|
||||
<ClInclude Include="..\GraphingInterfaces\IMathSolver.h" />
|
||||
<ClInclude Include="Mocks\MathSolver.h" />
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="targetver.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="dllmain.cpp" />
|
||||
<ClCompile Include="Mocks\MathSolver.cpp" />
|
||||
<ClCompile Include="pch.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
47
src/MockGraphingImpl/MockGraphingImpl.vcxproj.filters
Normal file
47
src/MockGraphingImpl/MockGraphingImpl.vcxproj.filters
Normal file
|
@ -0,0 +1,47 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tga;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="GraphingInterfaces">
|
||||
<UniqueIdentifier>{a74bebcf-8242-4c82-bd5f-6735feda8879}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Mocks">
|
||||
<UniqueIdentifier>{e5205167-e65a-458c-a7e4-b3bc468c60ab}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="dllmain.cpp" />
|
||||
<ClCompile Include="pch.cpp" />
|
||||
<ClCompile Include="Mocks\MathSolver.cpp">
|
||||
<Filter>Mocks</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="targetver.h" />
|
||||
<ClInclude Include="..\GraphingInterfaces\Common.h">
|
||||
<Filter>GraphingInterfaces</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\GraphingInterfaces\GraphingEnums.h">
|
||||
<Filter>GraphingInterfaces</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\GraphingInterfaces\IGraph.h">
|
||||
<Filter>GraphingInterfaces</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\GraphingInterfaces\IGraphingOptions.h">
|
||||
<Filter>GraphingInterfaces</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\GraphingInterfaces\IMathSolver.h">
|
||||
<Filter>GraphingInterfaces</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Mocks\MathSolver.h">
|
||||
<Filter>Mocks</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\GraphingInterfaces\IGraphRenderer.h">
|
||||
<Filter>GraphingInterfaces</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
12
src/MockGraphingImpl/Mocks/MathSolver.cpp
Normal file
12
src/MockGraphingImpl/Mocks/MathSolver.cpp
Normal file
|
@ -0,0 +1,12 @@
|
|||
#include "pch.h"
|
||||
#include "MathSolver.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace Graphing
|
||||
{
|
||||
unique_ptr<IMathSolver> IMathSolver::CreateMathSolver()
|
||||
{
|
||||
return make_unique<MockGraphingImpl::MathSolver>();
|
||||
}
|
||||
}
|
68
src/MockGraphingImpl/Mocks/MathSolver.h
Normal file
68
src/MockGraphingImpl/Mocks/MathSolver.h
Normal file
|
@ -0,0 +1,68 @@
|
|||
#pragma once
|
||||
|
||||
#include "GraphingInterfaces/IMathSolver.h"
|
||||
|
||||
namespace MockGraphingImpl
|
||||
{
|
||||
class ParsingOptions : public Graphing::IParsingOptions
|
||||
{
|
||||
public:
|
||||
void SetFormatType(Graphing::FormatType type) override
|
||||
{ }
|
||||
};
|
||||
|
||||
class EvalOptions : public Graphing::IEvalOptions
|
||||
{
|
||||
};
|
||||
|
||||
class FormatOptions : public Graphing::IFormatOptions
|
||||
{
|
||||
public:
|
||||
void SetFormatType(Graphing::FormatType type) override
|
||||
{ }
|
||||
};
|
||||
|
||||
class MathSolver : public Graphing::IMathSolver
|
||||
{
|
||||
public:
|
||||
Graphing::IParsingOptions& ParsingOptions() override
|
||||
{
|
||||
return m_parsingOptions;
|
||||
}
|
||||
|
||||
Graphing::IEvalOptions& EvalOptions() override
|
||||
{
|
||||
return m_evalOptions;
|
||||
}
|
||||
|
||||
Graphing::IFormatOptions& FormatOptions() override
|
||||
{
|
||||
return m_formatOptions;
|
||||
}
|
||||
|
||||
std::unique_ptr<Graphing::IExpression> ParseInput(const std::wstring& input) override
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<Graphing::IGraph> CreateGrapher(const Graphing::IExpression* expression) override
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<Graphing::IGraph> CreateGrapher() override
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::wstring Serialize(const Graphing::IExpression* expression) override
|
||||
{
|
||||
return std::wstring{};
|
||||
}
|
||||
|
||||
private:
|
||||
MockGraphingImpl::ParsingOptions m_parsingOptions;
|
||||
MockGraphingImpl::EvalOptions m_evalOptions;
|
||||
MockGraphingImpl::FormatOptions m_formatOptions;
|
||||
};
|
||||
}
|
14
src/MockGraphingImpl/dllmain.cpp
Normal file
14
src/MockGraphingImpl/dllmain.cpp
Normal file
|
@ -0,0 +1,14 @@
|
|||
#include "pch.h"
|
||||
|
||||
BOOL APIENTRY DllMain(HMODULE /* hModule */, DWORD ul_reason_for_call, LPVOID /* lpReserved */)
|
||||
{
|
||||
switch (ul_reason_for_call)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
case DLL_THREAD_ATTACH:
|
||||
case DLL_THREAD_DETACH:
|
||||
case DLL_PROCESS_DETACH:
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
1
src/MockGraphingImpl/pch.cpp
Normal file
1
src/MockGraphingImpl/pch.cpp
Normal file
|
@ -0,0 +1 @@
|
|||
#include "pch.h"
|
9
src/MockGraphingImpl/pch.h
Normal file
9
src/MockGraphingImpl/pch.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
#include "targetver.h"
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
8
src/MockGraphingImpl/targetver.h
Normal file
8
src/MockGraphingImpl/targetver.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
// Including SDKDDKVer.h defines the highest available Windows platform.
|
||||
|
||||
// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
|
||||
// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
|
||||
|
||||
#include <SDKDDKVer.h>
|
Loading…
Add table
Add a link
Reference in a new issue