Hello GitHub
This commit is contained in:
29
src/Calculator/Controls/AppBar.h
Normal file
29
src/Calculator/Controls/AppBar.h
Normal file
@@ -0,0 +1,29 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Common\KeyboardShortcutManager.h"
|
||||
|
||||
namespace CalculatorApp
|
||||
{
|
||||
namespace Controls
|
||||
{
|
||||
public ref class AppBar sealed : public Windows::UI::Xaml::Controls::AppBar
|
||||
{
|
||||
public:
|
||||
AppBar()
|
||||
{}
|
||||
|
||||
protected:
|
||||
virtual void OnKeyDown(Windows::UI::Xaml::Input::KeyRoutedEventArgs^ e) override
|
||||
{
|
||||
Windows::UI::Xaml::Controls::AppBar::OnKeyDown(e);
|
||||
if (e->Key == Windows::System::VirtualKey::Escape)
|
||||
{
|
||||
Common::KeyboardShortcutManager::IgnoreEscape(true);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
427
src/Calculator/Controls/CalculationResult.cpp
Normal file
427
src/Calculator/Controls/CalculationResult.cpp
Normal file
@@ -0,0 +1,427 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
#include "CalculationResult.h"
|
||||
#include "CalculationResultAutomationPeer.h"
|
||||
#include "CalcViewModel\Common\LocalizationSettings.h"
|
||||
|
||||
using namespace CalculatorApp;
|
||||
using namespace CalculatorApp::Controls;
|
||||
using namespace CalculatorApp::Common;
|
||||
|
||||
using namespace Platform;
|
||||
using namespace Windows::Devices::Input;
|
||||
using namespace Windows::Foundation;
|
||||
using namespace Windows::Foundation::Collections;
|
||||
using namespace Windows::UI::Xaml;
|
||||
using namespace Windows::UI::Xaml::Controls;
|
||||
using namespace Windows::UI::Xaml::Controls::Primitives;
|
||||
using namespace Windows::UI::Xaml::Data;
|
||||
using namespace Windows::UI::Xaml::Input;
|
||||
using namespace Windows::UI::Xaml::Media;
|
||||
using namespace Windows::UI::Xaml::Navigation;
|
||||
using namespace Windows::UI::Xaml::Automation;
|
||||
using namespace Windows::UI::Xaml::Automation::Peers;
|
||||
using namespace std;
|
||||
|
||||
DEPENDENCY_PROPERTY_INITIALIZATION(CalculationResult, IsActive);
|
||||
DEPENDENCY_PROPERTY_INITIALIZATION(CalculationResult, AccentColor);
|
||||
DEPENDENCY_PROPERTY_INITIALIZATION(CalculationResult, MinFontSize);
|
||||
DEPENDENCY_PROPERTY_INITIALIZATION(CalculationResult, DisplayMargin);
|
||||
DEPENDENCY_PROPERTY_INITIALIZATION(CalculationResult, MaxExpressionHistoryCharacters);
|
||||
DEPENDENCY_PROPERTY_INITIALIZATION(CalculationResult, ExpressionVisibility);
|
||||
DEPENDENCY_PROPERTY_INITIALIZATION(CalculationResult, DisplayValue);
|
||||
DEPENDENCY_PROPERTY_INITIALIZATION(CalculationResult, IsInError);
|
||||
DEPENDENCY_PROPERTY_INITIALIZATION(CalculationResult, IsOperatorCommand);
|
||||
DEPENDENCY_PROPERTY_INITIALIZATION(CalculationResult, DisplayStringExpression);
|
||||
|
||||
#define SCALEFACTOR 0.357143
|
||||
#define SMALLHEIGHTSCALEFACTOR 0
|
||||
#define HEIGHTCUTOFF 100
|
||||
#define INCREMENTOFFSET 1
|
||||
#define MAXFONTINCREMENT 5
|
||||
#define WIDTHTOFONTSCALAR 0.0556513
|
||||
#define WIDTHTOFONTOFFSET 3
|
||||
#define WIDTHCUTOFF 50
|
||||
#define FONTTOLERANCE 0.001
|
||||
|
||||
StringReference CalculationResult::s_FocusedState(L"Focused");
|
||||
StringReference CalculationResult::s_UnfocusedState(L"Unfocused");
|
||||
|
||||
CalculationResult::CalculationResult():
|
||||
m_startingFontSize(0.0),
|
||||
m_isScalingText(false),
|
||||
m_haveCalculatedMax(false)
|
||||
{
|
||||
}
|
||||
|
||||
Platform::String^ CalculationResult::GetRawDisplayValue()
|
||||
{
|
||||
std::wstring rawValue;
|
||||
|
||||
LocalizationSettings::GetInstance().RemoveGroupSeparators(DisplayValue->Data(), DisplayValue->Length(), &rawValue);
|
||||
|
||||
return ref new Platform::String(rawValue.c_str());
|
||||
}
|
||||
|
||||
void CalculationResult::OnApplyTemplate()
|
||||
{
|
||||
assert((m_scrollLeft == nullptr && m_scrollRight == nullptr) || (m_scrollLeft != nullptr && m_scrollRight != nullptr));
|
||||
if (m_textContainer)
|
||||
{
|
||||
m_textContainer->LayoutUpdated -= m_textContainerLayoutChangedToken;
|
||||
}
|
||||
m_textContainer = dynamic_cast<ScrollViewer^>(GetTemplateChild("textContainer"));
|
||||
if (m_textContainer)
|
||||
{
|
||||
m_textContainer->SizeChanged += ref new SizeChangedEventHandler(this, &CalculationResult::TextContainerSizeChanged);
|
||||
// We want to know when the size of the container changes so
|
||||
// we can rescale the textbox
|
||||
m_textContainerLayoutChangedToken = m_textContainer->LayoutUpdated += ref new EventHandler<Object^>(this, &CalculationResult::OnTextContainerLayoutUpdated);
|
||||
|
||||
m_textContainer->ChangeView(m_textContainer->ExtentWidth - m_textContainer->ViewportWidth,nullptr,nullptr);
|
||||
m_scrollLeft = dynamic_cast<HyperlinkButton^>(GetTemplateChild("scrollLeft"));
|
||||
m_scrollRight = dynamic_cast<HyperlinkButton^>(GetTemplateChild("scrollRight"));
|
||||
auto borderContainer = dynamic_cast<UIElement^>(GetTemplateChild("border"));
|
||||
if (m_scrollLeft && m_scrollRight)
|
||||
{
|
||||
m_scrollLeft->Click += ref new RoutedEventHandler(this, &CalculationResult::OnScrollClick);
|
||||
m_scrollRight->Click += ref new RoutedEventHandler(this, &CalculationResult::OnScrollClick);
|
||||
borderContainer->PointerEntered += ref new PointerEventHandler(this, &CalculationResult::OnPointerEntered);
|
||||
borderContainer->PointerExited += ref new PointerEventHandler(this, &CalculationResult::OnPointerExited);
|
||||
}
|
||||
m_textBlock = dynamic_cast<TextBlock^>(m_textContainer->FindName("normalOutput"));
|
||||
if (m_textBlock)
|
||||
{
|
||||
m_textBlock->Visibility = ::Visibility::Visible;
|
||||
m_startingFontSize = m_textBlock->FontSize;
|
||||
}
|
||||
}
|
||||
UpdateAllState();
|
||||
VisualStateManager::GoToState(this, s_UnfocusedState, false);
|
||||
}
|
||||
|
||||
void CalculationResult::OnPointerPressed(PointerRoutedEventArgs^ e)
|
||||
{
|
||||
if (m_scrollLeft && m_scrollRight && e->Pointer->PointerDeviceType == PointerDeviceType::Touch)
|
||||
{
|
||||
ShowHideScrollButtons(::Visibility::Collapsed, ::Visibility::Collapsed);
|
||||
}
|
||||
}
|
||||
|
||||
void CalculationResult::OnTextContainerLayoutUpdated(Object^ /*sender*/, Object^ /*e*/)
|
||||
{
|
||||
if (m_isScalingText)
|
||||
{
|
||||
UpdateTextState();
|
||||
}
|
||||
}
|
||||
|
||||
void CalculationResult::TextContainerSizeChanged(Object^ sender, SizeChangedEventArgs^ /*e*/)
|
||||
{
|
||||
UpdateTextState();
|
||||
}
|
||||
|
||||
void CalculationResult::OnIsActivePropertyChanged(bool /*oldValue*/, bool newValue)
|
||||
{
|
||||
UpdateVisualState();
|
||||
}
|
||||
|
||||
void CalculationResult::OnAccentColorPropertyChanged(Brush^ oldValue, Brush^ newValue)
|
||||
{
|
||||
// Force the "Active" transition to happen again
|
||||
if (IsActive)
|
||||
{
|
||||
VisualStateManager::GoToState(this, "Normal", true);
|
||||
VisualStateManager::GoToState(this, "Active", true);
|
||||
}
|
||||
}
|
||||
|
||||
void CalculationResult::OnDisplayValuePropertyChanged(String^ /*oldValue*/, String^ /*newValue*/)
|
||||
{
|
||||
UpdateTextState();
|
||||
}
|
||||
|
||||
void CalculationResult::OnIsInErrorPropertyChanged(bool /*oldValue*/, bool newValue)
|
||||
{
|
||||
// We need to have a good template for this to work
|
||||
if (m_textBlock == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (newValue)
|
||||
{
|
||||
// If there's an error message we need to override the normal display font
|
||||
// with the font appropiate for this language. This is because the error
|
||||
// message is localized and therefore can contain characters that are not
|
||||
// available in the normal font.
|
||||
// We use UIText as the font type because this is the most common font type to use
|
||||
m_textBlock->FontFamily = LocalizationService::GetInstance()->GetLanguageFontFamilyForType(LanguageFontType::UIText);
|
||||
}
|
||||
else
|
||||
{
|
||||
// The error result is no longer an error so we will restore the
|
||||
// value to FontFamily property to the value provided in the style
|
||||
// for the TextBlock in the template.
|
||||
m_textBlock->ClearValue(TextBlock::FontFamilyProperty);
|
||||
}
|
||||
}
|
||||
|
||||
void CalculationResult::UpdateVisualState()
|
||||
{
|
||||
if (IsActive)
|
||||
{
|
||||
VisualStateManager::GoToState(this, "Active", true);
|
||||
}
|
||||
else
|
||||
{
|
||||
VisualStateManager::GoToState(this, "Normal", true);
|
||||
}
|
||||
}
|
||||
|
||||
void CalculationResult::UpdateTextState()
|
||||
{
|
||||
if ((m_textContainer == nullptr) || (m_textBlock == nullptr))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto containerSize = m_textContainer->ActualWidth;
|
||||
String^ oldText = m_textBlock->Text;
|
||||
String^ newText = Utils::LRO + DisplayValue + Utils::PDF;
|
||||
|
||||
//Initiate the scaling operation
|
||||
//UpdateLayout will keep calling us until we make it through the below 2 if-statements
|
||||
if (!m_isScalingText || oldText != newText)
|
||||
{
|
||||
m_textBlock->Text = newText;
|
||||
|
||||
m_isScalingText = true;
|
||||
m_haveCalculatedMax = false;
|
||||
m_textBlock->InvalidateArrange();
|
||||
return;
|
||||
}
|
||||
if (containerSize > 0)
|
||||
{
|
||||
double widthDiff = abs(m_textBlock->ActualWidth - containerSize);
|
||||
double fontSizeChange = INCREMENTOFFSET;
|
||||
|
||||
if (widthDiff > WIDTHCUTOFF)
|
||||
{
|
||||
fontSizeChange = min(max(floor(WIDTHTOFONTSCALAR * widthDiff) - WIDTHTOFONTOFFSET, INCREMENTOFFSET), MAXFONTINCREMENT);
|
||||
}
|
||||
if (m_textBlock->ActualWidth < containerSize && abs(m_textBlock->FontSize - m_startingFontSize) > FONTTOLERANCE && !m_haveCalculatedMax)
|
||||
{
|
||||
ModifyFontAndMargin(m_textBlock, fontSizeChange);
|
||||
m_textBlock->InvalidateArrange();
|
||||
return;
|
||||
}
|
||||
if (fontSizeChange < 5)
|
||||
{
|
||||
m_haveCalculatedMax = true;
|
||||
}
|
||||
if (m_textBlock->ActualWidth >= containerSize && abs(m_textBlock->FontSize - MinFontSize) > FONTTOLERANCE)
|
||||
{
|
||||
ModifyFontAndMargin(m_textBlock, -1 * fontSizeChange);
|
||||
m_textBlock->InvalidateArrange();
|
||||
return;
|
||||
}
|
||||
assert(m_textBlock->FontSize >= MinFontSize && m_textBlock->FontSize <= m_startingFontSize);
|
||||
m_isScalingText = false;
|
||||
if (IsOperatorCommand)
|
||||
{
|
||||
m_textContainer->ChangeView(0.0,nullptr,nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_textContainer->ChangeView(m_textContainer->ExtentWidth - m_textContainer->ViewportWidth,nullptr,nullptr);
|
||||
}
|
||||
|
||||
if (m_scrollLeft && m_scrollRight)
|
||||
{
|
||||
if (m_textBlock->ActualWidth < containerSize)
|
||||
{
|
||||
ShowHideScrollButtons(::Visibility::Collapsed, ::Visibility::Collapsed);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IsOperatorCommand)
|
||||
{
|
||||
ShowHideScrollButtons(::Visibility::Collapsed, ::Visibility::Visible);
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowHideScrollButtons(::Visibility::Visible, ::Visibility::Collapsed);
|
||||
}
|
||||
}
|
||||
}
|
||||
m_textBlock->InvalidateArrange();
|
||||
}
|
||||
}
|
||||
|
||||
void CalculationResult::ScrollLeft()
|
||||
{
|
||||
if (m_textContainer->HorizontalOffset > 0)
|
||||
{
|
||||
double offset = m_textContainer->HorizontalOffset - (scrollRatio * m_textContainer->ViewportWidth);
|
||||
m_textContainer->ChangeView(offset, nullptr, nullptr);
|
||||
m_textContainer->UpdateLayout();
|
||||
UpdateScrollButtons();
|
||||
}
|
||||
}
|
||||
|
||||
void CalculationResult::ScrollRight()
|
||||
{
|
||||
if (m_textContainer->HorizontalOffset < m_textContainer->ExtentWidth - m_textContainer->ViewportWidth)
|
||||
{
|
||||
double offset = m_textContainer->HorizontalOffset + (scrollRatio * m_textContainer->ViewportWidth);
|
||||
m_textContainer->ChangeView(offset, nullptr, nullptr);
|
||||
m_textContainer->UpdateLayout();
|
||||
UpdateScrollButtons();
|
||||
}
|
||||
}
|
||||
|
||||
void CalculationResult::OnKeyDown(KeyRoutedEventArgs^ e)
|
||||
{
|
||||
if (m_scrollLeft != nullptr && m_scrollRight != nullptr)
|
||||
{
|
||||
auto key = e->Key;
|
||||
if (key == Windows::System::VirtualKey::Left)
|
||||
{
|
||||
this->ScrollLeft();
|
||||
}
|
||||
else if (key == Windows::System::VirtualKey::Right)
|
||||
{
|
||||
this->ScrollRight();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CalculationResult::OnScrollClick(Object^ sender, RoutedEventArgs^ /*e*/)
|
||||
{
|
||||
auto clicked = dynamic_cast<HyperlinkButton^>(sender);
|
||||
if (clicked == m_scrollLeft)
|
||||
{
|
||||
this->ScrollLeft();
|
||||
}
|
||||
else
|
||||
{
|
||||
this->ScrollRight();
|
||||
}
|
||||
}
|
||||
|
||||
void CalculationResult::OnPointerEntered(Platform::Object^ sender, PointerRoutedEventArgs^ e)
|
||||
{
|
||||
if (e->Pointer->PointerDeviceType == PointerDeviceType::Mouse && m_textBlock->ActualWidth >= m_textContainer->ActualWidth)
|
||||
{
|
||||
UpdateScrollButtons();
|
||||
}
|
||||
}
|
||||
|
||||
void CalculationResult::ShowHideScrollButtons(::Visibility vLeft, ::Visibility vRight)
|
||||
{
|
||||
m_scrollLeft->Visibility = vLeft;
|
||||
m_scrollRight->Visibility = vRight;
|
||||
}
|
||||
|
||||
void CalculationResult::UpdateScrollButtons()
|
||||
{
|
||||
// When the width is smaller than the container, don't show any
|
||||
if (m_textBlock->ActualWidth < m_textContainer->ActualWidth)
|
||||
{
|
||||
ShowHideScrollButtons(::Visibility::Collapsed, ::Visibility::Collapsed);
|
||||
}
|
||||
// We have more number on both side. Show both arrows
|
||||
else if (m_textContainer->HorizontalOffset > 0 && m_textContainer->HorizontalOffset < (m_textContainer->ExtentWidth - m_textContainer->ViewportWidth))
|
||||
{
|
||||
ShowHideScrollButtons(::Visibility::Visible, ::Visibility::Visible);
|
||||
}
|
||||
// Width is larger than the container and left most part of the number is shown. Should be able to scroll left.
|
||||
else if (m_textContainer->HorizontalOffset == 0)
|
||||
{
|
||||
ShowHideScrollButtons(::Visibility::Collapsed, ::Visibility::Visible);
|
||||
}
|
||||
else // Width is larger than the container and right most part of the number is shown. Should be able to scroll left.
|
||||
{
|
||||
ShowHideScrollButtons(::Visibility::Visible, ::Visibility::Collapsed);
|
||||
}
|
||||
}
|
||||
|
||||
void CalculationResult::OnPointerExited(Platform::Object^ sender, PointerRoutedEventArgs^ e)
|
||||
{
|
||||
if (e->Pointer->PointerDeviceType == PointerDeviceType::Mouse)
|
||||
{
|
||||
UpdateScrollButtons();
|
||||
}
|
||||
}
|
||||
|
||||
void CalculationResult::ModifyFontAndMargin(TextBlock^ textBox, double fontChange)
|
||||
{
|
||||
double cur = textBox->FontSize;
|
||||
double newFontSize = 0.0;
|
||||
Thickness t = textBox->Margin;
|
||||
double scaleFactor = SCALEFACTOR;
|
||||
if (m_textContainer->ActualHeight <= HEIGHTCUTOFF)
|
||||
{
|
||||
scaleFactor = SMALLHEIGHTSCALEFACTOR;
|
||||
}
|
||||
if (fontChange < 0)
|
||||
{
|
||||
newFontSize = max(cur + fontChange, MinFontSize);
|
||||
t.Bottom += scaleFactor * abs(cur - newFontSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
newFontSize = min(cur + fontChange, m_startingFontSize);
|
||||
t.Bottom -= scaleFactor * abs(cur - newFontSize);
|
||||
}
|
||||
textBox->FontSize = newFontSize;
|
||||
textBox->Margin = t;
|
||||
}
|
||||
|
||||
void CalculationResult::UpdateAllState()
|
||||
{
|
||||
UpdateVisualState();
|
||||
UpdateTextState();
|
||||
}
|
||||
|
||||
void CalculationResult::OnTapped(TappedRoutedEventArgs^ e)
|
||||
{
|
||||
this->Focus(::FocusState::Programmatic);
|
||||
RaiseSelectedEvent();
|
||||
}
|
||||
|
||||
void CalculationResult::OnRightTapped(RightTappedRoutedEventArgs^ e)
|
||||
{
|
||||
this->Focus(::FocusState::Programmatic);
|
||||
}
|
||||
|
||||
void CalculationResult::OnGotFocus(RoutedEventArgs^ e)
|
||||
{
|
||||
if (this->FocusState == ::FocusState::Keyboard)
|
||||
{
|
||||
VisualStateManager::GoToState(this, s_FocusedState, true);
|
||||
}
|
||||
}
|
||||
|
||||
void CalculationResult::OnLostFocus(RoutedEventArgs^ e)
|
||||
{
|
||||
VisualStateManager::GoToState(this, s_UnfocusedState, true);
|
||||
}
|
||||
|
||||
AutomationPeer^ CalculationResult::OnCreateAutomationPeer()
|
||||
{
|
||||
return ref new CalculationResultAutomationPeer(this);
|
||||
}
|
||||
|
||||
void CalculationResult::ProgrammaticSelect()
|
||||
{
|
||||
RaiseSelectedEvent();
|
||||
}
|
||||
|
||||
void CalculationResult::RaiseSelectedEvent()
|
||||
{
|
||||
Selected(this);
|
||||
}
|
82
src/Calculator/Controls/CalculationResult.h
Normal file
82
src/Calculator/Controls/CalculationResult.h
Normal file
@@ -0,0 +1,82 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace CalculatorApp
|
||||
{
|
||||
namespace Controls
|
||||
{
|
||||
public delegate void SelectedEventHandler(Platform::Object^ sender);
|
||||
|
||||
public ref class CalculationResult sealed: public Windows::UI::Xaml::Controls::Control
|
||||
{
|
||||
public:
|
||||
CalculationResult();
|
||||
|
||||
DEPENDENCY_PROPERTY_OWNER(CalculationResult);
|
||||
|
||||
DEPENDENCY_PROPERTY(Windows::UI::Xaml::Visibility, ExpressionVisibility);
|
||||
DEPENDENCY_PROPERTY(double, MinFontSize);
|
||||
DEPENDENCY_PROPERTY(Windows::UI::Xaml::Thickness, DisplayMargin);
|
||||
DEPENDENCY_PROPERTY(int, MaxExpressionHistoryCharacters);
|
||||
DEPENDENCY_PROPERTY_WITH_CALLBACK(bool, IsActive);
|
||||
DEPENDENCY_PROPERTY_WITH_CALLBACK(Windows::UI::Xaml::Media::Brush^, AccentColor);
|
||||
DEPENDENCY_PROPERTY_WITH_CALLBACK(Platform::String^, DisplayValue);
|
||||
DEPENDENCY_PROPERTY(Platform::String^, DisplayStringExpression);
|
||||
DEPENDENCY_PROPERTY_WITH_CALLBACK(bool, IsInError);
|
||||
DEPENDENCY_PROPERTY_WITH_DEFAULT(bool, IsOperatorCommand, false);
|
||||
|
||||
event SelectedEventHandler^ Selected;
|
||||
void ProgrammaticSelect();
|
||||
|
||||
internal:
|
||||
void UpdateTextState();
|
||||
Platform::String^ GetRawDisplayValue();
|
||||
|
||||
protected:
|
||||
virtual void OnKeyDown(Windows::UI::Xaml::Input::KeyRoutedEventArgs^ e) override;
|
||||
virtual void OnApplyTemplate() override;
|
||||
virtual void OnTapped(Windows::UI::Xaml::Input::TappedRoutedEventArgs^ e) override;
|
||||
virtual void OnPointerPressed(Windows::UI::Xaml::Input::PointerRoutedEventArgs^ e) override;
|
||||
virtual void OnRightTapped(Windows::UI::Xaml::Input::RightTappedRoutedEventArgs^ e) override;
|
||||
virtual void OnGotFocus(Windows::UI::Xaml::RoutedEventArgs^ e) override;
|
||||
virtual void OnLostFocus(Windows::UI::Xaml::RoutedEventArgs^ e) override;
|
||||
|
||||
virtual Windows::UI::Xaml::Automation::Peers::AutomationPeer^ OnCreateAutomationPeer() override;
|
||||
|
||||
private:
|
||||
void OnIsActivePropertyChanged(bool oldValue, bool newValue);
|
||||
void OnAccentColorPropertyChanged(Windows::UI::Xaml::Media::Brush^ oldValue, Windows::UI::Xaml::Media::Brush^ newValue);
|
||||
void OnDisplayValuePropertyChanged(Platform::String^ oldValue, Platform::String^ newValue);
|
||||
void OnIsInErrorPropertyChanged(bool oldValue, bool newValue);
|
||||
void TextContainerSizeChanged(Object^ sender, Windows::UI::Xaml::SizeChangedEventArgs^ e);
|
||||
void OnTextContainerLayoutUpdated(Object^ sender, Object^ e);
|
||||
void UpdateVisualState();
|
||||
void UpdateAllState();
|
||||
void OnScrollClick(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
|
||||
void OnPointerEntered(Platform::Object^ sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs^ e);
|
||||
void OnPointerExited(Platform::Object^ sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs^ e);
|
||||
void ModifyFontAndMargin(Windows::UI::Xaml::Controls::TextBlock^ textBlock, double fontChange);
|
||||
void ShowHideScrollButtons(Windows::UI::Xaml::Visibility vLeft, Windows::UI::Xaml::Visibility vRight);
|
||||
void UpdateScrollButtons();
|
||||
void ScrollLeft();
|
||||
void ScrollRight();
|
||||
void RaiseSelectedEvent();
|
||||
|
||||
// Visual states for focused
|
||||
static Platform::StringReference s_FocusedState;
|
||||
static Platform::StringReference s_UnfocusedState;
|
||||
|
||||
Windows::UI::Xaml::Controls::ScrollViewer^ m_textContainer;
|
||||
Windows::UI::Xaml::Controls::TextBlock^ m_textBlock;
|
||||
Windows::UI::Xaml::Controls::HyperlinkButton^ m_scrollLeft;
|
||||
Windows::UI::Xaml::Controls::HyperlinkButton^ m_scrollRight;
|
||||
double m_startingFontSize;
|
||||
double scrollRatio = 0.7;
|
||||
bool m_isScalingText;
|
||||
bool m_haveCalculatedMax;
|
||||
Windows::Foundation::EventRegistrationToken m_textContainerLayoutChangedToken;
|
||||
};
|
||||
}
|
||||
}
|
36
src/Calculator/Controls/CalculationResultAutomationPeer.cpp
Normal file
36
src/Calculator/Controls/CalculationResultAutomationPeer.cpp
Normal file
@@ -0,0 +1,36 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
#include "CalculationResultAutomationPeer.h"
|
||||
|
||||
using namespace Windows::UI::Xaml;
|
||||
using namespace Windows::UI::Xaml::Automation::Peers;
|
||||
|
||||
namespace CalculatorApp::Controls
|
||||
{
|
||||
CalculationResultAutomationPeer::CalculationResultAutomationPeer(FrameworkElement^ owner) :
|
||||
FrameworkElementAutomationPeer(owner)
|
||||
{ }
|
||||
|
||||
AutomationControlType CalculationResultAutomationPeer::GetAutomationControlTypeCore()
|
||||
{
|
||||
return AutomationControlType::Text;
|
||||
}
|
||||
|
||||
Platform::Object^ CalculationResultAutomationPeer::GetPatternCore(PatternInterface pattern)
|
||||
{
|
||||
if (pattern == PatternInterface::Invoke)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
return FrameworkElementAutomationPeer::GetPatternCore(pattern);
|
||||
}
|
||||
|
||||
void CalculationResultAutomationPeer::Invoke()
|
||||
{
|
||||
auto owner = static_cast<CalculationResult^>(this->Owner);
|
||||
owner->ProgrammaticSelect();
|
||||
}
|
||||
}
|
23
src/Calculator/Controls/CalculationResultAutomationPeer.h
Normal file
23
src/Calculator/Controls/CalculationResultAutomationPeer.h
Normal file
@@ -0,0 +1,23 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Controls\CalculationResult.h"
|
||||
|
||||
namespace CalculatorApp
|
||||
{
|
||||
namespace Controls
|
||||
{
|
||||
public ref class CalculationResultAutomationPeer sealed : Windows::UI::Xaml::Automation::Peers::FrameworkElementAutomationPeer,
|
||||
Windows::UI::Xaml::Automation::Provider::IInvokeProvider
|
||||
{
|
||||
public:
|
||||
CalculationResultAutomationPeer(Windows::UI::Xaml::FrameworkElement^ owner);
|
||||
|
||||
virtual Windows::UI::Xaml::Automation::Peers::AutomationControlType GetAutomationControlTypeCore() override;
|
||||
virtual Platform::Object^ GetPatternCore(Windows::UI::Xaml::Automation::Peers::PatternInterface pattern) override;
|
||||
virtual void Invoke();
|
||||
};
|
||||
}
|
||||
}
|
68
src/Calculator/Controls/CalculatorButton.cpp
Normal file
68
src/Calculator/Controls/CalculatorButton.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
#include "CalculatorButton.h"
|
||||
#include "CalcViewModel\Common\CalculatorButtonPressedEventArgs.h"
|
||||
|
||||
using namespace CalculatorApp;
|
||||
using namespace CalculatorApp::Common;
|
||||
using namespace CalculatorApp::Controls;
|
||||
using namespace Windows::System;
|
||||
using namespace Windows::UI::Xaml;
|
||||
using namespace Windows::UI::Xaml::Input;
|
||||
using namespace Windows::UI::Xaml::Data;
|
||||
using namespace Platform;
|
||||
using namespace Windows::Foundation::Collections;
|
||||
|
||||
DEPENDENCY_PROPERTY_INITIALIZATION(CalculatorButton, ButtonId);
|
||||
DEPENDENCY_PROPERTY_INITIALIZATION(CalculatorButton, AuditoryFeedback);
|
||||
DEPENDENCY_PROPERTY_INITIALIZATION(CalculatorButton, HoverBackground);
|
||||
DEPENDENCY_PROPERTY_INITIALIZATION(CalculatorButton, HoverForeground);
|
||||
DEPENDENCY_PROPERTY_INITIALIZATION(CalculatorButton, PressBackground);
|
||||
DEPENDENCY_PROPERTY_INITIALIZATION(CalculatorButton, PressForeground);
|
||||
|
||||
CalculatorButton::CalculatorButton()
|
||||
{
|
||||
// Set the default bindings for this button, these can be overwritten by Xaml if needed
|
||||
// These are a replacement for binding in styles
|
||||
Binding^ commandBinding = ref new Binding();
|
||||
commandBinding->Path = ref new PropertyPath("ButtonPressed");
|
||||
this->SetBinding(Button::CommandProperty, commandBinding);
|
||||
}
|
||||
|
||||
void CalculatorButton::OnKeyDown(KeyRoutedEventArgs^ e)
|
||||
{
|
||||
// Ignore the Enter key
|
||||
if (e->Key == VirtualKey::Enter)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Button::OnKeyDown(e);
|
||||
}
|
||||
|
||||
void CalculatorButton::OnKeyUp(KeyRoutedEventArgs^ e)
|
||||
{
|
||||
// Ignore the Enter key
|
||||
if (e->Key == VirtualKey::Enter)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Button::OnKeyUp(e);
|
||||
}
|
||||
|
||||
void CalculatorButton::OnButtonIdPropertyChanged(
|
||||
NumbersAndOperatorsEnum /*oldValue*/,
|
||||
NumbersAndOperatorsEnum newValue)
|
||||
{
|
||||
this->CommandParameter = ref new CalculatorButtonPressedEventArgs(AuditoryFeedback, newValue);
|
||||
}
|
||||
|
||||
void CalculatorButton::OnAuditoryFeedbackPropertyChanged(
|
||||
String^ /*oldValue*/,
|
||||
String^ newValue)
|
||||
{
|
||||
this->CommandParameter = ref new CalculatorButtonPressedEventArgs(newValue, ButtonId);
|
||||
}
|
35
src/Calculator/Controls/CalculatorButton.h
Normal file
35
src/Calculator/Controls/CalculatorButton.h
Normal file
@@ -0,0 +1,35 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace CalculatorApp
|
||||
{
|
||||
namespace Controls
|
||||
{
|
||||
public ref class CalculatorButton sealed: Windows::UI::Xaml::Controls::Button
|
||||
{
|
||||
public:
|
||||
|
||||
CalculatorButton();
|
||||
DEPENDENCY_PROPERTY_OWNER(CalculatorButton);
|
||||
|
||||
DEPENDENCY_PROPERTY_WITH_CALLBACK(NumbersAndOperatorsEnum, ButtonId);
|
||||
DEPENDENCY_PROPERTY_WITH_CALLBACK(Platform::String^, AuditoryFeedback);
|
||||
DEPENDENCY_PROPERTY(Windows::UI::Xaml::Media::Brush^, HoverBackground);
|
||||
DEPENDENCY_PROPERTY(Windows::UI::Xaml::Media::Brush^, HoverForeground);
|
||||
DEPENDENCY_PROPERTY(Windows::UI::Xaml::Media::Brush^, PressBackground);
|
||||
DEPENDENCY_PROPERTY(Windows::UI::Xaml::Media::Brush^, PressForeground);
|
||||
|
||||
protected:
|
||||
|
||||
virtual void OnKeyDown(Windows::UI::Xaml::Input::KeyRoutedEventArgs^ e) override;
|
||||
virtual void OnKeyUp(Windows::UI::Xaml::Input::KeyRoutedEventArgs^ e) override;
|
||||
|
||||
private:
|
||||
|
||||
void OnButtonIdPropertyChanged(NumbersAndOperatorsEnum oldValue, NumbersAndOperatorsEnum newValue);
|
||||
void OnAuditoryFeedbackPropertyChanged(Platform::String^ oldValue, Platform::String^ newValue);
|
||||
};
|
||||
}
|
||||
}
|
51
src/Calculator/Controls/FlipButtons.cpp
Normal file
51
src/Calculator/Controls/FlipButtons.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
#include "FlipButtons.h"
|
||||
|
||||
using namespace CalculatorApp;
|
||||
using namespace CalculatorApp::Controls;
|
||||
using namespace Windows::System;
|
||||
using namespace Windows::UI::Xaml;
|
||||
using namespace Windows::UI::Xaml::Input;
|
||||
using namespace Windows::UI::Xaml::Data;
|
||||
using namespace Platform;
|
||||
using namespace Windows::Foundation::Collections;
|
||||
|
||||
DEPENDENCY_PROPERTY_INITIALIZATION(FlipButtons, ButtonId);
|
||||
DEPENDENCY_PROPERTY_INITIALIZATION(FlipButtons, HoverBackground);
|
||||
DEPENDENCY_PROPERTY_INITIALIZATION(FlipButtons, HoverForeground);
|
||||
DEPENDENCY_PROPERTY_INITIALIZATION(FlipButtons, PressBackground);
|
||||
DEPENDENCY_PROPERTY_INITIALIZATION(FlipButtons, PressForeground);
|
||||
|
||||
|
||||
void FlipButtons::OnKeyDown(KeyRoutedEventArgs^ e)
|
||||
{
|
||||
// Ignore the Enter key
|
||||
if (e->Key == VirtualKey::Enter)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ToggleButton::OnKeyDown(e);
|
||||
}
|
||||
|
||||
void FlipButtons::OnKeyUp(KeyRoutedEventArgs^ e)
|
||||
{
|
||||
// Ignore the Enter key
|
||||
if (e->Key == VirtualKey::Enter)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ToggleButton::OnKeyUp(e);
|
||||
}
|
||||
|
||||
void FlipButtons::OnButtonIdPropertyChanged(
|
||||
NumbersAndOperatorsEnum /*oldValue*/,
|
||||
NumbersAndOperatorsEnum newValue)
|
||||
{
|
||||
this->CommandParameter = newValue;
|
||||
}
|
||||
|
33
src/Calculator/Controls/FlipButtons.h
Normal file
33
src/Calculator/Controls/FlipButtons.h
Normal file
@@ -0,0 +1,33 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace CalculatorApp
|
||||
{
|
||||
namespace Controls
|
||||
{
|
||||
public ref class FlipButtons sealed: Windows::UI::Xaml::Controls::Primitives::ToggleButton
|
||||
{
|
||||
public:
|
||||
DEPENDENCY_PROPERTY_OWNER(FlipButtons);
|
||||
|
||||
DEPENDENCY_PROPERTY_WITH_CALLBACK(NumbersAndOperatorsEnum, ButtonId);
|
||||
DEPENDENCY_PROPERTY(Windows::UI::Xaml::Media::Brush^, HoverBackground);
|
||||
DEPENDENCY_PROPERTY(Windows::UI::Xaml::Media::Brush^, HoverForeground);
|
||||
DEPENDENCY_PROPERTY(Windows::UI::Xaml::Media::Brush^, PressBackground);
|
||||
DEPENDENCY_PROPERTY(Windows::UI::Xaml::Media::Brush^, PressForeground);
|
||||
|
||||
protected:
|
||||
|
||||
virtual void OnKeyDown(Windows::UI::Xaml::Input::KeyRoutedEventArgs^ e) override;
|
||||
virtual void OnKeyUp(Windows::UI::Xaml::Input::KeyRoutedEventArgs^ e) override;
|
||||
|
||||
private:
|
||||
|
||||
void OnButtonIdPropertyChanged(
|
||||
NumbersAndOperatorsEnum oldValue,
|
||||
NumbersAndOperatorsEnum newValue);
|
||||
};
|
||||
}
|
||||
}
|
58
src/Calculator/Controls/OperandTextBox.cpp
Normal file
58
src/Calculator/Controls/OperandTextBox.cpp
Normal file
@@ -0,0 +1,58 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
#include "OperandTextBox.h"
|
||||
#include "regex"
|
||||
|
||||
using namespace CalculatorApp;
|
||||
using namespace CalculatorApp::Controls;
|
||||
|
||||
using namespace Platform;
|
||||
using namespace std;
|
||||
using namespace Windows::Foundation;
|
||||
using namespace Windows::Foundation::Collections;
|
||||
using namespace Windows::Devices::Input;
|
||||
using namespace Windows::System;
|
||||
using namespace Windows::UI::Xaml;
|
||||
using namespace Windows::UI::Xaml::Controls;
|
||||
using namespace Windows::UI::Xaml::Controls::Primitives;
|
||||
using namespace Windows::UI::Xaml::Data;
|
||||
using namespace Windows::UI::Xaml::Input;
|
||||
using namespace Windows::UI::Xaml::Media;
|
||||
using namespace Windows::UI::Xaml::Navigation;
|
||||
|
||||
void OperandTextBox::OnApplyTemplate()
|
||||
{
|
||||
this->IsEnabled = false;
|
||||
this->IsHitTestVisible = false;
|
||||
this->IsTapEnabled = false;
|
||||
this->MaxLength = 50;
|
||||
this->IsRightTapEnabled = false;
|
||||
this->IsTabStop = false;
|
||||
auto parent = VisualTreeHelper::GetParent(this);
|
||||
ListViewItem^ listViewItem;
|
||||
ListView^ listView;
|
||||
while (parent != nullptr)
|
||||
{
|
||||
if (listViewItem == nullptr)
|
||||
{
|
||||
listViewItem = dynamic_cast<ListViewItem^>(parent);
|
||||
}
|
||||
|
||||
listView = dynamic_cast<ListView^>(parent);
|
||||
if (listView != nullptr)
|
||||
{
|
||||
break;
|
||||
}
|
||||
parent = VisualTreeHelper::GetParent(parent);
|
||||
}
|
||||
|
||||
if (listView != nullptr)
|
||||
{
|
||||
listViewItem->IsEnabled = false;
|
||||
listViewItem->IsHitTestVisible = false;
|
||||
listViewItem->IsTapEnabled = false;
|
||||
}
|
||||
TextBox::OnApplyTemplate();
|
||||
}
|
19
src/Calculator/Controls/OperandTextBox.h
Normal file
19
src/Calculator/Controls/OperandTextBox.h
Normal file
@@ -0,0 +1,19 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace CalculatorApp
|
||||
{
|
||||
namespace Controls
|
||||
{
|
||||
public ref class OperandTextBox sealed : public Windows::UI::Xaml::Controls::TextBox
|
||||
{
|
||||
public:
|
||||
OperandTextBox() { }
|
||||
|
||||
protected:
|
||||
virtual void OnApplyTemplate() override;
|
||||
};
|
||||
}
|
||||
}
|
59
src/Calculator/Controls/OperatorTextBox.cpp
Normal file
59
src/Calculator/Controls/OperatorTextBox.cpp
Normal file
@@ -0,0 +1,59 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
#include "OperatorTextBox.h"
|
||||
#include "regex"
|
||||
|
||||
using namespace CalculatorApp;
|
||||
using namespace CalculatorApp::Controls;
|
||||
|
||||
using namespace Platform;
|
||||
using namespace std;
|
||||
using namespace Windows::Foundation;
|
||||
using namespace Windows::Foundation::Collections;
|
||||
using namespace Windows::Devices::Input;
|
||||
using namespace Windows::System;
|
||||
using namespace Windows::UI::Xaml;
|
||||
using namespace Windows::UI::Xaml::Controls;
|
||||
using namespace Windows::UI::Xaml::Controls::Primitives;
|
||||
using namespace Windows::UI::Xaml::Data;
|
||||
using namespace Windows::UI::Xaml::Input;
|
||||
using namespace Windows::UI::Xaml::Media;
|
||||
using namespace Windows::UI::Xaml::Navigation;
|
||||
|
||||
void OperatorTextBox::OnApplyTemplate()
|
||||
{
|
||||
this->IsEnabled = false;
|
||||
this->IsHitTestVisible = false;
|
||||
this->IsTapEnabled = false;
|
||||
this->MaxLength = 50;
|
||||
this->IsReadOnly = true;
|
||||
this->IsRightTapEnabled = false;
|
||||
this->IsTabStop = false;
|
||||
auto parent = VisualTreeHelper::GetParent(this);
|
||||
ListViewItem^ listViewItem;
|
||||
ListView^ listView;
|
||||
while (parent != nullptr)
|
||||
{
|
||||
if (listViewItem == nullptr)
|
||||
{
|
||||
listViewItem = dynamic_cast<ListViewItem^>(parent);
|
||||
}
|
||||
|
||||
listView = dynamic_cast<ListView^>(parent);
|
||||
if (listView != nullptr)
|
||||
{
|
||||
break;
|
||||
}
|
||||
parent = VisualTreeHelper::GetParent(parent);
|
||||
}
|
||||
|
||||
if (listView != nullptr)
|
||||
{
|
||||
listViewItem->IsEnabled = false;
|
||||
listViewItem->IsHitTestVisible = false;
|
||||
listViewItem->IsTapEnabled = false;
|
||||
}
|
||||
TextBox::OnApplyTemplate();
|
||||
}
|
19
src/Calculator/Controls/OperatorTextBox.h
Normal file
19
src/Calculator/Controls/OperatorTextBox.h
Normal file
@@ -0,0 +1,19 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace CalculatorApp
|
||||
{
|
||||
namespace Controls
|
||||
{
|
||||
public ref class OperatorTextBox sealed : public Windows::UI::Xaml::Controls::TextBox
|
||||
{
|
||||
public:
|
||||
OperatorTextBox() { }
|
||||
|
||||
protected:
|
||||
virtual void OnApplyTemplate() override;
|
||||
};
|
||||
}
|
||||
}
|
210
src/Calculator/Controls/OverflowTextBlock.cpp
Normal file
210
src/Calculator/Controls/OverflowTextBlock.cpp
Normal file
@@ -0,0 +1,210 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
#include "OverflowTextBlock.h"
|
||||
#include "OverflowTextBlockAutomationPeer.h"
|
||||
|
||||
using namespace CalculatorApp;
|
||||
using namespace CalculatorApp::Common;
|
||||
using namespace CalculatorApp::Controls;
|
||||
|
||||
using namespace Platform;
|
||||
using namespace std;
|
||||
using namespace Windows::Foundation;
|
||||
using namespace Windows::Foundation::Collections;
|
||||
using namespace Windows::Devices::Input;
|
||||
using namespace Windows::UI::Xaml;
|
||||
using namespace Windows::UI::Xaml::Automation;
|
||||
using namespace Windows::UI::Xaml::Automation::Peers;
|
||||
using namespace Windows::UI::Xaml::Controls;
|
||||
using namespace Windows::UI::Xaml::Controls::Primitives;
|
||||
using namespace Windows::UI::Xaml::Data;
|
||||
using namespace Windows::UI::Xaml::Input;
|
||||
using namespace Windows::UI::Xaml::Media;
|
||||
using namespace Windows::UI::Xaml::Navigation;
|
||||
|
||||
DEPENDENCY_PROPERTY_INITIALIZATION(OverflowTextBlock, IsActive);
|
||||
DEPENDENCY_PROPERTY_INITIALIZATION(OverflowTextBlock, TextStyle);
|
||||
DEPENDENCY_PROPERTY_INITIALIZATION(OverflowTextBlock, TokensUpdated);
|
||||
|
||||
void OverflowTextBlock::OnApplyTemplate()
|
||||
{
|
||||
assert(((m_scrollLeft == nullptr) && (m_scrollRight == nullptr)) || ((m_scrollLeft != nullptr) && (m_scrollRight != nullptr)));
|
||||
|
||||
m_expressionContainer = safe_cast<ScrollViewer^>(GetTemplateChild("expressionContainer"));
|
||||
m_expressionContainer->ChangeView(m_expressionContainer->ExtentWidth - m_expressionContainer->ViewportWidth, nullptr, nullptr);
|
||||
|
||||
m_scrollLeft = safe_cast<Button^>(GetTemplateChild("scrollLeft"));
|
||||
m_scrollRight = safe_cast<Button^>(GetTemplateChild("scrollRight"));
|
||||
|
||||
m_scrollLeftClickEventToken = m_scrollLeft->Click += ref new RoutedEventHandler(this, &OverflowTextBlock::OnScrollClick);
|
||||
m_scrollRightClickEventToken = m_scrollRight->Click += ref new RoutedEventHandler(this, &OverflowTextBlock::OnScrollClick);
|
||||
|
||||
m_scrollingLeft = false;
|
||||
m_scrollingRight = false;
|
||||
|
||||
auto borderContainer = safe_cast<Border^>(GetTemplateChild("expressionborder"));
|
||||
m_pointerEnteredEventToken = borderContainer->PointerEntered += ref new PointerEventHandler(this, &OverflowTextBlock::OnPointerEntered);
|
||||
m_pointerExitedEventToken = borderContainer->PointerExited += ref new PointerEventHandler(this, &OverflowTextBlock::OnPointerExited);
|
||||
|
||||
m_listView = safe_cast<ListView^>(GetTemplateChild("TokenList"));
|
||||
|
||||
UpdateAllState();
|
||||
}
|
||||
|
||||
AutomationPeer^ OverflowTextBlock::OnCreateAutomationPeer()
|
||||
{
|
||||
return ref new OverflowTextBlockAutomationPeer(this);
|
||||
}
|
||||
|
||||
void OverflowTextBlock::OnTokensUpdatedPropertyChanged(bool /*oldValue*/, bool newValue)
|
||||
{
|
||||
if ((m_listView != nullptr) && (newValue))
|
||||
{
|
||||
unsigned int tokenCount = m_listView->Items->Size;
|
||||
if (tokenCount > 0)
|
||||
{
|
||||
m_listView->UpdateLayout();
|
||||
m_listView->ScrollIntoView(m_listView->Items->GetAt(tokenCount - 1));
|
||||
m_expressionContainer->ChangeView(m_expressionContainer->ExtentWidth - m_expressionContainer->ViewportWidth, nullptr, nullptr);
|
||||
}
|
||||
}
|
||||
AutomationProperties::SetAccessibilityView(this,
|
||||
m_listView != nullptr && m_listView->Items->Size > 0 ? AccessibilityView::Control : AccessibilityView::Raw);
|
||||
}
|
||||
|
||||
void OverflowTextBlock::UpdateAllState()
|
||||
{
|
||||
UpdateVisualState();
|
||||
}
|
||||
|
||||
void OverflowTextBlock::UpdateVisualState()
|
||||
{
|
||||
if (IsActive)
|
||||
{
|
||||
VisualStateManager::GoToState(this, "Active", true);
|
||||
}
|
||||
else
|
||||
{
|
||||
VisualStateManager::GoToState(this, "Normal", true);
|
||||
}
|
||||
}
|
||||
|
||||
void OverflowTextBlock::ScrollLeft()
|
||||
{
|
||||
if (m_expressionContainer->HorizontalOffset > 0)
|
||||
{
|
||||
m_scrollingLeft = true;
|
||||
double offset = m_expressionContainer->HorizontalOffset - (scrollRatio * m_expressionContainer->ViewportWidth);
|
||||
m_expressionContainer->ChangeView(offset, nullptr, nullptr);
|
||||
m_expressionContainer->UpdateLayout();
|
||||
UpdateScrollButtons();
|
||||
}
|
||||
}
|
||||
|
||||
void OverflowTextBlock::ScrollRight()
|
||||
{
|
||||
if (m_expressionContainer->HorizontalOffset < m_expressionContainer->ExtentWidth - m_expressionContainer->ViewportWidth)
|
||||
{
|
||||
m_scrollingRight = true;
|
||||
double offset = m_expressionContainer->HorizontalOffset + (scrollRatio * m_expressionContainer->ViewportWidth);
|
||||
m_expressionContainer->ChangeView(offset, nullptr, nullptr);
|
||||
m_expressionContainer->UpdateLayout();
|
||||
UpdateScrollButtons();
|
||||
}
|
||||
}
|
||||
|
||||
void OverflowTextBlock::OnScrollClick(_In_ Object^ sender, _In_ RoutedEventArgs^)
|
||||
{
|
||||
auto clicked = safe_cast<Button^>(sender);
|
||||
if (clicked == m_scrollLeft)
|
||||
{
|
||||
ScrollLeft();
|
||||
}
|
||||
else
|
||||
{
|
||||
ScrollRight();
|
||||
}
|
||||
}
|
||||
|
||||
void OverflowTextBlock::OnPointerEntered(_In_ Object^, _In_ PointerRoutedEventArgs^ e)
|
||||
{
|
||||
if (e->Pointer->PointerDeviceType == PointerDeviceType::Mouse)
|
||||
{
|
||||
UpdateScrollButtons();
|
||||
}
|
||||
}
|
||||
|
||||
void OverflowTextBlock::OnPointerExited(_In_ Object^, _In_ PointerRoutedEventArgs^ e)
|
||||
{
|
||||
if (e->Pointer->PointerDeviceType == PointerDeviceType::Mouse)
|
||||
{
|
||||
UpdateScrollButtons();
|
||||
}
|
||||
}
|
||||
|
||||
void OverflowTextBlock::UpdateScrollButtons()
|
||||
{
|
||||
// When the width is smaller than the container, don't show any
|
||||
if (m_listView->ActualWidth <= m_expressionContainer->ActualWidth)
|
||||
{
|
||||
ShowHideScrollButtons(::Visibility::Collapsed, ::Visibility::Collapsed);
|
||||
}
|
||||
// We have more number on both side. Show both arrows
|
||||
else if ((m_expressionContainer->HorizontalOffset > 0) && (m_expressionContainer->HorizontalOffset < (m_expressionContainer->ExtentWidth - m_expressionContainer->ViewportWidth)))
|
||||
{
|
||||
ShowHideScrollButtons(::Visibility::Visible, ::Visibility::Visible);
|
||||
}
|
||||
// Width is larger than the container and left most part of the number is shown. Should be able to scroll left.
|
||||
else if (m_expressionContainer->HorizontalOffset == 0)
|
||||
{
|
||||
ShowHideScrollButtons(::Visibility::Collapsed, ::Visibility::Visible);
|
||||
if (m_scrollingLeft)
|
||||
{
|
||||
m_scrollingLeft = false;
|
||||
m_scrollRight->Focus(::FocusState::Programmatic);
|
||||
}
|
||||
}
|
||||
else // Width is larger than the container and right most part of the number is shown. Should be able to scroll left.
|
||||
{
|
||||
ShowHideScrollButtons(::Visibility::Visible, ::Visibility::Collapsed);
|
||||
if (m_scrollingRight)
|
||||
{
|
||||
m_scrollingRight = false;
|
||||
m_scrollLeft->Focus(::FocusState::Programmatic);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OverflowTextBlock::ShowHideScrollButtons(::Visibility vLeft, ::Visibility vRight)
|
||||
{
|
||||
if (m_scrollLeft != nullptr && m_scrollRight != nullptr)
|
||||
{
|
||||
m_scrollLeft->Visibility = vLeft;
|
||||
m_scrollRight->Visibility = vRight;
|
||||
}
|
||||
}
|
||||
|
||||
void OverflowTextBlock::UnregisterEventHandlers()
|
||||
{
|
||||
// Unregister the event handlers
|
||||
if (m_scrollLeft != nullptr)
|
||||
{
|
||||
m_scrollLeft->Click -= m_scrollLeftClickEventToken;
|
||||
}
|
||||
|
||||
if (m_scrollRight != nullptr)
|
||||
{
|
||||
m_scrollRight->Click -= m_scrollRightClickEventToken;
|
||||
}
|
||||
|
||||
auto borderContainer = safe_cast<Border^>(GetTemplateChild("expressionborder"));
|
||||
|
||||
// Adding an extra check, incase the returned template is null
|
||||
if (borderContainer != nullptr)
|
||||
{
|
||||
borderContainer->PointerEntered -= m_pointerEnteredEventToken;
|
||||
borderContainer->PointerExited -= m_pointerExitedEventToken;
|
||||
}
|
||||
}
|
56
src/Calculator/Controls/OverflowTextBlock.h
Normal file
56
src/Calculator/Controls/OverflowTextBlock.h
Normal file
@@ -0,0 +1,56 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace CalculatorApp
|
||||
{
|
||||
namespace Controls
|
||||
{
|
||||
public ref class OverflowTextBlock sealed : public Windows::UI::Xaml::Controls::Control
|
||||
{
|
||||
public:
|
||||
OverflowTextBlock()
|
||||
{
|
||||
}
|
||||
|
||||
DEPENDENCY_PROPERTY_OWNER(OverflowTextBlock);
|
||||
|
||||
DEPENDENCY_PROPERTY_WITH_CALLBACK(bool, TokensUpdated);
|
||||
DEPENDENCY_PROPERTY(bool, IsActive);
|
||||
DEPENDENCY_PROPERTY(Windows::UI::Xaml::Style^, TextStyle);
|
||||
void UpdateScrollButtons();
|
||||
void UnregisterEventHandlers();
|
||||
|
||||
protected:
|
||||
virtual void OnApplyTemplate() override;
|
||||
virtual Windows::UI::Xaml::Automation::Peers::AutomationPeer^ OnCreateAutomationPeer() override;
|
||||
|
||||
private:
|
||||
void OnScrollClick(_In_ Platform::Object^ sender, _In_ Windows::UI::Xaml::RoutedEventArgs^ e);
|
||||
void OnPointerEntered(_In_ Platform::Object^ sender, _In_ Windows::UI::Xaml::Input::PointerRoutedEventArgs^ e);
|
||||
void OnPointerExited(_In_ Platform::Object^ sender, _In_ Windows::UI::Xaml::Input::PointerRoutedEventArgs^ e);
|
||||
void ShowHideScrollButtons(Windows::UI::Xaml::Visibility vLeft, Windows::UI::Xaml::Visibility vRight);
|
||||
void OnTokensUpdatedPropertyChanged(bool oldValue, bool newValue);
|
||||
|
||||
void UpdateVisualState();
|
||||
void UpdateExpressionState();
|
||||
void UpdateAllState();
|
||||
void ScrollLeft();
|
||||
void ScrollRight();
|
||||
|
||||
double scrollRatio = 0.7;
|
||||
bool m_scrollingLeft;
|
||||
bool m_scrollingRight;
|
||||
Windows::UI::Xaml::Controls::ListView^ m_listView;
|
||||
Windows::UI::Xaml::Controls::ScrollViewer^ m_expressionContainer;
|
||||
Windows::UI::Xaml::Controls::Button^ m_scrollLeft;
|
||||
Windows::UI::Xaml::Controls::Button^ m_scrollRight;
|
||||
|
||||
Windows::Foundation::EventRegistrationToken m_scrollLeftClickEventToken;
|
||||
Windows::Foundation::EventRegistrationToken m_scrollRightClickEventToken;
|
||||
Windows::Foundation::EventRegistrationToken m_pointerEnteredEventToken;
|
||||
Windows::Foundation::EventRegistrationToken m_pointerExitedEventToken;
|
||||
};
|
||||
}
|
||||
}
|
26
src/Calculator/Controls/OverflowTextBlockAutomationPeer.cpp
Normal file
26
src/Calculator/Controls/OverflowTextBlockAutomationPeer.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
#include "Controls\OverflowTextBlock.h"
|
||||
#include "OverflowTextBlockAutomationPeer.h"
|
||||
|
||||
using namespace Windows::UI::Xaml::Automation::Peers;
|
||||
using namespace Windows::Foundation::Collections;
|
||||
|
||||
namespace CalculatorApp::Controls
|
||||
{
|
||||
OverflowTextBlockAutomationPeer::OverflowTextBlockAutomationPeer(OverflowTextBlock^ owner) :
|
||||
FrameworkElementAutomationPeer(owner)
|
||||
{ }
|
||||
|
||||
AutomationControlType OverflowTextBlockAutomationPeer::GetAutomationControlTypeCore()
|
||||
{
|
||||
return AutomationControlType::Text;
|
||||
}
|
||||
|
||||
IVector<AutomationPeer^>^ OverflowTextBlockAutomationPeer::GetChildrenCore()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
21
src/Calculator/Controls/OverflowTextBlockAutomationPeer.h
Normal file
21
src/Calculator/Controls/OverflowTextBlockAutomationPeer.h
Normal file
@@ -0,0 +1,21 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Controls\OverflowTextBlock.h"
|
||||
|
||||
namespace CalculatorApp
|
||||
{
|
||||
namespace Controls
|
||||
{
|
||||
public ref class OverflowTextBlockAutomationPeer sealed : Windows::UI::Xaml::Automation::Peers::FrameworkElementAutomationPeer
|
||||
{
|
||||
public:
|
||||
OverflowTextBlockAutomationPeer(OverflowTextBlock^ owner);
|
||||
|
||||
virtual Windows::UI::Xaml::Automation::Peers::AutomationControlType GetAutomationControlTypeCore() override;
|
||||
virtual Windows::Foundation::Collections::IVector<Windows::UI::Xaml::Automation::Peers::AutomationPeer^>^ GetChildrenCore() override;
|
||||
};
|
||||
}
|
||||
}
|
25
src/Calculator/Controls/RadixButton.cpp
Normal file
25
src/Calculator/Controls/RadixButton.cpp
Normal file
@@ -0,0 +1,25 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
#include "RadixButton.h"
|
||||
#include "CalcViewModel\Common\LocalizationSettings.h"
|
||||
|
||||
using namespace CalculatorApp;
|
||||
using namespace CalculatorApp::Common;
|
||||
using namespace CalculatorApp::Controls;
|
||||
using namespace Platform;
|
||||
using namespace std;
|
||||
using namespace Windows::Foundation::Collections;
|
||||
using namespace Windows::System;
|
||||
using namespace Windows::UI::Xaml;
|
||||
using namespace Windows::UI::Xaml::Input;
|
||||
using namespace Windows::UI::Xaml::Data;
|
||||
|
||||
String^ RadixButton::GetRawDisplayValue()
|
||||
{
|
||||
wstring rawValue;
|
||||
String^ radixContent = Content->ToString();
|
||||
LocalizationSettings::GetInstance().RemoveGroupSeparators(radixContent->Data(), radixContent->Length(), &rawValue);
|
||||
return ref new String(rawValue.c_str());
|
||||
}
|
18
src/Calculator/Controls/RadixButton.h
Normal file
18
src/Calculator/Controls/RadixButton.h
Normal file
@@ -0,0 +1,18 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace CalculatorApp
|
||||
{
|
||||
namespace Controls
|
||||
{
|
||||
public ref class RadixButton sealed : public Windows::UI::Xaml::Controls::RadioButton
|
||||
{
|
||||
public:
|
||||
RadixButton() {};
|
||||
internal:
|
||||
Platform::String^ GetRawDisplayValue();
|
||||
};
|
||||
}
|
||||
}
|
42
src/Calculator/Controls/SupplementaryItemsControl.cpp
Normal file
42
src/Calculator/Controls/SupplementaryItemsControl.cpp
Normal file
@@ -0,0 +1,42 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
#include "SupplementaryItemsControl.h"
|
||||
#include "CalcViewModel\UnitConverterViewModel.h"
|
||||
|
||||
using namespace CalculatorApp;
|
||||
using namespace CalculatorApp::Controls;
|
||||
using namespace CalculatorApp::ViewModel;
|
||||
using namespace Windows::System;
|
||||
using namespace Windows::UI::Xaml;
|
||||
using namespace Windows::UI::Xaml::Input;
|
||||
using namespace Windows::UI::Xaml::Data;
|
||||
using namespace Windows::UI::Xaml::Automation;
|
||||
using namespace Windows::UI::Xaml::Automation::Peers;
|
||||
using namespace Platform;
|
||||
using namespace Windows::Foundation::Collections;
|
||||
using namespace std;
|
||||
|
||||
DependencyObject^ SupplementaryItemsControl::GetContainerForItemOverride()
|
||||
{
|
||||
return ref new SupplementaryContentPresenter();
|
||||
}
|
||||
|
||||
void SupplementaryItemsControl::PrepareContainerForItemOverride(DependencyObject^ element, Object^ item)
|
||||
{
|
||||
ItemsControl::PrepareContainerForItemOverride(element, item);
|
||||
|
||||
auto supplementaryResult = dynamic_cast<SupplementaryResult^>(item);
|
||||
if (supplementaryResult)
|
||||
{
|
||||
AutomationProperties::SetName(element, supplementaryResult->GetLocalizedAutomationName());
|
||||
}
|
||||
}
|
||||
|
||||
AutomationPeer^ SupplementaryContentPresenter::OnCreateAutomationPeer()
|
||||
{
|
||||
return ref new SupplementaryContentPresenterAP(this);
|
||||
}
|
||||
|
||||
|
47
src/Calculator/Controls/SupplementaryItemsControl.h
Normal file
47
src/Calculator/Controls/SupplementaryItemsControl.h
Normal file
@@ -0,0 +1,47 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace CalculatorApp { namespace Controls {
|
||||
|
||||
public ref class SupplementaryItemsControl sealed: public Windows::UI::Xaml::Controls::ItemsControl
|
||||
{
|
||||
public:
|
||||
SupplementaryItemsControl()
|
||||
{ }
|
||||
|
||||
protected:
|
||||
virtual Windows::UI::Xaml::DependencyObject^ GetContainerForItemOverride() override;
|
||||
virtual void PrepareContainerForItemOverride(Windows::UI::Xaml::DependencyObject^ element, Platform::Object^ item) override;
|
||||
};
|
||||
|
||||
public ref class SupplementaryContentPresenter sealed: public Windows::UI::Xaml::Controls::ContentPresenter
|
||||
{
|
||||
public:
|
||||
SupplementaryContentPresenter()
|
||||
{ }
|
||||
|
||||
protected:
|
||||
virtual Windows::UI::Xaml::Automation::Peers::AutomationPeer^ OnCreateAutomationPeer() override;
|
||||
};
|
||||
|
||||
ref class SupplementaryContentPresenterAP sealed: public Windows::UI::Xaml::Automation::Peers::FrameworkElementAutomationPeer
|
||||
{
|
||||
protected:
|
||||
virtual Windows::UI::Xaml::Automation::Peers::AutomationControlType GetAutomationControlTypeCore() override
|
||||
{
|
||||
return Windows::UI::Xaml::Automation::Peers::AutomationControlType::Text;
|
||||
}
|
||||
|
||||
virtual Windows::Foundation::Collections::IVector<Windows::UI::Xaml::Automation::Peers::AutomationPeer^>^ GetChildrenCore() override
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
internal:
|
||||
SupplementaryContentPresenterAP(SupplementaryContentPresenter^ owner):
|
||||
Windows::UI::Xaml::Automation::Peers::FrameworkElementAutomationPeer(owner)
|
||||
{ }
|
||||
};
|
||||
}}
|
Reference in New Issue
Block a user