Merge remote-tracking branch 'upstream/master' into mergeFeature
This commit is contained in:
@@ -83,16 +83,6 @@ App::App()
|
||||
#endif
|
||||
}
|
||||
|
||||
bool App::m_isAnimationEnabled = true;
|
||||
|
||||
/// <summary>
|
||||
/// Return True if animation is enabled by user setting.
|
||||
/// </summary>
|
||||
bool App::IsAnimationEnabled()
|
||||
{
|
||||
return App::m_isAnimationEnabled;
|
||||
}
|
||||
|
||||
void App::AddWindowToMap(_In_ WindowFrameService ^ frameService)
|
||||
{
|
||||
reader_writer_lock::scoped_lock lock(m_windowsMapLock);
|
||||
@@ -218,9 +208,6 @@ void App::OnAppLaunch(IActivatedEventArgs ^ args, String ^ argument)
|
||||
// }
|
||||
//#endif
|
||||
|
||||
auto userSettings = ref new Windows::UI::ViewManagement::UISettings();
|
||||
m_isAnimationEnabled = userSettings->AnimationsEnabled;
|
||||
|
||||
args->SplashScreen->Dismissed += ref new TypedEventHandler<SplashScreen ^, Object ^>(this, &App::DismissedEventHandler);
|
||||
|
||||
auto rootFrame = dynamic_cast<Frame ^>(Window::Current->Content);
|
||||
|
@@ -29,8 +29,7 @@ namespace CalculatorApp
|
||||
virtual void OnLaunched(Windows::ApplicationModel::Activation::LaunchActivatedEventArgs ^ args) override;
|
||||
virtual void OnActivated(Windows::ApplicationModel::Activation::IActivatedEventArgs ^ args) override;
|
||||
|
||||
internal :
|
||||
static bool IsAnimationEnabled();
|
||||
internal:
|
||||
void RemoveWindow(_In_ WindowFrameService ^ frameService);
|
||||
void RemoveSecondaryWindow(_In_ WindowFrameService ^ frameService);
|
||||
|
||||
@@ -88,7 +87,5 @@ namespace CalculatorApp
|
||||
bool m_preLaunched;
|
||||
|
||||
Windows::UI::Xaml::Controls::Primitives::Popup ^ m_aboutPopup;
|
||||
|
||||
static bool m_isAnimationEnabled;
|
||||
};
|
||||
}
|
||||
|
@@ -236,11 +236,13 @@
|
||||
<DependentUpon>AboutFlyout.xaml</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Common\AppLifecycleLogger.h" />
|
||||
<ClInclude Include="Common\KeyboardShortcutManager.h" />
|
||||
<ClInclude Include="Common\ValidatingConverters.h" />
|
||||
<ClInclude Include="Common\ViewState.h" />
|
||||
<ClInclude Include="Controls\CalculationResultAutomationPeer.h" />
|
||||
<ClInclude Include="Controls\MathRichEditBox.h" />
|
||||
<ClInclude Include="Controls\OverflowTextBlockAutomationPeer.h" />
|
||||
<ClInclude Include="Common\AlwaysSelectedCollectionView.h" />
|
||||
<ClInclude Include="Common\BindableBase.h" />
|
||||
<ClInclude Include="Controls\CalculationResult.h" />
|
||||
<ClInclude Include="Controls\CalculatorButton.h" />
|
||||
<ClInclude Include="Controls\FlipButtons.h" />
|
||||
@@ -399,10 +401,11 @@
|
||||
<DependentUpon>App.xaml</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Common\AppLifecycleLogger.cpp" />
|
||||
<ClCompile Include="Common\KeyboardShortcutManager.cpp" />
|
||||
<ClCompile Include="Common\ViewState.cpp" />
|
||||
<ClCompile Include="Controls\CalculationResultAutomationPeer.cpp" />
|
||||
<ClCompile Include="Controls\MathRichEditBox.cpp" />
|
||||
<ClCompile Include="Controls\OverflowTextBlockAutomationPeer.cpp" />
|
||||
<ClCompile Include="Common\BindableBase.cpp" />
|
||||
<ClCompile Include="Controls\CalculationResult.cpp" />
|
||||
<ClCompile Include="Controls\CalculatorButton.cpp" />
|
||||
<ClCompile Include="Controls\FlipButtons.cpp" />
|
||||
|
@@ -231,9 +231,6 @@
|
||||
<ItemGroup>
|
||||
<ClCompile Include="App.xaml.cpp" />
|
||||
<ClCompile Include="pch.cpp" />
|
||||
<ClCompile Include="Common\BindableBase.cpp">
|
||||
<Filter>Common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Controls\CalculationResult.cpp">
|
||||
<Filter>Controls</Filter>
|
||||
</ClCompile>
|
||||
@@ -327,6 +324,10 @@
|
||||
<ClCompile Include="Utils\VisualTree.cpp">
|
||||
<Filter>Utils</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Common\KeyboardShortcutManager.cpp">
|
||||
<Filter>Common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Common\ViewState.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h" />
|
||||
@@ -334,9 +335,6 @@
|
||||
<ClInclude Include="Common\AlwaysSelectedCollectionView.h">
|
||||
<Filter>Common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Common\BindableBase.h">
|
||||
<Filter>Common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Controls\CalculationResult.h">
|
||||
<Filter>Controls</Filter>
|
||||
</ClInclude>
|
||||
@@ -430,6 +428,13 @@
|
||||
<ClInclude Include="Utils\VisualTree.h">
|
||||
<Filter>Utils</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Common\KeyboardShortcutManager.h">
|
||||
<Filter>Common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Common\ValidatingConverters.h">
|
||||
<Filter>Common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Common\ViewState.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AppxManifest Include="Package.appxmanifest" />
|
||||
@@ -515,6 +520,7 @@
|
||||
<Page Include="Views\GraphingCalculator\GraphingNumPad.xaml">
|
||||
<Filter>Views\GraphingCalculator</Filter>
|
||||
</Page>
|
||||
<Page Include="$(MSBuildThisFileDirectory)DensityStyles\Compact.xaml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PRIResource Include="Resources\en-US\CEngineStrings.resw">
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
#include "pch.h"
|
||||
#include "AppLifecycleLogger.h"
|
||||
#include "CalcViewModel/Common/TraceActivity.h"
|
||||
#include <winmeta.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace winrt;
|
||||
|
@@ -1,34 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
#include "BindableBase.h"
|
||||
|
||||
using namespace CalculatorApp::Common;
|
||||
|
||||
using namespace Platform;
|
||||
using namespace Windows::UI::Xaml::Data;
|
||||
|
||||
/// <summary>
|
||||
/// Notifies listeners that a property value has changed.
|
||||
/// </summary>
|
||||
/// <param name="propertyName">Name of the property used to notify listeners.</param>
|
||||
void BindableBase::OnPropertyChanged(String ^ propertyName)
|
||||
{
|
||||
PropertyChanged(this, ref new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
|
||||
Windows::UI::Xaml::Data::ICustomProperty ^ BindableBase::GetCustomProperty(Platform::String ^ name)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Windows::UI::Xaml::Data::ICustomProperty ^ BindableBase::GetIndexedProperty(Platform::String ^ name, Windows::UI::Xaml::Interop::TypeName type)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Platform::String ^ BindableBase::GetStringRepresentation()
|
||||
{
|
||||
return this->ToString();
|
||||
}
|
@@ -1,38 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace CalculatorApp
|
||||
{
|
||||
namespace Common
|
||||
{
|
||||
/// <summary>
|
||||
/// Implementation of <see cref="INotifyPropertyChanged"/> to simplify models.
|
||||
/// </summary>
|
||||
[Windows::Foundation::Metadata::WebHostHidden] public ref class BindableBase : Windows::UI::Xaml::DependencyObject,
|
||||
Windows::UI::Xaml::Data::INotifyPropertyChanged,
|
||||
Windows::UI::Xaml::Data::ICustomPropertyProvider
|
||||
{
|
||||
public:
|
||||
virtual event Windows::UI::Xaml::Data::PropertyChangedEventHandler ^ PropertyChanged;
|
||||
|
||||
public:
|
||||
// ICustomPropertyProvider
|
||||
virtual Windows::UI::Xaml::Data::ICustomProperty ^ GetCustomProperty(Platform::String ^ name);
|
||||
virtual Windows::UI::Xaml::Data::ICustomProperty ^ GetIndexedProperty(Platform::String ^ name, Windows::UI::Xaml::Interop::TypeName type);
|
||||
virtual Platform::String ^ GetStringRepresentation();
|
||||
|
||||
property Windows::UI::Xaml::Interop::TypeName Type
|
||||
{
|
||||
virtual Windows::UI::Xaml::Interop::TypeName get()
|
||||
{
|
||||
return this->GetType();
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void OnPropertyChanged(Platform::String ^ propertyName);
|
||||
};
|
||||
}
|
||||
}
|
823
src/Calculator/Common/KeyboardShortcutManager.cpp
Normal file
823
src/Calculator/Common/KeyboardShortcutManager.cpp
Normal file
@@ -0,0 +1,823 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
#include "KeyboardShortcutManager.h"
|
||||
#include "CalcViewModel/Common/AppResourceProvider.h"
|
||||
#include "CalcViewModel/ApplicationViewModel.h"
|
||||
#include "CalcViewModel/Common/LocalizationSettings.h"
|
||||
|
||||
using namespace Concurrency;
|
||||
using namespace Platform;
|
||||
using namespace std;
|
||||
using namespace std::chrono;
|
||||
using namespace Windows::ApplicationModel::Resources;
|
||||
using namespace Windows::UI::Xaml;
|
||||
using namespace Windows::UI::Xaml::Controls;
|
||||
using namespace Windows::Foundation;
|
||||
using namespace Windows::Foundation::Collections;
|
||||
using namespace Windows::UI::Core;
|
||||
using namespace Windows::UI::Xaml::Controls::Primitives;
|
||||
using namespace Windows::System;
|
||||
using namespace Utils;
|
||||
using namespace CalculatorApp;
|
||||
using namespace CalculatorApp::Common;
|
||||
using namespace CalculatorApp::ViewModel;
|
||||
|
||||
namespace MUXC = Microsoft::UI::Xaml::Controls;
|
||||
|
||||
DEPENDENCY_PROPERTY_INITIALIZATION(KeyboardShortcutManager, Character);
|
||||
DEPENDENCY_PROPERTY_INITIALIZATION(KeyboardShortcutManager, VirtualKey);
|
||||
DEPENDENCY_PROPERTY_INITIALIZATION(KeyboardShortcutManager, VirtualKeyControlChord);
|
||||
DEPENDENCY_PROPERTY_INITIALIZATION(KeyboardShortcutManager, VirtualKeyShiftChord);
|
||||
DEPENDENCY_PROPERTY_INITIALIZATION(KeyboardShortcutManager, VirtualKeyAltChord);
|
||||
DEPENDENCY_PROPERTY_INITIALIZATION(KeyboardShortcutManager, VirtualKeyControlShiftChord);
|
||||
DEPENDENCY_PROPERTY_INITIALIZATION(KeyboardShortcutManager, VirtualKeyInverseChord);
|
||||
DEPENDENCY_PROPERTY_INITIALIZATION(KeyboardShortcutManager, VirtualKeyControlInverseChord);
|
||||
|
||||
static multimap<int, multimap<wchar_t, WeakReference>> s_CharacterForButtons;
|
||||
static multimap<int, multimap<MyVirtualKey, WeakReference>> s_VirtualKeysForButtons;
|
||||
static multimap<int, multimap<MyVirtualKey, WeakReference>> s_VirtualKeyControlChordsForButtons;
|
||||
static multimap<int, multimap<MyVirtualKey, WeakReference>> s_VirtualKeyShiftChordsForButtons;
|
||||
static multimap<int, multimap<MyVirtualKey, WeakReference>> s_VirtualKeyAltChordsForButtons;
|
||||
static multimap<int, multimap<MyVirtualKey, WeakReference>> s_VirtualKeyControlShiftChordsForButtons;
|
||||
static multimap<int, multimap<MyVirtualKey, WeakReference>> s_VirtualKeyInverseChordsForButtons;
|
||||
static multimap<int, multimap<MyVirtualKey, WeakReference>> s_VirtualKeyControlInverseChordsForButtons;
|
||||
|
||||
static map<int, bool> s_ShiftKeyPressed;
|
||||
static map<int, bool> s_ControlKeyPressed;
|
||||
static map<int, bool> s_ShiftButtonChecked;
|
||||
static map<int, bool> s_IsDropDownOpen;
|
||||
|
||||
static map<int, bool> s_ignoreNextEscape;
|
||||
static map<int, bool> s_keepIgnoringEscape;
|
||||
static map<int, bool> s_fHonorShortcuts;
|
||||
static map<int, Flyout ^> s_AboutFlyout;
|
||||
|
||||
static reader_writer_lock s_keyboardShortcutMapLock;
|
||||
|
||||
namespace CalculatorApp
|
||||
{
|
||||
namespace Common
|
||||
{
|
||||
// Lights up all of the buttons in the given range
|
||||
// The range is defined by a pair of iterators
|
||||
template <typename T>
|
||||
void LightUpButtons(const T& buttons)
|
||||
{
|
||||
auto iterator = buttons.first;
|
||||
for (; iterator != buttons.second; ++iterator)
|
||||
{
|
||||
auto button = iterator->second.Resolve<ButtonBase>();
|
||||
if (button && button->IsEnabled)
|
||||
{
|
||||
LightUpButton(button);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LightUpButton(ButtonBase ^ button)
|
||||
{
|
||||
// If the button is a toggle button then we don't need
|
||||
// to change the UI of the button
|
||||
if (dynamic_cast<ToggleButton ^>(button))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// The button will go into the visual Pressed state with this call
|
||||
VisualStateManager::GoToState(button, "Pressed", true);
|
||||
|
||||
// This timer will fire after lightUpTime and make the button
|
||||
// go back to the normal state.
|
||||
// This timer will only fire once after which it will be destroyed
|
||||
auto timer = ref new DispatcherTimer();
|
||||
TimeSpan lightUpTime{};
|
||||
lightUpTime.Duration = 500000L; // Half second (in 100-ns units)
|
||||
timer->Interval = lightUpTime;
|
||||
|
||||
WeakReference timerWeakReference(timer);
|
||||
WeakReference buttonWeakReference(button);
|
||||
timer->Tick += ref new EventHandler<Object ^>([buttonWeakReference, timerWeakReference](Object ^, Object ^) {
|
||||
auto button = buttonWeakReference.Resolve<ButtonBase>();
|
||||
if (button)
|
||||
{
|
||||
VisualStateManager::GoToState(button, "Normal", true);
|
||||
}
|
||||
|
||||
// Cancel the timer after we're done so it only fires once
|
||||
auto timer = timerWeakReference.Resolve<DispatcherTimer>();
|
||||
if (timer)
|
||||
{
|
||||
timer->Stop();
|
||||
}
|
||||
});
|
||||
timer->Start();
|
||||
}
|
||||
|
||||
// Looks for the first button reference that it can resolve
|
||||
// and execute its command.
|
||||
// NOTE: It is assumed that all buttons associated with a particular
|
||||
// key have the same command
|
||||
template <typename T>
|
||||
void RunFirstEnabledButtonCommand(const T& buttons)
|
||||
{
|
||||
auto buttonIterator = buttons.first;
|
||||
for (; buttonIterator != buttons.second; ++buttonIterator)
|
||||
{
|
||||
auto button = buttonIterator->second.Resolve<ButtonBase>();
|
||||
if (button && button->IsEnabled)
|
||||
{
|
||||
RunButtonCommand(button);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RunButtonCommand(ButtonBase ^ button)
|
||||
{
|
||||
if (button->IsEnabled)
|
||||
{
|
||||
auto command = button->Command;
|
||||
auto parameter = button->CommandParameter;
|
||||
if (command && command->CanExecute(parameter))
|
||||
{
|
||||
command->Execute(parameter);
|
||||
}
|
||||
|
||||
auto radio = dynamic_cast<RadioButton ^>(button);
|
||||
if (radio)
|
||||
{
|
||||
radio->IsChecked = true;
|
||||
return;
|
||||
}
|
||||
|
||||
auto toggle = dynamic_cast<ToggleButton ^>(button);
|
||||
if (toggle)
|
||||
{
|
||||
toggle->IsChecked = !toggle->IsChecked->Value;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KeyboardShortcutManager::IgnoreEscape(bool onlyOnce)
|
||||
{
|
||||
// Writer lock for the static maps
|
||||
reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock);
|
||||
|
||||
int viewId = Utils::GetWindowId();
|
||||
|
||||
if (s_ignoreNextEscape.find(viewId) != s_ignoreNextEscape.end())
|
||||
{
|
||||
s_ignoreNextEscape[viewId] = true;
|
||||
}
|
||||
|
||||
if (s_keepIgnoringEscape.find(viewId) != s_keepIgnoringEscape.end())
|
||||
{
|
||||
s_keepIgnoringEscape[viewId] = !onlyOnce;
|
||||
}
|
||||
}
|
||||
|
||||
void KeyboardShortcutManager::HonorEscape()
|
||||
{
|
||||
// Writer lock for the static maps
|
||||
reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock);
|
||||
|
||||
int viewId = Utils::GetWindowId();
|
||||
|
||||
if (s_ignoreNextEscape.find(viewId) != s_ignoreNextEscape.end())
|
||||
{
|
||||
s_ignoreNextEscape[viewId] = false;
|
||||
}
|
||||
|
||||
if (s_keepIgnoringEscape.find(viewId) != s_keepIgnoringEscape.end())
|
||||
{
|
||||
s_keepIgnoringEscape[viewId] = false;
|
||||
}
|
||||
}
|
||||
|
||||
void KeyboardShortcutManager::OnCharacterPropertyChanged(DependencyObject ^ target, String ^ oldValue, String ^ newValue)
|
||||
{
|
||||
// Writer lock for the static maps
|
||||
reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock);
|
||||
|
||||
auto button = safe_cast<ButtonBase ^>(target);
|
||||
|
||||
int viewId = Utils::GetWindowId();
|
||||
auto iterViewMap = s_CharacterForButtons.find(viewId);
|
||||
|
||||
if (iterViewMap != s_CharacterForButtons.end())
|
||||
{
|
||||
if (oldValue)
|
||||
{
|
||||
iterViewMap->second.erase(oldValue->Data()[0]);
|
||||
}
|
||||
|
||||
if (newValue)
|
||||
{
|
||||
if (newValue == L".")
|
||||
{
|
||||
wchar_t decSep = LocalizationSettings::GetInstance().GetDecimalSeparator();
|
||||
iterViewMap->second.insert(std::make_pair(decSep, WeakReference(button)));
|
||||
}
|
||||
else
|
||||
{
|
||||
iterViewMap->second.insert(std::make_pair(newValue->Data()[0], WeakReference(button)));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
s_CharacterForButtons.insert(std::make_pair(viewId, std::multimap<wchar_t, WeakReference>()));
|
||||
|
||||
if (newValue == L".")
|
||||
{
|
||||
wchar_t decSep = LocalizationSettings::GetInstance().GetDecimalSeparator();
|
||||
s_CharacterForButtons.find(viewId)->second.insert(std::make_pair(decSep, WeakReference(button)));
|
||||
}
|
||||
else
|
||||
{
|
||||
s_CharacterForButtons.find(viewId)->second.insert(std::make_pair(newValue->Data()[0], WeakReference(button)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KeyboardShortcutManager::OnVirtualKeyPropertyChanged(DependencyObject ^ target, MyVirtualKey /*oldValue*/, MyVirtualKey newValue)
|
||||
{
|
||||
// Writer lock for the static maps
|
||||
reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock);
|
||||
|
||||
auto button = static_cast<ButtonBase ^>(target);
|
||||
|
||||
int viewId = Utils::GetWindowId();
|
||||
auto iterViewMap = s_VirtualKeysForButtons.find(viewId);
|
||||
|
||||
// Check if the View Id has already been registered
|
||||
if (iterViewMap != s_VirtualKeysForButtons.end())
|
||||
{
|
||||
iterViewMap->second.insert(std::make_pair(newValue, WeakReference(button)));
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the View Id is not already registered, then register it and make the entry
|
||||
s_VirtualKeysForButtons.insert(std::make_pair(viewId, std::multimap<MyVirtualKey, WeakReference>()));
|
||||
s_VirtualKeysForButtons.find(viewId)->second.insert(std::make_pair(newValue, WeakReference(button)));
|
||||
}
|
||||
}
|
||||
|
||||
void KeyboardShortcutManager::OnVirtualKeyControlChordPropertyChanged(DependencyObject ^ target, MyVirtualKey /*oldValue*/, MyVirtualKey newValue)
|
||||
{
|
||||
// Writer lock for the static maps
|
||||
reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock);
|
||||
|
||||
Control ^ control = dynamic_cast<ButtonBase ^>(target);
|
||||
|
||||
if (control == nullptr)
|
||||
{
|
||||
// Handling Ctrl+E shortcut for Date Calc, target would be NavigationView^ in that case
|
||||
control = safe_cast<MUXC::NavigationView ^>(target);
|
||||
}
|
||||
|
||||
int viewId = Utils::GetWindowId();
|
||||
auto iterViewMap = s_VirtualKeyControlChordsForButtons.find(viewId);
|
||||
|
||||
// Check if the View Id has already been registered
|
||||
if (iterViewMap != s_VirtualKeyControlChordsForButtons.end())
|
||||
{
|
||||
iterViewMap->second.insert(std::make_pair(newValue, WeakReference(control)));
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the View Id is not already registered, then register it and make the entry
|
||||
s_VirtualKeyControlChordsForButtons.insert(std::make_pair(viewId, std::multimap<MyVirtualKey, WeakReference>()));
|
||||
s_VirtualKeyControlChordsForButtons.find(viewId)->second.insert(std::make_pair(newValue, WeakReference(control)));
|
||||
}
|
||||
}
|
||||
|
||||
void KeyboardShortcutManager::OnVirtualKeyShiftChordPropertyChanged(DependencyObject ^ target, MyVirtualKey /*oldValue*/, MyVirtualKey newValue)
|
||||
{
|
||||
// Writer lock for the static maps
|
||||
reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock);
|
||||
|
||||
auto button = safe_cast<ButtonBase ^>(target);
|
||||
|
||||
int viewId = Utils::GetWindowId();
|
||||
auto iterViewMap = s_VirtualKeyShiftChordsForButtons.find(viewId);
|
||||
|
||||
// Check if the View Id has already been registered
|
||||
if (iterViewMap != s_VirtualKeyShiftChordsForButtons.end())
|
||||
{
|
||||
iterViewMap->second.insert(std::make_pair(newValue, WeakReference(button)));
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the View Id is not already registered, then register it and make the entry
|
||||
s_VirtualKeyShiftChordsForButtons.insert(std::make_pair(viewId, std::multimap<MyVirtualKey, WeakReference>()));
|
||||
s_VirtualKeyShiftChordsForButtons.find(viewId)->second.insert(std::make_pair(newValue, WeakReference(button)));
|
||||
}
|
||||
}
|
||||
|
||||
void KeyboardShortcutManager::OnVirtualKeyAltChordPropertyChanged(DependencyObject ^ target, MyVirtualKey /*oldValue*/, MyVirtualKey newValue)
|
||||
{
|
||||
// Writer lock for the static maps
|
||||
reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock);
|
||||
|
||||
MUXC::NavigationView ^ navView = safe_cast<MUXC::NavigationView ^>(target);
|
||||
|
||||
int viewId = Utils::GetWindowId();
|
||||
auto iterViewMap = s_VirtualKeyAltChordsForButtons.find(viewId);
|
||||
|
||||
// Check if the View Id has already been registered
|
||||
if (iterViewMap != s_VirtualKeyAltChordsForButtons.end())
|
||||
{
|
||||
iterViewMap->second.insert(std::make_pair(newValue, WeakReference(navView)));
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the View Id is not already registered, then register it and make the entry
|
||||
s_VirtualKeyAltChordsForButtons.insert(std::make_pair(viewId, std::multimap<MyVirtualKey, WeakReference>()));
|
||||
s_VirtualKeyAltChordsForButtons.find(viewId)->second.insert(std::make_pair(newValue, WeakReference(navView)));
|
||||
}
|
||||
}
|
||||
|
||||
void KeyboardShortcutManager::OnVirtualKeyControlShiftChordPropertyChanged(DependencyObject ^ target, MyVirtualKey /*oldValue*/, MyVirtualKey newValue)
|
||||
{
|
||||
// Writer lock for the static maps
|
||||
reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock);
|
||||
|
||||
auto button = safe_cast<ButtonBase ^>(target);
|
||||
|
||||
int viewId = Utils::GetWindowId();
|
||||
auto iterViewMap = s_VirtualKeyControlShiftChordsForButtons.find(viewId);
|
||||
|
||||
// Check if the View Id has already been registered
|
||||
if (iterViewMap != s_VirtualKeyControlShiftChordsForButtons.end())
|
||||
{
|
||||
iterViewMap->second.insert(std::make_pair(newValue, WeakReference(button)));
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the View Id is not already registered, then register it and make the entry
|
||||
s_VirtualKeyControlShiftChordsForButtons.insert(std::make_pair(viewId, std::multimap<MyVirtualKey, WeakReference>()));
|
||||
s_VirtualKeyControlShiftChordsForButtons.find(viewId)->second.insert(std::make_pair(newValue, WeakReference(button)));
|
||||
}
|
||||
}
|
||||
|
||||
void KeyboardShortcutManager::OnVirtualKeyInverseChordPropertyChanged(DependencyObject ^ target, MyVirtualKey /*oldValue*/, MyVirtualKey newValue)
|
||||
{
|
||||
// Writer lock for the static maps
|
||||
reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock);
|
||||
|
||||
auto button = safe_cast<ButtonBase ^>(target);
|
||||
|
||||
int viewId = Utils::GetWindowId();
|
||||
auto iterViewMap = s_VirtualKeyInverseChordsForButtons.find(viewId);
|
||||
|
||||
// Check if the View Id has already been registered
|
||||
if (iterViewMap != s_VirtualKeyInverseChordsForButtons.end())
|
||||
{
|
||||
iterViewMap->second.insert(std::make_pair(newValue, WeakReference(button)));
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the View Id is not already registered, then register it and make the entry
|
||||
s_VirtualKeyInverseChordsForButtons.insert(std::make_pair(viewId, std::multimap<MyVirtualKey, WeakReference>()));
|
||||
s_VirtualKeyInverseChordsForButtons.find(viewId)->second.insert(std::make_pair(newValue, WeakReference(button)));
|
||||
}
|
||||
}
|
||||
|
||||
void KeyboardShortcutManager::OnVirtualKeyControlInverseChordPropertyChanged(DependencyObject ^ target, MyVirtualKey /*oldValue*/, MyVirtualKey newValue)
|
||||
{
|
||||
// Writer lock for the static maps
|
||||
reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock);
|
||||
|
||||
auto button = safe_cast<ButtonBase ^>(target);
|
||||
|
||||
int viewId = Utils::GetWindowId();
|
||||
auto iterViewMap = s_VirtualKeyControlInverseChordsForButtons.find(viewId);
|
||||
|
||||
// Check if the View Id has already been registered
|
||||
if (iterViewMap != s_VirtualKeyControlInverseChordsForButtons.end())
|
||||
{
|
||||
iterViewMap->second.insert(std::make_pair(newValue, WeakReference(button)));
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the View Id is not already registered, then register it and make the entry
|
||||
s_VirtualKeyControlInverseChordsForButtons.insert(std::make_pair(viewId, std::multimap<MyVirtualKey, WeakReference>()));
|
||||
s_VirtualKeyControlInverseChordsForButtons.find(viewId)->second.insert(std::make_pair(newValue, WeakReference(button)));
|
||||
}
|
||||
}
|
||||
|
||||
// In the three event handlers below we will not mark the event as handled
|
||||
// because this is a supplemental operation and we don't want to interfere with
|
||||
// the normal keyboard handling.
|
||||
void KeyboardShortcutManager::OnCharacterReceivedHandler(CoreWindow ^ sender, CharacterReceivedEventArgs ^ args)
|
||||
{
|
||||
int viewId = Utils::GetWindowId();
|
||||
auto currentHonorShortcuts = s_fHonorShortcuts.find(viewId);
|
||||
|
||||
if (currentHonorShortcuts != s_fHonorShortcuts.end())
|
||||
{
|
||||
if (currentHonorShortcuts->second)
|
||||
{
|
||||
wchar_t character = static_cast<wchar_t>(args->KeyCode);
|
||||
auto buttons = s_CharacterForButtons.find(viewId)->second.equal_range(character);
|
||||
RunFirstEnabledButtonCommand(buttons);
|
||||
|
||||
LightUpButtons(buttons);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const std::multimap<MyVirtualKey, WeakReference>& GetCurrentKeyDictionary(MyVirtualKey key, bool altPressed = false)
|
||||
{
|
||||
int viewId = Utils::GetWindowId();
|
||||
|
||||
if (altPressed)
|
||||
{
|
||||
return s_VirtualKeyAltChordsForButtons.find(viewId)->second;
|
||||
}
|
||||
else if (
|
||||
(s_ShiftKeyPressed.find(viewId)->second)
|
||||
&& ((Window::Current->CoreWindow->GetKeyState(VirtualKey::Control) & CoreVirtualKeyStates::Down) == CoreVirtualKeyStates::Down))
|
||||
{
|
||||
return s_VirtualKeyControlShiftChordsForButtons.find(viewId)->second;
|
||||
}
|
||||
else if (s_ShiftKeyPressed.find(viewId)->second)
|
||||
{
|
||||
return s_VirtualKeyShiftChordsForButtons.find(viewId)->second;
|
||||
}
|
||||
else if (s_ShiftButtonChecked.find(viewId)->second)
|
||||
{
|
||||
if ((Window::Current->CoreWindow->GetKeyState(VirtualKey::Control) & CoreVirtualKeyStates::Down) == CoreVirtualKeyStates::Down)
|
||||
{
|
||||
auto iterViewMap = s_VirtualKeyControlInverseChordsForButtons.find(viewId);
|
||||
if (iterViewMap != s_VirtualKeyControlInverseChordsForButtons.end())
|
||||
{
|
||||
for (auto iterator = iterViewMap->second.begin(); iterator != iterViewMap->second.end(); ++iterator)
|
||||
{
|
||||
if (key == iterator->first)
|
||||
{
|
||||
return s_VirtualKeyControlInverseChordsForButtons.find(viewId)->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto iterViewMap = s_VirtualKeyInverseChordsForButtons.find(viewId);
|
||||
if (iterViewMap != s_VirtualKeyInverseChordsForButtons.end())
|
||||
{
|
||||
for (auto iterator = iterViewMap->second.begin(); iterator != iterViewMap->second.end(); ++iterator)
|
||||
{
|
||||
if (key == iterator->first)
|
||||
{
|
||||
return s_VirtualKeyInverseChordsForButtons.find(viewId)->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((Window::Current->CoreWindow->GetKeyState(VirtualKey::Control) & CoreVirtualKeyStates::Down) == CoreVirtualKeyStates::Down)
|
||||
{
|
||||
return s_VirtualKeyControlChordsForButtons.find(viewId)->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
return s_VirtualKeysForButtons.find(viewId)->second;
|
||||
}
|
||||
}
|
||||
|
||||
void KeyboardShortcutManager::OnKeyDownHandler(CoreWindow ^ sender, KeyEventArgs ^ args)
|
||||
{
|
||||
// If keyboard shortcuts like Ctrl+C or Ctrl+V are not handled
|
||||
if (!args->Handled)
|
||||
{
|
||||
auto key = args->VirtualKey;
|
||||
int viewId = Utils::GetWindowId();
|
||||
|
||||
auto currentControlKeyPressed = s_ControlKeyPressed.find(viewId);
|
||||
auto currentShiftKeyPressed = s_ShiftKeyPressed.find(viewId);
|
||||
|
||||
bool isControlKeyPressed = (currentControlKeyPressed != s_ControlKeyPressed.end()) && (currentControlKeyPressed->second);
|
||||
bool isShiftKeyPressed = (currentShiftKeyPressed != s_ShiftKeyPressed.end()) && (currentShiftKeyPressed->second);
|
||||
|
||||
// Handle Ctrl + E for DateCalculator
|
||||
if ((key == VirtualKey::E) && isControlKeyPressed && !isShiftKeyPressed)
|
||||
{
|
||||
const auto& lookupMap = GetCurrentKeyDictionary(static_cast<MyVirtualKey>(key));
|
||||
auto buttons = lookupMap.equal_range(static_cast<MyVirtualKey>(key));
|
||||
auto navView = buttons.first->second.Resolve<MUXC::NavigationView>();
|
||||
auto appViewModel = safe_cast<ApplicationViewModel ^>(navView->DataContext);
|
||||
appViewModel->Mode = ViewMode::Date;
|
||||
auto categoryName = AppResourceProvider::GetInstance()->GetResourceString(L"DateCalculationModeText");
|
||||
appViewModel->CategoryName = categoryName;
|
||||
|
||||
auto menuItems = static_cast<IObservableVector<Object ^> ^>(navView->MenuItemsSource);
|
||||
auto flatIndex = NavCategory::GetFlatIndex(ViewMode::Date);
|
||||
navView->SelectedItem = menuItems->GetAt(flatIndex);
|
||||
return;
|
||||
}
|
||||
|
||||
auto currentHonorShortcuts = s_fHonorShortcuts.find(viewId);
|
||||
|
||||
auto currentIgnoreNextEscape = s_ignoreNextEscape.find(viewId);
|
||||
|
||||
if (currentIgnoreNextEscape != s_ignoreNextEscape.end())
|
||||
{
|
||||
if (currentIgnoreNextEscape->second && key == VirtualKey::Escape)
|
||||
{
|
||||
auto currentKeepIgnoringEscape = s_keepIgnoringEscape.find(viewId);
|
||||
|
||||
if (currentKeepIgnoringEscape != s_keepIgnoringEscape.end())
|
||||
{
|
||||
if (!currentKeepIgnoringEscape->second)
|
||||
{
|
||||
HonorEscape();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (key == VirtualKey::Control)
|
||||
{
|
||||
// Writer lock for the static maps
|
||||
reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock);
|
||||
|
||||
auto currControlKeyPressed = s_ControlKeyPressed.find(viewId);
|
||||
|
||||
if (currControlKeyPressed != s_ControlKeyPressed.end())
|
||||
{
|
||||
s_ControlKeyPressed[viewId] = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (key == VirtualKey::Shift)
|
||||
{
|
||||
// Writer lock for the static maps
|
||||
reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock);
|
||||
|
||||
auto currShiftKeyPressed = s_ShiftKeyPressed.find(viewId);
|
||||
|
||||
if (currShiftKeyPressed != s_ShiftKeyPressed.end())
|
||||
{
|
||||
s_ShiftKeyPressed[viewId] = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentHonorShortcuts != s_fHonorShortcuts.end())
|
||||
{
|
||||
if (currentHonorShortcuts->second)
|
||||
{
|
||||
const auto myVirtualKey = static_cast<MyVirtualKey>(key);
|
||||
const auto& lookupMap = GetCurrentKeyDictionary(myVirtualKey);
|
||||
auto buttons = lookupMap.equal_range(myVirtualKey);
|
||||
RunFirstEnabledButtonCommand(buttons);
|
||||
|
||||
// Ctrl+C and Ctrl+V shifts focus to some button because of which enter doesn't work after copy/paste. So don't shift focus if Ctrl+C or Ctrl+V
|
||||
// is pressed. When drop down is open, pressing escape shifts focus to clear button. So dont's shift focus if drop down is open. Ctrl+Insert is
|
||||
// equivalent to Ctrl+C and Shift+Insert is equivalent to Ctrl+V
|
||||
auto currentIsDropDownOpen = s_IsDropDownOpen.find(viewId);
|
||||
if (currentIsDropDownOpen != s_IsDropDownOpen.end() && !currentIsDropDownOpen->second)
|
||||
{
|
||||
// Do not Light Up Buttons when Ctrl+C, Ctrl+V, Ctrl+Insert or Shift+Insert is pressed
|
||||
if (!(isControlKeyPressed && (key == VirtualKey::C || key == VirtualKey::V || key == VirtualKey::Insert))
|
||||
&& !(isShiftKeyPressed && (key == VirtualKey::Insert)))
|
||||
{
|
||||
LightUpButtons(buttons);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KeyboardShortcutManager::OnKeyUpHandler(CoreWindow ^ sender, KeyEventArgs ^ args)
|
||||
{
|
||||
int viewId = Utils::GetWindowId();
|
||||
auto key = args->VirtualKey;
|
||||
|
||||
if (key == VirtualKey::Shift)
|
||||
{
|
||||
// Writer lock for the static maps
|
||||
reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock);
|
||||
|
||||
auto currentShiftKeyPressed = s_ShiftKeyPressed.find(viewId);
|
||||
|
||||
if (currentShiftKeyPressed != s_ShiftKeyPressed.end())
|
||||
{
|
||||
s_ShiftKeyPressed[viewId] = false;
|
||||
}
|
||||
}
|
||||
else if (key == VirtualKey::Control)
|
||||
{
|
||||
// Writer lock for the static maps
|
||||
reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock);
|
||||
|
||||
auto currControlKeyPressed = s_ControlKeyPressed.find(viewId);
|
||||
|
||||
if (currControlKeyPressed != s_ControlKeyPressed.end())
|
||||
{
|
||||
s_ControlKeyPressed[viewId] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KeyboardShortcutManager::OnAcceleratorKeyActivated(CoreDispatcher ^, AcceleratorKeyEventArgs ^ args)
|
||||
{
|
||||
if (args->KeyStatus.IsKeyReleased)
|
||||
{
|
||||
auto key = args->VirtualKey;
|
||||
bool altPressed = args->KeyStatus.IsMenuKeyDown;
|
||||
|
||||
// If the Alt/Menu key is not pressed then we don't care about the key anymore
|
||||
if (!altPressed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& lookupMap = GetCurrentKeyDictionary(static_cast<MyVirtualKey>(key), altPressed);
|
||||
auto listItems = lookupMap.equal_range(static_cast<MyVirtualKey>(key));
|
||||
for (auto listIterator = listItems.first; listIterator != listItems.second; ++listIterator)
|
||||
{
|
||||
auto item = listIterator->second.Resolve<MUXC::NavigationView>();
|
||||
if (item != nullptr)
|
||||
{
|
||||
auto navView = safe_cast<MUXC::NavigationView ^>(item);
|
||||
|
||||
auto menuItems = static_cast<IObservableVector<Object ^> ^>(navView->MenuItemsSource);
|
||||
if (menuItems != nullptr)
|
||||
{
|
||||
auto vm = safe_cast<ApplicationViewModel ^>(navView->DataContext);
|
||||
if (nullptr != vm)
|
||||
{
|
||||
ViewMode toMode = NavCategory::GetViewModeForVirtualKey(static_cast<MyVirtualKey>(key));
|
||||
auto nvi = dynamic_cast<MUXC::NavigationViewItem ^>(menuItems->GetAt(NavCategory::GetFlatIndex(toMode)));
|
||||
if (nvi && nvi->IsEnabled && NavCategory::IsValidViewMode(toMode))
|
||||
{
|
||||
vm->Mode = toMode;
|
||||
navView->SelectedItem = nvi;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (args->VirtualKey == VirtualKey::Escape)
|
||||
{
|
||||
int viewId = Utils::GetWindowId();
|
||||
auto iterViewMap = s_AboutFlyout.find(viewId);
|
||||
|
||||
if ((iterViewMap != s_AboutFlyout.end()) && (iterViewMap->second != nullptr))
|
||||
{
|
||||
iterViewMap->second->Hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KeyboardShortcutManager::Initialize()
|
||||
{
|
||||
auto coreWindow = Window::Current->CoreWindow;
|
||||
coreWindow->CharacterReceived +=
|
||||
ref new TypedEventHandler<CoreWindow ^, CharacterReceivedEventArgs ^>(&KeyboardShortcutManager::OnCharacterReceivedHandler);
|
||||
coreWindow->KeyDown += ref new TypedEventHandler<CoreWindow ^, KeyEventArgs ^>(&KeyboardShortcutManager::OnKeyDownHandler);
|
||||
coreWindow->KeyUp += ref new TypedEventHandler<CoreWindow ^, KeyEventArgs ^>(&KeyboardShortcutManager::OnKeyUpHandler);
|
||||
coreWindow->Dispatcher->AcceleratorKeyActivated +=
|
||||
ref new TypedEventHandler<CoreDispatcher ^, AcceleratorKeyEventArgs ^>(&KeyboardShortcutManager::OnAcceleratorKeyActivated);
|
||||
|
||||
KeyboardShortcutManager::RegisterNewAppViewId();
|
||||
}
|
||||
|
||||
void KeyboardShortcutManager::ShiftButtonChecked(bool checked)
|
||||
{
|
||||
int viewId = Utils::GetWindowId();
|
||||
|
||||
if (s_ShiftButtonChecked.find(viewId) != s_ShiftButtonChecked.end())
|
||||
{
|
||||
s_ShiftButtonChecked[viewId] = checked;
|
||||
}
|
||||
}
|
||||
|
||||
void KeyboardShortcutManager::UpdateDropDownState(bool isOpen)
|
||||
{
|
||||
int viewId = Utils::GetWindowId();
|
||||
|
||||
if (s_IsDropDownOpen.find(viewId) != s_IsDropDownOpen.end())
|
||||
{
|
||||
s_IsDropDownOpen[viewId] = isOpen;
|
||||
}
|
||||
}
|
||||
|
||||
void KeyboardShortcutManager::UpdateDropDownState(Flyout ^ aboutPageFlyout)
|
||||
{
|
||||
int viewId = Utils::GetWindowId();
|
||||
|
||||
if (s_AboutFlyout.find(viewId) != s_AboutFlyout.end())
|
||||
{
|
||||
s_AboutFlyout[viewId] = aboutPageFlyout;
|
||||
}
|
||||
}
|
||||
|
||||
void KeyboardShortcutManager::HonorShortcuts(bool allow)
|
||||
{
|
||||
// Writer lock for the static maps
|
||||
reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock);
|
||||
|
||||
int viewId = Utils::GetWindowId();
|
||||
|
||||
if (s_fHonorShortcuts.find(viewId) != s_fHonorShortcuts.end())
|
||||
{
|
||||
s_fHonorShortcuts[viewId] = allow;
|
||||
}
|
||||
}
|
||||
|
||||
void KeyboardShortcutManager::RegisterNewAppViewId()
|
||||
{
|
||||
// Writer lock for the static maps
|
||||
reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock);
|
||||
|
||||
int appViewId = Utils::GetWindowId();
|
||||
|
||||
// Check if the View Id has already been registered
|
||||
if (s_CharacterForButtons.find(appViewId) == s_CharacterForButtons.end())
|
||||
{
|
||||
s_CharacterForButtons.insert(std::make_pair(appViewId, std::multimap<wchar_t, WeakReference>()));
|
||||
}
|
||||
|
||||
if (s_VirtualKeysForButtons.find(appViewId) == s_VirtualKeysForButtons.end())
|
||||
{
|
||||
s_VirtualKeysForButtons.insert(std::make_pair(appViewId, std::multimap<MyVirtualKey, WeakReference>()));
|
||||
}
|
||||
|
||||
if (s_VirtualKeyControlChordsForButtons.find(appViewId) == s_VirtualKeyControlChordsForButtons.end())
|
||||
{
|
||||
s_VirtualKeyControlChordsForButtons.insert(std::make_pair(appViewId, std::multimap<MyVirtualKey, WeakReference>()));
|
||||
}
|
||||
|
||||
if (s_VirtualKeyShiftChordsForButtons.find(appViewId) == s_VirtualKeyShiftChordsForButtons.end())
|
||||
{
|
||||
s_VirtualKeyShiftChordsForButtons.insert(std::make_pair(appViewId, std::multimap<MyVirtualKey, WeakReference>()));
|
||||
}
|
||||
|
||||
if (s_VirtualKeyAltChordsForButtons.find(appViewId) == s_VirtualKeyAltChordsForButtons.end())
|
||||
{
|
||||
s_VirtualKeyAltChordsForButtons.insert(std::make_pair(appViewId, std::multimap<MyVirtualKey, WeakReference>()));
|
||||
}
|
||||
|
||||
if (s_VirtualKeyControlShiftChordsForButtons.find(appViewId) == s_VirtualKeyControlShiftChordsForButtons.end())
|
||||
{
|
||||
s_VirtualKeyControlShiftChordsForButtons.insert(std::make_pair(appViewId, std::multimap<MyVirtualKey, WeakReference>()));
|
||||
}
|
||||
|
||||
if (s_VirtualKeyInverseChordsForButtons.find(appViewId) == s_VirtualKeyInverseChordsForButtons.end())
|
||||
{
|
||||
s_VirtualKeyInverseChordsForButtons.insert(std::make_pair(appViewId, std::multimap<MyVirtualKey, WeakReference>()));
|
||||
}
|
||||
|
||||
if (s_VirtualKeyControlInverseChordsForButtons.find(appViewId) == s_VirtualKeyControlInverseChordsForButtons.end())
|
||||
{
|
||||
s_VirtualKeyControlInverseChordsForButtons.insert(std::make_pair(appViewId, std::multimap<MyVirtualKey, WeakReference>()));
|
||||
}
|
||||
|
||||
s_ShiftKeyPressed[appViewId] = false;
|
||||
s_ControlKeyPressed[appViewId] = false;
|
||||
s_ShiftButtonChecked[appViewId] = false;
|
||||
s_IsDropDownOpen[appViewId] = false;
|
||||
s_ignoreNextEscape[appViewId] = false;
|
||||
s_keepIgnoringEscape[appViewId] = false;
|
||||
s_fHonorShortcuts[appViewId] = true;
|
||||
s_AboutFlyout[appViewId] = nullptr;
|
||||
}
|
||||
|
||||
void KeyboardShortcutManager::OnWindowClosed(int viewId)
|
||||
{
|
||||
// Writer lock for the static maps
|
||||
reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock);
|
||||
|
||||
s_CharacterForButtons.erase(viewId);
|
||||
|
||||
s_VirtualKeysForButtons.erase(viewId);
|
||||
s_VirtualKeyControlChordsForButtons.erase(viewId);
|
||||
s_VirtualKeyShiftChordsForButtons.erase(viewId);
|
||||
s_VirtualKeyAltChordsForButtons.erase(viewId);
|
||||
s_VirtualKeyControlShiftChordsForButtons.erase(viewId);
|
||||
s_VirtualKeyInverseChordsForButtons.erase(viewId);
|
||||
s_VirtualKeyControlInverseChordsForButtons.erase(viewId);
|
||||
|
||||
s_ShiftKeyPressed.erase(viewId);
|
||||
s_ControlKeyPressed.erase(viewId);
|
||||
s_ShiftButtonChecked.erase(viewId);
|
||||
s_IsDropDownOpen.erase(viewId);
|
||||
s_ignoreNextEscape.erase(viewId);
|
||||
s_keepIgnoringEscape.erase(viewId);
|
||||
s_fHonorShortcuts.erase(viewId);
|
||||
s_AboutFlyout.erase(viewId);
|
||||
}
|
78
src/Calculator/Common/KeyboardShortcutManager.h
Normal file
78
src/Calculator/Common/KeyboardShortcutManager.h
Normal file
@@ -0,0 +1,78 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CalcViewModel/Common/Utils.h"
|
||||
#include "CalcViewModel/Common/MyVirtualKey.h"
|
||||
|
||||
namespace CalculatorApp
|
||||
{
|
||||
namespace Common
|
||||
{
|
||||
public
|
||||
ref class KeyboardShortcutManager sealed
|
||||
{
|
||||
public:
|
||||
KeyboardShortcutManager()
|
||||
{
|
||||
}
|
||||
|
||||
DEPENDENCY_PROPERTY_OWNER(KeyboardShortcutManager);
|
||||
|
||||
DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(Platform::String ^, Character);
|
||||
DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(MyVirtualKey, VirtualKey);
|
||||
DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(MyVirtualKey, VirtualKeyControlChord);
|
||||
DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(MyVirtualKey, VirtualKeyShiftChord);
|
||||
DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(MyVirtualKey, VirtualKeyAltChord);
|
||||
DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(MyVirtualKey, VirtualKeyControlShiftChord);
|
||||
DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(MyVirtualKey, VirtualKeyInverseChord);
|
||||
DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(MyVirtualKey, VirtualKeyControlInverseChord);
|
||||
|
||||
internal :
|
||||
|
||||
static void
|
||||
Initialize();
|
||||
|
||||
// Sometimes, like with popups, escape is treated as special and even
|
||||
// though it is handled we get it passed through to us. In those cases
|
||||
// we need to be able to ignore it (looking at e->Handled isn't sufficient
|
||||
// because that always returns true).
|
||||
// The onlyOnce flag is used to indicate whether we should only ignore the
|
||||
// next escape, or keep ignoring until you explicitly HonorEscape.
|
||||
static void IgnoreEscape(bool onlyOnce);
|
||||
static void HonorEscape();
|
||||
static void HonorShortcuts(bool allow);
|
||||
static void UpdateDropDownState(bool);
|
||||
static void ShiftButtonChecked(bool checked);
|
||||
static void UpdateDropDownState(Windows::UI::Xaml::Controls::Flyout ^ aboutPageFlyout);
|
||||
|
||||
static void RegisterNewAppViewId();
|
||||
static void OnWindowClosed(int viewId);
|
||||
|
||||
private:
|
||||
static void OnCharacterPropertyChanged(Windows::UI::Xaml::DependencyObject ^ target, Platform::String ^ oldValue, Platform::String ^ newValue);
|
||||
|
||||
static void OnVirtualKeyPropertyChanged(Windows::UI::Xaml::DependencyObject ^ target, MyVirtualKey oldValue, MyVirtualKey newValue);
|
||||
|
||||
static void OnVirtualKeyControlChordPropertyChanged(Windows::UI::Xaml::DependencyObject ^ target, MyVirtualKey oldValue, MyVirtualKey newValue);
|
||||
|
||||
static void OnVirtualKeyShiftChordPropertyChanged(Windows::UI::Xaml::DependencyObject ^ target, MyVirtualKey oldValue, MyVirtualKey newValue);
|
||||
|
||||
static void OnVirtualKeyInverseChordPropertyChanged(Windows::UI::Xaml::DependencyObject ^ target, MyVirtualKey oldValue, MyVirtualKey newValue);
|
||||
|
||||
static void
|
||||
OnVirtualKeyControlInverseChordPropertyChanged(Windows::UI::Xaml::DependencyObject ^ target, MyVirtualKey oldValue, MyVirtualKey newValue);
|
||||
|
||||
static void OnVirtualKeyAltChordPropertyChanged(Windows::UI::Xaml::DependencyObject ^ target, MyVirtualKey oldValue, MyVirtualKey newValue);
|
||||
|
||||
static void
|
||||
OnVirtualKeyControlShiftChordPropertyChanged(Windows::UI::Xaml::DependencyObject ^ target, MyVirtualKey oldValue, MyVirtualKey newValue);
|
||||
|
||||
static void OnCharacterReceivedHandler(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Core::CharacterReceivedEventArgs ^ args);
|
||||
static void OnKeyDownHandler(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Core::KeyEventArgs ^ args);
|
||||
static void OnKeyUpHandler(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Core::KeyEventArgs ^ args);
|
||||
static void OnAcceleratorKeyActivated(Windows::UI::Core::CoreDispatcher ^, Windows::UI::Core::AcceleratorKeyEventArgs ^ args);
|
||||
};
|
||||
}
|
||||
}
|
92
src/Calculator/Common/ValidatingConverters.h
Normal file
92
src/Calculator/Common/ValidatingConverters.h
Normal file
@@ -0,0 +1,92 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace CalculatorApp
|
||||
{
|
||||
namespace Common
|
||||
{
|
||||
public
|
||||
ref class ValidSelectedItemConverter sealed : public Windows::UI::Xaml::Data::IValueConverter
|
||||
{
|
||||
public:
|
||||
ValidSelectedItemConverter()
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
virtual Platform::Object
|
||||
^ Convert(
|
||||
Platform::Object ^ value,
|
||||
Windows::UI::Xaml::Interop::TypeName /*targetType*/,
|
||||
Platform::Object ^ /*parameter*/,
|
||||
Platform::String ^ /*language*/) = Windows::UI::Xaml::Data::IValueConverter::Convert
|
||||
{
|
||||
// Pass through as we don't want to change the value from the source
|
||||
return value;
|
||||
}
|
||||
|
||||
virtual Platform::Object
|
||||
^ ConvertBack(
|
||||
Platform::Object ^ value,
|
||||
Windows::UI::Xaml::Interop::TypeName /*targetType*/,
|
||||
Platform::Object ^ /*parameter*/,
|
||||
Platform::String ^ /*language*/) = Windows::UI::Xaml::Data::IValueConverter::ConvertBack
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
// Stop the binding if the object is nullptr
|
||||
return Windows::UI::Xaml::DependencyProperty::UnsetValue;
|
||||
}
|
||||
};
|
||||
|
||||
public
|
||||
ref class ValidSelectedIndexConverter sealed : public Windows::UI::Xaml::Data::IValueConverter
|
||||
{
|
||||
public:
|
||||
ValidSelectedIndexConverter()
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
virtual Platform::Object
|
||||
^ Convert(
|
||||
Platform::Object ^ value,
|
||||
Windows::UI::Xaml::Interop::TypeName /*targetType*/,
|
||||
Platform::Object ^ /*parameter*/,
|
||||
Platform::String ^ /*language*/) = Windows::UI::Xaml::Data::IValueConverter::Convert
|
||||
{
|
||||
// Pass through as we don't want to change the value from the source
|
||||
return value;
|
||||
}
|
||||
|
||||
virtual Platform::Object
|
||||
^ ConvertBack(
|
||||
Platform::Object ^ value,
|
||||
Windows::UI::Xaml::Interop::TypeName /*targetType*/,
|
||||
Platform::Object ^ /*parameter*/,
|
||||
Platform::String ^ /*language*/) = Windows::UI::Xaml::Data::IValueConverter::ConvertBack
|
||||
{
|
||||
// The value to be valid has to be a boxed int32 value
|
||||
// extract that value and ensure it is valid, ie >= 0
|
||||
if (value)
|
||||
{
|
||||
auto box = dynamic_cast<Windows::Foundation::IPropertyValue ^>(value);
|
||||
if (box && box->Type == Windows::Foundation::PropertyType::Int32)
|
||||
{
|
||||
int index = box->GetInt32();
|
||||
if (index >= 0)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
// The value is not valid therefore stop the binding right here
|
||||
return Windows::UI::Xaml::DependencyProperty::UnsetValue;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
19
src/Calculator/Common/ViewState.cpp
Normal file
19
src/Calculator/Common/ViewState.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
#include "ViewState.h"
|
||||
|
||||
namespace CalculatorApp
|
||||
{
|
||||
namespace ViewState
|
||||
{
|
||||
Platform::StringReference Snap(L"Snap");
|
||||
Platform::StringReference DockedView(L"DockedView");
|
||||
|
||||
bool IsValidViewState(Platform::String ^ viewState)
|
||||
{
|
||||
return viewState->Equals(ViewState::Snap) || viewState->Equals(ViewState::DockedView);
|
||||
}
|
||||
}
|
||||
}
|
15
src/Calculator/Common/ViewState.h
Normal file
15
src/Calculator/Common/ViewState.h
Normal file
@@ -0,0 +1,15 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace CalculatorApp
|
||||
{
|
||||
namespace ViewState
|
||||
{
|
||||
extern Platform::StringReference Snap;
|
||||
extern Platform::StringReference DockedView;
|
||||
|
||||
bool IsValidViewState(Platform::String ^ viewState);
|
||||
}
|
||||
}
|
@@ -26,16 +26,12 @@ 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, MaxFontSize);
|
||||
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
|
||||
@@ -46,15 +42,13 @@ DEPENDENCY_PROPERTY_INITIALIZATION(CalculationResult, DisplayStringExpression);
|
||||
#define WIDTHTOFONTOFFSET 3
|
||||
#define WIDTHCUTOFF 50
|
||||
#define FONTTOLERANCE 0.001
|
||||
#define SCROLL_RATIO 0.7
|
||||
|
||||
// We need a safety margin to guarantee we correctly always show/hide ScrollLeft and ScrollRight buttons when necessary.
|
||||
// In rare cases, ScrollViewer::HorizontalOffset is a little low by a few (sub)pixels when users scroll to one of the extremity
|
||||
// and no events are launched when they scroll again in the same direction
|
||||
#define SCROLL_BUTTONS_APPROXIMATION_RANGE 4
|
||||
|
||||
StringReference CalculationResult::s_FocusedState(L"Focused");
|
||||
StringReference CalculationResult::s_UnfocusedState(L"Unfocused");
|
||||
|
||||
CalculationResult::CalculationResult()
|
||||
: m_isScalingText(false)
|
||||
, m_haveCalculatedMax(false)
|
||||
@@ -123,12 +117,12 @@ void CalculationResult::OnApplyTemplate()
|
||||
m_scrollLeft = dynamic_cast<HyperlinkButton ^>(GetTemplateChild("ScrollLeft"));
|
||||
if (m_scrollLeft)
|
||||
{
|
||||
m_scrollLeftClickToken = m_scrollLeft->Click += ref new RoutedEventHandler(this, &CalculationResult::OnScrollClick);
|
||||
m_scrollLeftClickToken = m_scrollLeft->Click += ref new RoutedEventHandler(this, &CalculationResult::OnScrollLeftClick);
|
||||
}
|
||||
m_scrollRight = dynamic_cast<HyperlinkButton ^>(GetTemplateChild("ScrollRight"));
|
||||
if (m_scrollRight)
|
||||
{
|
||||
m_scrollRightClickToken = m_scrollRight->Click += ref new RoutedEventHandler(this, &CalculationResult::OnScrollClick);
|
||||
m_scrollRightClickToken = m_scrollRight->Click += ref new RoutedEventHandler(this, &CalculationResult::OnScrollRightClick);
|
||||
}
|
||||
m_textBlock = dynamic_cast<TextBlock ^>(GetTemplateChild("NormalOutput"));
|
||||
if (m_textBlock)
|
||||
@@ -139,7 +133,6 @@ void CalculationResult::OnApplyTemplate()
|
||||
}
|
||||
UpdateVisualState();
|
||||
UpdateTextState();
|
||||
VisualStateManager::GoToState(this, s_UnfocusedState, false);
|
||||
}
|
||||
|
||||
void CalculationResult::OnTextContainerLayoutUpdated(Object ^ /*sender*/, Object ^ /*e*/)
|
||||
@@ -160,16 +153,6 @@ void CalculationResult::OnIsActivePropertyChanged(bool /*oldValue*/, bool /*newV
|
||||
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();
|
||||
@@ -291,7 +274,7 @@ void CalculationResult::ScrollLeft()
|
||||
}
|
||||
if (m_textContainer->HorizontalOffset > 0)
|
||||
{
|
||||
double offset = m_textContainer->HorizontalOffset - (scrollRatio * m_textContainer->ViewportWidth);
|
||||
double offset = m_textContainer->HorizontalOffset - (SCROLL_RATIO * m_textContainer->ViewportWidth);
|
||||
m_textContainer->ChangeView(offset, nullptr, nullptr);
|
||||
}
|
||||
}
|
||||
@@ -305,7 +288,7 @@ void CalculationResult::ScrollRight()
|
||||
|
||||
if (m_textContainer->HorizontalOffset < m_textContainer->ExtentWidth - m_textContainer->ViewportWidth)
|
||||
{
|
||||
double offset = m_textContainer->HorizontalOffset + (scrollRatio * m_textContainer->ViewportWidth);
|
||||
double offset = m_textContainer->HorizontalOffset + (SCROLL_RATIO * m_textContainer->ViewportWidth);
|
||||
m_textContainer->ChangeView(offset, nullptr, nullptr);
|
||||
}
|
||||
}
|
||||
@@ -323,17 +306,14 @@ void CalculationResult::OnKeyDown(KeyRoutedEventArgs ^ e)
|
||||
}
|
||||
}
|
||||
|
||||
void CalculationResult::OnScrollClick(Object ^ sender, RoutedEventArgs ^ /*e*/)
|
||||
void CalculationResult::OnScrollLeftClick(Object ^ sender, RoutedEventArgs ^ /*e*/)
|
||||
{
|
||||
auto clicked = dynamic_cast<HyperlinkButton ^>(sender);
|
||||
if (clicked == m_scrollLeft)
|
||||
{
|
||||
this->ScrollLeft();
|
||||
}
|
||||
else
|
||||
{
|
||||
this->ScrollRight();
|
||||
}
|
||||
ScrollLeft();
|
||||
}
|
||||
|
||||
void CalculationResult::OnScrollRightClick(Object ^ sender, RoutedEventArgs ^ /*e*/)
|
||||
{
|
||||
ScrollRight();
|
||||
}
|
||||
|
||||
void CalculationResult::UpdateScrollButtons()
|
||||
@@ -392,19 +372,6 @@ void CalculationResult::OnRightTapped(RightTappedRoutedEventArgs ^ e)
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
@@ -20,15 +20,11 @@ namespace CalculatorApp
|
||||
|
||||
DEPENDENCY_PROPERTY_OWNER(CalculationResult);
|
||||
|
||||
DEPENDENCY_PROPERTY(Windows::UI::Xaml::Visibility, ExpressionVisibility);
|
||||
DEPENDENCY_PROPERTY_WITH_DEFAULT_AND_CALLBACK(double, MinFontSize, 0.0);
|
||||
DEPENDENCY_PROPERTY_WITH_DEFAULT_AND_CALLBACK(double, MaxFontSize, 30.0);
|
||||
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);
|
||||
|
||||
@@ -43,14 +39,11 @@ namespace CalculatorApp
|
||||
virtual void OnApplyTemplate() override;
|
||||
virtual void OnTapped(Windows::UI::Xaml::Input::TappedRoutedEventArgs ^ 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 OnMinFontSizePropertyChanged(double oldValue, double newValue);
|
||||
@@ -60,22 +53,21 @@ namespace CalculatorApp
|
||||
void OnTextContainerLayoutUpdated(Object ^ sender, Object ^ e);
|
||||
void OnTextContainerOnViewChanged(Object ^ sender, Windows::UI::Xaml::Controls::ScrollViewerViewChangedEventArgs ^ e);
|
||||
void UpdateVisualState();
|
||||
void OnScrollClick(Platform::Object ^ sender, Windows::UI::Xaml::RoutedEventArgs ^ e);
|
||||
void UpdateAllState();
|
||||
void OnScrollLeftClick(Platform::Object ^ sender, Windows::UI::Xaml::RoutedEventArgs ^ e);
|
||||
void OnScrollRightClick(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 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 scrollRatio = 0.7;
|
||||
bool m_isScalingText;
|
||||
bool m_haveCalculatedMax;
|
||||
Windows::Foundation::EventRegistrationToken m_textContainerLayoutChangedToken;
|
||||
|
@@ -547,7 +547,6 @@
|
||||
</VisualState.StateTriggers>
|
||||
<VisualState.Setters>
|
||||
<Setter Target="Results.MaxFontSize" Value="72"/>
|
||||
<Setter Target="Results.MaxExpressionHistoryCharacters" Value="51"/>
|
||||
<Setter Target="RowResult.MinHeight" Value="108"/>
|
||||
<Setter Target="RowResult.Height" Value="72*"/>
|
||||
</VisualState.Setters>
|
||||
@@ -558,7 +557,6 @@
|
||||
</VisualState.StateTriggers>
|
||||
<VisualState.Setters>
|
||||
<Setter Target="Results.MaxFontSize" Value="46"/>
|
||||
<Setter Target="Results.MaxExpressionHistoryCharacters" Value="30"/>
|
||||
<Setter Target="RowResult.MinHeight" Value="72"/>
|
||||
<Setter Target="RowResult.Height" Value="72*"/>
|
||||
</VisualState.Setters>
|
||||
@@ -569,7 +567,6 @@
|
||||
</VisualState.StateTriggers>
|
||||
<VisualState.Setters>
|
||||
<Setter Target="Results.MaxFontSize" Value="26"/>
|
||||
<Setter Target="Results.MaxExpressionHistoryCharacters" Value="30"/>
|
||||
<Setter Target="RowResult.MinHeight" Value="42"/>
|
||||
<Setter Target="RowResult.Height" Value="42*"/>
|
||||
</VisualState.Setters>
|
||||
@@ -615,9 +612,7 @@
|
||||
AutomationProperties.Name="{x:Bind Model.CalculationResultAutomationName, Mode=OneWay}"
|
||||
ContextCanceled="OnContextCanceled"
|
||||
ContextRequested="OnContextRequested"
|
||||
DisplayStringExpression="{x:Bind Model.DisplayStringExpression, Mode=OneWay}"
|
||||
DisplayValue="{x:Bind Model.DisplayValue, Mode=OneWay}"
|
||||
ExpressionVisibility="Visible"
|
||||
IsInError="{x:Bind Model.IsInError, Mode=OneWay}"
|
||||
IsOperatorCommand="{x:Bind Model.IsOperatorCommand, Mode=OneWay}"
|
||||
TabIndex="1"
|
||||
|
@@ -195,7 +195,8 @@ void Calculator::UpdateViewState()
|
||||
|
||||
void Calculator::AnimateCalculator(bool resultAnimate)
|
||||
{
|
||||
if (App::IsAnimationEnabled())
|
||||
static auto uiSettings = ref new UISettings();
|
||||
if (uiSettings->AnimationsEnabled)
|
||||
{
|
||||
m_doAnimate = true;
|
||||
m_resultAnimate = resultAnimate;
|
||||
|
@@ -8,7 +8,7 @@
|
||||
|
||||
#include "pch.h"
|
||||
#include "CalculatorScientificOperators.xaml.h"
|
||||
#include "CalcViewModel/Common/KeyboardShortcutManager.h"
|
||||
#include "Common/KeyboardShortcutManager.h"
|
||||
#include "CalcViewModel/Common/TraceLogger.h"
|
||||
#include "Controls/CalculatorButton.h"
|
||||
#include "CalcViewModel/StandardCalculatorViewModel.h"
|
||||
|
@@ -4,7 +4,6 @@
|
||||
#include "pch.h"
|
||||
#include "MainPage.xaml.h"
|
||||
#include "CalcViewModel/Common/TraceLogger.h"
|
||||
#include "CalcViewModel/Common/KeyboardShortcutManager.h"
|
||||
#include "CalcViewModel/Common/LocalizationService.h"
|
||||
#include "CalcViewModel/Common/Automation/NarratorNotifier.h"
|
||||
#include "CalcViewModel/Common/AppResourceProvider.h"
|
||||
@@ -12,6 +11,8 @@
|
||||
#include "Converters/BooleanToVisibilityConverter.h"
|
||||
#include "CalcViewModel/Common/LocalizationStringUtil.h"
|
||||
#include "Common/AppLifecycleLogger.h"
|
||||
#include "Common/KeyboardShortcutManager.h"
|
||||
|
||||
using namespace CalculatorApp;
|
||||
using namespace CalculatorApp::Common;
|
||||
using namespace CalculatorApp::Common::Automation;
|
||||
|
@@ -9,7 +9,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "Views/NumberPad.g.h"
|
||||
#include "CalcViewModel/Common/KeyboardShortcutManager.h"
|
||||
#include "Common/KeyboardShortcutManager.h"
|
||||
#include "CalcViewModel/Common/NumberBase.h"
|
||||
#include "CalcManager/Header Files/RadixType.h"
|
||||
|
||||
|
@@ -559,7 +559,6 @@
|
||||
ContextCanceled="OnContextCanceled"
|
||||
ContextRequested="OnContextRequested"
|
||||
DisplayValue="{x:Bind Model.Value1, Mode=OneWay}"
|
||||
ExpressionVisibility="Collapsed"
|
||||
FlowDirection="{x:Bind LayoutDirection}"
|
||||
IsActive="{Binding Value1Active, Mode=TwoWay}"
|
||||
KeyDown="OnValueKeyDown"
|
||||
@@ -610,7 +609,6 @@
|
||||
ContextCanceled="OnContextCanceled"
|
||||
ContextRequested="OnContextRequested"
|
||||
DisplayValue="{x:Bind Model.Value2, Mode=OneWay}"
|
||||
ExpressionVisibility="Collapsed"
|
||||
FlowDirection="{x:Bind LayoutDirection}"
|
||||
IsActive="{Binding Value2Active, Mode=TwoWay}"
|
||||
KeyDown="OnValueKeyDown"
|
||||
|
@@ -11,9 +11,9 @@
|
||||
#include "Controls/CalculationResult.h"
|
||||
#include "Controls/CalculatorButton.h"
|
||||
#include "CalcViewModel/Common/CopyPasteManager.h"
|
||||
#include "CalcViewModel/Common/KeyboardShortcutManager.h"
|
||||
#include "CalcViewModel/Common/LocalizationService.h"
|
||||
#include "CalcViewModel/Common/LocalizationSettings.h"
|
||||
#include "Common/KeyboardShortcutManager.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace CalculatorApp;
|
||||
@@ -46,7 +46,6 @@ static const long long DURATION_500_MS = 10000 * 500;
|
||||
|
||||
UnitConverter::UnitConverter()
|
||||
: m_meteredConnectionOverride(false)
|
||||
, m_isAnimationEnabled(false)
|
||||
{
|
||||
m_layoutDirection = LocalizationService::GetInstance()->GetFlowDirection();
|
||||
m_FlowDirectionHorizontalAlignment = m_layoutDirection == ::FlowDirection::RightToLeft ? ::HorizontalAlignment::Right : ::HorizontalAlignment::Left;
|
||||
@@ -60,9 +59,6 @@ UnitConverter::UnitConverter()
|
||||
bool preferRight = LocalizationSettings::GetInstance().GetCurrencySymbolPrecedence() == 0;
|
||||
VisualStateManager::GoToState(this, preferRight ? "CurrencySymbolRightState" : "CurrencySymbolLeftState", false);
|
||||
|
||||
auto userSettings = ref new UISettings();
|
||||
m_isAnimationEnabled = userSettings->AnimationsEnabled;
|
||||
|
||||
auto resLoader = AppResourceProvider::GetInstance();
|
||||
m_chargesMayApplyText = resLoader->GetResourceString(L"DataChargesMayApply");
|
||||
m_failedToRefreshText = resLoader->GetResourceString(L"FailedToRefresh");
|
||||
@@ -250,7 +246,8 @@ void UnitConverter::OnPasteMenuItemClicked(_In_ Object ^ sender, _In_ RoutedEven
|
||||
|
||||
void UnitConverter::AnimateConverter()
|
||||
{
|
||||
if (App::IsAnimationEnabled())
|
||||
static auto uiSettings = ref new UISettings();
|
||||
if (uiSettings->AnimationsEnabled)
|
||||
{
|
||||
AnimationStory->Begin();
|
||||
}
|
||||
@@ -332,7 +329,7 @@ void UnitConverter::OnIsDisplayVisibleChanged()
|
||||
|
||||
if (Model->IsCurrencyCurrentCategory && !Model->CurrencyTimestamp->IsEmpty())
|
||||
{
|
||||
VisualStateManager::GoToState(this, L"CurrencyLoadedState", m_isAnimationEnabled);
|
||||
VisualStateManager::GoToState(this, L"CurrencyLoadedState", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -8,7 +8,7 @@
|
||||
|
||||
#include "Views/UnitConverter.g.h"
|
||||
#include "Common/AlwaysSelectedCollectionView.h"
|
||||
#include "CalcViewModel/Common/ValidatingConverters.h"
|
||||
#include "Common/ValidatingConverters.h"
|
||||
#include "Converters/BooleanToVisibilityConverter.h"
|
||||
#include "Converters/VisibilityNegationConverter.h"
|
||||
#include "CalcViewModel/UnitConverterViewModel.h"
|
||||
@@ -87,7 +87,6 @@ namespace CalculatorApp
|
||||
|
||||
Windows::UI::Xaml::DispatcherTimer ^ m_delayTimer;
|
||||
|
||||
bool m_isAnimationEnabled;
|
||||
void SupplementaryResultsPanelInGrid_SizeChanged(Platform::Object ^ sender, Windows::UI::Xaml::SizeChangedEventArgs ^ e);
|
||||
void OnVisualStateChanged(Platform::Object ^ sender, Windows::UI::Xaml::VisualStateChangedEventArgs ^ e);
|
||||
};
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
#include "pch.h"
|
||||
#include "WindowFrameService.h"
|
||||
#include "CalcViewModel/Common/KeyboardShortcutManager.h"
|
||||
#include "Common/KeyboardShortcutManager.h"
|
||||
#include "CalcViewModel/Common/TraceLogger.h"
|
||||
|
||||
using namespace concurrency;
|
||||
|
Reference in New Issue
Block a user