From f6f10444f716f117f9d78884d69d54e3940b120f Mon Sep 17 00:00:00 2001 From: Pepe Rivera Date: Thu, 11 Apr 2019 15:20:01 -0700 Subject: [PATCH 001/154] Simplify some of the calc engine string logic (#449) Description of the changes: Currently Calculator handles strings by defining integers for each type of function that can be performed, this integer will eventually correspond with an index in s_engineStrings which holds the corresponding display string for each function. Some functions such as Sin can have multiple strings (degrees, rads, grads, inverse). Functions like Sin are mapped to another array called "rgUfne" where a new integer is given depending on the output string which will then be given to s_engineStrings. The new integer returned by the "rgUfne" array runs the risk of overlapping with any new functions that may be added in CCommand.h. Furthermore, it is expected that the strings in s_engineStrings and rgUfne are defined in a particular order (not necessarily sequential), otherwise the logic will break. This makes adding new strings for new functions confusing and difficult, since a lot of the logic is not clearly defined. This PR attempts to make this a bit simpler by changing the s_engineStrings and rgUfne arrays to be unordered_maps instead of arrays. For s_engineStrings the keys will now be strings, allowing the existing logic for indexing to be used by simply converting the number into a string to access the value. This will also allow us to create keys in the future that are not limited to integers but to strings that hold more meaning. The rgUfne array will also be updated to be a map that will take in an integer and give you the corresponding string that can be passed to s_engineStrings. The UFNE object in the rgUfne array will also be updated to hold all the possible string keys for a function, instead of indexing them on other numbers that may overlap with existing definitions. Now to add a new string for a new IDC_FOO function, we would just need to add the "FooString" resource keys to the g_sids array and use the updated rgUfne map to link the IDC_FOO value to the corresponding "FooString" resource key. This way the resource key can be a meaningful string, and not an integer that must be in any particular order. How changes were validated: Tested each function manually in standard, scientific, and programmer modes. --- src/CalcManager/CEngine/calc.cpp | 13 +- src/CalcManager/CEngine/scicomm.cpp | 204 +++---- src/CalcManager/Header Files/CalcEngine.h | 8 +- src/CalcManager/Header Files/EngineStrings.h | 578 +++++++++---------- src/CalcViewModel/UnitConverterViewModel.cpp | 4 +- 5 files changed, 348 insertions(+), 459 deletions(-) diff --git a/src/CalcManager/CEngine/calc.cpp b/src/CalcManager/CEngine/calc.cpp index 9d1ca9de..0e4979f2 100644 --- a/src/CalcManager/CEngine/calc.cpp +++ b/src/CalcManager/CEngine/calc.cpp @@ -25,13 +25,18 @@ static constexpr wstring_view DEFAULT_NUMBER_STR = L"0"; // Read strings for keys, errors, trig types, etc. // These will be copied from the resources to local memory. -array CCalcEngine::s_engineStrings; +unordered_map CCalcEngine::s_engineStrings; void CCalcEngine::LoadEngineStrings(CalculationManager::IResourceProvider& resourceProvider) { - for (size_t i = 0; i < s_engineStrings.size(); i++) + for (const auto& sid : g_sids) { - s_engineStrings[i] = resourceProvider.GetCEngineString(g_sids[i]); + auto locKey = wstring{ sid }; + auto locString = resourceProvider.GetCEngineString(locKey); + if (!locString.empty()) + { + s_engineStrings[locKey] = locString; + } } } @@ -168,7 +173,7 @@ void CCalcEngine::SettingsChanged() m_HistoryCollector.SetDecimalSymbol(m_decimalSeparator); // put the new decimal symbol into the table used to draw the decimal key - s_engineStrings[IDS_DECIMAL] = m_decimalSeparator; + s_engineStrings[SIDS_DECIMAL_SEPARATOR] = m_decimalSeparator; // we need to redraw to update the decimal point button numChanged = true; diff --git a/src/CalcManager/CEngine/scicomm.cpp b/src/CalcManager/CEngine/scicomm.cpp index 022bceb8..d450a70d 100644 --- a/src/CalcManager/CEngine/scicomm.cpp +++ b/src/CalcManager/CEngine/scicomm.cpp @@ -16,13 +16,6 @@ #include "Header Files/CalcEngine.h" #include "Header Files/CalcUtils.h" -#define IDC_RADSIN IDC_UNARYLAST+1 -#define IDC_RADCOS IDC_UNARYLAST+2 -#define IDC_RADTAN IDC_UNARYLAST+3 -#define IDC_GRADSIN IDC_UNARYLAST+4 -#define IDC_GRADCOS IDC_UNARYLAST+5 -#define IDC_GRADTAN IDC_UNARYLAST+6 - using namespace std; using namespace CalcEngine; @@ -868,155 +861,94 @@ void CCalcEngine::DisplayAnnounceBinaryOperator() // Unary operator Function Name table Element // since unary operators button names aren't exactly friendly for history purpose, // we have this separate table to get its localized name and for its Inv function if it exists. -typedef struct +struct FunctionNameElement { - int idsFunc; // index of string for the unary op function. Can be NULL, in which case it same as button name - int idsFuncInv; // index of string for Inv of unary op. Can be NULL, in case it is same as idsFunc - bool fDontUseInExpEval; // true if this cant be used in reverse direction as well, ie. during expression evaluation -} UFNE; + wstring degreeString; // Used by default if there are no rad or grad specific strings. + wstring inverseDegreeString; // Will fall back to degreeString if empty + + wstring radString; + wstring inverseRadString; // Will fall back to radString if empty + + wstring gradString; + wstring inverseGradString; // Will fall back to gradString if empty + + bool hasAngleStrings = ((!radString.empty()) || (!inverseRadString.empty()) || (!gradString.empty()) || (!inverseGradString.empty())); +}; // Table for each unary operator -static const UFNE rgUfne[] = +static const std::unordered_map unaryOperatorStringTable = { - /* IDC_CHOP */{ 0, IDS_FRAC, false }, - /* IDC_ROL */{ 0, 0, true }, - /* IDC_ROR */{ 0, 0, true }, + { IDC_CHOP, { L"", SIDS_FRAC} }, - /* IDC_COM */{ 0, 0, true }, - /* IDC_SIN */{ IDS_SIND, IDS_ASIND, false }, // default in this table is degrees for sin,cos & tan - /* IDC_COS */{ IDS_COSD, IDS_ACOSD, false }, - /* IDC_TAN */{ IDS_TAND, IDS_ATAND, false }, + { IDC_SIN, { SIDS_SIND, SIDS_ASIND, SIDS_SINR, SIDS_ASINR, SIDS_SING, SIDS_ASING } }, + { IDC_COS, { SIDS_COSD, SIDS_ACOSD, SIDS_COSR, SIDS_ACOSR, SIDS_COSG, SIDS_ACOSG } }, + { IDC_TAN, { SIDS_TAND, SIDS_ATAND, SIDS_TANR, SIDS_ATANR, SIDS_TANG, SIDS_ATANG } }, - /* IDC_SINH */{ 0, IDS_ASINH, false }, - /* IDC_COSH */{ 0, IDS_ACOSH, false }, - /* IDC_TANH */{ 0, IDS_ATANH, false }, + { IDC_SINH, { L"", SIDS_ASINH } }, + { IDC_COSH, { L"", SIDS_ACOSH } }, + { IDC_TANH, { L"", SIDS_ATANH } }, - /* IDC_LN */{ 0, IDS_POWE, false }, - /* IDC_LOG */{ 0, 0, false }, - /* IDC_SQRT */{ 0, 0, false }, - /* IDC_SQR */{ IDS_SQR, 0, false }, - /* IDC_CUB */{ IDS_CUBE, 0, false }, - /* IDC_FAC */{ IDS_FACT, 0, false }, - /* IDC_REC */{ IDS_REC, 0, false }, - /* IDC_DMS */{ 0, IDS_DEGREES, false }, - /* IDC_CUBEROOT */{ 0, 0, false }, - /* IDC_POW10 */{ 0, 0, false }, - /* IDC_PERCENT */{ 0, 0, false }, - - /* IDC_RADSIN */{ IDS_SINR, IDS_ASINR, false }, - /* IDC_RADCOS */{ IDS_COSR, IDS_ACOSR, false }, - /* IDC_RADTAN */{ IDS_TANR, IDS_ATANR, false }, - /* IDC_GRADCOS */{ IDS_SING, IDS_ASING, false }, - /* IDC_GRADCOS */{ IDS_COSG, IDS_ACOSG, false }, - /* IDC_GRADTAN */{ IDS_TANG, IDS_ATANG, false }, + { IDC_LN , { L"", SIDS_POWE } }, + { IDC_SQR, { SIDS_SQR } }, + { IDC_CUB, { SIDS_CUBE } }, + { IDC_FAC, { SIDS_FACT } }, + { IDC_REC, { SIDS_RECIPROC } }, + { IDC_DMS, { L"", SIDS_DEGREES } }, + { IDC_SIGN, { SIDS_NEGATE } }, + { IDC_DEGREES, { SIDS_DEGREES } } }; wstring_view CCalcEngine::OpCodeToUnaryString(int nOpCode, bool fInv, ANGLE_TYPE angletype) { - // Special cases for Sign and Degrees - if (IDC_SIGN == nOpCode) - { - return GetString(IDS_NEGATE); - } - if (IDC_DEGREES == nOpCode) - { - return GetString(IDS_DEGREES); - } - - // Correct the trigonometric functions with type of angle argument they take - if (ANGLE_RAD == angletype) - { - switch (nOpCode) - { - case IDC_SIN: - nOpCode = IDC_RADSIN; - break; - case IDC_COS: - nOpCode = IDC_RADCOS; - break; - case IDC_TAN: - nOpCode = IDC_RADTAN; - break; - } - } - else if (ANGLE_GRAD == angletype) - { - switch (nOpCode) - { - case IDC_SIN: - nOpCode = IDC_GRADSIN; - break; - case IDC_COS: - nOpCode = IDC_GRADCOS; - break; - case IDC_TAN: - nOpCode = IDC_GRADTAN; - break; - } - } - // Try to lookup the ID in the UFNE table - int ids = 0; - int iufne = nOpCode - IDC_UNARYFIRST; - if (iufne >= 0 && (size_t)iufne < size(rgUfne)) + wstring ids = L""; + + if (auto pair = unaryOperatorStringTable.find(nOpCode); pair != unaryOperatorStringTable.end()) { - if (fInv) + const FunctionNameElement& element = pair->second; + if (!element.hasAngleStrings || ANGLE_DEG == angletype) { - ids = rgUfne[iufne].idsFuncInv; + if (fInv) + { + ids = element.inverseDegreeString; + } + + if (ids.empty()) + { + ids = element.degreeString; + } } - if (0 == ids) + else if (ANGLE_RAD == angletype) { - ids = rgUfne[iufne].idsFunc; + if (fInv) + { + ids = element.inverseRadString; + } + if (ids.empty()) + { + ids = element.radString; + } } + else if (ANGLE_GRAD == angletype) + { + if (fInv) + { + ids = element.inverseGradString; + } + if (ids.empty()) + { + ids = element.gradString; + } + } + } + + if (!ids.empty()) + { + return GetString(ids); } // If we didn't find an ID in the table, use the op code. - if (0 == ids) - { - ids = IdStrFromCmdId(nOpCode); - } - - return GetString(ids); -} - -// -// Sets the Angle Mode for special unary op IDC's which are used to index to the table rgUfne -// and returns the equivalent plain IDC for trigonometric function. If it isn't a trigonometric function -// returns the passed in idc itself. -int CCalcEngine::IdcSetAngleTypeDecMode(int idc) -{ - int idcAngleCmd = IDM_DEG; - - switch (idc) - { - case IDC_RADSIN: - idcAngleCmd = IDM_RAD; - idc = IDC_SIN; - break; - case IDC_RADCOS: - idcAngleCmd = IDM_RAD; - idc = IDC_COS; - break; - case IDC_RADTAN: - idcAngleCmd = IDM_RAD; - idc = IDC_TAN; - break; - case IDC_GRADSIN: - idcAngleCmd = IDM_GRAD; - idc = IDC_SIN; - break; - case IDC_GRADCOS: - idcAngleCmd = IDM_GRAD; - idc = IDC_COS; - break; - case IDC_GRADTAN: - idcAngleCmd = IDM_GRAD; - idc = IDC_TAN; - break; - } - ProcessCommand(idcAngleCmd); - return idc; - + return OpCodeToString(nOpCode); } bool CCalcEngine::IsCurrentTooBigForTrig() diff --git a/src/CalcManager/Header Files/CalcEngine.h b/src/CalcManager/Header Files/CalcEngine.h index d9550a1b..db906e51 100644 --- a/src/CalcManager/Header Files/CalcEngine.h +++ b/src/CalcManager/Header Files/CalcEngine.h @@ -72,7 +72,8 @@ public: // Static methods for the instance static void InitialOneTimeOnlySetup(CalculationManager::IResourceProvider& resourceProvider); // Once per load time to call to initialize all shared global variables // returns the ptr to string representing the operator. Mostly same as the button, but few special cases for x^y etc. - static std::wstring_view GetString(int ids) { return s_engineStrings[ids]; } + static std::wstring_view GetString(int ids) { return s_engineStrings[std::to_wstring(ids)]; } + static std::wstring_view GetString(std::wstring ids) { return s_engineStrings[ids]; } static std::wstring_view OpCodeToString(int nOpCode) { return GetString(IdStrFromCmdId(nOpCode)); } static std::wstring_view OpCodeToUnaryString(int nOpCode, bool fInv, ANGLE_TYPE angletype); @@ -123,7 +124,7 @@ private: std::array m_chopNumbers; // word size enforcement std::array m_maxDecimalValueStrings; // maximum values represented by a given word width based off m_chopNumbers - static std::array s_engineStrings; // the string table shared across all instances + static std::unordered_map s_engineStrings; // the string table shared across all instances wchar_t m_decimalSeparator; wchar_t m_groupSeparator; @@ -146,12 +147,11 @@ private: bool TryToggleBit(CalcEngine::Rational& rat, uint32_t wbitno); void CheckAndAddLastBinOpToHistory(bool addToHistory = true); - int IdcSetAngleTypeDecMode(int idc); void InitChopNumbers(); static void LoadEngineStrings(CalculationManager::IResourceProvider& resourceProvider); - static int IdStrFromCmdId(int id) { return id - IDC_FIRSTCONTROL + IDS_FIRSTENGSTR; } + static int IdStrFromCmdId(int id) { return id - IDC_FIRSTCONTROL + IDS_ENGINESTR_FIRST; } static std::vector DigitGroupingStringToGroupingVector(std::wstring_view groupingString); std::wstring GroupDigits(std::wstring_view delimiter, std::vector const& grouping, std::wstring_view displayString, bool isNumNegative = false); diff --git a/src/CalcManager/Header Files/EngineStrings.h b/src/CalcManager/Header Files/EngineStrings.h index 2ada6bba..37f11483 100644 --- a/src/CalcManager/Header Files/EngineStrings.h +++ b/src/CalcManager/Header Files/EngineStrings.h @@ -13,327 +13,279 @@ * Created: 13-Feb-2008 * \****************************************************************************/ -#define IDS_FIRSTENGSTR IDS_ENGINESTR_FIRST - -#define IDS_DECIMAL 4 - -// All unary op function names for easy history reading -// This is where the first string after all the commands in order have been placed, should be placed -// keeping in consecutive helps us to allocate 1 string table and index them -#define IDS_FNSZFIRST (IDC_F -IDC_FIRSTCONTROL)+1 - -#define IDS_FRAC IDS_FNSZFIRST - -#define IDS_SIND IDS_FNSZFIRST+1 -#define IDS_COSD IDS_FNSZFIRST+2 -#define IDS_TAND IDS_FNSZFIRST+3 -#define IDS_ASIND IDS_FNSZFIRST+4 -#define IDS_ACOSD IDS_FNSZFIRST+5 -#define IDS_ATAND IDS_FNSZFIRST+6 - -#define IDS_SINR IDS_FNSZFIRST+7 -#define IDS_COSR IDS_FNSZFIRST+8 -#define IDS_TANR IDS_FNSZFIRST+9 -#define IDS_ASINR IDS_FNSZFIRST+10 -#define IDS_ACOSR IDS_FNSZFIRST+11 -#define IDS_ATANR IDS_FNSZFIRST+12 - -#define IDS_SING IDS_FNSZFIRST+13 -#define IDS_COSG IDS_FNSZFIRST+14 -#define IDS_TANG IDS_FNSZFIRST+15 -#define IDS_ASING IDS_FNSZFIRST+16 -#define IDS_ACOSG IDS_FNSZFIRST+17 -#define IDS_ATANG IDS_FNSZFIRST+18 - -#define IDS_ASINH IDS_FNSZFIRST+19 -#define IDS_ACOSH IDS_FNSZFIRST+20 -#define IDS_ATANH IDS_FNSZFIRST+21 -#define IDS_POWE IDS_FNSZFIRST+22 -#define IDS_POW10 IDS_FNSZFIRST+23 -#define IDS_SQRT IDS_FNSZFIRST+24 -#define IDS_SQR IDS_FNSZFIRST+25 -#define IDS_CUBE IDS_FNSZFIRST+26 -#define IDS_CUBERT IDS_FNSZFIRST+27 -#define IDS_FACT IDS_FNSZFIRST+28 -#define IDS_REC IDS_FNSZFIRST+29 -#define IDS_DEGREES IDS_FNSZFIRST+30 -#define IDS_NEGATE IDS_FNSZFIRST+31 -#define IDS_RSH IDS_FNSZFIRST+32 - -#define IDS_FNSZLAST IDS_RSH - -#define IDS_ERRORS_FIRST IDS_FNSZLAST+1 +inline constexpr auto IDS_ERRORS_FIRST = 99; // This is the list of error strings corresponding to SCERR_DIVIDEZERO.. -#define IDS_DIVBYZERO IDS_ERRORS_FIRST -#define IDS_DOMAIN IDS_ERRORS_FIRST+1 -#define IDS_UNDEFINED IDS_ERRORS_FIRST+2 -#define IDS_POS_INFINITY IDS_ERRORS_FIRST+3 -#define IDS_NEG_INFINITY IDS_ERRORS_FIRST+4 -#define IDS_NOMEM IDS_ERRORS_FIRST+6 -#define IDS_TOOMANY IDS_ERRORS_FIRST+7 -#define IDS_OVERFLOW IDS_ERRORS_FIRST+8 -#define IDS_NORESULT IDS_ERRORS_FIRST+9 -#define IDS_INSUFFICIENT_DATA IDS_ERRORS_FIRST+10 +inline constexpr auto IDS_DIVBYZERO = IDS_ERRORS_FIRST; +inline constexpr auto IDS_DOMAIN = IDS_ERRORS_FIRST + 1; +inline constexpr auto IDS_UNDEFINED = IDS_ERRORS_FIRST + 2; +inline constexpr auto IDS_POS_INFINITY = IDS_ERRORS_FIRST + 3; +inline constexpr auto IDS_NEG_INFINITY = IDS_ERRORS_FIRST + 4; +inline constexpr auto IDS_NOMEM = IDS_ERRORS_FIRST + 6; +inline constexpr auto IDS_TOOMANY = IDS_ERRORS_FIRST + 7; +inline constexpr auto IDS_OVERFLOW = IDS_ERRORS_FIRST + 8; +inline constexpr auto IDS_NORESULT = IDS_ERRORS_FIRST + 9; +inline constexpr auto IDS_INSUFFICIENT_DATA = IDS_ERRORS_FIRST + 10; -#define CSTRINGSENGMAX IDS_INSUFFICIENT_DATA+1 +inline constexpr auto CSTRINGSENGMAX = IDS_INSUFFICIENT_DATA + 1; // Arithmetic expression evaluator error strings -#define IDS_ERR_UNK_CH CSTRINGSENGMAX+1 -#define IDS_ERR_UNK_FN CSTRINGSENGMAX+2 -#define IDS_ERR_UNEX_NUM CSTRINGSENGMAX+3 -#define IDS_ERR_UNEX_CH CSTRINGSENGMAX+4 -#define IDS_ERR_UNEX_SZ CSTRINGSENGMAX+5 -#define IDS_ERR_MISMATCH_CLOSE CSTRINGSENGMAX+6 -#define IDS_ERR_UNEX_END CSTRINGSENGMAX+7 -#define IDS_ERR_SG_INV_ERROR CSTRINGSENGMAX+8 -#define IDS_ERR_INPUT_OVERFLOW CSTRINGSENGMAX+9 -#define IDS_ERR_OUTPUT_OVERFLOW CSTRINGSENGMAX+10 +inline constexpr auto IDS_ERR_UNK_CH = CSTRINGSENGMAX + 1; +inline constexpr auto IDS_ERR_UNK_FN = CSTRINGSENGMAX + 2; +inline constexpr auto IDS_ERR_UNEX_NUM = CSTRINGSENGMAX + 3; +inline constexpr auto IDS_ERR_UNEX_CH = CSTRINGSENGMAX + 4; +inline constexpr auto IDS_ERR_UNEX_SZ = CSTRINGSENGMAX + 5; +inline constexpr auto IDS_ERR_MISMATCH_CLOSE = CSTRINGSENGMAX + 6; +inline constexpr auto IDS_ERR_UNEX_END = CSTRINGSENGMAX + 7; +inline constexpr auto IDS_ERR_SG_INV_ERROR = CSTRINGSENGMAX + 8; +inline constexpr auto IDS_ERR_INPUT_OVERFLOW = CSTRINGSENGMAX + 9; +inline constexpr auto IDS_ERR_OUTPUT_OVERFLOW = CSTRINGSENGMAX + 10; - -#define SIDS_PLUS_MINUS L"0" -#define SIDS_CLEAR L"1" -#define SIDS_CE L"2" -#define SIDS_BACKSPACE L"3" -#define SIDS_DECIMAL_SEPARATOR L"4" -#define SIDS_EMPTY_STRING L"5" -#define SIDS_AND L"6" -#define SIDS_OR L"7" -#define SIDS_XOR L"8" -#define SIDS_LSH L"9" -#define SIDS_RSH L"10" -#define SIDS_DIVIDE L"11" -#define SIDS_MULTIPLY L"12" -#define SIDS_PLUS L"13" -#define SIDS_MINUS L"14" -#define SIDS_MOD L"15" -#define SIDS_YROOT L"16" -#define SIDS_POW_HAT L"17" -#define SIDS_INT L"18" -#define SIDS_ROL L"19" -#define SIDS_ROR L"20" -#define SIDS_NOT L"21" -#define SIDS_SIN L"22" -#define SIDS_COS L"23" -#define SIDS_TAN L"24" -#define SIDS_SINH L"25" -#define SIDS_COSH L"26" -#define SIDS_TANH L"27" -#define SIDS_LN L"28" -#define SIDS_LOG L"29" -#define SIDS_SQRT L"30" -#define SIDS_XPOW2 L"31" -#define SIDS_XPOW3 L"32" -#define SIDS_NFACTORIAL L"33" -#define SIDS_RECIPROCAL L"34" -#define SIDS_DMS L"35" -#define SIDS_CUBEROOT L"36" -#define SIDS_POWTEN L"37" -#define SIDS_PERCENT L"38" -#define SIDS_SCIENTIFIC_NOTATION L"39" -#define SIDS_PI L"40" -#define SIDS_EQUAL L"41" -#define SIDS_MC L"42" -#define SIDS_MR L"43" -#define SIDS_MS L"44" -#define SIDS_MPLUS L"45" -#define SIDS_MMINUS L"46" -#define SIDS_EXP L"47" -#define SIDS_OPEN_PAREN L"48" -#define SIDS_CLOSE_PAREN L"49" -#define SIDS_0 L"50" -#define SIDS_1 L"51" -#define SIDS_2 L"52" -#define SIDS_3 L"53" -#define SIDS_4 L"54" -#define SIDS_5 L"55" -#define SIDS_6 L"56" -#define SIDS_7 L"57" -#define SIDS_8 L"58" -#define SIDS_9 L"59" -#define SIDS_A L"60" -#define SIDS_B L"61" -#define SIDS_C L"62" -#define SIDS_D L"63" -#define SIDS_E L"64" -#define SIDS_F L"65" -#define SIDS_FRAC L"66" -#define SIDS_SIND L"67" -#define SIDS_COSD L"68" -#define SIDS_TAND L"69" -#define SIDS_ASIND L"70" -#define SIDS_ACOSD L"71" -#define SIDS_ATAND L"72" -#define SIDS_SINR L"73" -#define SIDS_COSR L"74" -#define SIDS_TANR L"75" -#define SIDS_ASINR L"76" -#define SIDS_ACOSR L"77" -#define SIDS_ATANR L"78" -#define SIDS_SING L"79" -#define SIDS_COSG L"80" -#define SIDS_TANG L"81" -#define SIDS_ASING L"82" -#define SIDS_ACOSG L"83" -#define SIDS_ATANG L"84" -#define SIDS_ASINH L"85" -#define SIDS_ACOSH L"86" -#define SIDS_ATANH L"87" -#define SIDS_POWE L"88" -#define SIDS_POWTEN2 L"89" -#define SIDS_SQRT2 L"90" -#define SIDS_SQR L"91" -#define SIDS_CUBE L"92" -#define SIDS_CUBERT L"93" -#define SIDS_FACT L"94" -#define SIDS_RECIPROC L"95" -#define SIDS_DEGREES L"96" -#define SIDS_NEGATE L"97" -#define SIDS_RSH2 L"98" -#define SIDS_DIVIDEBYZERO L"99" -#define SIDS_DOMAIN L"100" -#define SIDS_UNDEFINED L"101" -#define SIDS_POS_INFINITY L"102" -#define SIDS_NEG_INFINITY L"103" -#define SIDS_ABORTED L"104" -#define SIDS_NOMEM L"105" -#define SIDS_TOOMANY L"106" -#define SIDS_OVERFLOW L"107" -#define SIDS_NORESULT L"108" -#define SIDS_INSUFFICIENT_DATA L"109" +// Resource keys for CEngineStrings.resw +inline constexpr auto SIDS_PLUS_MINUS = L"0"; +inline constexpr auto SIDS_CLEAR = L"1"; +inline constexpr auto SIDS_CE = L"2"; +inline constexpr auto SIDS_BACKSPACE = L"3"; +inline constexpr auto SIDS_DECIMAL_SEPARATOR = L"4"; +inline constexpr auto SIDS_EMPTY_STRING = L"5"; +inline constexpr auto SIDS_AND = L"6"; +inline constexpr auto SIDS_OR = L"7"; +inline constexpr auto SIDS_XOR = L"8"; +inline constexpr auto SIDS_LSH = L"9"; +inline constexpr auto SIDS_RSH = L"10"; +inline constexpr auto SIDS_DIVIDE = L"11"; +inline constexpr auto SIDS_MULTIPLY = L"12"; +inline constexpr auto SIDS_PLUS = L"13"; +inline constexpr auto SIDS_MINUS = L"14"; +inline constexpr auto SIDS_MOD = L"15"; +inline constexpr auto SIDS_YROOT = L"16"; +inline constexpr auto SIDS_POW_HAT = L"17"; +inline constexpr auto SIDS_INT = L"18"; +inline constexpr auto SIDS_ROL = L"19"; +inline constexpr auto SIDS_ROR = L"20"; +inline constexpr auto SIDS_NOT = L"21"; +inline constexpr auto SIDS_SIN = L"22"; +inline constexpr auto SIDS_COS = L"23"; +inline constexpr auto SIDS_TAN = L"24"; +inline constexpr auto SIDS_SINH = L"25"; +inline constexpr auto SIDS_COSH = L"26"; +inline constexpr auto SIDS_TANH = L"27"; +inline constexpr auto SIDS_LN = L"28"; +inline constexpr auto SIDS_LOG = L"29"; +inline constexpr auto SIDS_SQRT = L"30"; +inline constexpr auto SIDS_XPOW2 = L"31"; +inline constexpr auto SIDS_XPOW3 = L"32"; +inline constexpr auto SIDS_NFACTORIAL = L"33"; +inline constexpr auto SIDS_RECIPROCAL = L"34"; +inline constexpr auto SIDS_DMS = L"35"; +inline constexpr auto SIDS_CUBEROOT = L"36"; +inline constexpr auto SIDS_POWTEN = L"37"; +inline constexpr auto SIDS_PERCENT = L"38"; +inline constexpr auto SIDS_SCIENTIFIC_NOTATION = L"39"; +inline constexpr auto SIDS_PI = L"40"; +inline constexpr auto SIDS_EQUAL = L"41"; +inline constexpr auto SIDS_MC = L"42"; +inline constexpr auto SIDS_MR = L"43"; +inline constexpr auto SIDS_MS = L"44"; +inline constexpr auto SIDS_MPLUS = L"45"; +inline constexpr auto SIDS_MMINUS = L"46"; +inline constexpr auto SIDS_EXP = L"47"; +inline constexpr auto SIDS_OPEN_PAREN = L"48"; +inline constexpr auto SIDS_CLOSE_PAREN = L"49"; +inline constexpr auto SIDS_0 = L"50"; +inline constexpr auto SIDS_1 = L"51"; +inline constexpr auto SIDS_2 = L"52"; +inline constexpr auto SIDS_3 = L"53"; +inline constexpr auto SIDS_4 = L"54"; +inline constexpr auto SIDS_5 = L"55"; +inline constexpr auto SIDS_6 = L"56"; +inline constexpr auto SIDS_7 = L"57"; +inline constexpr auto SIDS_8 = L"58"; +inline constexpr auto SIDS_9 = L"59"; +inline constexpr auto SIDS_A = L"60"; +inline constexpr auto SIDS_B = L"61"; +inline constexpr auto SIDS_C = L"62"; +inline constexpr auto SIDS_D = L"63"; +inline constexpr auto SIDS_E = L"64"; +inline constexpr auto SIDS_F = L"65"; +inline constexpr auto SIDS_FRAC = L"66"; +inline constexpr auto SIDS_SIND = L"67"; +inline constexpr auto SIDS_COSD = L"68"; +inline constexpr auto SIDS_TAND = L"69"; +inline constexpr auto SIDS_ASIND = L"70"; +inline constexpr auto SIDS_ACOSD = L"71"; +inline constexpr auto SIDS_ATAND = L"72"; +inline constexpr auto SIDS_SINR = L"73"; +inline constexpr auto SIDS_COSR = L"74"; +inline constexpr auto SIDS_TANR = L"75"; +inline constexpr auto SIDS_ASINR = L"76"; +inline constexpr auto SIDS_ACOSR = L"77"; +inline constexpr auto SIDS_ATANR = L"78"; +inline constexpr auto SIDS_SING = L"79"; +inline constexpr auto SIDS_COSG = L"80"; +inline constexpr auto SIDS_TANG = L"81"; +inline constexpr auto SIDS_ASING = L"82"; +inline constexpr auto SIDS_ACOSG = L"83"; +inline constexpr auto SIDS_ATANG = L"84"; +inline constexpr auto SIDS_ASINH = L"85"; +inline constexpr auto SIDS_ACOSH = L"86"; +inline constexpr auto SIDS_ATANH = L"87"; +inline constexpr auto SIDS_POWE = L"88"; +inline constexpr auto SIDS_POWTEN2 = L"89"; +inline constexpr auto SIDS_SQRT2 = L"90"; +inline constexpr auto SIDS_SQR = L"91"; +inline constexpr auto SIDS_CUBE = L"92"; +inline constexpr auto SIDS_CUBERT = L"93"; +inline constexpr auto SIDS_FACT = L"94"; +inline constexpr auto SIDS_RECIPROC = L"95"; +inline constexpr auto SIDS_DEGREES = L"96"; +inline constexpr auto SIDS_NEGATE = L"97"; +inline constexpr auto SIDS_RSH2 = L"98"; +inline constexpr auto SIDS_DIVIDEBYZERO = L"99"; +inline constexpr auto SIDS_DOMAIN = L"100"; +inline constexpr auto SIDS_UNDEFINED = L"101"; +inline constexpr auto SIDS_POS_INFINITY = L"102"; +inline constexpr auto SIDS_NEG_INFINITY = L"103"; +inline constexpr auto SIDS_ABORTED = L"104"; +inline constexpr auto SIDS_NOMEM = L"105"; +inline constexpr auto SIDS_TOOMANY = L"106"; +inline constexpr auto SIDS_OVERFLOW = L"107"; +inline constexpr auto SIDS_NORESULT = L"108"; +inline constexpr auto SIDS_INSUFFICIENT_DATA = L"109"; // 110 is skipped by CSTRINGSENGMAX -#define SIDS_ERR_UNK_CH L"111" -#define SIDS_ERR_UNK_FN L"112" -#define SIDS_ERR_UNEX_NUM L"113" -#define SIDS_ERR_UNEX_CH L"114" -#define SIDS_ERR_UNEX_SZ L"115" -#define SIDS_ERR_MISMATCH_CLOSE L"116" -#define SIDS_ERR_UNEX_END L"117" -#define SIDS_ERR_SG_INV_ERROR L"118" -#define SIDS_ERR_INPUT_OVERFLOW L"119" -#define SIDS_ERR_OUTPUT_OVERFLOW L"120" +inline constexpr auto SIDS_ERR_UNK_CH = L"111"; +inline constexpr auto SIDS_ERR_UNK_FN = L"112"; +inline constexpr auto SIDS_ERR_UNEX_NUM = L"113"; +inline constexpr auto SIDS_ERR_UNEX_CH = L"114"; +inline constexpr auto SIDS_ERR_UNEX_SZ = L"115"; +inline constexpr auto SIDS_ERR_MISMATCH_CLOSE = L"116"; +inline constexpr auto SIDS_ERR_UNEX_END = L"117"; +inline constexpr auto SIDS_ERR_SG_INV_ERROR = L"118"; +inline constexpr auto SIDS_ERR_INPUT_OVERFLOW = L"119"; +inline constexpr auto SIDS_ERR_OUTPUT_OVERFLOW = L"120"; -__declspec(selectany) std::wstring g_sids[] = +// Include the resource key ID from above into this vector to load it into memory for the engine to use +inline constexpr std::array g_sids = { - std::wstring(SIDS_PLUS_MINUS), - std::wstring(SIDS_C), - std::wstring(SIDS_CE), - std::wstring(SIDS_BACKSPACE), - std::wstring(SIDS_DECIMAL_SEPARATOR), - std::wstring(SIDS_EMPTY_STRING), - std::wstring(SIDS_AND), - std::wstring(SIDS_OR), - std::wstring(SIDS_XOR), - std::wstring(SIDS_LSH), - std::wstring(SIDS_RSH), - std::wstring(SIDS_DIVIDE), - std::wstring(SIDS_MULTIPLY), - std::wstring(SIDS_PLUS), - std::wstring(SIDS_MINUS), - std::wstring(SIDS_MOD), - std::wstring(SIDS_YROOT), - std::wstring(SIDS_POW_HAT), - std::wstring(SIDS_INT), - std::wstring(SIDS_ROL), - std::wstring(SIDS_ROR), - std::wstring(SIDS_NOT), - std::wstring(SIDS_SIN), - std::wstring(SIDS_COS), - std::wstring(SIDS_TAN), - std::wstring(SIDS_SINH), - std::wstring(SIDS_COSH), - std::wstring(SIDS_TANH), - std::wstring(SIDS_LN), - std::wstring(SIDS_LOG), - std::wstring(SIDS_SQRT), - std::wstring(SIDS_XPOW2), - std::wstring(SIDS_XPOW3), - std::wstring(SIDS_NFACTORIAL), - std::wstring(SIDS_RECIPROCAL), - std::wstring(SIDS_DMS), - std::wstring(SIDS_CUBEROOT), - std::wstring(SIDS_POWTEN), - std::wstring(SIDS_PERCENT), - std::wstring(SIDS_SCIENTIFIC_NOTATION), - std::wstring(SIDS_PI), - std::wstring(SIDS_EQUAL), - std::wstring(SIDS_MC), - std::wstring(SIDS_MR), - std::wstring(SIDS_MS), - std::wstring(SIDS_MPLUS), - std::wstring(SIDS_MMINUS), - std::wstring(SIDS_EXP), - std::wstring(SIDS_OPEN_PAREN), - std::wstring(SIDS_CLOSE_PAREN), - std::wstring(SIDS_0), - std::wstring(SIDS_1), - std::wstring(SIDS_2), - std::wstring(SIDS_3), - std::wstring(SIDS_4), - std::wstring(SIDS_5), - std::wstring(SIDS_6), - std::wstring(SIDS_7), - std::wstring(SIDS_8), - std::wstring(SIDS_9), - std::wstring(SIDS_A), - std::wstring(SIDS_B), - std::wstring(SIDS_C), - std::wstring(SIDS_D), - std::wstring(SIDS_E), - std::wstring(SIDS_F), - std::wstring(SIDS_FRAC), - std::wstring(SIDS_SIND), - std::wstring(SIDS_COSD), - std::wstring(SIDS_TAND), - std::wstring(SIDS_ASIND), - std::wstring(SIDS_ACOSD), - std::wstring(SIDS_ATAND), - std::wstring(SIDS_SINR), - std::wstring(SIDS_COSR), - std::wstring(SIDS_TANR), - std::wstring(SIDS_ASINR), - std::wstring(SIDS_ACOSR), - std::wstring(SIDS_ATANR), - std::wstring(SIDS_SING), - std::wstring(SIDS_COSG), - std::wstring(SIDS_TANG), - std::wstring(SIDS_ASING), - std::wstring(SIDS_ACOSG), - std::wstring(SIDS_ATANG), - std::wstring(SIDS_ASINH), - std::wstring(SIDS_ACOSH), - std::wstring(SIDS_ATANH), - std::wstring(SIDS_POWE), - std::wstring(SIDS_POWTEN2), - std::wstring(SIDS_SQRT2), - std::wstring(SIDS_SQR), - std::wstring(SIDS_CUBE), - std::wstring(SIDS_CUBERT), - std::wstring(SIDS_FACT), - std::wstring(SIDS_RECIPROC), - std::wstring(SIDS_DEGREES), - std::wstring(SIDS_NEGATE), - std::wstring(SIDS_RSH), - std::wstring(SIDS_DIVIDEBYZERO), - std::wstring(SIDS_DOMAIN), - std::wstring(SIDS_UNDEFINED), - std::wstring(SIDS_POS_INFINITY), - std::wstring(SIDS_NEG_INFINITY), - std::wstring(SIDS_ABORTED), - std::wstring(SIDS_NOMEM), - std::wstring(SIDS_TOOMANY), - std::wstring(SIDS_OVERFLOW), - std::wstring(SIDS_NORESULT), - std::wstring(SIDS_INSUFFICIENT_DATA), - std::wstring(SIDS_ERR_UNK_CH), - std::wstring(SIDS_ERR_UNK_FN), - std::wstring(SIDS_ERR_UNEX_NUM), - std::wstring(SIDS_ERR_UNEX_CH), - std::wstring(SIDS_ERR_UNEX_SZ), - std::wstring(SIDS_ERR_MISMATCH_CLOSE), - std::wstring(SIDS_ERR_UNEX_END), - std::wstring(SIDS_ERR_SG_INV_ERROR), - std::wstring(SIDS_ERR_INPUT_OVERFLOW), - std::wstring(SIDS_ERR_OUTPUT_OVERFLOW) + SIDS_PLUS_MINUS, + SIDS_C, + SIDS_CE, + SIDS_BACKSPACE, + SIDS_DECIMAL_SEPARATOR, + SIDS_EMPTY_STRING, + SIDS_AND, + SIDS_OR, + SIDS_XOR, + SIDS_LSH, + SIDS_RSH, + SIDS_DIVIDE, + SIDS_MULTIPLY, + SIDS_PLUS, + SIDS_MINUS, + SIDS_MOD, + SIDS_YROOT, + SIDS_POW_HAT, + SIDS_INT, + SIDS_ROL, + SIDS_ROR, + SIDS_NOT, + SIDS_SIN, + SIDS_COS, + SIDS_TAN, + SIDS_SINH, + SIDS_COSH, + SIDS_TANH, + SIDS_LN, + SIDS_LOG, + SIDS_SQRT, + SIDS_XPOW2, + SIDS_XPOW3, + SIDS_NFACTORIAL, + SIDS_RECIPROCAL, + SIDS_DMS, + SIDS_CUBEROOT, + SIDS_POWTEN, + SIDS_PERCENT, + SIDS_SCIENTIFIC_NOTATION, + SIDS_PI, + SIDS_EQUAL, + SIDS_MC, + SIDS_MR, + SIDS_MS, + SIDS_MPLUS, + SIDS_MMINUS, + SIDS_EXP, + SIDS_OPEN_PAREN, + SIDS_CLOSE_PAREN, + SIDS_0, + SIDS_1, + SIDS_2, + SIDS_3, + SIDS_4, + SIDS_5, + SIDS_6, + SIDS_7, + SIDS_8, + SIDS_9, + SIDS_A, + SIDS_B, + SIDS_C, + SIDS_D, + SIDS_E, + SIDS_F, + SIDS_FRAC, + SIDS_SIND, + SIDS_COSD, + SIDS_TAND, + SIDS_ASIND, + SIDS_ACOSD, + SIDS_ATAND, + SIDS_SINR, + SIDS_COSR, + SIDS_TANR, + SIDS_ASINR, + SIDS_ACOSR, + SIDS_ATANR, + SIDS_SING, + SIDS_COSG, + SIDS_TANG, + SIDS_ASING, + SIDS_ACOSG, + SIDS_ATANG, + SIDS_ASINH, + SIDS_ACOSH, + SIDS_ATANH, + SIDS_POWE, + SIDS_POWTEN2, + SIDS_SQRT2, + SIDS_SQR, + SIDS_CUBE, + SIDS_CUBERT, + SIDS_FACT, + SIDS_RECIPROC, + SIDS_DEGREES, + SIDS_NEGATE, + SIDS_RSH, + SIDS_DIVIDEBYZERO, + SIDS_DOMAIN, + SIDS_UNDEFINED, + SIDS_POS_INFINITY, + SIDS_NEG_INFINITY, + SIDS_ABORTED, + SIDS_NOMEM, + SIDS_TOOMANY, + SIDS_OVERFLOW, + SIDS_NORESULT, + SIDS_INSUFFICIENT_DATA, + SIDS_ERR_UNK_CH, + SIDS_ERR_UNK_FN, + SIDS_ERR_UNEX_NUM, + SIDS_ERR_UNEX_CH, + SIDS_ERR_UNEX_SZ, + SIDS_ERR_MISMATCH_CLOSE, + SIDS_ERR_UNEX_END, + SIDS_ERR_SG_INV_ERROR, + SIDS_ERR_INPUT_OVERFLOW, + SIDS_ERR_OUTPUT_OVERFLOW }; diff --git a/src/CalcViewModel/UnitConverterViewModel.cpp b/src/CalcViewModel/UnitConverterViewModel.cpp index a04b584e..76d9aa3a 100644 --- a/src/CalcViewModel/UnitConverterViewModel.cpp +++ b/src/CalcViewModel/UnitConverterViewModel.cpp @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #include "pch.h" @@ -394,7 +394,7 @@ String^ UnitConverterViewModel::ConvertToLocalizedString(const std::wstring& str void UnitConverterViewModel::DisplayPasteError() { - String^ errorMsg = AppResourceProvider::GetInstance().GetCEngineString(SIDS_DOMAIN); /*SIDS_DOMAIN is for "invalid input"*/ + String^ errorMsg = AppResourceProvider::GetInstance().GetCEngineString(StringReference(SIDS_DOMAIN)); /*SIDS_DOMAIN is for "invalid input"*/ Value1 = errorMsg; Value2 = errorMsg; m_relocalizeStringOnSwitch = false; From afdda581a42dc869d9487bf4aa9d7e941f71aa27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Janiszewski?= Date: Fri, 12 Apr 2019 22:40:02 +0200 Subject: [PATCH 002/154] Drop unneeded const-qualifier on return type (#396) --- src/CalcManager/CalculatorHistory.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CalcManager/CalculatorHistory.h b/src/CalcManager/CalculatorHistory.h index 8116e9e4..ea87f857 100644 --- a/src/CalcManager/CalculatorHistory.h +++ b/src/CalcManager/CalculatorHistory.h @@ -38,7 +38,7 @@ namespace CalculationManager void ClearHistory(); unsigned int AddItem(_In_ std::shared_ptr const &spHistoryItem); bool RemoveItem(unsigned int uIdx); - const size_t MaxHistorySize() const { return m_maxHistorySize; } + size_t MaxHistorySize() const { return m_maxHistorySize; } ~CalculatorHistory(void); private: From 109326508f6b13410fc2baf953ea5e1ce26ece0b Mon Sep 17 00:00:00 2001 From: Rudy Huyn Date: Mon, 15 Apr 2019 09:31:02 -0700 Subject: [PATCH 003/154] Improve the support of Narrator with parenthesis (#368) * Modify how we manage Narrator with parenthesis and refactor right parenthesis * Optimization * remove extra spaces * take feedback into account --- src/CalcManager/CEngine/scicomm.cpp | 4 +- src/CalcManager/CalculatorManager.cpp | 6 +- src/CalcManager/CalculatorManager.h | 2 +- src/CalcManager/Header Files/ICalcDisplay.h | 2 +- .../Common/Automation/NarratorNotifier.cpp | 2 +- .../Common/CalculatorDisplay.cpp | 2 +- src/CalcViewModel/Common/CalculatorDisplay.h | 2 +- .../StandardCalculatorViewModel.cpp | 73 +++++++++---------- .../StandardCalculatorViewModel.h | 14 +--- src/Calculator/Resources/am-ET/Resources.resw | 5 +- src/Calculator/Resources/ar-SA/Resources.resw | 5 +- .../Resources/az-Latn-AZ/Resources.resw | 5 +- src/Calculator/Resources/be-BY/Resources.resw | 5 +- src/Calculator/Resources/bg-BG/Resources.resw | 5 +- src/Calculator/Resources/ca-ES/Resources.resw | 5 +- src/Calculator/Resources/cs-CZ/Resources.resw | 5 +- src/Calculator/Resources/da-DK/Resources.resw | 5 +- src/Calculator/Resources/de-DE/Resources.resw | 5 +- src/Calculator/Resources/el-GR/Resources.resw | 5 +- src/Calculator/Resources/en-GB/Resources.resw | 5 +- src/Calculator/Resources/es-ES/Resources.resw | 5 +- src/Calculator/Resources/es-MX/Resources.resw | 5 +- src/Calculator/Resources/et-EE/Resources.resw | 5 +- src/Calculator/Resources/eu-ES/Resources.resw | 5 +- src/Calculator/Resources/fa-IR/Resources.resw | 5 +- src/Calculator/Resources/fi-FI/Resources.resw | 5 +- .../Resources/fil-PH/Resources.resw | 5 +- src/Calculator/Resources/fr-CA/Resources.resw | 5 +- src/Calculator/Resources/fr-FR/Resources.resw | 5 +- src/Calculator/Resources/gl-ES/Resources.resw | 5 +- src/Calculator/Resources/he-IL/Resources.resw | 5 +- src/Calculator/Resources/hi-IN/Resources.resw | 5 +- src/Calculator/Resources/hr-HR/Resources.resw | 5 +- src/Calculator/Resources/hu-HU/Resources.resw | 5 +- src/Calculator/Resources/id-ID/Resources.resw | 5 +- src/Calculator/Resources/is-IS/Resources.resw | 5 +- src/Calculator/Resources/it-IT/Resources.resw | 5 +- src/Calculator/Resources/ja-JP/Resources.resw | 5 +- src/Calculator/Resources/kk-KZ/Resources.resw | 5 +- src/Calculator/Resources/km-KH/Resources.resw | 5 +- src/Calculator/Resources/kn-IN/Resources.resw | 5 +- src/Calculator/Resources/ko-KR/Resources.resw | 5 +- src/Calculator/Resources/lo-LA/Resources.resw | 5 +- src/Calculator/Resources/lt-LT/Resources.resw | 5 +- src/Calculator/Resources/lv-LV/Resources.resw | 5 +- src/Calculator/Resources/mk-MK/Resources.resw | 5 +- src/Calculator/Resources/ml-IN/Resources.resw | 5 +- src/Calculator/Resources/ms-MY/Resources.resw | 5 +- src/Calculator/Resources/nb-NO/Resources.resw | 5 +- src/Calculator/Resources/nl-NL/Resources.resw | 5 +- src/Calculator/Resources/pl-PL/Resources.resw | 5 +- src/Calculator/Resources/pt-BR/Resources.resw | 5 +- src/Calculator/Resources/pt-PT/Resources.resw | 5 +- src/Calculator/Resources/ro-RO/Resources.resw | 5 +- src/Calculator/Resources/ru-RU/Resources.resw | 5 +- src/Calculator/Resources/sk-SK/Resources.resw | 5 +- src/Calculator/Resources/sl-SI/Resources.resw | 5 +- src/Calculator/Resources/sq-AL/Resources.resw | 5 +- .../Resources/sr-Latn-RS/Resources.resw | 5 +- src/Calculator/Resources/sv-SE/Resources.resw | 5 +- src/Calculator/Resources/sw-KE/Resources.resw | 5 +- src/Calculator/Resources/ta-IN/Resources.resw | 5 +- src/Calculator/Resources/te-IN/Resources.resw | 5 +- src/Calculator/Resources/th-TH/Resources.resw | 5 +- src/Calculator/Resources/tr-TR/Resources.resw | 5 +- src/Calculator/Resources/uk-UA/Resources.resw | 5 +- .../Resources/uz-Latn-UZ/Resources.resw | 5 +- src/Calculator/Resources/vi-VN/Resources.resw | 5 +- src/Calculator/Resources/zh-CN/Resources.resw | 5 +- src/Calculator/Resources/zh-TW/Resources.resw | 5 +- .../CalculatorProgrammerRadixOperators.xaml | 4 +- ...alculatorProgrammerRadixOperators.xaml.cpp | 18 ++--- .../CalculatorProgrammerRadixOperators.xaml.h | 4 +- .../Views/CalculatorScientificOperators.xaml | 6 +- .../CalculatorScientificOperators.xaml.cpp | 21 ++---- .../CalculatorScientificOperators.xaml.h | 8 +- src/Calculator/pch.h | 1 + .../CalculatorManagerTest.cpp | 4 +- 78 files changed, 133 insertions(+), 345 deletions(-) diff --git a/src/CalcManager/CEngine/scicomm.cpp b/src/CalcManager/CEngine/scicomm.cpp index d450a70d..4e0322d0 100644 --- a/src/CalcManager/CEngine/scicomm.cpp +++ b/src/CalcManager/CEngine/scicomm.cpp @@ -390,7 +390,7 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam) cleared for CENTR */ if (nullptr != m_pCalcDisplay) { - m_pCalcDisplay->SetParenDisplayText(L""); + m_pCalcDisplay->SetParenthesisNumber(0); m_pCalcDisplay->SetExpressionDisplay(make_shared>>(), make_shared>>()); } @@ -594,7 +594,7 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam) // Set the "(=xx" indicator. if (nullptr != m_pCalcDisplay) { - m_pCalcDisplay->SetParenDisplayText(m_openParenCount ? to_wstring(m_openParenCount) : L""); + m_pCalcDisplay->SetParenthesisNumber(m_openParenCount >= 0 ? static_cast(m_openParenCount) : 0); } if (!m_bError) diff --git a/src/CalcManager/CalculatorManager.cpp b/src/CalcManager/CalculatorManager.cpp index b4b4dfaf..d5bbd029 100644 --- a/src/CalcManager/CalculatorManager.cpp +++ b/src/CalcManager/CalculatorManager.cpp @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #include "pch.h" @@ -111,9 +111,9 @@ namespace CalculationManager /// Callback from the engine /// /// string containing the parenthesis count - void CalculatorManager::SetParenDisplayText(const wstring& parenthesisCount) + void CalculatorManager::SetParenthesisNumber(_In_ unsigned int parenthesisCount) { - m_displayCallback->SetParenDisplayText(parenthesisCount); + m_displayCallback->SetParenthesisNumber(parenthesisCount); } /// diff --git a/src/CalcManager/CalculatorManager.h b/src/CalcManager/CalculatorManager.h index 0b9986b0..e00dc243 100644 --- a/src/CalcManager/CalculatorManager.h +++ b/src/CalcManager/CalculatorManager.h @@ -94,7 +94,7 @@ namespace CalculationManager void SetExpressionDisplay(_Inout_ std::shared_ptr>> const &tokens, _Inout_ std::shared_ptr>> const &commands) override; void SetMemorizedNumbers(_In_ const std::vector& memorizedNumbers) override; void OnHistoryItemAdded(_In_ unsigned int addedItemIndex) override; - void SetParenDisplayText(const std::wstring& parenthesisCount) override; + void SetParenthesisNumber(_In_ unsigned int parenthesisCount) override; void OnNoRightParenAdded() override; void DisplayPasteError(); void MaxDigitsReached() override; diff --git a/src/CalcManager/Header Files/ICalcDisplay.h b/src/CalcManager/Header Files/ICalcDisplay.h index 2ba57e65..73fce932 100644 --- a/src/CalcManager/Header Files/ICalcDisplay.h +++ b/src/CalcManager/Header Files/ICalcDisplay.h @@ -12,7 +12,7 @@ public: virtual void SetPrimaryDisplay(const std::wstring& pszText, bool isError) = 0; virtual void SetIsInError(bool isInError) = 0; virtual void SetExpressionDisplay(_Inout_ std::shared_ptr>> const &tokens, _Inout_ std::shared_ptr>> const &commands) = 0; - virtual void SetParenDisplayText(const std::wstring& pszText) = 0; + virtual void SetParenthesisNumber(_In_ unsigned int count) = 0; virtual void OnNoRightParenAdded() = 0; virtual void MaxDigitsReached() = 0; // not an error but still need to inform UI layer. virtual void BinaryOperatorReceived() = 0; diff --git a/src/CalcViewModel/Common/Automation/NarratorNotifier.cpp b/src/CalcViewModel/Common/Automation/NarratorNotifier.cpp index 4dc48074..b17aaba4 100644 --- a/src/CalcViewModel/Common/Automation/NarratorNotifier.cpp +++ b/src/CalcViewModel/Common/Automation/NarratorNotifier.cpp @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. // Implementation of the NarratorNotifier class. diff --git a/src/CalcViewModel/Common/CalculatorDisplay.cpp b/src/CalcViewModel/Common/CalculatorDisplay.cpp index cd531e01..4da98129 100644 --- a/src/CalcViewModel/Common/CalculatorDisplay.cpp +++ b/src/CalcViewModel/Common/CalculatorDisplay.cpp @@ -36,7 +36,7 @@ void CalculatorDisplay::SetPrimaryDisplay(_In_ const wstring& displayStringValue } } -void CalculatorDisplay::SetParenDisplayText(_In_ const std::wstring& parenthesisCount) +void CalculatorDisplay::SetParenthesisNumber(_In_ unsigned int parenthesisCount) { if (m_callbackReference != nullptr) { diff --git a/src/CalcViewModel/Common/CalculatorDisplay.h b/src/CalcViewModel/Common/CalculatorDisplay.h index 9ff06a6e..877bdf06 100644 --- a/src/CalcViewModel/Common/CalculatorDisplay.h +++ b/src/CalcViewModel/Common/CalculatorDisplay.h @@ -21,7 +21,7 @@ namespace CalculatorApp void SetExpressionDisplay(_Inout_ std::shared_ptr>> const &tokens, _Inout_ std::shared_ptr>> const &commands) override; void SetMemorizedNumbers(_In_ const std::vector& memorizedNumbers) override; void OnHistoryItemAdded(_In_ unsigned int addedItemIndex) override; - void SetParenDisplayText(_In_ const std::wstring& parenthesisCount) override; + void SetParenthesisNumber(_In_ unsigned int parenthesisCount) override; void OnNoRightParenAdded() override; void MaxDigitsReached() override; void BinaryOperatorReceived() override; diff --git a/src/CalcViewModel/StandardCalculatorViewModel.cpp b/src/CalcViewModel/StandardCalculatorViewModel.cpp index c01c4789..944b8d1a 100644 --- a/src/CalcViewModel/StandardCalculatorViewModel.cpp +++ b/src/CalcViewModel/StandardCalculatorViewModel.cpp @@ -48,7 +48,6 @@ namespace CalculatorResourceKeys StringReference DecButton(L"Format_DecButtonValue"); StringReference OctButton(L"Format_OctButtonValue"); StringReference BinButton(L"Format_BinButtonValue"); - StringReference LeftParenthesisAutomationFormat(L"Format_OpenParenthesisAutomationNamePrefix"); StringReference OpenParenthesisCountAutomationFormat(L"Format_OpenParenthesisCountAutomationNamePrefix"); StringReference NoParenthesisAdded(L"NoRightParenthesisAdded_Announcement"); StringReference MaxDigitsReachedFormat(L"Format_MaxDigitsReached"); @@ -80,8 +79,8 @@ StandardCalculatorViewModel::StandardCalculatorViewModel() : m_isBinaryBitFlippingEnabled(false), m_CurrentRadixType(RADIX_TYPE::DEC_RADIX), m_CurrentAngleType(NumbersAndOperatorsEnum::Degree), - m_OpenParenthesisCount(L""), m_Announcement(nullptr), + m_OpenParenthesisCount(0), m_feedbackForButtonPress(nullptr), m_isRtlLanguage(false), m_localizedMaxDigitsReachedAutomationFormat(nullptr), @@ -102,7 +101,6 @@ StandardCalculatorViewModel::StandardCalculatorViewModel() : m_localizedDecimalAutomationFormat = AppResourceProvider::GetInstance().GetResourceString(CalculatorResourceKeys::DecButton); m_localizedOctalAutomationFormat = AppResourceProvider::GetInstance().GetResourceString(CalculatorResourceKeys::OctButton); m_localizedBinaryAutomationFormat = AppResourceProvider::GetInstance().GetResourceString(CalculatorResourceKeys::BinButton); - m_leftParenthesisAutomationFormat = AppResourceProvider::GetInstance().GetResourceString(CalculatorResourceKeys::LeftParenthesisAutomationFormat); // Initialize the Automation Name CalculationResultAutomationName = GetLocalizedStringFormat(m_localizedCalculationResultAutomationFormat, m_DisplayValue); @@ -216,19 +214,23 @@ void StandardCalculatorViewModel::DisplayPasteError() m_standardCalculatorManager.DisplayPasteError(); } -void StandardCalculatorViewModel::SetParenthesisCount(_In_ const wstring& parenthesisCount) +void StandardCalculatorViewModel::SetParenthesisCount(_In_ unsigned int parenthesisCount) { + if (m_OpenParenthesisCount == parenthesisCount) + { + return; + } + + OpenParenthesisCount = parenthesisCount; if (IsProgrammer || IsScientific) { - OpenParenthesisCount = ref new String(parenthesisCount.c_str()); - RaisePropertyChanged("LeftParenthesisAutomationName"); + SetOpenParenthesisCountNarratorAnnouncement(); } } void StandardCalculatorViewModel::SetOpenParenthesisCountNarratorAnnouncement() { - String^ parenthesisCount = ((m_OpenParenthesisCount == nullptr) ? "0" : m_OpenParenthesisCount); - wstring localizedParenthesisCount = parenthesisCount->Data(); + wstring localizedParenthesisCount = to_wstring(m_OpenParenthesisCount).c_str(); LocalizationSettings::GetInstance().LocalizeDisplayValue(&localizedParenthesisCount); String^ announcement = LocalizationStringUtil::GetLocalizedNarratorAnnouncement( @@ -281,15 +283,6 @@ void StandardCalculatorViewModel::DisableButtons(CommandType selectedExpressionC } } -String ^ StandardCalculatorViewModel::GetLeftParenthesisAutomationName() -{ - String^ parenthesisCount = ((m_OpenParenthesisCount == nullptr) ? "0" : m_OpenParenthesisCount); - wstring localizedParenthesisCount = std::wstring(parenthesisCount->Data()); - LocalizationSettings::GetInstance().LocalizeDisplayValue(&localizedParenthesisCount); - - return GetLocalizedStringFormat(m_leftParenthesisAutomationFormat, ref new String(localizedParenthesisCount.c_str())); -} - void StandardCalculatorViewModel::SetExpressionDisplay(_Inout_ shared_ptr>> const &tokens, _Inout_ shared_ptr>> const &commands) { m_tokens = tokens; @@ -1422,29 +1415,29 @@ void StandardCalculatorViewModel::SaveEditedCommand(_In_ unsigned int tokenPosit switch (nOpCode) { - case static_cast(Command::CommandASIN) : - updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast(Command::CommandSIN), true, angleType); - break; - case static_cast(Command::CommandACOS) : - updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast(Command::CommandCOS), true, angleType); - break; - case static_cast(Command::CommandATAN) : - updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast(Command::CommandTAN), true, angleType); - break; - case static_cast(Command::CommandASINH) : - updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast(Command::CommandSINH), true, angleType); - break; - case static_cast(Command::CommandACOSH) : - updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast(Command::CommandCOSH), true, angleType); - break; - case static_cast(Command::CommandATANH) : - updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast(Command::CommandTANH), true, angleType); - break; - case static_cast(Command::CommandPOWE) : - updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast(Command::CommandLN), true, angleType); - break; - default: - updatedToken = CCalcEngine::OpCodeToUnaryString(nOpCode, false, angleType); + case static_cast(Command::CommandASIN) : + updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast(Command::CommandSIN), true, angleType); + break; + case static_cast(Command::CommandACOS) : + updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast(Command::CommandCOS), true, angleType); + break; + case static_cast(Command::CommandATAN) : + updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast(Command::CommandTAN), true, angleType); + break; + case static_cast(Command::CommandASINH) : + updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast(Command::CommandSINH), true, angleType); + break; + case static_cast(Command::CommandACOSH) : + updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast(Command::CommandCOSH), true, angleType); + break; + case static_cast(Command::CommandATANH) : + updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast(Command::CommandTANH), true, angleType); + break; + case static_cast(Command::CommandPOWE) : + updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast(Command::CommandLN), true, angleType); + break; + default: + updatedToken = CCalcEngine::OpCodeToUnaryString(nOpCode, false, angleType); } if ((token.first.length() > 0) && (token.first[token.first.length() - 1] == L'(')) { diff --git a/src/CalcViewModel/StandardCalculatorViewModel.h b/src/CalcViewModel/StandardCalculatorViewModel.h index ba6dc82b..91ba2557 100644 --- a/src/CalcViewModel/StandardCalculatorViewModel.h +++ b/src/CalcViewModel/StandardCalculatorViewModel.h @@ -75,12 +75,12 @@ namespace CalculatorApp OBSERVABLE_PROPERTY_RW(bool, IsDwordEnabled); OBSERVABLE_PROPERTY_RW(bool, IsWordEnabled); OBSERVABLE_PROPERTY_RW(bool, IsByteEnabled); - OBSERVABLE_NAMED_PROPERTY_RW(Platform::String^, OpenParenthesisCount); OBSERVABLE_PROPERTY_RW(int, CurrentRadixType); OBSERVABLE_PROPERTY_RW(bool, AreTokensUpdated); OBSERVABLE_PROPERTY_RW(bool, AreHistoryShortcutsEnabled); OBSERVABLE_PROPERTY_RW(bool, AreProgrammerRadixOperatorsEnabled); OBSERVABLE_PROPERTY_RW(CalculatorApp::Common::Automation::NarratorAnnouncement^, Announcement); + OBSERVABLE_PROPERTY_R(unsigned int, OpenParenthesisCount); COMMAND_FOR_METHOD(CopyCommand, StandardCalculatorViewModel::OnCopyCommand); COMMAND_FOR_METHOD(PasteCommand, StandardCalculatorViewModel::OnPasteCommand); @@ -255,14 +255,6 @@ namespace CalculatorApp void set(bool value) { m_completeTextSelection = value; } } - property Platform::String^ LeftParenthesisAutomationName - { - Platform::String^ get() - { - return GetLeftParenthesisAutomationName(); - } - } - internal: void OnPaste(Platform::String^ pastedString, CalculatorApp::Common::ViewMode mode); void OnCopyCommand(Platform::Object^ parameter); @@ -283,7 +275,7 @@ namespace CalculatorApp void SetTokens(_Inout_ std::shared_ptr>> const &tokens); void SetExpressionDisplay(_Inout_ std::shared_ptr>> const &tokens, _Inout_ std::shared_ptr>> const &commands); void SetHistoryExpressionDisplay(_Inout_ std::shared_ptr>> const &tokens, _Inout_ std::shared_ptr>> const &commands); - void SetParenthesisCount(_In_ const std::wstring& parenthesisCount); + void SetParenthesisCount(_In_ unsigned int parenthesisCount); void SetOpenParenthesisCountNarratorAnnouncement(); void OnNoRightParenAdded(); void SetNoParenAddedNarratorAnnouncement(); @@ -354,7 +346,6 @@ namespace CalculatorApp bool m_isLastOperationHistoryLoad; Platform::String^ m_selectedExpressionLastData; Common::DisplayExpressionToken^ m_selectedExpressionToken; - Platform::String^ m_leftParenthesisAutomationFormat; Platform::String^ LocalizeDisplayValue(_In_ std::wstring const &displayValue, _In_ bool isError); Platform::String^ CalculateNarratorDisplayValue(_In_ std::wstring const &displayValue, _In_ Platform::String^ localizedDisplayValue, _In_ bool isError); @@ -364,7 +355,6 @@ namespace CalculatorApp CalculationManager::Command ConvertToOperatorsEnum(NumbersAndOperatorsEnum operation); void DisableButtons(CalculationManager::CommandType selectedExpressionCommandType); - Platform::String^ GetLeftParenthesisAutomationName(); Platform::String^ m_feedbackForButtonPress; void OnButtonPressed(Platform::Object^ parameter); diff --git a/src/Calculator/Resources/am-ET/Resources.resw b/src/Calculator/Resources/am-ET/Resources.resw index 24edcb5f..5ccff34a 100644 --- a/src/Calculator/Resources/am-ET/Resources.resw +++ b/src/Calculator/Resources/am-ET/Resources.resw @@ -901,10 +901,7 @@ የግራ ቅንፍ Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - የግራ ቅንፍ፣ የክፍት ቅንፍ ቁጥር %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + የቀኝ ቅንፍ Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/ar-SA/Resources.resw b/src/Calculator/Resources/ar-SA/Resources.resw index 051c055c..90780d3c 100644 --- a/src/Calculator/Resources/ar-SA/Resources.resw +++ b/src/Calculator/Resources/ar-SA/Resources.resw @@ -901,10 +901,7 @@ أقواس يسرى Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - القوس الأيسر، عدد الأقواس المفتوحة %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + أقواس يمنى Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/az-Latn-AZ/Resources.resw b/src/Calculator/Resources/az-Latn-AZ/Resources.resw index 60fa2da8..e5941d65 100644 --- a/src/Calculator/Resources/az-Latn-AZ/Resources.resw +++ b/src/Calculator/Resources/az-Latn-AZ/Resources.resw @@ -901,10 +901,7 @@ Sol mötərizə Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - Sol mötərizə, açıq mötərizənin sayı %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + Sağ mötərizə Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/be-BY/Resources.resw b/src/Calculator/Resources/be-BY/Resources.resw index f5498b31..85457396 100644 --- a/src/Calculator/Resources/be-BY/Resources.resw +++ b/src/Calculator/Resources/be-BY/Resources.resw @@ -901,10 +901,7 @@ Левая дужка Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - Левая дужка, пачатак адліку дужак (%1) - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + Правая дужка Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/bg-BG/Resources.resw b/src/Calculator/Resources/bg-BG/Resources.resw index 069f995a..9737c537 100644 --- a/src/Calculator/Resources/bg-BG/Resources.resw +++ b/src/Calculator/Resources/bg-BG/Resources.resw @@ -901,10 +901,7 @@ Лява скоба Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - Лява скоба, брой на отваряща скоба %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + Дясна скоба Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/ca-ES/Resources.resw b/src/Calculator/Resources/ca-ES/Resources.resw index b2672e8f..28177726 100644 --- a/src/Calculator/Resources/ca-ES/Resources.resw +++ b/src/Calculator/Resources/ca-ES/Resources.resw @@ -901,10 +901,7 @@ Parèntesi d'obertura Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - Parèntesi d'obertura, recompte de parèntesis d'obertura %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + Parèntesi de tancament Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/cs-CZ/Resources.resw b/src/Calculator/Resources/cs-CZ/Resources.resw index 85db6271..db9a320e 100644 --- a/src/Calculator/Resources/cs-CZ/Resources.resw +++ b/src/Calculator/Resources/cs-CZ/Resources.resw @@ -901,10 +901,7 @@ Levá závorka Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - Levá závorka, počet otevřených závorek %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + Pravá závorka Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/da-DK/Resources.resw b/src/Calculator/Resources/da-DK/Resources.resw index 5f69bd5d..96c16947 100644 --- a/src/Calculator/Resources/da-DK/Resources.resw +++ b/src/Calculator/Resources/da-DK/Resources.resw @@ -901,10 +901,7 @@ Venstreparentes Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - Venstre parentes, åben parentes antal %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + Højreparentes Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/de-DE/Resources.resw b/src/Calculator/Resources/de-DE/Resources.resw index 8d0a6adb..2c76b451 100644 --- a/src/Calculator/Resources/de-DE/Resources.resw +++ b/src/Calculator/Resources/de-DE/Resources.resw @@ -901,10 +901,7 @@ Öffnende Klammer Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - Runde Klammer links, Anzahl der öffnenden Klammern: %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + Schließende Klammer Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/el-GR/Resources.resw b/src/Calculator/Resources/el-GR/Resources.resw index 5a394bf3..cc791405 100644 --- a/src/Calculator/Resources/el-GR/Resources.resw +++ b/src/Calculator/Resources/el-GR/Resources.resw @@ -901,10 +901,7 @@ Αριστερή παρένθεση Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - Αριστερή παρένθεση, πλήθος ανοιχτών παρενθέσεων %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + Δεξιά παρένθεση Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/en-GB/Resources.resw b/src/Calculator/Resources/en-GB/Resources.resw index 84310eb0..b8077985 100644 --- a/src/Calculator/Resources/en-GB/Resources.resw +++ b/src/Calculator/Resources/en-GB/Resources.resw @@ -901,10 +901,7 @@ Left parenthesis Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - Left parenthesis, open parenthesis count %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + Right parenthesis Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/es-ES/Resources.resw b/src/Calculator/Resources/es-ES/Resources.resw index e2e44b8e..34cc2c94 100644 --- a/src/Calculator/Resources/es-ES/Resources.resw +++ b/src/Calculator/Resources/es-ES/Resources.resw @@ -901,10 +901,7 @@ Paréntesis de apertura Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - Paréntesis de apertura, número de paréntesis abiertos %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + Paréntesis de cierre Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/es-MX/Resources.resw b/src/Calculator/Resources/es-MX/Resources.resw index a0d04589..44151b87 100644 --- a/src/Calculator/Resources/es-MX/Resources.resw +++ b/src/Calculator/Resources/es-MX/Resources.resw @@ -901,10 +901,7 @@ Paréntesis de apertura Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - Abrir paréntesis, recuento de paréntesis abiertos %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + Paréntesis de cierre Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/et-EE/Resources.resw b/src/Calculator/Resources/et-EE/Resources.resw index 2709cabd..41060649 100644 --- a/src/Calculator/Resources/et-EE/Resources.resw +++ b/src/Calculator/Resources/et-EE/Resources.resw @@ -901,10 +901,7 @@ Vasaksulg Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - Vasaksulg, avavate sulgude arv %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + Paremsulg Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/eu-ES/Resources.resw b/src/Calculator/Resources/eu-ES/Resources.resw index dcea8382..98264063 100644 --- a/src/Calculator/Resources/eu-ES/Resources.resw +++ b/src/Calculator/Resources/eu-ES/Resources.resw @@ -901,10 +901,7 @@ Ezkerreko parentesia Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - Ezkerreko parentesia, ireki %1. parentesia - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + Eskuineko parentesia Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/fa-IR/Resources.resw b/src/Calculator/Resources/fa-IR/Resources.resw index 713f24fa..edd9e34b 100644 --- a/src/Calculator/Resources/fa-IR/Resources.resw +++ b/src/Calculator/Resources/fa-IR/Resources.resw @@ -901,10 +901,7 @@ پرانتز سمت چپ Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - پرانتز چپ، تعداد پرانتزهای باز %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + پرانتز سمت راست Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/fi-FI/Resources.resw b/src/Calculator/Resources/fi-FI/Resources.resw index 71dcaa25..b2a92d88 100644 --- a/src/Calculator/Resources/fi-FI/Resources.resw +++ b/src/Calculator/Resources/fi-FI/Resources.resw @@ -901,10 +901,7 @@ Vasen sulje Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - Vasen sulje, avaavien sulkeiden määrä %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + Oikea sulje Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/fil-PH/Resources.resw b/src/Calculator/Resources/fil-PH/Resources.resw index 24805b92..1409ce52 100644 --- a/src/Calculator/Resources/fil-PH/Resources.resw +++ b/src/Calculator/Resources/fil-PH/Resources.resw @@ -901,10 +901,7 @@ Kaliwang parenthesis Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - Bilang ng kaliwang panaklong, pambukas na panaklong %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + Kanang parenthesis Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/fr-CA/Resources.resw b/src/Calculator/Resources/fr-CA/Resources.resw index b4ad2696..895689d9 100644 --- a/src/Calculator/Resources/fr-CA/Resources.resw +++ b/src/Calculator/Resources/fr-CA/Resources.resw @@ -901,10 +901,7 @@ Parenthèse gauche Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - %1 parenthèses gauches ouvrantes - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + Parenthèse droite Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/fr-FR/Resources.resw b/src/Calculator/Resources/fr-FR/Resources.resw index ef24ec55..c5f0a6c4 100644 --- a/src/Calculator/Resources/fr-FR/Resources.resw +++ b/src/Calculator/Resources/fr-FR/Resources.resw @@ -901,10 +901,7 @@ Parenthèse gauche Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - Parenthèse gauche, nombre de parenthèses ouvertes %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + Parenthèse droite Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/gl-ES/Resources.resw b/src/Calculator/Resources/gl-ES/Resources.resw index dbc0137a..21aac3cd 100644 --- a/src/Calculator/Resources/gl-ES/Resources.resw +++ b/src/Calculator/Resources/gl-ES/Resources.resw @@ -901,10 +901,7 @@ Paréntese esquerda Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - Paréntese de apertura, total de parénteses abertos %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + Paréntese dereita Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/he-IL/Resources.resw b/src/Calculator/Resources/he-IL/Resources.resw index c72e7a71..2a86f3ff 100644 --- a/src/Calculator/Resources/he-IL/Resources.resw +++ b/src/Calculator/Resources/he-IL/Resources.resw @@ -901,10 +901,7 @@ סוגר שמאלי Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - סוגריים ימניים, פתח ספירת סוגריים %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + סוגר ימני Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/hi-IN/Resources.resw b/src/Calculator/Resources/hi-IN/Resources.resw index aeb6b18f..9a4ce3f5 100644 --- a/src/Calculator/Resources/hi-IN/Resources.resw +++ b/src/Calculator/Resources/hi-IN/Resources.resw @@ -901,10 +901,7 @@ बायाँ कोष्ठक Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - बायाँ कोष्ठक, खुले कोष्ठक की संख्या %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + दायाँ कोष्ठक Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/hr-HR/Resources.resw b/src/Calculator/Resources/hr-HR/Resources.resw index 4a3ecbdb..4039f357 100644 --- a/src/Calculator/Resources/hr-HR/Resources.resw +++ b/src/Calculator/Resources/hr-HR/Resources.resw @@ -901,10 +901,7 @@ Lijeva zagrada Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - Lijeva zagrada, broj otvorenih zagrada %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + Desna zagrada Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/hu-HU/Resources.resw b/src/Calculator/Resources/hu-HU/Resources.resw index bef5d1fa..3afa8a62 100644 --- a/src/Calculator/Resources/hu-HU/Resources.resw +++ b/src/Calculator/Resources/hu-HU/Resources.resw @@ -901,10 +901,7 @@ Nyitó zárójel Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - Bal oldali vagy nyitó zárójelek száma: %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + Berekesztő zárójel Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/id-ID/Resources.resw b/src/Calculator/Resources/id-ID/Resources.resw index 9fb7e6b4..dc8fc070 100644 --- a/src/Calculator/Resources/id-ID/Resources.resw +++ b/src/Calculator/Resources/id-ID/Resources.resw @@ -901,10 +901,7 @@ Tanda kurung tutup Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - Tanda kurung kiri, tanda kurung terbuka berjumlah %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + Tanda kurung buka Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/is-IS/Resources.resw b/src/Calculator/Resources/is-IS/Resources.resw index a5f382ef..32c1df20 100644 --- a/src/Calculator/Resources/is-IS/Resources.resw +++ b/src/Calculator/Resources/is-IS/Resources.resw @@ -901,10 +901,7 @@ Vinstri svigi Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - Vinstri svigi, opnir svigar telja %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + Hægri svigi Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/it-IT/Resources.resw b/src/Calculator/Resources/it-IT/Resources.resw index 039fdc97..21abf33e 100644 --- a/src/Calculator/Resources/it-IT/Resources.resw +++ b/src/Calculator/Resources/it-IT/Resources.resw @@ -901,10 +901,7 @@ Parentesi sinistra Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - Conteggio parentesi sinistra, parentesi aperta %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + Parentesi destra Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/ja-JP/Resources.resw b/src/Calculator/Resources/ja-JP/Resources.resw index f0015cb1..805294a3 100644 --- a/src/Calculator/Resources/ja-JP/Resources.resw +++ b/src/Calculator/Resources/ja-JP/Resources.resw @@ -901,10 +901,7 @@ 始め丸かっこ Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - 左かっこ、開きかっこの数 %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + 終わり丸かっこ Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/kk-KZ/Resources.resw b/src/Calculator/Resources/kk-KZ/Resources.resw index aac098dd..9cae015a 100644 --- a/src/Calculator/Resources/kk-KZ/Resources.resw +++ b/src/Calculator/Resources/kk-KZ/Resources.resw @@ -901,10 +901,7 @@ Сол жақ жақша Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - Сол жақ жақша, ашық жақша саны: %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + Оң жақ жақша Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/km-KH/Resources.resw b/src/Calculator/Resources/km-KH/Resources.resw index 2ccfb850..001536c3 100644 --- a/src/Calculator/Resources/km-KH/Resources.resw +++ b/src/Calculator/Resources/km-KH/Resources.resw @@ -901,10 +901,7 @@ វង់ក្រចកឆ្វេង Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - វង់​ក្រចក​ឆ្វេង បើក​ការ​រាប់​វង់​ក្រចក %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + វង់ក្រចកស្តាំ Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/kn-IN/Resources.resw b/src/Calculator/Resources/kn-IN/Resources.resw index c6a2cb3c..f7205b98 100644 --- a/src/Calculator/Resources/kn-IN/Resources.resw +++ b/src/Calculator/Resources/kn-IN/Resources.resw @@ -901,10 +901,7 @@ ಎಡ ಆವರಣ ಚಿಹ್ನೆ Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - ಎಡ ಆವರಣ, ಬಲ ಆವರಣ ಎಣಿಕೆ %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + ಬಲ ಆವರಣ ಚಿಹ್ನೆ Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/ko-KR/Resources.resw b/src/Calculator/Resources/ko-KR/Resources.resw index 6a9c6903..636cd7fa 100644 --- a/src/Calculator/Resources/ko-KR/Resources.resw +++ b/src/Calculator/Resources/ko-KR/Resources.resw @@ -901,10 +901,7 @@ 여는 괄호 Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - 왼쪽 괄호 또는 여는 괄호 수 %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + 닫는 괄호 Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/lo-LA/Resources.resw b/src/Calculator/Resources/lo-LA/Resources.resw index 4ca195ee..668cbcfd 100644 --- a/src/Calculator/Resources/lo-LA/Resources.resw +++ b/src/Calculator/Resources/lo-LA/Resources.resw @@ -901,10 +901,7 @@ ວົງເລັບຊ້າຍ Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - <mrk mtype="seg" mid="55">ວົງເລັບຊ້າຍ, ເປີດຍອດລວມວົງເລັບ %1</mrk> - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + ວົງເລັບຂວາ Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/lt-LT/Resources.resw b/src/Calculator/Resources/lt-LT/Resources.resw index 65350a0a..6fe0cdb0 100644 --- a/src/Calculator/Resources/lt-LT/Resources.resw +++ b/src/Calculator/Resources/lt-LT/Resources.resw @@ -901,10 +901,7 @@ Kairysis lenktinis skliaustas Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - Kairysis skliaustas, atidarančio skliausto skaičius %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + Dešinysis lenktinis skliaustas Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/lv-LV/Resources.resw b/src/Calculator/Resources/lv-LV/Resources.resw index 3925267a..fd0aa0d3 100644 --- a/src/Calculator/Resources/lv-LV/Resources.resw +++ b/src/Calculator/Resources/lv-LV/Resources.resw @@ -901,10 +901,7 @@ Kreisās puses apaļā iekava Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - Kreisā iekava, atvērto iekavu skaits: %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + Labās puses apaļā iekava Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/mk-MK/Resources.resw b/src/Calculator/Resources/mk-MK/Resources.resw index e655626d..ae662665 100644 --- a/src/Calculator/Resources/mk-MK/Resources.resw +++ b/src/Calculator/Resources/mk-MK/Resources.resw @@ -901,10 +901,7 @@ Лева заграда Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - Лева заграда, отворена заграда пресметува %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + Десна заграда Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/ml-IN/Resources.resw b/src/Calculator/Resources/ml-IN/Resources.resw index 4c49b6db..dfd4f85c 100644 --- a/src/Calculator/Resources/ml-IN/Resources.resw +++ b/src/Calculator/Resources/ml-IN/Resources.resw @@ -901,10 +901,7 @@ ഇടത് ആവരണചിഹ്നം Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - ഇടത് പാരന്തെസിസ്, പാരന്തെസിസ് കൗണ്ട് %1 തുറക്കുക - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + വലത് ബ്രാക്കറ്റ് Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/ms-MY/Resources.resw b/src/Calculator/Resources/ms-MY/Resources.resw index 11478d55..f92fb352 100644 --- a/src/Calculator/Resources/ms-MY/Resources.resw +++ b/src/Calculator/Resources/ms-MY/Resources.resw @@ -901,10 +901,7 @@ Tanda kurungan kiri Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - Tanda kurung kiri, buka kiraan tanda kurung %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + Tanda kurungan kanan Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/nb-NO/Resources.resw b/src/Calculator/Resources/nb-NO/Resources.resw index 54d286c6..7bdbe851 100644 --- a/src/Calculator/Resources/nb-NO/Resources.resw +++ b/src/Calculator/Resources/nb-NO/Resources.resw @@ -901,10 +901,7 @@ Venstreparentes Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - Venstreparentes, åpen parentes teller %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + Høyreparentes Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/nl-NL/Resources.resw b/src/Calculator/Resources/nl-NL/Resources.resw index cd523a0f..da027ca9 100644 --- a/src/Calculator/Resources/nl-NL/Resources.resw +++ b/src/Calculator/Resources/nl-NL/Resources.resw @@ -901,10 +901,7 @@ Haakje openen Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - Haakje openen, aantal haakjes openen %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + Haakje sluiten Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/pl-PL/Resources.resw b/src/Calculator/Resources/pl-PL/Resources.resw index 0aa9f567..6f168924 100644 --- a/src/Calculator/Resources/pl-PL/Resources.resw +++ b/src/Calculator/Resources/pl-PL/Resources.resw @@ -901,10 +901,7 @@ Lewy nawias Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - Lewy nawias, liczba otwartych nawiasów: %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + Prawy nawias Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/pt-BR/Resources.resw b/src/Calculator/Resources/pt-BR/Resources.resw index 8a9fb639..9caeb8d7 100644 --- a/src/Calculator/Resources/pt-BR/Resources.resw +++ b/src/Calculator/Resources/pt-BR/Resources.resw @@ -901,10 +901,7 @@ Parêntese esquerdo Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - Parêntese esquerdo, contagem de parêntese de abertura %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + Parêntese direito Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/pt-PT/Resources.resw b/src/Calculator/Resources/pt-PT/Resources.resw index d8f59c86..3a120893 100644 --- a/src/Calculator/Resources/pt-PT/Resources.resw +++ b/src/Calculator/Resources/pt-PT/Resources.resw @@ -901,10 +901,7 @@ Parêntese à esquerda Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - Parêntese à esquerda, abrir contagem de parênteses %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + Parêntese à direita Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/ro-RO/Resources.resw b/src/Calculator/Resources/ro-RO/Resources.resw index 71f717ed..02a518d5 100644 --- a/src/Calculator/Resources/ro-RO/Resources.resw +++ b/src/Calculator/Resources/ro-RO/Resources.resw @@ -901,10 +901,7 @@ Paranteză stânga Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - Contor paranteze stânga, paranteze deschise %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + Paranteză dreapta Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/ru-RU/Resources.resw b/src/Calculator/Resources/ru-RU/Resources.resw index b1397c57..9c46030e 100644 --- a/src/Calculator/Resources/ru-RU/Resources.resw +++ b/src/Calculator/Resources/ru-RU/Resources.resw @@ -901,10 +901,7 @@ Открывающая круглая скобка Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - Левая круглая скобка, количество открывающих круглых скобок — %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + Закрывающая круглая скобка Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/sk-SK/Resources.resw b/src/Calculator/Resources/sk-SK/Resources.resw index 220ab2e7..48c4aeb6 100644 --- a/src/Calculator/Resources/sk-SK/Resources.resw +++ b/src/Calculator/Resources/sk-SK/Resources.resw @@ -901,10 +901,7 @@ Ľavá zátvorka Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - Ľavá zátvorka, počet ľavých zátvoriek je %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + Pravá zátvorka Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/sl-SI/Resources.resw b/src/Calculator/Resources/sl-SI/Resources.resw index 861bfdfd..e2ef8cdc 100644 --- a/src/Calculator/Resources/sl-SI/Resources.resw +++ b/src/Calculator/Resources/sl-SI/Resources.resw @@ -901,10 +901,7 @@ Levi oklepaj Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - Levi oklepaj, število oklepajev %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + Desni oklepaj Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/sq-AL/Resources.resw b/src/Calculator/Resources/sq-AL/Resources.resw index 577d6e9f..10165d09 100644 --- a/src/Calculator/Resources/sq-AL/Resources.resw +++ b/src/Calculator/Resources/sq-AL/Resources.resw @@ -901,10 +901,7 @@ Kllapa e majtë Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - Kllapa e majtë, numri i kllapave hapëse %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + Kllapa e djathtë Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/sr-Latn-RS/Resources.resw b/src/Calculator/Resources/sr-Latn-RS/Resources.resw index 5939e576..d4545c5b 100644 --- a/src/Calculator/Resources/sr-Latn-RS/Resources.resw +++ b/src/Calculator/Resources/sr-Latn-RS/Resources.resw @@ -901,10 +901,7 @@ Leva zagrada Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - Otvorena zagrada, broj otvorenih zagrada %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + Desna zagrada Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/sv-SE/Resources.resw b/src/Calculator/Resources/sv-SE/Resources.resw index 4bdb8fa9..4e5afb85 100644 --- a/src/Calculator/Resources/sv-SE/Resources.resw +++ b/src/Calculator/Resources/sv-SE/Resources.resw @@ -901,10 +901,7 @@ Vänster parentes Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - Vänster parentes, antal inledande parenteser är %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + Höger parentes Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/sw-KE/Resources.resw b/src/Calculator/Resources/sw-KE/Resources.resw index 0faa58ca..15a1cfc8 100644 --- a/src/Calculator/Resources/sw-KE/Resources.resw +++ b/src/Calculator/Resources/sw-KE/Resources.resw @@ -901,10 +901,7 @@ Mabano ya kushoto Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - Mabano ya kushoto, fungua idadi ya mabano %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + Mabano ya kulia Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/ta-IN/Resources.resw b/src/Calculator/Resources/ta-IN/Resources.resw index 17c7e276..7bbfc867 100644 --- a/src/Calculator/Resources/ta-IN/Resources.resw +++ b/src/Calculator/Resources/ta-IN/Resources.resw @@ -901,10 +901,7 @@ இடது அடைப்புக்குறி Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - இடது அடைப்புக்குறி, திறப்பு அடைப்புக்குறி கணக்கு %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + வலது அடைப்புக்குறி Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/te-IN/Resources.resw b/src/Calculator/Resources/te-IN/Resources.resw index 455a5670..40f55346 100644 --- a/src/Calculator/Resources/te-IN/Resources.resw +++ b/src/Calculator/Resources/te-IN/Resources.resw @@ -901,10 +901,7 @@ ఎడమ కుండలీకరణం Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - ఎడమ కుండలీకరణం, కుండలీకరణ గణనను %1 తెరవు - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + కుడి కుండలీకరణం Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/th-TH/Resources.resw b/src/Calculator/Resources/th-TH/Resources.resw index df9449b9..a3cbf576 100644 --- a/src/Calculator/Resources/th-TH/Resources.resw +++ b/src/Calculator/Resources/th-TH/Resources.resw @@ -901,10 +901,7 @@ วงเล็บเปิด Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - วงเล็บเปิด จำนวนวงเล็บเปิด %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + วงเล็บปิด Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/tr-TR/Resources.resw b/src/Calculator/Resources/tr-TR/Resources.resw index 0e2fa16f..08403c8c 100644 --- a/src/Calculator/Resources/tr-TR/Resources.resw +++ b/src/Calculator/Resources/tr-TR/Resources.resw @@ -901,10 +901,7 @@ Sol parantez Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - Sol parantez, parantez sayımını aç %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + Sağ parantez Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/uk-UA/Resources.resw b/src/Calculator/Resources/uk-UA/Resources.resw index 332499ac..66d44cb7 100644 --- a/src/Calculator/Resources/uk-UA/Resources.resw +++ b/src/Calculator/Resources/uk-UA/Resources.resw @@ -901,10 +901,7 @@ Ліва кругла дужка Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - Ліва кругла дужка, кількість відкривних круглих дужок – %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + Права кругла дужка Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/uz-Latn-UZ/Resources.resw b/src/Calculator/Resources/uz-Latn-UZ/Resources.resw index 40d72599..257528d1 100644 --- a/src/Calculator/Resources/uz-Latn-UZ/Resources.resw +++ b/src/Calculator/Resources/uz-Latn-UZ/Resources.resw @@ -901,10 +901,7 @@ Chap qavs Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - Chap qavs, ochiq qavslar soni - %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + O‘ng qavs Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/vi-VN/Resources.resw b/src/Calculator/Resources/vi-VN/Resources.resw index c1febc7f..606eba80 100644 --- a/src/Calculator/Resources/vi-VN/Resources.resw +++ b/src/Calculator/Resources/vi-VN/Resources.resw @@ -901,10 +901,7 @@ Dấu ngoặc đơn trái Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - Ngoặc trái, tính ngoặc mở %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + Dấu ngoặc đơn phải Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/zh-CN/Resources.resw b/src/Calculator/Resources/zh-CN/Resources.resw index c64d8e8d..786d6f7d 100644 --- a/src/Calculator/Resources/zh-CN/Resources.resw +++ b/src/Calculator/Resources/zh-CN/Resources.resw @@ -901,10 +901,7 @@ 左括号 Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - 左括号,左开式括号计数 %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + 右括号 Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Resources/zh-TW/Resources.resw b/src/Calculator/Resources/zh-TW/Resources.resw index 2e9708fa..ac0798ad 100644 --- a/src/Calculator/Resources/zh-TW/Resources.resw +++ b/src/Calculator/Resources/zh-TW/Resources.resw @@ -901,10 +901,7 @@ 左括弧 Screen reader prompt for the Calculator "(" button on the scientific operator keypad - - 左括弧,左括弧計數 %1 - {Locked="%1"} Screen reader prompt for the Calculator "(" button on the scientific operator keypad. %1 is the localized count of open parenthesis, e.g. "2". - + 右括弧 Screen reader prompt for the Calculator ")" button on the scientific operator keypad diff --git a/src/Calculator/Views/CalculatorProgrammerRadixOperators.xaml b/src/Calculator/Views/CalculatorProgrammerRadixOperators.xaml index 5c84f4f7..06cf0123 100644 --- a/src/Calculator/Views/CalculatorProgrammerRadixOperators.xaml +++ b/src/Calculator/Views/CalculatorProgrammerRadixOperators.xaml @@ -409,10 +409,10 @@ Style="{StaticResource ParenthesisCalcButtonStyle}" FontSize="18" AutomationProperties.AutomationId="openParenthesisButton" - AutomationProperties.Name="{Binding LeftParenthesisAutomationName}" ButtonId="OpenParenthesis" Content="(" - Tag="{x:Bind Model.OpenParenthesisCount, Mode=OneWay}"/> + GotFocus="OpenParenthesisButton_GotFocus" + Tag="{x:Bind ParenthesisCountToString(Model.OpenParenthesisCount), Mode=OneWay}"/> ProgModeRadixChange += ref new ProgModeRadixChangeHandler(this, &CalculatorProgrammerRadixOperators::ProgModeRadixChange); - m_propertyChangedToken = Model->PropertyChanged += ref new PropertyChangedEventHandler(this, &CalculatorProgrammerRadixOperators::OnViewModelPropertyChanged); } void CalculatorProgrammerRadixOperators::OnUnloaded(Object^, RoutedEventArgs^) { Model->ProgModeRadixChange -= m_progModeRadixChangeToken; - Model->PropertyChanged -= m_propertyChangedToken; } void CalculatorProgrammerRadixOperators::Shift_Clicked(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e) @@ -100,10 +98,12 @@ void CalculatorProgrammerRadixOperators::IsErrorVisualState::set(bool value) } } -void CalculatorProgrammerRadixOperators::OnViewModelPropertyChanged(Object^ sender, PropertyChangedEventArgs^ e) -{ - if (e->PropertyName == StandardCalculatorViewModel::OpenParenthesisCountPropertyName && closeParenthesisButton->FocusState != ::FocusState::Unfocused) - { - Model->SetOpenParenthesisCountNarratorAnnouncement(); - } +String^ CalculatorProgrammerRadixOperators::ParenthesisCountToString(unsigned int count) { + return (count == 0) ? ref new String() : ref new String(to_wstring(count).data()); +} + + +void CalculatorProgrammerRadixOperators::CalculatorProgrammerRadixOperators::OpenParenthesisButton_GotFocus(Object^ sender, RoutedEventArgs^ e) +{ + Model->SetOpenParenthesisCountNarratorAnnouncement(); } diff --git a/src/Calculator/Views/CalculatorProgrammerRadixOperators.xaml.h b/src/Calculator/Views/CalculatorProgrammerRadixOperators.xaml.h index 7dd819d0..407fb1a6 100644 --- a/src/Calculator/Views/CalculatorProgrammerRadixOperators.xaml.h +++ b/src/Calculator/Views/CalculatorProgrammerRadixOperators.xaml.h @@ -26,6 +26,7 @@ namespace CalculatorApp bool get(); void set(bool value); } + Platform::String^ ParenthesisCountToString(unsigned int count); DEPENDENCY_PROPERTY_OWNER(CalculatorProgrammerRadixOperators); @@ -35,10 +36,9 @@ namespace CalculatorApp void OnLoaded(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); void OnUnloaded(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); void ProgModeRadixChange(); - void OnViewModelPropertyChanged(Platform::Object^ sender, Windows::UI::Xaml::Data::PropertyChangedEventArgs ^ e); bool m_isErrorVisualState; Windows::Foundation::EventRegistrationToken m_progModeRadixChangeToken; - Windows::Foundation::EventRegistrationToken m_propertyChangedToken; + void OpenParenthesisButton_GotFocus(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); }; } diff --git a/src/Calculator/Views/CalculatorScientificOperators.xaml b/src/Calculator/Views/CalculatorScientificOperators.xaml index 3db97aa9..1ef614c3 100644 --- a/src/Calculator/Views/CalculatorScientificOperators.xaml +++ b/src/Calculator/Views/CalculatorScientificOperators.xaml @@ -11,8 +11,6 @@ x:Name="ControlRoot" d:DesignHeight="400" d:DesignWidth="315" - Loaded="OnLoaded" - Unloaded="OnUnloaded" mc:Ignorable="d"> @@ -729,10 +727,10 @@ Style="{StaticResource ParenthesisCalcButtonStyle}" FontSize="19" AutomationProperties.AutomationId="openParenthesisButton" - AutomationProperties.Name="{Binding LeftParenthesisAutomationName}" ButtonId="OpenParenthesis" Content="(" - Tag="{x:Bind Model.OpenParenthesisCount, Mode=OneWay}"/> + GotFocus="OpenParenthesisButton_GotFocus" + Tag="{x:Bind ParenthesisCountToString(Model.OpenParenthesisCount), Mode=OneWay}"/> PropertyChanged += ref new PropertyChangedEventHandler(this, &CalculatorScientificOperators::OnViewModelPropertyChanged); -} -void CalculatorScientificOperators::OnUnloaded(Object^, RoutedEventArgs^) -{ - Model->PropertyChanged -= m_propertyChangedToken; -} - void CalculatorScientificOperators::ShortLayout_Completed(_In_ Platform::Object^ /*sender*/, _In_ Platform::Object^ /*e*/) { IsWideLayout = false; @@ -107,10 +99,11 @@ void CalculatorScientificOperators::SetOperatorRowVisibility() InvRow2->Visibility = invRowVis; } -void CalculatorScientificOperators::OnViewModelPropertyChanged(Object^ sender, PropertyChangedEventArgs^ e) +void CalculatorScientificOperators::OpenParenthesisButton_GotFocus(Object^ sender, RoutedEventArgs^ e) { - if (e->PropertyName == StandardCalculatorViewModel::OpenParenthesisCountPropertyName && closeParenthesisButton->FocusState != ::FocusState::Unfocused) - { - Model->SetOpenParenthesisCountNarratorAnnouncement(); - } + Model->SetOpenParenthesisCountNarratorAnnouncement(); +} + +String^ CalculatorScientificOperators::ParenthesisCountToString(unsigned int count) { + return (count == 0) ? ref new String() : ref new String(to_wstring(count).data()); } diff --git a/src/Calculator/Views/CalculatorScientificOperators.xaml.h b/src/Calculator/Views/CalculatorScientificOperators.xaml.h index ec10191c..ebe185ca 100644 --- a/src/Calculator/Views/CalculatorScientificOperators.xaml.h +++ b/src/Calculator/Views/CalculatorScientificOperators.xaml.h @@ -33,7 +33,8 @@ namespace CalculatorApp DEPENDENCY_PROPERTY_WITH_DEFAULT(bool, IsWideLayout, false); bool IsShiftEnabled(bool isWideLayout, bool isErrorState) { return !(isWideLayout || isErrorState); } - + void OpenParenthesisButton_GotFocus(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); + Platform::String^ ParenthesisCountToString(unsigned int count); private: void ShortLayout_Completed(_In_ Platform::Object^ sender, _In_ Platform::Object^ e); void WideLayout_Completed(_In_ Platform::Object^ sender, _In_ Platform::Object^ e); @@ -41,10 +42,5 @@ namespace CalculatorApp void shiftButton_Check(_In_ Platform::Object^ sender, _In_ Windows::UI::Xaml::RoutedEventArgs^ e); void shiftButton_IsEnabledChanged(_In_ Platform::Object^ sender, _In_ Windows::UI::Xaml::DependencyPropertyChangedEventArgs^ e); void SetOperatorRowVisibility(); - void OnViewModelPropertyChanged(Platform::Object^ sender, Windows::UI::Xaml::Data::PropertyChangedEventArgs ^ e); - void OnLoaded(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); - void OnUnloaded(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); - - Windows::Foundation::EventRegistrationToken m_propertyChangedToken; }; } diff --git a/src/Calculator/pch.h b/src/Calculator/pch.h index b29e1e45..f37ca4bf 100644 --- a/src/Calculator/pch.h +++ b/src/Calculator/pch.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include diff --git a/src/CalculatorUnitTests/CalculatorManagerTest.cpp b/src/CalculatorUnitTests/CalculatorManagerTest.cpp index 14939d34..79e0637e 100644 --- a/src/CalculatorUnitTests/CalculatorManagerTest.cpp +++ b/src/CalculatorUnitTests/CalculatorManagerTest.cpp @@ -57,7 +57,7 @@ namespace CalculatorManagerTest m_memorizedNumberStrings = numbers; } - void SetParenDisplayText(const std::wstring& parenthesisCount) override + void SetParenthesisNumber(unsigned int parenthesisCount) override { m_parenDisplay = parenthesisCount; } @@ -115,7 +115,7 @@ namespace CalculatorManagerTest private: wstring m_primaryDisplay; wstring m_expression; - wstring m_parenDisplay; + unsigned int m_parenDisplay; bool m_isError; vector m_memorizedNumberStrings; int m_maxDigitsCalledCount; From 5a6c6f427464fb6a53d7caa0a9879fb3ba61aa39 Mon Sep 17 00:00:00 2001 From: Rudy Huyn Date: Mon, 15 Apr 2019 09:51:06 -0700 Subject: [PATCH 004/154] Prevent the application to crash when the current page is Date Calculation and users paste a text (#391) Fix the else condition in ApplicationViewModel::OnPaste How changes were validated: Manually Fixes #389 --- src/CalcViewModel/ApplicationViewModel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CalcViewModel/ApplicationViewModel.cpp b/src/CalcViewModel/ApplicationViewModel.cpp index f99ce036..358589b5 100644 --- a/src/CalcViewModel/ApplicationViewModel.cpp +++ b/src/CalcViewModel/ApplicationViewModel.cpp @@ -189,7 +189,7 @@ void ApplicationViewModel::OnPasteCommand(Object^ parameter) { ConverterViewModel->OnPasteCommand(parameter); } - else + else if (NavCategory::IsCalculatorViewMode(m_mode)) { CalculatorViewModel->OnPasteCommand(parameter); } From 775771d62a664230edc16d964bc71ea462190f92 Mon Sep 17 00:00:00 2001 From: Matt Cooley Date: Mon, 15 Apr 2019 14:12:10 -0700 Subject: [PATCH 005/154] Internal builds now require the OAuth access token (#457) --- .../prepare-release-internalonly.yaml | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/build/pipelines/templates/prepare-release-internalonly.yaml b/build/pipelines/templates/prepare-release-internalonly.yaml index 363ca049..a6a4973b 100644 --- a/build/pipelines/templates/prepare-release-internalonly.yaml +++ b/build/pipelines/templates/prepare-release-internalonly.yaml @@ -28,8 +28,8 @@ jobs: - task: PkgESSetupBuild@10 displayName: Initialize Package ES inputs: - productName: Calculator - disableWorkspace: true + productName: Calculator + disableWorkspace: true env: XES_DISABLEPROV: true @@ -46,6 +46,8 @@ jobs: - task: PkgESCodeSign@10 displayName: Send bundle to Package ES code signing service + env: + SYSTEM_ACCESSTOKEN: $(System.AccessToken) inputs: signConfigXml: build\config\SignConfig.xml inPathRoot: $(Build.ArtifactStagingDirectory)\appxBundle @@ -60,25 +62,25 @@ jobs: - task: CopyFiles@2 displayName: Copy signed AppxBundle to vpack staging folder inputs: - sourceFolder: $(Build.ArtifactStagingDirectory)\appxBundleSigned - targetFolder: $(Build.ArtifactStagingDirectory)\vpack\appxBundle + sourceFolder: $(Build.ArtifactStagingDirectory)\appxBundleSigned + targetFolder: $(Build.ArtifactStagingDirectory)\vpack\appxBundle - task: PkgESVPack@10 displayName: Create and push vpack for app env: - SYSTEM_ACCESSTOKEN: $(System.AccessToken) + SYSTEM_ACCESSTOKEN: $(System.AccessToken) inputs: - sourceDirectory: $(Build.ArtifactStagingDirectory)\vpack\appxBundle - description: VPack for the Calculator Application - pushPkgName: calculator.app - version: $(versionMajor).$(versionMinor).$(versionBuild) - owner: paxeeapps + sourceDirectory: $(Build.ArtifactStagingDirectory)\vpack\appxBundle + description: VPack for the Calculator Application + pushPkgName: calculator.app + version: $(versionMajor).$(versionMinor).$(versionBuild) + owner: paxeeapps - task: PublishBuildArtifacts@1 displayName: Publish vpack\app artifact with vpack manifest inputs: - pathtoPublish: $(XES_VPACKMANIFESTDIRECTORY)\$(XES_VPACKMANIFESTNAME) - artifactName: vpack\app + pathtoPublish: $(XES_VPACKMANIFESTDIRECTORY)\$(XES_VPACKMANIFESTNAME) + artifactName: vpack\app # TODO (macool): create and push internal test packages and test config From ad25feda6bfac4b4779b92500b01d341931dcbb0 Mon Sep 17 00:00:00 2001 From: Rudy Huyn Date: Tue, 16 Apr 2019 11:29:43 -0700 Subject: [PATCH 006/154] Keep input when users refresh currency rates (#369) Fixes #260 Description of the changes: prevent UnitConverterViewModel to reset values when users click on update rates. recompute UnitConverter's caches (m_ratioMap and m_categoryToUnits) once rates are updated (but check first if the user did/didn't change the category) How changes were validated: Manually tested with fake currency rates (HTTP responses modified on the fly via FiddlerCore) Verified that it works no matter the selected field (From or To) Verified that the currencies selected are kept after a refresh --- src/CalcManager/UnitConverter.cpp | 41 +++++++++++-------- src/CalcManager/UnitConverter.h | 8 ++-- src/CalcViewModel/UnitConverterViewModel.cpp | 12 ++++-- src/CalcViewModel/UnitConverterViewModel.h | 2 + .../UnitConverterViewModelUnitTests.h | 5 ++- 5 files changed, 43 insertions(+), 25 deletions(-) diff --git a/src/CalcManager/UnitConverter.cpp b/src/CalcManager/UnitConverter.cpp index 0548719a..718e47f4 100644 --- a/src/CalcManager/UnitConverter.cpp +++ b/src/CalcManager/UnitConverter.cpp @@ -63,7 +63,8 @@ UnitConverter::UnitConverter(_In_ const shared_ptr& dataLo unquoteConversions[L"{sc}"] = L';'; unquoteConversions[L"{lb}"] = LEFTESCAPECHAR; unquoteConversions[L"{rb}"] = RIGHTESCAPECHAR; - Reset(); + ClearValues(); + ResetCategoriesAndRatios(); } void UnitConverter::Initialize() @@ -75,7 +76,7 @@ bool UnitConverter::CheckLoad() { if (m_categories.empty()) { - Reset(); + ResetCategoriesAndRatios(); } return !m_categories.empty(); } @@ -152,7 +153,6 @@ void UnitConverter::SetCurrentUnitTypes(const Unit& fromType, const Unit& toType Calculate(); UpdateCurrencySymbols(); - UpdateViewModel(); } /// @@ -336,7 +336,8 @@ wstring UnitConverter::Serialize() /// wstring holding the serialized data. If it does not have expected number of parameters, we will ignore it void UnitConverter::DeSerialize(const wstring& serializedData) { - Reset(); + ClearValues(); + ResetCategoriesAndRatios(); if (serializedData.empty()) { @@ -615,7 +616,7 @@ void UnitConverter::SendCommand(Command command) clearFront = false; clearBack = false; ClearValues(); - Reset(); + ResetCategoriesAndRatios(); break; default: @@ -634,8 +635,6 @@ void UnitConverter::SendCommand(Command command) } Calculate(); - - UpdateViewModel(); } /// @@ -824,19 +823,16 @@ vector> UnitConverter::CalculateSuggested() returnVector.push_back(whimsicalReturnVector.at(0)); } - // - return returnVector; } /// -/// Resets the converter to its initial state +/// Resets categories and ratios /// -void UnitConverter::Reset() +void UnitConverter::ResetCategoriesAndRatios() { m_categories = m_dataLoader->LoadOrderedCategories(); - ClearValues(); m_switchedActive = false; if (m_categories.empty()) @@ -881,7 +877,6 @@ void UnitConverter::Reset() } InitializeSelectedUnits(); - Calculate(); } /// @@ -972,11 +967,21 @@ bool UnitConverter::AnyUnitIsEmpty() /// void UnitConverter::Calculate() { - unordered_map conversionTable = m_ratioMap[m_fromType]; - double returnValue = stod(m_currentDisplay); - if (AnyUnitIsEmpty() || (conversionTable[m_toType].ratio == 1.0 && conversionTable[m_toType].offset == 0.0)) + if (AnyUnitIsEmpty()) { m_returnDisplay = m_currentDisplay; + m_returnHasDecimal = m_currentHasDecimal; + TrimString(m_returnDisplay); + UpdateViewModel(); + return; + } + + unordered_map conversionTable = m_ratioMap[m_fromType]; + double returnValue = stod(m_currentDisplay); + if (conversionTable[m_toType].ratio == 1.0 && conversionTable[m_toType].offset == 0.0) + { + m_returnDisplay = m_currentDisplay; + m_returnHasDecimal = m_currentHasDecimal; TrimString(m_returnDisplay); } else @@ -1015,9 +1020,9 @@ void UnitConverter::Calculate() m_returnDisplay = returnString; TrimString(m_returnDisplay); } + m_returnHasDecimal = (m_returnDisplay.find(L'.') != m_returnDisplay.npos); } - - m_returnHasDecimal = (m_returnDisplay.find(L'.') != m_returnDisplay.npos); + UpdateViewModel(); } /// diff --git a/src/CalcManager/UnitConverter.h b/src/CalcManager/UnitConverter.h index 4e130d12..010216f0 100644 --- a/src/CalcManager/UnitConverter.h +++ b/src/CalcManager/UnitConverter.h @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #pragma once @@ -195,6 +195,8 @@ namespace UnitConversionManager virtual void SetViewModelCallback(_In_ const std::shared_ptr& newCallback) = 0; virtual void SetViewModelCurrencyCallback(_In_ const std::shared_ptr& newCallback) = 0; virtual concurrency::task> RefreshCurrencyRatios() = 0; + virtual void Calculate() = 0; + virtual void ResetCategoriesAndRatios() = 0; }; class UnitConverter : public IUnitConverter, public std::enable_shared_from_this @@ -218,6 +220,8 @@ namespace UnitConversionManager void SetViewModelCallback(_In_ const std::shared_ptr& newCallback) override; void SetViewModelCurrencyCallback(_In_ const std::shared_ptr& newCallback) override; concurrency::task> RefreshCurrencyRatios() override; + void Calculate() override; + void ResetCategoriesAndRatios() override; // IUnitConverter static std::vector StringToVector(const std::wstring& w, const wchar_t * delimiter, bool addRemainder = false); @@ -228,9 +232,7 @@ namespace UnitConversionManager bool CheckLoad(); double Convert(double value, ConversionData conversionData); std::vector> CalculateSuggested(); - void Reset(); void ClearValues(); - void Calculate(); void TrimString(std::wstring& input); void InitializeSelectedUnits(); std::wstring RoundSignificant(double num, int numSignificant); diff --git a/src/CalcViewModel/UnitConverterViewModel.cpp b/src/CalcViewModel/UnitConverterViewModel.cpp index 76d9aa3a..446ae582 100644 --- a/src/CalcViewModel/UnitConverterViewModel.cpp +++ b/src/CalcViewModel/UnitConverterViewModel.cpp @@ -165,12 +165,16 @@ void UnitConverterViewModel::PopulateData() } void UnitConverterViewModel::OnCategoryChanged(Object^ parameter) +{ + m_model->SendCommand(UCM::Command::Clear); + ResetCategory(); +} + +void UnitConverterViewModel::ResetCategory() { UCM::Category currentCategory = CurrentCategory->GetModelCategory(); IsCurrencyCurrentCategory = currentCategory.id == NavCategory::Serialize(ViewMode::Currency); - m_model->SendCommand(UCM::Command::Clear); - m_isInputBlocked = false; SetSelectedUnits(); @@ -706,7 +710,9 @@ void UnitConverterViewModel::OnCurrencyDataLoadFinished(bool didLoad) { m_isCurrencyDataLoaded = true; CurrencyDataLoadFailed = !didLoad; - ResetView(); + m_model->ResetCategoriesAndRatios(); + m_model->Calculate(); + ResetCategory(); StringReference key = didLoad ? UnitConverterResourceKeys::CurrencyRatesUpdated : UnitConverterResourceKeys::CurrencyRatesUpdateFailed; String^ announcement = AppResourceProvider::GetInstance().GetResourceString(key); diff --git a/src/CalcViewModel/UnitConverterViewModel.h b/src/CalcViewModel/UnitConverterViewModel.h index 5a982384..2c6c8af3 100644 --- a/src/CalcViewModel/UnitConverterViewModel.h +++ b/src/CalcViewModel/UnitConverterViewModel.h @@ -223,6 +223,7 @@ namespace CalculatorApp void UpdateValue2AutomationName(); Platform::String^ Serialize(); void Deserialize(Platform::String^ state); + void ResetCategoriesAndRatio(); // Saving And Restoring User Preferences of Category and Associated-Units across Sessions. void SaveUserPreferences(); @@ -263,6 +264,7 @@ namespace CalculatorApp void RefreshSupplementaryResults(); void UpdateInputBlocked(_In_ const std::wstring& currencyInput); bool UnitsAreValid(); + void ResetCategory(); void OnButtonPressed(Platform::Object^ parameter); Platform::String^ ConvertToLocalizedString(const std::wstring& stringToLocalize, bool allowPartialStrings); diff --git a/src/CalculatorUnitTests/UnitConverterViewModelUnitTests.h b/src/CalculatorUnitTests/UnitConverterViewModelUnitTests.h index 1e1b57c8..903fd074 100644 --- a/src/CalculatorUnitTests/UnitConverterViewModelUnitTests.h +++ b/src/CalculatorUnitTests/UnitConverterViewModelUnitTests.h @@ -42,11 +42,14 @@ namespace CalculatorUnitTests void SendCommand(UCM::Command command) override; void SetViewModelCallback(const std::shared_ptr& newCallback) override; void SetViewModelCurrencyCallback(_In_ const std::shared_ptr& /*newCallback*/) override {} + void Calculate() override {} + void ResetCategoriesAndRatios() override{} concurrency::task> RefreshCurrencyRatios() override { - co_return std::make_pair(L"", L""); + co_return std::make_pair(true, L""); } + UINT m_initCallCount; UINT m_getCategoriesCallCount; UINT m_setCurrentCategoryCallCount; From 7a7ceb58882828096cac87494f5a1ffb5359e212 Mon Sep 17 00:00:00 2001 From: Rudy Huyn Date: Tue, 16 Apr 2019 17:17:24 -0700 Subject: [PATCH 007/154] Modify how modulo is calculated in Normal and Scientific mode. (#412) ## Fixes #111 > The modulo operator on this calculator gives the result that is different to the most used calculators. The current `modrate` function is the equivalent of rem(...)/remainder(...), not mod(...)/modulo(...) available in some popular Math apps. ### Description of the changes: - rename `modrate` in `remrate` to be more accurate. - add `modrate`, calculating modulo similarly to Matlab, Bing, Google calculator, Maxima, Wolfram Alpha and Microsoft Excel - Add `RationalMath::Mod` using `modrate` as an alternative to `Rational::operator%` using `remrate` - Add a helper `SIGN` to retrieve the sign of a `Rational`. - modify `CalcEngine` to use `modrate` in Normal and Scientific mode and `remrate` in Programmer mode. ### How changes were validated: - manually and unit tests added --- src/CalcManager/CEngine/Rational.cpp | 15 +- src/CalcManager/CEngine/RationalMath.cpp | 30 +++ src/CalcManager/CEngine/scioper.cpp | 28 ++- src/CalcManager/Header Files/CalcEngine.h | 4 +- src/CalcManager/Header Files/RationalMath.h | 1 + src/CalcManager/Ratpack/exp.cpp | 2 +- src/CalcManager/Ratpack/fact.cpp | 4 +- src/CalcManager/Ratpack/itrans.cpp | 14 +- src/CalcManager/Ratpack/logic.cpp | 186 +++++++++------ src/CalcManager/Ratpack/ratpak.h | 6 +- src/CalcManager/Ratpack/support.cpp | 16 +- src/CalculatorUnitTests/CalcEngineTests.cpp | 2 +- src/CalculatorUnitTests/CalcInputTest.cpp | 2 +- .../CalculatorUnitTests.vcxproj | 1 + .../CalculatorUnitTests.vcxproj.filters | 1 + src/CalculatorUnitTests/RationalTest.cpp | 225 ++++++++++++++++++ 16 files changed, 429 insertions(+), 108 deletions(-) create mode 100644 src/CalculatorUnitTests/RationalTest.cpp diff --git a/src/CalcManager/CEngine/Rational.cpp b/src/CalcManager/CEngine/Rational.cpp index fd86b72a..c93c79a6 100644 --- a/src/CalcManager/CEngine/Rational.cpp +++ b/src/CalcManager/CEngine/Rational.cpp @@ -182,6 +182,13 @@ namespace CalcEngine return *this; } + /// + /// Calculate the remainder after division, the sign of a result will match the sign of the current object. + /// + /// + /// This function has the same behavior as the standard C/C++ operator '%' + /// to calculate the modulus after division instead, use instead. + /// Rational& Rational::operator%=(Rational const& rhs) { PRAT lhsRat = this->ToPRAT(); @@ -189,7 +196,7 @@ namespace CalcEngine try { - modrat(&lhsRat, rhsRat); + remrat(&lhsRat, rhsRat); destroyrat(rhsRat); } catch (uint32_t error) @@ -342,6 +349,12 @@ namespace CalcEngine return lhs; } + /// + /// Calculate the remainder after division, the sign of a result will match the sign of lhs. + /// + /// + /// This function has the same behavior as the standard C/C++ operator '%', to calculate the modulus after division instead, use instead. + /// Rational operator%(Rational lhs, Rational const& rhs) { lhs %= rhs; diff --git a/src/CalcManager/CEngine/RationalMath.cpp b/src/CalcManager/CEngine/RationalMath.cpp index 37dc7926..f5de74fc 100644 --- a/src/CalcManager/CEngine/RationalMath.cpp +++ b/src/CalcManager/CEngine/RationalMath.cpp @@ -387,3 +387,33 @@ Rational RationalMath::ATanh(Rational const& rat) return result; } + +/// +/// Calculate the modulus after division, the sign of the result will match the sign of b. +/// +/// +/// When one of the operand is negative +/// the result will differ from the C/C++ operator '%' +/// use instead to calculate the remainder after division. +/// +Rational RationalMath::Mod(Rational const& a, Rational const& b) +{ + PRAT prat = a.ToPRAT(); + PRAT pn = b.ToPRAT(); + + try + { + modrat(&prat, pn); + destroyrat(pn); + } + catch (uint32_t error) + { + destroyrat(prat); + destroyrat(pn); + throw(error); + } + + auto res = Rational{ prat }; + destroyrat(prat); + return res; +} diff --git a/src/CalcManager/CEngine/scioper.cpp b/src/CalcManager/CEngine/scioper.cpp index b09083c4..9ced7021 100644 --- a/src/CalcManager/CEngine/scioper.cpp +++ b/src/CalcManager/CEngine/scioper.cpp @@ -78,7 +78,7 @@ CalcEngine::Rational CCalcEngine::DoOperation(int operation, CalcEngine::Rationa case IDC_DIV: case IDC_MOD: { - int iNumeratorSign = 1, iDenominatorSign = 1, iFinalSign = 1; + int iNumeratorSign = 1, iDenominatorSign = 1; auto temp = result; result = rhs; @@ -107,20 +107,30 @@ CalcEngine::Rational CCalcEngine::DoOperation(int operation, CalcEngine::Rationa if (operation == IDC_DIV) { - iFinalSign = iNumeratorSign * iDenominatorSign; result /= temp; + if (m_fIntegerMode && (iNumeratorSign * iDenominatorSign) == -1) + { + result = -(Integer(result)); + } } else { - iFinalSign = iNumeratorSign; - result %= temp; - } + if (m_fIntegerMode) + { + // Programmer mode, use remrat (remainder after division) + result %= temp; - if (m_fIntegerMode && iFinalSign == -1) - { - result = -(Integer(result)); + if (iNumeratorSign == -1) + { + result = -(Integer(result)); + } + } + else + { + //other modes, use modrat (modulus after division) + result = Mod(result, temp); + } } - break; } diff --git a/src/CalcManager/Header Files/CalcEngine.h b/src/CalcManager/Header Files/CalcEngine.h index db906e51..c84f2d55 100644 --- a/src/CalcManager/Header Files/CalcEngine.h +++ b/src/CalcManager/Header Files/CalcEngine.h @@ -45,7 +45,7 @@ namespace CalculationManager class IResourceProvider; } -namespace CalculatorUnitTests +namespace CalculatorEngineTests { class CalcEngineTests; } @@ -160,5 +160,5 @@ private: static void ChangeBaseConstants(uint32_t radix, int maxIntDigits, int32_t precision); void BaseOrPrecisionChanged(); - friend class CalculatorUnitTests::CalcEngineTests; + friend class CalculatorEngineTests::CalcEngineTests; }; diff --git a/src/CalcManager/Header Files/RationalMath.h b/src/CalcManager/Header Files/RationalMath.h index b52c1c5f..59500573 100644 --- a/src/CalcManager/Header Files/RationalMath.h +++ b/src/CalcManager/Header Files/RationalMath.h @@ -13,6 +13,7 @@ namespace CalcEngine::RationalMath Rational Pow(Rational const& base, Rational const& pow); Rational Root(Rational const& base, Rational const& root); Rational Fact(Rational const& rat); + Rational Mod(Rational const& a, Rational const& b); Rational Exp(Rational const& rat); Rational Log(Rational const& rat); diff --git a/src/CalcManager/Ratpack/exp.cpp b/src/CalcManager/Ratpack/exp.cpp index c8691cfa..95637404 100644 --- a/src/CalcManager/Ratpack/exp.cpp +++ b/src/CalcManager/Ratpack/exp.cpp @@ -408,7 +408,7 @@ void powratNumeratorDenominator(PRAT *px, PRAT y, uint32_t radix, int32_t precis //--------------------------------------------------------------------------- void powratcomp(PRAT *px, PRAT y, uint32_t radix, int32_t precision) { - int32_t sign = ((*px)->pp->sign * (*px)->pq->sign); + int32_t sign = SIGN(*px); // Take the absolute value (*px)->pp->sign = 1; diff --git a/src/CalcManager/Ratpack/fact.cpp b/src/CalcManager/Ratpack/fact.cpp index c974b005..276151ae 100644 --- a/src/CalcManager/Ratpack/fact.cpp +++ b/src/CalcManager/Ratpack/fact.cpp @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. //----------------------------------------------------------------------------- @@ -216,7 +216,7 @@ void factrat( PRAT *px, uint32_t radix, int32_t precision) // Check for negative integers and throw an error. if ( ( zerrat(frac) || ( LOGRATRADIX(frac) <= -precision) ) && - ( (*px)->pp->sign * (*px)->pq->sign == -1 ) ) + ( SIGN(*px) == -1 ) ) { throw CALC_E_DOMAIN; } diff --git a/src/CalcManager/Ratpack/itrans.cpp b/src/CalcManager/Ratpack/itrans.cpp index 1ecbf4a1..0d2a297e 100644 --- a/src/CalcManager/Ratpack/itrans.cpp +++ b/src/CalcManager/Ratpack/itrans.cpp @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. //----------------------------------------------------------------------------- @@ -92,11 +92,9 @@ void asinanglerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32 void asinrat( PRAT *px, uint32_t radix, int32_t precision) { - int32_t sgn; PRAT pret= nullptr; PRAT phack= nullptr; - - sgn = (*px)->pp->sign* (*px)->pq->sign; + int32_t sgn = SIGN(*px); (*px)->pp->sign = 1; (*px)->pq->sign = 1; @@ -204,9 +202,7 @@ void _acosrat( PRAT *px, int32_t precision) void acosrat( PRAT *px, uint32_t radix, int32_t precision) { - int32_t sgn; - - sgn = (*px)->pp->sign*(*px)->pq->sign; + int32_t sgn = SIGN(*px); (*px)->pp->sign = 1; (*px)->pq->sign = 1; @@ -291,10 +287,8 @@ void _atanrat( PRAT *px, int32_t precision) void atanrat( PRAT *px, uint32_t radix, int32_t precision) { - int32_t sgn; PRAT tmpx= nullptr; - - sgn = (*px)->pp->sign * (*px)->pq->sign; + int32_t sgn = SIGN(*px); (*px)->pp->sign = 1; (*px)->pq->sign = 1; diff --git a/src/CalcManager/Ratpack/logic.cpp b/src/CalcManager/Ratpack/logic.cpp index c7f8a3a3..6444898e 100644 --- a/src/CalcManager/Ratpack/logic.cpp +++ b/src/CalcManager/Ratpack/logic.cpp @@ -18,54 +18,54 @@ using namespace std; -void lshrat( PRAT *pa, PRAT b, uint32_t radix, int32_t precision) +void lshrat(PRAT *pa, PRAT b, uint32_t radix, int32_t precision) { - PRAT pwr= nullptr; + PRAT pwr = nullptr; int32_t intb; intrat(pa, radix, precision); - if ( !zernum( (*pa)->pp ) ) - { + if (!zernum((*pa)->pp)) + { // If input is zero we're done. - if ( rat_gt( b, rat_max_exp, precision) ) - { + if (rat_gt(b, rat_max_exp, precision)) + { // Don't attempt lsh of anything big - throw( CALC_E_DOMAIN ); - } + throw(CALC_E_DOMAIN); + } intb = rattoi32(b, radix, precision); - DUPRAT(pwr,rat_two); + DUPRAT(pwr, rat_two); ratpowi32(&pwr, intb, precision); mulrat(pa, pwr, precision); destroyrat(pwr); - } + } } -void rshrat( PRAT *pa, PRAT b, uint32_t radix, int32_t precision) +void rshrat(PRAT *pa, PRAT b, uint32_t radix, int32_t precision) { - PRAT pwr= nullptr; + PRAT pwr = nullptr; int32_t intb; intrat(pa, radix, precision); - if ( !zernum( (*pa)->pp ) ) - { + if (!zernum((*pa)->pp)) + { // If input is zero we're done. - if ( rat_lt( b, rat_min_exp, precision) ) - { + if (rat_lt(b, rat_min_exp, precision)) + { // Don't attempt rsh of anything big and negative. - throw( CALC_E_DOMAIN ); - } + throw(CALC_E_DOMAIN); + } intb = rattoi32(b, radix, precision); - DUPRAT(pwr,rat_two); + DUPRAT(pwr, rat_two); ratpowi32(&pwr, intb, precision); divrat(pa, pwr, precision); destroyrat(pwr); - } + } } -void boolrat( PRAT *pa, PRAT b, int func, uint32_t radix, int32_t precision); -void boolnum( PNUMBER *pa, PNUMBER b, int func ); +void boolrat(PRAT *pa, PRAT b, int func, uint32_t radix, int32_t precision); +void boolnum(PNUMBER *pa, PNUMBER b, int func); enum { @@ -74,22 +74,22 @@ enum { FUNC_XOR } BOOL_FUNCS; -void andrat( PRAT *pa, PRAT b, uint32_t radix, int32_t precision) +void andrat(PRAT *pa, PRAT b, uint32_t radix, int32_t precision) { - boolrat( pa, b, FUNC_AND, radix, precision); + boolrat(pa, b, FUNC_AND, radix, precision); } -void orrat( PRAT *pa, PRAT b, uint32_t radix, int32_t precision) +void orrat(PRAT *pa, PRAT b, uint32_t radix, int32_t precision) { - boolrat( pa, b, FUNC_OR, radix, precision); + boolrat(pa, b, FUNC_OR, radix, precision); } -void xorrat( PRAT *pa, PRAT b, uint32_t radix, int32_t precision) +void xorrat(PRAT *pa, PRAT b, uint32_t radix, int32_t precision) { - boolrat( pa, b, FUNC_XOR, radix, precision); + boolrat(pa, b, FUNC_XOR, radix, precision); } //--------------------------------------------------------------------------- @@ -104,15 +104,15 @@ void xorrat( PRAT *pa, PRAT b, uint32_t radix, int32_t precision) // //--------------------------------------------------------------------------- -void boolrat( PRAT *pa, PRAT b, int func, uint32_t radix, int32_t precision) +void boolrat(PRAT *pa, PRAT b, int func, uint32_t radix, int32_t precision) { - PRAT tmp= nullptr; - intrat( pa, radix, precision); - DUPRAT(tmp,b); - intrat( &tmp, radix, precision); + PRAT tmp = nullptr; + intrat(pa, radix, precision); + DUPRAT(tmp, b); + intrat(&tmp, radix, precision); - boolnum( &((*pa)->pp), tmp->pp, func ); + boolnum(&((*pa)->pp), tmp->pp, func); destroyrat(tmp); } @@ -130,11 +130,11 @@ void boolrat( PRAT *pa, PRAT b, int func, uint32_t radix, int32_t precision) // //--------------------------------------------------------------------------- -void boolnum( PNUMBER *pa, PNUMBER b, int func ) +void boolnum(PNUMBER *pa, PNUMBER b, int func) { - PNUMBER c= nullptr; - PNUMBER a= nullptr; + PNUMBER c = nullptr; + PNUMBER a = nullptr; MANTTYPE *pcha; MANTTYPE *pchb; MANTTYPE *pchc; @@ -143,26 +143,26 @@ void boolnum( PNUMBER *pa, PNUMBER b, int func ) MANTTYPE da; MANTTYPE db; - a=*pa; - cdigits = max( a->cdigit+a->exp, b->cdigit+b->exp ) - - min( a->exp, b->exp ); - createnum( c, cdigits ); - c->exp = min( a->exp, b->exp ); + a = *pa; + cdigits = max(a->cdigit + a->exp, b->cdigit + b->exp) - + min(a->exp, b->exp); + createnum(c, cdigits); + c->exp = min(a->exp, b->exp); mexp = c->exp; c->cdigit = cdigits; pcha = a->mant; pchb = b->mant; pchc = c->mant; - for ( ;cdigits > 0; cdigits--, mexp++ ) + for (; cdigits > 0; cdigits--, mexp++) + { + da = (((mexp >= a->exp) && (cdigits + a->exp - c->exp > + (c->cdigit - a->cdigit))) ? + *pcha++ : 0); + db = (((mexp >= b->exp) && (cdigits + b->exp - c->exp > + (c->cdigit - b->cdigit))) ? + *pchb++ : 0); + switch (func) { - da = ( ( ( mexp >= a->exp ) && ( cdigits + a->exp - c->exp > - (c->cdigit - a->cdigit) ) ) ? - *pcha++ : 0 ); - db = ( ( ( mexp >= b->exp ) && ( cdigits + b->exp - c->exp > - (c->cdigit - b->cdigit) ) ) ? - *pchb++ : 0 ); - switch ( func ) - { case FUNC_AND: *pchc++ = da & db; break; @@ -172,15 +172,51 @@ void boolnum( PNUMBER *pa, PNUMBER b, int func ) case FUNC_XOR: *pchc++ = da ^ db; break; - } } + } c->sign = a->sign; - while ( c->cdigit > 1 && *(--pchc) == 0 ) - { + while (c->cdigit > 1 && *(--pchc) == 0) + { c->cdigit--; - } - destroynum( *pa ); - *pa=c; + } + destroynum(*pa); + *pa = c; +} + +//----------------------------------------------------------------------------- +// +// FUNCTION: remrat +// +// ARGUMENTS: pointer to a rational a second rational. +// +// RETURN: None, changes pointer. +// +// DESCRIPTION: Calculate the remainder of *pa / b, +// equivalent of 'pa % b' in C/C++ and produces a result +// that is either zero or has the same sign as the dividend. +// +//----------------------------------------------------------------------------- + +void remrat(PRAT *pa, PRAT b) + +{ + if (zerrat(b)) + { + throw CALC_E_INDEFINITE; + } + + PRAT tmp = nullptr; + DUPRAT(tmp, b); + + mulnumx(&((*pa)->pp), tmp->pq); + mulnumx(&(tmp->pp), (*pa)->pq); + remnum(&((*pa)->pp), tmp->pp, BASEX); + mulnumx(&((*pa)->pq), tmp->pq); + + // Get *pa back in the integer over integer form. + RENORMALIZE(*pa); + + destroyrat(tmp); } //----------------------------------------------------------------------------- @@ -191,28 +227,38 @@ void boolnum( PNUMBER *pa, PNUMBER b, int func ) // // RETURN: None, changes pointer. // -// DESCRIPTION: Does the rational equivalent of frac(*pa); +// DESCRIPTION: Calculate the remainder of *pa / b, with the sign of the result +// either zero or has the same sign as the divisor. +// NOTE: When *pa or b are negative, the result won't be the same as +// the C/C++ operator %, use remrat if it's the behavior you expect. // //----------------------------------------------------------------------------- -void modrat( PRAT *pa, PRAT b ) - +void modrat(PRAT *pa, PRAT b) { + //contrary to remrat(X, 0) returning 0, modrat(X, 0) must return X + if (zerrat(b)) + { + return; + } + PRAT tmp = nullptr; + DUPRAT(tmp, b); - if ( zerrat( b ) ) - { - throw CALC_E_INDEFINITE; - } - DUPRAT(tmp,b); + auto needAdjust = (SIGN(*pa) == -1 ? (SIGN(b) == 1) : (SIGN(b) == -1)); - mulnumx( &((*pa)->pp), tmp->pq ); - mulnumx( &(tmp->pp), (*pa)->pq ); - remnum( &((*pa)->pp), tmp->pp, BASEX ); - mulnumx( &((*pa)->pq), tmp->pq ); + mulnumx(&((*pa)->pp), tmp->pq); + mulnumx(&(tmp->pp), (*pa)->pq); + remnum(&((*pa)->pp), tmp->pp, BASEX); + mulnumx(&((*pa)->pq), tmp->pq); + + if (needAdjust && !zerrat(*pa)) + { + addrat(pa, b, BASEX); + } // Get *pa back in the integer over integer form. RENORMALIZE(*pa); - destroyrat( tmp ); + destroyrat(tmp); } diff --git a/src/CalcManager/Ratpack/ratpak.h b/src/CalcManager/Ratpack/ratpak.h index 75ac28de..d9bc11ce 100644 --- a/src/CalcManager/Ratpack/ratpak.h +++ b/src/CalcManager/Ratpack/ratpak.h @@ -148,6 +148,9 @@ extern PRAT rat_min_i32; #define LOGNUM2(pnum) ((pnum)->cdigit+(pnum)->exp) #define LOGRAT2(prat) (LOGNUM2((prat)->pp)-LOGNUM2((prat)->pq)) +// SIGN returns the sign of the rational +#define SIGN(prat) ((prat)->pp->sign*(prat)->pq->sign) + #if defined( DEBUG_RATPAK ) //----------------------------------------------------------------------------- // @@ -423,7 +426,8 @@ extern void divnumx( _Inout_ PNUMBER *pa, _In_ PNUMBER b, int32_t precision); extern void divrat( _Inout_ PRAT *pa, _In_ PRAT b, int32_t precision); extern void fracrat( _Inout_ PRAT *pa , uint32_t radix, int32_t precision); extern void factrat( _Inout_ PRAT *pa, uint32_t radix, int32_t precision); -extern void modrat( _Inout_ PRAT *pa, _In_ PRAT b ); +extern void remrat(_Inout_ PRAT *pa, _In_ PRAT b); +extern void modrat(_Inout_ PRAT *pa, _In_ PRAT b); extern void gcdrat( _Inout_ PRAT *pa, int32_t precision); extern void intrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision); extern void mulnum( _Inout_ PNUMBER *pa, _In_ PNUMBER b, uint32_t radix); diff --git a/src/CalcManager/Ratpack/support.cpp b/src/CalcManager/Ratpack/support.cpp index ebee00c6..22683b4c 100644 --- a/src/CalcManager/Ratpack/support.cpp +++ b/src/CalcManager/Ratpack/support.cpp @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. //---------------------------------------------------------------------------- @@ -296,7 +296,7 @@ void intrat( PRAT *px, uint32_t radix, int32_t precision) // Subtract the fractional part of the rational PRAT pret = nullptr; DUPRAT(pret,*px); - modrat( &pret, rat_one ); + remrat( &pret, rat_one ); subrat( px, pret, precision); destroyrat( pret ); @@ -348,8 +348,7 @@ bool rat_ge( PRAT a, PRAT b, int32_t precision) b->pp->sign *= -1; addrat( &rattmp, b, precision); b->pp->sign *= -1; - bool bret = ( zernum( rattmp->pp ) || - rattmp->pp->sign * rattmp->pq->sign == 1 ); + bool bret = ( zernum( rattmp->pp ) || SIGN(rattmp) == 1 ); destroyrat( rattmp ); return( bret ); } @@ -374,8 +373,7 @@ bool rat_gt( PRAT a, PRAT b, int32_t precision) b->pp->sign *= -1; addrat( &rattmp, b, precision); b->pp->sign *= -1; - bool bret = ( !zernum( rattmp->pp ) && - rattmp->pp->sign * rattmp->pq->sign == 1 ); + bool bret = ( !zernum( rattmp->pp ) && SIGN(rattmp) == 1 ); destroyrat( rattmp ); return( bret ); } @@ -400,8 +398,7 @@ bool rat_le( PRAT a, PRAT b, int32_t precision) b->pp->sign *= -1; addrat( &rattmp, b, precision); b->pp->sign *= -1; - bool bret = ( zernum( rattmp->pp ) || - rattmp->pp->sign * rattmp->pq->sign == -1 ); + bool bret = ( zernum( rattmp->pp ) || SIGN(rattmp) == -1 ); destroyrat( rattmp ); return( bret ); } @@ -426,8 +423,7 @@ bool rat_lt( PRAT a, PRAT b, int32_t precision) b->pp->sign *= -1; addrat( &rattmp, b, precision); b->pp->sign *= -1; - bool bret = ( !zernum( rattmp->pp ) && - rattmp->pp->sign * rattmp->pq->sign == -1 ); + bool bret = ( !zernum( rattmp->pp ) && SIGN(rattmp) == -1 ); destroyrat( rattmp ); return( bret ); } diff --git a/src/CalculatorUnitTests/CalcEngineTests.cpp b/src/CalculatorUnitTests/CalcEngineTests.cpp index d572a442..9109c8d6 100644 --- a/src/CalculatorUnitTests/CalcEngineTests.cpp +++ b/src/CalculatorUnitTests/CalcEngineTests.cpp @@ -13,7 +13,7 @@ using namespace Microsoft::VisualStudio::CppUnitTestFramework; static constexpr size_t MAX_HISTORY_SIZE = 20; -namespace CalculatorUnitTests +namespace CalculatorEngineTests { TEST_CLASS(CalcEngineTests) { diff --git a/src/CalculatorUnitTests/CalcInputTest.cpp b/src/CalculatorUnitTests/CalcInputTest.cpp index 551fbd71..4d224a3e 100644 --- a/src/CalculatorUnitTests/CalcInputTest.cpp +++ b/src/CalculatorUnitTests/CalcInputTest.cpp @@ -8,7 +8,7 @@ using namespace std; using namespace CalculationManager; using namespace Microsoft::VisualStudio::CppUnitTestFramework; -namespace CalculatorUnitTests +namespace CalculatorEngineTests { TEST_CLASS(CalcInputTest) { diff --git a/src/CalculatorUnitTests/CalculatorUnitTests.vcxproj b/src/CalculatorUnitTests/CalculatorUnitTests.vcxproj index d199044c..0afdfd14 100644 --- a/src/CalculatorUnitTests/CalculatorUnitTests.vcxproj +++ b/src/CalculatorUnitTests/CalculatorUnitTests.vcxproj @@ -248,6 +248,7 @@ + diff --git a/src/CalculatorUnitTests/CalculatorUnitTests.vcxproj.filters b/src/CalculatorUnitTests/CalculatorUnitTests.vcxproj.filters index 57ac4fe2..20400d4a 100644 --- a/src/CalculatorUnitTests/CalculatorUnitTests.vcxproj.filters +++ b/src/CalculatorUnitTests/CalculatorUnitTests.vcxproj.filters @@ -29,6 +29,7 @@ Mocks + diff --git a/src/CalculatorUnitTests/RationalTest.cpp b/src/CalculatorUnitTests/RationalTest.cpp new file mode 100644 index 00000000..c19692fd --- /dev/null +++ b/src/CalculatorUnitTests/RationalTest.cpp @@ -0,0 +1,225 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "pch.h" +#include +#include "Header Files/Rational.h" +#include "Header Files/RationalMath.h" + +using namespace CalcEngine; +using namespace CalcEngine::RationalMath; +using namespace Microsoft::VisualStudio::CppUnitTestFramework; + +namespace CalculatorEngineTests +{ + TEST_CLASS(RationalTest) + { + public: + TEST_CLASS_INITIALIZE(CommonSetup) + { + ChangeConstants(10, 128); + } + + TEST_METHOD(TestModuloOperandsNotModified) + { + // Verify results but also check that operands are not modified + Rational rat25(25); + Rational ratminus25(-25); + Rational rat4(4); + Rational ratminus4(-4); + Rational res = Mod(rat25, rat4); + VERIFY_ARE_EQUAL(res, 1); + VERIFY_ARE_EQUAL(rat25, 25); + VERIFY_ARE_EQUAL(rat4, 4); + res = Mod(rat25, ratminus4); + VERIFY_ARE_EQUAL(res, -3); + VERIFY_ARE_EQUAL(rat25, 25); + VERIFY_ARE_EQUAL(ratminus4, -4); + res = Mod(ratminus25, ratminus4); + VERIFY_ARE_EQUAL(res, -1); + VERIFY_ARE_EQUAL(ratminus25, -25); + VERIFY_ARE_EQUAL(ratminus4, -4); + res = Mod(ratminus25, rat4); + VERIFY_ARE_EQUAL(res, 3); + VERIFY_ARE_EQUAL(ratminus25, -25); + VERIFY_ARE_EQUAL(rat4, 4); + } + + TEST_METHOD(TestModuloInteger) + { + // Check with integers + auto res = Mod(Rational(426), Rational(56478)); + VERIFY_ARE_EQUAL(res, 426); + res = Mod(Rational(56478), Rational(426)); + VERIFY_ARE_EQUAL(res, 246); + res = Mod(Rational(-643), Rational(8756)); + VERIFY_ARE_EQUAL(res, 8113); + res = Mod(Rational(643), Rational(-8756)); + VERIFY_ARE_EQUAL(res, -8113); + res = Mod(Rational(-643), Rational(-8756)); + VERIFY_ARE_EQUAL(res, -643); + res = Mod(Rational(1000), Rational(250)); + VERIFY_ARE_EQUAL(res, 0); + res = Mod(Rational(1000), Rational(-250)); + VERIFY_ARE_EQUAL(res, 0); + } + + TEST_METHOD(TestModuloZero) + { + // Test with Zero + auto res = Mod(Rational(343654332), Rational(0)); + VERIFY_ARE_EQUAL(res, 343654332); + res = Mod(Rational(0), Rational(8756)); + VERIFY_ARE_EQUAL(res, 0); + res = Mod(Rational(0), Rational(-242)); + VERIFY_ARE_EQUAL(res, 0); + res = Mod(Rational(0), Rational(0)); + VERIFY_ARE_EQUAL(res, 0); + res = Mod(Rational(Number(1, 0, { 23242 }), Number(1, 0, { 2 })), Rational(Number(1, 0, { 0 }), Number(1, 0, { 23 }))); + VERIFY_ARE_EQUAL(res, 11621); + } + + TEST_METHOD(TestModuloRational) + { + // Test with rational numbers + auto res = Mod(Rational(Number(1, 0, { 250 }), Number(1, 0, { 100 })), Rational(89)); + VERIFY_ARE_EQUAL(res.ToString(10, FMT_FLOAT, 8), L"2.5"); + res = Mod(Rational(Number(1, 0, { 3330 }), Number(1, 0, { 1332 })), Rational(1)); + VERIFY_ARE_EQUAL(res.ToString(10, FMT_FLOAT, 8), L"0.5"); + res = Mod(Rational(Number(1, 0, { 12250 }), Number(1, 0, { 100 })), Rational(10)); + VERIFY_ARE_EQUAL(res.ToString(10, FMT_FLOAT, 8), L"2.5"); + res = Mod(Rational(Number(-1, 0, { 12250 }), Number(1, 0, { 100 })), Rational(10)); + VERIFY_ARE_EQUAL(res.ToString(10, FMT_FLOAT, 8), L"7.5"); + res = Mod(Rational(Number(-1, 0, { 12250 }), Number(1, 0, { 100 })), Rational(-10)); + VERIFY_ARE_EQUAL(res.ToString(10, FMT_FLOAT, 8), L"-2.5"); + res = Mod(Rational(Number(1, 0, { 12250 }), Number(1, 0, { 100 })), Rational(-10)); + VERIFY_ARE_EQUAL(res.ToString(10, FMT_FLOAT, 8), L"-7.5"); + res = Mod(Rational(Number(1, 0, { 1000 }), Number(1, 0, { 3 })), Rational(1)); + VERIFY_ARE_EQUAL(res.ToString(10, FMT_FLOAT, 8), L"0.33333333"); + res = Mod(Rational(Number(1, 0, { 1000 }), Number(1, 0, { 3 })), Rational(-10)); + VERIFY_ARE_EQUAL(res.ToString(10, FMT_FLOAT, 8), L"-6.6666667"); + res = Mod(Rational(834345), Rational(Number(1, 0, { 103 }), Number(1, 0, { 100 }))); + VERIFY_ARE_EQUAL(res.ToString(10, FMT_FLOAT, 8), L"0.71"); + res = Mod(Rational(834345), Rational(Number(-1, 0, { 103 }), Number(1, 0, { 100 }))); + VERIFY_ARE_EQUAL(res.ToString(10, FMT_FLOAT, 8), L"-0.32"); + } + + TEST_METHOD(TestRemainderOperandsNotModified) + { + //Verify results but also check that operands are not modified + Rational rat25(25); + Rational ratminus25(-25); + Rational rat4(4); + Rational ratminus4(-4); + Rational res = rat25 % rat4; + VERIFY_ARE_EQUAL(res, 1); + VERIFY_ARE_EQUAL(rat25, 25); + VERIFY_ARE_EQUAL(rat4, 4); + res = rat25 % ratminus4; + VERIFY_ARE_EQUAL(res, 1); + VERIFY_ARE_EQUAL(rat25, 25); + VERIFY_ARE_EQUAL(ratminus4, -4); + res = ratminus25 % ratminus4; + VERIFY_ARE_EQUAL(res, -1); + VERIFY_ARE_EQUAL(ratminus25, -25); + VERIFY_ARE_EQUAL(ratminus4, -4); + res = ratminus25 % rat4; + VERIFY_ARE_EQUAL(res, -1); + VERIFY_ARE_EQUAL(ratminus25, -25); + VERIFY_ARE_EQUAL(rat4, 4); + } + + TEST_METHOD(TestRemainderInteger) + { + // Check with integers + auto res = Rational(426) % Rational(56478); + VERIFY_ARE_EQUAL(res, 426); + res = Rational(56478) % Rational(426); + VERIFY_ARE_EQUAL(res, 246); + res = Rational(-643) % Rational(8756); + VERIFY_ARE_EQUAL(res, -643); + res = Rational(643) % Rational(-8756); + VERIFY_ARE_EQUAL(res, 643); + res = Rational(-643) % Rational(-8756); + VERIFY_ARE_EQUAL(res, -643); + res = Rational(-124) % Rational(-124); + VERIFY_ARE_EQUAL(res, 0); + res = Rational(24) % Rational(24); + VERIFY_ARE_EQUAL(res, 0); + } + + TEST_METHOD(TestRemainderZero) + { + // Test with Zero + auto res = Rational(0) % Rational(3654); + VERIFY_ARE_EQUAL(res, 0); + res = Rational(0) % Rational(-242); + VERIFY_ARE_EQUAL(res, 0); + for (auto number : { 343654332, 0, -23423 }) + { + try + { + res = Rational(number) % Rational(0); + Assert::Fail(); + } + catch (uint32_t t) + { + if (t != CALC_E_INDEFINITE) + { + Assert::Fail(); + } + } + catch (...) + { + Assert::Fail(); + } + + try + { + res = Rational(Number(1, number, { 0 }), Number(1, 0, { 2 })) % Rational(Number(1, 0, { 0 }), Number(1, 0, { 23 })); + Assert::Fail(); + } + catch (uint32_t t) + { + if (t != CALC_E_INDEFINITE) + { + Assert::Fail(); + } + } + catch (...) + { + Assert::Fail(); + } + } + } + + TEST_METHOD(TestRemainderRational) + { + //Test with rational numbers + auto res = Rational(Number(1, 0, { 250 }), Number(1, 0, { 100 })) % Rational(89); + VERIFY_ARE_EQUAL(res.ToString(10, FMT_FLOAT, 8), L"2.5"); + res = Rational(Number(1, 0, { 3330 }), Number(1, 0, { 1332 })) % Rational(1); + VERIFY_ARE_EQUAL(res.ToString(10, FMT_FLOAT, 8), L"0.5"); + res = Rational(Number(1, 0, { 12250 }), Number(1, 0, { 100 })) % Rational(10); + VERIFY_ARE_EQUAL(res.ToString(10, FMT_FLOAT, 8), L"2.5"); + res = Rational(Number(-1, 0, { 12250 }), Number(1, 0, { 100 })) % Rational(10); + VERIFY_ARE_EQUAL(res.ToString(10, FMT_FLOAT, 8), L"-2.5"); + res = Rational(Number(-1, 0, { 12250 }), Number(1, 0, { 100 })) % Rational(-10); + VERIFY_ARE_EQUAL(res.ToString(10, FMT_FLOAT, 8), L"-2.5"); + res = Rational(Number(1, 0, { 12250 }), Number(1, 0, { 100 })) % Rational(-10); + VERIFY_ARE_EQUAL(res.ToString(10, FMT_FLOAT, 8), L"2.5"); + res = Rational(Number(1, 0, { 1000 }), Number(1, 0, { 3 })) % Rational(1); + VERIFY_ARE_EQUAL(res.ToString(10, FMT_FLOAT, 8), L"0.33333333"); + res = Rational(Number(1, 0, { 1000 }), Number(1, 0, { 3 })) % Rational(-10); + VERIFY_ARE_EQUAL(res.ToString(10, FMT_FLOAT, 8), L"3.3333333"); + res = Rational(Number(-1, 0, { 1000 }), Number(1, 0, { 3 })) % Rational(-10); + VERIFY_ARE_EQUAL(res.ToString(10, FMT_FLOAT, 8), L"-3.3333333"); + res = Rational(834345) % Rational(Number(1, 0, { 103 }), Number(1, 0, { 100 })); + VERIFY_ARE_EQUAL(res.ToString(10, FMT_FLOAT, 8), L"0.71"); + res = Rational(834345) % Rational(Number(-1, 0, { 103 }), Number(1, 0, { 100 })); + VERIFY_ARE_EQUAL(res.ToString(10, FMT_FLOAT, 8), L"0.71"); + res = Rational(-834345) % Rational(Number(1, 0, { 103 }), Number(1, 0, { 100 })); + VERIFY_ARE_EQUAL(res.ToString(10, FMT_FLOAT, 8), L"-0.71"); + } + }; +} From c150cd4ece9945aee39a6b174c2ea97b5cade0c7 Mon Sep 17 00:00:00 2001 From: jatinkumar Date: Tue, 16 Apr 2019 20:46:07 -0400 Subject: [PATCH 008/154] Removed AppBar, OperatorTextBox and OperandTextBox controls (#440) Fixes #407 Removed AppBar, OperatorTextBox and OperandTextBox controls --- src/CalcViewModel/ApplicationViewModel.cpp | 2 - src/CalcViewModel/ApplicationViewModel.h | 10 -- .../StandardCalculatorViewModel.h | 1 - src/Calculator/Calculator.vcxproj | 5 - src/Calculator/Calculator.vcxproj.filters | 15 --- src/Calculator/Controls/AppBar.h | 29 ----- src/Calculator/Controls/OperandTextBox.cpp | 58 ---------- src/Calculator/Controls/OperandTextBox.h | 19 ---- src/Calculator/Controls/OperatorTextBox.cpp | 59 ---------- src/Calculator/Controls/OperatorTextBox.h | 19 ---- src/Calculator/Views/Calculator.xaml | 101 +----------------- src/Calculator/Views/MainPage.xaml.cpp | 7 -- src/Calculator/Views/MainPage.xaml.h | 2 - .../Views/SupplementaryResults.xaml.h | 2 - 14 files changed, 1 insertion(+), 328 deletions(-) delete mode 100644 src/Calculator/Controls/AppBar.h delete mode 100644 src/Calculator/Controls/OperandTextBox.cpp delete mode 100644 src/Calculator/Controls/OperandTextBox.h delete mode 100644 src/Calculator/Controls/OperatorTextBox.cpp delete mode 100644 src/Calculator/Controls/OperatorTextBox.h diff --git a/src/CalcViewModel/ApplicationViewModel.cpp b/src/CalcViewModel/ApplicationViewModel.cpp index 358589b5..5033080b 100644 --- a/src/CalcViewModel/ApplicationViewModel.cpp +++ b/src/CalcViewModel/ApplicationViewModel.cpp @@ -36,7 +36,6 @@ namespace { StringReference CategoriesPropertyName(L"Categories"); StringReference ClearMemoryVisibilityPropertyName(L"ClearMemoryVisibility"); - StringReference AppBarVisibilityPropertyName(L"AppBarVisibility"); } ApplicationViewModel::ApplicationViewModel() : @@ -164,7 +163,6 @@ void ApplicationViewModel::OnModeChanged() TraceLogger::GetInstance().LogModeChangeEnd(m_mode, ApplicationView::GetApplicationViewIdForWindow(CoreWindow::GetForCurrentThread())); RaisePropertyChanged(ClearMemoryVisibilityPropertyName); - RaisePropertyChanged(AppBarVisibilityPropertyName); } void ApplicationViewModel::OnCopyCommand(Object^ parameter) diff --git a/src/CalcViewModel/ApplicationViewModel.h b/src/CalcViewModel/ApplicationViewModel.h index f13e00ad..74567ca1 100644 --- a/src/CalcViewModel/ApplicationViewModel.h +++ b/src/CalcViewModel/ApplicationViewModel.h @@ -66,16 +66,6 @@ namespace CalculatorApp } } - property Windows::UI::Xaml::Visibility AppBarVisibility - { - Windows::UI::Xaml::Visibility get() - { - return CalculatorApp::Common::NavCategory::IsCalculatorViewMode(Mode) - ? Windows::UI::Xaml::Visibility::Visible - : Windows::UI::Xaml::Visibility::Collapsed; - } - } - private: bool TryRecoverFromNavigationModeFailure(); diff --git a/src/CalcViewModel/StandardCalculatorViewModel.h b/src/CalcViewModel/StandardCalculatorViewModel.h index 91ba2557..42d025c4 100644 --- a/src/CalcViewModel/StandardCalculatorViewModel.h +++ b/src/CalcViewModel/StandardCalculatorViewModel.h @@ -86,7 +86,6 @@ namespace CalculatorApp COMMAND_FOR_METHOD(PasteCommand, StandardCalculatorViewModel::OnPasteCommand); COMMAND_FOR_METHOD(ButtonPressed, StandardCalculatorViewModel::OnButtonPressed); COMMAND_FOR_METHOD(ClearMemoryCommand, StandardCalculatorViewModel::OnClearMemoryCommand); - COMMAND_FOR_METHOD(PinUnpinAppBarButtonOnClicked, StandardCalculatorViewModel::OnPinUnpinCommand); COMMAND_FOR_METHOD(MemoryItemPressed, StandardCalculatorViewModel::OnMemoryItemPressed); COMMAND_FOR_METHOD(MemoryAdd, StandardCalculatorViewModel::OnMemoryAdd); COMMAND_FOR_METHOD(MemorySubtract, StandardCalculatorViewModel::OnMemorySubtract); diff --git a/src/Calculator/Calculator.vcxproj b/src/Calculator/Calculator.vcxproj index 4e19aab2..64e4ad06 100644 --- a/src/Calculator/Calculator.vcxproj +++ b/src/Calculator/Calculator.vcxproj @@ -234,12 +234,9 @@ - - - @@ -372,8 +369,6 @@ - - diff --git a/src/Calculator/Calculator.vcxproj.filters b/src/Calculator/Calculator.vcxproj.filters index cc25a224..a888b192 100644 --- a/src/Calculator/Calculator.vcxproj.filters +++ b/src/Calculator/Calculator.vcxproj.filters @@ -271,12 +271,6 @@ - - Controls - - - Controls - Controls @@ -321,9 +315,6 @@ Common - - Controls - Controls @@ -370,12 +361,6 @@ - - Controls - - - Controls - Controls diff --git a/src/Calculator/Controls/AppBar.h b/src/Calculator/Controls/AppBar.h deleted file mode 100644 index b6ac3740..00000000 --- a/src/Calculator/Controls/AppBar.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#pragma once - -#include "Common/KeyboardShortcutManager.h" - -namespace CalculatorApp -{ - namespace Controls - { - public ref class AppBar sealed : public Windows::UI::Xaml::Controls::AppBar - { - public: - AppBar() - {} - - protected: - virtual void OnKeyDown(Windows::UI::Xaml::Input::KeyRoutedEventArgs^ e) override - { - Windows::UI::Xaml::Controls::AppBar::OnKeyDown(e); - if (e->Key == Windows::System::VirtualKey::Escape) - { - Common::KeyboardShortcutManager::IgnoreEscape(true); - } - } - }; - } -} diff --git a/src/Calculator/Controls/OperandTextBox.cpp b/src/Calculator/Controls/OperandTextBox.cpp deleted file mode 100644 index 31e814c2..00000000 --- a/src/Calculator/Controls/OperandTextBox.cpp +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#include "pch.h" -#include "OperandTextBox.h" -#include "regex" - -using namespace CalculatorApp; -using namespace CalculatorApp::Controls; - -using namespace Platform; -using namespace std; -using namespace Windows::Foundation; -using namespace Windows::Foundation::Collections; -using namespace Windows::Devices::Input; -using namespace Windows::System; -using namespace Windows::UI::Xaml; -using namespace Windows::UI::Xaml::Controls; -using namespace Windows::UI::Xaml::Controls::Primitives; -using namespace Windows::UI::Xaml::Data; -using namespace Windows::UI::Xaml::Input; -using namespace Windows::UI::Xaml::Media; -using namespace Windows::UI::Xaml::Navigation; - -void OperandTextBox::OnApplyTemplate() -{ - this->IsEnabled = false; - this->IsHitTestVisible = false; - this->IsTapEnabled = false; - this->MaxLength = 50; - this->IsRightTapEnabled = false; - this->IsTabStop = false; - auto parent = VisualTreeHelper::GetParent(this); - ListViewItem^ listViewItem; - ListView^ listView; - while (parent != nullptr) - { - if (listViewItem == nullptr) - { - listViewItem = dynamic_cast(parent); - } - - listView = dynamic_cast(parent); - if (listView != nullptr) - { - break; - } - parent = VisualTreeHelper::GetParent(parent); - } - - if (listView != nullptr) - { - listViewItem->IsEnabled = false; - listViewItem->IsHitTestVisible = false; - listViewItem->IsTapEnabled = false; - } - TextBox::OnApplyTemplate(); -} diff --git a/src/Calculator/Controls/OperandTextBox.h b/src/Calculator/Controls/OperandTextBox.h deleted file mode 100644 index a8508e12..00000000 --- a/src/Calculator/Controls/OperandTextBox.h +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#pragma once - -namespace CalculatorApp -{ - namespace Controls - { - public ref class OperandTextBox sealed : public Windows::UI::Xaml::Controls::TextBox - { - public: - OperandTextBox() { } - - protected: - virtual void OnApplyTemplate() override; - }; - } -} diff --git a/src/Calculator/Controls/OperatorTextBox.cpp b/src/Calculator/Controls/OperatorTextBox.cpp deleted file mode 100644 index 53153504..00000000 --- a/src/Calculator/Controls/OperatorTextBox.cpp +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#include "pch.h" -#include "OperatorTextBox.h" -#include "regex" - -using namespace CalculatorApp; -using namespace CalculatorApp::Controls; - -using namespace Platform; -using namespace std; -using namespace Windows::Foundation; -using namespace Windows::Foundation::Collections; -using namespace Windows::Devices::Input; -using namespace Windows::System; -using namespace Windows::UI::Xaml; -using namespace Windows::UI::Xaml::Controls; -using namespace Windows::UI::Xaml::Controls::Primitives; -using namespace Windows::UI::Xaml::Data; -using namespace Windows::UI::Xaml::Input; -using namespace Windows::UI::Xaml::Media; -using namespace Windows::UI::Xaml::Navigation; - -void OperatorTextBox::OnApplyTemplate() -{ - this->IsEnabled = false; - this->IsHitTestVisible = false; - this->IsTapEnabled = false; - this->MaxLength = 50; - this->IsReadOnly = true; - this->IsRightTapEnabled = false; - this->IsTabStop = false; - auto parent = VisualTreeHelper::GetParent(this); - ListViewItem^ listViewItem; - ListView^ listView; - while (parent != nullptr) - { - if (listViewItem == nullptr) - { - listViewItem = dynamic_cast(parent); - } - - listView = dynamic_cast(parent); - if (listView != nullptr) - { - break; - } - parent = VisualTreeHelper::GetParent(parent); - } - - if (listView != nullptr) - { - listViewItem->IsEnabled = false; - listViewItem->IsHitTestVisible = false; - listViewItem->IsTapEnabled = false; - } - TextBox::OnApplyTemplate(); -} diff --git a/src/Calculator/Controls/OperatorTextBox.h b/src/Calculator/Controls/OperatorTextBox.h deleted file mode 100644 index db92c46e..00000000 --- a/src/Calculator/Controls/OperatorTextBox.h +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#pragma once - -namespace CalculatorApp -{ - namespace Controls - { - public ref class OperatorTextBox sealed : public Windows::UI::Xaml::Controls::TextBox - { - public: - OperatorTextBox() { } - - protected: - virtual void OnApplyTemplate() override; - }; - } -} diff --git a/src/Calculator/Views/Calculator.xaml b/src/Calculator/Views/Calculator.xaml index 0ceec73e..c58bcdfb 100644 --- a/src/Calculator/Views/Calculator.xaml +++ b/src/Calculator/Views/Calculator.xaml @@ -36,106 +36,7 @@ - - - - - + - - - - - - - - - - diff --git a/src/Calculator/Views/HistoryList.xaml.cpp b/src/Calculator/Views/HistoryList.xaml.cpp index 3dd7f301..e9e74e4c 100644 --- a/src/Calculator/Views/HistoryList.xaml.cpp +++ b/src/Calculator/Views/HistoryList.xaml.cpp @@ -42,11 +42,11 @@ HistoryList::HistoryList() void HistoryList::ListView_ItemClick(_In_ Object ^ sender, _In_ ItemClickEventArgs ^ e) { - HistoryViewModel ^ historyVM = static_cast(this->DataContext); - HistoryItemViewModel ^ clickedItem = safe_cast(e->ClickedItem); + HistoryViewModel^ historyVM = dynamic_cast(this->DataContext); + HistoryItemViewModel^ clickedItem = dynamic_cast(e->ClickedItem); // When the user clears the history list in the overlay view and presses enter, the clickedItem is nullptr - if (clickedItem != nullptr) + if (clickedItem != nullptr && historyVM != nullptr) { historyVM->ShowItem(clickedItem); } @@ -54,16 +54,21 @@ void HistoryList::ListView_ItemClick(_In_ Object ^ sender, _In_ ItemClickEventAr void HistoryList::OnDeleteMenuItemClicked(_In_ Object ^ sender, _In_ RoutedEventArgs ^ e) { - auto clickedItem = safe_cast(safe_cast(sender)->DataContext); - - Model->DeleteItem(clickedItem); + auto listViewItem = HistoryContextMenu->Target; + auto itemViewModel = dynamic_cast(HistoryListView->ItemFromContainer(listViewItem)); + if (itemViewModel != nullptr) + { + Model->DeleteItem(itemViewModel); + } } void HistoryList::OnDeleteSwipeInvoked(_In_ MUXC::SwipeItem ^ sender, _In_ MUXC::SwipeItemInvokedEventArgs ^ e) { - auto swipedItem = safe_cast(e->SwipeControl->DataContext); - - Model->DeleteItem(swipedItem); + auto swipedItem = dynamic_cast(e->SwipeControl->DataContext); + if (swipedItem != nullptr) + { + Model->DeleteItem(swipedItem); + } } void HistoryList::ScrollToBottom() diff --git a/src/Calculator/Views/Memory.xaml b/src/Calculator/Views/Memory.xaml index d5f7d117..b609f9fa 100644 --- a/src/Calculator/Views/Memory.xaml +++ b/src/Calculator/Views/Memory.xaml @@ -17,7 +17,7 @@ - + @@ -42,6 +42,7 @@ BasedOn="{StaticResource HistoryMemoryItemContainerStyle}" TargetType="ListViewItem"> + @@ -103,8 +104,6 @@ (Resources->Lookup("MemoryContextMenu")); MemoryPaneEmpty->FlowDirection = LocalizationService::GetInstance()->GetFlowDirection(); } @@ -56,53 +55,31 @@ void Memory::MemoryListItemClick(_In_ Object ^ sender, _In_ ItemClickEventArgs ^ } } -void Memory::OnContextRequested(Windows::UI::Xaml::UIElement ^ sender, Windows::UI::Xaml::Input::ContextRequestedEventArgs ^ e) -{ - // Walk up the tree to find the ListViewItem. - // There may not be one if the click wasn't on an item. - auto requestedElement = safe_cast(e->OriginalSource); - while ((requestedElement != sender) && !dynamic_cast(requestedElement)) - { - requestedElement = safe_cast(VisualTreeHelper::GetParent(requestedElement)); - } - - if (requestedElement != sender) - { - // The context menu request was for a ListViewItem. - auto memorySlot = safe_cast(MemoryListView->ItemFromContainer(requestedElement)); - Point point; - if (e->TryGetPosition(requestedElement, &point)) - { - m_memoryItemFlyout->ShowAt(requestedElement, point); - } - else - { - // Not invoked via pointer, so let XAML choose a default location. - m_memoryItemFlyout->ShowAt(requestedElement); - } - - e->Handled = true; - } -} - -void Memory::OnContextCanceled(Windows::UI::Xaml::UIElement ^ sender, Windows::UI::Xaml::RoutedEventArgs ^ e) -{ - m_memoryItemFlyout->Hide(); -} - void Memory::OnClearMenuItemClicked(_In_ Object ^ sender, _In_ RoutedEventArgs ^ e) { - GetMemoryItemForCurrentFlyout()->Clear(); + auto memoryItem = GetMemoryItemForCurrentFlyout(); + if (memoryItem != nullptr) + { + memoryItem->Clear(); + } } void Memory::OnMemoryAddMenuItemClicked(_In_ Object ^ sender, _In_ RoutedEventArgs ^ e) { - GetMemoryItemForCurrentFlyout()->MemoryAdd(); + auto memoryItem = GetMemoryItemForCurrentFlyout(); + if (memoryItem != nullptr) + { + memoryItem->MemoryAdd(); + } } void Memory::OnMemorySubtractMenuItemClicked(_In_ Object ^ sender, _In_ RoutedEventArgs ^ e) { - GetMemoryItemForCurrentFlyout()->MemorySubtract(); + auto memoryItem = GetMemoryItemForCurrentFlyout(); + if (memoryItem != nullptr) + { + memoryItem->MemorySubtract(); + } } bool Memory::IsErrorVisualState::get() @@ -122,7 +99,6 @@ void Memory::IsErrorVisualState::set(bool value) MemoryItemViewModel ^ Memory::GetMemoryItemForCurrentFlyout() { - auto listViewItem = m_memoryItemFlyout->Target; - - return safe_cast(MemoryListView->ItemFromContainer(listViewItem)); + auto listViewItem = MemoryContextMenu->Target; + return dynamic_cast(MemoryListView->ItemFromContainer(listViewItem)); } diff --git a/src/Calculator/Views/Memory.xaml.h b/src/Calculator/Views/Memory.xaml.h index 4ebf0b1d..31b7900e 100644 --- a/src/Calculator/Views/Memory.xaml.h +++ b/src/Calculator/Views/Memory.xaml.h @@ -36,14 +36,11 @@ namespace CalculatorApp } private: - Windows::UI::Xaml::Controls::MenuFlyout ^ m_memoryItemFlyout; Windows::Foundation::Rect m_visibleBounds; Windows::Foundation::Rect m_coreBounds; bool m_isErrorVisualState; void MemoryListItemClick(_In_ Platform::Object ^ sender, _In_ Windows::UI::Xaml::Controls::ItemClickEventArgs ^ e); - void OnContextRequested(Windows::UI::Xaml::UIElement ^ sender, Windows::UI::Xaml::Input::ContextRequestedEventArgs ^ e); - void OnContextCanceled(Windows::UI::Xaml::UIElement ^ sender, Windows::UI::Xaml::RoutedEventArgs ^ e); void OnClearMenuItemClicked(_In_ Platform::Object ^ sender, _In_ Windows::UI::Xaml::RoutedEventArgs ^ e); void OnMemoryAddMenuItemClicked(_In_ Platform::Object ^ sender, _In_ Windows::UI::Xaml::RoutedEventArgs ^ e); void OnMemorySubtractMenuItemClicked(_In_ Platform::Object ^ sender, _In_ Windows::UI::Xaml::RoutedEventArgs ^ e); From 1b9d6b8fbeed778d94e611513fd71f9c2a68981f Mon Sep 17 00:00:00 2001 From: Matt Cooley Date: Tue, 16 Jul 2019 16:21:45 -0700 Subject: [PATCH 070/154] Use 2020 as the major version for the appxbundle (#586) Calculator's build number in release builds follows the pattern 10.{YYMM}.{build}.0. We use the build number in lots of places, including the app binaries, the app package version, and the app bundle version. Before Calculator moved to GitHub, the app bundle version was generated using a date-based formula which produced versions like "2019.105.612.0". This means that the bundles generated from GitHub have a lower version than previous bundles. This appears to cause some issues during device reset. This change sets the app bundle major version number to "2020" to ensure that newly-produced appxbundles have higher versions than legacy bundles. The remaining parts of the bundle version number will match the build number for easy reference. Also updating the MakeAppx version used in bundle creation to 18362. --- build/pipelines/templates/package-appxbundle.yaml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/build/pipelines/templates/package-appxbundle.yaml b/build/pipelines/templates/package-appxbundle.yaml index f88f155f..1e06d20d 100644 --- a/build/pipelines/templates/package-appxbundle.yaml +++ b/build/pipelines/templates/package-appxbundle.yaml @@ -38,10 +38,13 @@ jobs: filePath: $(Build.SourcesDirectory)\build\scripts\CreateAppxBundleMapping.ps1 arguments: '-InputPath $(Build.ArtifactStagingDirectory)\drop\Release -ProjectName Calculator -OutputFile $(Build.BinariesDirectory)\AppxBundleMapping.txt' - - script: '"C:\Program Files (x86)\Windows Kits\10\bin\10.0.17763.0\x86\MakeAppx.exe" bundle /v /bv %BUNDLEVERSION% /f %MAPPINGFILEPATH% /p %OUTPUTPATH%' + - powershell: | + $buildVersion = [version]$Env:BUILDVERSION + $bundleVersion = "2020.$($buildVersion.Minor).$($buildVersion.Build).$($buildVersion.Revision)" + & "C:\Program Files (x86)\Windows Kits\10\bin\10.0.18362.0\x86\MakeAppx.exe" bundle /v /bv $bundleVersion /f $Env:MAPPINGFILEPATH /p $Env:OUTPUTPATH displayName: Make AppxBundle env: - BUNDLEVERSION: $(Build.BuildNumber) + BUILDVERSION: $(Build.BuildNumber) MAPPINGFILEPATH: $(Build.BinariesDirectory)\AppxBundleMapping.txt OUTPUTPATH: $(Build.BinariesDirectory)\Microsoft.WindowsCalculator_8wekyb3d8bbwe.appxbundle From 2ff7bb408968597135321e0e623d5cac1edfbed3 Mon Sep 17 00:00:00 2001 From: Rudy Huyn Date: Tue, 16 Jul 2019 17:00:57 -0700 Subject: [PATCH 071/154] Unit Converter - Calculate the rounding precision of results based on the source (#498) * precisely calculates the number of digits of the source and compute the number of significant digits of the result based on that. * fix unit test * Fix warning C4267 * Optimize how we calculate the number of digits in the integer part and don't trim the value when used by the currency converter * modify GetNumberSignificantDigits * fix CI error * Access to wstring::npos from static calls * Move UnitConverter static methods related to number to NumberFormattingUtils * rename namespace * Add comment and fix typo * Move standard headers --- src/CalcManager/CalcManager.vcxproj | 2 + src/CalcManager/CalcManager.vcxproj.filters | 4 +- src/CalcManager/NumberFormattingUtils.cpp | 84 +++++++++++++ src/CalcManager/NumberFormattingUtils.h | 15 +++ src/CalcManager/UnitConverter.cpp | 119 ++++++------------ src/CalcManager/UnitConverter.h | 2 - src/CalcManager/pch.h | 2 + .../CalculatorManagerTest.cpp | 103 +++++++++++++++ src/CalculatorUnitTests/UnitConverterTest.cpp | 2 +- 9 files changed, 251 insertions(+), 82 deletions(-) create mode 100644 src/CalcManager/NumberFormattingUtils.cpp create mode 100644 src/CalcManager/NumberFormattingUtils.h diff --git a/src/CalcManager/CalcManager.vcxproj b/src/CalcManager/CalcManager.vcxproj index c14d5edd..7022cd3e 100644 --- a/src/CalcManager/CalcManager.vcxproj +++ b/src/CalcManager/CalcManager.vcxproj @@ -309,6 +309,7 @@ + @@ -349,6 +350,7 @@ Create Create + diff --git a/src/CalcManager/CalcManager.vcxproj.filters b/src/CalcManager/CalcManager.vcxproj.filters index 2ca11666..53098917 100644 --- a/src/CalcManager/CalcManager.vcxproj.filters +++ b/src/CalcManager/CalcManager.vcxproj.filters @@ -89,6 +89,7 @@ CEngine + @@ -160,5 +161,6 @@ Header Files + - + \ No newline at end of file diff --git a/src/CalcManager/NumberFormattingUtils.cpp b/src/CalcManager/NumberFormattingUtils.cpp new file mode 100644 index 00000000..8fde3d9a --- /dev/null +++ b/src/CalcManager/NumberFormattingUtils.cpp @@ -0,0 +1,84 @@ +#include "pch.h" +#include "NumberFormattingUtils.h" + +using namespace std; + +namespace CalcManager::NumberFormattingUtils +{ + /// + /// Trims out any trailing zeros or decimals in the given input string + /// + /// number to trim + void TrimTrailingZeros(_Inout_ wstring& number) + { + if (number.find(L'.') == wstring::npos) + { + return; + } + + wstring::iterator iter; + for (iter = number.end() - 1;; iter--) + { + if (*iter != L'0') + { + number.erase(iter + 1, number.end()); + break; + } + } + if (*(number.end() - 1) == L'.') + { + number.erase(number.end() - 1, number.end()); + } + } + + /// + /// Get number of digits (whole number part + decimal part) + /// the number + unsigned int GetNumberDigits(wstring value) + { + TrimTrailingZeros(value); + unsigned int numberSignificantDigits = static_cast(value.size()); + if (value.find(L'.') != wstring::npos) + { + --numberSignificantDigits; + } + if (value.find(L'-') != wstring::npos) + { + --numberSignificantDigits; + } + return numberSignificantDigits; + } + + /// + /// Get number of digits (whole number part only) + /// the number + unsigned int GetNumberDigitsWholeNumberPart(double value) + { + return value == 0 ? 1 : (1 + (int)log10(abs(value))); + } + + /// + /// Rounds the given double to the given number of significant digits + /// + /// input double + /// int number of significant digits to round to + wstring RoundSignificantDigits(double num, int numSignificant) + { + wstringstream out(wstringstream::out); + out << fixed; + out.precision(numSignificant); + out << num; + return out.str(); + } + + /// + /// Convert a Number to Scientific Notation + /// + /// number to convert + wstring ToScientificNumber(double number) + { + wstringstream out(wstringstream::out); + out << scientific << number; + return out.str(); + } +} diff --git a/src/CalcManager/NumberFormattingUtils.h b/src/CalcManager/NumberFormattingUtils.h new file mode 100644 index 00000000..ab337eed --- /dev/null +++ b/src/CalcManager/NumberFormattingUtils.h @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include + +namespace CalcManager::NumberFormattingUtils +{ + void TrimTrailingZeros(_Inout_ std::wstring& input); + unsigned int GetNumberDigits(std::wstring value); + unsigned int GetNumberDigitsWholeNumberPart(double value); + std::wstring RoundSignificantDigits(double value, int numberSignificantDigits); + std::wstring ToScientificNumber(double number); +} diff --git a/src/CalcManager/UnitConverter.cpp b/src/CalcManager/UnitConverter.cpp index bbf761ba..983ef6db 100644 --- a/src/CalcManager/UnitConverter.cpp +++ b/src/CalcManager/UnitConverter.cpp @@ -7,9 +7,11 @@ #include // for std::sort #include "Command.h" #include "UnitConverter.h" +#include "NumberFormattingUtils.h" using namespace std; using namespace UnitConversionManager; +using namespace CalcManager::NumberFormattingUtils; static constexpr uint32_t EXPECTEDSERIALIZEDCATEGORYTOKENCOUNT = 3; static constexpr uint32_t EXPECTEDSERIALIZEDUNITTOKENCOUNT = 6; @@ -178,7 +180,7 @@ void UnitConverter::SwitchActive(const wstring& newValue) swap(m_currentHasDecimal, m_returnHasDecimal); m_returnDisplay = m_currentDisplay; m_currentDisplay = newValue; - m_currentHasDecimal = (m_currentDisplay.find(L'.') != m_currentDisplay.npos); + m_currentHasDecimal = (m_currentDisplay.find(L'.') != wstring::npos); m_switchedActive = true; if (m_currencyDataLoader != nullptr && m_vmCurrencyCallback != nullptr) @@ -202,7 +204,7 @@ vector UnitConverter::StringToVector(const wstring& w, const wchar_t* d size_t delimiterIndex = w.find(delimiter); size_t startIndex = 0; vector serializedTokens = vector(); - while (delimiterIndex != w.npos) + while (delimiterIndex != wstring::npos) { serializedTokens.push_back(w.substr(startIndex, delimiterIndex - startIndex)); startIndex = delimiterIndex + (int)wcslen(delimiter); @@ -634,19 +636,19 @@ vector> UnitConverter::CalculateSuggested() wstring roundedString; if (abs(entry.value) < 100) { - roundedString = RoundSignificant(entry.value, 2); + roundedString = RoundSignificantDigits(entry.value, 2); } else if (abs(entry.value) < 1000) { - roundedString = RoundSignificant(entry.value, 1); + roundedString = RoundSignificantDigits(entry.value, 1); } else { - roundedString = RoundSignificant(entry.value, 0); + roundedString = RoundSignificantDigits(entry.value, 0); } if (stod(roundedString) != 0.0 || m_currentCategory.supportsNegative) { - TrimString(roundedString); + TrimTrailingZeros(roundedString); returnVector.push_back(make_tuple(roundedString, entry.type)); } } @@ -672,21 +674,21 @@ vector> UnitConverter::CalculateSuggested() wstring roundedString; if (abs(entry.value) < 100) { - roundedString = RoundSignificant(entry.value, 2); + roundedString = RoundSignificantDigits(entry.value, 2); } else if (abs(entry.value) < 1000) { - roundedString = RoundSignificant(entry.value, 1); + roundedString = RoundSignificantDigits(entry.value, 1); } else { - roundedString = RoundSignificant(entry.value, 0); + roundedString = RoundSignificantDigits(entry.value, 0); } // How to work out which is the best whimsical value to add to the vector? if (stod(roundedString) != 0.0) { - TrimString(roundedString); + TrimTrailingZeros(roundedString); whimsicalReturnVector.push_back(make_tuple(roundedString, entry.type)); } } @@ -843,100 +845,61 @@ void UnitConverter::Calculate() { m_returnDisplay = m_currentDisplay; m_returnHasDecimal = m_currentHasDecimal; - TrimString(m_returnDisplay); + TrimTrailingZeros(m_returnDisplay); UpdateViewModel(); return; } unordered_map conversionTable = m_ratioMap[m_fromType]; - double returnValue = stod(m_currentDisplay); - if (conversionTable[m_toType].ratio == 1.0 && conversionTable[m_toType].offset == 0.0) + if (AnyUnitIsEmpty() || (conversionTable[m_toType].ratio == 1.0 && conversionTable[m_toType].offset == 0.0)) { m_returnDisplay = m_currentDisplay; m_returnHasDecimal = m_currentHasDecimal; - TrimString(m_returnDisplay); + TrimTrailingZeros(m_returnDisplay); } else { - returnValue = Convert(returnValue, conversionTable[m_toType]); - m_returnDisplay = RoundSignificant(returnValue, MAXIMUMDIGITSALLOWED); - TrimString(m_returnDisplay); - int numPreDecimal = (int)m_returnDisplay.size(); - if (m_returnDisplay.find(L'.') != m_returnDisplay.npos) - { - numPreDecimal = (int)m_returnDisplay.find(L'.'); - } - if (returnValue < 0) - { - numPreDecimal--; - } + double currentValue = stod(m_currentDisplay); + double returnValue = Convert(currentValue, conversionTable[m_toType]); - if (numPreDecimal > MAXIMUMDIGITSALLOWED || (returnValue != 0 && abs(returnValue) < MINIMUMDECIMALALLOWED)) + auto isCurrencyConverter = m_currencyDataLoader != nullptr && m_currencyDataLoader->SupportsCategory(this->m_currentCategory); + if (isCurrencyConverter) { - wstringstream out(wstringstream::out); - out << scientific << returnValue; - m_returnDisplay = out.str(); + // We don't need to trim the value when it's a currency. + m_returnDisplay = RoundSignificantDigits(returnValue, MAXIMUMDIGITSALLOWED); + TrimTrailingZeros(m_returnDisplay); } else { - returnValue = stod(m_returnDisplay); - wstring returnString; - if (m_currentDisplay.size() <= OPTIMALDIGITSALLOWED && abs(returnValue) >= OPTIMALDECIMALALLOWED) + int numPreDecimal = GetNumberDigitsWholeNumberPart(returnValue); + if (numPreDecimal > MAXIMUMDIGITSALLOWED || (returnValue != 0 && abs(returnValue) < MINIMUMDECIMALALLOWED)) { - returnString = RoundSignificant(returnValue, OPTIMALDIGITSALLOWED - min(numPreDecimal, OPTIMALDIGITSALLOWED)); + m_returnDisplay = ToScientificNumber(returnValue); } else { - returnString = RoundSignificant(returnValue, MAXIMUMDIGITSALLOWED - min(numPreDecimal, MAXIMUMDIGITSALLOWED)); + int currentNumberSignificantDigits = GetNumberDigits(m_currentDisplay); + int precision = 0; + if (abs(returnValue) < OPTIMALDECIMALALLOWED) + { + precision = MAXIMUMDIGITSALLOWED; + } + else + { + // Fewer digits are needed following the decimal if the number is large, + // we calculate the number of decimals necessary based on the number of digits in the integer part. + precision = max(0, max(OPTIMALDIGITSALLOWED, min(MAXIMUMDIGITSALLOWED, currentNumberSignificantDigits)) - numPreDecimal); + } + + m_returnDisplay = RoundSignificantDigits(returnValue, precision); + TrimTrailingZeros(m_returnDisplay); } - m_returnDisplay = returnString; - TrimString(m_returnDisplay); + m_returnHasDecimal = (m_returnDisplay.find(L'.') != wstring::npos); } - m_returnHasDecimal = (m_returnDisplay.find(L'.') != m_returnDisplay.npos); } UpdateViewModel(); } -/// -/// Trims out any trailing zeros or decimals in the given input string -/// -/// wstring to trim -void UnitConverter::TrimString(wstring& returnString) -{ - if (returnString.find(L'.') == m_returnDisplay.npos) - { - return; - } - - wstring::iterator iter; - for (iter = returnString.end() - 1;; iter--) - { - if (*iter != L'0') - { - returnString.erase(iter + 1, returnString.end()); - break; - } - } - if (*(returnString.end() - 1) == L'.') - { - returnString.erase(returnString.end() - 1, returnString.end()); - } -} - -/// -/// Rounds the given double to the given number of significant digits -/// -/// input double -/// int number of significant digits to round to -wstring UnitConverter::RoundSignificant(double num, int numSignificant) -{ - wstringstream out(wstringstream::out); - out << fixed; - out.precision(numSignificant); - out << num; - return out.str(); -} - void UnitConverter::UpdateCurrencySymbols() { if (m_currencyDataLoader != nullptr && m_vmCurrencyCallback != nullptr) diff --git a/src/CalcManager/UnitConverter.h b/src/CalcManager/UnitConverter.h index 0d1b8acd..27b8629d 100644 --- a/src/CalcManager/UnitConverter.h +++ b/src/CalcManager/UnitConverter.h @@ -279,9 +279,7 @@ namespace UnitConversionManager double Convert(double value, ConversionData conversionData); std::vector> CalculateSuggested(); void ClearValues(); - void TrimString(std::wstring& input); void InitializeSelectedUnits(); - std::wstring RoundSignificant(double num, int numSignificant); Category StringToCategory(const std::wstring& w); std::wstring CategoryToString(const Category& c, const wchar_t* delimiter); std::wstring UnitToString(const Unit& u, const wchar_t* delimiter); diff --git a/src/CalcManager/pch.h b/src/CalcManager/pch.h index 2bcedb7a..9207ebff 100644 --- a/src/CalcManager/pch.h +++ b/src/CalcManager/pch.h @@ -20,3 +20,5 @@ #include #include #include +#include +#include diff --git a/src/CalculatorUnitTests/CalculatorManagerTest.cpp b/src/CalculatorUnitTests/CalculatorManagerTest.cpp index 34acafea..9696a898 100644 --- a/src/CalculatorUnitTests/CalculatorManagerTest.cpp +++ b/src/CalculatorUnitTests/CalculatorManagerTest.cpp @@ -7,9 +7,11 @@ #include "CalcManager/CalculatorHistory.h" #include "CalcViewModel/Common/EngineResourceProvider.h" +#include "CalcManager/NumberFormattingUtils.h" using namespace CalculatorApp; using namespace CalculationManager; +using namespace CalcManager::NumberFormattingUtils; using namespace Platform; using namespace std; using namespace Microsoft::VisualStudio::CppUnitTestFramework; @@ -185,6 +187,11 @@ namespace CalculatorManagerTest TEST_METHOD(CalculatorManagerTestMaxDigitsReached_LeadingDecimal); TEST_METHOD(CalculatorManagerTestMaxDigitsReached_TrailingDecimal); + TEST_METHOD(CalculatorManagerNumberFormattingUtils_TrimTrailingZeros); + TEST_METHOD(CalculatorManagerNumberFormattingUtils_GetNumberDigits); + TEST_METHOD(CalculatorManagerNumberFormattingUtils_GetNumberDigitsWholeNumberPart); + TEST_METHOD(CalculatorManagerNumberFormattingUtils_RoundSignificantDigits); + TEST_METHOD(CalculatorManagerNumberFormattingUtils_ToScientificNumber); // TODO re-enable when cause of failure is determined. Bug 20226670 // TEST_METHOD(CalculatorManagerTestBinaryOperatorReceived); // TEST_METHOD(CalculatorManagerTestBinaryOperatorReceived_Multiple); @@ -807,6 +814,102 @@ namespace CalculatorManagerTest TestMaxDigitsReachedScenario(L"123,456,789,101,112.13"); } + void CalculatorManagerTest::CalculatorManagerNumberFormattingUtils_TrimTrailingZeros() + { + wstring number = L"2.1032100000000"; + TrimTrailingZeros(number); + VERIFY_ARE_EQUAL(number, L"2.10321"); + number = L"-122.123200"; + TrimTrailingZeros(number); + VERIFY_ARE_EQUAL(number, L"-122.1232"); + number = L"0.0001200"; + TrimTrailingZeros(number); + VERIFY_ARE_EQUAL(number, L"0.00012"); + number = L"12.000"; + TrimTrailingZeros(number); + VERIFY_ARE_EQUAL(number, L"12"); + number = L"-12.00000"; + TrimTrailingZeros(number); + VERIFY_ARE_EQUAL(number, L"-12"); + number = L"0.000"; + TrimTrailingZeros(number); + VERIFY_ARE_EQUAL(number, L"0"); + number = L"322423"; + TrimTrailingZeros(number); + VERIFY_ARE_EQUAL(number, L"322423"); + } + + void CalculatorManagerTest::CalculatorManagerNumberFormattingUtils_GetNumberDigits() + { + wstring number = L"2.10321"; + unsigned int digitsCount = GetNumberDigits(number); + VERIFY_ARE_EQUAL(digitsCount, 6); + number = L"-122.1232"; + digitsCount = GetNumberDigits(number); + VERIFY_ARE_EQUAL(digitsCount, 7); + number = L"-3432"; + digitsCount = GetNumberDigits(number); + VERIFY_ARE_EQUAL(digitsCount, 4); + number = L"0"; + digitsCount = GetNumberDigits(number); + VERIFY_ARE_EQUAL(digitsCount, 1); + number = L"0.0001223"; + digitsCount = GetNumberDigits(number); + VERIFY_ARE_EQUAL(digitsCount, 8); + } + + void CalculatorManagerTest::CalculatorManagerNumberFormattingUtils_GetNumberDigitsWholeNumberPart() + { + unsigned int digitsCount = GetNumberDigitsWholeNumberPart(2.10321); + VERIFY_ARE_EQUAL(digitsCount, 1); + digitsCount = GetNumberDigitsWholeNumberPart(-122.1232); + VERIFY_ARE_EQUAL(digitsCount, 3); + digitsCount = GetNumberDigitsWholeNumberPart(-3432); + VERIFY_ARE_EQUAL(digitsCount, 4); + digitsCount = GetNumberDigitsWholeNumberPart(0); + VERIFY_ARE_EQUAL(digitsCount, 1); + digitsCount = GetNumberDigitsWholeNumberPart(324328412837382); + VERIFY_ARE_EQUAL(digitsCount, 15); + digitsCount = GetNumberDigitsWholeNumberPart(324328412837382.232213214324234); + VERIFY_ARE_EQUAL(digitsCount, 15); + } + + void CalculatorManagerTest::CalculatorManagerNumberFormattingUtils_RoundSignificantDigits() + { + wstring result = RoundSignificantDigits(12.342343242, 3); + VERIFY_ARE_EQUAL(result, L"12.342"); + result = RoundSignificantDigits(12.3429999, 3); + VERIFY_ARE_EQUAL(result, L"12.343"); + result = RoundSignificantDigits(12.342500001, 3); + VERIFY_ARE_EQUAL(result, L"12.343"); + result = RoundSignificantDigits(-2312.1244243346454345, 5); + VERIFY_ARE_EQUAL(result, L"-2312.12442"); + result = RoundSignificantDigits(0.3423432423, 5); + VERIFY_ARE_EQUAL(result, L"0.34234"); + result = RoundSignificantDigits(0.3423, 7); + VERIFY_ARE_EQUAL(result, L"0.3423000"); + } + + void CalculatorManagerTest::CalculatorManagerNumberFormattingUtils_ToScientificNumber() + { + wstring result = ToScientificNumber(3423); + VERIFY_ARE_EQUAL(result, L"3.423000e+03"); + result = ToScientificNumber(-21); + VERIFY_ARE_EQUAL(result, L"-2.100000e+01"); + result = ToScientificNumber(0.0232); + VERIFY_ARE_EQUAL(result, L"2.320000e-02"); + result = ToScientificNumber(-0.00921); + VERIFY_ARE_EQUAL(result, L"-9.210000e-03"); + result = ToScientificNumber(2343243345677); + VERIFY_ARE_EQUAL(result, L"2.343243e+12"); + result = ToScientificNumber(-3432474247332942); + VERIFY_ARE_EQUAL(result, L"-3.432474e+15"); + result = ToScientificNumber(0.000000003432432); + VERIFY_ARE_EQUAL(result, L"3.432432e-09"); + result = ToScientificNumber(-0.000000003432432); + VERIFY_ARE_EQUAL(result, L"-3.432432e-09"); + } + // TODO re-enable when cause of failure is determined. Bug 20226670 // void CalculatorManagerTest::CalculatorManagerTestBinaryOperatorReceived() // { diff --git a/src/CalculatorUnitTests/UnitConverterTest.cpp b/src/CalculatorUnitTests/UnitConverterTest.cpp index 3f3559d2..fc2655fd 100644 --- a/src/CalculatorUnitTests/UnitConverterTest.cpp +++ b/src/CalculatorUnitTests/UnitConverterTest.cpp @@ -441,7 +441,7 @@ namespace UnitConverterUnitTests s_unitConverter->SendCommand(Command::Six); s_unitConverter->SendCommand(Command::Seven); s_unitConverter->SendCommand(Command::Eight); - VERIFY_IS_TRUE(s_testVMCallback->CheckDisplayValues(wstring(L"12345678"), wstring(L"27217528.63236"))); + VERIFY_IS_TRUE(s_testVMCallback->CheckDisplayValues(wstring(L"12345678"), wstring(L"27217529"))); } // Test large values From a6384269bc71a679df21f63ebb597cf26bff687c Mon Sep 17 00:00:00 2001 From: Stephanie Anderl <46726333+sanderl@users.noreply.github.com> Date: Wed, 17 Jul 2019 18:09:39 -0700 Subject: [PATCH 072/154] Updated Calculator diagnostic data collection per the specification (#572) - Removed unneeded diagnostic events and code - Added and consolidated events into the events defined in the spec --- README.md | 4 +- src/CalcViewModel/ApplicationViewModel.cpp | 22 +- src/CalcViewModel/CalcViewModel.vcxproj | 4 +- .../Common/CalculatorButtonUser.h | 57 +- src/CalcViewModel/Common/CopyPasteManager.cpp | 12 +- src/CalcViewModel/Common/CopyPasteManager.h | 2 +- src/CalcViewModel/Common/TraceLogger.cpp | 1125 ++++------------- src/CalcViewModel/Common/TraceLogger.h | 143 +-- .../DataLoaders/CurrencyDataLoader.cpp | 10 +- src/CalcViewModel/DateCalculatorViewModel.cpp | 3 - src/CalcViewModel/HistoryViewModel.cpp | 4 +- .../StandardCalculatorViewModel.cpp | 72 +- .../StandardCalculatorViewModel.h | 5 +- src/CalcViewModel/UnitConverterViewModel.cpp | 8 +- src/CalcViewModel/UnitConverterViewModel.h | 2 +- src/Calculator/AboutFlyout.xaml | 1 - src/Calculator/AboutFlyout.xaml.cpp | 5 - src/Calculator/AboutFlyout.xaml.h | 3 +- src/Calculator/App.xaml.cpp | 25 +- src/Calculator/App.xaml.h | 4 +- src/Calculator/Calculator.vcxproj | 4 +- src/Calculator/Common/AppLifecycleLogger.cpp | 20 +- src/Calculator/Common/AppLifecycleLogger.h | 4 +- src/Calculator/Views/Calculator.xaml | 4 +- src/Calculator/Views/Calculator.xaml.cpp | 21 +- src/Calculator/Views/Calculator.xaml.h | 2 +- .../CalculatorProgrammerBitFlipPanel.xaml.cpp | 2 - .../CalculatorProgrammerDisplayPanel.xaml | 1 - .../CalculatorProgrammerDisplayPanel.xaml.cpp | 7 +- .../CalculatorProgrammerOperators.xaml.cpp | 8 +- .../CalculatorScientificAngleButtons.xaml.cpp | 2 - src/Calculator/Views/DateCalculator.xaml | 2 +- src/Calculator/Views/DateCalculator.xaml.cpp | 20 +- src/Calculator/Views/DateCalculator.xaml.h | 2 + src/Calculator/Views/MainPage.xaml.cpp | 1 - src/Calculator/Views/UnitConverter.xaml | 2 +- src/Calculator/Views/UnitConverter.xaml.cpp | 10 +- src/Calculator/Views/UnitConverter.xaml.h | 1 + src/Calculator/WindowFrameService.cpp | 15 +- src/Calculator/WindowFrameService.h | 4 +- .../CopyPasteManagerTest.cpp | 2 +- .../StandardViewModelUnitTests.cpp | 24 +- .../UnitConverterViewModelUnitTests.cpp | 29 +- 43 files changed, 449 insertions(+), 1249 deletions(-) diff --git a/README.md b/README.md index fd39861b..e27f55b8 100644 --- a/README.md +++ b/README.md @@ -48,10 +48,10 @@ We also welcome [issues submitted on GitHub](https://github.com/Microsoft/calcul ## Roadmap For information regarding Windows Calculator plans and release schedule, please see the [Windows Calculator Roadmap](docs/Roadmap.md). -## Data / Telemetry +## Diagnostic Data This project collects usage data and sends it to Microsoft to help improve our products and services. Read our [privacy statement](https://go.microsoft.com/fwlink/?LinkId=521839) to learn more. -Telemetry is disabled in development builds by default, and can be enabled with the `SEND_TELEMETRY` +Diagnostic data is disabled in development builds by default, and can be enabled with the `SEND_DIAGNOSTICS` build flag. ## Currency Converter diff --git a/src/CalcViewModel/ApplicationViewModel.cpp b/src/CalcViewModel/ApplicationViewModel.cpp index e5f55ed4..edec2a41 100644 --- a/src/CalcViewModel/ApplicationViewModel.cpp +++ b/src/CalcViewModel/ApplicationViewModel.cpp @@ -82,7 +82,7 @@ void ApplicationViewModel::Initialize(ViewMode mode) } catch (const std::exception& e) { - TraceLogger::GetInstance().LogStandardException(__FUNCTIONW__, e); + TraceLogger::GetInstance().LogStandardException(mode, __FUNCTIONW__, e); if (!TryRecoverFromNavigationModeFailure()) { // Could not navigate to standard mode either. @@ -92,7 +92,7 @@ void ApplicationViewModel::Initialize(ViewMode mode) } catch (Exception ^ e) { - TraceLogger::GetInstance().LogPlatformException(__FUNCTIONW__, e); + TraceLogger::GetInstance().LogPlatformException(mode, __FUNCTIONW__, e); if (!TryRecoverFromNavigationModeFailure()) { // Could not navigate to standard mode either. @@ -121,10 +121,8 @@ bool ApplicationViewModel::TryRecoverFromNavigationModeFailure() void ApplicationViewModel::OnModeChanged() { assert(NavCategory::IsValidViewMode(m_mode)); - TraceLogger::GetInstance().LogModeChangeBegin(m_PreviousMode, m_mode, ApplicationView::GetApplicationViewIdForWindow(CoreWindow::GetForCurrentThread())); if (NavCategory::IsCalculatorViewMode(m_mode)) { - TraceLogger::GetInstance().LogCalculatorModeViewed(m_mode, ApplicationView::GetApplicationViewIdForWindow(CoreWindow::GetForCurrentThread())); if (!m_CalculatorViewModel) { m_CalculatorViewModel = ref new StandardCalculatorViewModel(); @@ -133,7 +131,6 @@ void ApplicationViewModel::OnModeChanged() } else if (NavCategory::IsDateCalculatorViewMode(m_mode)) { - TraceLogger::GetInstance().LogDateCalculatorModeViewed(m_mode, ApplicationView::GetApplicationViewIdForWindow(CoreWindow::GetForCurrentThread())); if (!m_DateCalcViewModel) { m_DateCalcViewModel = ref new DateCalculatorViewModel(); @@ -141,7 +138,6 @@ void ApplicationViewModel::OnModeChanged() } else if (NavCategory::IsConverterViewMode(m_mode)) { - TraceLogger::GetInstance().LogConverterModeViewed(m_mode, ApplicationView::GetApplicationViewIdForWindow(CoreWindow::GetForCurrentThread())); if (!m_ConverterViewModel) { auto dataLoader = make_shared(ref new GeographicRegion()); @@ -155,13 +151,21 @@ void ApplicationViewModel::OnModeChanged() auto resProvider = AppResourceProvider::GetInstance(); CategoryName = resProvider.GetResourceString(NavCategory::GetNameResourceKey(m_mode)); - // This is the only place where a ViewMode enum should be cast to an int. - // + // Cast mode to an int in order to save it to app data. // Save the changed mode, so that the new window launches in this mode. // Don't save until after we have adjusted to the new mode, so we don't save a mode that fails to load. ApplicationData::Current->LocalSettings->Values->Insert(ModePropertyName, NavCategory::Serialize(m_mode)); - TraceLogger::GetInstance().LogModeChangeEnd(m_mode, ApplicationView::GetApplicationViewIdForWindow(CoreWindow::GetForCurrentThread())); + // Log ModeChange event when not first launch, log WindowCreated on first launch + if (NavCategory::IsValidViewMode(m_PreviousMode)) + { + TraceLogger::GetInstance().LogModeChange(m_mode); + } + else + { + TraceLogger::GetInstance().LogWindowCreated(m_mode); + } + RaisePropertyChanged(ClearMemoryVisibilityPropertyName); } diff --git a/src/CalcViewModel/CalcViewModel.vcxproj b/src/CalcViewModel/CalcViewModel.vcxproj index 173e011a..c9fae3ce 100644 --- a/src/CalcViewModel/CalcViewModel.vcxproj +++ b/src/CalcViewModel/CalcViewModel.vcxproj @@ -308,7 +308,7 @@ - /DSEND_TELEMETRY %(AdditionalOptions) + /DSEND_DIAGNOSTICS %(AdditionalOptions) @@ -439,4 +439,4 @@ - \ No newline at end of file + diff --git a/src/CalcViewModel/Common/CalculatorButtonUser.h b/src/CalcViewModel/Common/CalculatorButtonUser.h index 19fa4044..b9ce3329 100644 --- a/src/CalcViewModel/Common/CalculatorButtonUser.h +++ b/src/CalcViewModel/Common/CalculatorButtonUser.h @@ -161,55 +161,14 @@ public BINPOS62 = (int)CM::Command::CommandBINPOS62, BINPOS63 = (int)CM::Command::CommandBINPOS63, BINEND = (int)CM::Command::CommandBINEDITEND, - Hyp = (int)CM::Command::CommandHYP - }; + Hyp = (int)CM::Command::CommandHYP, - // This contains list of functions whose usage we are tracelogging -public - enum class FunctionLogEnum - { - Invert = (int)CM::Command::CommandREC, - Sqrt = (int)CM::Command::CommandSQRT, - Percent = (int)CM::Command::CommandPERCENT, - Negate = (int)CM::Command::CommandSIGN, - Degrees = (int)CM::Command::CommandDegrees, - Pi = (int)CM::Command::CommandPI, - Sin = (int)CM::Command::CommandSIN, - Cos = (int)CM::Command::CommandCOS, - Tan = (int)CM::Command::CommandTAN, - Factorial = (int)CM::Command::CommandFAC, - XPower2 = (int)CM::Command::CommandSQR, - Mod = (int)CM::Command::CommandMOD, - FToE = (int)CM::Command::CommandFE, - LogBaseE = (int)CM::Command::CommandLN, - InvSin = (int)CM::Command::CommandASIN, - InvCos = (int)CM::Command::CommandACOS, - InvTan = (int)CM::Command::CommandATAN, - LogBase10 = (int)CM::Command::CommandLOG, - XPowerY = (int)CM::Command::CommandPWR, - YRootX = (int)CM::Command::CommandROOT, - TenPowerX = (int)CM::Command::CommandPOW10, - EPowerX = (int)CM::Command::CommandPOWE, - Exp = (int)CM::Command::CommandEXP, - DecButton = (int)CM::Command::CommandDec, - OctButton = (int)CM::Command::CommandOct, - HexButton = (int)CM::Command::CommandHex, - BinButton = (int)CM::Command::CommandBin, - And = (int)CM::Command::CommandAnd, - Ror = (int)CM::Command::CommandROR, - Rol = (int)CM::Command::CommandROL, - Or = (int)CM::Command::CommandOR, - Lsh = (int)CM::Command::CommandLSHF, - Rsh = (int)CM::Command::CommandRSHF, - Xor = (int)CM::Command::CommandXor, - Not = (int)CM::Command::CommandNot, - Sinh = (int)CM::Command::CommandSINH, - Cosh = (int)CM::Command::CommandCOSH, - Tanh = (int)CM::Command::CommandTANH, - InvSinh = (int)CM::Command::CommandASINH, - InvCosh = (int)CM::Command::CommandACOSH, - InvTanh = (int)CM::Command::CommandATANH, - Cube = (int)CM::Command::CommandCUB, - DMS = (int)CM::Command::CommandDMS, + // Enum values below are used for Tracelogging and do not map to the Calculator engine + MemoryAdd = (int)CM::Command::CommandMPLUS, + MemorySubtract = (int)CM::Command::CommandMMINUS, + MemoryRecall = (int)CM::Command::CommandRECALL, + MemoryClear = (int)CM::Command::CommandMCLEAR, + BitflipButton = 1000, + FullKeypadButton = 1001 }; } diff --git a/src/CalcViewModel/Common/CopyPasteManager.cpp b/src/CalcViewModel/Common/CopyPasteManager.cpp index db2439f7..8c00d417 100644 --- a/src/CalcViewModel/Common/CopyPasteManager.cpp +++ b/src/CalcViewModel/Common/CopyPasteManager.cpp @@ -109,7 +109,7 @@ String ^ CopyPasteManager::ValidatePasteExpression(String ^ pastedText, ViewMode if (pastedText->Length() > MaxPasteableLength) { // return NoOp to indicate don't paste anything. - TraceLogger::GetInstance().LogInvalidPastedInputOccurred(L"PastedExpressionSizeGreaterThanMaxAllowed", mode, programmerNumberBase, bitLengthType); + TraceLogger::GetInstance().LogError(mode, L"CopyPasteManager::ValidatePasteExpression", L"PastedExpressionSizeGreaterThanMaxAllowed"); return StringReference(PasteErrorString); } @@ -129,7 +129,7 @@ String ^ CopyPasteManager::ValidatePasteExpression(String ^ pastedText, ViewMode // Extract operands from the expression to make regex comparison easy and quick. For whole expression it was taking too much of time. // Operands vector will have the list of operands in the pasteExpression - vector operands = ExtractOperands(pasteExpression, mode, programmerNumberBase, bitLengthType); + vector operands = ExtractOperands(pasteExpression, mode); if (operands.empty()) { // return NoOp to indicate don't paste anything. @@ -144,14 +144,14 @@ String ^ CopyPasteManager::ValidatePasteExpression(String ^ pastedText, ViewMode // validate each operand with patterns for different modes if (!ExpressionRegExMatch(operands, mode, modeType, programmerNumberBase, bitLengthType)) { - TraceLogger::GetInstance().LogInvalidPastedInputOccurred(L"InvalidExpressionForPresentMode", mode, programmerNumberBase, bitLengthType); + TraceLogger::GetInstance().LogError(mode, L"CopyPasteManager::ValidatePasteExpression", L"InvalidExpressionForPresentMode"); return StringReference(PasteErrorString); } return ref new String(pastedText->Data()); } -vector CopyPasteManager::ExtractOperands(const wstring& pasteExpression, ViewMode mode, int programmerNumberBase, int bitLengthType) +vector CopyPasteManager::ExtractOperands(const wstring& pasteExpression, ViewMode mode) { vector operands{}; size_t lastIndex = 0; @@ -173,7 +173,7 @@ vector CopyPasteManager::ExtractOperands(const wstring& pasteExpression if (operands.size() >= MaxOperandCount) { - TraceLogger::GetInstance().LogInvalidPastedInputOccurred(L"OperandCountGreaterThanMaxCount", mode, programmerNumberBase, bitLengthType); + TraceLogger::GetInstance().LogError(mode, L"CopyPasteManager::ExtractOperands", L"OperandCountGreaterThanMaxCount"); operands.clear(); return operands; } @@ -187,7 +187,7 @@ vector CopyPasteManager::ExtractOperands(const wstring& pasteExpression // to disallow pasting of 1e+12345 as 1e+1234, max exponent that can be pasted is 9999. if (expLength > MaxExponentLength) { - TraceLogger::GetInstance().LogInvalidPastedInputOccurred(L"ExponentLengthGreaterThanMaxLength", mode, programmerNumberBase, bitLengthType); + TraceLogger::GetInstance().LogError(mode, L"CopyPasteManager::ExtractOperands", L"ExponentLengthGreaterThanMaxLength"); operands.clear(); return operands; } diff --git a/src/CalcViewModel/Common/CopyPasteManager.h b/src/CalcViewModel/Common/CopyPasteManager.h index b393dab5..0359e180 100644 --- a/src/CalcViewModel/Common/CopyPasteManager.h +++ b/src/CalcViewModel/Common/CopyPasteManager.h @@ -51,7 +51,7 @@ namespace CalculatorApp int bitLengthType); static std::vector - ExtractOperands(const std::wstring& pasteExpression, CalculatorApp::Common::ViewMode mode, int programmerNumberBase = -1, int bitLengthType = -1); + ExtractOperands(const std::wstring& pasteExpression, CalculatorApp::Common::ViewMode mode); static bool ExpressionRegExMatch( std::vector operands, CalculatorApp::Common::ViewMode mode, diff --git a/src/CalcViewModel/Common/TraceLogger.cpp b/src/CalcViewModel/Common/TraceLogger.cpp index f7d32d99..af698f4c 100644 --- a/src/CalcViewModel/Common/TraceLogger.cpp +++ b/src/CalcViewModel/Common/TraceLogger.cpp @@ -19,94 +19,50 @@ using namespace winrt::Windows::System::UserProfile; namespace CalculatorApp { - static multimap> s_memoryMap; - static constexpr array s_programmerType{ L"N/A", L"QwordType", L"DwordType", L"WordType", L"ByteType", L"HexBase", L"DecBase", L"OctBase", L"BinBase" }; static reader_writer_lock s_traceLoggerLock; - // Telemetry events. Uploaded to asimov. - constexpr auto EVENT_NAME_DEBUG = L"Debug"; - constexpr auto EVENT_NAME_ERROR = L"ErrorMessage"; - constexpr auto EVENT_NAME_APP_PRELAUNCHED_BY_SYSTEM = L"AppPrelaunchedBySystem"; - constexpr auto EVENT_NAME_PRELAUNCHED_APP_ACTIVATED_BY_USER = L"PrelaunchedAppActivatedByUser"; - constexpr auto EVENT_NAME_APP_LAUNCH_BEGIN = L"AppLaunchBegin"; - constexpr auto EVENT_NAME_APP_LAUNCH_END = L"AppLaunchEnd"; - constexpr auto EVENT_NAME_APP_RESUME_END = L"AppResumeEnd"; - constexpr auto EVENT_NAME_PREVIOUS_STATE_WINDOW_ON_CREATION = L"PreviousStateOnWindowCreation"; - constexpr auto EVENT_NAME_SIZE_ON_SUSPENSION = L"CalculatorSizeOnSuspension"; - constexpr auto EVENT_NAME_CALCULATOR_VIEWED_IN_SESSION = L"CalculatorViewedInSession"; - constexpr auto EVENT_NAME_DATE_CALCULATOR_VIEWED_IN_SESSION = L"DateCalculatorViewedInSession"; - constexpr auto EVENT_NAME_CONVERTER_VIEWED_IN_SESSION = L"ConverterViewedInSession"; - constexpr auto EVENT_NAME_MODE_CHANGE_BEGIN = L"ModeChangeBegin"; - constexpr auto EVENT_NAME_MODE_CHANGE_END = L"ModeChangeEnd"; - constexpr auto EVENT_NAME_HISTORY_BODY_OPENED = L"HistoryBodyOpened"; - constexpr auto EVENT_NAME_HISTORY_ITEM_LOAD_BEGIN = L"HistoryItemLoadBegin"; - constexpr auto EVENT_NAME_HISTORY_ITEM_LOAD_END = L"HistoryItemLoadEnd"; - constexpr auto EVENT_NAME_HISTORY_FLYOUT_OPEN_BEGIN = L"HistoryFlyoutOpenBegin"; - constexpr auto EVENT_NAME_HISTORY_FLYOUT_OPEN_END = L"HistoryFlyoutOpenEnd"; - constexpr auto EVENT_NAME_NEW_WINDOW_CREATION_BEGIN = L"NewWindowCreationBegin"; - constexpr auto EVENT_NAME_NEW_WINDOW_CREATION_END = L"NewWindowCreationEnd"; - constexpr auto EVENT_NAME_HISTORY_CLEAR = L"HistoryClearBegin"; - constexpr auto EVENT_NAME_MULTIPLE_MEMORY_USED = L"MultipleMemoryUsed"; - constexpr auto EVENT_NAME_SINGLE_MEMORY_USED = L"SingleMemoryUsed"; - constexpr auto EVENT_NAME_SHARED_MEMORY_USED = L"SharedMemoryUsed"; - constexpr auto EVENT_NAME_MEMORY_BODY_OPENED = L"MemoryBodyOpened"; - constexpr auto EVENT_NAME_MEMORY_FLYOUT_OPEN_BEGIN = L"MemoryFlyoutOpenBegin"; - constexpr auto EVENT_NAME_MEMORY_FLYOUT_OPEN_END = L"MemoryFlyoutOpenEnd"; - constexpr auto EVENT_NAME_MEMORY_CLEAR_ALL = L"MemoryClearAll"; - constexpr auto EVENT_NAME_INVALID_PASTED_INPUT_OCCURRED = L"InvalidPastedInputOccurred"; - constexpr auto EVENT_NAME_VALID_INPUT_PASTED = L"ValidInputPasted"; - constexpr auto EVENT_NAME_BITFLIP_PANE_CLICKED = L"BitFlipPaneClicked"; - constexpr auto EVENT_NAME_BITFLIP_BUTTONS_USED = L"BitFlipToggleButtonUsed"; - constexpr auto EVENT_NAME_ANGLE_BUTTONS_USED = L"AngleButtonUsedInSession"; - constexpr auto EVENT_NAME_HYP_BUTTON_USED = L"HypButtonUsedInSession"; - constexpr auto EVENT_NAME_FUNCTION_USAGE = L"FunctionUsageInSession"; - constexpr auto EVENT_NAME_BITLENGTH_BUTTON_USED = L"BitLengthButtonUsed"; - constexpr auto EVENT_NAME_RADIX_BUTTON_USED = L"RadixButtonUsed"; - constexpr auto EVENT_NAME_MAX_WINDOW_COUNT = L"MaxWindowCountInSession"; - constexpr auto EVENT_NAME_WINDOW_LAUNCHED_PROTOCOL = L"WindowActivatedThroughProtocol"; - constexpr auto EVENT_NAME_WINDOW_LAUNCHED_TILESEARCH = L"WindowLaunchedThroughTile"; - constexpr auto EVENT_NAME_DATE_DIFFERENCE_USED = L"DateDifferenceModeUsed"; - constexpr auto EVENT_NAME_DATE_ADD_SUBTRACT_USED = L"DateAddSubtractModeUsed"; - constexpr auto EVENT_NAME_DATE_DIFFERENCE_FOUND = L"DateDifferenceFound"; - constexpr auto EVENT_NAME_HIDE_IF_SHOWN = L"HideIfShown"; - constexpr auto EVENT_NAME_ABOUT_FLYOUT_OPENED = L"AboutFlyoutOpened"; - constexpr auto EVENT_NAME_NAV_BAR_OPENED = L"NavBarOpened"; - constexpr auto EVENT_NAME_CORE_WINDOW_WAS_NULL = L"CoreWindowWasNull"; + // Diagnostics events. Uploaded to asimov. + constexpr auto EVENT_NAME_WINDOW_ON_CREATED = L"WindowCreated"; + constexpr auto EVENT_NAME_BUTTON_USAGE = L"ButtonUsageInSession"; + constexpr auto EVENT_NAME_NAV_BAR_OPENED = L"NavigationViewOpened"; + constexpr auto EVENT_NAME_MODE_CHANGED = L"ModeChanged"; + constexpr auto EVENT_NAME_DATE_CALCULATION_MODE_USED = L"DateCalculationModeUsed"; + constexpr auto EVENT_NAME_HISTORY_ITEM_LOAD = L"HistoryItemLoad"; + constexpr auto EVENT_NAME_MEMORY_ITEM_LOAD = L"MemoryItemLoad"; + constexpr auto EVENT_NAME_VISUAL_STATE_CHANGED = L"VisualStateChanged"; + constexpr auto EVENT_NAME_CONVERTER_INPUT_RECEIVED = L"ConverterInputReceived"; constexpr auto EVENT_NAME_EXCEPTION = L"Exception"; constexpr auto PDT_PRIVACY_DATA_TAG = L"PartA_PrivTags"; constexpr auto PDT_PRODUCT_AND_SERVICE_USAGE = 0x0000'0000'0200'0000u; -#ifdef SEND_TELEMETRY +#ifdef SEND_DIAGNOSTICS // c.f. WINEVENT_KEYWORD_RESERVED_63-56 0xFF00000000000000 // Bits 63-56 - channel keywords // c.f. WINEVENT_KEYWORD_* 0x00FF000000000000 // Bits 55-48 - system-reserved keywords - constexpr int64_t MICROSOFT_KEYWORD_CRITICAL_DATA = 0x0000800000000000; // Bit 47 - constexpr int64_t MICROSOFT_KEYWORD_MEASURES = 0x0000400000000000; // Bit 46 - constexpr int64_t MICROSOFT_KEYWORD_TELEMETRY = 0x0000200000000000; // Bit 45 - constexpr int64_t MICROSOFT_KEYWORD_RESERVED_44 = 0x0000100000000000; // Bit 44 (reserved for future assignment) + constexpr int64_t MICROSOFT_KEYWORD_LEVEL_1 = 0x0000800000000000; // Bit 47 + constexpr int64_t MICROSOFT_KEYWORD_LEVEL_2 = 0x0000400000000000; // Bit 46 + constexpr int64_t MICROSOFT_KEYWORD_LEVEL_3 = 0x0000200000000000; // Bit 45 #else - // define all Keyword options as 0 when we do not want to upload app telemetry - constexpr int64_t MICROSOFT_KEYWORD_CRITICAL_DATA = 0; - constexpr int64_t MICROSOFT_KEYWORD_MEASURES = 0; - constexpr int64_t MICROSOFT_KEYWORD_TELEMETRY = 0; - constexpr int64_t MICROSOFT_KEYWORD_RESERVED_44 = 0; + // define all Keyword options as 0 when we do not want to upload app diagnostics + constexpr int64_t MICROSOFT_KEYWORD_LEVEL_1 = 0; + constexpr int64_t MICROSOFT_KEYWORD_LEVEL_2 = 0; + constexpr int64_t MICROSOFT_KEYWORD_LEVEL_3 = 0; #endif #pragma region TraceLogger setup and cleanup TraceLogger::TraceLogger() : g_calculatorProvider( - L"MicrosoftCalculator", - LoggingChannelOptions(GUID{ 0x4f50731a, 0x89cf, 0x4782, 0xb3, 0xe0, 0xdc, 0xe8, 0xc9, 0x4, 0x76, 0xba }), // Microsoft Telemetry group - GUID{ 0x905ca09, 0x610e, 0x401e, 0xb6, 0x50, 0x2f, 0x21, 0x29, 0x80, 0xb9, 0xe0 }) + L"MicrosoftCalculator", + LoggingChannelOptions(GUID{ 0x4f50731a, 0x89cf, 0x4782, 0xb3, 0xe0, 0xdc, 0xe8, 0xc9, 0x4, 0x76, 0xba }), + GUID{ 0x905ca09, 0x610e, 0x401e, 0xb6, 0x50, 0x2f, 0x21, 0x29, 0x80, 0xb9, 0xe0 }) , // Unique providerID {0905CA09-610E-401E-B650-2F212980B9E0} m_appLaunchActivity{ nullptr } { - // initialize the function array - InitFunctionLogArray(); + CoCreateGuid(&sessionGuid); } TraceLogger::~TraceLogger() @@ -125,29 +81,19 @@ namespace CalculatorApp } #pragma region Tracing methods - void TraceLogger::LogTelemetryEvent(wstring_view eventName, LoggingFields fields) const + void TraceLogger::LogLevel1Event(wstring_view eventName, LoggingFields fields) const { - g_calculatorProvider.LogEvent(eventName, fields, LoggingLevel::Verbose, LoggingOptions(MICROSOFT_KEYWORD_TELEMETRY)); + g_calculatorProvider.LogEvent(eventName, fields, LoggingLevel::Verbose, LoggingOptions(MICROSOFT_KEYWORD_LEVEL_1)); } - void TraceLogger::LogMeasureEvent(wstring_view eventName, LoggingFields fields) const + void TraceLogger::LogLevel2Event(wstring_view eventName, LoggingFields fields) const { - g_calculatorProvider.LogEvent(eventName, fields, LoggingLevel::Verbose, LoggingOptions(MICROSOFT_KEYWORD_MEASURES)); + g_calculatorProvider.LogEvent(eventName, fields, LoggingLevel::Verbose, LoggingOptions(MICROSOFT_KEYWORD_LEVEL_2)); } - void TraceLogger::LogCriticalDataEvent(wstring_view eventName, LoggingFields fields) const + void TraceLogger::LogLevel3Event(wstring_view eventName, LoggingFields fields) const { - g_calculatorProvider.LogEvent(eventName, fields, LoggingLevel::Verbose, LoggingOptions(MICROSOFT_KEYWORD_CRITICAL_DATA)); - } - - void TraceLogger::LogPerformanceEvent(wstring_view eventName, LoggingFields fields) const - { - g_calculatorProvider.LogEvent(eventName, fields, LoggingLevel::Verbose, LoggingOptions(WINEVENT_KEYWORD_RESPONSE_TIME)); - } - - void TraceLogger::LogInfoEvent(wstring_view eventName, LoggingFields fields) const - { - g_calculatorProvider.LogEvent(eventName, fields, LoggingLevel::Information); + g_calculatorProvider.LogEvent(eventName, fields, LoggingLevel::Verbose, LoggingOptions(MICROSOFT_KEYWORD_LEVEL_3)); } unique_ptr TraceLogger::CreateTraceActivity(wstring_view eventName, LoggingFields fields) const @@ -156,69 +102,10 @@ namespace CalculatorApp } #pragma endregion - void TraceLogger::InsertIntoMemoryMap(int windowId, bool isStandard, bool isScientific, bool isProgrammer) - { - // Writer lock for the static resources - reader_writer_lock::scoped_lock lock(s_traceLoggerLock); - - auto iterMap = s_memoryMap.find(windowId); - if (iterMap == s_memoryMap.end()) - { - s_memoryMap.insert(std::make_pair(windowId, vector())); - iterMap = s_memoryMap.find(windowId); - } - - if (isScientific) - { - iterMap->second.insert(iterMap->second.begin(), L"Scientific"); - } - else if (isProgrammer) - { - iterMap->second.insert(iterMap->second.begin(), L"Programmer"); - } - else if (isStandard) - { - iterMap->second.insert(iterMap->second.begin(), L"Standard"); - } - } - - void TraceLogger::UpdateMemoryMap(int windowId, int memoryPosition, bool isStandard, bool isScientific, bool isProgrammer) - { - // Writer lock for the static resources - reader_writer_lock::scoped_lock lock(s_traceLoggerLock); - - auto iterMap = s_memoryMap.find(windowId); - assert(iterMap != s_memoryMap.end()); - assert(iterMap->second.size() >= (unsigned int)memoryPosition); - - if (isScientific) - { - iterMap->second[memoryPosition] = L"Scientific"; - } - else if (isProgrammer) - { - iterMap->second[memoryPosition] = L"Programmer"; - } - else if (isStandard) - { - iterMap->second[memoryPosition] = L"Standard"; - } - } - - void TraceLogger::DeleteFromMemoryMap(int windowId, int memoryPosition) - { - // Writer lock for the static resources - reader_writer_lock::scoped_lock lock(s_traceLoggerLock); - auto iterMap = s_memoryMap.find(windowId); - assert(iterMap != s_memoryMap.end()); - - iterMap->second.erase(iterMap->second.begin() + memoryPosition); - } - // return true if windowId is logged once else return false bool TraceLogger::UpdateWindowIdLog(int windowId) { - // Writer lock for the static resources + // Writer lock for the windowIdLog resource reader_writer_lock::scoped_lock lock(s_traceLoggerLock); if (windowIdLog.find(windowId) == windowIdLog.end()) @@ -236,170 +123,240 @@ namespace CalculatorApp } } - // call comes here at the time of ApplicationViewModel initialisation - void TraceLogger::LogCalculatorModeViewed(ViewMode mode, int windowId) + void TraceLogger::LogVisualStateChanged(ViewMode mode, wstring_view state) const { - // Writer lock for the static resources - reader_writer_lock::scoped_lock lock(s_traceLoggerLock); - - // store windowId in windowIdLog which says we have logged mode for the present windowId. - if (windowIdLog.find(windowId) == windowIdLog.end()) + if (!GetTraceLoggingProviderEnabled()) { - windowIdLog.insert(pair(windowId, false)); + return; } - // if the event is not logged already for the present mode - if (currentMode != mode) - { - currentMode = mode; + LoggingFields fields{}; + fields.AddGuid(L"SessionGuid", sessionGuid); + fields.AddString(L"CalcMode", NavCategory::GetFriendlyName(mode)->Data()); + fields.AddString(L"VisualState", state); + fields.AddUInt64(PDT_PRIVACY_DATA_TAG, PDT_PRODUCT_AND_SERVICE_USAGE); + LogLevel2Event(EVENT_NAME_VISUAL_STATE_CHANGED, fields); + } + + void TraceLogger::LogWindowCreated(ViewMode mode) const + { + if (!GetTraceLoggingProviderEnabled()) + return; + + LoggingFields fields{}; + fields.AddGuid(L"SessionGuid", sessionGuid); + fields.AddString(L"CalcMode", NavCategory::GetFriendlyName(mode)->Data()); + fields.AddUInt64(L"NumOfOpenWindows", currentWindowCount); + fields.AddUInt64(PDT_PRIVACY_DATA_TAG, PDT_PRODUCT_AND_SERVICE_USAGE); + LogLevel2Event(EVENT_NAME_WINDOW_ON_CREATED, fields); + } + + void TraceLogger::LogModeChange(ViewMode mode) const + { + if (!GetTraceLoggingProviderEnabled()) + return; + + if (NavCategory::IsValidViewMode(mode)) + { LoggingFields fields{}; - fields.AddString(L"CalculatorMode", NavCategory::GetFriendlyName(mode)->Data()); - fields.AddUInt32(L"WindowId", windowId); - LogTelemetryEvent(EVENT_NAME_CALCULATOR_VIEWED_IN_SESSION, fields); + fields.AddGuid(L"SessionGuid", sessionGuid); + fields.AddString(L"CalcMode", NavCategory::GetFriendlyName(mode)->Data()); + fields.AddUInt64(PDT_PRIVACY_DATA_TAG, PDT_PRODUCT_AND_SERVICE_USAGE); + LogLevel2Event(EVENT_NAME_MODE_CHANGED, fields); } } - // call comes here at the time of ApplicationViewModel initialization - void TraceLogger::LogDateCalculatorModeViewed(ViewMode mode, int windowId) + void TraceLogger::LogHistoryItemLoad(ViewMode mode, int historyListSize, int loadedIndex) const { - // Writer lock for the static resources + if (!GetTraceLoggingProviderEnabled()) + { + return; + } + + LoggingFields fields{}; + fields.AddGuid(L"SessionGuid", sessionGuid); + fields.AddString(L"CalcMode", NavCategory::GetFriendlyName(mode)->Data()); + fields.AddInt32(L"HistoryListSize", historyListSize); + fields.AddInt32(L"HistoryItemIndex", loadedIndex); + fields.AddUInt64(PDT_PRIVACY_DATA_TAG, PDT_PRODUCT_AND_SERVICE_USAGE); + LogLevel2Event(EVENT_NAME_HISTORY_ITEM_LOAD, fields); + } + + void TraceLogger::LogMemoryItemLoad(ViewMode mode, int memoryListSize, int loadedIndex) const + { + if (!GetTraceLoggingProviderEnabled()) + { + return; + } + + LoggingFields fields{}; + fields.AddGuid(L"SessionGuid", sessionGuid); + fields.AddString(L"CalcMode", NavCategory::GetFriendlyName(mode)->Data()); + fields.AddInt32(L"MemoryListSize", memoryListSize); + fields.AddInt32(L"MemoryItemIndex", loadedIndex); + fields.AddUInt64(PDT_PRIVACY_DATA_TAG, PDT_PRODUCT_AND_SERVICE_USAGE); + LogLevel2Event(EVENT_NAME_MEMORY_ITEM_LOAD, fields); + } + + void TraceLogger::LogError(ViewMode mode, wstring_view functionName, wstring_view errorString) + { + if (!GetTraceLoggingProviderEnabled()) + return; + + LoggingFields fields{}; + fields.AddGuid(L"SessionGuid", sessionGuid); + fields.AddString(L"CalcMode", NavCategory::GetFriendlyName(mode)->Data()); + fields.AddString(L"FunctionName", functionName); + fields.AddString(L"Message", errorString); + fields.AddUInt64(PDT_PRIVACY_DATA_TAG, PDT_PRODUCT_AND_SERVICE_USAGE); + LogLevel2Event(EVENT_NAME_EXCEPTION, fields); + } + + void TraceLogger::LogStandardException(ViewMode mode, wstring_view functionName, const exception& e) const + { + if (!GetTraceLoggingProviderEnabled()) + return; + + LoggingFields fields{}; + fields.AddGuid(L"SessionGuid", sessionGuid); + fields.AddString(L"CalcMode", NavCategory::GetFriendlyName(mode)->Data()); + fields.AddString(L"FunctionName", functionName); + wstringstream exceptionMessage; + exceptionMessage << e.what(); + fields.AddString(L"Message", exceptionMessage.str()); + fields.AddUInt64(PDT_PRIVACY_DATA_TAG, PDT_PRODUCT_AND_SERVICE_USAGE); + LogLevel2Event(EVENT_NAME_EXCEPTION, fields); + } + + void TraceLogger::LogWinRTException(ViewMode mode, wstring_view functionName, hresult_error const& e) const + { + if (!GetTraceLoggingProviderEnabled()) + return; + + LoggingFields fields{}; + fields.AddGuid(L"SessionGuid", sessionGuid); + fields.AddString(L"CalcMode", NavCategory::GetFriendlyName(mode)->Data()); + fields.AddString(L"FunctionName", functionName); + fields.AddString(L"Message", e.message()); + fields.AddInt32(L"HRESULT", e.code()); + fields.AddUInt64(PDT_PRIVACY_DATA_TAG, PDT_PRODUCT_AND_SERVICE_USAGE); + LogLevel2Event(EVENT_NAME_EXCEPTION, fields); + } + + void TraceLogger::LogPlatformException(ViewMode mode, wstring_view functionName, Platform::Exception ^ e) const + { + if (!GetTraceLoggingProviderEnabled()) + return; + + LoggingFields fields{}; + fields.AddGuid(L"SessionGuid", sessionGuid); + fields.AddString(L"CalcMode", NavCategory::GetFriendlyName(mode)->Data()); + fields.AddString(L"FunctionName", functionName); + fields.AddString(L"Message", e->Message->Data()); + fields.AddInt32(L"HRESULT", e->HResult); + fields.AddUInt64(PDT_PRIVACY_DATA_TAG, PDT_PRODUCT_AND_SERVICE_USAGE); + LogLevel2Event(EVENT_NAME_EXCEPTION, fields); + } + + void TraceLogger::UpdateButtonUsage(NumbersAndOperatorsEnum button, ViewMode mode) + { + // IsProgrammerMode, IsScientificMode, IsStandardMode and None are not actual buttons, so ignore them + if (button == NumbersAndOperatorsEnum::IsProgrammerMode || button == NumbersAndOperatorsEnum::IsScientificMode + || button == NumbersAndOperatorsEnum::IsStandardMode || button == NumbersAndOperatorsEnum::None) + { + return; + } + + { + // Writer lock for the buttonLog resource + reader_writer_lock::scoped_lock lock(s_traceLoggerLock); + + vector::iterator it = std::find_if( + buttonLog.begin(), buttonLog.end(), [button, mode](const ButtonLog& bLog) -> bool { return bLog.button == button && bLog.mode == mode; }); + if (it != buttonLog.end()) + { + it->count++; + } + else + { + buttonLog.push_back(ButtonLog(button, mode)); + } + } + + // Periodically log the button usage so that we do not lose all button data if the app is foricibly closed or crashes + if (buttonLog.size() >= 10) + { + LogButtonUsage(); + } + } + + void TraceLogger::UpdateWindowCount(size_t windowCount) + { + if (windowCount == 0) + { + currentWindowCount--; + return; + } + currentWindowCount = windowCount; + } + + void TraceLogger::LogButtonUsage() + { + if (!GetTraceLoggingProviderEnabled()) + return; + + // Writer lock for the buttonLog resource reader_writer_lock::scoped_lock lock(s_traceLoggerLock); - // store windowId in windowIdLog which says we have logged mode for the present windowId. - if (windowIdLog.find(windowId) == windowIdLog.end()) + if (buttonLog.size() == 0) { - windowIdLog.insert(pair(windowId, false)); + return; } - // if the event is not logged already for the present mode - if (currentMode != mode) - { - currentMode = mode; - LoggingFields fields{}; - fields.AddString(L"DateCalculatorMode", NavCategory::GetFriendlyName(mode)->Data()); - fields.AddUInt32(L"WindowId", windowId); - LogTelemetryEvent(EVENT_NAME_DATE_CALCULATOR_VIEWED_IN_SESSION, fields); + Platform::String ^ buttonUsageString; + for (int i = 0; i < buttonLog.size(); i++) + { + buttonUsageString += NavCategory::GetFriendlyName(buttonLog[i].mode); + buttonUsageString += "|"; + buttonUsageString += buttonLog[i].button.ToString(); + buttonUsageString += "|"; + buttonUsageString += buttonLog[i].count; + if (i != buttonLog.size() - 1) + { + buttonUsageString += ","; + } } + + LoggingFields fields{}; + fields.AddGuid(L"SessionGuid", sessionGuid); + fields.AddString(L"ButtonUsage", buttonUsageString->Data()); + fields.AddUInt64(PDT_PRIVACY_DATA_TAG, PDT_PRODUCT_AND_SERVICE_USAGE); + LogLevel2Event(EVENT_NAME_BUTTON_USAGE, fields); + + buttonLog.clear(); } - // call comes here at the time of ApplicationViewModel initialization - void TraceLogger::LogConverterModeViewed(ViewMode mode, int windowId) + void TraceLogger::LogDateCalculationModeUsed(bool AddSubtractMode) { - // Writer lock for the static resources - reader_writer_lock::scoped_lock lock(s_traceLoggerLock); - - if (windowIdLog.find(windowId) == windowIdLog.end()) - { - windowIdLog.insert(pair(windowId, false)); - } - // if the event is not logged already for the present mode - if (currentMode != mode) - { - currentMode = mode; - - LoggingFields fields{}; - fields.AddString(L"ConverterMode", NavCategory::GetFriendlyName(mode)->Data()); - fields.AddUInt32(L"WindowId", windowId); - LogTelemetryEvent(EVENT_NAME_CONVERTER_VIEWED_IN_SESSION, fields); - } + const wchar_t* calculationType = AddSubtractMode ? L"AddSubtractMode" : L"DateDifferenceMode"; + LoggingFields fields{}; + fields.AddGuid(L"SessionGuid", sessionGuid); + fields.AddString(L"CalcMode", NavCategory::GetFriendlyName(ViewMode::Date)->Data()); + fields.AddString(L"CalculationType", calculationType); + fields.AddUInt64(PDT_PRIVACY_DATA_TAG, PDT_PRODUCT_AND_SERVICE_USAGE); + LogLevel2Event(EVENT_NAME_DATE_CALCULATION_MODE_USED, fields); } - void TraceLogger::LogSharedMemoryUsed(wstring_view fromMode, wstring_view toMode, unsigned int memorySize) const + void TraceLogger::LogConverterInputReceived(ViewMode mode) const { if (!GetTraceLoggingProviderEnabled()) return; LoggingFields fields{}; - fields.AddString(L"FromMode", fromMode); - fields.AddString(L"ToMode", toMode); - fields.AddUInt32(L"MemoryListSize", memorySize); - LogTelemetryEvent(EVENT_NAME_SHARED_MEMORY_USED, fields); - } - - void TraceLogger::LogBitFlipPaneClicked() const - { - if (!GetTraceLoggingProviderEnabled()) - return; - - LoggingFields fields{}; - LogTelemetryEvent(EVENT_NAME_BITFLIP_PANE_CLICKED, fields); - } - - void TraceLogger::LogBitFlipUsed() const - { - if (!GetTraceLoggingProviderEnabled()) - return; - - LoggingFields fields{}; - LogTelemetryEvent(EVENT_NAME_BITFLIP_BUTTONS_USED, fields); - } - - void TraceLogger::LogAppLaunchStart() - { - // Writer lock for the static resources - reader_writer_lock::scoped_lock lock(s_traceLoggerLock); - - if (!isAppLaunchBeginLogged) - { - m_appLaunchActivity = - g_calculatorProvider.StartActivity(EVENT_NAME_APP_LAUNCH_BEGIN, nullptr, LoggingLevel::Verbose, LoggingOptions(MICROSOFT_KEYWORD_TELEMETRY)); - - isAppLaunchBeginLogged = true; - } - } - - void TraceLogger::LogAppLaunchComplete(/*Windows::ApplicationModel::Activation::ActivationKind activationKind, Windows::ApplicationModel::Activation::ApplicationExecutionState executionState*/) - { - // Writer lock for the static resources - reader_writer_lock::scoped_lock lock(s_traceLoggerLock); - - if ((m_appLaunchActivity != nullptr) && (!isAppLaunchEndLogged)) - { - m_appLaunchActivity.StopActivity(EVENT_NAME_APP_LAUNCH_END); - - isAppLaunchEndLogged = true; - } - - m_appLaunchActivity = nullptr; - } - - void TraceLogger::LogAppResumeComplete() - { - if (m_appLaunchActivity != nullptr) - { - m_appLaunchActivity.StopActivity(EVENT_NAME_APP_RESUME_END); - } - - m_appLaunchActivity = nullptr; - } - - void TraceLogger::LogDebug(wstring_view debugData) - { - if (!GetTraceLoggingProviderEnabled()) - return; - - LoggingFields fields{}; - fields.AddString(L"DebugData", debugData); - LogTelemetryEvent(EVENT_NAME_DEBUG, fields); - } - - void TraceLogger::LogOnAppLaunch(wstring_view previousExecutionState) const - { - if (!GetTraceLoggingProviderEnabled()) - return; - - LoggingFields fields{}; - fields.AddString(L"PreviousExecutionState", previousExecutionState); - LogTelemetryEvent(EVENT_NAME_PREVIOUS_STATE_WINDOW_ON_CREATION, fields); - } - - void TraceLogger::LogAboutFlyoutOpened() const - { - if (!GetTraceLoggingProviderEnabled()) - return; - - LoggingFields fields{}; - LogTelemetryEvent(EVENT_NAME_ABOUT_FLYOUT_OPENED, fields); + fields.AddGuid(L"SessionGuid", sessionGuid); + fields.AddString(L"CalcMode", NavCategory::GetFriendlyName(mode)->Data()); + fields.AddUInt64(PDT_PRIVACY_DATA_TAG, PDT_PRODUCT_AND_SERVICE_USAGE); + LogLevel2Event(EVENT_NAME_CONVERTER_INPUT_RECEIVED, fields); } void TraceLogger::LogNavBarOpened() const @@ -408,610 +365,8 @@ namespace CalculatorApp return; LoggingFields fields{}; - LogTelemetryEvent(EVENT_NAME_NAV_BAR_OPENED, fields); - } - - void TraceLogger::LogClearHistory() const - { - if (!GetTraceLoggingProviderEnabled()) - return; - - LoggingFields fields{}; - LogTelemetryEvent(EVENT_NAME_HISTORY_CLEAR, fields); - } - - void TraceLogger::LogHistoryFlyoutOpenBegin(unsigned int historyItemCount) const - { - if (!GetTraceLoggingProviderEnabled()) - return; - - // we want to record the event only when history item count is atleast 20 - if (historyItemCount >= 20) - { - LoggingFields fields{}; - fields.AddUInt32(L"HistoryItemCount", historyItemCount); - LogTelemetryEvent(EVENT_NAME_HISTORY_FLYOUT_OPEN_BEGIN, fields); - } - } - - void TraceLogger::LogHistoryFlyoutOpenEnd(int historyItemCount) const - { - if (!GetTraceLoggingProviderEnabled()) - return; - - if (historyItemCount >= 20) - { - LoggingFields fields{}; - fields.AddUInt32(L"HistoryItemCount", historyItemCount); - LogTelemetryEvent(EVENT_NAME_HISTORY_FLYOUT_OPEN_END, fields); - } - } - - void TraceLogger::LogHistoryBodyOpened() const - { - if (!GetTraceLoggingProviderEnabled()) - return; - - LoggingFields fields{}; - LogTelemetryEvent(EVENT_NAME_HISTORY_BODY_OPENED, fields); - } - - void TraceLogger::LogMemoryFlyoutOpenBegin(unsigned int memoryItemCount) const - { - if (!GetTraceLoggingProviderEnabled()) - return; - - // we want to record the event only when memory item count is atleast 4 - if (memoryItemCount >= 4) - { - LoggingFields fields{}; - fields.AddUInt32(L"MemoryItemCount", memoryItemCount); - LogTelemetryEvent(EVENT_NAME_MEMORY_FLYOUT_OPEN_BEGIN, fields); - } - } - - void TraceLogger::LogMemoryFlyoutOpenEnd(unsigned int memoryItemCount) const - { - if (!GetTraceLoggingProviderEnabled()) - return; - - if (memoryItemCount >= 4) - { - LoggingFields fields{}; - fields.AddUInt32(L"MemoryItemCount", memoryItemCount); - LogTelemetryEvent(EVENT_NAME_MEMORY_FLYOUT_OPEN_END, fields); - } - } - - void TraceLogger::LogMemoryBodyOpened() const - { - if (!GetTraceLoggingProviderEnabled()) - return; - - LoggingFields fields{}; - LogTelemetryEvent(EVENT_NAME_MEMORY_BODY_OPENED, fields); - } - - // If calculator is launched in any mode other than standard then this call will come which is not intended. But there is no way to avoid it. - // So don't use this function to analyze the count of mode change in session instead use CalculatorViewedInSession and ConverterViewedInSession to do that. - // Use of this function is to analyze perf of mode change. - void TraceLogger::LogModeChangeBegin(ViewMode fromMode, ViewMode toMode, int windowId) - { - if (!GetTraceLoggingProviderEnabled()) - return; - - if (NavCategory::IsValidViewMode(fromMode) && NavCategory::IsValidViewMode(toMode)) - { - LoggingFields fields{}; - fields.AddString(L"FromMode", NavCategory::GetFriendlyName(fromMode)->Data()); - fields.AddString(L"ToMode", NavCategory::GetFriendlyName(toMode)->Data()); - fields.AddInt32(L"WindowId", windowId); - LogMeasureEvent(EVENT_NAME_MODE_CHANGE_BEGIN, fields); - } - } - - // comment: same as LogModeChangeBegin - void TraceLogger::LogModeChangeEnd(ViewMode toMode, int windowId) const - { - if (!GetTraceLoggingProviderEnabled()) - return; - - if (NavCategory::IsValidViewMode(toMode)) - { - LoggingFields fields{}; - fields.AddString(L"ToMode", NavCategory::GetFriendlyName(toMode)->Data()); - fields.AddInt32(L"WindowId", windowId); - LogMeasureEvent(EVENT_NAME_MODE_CHANGE_END, fields); - } - } - - void TraceLogger::LogHistoryItemLoadBegin() const - { - if (!GetTraceLoggingProviderEnabled()) - return; - - LoggingFields fields{}; - LogTelemetryEvent(EVENT_NAME_HISTORY_ITEM_LOAD_BEGIN, fields); - } - - void TraceLogger::LogHistoryItemLoadEnd(unsigned int historyTokenCount) const - { - if (!GetTraceLoggingProviderEnabled()) - return; - - LoggingFields fields{}; - fields.AddUInt32(L"HistoryTokenCount", historyTokenCount); - LogTelemetryEvent(EVENT_NAME_HISTORY_ITEM_LOAD_END, fields); - } - - void TraceLogger::LogNewWindowCreationBegin(int windowId) - { - if (!GetTraceLoggingProviderEnabled()) - return; - - LoggingFields fields{}; - fields.AddUInt32(L"WindowId", windowId); - LogTelemetryEvent(EVENT_NAME_NEW_WINDOW_CREATION_BEGIN, fields); - } - - void TraceLogger::LogNewWindowCreationEnd(int windowId) - { - if (!GetTraceLoggingProviderEnabled()) - return; - - LoggingFields fields{}; - fields.AddUInt32(L"WindowId", windowId); - LogTelemetryEvent(EVENT_NAME_NEW_WINDOW_CREATION_END, fields); - } - - void TraceLogger::LogError(wstring_view errorString) - { - if (!GetTraceLoggingProviderEnabled()) - return; - - LoggingFields fields{}; - fields.AddString(L"ErrorString", errorString); - LogTelemetryEvent(EVENT_NAME_ERROR, fields); - } - - void TraceLogger::LogPrelaunchedAppActivatedByUser() - { - if (!GetTraceLoggingProviderEnabled()) - return; - - LoggingFields fields{}; - LogTelemetryEvent(EVENT_NAME_PRELAUNCHED_APP_ACTIVATED_BY_USER, fields); - } - - void TraceLogger::LogAppPrelaunchedBySystem() - { - if (!GetTraceLoggingProviderEnabled()) - return; - - LoggingFields fields{}; - LogTelemetryEvent(EVENT_NAME_APP_PRELAUNCHED_BY_SYSTEM, fields); - } - - void TraceLogger::LogMemoryClearAll(int windowId) - { - // Writer lock for the static resources - reader_writer_lock::scoped_lock lock(s_traceLoggerLock); - auto iterMap = s_memoryMap.find(windowId); - - LoggingFields fields{}; - LogTelemetryEvent(EVENT_NAME_MEMORY_CLEAR_ALL, fields); - - if (iterMap != s_memoryMap.end()) - { - iterMap->second.clear(); - } - } - - void - TraceLogger::LogMemoryUsed(int windowId, unsigned int slotPosition, bool isStandard, bool isScientific, bool isProgrammer, unsigned int memorySize) const - { - if (!GetTraceLoggingProviderEnabled()) - return; - - // Reader lock for the static resources - reader_writer_lock::scoped_lock_read lock(s_traceLoggerLock); - auto iterMap = s_memoryMap.find(windowId); - - if (slotPosition == 0) - { - LogSingleMemoryUsed(memorySize); - } - else - { - LogMultipleMemoryUsed(slotPosition, memorySize); - } - - if (iterMap != s_memoryMap.end()) - { - // if current mode is not equal to mode of memoryMap[slotPosition] then LogSharedMemoryUsed - if (isStandard && (iterMap->second[slotPosition] != L"Standard")) - { - LogSharedMemoryUsed(iterMap->second[slotPosition], L"Standard", memorySize); - } - else if (isScientific && (iterMap->second[slotPosition] != L"Scientific")) - { - LogSharedMemoryUsed(iterMap->second[slotPosition], L"Scientific", memorySize); - } - else if (isProgrammer && (iterMap->second[slotPosition] != L"Programmer")) - { - LogSharedMemoryUsed(iterMap->second[slotPosition], L"Programmer", memorySize); - } - } - } - - void TraceLogger::LogMultipleMemoryUsed(unsigned int slotPosition, unsigned int memorySize) const - { - if (!GetTraceLoggingProviderEnabled()) - return; - - LoggingFields fields{}; - fields.AddUInt32(L"MemoryIndex", slotPosition); - fields.AddUInt32(L"MemoryListSize", memorySize); - LogTelemetryEvent(EVENT_NAME_MULTIPLE_MEMORY_USED, fields); - } - - void TraceLogger::LogSingleMemoryUsed(unsigned int memorySize) const - { - if (!GetTraceLoggingProviderEnabled()) - return; - - LoggingFields fields{}; - fields.AddUInt32(L"MemoryListSize", memorySize); - LogTelemetryEvent(EVENT_NAME_SINGLE_MEMORY_USED, fields); - } - - void TraceLogger::LogInvalidPastedInputOccurred(wstring_view reason, ViewMode mode, int programmerNumberBase, int bitLengthType) - { - if (!GetTraceLoggingProviderEnabled()) - return; - - LoggingFields fields{}; - fields.AddString(L"Mode", NavCategory::GetFriendlyName(mode)->Data()); - fields.AddString(L"Reason", reason); - fields.AddString(L"ProgrammerNumberBase", GetProgrammerType(programmerNumberBase).c_str()); - fields.AddString(L"BitLengthType", GetProgrammerType(bitLengthType).c_str()); + fields.AddGuid(L"SessionGuid", sessionGuid); fields.AddUInt64(PDT_PRIVACY_DATA_TAG, PDT_PRODUCT_AND_SERVICE_USAGE); - LogTelemetryEvent(EVENT_NAME_INVALID_PASTED_INPUT_OCCURRED, fields); - } - - void TraceLogger::LogValidInputPasted(ViewMode mode) const - { - if (!GetTraceLoggingProviderEnabled()) - return; - - LoggingFields fields{}; - fields.AddString(L"Mode", NavCategory::GetFriendlyName(mode)->Data()); - LogTelemetryEvent(EVENT_NAME_VALID_INPUT_PASTED, fields); - } - - void TraceLogger::LogStandardException(wstring_view functionName, const exception& e) const - { - if (!GetTraceLoggingProviderEnabled()) - return; - - LoggingFields fields{}; - fields.AddString(L"FunctionName", functionName); - wstringstream exceptionMessage; - exceptionMessage << e.what(); - fields.AddString(L"ExceptionMessage", exceptionMessage.str()); - LogMeasureEvent(EVENT_NAME_EXCEPTION, fields); - } - - void TraceLogger::LogWinRTException(wstring_view functionName, hresult_error const& e) const - { - if (!GetTraceLoggingProviderEnabled()) - return; - - LoggingFields fields{}; - fields.AddString(L"FunctionName", functionName); - fields.AddInt32(L"HRESULT", e.code()); - fields.AddString(L"ExceptionMessage", e.message()); - LogMeasureEvent(EVENT_NAME_EXCEPTION, fields); - } - - void TraceLogger::LogPlatformException(wstring_view functionName, Platform::Exception ^ e) const - { - if (!GetTraceLoggingProviderEnabled()) - return; - - LoggingFields fields{}; - fields.AddString(L"FunctionName", functionName); - fields.AddInt32(L"HRESULT", e->HResult); - fields.AddString(L"ExceptionMessage", e->Message->Data()); - LogMeasureEvent(EVENT_NAME_EXCEPTION, fields); - } - - void TraceLogger::UpdateFunctionUsage(int funcIndex) - { - // Writer lock for the static resources - reader_writer_lock::scoped_lock lock(s_traceLoggerLock); - - if (GetIndex(funcIndex)) - { - // funcIndex is passed by reference and will be having the returned index - funcLog[funcIndex].count++; - } - } - - void TraceLogger::InitFunctionLogArray() - { - int i = -1; - for (int funcIndex = 0; funcIndex != maxFunctionSize; funcIndex++) - { - FunctionLogEnum func = safe_cast(funcIndex); - wstring functionName = func.ToString()->Data(); - if (functionName.compare(L"CalculatorApp.FunctionLogEnum") != 0) - { - findIndex[funcIndex] = ++i; - funcLog.push_back(FuncLog(functionName)); - } - } - // update the functionCount with total function count which we are tracking through tracelog. - functionCount = i; - } - - wstring TraceLogger::GetProgrammerType(int index) - { - if (index >= 0) - { - return s_programmerType[index]; - } - // return "N/A" - return s_programmerType[0]; - } - - bool TraceLogger::GetIndex(int& index) - { - if (findIndex[index] > 0) - { - index = findIndex[index]; - return true; - } - return false; - } - - void TraceLogger::UpdateWindowCount(size_t windowCount) - { - maxWindowCount = (maxWindowCount > windowCount) ? maxWindowCount : windowCount; - windowLaunchCount++; - } - - void TraceLogger::LogMaxWindowCount() - { - if (!GetTraceLoggingProviderEnabled()) - return; - - LoggingFields fields{}; - fields.AddUInt32(L"WindowCount", (unsigned int)maxWindowCount); - LogTelemetryEvent(EVENT_NAME_MAX_WINDOW_COUNT, fields); - } - - void TraceLogger::LogWindowActivated() const - { - if (!GetTraceLoggingProviderEnabled()) - return; - - LoggingFields fields{}; - LogTelemetryEvent(EVENT_NAME_WINDOW_LAUNCHED_PROTOCOL, fields); - } - - void TraceLogger::LogWindowLaunched() const - { - if (!GetTraceLoggingProviderEnabled()) - return; - - LoggingFields fields{}; - LogTelemetryEvent(EVENT_NAME_WINDOW_LAUNCHED_TILESEARCH, fields); - } - - void TraceLogger::LogBitLengthButtonUsed(int windowId) - { - if (bitLengthButtonUsage.find(windowId) == bitLengthButtonUsage.end()) - { - bitLengthButtonUsage.insert(pair(windowId, 1)); - } - else - { - bitLengthButtonUsage[windowId]++; - } - if ((bitLengthButtonUsage[windowId] == 5) && !bitLengthButtonLoggedInSession) - { - LoggingFields fields{}; - fields.AddUInt32(L"WindowId", windowId); - LogTelemetryEvent(EVENT_NAME_BITLENGTH_BUTTON_USED, fields); - - bitLengthButtonLoggedInSession = true; - } - } - - void TraceLogger::LogRadixButtonUsed(int windowId) - { - if (radixButtonUsage.find(windowId) == radixButtonUsage.end()) - { - radixButtonUsage.insert(pair(windowId, 1)); - } - else - { - radixButtonUsage[windowId]++; - } - if ((radixButtonUsage[windowId] == 2) && !radixButtonLoggedInSession) - { - LoggingFields fields{}; - fields.AddUInt32(L"WindowId", windowId); - LogTelemetryEvent(EVENT_NAME_RADIX_BUTTON_USED, fields); - - radixButtonLoggedInSession = true; - } - } - - void TraceLogger::LogAngleButtonUsed(int windowId) - { - if (angleButtonUsage.find(windowId) == angleButtonUsage.end()) - { - angleButtonUsage.insert(pair(windowId, 1)); - } - else - { - angleButtonUsage[windowId]++; - } - if ((angleButtonUsage[windowId] == 2) && !angleButtonLoggedInSession) - { - LoggingFields fields{}; - fields.AddUInt32(L"WindowId", windowId); - LogTelemetryEvent(EVENT_NAME_ANGLE_BUTTONS_USED, fields); - - angleButtonLoggedInSession = true; - } - } - - void TraceLogger::LogFunctionUsage(int windowId) - { - if (!GetTraceLoggingProviderEnabled()) - return; - - for (int i = 0; i < functionCount; i++) - { - // log only those functions which are used - if (funcLog[i].count > 0) - { - LoggingFields fields{}; - fields.AddString(L"FunctionName", funcLog[i].funcName.data()); - fields.AddUInt32(L"UsageCount", funcLog[i].count); - fields.AddUInt32(L"WindowId", windowId); - LogTelemetryEvent(EVENT_NAME_FUNCTION_USAGE, fields); - } - } - } - - void TraceLogger::LogHypButtonUsed(int windowId) - { - if (!isHypButtonLogged) - { - LoggingFields fields{}; - fields.AddUInt32(L"WindowId", windowId); - LogTelemetryEvent(EVENT_NAME_HYP_BUTTON_USED, fields); - - isHypButtonLogged = true; - } - } - - void TraceLogger::LogDateDifferenceModeUsed(int windowId) - { - if (!m_dateDiffUsageLoggedInSession) - { - LoggingFields fields{}; - fields.AddUInt32(L"WindowId", windowId); - LogTelemetryEvent(EVENT_NAME_DATE_DIFFERENCE_USED, fields); - - m_dateDiffUsageLoggedInSession = true; - } - } - - void TraceLogger::LogDateAddSubtractModeUsed(int windowId, bool isAddMode) - { - auto usageMap = isAddMode ? &m_dateAddModeUsage : &m_dateSubtractModeUsage; - auto isLoggedInSession = isAddMode ? &m_dateAddUsageLoggedInSession : &m_dateSubtractUsageLoggedInSession; - - if (usageMap->find(windowId) == usageMap->end()) - { - usageMap->insert(pair(windowId, 1)); - } - else - { - (*usageMap)[windowId]++; - } - - // Ignore first 3 calls during the initialization of the combo box selected items for Add mode - int firstChangeEventCount = isAddMode ? 4 : 1; - - if (((*usageMap)[windowId] == firstChangeEventCount) && (!(*isLoggedInSession))) - { - LoggingFields fields{}; - fields.AddString(L"AddSubtractMode", isAddMode ? L"Add" : L"Subtract"); - LogTelemetryEvent(EVENT_NAME_DATE_ADD_SUBTRACT_USED, fields); - - *isLoggedInSession = true; - } - } - - void TraceLogger::LogDateClippedTimeDifferenceFound(Calendar const& today, DateTime const& clippedTime) const - { - if (!GetTraceLoggingProviderEnabled()) - return; - - auto calendarSystem = today.GetCalendarSystem(); - auto clock = today.GetClock(); - DateTimeFormatter dtFormatter{ L"longdate shorttime", { L"en-US" }, GlobalizationPreferences::HomeGeographicRegion(), calendarSystem, clock }; - - LoggingFields fields{}; - fields.AddString(L"ResolvedCalendarLanguage", today.ResolvedLanguage()); - fields.AddString(L"Timezone", today.GetTimeZone()); - fields.AddString(L"CalendarSystem", calendarSystem); - fields.AddString(L"Clock", clock); - fields.AddBoolean(L"IsDaylightSavingTime", today.IsDaylightSavingTime()); - fields.AddString(L"TodayDate", dtFormatter.Format(today.GetDateTime())); - fields.AddString(L"ClippedDate", dtFormatter.Format(clippedTime)); - LogTelemetryEvent(EVENT_NAME_DATE_DIFFERENCE_FOUND, fields); - } - - void TraceLogger::LogUserRequestedRefreshFailed() const - { - if (!GetTraceLoggingProviderEnabled()) - return; - - LoggingFields fields{}; - LogTelemetryEvent(L"UserRequestedRefreshFailed", fields); - } - - void TraceLogger::LogConversionResult(wstring_view fromValue, wstring_view fromUnit, wstring_view toValue, wstring_view toUnit) const - { - if (!GetTraceLoggingProviderEnabled()) - return; - - wstring behaviorString{}; - NetworkAccessBehavior behavior = NetworkManager::GetNetworkAccessBehavior(); - switch (behavior) - { - case NetworkAccessBehavior::Offline: - behaviorString = L"Offline"; - break; - - case NetworkAccessBehavior::OptIn: - behaviorString = L"Metered"; - break; - - case NetworkAccessBehavior::Normal: - default: - behaviorString = L"Online"; - break; - } - - LoggingFields fields{}; - fields.AddString(L"NetworkAccess", behaviorString); - fields.AddString(L"FromValue", fromValue); - fields.AddString(L"FromUnit", fromUnit); - fields.AddString(L"ToValue", toValue); - fields.AddString(L"ToUnit", toUnit); - LogTelemetryEvent(L"CurrencyConverterInputReceived", fields); - } - - void TraceLogger::LogViewClosingTelemetry(int windowId) - { - LogFunctionUsage(windowId); - LogMaxWindowCount(); - } - - void TraceLogger::LogCoreWindowWasNull() const - { - if (!GetTraceLoggingProviderEnabled()) - return; - - LoggingFields fields{}; - LogTelemetryEvent(EVENT_NAME_CORE_WINDOW_WAS_NULL, fields); + LogLevel2Event(EVENT_NAME_NAV_BAR_OPENED, fields); } } diff --git a/src/CalcViewModel/Common/TraceLogger.h b/src/CalcViewModel/Common/TraceLogger.h index 870cddf8..875a1255 100644 --- a/src/CalcViewModel/Common/TraceLogger.h +++ b/src/CalcViewModel/Common/TraceLogger.h @@ -6,6 +6,7 @@ #include "CalcManager/Command.h" #include "TraceActivity.h" #include "NavCategory.h" +#include "CalculatorButtonUser.h" static const int maxFunctionSize = (int)CalculationManager::Command::CommandBINEDITEND; @@ -13,19 +14,17 @@ static const int maxFunctionSize = (int)CalculationManager::Command::CommandBINE // This class implements a singleton model ensure that only one instance is created. namespace CalculatorApp { - struct FuncLog + struct ButtonLog { public: int count; - std::wstring funcName; - FuncLog() + CalculatorApp::NumbersAndOperatorsEnum button; + CalculatorApp::Common::ViewMode mode; + ButtonLog(CalculatorApp::NumbersAndOperatorsEnum btn, CalculatorApp::Common::ViewMode vMode) { - count = 0; - } - FuncLog(std::wstring fName) - { - funcName = fName; - count = 0; + button = btn; + mode = vMode; + count = 1; } }; @@ -38,123 +37,45 @@ namespace CalculatorApp static TraceLogger& GetInstance(); bool GetTraceLoggingProviderEnabled() const; - void LogAppLaunchStart(); - void LogAppLaunchComplete(); - void LogAppResumeComplete(); - void LogOnAppLaunch(std::wstring_view previousExecutionState) const; - void LogMemoryClearAll(int); - void LogBitFlipPaneClicked() const; - void LogBitFlipUsed() const; - void LogHistoryBodyOpened() const; - void LogHistoryItemLoadBegin() const; - void LogHistoryItemLoadEnd(unsigned int) const; - void LogHistoryFlyoutOpenBegin(unsigned int) const; - void LogHistoryFlyoutOpenEnd(int) const; - void LogCalculatorModeViewed(CalculatorApp::Common::ViewMode, int); - void LogDateCalculatorModeViewed(CalculatorApp::Common::ViewMode, int); - void LogConverterModeViewed(CalculatorApp::Common::ViewMode, int); - void LogModeChangeBegin(CalculatorApp::Common::ViewMode, CalculatorApp::Common::ViewMode, int); - void LogModeChangeEnd(CalculatorApp::Common::ViewMode, int) const; - void LogClearHistory() const; - void InsertIntoMemoryMap(int, bool, bool, bool); - void UpdateMemoryMap(int, int, bool, bool, bool); - void DeleteFromMemoryMap(int, int); - void LogMemoryUsed(int, unsigned int, bool, bool, bool, unsigned int) const; - void LogMultipleMemoryUsed(unsigned int, unsigned int) const; - void LogSingleMemoryUsed(unsigned int) const; - void LogSharedMemoryUsed(std::wstring_view, std::wstring_view, unsigned int) const; - void LogMemoryBodyOpened() const; - void LogMemoryFlyoutOpenBegin(unsigned int) const; - void LogDebug(std::wstring_view debugData); - void LogMemoryFlyoutOpenEnd(unsigned int) const; - void LogInvalidPastedInputOccurred(std::wstring_view reason, CalculatorApp::Common::ViewMode mode, int ProgrammerNumberBase, int bitLengthType); - void LogValidInputPasted(CalculatorApp::Common::ViewMode mode) const; - void UpdateFunctionUsage(int func); - void LogFunctionUsage(int); - void InitFunctionLogArray(); - void LogBitLengthButtonUsed(int windowId); - void LogRadixButtonUsed(int windowId); - void LogAngleButtonUsed(int windowId); - void LogHypButtonUsed(int windowId); - void LogNewWindowCreationBegin(int windowId); - void LogNewWindowCreationEnd(int windowId); - void LogError(std::wstring_view errorString); - void LogPrelaunchedAppActivatedByUser(); - void LogAppPrelaunchedBySystem(); - void UpdateWindowCount(size_t windowCount); + void LogModeChange(CalculatorApp::Common::ViewMode mode) const; + void LogHistoryItemLoad(CalculatorApp::Common::ViewMode mode, int historyListSize, int loadedIndex) const; + void LogMemoryItemLoad(CalculatorApp::Common::ViewMode mode, int memoryListSize, int loadedIndex) const; + void UpdateButtonUsage(CalculatorApp::NumbersAndOperatorsEnum button, CalculatorApp::Common::ViewMode mode); + void LogButtonUsage(); + void LogDateCalculationModeUsed(bool AddSubtractMode); + void UpdateWindowCount(size_t windowCount = 0); bool UpdateWindowIdLog(int windowId); - void LogMaxWindowCount(); - void LogWindowActivated() const; - void LogWindowLaunched() const; - void LogUserRequestedRefreshFailed() const; - void LogConversionResult(std::wstring_view fromValue, std::wstring_view fromUnit, std::wstring_view toValue, std::wstring_view toUnit) const; - void LogAboutFlyoutOpened() const; + void LogVisualStateChanged(CalculatorApp::Common::ViewMode mode, std::wstring_view state) const; + void LogWindowCreated(CalculatorApp::Common::ViewMode mode) const; + void LogConverterInputReceived(CalculatorApp::Common::ViewMode mode) const; void LogNavBarOpened() const; - void LogViewClosingTelemetry(int); - void LogCoreWindowWasNull() const; - // Trace methods for Date Calculator usage - void LogDateDifferenceModeUsed(int windowId); - void LogDateAddSubtractModeUsed(int windowId, bool isAddMode); - void - LogDateClippedTimeDifferenceFound(winrt::Windows::Globalization::Calendar const& today, winrt::Windows::Foundation::DateTime const& clippedTime) const; - - void LogStandardException(std::wstring_view functionName, _In_ const std::exception& e) const; - void LogWinRTException(std::wstring_view functionName, _In_ winrt::hresult_error const& e) const; - void LogPlatformException(std::wstring_view functionName, _In_ Platform::Exception ^ e) const; + void LogError(CalculatorApp::Common::ViewMode mode, std::wstring_view functionName, std::wstring_view errorString); + void LogStandardException(CalculatorApp::Common::ViewMode mode, std::wstring_view functionName, _In_ const std::exception& e) const; + void LogWinRTException(CalculatorApp::Common::ViewMode mode, std::wstring_view functionName, _In_ winrt::hresult_error const& e) const; + void LogPlatformException(CalculatorApp::Common::ViewMode mode, std::wstring_view functionName, _In_ Platform::Exception ^ e) const; private: // Create an instance of TraceLogger TraceLogger(); - // Any new Log method should - // a) decide the level of logging. This will help us in limiting recording of events only up to a certain level. See this link for guidance - // https://msdn.microsoft.com/en-us/library/windows/desktop/aa363742(v=vs.85).aspx We're using Verbose level for events that are called frequently and - // needed only for debugging or capturing perf for specific scenarios b) should decide whether or not to log to telemetry and pass - // TraceLoggingKeyword(MICROSOFT_KEYWORD_TELEMETRY) accordingly c) Should accept a variable number of additional data arguments if needed - void LogTelemetryEvent(std::wstring_view eventName, winrt::Windows::Foundation::Diagnostics::LoggingFields fields) const; - void LogMeasureEvent(std::wstring_view eventName, winrt::Windows::Foundation::Diagnostics::LoggingFields fields) const; - void LogCriticalDataEvent(std::wstring_view eventName, winrt::Windows::Foundation::Diagnostics::LoggingFields fields) const; - void LogPerformanceEvent(std::wstring_view eventName, winrt::Windows::Foundation::Diagnostics::LoggingFields fields) const; - void LogInfoEvent(std::wstring_view eventName, winrt::Windows::Foundation::Diagnostics::LoggingFields fields) const; + // As mentioned in Microsoft's Privacy Statement(https://privacy.microsoft.com/en-US/privacystatement#maindiagnosticsmodule), + // sampling is involved in Microsoft's diagnostic data collection process. + // These keywords provide additional input into how frequently an event might be sampled. + // The lower the level of the keyword, the higher the possibility that the corresponding event may be sampled. + void LogLevel1Event(std::wstring_view eventName, winrt::Windows::Foundation::Diagnostics::LoggingFields fields) const; + void LogLevel2Event(std::wstring_view eventName, winrt::Windows::Foundation::Diagnostics::LoggingFields fields) const; + void LogLevel3Event(std::wstring_view eventName, winrt::Windows::Foundation::Diagnostics::LoggingFields fields) const; std::unique_ptr CreateTraceActivity(std::wstring_view activityName, winrt::Windows::Foundation::Diagnostics::LoggingFields fields) const; winrt::Windows::Foundation::Diagnostics::LoggingChannel g_calculatorProvider; - bool isSizeChangeLogged = false; - bool isHideIfShownLogged = false; - bool isSizeChangedFirstTime = true; // to track the first size changed event which is fired on the launch of app - bool isAutoConversionBeginLoggedInSession = false; - bool isAutoConversionEndLoggedInSession = false; - bool angleButtonLoggedInSession = false; - bool radixButtonLoggedInSession = false; - bool bitLengthButtonLoggedInSession = false; - GUID sessionGuid; - CalculatorApp::Common::ViewMode currentMode = CalculatorApp::Common::ViewMode::None; - std::vector funcLog; - int functionCount = 0; - bool isHypButtonLogged = false; - bool isAngleButtonInitialized = false; - unsigned int findIndex[maxFunctionSize] = { 0 }; - bool GetIndex(int& index); - std::wstring GetProgrammerType(int index); - size_t maxWindowCount = 0; - bool isAppLaunchBeginLogged = false; - bool isAppLaunchEndLogged = false; - std::map bitLengthButtonUsage; - std::map angleButtonUsage; - std::map radixButtonUsage; + std::vector buttonLog; std::map windowIdLog; - // Private variables for Date Calculator usage - bool m_dateDiffUsageLoggedInSession = false; - bool m_dateAddUsageLoggedInSession = false; - bool m_dateSubtractUsageLoggedInSession = false; - std::map m_dateAddModeUsage; - std::map m_dateSubtractModeUsage; - - size_t windowLaunchCount = 0; + GUID sessionGuid; + size_t currentWindowCount = 0; winrt::Windows::Foundation::Diagnostics::LoggingActivity m_appLaunchActivity; }; diff --git a/src/CalcViewModel/DataLoaders/CurrencyDataLoader.cpp b/src/CalcViewModel/DataLoaders/CurrencyDataLoader.cpp index 97efc03a..1e83736c 100644 --- a/src/CalcViewModel/DataLoaders/CurrencyDataLoader.cpp +++ b/src/CalcViewModel/DataLoaders/CurrencyDataLoader.cpp @@ -335,12 +335,12 @@ future CurrencyDataLoader::TryLoadDataFromCacheAsync() } catch (Exception ^ ex) { - TraceLogger::GetInstance().LogPlatformException(__FUNCTIONW__, ex); + TraceLogger::GetInstance().LogPlatformException(ViewMode::Currency, __FUNCTIONW__, ex); co_return false; } catch (const exception& e) { - TraceLogger::GetInstance().LogStandardException(__FUNCTIONW__, e); + TraceLogger::GetInstance().LogStandardException(ViewMode::Currency, __FUNCTIONW__, e); co_return false; } catch (...) @@ -445,12 +445,12 @@ future CurrencyDataLoader::TryLoadDataFromWebAsync() } catch (Exception ^ ex) { - TraceLogger::GetInstance().LogPlatformException(__FUNCTIONW__, ex); + TraceLogger::GetInstance().LogPlatformException(ViewMode::Currency, __FUNCTIONW__, ex); co_return false; } catch (const exception& e) { - TraceLogger::GetInstance().LogStandardException(__FUNCTIONW__, e); + TraceLogger::GetInstance().LogStandardException(ViewMode::Currency, __FUNCTIONW__, e); co_return false; } catch (...) @@ -466,7 +466,7 @@ future CurrencyDataLoader::TryLoadDataFromWebOverrideAsync() if (!didLoad) { m_loadStatus = CurrencyLoadStatus::FailedToLoad; - TraceLogger::GetInstance().LogUserRequestedRefreshFailed(); + TraceLogger::GetInstance().LogError(ViewMode::Currency, L"CurrencyDataLoader::TryLoadDataFromWebOverrideAsync", L"UserRequestedRefreshFailed"); } co_return didLoad; diff --git a/src/CalcViewModel/DateCalculatorViewModel.cpp b/src/CalcViewModel/DateCalculatorViewModel.cpp index 471d5df8..e89c136a 100644 --- a/src/CalcViewModel/DateCalculatorViewModel.cpp +++ b/src/CalcViewModel/DateCalculatorViewModel.cpp @@ -88,9 +88,6 @@ DateCalculatorViewModel::DateCalculatorViewModel() if (calendar->DayOfWeek != trueDayOfWeek) { calendar->SetDateTime(today); - TraceLogger::GetInstance().LogDateClippedTimeDifferenceFound( - from_cx(calendar), - winrt::Windows::Foundation::DateTime{ winrt::Windows::Foundation::TimeSpan{ clippedTime.UniversalTime } }); } } diff --git a/src/CalcViewModel/HistoryViewModel.cpp b/src/CalcViewModel/HistoryViewModel.cpp index 70374252..8da5007a 100644 --- a/src/CalcViewModel/HistoryViewModel.cpp +++ b/src/CalcViewModel/HistoryViewModel.cpp @@ -118,6 +118,9 @@ void HistoryViewModel::SetCalculatorDisplay(CalculatorDisplay& calculatorDisplay void HistoryViewModel::ShowItem(_In_ HistoryItemViewModel ^ e) { + unsigned int index; + Items->IndexOf(e, &index); + TraceLogger::GetInstance().LogHistoryItemLoad((ViewMode)m_currentMode, ItemSize, (int)(index)); HistoryItemClicked(e); } @@ -149,7 +152,6 @@ void HistoryViewModel::OnHideCommand(_In_ Platform::Object ^ e) void HistoryViewModel::OnClearCommand(_In_ Platform::Object ^ e) { - TraceLogger::GetInstance().LogClearHistory(); if (AreHistoryShortcutsEnabled == true) { m_calculatorManager->ClearHistory(); diff --git a/src/CalcViewModel/StandardCalculatorViewModel.cpp b/src/CalcViewModel/StandardCalculatorViewModel.cpp index dd0283da..1f1aa78e 100644 --- a/src/CalcViewModel/StandardCalculatorViewModel.cpp +++ b/src/CalcViewModel/StandardCalculatorViewModel.cpp @@ -37,6 +37,7 @@ namespace StringReference IsProgrammerPropertyName(L"IsProgrammer"); StringReference DisplayValuePropertyName(L"DisplayValue"); StringReference CalculationResultAutomationNamePropertyName(L"CalculationResultAutomationName"); + StringReference IsBitFlipCheckedPropertyName(L"IsBitFlipChecked"); } namespace CalculatorResourceKeys @@ -599,8 +600,6 @@ void StandardCalculatorViewModel::OnButtonPressed(Object ^ parameter) NumbersAndOperatorsEnum numOpEnum = CalculatorButtonPressedEventArgs::GetOperationFromCommandParameter(parameter); Command cmdenum = ConvertToOperatorsEnum(numOpEnum); - TraceLogger::GetInstance().UpdateFunctionUsage((int)numOpEnum); - if (IsInError) { m_standardCalculatorManager.SendCommand(Command::CommandCLEAR); @@ -668,6 +667,7 @@ void StandardCalculatorViewModel::OnButtonPressed(Object ^ parameter) m_isLastOperationHistoryLoad = false; } + TraceLogger::GetInstance().UpdateButtonUsage(numOpEnum, GetCalculatorMode()); m_standardCalculatorManager.SendCommand(cmdenum); } } @@ -748,7 +748,7 @@ void StandardCalculatorViewModel::OnPasteCommand(Object ^ parameter) // Ensure that the paste happens on the UI thread CopyPasteManager::GetStringToPaste(mode, NavCategory::GetGroupType(mode), NumberBase, bitLengthType) - .then([this, mode](String ^ pastedString) { OnPaste(pastedString, mode); }, concurrency::task_continuation_context::use_current()); + .then([this, mode](String ^ pastedString) { OnPaste(pastedString); }, concurrency::task_continuation_context::use_current()); } CalculationManager::Command StandardCalculatorViewModel::ConvertToOperatorsEnum(NumbersAndOperatorsEnum operation) @@ -756,7 +756,7 @@ CalculationManager::Command StandardCalculatorViewModel::ConvertToOperatorsEnum( return safe_cast(operation); } -void StandardCalculatorViewModel::OnPaste(String ^ pastedString, ViewMode mode) +void StandardCalculatorViewModel::OnPaste(String ^ pastedString) { // If pastedString is invalid("NoOp") then display pasteError else process the string if (pastedString == StringReference(CopyPasteManager::PasteErrorString)) @@ -765,7 +765,6 @@ void StandardCalculatorViewModel::OnPaste(String ^ pastedString, ViewMode mode) return; } - TraceLogger::GetInstance().LogValidInputPasted(mode); bool isFirstLegalChar = true; m_standardCalculatorManager.SendCommand(Command::CommandCENTR); bool sendNegate = false; @@ -884,7 +883,7 @@ void StandardCalculatorViewModel::OnPaste(String ^ pastedString, ViewMode mode) // Handle exponent and exponent sign (...e+... or ...e-... or ...e...) if (mappedNumOp == NumbersAndOperatorsEnum::Exp) { - //Check the following item + // Check the following item switch (MapCharacterToButtonId(*(it + 1), canSendNegate)) { case NumbersAndOperatorsEnum::Subtract: @@ -896,7 +895,7 @@ void StandardCalculatorViewModel::OnPaste(String ^ pastedString, ViewMode mode) break; case NumbersAndOperatorsEnum::Add: { - //Nothing to do, skip to the next item + // Nothing to do, skip to the next item ++it; } break; @@ -911,8 +910,7 @@ void StandardCalculatorViewModel::OnClearMemoryCommand(Object ^ parameter) { m_standardCalculatorManager.MemorizedNumberClearAll(); - int windowId = Utils::GetWindowId(); - TraceLogger::GetInstance().LogMemoryClearAll(windowId); + TraceLogger::GetInstance().UpdateButtonUsage(NumbersAndOperatorsEnum::MemoryClear, GetCalculatorMode()); String ^ announcement = LocalizationStringUtil::GetLocalizedNarratorAnnouncement(CalculatorResourceKeys::MemoryCleared, m_localizedMemoryCleared); Announcement = CalculatorAnnouncement::GetMemoryClearedAnnouncement(announcement); @@ -1046,8 +1044,7 @@ void StandardCalculatorViewModel::OnMemoryButtonPressed() { m_standardCalculatorManager.MemorizeNumber(); - int windowId = Utils::GetWindowId(); - TraceLogger::GetInstance().InsertIntoMemoryMap(windowId, IsStandard, IsScientific, IsProgrammer); + TraceLogger::GetInstance().UpdateButtonUsage(NumbersAndOperatorsEnum::Memory, GetCalculatorMode()); String ^ announcement = LocalizationStringUtil::GetLocalizedNarratorAnnouncement( CalculatorResourceKeys::MemorySave, m_localizedMemorySavedAutomationFormat, m_DisplayValue->Data()); @@ -1079,49 +1076,31 @@ void StandardCalculatorViewModel::OnMemoryItemPressed(Object ^ memoryItemPositio auto boxedPosition = safe_cast ^>(memoryItemPosition); m_standardCalculatorManager.MemorizedNumberLoad(boxedPosition->Value); HideMemoryClicked(); - int windowId = Utils::GetWindowId(); - TraceLogger::GetInstance().LogMemoryUsed(windowId, boxedPosition->Value, IsStandard, IsScientific, IsProgrammer, MemorizedNumbers->Size); + + auto mode = IsStandard ? ViewMode::Standard : IsScientific ? ViewMode::Scientific : ViewMode::Programmer; + TraceLogger::GetInstance().LogMemoryItemLoad(mode, MemorizedNumbers->Size, boxedPosition->Value); } } void StandardCalculatorViewModel::OnMemoryAdd(Object ^ memoryItemPosition) { // M+ will add display to memorylist if memory list is empty. - int windowId = Utils::GetWindowId(); if (MemorizedNumbers) { auto boxedPosition = safe_cast ^>(memoryItemPosition); - if (MemorizedNumbers->Size > 0) - { - TraceLogger::GetInstance().LogMemoryUsed(windowId, boxedPosition->Value, IsStandard, IsScientific, IsProgrammer, MemorizedNumbers->Size); - TraceLogger::GetInstance().UpdateMemoryMap(windowId, boxedPosition->Value, IsStandard, IsScientific, IsProgrammer); - } - else - { - TraceLogger::GetInstance().InsertIntoMemoryMap(windowId, IsStandard, IsScientific, IsProgrammer); - } + TraceLogger::GetInstance().UpdateButtonUsage(NumbersAndOperatorsEnum::MemoryAdd, GetCalculatorMode()); m_standardCalculatorManager.MemorizedNumberAdd(boxedPosition->Value); } } void StandardCalculatorViewModel::OnMemorySubtract(Object ^ memoryItemPosition) { - int windowId = Utils::GetWindowId(); - // M- will add negative of displayed number to memorylist if memory list is empty. if (MemorizedNumbers) { auto boxedPosition = safe_cast ^>(memoryItemPosition); - if (MemorizedNumbers->Size > 0) - { - TraceLogger::GetInstance().LogMemoryUsed(windowId, boxedPosition->Value, IsStandard, IsScientific, IsProgrammer, MemorizedNumbers->Size); - TraceLogger::GetInstance().UpdateMemoryMap(windowId, boxedPosition->Value, IsStandard, IsScientific, IsProgrammer); - } - else - { - TraceLogger::GetInstance().InsertIntoMemoryMap(windowId, IsStandard, IsScientific, IsProgrammer); - } + TraceLogger::GetInstance().UpdateButtonUsage(NumbersAndOperatorsEnum::MemorySubtract, GetCalculatorMode()); m_standardCalculatorManager.MemorizedNumberSubtract(boxedPosition->Value); } } @@ -1130,7 +1109,6 @@ void StandardCalculatorViewModel::OnMemoryClear(_In_ Object ^ memoryItemPosition { if (MemorizedNumbers && MemorizedNumbers->Size > 0) { - int windowId = Utils::GetWindowId(); auto boxedPosition = safe_cast ^>(memoryItemPosition); if (boxedPosition->Value >= 0) @@ -1148,9 +1126,7 @@ void StandardCalculatorViewModel::OnMemoryClear(_In_ Object ^ memoryItemPosition { IsMemoryEmpty = true; } - - TraceLogger::GetInstance().LogMemoryUsed(windowId, boxedPosition->Value, IsStandard, IsScientific, IsProgrammer, MemorizedNumbers->Size); - TraceLogger::GetInstance().DeleteFromMemoryMap(windowId, boxedPosition->Value); + TraceLogger::GetInstance().UpdateButtonUsage(NumbersAndOperatorsEnum::MemoryClear, GetCalculatorMode()); wstring localizedIndex = to_wstring(boxedPosition->Value + 1); LocalizationSettings::GetInstance().LocalizeDisplayValue(&localizedIndex); @@ -1191,6 +1167,11 @@ void StandardCalculatorViewModel::OnPropertyChanged(String ^ propertyname) RaisePropertyChanged(CalculationResultAutomationNamePropertyName); Announcement = GetDisplayUpdatedNarratorAnnouncement(); } + else if (propertyname == IsBitFlipCheckedPropertyName) + { + TraceLogger::GetInstance().UpdateButtonUsage( + IsBitFlipChecked ? NumbersAndOperatorsEnum::BitflipButton : NumbersAndOperatorsEnum::FullKeypadButton, ViewMode::Programmer); + } } void StandardCalculatorViewModel::SetCalculatorType(ViewMode targetState) @@ -1223,7 +1204,7 @@ void StandardCalculatorViewModel::SetCalculatorType(ViewMode targetState) } } -String^ StandardCalculatorViewModel::GetRawDisplayValue() +String ^ StandardCalculatorViewModel::GetRawDisplayValue() { if (IsInError) { @@ -1884,3 +1865,16 @@ NarratorAnnouncement ^ StandardCalculatorViewModel::GetDisplayUpdatedNarratorAnn return CalculatorAnnouncement::GetDisplayUpdatedAnnouncement(announcement); } + +ViewMode StandardCalculatorViewModel::GetCalculatorMode() +{ + if (IsStandard) + { + return ViewMode::Standard; + } + else if (IsScientific) + { + return ViewMode::Scientific; + } + return ViewMode::Programmer; +} diff --git a/src/CalcViewModel/StandardCalculatorViewModel.h b/src/CalcViewModel/StandardCalculatorViewModel.h index 59dbbcb1..03f5c0b0 100644 --- a/src/CalcViewModel/StandardCalculatorViewModel.h +++ b/src/CalcViewModel/StandardCalculatorViewModel.h @@ -317,7 +317,7 @@ namespace CalculatorApp } } - internal : void OnPaste(Platform::String ^ pastedString, CalculatorApp::Common::ViewMode mode); + internal : void OnPaste(Platform::String ^ pastedString); void OnCopyCommand(Platform::Object ^ parameter); void OnPasteCommand(Platform::Object ^ parameter); @@ -348,7 +348,6 @@ namespace CalculatorApp void OnBinaryOperatorReceived(); void OnMemoryItemChanged(unsigned int indexOfMemory); - Platform::String ^ GetLocalizedStringFormat(Platform::String ^ format, Platform::String ^ displayValue); void OnPropertyChanged(Platform::String ^ propertyname); void SetCalculatorType(CalculatorApp::Common::ViewMode targetState); @@ -451,6 +450,8 @@ namespace CalculatorApp bool IsViewPinned(); void SetViewPinnedState(bool pinned); + CalculatorApp::Common::ViewMode GetCalculatorMode(); + friend class CalculatorDisplay; friend class CalculatorFunctionalTests::HistoryTests; friend class CalculatorUnitTests::MultiWindowUnitTests; diff --git a/src/CalcViewModel/UnitConverterViewModel.cpp b/src/CalcViewModel/UnitConverterViewModel.cpp index 821cdc70..b0153dad 100644 --- a/src/CalcViewModel/UnitConverterViewModel.cpp +++ b/src/CalcViewModel/UnitConverterViewModel.cpp @@ -502,6 +502,8 @@ void UnitConverterViewModel::OnButtonPressed(Platform::Object ^ parameter) } m_model->SendCommand(command); + + TraceLogger::GetInstance().LogConverterInputReceived(Mode); } void UnitConverterViewModel::OnCopyCommand(Platform::Object ^ parameter) @@ -523,7 +525,7 @@ void UnitConverterViewModel::OnPasteCommand(Platform::Object ^ parameter) // EventWriteClipboardPaste_Start(); // Any converter ViewMode is fine here. CopyPasteManager::GetStringToPaste(m_Mode, NavCategory::GetGroupType(m_Mode)) - .then([this](String ^ pastedString) { OnPaste(pastedString, m_Mode); }, concurrency::task_continuation_context::use_current()); + .then([this](String ^ pastedString) { OnPaste(pastedString); }, concurrency::task_continuation_context::use_current()); } void UnitConverterViewModel::InitializeView() @@ -882,7 +884,7 @@ NumbersAndOperatorsEnum UnitConverterViewModel::MapCharacterToButtonId(const wch return mappedValue; } -void UnitConverterViewModel::OnPaste(String ^ stringToPaste, ViewMode mode) +void UnitConverterViewModel::OnPaste(String ^ stringToPaste) { // If pastedString is invalid("NoOp") then display pasteError else process the string if (stringToPaste == StringReference(CopyPasteManager::PasteErrorString)) @@ -891,7 +893,6 @@ void UnitConverterViewModel::OnPaste(String ^ stringToPaste, ViewMode mode) return; } - TraceLogger::GetInstance().LogValidInputPasted(mode); bool isFirstLegalChar = true; bool sendNegate = false; wstring accumulation = L""; @@ -1014,7 +1015,6 @@ void UnitConverterViewModel::StartConversionResultTimer() { String ^ valueFrom = m_Value1Active ? m_Value1 : m_Value2; String ^ valueTo = m_Value1Active ? m_Value2 : m_Value1; - TraceLogger::GetInstance().LogConversionResult(valueFrom->Data(), UnitFrom->ToString()->Data(), valueTo->Data(), UnitTo->ToString()->Data()); } }); } diff --git a/src/CalcViewModel/UnitConverterViewModel.h b/src/CalcViewModel/UnitConverterViewModel.h index b0cc0241..8eda417d 100644 --- a/src/CalcViewModel/UnitConverterViewModel.h +++ b/src/CalcViewModel/UnitConverterViewModel.h @@ -204,7 +204,7 @@ namespace CalculatorApp NumbersAndOperatorsEnum MapCharacterToButtonId(const wchar_t ch, bool& canSendNegate); void DisplayPasteError(); void OnValueActivated(IActivatable ^ control); - void OnPaste(Platform::String ^ stringToPaste, CalculatorApp::Common::ViewMode mode); + void OnPaste(Platform::String ^ stringToPaste); void OnCopyCommand(Platform::Object ^ parameter); void OnPasteCommand(Platform::Object ^ parameter); diff --git a/src/Calculator/AboutFlyout.xaml b/src/Calculator/AboutFlyout.xaml index c2d82f47..50f6f4e1 100644 --- a/src/Calculator/AboutFlyout.xaml +++ b/src/Calculator/AboutFlyout.xaml @@ -4,7 +4,6 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="using:CalculatorApp.Common" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" - Loaded="UserControl_Loaded" mc:Ignorable="d"> diff --git a/src/Calculator/AboutFlyout.xaml.cpp b/src/Calculator/AboutFlyout.xaml.cpp index 6ec7d4e1..87a15e69 100644 --- a/src/Calculator/AboutFlyout.xaml.cpp +++ b/src/Calculator/AboutFlyout.xaml.cpp @@ -61,8 +61,3 @@ void AboutFlyout::SetDefaultFocus() { AboutFlyoutEULA->Focus(::FocusState::Programmatic); } - -void CalculatorApp::AboutFlyout::UserControl_Loaded(Platform::Object ^ sender, Windows::UI::Xaml::RoutedEventArgs ^ e) -{ - TraceLogger::GetInstance().LogAboutFlyoutOpened(); -} diff --git a/src/Calculator/AboutFlyout.xaml.h b/src/Calculator/AboutFlyout.xaml.h index 87b53e9c..ab0e481e 100644 --- a/src/Calculator/AboutFlyout.xaml.h +++ b/src/Calculator/AboutFlyout.xaml.h @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #pragma once @@ -18,6 +18,5 @@ public private: void FeedbackButton_Click(_In_ Platform::Object ^ sender, _In_ Windows::UI::Xaml::RoutedEventArgs ^ e); void SetVersionString(); - void UserControl_Loaded(Platform::Object ^ sender, Windows::UI::Xaml::RoutedEventArgs ^ e); }; } /* namespace CalculatorApp */ diff --git a/src/Calculator/App.xaml.cpp b/src/Calculator/App.xaml.cpp index 5fe8152e..a3e20469 100644 --- a/src/Calculator/App.xaml.cpp +++ b/src/Calculator/App.xaml.cpp @@ -60,7 +60,6 @@ namespace CalculatorApp /// App::App() { - TraceLogger::GetInstance().LogAppLaunchStart(); InitializeComponent(); m_preLaunched = false; @@ -71,6 +70,8 @@ App::App() // Currently this is bugged so the property is only respected from code-behind. this->HighContrastAdjustment = ApplicationHighContrastAdjustment::None; + this->Suspending += ref new SuspendingEventHandler(this, &App::OnSuspending); + #if _DEBUG this->DebugSettings->IsBindingTracingEnabled = true; this->DebugSettings->BindingFailed += ref new BindingFailedEventHandler([](_In_ Object ^ /*sender*/, _In_ BindingFailedEventArgs ^ e) { @@ -219,21 +220,16 @@ Frame ^ App::CreateFrame() /// Details about the launch request and process. void App::OnLaunched(LaunchActivatedEventArgs ^ args) { - TraceLogger::GetInstance().LogWindowLaunched(); if (args->PrelaunchActivated) { // If the app got pre-launch activated, then save that state in a flag m_preLaunched = true; - TraceLogger::GetInstance().LogAppPrelaunchedBySystem(); } OnAppLaunch(args, args->Arguments); } void App::OnAppLaunch(IActivatedEventArgs ^ args, String ^ argument) { - auto previousExecutionState = args->PreviousExecutionState; - - TraceLogger::GetInstance().LogOnAppLaunch(previousExecutionState.ToString()->Data()); // Uncomment the following lines to display frame-rate and per-frame CPU usage info. //#if _DEBUG @@ -307,7 +303,6 @@ void App::OnAppLaunch(IActivatedEventArgs ^ args, String ^ argument) else { // For first launch, LaunchStart is logged in constructor, this is for subsequent launches. - TraceLogger::GetInstance().LogAppLaunchStart(); // !Phone check is required because even in continuum mode user interaction mode is Mouse not Touch if ((UIViewSettings::GetForCurrentView()->UserInteractionMode == UserInteractionMode::Mouse) @@ -319,7 +314,6 @@ void App::OnAppLaunch(IActivatedEventArgs ^ args, String ^ argument) auto newCoreAppView = CoreApplication::CreateNewView(); newCoreAppView->Dispatcher->RunAsync( CoreDispatcherPriority::Normal, ref new DispatchedHandler([args, argument, minWindowSize, weak]() { - TraceLogger::GetInstance().LogNewWindowCreationBegin(ApplicationView::GetApplicationViewIdForWindow(CoreWindow::GetForCurrentThread())); auto that = weak.Resolve(); if (that != nullptr) { @@ -372,13 +366,10 @@ void App::OnAppLaunch(IActivatedEventArgs ^ args, String ^ argument) } } } - TraceLogger::GetInstance().LogNewWindowCreationEnd(ApplicationView::GetApplicationViewIdForWindow(CoreWindow::GetForCurrentThread())); })); } else { - TraceLogger::GetInstance().LogNewWindowCreationBegin(ApplicationView::GetApplicationViewIdForWindow(CoreWindow::GetForCurrentThread())); - ActivationViewSwitcher ^ activationViewSwitcher; auto activateEventArgs = dynamic_cast(args); if (activateEventArgs != nullptr) @@ -390,12 +381,10 @@ void App::OnAppLaunch(IActivatedEventArgs ^ args, String ^ argument) { activationViewSwitcher->ShowAsStandaloneAsync( ApplicationView::GetApplicationViewIdForWindow(CoreWindow::GetForCurrentThread()), ViewSizePreference::Default); - TraceLogger::GetInstance().LogNewWindowCreationEnd(ApplicationView::GetApplicationViewIdForWindow(CoreWindow::GetForCurrentThread())); - TraceLogger::GetInstance().LogPrelaunchedAppActivatedByUser(); } else { - TraceLogger::GetInstance().LogError(L"Null_ActivationViewSwitcher"); + TraceLogger::GetInstance().LogError(ViewMode::None, L"App::OnAppLaunch", L"Null_ActivationViewSwitcher"); } } // Set the preLaunched flag to false @@ -460,13 +449,17 @@ void App::OnActivated(IActivatedEventArgs ^ args) { if (args->Kind == ActivationKind::Protocol) { - TraceLogger::GetInstance().LogWindowActivated(); // We currently don't pass the uri as an argument, // and handle any protocol launch as a normal app launch. OnAppLaunch(args, nullptr); } } +void CalculatorApp::App::OnSuspending(Object ^ sender, SuspendingEventArgs ^ args) +{ + TraceLogger::GetInstance().LogButtonUsage(); +} + void App::DismissedEventHandler(SplashScreen ^ sender, Object ^ e) { SetupJumpList(); @@ -477,3 +470,5 @@ float App::GetAppWindowHeight() CoreWindow ^ window = CoreWindow::GetForCurrentThread(); return window->Bounds.Height; } + + diff --git a/src/Calculator/App.xaml.h b/src/Calculator/App.xaml.h index 1de1aa8c..44e3499f 100644 --- a/src/Calculator/App.xaml.h +++ b/src/Calculator/App.xaml.h @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. // @@ -42,6 +42,8 @@ namespace CalculatorApp void OnAppLaunch(Windows::ApplicationModel::Activation::IActivatedEventArgs ^ args, Platform::String ^ argument); void DismissedEventHandler(Windows::ApplicationModel::Activation::SplashScreen ^ sender, Platform::Object ^ e); void RegisterDependencyProperties(); + void OnSuspending(Platform::Object ^ sender, Windows::ApplicationModel::SuspendingEventArgs ^ args); + class SafeFrameWindowCreation final { diff --git a/src/Calculator/Calculator.vcxproj b/src/Calculator/Calculator.vcxproj index 18a5f80b..39400f1f 100644 --- a/src/Calculator/Calculator.vcxproj +++ b/src/Calculator/Calculator.vcxproj @@ -216,7 +216,7 @@ - /DSEND_TELEMETRY %(AdditionalOptions) + /DSEND_DIAGNOSTICS %(AdditionalOptions) @@ -849,4 +849,4 @@ - \ No newline at end of file + diff --git a/src/Calculator/Common/AppLifecycleLogger.cpp b/src/Calculator/Common/AppLifecycleLogger.cpp index 2134fb84..0df91361 100644 --- a/src/Calculator/Common/AppLifecycleLogger.cpp +++ b/src/Calculator/Common/AppLifecycleLogger.cpp @@ -15,18 +15,18 @@ using namespace winrt::Windows::UI::ViewManagement; namespace CalculatorApp { -#ifdef SEND_TELEMETRY +#ifdef SEND_DIAGNOSTICS // c.f. WINEVENT_KEYWORD_RESERVED_63-56 0xFF00000000000000 // Bits 63-56 - channel keywords // c.f. WINEVENT_KEYWORD_* 0x00FF000000000000 // Bits 55-48 - system-reserved keywords - constexpr int64_t MICROSOFT_KEYWORD_CRITICAL_DATA = 0x0000800000000000; // Bit 47 - constexpr int64_t MICROSOFT_KEYWORD_MEASURES = 0x0000400000000000; // Bit 46 - constexpr int64_t MICROSOFT_KEYWORD_TELEMETRY = 0x0000200000000000; // Bit 45 + constexpr int64_t MICROSOFT_KEYWORD_LEVEL_1 = 0x0000800000000000; // Bit 47 + constexpr int64_t MICROSOFT_KEYWORD_LEVEL_2 = 0x0000400000000000; // Bit 46 + constexpr int64_t MICROSOFT_KEYWORD_LEVEL_3 = 0x0000200000000000; // Bit 45 constexpr int64_t MICROSOFT_KEYWORD_RESERVED_44 = 0x0000100000000000; // Bit 44 (reserved for future assignment) #else - // define all Keyword options as 0 when we do not want to upload app telemetry - constexpr int64_t MICROSOFT_KEYWORD_CRITICAL_DATA = 0; - constexpr int64_t MICROSOFT_KEYWORD_MEASURES = 0; - constexpr int64_t MICROSOFT_KEYWORD_TELEMETRY = 0; + // define all Keyword options as 0 when we do not want to upload app diagnostics + constexpr int64_t MICROSOFT_KEYWORD_LEVEL_1 = 0; + constexpr int64_t MICROSOFT_KEYWORD_LEVEL_2 = 0; + constexpr int64_t MICROSOFT_KEYWORD_LEVEL_3 = 0; constexpr int64_t MICROSOFT_KEYWORD_RESERVED_44 = 0; #endif @@ -35,7 +35,7 @@ namespace CalculatorApp AppLifecycleLogger::AppLifecycleLogger() : m_appLifecycleProvider( L"Microsoft.Windows.AppLifeCycle", - LoggingChannelOptions(GUID{ 0x4f50731a, 0x89cf, 0x4782, 0xb3, 0xe0, 0xdc, 0xe8, 0xc9, 0x4, 0x76, 0xba }), // Microsoft Telemetry group + LoggingChannelOptions(GUID{ 0x4f50731a, 0x89cf, 0x4782, 0xb3, 0xe0, 0xdc, 0xe8, 0xc9, 0x4, 0x76, 0xba }), GUID{ 0xef00584a, 0x2655, 0x462c, 0xbc, 0x24, 0xe7, 0xde, 0x63, 0xe, 0x7f, 0xbf }) // Unique provider ID {EF00584A-2655-462C-BC24-E7DE630E7FBF} { } @@ -59,7 +59,7 @@ namespace CalculatorApp void AppLifecycleLogger::LogAppLifecycleEvent(hstring const& eventName, LoggingFields const& fields) const { m_appLifecycleProvider.LogEvent( - eventName, fields, LoggingLevel::Information, LoggingOptions(MICROSOFT_KEYWORD_TELEMETRY | WINEVENT_KEYWORD_RESPONSE_TIME)); + eventName, fields, LoggingLevel::Information, LoggingOptions(MICROSOFT_KEYWORD_LEVEL_3 | WINEVENT_KEYWORD_RESPONSE_TIME)); } #pragma endregion diff --git a/src/Calculator/Common/AppLifecycleLogger.h b/src/Calculator/Common/AppLifecycleLogger.h index cb43327e..fdb8702e 100644 --- a/src/Calculator/Common/AppLifecycleLogger.h +++ b/src/Calculator/Common/AppLifecycleLogger.h @@ -31,8 +31,8 @@ namespace CalculatorApp // Any new Log method should // a) Decide the level of logging. This will help us in limiting recording of events only up to a certain level. See this link for guidance // https://msdn.microsoft.com/en-us/library/windows/desktop/aa363742(v=vs.85).aspx We're using Verbose level for events that are called frequently and - // needed only for debugging or capturing perf for specific scenarios b) Should decide whether or not to log to telemetry and pass - // TraceLoggingKeyword(MICROSOFT_KEYWORD_TELEMETRY) accordingly c) Should accept a variable number of additional data arguments if needed + // needed only for debugging or capturing perf for specific scenarios b) Should decide whether or not to log to diagnostics and pass + // TraceLoggingKeyword(MICROSOFT_KEYWORD_LEVEL_3) accordingly c) Should accept a variable number of additional data arguments if needed void LogAppLifecycleEvent(winrt::hstring const& eventName, winrt::Windows::Foundation::Diagnostics::LoggingFields const& fields) const; void PopulateAppInfo(winrt::Windows::Foundation::Diagnostics::LoggingFields& fields) const; diff --git a/src/Calculator/Views/Calculator.xaml b/src/Calculator/Views/Calculator.xaml index dffa3270..c8cd45e5 100644 --- a/src/Calculator/Views/Calculator.xaml +++ b/src/Calculator/Views/Calculator.xaml @@ -35,7 +35,6 @@ - + + + + + + + + @@ -236,7 +368,6 @@ - @@ -246,6 +377,11 @@ OperatorTemplate="{StaticResource Operator}" SeparatorTemplate="{StaticResource Separator}"/> + + @@ -288,6 +424,28 @@ + + + + + + + + + + + + + + + + + + + + + + @@ -364,7 +522,7 @@ - + @@ -377,6 +535,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -419,19 +601,29 @@ + MinHeight="0"/> + MinHeight="20"/> + MinHeight="0"/> + - + + AutomationProperties.AutomationId="CalculatorAlwaysOnTopResults" + AutomationProperties.HeadingLevel="Level1" + AutomationProperties.Name="{x:Bind Model.CalculationResultAutomationName, Mode=OneWay}" + TokensUpdated="{x:Bind Model.AreAlwaysOnTopResultsUpdated, Mode=OneWay}" + HorizontalContentAlignment="Right" + IsActive="True" + UseSystemFocusVisuals="True" + Visibility="{x:Bind Model.IsAlwaysOnTop, Mode=OneWay}"/> - - + + + + + + diff --git a/src/Calculator/Views/Calculator.xaml.cpp b/src/Calculator/Views/Calculator.xaml.cpp index 25458301..ce84bb71 100644 --- a/src/Calculator/Views/Calculator.xaml.cpp +++ b/src/Calculator/Views/Calculator.xaml.cpp @@ -40,6 +40,7 @@ using namespace Windows::UI::ViewManagement; DEPENDENCY_PROPERTY_INITIALIZATION(Calculator, IsStandard); DEPENDENCY_PROPERTY_INITIALIZATION(Calculator, IsScientific); DEPENDENCY_PROPERTY_INITIALIZATION(Calculator, IsProgrammer); +DEPENDENCY_PROPERTY_INITIALIZATION(Calculator, IsAlwaysOnTop); Calculator::Calculator() : m_doAnimate(false) @@ -60,6 +61,8 @@ Calculator::Calculator() auto resLoader = AppResourceProvider::GetInstance(); CopyMenuItem->Text = resLoader.GetResourceString(L"copyMenuItem"); PasteMenuItem->Text = resLoader.GetResourceString(L"pasteMenuItem"); + + this->SizeChanged += ref new SizeChangedEventHandler(this, &Calculator::Calculator_SizeChanged); } void Calculator::LoadResourceStrings() @@ -97,7 +100,7 @@ void Calculator::SetFontSizeResources() { L"Tibt", 104, 29.333, 20, 40, 56, 40, 56 }, { L"Default", 104, 29.333, 23, 40, 56, 40, 56 } }; - DecimalFormatter^ formatter = LocalizationService::GetInstance()->GetRegionalSettingsAwareDecimalFormatter(); + DecimalFormatter ^ formatter = LocalizationService::GetInstance()->GetRegionalSettingsAwareDecimalFormatter(); const FontTable* currentItem = fontTables; while (currentItem->numericSystem.compare(std::wstring(L"Default")) != 0 && currentItem->numericSystem.compare(formatter->NumeralSystem->Data()) != 0) @@ -279,6 +282,35 @@ void Calculator::OnIsProgrammerPropertyChanged(bool /*oldValue*/, bool newValue) UpdatePanelViewState(); } +void Calculator::OnIsAlwaysOnTopPropertyChanged(bool /*oldValue*/, bool newValue) +{ + if (newValue) + { + VisualStateManager::GoToState(this, L"AlwaysOnTop", false); + } + else + { + VisualStateManager::GoToState(this, L"Normal", false); + if (Model->IsInError) + { + VisualStateManager::GoToState(this, L"ErrorLayout", false); + } + else + { + EnableMemoryControls(true); + } + } + + Model->IsMemoryEmpty = (Model->MemorizedNumbers->Size == 0) || IsAlwaysOnTop; + + AlwaysOnTopResults->UpdateScrollButtons(); + Results->UpdateTextState(); + + UpdateViewState(); + UpdatePanelViewState(); + SetDefaultFocus(); +} + void Calculator::OnIsInErrorPropertyChanged() { bool isError = Model->IsInError; @@ -395,33 +427,36 @@ void Calculator::UpdateHistoryState() void Calculator::UpdateMemoryState() { - if (!Model->IsMemoryEmpty) + if (!IsAlwaysOnTop) { - MemRecall->IsEnabled = true; - ClearMemoryButton->IsEnabled = true; - } - else - { - MemRecall->IsEnabled = false; - ClearMemoryButton->IsEnabled = false; - } - - String ^ viewState = App::GetAppViewState(); - if (viewState == ViewState::DockedView) - { - CloseMemoryFlyout(); - SetChildAsMemory(); - MemoryButton->Visibility = ::Visibility::Collapsed; - - if (m_IsLastFlyoutMemory && !IsProgrammer) + if (!Model->IsMemoryEmpty) { - DockPivot->SelectedIndex = 1; + MemRecall->IsEnabled = true; + ClearMemoryButton->IsEnabled = true; + } + else + { + MemRecall->IsEnabled = false; + ClearMemoryButton->IsEnabled = false; + } + + String ^ viewState = App::GetAppViewState(); + if (viewState == ViewState::DockedView) + { + CloseMemoryFlyout(); + SetChildAsMemory(); + MemoryButton->Visibility = ::Visibility::Collapsed; + + if (m_IsLastFlyoutMemory && !IsProgrammer) + { + DockPivot->SelectedIndex = 1; + } + } + else + { + MemoryButton->Visibility = ::Visibility::Visible; + DockMemoryHolder->Child = nullptr; } - } - else - { - MemoryButton->Visibility = ::Visibility::Visible; - DockMemoryHolder->Child = nullptr; } } @@ -507,7 +542,14 @@ void Calculator::CloseMemoryFlyout() void Calculator::SetDefaultFocus() { - Results->Focus(::FocusState::Programmatic); + if (!IsAlwaysOnTop) + { + Results->Focus(::FocusState::Programmatic); + } + else + { + AlwaysOnTopResults->Focus(::FocusState::Programmatic); + } } void Calculator::ToggleHistoryFlyout(Object ^ /*parameter*/) @@ -696,5 +738,13 @@ void CalculatorApp::Calculator::OnVisualStateChanged(Platform::Object ^ sender, { auto mode = IsStandard ? ViewMode::Standard : IsScientific ? ViewMode::Scientific : ViewMode::Programmer; auto state = std::wstring(e->NewState->Name->Begin()); - TraceLogger::GetInstance().LogVisualStateChanged(mode, state); + TraceLogger::GetInstance().LogVisualStateChanged(mode, state, IsAlwaysOnTop); +} + +void Calculator::Calculator_SizeChanged(Object ^ /*sender*/, SizeChangedEventArgs ^ /*e*/) +{ + if (Model->IsAlwaysOnTop) + { + AlwaysOnTopResults->UpdateScrollButtons(); + } } diff --git a/src/Calculator/Views/Calculator.xaml.h b/src/Calculator/Views/Calculator.xaml.h index 04099f8b..a1094a4b 100644 --- a/src/Calculator/Views/Calculator.xaml.h +++ b/src/Calculator/Views/Calculator.xaml.h @@ -53,6 +53,7 @@ public DEPENDENCY_PROPERTY_WITH_DEFAULT_AND_CALLBACK(bool, IsStandard, false); DEPENDENCY_PROPERTY_WITH_DEFAULT_AND_CALLBACK(bool, IsScientific, false); DEPENDENCY_PROPERTY_WITH_DEFAULT_AND_CALLBACK(bool, IsProgrammer, false); + DEPENDENCY_PROPERTY_WITH_DEFAULT_AND_CALLBACK(bool, IsAlwaysOnTop, false); COMMAND_FOR_METHOD(HistoryButtonPressed, Calculator::ToggleHistoryFlyout); @@ -75,12 +76,12 @@ public void UpdateMemoryState(); void UpdateHistoryState(); - void CalculationResultsOnSelected(_In_ Platform::Object ^ sender); void OnContextRequested(Windows::UI::Xaml::UIElement ^ sender, Windows::UI::Xaml::Input::ContextRequestedEventArgs ^ e); void OnContextCanceled(Windows::UI::Xaml::UIElement ^ sender, Windows::UI::Xaml::RoutedEventArgs ^ e); void OnIsScientificPropertyChanged(bool oldValue, bool newValue); void OnIsProgrammerPropertyChanged(bool oldValue, bool newValue); void OnIsStandardPropertyChanged(bool oldValue, bool newValue); + void OnIsAlwaysOnTopPropertyChanged(bool oldValue, bool newValue); void OnIsInErrorPropertyChanged(); void OnCalcPropertyChanged(_In_ Platform::Object ^ sender, _In_ Windows::UI::Xaml::Data::PropertyChangedEventArgs ^ e); void OnStoryboardCompleted(_In_ Platform::Object ^ sender, _In_ Platform::Object ^ e); @@ -89,6 +90,7 @@ public void EnsureProgrammer(); void SetFontSizeResources(); std::wstring GetCurrentLayoutState(); + void Calculator_SizeChanged(Object ^ sender, Windows::UI::Xaml::SizeChangedEventArgs ^ e); private: Windows::UI::Xaml::Controls::ListView ^ m_tokenList; diff --git a/src/Calculator/Views/CalculatorProgrammerRadixOperators.xaml b/src/Calculator/Views/CalculatorProgrammerRadixOperators.xaml index 6cd455be..eefbb757 100644 --- a/src/Calculator/Views/CalculatorProgrammerRadixOperators.xaml +++ b/src/Calculator/Views/CalculatorProgrammerRadixOperators.xaml @@ -216,7 +216,7 @@ FontSize="16" AutomationProperties.AutomationId="shiftButton" Checked="Shift_Clicked" - Content="" + Content="" Unchecked="Shift_Clicked"/> + Content=""/> diff --git a/src/Calculator/Views/CalculatorScientificOperators.xaml b/src/Calculator/Views/CalculatorScientificOperators.xaml index 15f6600f..e98ad4ea 100644 --- a/src/Calculator/Views/CalculatorScientificOperators.xaml +++ b/src/Calculator/Views/CalculatorScientificOperators.xaml @@ -511,7 +511,7 @@ Style="{StaticResource SymbolOperatorButtonStyle}" AutomationProperties.AutomationId="squareRootButton" ButtonId="Sqrt" - Content=""/> + Content=""/> @@ -718,7 +718,7 @@ FontSize="16" AutomationProperties.AutomationId="negateButton" ButtonId="Negate" - Content="" + Content="" IsEnabled="{x:Bind Model.IsNegateEnabled, Mode=OneWay}"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -238,11 +292,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -279,7 +363,7 @@ Style="{StaticResource SymbolOperatorButtonStyle}" AutomationProperties.AutomationId="squareRootButton" ButtonId="Sqrt" - Content=""/> + Content=""/> + Content=""/> diff --git a/src/Calculator/Views/CalculatorStandardOperators.xaml.cpp b/src/Calculator/Views/CalculatorStandardOperators.xaml.cpp index 7ebd5928..62dcec6f 100644 --- a/src/Calculator/Views/CalculatorStandardOperators.xaml.cpp +++ b/src/Calculator/Views/CalculatorStandardOperators.xaml.cpp @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. // diff --git a/src/Calculator/Views/CalculatorStandardOperators.xaml.h b/src/Calculator/Views/CalculatorStandardOperators.xaml.h index ebd71b99..3fb1069f 100644 --- a/src/Calculator/Views/CalculatorStandardOperators.xaml.h +++ b/src/Calculator/Views/CalculatorStandardOperators.xaml.h @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. // diff --git a/src/Calculator/Views/MainPage.xaml b/src/Calculator/Views/MainPage.xaml index bcf2908d..ca372eac 100644 --- a/src/Calculator/Views/MainPage.xaml +++ b/src/Calculator/Views/MainPage.xaml @@ -32,6 +32,9 @@ + + + @@ -83,8 +86,21 @@ Command="{x:Bind Model.PasteCommand}"/> - - + + + + + + + + + + + + + + + - + + + + - - - - - - - - - - + Text="{x:Bind Model.CategoryName, Mode=OneWay}" + Grid.Column="0"/> +