Update Calculator keyboard for greater consistency and extensibility (#688)
This commit is contained in:
44
src/Calculator/Controls/OperatorPanelButton.cpp
Normal file
44
src/Calculator/Controls/OperatorPanelButton.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
#include "OperatorPanelButton.h"
|
||||
|
||||
using namespace Platform;
|
||||
using namespace Windows::Foundation;
|
||||
using namespace Windows::UI::ViewManagement;
|
||||
using namespace Windows::UI::Xaml;
|
||||
using namespace Windows::UI::Xaml::Controls;
|
||||
using namespace Windows::UI::Xaml::Media;
|
||||
using namespace CalculatorApp;
|
||||
using namespace CalculatorApp::Common;
|
||||
using namespace CalculatorApp::Controls;
|
||||
|
||||
DEPENDENCY_PROPERTY_INITIALIZATION(OperatorPanelButton, Text);
|
||||
DEPENDENCY_PROPERTY_INITIALIZATION(OperatorPanelButton, Glyph);
|
||||
DEPENDENCY_PROPERTY_INITIALIZATION(OperatorPanelButton, GlyphFontSize);
|
||||
DEPENDENCY_PROPERTY_INITIALIZATION(OperatorPanelButton, ChevronFontSize);
|
||||
DEPENDENCY_PROPERTY_INITIALIZATION(OperatorPanelButton, FlyoutMenu);
|
||||
|
||||
void OperatorPanelButton::OnApplyTemplate()
|
||||
{
|
||||
if (FlyoutMenu != nullptr)
|
||||
{
|
||||
FlyoutMenu->Closed += ref new EventHandler<Object ^>(this, &OperatorPanelButton::FlyoutClosed);
|
||||
}
|
||||
}
|
||||
|
||||
void OperatorPanelButton::OnToggle()
|
||||
{
|
||||
ToggleButton::OnToggle();
|
||||
|
||||
if (IsChecked)
|
||||
{
|
||||
FlyoutMenu->ShowAt(this);
|
||||
}
|
||||
}
|
||||
|
||||
void OperatorPanelButton::FlyoutClosed(Object ^ sender, Object ^ args)
|
||||
{
|
||||
IsChecked = false;
|
||||
}
|
36
src/Calculator/Controls/OperatorPanelButton.h
Normal file
36
src/Calculator/Controls/OperatorPanelButton.h
Normal file
@@ -0,0 +1,36 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CalcViewModel/Common/Utils.h"
|
||||
|
||||
namespace CalculatorApp
|
||||
{
|
||||
namespace Controls
|
||||
{
|
||||
public
|
||||
ref class OperatorPanelButton sealed : Windows::UI::Xaml::Controls::Primitives::ToggleButton
|
||||
{
|
||||
public:
|
||||
OperatorPanelButton()
|
||||
{
|
||||
}
|
||||
|
||||
DEPENDENCY_PROPERTY_OWNER(OperatorPanelButton);
|
||||
|
||||
DEPENDENCY_PROPERTY(Platform::String^, Text);
|
||||
DEPENDENCY_PROPERTY(Platform::String^, Glyph);
|
||||
DEPENDENCY_PROPERTY(double, GlyphFontSize);
|
||||
DEPENDENCY_PROPERTY(double, ChevronFontSize);
|
||||
DEPENDENCY_PROPERTY(Windows::UI::Xaml::Controls::Flyout^, FlyoutMenu);
|
||||
|
||||
protected:
|
||||
virtual void OnApplyTemplate() override;
|
||||
virtual void OnToggle() override;
|
||||
|
||||
private:
|
||||
void FlyoutClosed(Platform::Object^ sender, Platform::Object^ args);
|
||||
};
|
||||
}
|
||||
}
|
147
src/Calculator/Controls/OperatorPanelListView.cpp
Normal file
147
src/Calculator/Controls/OperatorPanelListView.cpp
Normal file
@@ -0,0 +1,147 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
#include "OperatorPanelListView.h"
|
||||
|
||||
using namespace CalculatorApp;
|
||||
using namespace CalculatorApp::Controls;
|
||||
|
||||
using namespace Platform;
|
||||
using namespace std;
|
||||
using namespace Windows::Foundation;
|
||||
using namespace Windows::Devices::Input;
|
||||
using namespace Windows::UI::Xaml;
|
||||
using namespace Windows::UI::Xaml::Input;
|
||||
using namespace Windows::UI::Xaml::Controls;
|
||||
|
||||
OperatorPanelListView::OperatorPanelListView()
|
||||
{
|
||||
}
|
||||
|
||||
void OperatorPanelListView::OnApplyTemplate()
|
||||
{
|
||||
m_scrollViewer = dynamic_cast<ScrollViewer^>(GetTemplateChild("ScrollViewer"));
|
||||
m_scrollLeft = dynamic_cast<Button^>(GetTemplateChild("ScrollLeft"));
|
||||
m_scrollRight = dynamic_cast<Button^>(GetTemplateChild("ScrollRight"));
|
||||
m_content = dynamic_cast<ItemsPresenter^>(GetTemplateChild("Content"));
|
||||
|
||||
if (m_scrollLeft != nullptr)
|
||||
{
|
||||
m_scrollLeft->Click += ref new RoutedEventHandler(this, &OperatorPanelListView::OnScrollClick);
|
||||
m_scrollLeft->PointerExited += ref new PointerEventHandler(this, &OperatorPanelListView::OnButtonPointerExited);
|
||||
}
|
||||
|
||||
if (m_scrollRight != nullptr)
|
||||
{
|
||||
m_scrollRight->Click += ref new RoutedEventHandler(this, &OperatorPanelListView::OnScrollClick);
|
||||
m_scrollRight->PointerExited += ref new PointerEventHandler(this, &OperatorPanelListView::OnButtonPointerExited);
|
||||
}
|
||||
|
||||
if (m_scrollViewer != nullptr)
|
||||
{
|
||||
m_scrollViewer->ViewChanged += ref new EventHandler<ScrollViewerViewChangedEventArgs^>(this, &OperatorPanelListView::ScrollViewChanged);
|
||||
}
|
||||
|
||||
this->PointerEntered += ref new PointerEventHandler(this, &OperatorPanelListView::OnPointerEntered);
|
||||
this->PointerExited += ref new PointerEventHandler(this, &OperatorPanelListView::OnPointerExited);
|
||||
|
||||
ListView::OnApplyTemplate();
|
||||
}
|
||||
|
||||
void OperatorPanelListView::ScrollViewChanged(_In_ Object^, _In_ ScrollViewerViewChangedEventArgs^ e)
|
||||
{
|
||||
if (m_isPointerEntered && !e->IsIntermediate)
|
||||
{
|
||||
UpdateScrollButtons();
|
||||
}
|
||||
}
|
||||
|
||||
void OperatorPanelListView::OnScrollClick(_In_ Object^ sender, _In_ RoutedEventArgs^)
|
||||
{
|
||||
auto clicked = dynamic_cast<Button^>(sender);
|
||||
if (clicked == m_scrollLeft)
|
||||
{
|
||||
ScrollLeft();
|
||||
}
|
||||
else
|
||||
{
|
||||
ScrollRight();
|
||||
}
|
||||
}
|
||||
|
||||
void OperatorPanelListView::OnButtonPointerExited(_In_ Object^ sender, _In_ PointerRoutedEventArgs^ e)
|
||||
{
|
||||
auto button = dynamic_cast<Button^>(sender);
|
||||
|
||||
// Do not bubble up the pointer exit event to the control if the button being exited was not visible
|
||||
if (button->Visibility == ::Visibility::Collapsed)
|
||||
{
|
||||
e->Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
void OperatorPanelListView::OnPointerEntered(_In_ Object^ sender, _In_ PointerRoutedEventArgs^ e)
|
||||
{
|
||||
if (e->Pointer->PointerDeviceType == PointerDeviceType::Mouse)
|
||||
{
|
||||
UpdateScrollButtons();
|
||||
m_isPointerEntered = true;
|
||||
}
|
||||
}
|
||||
|
||||
void OperatorPanelListView::OnPointerExited(_In_ Object^ sender, _In_ PointerRoutedEventArgs^ e)
|
||||
{
|
||||
m_scrollLeft->Visibility = ::Visibility::Collapsed;
|
||||
m_scrollRight->Visibility = ::Visibility::Collapsed;
|
||||
m_isPointerEntered = false;
|
||||
}
|
||||
|
||||
void OperatorPanelListView::ScrollLeft()
|
||||
{
|
||||
double offset = m_scrollViewer->HorizontalOffset - (scrollRatio * m_scrollViewer->ViewportWidth);
|
||||
m_scrollViewer->ChangeView(offset, nullptr, nullptr);
|
||||
}
|
||||
|
||||
void OperatorPanelListView::ScrollRight()
|
||||
{
|
||||
double offset = m_scrollViewer->HorizontalOffset + (scrollRatio * m_scrollViewer->ViewportWidth);
|
||||
m_scrollViewer->ChangeView(offset, nullptr, nullptr);
|
||||
}
|
||||
|
||||
void OperatorPanelListView::UpdateScrollButtons()
|
||||
{
|
||||
if (m_content == nullptr || m_scrollViewer == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// When the width is smaller than the container, don't show any
|
||||
if (m_content->ActualWidth <= m_scrollViewer->ActualWidth)
|
||||
{
|
||||
ShowHideScrollButtons(::Visibility::Collapsed, ::Visibility::Collapsed);
|
||||
}
|
||||
// We have more number on both side. Show both arrows
|
||||
else if ((m_scrollViewer->HorizontalOffset > 0) && (m_scrollViewer->HorizontalOffset < (m_scrollViewer->ExtentWidth - m_scrollViewer->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_scrollViewer->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 OperatorPanelListView::ShowHideScrollButtons(::Visibility vLeft, ::Visibility vRight)
|
||||
{
|
||||
if (m_scrollLeft != nullptr && m_scrollRight != nullptr)
|
||||
{
|
||||
m_scrollLeft->Visibility = vLeft;
|
||||
m_scrollRight->Visibility = vRight;
|
||||
}
|
||||
}
|
43
src/Calculator/Controls/OperatorPanelListView.h
Normal file
43
src/Calculator/Controls/OperatorPanelListView.h
Normal file
@@ -0,0 +1,43 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CalcViewModel/Common/Utils.h"
|
||||
|
||||
namespace CalculatorApp
|
||||
{
|
||||
namespace Controls
|
||||
{
|
||||
public
|
||||
ref class OperatorPanelListView sealed : public Windows::UI::Xaml::Controls::ListView
|
||||
{
|
||||
public:
|
||||
OperatorPanelListView();
|
||||
|
||||
protected:
|
||||
virtual void OnApplyTemplate() 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 OnButtonPointerExited(_In_ Platform::Object^ sender, _In_ Windows::UI::Xaml::Input::PointerRoutedEventArgs^ e);
|
||||
void ScrollViewChanged(_In_ Platform::Object^ sender, _In_ Windows::UI::Xaml::Controls::ScrollViewerViewChangedEventArgs^ args);
|
||||
void ShowHideScrollButtons(Windows::UI::Xaml::Visibility vLeft, Windows::UI::Xaml::Visibility vRight);
|
||||
void UpdateScrollButtons();
|
||||
|
||||
void ScrollLeft();
|
||||
void ScrollRight();
|
||||
|
||||
double scrollRatio = 0.7;
|
||||
|
||||
bool m_isPointerEntered;
|
||||
|
||||
Windows::UI::Xaml::Controls::ItemsPresenter^ m_content;
|
||||
Windows::UI::Xaml::Controls::ScrollViewer^ m_scrollViewer;
|
||||
Windows::UI::Xaml::Controls::Button^ m_scrollLeft;
|
||||
Windows::UI::Xaml::Controls::Button^ m_scrollRight;
|
||||
};
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user