From d9bf57ff99576ed3ef907081864b0edc28373040 Mon Sep 17 00:00:00 2001 From: Matt Cooley Date: Sun, 29 Sep 2019 16:42:37 -0700 Subject: [PATCH] Code cleanup: simplify NarratorNotifier (#646) Now that the RaiseNotificationEvent API is available on all platforms where the Calculator app runs, we can remove the factory classes which switched between RaiseNotificationEvent and an alternative implementation based on live regions. --- src/CalcViewModel/CalcViewModel.vcxproj | 7 -- .../CalcViewModel.vcxproj.filters | 34 +------ .../Automation/INarratorAnnouncementHost.h | 27 ------ .../Common/Automation/LiveRegionHost.cpp | 42 -------- .../Common/Automation/LiveRegionHost.h | 33 ------- .../Automation/NarratorAnnouncement.cpp | 1 + .../Common/Automation/NarratorAnnouncement.h | 42 ++------ .../NarratorAnnouncementHostFactory.cpp | 61 ------------ .../NarratorAnnouncementHostFactory.h | 33 ------- .../Common/Automation/NarratorNotifier.cpp | 15 ++- .../Common/Automation/NarratorNotifier.h | 6 +- .../Common/Automation/NotificationHost.cpp | 97 ------------------- .../Common/Automation/NotificationHost.h | 34 ------- .../BooleanToVisibilityConverter.cpp | 4 +- src/Calculator/pch.h | 11 --- 15 files changed, 29 insertions(+), 418 deletions(-) delete mode 100644 src/CalcViewModel/Common/Automation/INarratorAnnouncementHost.h delete mode 100644 src/CalcViewModel/Common/Automation/LiveRegionHost.cpp delete mode 100644 src/CalcViewModel/Common/Automation/LiveRegionHost.h delete mode 100644 src/CalcViewModel/Common/Automation/NarratorAnnouncementHostFactory.cpp delete mode 100644 src/CalcViewModel/Common/Automation/NarratorAnnouncementHostFactory.h delete mode 100644 src/CalcViewModel/Common/Automation/NotificationHost.cpp delete mode 100644 src/CalcViewModel/Common/Automation/NotificationHost.h diff --git a/src/CalcViewModel/CalcViewModel.vcxproj b/src/CalcViewModel/CalcViewModel.vcxproj index e4677aa..284640c 100644 --- a/src/CalcViewModel/CalcViewModel.vcxproj +++ b/src/CalcViewModel/CalcViewModel.vcxproj @@ -315,12 +315,8 @@ - - - - @@ -363,11 +359,8 @@ - - - diff --git a/src/CalcViewModel/CalcViewModel.vcxproj.filters b/src/CalcViewModel/CalcViewModel.vcxproj.filters index 6c723f1..625cb91 100644 --- a/src/CalcViewModel/CalcViewModel.vcxproj.filters +++ b/src/CalcViewModel/CalcViewModel.vcxproj.filters @@ -69,21 +69,9 @@ Common - - Common\Automation - - - Common\Automation - - - Common\Automation - Common\Automation - - Common\Automation - DataLoaders @@ -93,6 +81,9 @@ DataLoaders + + Common\Automation + @@ -177,24 +168,9 @@ Common - - Common\Automation - - - Common\Automation - - - Common\Automation - - - Common\Automation - Common\Automation - - Common\Automation - DataLoaders @@ -216,8 +192,8 @@ DataLoaders - - DataLoaders + + Common\Automation Common diff --git a/src/CalcViewModel/Common/Automation/INarratorAnnouncementHost.h b/src/CalcViewModel/Common/Automation/INarratorAnnouncementHost.h deleted file mode 100644 index 9f947f4..0000000 --- a/src/CalcViewModel/Common/Automation/INarratorAnnouncementHost.h +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#pragma once -#include "NarratorAnnouncement.h" - -// Declaration of the INarratorAnnouncementHost interface. -// This interface exists to hide the concrete announcement host -// being used. Depending on the version of the OS the app is running on, -// the app may need a host that uses LiveRegionChanged or RaiseNotification. - -namespace CalculatorApp::Common::Automation -{ -public - interface class INarratorAnnouncementHost - { - public: - // Is the host available on this OS. - bool IsHostAvailable(); - - // Make a new instance of a concrete host. - INarratorAnnouncementHost ^ MakeHost(); - - // Make an announcement using the concrete host's preferred method. - void Announce(NarratorAnnouncement ^ announcement); - }; -} diff --git a/src/CalcViewModel/Common/Automation/LiveRegionHost.cpp b/src/CalcViewModel/Common/Automation/LiveRegionHost.cpp deleted file mode 100644 index 0df3a96..0000000 --- a/src/CalcViewModel/Common/Automation/LiveRegionHost.cpp +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#include "pch.h" -#include "LiveRegionHost.h" - -using namespace CalculatorApp::Common::Automation; -using namespace Windows::UI::Xaml::Automation; -using namespace Windows::UI::Xaml::Automation::Peers; -using namespace Windows::UI::Xaml::Controls; - -LiveRegionHost::LiveRegionHost() - : m_host(nullptr) -{ -} - -bool LiveRegionHost::IsHostAvailable() -{ - // LiveRegion is always available. - return true; -} - -INarratorAnnouncementHost ^ LiveRegionHost::MakeHost() -{ - return ref new LiveRegionHost(); -} - -void LiveRegionHost::Announce(NarratorAnnouncement ^ announcement) -{ - if (m_host == nullptr) - { - m_host = ref new TextBlock(); - AutomationProperties::SetLiveSetting(m_host, AutomationLiveSetting::Assertive); - } - - AutomationProperties::SetName(m_host, announcement->Announcement); - AutomationPeer ^ peer = FrameworkElementAutomationPeer::FromElement(m_host); - if (peer != nullptr) - { - peer->RaiseAutomationEvent(AutomationEvents::LiveRegionChanged); - } -} diff --git a/src/CalcViewModel/Common/Automation/LiveRegionHost.h b/src/CalcViewModel/Common/Automation/LiveRegionHost.h deleted file mode 100644 index fef7c71..0000000 --- a/src/CalcViewModel/Common/Automation/LiveRegionHost.h +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#pragma once -#include "INarratorAnnouncementHost.h" - -// Declaration of the LiveRegionHost class. -// This class announces NarratorAnnouncements using the LiveRegionChanged event. -// This event is unreliable and should be deprecated in favor of the new -// RaiseNotification API in RS3. - -namespace CalculatorApp::Common::Automation -{ - // This class exists so that the app can run on RS2 and use LiveRegions - // to host notifications on those builds. - // When the app switches to min version RS3, this class can be removed - // and the app will switch to using the Notification API. - // TODO - MSFT 12735088 -public - ref class LiveRegionHost sealed : public INarratorAnnouncementHost - { - public: - LiveRegionHost(); - - virtual bool IsHostAvailable(); - virtual INarratorAnnouncementHost ^ MakeHost(); - - virtual void Announce(NarratorAnnouncement ^ announcement); - - private: - Windows::UI::Xaml::UIElement ^ m_host; - }; -} diff --git a/src/CalcViewModel/Common/Automation/NarratorAnnouncement.cpp b/src/CalcViewModel/Common/Automation/NarratorAnnouncement.cpp index 5b6d99b..940c88c 100644 --- a/src/CalcViewModel/Common/Automation/NarratorAnnouncement.cpp +++ b/src/CalcViewModel/Common/Automation/NarratorAnnouncement.cpp @@ -6,6 +6,7 @@ using namespace CalculatorApp::Common::Automation; using namespace Platform; +using namespace Windows::UI::Xaml::Automation::Peers; namespace CalculatorApp::Common::Automation { diff --git a/src/CalcViewModel/Common/Automation/NarratorAnnouncement.h b/src/CalcViewModel/Common/Automation/NarratorAnnouncement.h index c4c0c52..fef7e26 100644 --- a/src/CalcViewModel/Common/Automation/NarratorAnnouncement.h +++ b/src/CalcViewModel/Common/Automation/NarratorAnnouncement.h @@ -5,32 +5,6 @@ namespace CalculatorApp::Common::Automation { - // These enum types are copied from the types available in - // Windows::UI::Xaml::Automation::Peers in the RS3 SDK. - // When this app switches to min version RS3, these custom - // enums should be removed and the Windows types should be used - // instead. - // TODO - MSFT 12735088 -public - enum class AutomationNotificationKind - { - ItemAdded = 0, - ItemRemoved = 1, - ActionCompleted = 2, - ActionAborted = 3, - Other = 4 - }; - -public - enum class AutomationNotificationProcessing - { - ImportantAll = 0, - ImportantMostRecent = 1, - All = 2, - MostRecent = 3, - CurrentThenMostRecent = 4 - }; - public ref class NarratorAnnouncement sealed { @@ -41,14 +15,14 @@ public property Platform::String ^ ActivityId { Platform::String ^ get(); } - property AutomationNotificationKind Kind + property Windows::UI::Xaml::Automation::Peers::AutomationNotificationKind Kind { - AutomationNotificationKind get(); + Windows::UI::Xaml::Automation::Peers::AutomationNotificationKind get(); } - property AutomationNotificationProcessing Processing + property Windows::UI::Xaml::Automation::Peers::AutomationNotificationProcessing Processing { - AutomationNotificationProcessing get(); + Windows::UI::Xaml::Automation::Peers::AutomationNotificationProcessing get(); } static bool IsValid(NarratorAnnouncement ^ announcement); @@ -61,13 +35,13 @@ public NarratorAnnouncement( Platform::String ^ announcement, Platform::String ^ activityId, - AutomationNotificationKind kind, - AutomationNotificationProcessing processing); + Windows::UI::Xaml::Automation::Peers::AutomationNotificationKind kind, + Windows::UI::Xaml::Automation::Peers::AutomationNotificationProcessing processing); Platform::String ^ m_announcement; Platform::String ^ m_activityId; - AutomationNotificationKind m_kind; - AutomationNotificationProcessing m_processing; + Windows::UI::Xaml::Automation::Peers::AutomationNotificationKind m_kind; + Windows::UI::Xaml::Automation::Peers::AutomationNotificationProcessing m_processing; }; // CalculatorAnnouncement is intended to contain only static methods diff --git a/src/CalcViewModel/Common/Automation/NarratorAnnouncementHostFactory.cpp b/src/CalcViewModel/Common/Automation/NarratorAnnouncementHostFactory.cpp deleted file mode 100644 index a103c7e..0000000 --- a/src/CalcViewModel/Common/Automation/NarratorAnnouncementHostFactory.cpp +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#include "pch.h" -#include "NarratorAnnouncementHostFactory.h" -#include "NotificationHost.h" -#include "LiveRegionHost.h" - -using namespace CalculatorApp::Common::Automation; -using namespace std; - -INarratorAnnouncementHost ^ NarratorAnnouncementHostFactory::s_hostProducer; -vector NarratorAnnouncementHostFactory::s_hosts; - -// This static variable is used only to call the initialization function, to initialize the other static variables. -int NarratorAnnouncementHostFactory::s_init = NarratorAnnouncementHostFactory::Initialize(); -int NarratorAnnouncementHostFactory::Initialize() -{ - RegisterHosts(); - NarratorAnnouncementHostFactory::s_hostProducer = GetHostProducer(); - - return 0; -} - -// For now, there are two type of announcement hosts. -// We'd prefer to use Notification if it's available and fall back to LiveRegion -// if not. The availability of the host depends on the version of the OS the app is running on. -// When the app switches to min version RS3, the LiveRegionHost can be removed and we will always -// use NotificationHost. -// TODO - MSFT 12735088 -void NarratorAnnouncementHostFactory::RegisterHosts() -{ - // The host that will be used is the first available host, - // therefore, order of hosts is important here. - NarratorAnnouncementHostFactory::s_hosts = { ref new NotificationHost(), ref new LiveRegionHost() }; -} - -INarratorAnnouncementHost ^ NarratorAnnouncementHostFactory::GetHostProducer() -{ - for (INarratorAnnouncementHost ^ host : NarratorAnnouncementHostFactory::s_hosts) - { - if (host->IsHostAvailable()) - { - return host; - } - } - - assert(false && L"No suitable AnnouncementHost was found."); - return nullptr; -} - -INarratorAnnouncementHost ^ NarratorAnnouncementHostFactory::MakeHost() -{ - if (NarratorAnnouncementHostFactory::s_hostProducer == nullptr) - { - assert(false && L"No host producer has been assigned."); - return nullptr; - } - - return NarratorAnnouncementHostFactory::s_hostProducer->MakeHost(); -} diff --git a/src/CalcViewModel/Common/Automation/NarratorAnnouncementHostFactory.h b/src/CalcViewModel/Common/Automation/NarratorAnnouncementHostFactory.h deleted file mode 100644 index 4b739a7..0000000 --- a/src/CalcViewModel/Common/Automation/NarratorAnnouncementHostFactory.h +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#pragma once -#include "INarratorAnnouncementHost.h" - -// Declaration of the NarratorAnnouncementHostFactory class. -// This class exists to hide the construction of a concrete INarratorAnnouncementHost. -// Depending on the version of the OS the app is running on, the factory will return -// an announcement host appropriate for that version. - -namespace CalculatorApp::Common::Automation -{ - class NarratorAnnouncementHostFactory - { - public: - static INarratorAnnouncementHost ^ MakeHost(); - - private: - NarratorAnnouncementHostFactory() - { - } - - static int Initialize(); - static void RegisterHosts(); - static INarratorAnnouncementHost ^ GetHostProducer(); - - private: - static int s_init; - static INarratorAnnouncementHost ^ s_hostProducer; - static std::vector s_hosts; - }; -} diff --git a/src/CalcViewModel/Common/Automation/NarratorNotifier.cpp b/src/CalcViewModel/Common/Automation/NarratorNotifier.cpp index bc146e6..89fa0c0 100644 --- a/src/CalcViewModel/Common/Automation/NarratorNotifier.cpp +++ b/src/CalcViewModel/Common/Automation/NarratorNotifier.cpp @@ -5,7 +5,6 @@ #include "pch.h" #include "NarratorNotifier.h" -#include "NarratorAnnouncementHostFactory.h" using namespace CalculatorApp::Common::Automation; using namespace Platform; @@ -17,14 +16,22 @@ DependencyProperty ^ NarratorNotifier::s_announcementProperty; NarratorNotifier::NarratorNotifier() { - m_announcementHost = NarratorAnnouncementHostFactory::MakeHost(); } void NarratorNotifier::Announce(NarratorAnnouncement ^ announcement) { - if (NarratorAnnouncement::IsValid(announcement) && m_announcementHost != nullptr) + if (NarratorAnnouncement::IsValid(announcement)) { - m_announcementHost->Announce(announcement); + if (m_announcementElement == nullptr) + { + m_announcementElement = ref new Windows::UI::Xaml::Controls::TextBlock(); + } + + auto peer = FrameworkElementAutomationPeer::FromElement(m_announcementElement); + if (peer != nullptr) + { + peer->RaiseNotificationEvent(announcement->Kind, announcement->Processing, announcement->Announcement, announcement->ActivityId); + } } } diff --git a/src/CalcViewModel/Common/Automation/NarratorNotifier.h b/src/CalcViewModel/Common/Automation/NarratorNotifier.h index 55bed4e..359bb09 100644 --- a/src/CalcViewModel/Common/Automation/NarratorNotifier.h +++ b/src/CalcViewModel/Common/Automation/NarratorNotifier.h @@ -1,10 +1,10 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. // Declaration of the NarratorNotifier class. #pragma once -#include "INarratorAnnouncementHost.h" +#include "NarratorAnnouncement.h" namespace CalculatorApp::Common::Automation { @@ -47,6 +47,6 @@ public static Windows::UI::Xaml::DependencyProperty ^ s_announcementProperty; private: - INarratorAnnouncementHost ^ m_announcementHost; + Windows::UI::Xaml::UIElement ^ m_announcementElement; }; } diff --git a/src/CalcViewModel/Common/Automation/NotificationHost.cpp b/src/CalcViewModel/Common/Automation/NotificationHost.cpp deleted file mode 100644 index 92bf846..0000000 --- a/src/CalcViewModel/Common/Automation/NotificationHost.cpp +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#include "pch.h" -#include "NotificationHost.h" - -using namespace CalculatorApp::Common::Automation; -using namespace Windows::Foundation::Metadata; -using namespace Windows::UI::Xaml::Automation; -using namespace Windows::UI::Xaml::Automation::Peers; -using namespace Windows::UI::Xaml::Controls; - -NotificationHost::NotificationHost() - : m_host(nullptr) -{ -} - -bool NotificationHost::IsHostAvailable() -{ - return ApiInformation::IsMethodPresent(L"Windows.UI.Xaml.Automation.Peers.AutomationPeer", L"RaiseNotificationEvent"); -} - -INarratorAnnouncementHost ^ NotificationHost::MakeHost() -{ - return ref new NotificationHost(); -} - -void NotificationHost::Announce(NarratorAnnouncement ^ announcement) -{ - if (m_host == nullptr) - { - m_host = ref new TextBlock(); - } - - auto peer = FrameworkElementAutomationPeer::FromElement(m_host); - if (peer != nullptr) - { - peer->RaiseNotificationEvent( - GetWindowsNotificationKind(announcement->Kind), - GetWindowsNotificationProcessing(announcement->Processing), - announcement->Announcement, - announcement->ActivityId); - } -} - -StandardPeers::AutomationNotificationKind NotificationHost::GetWindowsNotificationKind(CustomPeers::AutomationNotificationKind customKindType) -{ - switch (customKindType) - { - case CustomPeers::AutomationNotificationKind::ItemAdded: - return StandardPeers::AutomationNotificationKind::ItemAdded; - - case CustomPeers::AutomationNotificationKind::ItemRemoved: - return StandardPeers::AutomationNotificationKind::ItemRemoved; - - case CustomPeers::AutomationNotificationKind::ActionCompleted: - return StandardPeers::AutomationNotificationKind::ActionCompleted; - - case CustomPeers::AutomationNotificationKind::ActionAborted: - return StandardPeers::AutomationNotificationKind::ActionAborted; - - case CustomPeers::AutomationNotificationKind::Other: - return StandardPeers::AutomationNotificationKind::Other; - - default: - assert(false && L"Unexpected AutomationNotificationKind"); - } - - return StandardPeers::AutomationNotificationKind::Other; -} - -StandardPeers::AutomationNotificationProcessing -NotificationHost::GetWindowsNotificationProcessing(CustomPeers::AutomationNotificationProcessing customProcessingType) -{ - switch (customProcessingType) - { - case CustomPeers::AutomationNotificationProcessing::ImportantAll: - return StandardPeers::AutomationNotificationProcessing::ImportantAll; - - case CustomPeers::AutomationNotificationProcessing::ImportantMostRecent: - return StandardPeers::AutomationNotificationProcessing::ImportantMostRecent; - - case CustomPeers::AutomationNotificationProcessing::All: - return StandardPeers::AutomationNotificationProcessing::All; - - case CustomPeers::AutomationNotificationProcessing::MostRecent: - return StandardPeers::AutomationNotificationProcessing::MostRecent; - - case CustomPeers::AutomationNotificationProcessing::CurrentThenMostRecent: - return StandardPeers::AutomationNotificationProcessing::CurrentThenMostRecent; - - default: - assert(false && L"Unexpected AutomationNotificationProcessing"); - } - - return StandardPeers::AutomationNotificationProcessing::ImportantMostRecent; -} diff --git a/src/CalcViewModel/Common/Automation/NotificationHost.h b/src/CalcViewModel/Common/Automation/NotificationHost.h deleted file mode 100644 index d0a929c..0000000 --- a/src/CalcViewModel/Common/Automation/NotificationHost.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#pragma once -#include "INarratorAnnouncementHost.h" - -// Declaration of the NotificationHost class. -// This class announces NarratorAnnouncements using the RaiseNotification API -// available in RS3. - -namespace CalculatorApp::Common::Automation -{ -public - ref class NotificationHost sealed : public INarratorAnnouncementHost - { - public: - NotificationHost(); - - virtual bool IsHostAvailable(); - virtual INarratorAnnouncementHost ^ MakeHost(); - - virtual void Announce(NarratorAnnouncement ^ announcement); - - private: - static Windows::UI::Xaml::Automation::Peers::AutomationNotificationKind - GetWindowsNotificationKind(CalculatorApp::Common::Automation::AutomationNotificationKind customKindType); - - static Windows::UI::Xaml::Automation::Peers::AutomationNotificationProcessing - GetWindowsNotificationProcessing(CalculatorApp::Common::Automation::AutomationNotificationProcessing customProcessingType); - - private: - Windows::UI::Xaml::UIElement ^ m_host; - }; -} diff --git a/src/Calculator/Converters/BooleanToVisibilityConverter.cpp b/src/Calculator/Converters/BooleanToVisibilityConverter.cpp index 7746365..ea658d3 100644 --- a/src/Calculator/Converters/BooleanToVisibilityConverter.cpp +++ b/src/Calculator/Converters/BooleanToVisibilityConverter.cpp @@ -1,11 +1,9 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #include "pch.h" #include "BooleanToVisibilityConverter.h" -using namespace CalculatorApp::Common; - using namespace Platform; using namespace Windows::Foundation; using namespace Windows::UI::Xaml; diff --git a/src/Calculator/pch.h b/src/Calculator/pch.h index ff02ef8..add4efd 100644 --- a/src/Calculator/pch.h +++ b/src/Calculator/pch.h @@ -39,16 +39,5 @@ #include "winrt/Windows.UI.ViewManagement.h" #include "winrt/Windows.UI.Xaml.h" -// The following namespaces exist as a convenience to resolve -// ambiguity for Windows types in the Windows::UI::Xaml::Automation::Peers -// namespace that only exist on RS3. -// Once the app switches to min version RS3, the namespaces can be removed. -// TODO - MSFT 12735088 -namespace StandardPeers = Windows::UI::Xaml::Automation::Peers; -namespace CalculatorApp::Common::Automation -{ -} -namespace CustomPeers = CalculatorApp::Common::Automation; - // Project Headers #include "App.xaml.h"