Hello GitHub

This commit is contained in:
Howard Wolosky
2019-01-28 16:24:37 -08:00
parent 456fe5e355
commit c13b8a099e
822 changed files with 276650 additions and 75 deletions

View File

@@ -0,0 +1,26 @@
// 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);
};
}

View File

@@ -0,0 +1,41 @@
// 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);
}
}

View File

@@ -0,0 +1,32 @@
// 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 notifiactions 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;
};
}

View File

@@ -0,0 +1,144 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#include "pch.h"
#include "NarratorAnnouncement.h"
using namespace CalculatorApp::Common::Automation;
using namespace Platform;
namespace CalculatorApp::Common::Automation
{
namespace CalculatorActivityIds
{
StringReference DisplayUpdated(L"DisplayUpdated");
StringReference MaxDigitsReached(L"MaxDigitsReached");
StringReference MemoryCleared(L"MemoryCleared");
StringReference MemoryItemChanged(L"MemorySlotChanged");
StringReference MemoryItemAdded(L"MemorySlotAdded");
StringReference HistoryCleared(L"HistoryCleared");
StringReference CategoryNameChanged(L"CategoryNameChanged");
StringReference UpdateCurrencyRates(L"UpdateCurrencyRates");
StringReference DisplayCopied(L"DisplayCopied");
}
}
NarratorAnnouncement::NarratorAnnouncement(
String^ announcement,
String^ activityId,
AutomationNotificationKind kind,
AutomationNotificationProcessing processing)
:
m_announcement(announcement),
m_activityId(activityId),
m_kind(kind),
m_processing(processing)
{}
String^ NarratorAnnouncement::Announcement::get()
{
return m_announcement;
}
String^ NarratorAnnouncement::ActivityId::get()
{
return m_activityId;
}
AutomationNotificationKind NarratorAnnouncement::Kind::get()
{
return m_kind;
}
AutomationNotificationProcessing NarratorAnnouncement::Processing::get()
{
return m_processing;
}
bool NarratorAnnouncement::IsValid(NarratorAnnouncement^ announcement)
{
return announcement != nullptr
&& announcement->Announcement != nullptr
&& !announcement->Announcement->IsEmpty();
}
NarratorAnnouncement^ CalculatorAnnouncement::GetDisplayUpdatedAnnouncement(String^ announcement)
{
return ref new NarratorAnnouncement(
announcement,
CalculatorActivityIds::DisplayUpdated,
AutomationNotificationKind::Other,
AutomationNotificationProcessing::ImportantMostRecent);
}
NarratorAnnouncement^ CalculatorAnnouncement::GetMaxDigitsReachedAnnouncement(String^ announcement)
{
return ref new NarratorAnnouncement(
announcement,
CalculatorActivityIds::MaxDigitsReached,
AutomationNotificationKind::Other,
AutomationNotificationProcessing::ImportantMostRecent);
}
NarratorAnnouncement^ CalculatorAnnouncement::GetMemoryClearedAnnouncement(String^ announcement)
{
return ref new NarratorAnnouncement(
announcement,
CalculatorActivityIds::MemoryCleared,
AutomationNotificationKind::ItemRemoved,
AutomationNotificationProcessing::ImportantMostRecent);
}
NarratorAnnouncement^ CalculatorAnnouncement::GetMemoryItemChangedAnnouncement(String^ announcement)
{
return ref new NarratorAnnouncement(
announcement,
CalculatorActivityIds::MemoryItemChanged,
AutomationNotificationKind::ActionCompleted,
AutomationNotificationProcessing::MostRecent);
}
NarratorAnnouncement^ CalculatorAnnouncement::GetMemoryItemAddedAnnouncement(String^ announcement)
{
return ref new NarratorAnnouncement(
announcement,
CalculatorActivityIds::MemoryItemAdded,
AutomationNotificationKind::ItemAdded,
AutomationNotificationProcessing::MostRecent);
}
NarratorAnnouncement^ CalculatorAnnouncement::GetHistoryClearedAnnouncement(String^ announcement)
{
return ref new NarratorAnnouncement(
announcement,
CalculatorActivityIds::HistoryCleared,
AutomationNotificationKind::ItemRemoved,
AutomationNotificationProcessing::MostRecent);
}
NarratorAnnouncement^ CalculatorAnnouncement::GetCategoryNameChangedAnnouncement(String^ announcement)
{
return ref new NarratorAnnouncement(
announcement,
CalculatorActivityIds::CategoryNameChanged,
AutomationNotificationKind::ActionCompleted,
AutomationNotificationProcessing::ImportantMostRecent);
}
NarratorAnnouncement^ CalculatorAnnouncement::GetUpdateCurrencyRatesAnnouncement(String^ announcement)
{
return ref new NarratorAnnouncement(
announcement,
CalculatorActivityIds::UpdateCurrencyRates,
AutomationNotificationKind::ActionCompleted,
AutomationNotificationProcessing::ImportantMostRecent);
}
NarratorAnnouncement^ CalculatorAnnouncement::GetDisplayCopiedAnnouncement(String^ announcement)
{
return ref new NarratorAnnouncement(
announcement,
CalculatorActivityIds::DisplayCopied,
AutomationNotificationKind::ActionCompleted,
AutomationNotificationProcessing::ImportantMostRecent);
}

View File

@@ -0,0 +1,94 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#pragma once
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
{
public:
property Platform::String^ Announcement
{
Platform::String^ get();
}
property Platform::String^ ActivityId
{
Platform::String^ get();
}
property AutomationNotificationKind Kind
{
AutomationNotificationKind get();
}
property AutomationNotificationProcessing Processing
{
AutomationNotificationProcessing get();
}
static bool IsValid(NarratorAnnouncement^ announcement);
private:
// Make CalculatorAnnouncement a friend class so it is the only
// class that can access the private constructor.
friend class CalculatorAnnouncement;
NarratorAnnouncement(
Platform::String^ announcement,
Platform::String^ activityId,
AutomationNotificationKind kind,
AutomationNotificationProcessing processing);
Platform::String^ m_announcement;
Platform::String^ m_activityId;
AutomationNotificationKind m_kind;
AutomationNotificationProcessing m_processing;
};
// CalculatorAnnouncement is intended to contain only static methods
// that return announcements made for the Calculator app.
class CalculatorAnnouncement
{
public:
static NarratorAnnouncement^ GetDisplayUpdatedAnnouncement(Platform::String^ announcement);
static NarratorAnnouncement^ GetMaxDigitsReachedAnnouncement(Platform::String^ announcement);
static NarratorAnnouncement^ GetMemoryClearedAnnouncement(Platform::String^ announcement);
static NarratorAnnouncement^ GetMemoryItemChangedAnnouncement(Platform::String^ announcement);
static NarratorAnnouncement^ GetMemoryItemAddedAnnouncement(Platform::String^ announcement);
static NarratorAnnouncement^ GetHistoryClearedAnnouncement(Platform::String^ announcement);
static NarratorAnnouncement^ GetCategoryNameChangedAnnouncement(Platform::String^ announcement);
static NarratorAnnouncement^ GetUpdateCurrencyRatesAnnouncement(Platform::String^ announcement);
static NarratorAnnouncement^ GetDisplayCopiedAnnouncement(Platform::String^ announcement);
};
}

View File

@@ -0,0 +1,64 @@
// 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<INarratorAnnouncementHost^> 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 fallback to LiveRegion
// if not. The availabilty 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();
}

View File

@@ -0,0 +1,31 @@
// 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<INarratorAnnouncementHost^> s_hosts;
};
}

View File

@@ -0,0 +1,50 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
// Implementation of the NarratorNotifier class.
#include "pch.h"
#include "NarratorNotifier.h"
#include "NarratorAnnouncementHostFactory.h"
using namespace CalculatorApp::Common::Automation;
using namespace Platform;
using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Automation;
using namespace Windows::UI::Xaml::Automation::Peers;
DependencyProperty^ NarratorNotifier::s_announcementProperty;
NarratorNotifier::NarratorNotifier()
{
m_announcementHost = NarratorAnnouncementHostFactory::MakeHost();
}
void NarratorNotifier::Announce(NarratorAnnouncement^ announcement)
{
if (NarratorAnnouncement::IsValid(announcement)
&& m_announcementHost != nullptr)
{
m_announcementHost->Announce(announcement);
}
}
void NarratorNotifier::RegisterDependencyProperties()
{
s_announcementProperty = DependencyProperty::Register(
L"Announcement", // The name of the dependency property.
NarratorAnnouncement::typeid, // The type of the dependency property.
NarratorNotifier::typeid, // The owner of the dependency property.
ref new PropertyMetadata(
nullptr, // Default value of the dependency property.
ref new PropertyChangedCallback(OnAnnouncementChanged)));
}
void NarratorNotifier::OnAnnouncementChanged(_In_ DependencyObject^ dependencyObject, _In_ DependencyPropertyChangedEventArgs^ e)
{
auto instance = safe_cast<NarratorNotifier^>(dependencyObject);
if (instance != nullptr)
{
instance->Announce(safe_cast<NarratorAnnouncement^>(e->NewValue));
}
}

View File

@@ -0,0 +1,57 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
// Declaration of the NarratorNotifier class.
#pragma once
#include "INarratorAnnouncementHost.h"
namespace CalculatorApp::Common::Automation
{
public ref class NarratorNotifier sealed : public Windows::UI::Xaml::DependencyObject
{
public:
NarratorNotifier();
void Announce(NarratorAnnouncement^ announcement);
property NarratorAnnouncement^ Announcement
{
NarratorAnnouncement^ get() { return GetAnnouncement(this); }
void set(NarratorAnnouncement^ value)
{
SetAnnouncement(this, value);
}
}
static void RegisterDependencyProperties();
static property Windows::UI::Xaml::DependencyProperty^ AnnouncementProperty
{
Windows::UI::Xaml::DependencyProperty^ get()
{
return s_announcementProperty;
}
}
static NarratorAnnouncement^ GetAnnouncement(Windows::UI::Xaml::DependencyObject^ element)
{
return safe_cast<NarratorAnnouncement^>(element->GetValue(s_announcementProperty));
}
static void SetAnnouncement(Windows::UI::Xaml::DependencyObject^ element, NarratorAnnouncement^ value)
{
element->SetValue(s_announcementProperty, value);
}
private:
static void OnAnnouncementChanged(
_In_ Windows::UI::Xaml::DependencyObject^ dependencyObject,
_In_ Windows::UI::Xaml::DependencyPropertyChangedEventArgs^ eventArgs);
static Windows::UI::Xaml::DependencyProperty^ s_announcementProperty;
private:
INarratorAnnouncementHost^ m_announcementHost;
};
}

View File

@@ -0,0 +1,99 @@
// 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;
}

View File

@@ -0,0 +1,34 @@
// 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;
};
}