diff --git a/src/CalcViewModel/CalcViewModel.vcxproj b/src/CalcViewModel/CalcViewModel.vcxproj
index c2a69b5c..41d46c5a 100644
--- a/src/CalcViewModel/CalcViewModel.vcxproj
+++ b/src/CalcViewModel/CalcViewModel.vcxproj
@@ -334,6 +334,7 @@
+
@@ -374,6 +375,7 @@
+
diff --git a/src/CalcViewModel/CalcViewModel.vcxproj.filters b/src/CalcViewModel/CalcViewModel.vcxproj.filters
index 7a0619ee..c9408c82 100644
--- a/src/CalcViewModel/CalcViewModel.vcxproj.filters
+++ b/src/CalcViewModel/CalcViewModel.vcxproj.filters
@@ -13,6 +13,9 @@
{cf7dca32-9727-4f98-83c3-1c0ca7dd1e0c}
+
+ {68bb415f-fcb1-4759-b0a7-c5caf9d72396}
+
@@ -86,6 +89,9 @@
GraphingCalculator
+
+ Utils
+
@@ -199,6 +205,9 @@
Common
+
+ Utils
+
diff --git a/src/CalcViewModel/Utils/DeviceFamilyHelper.cpp b/src/CalcViewModel/Utils/DeviceFamilyHelper.cpp
new file mode 100644
index 00000000..49fd51be
--- /dev/null
+++ b/src/CalcViewModel/Utils/DeviceFamilyHelper.cpp
@@ -0,0 +1,54 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+#include "pch.h"
+#include "DeviceFamilyHelper.h"
+
+using namespace CalculatorApp::ViewModel::Utils;
+using namespace Windows::System::Profile;
+
+bool DeviceFamilyHelper::m_isInit{ false };
+DeviceFamily DeviceFamilyHelper::m_deviceFamily{ DeviceFamily::Unknown };
+
+DeviceFamily DeviceFamilyHelper::GetDeviceFamily()
+{
+ if (!m_isInit)
+ {
+ InitDeviceFamily();
+ m_isInit = true;
+ }
+ return m_deviceFamily;
+}
+
+void DeviceFamilyHelper::InitDeviceFamily()
+{
+ auto deviceFamily = AnalyticsInfo::VersionInfo->DeviceFamily;
+ if (deviceFamily == L"Windows.Desktop")
+ {
+ m_deviceFamily = DeviceFamily::Desktop;
+ }
+ else if (deviceFamily == L"Windows.Core")
+ {
+ m_deviceFamily = DeviceFamily::WindowsCore;
+ }
+ else if (deviceFamily == L"Windows.Xbox")
+ {
+ m_deviceFamily = DeviceFamily::Xbox;
+ }
+ else if (deviceFamily == L"Windows.Team")
+ {
+ m_deviceFamily = DeviceFamily::SurfaceHub;
+ }
+ else if (deviceFamily == L"Windows.Holographic")
+ {
+ m_deviceFamily = DeviceFamily::HoloLens;
+ }
+ else if (deviceFamily == L"Windows.Mobile")
+ {
+ m_deviceFamily = DeviceFamily::Mobile;
+ }
+ else
+ {
+ m_deviceFamily = DeviceFamily::Unknown;
+ }
+}
diff --git a/src/CalcViewModel/Utils/DeviceFamilyHelper.h b/src/CalcViewModel/Utils/DeviceFamilyHelper.h
new file mode 100644
index 00000000..4811cd3b
--- /dev/null
+++ b/src/CalcViewModel/Utils/DeviceFamilyHelper.h
@@ -0,0 +1,31 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+#pragma once
+
+namespace CalculatorApp::ViewModel::Utils
+{
+ public enum class DeviceFamily
+ {
+ Unknown,
+ Desktop,
+ Mobile,
+ Xbox,
+ SurfaceHub,
+ HoloLens,
+ WindowsCore,
+ };
+
+ public ref class DeviceFamilyHelper sealed
+ {
+ private:
+ DeviceFamilyHelper() {}
+ public:
+ static DeviceFamily GetDeviceFamily();
+ private:
+ static void InitDeviceFamily();
+ private:
+ static bool m_isInit;
+ static DeviceFamily m_deviceFamily;
+ };
+}
diff --git a/src/Calculator/App.xaml b/src/Calculator/App.xaml
index 50472efd..f12d0921 100644
--- a/src/Calculator/App.xaml
+++ b/src/Calculator/App.xaml
@@ -3,6 +3,8 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Controls="using:CalculatorApp.Controls"
xmlns:common="using:CalculatorApp.Common"
+ xmlns:contract7NotPresent="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractNotPresent(Windows.Foundation.UniversalApiContract,7)"
+ xmlns:contract7Present="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract,7)"
xmlns:local="using:CalculatorApp">
@@ -84,7 +86,7 @@
-
+
0,0,0,0
@@ -163,6 +165,7 @@
+
0,1,0,0
@@ -197,6 +200,7 @@
+
@@ -1764,6 +1768,125 @@
+
+
diff --git a/src/Calculator/Calculator.vcxproj b/src/Calculator/Calculator.vcxproj
index eb39777f..6bca12fc 100644
--- a/src/Calculator/Calculator.vcxproj
+++ b/src/Calculator/Calculator.vcxproj
@@ -252,6 +252,7 @@
+
@@ -329,6 +330,7 @@
Views\OperatorsPanel.xaml
+
@@ -422,6 +424,7 @@
+
@@ -505,6 +508,7 @@
Views\OperatorsPanel.xaml
+
@@ -976,7 +980,7 @@
-
+
@@ -984,6 +988,6 @@
-
+
diff --git a/src/Calculator/Calculator.vcxproj.filters b/src/Calculator/Calculator.vcxproj.filters
index 7782ca13..7803c6c5 100644
--- a/src/Calculator/Calculator.vcxproj.filters
+++ b/src/Calculator/Calculator.vcxproj.filters
@@ -329,6 +329,12 @@
+
+ Controls
+
+
+ Views\StateTriggers
+
@@ -437,6 +443,12 @@
+
+ Controls
+
+
+ Views\StateTriggers
+
@@ -522,7 +534,6 @@
Views\GraphingCalculator
-
diff --git a/src/Calculator/Controls/TwoPaneViewCX.cpp b/src/Calculator/Controls/TwoPaneViewCX.cpp
new file mode 100644
index 00000000..d117ce2b
--- /dev/null
+++ b/src/Calculator/Controls/TwoPaneViewCX.cpp
@@ -0,0 +1,487 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See LICENSE in the project root for license information.
+
+#include "pch.h"
+#include "TwoPaneViewCX.h"
+#include "Utils/VisualTree.h"
+#include
+
+using namespace std;
+using namespace Platform;
+using namespace CalculatorApp::Controls;
+using namespace Calculator::Utils;
+using namespace Windows::Foundation;
+using namespace Windows::UI::ViewManagement;
+using namespace Windows::UI::Xaml;
+using namespace Windows::UI::Xaml::Controls;
+using Windows::Foundation::Metadata::ApiInformation;
+namespace MUXC = Microsoft::UI::Xaml::Controls;
+
+StringReference c_pane1ScrollViewerName(L"PART_Pane1ScrollViewer");
+StringReference c_pane2ScrollViewerName(L"PART_Pane2ScrollViewer");
+StringReference c_columnLeftName(L"PART_ColumnLeft");
+StringReference c_columnMiddleName(L"PART_ColumnMiddle");
+StringReference c_columnRightName(L"PART_ColumnRight");
+StringReference c_rowTopName(L"PART_RowTop");
+StringReference c_rowMiddleName(L"PART_RowMiddle");
+StringReference c_rowBottomName(L"PART_RowBottom");
+
+DEPENDENCY_PROPERTY_INITIALIZATION(TwoPaneViewCX, Pane1);
+DEPENDENCY_PROPERTY_INITIALIZATION(TwoPaneViewCX, Pane2);
+DEPENDENCY_PROPERTY_INITIALIZATION(TwoPaneViewCX, Pane1Length);
+DEPENDENCY_PROPERTY_INITIALIZATION(TwoPaneViewCX, Pane2Length);
+DEPENDENCY_PROPERTY_INITIALIZATION(TwoPaneViewCX, Pane1MinLength);
+DEPENDENCY_PROPERTY_INITIALIZATION(TwoPaneViewCX, Pane2MinLength);
+DEPENDENCY_PROPERTY_INITIALIZATION(TwoPaneViewCX, Pane1MaxLength);
+DEPENDENCY_PROPERTY_INITIALIZATION(TwoPaneViewCX, Pane2MaxLength);
+DEPENDENCY_PROPERTY_INITIALIZATION(TwoPaneViewCX, PanePriority);
+DEPENDENCY_PROPERTY_INITIALIZATION(TwoPaneViewCX, Mode);
+DEPENDENCY_PROPERTY_INITIALIZATION(TwoPaneViewCX, WideModeConfiguration);
+DEPENDENCY_PROPERTY_INITIALIZATION(TwoPaneViewCX, TallModeConfiguration);
+DEPENDENCY_PROPERTY_INITIALIZATION(TwoPaneViewCX, MinWideModeWidth);
+DEPENDENCY_PROPERTY_INITIALIZATION(TwoPaneViewCX, MinTallModeHeight);
+
+TwoPaneViewCX::TwoPaneViewCX()
+{
+ this->DefaultStyleKey = L"CalculatorApp.Controls.TwoPaneViewCX";
+ this->SizeChanged += ref new Windows::UI::Xaml::SizeChangedEventHandler(this, &TwoPaneViewCX::OnSizeChanged);
+ m_windowSizeChangedToken = Window::Current->SizeChanged +=
+ ref new Windows::UI::Xaml::WindowSizeChangedEventHandler(this, &TwoPaneViewCX::OnWindowSizeChanged);
+}
+
+TwoPaneViewCX::~TwoPaneViewCX()
+{
+ Window::Current->SizeChanged -= m_windowSizeChangedToken;
+}
+
+void TwoPaneViewCX::OnApplyTemplate()
+{
+ m_loaded = true;
+ this->SetScrollViewerProperties(c_pane1ScrollViewerName);
+ this->SetScrollViewerProperties(c_pane2ScrollViewerName);
+
+ if (auto column = dynamic_cast(this->GetTemplateChild(c_columnLeftName)))
+ {
+ m_columnLeft = column;
+ }
+ if (auto column = dynamic_cast(this->GetTemplateChild(c_columnMiddleName)))
+ {
+ m_columnMiddle = column;
+ }
+ if (auto column = dynamic_cast(this->GetTemplateChild(c_columnRightName)))
+ {
+ m_columnRight = column;
+ }
+ if (auto row = dynamic_cast(this->GetTemplateChild(c_rowTopName)))
+ {
+ m_rowTop = row;
+ }
+ if (auto row = dynamic_cast(this->GetTemplateChild(c_rowMiddleName)))
+ {
+ m_rowMiddle = row;
+ }
+ if (auto row = dynamic_cast(this->GetTemplateChild(c_rowBottomName)))
+ {
+ m_rowBottom = row;
+ }
+}
+
+void TwoPaneViewCX::UpdateMode()
+{
+ // Don't bother running this logic until after we hit OnApplyTemplate.
+ if (!m_loaded)
+ return;
+
+ double controlWidth = this->ActualWidth;
+ double controlHeight = this->ActualHeight;
+
+ ViewMode newMode = (this->PanePriority == MUXC::TwoPaneViewPriority::Pane1) ? ViewMode::Pane1Only : ViewMode::Pane2Only;
+
+ // Calculate new mode
+ Rect rcControl = GetControlRect();
+ auto info = this->GetDisplayRegionHelperInfo();
+ bool isInMultipleRegions = IsInMultipleRegions(info, rcControl);
+
+ if (isInMultipleRegions)
+ {
+ if (info.Mode == MUXC::TwoPaneViewMode::Wide)
+ {
+ // Regions are laid out horizontally
+ if (this->WideModeConfiguration != MUXC::TwoPaneViewWideModeConfiguration::SinglePane)
+ {
+ newMode = (this->WideModeConfiguration == MUXC::TwoPaneViewWideModeConfiguration::LeftRight) ? ViewMode::LeftRight : ViewMode::RightLeft;
+ }
+ }
+ else if (info.Mode == MUXC::TwoPaneViewMode::Tall)
+ {
+ // Regions are laid out vertically
+ if (this->TallModeConfiguration != MUXC::TwoPaneViewTallModeConfiguration::SinglePane)
+ {
+ newMode = (this->TallModeConfiguration == MUXC::TwoPaneViewTallModeConfiguration::TopBottom) ? ViewMode::TopBottom : ViewMode::BottomTop;
+ }
+ }
+ }
+ else
+ {
+ // One region
+ if (controlWidth > this->MinWideModeWidth && this->WideModeConfiguration != MUXC::TwoPaneViewWideModeConfiguration::SinglePane)
+ {
+ // Split horizontally
+ newMode = (this->WideModeConfiguration == MUXC::TwoPaneViewWideModeConfiguration::LeftRight) ? ViewMode::LeftRight : ViewMode::RightLeft;
+ }
+ else if (controlHeight > this->MinTallModeHeight && this->TallModeConfiguration != MUXC::TwoPaneViewTallModeConfiguration::SinglePane)
+ {
+ // Split vertically
+ newMode = (this->TallModeConfiguration == MUXC::TwoPaneViewTallModeConfiguration::TopBottom) ? ViewMode::TopBottom : ViewMode::BottomTop;
+ }
+ }
+
+ // Update row/column sizes (this may need to happen even if the mode doesn't change)
+ UpdateRowsColumns(newMode, info, rcControl);
+
+ // Update mode if necessary
+ if (newMode != m_currentMode)
+ {
+ m_currentMode = newMode;
+
+ auto newViewMode = MUXC::TwoPaneViewMode::SinglePane;
+
+ switch (m_currentMode)
+ {
+ case ViewMode::Pane1Only:
+ VisualStateManager::GoToState(this, L"ViewMode_OneOnly", true);
+ break;
+ case ViewMode::Pane2Only:
+ VisualStateManager::GoToState(this, L"ViewMode_TwoOnly", true);
+ break;
+ case ViewMode::LeftRight:
+ VisualStateManager::GoToState(this, L"ViewMode_LeftRight", true);
+ newViewMode = MUXC::TwoPaneViewMode::Wide;
+ break;
+ case ViewMode::RightLeft:
+ VisualStateManager::GoToState(this, L"ViewMode_RightLeft", true);
+ newViewMode = MUXC::TwoPaneViewMode::Wide;
+ break;
+ case ViewMode::TopBottom:
+ VisualStateManager::GoToState(this, L"ViewMode_TopBottom", true);
+ newViewMode = MUXC::TwoPaneViewMode::Tall;
+ break;
+ case ViewMode::BottomTop:
+ VisualStateManager::GoToState(this, L"ViewMode_BottomTop", true);
+ newViewMode = MUXC::TwoPaneViewMode::Tall;
+ break;
+ }
+
+ if (newViewMode != this->Mode)
+ {
+ SetValue(s_ModeProperty, newViewMode);
+ this->ModeChanged(this, this);
+ }
+ }
+}
+
+void TwoPaneViewCX::UpdateRowsColumns(ViewMode newMode, DisplayRegionHelperInfo info, Rect rcControl)
+{
+ if (m_columnLeft && m_columnMiddle && m_columnRight && m_rowTop && m_rowMiddle && m_rowBottom)
+ {
+ // Reset split lengths
+ this->m_columnMiddle->Width = GridLengthHelper::FromPixels(0);
+ this->m_rowMiddle->Height = GridLengthHelper::FromPixels(0);
+
+ // Set columns lengths
+ if (newMode == ViewMode::LeftRight || newMode == ViewMode::RightLeft)
+ {
+ if (newMode == ViewMode::LeftRight)
+ {
+ this->m_columnLeft->MinWidth = this->Pane1MinLength;
+ this->m_columnLeft->MaxWidth = this->Pane1MaxLength;
+ this->m_columnLeft->Width = this->Pane1Length;
+ this->m_columnRight->MinWidth = this->Pane2MinLength;
+ this->m_columnRight->MaxWidth = this->Pane2MaxLength;
+ this->m_columnRight->Width = this->Pane2Length;
+ }
+ else
+ {
+ this->m_columnLeft->MinWidth = this->Pane2MinLength;
+ this->m_columnLeft->MaxWidth = this->Pane2MaxLength;
+ this->m_columnLeft->Width = this->Pane2Length;
+ this->m_columnRight->MinWidth = this->Pane1MinLength;
+ this->m_columnRight->MaxWidth = this->Pane1MaxLength;
+ this->m_columnRight->Width = this->Pane1Length;
+ }
+ }
+ else
+ {
+ this->m_columnLeft->MinWidth = 0.0;
+ this->m_columnRight->MinWidth = 0.0;
+ this->m_columnLeft->MaxWidth = std::numeric_limits::max();
+ this->m_columnRight->MaxWidth = std::numeric_limits::max();
+ this->m_columnLeft->Width = GridLengthHelper::FromValueAndType(1, GridUnitType::Star);
+ this->m_columnRight->Width = GridLengthHelper::FromPixels(0);
+ }
+
+ // Set row lengths
+ if (newMode == ViewMode::TopBottom || newMode == ViewMode::BottomTop)
+ {
+ if (newMode == ViewMode::TopBottom)
+ {
+ this->m_rowTop->MinHeight = this->Pane1MinLength;
+ this->m_rowTop->MaxHeight = this->Pane1MaxLength;
+ this->m_rowTop->Height = this->Pane1Length;
+ this->m_rowBottom->MinHeight = this->Pane2MinLength;
+ this->m_rowBottom->MaxHeight = this->Pane2MaxLength;
+ this->m_rowBottom->Height = this->Pane2Length;
+ }
+ else
+ {
+ this->m_rowTop->MinHeight = this->Pane2MinLength;
+ this->m_rowTop->MaxHeight = this->Pane2MaxLength;
+ this->m_rowTop->Height = this->Pane2Length;
+ this->m_rowBottom->MinHeight = this->Pane1MinLength;
+ this->m_rowBottom->MaxHeight = this->Pane1MaxLength;
+ this->m_rowBottom->Height = this->Pane1Length;
+ }
+ }
+ else
+ {
+ this->m_rowTop->MinHeight = 0.0;
+ this->m_rowBottom->MinHeight = 0.0;
+ this->m_rowTop->MaxHeight = std::numeric_limits::max();
+ this->m_rowBottom->MaxHeight = std::numeric_limits::max();
+ this->m_rowTop->Height = GridLengthHelper::FromValueAndType(1, GridUnitType::Star);
+ this->m_rowBottom->Height = GridLengthHelper::FromPixels(0);
+ }
+
+ // Handle regions
+ if (IsInMultipleRegions(info, rcControl) && newMode != ViewMode::Pane1Only && newMode != ViewMode::Pane2Only)
+ {
+ Rect rc1 = info.Regions[0];
+ Rect rc2 = info.Regions[1];
+ Rect rcWindow = Window::Current->Bounds;
+
+ if (info.Mode == MUXC::TwoPaneViewMode::Wide)
+ {
+ this->m_columnMiddle->Width = GridLengthHelper::FromPixels(rc2.X - rc1.Width);
+
+ this->m_columnLeft->MinWidth = 0.0;
+ this->m_columnRight->MinWidth = 0.0;
+ this->m_columnLeft->MaxWidth = std::numeric_limits::max();
+ this->m_columnRight->MaxWidth = std::numeric_limits::max();
+ this->m_columnLeft->Width = GridLengthHelper::FromPixels(rc1.Width - rcControl.X);
+ this->m_columnRight->Width = GridLengthHelper::FromPixels(rc2.Width - ((rcWindow.Width - rcControl.Width) - rcControl.X));
+ }
+ else
+ {
+ this->m_rowMiddle->Height = GridLengthHelper::FromPixels(rc2.Y - rc1.Height);
+
+ this->m_rowTop->MinHeight = 0.0;
+ this->m_rowBottom->MinHeight = 0.0;
+ this->m_rowTop->MaxHeight = std::numeric_limits::max();
+ this->m_rowBottom->MaxHeight = std::numeric_limits::max();
+ this->m_rowTop->Height = GridLengthHelper::FromPixels(rc1.Height - rcControl.Y);
+ this->m_rowBottom->Height = GridLengthHelper::FromPixels(rc2.Height - ((rcWindow.Height - rcControl.Height) - rcControl.Y));
+ }
+ }
+ }
+}
+
+Rect TwoPaneViewCX::GetControlRect()
+{
+ // Find out where this control is in the window
+ auto transform = TransformToVisual(Window::Current->Content);
+ return transform->TransformBounds(RectHelper::FromCoordinatesAndDimensions(0, 0, (float)this->ActualWidth, (float)this->ActualHeight));
+}
+
+bool TwoPaneViewCX::IsInMultipleRegions(DisplayRegionHelperInfo info, Rect rcControl)
+{
+ bool isInMultipleRegions = false;
+
+ if (info.Mode != MUXC::TwoPaneViewMode::SinglePane)
+ {
+ Rect rc1 = info.Regions[0];
+ Rect rc2 = info.Regions[1];
+
+ if (info.Mode == MUXC::TwoPaneViewMode::Wide)
+ {
+ // Check that the control is over the split
+ if (rcControl.X < rc1.Width && rcControl.X + rcControl.Width > rc2.X)
+ {
+ isInMultipleRegions = true;
+ }
+ }
+ else if (info.Mode == MUXC::TwoPaneViewMode::Tall)
+ {
+ // Check that the control is over the split
+ if (rcControl.Y < rc1.Height && rcControl.Y + rcControl.Height > rc2.Y)
+ {
+ isInMultipleRegions = true;
+ }
+ }
+ }
+
+ return isInMultipleRegions;
+}
+
+void TwoPaneViewCX::OnSizeChanged(Platform::Object ^ /*sender*/, Windows::UI::Xaml::SizeChangedEventArgs ^ /*e*/)
+{
+ this->UpdateMode();
+}
+
+void TwoPaneViewCX::OnWindowSizeChanged(Platform::Object ^ /*sender*/, Windows::UI::Core::WindowSizeChangedEventArgs ^ /*e*/)
+{
+ this->UpdateMode();
+}
+
+void TwoPaneViewCX::OnPane1LengthPropertyChanged(GridLength /*oldValue*/, GridLength /*newValue*/)
+{
+ this->UpdateMode();
+}
+
+void TwoPaneViewCX::OnPane2LengthPropertyChanged(GridLength /*oldValue*/, GridLength /*newValue*/)
+{
+ this->UpdateMode();
+}
+
+void TwoPaneViewCX::OnPane1MinLengthPropertyChanged(double /*oldValue*/, double /*newValue*/)
+{
+ this->UpdateMode();
+}
+
+void TwoPaneViewCX::OnPane2MinLengthPropertyChanged(double /*oldValue*/, double /*newValue*/)
+{
+ this->UpdateMode();
+}
+
+void TwoPaneViewCX::OnPane1MaxLengthPropertyChanged(double /*oldValue*/, double /*newValue*/)
+{
+ this->UpdateMode();
+}
+
+void TwoPaneViewCX::OnPane2MaxLengthPropertyChanged(double /*oldValue*/, double /*newValue*/)
+{
+ this->UpdateMode();
+}
+
+void TwoPaneViewCX::OnMinTallModeHeightPropertyChanged(double /*oldValue*/, double newValue)
+{
+ auto clampedValue = max(0.0, newValue);
+ if (clampedValue != newValue)
+ {
+ this->MinTallModeHeight = clampedValue;
+ return;
+ }
+ this->UpdateMode();
+}
+
+void TwoPaneViewCX::OnMinWideModeWidthPropertyChanged(double /*oldValue*/, double newValue)
+{
+ auto clampedValue = max(0.0, newValue);
+ if (clampedValue != newValue)
+ {
+ this->MinWideModeWidth = clampedValue;
+ return;
+ }
+ this->UpdateMode();
+}
+
+void TwoPaneViewCX::OnWideModeConfigurationPropertyChanged(
+ MUXC::TwoPaneViewWideModeConfiguration /*oldValue*/,
+ MUXC::TwoPaneViewWideModeConfiguration /*newValue*/)
+{
+ this->UpdateMode();
+}
+
+void TwoPaneViewCX::OnTallModeConfigurationPropertyChanged(
+ MUXC::TwoPaneViewTallModeConfiguration /*oldValue*/,
+ MUXC::TwoPaneViewTallModeConfiguration /*newValue*/)
+{
+ this->UpdateMode();
+}
+
+void TwoPaneViewCX::OnPanePriorityPropertyChanged(MUXC::TwoPaneViewPriority /*oldValue*/, MUXC::TwoPaneViewPriority /*newValue*/)
+{
+ this->UpdateMode();
+}
+
+TwoPaneViewCX::DisplayRegionHelperInfo TwoPaneViewCX::GetDisplayRegionHelperInfo()
+{
+ DisplayRegionHelperInfo info;
+ info.Mode = MUXC::TwoPaneViewMode::SinglePane;
+
+ if (!Windows::Foundation::Metadata::ApiInformation::IsMethodPresent(L"Windows.UI.ViewManagement.ApplicationView", L"GetDisplayRegions"))
+ {
+ return info;
+ }
+
+ // ApplicationView::GetForCurrentView throws on failure; in that case we just won't do anything.
+ ApplicationView ^ view;
+ try
+ {
+ view = ApplicationView::GetForCurrentView();
+ }
+ catch (...)
+ {
+ }
+
+ if (view && (int)view->ViewMode == 2 /*ApplicationViewMode::Spanning*/)
+ {
+ auto regions = view->GetDisplayRegions();
+ if (regions->Size == 2)
+ {
+ auto region1 = regions->GetAt(0);
+ auto region2 = regions->GetAt(1);
+ info.Regions = ref new Array(2);
+ info.Regions[0] = RectHelper::FromCoordinatesAndDimensions(
+ region1->WorkAreaOffset.X, region1->WorkAreaOffset.Y, region1->WorkAreaSize.Width, region1->WorkAreaSize.Height);
+ info.Regions[1] = RectHelper::FromCoordinatesAndDimensions(
+ region2->WorkAreaOffset.X, region2->WorkAreaOffset.Y, region2->WorkAreaSize.Width, region2->WorkAreaSize.Height);
+
+ // Determine orientation. If neither of these are true, default to doing nothing.
+ if (info.Regions[0].X < info.Regions[1].X && info.Regions[0].Y == info.Regions[1].Y)
+ {
+ // Double portrait
+ info.Mode = MUXC::TwoPaneViewMode::Wide;
+ }
+ else if (info.Regions[0].X == info.Regions[1].X && info.Regions[0].Y < info.Regions[1].Y)
+ {
+ // Double landscape
+ info.Mode = MUXC::TwoPaneViewMode::Tall;
+ }
+ }
+ }
+ return info;
+}
+
+void TwoPaneViewCX::SetScrollViewerProperties(String ^ scrollViewerName)
+{
+ if (ApiInformation::IsApiContractPresent(L"Windows.Foundation.UniversalApiContract", 7))
+ {
+ if (auto scrollViewer = dynamic_cast(this->GetTemplateChild(scrollViewerName)))
+ {
+ if (ApiInformation::IsPropertyPresent(L"Windows.UI.Xaml.Controls.ScrollContentPresenter", L"SizesContentToTemplatedParent"))
+ {
+ scrollViewer->Loaded += ref new RoutedEventHandler(this, &TwoPaneViewCX::OnScrollViewerLoaded);
+ }
+
+ if (ApiInformation::IsPropertyPresent(L"Windows.UI.Xaml.Controls.ScrollViewer", L"ReduceViewportForCoreInputViewOcclusions"))
+ {
+ scrollViewer->ReduceViewportForCoreInputViewOcclusions = true;
+ }
+ }
+ }
+}
+
+void TwoPaneViewCX::OnScrollViewerLoaded(Object ^ sender, RoutedEventArgs ^ e)
+{
+ if (auto scrollViewer = dynamic_cast(sender))
+ {
+ auto scrollContentPresenterFE = VisualTree::FindDescendantByName(scrollViewer, L"ScrollContentPresenter");
+ if (scrollContentPresenterFE)
+ {
+ if (auto scrollContentPresenter = dynamic_cast(scrollContentPresenterFE))
+ {
+ scrollContentPresenter->SizesContentToTemplatedParent = true;
+ }
+ }
+ }
+}
diff --git a/src/Calculator/Controls/TwoPaneViewCX.h b/src/Calculator/Controls/TwoPaneViewCX.h
new file mode 100644
index 00000000..d3f79326
--- /dev/null
+++ b/src/Calculator/Controls/TwoPaneViewCX.h
@@ -0,0 +1,116 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See LICENSE in the project root for license information.
+
+#pragma once
+#include "CalcViewModel/Common/Utils.h"
+
+namespace CalculatorApp::Controls
+{
+ ref class TwoPaneViewCX;
+public
+ interface class ITwoPaneViewCX
+ {
+ event Windows::Foundation::TypedEventHandler ^ ModeChanged;
+ };
+
+ // We can't use the TwoPaneView control from the SDK or from Microsoft.UI.Xaml because of a bug with C++ apps.
+ // (see this issue: https://github.com/microsoft/microsoft-ui-xaml/pull/2045)
+ // This class is a C++/CX port of the C++/WinRT version of Microsoft.UI.Xaml (commit b3a2e45) which include the patch to fix the crash.
+ // This fork adds also 4 new properties Pane1MinLength, Pane2MinLength, Pane1MaxLength, Pane2MaxLength
+public
+ ref class TwoPaneViewCX sealed : public Windows::UI::Xaml::Controls::Control, [Windows::Foundation::Metadata::Default] ITwoPaneViewCX
+ {
+ enum class ViewMode
+ {
+ Pane1Only,
+ Pane2Only,
+ LeftRight,
+ RightLeft,
+ TopBottom,
+ BottomTop,
+ None
+ };
+
+ struct DisplayRegionHelperInfo
+ {
+ Microsoft::UI::Xaml::Controls::TwoPaneViewMode Mode = Microsoft::UI::Xaml::Controls::TwoPaneViewMode::SinglePane;
+ Platform::Array ^ Regions;
+ };
+
+ public:
+ DEPENDENCY_PROPERTY_OWNER(TwoPaneViewCX);
+ DEPENDENCY_PROPERTY(Windows::UI::Xaml::UIElement ^, Pane1);
+ DEPENDENCY_PROPERTY(Windows::UI::Xaml::UIElement ^, Pane2);
+ DEPENDENCY_PROPERTY_WITH_DEFAULT_AND_CALLBACK(
+ Windows::UI::Xaml::GridLength,
+ Pane1Length,
+ Windows::UI::Xaml::GridLengthHelper::FromValueAndType(1, Windows::UI::Xaml::GridUnitType::Auto));
+ DEPENDENCY_PROPERTY_WITH_DEFAULT_AND_CALLBACK(
+ Windows::UI::Xaml::GridLength,
+ Pane2Length,
+ Windows::UI::Xaml::GridLengthHelper::FromValueAndType(1, Windows::UI::Xaml::GridUnitType::Star));
+ DEPENDENCY_PROPERTY_WITH_DEFAULT_AND_CALLBACK(double, Pane1MinLength, 0.0);
+ DEPENDENCY_PROPERTY_WITH_DEFAULT_AND_CALLBACK(double, Pane2MinLength, 0.0);
+ DEPENDENCY_PROPERTY_WITH_DEFAULT_AND_CALLBACK(double, Pane1MaxLength, std::numeric_limits::max());
+ DEPENDENCY_PROPERTY_WITH_DEFAULT_AND_CALLBACK(double, Pane2MaxLength, std::numeric_limits::max());
+
+ DEPENDENCY_PROPERTY_WITH_DEFAULT_AND_CALLBACK(Microsoft::UI::Xaml::Controls::TwoPaneViewPriority,
+ PanePriority,
+ Microsoft::UI::Xaml::Controls::TwoPaneViewPriority::Pane1);
+ DEPENDENCY_PROPERTY(Microsoft::UI::Xaml::Controls::TwoPaneViewMode, Mode);
+ DEPENDENCY_PROPERTY_WITH_DEFAULT_AND_CALLBACK(
+ Microsoft::UI::Xaml::Controls::TwoPaneViewWideModeConfiguration,
+ WideModeConfiguration,
+ Microsoft::UI::Xaml::Controls::TwoPaneViewWideModeConfiguration::LeftRight);
+ DEPENDENCY_PROPERTY_WITH_DEFAULT_AND_CALLBACK(
+ Microsoft::UI::Xaml::Controls::TwoPaneViewTallModeConfiguration,
+ TallModeConfiguration,
+ Microsoft::UI::Xaml::Controls::TwoPaneViewTallModeConfiguration::TopBottom);
+ DEPENDENCY_PROPERTY_WITH_DEFAULT_AND_CALLBACK(double, MinWideModeWidth, 641);
+ DEPENDENCY_PROPERTY_WITH_DEFAULT_AND_CALLBACK(double, MinTallModeHeight, 641);
+
+ TwoPaneViewCX();
+ virtual ~TwoPaneViewCX();
+ void OnApplyTemplate() override;
+ virtual event Windows::Foundation::TypedEventHandler ^ ModeChanged;
+
+ private:
+ void UpdateRowsColumns(ViewMode newMode, DisplayRegionHelperInfo info, Windows::Foundation::Rect rcControl);
+ void UpdateMode();
+ bool IsInMultipleRegions(DisplayRegionHelperInfo info, Windows::Foundation::Rect rcControl);
+ void SetScrollViewerProperties(Platform::String ^ scrollViewerName);
+ Windows::Foundation::Rect GetControlRect();
+ DisplayRegionHelperInfo GetDisplayRegionHelperInfo();
+
+ void OnSizeChanged(Platform::Object ^ sender, Windows::UI::Xaml::SizeChangedEventArgs ^ e);
+ void OnWindowSizeChanged(Platform::Object ^ sender, Windows::UI::Core::WindowSizeChangedEventArgs ^ e);
+ void OnPane1LengthPropertyChanged(Windows::UI::Xaml::GridLength oldValue, Windows::UI::Xaml::GridLength newValue);
+ void OnPane2LengthPropertyChanged(Windows::UI::Xaml::GridLength oldValue, Windows::UI::Xaml::GridLength newValue);
+ void OnPane1MinLengthPropertyChanged(double oldValue, double newValue);
+ void OnPane2MinLengthPropertyChanged(double oldValue, double newValue);
+ void OnPane1MaxLengthPropertyChanged(double oldValue, double newValue);
+ void OnPane2MaxLengthPropertyChanged(double oldValue, double newValue);
+ void
+ OnPanePriorityPropertyChanged(Microsoft::UI::Xaml::Controls::TwoPaneViewPriority oldValue, Microsoft::UI::Xaml::Controls::TwoPaneViewPriority newValue);
+ void OnMinTallModeHeightPropertyChanged(double oldValue, double newValue);
+ void OnMinWideModeWidthPropertyChanged(double oldValue, double newValue);
+ void OnWideModeConfigurationPropertyChanged(
+ Microsoft::UI::Xaml::Controls::TwoPaneViewWideModeConfiguration oldValue,
+ Microsoft::UI::Xaml::Controls::TwoPaneViewWideModeConfiguration newValue);
+ void OnTallModeConfigurationPropertyChanged(
+ Microsoft::UI::Xaml::Controls::TwoPaneViewTallModeConfiguration oldValue,
+ Microsoft::UI::Xaml::Controls::TwoPaneViewTallModeConfiguration newValue);
+ void OnScrollViewerLoaded(Platform::Object ^ sender, Windows::UI::Xaml::RoutedEventArgs ^ e);
+
+ private:
+ Windows::UI::Xaml::Controls::ColumnDefinition ^ m_columnLeft;
+ Windows::UI::Xaml::Controls::ColumnDefinition ^ m_columnMiddle;
+ Windows::UI::Xaml::Controls::ColumnDefinition ^ m_columnRight;
+ Windows::UI::Xaml::Controls::RowDefinition ^ m_rowTop;
+ Windows::UI::Xaml::Controls::RowDefinition ^ m_rowMiddle;
+ Windows::UI::Xaml::Controls::RowDefinition ^ m_rowBottom;
+ Windows::Foundation::EventRegistrationToken m_windowSizeChangedToken;
+ ViewMode m_currentMode{ ViewMode::None };
+ bool m_loaded{ false };
+ };
+}
diff --git a/src/Calculator/MultiTrigger.cpp b/src/Calculator/MultiTrigger.cpp
new file mode 100644
index 00000000..e69de29b
diff --git a/src/Calculator/MultiTrigger.h b/src/Calculator/MultiTrigger.h
new file mode 100644
index 00000000..e69de29b
diff --git a/src/Calculator/Package.appxmanifest b/src/Calculator/Package.appxmanifest
index 76d1c97f..db28a967 100644
--- a/src/Calculator/Package.appxmanifest
+++ b/src/Calculator/Package.appxmanifest
@@ -8,7 +8,7 @@
Assets\CalculatorStoreLogo.png
-
+
diff --git a/src/Calculator/Views/Calculator.xaml b/src/Calculator/Views/Calculator.xaml
index 71dddefa..274ee6ea 100644
--- a/src/Calculator/Views/Calculator.xaml
+++ b/src/Calculator/Views/Calculator.xaml
@@ -8,6 +8,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:CalculatorApp"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:triggers="using:CalculatorApp.Views.StateTriggers"
Loaded="OnLoaded"
mc:Ignorable="d">
@@ -382,15 +383,7 @@
Icon="Paste"/>
-
-
-
-
-
-
@@ -415,18 +408,13 @@
-
+
-
+
-
-
-
-
-
@@ -460,12 +448,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -476,7 +496,7 @@
-
+
@@ -487,8 +507,8 @@
-
-
+
+
@@ -516,11 +536,18 @@
-
+
+
+
+
+
+
+
+
-
+
@@ -529,7 +556,7 @@
-
+
@@ -539,8 +566,6 @@
-
-
@@ -574,704 +599,751 @@
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ TokensUpdated="{x:Bind Model.AreTokensUpdated, Mode=OneWay}"
+ Visibility="{x:Bind Model.IsAlwaysOnTop, Converter={StaticResource BooleanToVisibilityNegationConverter}, Mode=OneWay}"/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Calculator/Views/Calculator.xaml.cpp b/src/Calculator/Views/Calculator.xaml.cpp
index 40de0449..ffb6ed04 100644
--- a/src/Calculator/Views/Calculator.xaml.cpp
+++ b/src/Calculator/Views/Calculator.xaml.cpp
@@ -674,6 +674,11 @@ void Calculator::DockPanelTapped(_In_ TappedRoutedEventArgs ^ e)
void Calculator::UnregisterEventHandlers()
{
ExpressionText->UnregisterEventHandlers();
+ AlwaysOnTopResults->UnregisterEventHandlers();
+ if (DualScreenExpressionText != nullptr)
+ {
+ DualScreenExpressionText->UnregisterEventHandlers();
+ }
}
void Calculator::OnErrorVisualStateCompleted(_In_ Platform::Object ^ sender, _In_ Platform::Object ^ e)
diff --git a/src/Calculator/Views/Calculator.xaml.h b/src/Calculator/Views/Calculator.xaml.h
index 16979d83..3ec1a1f3 100644
--- a/src/Calculator/Views/Calculator.xaml.h
+++ b/src/Calculator/Views/Calculator.xaml.h
@@ -24,6 +24,7 @@
#include "Views/Memory.xaml.h"
#include "Views/OperatorsPanel.xaml.h"
#include "Views/StateTriggers/ControlSizeTrigger.h"
+#include "Views/StateTriggers/ApplicationViewModeTrigger.h"
namespace CalculatorApp
{
diff --git a/src/Calculator/Views/GraphingCalculator/EquationInputArea.xaml b/src/Calculator/Views/GraphingCalculator/EquationInputArea.xaml
index 55491b4b..13fd008d 100644
--- a/src/Calculator/Views/GraphingCalculator/EquationInputArea.xaml
+++ b/src/Calculator/Views/GraphingCalculator/EquationInputArea.xaml
@@ -851,21 +851,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/Calculator/Views/GraphingCalculator/GraphingCalculator.xaml b/src/Calculator/Views/GraphingCalculator/GraphingCalculator.xaml
index 4682c27e..f2b33219 100644
--- a/src/Calculator/Views/GraphingCalculator/GraphingCalculator.xaml
+++ b/src/Calculator/Views/GraphingCalculator/GraphingCalculator.xaml
@@ -2,11 +2,14 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:contract7Present="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract,7)"
+ xmlns:controls="using:CalculatorApp.Controls"
xmlns:converters="using:CalculatorApp.Converters"
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:muxc="using:Microsoft.UI.Xaml.Controls"
+ xmlns:states="using:CalculatorApp.Views.StateTriggers"
x:Name="Control"
DataContextChanged="GraphingCalculator_DataContextChanged"
mc:Ignorable="d">
@@ -383,26 +386,60 @@
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ TopBottom
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
+
+ SinglePane
+
+
@@ -411,246 +448,257 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
- 4,4,0,0
- 0,0,4,4
- 4,0,0,4
- 0,4,4,0
-
-
-
- 4,4,0,0
- 0,0,4,4
- 4,0,0,4
- 0,4,4,0
-
-
-
- 0
- 0
- 0
- 0
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+ 4,4,0,0
+ 0,0,4,4
+ 4,0,0,4
+ 0,4,4,0
+
+
+
+ 4,4,0,0
+ 0,0,4,4
+ 4,0,0,4
+ 0,4,4,0
+
+
+
+ 0
+ 0
+ 0
+ 0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
+
+
+
diff --git a/src/Calculator/Views/GraphingCalculator/GraphingCalculator.xaml.cpp b/src/Calculator/Views/GraphingCalculator/GraphingCalculator.xaml.cpp
index 1a2096f4..8619f1e5 100644
--- a/src/Calculator/Views/GraphingCalculator/GraphingCalculator.xaml.cpp
+++ b/src/Calculator/Views/GraphingCalculator/GraphingCalculator.xaml.cpp
@@ -49,8 +49,9 @@ using namespace Windows::UI::Xaml::Media;
using namespace Windows::UI::Xaml::Media::Imaging;
using namespace Windows::UI::Popups;
using namespace Windows::UI::ViewManagement;
+namespace MUXC = Microsoft::UI::Xaml::Controls;
-constexpr auto sc_ViewModelPropertyName = L"ViewModel";
+ constexpr auto sc_ViewModelPropertyName = L"ViewModel";
DEPENDENCY_PROPERTY_INITIALIZATION(GraphingCalculator, IsSmallState);
DEPENDENCY_PROPERTY_INITIALIZATION(GraphingCalculator, GraphControlAutomationName);
@@ -434,9 +435,9 @@ void GraphingCalculator::OnKeyGraphFeaturesClosed(Object ^ sender, RoutedEventAr
ViewModel->SelectedEquation->GraphEquation->IsSelected = false;
}
-Visibility GraphingCalculator::ShouldDisplayPanel(bool isSmallState, bool isEquationModeActivated, bool isGraphPanel)
+MUXC::TwoPaneViewPriority GraphingCalculator::GetPanePriority(bool isEquationModeActivated)
{
- return (!isSmallState || isEquationModeActivated ^ isGraphPanel) ? ::Visibility::Visible : ::Visibility::Collapsed;
+ return isEquationModeActivated ? MUXC::TwoPaneViewPriority::Pane2 : MUXC::TwoPaneViewPriority::Pane1;
}
Platform::String ^ GraphingCalculator::GetInfoForSwitchModeToggleButton(bool isChecked)
@@ -573,7 +574,10 @@ void GraphingCalculator::DisplayGraphSettings()
auto flyoutGraphSettings = ref new Flyout();
flyoutGraphSettings->Content = graphSettings;
flyoutGraphSettings->Closing += ref new TypedEventHandler(this, &GraphingCalculator::OnSettingsFlyout_Closing);
- flyoutGraphSettings->ShowAt(GraphSettingsButton);
+
+ auto options = ref new FlyoutShowOptions();
+ options->Placement = FlyoutPlacementMode::BottomEdgeAlignedRight;
+ flyoutGraphSettings->ShowAt(GraphSettingsButton, options);
}
void CalculatorApp::GraphingCalculator::AddTracePointerShadow()
diff --git a/src/Calculator/Views/GraphingCalculator/GraphingCalculator.xaml.h b/src/Calculator/Views/GraphingCalculator/GraphingCalculator.xaml.h
index 9810ce88..5e1988a2 100644
--- a/src/Calculator/Views/GraphingCalculator/GraphingCalculator.xaml.h
+++ b/src/Calculator/Views/GraphingCalculator/GraphingCalculator.xaml.h
@@ -9,7 +9,9 @@
#include "Views\GraphingCalculator\KeyGraphFeaturesPanel.xaml.h"
#include "Views\GraphingCalculator\GraphingNumPad.xaml.h"
#include "Views\GraphingCalculator\GraphingSettings.xaml.h"
-#include "CalcViewModel/Common/TraceLogger.h"
+#include "Views\StateTriggers\ApplicationViewModeTrigger.h"
+#include "Controls\TwoPaneViewCX.h"
+#include "CalcViewModel\Common\TraceLogger.h"
namespace CalculatorApp
{
@@ -36,7 +38,7 @@ public ref class GraphingCalculator sealed : public Windows::UI::Xaml::Data::INo
void set(CalculatorApp::ViewModel::GraphingCalculatorViewModel^ vm);
}
- static Windows::UI::Xaml::Visibility ShouldDisplayPanel(bool isSmallState, bool isEquationModeActivated, bool isGraphPanel);
+ static Microsoft::UI::Xaml::Controls::TwoPaneViewPriority GetPanePriority(bool isEquationModeActivated);
static Platform::String ^ GetInfoForSwitchModeToggleButton(bool isChecked);
static Windows::UI::Xaml::Visibility ManageEditVariablesButtonVisibility(unsigned int numberOfVariables);
static Platform::String ^ GetTracingLegend(Platform::IBox ^ isTracing);
diff --git a/src/Calculator/Views/StateTriggers/ApplicationViewModeTrigger.cpp b/src/Calculator/Views/StateTriggers/ApplicationViewModeTrigger.cpp
new file mode 100644
index 00000000..fb7c947a
--- /dev/null
+++ b/src/Calculator/Views/StateTriggers/ApplicationViewModeTrigger.cpp
@@ -0,0 +1,80 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+#include "pch.h"
+#include "ApplicationViewModeTrigger.h"
+using namespace CalculatorApp::Views::StateTriggers;
+using namespace Windows::System::Profile;
+using namespace Windows::UI::ViewManagement;
+using namespace Windows::UI::Xaml;
+
+DEPENDENCY_PROPERTY_INITIALIZATION(ApplicationViewModeTrigger, ViewMode);
+DEPENDENCY_PROPERTY_INITIALIZATION(ApplicationViewModeTrigger, MinWindowHeight);
+DEPENDENCY_PROPERTY_INITIALIZATION(ApplicationViewModeTrigger, MinWindowWidth);
+
+ApplicationViewModeTrigger::ApplicationViewModeTrigger()
+{
+ m_windowSizeEventToken = Window::Current->SizeChanged += ref new WindowSizeChangedEventHandler(this, &ApplicationViewModeTrigger::WindowSizeChanged);
+ UpdateTrigger();
+}
+
+void ApplicationViewModeTrigger::WindowSizeChanged(_In_ Platform::Object ^ /*sender*/, _In_ Windows::UI::Core::WindowSizeChangedEventArgs ^ /*e*/)
+{
+ // We don't use layout aware page's view states, we have our own
+ UpdateTrigger();
+}
+void ApplicationViewModeTrigger::OnViewModePropertyChanged(_In_ AppViewMode /*oldValue*/, _In_ AppViewMode /*newValue*/)
+{
+ UpdateTrigger();
+}
+void ApplicationViewModeTrigger::OnMinWindowHeightPropertyChanged(double /*oldValue*/, double /*newValue*/)
+{
+ UpdateTrigger();
+}
+
+void ApplicationViewModeTrigger::OnMinWindowWidthPropertyChanged(double /*oldValue*/, double /*newValue*/)
+{
+ UpdateTrigger();
+}
+
+void ApplicationViewModeTrigger::UpdateTrigger()
+{
+ auto applicationView = ApplicationView::GetForCurrentView();
+ auto viewMode = applicationView->ViewMode;
+ if (applicationView->VisibleBounds.Width < this->MinWindowWidth || applicationView->VisibleBounds.Height < this->MinWindowHeight)
+ {
+ SetActive(false);
+ return;
+ }
+
+ switch (static_cast(viewMode))
+ {
+ case 0 /*ApplicationViewMode::Default*/:
+ SetActive(this->ViewMode == AppViewMode::Normal);
+ break;
+ case 1 /*ApplicationViewMode::CompactOverlay*/:
+ SetActive(this->ViewMode == AppViewMode::CompactOverlay);
+ break;
+ case 2 /*ApplicationViewMode::Spanning*/:
+
+ // We will need to update this code to use new SpanningRects API instead of DisplayRegions when the app will use the SDK for windows 10 2004.
+ auto displayRegions = applicationView->GetDisplayRegions();
+ if (displayRegions->Size == 2)
+ {
+ auto display1 = displayRegions->GetAt(0);
+ auto display2 = displayRegions->GetAt(1);
+ if (display1->WorkAreaOffset.X < display2->WorkAreaOffset.X && display1->WorkAreaOffset.Y == display2->WorkAreaOffset.Y)
+ {
+ this->SetActive(this->ViewMode == AppViewMode::DoublePortrait);
+ return;
+ }
+ else if (display1->WorkAreaOffset.X == display2->WorkAreaOffset.X && display1->WorkAreaOffset.Y < display2->WorkAreaOffset.Y)
+ {
+ this->SetActive(this->ViewMode == AppViewMode::DoubleLandscape);
+ return;
+ }
+ }
+ SetActive(this->ViewMode == AppViewMode::Normal);
+ break;
+ }
+}
diff --git a/src/Calculator/Views/StateTriggers/ApplicationViewModeTrigger.h b/src/Calculator/Views/StateTriggers/ApplicationViewModeTrigger.h
new file mode 100644
index 00000000..a708ea1b
--- /dev/null
+++ b/src/Calculator/Views/StateTriggers/ApplicationViewModeTrigger.h
@@ -0,0 +1,40 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+#pragma once
+#include "CalcViewModel/Common/Utils.h"
+
+namespace CalculatorApp::Views::StateTriggers
+{
+public
+ enum class AppViewMode
+ {
+ Normal = 0,
+ CompactOverlay = 1,
+ DoublePortrait = 2,
+ DoubleLandscape = 3
+ };
+
+public
+ ref class ApplicationViewModeTrigger sealed : public Windows::UI::Xaml::StateTriggerBase
+ {
+ public:
+ ApplicationViewModeTrigger();
+ DEPENDENCY_PROPERTY_OWNER(ApplicationViewModeTrigger);
+
+ /* The view mode that will cause the trigger to fire. */
+ DEPENDENCY_PROPERTY_WITH_DEFAULT_AND_CALLBACK(AppViewMode, ViewMode, AppViewMode::Normal);
+
+ DEPENDENCY_PROPERTY_WITH_DEFAULT_AND_CALLBACK(double, MinWindowHeight, -1);
+
+ DEPENDENCY_PROPERTY_WITH_DEFAULT_AND_CALLBACK(double, MinWindowWidth, -1);
+ private:
+ void OnViewModePropertyChanged(AppViewMode oldValue, AppViewMode newValue);
+ void OnMinWindowHeightPropertyChanged(double oldValue, double newValue);
+ void OnMinWindowWidthPropertyChanged(double oldValue, double newValue);
+ void WindowSizeChanged(_In_ Platform::Object ^ sender, _In_ Windows::UI::Core::WindowSizeChangedEventArgs ^ e);
+ void UpdateTrigger();
+ private:
+ Windows::Foundation::EventRegistrationToken m_windowSizeEventToken;
+ };
+}
diff --git a/src/Calculator/Views/TitleBar.xaml.cpp b/src/Calculator/Views/TitleBar.xaml.cpp
index 44f4a8c4..99958823 100644
--- a/src/Calculator/Views/TitleBar.xaml.cpp
+++ b/src/Calculator/Views/TitleBar.xaml.cpp
@@ -5,9 +5,11 @@
#include "TitleBar.xaml.h"
#include "CalcViewModel/Common/AppResourceProvider.h"
#include "CalcViewModel/Common/Utils.h"
+#include "CalcViewModel/Utils/DeviceFamilyHelper.h"
using namespace std;
using namespace Platform;
+using namespace CalculatorApp::ViewModel::Utils;
using namespace Windows::ApplicationModel;
using namespace Windows::ApplicationModel::Core;
using namespace Windows::Foundation;
@@ -50,7 +52,7 @@ namespace CalculatorApp
[this](CoreApplicationViewTitleBar ^ cTitleBar, Object ^) { this->SetTitleBarVisibility(); });
m_layoutChangedToken = m_coreTitleBar->LayoutMetricsChanged +=
ref new TypedEventHandler([this](CoreApplicationViewTitleBar ^ cTitleBar, Object ^) {
- this->LayoutRoot->Height = cTitleBar->Height;
+ this->SetTitleBarHeight();
this->SetTitleBarPadding();
});
@@ -60,11 +62,10 @@ namespace CalculatorApp
m_windowActivatedToken = Window::Current->Activated +=
ref new Windows::UI::Xaml::WindowActivatedEventHandler(this, &CalculatorApp::TitleBar::OnWindowActivated);
// Set properties
- LayoutRoot->Height = m_coreTitleBar->Height;
- SetTitleBarControlColors();
-
- SetTitleBarVisibility();
- SetTitleBarPadding();
+ this->SetTitleBarHeight();
+ this->SetTitleBarControlColors();
+ this->SetTitleBarVisibility();
+ this->SetTitleBarPadding();
}
void TitleBar::OnUnloaded(_In_ Object ^ /*sender*/, _In_ RoutedEventArgs ^ /*e*/)
@@ -84,7 +85,25 @@ namespace CalculatorApp
void TitleBar::SetTitleBarVisibility()
{
- this->LayoutRoot->Visibility = m_coreTitleBar->IsVisible || IsAlwaysOnTopMode ? ::Visibility::Visible : ::Visibility::Collapsed;
+ // CoreApplication::GetCurrentView()->TitleBar->IsVisible currently returns False instead of True on Windows 10X.
+ // This issue is already tracked and will be fixed in a future preview version of 10X.
+ this->LayoutRoot->Visibility = m_coreTitleBar->IsVisible || DeviceFamilyHelper::GetDeviceFamily() == DeviceFamily::WindowsCore || IsAlwaysOnTopMode
+ ? ::Visibility::Visible
+ : ::Visibility::Collapsed;
+ }
+
+ void TitleBar::SetTitleBarHeight()
+ {
+ if (m_coreTitleBar->Height == 0 && DeviceFamilyHelper::GetDeviceFamily() == DeviceFamily::WindowsCore)
+ {
+ // CoreApplication::GetCurrentView()->TitleBar doesn't return the correct height on Windows 10X.
+ // This issue is already tracked and will be fixed in a future preview version of 10X.
+ this->LayoutRoot->Height = 32;
+ }
+ else
+ {
+ this->LayoutRoot->Height = m_coreTitleBar->Height;
+ }
}
void TitleBar::SetTitleBarPadding()
diff --git a/src/Calculator/Views/TitleBar.xaml.h b/src/Calculator/Views/TitleBar.xaml.h
index 53bf6ff7..98325c18 100644
--- a/src/Calculator/Views/TitleBar.xaml.h
+++ b/src/Calculator/Views/TitleBar.xaml.h
@@ -29,6 +29,7 @@ public
void SetTitleBarText(Platform::String ^ text);
void SetTitleBarVisibility();
+ void SetTitleBarHeight();
void SetTitleBarPadding();
void SetTitleBarControlColors();
void ColorValuesChanged(_In_ Windows::UI::ViewManagement::UISettings ^ sender, _In_ Platform::Object ^ e);
diff --git a/src/Calculator/Views/UnitConverter.xaml b/src/Calculator/Views/UnitConverter.xaml
index 60fd7248..31b13705 100644
--- a/src/Calculator/Views/UnitConverter.xaml
+++ b/src/Calculator/Views/UnitConverter.xaml
@@ -277,36 +277,47 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
-
-
-
-
-
+
+
@@ -400,7 +409,6 @@
-
@@ -437,8 +445,8 @@
-
-
+
+
@@ -506,259 +514,287 @@
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
+ Grid.RowSpan="5"
+ Visibility="Collapsed">
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
+
+
+
+
+
-
-
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/src/Calculator/Views/UnitConverter.xaml.h b/src/Calculator/Views/UnitConverter.xaml.h
index 16c669c0..21a69219 100644
--- a/src/Calculator/Views/UnitConverter.xaml.h
+++ b/src/Calculator/Views/UnitConverter.xaml.h
@@ -13,6 +13,7 @@
#include "Converters/VisibilityNegationConverter.h"
#include "CalcViewModel/UnitConverterViewModel.h"
#include "Views/StateTriggers/AspectRatioTrigger.h"
+#include "Views/StateTriggers/ApplicationViewModeTrigger.h"
namespace CalculatorApp
{
diff --git a/src/Calculator/packages.config b/src/Calculator/packages.config
index a33d8464..ef1db862 100644
--- a/src/Calculator/packages.config
+++ b/src/Calculator/packages.config
@@ -1,5 +1,5 @@
-
+
\ No newline at end of file
diff --git a/src/Calculator/pch.h b/src/Calculator/pch.h
index 13812fec..0ae56d8d 100644
--- a/src/Calculator/pch.h
+++ b/src/Calculator/pch.h
@@ -41,6 +41,7 @@
#include "winrt/Windows.System.UserProfile.h"
#include "winrt/Windows.UI.ViewManagement.h"
#include "winrt/Windows.UI.Xaml.h"
+#include "winrt/Windows.System.Profile.h"
#include "winrt/Windows.Foundation.h"
// Project Headers