From 07d012cf6b6501d6a084f5744d8c2d6743c433bf Mon Sep 17 00:00:00 2001 From: Rudy Huyn Date: Tue, 10 Dec 2019 11:06:37 -0800 Subject: [PATCH] [Graph] Replace the Add button by a EquationTextBlock (#826) * init * Replace the Add equation button by an EquationTextBox * Move automatically the focus to the next textbox when users press Enter * nit * localize the placeholder * rebase * rebased and disable remove context menu when the equation is the last one * replace storyboards by setters in visual states --- .../GraphingCalculator/EquationViewModel.h | 1 + src/Calculator/App.xaml | 227 ++++++------------ src/Calculator/Calculator.vcxproj | 2 + src/Calculator/Calculator.vcxproj.filters | 11 +- src/Calculator/Controls/EquationTextBox.cpp | 99 ++++++-- src/Calculator/Controls/EquationTextBox.h | 68 +++--- src/Calculator/Resources/en-US/Resources.resw | 8 +- src/Calculator/Utils/VisualTree.cpp | 104 ++++++++ src/Calculator/Utils/VisualTree.h | 50 ++++ .../GraphingCalculator/EquationInputArea.xaml | 56 +---- .../EquationInputArea.xaml.cpp | 90 +++++-- .../EquationInputArea.xaml.h | 14 +- 12 files changed, 449 insertions(+), 281 deletions(-) create mode 100644 src/Calculator/Utils/VisualTree.cpp create mode 100644 src/Calculator/Utils/VisualTree.h diff --git a/src/CalcViewModel/GraphingCalculator/EquationViewModel.h b/src/CalcViewModel/GraphingCalculator/EquationViewModel.h index cf435e6f..299569b6 100644 --- a/src/CalcViewModel/GraphingCalculator/EquationViewModel.h +++ b/src/CalcViewModel/GraphingCalculator/EquationViewModel.h @@ -41,6 +41,7 @@ public OBSERVABLE_OBJECT(); OBSERVABLE_PROPERTY_R(GraphControl::Equation ^, GraphEquation); OBSERVABLE_PROPERTY_RW(int, FunctionLabelIndex); + OBSERVABLE_PROPERTY_RW(bool, IsLastItemInList); property Platform::String ^ Expression { diff --git a/src/Calculator/App.xaml b/src/Calculator/App.xaml index 7d75721e..957adc61 100644 --- a/src/Calculator/App.xaml +++ b/src/Calculator/App.xaml @@ -3,6 +3,7 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:Controls="using:CalculatorApp.Controls" xmlns:common="using:CalculatorApp.Common" + xmlns:contract7Present="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract,7)" xmlns:local="using:CalculatorApp"> @@ -68,10 +69,10 @@ FallbackColor="{ThemeResource SystemChromeMediumColor}" TintColor="{ThemeResource SystemChromeLowColor}" TintOpacity="0.7"/> + - @@ -164,6 +165,7 @@ FallbackColor="{ThemeResource SystemChromeMediumColor}" TintColor="{ThemeResource SystemChromeLowColor}" TintOpacity="0.8"/> + @@ -222,6 +224,7 @@ + @@ -1856,7 +1859,6 @@ AutomationProperties.AccessibilityView="Raw" Content="{TemplateBinding Description}" x:Load="False"/> - @@ -1890,155 +1892,71 @@ - - - - - - + + + + + + + + + + + - - - - - - - - - - - - Visible - - - - + + + + + - - - - - - - - - - Visible - - - - - - - Visible - - - - - - - Visible - - - - - - - Collapsed - - - - + + + + + + + - - - - - - - - - - - - - Visible - - - - - - - Collapsed - - - - - - - Visible - - - - - - - Collapsed - - - - + + + + + + + + - - - - - - - - - - - - + + + + + - - - - - - - - - + + + + - - - - - - - Visible - - - - - - - Collapsed - - - - + + + + + + + + + + @@ -2158,8 +2076,8 @@ Grid.Column="1" Background="{ThemeResource TextControlBackground}" BorderBrush="{TemplateBinding EquationColor}" - BorderThickness="{TemplateBinding BorderThickness}"> - + BorderThickness="{TemplateBinding BorderThickness}" + contract7Present:BackgroundSizing="OuterBorderEdge"> @@ -2218,28 +2136,29 @@ Visibility="Collapsed"/> - diff --git a/src/Calculator/Views/GraphingCalculator/EquationInputArea.xaml.cpp b/src/Calculator/Views/GraphingCalculator/EquationInputArea.xaml.cpp index 3c8aa894..6b960c0c 100644 --- a/src/Calculator/Views/GraphingCalculator/EquationInputArea.xaml.cpp +++ b/src/Calculator/Views/GraphingCalculator/EquationInputArea.xaml.cpp @@ -3,6 +3,7 @@ #include "pch.h" #include "EquationInputArea.xaml.h" +#include "Utils/VisualTree.h" using namespace CalculatorApp; using namespace CalculatorApp::Common; @@ -21,6 +22,7 @@ using namespace Windows::UI::Xaml::Controls; using namespace Windows::UI::Xaml::Controls::Primitives; using namespace Windows::UI::Xaml::Input; using namespace GraphControl; +using namespace Calculator::Utils; namespace { @@ -31,6 +33,7 @@ EquationInputArea::EquationInputArea() : m_lastLineColorIndex{ -1 } , m_AvailableColors{ ref new Vector() } , m_accessibilitySettings{ ref new AccessibilitySettings() } + , m_equationToFocus{ nullptr } { m_accessibilitySettings->HighContrastChanged += ref new TypedEventHandler(this, &EquationInputArea::OnHighContrastChanged); @@ -56,14 +59,15 @@ void EquationInputArea::OnEquationsPropertyChanged() } } -void EquationInputArea::AddEquationButton_Click(Object ^ sender, RoutedEventArgs ^ e) -{ - AddNewEquation(); -} - void EquationInputArea::AddNewEquation() { auto eq = ref new EquationViewModel(ref new Equation()); + eq->IsLastItemInList = true; + + if (Equations->Size > 0) + { + Equations->GetAt(Equations->Size - 1)->IsLastItemInList = false; + } m_lastLineColorIndex = (m_lastLineColorIndex + 1) % AvailableColors->Size; @@ -71,7 +75,7 @@ void EquationInputArea::AddNewEquation() eq->IsLineEnabled = true; eq->FunctionLabelIndex = ++m_lastFunctionLabelIndex; Equations->Append(eq); - EquationInputList->ScrollIntoView(eq); + m_equationToFocus = eq; } void EquationInputArea::InputTextBox_GotFocus(Object ^ sender, RoutedEventArgs ^ e) @@ -84,20 +88,65 @@ void EquationInputArea::InputTextBox_LostFocus(Object ^ sender, RoutedEventArgs KeyboardShortcutManager::HonorShortcuts(true); } -void EquationInputArea::InputTextBox_Submitted(Object ^ sender, RoutedEventArgs ^ e) +void EquationInputArea::InputTextBox_Submitted(Object ^ sender, EquationSubmissionSource source) { auto tb = static_cast(sender); - auto eq = static_cast(tb->DataContext); - - // eq can be null if the equation has been removed - if (eq != nullptr) + if (tb == nullptr) { - eq->Expression = tb->GetEquationText(); + return; + } + auto eq = static_cast(tb->DataContext); + if (eq == nullptr) + { + return; } - if (tb->HasFocus) + auto expressionText = tb->GetEquationText(); + if (source == EquationSubmissionSource::FOCUS_LOST && eq->Expression == expressionText) { - FocusManager::TryMoveFocus(::FocusNavigationDirection::Left); + // The expression didn't change. + return; + } + + eq->Expression = expressionText; + + if (source == EquationSubmissionSource::ENTER_KEY || eq->Expression != nullptr && eq->Expression->Length() > 0) + { + unsigned int index = 0; + if (Equations->IndexOf(eq, &index) && index == Equations->Size - 1) + { + // If it's the last equation of the list + AddNewEquation(); + } + else + { + auto nextEquation = Equations->GetAt(index + 1); + FocusEquationTextBox(nextEquation); + } + } +} + +void EquationInputArea::FocusEquationTextBox(EquationViewModel ^ equation) +{ + auto nextContainer = EquationInputList->ContainerFromItem(equation); + if (nextContainer == nullptr) + { + return; + } + auto listviewItem = dynamic_cast(nextContainer); + if (listviewItem == nullptr) + { + return; + } + auto equationInput = VisualTree::FindDescendantByName(nextContainer, "EquationInputButton"); + if (equationInput == nullptr) + { + return; + } + auto equationTextBox = dynamic_cast(equationInput); + if (equationTextBox != nullptr) + { + equationTextBox->FocusTextBox(); } } @@ -113,6 +162,10 @@ void EquationInputArea::EquationTextBox_RemoveButtonClicked(Object ^ sender, Rou m_lastFunctionLabelIndex--; } + if (index == Equations->Size - 1 && Equations->Size > 1) + { + Equations->GetAt(Equations->Size - 2)->IsLastItemInList = true; + } Equations->RemoveAt(index); } } @@ -124,7 +177,7 @@ void EquationInputArea::EquationTextBox_KeyGraphFeaturesButtonClicked(Object ^ s // ensure the equation has been submitted before trying to get key graph features out of it if (tb->HasFocus) { - EquationInputArea::InputTextBox_Submitted(sender, e); + EquationInputArea::InputTextBox_Submitted(sender, EquationSubmissionSource::FOCUS_LOST); } auto eq = static_cast(tb->DataContext); @@ -143,10 +196,15 @@ void EquationInputArea::EquationTextBox_EquationButtonClicked(Object ^ sender, R void EquationInputArea::EquationTextBoxLoaded(Object ^ sender, RoutedEventArgs ^ e) { auto tb = static_cast(sender); - auto eq = static_cast(tb->DataContext); auto colorChooser = static_cast(tb->ColorChooserFlyout->Content); colorChooser->AvailableColors = AvailableColors; + + if (tb->DataContext == m_equationToFocus) + { + m_equationToFocus = nullptr; + tb->FocusTextBox(); + } } void EquationInputArea::OnHighContrastChanged(AccessibilitySettings ^ sender, Object ^ args) diff --git a/src/Calculator/Views/GraphingCalculator/EquationInputArea.xaml.h b/src/Calculator/Views/GraphingCalculator/EquationInputArea.xaml.h index 8d5996db..17a5f582 100644 --- a/src/Calculator/Views/GraphingCalculator/EquationInputArea.xaml.h +++ b/src/Calculator/Views/GraphingCalculator/EquationInputArea.xaml.h @@ -29,23 +29,25 @@ namespace CalculatorApp void OnPropertyChanged(Platform::String^ propertyName); void OnEquationsPropertyChanged(); - void AddEquationButton_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); void AddNewEquation(); void InputTextBox_GotFocus(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); void InputTextBox_LostFocus(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); - void InputTextBox_Submitted(Platform::Object ^ sender, Windows::UI::Xaml::RoutedEventArgs ^ e); + void InputTextBox_Submitted(Platform::Object ^ sender, CalculatorApp::Controls::EquationSubmissionSource e); void OnHighContrastChanged(Windows::UI::ViewManagement::AccessibilitySettings ^ sender, Platform::Object ^ args); void ReloadAvailableColors(bool isHighContrast); + void FocusEquationTextBox(ViewModel::EquationViewModel ^ equation); + + void EquationTextBox_RemoveButtonClicked(Platform::Object ^ sender, Windows::UI::Xaml::RoutedEventArgs ^ e); + void EquationTextBox_KeyGraphFeaturesButtonClicked(Platform::Object ^ sender, Windows::UI::Xaml::RoutedEventArgs ^ e); + void EquationTextBox_EquationButtonClicked(Platform::Object ^ sender, Windows::UI::Xaml::RoutedEventArgs ^ e); + void EquationTextBoxLoaded(Platform::Object ^ sender, Windows::UI::Xaml::RoutedEventArgs ^ e); private: Windows::UI::ViewManagement::AccessibilitySettings ^ m_accessibilitySettings; int m_lastLineColorIndex; int m_lastFunctionLabelIndex; - void EquationTextBox_RemoveButtonClicked(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); - void EquationTextBox_KeyGraphFeaturesButtonClicked(Platform::Object ^ sender, Windows::UI::Xaml::RoutedEventArgs ^ e); - void EquationTextBox_EquationButtonClicked(Platform::Object ^ sender, Windows::UI::Xaml::RoutedEventArgs ^ e); - void EquationTextBoxLoaded(Platform::Object ^ sender, Windows::UI::Xaml::RoutedEventArgs ^ e); + ViewModel::EquationViewModel ^ m_equationToFocus; }; }