diff --git a/src/Calculator/Calculator.vcxproj b/src/Calculator/Calculator.vcxproj
index e0a757f0..4e19aab2 100644
--- a/src/Calculator/Calculator.vcxproj
+++ b/src/Calculator/Calculator.vcxproj
@@ -251,6 +251,7 @@
+
App.xaml
@@ -384,6 +385,7 @@
+
Create
Create
diff --git a/src/Calculator/Calculator.vcxproj.filters b/src/Calculator/Calculator.vcxproj.filters
index 2cd7dcde..cc25a224 100644
--- a/src/Calculator/Calculator.vcxproj.filters
+++ b/src/Calculator/Calculator.vcxproj.filters
@@ -308,6 +308,9 @@
Common
+
+ Controls
+
@@ -407,6 +410,9 @@
Common
+
+ Controls
+
diff --git a/src/Calculator/Controls/HorizontalNoOverflowStackPanel.cpp b/src/Calculator/Controls/HorizontalNoOverflowStackPanel.cpp
new file mode 100644
index 00000000..b009bc28
--- /dev/null
+++ b/src/Calculator/Controls/HorizontalNoOverflowStackPanel.cpp
@@ -0,0 +1,70 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+//
+// HorizontalNoOverflowStackPanel.xaml.cpp
+// Implementation of the HorizontalNoOverflowStackPanel class
+//
+
+#include "pch.h"
+#include "HorizontalNoOverflowStackPanel.h"
+
+using namespace std;
+using namespace CalculatorApp::Controls;
+using namespace Windows::Foundation;
+
+Size HorizontalNoOverflowStackPanel::MeasureOverride(Size availableSize)
+{
+ float maxHeight = 0;
+ float width = 0;
+ for (auto child : Children)
+ {
+ child->Measure(Size(numeric_limits::infinity(), numeric_limits::infinity()));
+ maxHeight = max(maxHeight, child->DesiredSize.Height);
+ width += child->DesiredSize.Width;
+ }
+ return Size(min(width, availableSize.Width), min(availableSize.Height, maxHeight));
+}
+
+bool HorizontalNoOverflowStackPanel::ShouldPrioritizeLastItem()
+{
+ return false;
+}
+
+Size HorizontalNoOverflowStackPanel::ArrangeOverride(Size finalSize)
+{
+ if (Children->Size == 0)
+ {
+ return finalSize;
+ }
+
+ float posX = 0;
+ auto lastChild = Children->GetAt(Children->Size - 1);
+ float lastChildWidth = 0;
+ if (Children->Size > 2 && ShouldPrioritizeLastItem())
+ {
+ lastChildWidth = lastChild->DesiredSize.Width;
+ }
+ for (auto item : Children)
+ {
+ auto widthAvailable = finalSize.Width - posX;
+ if (item != lastChild)
+ {
+ widthAvailable -= lastChildWidth;
+ }
+ float itemWidth = item->DesiredSize.Width;
+ if (widthAvailable > 0 && itemWidth <= widthAvailable)
+ {
+ //stack the items horizontally (left to right)
+ item->Arrange(Rect(posX, 0, itemWidth, finalSize.Height));
+ posX += item->RenderSize.Width;
+ }
+ else
+ {
+ //Not display the item
+ item->Arrange(Rect(0, 0, 0, 0));
+ }
+ }
+ return finalSize;
+}
+
diff --git a/src/Calculator/Controls/HorizontalNoOverflowStackPanel.h b/src/Calculator/Controls/HorizontalNoOverflowStackPanel.h
new file mode 100644
index 00000000..7619faf4
--- /dev/null
+++ b/src/Calculator/Controls/HorizontalNoOverflowStackPanel.h
@@ -0,0 +1,28 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+//
+// HorizontalNoOverflowStackPanel.h
+// Declaration of the HorizontalNoOverflowStackPanel class
+//
+
+#pragma once
+#include "CalcViewModel/Common/Utils.h"
+
+namespace CalculatorApp
+{
+ namespace Controls
+ {
+ public ref class HorizontalNoOverflowStackPanel : public Windows::UI::Xaml::Controls::Panel
+ {
+ DEPENDENCY_PROPERTY_OWNER(HorizontalNoOverflowStackPanel);
+ //Prioritize the last item over all other items (except the first one)
+ internal:
+ HorizontalNoOverflowStackPanel() {}
+ protected:
+ virtual Windows::Foundation::Size MeasureOverride(Windows::Foundation::Size availableSize) override;
+ virtual Windows::Foundation::Size ArrangeOverride(Windows::Foundation::Size finalSize) override;
+ virtual bool ShouldPrioritizeLastItem();
+ };
+ }
+}
diff --git a/src/Calculator/Controls/SupplementaryItemsControl.cpp b/src/Calculator/Controls/SupplementaryItemsControl.cpp
index d5bc00a4..665c1d16 100644
--- a/src/Calculator/Controls/SupplementaryItemsControl.cpp
+++ b/src/Calculator/Controls/SupplementaryItemsControl.cpp
@@ -38,5 +38,3 @@ void SupplementaryItemsControl::PrepareContainerForItemOverride(DependencyObject
{
return ref new SupplementaryContentPresenterAP(this);
}
-
-
diff --git a/src/Calculator/Views/SupplementaryResults.xaml b/src/Calculator/Views/SupplementaryResults.xaml
index 9ac6421d..c3db4f40 100644
--- a/src/Calculator/Views/SupplementaryResults.xaml
+++ b/src/Calculator/Views/SupplementaryResults.xaml
@@ -80,7 +80,7 @@
-
+
@@ -102,6 +102,6 @@
Style="{ThemeResource SupplementaryValuesStyle}"
IsTextScaleFactorEnabled="False"
ItemTemplateSelector="{StaticResource ResultTemplateSelector}"
- LayoutUpdated="OnSupplementaryValuesLayoutUpdated"/>
+ ItemsSource="{x:Bind Results, Mode=OneWay}"/>
diff --git a/src/Calculator/Views/SupplementaryResults.xaml.cpp b/src/Calculator/Views/SupplementaryResults.xaml.cpp
index 978df9a3..06c83600 100644
--- a/src/Calculator/Views/SupplementaryResults.xaml.cpp
+++ b/src/Calculator/Views/SupplementaryResults.xaml.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
+// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
//
@@ -27,6 +27,8 @@ using namespace Windows::UI::Xaml::Navigation;
// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236
+DEPENDENCY_PROPERTY_INITIALIZATION(SupplementaryResults, Results);
+
Object^ DelighterUnitToStyleConverter::Convert(Object^ value, TypeName /*targetType*/, Object^ /*parameter*/, String^ /*language*/)
{
Unit^ unit = safe_cast(value);
@@ -62,74 +64,22 @@ Windows::UI::Xaml::DataTemplate^ SupplementaryResultDataTemplateSelector::Select
}
}
-SupplementaryResults::SupplementaryResults() :
- m_data(ref new Vector)
+SupplementaryResults::SupplementaryResults()
{
InitializeComponent();
-
- this->Loaded += ref new RoutedEventHandler(this, &SupplementaryResults::OnLoaded);
}
-void SupplementaryResults::RefreshData()
+bool SupplementaryResultNoOverflowStackPanel::ShouldPrioritizeLastItem()
{
- // Copy the list so that when we chop stuff off, we don't modify the original
- // complete list.
- m_data->Clear();
- for(SupplementaryResult^ sr : safe_cast(this->DataContext)->SupplementaryResults)
+ if (Children->Size == 0)
{
- m_data->Append(sr);
+ return false;
}
-
- // Set as source
- SupplementaryValues->ItemsSource = m_data;
-}
-
-void SupplementaryResults::OnLoaded(Object^ sender, RoutedEventArgs^ e)
-{
- UnitConverterViewModel^ vm = safe_cast(this->DataContext);
- vm->PropertyChanged += ref new PropertyChangedEventHandler(this, &SupplementaryResults::OnConverterPropertyChanged);
- Window::Current->SizeChanged += ref new WindowSizeChangedEventHandler(this, &SupplementaryResults::OnWindowSizeChanged);
- // We may be loaded into a state where we need to render (like rehydrate), so prepare data
- RefreshData();
-}
-
-void SupplementaryResults::OnConverterPropertyChanged(Object^ /*sender*/, PropertyChangedEventArgs^ e)
-{
- if (e->PropertyName == UnitConverterViewModel::SupplementaryResultsPropertyName)
+ auto lastChild = dynamic_cast(Children->GetAt(Children->Size - 1));
+ if (lastChild == nullptr)
{
- RefreshData();
- }
-}
-
-void SupplementaryResults::OnWindowSizeChanged(Platform::Object^ sender, Windows::UI::Core::WindowSizeChangedEventArgs^ e)
-{
- // to reload supplementary results every time the window is resized
- RefreshData();
-}
-
-void SupplementaryResults::OnSupplementaryValuesLayoutUpdated(Platform::Object^ sender, Platform::Object^ e)
-{
- // This means we overflowed and are cutting off, or in a very rare case we fit exactly. Unfortunately
- // the fitting exactly case will still have an item removed, as there is no other way for us to
- // detect that we need to trim.
- Grid^ parentGrid = dynamic_cast(VisualTreeHelper::GetParent(this));
- if (parentGrid != nullptr)
- {
- double parentWidth = parentGrid->ActualWidth;
- if (SupplementaryValues && SupplementaryValues->ActualWidth >= parentWidth)
- {
- if (m_data->Size > 0)
- {
- SupplementaryResult^ last = m_data->GetAt(m_data->Size - 1);
- if (!last->IsWhimsical() || m_data->Size <= 2)
- {
- m_data->RemoveAtEnd();
- }
- else
- {
- m_data->RemoveAt(m_data->Size - 2);
- }
- }
- }
+ return false;
}
+ auto suppResult = dynamic_cast(lastChild->DataContext);
+ return suppResult == nullptr? false: suppResult->IsWhimsical();
}
diff --git a/src/Calculator/Views/SupplementaryResults.xaml.h b/src/Calculator/Views/SupplementaryResults.xaml.h
index 1d94b0ab..a0be9e03 100644
--- a/src/Calculator/Views/SupplementaryResults.xaml.h
+++ b/src/Calculator/Views/SupplementaryResults.xaml.h
@@ -12,6 +12,7 @@
#include "Controls/SupplementaryItemsControl.h"
#include "Controls/OperandTextBox.h"
#include "Controls/OperatorTextBox.h"
+#include "Controls/HorizontalNoOverflowStackPanel.h"
#include "CalcViewModel/UnitConverterViewModel.h"
namespace CalculatorApp
@@ -58,18 +59,18 @@ namespace CalculatorApp
Windows::UI::Xaml::DataTemplate^ m_delighterTemplate;
};
+ public ref class SupplementaryResultNoOverflowStackPanel sealed: public CalculatorApp::Controls::HorizontalNoOverflowStackPanel
+ {
+ protected:
+ virtual bool ShouldPrioritizeLastItem() override;
+ };
+
[Windows::Foundation::Metadata::WebHostHidden]
public ref class SupplementaryResults sealed
{
public:
SupplementaryResults();
-
- private:
- void RefreshData();
- void OnLoaded(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
- void OnConverterPropertyChanged(Platform::Object^ sender, Windows::UI::Xaml::Data::PropertyChangedEventArgs^ e);
- void OnSupplementaryValuesLayoutUpdated(Platform::Object^ sender, Platform::Object^ e);
- void OnWindowSizeChanged(Platform::Object^ sender, Windows::UI::Core::WindowSizeChangedEventArgs^ e);
- Windows::Foundation::Collections::IObservableVector^ m_data;
+ DEPENDENCY_PROPERTY_OWNER(SupplementaryResults);
+ DEPENDENCY_PROPERTY_WITH_DEFAULT(Windows::Foundation::Collections::IIterable^, Results, nullptr);
};
}
diff --git a/src/Calculator/Views/UnitConverter.xaml b/src/Calculator/Views/UnitConverter.xaml
index ab886436..e21dd503 100644
--- a/src/Calculator/Views/UnitConverter.xaml
+++ b/src/Calculator/Views/UnitConverter.xaml
@@ -1,4 +1,4 @@
-
-
+
@@ -651,7 +656,7 @@
-
+
IsActive = false;
}
+
+// The function will make sure the UI will have enough space to display supplementary results and currency information
+void CalculatorApp::UnitConverter::SupplementaryResultsPanelInGrid_SizeChanged(Platform::Object^ sender, Windows::UI::Xaml::SizeChangedEventArgs^ e)
+{
+ //We add 0.01 to be sure to not create an infinite loop with SizeChanged events cascading due to float approximation
+ RowDltrUnits->MinHeight = max(48.0, e->NewSize.Height + 0.01);
+}
diff --git a/src/Calculator/Views/UnitConverter.xaml.h b/src/Calculator/Views/UnitConverter.xaml.h
index b4b84449..df370eaa 100644
--- a/src/Calculator/Views/UnitConverter.xaml.h
+++ b/src/Calculator/Views/UnitConverter.xaml.h
@@ -88,5 +88,6 @@ namespace CalculatorApp
Windows::UI::Xaml::DispatcherTimer^ m_delayTimer;
bool m_isAnimationEnabled;
+ void SupplementaryResultsPanelInGrid_SizeChanged(Platform::Object^ sender, Windows::UI::Xaml::SizeChangedEventArgs^ e);
};
}