Optimize BitFlipPanel to suppress flicker when users switch between bit lengths (#640)
* Optimize BitFlipPanel * remove namespace in cpp file * improve localization + add tests * add helper to compare ivector * Modify how the control manages AutomationProperties::Name
This commit is contained in:
@@ -322,6 +322,7 @@
|
||||
<ClInclude Include="Common\Automation\NarratorNotifier.h" />
|
||||
<ClInclude Include="Common\Automation\NotificationHost.h" />
|
||||
<ClInclude Include="Common\BindableBase.h" />
|
||||
<ClInclude Include="Common\BitLength.h" />
|
||||
<ClInclude Include="Common\CalculatorButtonPressedEventArgs.h" />
|
||||
<ClInclude Include="Common\CalculatorButtonUser.h" />
|
||||
<ClInclude Include="Common\CalculatorDisplay.h" />
|
||||
@@ -439,4 +440,4 @@
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\packages\Microsoft.UI.Xaml.2.0.181018003.1\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.UI.Xaml.2.0.181018003.1\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
</Project>
|
@@ -219,6 +219,9 @@
|
||||
<ClInclude Include="DataLoaders\DataLoaderConstants.h">
|
||||
<Filter>DataLoaders</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Common\BitLength.h">
|
||||
<Filter>Common</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="DataLoaders\DefaultFromToCurrency.json">
|
||||
|
17
src/CalcViewModel/Common/BitLength.h
Normal file
17
src/CalcViewModel/Common/BitLength.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
namespace CalculatorApp
|
||||
{
|
||||
namespace Common
|
||||
{
|
||||
public
|
||||
enum class BitLength : int
|
||||
{
|
||||
BitLengthUnknown = -1,
|
||||
BitLengthByte = 8,
|
||||
BitLengthWord = 16,
|
||||
BitLengthDWord = 32,
|
||||
BitLengthQWord = 64,
|
||||
};
|
||||
}
|
||||
}
|
@@ -65,7 +65,7 @@ void CopyPasteManager::CopyToClipboard(String ^ stringToCopy)
|
||||
Clipboard::SetContent(dataPackage);
|
||||
}
|
||||
|
||||
task<String ^> CopyPasteManager::GetStringToPaste(ViewMode mode, CategoryGroupType modeType, int programmerNumberBase, int bitLengthType)
|
||||
task<String ^> CopyPasteManager::GetStringToPaste(ViewMode mode, CategoryGroupType modeType, int programmerNumberBase, BitLength bitLengthType)
|
||||
{
|
||||
// Retrieve the text in the clipboard
|
||||
auto dataPackageView = Clipboard::GetContent();
|
||||
@@ -97,14 +97,14 @@ int CopyPasteManager::ClipboardTextFormat()
|
||||
return -1;
|
||||
}
|
||||
|
||||
String ^ CopyPasteManager::ValidatePasteExpression(String ^ pastedText, ViewMode mode, int programmerNumberBase, int bitLengthType)
|
||||
String ^ CopyPasteManager::ValidatePasteExpression(String ^ pastedText, ViewMode mode, int programmerNumberBase, BitLength bitLengthType)
|
||||
{
|
||||
return CopyPasteManager::ValidatePasteExpression(pastedText, mode, NavCategory::GetGroupType(mode), programmerNumberBase, bitLengthType);
|
||||
}
|
||||
|
||||
// return "NoOp" if pastedText is invalid else return pastedText
|
||||
|
||||
String ^ CopyPasteManager::ValidatePasteExpression(String ^ pastedText, ViewMode mode, CategoryGroupType modeType, int programmerNumberBase, int bitLengthType)
|
||||
String ^ CopyPasteManager::ValidatePasteExpression(String ^ pastedText, ViewMode mode, CategoryGroupType modeType, int programmerNumberBase, BitLength bitLengthType)
|
||||
{
|
||||
if (pastedText->Length() > MaxPasteableLength)
|
||||
{
|
||||
@@ -241,7 +241,7 @@ vector<wstring> CopyPasteManager::ExtractOperands(const wstring& pasteExpression
|
||||
return operands;
|
||||
}
|
||||
|
||||
bool CopyPasteManager::ExpressionRegExMatch(vector<wstring> operands, ViewMode mode, CategoryGroupType modeType, int programmerNumberBase, int bitLengthType)
|
||||
bool CopyPasteManager::ExpressionRegExMatch(vector<wstring> operands, ViewMode mode, CategoryGroupType modeType, int programmerNumberBase, BitLength bitLengthType)
|
||||
{
|
||||
if (operands.empty())
|
||||
{
|
||||
@@ -317,7 +317,7 @@ bool CopyPasteManager::ExpressionRegExMatch(vector<wstring> operands, ViewMode m
|
||||
return expMatched;
|
||||
}
|
||||
|
||||
pair<size_t, uint64_t> CopyPasteManager::GetMaxOperandLengthAndValue(ViewMode mode, CategoryGroupType modeType, int programmerNumberBase, int bitLengthType)
|
||||
pair<size_t, uint64_t> CopyPasteManager::GetMaxOperandLengthAndValue(ViewMode mode, CategoryGroupType modeType, int programmerNumberBase, BitLength bitLengthType)
|
||||
{
|
||||
constexpr size_t defaultMaxOperandLength = 0;
|
||||
constexpr uint64_t defaultMaxValue = 0;
|
||||
@@ -335,16 +335,16 @@ pair<size_t, uint64_t> CopyPasteManager::GetMaxOperandLengthAndValue(ViewMode mo
|
||||
unsigned int bitLength = 0;
|
||||
switch (bitLengthType)
|
||||
{
|
||||
case QwordType:
|
||||
case BitLength::BitLengthQWord:
|
||||
bitLength = 64;
|
||||
break;
|
||||
case DwordType:
|
||||
case BitLength::BitLengthDWord:
|
||||
bitLength = 32;
|
||||
break;
|
||||
case WordType:
|
||||
case BitLength::BitLengthWord:
|
||||
bitLength = 16;
|
||||
break;
|
||||
case ByteType:
|
||||
case BitLength::BitLengthByte:
|
||||
bitLength = 8;
|
||||
break;
|
||||
}
|
||||
|
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "AppResourceProvider.h"
|
||||
#include "NavCategory.h"
|
||||
#include "BitLength.h"
|
||||
|
||||
namespace CalculatorUnitTests
|
||||
{
|
||||
@@ -13,10 +14,6 @@ namespace CalculatorUnitTests
|
||||
|
||||
namespace CalculatorApp
|
||||
{
|
||||
inline constexpr auto QwordType = 1;
|
||||
inline constexpr auto DwordType = 2;
|
||||
inline constexpr auto WordType = 3;
|
||||
inline constexpr auto ByteType = 4;
|
||||
inline constexpr auto HexBase = 5;
|
||||
inline constexpr auto DecBase = 6;
|
||||
inline constexpr auto OctBase = 7;
|
||||
@@ -30,7 +27,7 @@ namespace CalculatorApp
|
||||
CalculatorApp::Common::ViewMode mode,
|
||||
CalculatorApp::Common::CategoryGroupType modeType,
|
||||
int programmerNumberBase = -1,
|
||||
int bitLengthType = -1);
|
||||
CalculatorApp::Common::BitLength bitLengthType = CalculatorApp::Common::BitLength::BitLengthUnknown);
|
||||
static bool HasStringToPaste()
|
||||
{
|
||||
return ClipboardTextFormat() >= 0;
|
||||
@@ -41,14 +38,18 @@ namespace CalculatorApp
|
||||
private:
|
||||
static int ClipboardTextFormat();
|
||||
static Platform::String
|
||||
^ ValidatePasteExpression(Platform::String ^ pastedText, CalculatorApp::Common::ViewMode mode, int programmerNumberBase, int bitLengthType);
|
||||
^ ValidatePasteExpression(
|
||||
Platform::String ^ pastedText,
|
||||
CalculatorApp::Common::ViewMode mode,
|
||||
int programmerNumberBase,
|
||||
CalculatorApp::Common::BitLength bitLengthType);
|
||||
static Platform::String
|
||||
^ ValidatePasteExpression(
|
||||
Platform::String ^ pastedText,
|
||||
CalculatorApp::Common::ViewMode mode,
|
||||
CalculatorApp::Common::CategoryGroupType modeType,
|
||||
int programmerNumberBase,
|
||||
int bitLengthType);
|
||||
CalculatorApp::Common::BitLength bitLengthType);
|
||||
|
||||
static std::vector<std::wstring>
|
||||
ExtractOperands(const std::wstring& pasteExpression, CalculatorApp::Common::ViewMode mode);
|
||||
@@ -57,13 +58,13 @@ namespace CalculatorApp
|
||||
CalculatorApp::Common::ViewMode mode,
|
||||
CalculatorApp::Common::CategoryGroupType modeType,
|
||||
int programmerNumberBase = -1,
|
||||
int bitLengthType = -1);
|
||||
CalculatorApp::Common::BitLength bitLengthType = CalculatorApp::Common::BitLength::BitLengthUnknown);
|
||||
|
||||
static std::pair<size_t, uint64_t> GetMaxOperandLengthAndValue(
|
||||
CalculatorApp::Common::ViewMode mode,
|
||||
CalculatorApp::Common::CategoryGroupType modeType,
|
||||
int programmerNumberBase = -1,
|
||||
int bitLengthType = -1);
|
||||
CalculatorApp::Common::BitLength bitLengthType = CalculatorApp::Common::BitLength::BitLengthUnknown);
|
||||
static std::wstring SanitizeOperand(const std::wstring& operand);
|
||||
static bool TryOperandToULL(const std::wstring& operand, int numberBase, unsigned long long int& result);
|
||||
static size_t OperandLength(
|
||||
|
@@ -67,6 +67,7 @@ StandardCalculatorViewModel::StandardCalculatorViewModel()
|
||||
, m_HexDisplayValue(L"0")
|
||||
, m_BinaryDisplayValue(L"0")
|
||||
, m_OctalDisplayValue(L"0")
|
||||
, m_BinaryDigits(ref new Vector<bool>(64, false))
|
||||
, m_standardCalculatorManager(&m_calculatorDisplay, &m_resourceProvider)
|
||||
, m_ExpressionTokens(ref new Vector<DisplayExpressionToken ^>())
|
||||
, m_MemorizedNumbers(ref new Vector<MemoryItemViewModel ^>())
|
||||
@@ -74,10 +75,7 @@ StandardCalculatorViewModel::StandardCalculatorViewModel()
|
||||
, m_IsFToEChecked(false)
|
||||
, m_isShiftChecked(false)
|
||||
, m_IsShiftProgrammerChecked(false)
|
||||
, m_IsQwordEnabled(true)
|
||||
, m_IsDwordEnabled(true)
|
||||
, m_IsWordEnabled(true)
|
||||
, m_IsByteEnabled(true)
|
||||
, m_valueBitLength(BitLength::BitLengthQWord)
|
||||
, m_isBitFlipChecked(false)
|
||||
, m_isBinaryBitFlippingEnabled(false)
|
||||
, m_CurrentRadixType(RADIX_TYPE::DEC_RADIX)
|
||||
@@ -679,26 +677,6 @@ void StandardCalculatorViewModel::OnButtonPressed(Object ^ parameter)
|
||||
}
|
||||
}
|
||||
|
||||
int StandardCalculatorViewModel::GetBitLengthType()
|
||||
{
|
||||
if (IsQwordEnabled)
|
||||
{
|
||||
return QwordType;
|
||||
}
|
||||
else if (IsDwordEnabled)
|
||||
{
|
||||
return DwordType;
|
||||
}
|
||||
else if (IsWordEnabled)
|
||||
{
|
||||
return WordType;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ByteType;
|
||||
}
|
||||
}
|
||||
|
||||
int StandardCalculatorViewModel::GetNumberBase()
|
||||
{
|
||||
if (CurrentRadixType == HEX_RADIX)
|
||||
@@ -729,9 +707,10 @@ void StandardCalculatorViewModel::OnCopyCommand(Object ^ parameter)
|
||||
|
||||
void StandardCalculatorViewModel::OnPasteCommand(Object ^ parameter)
|
||||
{
|
||||
auto that(this);
|
||||
ViewMode mode;
|
||||
int NumberBase = -1;
|
||||
int bitLengthType = -1;
|
||||
BitLength bitLengthType = BitLength::BitLengthUnknown;
|
||||
if (IsScientific)
|
||||
{
|
||||
mode = ViewMode::Scientific;
|
||||
@@ -740,7 +719,7 @@ void StandardCalculatorViewModel::OnPasteCommand(Object ^ parameter)
|
||||
{
|
||||
mode = ViewMode::Programmer;
|
||||
NumberBase = GetNumberBase();
|
||||
bitLengthType = GetBitLengthType();
|
||||
bitLengthType = m_valueBitLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -754,7 +733,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); }, concurrency::task_continuation_context::use_current());
|
||||
.then([that, mode](String ^ pastedString) { that->OnPaste(pastedString); }, concurrency::task_continuation_context::use_current());
|
||||
}
|
||||
|
||||
CalculationManager::Command StandardCalculatorViewModel::ConvertToOperatorsEnum(NumbersAndOperatorsEnum operation)
|
||||
@@ -1642,6 +1621,7 @@ wstring StandardCalculatorViewModel::AddPadding(wstring binaryString)
|
||||
|
||||
void StandardCalculatorViewModel::UpdateProgrammerPanelDisplay()
|
||||
{
|
||||
constexpr int32_t precision = 64;
|
||||
wstring hexDisplayString;
|
||||
wstring decimalDisplayString;
|
||||
wstring octalDisplayString;
|
||||
@@ -1649,8 +1629,7 @@ void StandardCalculatorViewModel::UpdateProgrammerPanelDisplay()
|
||||
if (!IsInError)
|
||||
{
|
||||
// we want the precision to be set to maximum value so that the autoconversions result as desired
|
||||
int32_t precision = 64;
|
||||
if (m_standardCalculatorManager.GetResultForRadix(16, precision) == L"")
|
||||
if ((hexDisplayString = m_standardCalculatorManager.GetResultForRadix(16, precision, true)) == L"")
|
||||
{
|
||||
hexDisplayString = DisplayValue->Data();
|
||||
decimalDisplayString = DisplayValue->Data();
|
||||
@@ -1659,10 +1638,9 @@ void StandardCalculatorViewModel::UpdateProgrammerPanelDisplay()
|
||||
}
|
||||
else
|
||||
{
|
||||
hexDisplayString = m_standardCalculatorManager.GetResultForRadix(16, precision);
|
||||
decimalDisplayString = m_standardCalculatorManager.GetResultForRadix(10, precision);
|
||||
octalDisplayString = m_standardCalculatorManager.GetResultForRadix(8, precision);
|
||||
binaryDisplayString = m_standardCalculatorManager.GetResultForRadix(2, precision);
|
||||
decimalDisplayString = m_standardCalculatorManager.GetResultForRadix(10, precision, true);
|
||||
octalDisplayString = m_standardCalculatorManager.GetResultForRadix(8, precision, true);
|
||||
binaryDisplayString = m_standardCalculatorManager.GetResultForRadix(2, precision, true);
|
||||
}
|
||||
}
|
||||
const auto& localizer = LocalizationSettings::GetInstance();
|
||||
@@ -1681,6 +1659,17 @@ void StandardCalculatorViewModel::UpdateProgrammerPanelDisplay()
|
||||
DecDisplayValue_AutomationName = GetLocalizedStringFormat(m_localizedDecimalAutomationFormat, DecimalDisplayValue);
|
||||
OctDisplayValue_AutomationName = GetLocalizedStringFormat(m_localizedOctalAutomationFormat, GetNarratorStringReadRawNumbers(OctalDisplayValue));
|
||||
BinDisplayValue_AutomationName = GetLocalizedStringFormat(m_localizedBinaryAutomationFormat, GetNarratorStringReadRawNumbers(BinaryDisplayValue));
|
||||
|
||||
auto binaryValueArray = ref new Vector<bool>(64, false);
|
||||
auto binaryValue = m_standardCalculatorManager.GetResultForRadix(2, precision, false);
|
||||
int i = 0;
|
||||
|
||||
// To get bit 0, grab from opposite end of string.
|
||||
for (std::wstring::reverse_iterator it = binaryValue.rbegin(); it != binaryValue.rend(); ++it)
|
||||
{
|
||||
binaryValueArray->SetAt(i++, *it == L'1');
|
||||
}
|
||||
BinaryDigits = binaryValueArray;
|
||||
}
|
||||
|
||||
void StandardCalculatorViewModel::SwitchAngleType(NumbersAndOperatorsEnum num)
|
||||
@@ -1885,3 +1874,31 @@ ViewMode StandardCalculatorViewModel::GetCalculatorMode()
|
||||
}
|
||||
return ViewMode::Programmer;
|
||||
}
|
||||
|
||||
void StandardCalculatorViewModel::ValueBitLength::set(CalculatorApp::Common::BitLength value)
|
||||
{
|
||||
if (m_valueBitLength != value)
|
||||
{
|
||||
m_valueBitLength = value;
|
||||
RaisePropertyChanged(L"ValueBitLength");
|
||||
|
||||
switch (value)
|
||||
{
|
||||
case BitLength::BitLengthQWord:
|
||||
ButtonPressed->Execute(NumbersAndOperatorsEnum::Qword);
|
||||
break;
|
||||
case BitLength::BitLengthDWord:
|
||||
ButtonPressed->Execute(NumbersAndOperatorsEnum::Dword);
|
||||
break;
|
||||
case BitLength::BitLengthWord:
|
||||
ButtonPressed->Execute(NumbersAndOperatorsEnum::Word);
|
||||
break;
|
||||
case BitLength::BitLengthByte:
|
||||
ButtonPressed->Execute(NumbersAndOperatorsEnum::Byte);
|
||||
break;
|
||||
}
|
||||
|
||||
// update memory list according to bit length
|
||||
SetMemorizedNumbersString();
|
||||
}
|
||||
}
|
||||
|
@@ -9,6 +9,7 @@
|
||||
#include "Common/CalculatorButtonUser.h"
|
||||
#include "HistoryViewModel.h"
|
||||
#include "MemoryItemViewModel.h"
|
||||
#include "Common/BitLength.h"
|
||||
|
||||
namespace CalculatorFunctionalTests
|
||||
{
|
||||
@@ -40,7 +41,6 @@ namespace CalculatorApp
|
||||
StandardCalculatorViewModel();
|
||||
void UpdateOperand(int pos, Platform::String ^ text);
|
||||
void UpdatecommandsInRecordingMode();
|
||||
int GetBitLengthType();
|
||||
int GetNumberBase();
|
||||
|
||||
OBSERVABLE_OBJECT_CALLBACK(OnPropertyChanged);
|
||||
@@ -54,6 +54,7 @@ namespace CalculatorApp
|
||||
OBSERVABLE_PROPERTY_RW(Platform::String ^, HexDisplayValue);
|
||||
OBSERVABLE_PROPERTY_RW(Platform::String ^, OctalDisplayValue);
|
||||
OBSERVABLE_NAMED_PROPERTY_RW(Platform::String ^, BinaryDisplayValue);
|
||||
OBSERVABLE_NAMED_PROPERTY_R(Windows::Foundation::Collections::IVector<bool> ^, BinaryDigits);
|
||||
OBSERVABLE_PROPERTY_RW(Platform::String ^, HexDisplayValue_AutomationName);
|
||||
OBSERVABLE_PROPERTY_RW(Platform::String ^, DecDisplayValue_AutomationName);
|
||||
OBSERVABLE_PROPERTY_RW(Platform::String ^, OctDisplayValue_AutomationName);
|
||||
@@ -72,10 +73,6 @@ namespace CalculatorApp
|
||||
OBSERVABLE_PROPERTY_RW(Platform::String ^, CalculationResultAutomationName);
|
||||
OBSERVABLE_PROPERTY_RW(Platform::String ^, CalculationExpressionAutomationName);
|
||||
OBSERVABLE_PROPERTY_RW(bool, IsShiftProgrammerChecked);
|
||||
OBSERVABLE_PROPERTY_RW(bool, IsQwordEnabled);
|
||||
OBSERVABLE_PROPERTY_RW(bool, IsDwordEnabled);
|
||||
OBSERVABLE_PROPERTY_RW(bool, IsWordEnabled);
|
||||
OBSERVABLE_PROPERTY_RW(bool, IsByteEnabled);
|
||||
OBSERVABLE_PROPERTY_RW(int, CurrentRadixType);
|
||||
OBSERVABLE_PROPERTY_RW(bool, AreTokensUpdated);
|
||||
OBSERVABLE_PROPERTY_RW(bool, AreAlwaysOnTopResultsUpdated);
|
||||
@@ -128,6 +125,13 @@ namespace CalculatorApp
|
||||
}
|
||||
}
|
||||
}
|
||||
static property Platform::String ^ IsBitFlipCheckedPropertyName
|
||||
{
|
||||
Platform::String ^ get()
|
||||
{
|
||||
return Platform::StringReference(L"IsBitFlipChecked");
|
||||
}
|
||||
}
|
||||
|
||||
property bool IsBinaryBitFlippingEnabled
|
||||
{
|
||||
@@ -145,6 +149,15 @@ namespace CalculatorApp
|
||||
}
|
||||
}
|
||||
|
||||
property CalculatorApp::Common::BitLength ValueBitLength
|
||||
{
|
||||
CalculatorApp::Common::BitLength get()
|
||||
{
|
||||
return m_valueBitLength;
|
||||
}
|
||||
void set(CalculatorApp::Common::BitLength value);
|
||||
}
|
||||
|
||||
property bool IsStandard
|
||||
{
|
||||
bool get()
|
||||
@@ -213,6 +226,13 @@ namespace CalculatorApp
|
||||
}
|
||||
}
|
||||
}
|
||||
static property Platform::String ^ IsProgrammerPropertyName
|
||||
{
|
||||
Platform::String ^ get()
|
||||
{
|
||||
return Platform::StringReference(L"IsProgrammer");
|
||||
}
|
||||
}
|
||||
|
||||
property bool IsAlwaysOnTop
|
||||
{
|
||||
@@ -433,6 +453,7 @@ namespace CalculatorApp
|
||||
bool m_operandUpdated;
|
||||
bool m_completeTextSelection;
|
||||
bool m_isLastOperationHistoryLoad;
|
||||
CalculatorApp::Common::BitLength m_valueBitLength;
|
||||
Platform::String ^ m_selectedExpressionLastData;
|
||||
Common::DisplayExpressionToken ^ m_selectedExpressionToken;
|
||||
|
||||
|
Reference in New Issue
Block a user