Feature/GraphingCalculator initial commit (#450)
Initial PR for the feature/GraphingCalculator feature branch, part of #338. The feature incorporates a proprietary Microsoft-owned graphing engine to drive graphing experiences in the Windows Calculator app. Due to the private nature of the graphing engine, the source available in the public repo will make use of a mock graphing engine. See README.md for more details. This PR simply serves as a base for future feature development. As such, the PR will be immediately merged. Feedback on the content of this PR, and on the feature in general, is encouraged. If there is feedback related to the content of this specific PR, please leave comments on the PR page. We will address the comments in future PRs to the feature branch.
This commit is contained in:
@@ -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);
|
||||
};
|
||||
}
|
Reference in New Issue
Block a user