Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Always-on-Top mode implemented #579

Merged
merged 36 commits into from Jul 31, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
010f05b
Compact overlay mode implemented & memory buttons removed
greedyAI Jun 15, 2019
d8c66fa
Hide NavigationView when in AlwaysOnTop mode
greedyAI Jun 18, 2019
d408c3d
Always-on-top mode now saves and restores window size
greedyAI Jun 20, 2019
eb48d28
Responsiveness to screen size debugged
greedyAI Jun 21, 2019
4f232e6
All specced features completed
greedyAI Jun 27, 2019
b95129b
Rewriting logic of main expression result
greedyAI Jun 29, 2019
6d94e34
Scrolling behavior & AlwaysOnTop button icons working
greedyAI Jul 2, 2019
1c564ea
Feature complete
greedyAI Jul 10, 2019
a1fde4b
Icon fixes & AoT button only shows up in Standard mode
greedyAI Jul 10, 2019
9f57f8d
Mostly debugged
greedyAI Jul 12, 2019
dc69b61
More debugging & style improvements
greedyAI Jul 13, 2019
489fa2b
More stylistic improvements
greedyAI Jul 16, 2019
6adc733
More debugging & stylistic improvements
greedyAI Jul 17, 2019
90ba9dc
Crashing bug on converter/data calculation modes fixed
greedyAI Jul 18, 2019
c6e2025
More stylistic/UI updates
greedyAI Jul 19, 2019
c1ea0bf
Even more bug fixes & style improvements
greedyAI Jul 20, 2019
853ecbb
Font size fix
greedyAI Jul 20, 2019
fe9d89e
More debugging
greedyAI Jul 20, 2019
d2d9832
More UI fixes
greedyAI Jul 20, 2019
7da6a8d
More stylistic changes
greedyAI Jul 23, 2019
6cc40f6
Final bug/style fixes
greedyAI Jul 23, 2019
04846a1
Merged with master
greedyAI Jul 23, 2019
2dcf6b2
Telemetry endpoint added
greedyAI Jul 23, 2019
e8a8908
Manual tests added
greedyAI Jul 24, 2019
6b4ae8a
Small margin fix
greedyAI Jul 24, 2019
1afbcd3
Updated manual tests
greedyAI Jul 24, 2019
5efe0d7
Simplifying code a bit more
greedyAI Jul 25, 2019
29cd411
Final fixes!
greedyAI Jul 25, 2019
40fd2d6
Final feedback incorporated
greedyAI Jul 30, 2019
da55781
More feedback incorporated
greedyAI Jul 30, 2019
b82332a
Typo
greedyAI Jul 30, 2019
b7fe153
Merge branch 'master' into always-on-top
joseartrivera Jul 30, 2019
e9d6c6e
Font size change
greedyAI Jul 31, 2019
284291c
Merge branch 'always-on-top' of https://github.com/greedyAI/calculato…
greedyAI Jul 31, 2019
124514e
Final style updates!
greedyAI Jul 31, 2019
2f47cd9
Final style fixes!
greedyAI Jul 31, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
82 changes: 81 additions & 1 deletion docs/ManualTests.md
Expand Up @@ -54,6 +54,59 @@ Steps:
2. Select “miles” as the unit type in the output field
*Expected: The output starts with is “3.106856”*

### Always-on-Top

**Test 1**
Steps:
1. Launch the "Calculator" app and navigate to "Standard" Calculator
*Expected: Always-on-Top button's tooltip says "Keep on top"*
2. Click the Always-on-Top button
*Expected: Always-on-Top button's tooltip now says "Back to full view"*
3. Launch the "Notepad" app and put it in full-screen mode
*Expected: Calculator is still on top of Notepad and in Always-on-Top mode*

**Test 2**
Steps:
1. Launch the "Calculator" app and from "Standard" Calculator, input “3”, “+”, “3” (do not press “Enter”)
2. Tab over the Always-on-Top button and press "Enter" on the keyboard
*Expected: The application title, hamburger menu, calculator type title, calculation expression (the secondary line above the main display), history button and memory buttons are no longer visible. The main display shows "3"*
2. Press “Enter”
*Expected: The main display shows "6"*
3. Press "Ctrl-H" on the keyboard
*Expected: Nothing happens (history keyboard shortcuts are disabled)*
4. Press "Ctrl-P" on the keyboard, then tab over the Always-on-Top button and press "Enter" on the keyboard again
5. Open the Memory panel
*Expected: Nothing is stored in memory (memory keyboard shortcuts are disabled in Always-on-Top mode) and "6" is in history*

**Test 3**
Steps:
1. Launch the "Calculator" app and from "Standard" Calculator, click the Always-on-Top button
2. Resize the window horizontally
*Expected: The buttons automatically expand or shrink to fit the available screen size*
3. Resize the window vertically
*Expected: The buttons automatically expand or shrink to fit the available screen size and the percent, square-root, squared and reciprocal buttons disappear when the screen height is small*
4. Click the Always-on-Top button again
*Expected: Calculator is in Standard mode and the original window layout from before Step 1 is restored*
5. Click the Always-on-Top button again
*Expected: Calculator is in Always-on-Top mode and the window size from after Step 3 is restored*
6. Close the "Calculator" app
7. Launch the "Calculator" app again and click the Always-on-Top button
*Expected: The window size from right before closing from Always-on-Top mode (ie. after Step 5) is restored*

**Test 4**
Steps:
1. Launch the "Calculator" app and from "Standard" Calculator, click the Always-on-Top button
2. Input "/", "0", “Enter” on the keyboard
*Expected: "Result is undefined" is displayed in the system default app language*
3. Click the Always-on-Top button again
*Expected: Calculator is in Standard mode and all operator (except for "CE", "C", "Delete" and "=") and memory buttons are disabled

**Test 5**
Steps:
1. Launch the "Calculator" app and navigate to "Scientific" Calculator
*Expected: The Always-on-Top button is hidden*
2. Navigate to "Standard" Calculator
*Expected: The Always-on-Top button is visible*

## Basic Verification Tests

Expand Down Expand Up @@ -278,7 +331,7 @@ Steps:
Steps:
1. Launch the "Calculator" app.

For All Applicable Modes verify the following:
For All Applicable Modes verify the following (note: only 11-15 and 20 work in Always-on-Top mode):
2. Press **Alt +1** to Enter "Standard" mode
*Expected: Move to "Standard" screen.*
3. Press **Alt +2** to Enter "Scientific" mode
Expand Down Expand Up @@ -353,3 +406,30 @@ Steps:
61. Press **|** to Select 'Or'
62. Press **~** to Select 'Not'
63. Press **&** to Select 'And'

## Localization Tests

### Always-on-Top

**Test 1**
Steps:
1. Change the system default app language to Arabic
2. Launch the "Calculator" app and from "Standard" Calculator, click the Always-on-Top button
*Expected: UI/Menu is localized (for example, the title bar buttons is in right-to-left order)*
3. Input "/", "0", “Enter” on the keyboard
*Expected: Error message is in Arabic*

## Ease of Access Tests

### Always-on-Top

**Test 1**
Steps:
1. Open the "Narrator" app
2. Launch the "Calculator" app and from "Standard" Calculator, click the Always-on-Top button
3. Tab over the Always-on-Top button
*Expected: Narrator reads the localized version of "Back to full view"*
4. Tab over the main results field
*Expected: Narrator reads the localized version of exactly what's displayed (ie. "0")*
5. Tab over the rest of the UI elements
*Expected: Narrator reads the localized version of the UI elements' contents*
60 changes: 60 additions & 0 deletions src/CalcViewModel/ApplicationViewModel.cpp
Expand Up @@ -31,6 +31,8 @@ using namespace Windows::UI::Xaml::Controls;
using namespace Windows::UI::Xaml::Data;
using namespace Windows::UI::Xaml::Input;
using namespace Windows::UI::Xaml::Media;
using namespace Windows::Foundation;
using namespace Concurrency;

namespace
{
Expand All @@ -55,6 +57,7 @@ void ApplicationViewModel::Mode::set(ViewMode value)
{
PreviousMode = m_mode;
m_mode = value;
SetDisplayNormalAlwaysOnTopOption();
OnModeChanged();
RaisePropertyChanged(ModePropertyName);
}
Expand Down Expand Up @@ -204,3 +207,60 @@ void ApplicationViewModel::SetMenuCategories()
// property setter logic.
Categories = NavCategoryGroup::CreateMenuOptions();
}

void ApplicationViewModel::ToggleAlwaysOnTop(float width, float height)
{
HandleToggleAlwaysOnTop(width, height);
}

task<void> ApplicationViewModel::HandleToggleAlwaysOnTop(float width, float height)
{
if (ApplicationView::GetForCurrentView()->ViewMode == ApplicationViewMode::CompactOverlay)
{
ApplicationDataContainer ^ localSettings = ApplicationData::Current->LocalSettings;
localSettings->Values->Insert(WidthLocalSettings, width);
greedyAI marked this conversation as resolved.
Show resolved Hide resolved
localSettings->Values->Insert(HeightLocalSettings, height);

bool success = co_await ApplicationView::GetForCurrentView()->TryEnterViewModeAsync(ApplicationViewMode::Default);
CalculatorViewModel->AreHistoryShortcutsEnabled = success;
CalculatorViewModel->HistoryVM->AreHistoryShortcutsEnabled = success;
CalculatorViewModel->IsAlwaysOnTop = !success;
IsAlwaysOnTop = !success;
}
else
{
ApplicationDataContainer ^ localSettings = ApplicationData::Current->LocalSettings;
ViewModePreferences ^ compactOptions = ViewModePreferences::CreateDefault(ApplicationViewMode::CompactOverlay);
if (!localSettings->Values->GetView()->HasKey(LaunchedLocalSettings))
{
compactOptions->CustomSize = Size(320, 394);
localSettings->Values->Insert(LaunchedLocalSettings, true);
}
else
{
if (localSettings->Values->GetView()->HasKey(WidthLocalSettings) && localSettings->Values->GetView()->HasKey(HeightLocalSettings))
{
float oldWidth = safe_cast<IPropertyValue ^>(localSettings->Values->GetView()->Lookup(WidthLocalSettings))->GetSingle();
float oldHeight = safe_cast<IPropertyValue ^>(localSettings->Values->GetView()->Lookup(HeightLocalSettings))->GetSingle();
compactOptions->CustomSize = Size(oldWidth, oldHeight);
}
else
{
compactOptions->CustomSize = Size(320, 394);
}
}

bool success = co_await ApplicationView::GetForCurrentView()->TryEnterViewModeAsync(ApplicationViewMode::CompactOverlay, compactOptions);
CalculatorViewModel->AreHistoryShortcutsEnabled = !success;
CalculatorViewModel->HistoryVM->AreHistoryShortcutsEnabled = !success;
CalculatorViewModel->IsAlwaysOnTop = success;
IsAlwaysOnTop = success;
}
SetDisplayNormalAlwaysOnTopOption();
}

void ApplicationViewModel::SetDisplayNormalAlwaysOnTopOption()
{
DisplayNormalAlwaysOnTopOption =
m_mode == ViewMode::Standard && ApplicationView::GetForCurrentView()->IsViewModeSupported(ApplicationViewMode::CompactOverlay) && !IsAlwaysOnTop;
}
49 changes: 49 additions & 0 deletions src/CalcViewModel/ApplicationViewModel.h
Expand Up @@ -25,6 +25,9 @@ namespace CalculatorApp
OBSERVABLE_PROPERTY_RW(CalculatorApp::Common::ViewMode, PreviousMode);
OBSERVABLE_NAMED_PROPERTY_RW(Platform::String ^, CategoryName);

// Indicates whether calculator is currently in standard mode _and_ supports CompactOverlay _and_ is not in Always-on-Top mode
OBSERVABLE_PROPERTY_RW(bool, DisplayNormalAlwaysOnTopOption);

COMMAND_FOR_METHOD(CopyCommand, ApplicationViewModel::OnCopyCommand);
COMMAND_FOR_METHOD(PasteCommand, ApplicationViewModel::OnPasteCommand);

Expand Down Expand Up @@ -64,6 +67,48 @@ namespace CalculatorApp
}
}

static property Platform::String ^ LaunchedLocalSettings
{
Platform::String ^ get()
{
return Platform::StringReference(L"calculatorAlwaysOnTopLaunched");
}
}

static property Platform::String ^ WidthLocalSettings
{
Platform::String ^ get()
{
return Platform::StringReference(L"calculatorAlwaysOnTopLastWidth");
}
}

static property Platform::String ^ HeightLocalSettings
{
Platform::String ^ get()
{
return Platform::StringReference(L"calculatorAlwaysOnTopLastHeight");
}
}

property bool IsAlwaysOnTop
{
bool get()
{
return m_isAlwaysOnTop;
}
void set(bool value)
{
if (m_isAlwaysOnTop != value)
{
m_isAlwaysOnTop = value;
RaisePropertyChanged(L"IsAlwaysOnTop");
}
}
}

void ToggleAlwaysOnTop(float width, float height);

private:
bool TryRecoverFromNavigationModeFailure();

Expand All @@ -76,6 +121,10 @@ namespace CalculatorApp

CalculatorApp::Common::ViewMode m_mode;
Windows::Foundation::Collections::IObservableVector<CalculatorApp::Common::NavCategoryGroup ^> ^ m_categories;
Concurrency::task<void> HandleToggleAlwaysOnTop(float width, float height);
void SetDisplayNormalAlwaysOnTopOption();

bool m_isAlwaysOnTop;
};
}
}
5 changes: 3 additions & 2 deletions src/CalcViewModel/Common/KeyboardShortcutManager.cpp
Expand Up @@ -668,10 +668,11 @@ void KeyboardShortcutManager::OnAcceleratorKeyActivated(CoreDispatcher ^, Accele
if (nullptr != vm)
{
ViewMode toMode = NavCategory::GetViewModeForVirtualKey(static_cast<MyVirtualKey>(key));
if (NavCategory::IsValidViewMode(toMode))
auto nvi = dynamic_cast<MUXC::NavigationViewItem ^>(menuItems->GetAt(NavCategory::GetFlatIndex(toMode)));
if (nvi && nvi->IsEnabled && NavCategory::IsValidViewMode(toMode))
{
vm->Mode = toMode;
navView->SelectedItem = menuItems->GetAt(NavCategory::GetFlatIndex(toMode));
navView->SelectedItem = nvi;
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/CalcViewModel/Common/TraceLogger.cpp
Expand Up @@ -117,7 +117,7 @@ namespace CalculatorApp
return true;
}

void TraceLogger::LogVisualStateChanged(ViewMode mode, wstring_view state) const
void TraceLogger::LogVisualStateChanged(ViewMode mode, wstring_view state, bool isAlwaysOnTop) const
{
if (!GetTraceLoggingProviderEnabled())
{
Expand All @@ -128,6 +128,7 @@ namespace CalculatorApp
fields.AddGuid(L"SessionGuid", sessionGuid);
fields.AddString(L"CalcMode", NavCategory::GetFriendlyName(mode)->Data());
fields.AddString(L"VisualState", state);
fields.AddBoolean(L"IsAlwaysOnTop", isAlwaysOnTop);
fields.AddUInt64(PDT_PRIVACY_DATA_TAG, PDT_PRODUCT_AND_SERVICE_USAGE);
LogLevel2Event(EVENT_NAME_VISUAL_STATE_CHANGED, fields);
}
Expand Down
2 changes: 1 addition & 1 deletion src/CalcViewModel/Common/TraceLogger.h
Expand Up @@ -45,7 +45,7 @@ namespace CalculatorApp
void LogDateCalculationModeUsed(bool AddSubtractMode);
void UpdateWindowCount(size_t windowCount = 0);
bool IsWindowIdInLog(int windowId);
void LogVisualStateChanged(CalculatorApp::Common::ViewMode mode, std::wstring_view state) const;
void LogVisualStateChanged(CalculatorApp::Common::ViewMode mode, std::wstring_view state, bool isAlwaysOnTop = false) const;
void LogWindowCreated(CalculatorApp::Common::ViewMode mode, int windowId);
void LogConverterInputReceived(CalculatorApp::Common::ViewMode mode) const;
void LogNavBarOpened() const;
Expand Down
10 changes: 8 additions & 2 deletions src/CalcViewModel/StandardCalculatorViewModel.cpp
Expand Up @@ -35,6 +35,7 @@ namespace
StringReference IsStandardPropertyName(L"IsStandard");
StringReference IsScientificPropertyName(L"IsScientific");
StringReference IsProgrammerPropertyName(L"IsProgrammer");
StringReference IsAlwaysOnTopPropertyName(L"IsAlwaysOnTop");
StringReference DisplayValuePropertyName(L"DisplayValue");
StringReference CalculationResultAutomationNamePropertyName(L"CalculationResultAutomationName");
StringReference IsBitFlipCheckedPropertyName(L"IsBitFlipChecked");
Expand Down Expand Up @@ -202,7 +203,12 @@ void StandardCalculatorViewModel::SetPrimaryDisplay(_In_ wstring const& displayS
// not match what the narrator is saying
m_CalculationResultAutomationName = CalculateNarratorDisplayValue(displayStringValue, localizedDisplayStringValue, isError);

DisplayValue = localizedDisplayStringValue;
AreAlwaysOnTopResultsUpdated = false;
if (DisplayValue != localizedDisplayStringValue)
{
DisplayValue = localizedDisplayStringValue;
AreAlwaysOnTopResultsUpdated = true;
}

IsInError = isError;

Expand Down Expand Up @@ -415,7 +421,7 @@ void StandardCalculatorViewModel::SetMemorizedNumbers(const vector<wstring>& new
memorySlot->Value = Utils::LRO + ref new String(stringValue.c_str()) + Utils::PDF;

MemorizedNumbers->InsertAt(0, memorySlot);
IsMemoryEmpty = false;
IsMemoryEmpty = IsAlwaysOnTop;

// Update the slot position for the rest of the slots
for (unsigned int i = 1; i < MemorizedNumbers->Size; i++)
Expand Down
18 changes: 18 additions & 0 deletions src/CalcViewModel/StandardCalculatorViewModel.h
Expand Up @@ -78,6 +78,7 @@ namespace CalculatorApp
OBSERVABLE_PROPERTY_RW(bool, IsByteEnabled);
OBSERVABLE_PROPERTY_RW(int, CurrentRadixType);
OBSERVABLE_PROPERTY_RW(bool, AreTokensUpdated);
OBSERVABLE_PROPERTY_RW(bool, AreAlwaysOnTopResultsUpdated);
OBSERVABLE_PROPERTY_RW(bool, AreHistoryShortcutsEnabled);
OBSERVABLE_PROPERTY_RW(bool, AreProgrammerRadixOperatorsEnabled);
OBSERVABLE_PROPERTY_RW(CalculatorApp::Common::Automation::NarratorAnnouncement ^, Announcement);
Expand Down Expand Up @@ -213,6 +214,22 @@ namespace CalculatorApp
}
}

property bool IsAlwaysOnTop
{
bool get()
{
return m_isAlwaysOnTop;
}
void set(bool value)
{
if (m_isAlwaysOnTop != value)
{
m_isAlwaysOnTop = value;
RaisePropertyChanged(L"IsAlwaysOnTop");
}
}
}

property bool IsEditingEnabled
{
bool get()
Expand Down Expand Up @@ -406,6 +423,7 @@ namespace CalculatorApp
bool m_isStandard;
bool m_isScientific;
bool m_isProgrammer;
bool m_isAlwaysOnTop;
bool m_isBinaryBitFlippingEnabled;
bool m_isBitFlipChecked;
bool m_isShiftChecked;
Expand Down
1 change: 1 addition & 0 deletions src/CalcViewModel/pch.h
Expand Up @@ -30,6 +30,7 @@
#include <concrt.h>
#include <regex>
#include <iterator>
#include <intsafe.h>
// C++\WinRT Headers
#include "winrt/base.h"
#include "winrt/Windows.Foundation.Diagnostics.h"
Expand Down
12 changes: 12 additions & 0 deletions src/Calculator/App.xaml
Expand Up @@ -128,6 +128,8 @@
<x:Double x:Key="CalcStandardOperatorCaptionSizeLarge">24</x:Double>
<!-- Numpad Standard/Scientific in Fill/Full -->
<x:Double x:Key="CalcStandardOperatorCaptionSize">20</x:Double>
<x:Double x:Key="CalcStandardOperatorCaptionSizeSmall">15</x:Double>
<x:Double x:Key="CalcStandardOperatorCaptionSizeTiny">12</x:Double>
<!-- Standard Operators Standard/Scientific in Fill/Full -->
<x:Double x:Key="CalcOperatorCaptionSize">15</x:Double>

Expand Down Expand Up @@ -210,11 +212,21 @@
TargetType="Controls:CalculatorButton">
<Setter Property="FontWeight" Value="SemiBold"/>
</Style>
<Style x:Key="NumericButtonStyle10"
BasedOn="{StaticResource NumericButtonStyle}"
TargetType="Controls:CalculatorButton">
<Setter Property="FontSize" Value="10"/>
</Style>
<Style x:Key="NumericButtonStyle12"
BasedOn="{StaticResource NumericButtonStyle}"
TargetType="Controls:CalculatorButton">
<Setter Property="FontSize" Value="12"/>
</Style>
<Style x:Key="NumericButtonStyle16"
BasedOn="{StaticResource NumericButtonStyle}"
TargetType="Controls:CalculatorButton">
<Setter Property="FontSize" Value="16"/>
</Style>
<Style x:Key="NumericButtonStyle18"
BasedOn="{StaticResource NumericButtonStyle}"
TargetType="Controls:CalculatorButton">
Expand Down