Hide or Disable graphing calculator menu item when necessary (#848)

This commit is contained in:
Rudy Huyn 2019-12-06 15:03:07 -08:00 committed by GitHub
parent 81747a0a93
commit 503831895d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 369 additions and 297 deletions

View File

@ -5,6 +5,7 @@
#include "NavCategory.h" #include "NavCategory.h"
#include "AppResourceProvider.h" #include "AppResourceProvider.h"
#include "Common/LocalizationStringUtil.h" #include "Common/LocalizationStringUtil.h"
#include <initializer_list>
using namespace CalculatorApp; using namespace CalculatorApp;
using namespace CalculatorApp::Common; using namespace CalculatorApp::Common;
@ -22,12 +23,6 @@ static constexpr bool SUPPORTS_ALL = true;
static constexpr bool SUPPORTS_NEGATIVE = true; static constexpr bool SUPPORTS_NEGATIVE = true;
static constexpr bool POSITIVE_ONLY = false; static constexpr bool POSITIVE_ONLY = false;
// The order of items in this list determines the order of groups in the menu.
static constexpr array<const NavCategoryGroupInitializer, 2> s_categoryGroupManifest = {
NavCategoryGroupInitializer{ CategoryGroupType::Calculator, L"CalculatorModeTextCaps", L"CalculatorModeText", L"CalculatorModePluralText" },
NavCategoryGroupInitializer{ CategoryGroupType::Converter, L"ConverterModeTextCaps", L"ConverterModeText", L"ConverterModePluralText" }
};
// vvv THESE CONSTANTS SHOULD NEVER CHANGE vvv // vvv THESE CONSTANTS SHOULD NEVER CHANGE vvv
static constexpr int STANDARD_ID = 0; static constexpr int STANDARD_ID = 0;
static constexpr int SCIENTIFIC_ID = 1; static constexpr int SCIENTIFIC_ID = 1;
@ -49,151 +44,263 @@ static constexpr int CURRENCY_ID = 16;
static constexpr int GRAPHING_ID = 17; static constexpr int GRAPHING_ID = 17;
// ^^^ THESE CONSTANTS SHOULD NEVER CHANGE ^^^ // ^^^ THESE CONSTANTS SHOULD NEVER CHANGE ^^^
wchar_t* towchar_t(int number)
{
auto wstr = to_wstring(number);
return _wcsdup(wstr.c_str());
}
extern "C"
{
WINADVAPI LSTATUS APIENTRY RegGetValueW(
_In_ HKEY hkey,
_In_opt_ LPCWSTR lpSubKey,
_In_opt_ LPCWSTR lpValue,
_In_ DWORD dwFlags,
_Out_opt_ LPDWORD pdwType,
_When_(
(dwFlags & 0x7F) == RRF_RT_REG_SZ || (dwFlags & 0x7F) == RRF_RT_REG_EXPAND_SZ || (dwFlags & 0x7F) == (RRF_RT_REG_SZ | RRF_RT_REG_EXPAND_SZ)
|| *pdwType == REG_SZ || *pdwType == REG_EXPAND_SZ,
_Post_z_) _When_((dwFlags & 0x7F) == RRF_RT_REG_MULTI_SZ || *pdwType == REG_MULTI_SZ, _Post_ _NullNull_terminated_)
_Out_writes_bytes_to_opt_(*pcbData, *pcbData) PVOID pvData,
_Inout_opt_ LPDWORD pcbData);
}
bool IsGraphingModeAvailable()
{
static bool supportGraph = Windows::Foundation::Metadata::ApiInformation::IsMethodPresent("Windows.UI.Text.RichEditTextDocument", "GetMath");
return supportGraph;
}
Box<bool> ^ _isGraphingModeEnabledCached = nullptr;
bool IsGraphingModeEnabled()
{
if (!IsGraphingModeAvailable())
{
return false;
}
if (_isGraphingModeEnabledCached != nullptr)
{
return _isGraphingModeEnabledCached->Value;
}
DWORD allowGraphingCalculator{ 0 };
DWORD bufferSize{ sizeof(allowGraphingCalculator) };
// Make sure to call RegGetValueW only on Windows 10 1903+
if (RegGetValueW(
HKEY_LOCAL_MACHINE,
L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\Calculator",
L"AllowGraphingCalculator",
RRF_RT_REG_DWORD | RRF_RT_REG_BINARY,
nullptr,
reinterpret_cast<LPBYTE>(&allowGraphingCalculator),
&bufferSize)
== ERROR_SUCCESS)
{
_isGraphingModeEnabledCached = allowGraphingCalculator != 0;
}
else
{
_isGraphingModeEnabledCached = true;
}
return _isGraphingModeEnabledCached->Value;
}
// The order of items in this list determines the order of items in the menu. // The order of items in this list determines the order of items in the menu.
static constexpr array<const NavCategoryInitializer, 18> s_categoryManifest = { NavCategoryInitializer{ ViewMode::Standard, static const list<NavCategoryInitializer> s_categoryManifest = [] {
STANDARD_ID, auto res = list<NavCategoryInitializer>{ NavCategoryInitializer{ ViewMode::Standard,
L"Standard", STANDARD_ID,
L"StandardMode", L"Standard",
L"\uE8EF", L"StandardMode",
CategoryGroupType::Calculator, L"\uE8EF",
MyVirtualKey::Number1, CategoryGroupType::Calculator,
SUPPORTS_ALL }, MyVirtualKey::Number1,
NavCategoryInitializer{ ViewMode::Scientific, L"1",
SCIENTIFIC_ID, SUPPORTS_ALL,
L"Scientific", true },
L"ScientificMode", NavCategoryInitializer{ ViewMode::Scientific,
L"\uF196", SCIENTIFIC_ID,
CategoryGroupType::Calculator, L"Scientific",
MyVirtualKey::Number2, L"ScientificMode",
SUPPORTS_ALL }, L"\uF196",
NavCategoryInitializer{ ViewMode::Programmer, CategoryGroupType::Calculator,
PROGRAMMER_ID, MyVirtualKey::Number2,
L"Programmer", L"2",
L"ProgrammerMode", SUPPORTS_ALL,
L"\uECCE", true } };
CategoryGroupType::Calculator,
MyVirtualKey::Number3, int currentIndex = 3;
SUPPORTS_ALL }, bool supportGraphingCalculator = IsGraphingModeAvailable();
NavCategoryInitializer{ ViewMode::Graphing, if (supportGraphingCalculator)
GRAPHING_ID, {
L"Graphing", const bool isEnabled = IsGraphingModeEnabled();
L"GraphingCalculatorMode", res.push_back(NavCategoryInitializer{ ViewMode::Graphing,
L"\uF770", GRAPHING_ID,
CategoryGroupType::Calculator, L"Graphing",
MyVirtualKey::Number5, L"GraphingCalculatorMode",
SUPPORTS_ALL }, L"\uF770",
NavCategoryInitializer{ ViewMode::Date, CategoryGroupType::Calculator,
DATE_ID, MyVirtualKey::Number3,
L"Date", L"3",
L"DateCalculationMode", SUPPORTS_ALL,
L"\uE787", isEnabled });
CategoryGroupType::Calculator, ++currentIndex;
MyVirtualKey::Number4, }
SUPPORTS_ALL }, res.insert(
NavCategoryInitializer{ ViewMode::Currency, res.end(),
CURRENCY_ID, { NavCategoryInitializer{ ViewMode::Programmer,
L"Currency", PROGRAMMER_ID,
L"CategoryName_Currency", L"Programmer",
L"\uEB0D", L"ProgrammerMode",
CategoryGroupType::Converter, L"\uECCE",
MyVirtualKey::None, CategoryGroupType::Calculator,
POSITIVE_ONLY }, supportGraphingCalculator ? MyVirtualKey::Number4 : MyVirtualKey::Number3,
NavCategoryInitializer{ ViewMode::Volume, towchar_t(currentIndex++),
VOLUME_ID, SUPPORTS_ALL,
L"Volume", true },
L"CategoryName_Volume", NavCategoryInitializer{ ViewMode::Date,
L"\uF1AA", DATE_ID,
CategoryGroupType::Converter, L"Date",
MyVirtualKey::None, L"DateCalculationMode",
POSITIVE_ONLY }, L"\uE787",
NavCategoryInitializer{ ViewMode::Length, CategoryGroupType::Calculator,
LENGTH_ID, supportGraphingCalculator ? MyVirtualKey::Number5 : MyVirtualKey::Number4,
L"Length", towchar_t(currentIndex++),
L"CategoryName_Length", SUPPORTS_ALL,
L"\uECC6", true },
CategoryGroupType::Converter, NavCategoryInitializer{ ViewMode::Currency,
MyVirtualKey::None, CURRENCY_ID,
POSITIVE_ONLY }, L"Currency",
NavCategoryInitializer{ ViewMode::Weight, L"CategoryName_Currency",
WEIGHT_ID, L"\uEB0D",
L"Weight and Mass", CategoryGroupType::Converter,
L"CategoryName_Weight", MyVirtualKey::None,
L"\uF4C1", nullptr,
CategoryGroupType::Converter, POSITIVE_ONLY,
MyVirtualKey::None, true },
POSITIVE_ONLY }, NavCategoryInitializer{ ViewMode::Volume,
NavCategoryInitializer{ ViewMode::Temperature, VOLUME_ID,
TEMPERATURE_ID, L"Volume",
L"Temperature", L"CategoryName_Volume",
L"CategoryName_Temperature", L"\uF1AA",
L"\uE7A3", CategoryGroupType::Converter,
CategoryGroupType::Converter, MyVirtualKey::None,
MyVirtualKey::None, nullptr,
SUPPORTS_NEGATIVE }, POSITIVE_ONLY,
NavCategoryInitializer{ ViewMode::Energy, true },
ENERGY_ID, NavCategoryInitializer{ ViewMode::Length,
L"Energy", LENGTH_ID,
L"CategoryName_Energy", L"Length",
L"\uECAD", L"CategoryName_Length",
CategoryGroupType::Converter, L"\uECC6",
MyVirtualKey::None, CategoryGroupType::Converter,
POSITIVE_ONLY }, MyVirtualKey::None,
NavCategoryInitializer{ ViewMode::Area, nullptr,
AREA_ID, POSITIVE_ONLY,
L"Area", true },
L"CategoryName_Area", NavCategoryInitializer{ ViewMode::Weight,
L"\uE809", WEIGHT_ID,
CategoryGroupType::Converter, L"Weight and Mass",
MyVirtualKey::None, L"CategoryName_Weight",
POSITIVE_ONLY }, L"\uF4C1",
NavCategoryInitializer{ ViewMode::Speed, CategoryGroupType::Converter,
SPEED_ID, MyVirtualKey::None,
L"Speed", nullptr,
L"CategoryName_Speed", POSITIVE_ONLY,
L"\uEADA", true },
CategoryGroupType::Converter, NavCategoryInitializer{ ViewMode::Temperature,
MyVirtualKey::None, TEMPERATURE_ID,
POSITIVE_ONLY }, L"Temperature",
NavCategoryInitializer{ ViewMode::Time, L"CategoryName_Temperature",
TIME_ID, L"\uE7A3",
L"Time", CategoryGroupType::Converter,
L"CategoryName_Time", MyVirtualKey::None,
L"\uE917", nullptr,
CategoryGroupType::Converter, SUPPORTS_NEGATIVE,
MyVirtualKey::None, true },
POSITIVE_ONLY }, NavCategoryInitializer{ ViewMode::Energy,
NavCategoryInitializer{ ViewMode::Power, ENERGY_ID,
POWER_ID, L"Energy",
L"Power", L"CategoryName_Energy",
L"CategoryName_Power", L"\uECAD",
L"\uE945", CategoryGroupType::Converter,
CategoryGroupType::Converter, MyVirtualKey::None,
MyVirtualKey::None, nullptr,
SUPPORTS_NEGATIVE }, POSITIVE_ONLY,
NavCategoryInitializer{ ViewMode::Data, true },
DATA_ID, NavCategoryInitializer{ ViewMode::Area,
L"Data", AREA_ID,
L"CategoryName_Data", L"Area",
L"\uF20F", L"CategoryName_Area",
CategoryGroupType::Converter, L"\uE809",
MyVirtualKey::None, CategoryGroupType::Converter,
POSITIVE_ONLY }, MyVirtualKey::None,
NavCategoryInitializer{ ViewMode::Pressure, nullptr,
PRESSURE_ID, POSITIVE_ONLY,
L"Pressure", true },
L"CategoryName_Pressure", NavCategoryInitializer{ ViewMode::Speed,
L"\uEC4A", SPEED_ID,
CategoryGroupType::Converter, L"Speed",
MyVirtualKey::None, L"CategoryName_Speed",
POSITIVE_ONLY }, L"\uEADA",
NavCategoryInitializer{ ViewMode::Angle, CategoryGroupType::Converter,
ANGLE_ID, MyVirtualKey::None,
L"Angle", nullptr,
L"CategoryName_Angle", POSITIVE_ONLY,
L"\uF515", true },
CategoryGroupType::Converter, NavCategoryInitializer{ ViewMode::Time,
MyVirtualKey::None, TIME_ID,
SUPPORTS_NEGATIVE } }; L"Time",
L"CategoryName_Time",
L"\uE917",
CategoryGroupType::Converter,
MyVirtualKey::None,
nullptr,
POSITIVE_ONLY,
true },
NavCategoryInitializer{ ViewMode::Power,
POWER_ID,
L"Power",
L"CategoryName_Power",
L"\uE945",
CategoryGroupType::Converter,
MyVirtualKey::None,
nullptr,
SUPPORTS_NEGATIVE,
true },
NavCategoryInitializer{ ViewMode::Data,
DATA_ID,
L"Data",
L"CategoryName_Data",
L"\uF20F",
CategoryGroupType::Converter,
MyVirtualKey::None,
nullptr,
POSITIVE_ONLY,
true },
NavCategoryInitializer{ ViewMode::Pressure,
PRESSURE_ID,
L"Pressure",
L"CategoryName_Pressure",
L"\uEC4A",
CategoryGroupType::Converter,
MyVirtualKey::None,
nullptr,
POSITIVE_ONLY,
true },
NavCategoryInitializer{ ViewMode::Angle,
ANGLE_ID,
L"Angle",
L"CategoryName_Angle",
L"\uF515",
CategoryGroupType::Converter,
MyVirtualKey::None,
nullptr,
SUPPORTS_NEGATIVE,
true } });
return res;
}();
// This function should only be used when storing the mode to app data. // This function should only be used when storing the mode to app data.
int NavCategory::Serialize(ViewMode mode) int NavCategory::Serialize(ViewMode mode)
@ -220,6 +327,14 @@ ViewMode NavCategory::Deserialize(Platform::Object ^ obj)
if (iter != s_categoryManifest.end()) if (iter != s_categoryManifest.end())
{ {
if (iter->viewMode == ViewMode::Graphing)
{
// check if the user is allowed to use this feature
if (!IsGraphingModeEnabled())
{
return ViewMode::None;
}
}
return iter->viewMode; return iter->viewMode;
} }
} }
@ -402,10 +517,12 @@ NavCategoryGroup::NavCategoryGroup(const NavCategoryGroupInitializer& groupIniti
categoryName, categoryName,
categoryAutomationName, categoryAutomationName,
StringReference(categoryInitializer.glyph), StringReference(categoryInitializer.glyph),
resProvider->GetResourceString(nameResourceKey + "AccessKey"), categoryInitializer.accessKey != nullptr ? ref new String(categoryInitializer.accessKey)
: resProvider->GetResourceString(nameResourceKey + "AccessKey"),
groupMode, groupMode,
categoryInitializer.viewMode, categoryInitializer.viewMode,
categoryInitializer.supportsNegative)); categoryInitializer.supportsNegative,
categoryInitializer.isEnabled));
} }
} }
} }
@ -420,29 +537,12 @@ IObservableVector<NavCategoryGroup ^> ^ NavCategoryGroup::CreateMenuOptions()
NavCategoryGroup ^ NavCategoryGroup::CreateCalculatorCategory() NavCategoryGroup ^ NavCategoryGroup::CreateCalculatorCategory()
{ {
return ref new NavCategoryGroup(s_categoryGroupManifest.at(0)); return ref new NavCategoryGroup(
NavCategoryGroupInitializer{ CategoryGroupType::Calculator, L"CalculatorModeTextCaps", L"CalculatorModeText", L"CalculatorModePluralText" });
} }
NavCategoryGroup ^ NavCategoryGroup::CreateConverterCategory() NavCategoryGroup ^ NavCategoryGroup::CreateConverterCategory()
{ {
return ref new NavCategoryGroup(s_categoryGroupManifest.at(1)); return ref new NavCategoryGroup(
} NavCategoryGroupInitializer{ CategoryGroupType::Converter, L"ConverterModeTextCaps", L"ConverterModeText", L"ConverterModePluralText" });
vector<NavCategoryInitializer> NavCategoryGroup::GetInitializerCategoryGroup(CategoryGroupType groupType)
{
vector<NavCategoryInitializer> initializers{};
copy_if(begin(s_categoryManifest), end(s_categoryManifest), back_inserter(initializers), [groupType](const NavCategoryInitializer& initializer) {
return initializer.groupType == groupType;
});
return initializers;
}
String ^ NavCategoryGroup::GetHeaderResourceKey(CategoryGroupType type)
{
auto iter = find_if(begin(s_categoryGroupManifest), end(s_categoryGroupManifest), [type](const NavCategoryGroupInitializer& initializer) {
return initializer.type == type;
});
return (iter != s_categoryGroupManifest.end()) ? StringReference(iter->headerResourceKey) : nullptr;
} }

View File

@ -67,7 +67,9 @@ namespace CalculatorApp
wchar_t const* glyph, wchar_t const* glyph,
CategoryGroupType group, CategoryGroupType group,
MyVirtualKey vKey, MyVirtualKey vKey,
bool categorySupportsNegative) wchar_t const* aKey,
bool categorySupportsNegative,
bool enabled)
: viewMode(mode) : viewMode(mode)
, serializationId(id) , serializationId(id)
, friendlyName(name) , friendlyName(name)
@ -75,7 +77,9 @@ namespace CalculatorApp
, glyph(glyph) , glyph(glyph)
, groupType(group) , groupType(group)
, virtualKey(vKey) , virtualKey(vKey)
, accessKey(aKey)
, supportsNegative(categorySupportsNegative) , supportsNegative(categorySupportsNegative)
, isEnabled(enabled)
{ {
} }
@ -86,7 +90,9 @@ namespace CalculatorApp
const wchar_t* const glyph; const wchar_t* const glyph;
const CategoryGroupType groupType; const CategoryGroupType groupType;
const MyVirtualKey virtualKey; const MyVirtualKey virtualKey;
const wchar_t* const accessKey;
const bool supportsNegative; const bool supportsNegative;
const bool isEnabled;
}; };
private private
@ -110,45 +116,17 @@ namespace CalculatorApp
{ {
public: public:
OBSERVABLE_OBJECT(); OBSERVABLE_OBJECT();
PROPERTY_R(Platform::String ^, Name);
PROPERTY_R(Platform::String ^, AutomationName);
PROPERTY_R(Platform::String ^, Glyph);
PROPERTY_R(ViewMode, Mode);
PROPERTY_R(Platform::String ^, AccessKey);
PROPERTY_R(bool, SupportsNegative);
PROPERTY_R(bool, IsEnabled);
property Platform::String property Platform::String
^ Name { Platform::String ^ get() { return m_name; } } ^ AutomationId { Platform::String ^ get() { return m_Mode.ToString(); } }
property Platform::String
^ AutomationName { Platform::String ^ get() { return m_automationName; } }
property Platform::String
^ Glyph { Platform::String ^ get() { return m_glyph; } }
property int Position
{
int get()
{
return m_position;
}
}
property ViewMode Mode
{
ViewMode get()
{
return m_viewMode;
}
}
property Platform::String
^ AutomationId { Platform::String ^ get() { return m_viewMode.ToString(); } }
property Platform::String
^ AccessKey { Platform::String ^ get() { return m_accessKey; } }
property bool SupportsNegative
{
bool get()
{
return m_supportsNegative;
}
}
// For saving/restoring last mode used. // For saving/restoring last mode used.
static int Serialize(ViewMode mode); static int Serialize(ViewMode mode);
@ -180,16 +158,17 @@ namespace CalculatorApp
Platform::String ^ accessKey, Platform::String ^ accessKey,
Platform::String ^ mode, Platform::String ^ mode,
ViewMode viewMode, ViewMode viewMode,
bool supportsNegative) bool supportsNegative,
: m_name(name) bool isEnabled)
, m_automationName(automationName) : m_Name(name)
, m_glyph(glyph) , m_AutomationName(automationName)
, m_accessKey(accessKey) , m_Glyph(glyph)
, m_mode(mode) , m_AccessKey(accessKey)
, m_viewMode(viewMode) , m_modeString(mode)
, m_supportsNegative(supportsNegative) , m_Mode(viewMode)
, m_SupportsNegative(supportsNegative)
, m_IsEnabled(isEnabled)
{ {
m_position = NavCategory::GetPosition(m_viewMode);
} }
static std::vector<MyVirtualKey> GetCategoryAcceleratorKeys(); static std::vector<MyVirtualKey> GetCategoryAcceleratorKeys();
@ -197,14 +176,7 @@ namespace CalculatorApp
private: private:
static bool IsModeInCategoryGroup(ViewMode mode, CategoryGroupType groupType); static bool IsModeInCategoryGroup(ViewMode mode, CategoryGroupType groupType);
ViewMode m_viewMode; Platform::String ^ m_modeString;
Platform::String ^ m_name;
Platform::String ^ m_automationName;
Platform::String ^ m_glyph;
Platform::String ^ m_accessKey;
Platform::String ^ m_mode;
int m_position;
bool m_supportsNegative;
}; };
[Windows::UI::Xaml::Data::Bindable] public ref class NavCategoryGroup sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged [Windows::UI::Xaml::Data::Bindable] public ref class NavCategoryGroup sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
@ -218,15 +190,11 @@ namespace CalculatorApp
static Windows::Foundation::Collections::IObservableVector<NavCategoryGroup ^> ^ CreateMenuOptions(); static Windows::Foundation::Collections::IObservableVector<NavCategoryGroup ^> ^ CreateMenuOptions();
static Platform::String ^ GetHeaderResourceKey(CategoryGroupType type);
internal : static NavCategoryGroup ^ CreateCalculatorCategory(); internal : static NavCategoryGroup ^ CreateCalculatorCategory();
static NavCategoryGroup ^ CreateConverterCategory(); static NavCategoryGroup ^ CreateConverterCategory();
private: private:
NavCategoryGroup(const NavCategoryGroupInitializer& groupInitializer); NavCategoryGroup(const NavCategoryGroupInitializer& groupInitializer);
static std::vector<NavCategoryInitializer> GetInitializerCategoryGroup(CategoryGroupType groupType);
}; };
} }
} }

View File

@ -40,6 +40,7 @@
#include "winrt/Windows.Globalization.DateTimeFormatting.h" #include "winrt/Windows.Globalization.DateTimeFormatting.h"
#include "winrt/Windows.System.UserProfile.h" #include "winrt/Windows.System.UserProfile.h"
#include "winrt/Windows.UI.Xaml.h" #include "winrt/Windows.UI.Xaml.h"
#include "winrt/Windows.Foundation.Metadata.h"
// The following namespaces exist as a convenience to resolve // The following namespaces exist as a convenience to resolve
// ambiguity for Windows types in the Windows::UI::Xaml::Automation::Peers // ambiguity for Windows types in the Windows::UI::Xaml::Automation::Peers

View File

@ -3163,10 +3163,6 @@
<value>AB</value> <value>AB</value>
<comment>AccessKey for the About button. {StringCategory="Accelerator"}</comment> <comment>AccessKey for the About button. {StringCategory="Accelerator"}</comment>
</data> </data>
<data name="DateCalculationModeAccessKey" xml:space="preserve">
<value>4</value>
<comment>AccessKey for the Date Calculation mode navbar item. {StringCategory="Accelerator"}</comment>
</data>
<data name="HistoryButton.AccessKey" xml:space="preserve"> <data name="HistoryButton.AccessKey" xml:space="preserve">
<value>I</value> <value>I</value>
<comment>Access key for the History button. {StringCategory="Accelerator"}</comment> <comment>Access key for the History button. {StringCategory="Accelerator"}</comment>
@ -3179,18 +3175,6 @@
<value>H</value> <value>H</value>
<comment>Access key for the Hamburger button. {StringCategory="Accelerator"}</comment> <comment>Access key for the Hamburger button. {StringCategory="Accelerator"}</comment>
</data> </data>
<data name="ProgrammerModeAccessKey" xml:space="preserve">
<value>3</value>
<comment>AccessKey for the Programmer mode navbar item. {StringCategory="Accelerator"}</comment>
</data>
<data name="ScientificModeAccessKey" xml:space="preserve">
<value>2</value>
<comment>AccessKey for the Scientific mode navbar item. {StringCategory="Accelerator"}</comment>
</data>
<data name="StandardModeAccessKey" xml:space="preserve">
<value>1</value>
<comment>AccessKey for the Standard mode navbar item. {StringCategory="Accelerator"}</comment>
</data>
<data name="CategoryName_AngleAccessKey" xml:space="preserve"> <data name="CategoryName_AngleAccessKey" xml:space="preserve">
<value>AN</value> <value>AN</value>
<comment>AccessKey for the angle converter navbar item. {StringCategory="Accelerator"}</comment> <comment>AccessKey for the angle converter navbar item. {StringCategory="Accelerator"}</comment>
@ -4218,4 +4202,4 @@
<value>Current mode is graph mode</value> <value>Current mode is graph mode</value>
<comment>Announcement used in Graphing Calculator when switching to the graph mode</comment> <comment>Announcement used in Graphing Calculator when switching to the graph mode</comment>
</data> </data>
</root> </root>

View File

@ -38,28 +38,29 @@
</Grid.RowDefinitions> </Grid.RowDefinitions>
<Button x:Name="KGFEquationButton" <Button x:Name="KGFEquationButton"
x:Uid="equationAnalysisBack" x:Uid="equationAnalysisBack"
MinWidth="44" MinWidth="44"
MinHeight="44" MinHeight="44"
VerticalAlignment="Stretch" VerticalAlignment="Stretch"
Background="{TemplateBinding EquationColor}" Background="{TemplateBinding EquationColor}"
Foreground="{StaticResource SystemChromeWhiteColor}" Foreground="{StaticResource SystemChromeWhiteColor}"
BorderThickness="0"> BorderThickness="0">
<Button.Content> <Button.Content>
<StackPanel x:Name="FunctionNumberLabel" <StackPanel x:Name="FunctionNumberLabel"
HorizontalAlignment="Center" Margin="5,0"
VerticalAlignment="Center" HorizontalAlignment="Center"
Background="Transparent" VerticalAlignment="Center"
Orientation="Horizontal" Background="Transparent"
Margin="5,0"> Orientation="Horizontal">
<FontIcon VerticalAlignment="Center" <FontIcon Margin="0,0,6,0"
VerticalAlignment="Center"
FontFamily="{ThemeResource SymbolThemeFontFamily}" FontFamily="{ThemeResource SymbolThemeFontFamily}"
FontSize="16" FontSize="16"
Glyph="&#xE72B;" Margin="0,0,6,0"/> Glyph="&#xE72B;"/>
<FontIcon FontFamily="{StaticResource CalculatorFontFamily}" Glyph="&#xF893;"/> <FontIcon FontFamily="{StaticResource CalculatorFontFamily}" Glyph="&#xF893;"/>
<TextBlock Margin="-5,19,0,0" <TextBlock Margin="-5,19,0,0"
FontSize="11" FontSize="11"
Text="{TemplateBinding EquationButtonContentIndex}"/> Text="{TemplateBinding EquationButtonContentIndex}"/>
</StackPanel> </StackPanel>
</Button.Content> </Button.Content>
@ -201,9 +202,9 @@
<ContentPresenter x:Name="DescriptionPresenter" <ContentPresenter x:Name="DescriptionPresenter"
Grid.Row="2" Grid.Row="2"
Foreground="{ThemeResource SystemControlDescriptionTextForegroundBrush}" Foreground="{ThemeResource SystemControlDescriptionTextForegroundBrush}"
x:Load="False"
AutomationProperties.AccessibilityView="Raw" AutomationProperties.AccessibilityView="Raw"
Content="{TemplateBinding Description}"/> Content="{TemplateBinding Description}"
x:Load="False"/>
</Grid> </Grid>

View File

@ -499,6 +499,7 @@ MUXC::NavigationViewItem ^ MainPage::CreateNavViewItemFromCategory(NavCategory ^
item->Content = category->Name; item->Content = category->Name;
item->AccessKey = category->AccessKey; item->AccessKey = category->AccessKey;
item->IsEnabled = category->IsEnabled;
item->Style = static_cast<Windows::UI::Xaml::Style ^>(Resources->Lookup(L"NavViewItemStyle")); item->Style = static_cast<Windows::UI::Xaml::Style ^>(Resources->Lookup(L"NavViewItemStyle"));
AutomationProperties::SetName(item, category->AutomationName); AutomationProperties::SetName(item, category->AutomationName);

View File

@ -103,8 +103,6 @@ namespace CalculatorUnitTests
{ {
constexpr auto sc_Language_EN = L"en-US"; constexpr auto sc_Language_EN = L"en-US";
const UCM::Category CURRENCY_CATEGORY = { NavCategory::Serialize(ViewMode::Currency), L"Currency", false /*supportsNegative*/ };
unique_ptr<CurrencyDataLoader> MakeLoaderWithResults(String ^ staticResponse, String ^ allRatiosResponse) unique_ptr<CurrencyDataLoader> MakeLoaderWithResults(String ^ staticResponse, String ^ allRatiosResponse)
{ {
auto client = make_unique<MockCurrencyHttpClientWithResult>(staticResponse, allRatiosResponse); auto client = make_unique<MockCurrencyHttpClientWithResult>(staticResponse, allRatiosResponse);
@ -382,8 +380,12 @@ TEST_METHOD(Load_Success_LoadedFromWeb)
} }
; ;
TEST_CLASS(CurrencyConverterUnitTests){ const UCM::Unit GetUnit(const vector<UCM::Unit>& unitList, const wstring& target){ TEST_CLASS(CurrencyConverterUnitTests){
return *find_if(begin(unitList), end(unitList), [&target](const UCM::Unit& u) { return u.abbreviation == target; });
const UCM::Category CURRENCY_CATEGORY = { NavCategory::Serialize(ViewMode::Currency), L"Currency", false /*supportsNegative*/ };
const UCM::Unit GetUnit(const vector<UCM::Unit>& unitList, const wstring& target){
return *find_if(begin(unitList), end(unitList), [&target](const UCM::Unit& u) { return u.abbreviation == target; });
} }
TEST_METHOD(Loaded_LoadOrderedUnits) TEST_METHOD(Loaded_LoadOrderedUnits)

View File

@ -260,8 +260,8 @@ namespace CalculatorUnitTests
ViewMode orderedModes[] = { ViewMode orderedModes[] = {
ViewMode::Standard, ViewMode::Standard,
ViewMode::Scientific, ViewMode::Scientific,
ViewMode::Programmer,
ViewMode::Graphing, ViewMode::Graphing,
ViewMode::Programmer,
ViewMode::Date, ViewMode::Date,
ViewMode::Currency, ViewMode::Currency,
ViewMode::Volume, ViewMode::Volume,
@ -291,7 +291,7 @@ namespace CalculatorUnitTests
void NavCategoryUnitTests::GetPosition() void NavCategoryUnitTests::GetPosition()
{ {
// Position is the 1-based ordering of modes // Position is the 1-based ordering of modes
vector<ViewMode> orderedModes = { ViewMode::Standard, ViewMode::Scientific, ViewMode::Programmer, ViewMode::Graphing, ViewMode::Date, vector<ViewMode> orderedModes = { ViewMode::Standard, ViewMode::Scientific, ViewMode::Graphing, ViewMode::Programmer, ViewMode::Date,
ViewMode::Currency, ViewMode::Volume, ViewMode::Length, ViewMode::Weight, ViewMode::Temperature, ViewMode::Currency, ViewMode::Volume, ViewMode::Length, ViewMode::Weight, ViewMode::Temperature,
ViewMode::Energy, ViewMode::Area, ViewMode::Speed, ViewMode::Time, ViewMode::Power, ViewMode::Energy, ViewMode::Area, ViewMode::Speed, ViewMode::Time, ViewMode::Power,
ViewMode::Data, ViewMode::Pressure, ViewMode::Angle }; ViewMode::Data, ViewMode::Pressure, ViewMode::Angle };
@ -319,8 +319,8 @@ namespace CalculatorUnitTests
{ {
VERIFY_ARE_EQUAL(0, NavCategory::GetIndexInGroup(ViewMode::Standard, CategoryGroupType::Calculator)); VERIFY_ARE_EQUAL(0, NavCategory::GetIndexInGroup(ViewMode::Standard, CategoryGroupType::Calculator));
VERIFY_ARE_EQUAL(1, NavCategory::GetIndexInGroup(ViewMode::Scientific, CategoryGroupType::Calculator)); VERIFY_ARE_EQUAL(1, NavCategory::GetIndexInGroup(ViewMode::Scientific, CategoryGroupType::Calculator));
VERIFY_ARE_EQUAL(2, NavCategory::GetIndexInGroup(ViewMode::Programmer, CategoryGroupType::Calculator)); VERIFY_ARE_EQUAL(2, NavCategory::GetIndexInGroup(ViewMode::Graphing, CategoryGroupType::Calculator));
VERIFY_ARE_EQUAL(3, NavCategory::GetIndexInGroup(ViewMode::Graphing, CategoryGroupType::Calculator)); VERIFY_ARE_EQUAL(3, NavCategory::GetIndexInGroup(ViewMode::Programmer, CategoryGroupType::Calculator));
VERIFY_ARE_EQUAL(4, NavCategory::GetIndexInGroup(ViewMode::Date, CategoryGroupType::Calculator)); VERIFY_ARE_EQUAL(4, NavCategory::GetIndexInGroup(ViewMode::Date, CategoryGroupType::Calculator));
VERIFY_ARE_EQUAL(0, NavCategory::GetIndexInGroup(ViewMode::Currency, CategoryGroupType::Converter)); VERIFY_ARE_EQUAL(0, NavCategory::GetIndexInGroup(ViewMode::Currency, CategoryGroupType::Converter));
@ -345,9 +345,17 @@ namespace CalculatorUnitTests
{ {
VERIFY_ARE_EQUAL(ViewMode::Standard, NavCategory::GetViewModeForVirtualKey(MyVirtualKey::Number1)); VERIFY_ARE_EQUAL(ViewMode::Standard, NavCategory::GetViewModeForVirtualKey(MyVirtualKey::Number1));
VERIFY_ARE_EQUAL(ViewMode::Scientific, NavCategory::GetViewModeForVirtualKey(MyVirtualKey::Number2)); VERIFY_ARE_EQUAL(ViewMode::Scientific, NavCategory::GetViewModeForVirtualKey(MyVirtualKey::Number2));
VERIFY_ARE_EQUAL(ViewMode::Programmer, NavCategory::GetViewModeForVirtualKey(MyVirtualKey::Number3)); if (Windows::Foundation::Metadata::ApiInformation::IsMethodPresent("Windows.UI.Text.RichEditTextDocument", "GetMath"))
VERIFY_ARE_EQUAL(ViewMode::Date, NavCategory::GetViewModeForVirtualKey(MyVirtualKey::Number4)); {
VERIFY_ARE_EQUAL(ViewMode::Graphing, NavCategory::GetViewModeForVirtualKey(MyVirtualKey::Number5)); VERIFY_ARE_EQUAL(ViewMode::Graphing, NavCategory::GetViewModeForVirtualKey(MyVirtualKey::Number3));
VERIFY_ARE_EQUAL(ViewMode::Programmer, NavCategory::GetViewModeForVirtualKey(MyVirtualKey::Number4));
VERIFY_ARE_EQUAL(ViewMode::Date, NavCategory::GetViewModeForVirtualKey(MyVirtualKey::Number5));
}
else
{
VERIFY_ARE_EQUAL(ViewMode::Programmer, NavCategory::GetViewModeForVirtualKey(MyVirtualKey::Number3));
VERIFY_ARE_EQUAL(ViewMode::Date, NavCategory::GetViewModeForVirtualKey(MyVirtualKey::Number4));
}
} }
TEST_CLASS(NavCategoryGroupUnitTests) TEST_CLASS(NavCategoryGroupUnitTests)
@ -356,14 +364,13 @@ namespace CalculatorUnitTests
TEST_METHOD(CreateNavCategoryGroup); TEST_METHOD(CreateNavCategoryGroup);
private: private:
void ValidateNavCategory(IObservableVector<NavCategory ^> ^ categories, unsigned int index, ViewMode expectedMode, int expectedPosition) void ValidateNavCategory(IObservableVector<NavCategory ^> ^ categories, unsigned int index, ViewMode expectedMode)
{ {
VERIFY_IS_LESS_THAN(0u, categories->Size); VERIFY_IS_LESS_THAN(0u, categories->Size);
VERIFY_IS_GREATER_THAN(categories->Size, index); VERIFY_IS_GREATER_THAN(categories->Size, index);
NavCategory ^ category = categories->GetAt(index); NavCategory ^ category = categories->GetAt(index);
VERIFY_ARE_EQUAL(expectedMode, category->Mode); VERIFY_ARE_EQUAL(expectedMode, category->Mode);
VERIFY_ARE_EQUAL(expectedPosition, category->Position);
} }
}; };
@ -378,29 +385,37 @@ namespace CalculatorUnitTests
IObservableVector<NavCategory^>^ calculatorCategories = calculatorGroup->Categories; IObservableVector<NavCategory^>^ calculatorCategories = calculatorGroup->Categories;
VERIFY_ARE_EQUAL(5, calculatorCategories->Size); VERIFY_ARE_EQUAL(5, calculatorCategories->Size);
ValidateNavCategory(calculatorCategories, 0u, ViewMode::Standard, 1); ValidateNavCategory(calculatorCategories, 0u, ViewMode::Standard);
ValidateNavCategory(calculatorCategories, 1u, ViewMode::Scientific, 2); ValidateNavCategory(calculatorCategories, 1u, ViewMode::Scientific);
ValidateNavCategory(calculatorCategories, 2u, ViewMode::Programmer, 3); if (Windows::Foundation::Metadata::ApiInformation::IsMethodPresent("Windows.UI.Text.RichEditTextDocument", "GetMath"))
ValidateNavCategory(calculatorCategories, 3u, ViewMode::Graphing, 4); {
ValidateNavCategory(calculatorCategories, 4u, ViewMode::Date, 5); ValidateNavCategory(calculatorCategories, 2u, ViewMode::Graphing);
ValidateNavCategory(calculatorCategories, 3u, ViewMode::Programmer);
ValidateNavCategory(calculatorCategories, 4u, ViewMode::Date);
}
else
{
ValidateNavCategory(calculatorCategories, 2u, ViewMode::Programmer);
ValidateNavCategory(calculatorCategories, 3u, ViewMode::Date);
}
NavCategoryGroup ^ converterGroup = menuOptions->GetAt(1); NavCategoryGroup ^ converterGroup = menuOptions->GetAt(1);
VERIFY_ARE_EQUAL(CategoryGroupType::Converter, converterGroup->GroupType); VERIFY_ARE_EQUAL(CategoryGroupType::Converter, converterGroup->GroupType);
IObservableVector<NavCategory ^> ^ converterCategories = converterGroup->Categories; IObservableVector<NavCategory ^> ^ converterCategories = converterGroup->Categories;
VERIFY_ARE_EQUAL(13, converterCategories->Size); VERIFY_ARE_EQUAL(13, converterCategories->Size);
ValidateNavCategory(converterCategories, 0u, ViewMode::Currency, 6); ValidateNavCategory(converterCategories, 0u, ViewMode::Currency);
ValidateNavCategory(converterCategories, 1u, ViewMode::Volume, 7); ValidateNavCategory(converterCategories, 1u, ViewMode::Volume);
ValidateNavCategory(converterCategories, 2u, ViewMode::Length, 8); ValidateNavCategory(converterCategories, 2u, ViewMode::Length);
ValidateNavCategory(converterCategories, 3u, ViewMode::Weight, 9); ValidateNavCategory(converterCategories, 3u, ViewMode::Weight);
ValidateNavCategory(converterCategories, 4u, ViewMode::Temperature, 10); ValidateNavCategory(converterCategories, 4u, ViewMode::Temperature);
ValidateNavCategory(converterCategories, 5u, ViewMode::Energy, 11); ValidateNavCategory(converterCategories, 5u, ViewMode::Energy);
ValidateNavCategory(converterCategories, 6u, ViewMode::Area, 12); ValidateNavCategory(converterCategories, 6u, ViewMode::Area);
ValidateNavCategory(converterCategories, 7u, ViewMode::Speed, 13); ValidateNavCategory(converterCategories, 7u, ViewMode::Speed);
ValidateNavCategory(converterCategories, 8u, ViewMode::Time, 14); ValidateNavCategory(converterCategories, 8u, ViewMode::Time);
ValidateNavCategory(converterCategories, 9u, ViewMode::Power, 15); ValidateNavCategory(converterCategories, 9u, ViewMode::Power);
ValidateNavCategory(converterCategories, 10u, ViewMode::Data, 16); ValidateNavCategory(converterCategories, 10u, ViewMode::Data);
ValidateNavCategory(converterCategories, 11u, ViewMode::Pressure, 17); ValidateNavCategory(converterCategories, 11u, ViewMode::Pressure);
ValidateNavCategory(converterCategories, 12u, ViewMode::Angle, 18); ValidateNavCategory(converterCategories, 12u, ViewMode::Angle);
} }
} }