Switch to RichEdit math mode in EquationTextBox (#672)
* Use RichEdit Math Mode * Add comment Co-Authored-By: Stephanie Anderl <46726333+sanderl@users.noreply.github.com>
This commit is contained in:
parent
41fbcfe9c5
commit
b2dd55a64f
@ -45,7 +45,7 @@
|
||||
<AppContainerApplication>true</AppContainerApplication>
|
||||
<ApplicationType>Windows Store</ApplicationType>
|
||||
<ApplicationTypeRevision>10.0</ApplicationTypeRevision>
|
||||
<WindowsTargetPlatformVersion Condition="'$(WindowsTargetPlatformVersion)' == ''">10.0.18362.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformVersion Condition="'$(WindowsTargetPlatformVersion)' == ''">10.0.18970.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformMinVersion>10.0.17134.0</WindowsTargetPlatformMinVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
|
@ -42,7 +42,7 @@
|
||||
<MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
|
||||
<AppContainerApplication>true</AppContainerApplication>
|
||||
<ApplicationType>Windows Store</ApplicationType>
|
||||
<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformVersion>10.0.18970.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformMinVersion>10.0.17134.0</WindowsTargetPlatformMinVersion>
|
||||
<ApplicationTypeRevision>10.0</ApplicationTypeRevision>
|
||||
</PropertyGroup>
|
||||
|
@ -1628,6 +1628,7 @@
|
||||
<Button x:Name="EquationButton"
|
||||
MinWidth="44"
|
||||
MinHeight="44"
|
||||
VerticalAlignment="Stretch"
|
||||
Background="{TemplateBinding EquationColor}"
|
||||
Foreground="{StaticResource SystemChromeWhiteColor}"
|
||||
Content="ƒₓ">
|
||||
@ -1651,7 +1652,7 @@
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<RichEditBox x:Name="EquationTextBox"
|
||||
MinHeight="42"
|
||||
MinHeight="44"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
VerticalAlignment="Stretch"
|
||||
Style="{StaticResource EquationTextBoxStyle}"
|
||||
|
@ -8,7 +8,7 @@
|
||||
<MinimumVisualStudioVersion>15.0</MinimumVisualStudioVersion>
|
||||
<AppContainerApplication>true</AppContainerApplication>
|
||||
<ApplicationType>Windows Store</ApplicationType>
|
||||
<WindowsTargetPlatformVersion Condition="'$(WindowsTargetPlatformVersion)' == ''">10.0.18362.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformVersion Condition="'$(WindowsTargetPlatformVersion)' == ''">10.0.18970.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformMinVersion>10.0.18362.0</WindowsTargetPlatformMinVersion>
|
||||
<!-- We want to manually control the MinVersion/MaxVersionTested in the manifest so turn of the replacement. -->
|
||||
<AppxOSMinVersionReplaceManifestVersion>false</AppxOSMinVersionReplaceManifestVersion>
|
||||
|
@ -11,12 +11,14 @@ using namespace CalculatorApp;
|
||||
using namespace CalculatorApp::Common;
|
||||
using namespace CalculatorApp::Controls;
|
||||
using namespace CalculatorApp::ViewModel;
|
||||
using namespace Windows::System;
|
||||
using namespace Windows::Foundation;
|
||||
using namespace Windows::ApplicationModel;
|
||||
using namespace Windows::UI::Text;
|
||||
using namespace Windows::UI::Xaml;
|
||||
using namespace Windows::UI::Xaml::Controls;
|
||||
using namespace Windows::UI::Xaml::Input;
|
||||
using namespace Windows::UI::Xaml::Controls::Primitives;
|
||||
using namespace Windows::UI::Text;
|
||||
|
||||
DEPENDENCY_PROPERTY_INITIALIZATION(EquationTextBox, EquationColor);
|
||||
DEPENDENCY_PROPERTY_INITIALIZATION(EquationTextBox, KeyGraphFeaturesContent);
|
||||
@ -33,9 +35,11 @@ void EquationTextBox::OnApplyTemplate()
|
||||
|
||||
if (m_richEditBox != nullptr)
|
||||
{
|
||||
m_richEditBox->Loaded += ref new RoutedEventHandler(this, &EquationTextBox::OnRichEditBoxLoaded);
|
||||
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;
|
||||
}
|
||||
|
||||
if (m_equationButton != nullptr)
|
||||
@ -94,6 +98,22 @@ void EquationTextBox::OnPointerCaptureLost(PointerRoutedEventArgs^ e)
|
||||
UpdateCommonVisualState();
|
||||
}
|
||||
|
||||
void EquationTextBox::OnKeyDown(KeyRoutedEventArgs ^ e)
|
||||
{
|
||||
if (e->Key == VirtualKey::Enter)
|
||||
{
|
||||
EquationSubmitted(this, ref new RoutedEventArgs());
|
||||
}
|
||||
}
|
||||
|
||||
void EquationTextBox::OnLostFocus(RoutedEventArgs ^ e)
|
||||
{
|
||||
if (!m_richEditBox->ContextFlyout->IsOpen)
|
||||
{
|
||||
EquationSubmitted(this, ref new RoutedEventArgs());
|
||||
}
|
||||
}
|
||||
|
||||
void EquationTextBox::OnColorFlyoutOpened(Object ^ sender, Object ^ e)
|
||||
{
|
||||
m_isColorChooserFlyoutOpen = true;
|
||||
@ -107,6 +127,15 @@ void EquationTextBox::OnColorFlyoutClosed(Object^ sender, Object^ e)
|
||||
UpdateCommonVisualState();
|
||||
}
|
||||
|
||||
void EquationTextBox::OnRichEditBoxLoaded(Object ^ sender, RoutedEventArgs ^ e)
|
||||
{
|
||||
LimitedAccessFeatures::TryUnlockFeature(
|
||||
"com.microsoft.windows.richeditmath",
|
||||
"H6wflFFz3gkOsAHtG/D9Tg==",
|
||||
"8wekyb3d8bbwe has registered their use of com.microsoft.windows.richeditmath with Microsoft and agrees to the terms of use.");
|
||||
m_richEditBox->TextDocument->SetMathMode(::RichEditMathMode::MathOnly);
|
||||
}
|
||||
|
||||
void EquationTextBox::OnRichEditBoxTextChanged(Object ^ sender, RoutedEventArgs ^ e)
|
||||
{
|
||||
UpdateDeleteButtonVisualState();
|
||||
@ -120,8 +149,11 @@ void EquationTextBox::OnRichEditBoxGotFocus(Object^ sender, RoutedEventArgs^ e)
|
||||
}
|
||||
|
||||
void EquationTextBox::OnRichEditBoxLostFocus(Object ^ sender, RoutedEventArgs ^ e)
|
||||
{
|
||||
if (!m_richEditBox->ContextFlyout->IsOpen)
|
||||
{
|
||||
m_isFocused = false;
|
||||
}
|
||||
UpdateCommonVisualState();
|
||||
UpdateDeleteButtonVisualState();
|
||||
}
|
||||
@ -130,13 +162,12 @@ void EquationTextBox::OnDeleteButtonClicked(Object^ sender, RoutedEventArgs^ e)
|
||||
{
|
||||
if (m_richEditBox != nullptr)
|
||||
{
|
||||
m_richEditBox->TextDocument->SetText(::TextSetOptions::None, L"");
|
||||
m_richEditBox->TextDocument->SetMath(L"");
|
||||
}
|
||||
}
|
||||
|
||||
void EquationTextBox::OnEquationButtonClicked(Object ^ sender, RoutedEventArgs ^ e)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void EquationTextBox::OnRemoveButtonClicked(Object ^ sender, RoutedEventArgs ^ e)
|
||||
@ -155,7 +186,8 @@ void EquationTextBox::OnColorChooserButtonClicked(Object^ sender, RoutedEventArg
|
||||
void EquationTextBox::OnFunctionButtonClicked(Object ^ sender, RoutedEventArgs ^ e)
|
||||
{
|
||||
auto equationViewModel = static_cast<EquationViewModel ^>(DataContext);
|
||||
equationViewModel->KeyGraphFeaturesVisibility = (equationViewModel->KeyGraphFeaturesVisibility == ::Visibility::Collapsed) ? ::Visibility::Visible : ::Visibility::Collapsed;
|
||||
equationViewModel->KeyGraphFeaturesVisibility =
|
||||
(equationViewModel->KeyGraphFeaturesVisibility == ::Visibility::Collapsed) ? ::Visibility::Visible : ::Visibility::Collapsed;
|
||||
UpdateCommonVisualState();
|
||||
}
|
||||
|
||||
@ -191,14 +223,22 @@ void EquationTextBox::UpdateCommonVisualState()
|
||||
VisualStateManager::GoToState(this, state, true);
|
||||
}
|
||||
|
||||
|
||||
Platform::String ^ EquationTextBox::GetEquationText()
|
||||
{
|
||||
String ^ text;
|
||||
|
||||
if (m_richEditBox != nullptr)
|
||||
{
|
||||
m_richEditBox->TextDocument->GetText(::TextGetOptions::NoHidden, &text);
|
||||
// Clear formatting since the graph control doesn't work with bold/italic/underlines
|
||||
ITextRange ^ range = m_richEditBox->TextDocument->GetRange(0, m_richEditBox->TextDocument->Selection->EndPosition);
|
||||
|
||||
if (range != nullptr)
|
||||
{
|
||||
range->CharacterFormat->Bold = FormatEffect::Off;
|
||||
range->CharacterFormat->Italic = FormatEffect::Off;
|
||||
range->CharacterFormat->Underline = UnderlineType::None;
|
||||
}
|
||||
|
||||
m_richEditBox->TextDocument->GetMath(&text);
|
||||
}
|
||||
|
||||
return text;
|
||||
@ -208,13 +248,18 @@ void EquationTextBox::SetEquationText(Platform::String^ equationText)
|
||||
{
|
||||
if (m_richEditBox != nullptr)
|
||||
{
|
||||
m_richEditBox->TextDocument->SetText(::TextSetOptions::None, equationText);
|
||||
m_richEditBox->TextDocument->SetMath(equationText);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool EquationTextBox::ShouldDeleteButtonBeVisible()
|
||||
{
|
||||
return (!GetEquationText()->IsEmpty() && m_isFocused);
|
||||
String ^ text;
|
||||
|
||||
if (m_richEditBox != nullptr)
|
||||
{
|
||||
m_richEditBox->TextDocument->GetMath(&text);
|
||||
}
|
||||
|
||||
return (!text->IsEmpty() && m_isFocused);
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ namespace CalculatorApp
|
||||
DEPENDENCY_PROPERTY(Windows::UI::Xaml::Controls::Flyout^, ColorChooserFlyout);
|
||||
|
||||
event Windows::UI::Xaml::RoutedEventHandler ^ RemoveButtonClicked;
|
||||
event Windows::UI::Xaml::RoutedEventHandler ^ EquationSubmitted;
|
||||
|
||||
Platform::String^ GetEquationText();
|
||||
void SetEquationText(Platform::String^ equationText);
|
||||
@ -32,14 +33,18 @@ 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;
|
||||
|
||||
private:
|
||||
void UpdateCommonVisualState();
|
||||
void UpdateDeleteButtonVisualState();
|
||||
bool ShouldDeleteButtonBeVisible();
|
||||
|
||||
void OnRichEditBoxLoaded(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
|
||||
void OnRichEditBoxGotFocus(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
|
||||
void OnRichEditBoxLostFocus(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
|
||||
void OnRichEditBoxLosingFocus(Windows::UI::Xaml::UIElement ^ sender, Windows::UI::Xaml::Input::LosingFocusEventArgs ^ e);
|
||||
void OnRichEditBoxTextChanged(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
|
||||
|
||||
void OnDeleteButtonClicked(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
|
||||
|
@ -45,8 +45,8 @@
|
||||
Grid.Column="1"
|
||||
Margin="0,0,3,0"
|
||||
Style="{StaticResource EquationTextBoxStyle}"
|
||||
EquationSubmitted="InputTextBox_Submitted"
|
||||
GotFocus="InputTextBox_GotFocus"
|
||||
KeyUp="InputTextBox_KeyUp"
|
||||
LostFocus="InputTextBox_LostFocus"
|
||||
RemoveButtonClicked="EquationTextBox_RemoveButtonClicked">
|
||||
<controls:EquationTextBox.EquationColor>
|
||||
|
@ -78,22 +78,13 @@ void EquationInputArea::InputTextBox_GotFocus(Object^ sender, RoutedEventArgs^ e
|
||||
void EquationInputArea::InputTextBox_LostFocus(Object^ sender, RoutedEventArgs^ e)
|
||||
{
|
||||
KeyboardShortcutManager::HonorShortcuts(true);
|
||||
|
||||
auto tb = static_cast<EquationTextBox^>(sender);
|
||||
auto eq = static_cast<EquationViewModel^>(tb->DataContext);
|
||||
tb->SetEquationText(eq->Expression);
|
||||
}
|
||||
|
||||
void EquationInputArea::InputTextBox_KeyUp(Object^ sender, KeyRoutedEventArgs^ e)
|
||||
{
|
||||
if (e->Key == VirtualKey::Enter)
|
||||
void EquationInputArea::InputTextBox_Submitted(Object ^ sender, RoutedEventArgs ^ e)
|
||||
{
|
||||
auto tb = static_cast<EquationTextBox^>(sender);
|
||||
auto eq = static_cast<EquationViewModel^>(tb->DataContext);
|
||||
eq->Expression = tb->GetEquationText();
|
||||
|
||||
e->Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
Color EquationInputArea::GetNextLineColor()
|
||||
|
@ -23,7 +23,7 @@ namespace CalculatorApp
|
||||
|
||||
void InputTextBox_GotFocus(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
|
||||
void InputTextBox_LostFocus(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
|
||||
void InputTextBox_KeyUp(Platform::Object^ sender, Windows::UI::Xaml::Input::KeyRoutedEventArgs^ e);
|
||||
void InputTextBox_Submitted(Platform::Object ^ sender, Windows::UI::Xaml::RoutedEventArgs ^ e);
|
||||
|
||||
Windows::UI::Color GetNextLineColor();
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
<MinimumVisualStudioVersion>15.0</MinimumVisualStudioVersion>
|
||||
<AppContainerApplication>true</AppContainerApplication>
|
||||
<ApplicationType>Windows Store</ApplicationType>
|
||||
<WindowsTargetPlatformVersion Condition=" '$(WindowsTargetPlatformVersion)' == '' ">10.0.18362.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformVersion Condition=" '$(WindowsTargetPlatformVersion)' == '' ">10.0.18970.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformMinVersion>10.0.17134.0</WindowsTargetPlatformMinVersion>
|
||||
<ApplicationTypeRevision>10.0</ApplicationTypeRevision>
|
||||
<UnitTestPlatformVersion Condition="'$(UnitTestPlatformVersion)' == ''">15.0</UnitTestPlatformVersion>
|
||||
|
@ -274,7 +274,7 @@ namespace CalculatorUnitTests
|
||||
void NavCategoryUnitTests::GetPosition()
|
||||
{
|
||||
// Position is the 1-based ordering of modes
|
||||
vector<ViewMode> orderedModes = { ViewMode::Standard, ViewMode::Scientific, ViewMode::Programmer, ViewMode::Date, ViewMode::Graphing
|
||||
vector<ViewMode> orderedModes = { ViewMode::Standard, ViewMode::Scientific, ViewMode::Programmer, ViewMode::Date, ViewMode::Graphing,
|
||||
ViewMode::Currency, ViewMode::Volume, ViewMode::Length, ViewMode::Weight, ViewMode::Temperature,
|
||||
ViewMode::Energy, ViewMode::Area, ViewMode::Speed, ViewMode::Time, ViewMode::Power,
|
||||
ViewMode::Data, ViewMode::Pressure, ViewMode::Angle };
|
||||
|
@ -9,6 +9,9 @@ using namespace Windows::UI::Xaml;
|
||||
|
||||
namespace GraphControl
|
||||
{
|
||||
// Remove mml: formatting specific to RichEditBox control, which is not understood by the graph engine.
|
||||
static constexpr wstring_view s_mathPrefix = L"mml:";
|
||||
|
||||
DependencyProperty^ Equation::s_expressionProperty;
|
||||
static constexpr auto s_propertyName_Expression = L"Expression";
|
||||
|
||||
@ -74,7 +77,7 @@ namespace GraphControl
|
||||
ss << GetRequestHeader()
|
||||
<< GetExpression()
|
||||
<< GetLineColor()
|
||||
<< L")";
|
||||
<< L"</mfenced></mrow>";
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
@ -82,19 +85,28 @@ namespace GraphControl
|
||||
wstring Equation::GetRequestHeader()
|
||||
{
|
||||
wstring expr{ Expression->Data() };
|
||||
if (expr.find(L"=") != wstring::npos)
|
||||
if (expr.find(L">=<") != wstring::npos)
|
||||
{
|
||||
return L"plotEq2d("s;
|
||||
return L"<mrow><mi>plotEq2d</mi><mfenced separators=\"\">"s;
|
||||
}
|
||||
else
|
||||
{
|
||||
return L"plot2d("s;
|
||||
return L"<mrow><mi>plot2d</mi><mfenced separators=\"\">"s;
|
||||
}
|
||||
}
|
||||
|
||||
wstring Equation::GetExpression()
|
||||
{
|
||||
return Expression->Data();
|
||||
wstring mathML = Expression->Data();
|
||||
|
||||
size_t mathPrefix = 0;
|
||||
while ((mathPrefix = mathML.find(s_mathPrefix, mathPrefix)) != std::string::npos)
|
||||
{
|
||||
mathML.replace(mathPrefix, s_mathPrefix.length(), L"");
|
||||
mathPrefix += s_mathPrefix.length();
|
||||
}
|
||||
|
||||
return mathML;
|
||||
}
|
||||
|
||||
wstring Equation::GetLineColor()
|
||||
|
@ -55,7 +55,7 @@ namespace GraphControl
|
||||
: m_solver{ IMathSolver::CreateMathSolver() }
|
||||
, m_graph{ m_solver->CreateGrapher() }
|
||||
{
|
||||
m_solver->ParsingOptions().SetFormatType(FormatType::Linear);
|
||||
m_solver->ParsingOptions().SetFormatType(FormatType::MathML);
|
||||
|
||||
DefaultStyleKey = StringReference(s_defaultStyleKey);
|
||||
|
||||
@ -365,20 +365,20 @@ namespace GraphControl
|
||||
if (!validEqs.empty())
|
||||
{
|
||||
wstringstream ss{};
|
||||
ss << L"show2d(";
|
||||
ss << L"<math xmlns=\"http://www.w3.org/1998/Math/MathML\"><mrow><mi>show2d</mi><mfenced separators=\"\">";
|
||||
|
||||
int numValidEquations = 0;
|
||||
for (Equation^ eq : validEqs)
|
||||
{
|
||||
if (numValidEquations++ > 0)
|
||||
{
|
||||
ss << L",";
|
||||
ss << L"<mo>,</mo>";
|
||||
}
|
||||
|
||||
ss << eq->GetRequest();
|
||||
}
|
||||
|
||||
ss << L")";
|
||||
ss << L"</mfenced></mrow></math>";
|
||||
|
||||
wstring request = ss.str();
|
||||
unique_ptr<IExpression> graphExpression;
|
||||
|
@ -42,7 +42,7 @@
|
||||
<MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
|
||||
<AppContainerApplication>true</AppContainerApplication>
|
||||
<ApplicationType>Windows Store</ApplicationType>
|
||||
<WindowsTargetPlatformVersion Condition="'$(WindowsTargetPlatformVersion)' == ''">10.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformVersion Condition="'$(WindowsTargetPlatformVersion)' == ''">10.0.18970.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformMinVersion>10.0.18362.0</WindowsTargetPlatformMinVersion>
|
||||
<ApplicationTypeRevision>10.0</ApplicationTypeRevision>
|
||||
</PropertyGroup>
|
||||
|
@ -42,7 +42,7 @@
|
||||
<MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
|
||||
<AppContainerApplication>true</AppContainerApplication>
|
||||
<ApplicationType>Windows Store</ApplicationType>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformVersion>10.0.18970.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformMinVersion>10.0.18362.0</WindowsTargetPlatformMinVersion>
|
||||
<ApplicationTypeRevision>10.0</ApplicationTypeRevision>
|
||||
</PropertyGroup>
|
||||
|
Loading…
Reference in New Issue
Block a user