diff --git a/src/Calculator/App.xaml b/src/Calculator/App.xaml index c550cfe..68d6963 100644 --- a/src/Calculator/App.xaml +++ b/src/Calculator/App.xaml @@ -2101,6 +2101,7 @@ FontWeight="{TemplateBinding FontWeight}" AcceptsReturn="false" InputScope="Text" + MathText="{Binding MathEquation, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" MaxLength="2048" TextWrapping="NoWrap"> diff --git a/src/Calculator/Controls/EquationTextBox.cpp b/src/Calculator/Controls/EquationTextBox.cpp index ef3d751..102ff84 100644 --- a/src/Calculator/Controls/EquationTextBox.cpp +++ b/src/Calculator/Controls/EquationTextBox.cpp @@ -26,6 +26,7 @@ DEPENDENCY_PROPERTY_INITIALIZATION(EquationTextBox, ColorChooserFlyout); DEPENDENCY_PROPERTY_INITIALIZATION(EquationTextBox, EquationButtonContentIndex); DEPENDENCY_PROPERTY_INITIALIZATION(EquationTextBox, HasError); DEPENDENCY_PROPERTY_INITIALIZATION(EquationTextBox, IsAddEquationMode); +DEPENDENCY_PROPERTY_INITIALIZATION(EquationTextBox, MathEquation); EquationTextBox::EquationTextBox() { @@ -51,8 +52,9 @@ void EquationTextBox::OnApplyTemplate() { m_richEditBox->GotFocus += ref new RoutedEventHandler(this, &EquationTextBox::OnRichEditBoxGotFocus); m_richEditBox->LostFocus += ref new RoutedEventHandler(this, &EquationTextBox::OnRichEditBoxLostFocus); - m_richEditBox->TextChanged += ref new RoutedEventHandler(this, &EquationTextBox::OnRichEditBoxTextChanged); m_richEditBox->SelectionFlyout = nullptr; + m_richEditBox->EquationSubmitted += + ref new EventHandler(this, &EquationTextBox::OnEquationSubmitted); } if (m_equationButton != nullptr) @@ -69,7 +71,7 @@ void EquationTextBox::OnApplyTemplate() if (m_richEditContextMenu != nullptr) { - m_richEditContextMenu->Opening += ref new Windows::Foundation::EventHandler(this, &EquationTextBox::OnRichEditMenuOpening); + m_richEditContextMenu->Opening += ref new EventHandler(this, &EquationTextBox::OnRichEditMenuOpening); } if (m_kgfEquationButton != nullptr) @@ -150,37 +152,6 @@ void EquationTextBox::OnPointerCaptureLost(PointerRoutedEventArgs ^ e) UpdateCommonVisualState(); } -void EquationTextBox::OnKeyDown(KeyRoutedEventArgs ^ e) -{ - if (e->Key == VirtualKey::Enter) - { - m_sourceSubmission = EquationSubmissionSource::ENTER_KEY; - // We will rely on OnLostFocus to submit the equation to prevent the launch of 2 events - if (!m_HasFocus || !FocusManager::TryMoveFocusAsync(::FocusNavigationDirection::Next)) - { - m_sourceSubmission = EquationSubmissionSource::FOCUS_LOST; - EquationSubmitted(this, EquationSubmissionSource::ENTER_KEY); - if (m_functionButton && m_richEditBox->MathText != L"") - { - m_functionButton->IsEnabled = true; - } - } - } -} - -void EquationTextBox::OnLostFocus(RoutedEventArgs ^ e) -{ - if (m_richEditBox == nullptr || m_richEditBox->ContextFlyout->IsOpen) - { - return; - } - - if (m_functionButton && m_richEditBox->MathText != L"") - { - m_functionButton->IsEnabled = true; - } -} - void EquationTextBox::OnColorFlyoutOpened(Object ^ sender, Object ^ e) { m_isColorChooserFlyoutOpen = true; @@ -194,15 +165,9 @@ void EquationTextBox::OnColorFlyoutClosed(Object ^ sender, Object ^ e) UpdateCommonVisualState(); } -void EquationTextBox::OnRichEditBoxTextChanged(Object ^ sender, RoutedEventArgs ^ e) -{ - UpdateButtonsVisualState(); -} - void EquationTextBox::OnRichEditBoxGotFocus(Object ^ sender, RoutedEventArgs ^ e) { m_HasFocus = true; - m_sourceSubmission = EquationSubmissionSource::FOCUS_LOST; UpdateCommonVisualState(); UpdateButtonsVisualState(); } @@ -216,8 +181,6 @@ void EquationTextBox::OnRichEditBoxLostFocus(Object ^ sender, RoutedEventArgs ^ UpdateCommonVisualState(); UpdateButtonsVisualState(); - - EquationSubmitted(this, m_sourceSubmission); } void EquationTextBox::OnDeleteButtonClicked(Object ^ sender, RoutedEventArgs ^ e) @@ -413,6 +376,19 @@ void EquationTextBox::FocusTextBox() { if (m_richEditBox != nullptr) { - m_richEditBox->Focus(::FocusState::Programmatic); + FocusManager::TryFocusAsync(m_richEditBox, ::FocusState::Programmatic); } } + +void EquationTextBox::OnEquationSubmitted(Platform::Object ^ sender, MathRichEditBoxSubmission ^ args) +{ + if (args->HasTextChanged) + { + if (m_functionButton && m_richEditBox->MathText != L"") + { + m_functionButton->IsEnabled = true; + } + } + + EquationSubmitted(this, args); +} diff --git a/src/Calculator/Controls/EquationTextBox.h b/src/Calculator/Controls/EquationTextBox.h index 53af156..add3467 100644 --- a/src/Calculator/Controls/EquationTextBox.h +++ b/src/Calculator/Controls/EquationTextBox.h @@ -11,13 +11,6 @@ namespace CalculatorApp { namespace Controls { - public - enum class EquationSubmissionSource - { - FOCUS_LOST, - ENTER_KEY - }; - public ref class EquationTextBox sealed : public Windows::UI::Xaml::Controls::Control { @@ -28,6 +21,7 @@ namespace CalculatorApp DEPENDENCY_PROPERTY(Windows::UI::Xaml::Media::SolidColorBrush ^, EquationColor); DEPENDENCY_PROPERTY(Windows::UI::Xaml::Controls::Flyout ^, ColorChooserFlyout); DEPENDENCY_PROPERTY(Platform::String ^, EquationButtonContentIndex); + DEPENDENCY_PROPERTY(Platform::String ^, MathEquation); DEPENDENCY_PROPERTY_WITH_CALLBACK(bool, HasError); DEPENDENCY_PROPERTY_WITH_CALLBACK(bool, IsAddEquationMode); @@ -35,7 +29,7 @@ namespace CalculatorApp event Windows::UI::Xaml::RoutedEventHandler ^ RemoveButtonClicked; event Windows::UI::Xaml::RoutedEventHandler ^ KeyGraphFeaturesButtonClicked; - event Windows::Foundation::EventHandler ^ EquationSubmitted; + event Windows::Foundation::EventHandler ^ EquationSubmitted; event Windows::UI::Xaml::RoutedEventHandler ^ EquationButtonClicked; Platform::String ^ GetEquationText(); @@ -48,8 +42,6 @@ namespace CalculatorApp virtual void OnPointerExited(Windows::UI::Xaml::Input::PointerRoutedEventArgs ^ e) override; virtual void OnPointerCanceled(Windows::UI::Xaml::Input::PointerRoutedEventArgs ^ e) override; virtual void OnPointerCaptureLost(Windows::UI::Xaml::Input::PointerRoutedEventArgs ^ e) override; - virtual void OnKeyDown(Windows::UI::Xaml::Input::KeyRoutedEventArgs ^ e) override; - virtual void OnLostFocus(Windows::UI::Xaml::RoutedEventArgs ^ e) override; void OnIsAddEquationModePropertyChanged(bool oldValue, bool newValue); private: @@ -59,7 +51,6 @@ namespace CalculatorApp void OnRichEditBoxGotFocus(Platform::Object ^ sender, Windows::UI::Xaml::RoutedEventArgs ^ e); void OnRichEditBoxLostFocus(Platform::Object ^ sender, Windows::UI::Xaml::RoutedEventArgs ^ e); - void OnRichEditBoxTextChanged(Platform::Object ^ sender, Windows::UI::Xaml::RoutedEventArgs ^ e); void OnDeleteButtonClicked(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); void OnEquationButtonClicked(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); @@ -89,7 +80,7 @@ namespace CalculatorApp bool m_isPointerOver; bool m_isColorChooserFlyoutOpen; - EquationSubmissionSource m_sourceSubmission; - }; + void OnEquationSubmitted(Platform::Object ^ sender, CalculatorApp::Controls::MathRichEditBoxSubmission ^ args); + }; } } diff --git a/src/Calculator/Controls/MathRichEditBox.cpp b/src/Calculator/Controls/MathRichEditBox.cpp index ca3489a..384f564 100644 --- a/src/Calculator/Controls/MathRichEditBox.cpp +++ b/src/Calculator/Controls/MathRichEditBox.cpp @@ -13,6 +13,7 @@ using namespace Windows::ApplicationModel; using namespace Windows::UI::Xaml; using namespace Windows::UI::Xaml::Controls; using namespace Windows::Foundation::Collections; +using namespace Windows::System; DEPENDENCY_PROPERTY_INITIALIZATION(MathRichEditBox, MathText); @@ -75,6 +76,9 @@ MathRichEditBox::MathRichEditBox() { throw Exception::CreateException(hr); } + this->LosingFocus += ref new Windows::Foundation::TypedEventHandler( + this, &CalculatorApp::Controls::MathRichEditBox::OnLosingFocus); + this->KeyUp += ref new Windows::UI::Xaml::Input::KeyEventHandler(this, &CalculatorApp::Controls::MathRichEditBox::OnKeyUp); } String ^ MathRichEditBox::GetMathTextProperty() @@ -111,4 +115,41 @@ void MathRichEditBox::SetMathTextProperty(String ^ newValue) } this->IsReadOnly = readOnlyState; + SetValue(MathTextProperty, newValue); +} + +void CalculatorApp::Controls::MathRichEditBox::OnLosingFocus(Windows::UI::Xaml::UIElement ^ sender, Windows::UI::Xaml::Input::LosingFocusEventArgs ^ args) +{ + auto newVal = GetMathTextProperty(); + if (MathText != newVal) + { + SetValue(MathTextProperty, newVal); + EquationSubmitted(this, ref new MathRichEditBoxSubmission(true, EquationSubmissionSource::FOCUS_LOST)); + } + else + { + EquationSubmitted(this, ref new MathRichEditBoxSubmission(false, EquationSubmissionSource::FOCUS_LOST)); + } +} + +void CalculatorApp::Controls::MathRichEditBox::OnKeyUp(Platform::Object ^ sender, Windows::UI::Xaml::Input::KeyRoutedEventArgs ^ e) +{ + if (e->Key == VirtualKey::Enter) + { + auto newVal = GetMathTextProperty(); + if (MathText != newVal) + { + SetValue(MathTextProperty, newVal); + EquationSubmitted(this, ref new MathRichEditBoxSubmission(true, EquationSubmissionSource::ENTER_KEY)); + } + else + { + EquationSubmitted(this, ref new MathRichEditBoxSubmission(true, EquationSubmissionSource::ENTER_KEY)); + } + } +} + +void MathRichEditBox::OnMathTextPropertyChanged(Platform::String ^ oldValue, Platform::String ^ newValue) +{ + SetMathTextProperty(newValue); } diff --git a/src/Calculator/Controls/MathRichEditBox.h b/src/Calculator/Controls/MathRichEditBox.h index b57f406..eb605f2 100644 --- a/src/Calculator/Controls/MathRichEditBox.h +++ b/src/Calculator/Controls/MathRichEditBox.h @@ -8,6 +8,27 @@ namespace CalculatorApp { namespace Controls { + public + enum class EquationSubmissionSource + { + FOCUS_LOST, + ENTER_KEY, + }; + + public + ref class MathRichEditBoxSubmission sealed + { + public: + PROPERTY_R(bool, HasTextChanged); + PROPERTY_R(EquationSubmissionSource, Source); + public: + MathRichEditBoxSubmission(bool hasTextChanged, EquationSubmissionSource source) + : m_HasTextChanged(hasTextChanged) + , m_Source(source) + { + } + }; + public ref class MathRichEditBox sealed : Windows::UI::Xaml::Controls::RichEditBox { @@ -15,35 +36,17 @@ namespace CalculatorApp MathRichEditBox(); DEPENDENCY_PROPERTY_OWNER(MathRichEditBox); + DEPENDENCY_PROPERTY_WITH_DEFAULT_AND_CALLBACK(Platform::String ^, MathText, L""); - static property Windows::UI::Xaml::DependencyProperty ^ MathTextProperty - { - Windows::UI::Xaml::DependencyProperty ^ get() { - return s_MathTextProperty; - } - } - property Platform::String ^ MathText - { - Platform::String ^ get() - { - return GetMathTextProperty(); - } - void set(Platform::String^ value) - { - SetMathTextProperty(value); - } - - } + event Windows::Foundation::EventHandler ^ EquationSubmitted; + void OnMathTextPropertyChanged(Platform::String ^ oldValue, Platform::String ^ newValue); - private : + private: Platform::String ^ GetMathTextProperty(); void SetMathTextProperty(Platform::String ^ newValue); - static Windows::UI::Xaml::DependencyProperty ^ s_MathTextProperty; - static Windows::UI::Xaml::DependencyProperty ^ InitializeMathTextProperty() - { - return Utils::RegisterDependencyProperty(L"MathText"); - } + void OnLosingFocus(Windows::UI::Xaml::UIElement ^ sender, Windows::UI::Xaml::Input::LosingFocusEventArgs ^ args); + void OnKeyUp(Platform::Object ^ sender, Windows::UI::Xaml::Input::KeyRoutedEventArgs ^ e); }; } } diff --git a/src/Calculator/Views/GraphingCalculator/EquationInputArea.xaml b/src/Calculator/Views/GraphingCalculator/EquationInputArea.xaml index 3f82bfa..b076621 100644 --- a/src/Calculator/Views/GraphingCalculator/EquationInputArea.xaml +++ b/src/Calculator/Views/GraphingCalculator/EquationInputArea.xaml @@ -243,6 +243,7 @@ KeyGraphFeaturesButtonClicked="EquationTextBox_KeyGraphFeaturesButtonClicked" Loaded="InputTextBox_Loaded" LostFocus="InputTextBox_LostFocus" + MathEquation="{x:Bind Expression, Mode=TwoWay}" RemoveButtonClicked="EquationTextBox_RemoveButtonClicked"> (sender); if (tb == nullptr) @@ -97,16 +97,8 @@ void EquationInputArea::InputTextBox_Submitted(Object ^ sender, EquationSubmissi return; } - auto expressionText = tb->GetEquationText(); - if (source == EquationSubmissionSource::FOCUS_LOST && eq->Expression == expressionText) - { - // The expression didn't change. - return; - } - - eq->Expression = expressionText; - - if (source == EquationSubmissionSource::ENTER_KEY || eq->Expression != nullptr && eq->Expression->Length() > 0) + if (submission->Source == EquationSubmissionSource::ENTER_KEY || + (submission->Source == EquationSubmissionSource::FOCUS_LOST && submission->HasTextChanged && eq->Expression != nullptr && eq->Expression->Length() > 0)) { unsigned int index = 0; if (Equations->IndexOf(eq, &index)) @@ -180,13 +172,6 @@ void EquationInputArea::EquationTextBox_RemoveButtonClicked(Object ^ sender, Rou void EquationInputArea::EquationTextBox_KeyGraphFeaturesButtonClicked(Object ^ sender, RoutedEventArgs ^ e) { auto tb = static_cast(sender); - - // ensure the equation has been submitted before trying to get key graph features out of it - if (tb->HasFocus) - { - EquationInputArea::InputTextBox_Submitted(sender, EquationSubmissionSource::FOCUS_LOST); - } - auto eq = static_cast(tb->DataContext); KeyGraphFeaturesRequested(this, eq); } diff --git a/src/Calculator/Views/GraphingCalculator/EquationInputArea.xaml.h b/src/Calculator/Views/GraphingCalculator/EquationInputArea.xaml.h index 78612d7..01d3240 100644 --- a/src/Calculator/Views/GraphingCalculator/EquationInputArea.xaml.h +++ b/src/Calculator/Views/GraphingCalculator/EquationInputArea.xaml.h @@ -38,9 +38,9 @@ namespace CalculatorApp 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, CalculatorApp::Controls::EquationSubmissionSource e); + 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, CalculatorApp::Controls::MathRichEditBoxSubmission ^ e); void OnHighContrastChanged(Windows::UI::ViewManagement::AccessibilitySettings ^ sender, Platform::Object ^ args); void ReloadAvailableColors(bool isHighContrast); diff --git a/src/Calculator/Views/GraphingCalculator/GraphingCalculator.xaml.cpp b/src/Calculator/Views/GraphingCalculator/GraphingCalculator.xaml.cpp index 690bc90..cb76110 100644 --- a/src/Calculator/Views/GraphingCalculator/GraphingCalculator.xaml.cpp +++ b/src/Calculator/Views/GraphingCalculator/GraphingCalculator.xaml.cpp @@ -461,7 +461,7 @@ void GraphingCalculator::TraceValuePopup_SizeChanged(Object ^ sender, SizeChange void CalculatorApp::GraphingCalculator::ActiveTracing_Checked(Platform::Object ^ sender, Windows::UI::Xaml::RoutedEventArgs ^ e) { - GraphingControl->Focus(::FocusState::Programmatic); + FocusManager::TryFocusAsync(GraphingControl, ::FocusState::Programmatic); m_activeTracingKeyUpToken = Window::Current->CoreWindow->KeyUp += ref new Windows::Foundation::TypedEventHandler( diff --git a/src/Calculator/Views/GraphingCalculator/GraphingNumPad.xaml.cpp b/src/Calculator/Views/GraphingCalculator/GraphingNumPad.xaml.cpp index 2de31dc..e25033d 100644 --- a/src/Calculator/Views/GraphingCalculator/GraphingNumPad.xaml.cpp +++ b/src/Calculator/Views/GraphingCalculator/GraphingNumPad.xaml.cpp @@ -32,7 +32,7 @@ void GraphingNumPad::ShiftButton_Uncheck(_In_ Platform::Object ^ /*sender*/, _In { ShiftButton->IsChecked = false; SetOperatorRowVisibility(); - ShiftButton->Focus(::FocusState::Programmatic); + FocusManager::TryFocusAsync(ShiftButton, ::FocusState::Programmatic); } void GraphingNumPad::TrigFlyoutShift_Toggle(_In_ Platform::Object ^ /*sender*/, _In_ Windows::UI::Xaml::RoutedEventArgs ^ /*e*/) diff --git a/src/Calculator/Views/MainPage.xaml.cpp b/src/Calculator/Views/MainPage.xaml.cpp index 5e7e793..d22081a 100644 --- a/src/Calculator/Views/MainPage.xaml.cpp +++ b/src/Calculator/Views/MainPage.xaml.cpp @@ -296,7 +296,7 @@ void MainPage::SetDefaultFocus() } if (m_graphingCalculator != nullptr && m_graphingCalculator->Visibility == ::Visibility::Visible) { - m_graphingCalculator->Focus(::FocusState::Programmatic); + FocusManager::TryFocusAsync(m_graphingCalculator, ::FocusState::Programmatic); } if (m_converter != nullptr && m_converter->Visibility == ::Visibility::Visible) {