mirror of
https://github.com/Microsoft/calculator.git
synced 2025-08-21 05:43:10 -07:00
Hello GitHub
This commit is contained in:
parent
456fe5e355
commit
c13b8a099e
822 changed files with 276650 additions and 75 deletions
188
docs/ApplicationArchitecture.md
Normal file
188
docs/ApplicationArchitecture.md
Normal file
|
@ -0,0 +1,188 @@
|
|||
# Application Architecture
|
||||
|
||||
Windows Calculator is a [C++/CX][C++/CX] application, built for the Universal Windows Platform ([UWP][What is UWP?]).
|
||||
Calculator uses the [XAML][XAML Overview] UI framework, and the project follows the Model-View-ViewModel ([MVVM][MVVM])
|
||||
design pattern. This document discusses each of the layers and how they are related to the three Visual Studio projects
|
||||
that build into the final Calculator application.
|
||||
|
||||
--------------------
|
||||
## Table of Contents
|
||||
|
||||
* [View](#view)
|
||||
* [VisualStates](#visualstates)
|
||||
* [Data-Binding](#data-binding)
|
||||
* [ViewModel](#viewmodel)
|
||||
* [PropertyChanged Events](#propertychanged-events)
|
||||
* [Model](#model)
|
||||
|
||||
--------------------
|
||||
|
||||
## View
|
||||
|
||||
The View layer is contained in the [Calculator project][Calculator folder]. This project contains mostly XAML files
|
||||
and various custom controls that support the UI. [App.xaml][App.xaml] contains many of the [static][StaticResource] and
|
||||
[theme][ThemeResource] resources that the other XAML files will reference. Its code-behind file, [App.xaml.cpp][App.xaml.cpp],
|
||||
contains the main entry point to the application. On startup, it navigates to the main page.
|
||||
|
||||
```C++
|
||||
rootFrame->Navigate(MainPage::typeid, argument)
|
||||
```
|
||||
|
||||
In Calculator, there is only one concrete [Page][Page] class: [MainPage.xaml][MainPage.xaml]. `MainPage` is the root
|
||||
container for all the other application UI elements. As you can see, there's not much content. `MainPage` uses a
|
||||
`NavigationView` control to display the toggleable navigation menu, and empty containers for delay-loaded UI elements.
|
||||
Of the many modes that Calculator shows in its menu, there are actually only three XAML files that `MainPage` needs to
|
||||
manage in order to support all modes. They are:
|
||||
|
||||
* [Calculator.xaml][Calculator.xaml]: This [UserControl] is itself a container for the [Standard][CalculatorStandardOperators.xaml],
|
||||
[Scientific][CalculatorScientificOperators.xaml], and [Programmer][CalculatorProgrammerOperators.xaml] modes.
|
||||
* [DateCalculator.xaml][DateCalculator.xaml]: Everything needed for the DateCalculator mode.
|
||||
* [UnitConverter.xaml][UnitConverter.xaml]: One `UserControl` to support every Converter mode.
|
||||
|
||||
### VisualStates
|
||||
|
||||
[VisualStates][VisualState] are used to change the size, position, and appearance ([Style][Style]) of UI elements
|
||||
in order to create an adaptive, responsive UI. A transition to a new `VisualState` is often triggered by specific
|
||||
window sizes. Here are a few important examples of `VisualStates` in Calculator. Note that it is not a
|
||||
complete list. When making UI changes, make sure you are considering the various `VisualStates` and layouts that
|
||||
Calculator defines.
|
||||
|
||||
#### History/Memory Dock Panel expansion
|
||||
|
||||
In the Standard, Scientific, and Programmer modes, the History/Memory panel is exposed as a flyout in small window sizes.
|
||||
Once the window is resized to have enough space, the panel becomes docked along the edge of the window.
|
||||
|
||||
<img src="Images\VisualStates\Standard1.gif" height="400" />
|
||||
|
||||
#### Scientific mode, inverse function button presence
|
||||
|
||||
In the Scientific mode, for small window sizes there is not enough room to show all the function buttons. The mode
|
||||
hides some of the buttons and provides a Shift (↑) button to toggle the visibility of the collapsed rows. When the
|
||||
window size is large enough, the buttons are re-arranged to display all function buttons at the same time.
|
||||
|
||||
<img src="Images\VisualStates\Scientific1.gif" height="400" />
|
||||
|
||||
#### Unit Converter aspect ratio adjustment
|
||||
|
||||
In the Unit Converter mode, the converter inputs and the numberpad will re-arrange depending on if the window is in
|
||||
a Portrait or Landscape aspect ratio.
|
||||
|
||||
<img src="Images\VisualStates\Converter1.gif" height="400" />
|
||||
|
||||
### Data-Binding
|
||||
|
||||
Calculator uses [data binding][Data Binding] to dynamically update the properties of UI elements. If this concept
|
||||
is new for you, it's also worth reading about [data binding in depth][Data binding in depth].
|
||||
|
||||
The [x:Bind][x:Bind] markup extension is a newer replacement for the older [Binding][Binding] style. You may see both
|
||||
styles in the Calculator codebase. Prefer `x:Bind` in new contributions because it has better performance. If you need
|
||||
to add or modify an existing `Binding`, updating to `x:Bind` is a great first step. Make sure to read and understand
|
||||
the difference between the two styles, as there are some subtle behavioral changes. Refer to the
|
||||
[binding feature comparison][BindingComparison] to learn more.
|
||||
|
||||
------------
|
||||
## ViewModel
|
||||
|
||||
The ViewModel layer is contained in the [CalcViewModel][CalcViewModel folder] project. ViewModels provide a source of
|
||||
data for the UI to bind against and act as the intermediary separating pure business logic from UI components that
|
||||
should not care about the model's implementation. Just as the View layer consists of a hierarchy of XAML files, the
|
||||
ViewModel consists of a hierarchy of ViewModel files. The relationship between XAML and ViewModel files is often 1:1.
|
||||
Here are the noteable ViewModel files to start exploring with:
|
||||
|
||||
* [ApplicationViewModel.h][ApplicationViewModel.h]: The ViewModel for [MainPage.xaml][MainPage.xaml]. This ViewModel
|
||||
is the root of the other mode-specific ViewModels. The application changes between modes by updating the `Mode` property
|
||||
of the `ApplicationViewModel`. The ViewModel will make sure the appropriate ViewModel for the new mode is initialized.
|
||||
* [StandardCalculatorViewModel.h][StandardCalculatorViewModel.h]: The ViewModel for [Calculator.xaml][Calculator.xaml].
|
||||
This ViewModel exposes functionality for the main three Calculator modes: Standard, Scientific, and Programmer.
|
||||
* [DateCalculatorViewModel.h][DateCalculatorViewModel.h]: The ViewModel for [DateCalculator.xaml][DateCalculator.xaml].
|
||||
* [UnitConverterViewModel.h][UnitConverterViewModel.h]: The ViewModel for [UnitConverter.xaml][UnitConverter.xaml].
|
||||
This ViewModel implements the logic to support every converter mode, including Currency Converter.
|
||||
|
||||
### PropertyChanged Events
|
||||
|
||||
In order for [data binding](#data-binding) to work, ViewModels need a way to inform the XAML framework about
|
||||
updates to their member properties. Most ViewModels in the project do so by implementing the
|
||||
[INotifyPropertyChanged][INotifyPropertyChanged] interface. The interface requires that the class provides a
|
||||
[PropertyChanged event][PropertyChanged]. Clients of the ViewModel (such as the UI), can register for the
|
||||
`PropertyChanged` event from the ViewModel, then re-evaluate bindings or handle the event in code-behind when the
|
||||
ViewModel decides to raise the event. ViewModels in the Calculator codebase generally uses a macro, defined in the
|
||||
[Utils.h][Utils.h] utility file, to implement the `INotifyPropertyChanged` interface. Here is a standard
|
||||
implementation, taken from [ApplicationViewModel.h][ApplicationViewModel.h].
|
||||
|
||||
```C++
|
||||
[Windows::UI::Xaml::Data::Bindable]
|
||||
public ref class ApplicationViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
|
||||
{
|
||||
public:
|
||||
ApplicationViewModel();
|
||||
|
||||
OBSERVABLE_OBJECT();
|
||||
```
|
||||
|
||||
The `OBSERVABLE_OBJECT()` macro defines the required `PropertyChanged` event. It also defines a private
|
||||
`RaisePropertyChanged` helper function for the class. The function takes a property name and raises a
|
||||
`PropertyChanged` event for that property.
|
||||
|
||||
Properties that are intended to be the source for a data binding are also typically implemented with a macro. Here is
|
||||
one such property from `ApplicationViewModel`:
|
||||
|
||||
```C++
|
||||
OBSERVABLE_PROPERTY_RW(Platform::String^, CategoryName);
|
||||
```
|
||||
|
||||
The `OBSERVABLE_PROPERTY_RW` macro defines a Read/Write property that will raise a `PropertyChanged` event if its value
|
||||
changes. Read/Write means the property exposes both a public getter and setter. For efficiency and to avoid raising
|
||||
unnecessary `PropertyChanged` events, the setter for these types of properties will check if the new value is
|
||||
different from the previous value before raising the event.
|
||||
|
||||
From this example, either `ApplicationViewModel` or clients of the class can simply assign to the `CategoryName`
|
||||
property and a `PropertyChanged` event will be raised, allowing the UI to respond to the new `CategoryName` value.
|
||||
|
||||
--------
|
||||
## Model
|
||||
|
||||
The Model for the Calculator modes is contained in the [CalcManager][CalcManager folder] project.
|
||||
<!-- TODO joshuako: Add the docs -->
|
||||
|
||||
[References]:####################################################################################################
|
||||
|
||||
[C++/CX]: https://docs.microsoft.com/en-us/cpp/cppcx/visual-c-language-reference-c-cx
|
||||
[What is UWP?]: https://docs.microsoft.com/en-us/windows/uwp/get-started/universal-application-platform-guide
|
||||
[XAML Overview]: https://docs.microsoft.com/en-us/windows/uwp/xaml-platform/xaml-overview
|
||||
[MVVM]: https://docs.microsoft.com/en-us/windows/uwp/data-binding/data-binding-and-mvvm
|
||||
|
||||
[Calculator folder]: ..\src\Calculator
|
||||
[App.xaml]: ..\src\Calculator\App.xaml
|
||||
[App.xaml.cpp]: ..\src\Calculator\App.xaml.cpp
|
||||
[StaticResource]: https://docs.microsoft.com/en-us/windows/uwp/xaml-platform/staticresource-markup-extension
|
||||
[ThemeResource]: https://docs.microsoft.com/en-us/windows/uwp/xaml-platform/themeresource-markup-extension
|
||||
[Page]: https://docs.microsoft.com/en-us/uwp/api/Windows.UI.Xaml.Controls.Page
|
||||
[UserControl]: https://docs.microsoft.com/en-us/uwp/api/Windows.UI.Xaml.Controls.UserControl
|
||||
[MainPage.xaml]: ..\src\Calculator\Views\MainPage.xaml
|
||||
[Calculator.xaml]: ..\src\Calculator\Views\Calculator.xaml
|
||||
[CalculatorStandardOperators.xaml]: ..\src\Calculator\Views\CalculatorStandardOperators.xaml
|
||||
[CalculatorScientificOperators.xaml]: ..\src\Calculator\Views\CalculatorScientificOperators.xaml
|
||||
[CalculatorProgrammerOperators.xaml]: ..\src\Calculator\Views\CalculatorProgrammerOperators.xaml
|
||||
[DateCalculator.xaml]: ..\src\Calculator\Views\DateCalculator.xaml
|
||||
[UnitConverter.xaml]: ..\src\Calculator\Views\UnitConverter.xaml
|
||||
|
||||
[VisualState]: https://docs.microsoft.com/en-us/windows/uwp/design/layout/layouts-with-xaml#adaptive-layouts-with-visual-states-and-state-triggers
|
||||
[Style]: https://docs.microsoft.com/en-us/windows/uwp/design/controls-and-patterns/xaml-styles
|
||||
|
||||
[Data Binding]: https://docs.microsoft.com/en-us/windows/uwp/data-binding/data-binding-quickstart
|
||||
[Data binding in depth]: https://docs.microsoft.com/en-us/windows/uwp/data-binding/data-binding-in-depth
|
||||
[x:Bind]: https://docs.microsoft.com/en-us/windows/uwp/xaml-platform/x-bind-markup-extension
|
||||
[Binding]: https://docs.microsoft.com/en-us/windows/uwp/xaml-platform/binding-markup-extension
|
||||
[BindingComparison]: https://docs.microsoft.com/en-us/windows/uwp/data-binding/data-binding-in-depth#xbind-and-binding-feature-comparison
|
||||
|
||||
[CalcViewModel folder]: ..\src\CalcViewModel
|
||||
[ApplicationViewModel.h]: ..\src\CalcViewModel\ApplicationViewModel.h
|
||||
[StandardCalculatorViewModel.h]: ..\src\CalcViewModel\StandardCalculatorViewModel.h
|
||||
[DateCalculatorViewModel.h]: ..\src\CalcViewModel\DateCalculatorViewModel.h
|
||||
[UnitConverterViewModel.h]: ..\src\CalcViewModel\UnitConverterViewModel.h
|
||||
|
||||
[INotifyPropertyChanged]: https://docs.microsoft.com/en-us/uwp/api/windows.ui.xaml.data.inotifypropertychanged
|
||||
[PropertyChanged]: https://docs.microsoft.com/en-us/uwp/api/windows.ui.xaml.data.inotifypropertychanged.propertychanged
|
||||
[Utils.h]: ..\src\CalcViewModel\Common\Utils.h
|
||||
|
||||
[CalcManager folder]: ..\src\CalcManager
|
Loading…
Add table
Add a link
Reference in a new issue