C# Migration: Initially migrated C# codebase by Han (#8)

* C# Migration: Initially migrated C# codebase by Han

* Resolved comments and misssing asset

* Added three files to Calculator project

* Added TODO comment and updated Object
This commit is contained in:
hanzhang54 2021-04-09 14:14:13 +08:00 committed by GitHub
commit 37ba91257c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
38 changed files with 14926 additions and 0 deletions

View file

@ -0,0 +1,95 @@
<UserControl x:Class="CalculatorApp.AboutFlyout"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:CalculatorApp.Common"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<UserControl.Transitions>
<TransitionCollection>
<EdgeUIThemeTransition Edge="Left"/>
</TransitionCollection>
</UserControl.Transitions>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="Header"
Grid.Column="1"
Margin="12,10,12,0"
Style="{ThemeResource SubtitleTextBlockStyle}"/>
<StackPanel Grid.Row="1"
Grid.ColumnSpan="2"
Margin="0,12,0,0"
Orientation="Vertical">
<RichTextBlock x:Name="AboutContentBody"
MaxWidth="292"
Margin="12,0,12,18"
HorizontalAlignment="Left"
Foreground="{ThemeResource SystemControlPageTextBaseHighBrush}"
FontSize="{ThemeResource BodyFontSize}">
<Paragraph>
<Run x:Name="AboutFlyoutVersion"/>
<LineBreak/>
<Run x:Name="AboutControlCopyrightRun"/>
</Paragraph>
</RichTextBlock>
<HyperlinkButton x:Name="AboutFlyoutEULA"
Margin="12,0,12,6"
NavigateUri="https://go.microsoft.com/fwlink/?LinkID=529064"
ToolTipService.ToolTip="https://go.microsoft.com/fwlink/?LinkID=529064">
<TextBlock x:Uid="AboutFlyoutEULA"
FontSize="{ThemeResource BodyFontSize}"
TextWrapping="Wrap"/>
</HyperlinkButton>
<HyperlinkButton Margin="12,0,12,6"
NavigateUri="https://go.microsoft.com/fwlink/?LinkID=822631"
ToolTipService.ToolTip="https://go.microsoft.com/fwlink/?LinkID=822631">
<TextBlock x:Uid="AboutControlServicesAgreement"
FontSize="{ThemeResource BodyFontSize}"
TextWrapping="Wrap"/>
</HyperlinkButton>
<HyperlinkButton Margin="12,0,12,6"
NavigateUri="https://go.microsoft.com/fwlink/?LinkID=521839"
ToolTipService.ToolTip="https://go.microsoft.com/fwlink/?LinkID=521839">
<TextBlock x:Uid="AboutControlPrivacyStatement"
FontSize="{ThemeResource BodyFontSize}"
TextWrapping="Wrap"/>
</HyperlinkButton>
<Button x:Name="FeedbackButton"
x:Uid="FeedbackButton"
MinWidth="120"
Margin="12,12,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Style="{StaticResource ButtonRevealStyle}"
Click="FeedbackButton_Click"/>
</StackPanel>
<RichTextBlock x:Name="AboutFlyoutContribute"
Grid.Row="2"
Grid.ColumnSpan="2"
Margin="12,18,12,6"
HorizontalAlignment="Left"
Foreground="{ThemeResource SystemControlPageTextBaseHighBrush}"
FontSize="{ThemeResource BodyFontSize}"
TextWrapping="Wrap">
<Paragraph>
<Run x:Name="ContributeRunBeforeLink"/>
<Hyperlink NavigateUri="https://go.microsoft.com/fwlink/?linkid=2099939"
TextDecorations="None"
ToolTipService.ToolTip="https://go.microsoft.com/fwlink/?linkid=2099939">
<Run x:Name="ContributeRunLink"/>
</Hyperlink>
<Run x:Name="ContributeRunAfterLink"/>
</Paragraph>
</RichTextBlock>
</Grid>
</UserControl>

View file

@ -0,0 +1,86 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using CalculatorApp.Common;
using System;
using System.Diagnostics;
using Windows.ApplicationModel;
using Windows.System;
using Windows.UI.Xaml;
namespace CalculatorApp
{
public sealed partial class AboutFlyout
{
// CSHARP_MIGRATION: TODO:
// BUILD_YEAR was a C++/CX macro and may update the value from the pipeline
private const string BUILD_YEAR = "2021";
public AboutFlyout()
{
var locService = LocalizationService.GetInstance();
var resourceLoader = AppResourceProvider.GetInstance();
InitializeComponent();
Language = locService.GetLanguage();
SetVersionString();
Header.Text = resourceLoader.GetResourceString("AboutButton/Content");
var copyrightText =
LocalizationStringUtil.GetLocalizedString(resourceLoader.GetResourceString("AboutControlCopyright"), BUILD_YEAR);
AboutControlCopyrightRun.Text = copyrightText;
InitializeContributeTextBlock();
}
public void SetDefaultFocus()
{
AboutFlyoutEULA.Focus(FocusState.Programmatic);
}
private void FeedbackButton_Click(object sender, RoutedEventArgs e)
{
PackageVersion version = Package.Current.Id.Version;
string versionNumber = "Version ";
versionNumber = versionNumber + version.Major + "." + version.Minor + "." + version.Build + "." + version.Revision;
_ = Launcher.LaunchUriAsync(new Uri("windows-feedback:?contextid=130&metadata=%7B%22Metadata%22:[%7B%22AppBuild%22:%22" + versionNumber + "%22%7D]%7D"));
}
private void SetVersionString()
{
PackageVersion version = Package.Current.Id.Version;
string appName = AppResourceProvider.GetInstance().GetResourceString("AppName");
AboutFlyoutVersion.Text = appName + " " + version.Major + "." + version.Minor + "." + version.Build + "." + version.Revision;
}
private void InitializeContributeTextBlock()
{
var resProvider = AppResourceProvider.GetInstance();
string contributeHyperlinkText = resProvider.GetResourceString("AboutFlyoutContribute");
// The resource string has the 'GitHub' hyperlink wrapped with '%HL%'.
// Break the string and assign pieces appropriately.
string delimiter = "%HL%";
int delimiterLength = delimiter.Length;
// Find the delimiters.
int firstSplitPosition = contributeHyperlinkText.IndexOf(delimiter, 0);
Debug.Assert(firstSplitPosition != -1);
int secondSplitPosition = contributeHyperlinkText.IndexOf(delimiter, firstSplitPosition + 1);
Debug.Assert(secondSplitPosition != -1);
int hyperlinkTextLength = secondSplitPosition - (firstSplitPosition + delimiterLength);
// Assign pieces.
var contributeTextBeforeHyperlink = contributeHyperlinkText.Substring(0, firstSplitPosition);
var contributeTextLink = contributeHyperlinkText.Substring(firstSplitPosition + delimiterLength, hyperlinkTextLength);
var contributeTextAfterHyperlink = contributeHyperlinkText.Substring(secondSplitPosition + delimiterLength);
ContributeRunBeforeLink.Text = contributeTextBeforeHyperlink;
ContributeRunLink.Text = contributeTextLink;
ContributeRunAfterLink.Text = contributeTextAfterHyperlink;
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

View file

@ -0,0 +1,500 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Diagnostics;
using CalculatorApp;
using CalculatorApp.Controls;
using CalculatorApp.Common;
using Windows.Devices.Input;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using Windows.UI.Xaml.Automation;
using Windows.UI.Xaml.Automation.Peers;
using System.Reflection;
namespace CalculatorApp
{
namespace Controls
{
public delegate void SelectedEventHandler(object sender);
public sealed class CalculationResult : Windows.UI.Xaml.Controls.Control
{
public CalculationResult()
{
m_isScalingText = false;
m_haveCalculatedMax = false;
}
public double MinFontSize
{
get { return (double)GetValue(MinFontSizeProperty); }
set { SetValue(MinFontSizeProperty, value); }
}
// Using a DependencyProperty as the backing store for MinFontSize. This enables animation, styling, binding, etc...
public static readonly DependencyProperty MinFontSizeProperty =
DependencyProperty.Register(nameof(MinFontSize), typeof(double), typeof(CalculationResult), new PropertyMetadata(0.0, new PropertyChangedCallback((sender, args) =>
{
var self = (CalculationResult)sender;
self.OnMinFontSizePropertyChanged((double)args.OldValue, (double)args.NewValue);
})));
public double MaxFontSize
{
get { return (double)GetValue(MaxFontSizeProperty); }
set { SetValue(MaxFontSizeProperty, value); }
}
// Using a DependencyProperty as the backing store for MaxFontSize. This enables animation, styling, binding, etc...
public static readonly DependencyProperty MaxFontSizeProperty =
DependencyProperty.Register(nameof(MaxFontSize), typeof(double), typeof(CalculationResult), new PropertyMetadata(30.0, new PropertyChangedCallback((sender, args) =>
{
var self = (CalculationResult)sender;
self.OnMaxFontSizePropertyChanged((double)args.OldValue, (double)args.NewValue);
})));
public Thickness DisplayMargin
{
get { return (Thickness)GetValue(DisplayMarginProperty); }
set { SetValue(DisplayMarginProperty, value); }
}
// Using a DependencyProperty as the backing store for DisplayMargin. This enables animation, styling, binding, etc...
public static readonly DependencyProperty DisplayMarginProperty =
DependencyProperty.Register(nameof(DisplayMargin), typeof(Thickness), typeof(CalculationResult), new PropertyMetadata(default(Thickness)));
public bool IsActive
{
get { return (bool)GetValue(IsActiveProperty); }
set { SetValue(IsActiveProperty, value); }
}
// Using a DependencyProperty as the backing store for IsActive. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsActiveProperty =
DependencyProperty.Register(nameof(IsActive), typeof(bool), typeof(CalculationResult), new PropertyMetadata(default(bool), new PropertyChangedCallback((sender, args) =>
{
var self = (CalculationResult)sender;
self.OnIsActivePropertyChanged((bool)args.OldValue, (bool)args.NewValue);
})));
public string DisplayValue
{
get { return (string)GetValue(DisplayValueProperty); }
set { SetValue(DisplayValueProperty, value); }
}
// Using a DependencyProperty as the backing store for DisplayValue. This enables animation, styling, binding, etc...
public static readonly DependencyProperty DisplayValueProperty =
DependencyProperty.Register(nameof(DisplayValue), typeof(string), typeof(CalculationResult), new PropertyMetadata(string.Empty, new PropertyChangedCallback((sender, args) =>
{
var self = (CalculationResult)sender;
self.OnDisplayValuePropertyChanged((string)args.OldValue, (string)args.NewValue);
})));
public bool IsInError
{
get { return (bool)GetValue(IsInErrorProperty); }
set { SetValue(IsInErrorProperty, value); }
}
// Using a DependencyProperty as the backing store for IsInError. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsInErrorProperty =
DependencyProperty.Register(nameof(IsInError), typeof(bool), typeof(CalculationResult), new PropertyMetadata(default(bool), new PropertyChangedCallback((sender, args) =>
{
var self = (CalculationResult)sender;
self.OnIsInErrorPropertyChanged((bool)args.OldValue, (bool)args.NewValue);
})));
public bool IsOperatorCommand
{
get { return (bool)GetValue(IsOperatorCommandProperty); }
set { SetValue(IsOperatorCommandProperty, value); }
}
// Using a DependencyProperty as the backing store for IsOperatorCommand. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsOperatorCommandProperty =
DependencyProperty.Register(nameof(IsOperatorCommand), typeof(bool), typeof(CalculationResult), new PropertyMetadata(false));
public event SelectedEventHandler Selected;
public void ProgrammaticSelect()
{
RaiseSelectedEvent();
}
internal void UpdateTextState()
{
if ((m_textContainer == null) || (m_textBlock == null))
{
return;
}
var containerSize = m_textContainer.ActualWidth;
string oldText = m_textBlock.Text;
string newText = DisplayValue;
// Initiate the scaling operation
// UpdateLayout will keep calling us until we make it through the below 2 if-statements
if (!m_isScalingText || oldText != newText)
{
m_textBlock.Text = newText;
m_isScalingText = true;
m_haveCalculatedMax = false;
m_textBlock.InvalidateArrange();
return;
}
if (containerSize > 0)
{
double widthDiff = Math.Abs(m_textBlock.ActualWidth - containerSize);
double fontSizeChange = INCREMENTOFFSET;
if (widthDiff > WIDTHCUTOFF)
{
fontSizeChange = Math.Min((double)Math.Max((double)Math.Floor(WIDTHTOFONTSCALAR * widthDiff) - WIDTHTOFONTOFFSET, INCREMENTOFFSET), MAXFONTINCREMENT);
}
if (m_textBlock.ActualWidth < containerSize && Math.Abs(m_textBlock.FontSize - MaxFontSize) > FONTTOLERANCE && !m_haveCalculatedMax)
{
ModifyFontAndMargin(m_textBlock, fontSizeChange);
m_textBlock.InvalidateArrange();
return;
}
if (fontSizeChange < 5)
{
m_haveCalculatedMax = true;
}
if (m_textBlock.ActualWidth >= containerSize && Math.Abs(m_textBlock.FontSize - MinFontSize) > FONTTOLERANCE)
{
ModifyFontAndMargin(m_textBlock, -1 * fontSizeChange);
m_textBlock.InvalidateArrange();
return;
}
Debug.Assert(m_textBlock.FontSize >= MinFontSize && m_textBlock.FontSize <= MaxFontSize);
m_isScalingText = false;
if (IsOperatorCommand)
{
m_textContainer.ChangeView(0.0, null, null);
}
else
{
m_textContainer.ChangeView(m_textContainer.ExtentWidth - m_textContainer.ViewportWidth, null, null);
}
}
}
public string GetRawDisplayValue()
{
return LocalizationSettings.GetInstance().RemoveGroupSeparators(DisplayValue);
}
protected override void OnKeyDown(KeyRoutedEventArgs e)
{
switch (e.Key)
{
case Windows.System.VirtualKey.Left:
this.ScrollLeft();
break;
case Windows.System.VirtualKey.Right:
this.ScrollRight();
break;
}
}
protected override void OnApplyTemplate()
{
if (m_textContainer != null)
{
m_textContainer.LayoutUpdated -= OnTextContainerLayoutUpdated;
m_textContainer.SizeChanged -= OnTextContainerSizeChanged;
m_textContainer.ViewChanged -= OnTextContainerOnViewChanged;
}
if (m_textBlock != null)
{
m_textBlock.SizeChanged -= OnTextBlockSizeChanged;
}
if (m_scrollLeft != null)
{
m_scrollLeft.Click -= OnScrollLeftClick;
}
if (m_scrollRight != null)
{
m_scrollRight.Click -= OnScrollRightClick;
}
m_textContainer = GetTemplateChild("TextContainer") as ScrollViewer;
if (m_textContainer != null)
{
// We want to know when the size of the container changes so
// we can rescale the textbox
m_textContainer.SizeChanged += OnTextContainerSizeChanged;
m_textContainer.ViewChanged += OnTextContainerOnViewChanged;
m_textContainer.LayoutUpdated += OnTextContainerLayoutUpdated;
m_textContainer.ChangeView(m_textContainer.ExtentWidth - m_textContainer.ViewportWidth, null, null);
m_scrollLeft = GetTemplateChild("ScrollLeft") as HyperlinkButton;
if (m_scrollLeft != null)
{
m_scrollLeft.Click += OnScrollLeftClick;
}
m_scrollRight = GetTemplateChild("ScrollRight") as HyperlinkButton;
if (m_scrollRight != null)
{
m_scrollRight.Click += OnScrollRightClick;
}
m_textBlock = GetTemplateChild("NormalOutput") as TextBlock;
if (m_textBlock != null)
{
m_textBlock.Visibility = Visibility.Visible;
m_textBlock.SizeChanged += OnTextBlockSizeChanged;
}
}
UpdateVisualState();
UpdateTextState();
}
protected override void OnTapped(TappedRoutedEventArgs e)
{
this.Focus(FocusState.Programmatic);
RaiseSelectedEvent();
}
protected override void OnRightTapped(RightTappedRoutedEventArgs e)
{
var requestedElement = e.OriginalSource;
if (requestedElement.Equals(m_textBlock as object))
{
m_textBlock.Focus(FocusState.Programmatic);
}
else
{
this.Focus(FocusState.Programmatic);
}
}
protected override AutomationPeer OnCreateAutomationPeer()
{
return new CalculationResultAutomationPeer(this);
}
private void OnIsActivePropertyChanged(bool oldValue, bool newValue)
{
UpdateVisualState();
}
private void OnDisplayValuePropertyChanged(string oldValue, string newValue)
{
UpdateTextState();
}
private void OnIsInErrorPropertyChanged(bool oldValue, bool newValue)
{
// We need to have a good template for this to work
if (m_textBlock == null)
{
return;
}
if (newValue)
{
// If there's an error message we need to override the normal display font
// with the font appropriate for this language. This is because the error
// message is localized and therefore can contain characters that are not
// available in the normal font.
// We use UIText as the font type because this is the most common font type to use
m_textBlock.FontFamily = LocalizationService.GetInstance().GetLanguageFontFamilyForType(LanguageFontType.UIText);
}
else
{
// The error result is no longer an error so we will restore the
// value to FontFamily property to the value provided in the style
// for the TextBlock in the template.
m_textBlock.ClearValue(TextBlock.FontFamilyProperty);
}
}
private void OnMinFontSizePropertyChanged(double oldValue, double newValue)
{
UpdateTextState();
}
private void OnMaxFontSizePropertyChanged(double oldValue, double newValue)
{
UpdateTextState();
}
private void OnTextContainerSizeChanged(object sender, SizeChangedEventArgs e)
{
UpdateTextState();
}
private void OnTextBlockSizeChanged(object sender, SizeChangedEventArgs e)
{
UpdateScrollButtons();
}
private void OnTextContainerLayoutUpdated(object sender, object e)
{
if (m_isScalingText)
{
UpdateTextState();
}
}
private void OnTextContainerOnViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
{
UpdateScrollButtons();
}
private void UpdateVisualState()
{
if (IsActive)
{
VisualStateManager.GoToState(this, "Active", true);
}
else
{
VisualStateManager.GoToState(this, "Normal", true);
}
}
private void OnScrollLeftClick(object sender, RoutedEventArgs e)
{
ScrollLeft();
}
private void OnScrollRightClick(object sender, RoutedEventArgs e)
{
ScrollRight();
}
private void ModifyFontAndMargin(TextBlock textBox, double fontChange)
{
double cur = textBox.FontSize;
double newFontSize = 0.0;
double scaleFactor = SCALEFACTOR;
if (m_textContainer.ActualHeight <= HEIGHTCUTOFF)
{
scaleFactor = SMALLHEIGHTSCALEFACTOR;
}
newFontSize = Math.Min(Math.Max(cur + fontChange, MinFontSize), MaxFontSize);
m_textContainer.Padding = new Thickness(0, 0, 0, scaleFactor * Math.Abs(cur - newFontSize));
textBox.FontSize = newFontSize;
}
private void UpdateScrollButtons()
{
if (m_textContainer == null)
{
return;
}
bool shouldTryFocusScrollRight = false;
if (m_scrollLeft != null)
{
var scrollLeftVisibility = m_textContainer.HorizontalOffset > SCROLL_BUTTONS_APPROXIMATION_RANGE ? Visibility.Visible : Visibility.Collapsed;
if (scrollLeftVisibility == Visibility.Collapsed)
{
shouldTryFocusScrollRight = m_scrollLeft.Equals(FocusManager.GetFocusedElement());
}
m_scrollLeft.Visibility = scrollLeftVisibility;
}
if (m_scrollRight != null)
{
var scrollRightVisibility =
m_textContainer.HorizontalOffset + m_textContainer.ViewportWidth + SCROLL_BUTTONS_APPROXIMATION_RANGE < m_textContainer.ExtentWidth
? Visibility.Visible
: Visibility.Collapsed;
if (scrollRightVisibility == Visibility.Collapsed && m_scrollLeft != null && m_scrollLeft.Visibility == Visibility.Visible
&& m_scrollRight.Equals(FocusManager.GetFocusedElement()))
{
// ScrollRight had the focus and will be collapsed, ScrollLeft should get the focus
m_scrollLeft.Focus(FocusState.Programmatic);
}
m_scrollRight.Visibility = scrollRightVisibility;
if (shouldTryFocusScrollRight && scrollRightVisibility == Visibility.Visible)
{
m_scrollRight.Focus(FocusState.Programmatic);
}
}
}
private void ScrollLeft()
{
if (m_textContainer == null)
{
return;
}
if (m_textContainer.HorizontalOffset > 0)
{
double offset = m_textContainer.HorizontalOffset - (SCROLL_RATIO * m_textContainer.ViewportWidth);
m_textContainer.ChangeView(offset, null, null);
}
}
private void ScrollRight()
{
if (m_textContainer == null)
{
return;
}
if (m_textContainer.HorizontalOffset < m_textContainer.ExtentWidth - m_textContainer.ViewportWidth)
{
double offset = m_textContainer.HorizontalOffset + (SCROLL_RATIO * m_textContainer.ViewportWidth);
m_textContainer.ChangeView(offset, null, null);
}
}
private void RaiseSelectedEvent()
{
Selected?.Invoke(this);
}
private const double SCALEFACTOR = 0.357143;
private const double SMALLHEIGHTSCALEFACTOR = 0;
private const double HEIGHTCUTOFF = 100;
private const double INCREMENTOFFSET = 1;
private const double MAXFONTINCREMENT = 5;
private const double WIDTHTOFONTSCALAR = 0.0556513;
private const double WIDTHTOFONTOFFSET = 3;
private const double WIDTHCUTOFF = 50;
private const double FONTTOLERANCE = 0.001;
private const double SCROLL_RATIO = 0.7;
// We need a safety margin to guarantee we correctly always show/hide ScrollLeft and ScrollRight buttons when necessary.
// In rare cases, ScrollViewer::HorizontalOffset is a little low by a few (sub)pixels when users scroll to one of the extremity
// and no events are launched when they scroll again in the same direction
private const double SCROLL_BUTTONS_APPROXIMATION_RANGE = 4;
private Windows.UI.Xaml.Controls.ScrollViewer m_textContainer;
private Windows.UI.Xaml.Controls.TextBlock m_textBlock;
private Windows.UI.Xaml.Controls.HyperlinkButton m_scrollLeft;
private Windows.UI.Xaml.Controls.HyperlinkButton m_scrollRight;
private bool m_isScalingText;
private bool m_haveCalculatedMax;
}
}
}

View file

@ -0,0 +1,44 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Diagnostics;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Automation.Peers;
namespace CalculatorApp
{
namespace Controls
{
public sealed class CalculationResultAutomationPeer : Windows.UI.Xaml.Automation.Peers.FrameworkElementAutomationPeer,
Windows.UI.Xaml.Automation.Provider.IInvokeProvider
{
public CalculationResultAutomationPeer(FrameworkElement owner) : base(owner)
{
}
protected override AutomationControlType GetAutomationControlTypeCore()
{
return AutomationControlType.Text;
}
protected override object GetPatternCore(PatternInterface pattern)
{
if (pattern == PatternInterface.Invoke)
{
return this;
}
return base.GetPatternCore(pattern);
}
public void Invoke()
{
var owner = (CalculationResult)this.Owner;
owner.ProgrammaticSelect();
}
}
}
}

View file

@ -0,0 +1,134 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Diagnostics;
using CalculatorApp;
using CalculatorApp.Common;
using CalculatorApp.Controls;
using Windows.System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Data;
using Windows.Foundation.Collections;
using Windows.Storage.Pickers;
namespace CalculatorApp
{
namespace Controls
{
public sealed class CalculatorButton : Windows.UI.Xaml.Controls.Button
{
public CalculatorButton()
{
// Set the default bindings for this button, these can be overwritten by Xaml if needed
// These are a replacement for binding in styles
Binding commandBinding = new Binding();
commandBinding.Path = new PropertyPath("ButtonPressed");
this.SetBinding(CommandProperty, commandBinding);
}
public NumbersAndOperatorsEnum ButtonId
{
get { return (NumbersAndOperatorsEnum)GetValue(ButtonIdProperty); }
set { SetValue(ButtonIdProperty, value); }
}
// Using a DependencyProperty as the backing store for ButtonId. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ButtonIdProperty =
DependencyProperty.Register(nameof(ButtonId), typeof(NumbersAndOperatorsEnum), typeof(CalculatorButton), new PropertyMetadata(default(NumbersAndOperatorsEnum), new PropertyChangedCallback((sender, args) =>
{
var self = (CalculatorButton)sender;
self.OnButtonIdPropertyChanged((NumbersAndOperatorsEnum)args.OldValue, (NumbersAndOperatorsEnum)args.NewValue);
})));
public string AuditoryFeedback
{
get { return (string)GetValue(AuditoryFeedbackProperty); }
set { SetValue(AuditoryFeedbackProperty, value); }
}
// Using a DependencyProperty as the backing store for AuditoryFeedback. This enables animation, styling, binding, etc...
public static readonly DependencyProperty AuditoryFeedbackProperty =
DependencyProperty.Register(nameof(AuditoryFeedback), typeof(string), typeof(CalculatorButton), new PropertyMetadata(string.Empty, new PropertyChangedCallback((sender, args) =>
{
var self = (CalculatorButton)sender;
self.OnAuditoryFeedbackPropertyChanged((string)args.OldValue, (string)args.NewValue);
})));
public Windows.UI.Xaml.Media.Brush HoverBackground
{
get { return (Windows.UI.Xaml.Media.Brush)GetValue(HoverBackgroundProperty); }
set { SetValue(HoverBackgroundProperty, value); }
}
// Using a DependencyProperty as the backing store for HoverBackground. This enables animation, styling, binding, etc...
public static readonly DependencyProperty HoverBackgroundProperty =
DependencyProperty.Register(nameof(HoverBackground), typeof(Windows.UI.Xaml.Media.Brush), typeof(CalculatorButton), new PropertyMetadata(default(Windows.UI.Xaml.Media.Brush)));
public Windows.UI.Xaml.Media.Brush HoverForeground
{
get { return (Windows.UI.Xaml.Media.Brush)GetValue(HoverForegroundProperty); }
set { SetValue(HoverForegroundProperty, value); }
}
// Using a DependencyProperty as the backing store for HoverForeground. This enables animation, styling, binding, etc...
public static readonly DependencyProperty HoverForegroundProperty =
DependencyProperty.Register(nameof(HoverForeground), typeof(Windows.UI.Xaml.Media.Brush), typeof(CalculatorButton), new PropertyMetadata(default(Windows.UI.Xaml.Media.Brush)));
public Windows.UI.Xaml.Media.Brush PressBackground
{
get { return (Windows.UI.Xaml.Media.Brush)GetValue(PressBackgroundProperty); }
set { SetValue(PressBackgroundProperty, value); }
}
// Using a DependencyProperty as the backing store for PressBackground. This enables animation, styling, binding, etc...
public static readonly DependencyProperty PressBackgroundProperty =
DependencyProperty.Register(nameof(PressBackground), typeof(Windows.UI.Xaml.Media.Brush), typeof(CalculatorButton), new PropertyMetadata(default(Windows.UI.Xaml.Media.Brush)));
public Windows.UI.Xaml.Media.Brush PressForeground
{
get { return (Windows.UI.Xaml.Media.Brush)GetValue(PressForegroundProperty); }
set { SetValue(PressForegroundProperty, value); }
}
// Using a DependencyProperty as the backing store for PressForeground. This enables animation, styling, binding, etc...
public static readonly DependencyProperty PressForegroundProperty =
DependencyProperty.Register(nameof(PressForeground), typeof(Windows.UI.Xaml.Media.Brush), typeof(CalculatorButton), new PropertyMetadata(default(Windows.UI.Xaml.Media.Brush)));
protected override void OnKeyDown(KeyRoutedEventArgs e)
{
// Ignore the Enter key
if (e.Key == VirtualKey.Enter)
{
return;
}
base.OnKeyDown(e);
}
protected override void OnKeyUp(KeyRoutedEventArgs e)
{
// Ignore the Enter key
if (e.Key == VirtualKey.Enter)
{
return;
}
base.OnKeyUp(e);
}
private void OnButtonIdPropertyChanged(NumbersAndOperatorsEnum oldValue, NumbersAndOperatorsEnum newValue)
{
this.CommandParameter = new CalculatorButtonPressedEventArgs(AuditoryFeedback, newValue);
}
private void OnAuditoryFeedbackPropertyChanged(string oldValue, string newValue)
{
this.CommandParameter = new CalculatorButtonPressedEventArgs(newValue, ButtonId);
}
}
}
}

View file

@ -0,0 +1,102 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Diagnostics;
using Windows.Foundation;
using Windows.UI.ViewManagement;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
using CalculatorApp;
using CalculatorApp.Common;
using CalculatorApp.Controls;
namespace CalculatorApp
{
namespace Controls
{
public sealed class OperatorPanelButton : Windows.UI.Xaml.Controls.Primitives.ToggleButton
{
public OperatorPanelButton()
{
}
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
// Using a DependencyProperty as the backing store for Text. This enables animation, styling, binding, etc...
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register(nameof(Text), typeof(string), typeof(OperatorPanelButton), new PropertyMetadata(string.Empty));
public string Glyph
{
get { return (string)GetValue(GlyphProperty); }
set { SetValue(GlyphProperty, value); }
}
// Using a DependencyProperty as the backing store for Glyph. This enables animation, styling, binding, etc...
public static readonly DependencyProperty GlyphProperty =
DependencyProperty.Register(nameof(Glyph), typeof(string), typeof(OperatorPanelButton), new PropertyMetadata(string.Empty));
public double GlyphFontSize
{
get { return (double)GetValue(GlyphFontSizeProperty); }
set { SetValue(GlyphFontSizeProperty, value); }
}
// Using a DependencyProperty as the backing store for GlyphFontSize. This enables animation, styling, binding, etc...
public static readonly DependencyProperty GlyphFontSizeProperty =
DependencyProperty.Register(nameof(GlyphFontSize), typeof(double), typeof(OperatorPanelButton), new PropertyMetadata(default(double)));
public double ChevronFontSize
{
get { return (double)GetValue(ChevronFontSizeProperty); }
set { SetValue(ChevronFontSizeProperty, value); }
}
// Using a DependencyProperty as the backing store for ChevronFontSize. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ChevronFontSizeProperty =
DependencyProperty.Register(nameof(ChevronFontSize), typeof(double), typeof(OperatorPanelButton), new PropertyMetadata(default(double)));
public Flyout FlyoutMenu
{
get { return (Flyout)GetValue(FlyoutMenuProperty); }
set { SetValue(FlyoutMenuProperty, value); }
}
// Using a DependencyProperty as the backing store for FlyoutMenu. This enables animation, styling, binding, etc...
public static readonly DependencyProperty FlyoutMenuProperty =
DependencyProperty.Register(nameof(FlyoutMenu), typeof(Flyout), typeof(OperatorPanelButton), new PropertyMetadata(default(Flyout)));
protected override void OnApplyTemplate()
{
if (FlyoutMenu != null)
{
FlyoutMenu.Closed += FlyoutClosed;
}
}
protected override void OnToggle()
{
base.OnToggle();
if (IsChecked == true)
{
FlyoutMenu.ShowAt(this);
}
}
private void FlyoutClosed(object sender, object args)
{
IsChecked = false;
}
}
}
}

View file

@ -0,0 +1,164 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Diagnostics;
using CalculatorApp;
using CalculatorApp.Controls;
using Windows.Foundation;
using Windows.Devices.Input;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Controls;
namespace CalculatorApp
{
namespace Controls
{
public sealed class OperatorPanelListView : Windows.UI.Xaml.Controls.ListView
{
public OperatorPanelListView()
{
}
protected override void OnApplyTemplate()
{
m_scrollViewer = GetTemplateChild("ScrollViewer") as ScrollViewer;
m_scrollLeft = GetTemplateChild("ScrollLeft") as Button;
m_scrollRight = GetTemplateChild("ScrollRight") as Button;
m_content = GetTemplateChild("Content") as ItemsPresenter;
if (m_scrollLeft != null)
{
m_scrollLeft.Click += OnScrollClick;
m_scrollLeft.PointerExited += OnButtonPointerExited;
}
if (m_scrollRight != null)
{
m_scrollRight.Click += OnScrollClick;
m_scrollRight.PointerExited += OnButtonPointerExited;
}
if (m_scrollViewer != null)
{
m_scrollViewer.ViewChanged += ScrollViewChanged;
}
this.PointerEntered += OnPointerEntered;
this.PointerExited += OnPointerExited;
base.OnApplyTemplate();
}
private void OnScrollClick(object sender, RoutedEventArgs e)
{
var clicked = sender as Button;
if (clicked == m_scrollLeft)
{
ScrollLeft();
}
else
{
ScrollRight();
}
}
private void OnPointerEntered(object sender, PointerRoutedEventArgs e)
{
if (e.Pointer.PointerDeviceType == PointerDeviceType.Mouse)
{
UpdateScrollButtons();
m_isPointerEntered = true;
}
}
private void OnPointerExited(object sender, PointerRoutedEventArgs e)
{
m_scrollLeft.Visibility = Visibility.Collapsed;
m_scrollRight.Visibility = Visibility.Collapsed;
m_isPointerEntered = false;
}
private void OnButtonPointerExited(object sender, PointerRoutedEventArgs e)
{
var button = sender as Button;
// Do not bubble up the pointer exit event to the control if the button being exited was not visible
if (button.Visibility == Visibility.Collapsed)
{
e.Handled = true;
}
}
private void ScrollViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
{
if (m_isPointerEntered && !e.IsIntermediate)
{
UpdateScrollButtons();
}
}
private void ShowHideScrollButtons(Visibility vLeft, Visibility vRight)
{
if (m_scrollLeft != null && m_scrollRight != null)
{
m_scrollLeft.Visibility = vLeft;
m_scrollRight.Visibility = vRight;
}
}
private void UpdateScrollButtons()
{
if (m_content == null || m_scrollViewer == null)
{
return;
}
// When the width is smaller than the container, don't show any
if (m_content.ActualWidth <= m_scrollViewer.ActualWidth)
{
ShowHideScrollButtons(Visibility.Collapsed, Visibility.Collapsed);
}
// We have more number on both side. Show both arrows
else if ((m_scrollViewer.HorizontalOffset > 0) && (m_scrollViewer.HorizontalOffset < (m_scrollViewer.ExtentWidth - m_scrollViewer.ViewportWidth)))
{
ShowHideScrollButtons(Visibility.Visible, Visibility.Visible);
}
// Width is larger than the container and left most part of the number is shown. Should be able to scroll left.
else if (m_scrollViewer.HorizontalOffset == 0)
{
ShowHideScrollButtons(Visibility.Collapsed, Visibility.Visible);
}
else // Width is larger than the container and right most part of the number is shown. Should be able to scroll left.
{
ShowHideScrollButtons(Visibility.Visible, Visibility.Collapsed);
}
}
private void ScrollLeft()
{
double offset = m_scrollViewer.HorizontalOffset - (scrollRatio * m_scrollViewer.ViewportWidth);
m_scrollViewer.ChangeView(offset, null, null);
}
private void ScrollRight()
{
double offset = m_scrollViewer.HorizontalOffset + (scrollRatio * m_scrollViewer.ViewportWidth);
m_scrollViewer.ChangeView(offset, null, null);
}
private double scrollRatio = 0.7;
private bool m_isPointerEntered;
private Windows.UI.Xaml.Controls.ItemsPresenter m_content;
private Windows.UI.Xaml.Controls.ScrollViewer m_scrollViewer;
private Windows.UI.Xaml.Controls.Button m_scrollLeft;
private Windows.UI.Xaml.Controls.Button m_scrollRight;
}
}
}

View file

@ -0,0 +1,334 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Diagnostics;
using CalculatorApp;
using CalculatorApp.Common;
using CalculatorApp.Controls;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.Devices.Input;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Automation;
using Windows.UI.Xaml.Automation.Peers;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using Windows.ApplicationModel.Store;
namespace CalculatorApp
{
namespace Controls
{
public enum OverflowButtonPlacement : int
{
InLine,
Above
};
public sealed class OverflowTextBlock : Windows.UI.Xaml.Controls.Control
{
public OverflowTextBlock()
{
m_isAccessibilityViewControl = false;
m_ignoreViewChanged = false;
m_expressionContent = null;
m_itemsControl = null;
m_expressionContainer = null;
m_scrollLeft = null;
m_scrollRight = null;
}
public bool TokensUpdated
{
get { return (bool)GetValue(TokensUpdatedProperty); }
set { SetValue(TokensUpdatedProperty, value); }
}
// Using a DependencyProperty as the backing store for TokensUpdated. This enables animation, styling, binding, etc...
public static readonly DependencyProperty TokensUpdatedProperty =
DependencyProperty.Register(nameof(TokensUpdated), typeof(bool), typeof(OverflowTextBlock), new PropertyMetadata(default(bool), new PropertyChangedCallback((sender, args) =>
{
var self = (OverflowTextBlock)sender;
self.OnTokensUpdatedPropertyChanged((bool)args.OldValue, (bool)args.NewValue);
})));
public OverflowButtonPlacement ScrollButtonsPlacement
{
get { return (OverflowButtonPlacement)GetValue(ScrollButtonsPlacementProperty); }
set { SetValue(ScrollButtonsPlacementProperty, value); }
}
// Using a DependencyProperty as the backing store for ScrollButtonsPlacement. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ScrollButtonsPlacementProperty =
DependencyProperty.Register(nameof(ScrollButtonsPlacement), typeof(OverflowButtonPlacement), typeof(OverflowTextBlock), new PropertyMetadata(default(OverflowButtonPlacement), new PropertyChangedCallback((sender, args) =>
{
var self = (OverflowTextBlock)sender;
self.OnScrollButtonsPlacementPropertyChanged((OverflowButtonPlacement)args.OldValue, (OverflowButtonPlacement)args.NewValue);
})));
public bool IsActive
{
get { return (bool)GetValue(IsActiveProperty); }
set { SetValue(IsActiveProperty, value); }
}
// Using a DependencyProperty as the backing store for IsActive. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsActiveProperty =
DependencyProperty.Register(nameof(IsActive), typeof(bool), typeof(OverflowTextBlock), new PropertyMetadata(default(bool)));
public Windows.UI.Xaml.Style TextStyle
{
get { return (Style)GetValue(TextStyleProperty); }
set { SetValue(TextStyleProperty, value); }
}
// Using a DependencyProperty as the backing store for TextStyle. This enables animation, styling, binding, etc...
public static readonly DependencyProperty TextStyleProperty =
DependencyProperty.Register(nameof(TextStyle), typeof(Style), typeof(OverflowTextBlock), new PropertyMetadata(default(Style)));
public double ScrollButtonsWidth
{
get { return (double)GetValue(ScrollButtonsWidthProperty); }
set { SetValue(ScrollButtonsWidthProperty, value); }
}
// Using a DependencyProperty as the backing store for ScrollButtonsWidth. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ScrollButtonsWidthProperty =
DependencyProperty.Register(nameof(ScrollButtonsWidth), typeof(double), typeof(OverflowTextBlock), new PropertyMetadata(default(double)));
public double ScrollButtonsFontSize
{
get { return (double)GetValue(ScrollButtonsFontSizeProperty); }
set { SetValue(ScrollButtonsFontSizeProperty, value); }
}
// Using a DependencyProperty as the backing store for ScrollButtonsFontSize. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ScrollButtonsFontSizeProperty =
DependencyProperty.Register(nameof(ScrollButtonsFontSize), typeof(double), typeof(OverflowTextBlock), new PropertyMetadata(default(double)));
public void OnTokensUpdatedPropertyChanged(bool oldValue, bool newValue)
{
if (m_expressionContainer != null && newValue)
{
m_expressionContainer.UpdateLayout();
m_expressionContainer.ChangeView(m_expressionContainer.ScrollableWidth, null, null, true);
}
var newIsAccessibilityViewControl = m_itemsControl != null && m_itemsControl.Items.Count > 0;
if (m_isAccessibilityViewControl != newIsAccessibilityViewControl)
{
m_isAccessibilityViewControl = newIsAccessibilityViewControl;
AutomationProperties.SetAccessibilityView(this, newIsAccessibilityViewControl ? AccessibilityView.Control : AccessibilityView.Raw);
}
UpdateScrollButtons();
}
public void OnScrollButtonsPlacementPropertyChanged(OverflowButtonPlacement oldValue, OverflowButtonPlacement newValue)
{
if (newValue == OverflowButtonPlacement.InLine)
{
m_expressionContainer.Padding = new Thickness(0);
m_expressionContent.Margin = new Thickness(0);
}
UpdateScrollButtons();
}
public void UpdateScrollButtons()
{
if (m_expressionContainer == null || m_scrollLeft == null || m_scrollRight == null)
{
return;
}
var realOffset = m_expressionContainer.HorizontalOffset + m_expressionContainer.Padding.Left + m_expressionContent.Margin.Left;
var scrollLeftVisibility = realOffset > SCROLL_BUTTONS_APPROXIMATION_RANGE ? Visibility.Visible : Visibility.Collapsed;
var scrollRightVisibility = realOffset + m_expressionContainer.ActualWidth + SCROLL_BUTTONS_APPROXIMATION_RANGE < m_expressionContent.ActualWidth
? Visibility.Visible
: Visibility.Collapsed;
bool shouldTryFocusScrollRight = false;
if (m_scrollLeft.Visibility != scrollLeftVisibility)
{
if (scrollLeftVisibility == Visibility.Collapsed)
{
shouldTryFocusScrollRight = m_scrollLeft.Equals(FocusManager.GetFocusedElement());
}
m_scrollLeft.Visibility = scrollLeftVisibility;
}
if (m_scrollRight.Visibility != scrollRightVisibility)
{
if (scrollRightVisibility == Visibility.Collapsed && m_scrollLeft.Visibility == Visibility.Visible
&& m_scrollRight.Equals(FocusManager.GetFocusedElement()))
{
m_scrollLeft.Focus(FocusState.Programmatic);
}
m_scrollRight.Visibility = scrollRightVisibility;
}
if (shouldTryFocusScrollRight && scrollRightVisibility == Visibility.Visible)
{
m_scrollRight.Focus(FocusState.Programmatic);
}
if (ScrollButtonsPlacement == OverflowButtonPlacement.Above && m_expressionContent != null)
{
double left = m_scrollLeft != null && m_scrollLeft.Visibility == Visibility.Visible ? ScrollButtonsWidth : 0;
double right = m_scrollRight != null && m_scrollRight.Visibility == Visibility.Visible ? ScrollButtonsWidth : 0;
if (m_expressionContainer.Padding.Left != left || m_expressionContainer.Padding.Right != right)
{
m_expressionContainer.ViewChanged -= OnViewChanged;
m_expressionContainer.Padding = new Thickness(left, 0, right, 0);
m_expressionContent.Margin = new Thickness(-left, 0, -right, 0);
m_expressionContainer.UpdateLayout();
m_expressionContainer.Measure(m_expressionContainer.RenderSize);
m_expressionContainer.ViewChanged += OnViewChanged;
}
}
}
public void UnregisterEventHandlers()
{
// Unregister the event handlers
if (m_scrollLeft != null)
{
m_scrollLeft.Click -= OnScrollLeftClick;
}
if (m_scrollRight != null)
{
m_scrollRight.Click -= OnScrollRightClick;
}
if (m_expressionContainer != null)
{
m_expressionContainer.ViewChanged -= OnViewChanged;
}
}
protected override void OnApplyTemplate()
{
UnregisterEventHandlers();
var uiElement = GetTemplateChild("ExpressionContainer");
if (uiElement != null)
{
m_expressionContainer = (ScrollViewer)uiElement;
m_expressionContainer.ChangeView(m_expressionContainer.ExtentWidth - m_expressionContainer.ViewportWidth, null, null);
m_expressionContainer.ViewChanged += OnViewChanged;
}
uiElement = GetTemplateChild("ExpressionContent");
if (uiElement != null)
{
m_expressionContent = (FrameworkElement)uiElement;
}
uiElement = GetTemplateChild("ScrollLeft");
if (uiElement != null)
{
m_scrollLeft = (Button)uiElement;
m_scrollLeft.Click += OnScrollLeftClick;
}
uiElement = GetTemplateChild("ScrollRight");
if (uiElement != null)
{
m_scrollRight = (Button)uiElement;
m_scrollRight.Click += OnScrollRightClick;
}
uiElement = GetTemplateChild("TokenList");
if (uiElement != null)
{
m_itemsControl = (ItemsControl)uiElement;
}
UpdateAllState();
}
protected override AutomationPeer OnCreateAutomationPeer()
{
return new OverflowTextBlockAutomationPeer(this);
}
private void OnScrollLeftClick(object sender, RoutedEventArgs e)
{
ScrollLeft();
}
private void OnScrollRightClick(object sender, RoutedEventArgs e)
{
ScrollRight();
}
private void OnViewChanged(object sender, ScrollViewerViewChangedEventArgs args)
{
UpdateScrollButtons();
}
private void UpdateVisualState()
{
if (IsActive)
{
VisualStateManager.GoToState(this, "Active", true);
}
else
{
VisualStateManager.GoToState(this, "Normal", true);
}
}
private void UpdateAllState()
{
UpdateVisualState();
}
private void ScrollLeft()
{
if (m_expressionContainer != null && m_expressionContainer.HorizontalOffset > 0)
{
double offset = m_expressionContainer.HorizontalOffset - (SCROLL_RATIO * m_expressionContainer.ViewportWidth);
m_expressionContainer.ChangeView(offset, null, null);
m_expressionContainer.UpdateLayout();
UpdateScrollButtons();
}
}
private void ScrollRight()
{
var realOffset = m_expressionContainer.HorizontalOffset + m_expressionContainer.Padding.Left + m_expressionContent.Margin.Left;
if (m_expressionContainer != null && realOffset + m_expressionContainer.ActualWidth < m_expressionContent.ActualWidth)
{
double offset = m_expressionContainer.HorizontalOffset + (SCROLL_RATIO * m_expressionContainer.ViewportWidth);
m_expressionContainer.ChangeView(offset, null, null);
m_expressionContainer.UpdateLayout();
UpdateScrollButtons();
}
}
private const uint SCROLL_BUTTONS_APPROXIMATION_RANGE = 4;
private const double SCROLL_RATIO = 0.7;
private bool m_isAccessibilityViewControl;
private bool m_ignoreViewChanged;
private Windows.UI.Xaml.FrameworkElement m_expressionContent;
private Windows.UI.Xaml.Controls.ItemsControl m_itemsControl;
private Windows.UI.Xaml.Controls.ScrollViewer m_expressionContainer;
private Windows.UI.Xaml.Controls.Button m_scrollLeft;
private Windows.UI.Xaml.Controls.Button m_scrollRight;
}
}
}

View file

@ -0,0 +1,32 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Diagnostics;
using Windows.UI.Xaml.Automation.Peers;
using Windows.Foundation.Collections;
namespace CalculatorApp
{
namespace Controls
{
public sealed class OverflowTextBlockAutomationPeer : Windows.UI.Xaml.Automation.Peers.FrameworkElementAutomationPeer
{
public OverflowTextBlockAutomationPeer(OverflowTextBlock owner) : base(owner)
{
}
protected override AutomationControlType GetAutomationControlTypeCore()
{
return AutomationControlType.Text;
}
protected override IList<AutomationPeer> GetChildrenCore()
{
return null;
}
}
}
}

View file

@ -0,0 +1,78 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Diagnostics;
using CalculatorApp;
using CalculatorApp.Controls;
using CalculatorApp.ViewModel;
using Windows.System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Automation;
using Windows.UI.Xaml.Automation.Peers;
using Windows.Foundation.Collections;
namespace CalculatorApp
{
namespace Controls
{
public sealed class SupplementaryItemsControl : ItemsControl
{
public SupplementaryItemsControl()
{
}
protected override DependencyObject GetContainerForItemOverride()
{
return new SupplementaryContentPresenter();
}
protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
{
base.PrepareContainerForItemOverride(element, item);
var supplementaryResult = item as SupplementaryResult;
if (supplementaryResult != null)
{
AutomationProperties.SetName(element, supplementaryResult.GetLocalizedAutomationName());
}
}
}
public sealed class SupplementaryContentPresenter : ContentPresenter
{
public SupplementaryContentPresenter()
{
}
protected override AutomationPeer OnCreateAutomationPeer()
{
return new SupplementaryContentPresenterAP(this);
}
}
sealed class SupplementaryContentPresenterAP : FrameworkElementAutomationPeer
{
protected override AutomationControlType GetAutomationControlTypeCore()
{
return AutomationControlType.Text;
}
protected override IList<AutomationPeer> GetChildrenCore()
{
return null;
}
internal SupplementaryContentPresenterAP(SupplementaryContentPresenter owner)
: base(owner)
{
}
}
}
}

View file

@ -0,0 +1,47 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using CalculatorApp.ViewModel;
using Windows.UI.Xaml;
namespace CalculatorApp
{
namespace TemplateSelectors
{
public sealed class KeyGraphFeaturesTemplateSelector : Windows.UI.Xaml.Controls.DataTemplateSelector
{
public KeyGraphFeaturesTemplateSelector()
{
}
public Windows.UI.Xaml.DataTemplate RichEditTemplate { get; set; }
public Windows.UI.Xaml.DataTemplate GridTemplate { get; set; }
public Windows.UI.Xaml.DataTemplate TextBlockTemplate { get; set; }
protected override DataTemplate SelectTemplateCore(object item)
{
var kgfItem = (KeyGraphFeaturesItem)item;
if (!kgfItem.IsText)
{
if (kgfItem.DisplayItems.Count != 0)
{
return RichEditTemplate;
}
else if (kgfItem.GridItems.Count != 0)
{
return GridTemplate;
}
}
return TextBlockTemplate;
}
protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
{
return SelectTemplateCore(item);
}
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,873 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Diagnostics;
using CalculatorApp;
using CalculatorApp.Common;
using CalculatorApp.Converters;
using CalculatorApp.Controls;
using CalculatorApp.ViewModel;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.Globalization.NumberFormatting;
using Windows.System;
using Windows.UI.Core;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Automation;
using Windows.UI.Xaml.Automation.Peers;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using Windows.System.Threading;
using Windows.UI.ViewManagement;
namespace CalculatorApp
{
public class FontTable
{
public string numericSystem;
public double fullFont;
public double fullFontMin;
public double portraitMin;
public double snapFont;
public double fullNumPadFont;
public double snapScientificNumPadFont;
public double portraitScientificNumPadFont;
}
public delegate void FullscreenFlyoutClosedEventHandler();
[Windows.Foundation.Metadata.WebHostHidden]
public sealed partial class Calculator
{
public event FullscreenFlyoutClosedEventHandler FullscreenFlyoutClosed;
public Calculator()
{
m_doAnimate = false;
m_isLastAnimatedInScientific = false;
m_isLastAnimatedInProgrammer = false;
m_resultAnimate = false;
SetFontSizeResources();
InitializeComponent();
LoadResourceStrings();
if (LocalizationService.GetInstance().IsRtlLayout())
{
HistoryButton.HorizontalAlignment = HorizontalAlignment.Left;
}
m_displayFlyout = (MenuFlyout)Resources["DisplayContextMenu"];
var resLoader = AppResourceProvider.GetInstance();
CopyMenuItem.Text = resLoader.GetResourceString("copyMenuItem");
PasteMenuItem.Text = resLoader.GetResourceString("pasteMenuItem");
this.SizeChanged += Calculator_SizeChanged;
}
public CalculatorApp.ViewModel.StandardCalculatorViewModel Model
{
get => (StandardCalculatorViewModel)this.DataContext;
}
public bool IsStandard
{
get { return (bool)GetValue(IsStandardProperty); }
set { SetValue(IsStandardProperty, value); }
}
// Using a DependencyProperty as the backing store for IsStandard. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsStandardProperty =
DependencyProperty.Register(nameof(IsStandard), typeof(bool), typeof(Calculator), new PropertyMetadata(false, (sender, args) =>
{
var self = (Calculator)sender;
self.OnIsStandardPropertyChanged((bool)args.OldValue, (bool)args.NewValue);
}));
public bool IsScientific
{
get { return (bool)GetValue(IsScientificProperty); }
set { SetValue(IsScientificProperty, value); }
}
// Using a DependencyProperty as the backing store for IsScientific. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsScientificProperty =
DependencyProperty.Register(nameof(IsScientific), typeof(bool), typeof(Calculator), new PropertyMetadata(false, (sender, args) =>
{
var self = (Calculator)sender;
self.OnIsScientificPropertyChanged((bool)args.OldValue, (bool)args.NewValue);
}));
public bool IsProgrammer
{
get { return (bool)GetValue(IsProgrammerProperty); }
set { SetValue(IsProgrammerProperty, value); }
}
// Using a DependencyProperty as the backing store for IsProgrammer. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsProgrammerProperty =
DependencyProperty.Register(nameof(IsProgrammer), typeof(bool), typeof(Calculator), new PropertyMetadata(false, (sender, args) =>
{
var self = (Calculator)sender;
self.OnIsProgrammerPropertyChanged((bool)args.OldValue, (bool)args.NewValue);
}));
public bool IsAlwaysOnTop
{
get { return (bool)GetValue(IsAlwaysOnTopProperty); }
set { SetValue(IsAlwaysOnTopProperty, value); }
}
// Using a DependencyProperty as the backing store for IsAlwaysOnTop. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsAlwaysOnTopProperty =
DependencyProperty.Register(nameof(IsAlwaysOnTop), typeof(bool), typeof(Calculator), new PropertyMetadata(false, (sender, args) =>
{
var self = (Calculator)sender;
self.OnIsAlwaysOnTopPropertyChanged((bool)args.OldValue, (bool)args.NewValue);
}));
public System.Windows.Input.ICommand HistoryButtonPressed
{
get
{
if (donotuse_HistoryButtonPressed == null)
{
donotuse_HistoryButtonPressed = new DelegateCommand<Calculator>(this, ToggleHistoryFlyout);
}
return donotuse_HistoryButtonPressed;
}
}
private System.Windows.Input.ICommand donotuse_HistoryButtonPressed;
private static UISettings uiSettings = new UISettings();
public void AnimateCalculator(bool resultAnimate)
{
if (uiSettings.AnimationsEnabled)
{
m_doAnimate = true;
m_resultAnimate = resultAnimate;
if (((m_isLastAnimatedInScientific && IsScientific) || (!m_isLastAnimatedInScientific && !IsScientific))
& ((m_isLastAnimatedInProgrammer && IsProgrammer) || (!m_isLastAnimatedInProgrammer && !IsProgrammer)))
{
// We are forcing the animation here
// It's because if last animation was in standard, then go to unit converter, then comes back to standard
// The state for the calculator does not change and the animation would not get run.
this.OnModeVisualStateCompleted(null, null);
}
}
}
public void InitializeHistoryView(CalculatorApp.ViewModel.HistoryViewModel historyVM)
{
if (m_historyList == null)
{
m_historyList = new HistoryList();
m_historyList.DataContext = historyVM;
historyVM.HideHistoryClicked += OnHideHistoryClicked;
historyVM.HistoryItemClicked += OnHistoryItemClicked;
}
}
public void UpdatePanelViewState()
{
UpdateHistoryState();
UpdateMemoryState();
}
public void UnregisterEventHandlers()
{
ExpressionText.UnregisterEventHandlers();
AlwaysOnTopResults.UnregisterEventHandlers();
}
public void CloseHistoryFlyout()
{
if (m_fIsHistoryFlyoutOpen)
{
HistoryFlyout.Hide();
}
}
public void CloseMemoryFlyout()
{
if (m_fIsMemoryFlyoutOpen)
{
MemoryFlyout.Hide();
}
}
public void SetDefaultFocus()
{
if (!IsAlwaysOnTop)
{
Results.Focus(FocusState.Programmatic);
}
else
{
AlwaysOnTopResults.Focus(FocusState.Programmatic);
}
}
// Methods used by native bindings
public static Visibility ShouldDisplayHistoryButton(bool isAlwaysOnTop, bool isProgrammer, Visibility dockPanelVisibility)
{
return !isAlwaysOnTop && !isProgrammer && dockPanelVisibility == Visibility.Collapsed ? Visibility.Visible : Visibility.Collapsed;
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
Model.PropertyChanged += OnCalcPropertyChanged;
Model.HideMemoryClicked += OnHideMemoryClicked;
InitializeHistoryView(Model.HistoryVM);
string historyPaneName = AppResourceProvider.GetInstance().GetResourceString("HistoryPane");
HistoryFlyout.FlyoutPresenterStyle.Setters.Add(new Setter(AutomationProperties.NameProperty, historyPaneName));
string memoryPaneName = AppResourceProvider.GetInstance().GetResourceString("MemoryPane");
MemoryFlyout.FlyoutPresenterStyle.Setters.Add(new Setter(AutomationProperties.NameProperty, memoryPaneName));
if (Windows.Foundation.Metadata.ApiInformation.IsEventPresent("Windows.UI.Xaml.Controls.Primitives.FlyoutBase", "Closing"))
{
HistoryFlyout.Closing += HistoryFlyout_Closing;
MemoryFlyout.Closing += OnMemoryFlyoutClosing;
}
// Delay load things later when we get a chance.
WeakReference weakThis = new WeakReference(this);
_ = this.Dispatcher.RunAsync(
CoreDispatcherPriority.Normal, new DispatchedHandler(() => {
if (TraceLogger.GetInstance().IsWindowIdInLog(ApplicationView.GetApplicationViewIdForWindow(CoreWindow.GetForCurrentThread())))
{
var refThis = weakThis.Target as Calculator;
if (refThis != null)
{
refThis.GetMemory();
}
}
}));
}
private void LoadResourceStrings()
{
var resProvider = AppResourceProvider.GetInstance();
m_openMemoryFlyoutAutomationName = resProvider.GetResourceString("MemoryButton_Open");
m_closeMemoryFlyoutAutomationName = resProvider.GetResourceString("MemoryButton_Close");
m_openHistoryFlyoutAutomationName = resProvider.GetResourceString("HistoryButton_Open");
m_closeHistoryFlyoutAutomationName = resProvider.GetResourceString("HistoryButton_Close");
m_dockPanelHistoryMemoryLists = resProvider.GetResourceString("DockPanel_HistoryMemoryLists");
m_dockPanelMemoryList = resProvider.GetResourceString("DockPanel_MemoryList");
AutomationProperties.SetName(MemoryButton, m_openMemoryFlyoutAutomationName);
AutomationProperties.SetName(HistoryButton, m_openHistoryFlyoutAutomationName);
AutomationProperties.SetName(DockPanel, m_dockPanelHistoryMemoryLists);
}
private void UpdateViewState()
{
string state;
if (IsProgrammer)
{
state = "Programmer";
Model.IsDecimalEnabled = false;
ResultsMVisualStateTrigger.MinWindowHeight = 640;
}
else if (IsScientific)
{
state = "Scientific";
Model.IsDecimalEnabled = true;
ResultsMVisualStateTrigger.MinWindowHeight = 544;
}
else
{
state = "Standard";
Model.IsDecimalEnabled = true;
ResultsMVisualStateTrigger.MinWindowHeight = 1;
}
CloseHistoryFlyout();
CloseMemoryFlyout();
VisualStateManager.GoToState(this, state, true);
}
private void UpdateMemoryState()
{
if (!IsAlwaysOnTop)
{
if (!Model.IsMemoryEmpty)
{
MemRecall.IsEnabled = true;
ClearMemoryButton.IsEnabled = true;
}
else
{
MemRecall.IsEnabled = false;
ClearMemoryButton.IsEnabled = false;
}
if (DockPanel.Visibility == Visibility.Visible)
{
CloseMemoryFlyout();
SetChildAsMemory();
MemoryButton.Visibility = Visibility.Collapsed;
if (m_IsLastFlyoutMemory && !IsProgrammer)
{
DockPivot.SelectedIndex = 1;
}
}
else
{
MemoryButton.Visibility = Visibility.Visible;
DockMemoryHolder.Child = null;
}
}
}
private void UpdateHistoryState()
{
if (DockPanel.Visibility == Visibility.Visible)
{
// docked view
CloseHistoryFlyout();
SetChildAsHistory();
if (!IsProgrammer && m_IsLastFlyoutHistory)
{
DockPivot.SelectedIndex = 0;
}
}
else
{
// flyout view
DockHistoryHolder.Child = null;
}
}
private void OnContextRequested(UIElement sender, ContextRequestedEventArgs e)
{
var requestedElement = (FrameworkElement)e.OriginalSource;
PasteMenuItem.IsEnabled = CopyPasteManager.HasStringToPaste();
Point point;
if (e.TryGetPosition(requestedElement, out point))
{
m_displayFlyout.ShowAt(requestedElement, point);
}
else
{
// Not invoked via pointer, so let XAML choose a default location.
m_displayFlyout.ShowAt(requestedElement);
}
e.Handled = true;
}
private void OnContextCanceled(UIElement sender, RoutedEventArgs e)
{
m_displayFlyout.Hide();
}
private void OnIsScientificPropertyChanged(bool oldValue, bool newValue)
{
if (newValue)
{
EnsureScientific();
}
UpdateViewState();
UpdatePanelViewState();
}
private void OnIsProgrammerPropertyChanged(bool oldValue, bool newValue)
{
if (newValue)
{
EnsureProgrammer();
m_pivotItem = (PivotItem)DockPivot.Items[0];
DockPivot.Items.RemoveAt(0);
}
else
{
if (m_pivotItem != null && DockPivot.Items.Count == 1)
{
DockPivot.Items.Insert(0, m_pivotItem);
}
}
DockPivot.SelectedIndex = 0;
UpdateViewState();
UpdatePanelViewState();
}
private void OnIsStandardPropertyChanged(bool oldValue, bool newValue)
{
UpdateViewState();
UpdatePanelViewState();
}
private void OnIsAlwaysOnTopPropertyChanged(bool oldValue, bool newValue)
{
if (newValue)
{
VisualStateManager.GoToState(this, "DisplayModeAlwaysOnTop", false);
AlwaysOnTopResults.UpdateScrollButtons();
}
else
{
VisualStateManager.GoToState(this, "DisplayModeNormal", false);
if (!Model.IsInError)
{
EnableMemoryControls(true);
}
Results.UpdateTextState();
}
Model.IsMemoryEmpty = (Model.MemorizedNumbers.Count == 0) || IsAlwaysOnTop;
UpdateViewState();
UpdatePanelViewState();
}
private void OnIsInErrorPropertyChanged()
{
bool isError = Model.IsInError;
string newState = isError ? "ErrorLayout" : "NoErrorLayout";
VisualStateManager.GoToState(this, newState, false);
if (m_memory != null)
{
m_memory.IsErrorVisualState = isError;
}
OpsPanel.IsErrorVisualState = isError;
if (IsScientific && ScientificAngleButtons != null)
{
ScientificAngleButtons.IsErrorVisualState = isError;
}
// CSHARP_MIGRATION: TODO:
// ScientificAngleButtons works but ProgrammerDisplayPanel doesn't
else if (IsProgrammer && ProgrammerDisplayPanel != null)
{
ProgrammerDisplayPanel.IsErrorVisualState = isError;
}
}
private void OnCalcPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
string prop = e.PropertyName;
if (prop == StandardCalculatorViewModel.IsMemoryEmptyPropertyName)
{
UpdateMemoryState();
}
else if (prop == StandardCalculatorViewModel.IsInErrorPropertyName)
{
OnIsInErrorPropertyChanged();
}
}
private void OnLayoutVisualStateCompleted(object sender, object e)
{
UpdatePanelViewState();
}
private void OnModeVisualStateCompleted(object sender, object e)
{
m_isLastAnimatedInScientific = IsScientific;
m_isLastAnimatedInProgrammer = IsProgrammer;
if (m_doAnimate)
{
m_doAnimate = false;
if (m_resultAnimate)
{
m_resultAnimate = false;
Animate.Begin();
}
else
{
AnimateWithoutResult.Begin();
}
}
if (IsProgrammer)
{
AutomationProperties.SetName(DockPanel, m_dockPanelMemoryList);
}
else
{
AutomationProperties.SetName(DockPanel, m_dockPanelHistoryMemoryLists);
}
}
private void OnErrorVisualStateCompleted(object sender, object e)
{
SetDefaultFocus();
}
private void OnDisplayVisualStateCompleted(object sender, object e)
{
SetDefaultFocus();
}
private void EnsureScientific()
{
OpsPanel.EnsureScientificOps();
if (ScientificAngleButtons == null)
{
this.FindName("ScientificAngleButtons");
}
}
private void EnsureProgrammer()
{
if (ProgrammerOperators == null)
{
this.FindName("ProgrammerOperators");
}
if (ProgrammerDisplayPanel == null)
{
this.FindName("ProgrammerDisplayPanel");
}
OpsPanel.EnsureProgrammerRadixOps();
ProgrammerOperators.SetRadixButton(Model.CurrentRadixType);
}
// Since we need different font sizes for different numeric system,
// we use a table of optimal font sizes for each numeric system.
private static readonly FontTable[] fontTables = new FontTable[] {
new FontTable { numericSystem = "Arab", fullFont = 104, fullFontMin = 29.333, portraitMin = 23, snapFont = 40,
fullNumPadFont = 56, snapScientificNumPadFont = 40, portraitScientificNumPadFont = 56 },
new FontTable { numericSystem = "ArabExt", fullFont = 104, fullFontMin = 29.333, portraitMin = 23, snapFont = 40,
fullNumPadFont = 56, snapScientificNumPadFont = 40, portraitScientificNumPadFont = 56 },
new FontTable { numericSystem = "Beng", fullFont = 104, fullFontMin = 26, portraitMin = 17, snapFont = 40,
fullNumPadFont = 56, snapScientificNumPadFont = 40, portraitScientificNumPadFont = 56 },
new FontTable { numericSystem = "Deva", fullFont = 104, fullFontMin = 29.333, portraitMin = 20.5, snapFont = 40,
fullNumPadFont = 56, snapScientificNumPadFont = 40, portraitScientificNumPadFont = 56 },
new FontTable { numericSystem = "Gujr", fullFont = 104, fullFontMin = 29.333, portraitMin = 18.5, snapFont = 40,
fullNumPadFont = 56, snapScientificNumPadFont = 40, portraitScientificNumPadFont = 56 },
new FontTable { numericSystem = "Khmr", fullFont = 104, fullFontMin = 29.333, portraitMin = 19.5, snapFont = 40,
fullNumPadFont = 56, snapScientificNumPadFont = 40, portraitScientificNumPadFont = 56 },
new FontTable { numericSystem = "Knda", fullFont = 104, fullFontMin = 25, portraitMin = 17, snapFont = 40,
fullNumPadFont = 56, snapScientificNumPadFont = 40, portraitScientificNumPadFont = 56 },
new FontTable { numericSystem = "Laoo", fullFont = 104, fullFontMin = 28, portraitMin = 18, snapFont = 40,
fullNumPadFont = 56, snapScientificNumPadFont = 40, portraitScientificNumPadFont = 56 },
new FontTable { numericSystem = "Latn", fullFont = 104, fullFontMin = 29.333, portraitMin = 23, snapFont = 40,
fullNumPadFont = 56, snapScientificNumPadFont = 40, portraitScientificNumPadFont = 56 },
new FontTable { numericSystem = "Mlym", fullFont = 80, fullFontMin = 22, portraitMin = 15.5, snapFont = 30,
fullNumPadFont = 56, snapScientificNumPadFont = 35, portraitScientificNumPadFont = 48 },
new FontTable { numericSystem = "Mymr", fullFont = 104, fullFontMin = 29.333, portraitMin = 20, snapFont = 35,
fullNumPadFont = 48, snapScientificNumPadFont = 36, portraitScientificNumPadFont = 48 },
new FontTable { numericSystem = "Orya", fullFont = 88, fullFontMin = 26, portraitMin = 20, snapFont = 40,
fullNumPadFont = 56, snapScientificNumPadFont = 40, portraitScientificNumPadFont = 56 },
new FontTable { numericSystem = "TamlDec", fullFont = 77, fullFontMin = 25, portraitMin = 16, snapFont = 28,
fullNumPadFont = 48, snapScientificNumPadFont = 34, portraitScientificNumPadFont = 48 },
new FontTable { numericSystem = "Telu", fullFont = 104, fullFontMin = 25, portraitMin = 16.5, snapFont = 40,
fullNumPadFont = 56, snapScientificNumPadFont = 40, portraitScientificNumPadFont = 56 },
new FontTable { numericSystem = "Thai", fullFont = 104, fullFontMin = 28, portraitMin = 18, snapFont = 40,
fullNumPadFont = 56, snapScientificNumPadFont = 40, portraitScientificNumPadFont = 56 },
new FontTable { numericSystem = "Tibt", fullFont = 104, fullFontMin = 29.333, portraitMin = 20, snapFont = 40,
fullNumPadFont = 56, snapScientificNumPadFont = 40, portraitScientificNumPadFont = 56 },
new FontTable { numericSystem = "Default", fullFont = 104, fullFontMin = 29.333, portraitMin = 23, snapFont = 40,
fullNumPadFont = 56, snapScientificNumPadFont = 40, portraitScientificNumPadFont = 56 }
};
private void SetFontSizeResources()
{
DecimalFormatter formatter = LocalizationService.GetInstance().GetRegionalSettingsAwareDecimalFormatter();
int currentItemIdx = 0;
while (!fontTables[currentItemIdx].numericSystem.Equals("Default") &&
!fontTables[currentItemIdx].numericSystem.Equals(formatter.NumeralSystem))
{
++currentItemIdx;
}
var currentItem = fontTables[currentItemIdx];
this.Resources.Add("ResultFullFontSize", currentItem.fullFont);
this.Resources.Add("ResultFullMinFontSize", currentItem.fullFontMin);
this.Resources.Add("ResultPortraitMinFontSize", currentItem.portraitMin);
this.Resources.Add("ResultSnapFontSize", currentItem.snapFont);
this.Resources.Add("CalcButtonCaptionSizeOverride", currentItem.fullNumPadFont);
this.Resources.Add("CalcButtonScientificSnapCaptionSizeOverride", currentItem.snapScientificNumPadFont);
this.Resources.Add("CalcButtonScientificPortraitCaptionSizeOverride", currentItem.portraitScientificNumPadFont);
}
private string GetCurrentLayoutState()
{
if (IsProgrammer)
{
return "Programmer";
}
else if (IsScientific)
{
return "Scientific";
}
else
{
return "Standard";
}
}
private void Calculator_SizeChanged(object sender, SizeChangedEventArgs e)
{
if (Model.IsAlwaysOnTop)
{
AlwaysOnTopResults.UpdateScrollButtons();
}
}
private Windows.UI.Xaml.Controls.ListView m_tokenList;
private Windows.UI.Xaml.Controls.MenuFlyout m_displayFlyout;
private bool m_doAnimate;
private bool m_resultAnimate;
private bool m_isLastAnimatedInScientific;
private bool m_isLastAnimatedInProgrammer;
private bool m_IsLastFlyoutMemory = false;
private bool m_IsLastFlyoutHistory = false;
private string m_openMemoryFlyoutAutomationName;
private string m_closeMemoryFlyoutAutomationName;
private string m_openHistoryFlyoutAutomationName;
private string m_closeHistoryFlyoutAutomationName;
private string m_dockPanelHistoryMemoryLists;
private string m_dockPanelMemoryList;
private Windows.UI.Xaml.Controls.PivotItem m_pivotItem;
private bool m_IsDigit = false;
private Memory m_memory;
private void HistoryFlyout_Opened(object sender, object args)
{
m_fIsHistoryFlyoutOpen = true;
m_IsLastFlyoutMemory = false;
m_IsLastFlyoutHistory = true;
EnableControls(false);
AutomationProperties.SetName(HistoryButton, m_closeHistoryFlyoutAutomationName);
}
private void HistoryFlyout_Closing(FlyoutBase sender, FlyoutBaseClosingEventArgs args)
{
// Set in the Closing event so the new name is available when the Flyout has Closed.
AutomationProperties.SetName(HistoryButton, m_openHistoryFlyoutAutomationName);
}
private void HistoryFlyout_Closed(object sender, object args)
{
// Ideally, this would be renamed in the Closing event because the Closed event is too late.
// Closing is not available until RS1+ so we set the name again here for TH2 support.
AutomationProperties.SetName(HistoryButton, m_openHistoryFlyoutAutomationName);
m_fIsHistoryFlyoutOpen = false;
EnableControls(true);
if (HistoryButton.IsEnabled && HistoryButton.Visibility == Visibility.Visible)
{
HistoryButton.Focus(FocusState.Programmatic);
}
FullscreenFlyoutClosed?.Invoke();
}
private void OnHideHistoryClicked()
{
ToggleHistoryFlyout(null);
}
private void OnHideMemoryClicked()
{
if (!m_fIsMemoryFlyoutOpen)
{
this.Focus(FocusState.Programmatic);
}
MemoryFlyout.Hide();
}
private void OnHistoryItemClicked(HistoryItemViewModel e)
{
Model.SelectHistoryItem(e);
CloseHistoryFlyout();
this.Focus(FocusState.Programmatic);
}
private void ToggleHistoryFlyout(object parameter)
{
if (Model.IsProgrammer || DockPanel.Visibility == Visibility.Visible)
{
return;
}
if (m_fIsHistoryFlyoutOpen)
{
HistoryFlyout.Hide();
}
else
{
HistoryFlyout.Content = m_historyList;
m_historyList.RowHeight = new GridLength(NumpadPanel.ActualHeight);
FlyoutBase.ShowAttachedFlyout(HistoryButton);
}
}
private void ToggleMemoryFlyout(object sender, RoutedEventArgs e)
{
if (DockPanel.Visibility == Visibility.Visible)
{
return;
}
if (m_fIsMemoryFlyoutOpen)
{
MemoryFlyout.Hide();
}
else
{
MemoryFlyout.Content = GetMemory();
m_memory.RowHeight = new GridLength(NumpadPanel.ActualHeight);
FlyoutBase.ShowAttachedFlyout(MemoryButton);
}
}
private CalculatorApp.HistoryList m_historyList;
private bool m_fIsHistoryFlyoutOpen;
private bool m_fIsMemoryFlyoutOpen;
private void OnMemoryFlyoutOpened(object sender, object args)
{
m_IsLastFlyoutMemory = true;
m_IsLastFlyoutHistory = false;
m_fIsMemoryFlyoutOpen = true;
AutomationProperties.SetName(MemoryButton, m_closeMemoryFlyoutAutomationName);
EnableControls(false);
}
private void OnMemoryFlyoutClosing(FlyoutBase sender, FlyoutBaseClosingEventArgs args)
{
// Set in the Closing event so the new name is available when the Flyout has Closed.
AutomationProperties.SetName(MemoryButton, m_openMemoryFlyoutAutomationName);
}
private void OnMemoryFlyoutClosed(object sender, object args)
{
// Ideally, this would be renamed in the Closing event because the Closed event is too late.
// Closing is not available until RS1+ so we set the name again here for TH2 support.
AutomationProperties.SetName(MemoryButton, m_openMemoryFlyoutAutomationName);
m_fIsMemoryFlyoutOpen = false;
EnableControls(true);
if (MemoryButton.IsEnabled)
{
MemoryButton.Focus(FocusState.Programmatic);
}
FullscreenFlyoutClosed?.Invoke();
}
private void SetChildAsMemory()
{
DockMemoryHolder.Child = GetMemory();
}
private void SetChildAsHistory()
{
if (m_historyList == null)
{
InitializeHistoryView(Model.HistoryVM);
}
DockHistoryHolder.Child = m_historyList;
}
private Memory GetMemory()
{
if (m_memory == null)
{
m_memory = new Memory();
VisualStateManager.GoToState(m_memory, GetCurrentLayoutState(), true);
}
return m_memory;
}
private void EnableControls(bool enable)
{
OpsPanel.IsEnabled = enable;
EnableMemoryControls(enable);
}
private void EnableMemoryControls(bool enable)
{
MemButton.IsEnabled = enable;
MemMinus.IsEnabled = enable;
MemPlus.IsEnabled = enable;
if (!Model.IsMemoryEmpty)
{
MemRecall.IsEnabled = enable;
ClearMemoryButton.IsEnabled = enable;
}
}
private void OnMemoryFlyOutTapped(object sender, TappedRoutedEventArgs e)
{
Grid grid = (Grid)sender;
Point point = e.GetPosition(null);
if (point.Y < (grid.ActualHeight - NumpadPanel.ActualHeight))
{
MemoryFlyout.Hide();
}
}
private void OnHistoryFlyOutTapped(object sender, TappedRoutedEventArgs e)
{
Grid grid = (Grid)sender;
Point point = e.GetPosition(null);
if (point.Y < (grid.ActualHeight - NumpadPanel.ActualHeight))
{
HistoryFlyout.Hide();
}
}
private void DockPanelTapped(object sender, TappedRoutedEventArgs e)
{
int index = DockPivot.SelectedIndex;
if (index == 1 && !IsProgrammer)
{
SetChildAsMemory();
}
m_IsLastFlyoutMemory = false;
m_IsLastFlyoutHistory = false;
}
private void OnHistoryAccessKeyInvoked(UIElement sender, AccessKeyInvokedEventArgs args)
{
DockPivot.SelectedItem = HistoryPivotItem;
}
private void OnMemoryAccessKeyInvoked(UIElement sender, AccessKeyInvokedEventArgs args)
{
DockPivot.SelectedItem = MemoryPivotItem;
}
private void OnVisualStateChanged(object sender, VisualStateChangedEventArgs e)
{
if (!IsStandard && !IsScientific && !IsProgrammer)
{
return;
}
var mode = IsStandard ? ViewMode.Standard : IsScientific ? ViewMode.Scientific : ViewMode.Programmer;
TraceLogger.GetInstance().LogVisualStateChanged(mode, e.NewState.Name, IsAlwaysOnTop);
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,286 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
//
// CalculatorProgrammerBitFlipPanel.xaml.h
// Declaration of the CalculatorProgrammerBitFlipPanel class
//
// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Diagnostics;
using CalculatorApp;
using CalculatorApp.Common;
using CalculatorApp.Controls;
using CalculatorApp.ViewModel;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Automation;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
namespace CalculatorApp
{
[Windows.Foundation.Metadata.WebHostHidden]
public sealed partial class CalculatorProgrammerBitFlipPanel
{
public CalculatorProgrammerBitFlipPanel()
{
m_updatingCheckedStates = false;
InitializeComponent();
AssignFlipButtons();
}
public bool ShouldEnableBit(BitLength length, int index)
{
return index <= GetIndexOfLastBit(length);
}
public StandardCalculatorViewModel Model
{
get { return (StandardCalculatorViewModel)this.DataContext; }
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
SubscribePropertyChanged();
}
private void OnUnloaded(object sender, RoutedEventArgs e)
{
UnsubscribePropertyChanged();
}
private void SubscribePropertyChanged()
{
if (Model != null)
{
Model.PropertyChanged += OnPropertyChanged;
m_currentValueBitLength = Model.ValueBitLength;
UpdateCheckedStates(true);
}
}
private void UnsubscribePropertyChanged()
{
if (Model != null)
{
Model.PropertyChanged -= OnPropertyChanged;
}
}
private void OnPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName == StandardCalculatorViewModel.BinaryDigitsPropertyName)
{
UpdateCheckedStates(false);
m_currentValueBitLength = Model.ValueBitLength;
}
else if (
e.PropertyName == StandardCalculatorViewModel.IsBitFlipCheckedPropertyName
|| e.PropertyName == StandardCalculatorViewModel.IsProgrammerPropertyName)
{
if (Model.IsBitFlipChecked && Model.IsProgrammer)
{
// OnBitToggle won't update the automation properties when this control isn't displayed
// We need to update all automation properties names manually when the BitFlipPanel is displayed again
UpdateAutomationPropertiesNames();
}
}
}
private void AssignFlipButtons()
{
Debug.Assert(m_flipButtons.Length == 64);
m_flipButtons[0] = this.Bit0;
m_flipButtons[1] = this.Bit1;
m_flipButtons[2] = this.Bit2;
m_flipButtons[3] = this.Bit3;
m_flipButtons[4] = this.Bit4;
m_flipButtons[5] = this.Bit5;
m_flipButtons[6] = this.Bit6;
m_flipButtons[7] = this.Bit7;
m_flipButtons[8] = this.Bit8;
m_flipButtons[9] = this.Bit9;
m_flipButtons[10] = this.Bit10;
m_flipButtons[11] = this.Bit11;
m_flipButtons[12] = this.Bit12;
m_flipButtons[13] = this.Bit13;
m_flipButtons[14] = this.Bit14;
m_flipButtons[15] = this.Bit15;
m_flipButtons[16] = this.Bit16;
m_flipButtons[17] = this.Bit17;
m_flipButtons[18] = this.Bit18;
m_flipButtons[19] = this.Bit19;
m_flipButtons[20] = this.Bit20;
m_flipButtons[21] = this.Bit21;
m_flipButtons[22] = this.Bit22;
m_flipButtons[23] = this.Bit23;
m_flipButtons[24] = this.Bit24;
m_flipButtons[25] = this.Bit25;
m_flipButtons[26] = this.Bit26;
m_flipButtons[27] = this.Bit27;
m_flipButtons[28] = this.Bit28;
m_flipButtons[29] = this.Bit29;
m_flipButtons[30] = this.Bit30;
m_flipButtons[31] = this.Bit31;
m_flipButtons[32] = this.Bit32;
m_flipButtons[33] = this.Bit33;
m_flipButtons[34] = this.Bit34;
m_flipButtons[35] = this.Bit35;
m_flipButtons[36] = this.Bit36;
m_flipButtons[37] = this.Bit37;
m_flipButtons[38] = this.Bit38;
m_flipButtons[39] = this.Bit39;
m_flipButtons[40] = this.Bit40;
m_flipButtons[41] = this.Bit41;
m_flipButtons[42] = this.Bit42;
m_flipButtons[43] = this.Bit43;
m_flipButtons[44] = this.Bit44;
m_flipButtons[45] = this.Bit45;
m_flipButtons[46] = this.Bit46;
m_flipButtons[47] = this.Bit47;
m_flipButtons[48] = this.Bit48;
m_flipButtons[49] = this.Bit49;
m_flipButtons[50] = this.Bit50;
m_flipButtons[51] = this.Bit51;
m_flipButtons[52] = this.Bit52;
m_flipButtons[53] = this.Bit53;
m_flipButtons[54] = this.Bit54;
m_flipButtons[55] = this.Bit55;
m_flipButtons[56] = this.Bit56;
m_flipButtons[57] = this.Bit57;
m_flipButtons[58] = this.Bit58;
m_flipButtons[59] = this.Bit59;
m_flipButtons[60] = this.Bit60;
m_flipButtons[61] = this.Bit61;
m_flipButtons[62] = this.Bit62;
m_flipButtons[63] = this.Bit63;
}
private void OnBitToggled(object sender, RoutedEventArgs e)
{
if (m_updatingCheckedStates)
{
return;
}
// Handle this the bit toggled event only if it is coming from BitFlip mode.
// Any input from the Numpad may also result in toggling the bit as their state is bound to the BinaryDisplayValue.
// Also, if the mode is switched to other Calculator modes when the BitFlip panel is open,
// a race condition exists in which the IsProgrammerMode property is still true and the UpdatePrimaryResult() is called,
// which continuously alters the Display Value and the state of the Bit Flip buttons.
if (Model.IsBitFlipChecked && Model.IsProgrammer)
{
var flipButton = (FlipButtons)sender;
int index = (int)flipButton.Tag;
flipButton.SetValue(AutomationProperties.NameProperty, GenerateAutomationPropertiesName(index, flipButton.IsChecked.Value));
Model.ButtonPressed.Execute(flipButton.ButtonId);
}
}
private string GenerateAutomationPropertiesName(int position, bool value)
{
var resourceLoader = AppResourceProvider.GetInstance();
string automationNameTemplate = resourceLoader.GetResourceString("BitFlipItemAutomationName");
string bitPosition;
if (position == 0)
{
bitPosition = resourceLoader.GetResourceString("LeastSignificantBit");
}
else
{
int lastPosition = -1;
if (Model != null)
{
lastPosition = GetIndexOfLastBit(Model.ValueBitLength);
}
if (position == lastPosition)
{
bitPosition = resourceLoader.GetResourceString("MostSignificantBit");
}
else
{
string indexName = resourceLoader.GetResourceString(position.ToString());
string bitPositionTemplate = resourceLoader.GetResourceString("BitPosition");
bitPosition = LocalizationStringUtil.GetLocalizedString(bitPositionTemplate, indexName);
}
}
return LocalizationStringUtil.GetLocalizedString(automationNameTemplate, bitPosition, value ? "1" : "0");
}
private void UpdateCheckedStates(bool updateAutomationPropertiesNames)
{
Debug.Assert(!m_updatingCheckedStates);
Debug.Assert(m_flipButtons.Length == s_numBits);
if (Model == null)
{
return;
}
m_updatingCheckedStates = true;
// CSHARP_MIGRATION:
// iterator and index move at the same time with same step
// add index validation in the loop
int index = 0;
bool mustUpdateTextOfMostSignificantDigits = m_currentValueBitLength != Model.ValueBitLength;
int previousMSDPosition = GetIndexOfLastBit(m_currentValueBitLength);
int newMSDPosition = GetIndexOfLastBit(Model.ValueBitLength);
foreach (bool val in Model.BinaryDigits)
{
if (index < m_flipButtons.Length)
{
bool hasValueChanged = m_flipButtons[index].IsChecked.Value != val;
m_flipButtons[index].IsChecked = val;
if (updateAutomationPropertiesNames
|| hasValueChanged
|| (mustUpdateTextOfMostSignificantDigits && (index == previousMSDPosition || index == newMSDPosition)))
{
m_flipButtons[index].SetValue(AutomationProperties.NameProperty, GenerateAutomationPropertiesName(index, val));
}
++index;
}
}
m_updatingCheckedStates = false;
}
private void UpdateAutomationPropertiesNames()
{
foreach (FlipButtons flipButton in m_flipButtons)
{
int index = (int)flipButton.Tag;
flipButton.SetValue(AutomationProperties.NameProperty, GenerateAutomationPropertiesName(index, flipButton.IsChecked.Value));
}
}
private int GetIndexOfLastBit(BitLength length)
{
switch (length)
{
case BitLength.BitLengthQWord:
return 63;
case BitLength.BitLengthDWord:
return 31;
case BitLength.BitLengthWord:
return 15;
case BitLength.BitLengthByte:
return 7;
}
return -1;
}
private static readonly uint s_numBits = 64;
private FlipButtons[] m_flipButtons = new FlipButtons[s_numBits];
private bool m_updatingCheckedStates;
private BitLength m_currentValueBitLength;
}
}

View file

@ -0,0 +1,239 @@
<UserControl x:Class="CalculatorApp.CalculatorProgrammerOperators"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:common="using:CalculatorApp.Common"
xmlns:controls="using:CalculatorApp.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:designdata="using:CalculatorApp.DesignData"
xmlns:local="using:CalculatorApp"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
x:Name="ControlRoot"
d:DesignHeight="400"
d:DesignWidth="315"
mc:Ignorable="d">
<UserControl.Resources>
<!-- Programmer mode display radio button -->
<Style x:Key="ProgModeRadioButtonStyle" TargetType="RadioButton">
<Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseMediumBrush}"/>
<Setter Property="MinHeight" Value="12"/>
<Setter Property="MinWidth" Value="280"/>
<Setter Property="MaxHeight" Value="60"/>
<Setter Property="VerticalAlignment" Value="Stretch"/>
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="Padding" Value="8,0,0,0"/>
<Setter Property="Typography.NumeralAlignment" Value="Tabular"/>
<Setter Property="FontSize" Value="{ThemeResource CaptionFontSize}"/>
<Setter Property="FontWeight" Value="SemiBold"/>
<Setter Property="IsTextScaleFactorEnabled" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="RadioButton">
<Grid x:Name="ControlRoot"
VerticalAlignment="Stretch"
Background="{ThemeResource SystemControlBackgroundTransparentBrush}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="PointerOver">
<VisualState.Setters>
<Setter Target="ControlRoot.(RevealBrush.State)" Value="PointerOver"/>
<Setter Target="ControlRoot.Background" Value="{ThemeResource ListViewItemRevealBackgroundPointerOver}"/>
<Setter Target="ContentPresenter.Foreground" Value="{ThemeResource SystemControlHighlightAltBaseHighBrush}"/>
<Setter Target="LabelPresenter.Foreground" Value="{ThemeResource SystemControlHighlightAltBaseHighBrush}"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Pressed">
<VisualState.Setters>
<Setter Target="ControlRoot.(RevealBrush.State)" Value="Pressed"/>
<Setter Target="ControlRoot.Background" Value="{ThemeResource ListViewItemRevealBackgroundPressed}"/>
<Setter Target="ContentPresenter.Foreground" Value="{ThemeResource SystemControlHighlightAltBaseHighBrush}"/>
<Setter Target="LabelPresenter.Foreground" Value="{ThemeResource SystemControlHighlightAltBaseHighBrush}"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Target="RevealBackplate.Visibility" Value="Collapsed"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="CheckStates">
<VisualState x:Name="Checked">
<VisualState.Setters>
<Setter Target="CheckedStatesGrid.Opacity" Value="1"/>
<Setter Target="NormalStatesGrid.Opacity" Value="0"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Unchecked"/>
<VisualState x:Name="Indeterminate"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="RevealBackplate"
Margin="0,-1,0,0"
Background="{ThemeResource ListViewItemRevealBackground}"
BorderBrush="{ThemeResource ListViewItemRevealBorderBrush}"
BorderThickness="0,1,0,1"/>
<Grid x:Name="NormalStatesGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="4"/>
<ColumnDefinition Width="Auto" MinWidth="48"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="ContentPresenter"
Grid.Column="2"
Margin="4,0,4,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Foreground="{ThemeResource SystemControlForegroundBaseHighBrush}"
FontFamily="{TemplateBinding FontFamily}"
FontSize="{TemplateBinding FontSize}"
FontWeight="{TemplateBinding FontWeight}"
AutomationProperties.AccessibilityView="Raw"
IsTextScaleFactorEnabled="{TemplateBinding IsTextScaleFactorEnabled}"
Text="{TemplateBinding Content}"
TextWrapping="Wrap"/>
<TextBlock x:Name="LabelPresenter"
Grid.Column="1"
Margin="{TemplateBinding Padding}"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Foreground="{ThemeResource SystemControlForegroundBaseHighBrush}"
FontFamily="{TemplateBinding FontFamily}"
FontSize="{TemplateBinding FontSize}"
FontWeight="{TemplateBinding FontWeight}"
AutomationProperties.AccessibilityView="Raw"
IsTextScaleFactorEnabled="{TemplateBinding IsTextScaleFactorEnabled}"
Text="{TemplateBinding Tag}"/>
</Grid>
<Grid x:Name="CheckedStatesGrid"
Background="{ThemeResource SystemControlHighlightTransparentBrush}"
Opacity="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="4"/>
<ColumnDefinition Width="Auto" MinWidth="48"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Rectangle x:Name="CheckedRectangle"
Grid.Column="0"
Margin="0,5,0,5"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Fill="{ThemeResource SystemControlHighlightAccentBrush}"/>
<TextBlock x:Name="CheckedContentPresenter"
Grid.Column="2"
Margin="4,0,4,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Foreground="{ThemeResource SystemControlHighlightAltBaseHighBrush}"
FontFamily="{TemplateBinding FontFamily}"
FontSize="{TemplateBinding FontSize}"
FontWeight="{TemplateBinding FontWeight}"
AutomationProperties.AccessibilityView="Raw"
IsTextScaleFactorEnabled="{TemplateBinding IsTextScaleFactorEnabled}"
Text="{TemplateBinding Content}"
TextWrapping="Wrap"/>
<TextBlock x:Name="CheckedLabelPresenter"
Grid.Column="1"
Margin="{TemplateBinding Padding}"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Foreground="{ThemeResource SystemControlHighlightAltBaseHighBrush}"
FontFamily="{TemplateBinding FontFamily}"
FontSize="{TemplateBinding FontSize}"
FontWeight="{TemplateBinding FontWeight}"
AutomationProperties.AccessibilityView="Raw"
IsTextScaleFactorEnabled="{TemplateBinding IsTextScaleFactorEnabled}"
Text="{TemplateBinding Tag}"/>
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<MenuFlyout x:Key="ProgrammerOperatorsContextMenu" x:Name="ProgrammerOperatorsContextMenu">
<MenuFlyoutItem x:Name="CopyMenuItem"
x:Uid="CopyMenuItem"
Click="OnCopyMenuItemClicked"
Icon="Copy"/>
</MenuFlyout>
</UserControl.Resources>
<Grid x:Name="ProgrammerOperators"
x:Uid="RadixGroup"
MaxHeight="244"
AutomationProperties.HeadingLevel="Level1"
FlowDirection="LeftToRight">
<Grid.RowDefinitions>
<RowDefinition Height="1*" MinHeight="0"/>
<RowDefinition Height="1*" MinHeight="0"/>
<RowDefinition Height="1*" MinHeight="0"/>
<RowDefinition Height="1*" MinHeight="{Binding ActualHeight, ElementName=BinaryButton, FallbackValue=16, Mode=OneWay}"/>
<RowDefinition Height="4"/>
</Grid.RowDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="LargeLayout">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowHeight="768" MinWindowWidth="1024"/>
</VisualState.StateTriggers>
</VisualState>
<VisualState x:Name="MinSizeLayout">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowHeight="{StaticResource AppMinWindowHeight}" MinWindowWidth="{StaticResource AppMinWindowWidth}"/>
</VisualState.StateTriggers>
</VisualState>
<VisualState x:Name="DefaultLayout">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowHeight="0" MinWindowWidth="0"/>
</VisualState.StateTriggers>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<controls:RadixButton x:Name="HexButton"
x:Uid="hexButton"
HorizontalAlignment="Stretch"
Style="{ThemeResource ProgModeRadioButtonStyle}"
AutomationProperties.AutomationId="hexButton"
AutomationProperties.Name="{x:Bind Model.HexDisplayValue_AutomationName, Mode=OneWay}"
Checked="HexButtonChecked"
Content="{x:Bind Model.HexDisplayValue, Mode=OneWay}"
ContextFlyout="{StaticResource ProgrammerOperatorsContextMenu}"
GroupName="BaseConversion"/>
<controls:RadixButton x:Name="DecimalButton"
x:Uid="decimalButton"
Grid.Row="1"
HorizontalAlignment="Stretch"
Style="{ThemeResource ProgModeRadioButtonStyle}"
AutomationProperties.AutomationId="decimalButton"
AutomationProperties.Name="{x:Bind Model.DecDisplayValue_AutomationName, Mode=OneWay}"
Checked="DecButtonChecked"
Content="{x:Bind Model.DecimalDisplayValue, Mode=OneWay}"
ContextFlyout="{StaticResource ProgrammerOperatorsContextMenu}"
GroupName="BaseConversion"
IsChecked="true"/>
<controls:RadixButton x:Name="OctButton"
x:Uid="octButton"
Grid.Row="2"
HorizontalAlignment="Stretch"
Style="{ThemeResource ProgModeRadioButtonStyle}"
AutomationProperties.AutomationId="octolButton"
AutomationProperties.Name="{x:Bind Model.OctDisplayValue_AutomationName, Mode=OneWay}"
Checked="OctButtonChecked"
Content="{x:Bind Model.OctalDisplayValue, Mode=OneWay}"
ContextFlyout="{StaticResource ProgrammerOperatorsContextMenu}"
GroupName="BaseConversion"/>
<controls:RadixButton x:Name="BinaryButton"
x:Uid="binaryButton"
Grid.Row="3"
HorizontalAlignment="Stretch"
Style="{ThemeResource ProgModeRadioButtonStyle}"
AutomationProperties.AutomationId="binaryButton"
AutomationProperties.Name="{x:Bind Model.BinDisplayValue_AutomationName, Mode=OneWay}"
Checked="BinButtonChecked"
Content="{x:Bind Model.BinaryDisplayValue, Mode=OneWay}"
ContextFlyout="{StaticResource ProgrammerOperatorsContextMenu}"
GroupName="BaseConversion"/>
</Grid>
</UserControl>

View file

@ -0,0 +1,120 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Diagnostics;
using CalculatorApp;
using CalculatorApp.Common;
using CalculatorApp.Controls;
using CalculatorApp.ViewModel;
using Windows.Devices.Input;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using Windows.UI.Xaml.Automation;
using Windows.UI.Xaml.Automation.Peers;
using Windows.UI.ViewManagement;
using Windows.UI.Core;
namespace CalculatorApp
{
[Windows.Foundation.Metadata.WebHostHidden]
public sealed partial class CalculatorProgrammerOperators
{
public CalculatorProgrammerOperators()
{
InitializeComponent();
CopyMenuItem.Text = AppResourceProvider.GetInstance().GetResourceString("copyMenuItem");
}
public StandardCalculatorViewModel Model
{
get { return (StandardCalculatorViewModel)this.DataContext; }
}
public Style SymbolButtonStyle
{
get { return (Style)GetValue(SymbolButtonStyleProperty); }
set { SetValue(SymbolButtonStyleProperty, value); }
}
// Using a DependencyProperty as the backing store for SymbolButtonStyle. This enables animation, styling, binding, etc...
public static readonly DependencyProperty SymbolButtonStyleProperty =
DependencyProperty.Register(nameof(SymbolButtonStyle), typeof(Style), typeof(CalculatorProgrammerOperators), new PropertyMetadata(default(Style)));
internal void SetRadixButton(NumberBase numberBase)
{
switch (numberBase)
{
case NumberBase.DecBase:
DecimalButton.IsChecked = true;
break;
case NumberBase.HexBase:
HexButton.IsChecked = true;
break;
case NumberBase.OctBase:
OctButton.IsChecked = true;
break;
case NumberBase.BinBase:
BinaryButton.IsChecked = true;
break;
default:
Debug.Assert(false);
break;
}
}
private void DecButtonChecked(object sender, RoutedEventArgs e)
{
TraceLogger.GetInstance().UpdateButtonUsage(NumbersAndOperatorsEnum.DecButton, ViewMode.Programmer);
if (Model != null)
{
Model.SwitchProgrammerModeBase(NumberBase.DecBase);
}
}
private void HexButtonChecked(object sender, RoutedEventArgs e)
{
TraceLogger.GetInstance().UpdateButtonUsage(NumbersAndOperatorsEnum.HexButton, ViewMode.Programmer);
if (Model != null)
{
Model.SwitchProgrammerModeBase(NumberBase.HexBase);
}
}
private void BinButtonChecked(object sender, RoutedEventArgs e)
{
TraceLogger.GetInstance().UpdateButtonUsage(NumbersAndOperatorsEnum.BinButton, ViewMode.Programmer);
if (Model != null)
{
Model.SwitchProgrammerModeBase(NumberBase.BinBase);
}
}
private void OctButtonChecked(object sender, RoutedEventArgs e)
{
TraceLogger.GetInstance().UpdateButtonUsage(NumbersAndOperatorsEnum.OctButton, ViewMode.Programmer);
if (Model != null)
{
Model.SwitchProgrammerModeBase(NumberBase.OctBase);
}
}
private void OnCopyMenuItemClicked(object sender, RoutedEventArgs e)
{
var source = (RadixButton)ProgrammerOperatorsContextMenu.Target;
CopyPasteManager.CopyToClipboard(source.GetRawDisplayValue());
}
}
}

View file

@ -0,0 +1,693 @@
<UserControl x:Class="CalculatorApp.CalculatorProgrammerRadixOperators"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Windows10version1803="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractNotPresent(Windows.Foundation.UniversalApiContract, 7)"
xmlns:Windows10version1809="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract, 7)"
xmlns:common="using:CalculatorApp.Common"
xmlns:controls="using:CalculatorApp.Controls"
xmlns:converters="using:CalculatorApp.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:CalculatorApp"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:triggers="using:CalculatorApp.Views.StateTriggers"
x:Name="ControlRoot"
d:DesignHeight="395"
d:DesignWidth="315"
XYFocusKeyboardNavigation="Enabled"
mc:Ignorable="d">
<UserControl.Resources>
<converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
<converters:BooleanToVisibilityNegationConverter x:Key="BooleanToVisibilityNegationConverter"/>
</UserControl.Resources>
<Grid x:Name="ProgRadixOps">
<Grid.RowDefinitions>
<RowDefinition x:Name="OperatorPanelRow" Height="Auto"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="GutterLeft" Width="0"/>
<ColumnDefinition x:Name="C0" Width="1*"/>
<ColumnDefinition x:Name="C1" Width="1*"/>
<ColumnDefinition x:Name="C2" Width="1*"/>
<ColumnDefinition x:Name="C3" Width="1*"/>
<ColumnDefinition x:Name="C4" Width="1*"/>
<ColumnDefinition x:Name="GutterRight" Width="0"/>
</Grid.ColumnDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="ErrorVisualStates">
<VisualState x:Name="NoErrorLayout"/>
<VisualState x:Name="ErrorLayout">
<VisualState.Setters>
<Setter Target="RolButton.IsEnabled" Value="False"/>
<Setter Target="RorButton.IsEnabled" Value="False"/>
<Setter Target="LshButton.IsEnabled" Value="False"/>
<Setter Target="RshButton.IsEnabled" Value="False"/>
<Setter Target="OrButton.IsEnabled" Value="False"/>
<Setter Target="XorButton.IsEnabled" Value="False"/>
<Setter Target="NotButton.IsEnabled" Value="False"/>
<Setter Target="AndButton.IsEnabled" Value="False"/>
<Setter Target="ModButton.IsEnabled" Value="False"/>
<Setter Target="DivideButton.IsEnabled" Value="False"/>
<Setter Target="MultiplyButton.IsEnabled" Value="False"/>
<Setter Target="MinusButton.IsEnabled" Value="False"/>
<Setter Target="PlusButton.IsEnabled" Value="False"/>
<Setter Target="OpenParenthesisButton.IsEnabled" Value="False"/>
<Setter Target="CloseParenthesisButton.IsEnabled" Value="False"/>
<Setter Target="NegateButton.IsEnabled" Value="False"/>
<Setter Target="BitShiftButton.IsEnabled" Value="False"/>
<Setter Target="BitwiseButton.IsEnabled" Value="False"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
<VisualStateGroup>
<VisualState x:Name="Large">
<VisualState.StateTriggers>
<triggers:ControlSizeTrigger MinWidth="1053"
MinHeight="729"
Source="{x:Bind ProgRadixOps}"/>
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="NumberPad.ButtonStyle" Value="{StaticResource NumericButtonStyle38}"/>
<Setter Target="AButton.Style" Value="{StaticResource NumericButtonStyle38}"/>
<Setter Target="BButton.Style" Value="{StaticResource NumericButtonStyle38}"/>
<Setter Target="CButton.Style" Value="{StaticResource NumericButtonStyle38}"/>
<Setter Target="DButton.Style" Value="{StaticResource NumericButtonStyle38}"/>
<Setter Target="EButton.Style" Value="{StaticResource NumericButtonStyle38}"/>
<Setter Target="FButton.Style" Value="{StaticResource NumericButtonStyle38}"/>
<Setter Target="ModButton.FontSize" Value="{StaticResource CalcButtonCaptionSize}"/>
<Setter Target="DivideButton.FontSize" Value="{StaticResource CalcButtonCaptionSize}"/>
<Setter Target="MultiplyButton.FontSize" Value="{StaticResource CalcButtonCaptionSize}"/>
<Setter Target="MinusButton.FontSize" Value="{StaticResource CalcButtonCaptionSize}"/>
<Setter Target="PlusButton.FontSize" Value="{StaticResource CalcButtonCaptionSize}"/>
<Setter Target="EqualButton.FontSize" Value="{StaticResource CalcButtonCaptionSize}"/>
<Setter Target="ClearButton.FontSize" Value="{StaticResource CalcButtonCaptionSize}"/>
<Setter Target="ClearEntryButton.FontSize" Value="{StaticResource CalcButtonCaptionSize}"/>
<Setter Target="BackSpaceButton.FontSize" Value="{StaticResource CalcButtonCaptionSize}"/>
<Setter Target="NegateButton.FontSize" Value="{StaticResource CalcButtonCaptionSize}"/>
<Setter Target="OpenParenthesisButton.FontSize" Value="{StaticResource CalcButtonCaptionSize}"/>
<Setter Target="CloseParenthesisButton.FontSize" Value="{StaticResource CalcButtonCaptionSize}"/>
<Setter Target="AndButton.FontSize" Value="{StaticResource CalcButtonCaptionSize}"/>
<Setter Target="OrButton.FontSize" Value="{StaticResource CalcButtonCaptionSize}"/>
<Setter Target="XorButton.FontSize" Value="{StaticResource CalcButtonCaptionSize}"/>
<Setter Target="NandButton.FontSize" Value="{StaticResource CalcButtonCaptionSize}"/>
<Setter Target="NorButton.FontSize" Value="{StaticResource CalcButtonCaptionSize}"/>
<Setter Target="RolButton.FontSize" Value="{StaticResource CalcButtonCaptionSize}"/>
<Setter Target="RorButton.FontSize" Value="{StaticResource CalcButtonCaptionSize}"/>
<Setter Target="RolCarryButton.FontSize" Value="{StaticResource CalcButtonCaptionSize}"/>
<Setter Target="RorCarryButton.FontSize" Value="{StaticResource CalcButtonCaptionSize}"/>
<Setter Target="LshButton.FontSize" Value="{StaticResource CalcButtonCaptionSize}"/>
<Setter Target="RshButton.FontSize" Value="{StaticResource CalcButtonCaptionSize}"/>
<Setter Target="LshLogicalButton.FontSize" Value="{StaticResource CalcButtonCaptionSize}"/>
<Setter Target="RshLogicalButton.FontSize" Value="{StaticResource CalcButtonCaptionSize}"/>
<Setter Target="NotButton.FontSize" Value="{StaticResource CalcButtonCaptionSize}"/>
<Setter Target="OperatorPanelRow.MinHeight" Value="{StaticResource OperatorPanelButtonRowSizeLarge}"/>
<Setter Target="BitwiseButton.Style" Value="{StaticResource OperatorPanelButtonLargeStyle}"/>
<Setter Target="BitShiftButton.Style" Value="{StaticResource OperatorPanelButtonLargeStyle}"/>
<Setter Target="BitwiseGrid.MinWidth" Value="387"/>
<Setter Target="BitwiseGrid.MinHeight" Value="192"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Medium">
<VisualState.StateTriggers>
<triggers:ControlSizeTrigger MinWidth="630"
MinHeight="437"
Source="{x:Bind ProgRadixOps}"/>
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="NumberPad.ButtonStyle" Value="{StaticResource NumericButtonStyle24}"/>
<Setter Target="AButton.Style" Value="{StaticResource NumericButtonStyle24}"/>
<Setter Target="BButton.Style" Value="{StaticResource NumericButtonStyle24}"/>
<Setter Target="CButton.Style" Value="{StaticResource NumericButtonStyle24}"/>
<Setter Target="DButton.Style" Value="{StaticResource NumericButtonStyle24}"/>
<Setter Target="EButton.Style" Value="{StaticResource NumericButtonStyle24}"/>
<Setter Target="FButton.Style" Value="{StaticResource NumericButtonStyle24}"/>
<Setter Target="ModButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSize}"/>
<Setter Target="DivideButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSize}"/>
<Setter Target="MultiplyButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSize}"/>
<Setter Target="MinusButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSize}"/>
<Setter Target="PlusButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSize}"/>
<Setter Target="EqualButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSize}"/>
<Setter Target="ClearButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSize}"/>
<Setter Target="ClearEntryButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSize}"/>
<Setter Target="BackSpaceButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSize}"/>
<Setter Target="NegateButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSizeLarge}"/>
<Setter Target="OpenParenthesisButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSize}"/>
<Setter Target="CloseParenthesisButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSize}"/>
<Setter Target="AndButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSize}"/>
<Setter Target="OrButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSize}"/>
<Setter Target="XorButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSize}"/>
<Setter Target="NandButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSize}"/>
<Setter Target="NorButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSize}"/>
<Setter Target="RolButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSize}"/>
<Setter Target="RorButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSize}"/>
<Setter Target="RolCarryButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSize}"/>
<Setter Target="RorCarryButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSize}"/>
<Setter Target="LshButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSize}"/>
<Setter Target="RshButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSize}"/>
<Setter Target="LshLogicalButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSize}"/>
<Setter Target="RshLogicalButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSize}"/>
<Setter Target="NotButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSize}"/>
<Setter Target="OperatorPanelRow.MinHeight" Value="{StaticResource OperatorPanelButtonRowSizeMedium}"/>
<Setter Target="BitwiseButton.Style" Value="{StaticResource OperatorPanelButtonMediumStyle}"/>
<Setter Target="BitShiftButton.Style" Value="{StaticResource OperatorPanelButtonMediumStyle}"/>
<Setter Target="BitwiseGrid.MinWidth" Value="416"/>
<Setter Target="BitwiseGrid.MinHeight" Value="144"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Small">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowHeight="{StaticResource AppMinWindowHeight}" MinWindowWidth="{StaticResource AppMinWindowWidth}"/>
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="NumberPad.ButtonStyle" Value="{StaticResource NumericButtonStyle18}"/>
<Setter Target="AButton.Style" Value="{StaticResource NumericButtonStyle14}"/>
<Setter Target="BButton.Style" Value="{StaticResource NumericButtonStyle14}"/>
<Setter Target="CButton.Style" Value="{StaticResource NumericButtonStyle14}"/>
<Setter Target="DButton.Style" Value="{StaticResource NumericButtonStyle14}"/>
<Setter Target="EButton.Style" Value="{StaticResource NumericButtonStyle14}"/>
<Setter Target="FButton.Style" Value="{StaticResource NumericButtonStyle14}"/>
<Setter Target="ModButton.FontSize" Value="{StaticResource CalcOperatorCaptionSize}"/>
<Setter Target="DivideButton.FontSize" Value="{StaticResource CalcOperatorCaptionSize}"/>
<Setter Target="MultiplyButton.FontSize" Value="{StaticResource CalcOperatorCaptionSize}"/>
<Setter Target="MinusButton.FontSize" Value="{StaticResource CalcOperatorCaptionSize}"/>
<Setter Target="PlusButton.FontSize" Value="{StaticResource CalcOperatorCaptionSize}"/>
<Setter Target="EqualButton.FontSize" Value="{StaticResource CalcOperatorCaptionSize}"/>
<Setter Target="ClearButton.FontSize" Value="{StaticResource CalcOperatorCaptionSize}"/>
<Setter Target="ClearEntryButton.FontSize" Value="{StaticResource CalcOperatorCaptionSize}"/>
<Setter Target="BackSpaceButton.FontSize" Value="{StaticResource CalcOperatorCaptionSize}"/>
<Setter Target="NegateButton.FontSize" Value="{StaticResource CalcOperatorCaptionSize}"/>
<Setter Target="OpenParenthesisButton.FontSize" Value="{StaticResource CalcOperatorCaptionSize}"/>
<Setter Target="CloseParenthesisButton.FontSize" Value="{StaticResource CalcOperatorCaptionSize}"/>
<Setter Target="AndButton.FontSize" Value="{StaticResource CalcOperatorCaptionSize}"/>
<Setter Target="OrButton.FontSize" Value="{StaticResource CalcOperatorCaptionSize}"/>
<Setter Target="XorButton.FontSize" Value="{StaticResource CalcOperatorCaptionSize}"/>
<Setter Target="NandButton.FontSize" Value="{StaticResource CalcOperatorCaptionSize}"/>
<Setter Target="NorButton.FontSize" Value="{StaticResource CalcOperatorCaptionSize}"/>
<Setter Target="RolButton.FontSize" Value="{StaticResource CalcOperatorCaptionSize}"/>
<Setter Target="RorButton.FontSize" Value="{StaticResource CalcOperatorCaptionSize}"/>
<Setter Target="RolCarryButton.FontSize" Value="{StaticResource CalcOperatorCaptionSize}"/>
<Setter Target="RorCarryButton.FontSize" Value="{StaticResource CalcOperatorCaptionSize}"/>
<Setter Target="LshButton.FontSize" Value="{StaticResource CalcOperatorCaptionSize}"/>
<Setter Target="RshButton.FontSize" Value="{StaticResource CalcOperatorCaptionSize}"/>
<Setter Target="LshLogicalButton.FontSize" Value="{StaticResource CalcOperatorCaptionSize}"/>
<Setter Target="RshLogicalButton.FontSize" Value="{StaticResource CalcOperatorCaptionSize}"/>
<Setter Target="NotButton.FontSize" Value="{StaticResource CalcOperatorCaptionSize}"/>
<Setter Target="OperatorPanelRow.MinHeight" Value="{StaticResource OperatorPanelButtonRowSizeSmall}"/>
<Setter Target="BitwiseButton.Style" Value="{StaticResource OperatorPanelButtonSmallStyle}"/>
<Setter Target="BitShiftButton.Style" Value="{StaticResource OperatorPanelButtonSmallStyle}"/>
<Setter Target="BitwiseGrid.MinWidth" Value="194"/>
<Setter Target="BitwiseGrid.MinHeight" Value="96"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<controls:OperatorPanelListView x:Uid="ProgrammerOperatorPanel"
Grid.ColumnSpan="6"
Background="{ThemeResource AppOperatorPanelBackground}"
AutomationProperties.HeadingLevel="Level1">
<controls:OperatorPanelButton x:Name="BitwiseButton"
x:Uid="bitwiseButton"
Style="{StaticResource OperatorPanelButtonStyle}"
AutomationProperties.AutomationId="bitwiseButton"
Glyph="&#xF895;">
<controls:OperatorPanelButton.FlyoutMenu>
<Flyout x:Name="BitwiseFlyout"
Windows10version1803:Placement="Bottom"
Windows10version1809:AreOpenCloseAnimationsEnabled="False"
Windows10version1809:Placement="BottomEdgeAlignedLeft"
FlyoutPresenterStyle="{ThemeResource OperatorPanelFlyoutStyle}">
<Grid x:Name="BitwiseGrid"
MinWidth="258"
MinHeight="96"
XYFocusKeyboardNavigation="Enabled">
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<!--
Because of the way we handle keyboard shortcuts, the IsEnabled property must be bound to a button outside the flyout.
This is because the content from within the Flyout do not inherit the IsEnabled property of the flyout parent,
causing the shortcut keys to be used when the control would normally be disabled.
-->
<controls:CalculatorButton x:Name="AndButton"
x:Uid="andButton"
Style="{StaticResource OperatorButtonStyle}"
FontSize="12"
AutomationProperties.AutomationId="andButton"
ButtonId="And"
Click="FlyoutButton_Clicked"
Command="{x:Bind Model.ButtonPressed}"
Content="AND"
IsEnabled="{x:Bind BitwiseButton.IsEnabled, Mode=OneWay}"/>
<controls:CalculatorButton x:Name="OrButton"
x:Uid="orButton"
Grid.Column="1"
Style="{StaticResource OperatorButtonStyle}"
FontSize="12"
AutomationProperties.AutomationId="orButton"
ButtonId="Or"
Click="FlyoutButton_Clicked"
Command="{x:Bind Model.ButtonPressed}"
Content="OR"
IsEnabled="{x:Bind BitwiseButton.IsEnabled, Mode=OneWay}"/>
<controls:CalculatorButton x:Name="NotButton"
x:Uid="notButton"
Grid.Column="2"
Style="{StaticResource OperatorButtonStyle}"
FontSize="12"
AutomationProperties.AutomationId="notButton"
ButtonId="Not"
Click="FlyoutButton_Clicked"
Command="{x:Bind Model.ButtonPressed}"
Content="NOT"
IsEnabled="{x:Bind BitwiseButton.IsEnabled, Mode=OneWay}"/>
<controls:CalculatorButton x:Name="NandButton"
x:Uid="nandButton"
Grid.Row="1"
Style="{StaticResource OperatorButtonStyle}"
FontSize="12"
AutomationProperties.AutomationId="nandButton"
ButtonId="Nand"
Click="FlyoutButton_Clicked"
Command="{x:Bind Model.ButtonPressed}"
Content="NAND"
IsEnabled="{x:Bind BitwiseButton.IsEnabled, Mode=OneWay}"/>
<controls:CalculatorButton x:Name="NorButton"
x:Uid="norButton"
Grid.Row="1"
Grid.Column="1"
Style="{StaticResource OperatorButtonStyle}"
FontSize="12"
AutomationProperties.AutomationId="norButton"
ButtonId="Nor"
Click="FlyoutButton_Clicked"
Command="{x:Bind Model.ButtonPressed}"
Content="NOR"
IsEnabled="{x:Bind BitwiseButton.IsEnabled, Mode=OneWay}"/>
<controls:CalculatorButton x:Name="XorButton"
x:Uid="xorButton"
Grid.Row="1"
Grid.Column="2"
Style="{StaticResource OperatorButtonStyle}"
FontSize="12"
AutomationProperties.AutomationId="xorButton"
ButtonId="Xor"
Click="FlyoutButton_Clicked"
Command="{x:Bind Model.ButtonPressed}"
Content="XOR"
IsEnabled="{x:Bind BitwiseButton.IsEnabled, Mode=OneWay}"/>
</Grid>
</Flyout>
</controls:OperatorPanelButton.FlyoutMenu>
</controls:OperatorPanelButton>
<controls:OperatorPanelButton x:Name="BitShiftButton"
x:Uid="bitShiftButton"
Style="{StaticResource OperatorPanelButtonStyle}"
AutomationProperties.AutomationId="bitShiftButton"
Glyph="&#xE301;">
<controls:OperatorPanelButton.FlyoutMenu>
<Flyout x:Name="BitShiftFlyout"
Windows10version1809:AreOpenCloseAnimationsEnabled="False"
FlyoutPresenterStyle="{ThemeResource OperatorPanelFlyoutStyle}"
Opened="BitShiftFlyout_Opened"
Placement="Bottom">
<StackPanel MaxWidth="192" Padding="12">
<RadioButton x:Name="ArithmeticShiftButton"
x:Uid="arithmeticShiftButton"
AutomationProperties.AutomationId="arithmeticShiftButton"
Checked="BitshiftFlyout_Checked"/>
<RadioButton x:Name="LogicalShiftButton"
x:Uid="logicalShiftButton"
AutomationProperties.AutomationId="logicalShiftButton"
Checked="BitshiftFlyout_Checked"/>
<RadioButton x:Name="RotateCircularButton"
x:Uid="rotateCircularButton"
AutomationProperties.AutomationId="rotateCircularButton"
Checked="BitshiftFlyout_Checked"/>
<RadioButton x:Name="RotateCarryShiftButton"
x:Uid="rotateCarryShiftButton"
AutomationProperties.AutomationId="rotateCarryShiftButton"
Checked="BitshiftFlyout_Checked"/>
</StackPanel>
</Flyout>
</controls:OperatorPanelButton.FlyoutMenu>
</controls:OperatorPanelButton>
</controls:OperatorPanelListView>
<Grid x:Uid="ProgrammerOperators"
Grid.Row="1"
Grid.Column="2"
Grid.ColumnSpan="2"
AutomationProperties.HeadingLevel="Level1">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<controls:CalculatorButton x:Name="RolButton"
x:Uid="rolButton"
Grid.Column="0"
Style="{StaticResource SymbolOperatorButtonStyle}"
FontSize="12"
x:DeferLoadStrategy="Lazy"
AutomationProperties.AutomationId="rolButton"
ButtonId="Rol"
Content="&#xF88E;"
Visibility="Collapsed"/>
<controls:CalculatorButton x:Name="RorButton"
x:Uid="rorButton"
Grid.Column="1"
Style="{StaticResource SymbolOperatorButtonStyle}"
FontSize="12"
x:DeferLoadStrategy="Lazy"
AutomationProperties.AutomationId="rorButton"
ButtonId="Ror"
Content="&#xF88F;"
Visibility="Collapsed"/>
<controls:CalculatorButton x:Name="RolCarryButton"
x:Uid="rolCarryButton"
Style="{StaticResource SymbolOperatorButtonStyle}"
FontSize="12"
x:DeferLoadStrategy="Lazy"
AutomationProperties.AutomationId="rolButton"
ButtonId="RolC"
Content="&#xF88E;"
Visibility="Collapsed"/>
<controls:CalculatorButton x:Name="RorCarryButton"
x:Uid="rorCarryButton"
Grid.Column="1"
Style="{StaticResource SymbolOperatorButtonStyle}"
FontSize="12"
x:DeferLoadStrategy="Lazy"
AutomationProperties.AutomationId="rorCarryButton"
ButtonId="RorC"
Content="&#xF88F;"
Visibility="Collapsed"/>
<controls:CalculatorButton x:Name="LshButton"
x:Uid="lshButton"
Style="{StaticResource SymbolOperatorButtonStyle}"
FontSize="12"
AutomationProperties.AutomationId="lshButton"
ButtonId="Lsh"
Content="&#xF88E;"/>
<controls:CalculatorButton x:Name="RshButton"
x:Uid="rshButton"
Grid.Column="1"
Style="{StaticResource SymbolOperatorButtonStyle}"
FontSize="12"
AutomationProperties.AutomationId="rshButton"
ButtonId="Rsh"
Content="&#xF88F;"/>
<controls:CalculatorButton x:Name="LshLogicalButton"
x:Uid="LshLogicalButton"
Style="{StaticResource SymbolOperatorButtonStyle}"
FontSize="12"
x:DeferLoadStrategy="Lazy"
AutomationProperties.AutomationId="lshLogicalButton"
ButtonId="Lsh"
Content="&#xF88E;"
Visibility="Collapsed"/>
<controls:CalculatorButton x:Name="RshLogicalButton"
x:Uid="rshLogicalButton"
Grid.Column="1"
Style="{StaticResource SymbolOperatorButtonStyle}"
FontSize="12"
x:DeferLoadStrategy="Lazy"
AutomationProperties.AutomationId="rshLogicalButton"
ButtonId="RshL"
Content="&#xF88F;"
Visibility="Collapsed"/>
</Grid>
<Grid x:Uid="DisplayControls"
Grid.Row="1"
Grid.Column="4"
Grid.ColumnSpan="2"
AutomationProperties.HeadingLevel="Level1">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<controls:CalculatorButton x:Name="ClearButton"
x:Uid="clearButton"
Style="{StaticResource OperatorButtonStyle}"
FontSize="12"
AutomationProperties.AutomationId="clearButton"
ButtonId="Clear"
Content="C"
LostFocus="ClearButton_LostFocus"
Visibility="{x:Bind Model.IsInputEmpty, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}"/>
<controls:CalculatorButton x:Name="ClearEntryButton"
x:Uid="clearEntryButton"
Style="{StaticResource OperatorButtonStyle}"
FontSize="12"
AutomationProperties.AutomationId="clearEntryButton"
ButtonId="ClearEntry"
Content="CE"
LostFocus="ClearEntryButton_LostFocus"
Visibility="{x:Bind Model.IsInputEmpty, Mode=OneWay, Converter={StaticResource BooleanToVisibilityNegationConverter}}"/>
<controls:CalculatorButton x:Name="BackSpaceButton"
x:Uid="backSpaceButton"
Grid.Column="1"
Style="{StaticResource SymbolOperatorButtonStyle}"
FontSize="12"
AutomationProperties.AutomationId="backSpaceButton"
ButtonId="Backspace"
Content="&#xE94F;"/>
</Grid>
<controls:CalculatorButton x:Name="OpenParenthesisButton"
x:Uid="openParenthesisButton"
Grid.Row="2"
Grid.Column="2"
Style="{StaticResource ParenthesisCalcButtonStyle}"
FontSize="18"
AutomationProperties.AutomationId="openParenthesisButton"
ButtonId="OpenParenthesis"
Content="("
GotFocus="OpenParenthesisButton_GotFocus"
Tag="{x:Bind ParenthesisCountToString(Model.OpenParenthesisCount), Mode=OneWay}"/>
<controls:CalculatorButton x:Name="CloseParenthesisButton"
x:Uid="closeParenthesisButton"
Grid.Row="2"
Grid.Column="3"
Style="{StaticResource OperatorButtonStyle}"
FontSize="18"
AutomationProperties.AutomationId="closeParenthesisButton"
ButtonId="CloseParenthesis"
Content=")"/>
<controls:CalculatorButton x:Name="ModButton"
x:Uid="modButton"
Grid.Row="2"
Grid.Column="4"
Style="{StaticResource OperatorButtonStyle}"
FontSize="12"
AutomationProperties.AutomationId="modButton"
ButtonId="Mod"
Content="%"/>
<Grid x:Uid="StandardOperators"
Grid.Row="2"
Grid.RowSpan="5"
Grid.Column="5"
AutomationProperties.HeadingLevel="Level1">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<controls:CalculatorButton x:Name="DivideButton"
x:Uid="divideButton"
Grid.Row="0"
Style="{StaticResource SymbolOperatorButtonStyle}"
FontSize="12"
AutomationProperties.AutomationId="divideButton"
ButtonId="Divide"
Content="&#xE94A;"/>
<controls:CalculatorButton x:Name="MultiplyButton"
x:Uid="multiplyButton"
Grid.Row="1"
Style="{StaticResource SymbolOperatorButtonStyle}"
FontSize="12"
AutomationProperties.AutomationId="multiplyButton"
ButtonId="Multiply"
Content="&#xE947;"/>
<controls:CalculatorButton x:Name="MinusButton"
x:Uid="minusButton"
Grid.Row="2"
Style="{StaticResource SymbolOperatorButtonStyle}"
FontSize="12"
AutomationProperties.AutomationId="minusButton"
ButtonId="Subtract"
Content="&#xE949;"/>
<controls:CalculatorButton x:Name="PlusButton"
x:Uid="plusButton"
Grid.Row="3"
Style="{StaticResource SymbolOperatorButtonStyle}"
FontSize="12"
AutomationProperties.AutomationId="plusButton"
ButtonId="Add"
Content="&#xE948;"/>
<controls:CalculatorButton x:Name="EqualButton"
x:Uid="equalButton"
Grid.Row="4"
Style="{StaticResource AccentEmphasizedCalcButtonStyle}"
FontSize="12"
AutomationProperties.AutomationId="equalButton"
ButtonId="Equals"
Content="&#xE94E;"/>
</Grid>
<Grid x:Uid="NumberPad"
Grid.Row="1"
Grid.RowSpan="6"
Grid.Column="1"
Grid.ColumnSpan="5"
AutomationProperties.AutomationId="NumberPad"
AutomationProperties.HeadingLevel="Level1">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<controls:CalculatorButton x:Name="AButton"
x:Uid="aButton"
Grid.Row="0"
Grid.Column="0"
Style="{StaticResource NumericButtonStyle12}"
AutomationProperties.AutomationId="aButton"
ButtonId="A"
Content="A"
IsEnabled="{x:Bind Model.AreHEXButtonsEnabled, Mode=OneWay}"/>
<controls:CalculatorButton x:Name="BButton"
x:Uid="bButton"
Grid.Row="1"
Grid.Column="0"
Style="{StaticResource NumericButtonStyle12}"
AutomationProperties.AutomationId="bButton"
ButtonId="B"
Content="B"
IsEnabled="{x:Bind Model.AreHEXButtonsEnabled, Mode=OneWay}"/>
<controls:CalculatorButton x:Name="CButton"
x:Uid="cButton"
Grid.Row="2"
Grid.Column="0"
Style="{StaticResource NumericButtonStyle12}"
AutomationProperties.AutomationId="cButton"
ButtonId="C"
Content="C"
IsEnabled="{x:Bind Model.AreHEXButtonsEnabled, Mode=OneWay}"/>
<controls:CalculatorButton x:Name="DButton"
x:Uid="dButton"
Grid.Row="3"
Grid.Column="0"
Style="{StaticResource NumericButtonStyle12}"
AutomationProperties.AutomationId="dButton"
ButtonId="D"
Content="D"
IsEnabled="{x:Bind Model.AreHEXButtonsEnabled, Mode=OneWay}"/>
<controls:CalculatorButton x:Name="EButton"
x:Uid="eButton"
Grid.Row="4"
Grid.Column="0"
Style="{StaticResource NumericButtonStyle12}"
AutomationProperties.AutomationId="eButton"
ButtonId="E"
Content="E"
IsEnabled="{x:Bind Model.AreHEXButtonsEnabled, Mode=OneWay}"/>
<controls:CalculatorButton x:Name="FButton"
x:Uid="fButton"
Grid.Row="5"
Grid.Column="0"
Style="{StaticResource NumericButtonStyle12}"
AutomationProperties.AutomationId="fButton"
ButtonId="F"
Content="F"
IsEnabled="{x:Bind Model.AreHEXButtonsEnabled, Mode=OneWay}"/>
<local:NumberPad x:Name="NumberPad"
Grid.Row="2"
Grid.RowSpan="4"
Grid.Column="1"
Grid.ColumnSpan="3"
ButtonStyle="{StaticResource NumericButtonStyle18}"
CurrentRadixType="{x:Bind Model.CurrentRadixType, Mode=OneWay}"/>
</Grid>
<controls:CalculatorButton x:Name="NegateButton"
x:Uid="negateButton"
Grid.Row="6"
Grid.Column="2"
Style="{StaticResource SymbolOperatorKeypadButtonStyle}"
FontSize="12"
FontWeight="Normal"
AutomationProperties.AutomationId="negateButton"
ButtonId="Negate"
Content="&#xF898;"/>
</Grid>
</UserControl>

View file

@ -0,0 +1,238 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Diagnostics;
using CalculatorApp;
using CalculatorApp.ViewModel;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using CalculatorApp.Common;
using Windows.UI.Xaml.Media;
namespace CalculatorApp
{
[Windows.Foundation.Metadata.WebHostHidden]
public sealed partial class CalculatorProgrammerRadixOperators
{
public CalculatorProgrammerRadixOperators()
{
m_isErrorVisualState = false;
InitializeComponent();
LoadResourceStrings();
}
public StandardCalculatorViewModel Model
{
get { return (StandardCalculatorViewModel)this.DataContext; }
}
public bool IsErrorVisualState { get; set; }
public string ParenthesisCountToString(uint count)
{
return (count == 0) ? "" : count.ToString();
}
public void checkDefaultBitShift()
{
LoadDeferredLoadButtons();
if (IsButtonLoaded())
{
return;
}
CollapseBitshiftButtons();
m_selectedShiftButtonMode = BitShiftMode.Arithmetic;
LshButton.Visibility = Visibility.Visible;
RshButton.Visibility = Visibility.Visible;
LshButton.IsEnabled = true;
RshButton.IsEnabled = true;
}
private enum BitShiftMode
{
Arithmetic,
LogicalShift,
RotateCircular,
RotateCarry
};
private void BitshiftFlyout_Checked(object sender, RoutedEventArgs e)
{
// Load deferred load buttons
LoadDeferredLoadButtons();
if (IsButtonLoaded())
{
return;
}
CollapseBitshiftButtons();
var radioButton = (RadioButton)sender;
string announcementString = "";
BitShiftMode selectedButtonMode = m_selectedShiftButtonMode;
if (radioButton == ArithmeticShiftButton)
{
LshButton.Visibility = Visibility.Visible;
RshButton.Visibility = Visibility.Visible;
LshButton.IsEnabled = true;
RshButton.IsEnabled = true;
announcementString = m_arithmeticShiftButtonContent;
selectedButtonMode = BitShiftMode.Arithmetic;
}
else if (radioButton == LogicalShiftButton)
{
LshLogicalButton.Visibility = Visibility.Visible;
RshLogicalButton.Visibility = Visibility.Visible;
LshLogicalButton.IsEnabled = true;
RshLogicalButton.IsEnabled = true;
announcementString = m_logicalShiftButtonContent;
selectedButtonMode = BitShiftMode.LogicalShift;
}
else if (radioButton == RotateCircularButton)
{
RolButton.Visibility = Visibility.Visible;
RorButton.Visibility = Visibility.Visible;
RolButton.IsEnabled = true;
RorButton.IsEnabled = true;
announcementString = m_rotateCircularButtonContent;
selectedButtonMode = BitShiftMode.RotateCircular;
}
else if (radioButton == RotateCarryShiftButton)
{
RolCarryButton.Visibility = Visibility.Visible;
RorCarryButton.Visibility = Visibility.Visible;
RolCarryButton.IsEnabled = true;
RorCarryButton.IsEnabled = true;
announcementString = m_rotateCarryShiftButtonContent;
selectedButtonMode = BitShiftMode.RotateCarry;
}
if (selectedButtonMode != m_selectedShiftButtonMode)
{
this.BitShiftFlyout.Hide();
m_selectedShiftButtonMode = selectedButtonMode;
}
Model.SetBitshiftRadioButtonCheckedAnnouncement(announcementString);
}
private void FlyoutButton_Clicked(object sender, RoutedEventArgs e)
{
this.BitwiseFlyout.Hide();
}
private void CollapseBitshiftButtons()
{
RolButton.Visibility = Visibility.Collapsed;
RorButton.Visibility = Visibility.Collapsed;
RolCarryButton.Visibility = Visibility.Collapsed;
RorCarryButton.Visibility = Visibility.Collapsed;
LshButton.Visibility = Visibility.Collapsed;
RshButton.Visibility = Visibility.Collapsed;
LshLogicalButton.Visibility = Visibility.Collapsed;
RshLogicalButton.Visibility = Visibility.Collapsed;
// We need to set the collapsed buttons to disabled so that the KeyboardShortcutManager can skip the keybinds for the disabled buttons
RolButton.IsEnabled = false;
RorButton.IsEnabled = false;
RolCarryButton.IsEnabled = false;
RorCarryButton.IsEnabled = false;
LshButton.IsEnabled = false;
RshButton.IsEnabled = false;
LshLogicalButton.IsEnabled = false;
RshLogicalButton.IsEnabled = false;
}
private void LoadResourceStrings()
{
var resProvider = AppResourceProvider.GetInstance();
m_arithmeticShiftButtonContent = resProvider.GetResourceString("arithmeticShiftButtonSelected");
m_logicalShiftButtonContent = resProvider.GetResourceString("logicalShiftButtonSelected");
m_rotateCircularButtonContent = resProvider.GetResourceString("rotateCircularButtonSelected");
m_rotateCarryShiftButtonContent = resProvider.GetResourceString("rotateCarryShiftButtonSelected");
}
private void LoadDeferredLoadButtons()
{
// Load deferred load buttons
if (RolButton == null)
{
FindName("RolButton");
FindName("RorButton");
FindName("RolCarryButton");
FindName("RorCarryButton");
FindName("LshLogicalButton");
FindName("RshLogicalButton");
}
}
private bool IsButtonLoaded()
{
// Since arithmeticShiftButton defaults to IsChecked = true, this event an fire before we can load the deferred loaded controls. If that is the case, just
// return and do nothing.
return RolButton == null || RorButton == null || RolCarryButton == null || RorCarryButton == null || LshLogicalButton == null
|| RshLogicalButton == null;
}
private bool m_isErrorVisualState;
private void OpenParenthesisButton_GotFocus(object sender, RoutedEventArgs e)
{
Model.SetOpenParenthesisCountNarratorAnnouncement();
}
private void ClearEntryButton_LostFocus(object sender, RoutedEventArgs e)
{
if (ClearEntryButton.Visibility == Visibility.Collapsed && ClearButton.Visibility == Visibility.Visible)
{
ClearButton.Focus(FocusState.Programmatic);
}
}
private void ClearButton_LostFocus(object sender, RoutedEventArgs e)
{
if (ClearEntryButton.Visibility == Visibility.Visible && ClearButton.Visibility == Visibility.Collapsed)
{
ClearEntryButton.Focus(FocusState.Programmatic);
}
}
private void BitShiftFlyout_Opened(object sender, object e)
{
if (m_selectedShiftButtonMode == BitShiftMode.Arithmetic)
{
ArithmeticShiftButton.IsChecked = true;
}
else if (m_selectedShiftButtonMode == BitShiftMode.LogicalShift)
{
LogicalShiftButton.IsChecked = true;
}
else if (m_selectedShiftButtonMode == BitShiftMode.RotateCircular)
{
RotateCircularButton.IsChecked = true;
}
else if (m_selectedShiftButtonMode == BitShiftMode.RotateCarry)
{
RotateCarryShiftButton.IsChecked = true;
}
}
private BitShiftMode m_selectedShiftButtonMode;
private string m_arithmeticShiftButtonContent;
private string m_logicalShiftButtonContent;
private string m_rotateCircularButtonContent;
private string m_rotateCarryShiftButtonContent;
}
}

View file

@ -0,0 +1,106 @@
<UserControl x:Class="CalculatorApp.CalculatorScientificAngleButtons"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Controls="using:CalculatorApp.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:CalculatorApp"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
x:Name="ControlRoot"
d:DesignHeight="315"
d:DesignWidth="400"
mc:Ignorable="d">
<UserControl.Resources>
<Style x:Key="CaptionButtonSmallStyle"
BasedOn="{StaticResource CaptionButtonStyle}"
TargetType="Button">
<Setter Property="MinHeight" Value="0"/>
</Style>
</UserControl.Resources>
<Grid x:Name="ScientificAngleOperators"
x:Uid="ScientificAngleOperators"
Margin="3,0,3,0"
AutomationProperties.HeadingLevel="Level1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" MaxWidth="80"/>
<ColumnDefinition Width="1*" MaxWidth="80"/>
<ColumnDefinition Width="1*" MaxWidth="80"/>
<ColumnDefinition Width="1*" MaxWidth="80"/>
<ColumnDefinition Width="1*" MaxWidth="80"/>
<ColumnDefinition Width="0.01*"/>
<ColumnDefinition Width="1*" MaxWidth="80"/>
</Grid.ColumnDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="Sizing">
<VisualState x:Name="MinSizeLayout">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowHeight="{StaticResource AppMinWindowHeight}" MinWindowWidth="{StaticResource AppMinWindowWidth}"/>
</VisualState.StateTriggers>
</VisualState>
<VisualState x:Name="DefaultLayout">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowHeight="0" MinWindowWidth="0"/>
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="DegreeButton.Style" Value="{StaticResource CaptionButtonSmallStyle}"/>
<Setter Target="RadianButton.Style" Value="{StaticResource CaptionButtonSmallStyle}"/>
<Setter Target="GradsButton.Style" Value="{StaticResource CaptionButtonSmallStyle}"/>
<Setter Target="FtoeButton.Style" Value="{StaticResource CaptionToggleButtonSmallStyle}"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="ErrorVisualStates">
<VisualState x:Name="NoErrorLayout"/>
<VisualState x:Name="ErrorLayout">
<VisualState.Setters>
<Setter Target="DegreeButton.IsEnabled" Value="False"/>
<Setter Target="RadianButton.IsEnabled" Value="False"/>
<Setter Target="GradsButton.IsEnabled" Value="False"/>
<Setter Target="FtoeButton.IsEnabled" Value="False"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Button x:Name="DegreeButton"
x:Uid="degButton"
Style="{StaticResource CaptionButtonStyle}"
AutomationProperties.AutomationId="degButton"
Command="{x:Bind ButtonPressed}"
CommandParameter="0"
Content="DEG"/>
<Button x:Name="RadianButton"
x:Uid="radButton"
Style="{StaticResource CaptionButtonStyle}"
AutomationProperties.AutomationId="radButton"
Command="{x:Bind ButtonPressed}"
CommandParameter="1"
Content="RAD"
Visibility="Collapsed"/>
<Button x:Name="GradsButton"
x:Uid="gradButton"
Style="{StaticResource CaptionButtonStyle}"
AutomationProperties.AutomationId="gradButton"
Command="{x:Bind ButtonPressed}"
CommandParameter="2"
Content="GRAD"
Visibility="Collapsed"/>
<ToggleButton x:Name="FtoeButton"
x:Uid="ftoeButton"
Grid.Column="1"
Style="{StaticResource CaptionToggleButtonStyle}"
Background="{ThemeResource SystemControlBackgroundTransparentBrush}"
FontWeight="SemiBold"
AutomationProperties.AutomationId="ftoeButton"
Checked="FToEButton_Toggled"
Content="F-E"
IsChecked="{x:Bind Model.IsFToEChecked, Mode=OneWay}"
Unchecked="FToEButton_Toggled"
IsEnabled="{x:Bind Model.IsFToEEnabled, Mode=OneWay}">
<ToggleButton.CommandParameter>
<local:NumbersAndOperatorsEnum>FToE</local:NumbersAndOperatorsEnum>
</ToggleButton.CommandParameter>
</ToggleButton>
</Grid>
</UserControl>

View file

@ -0,0 +1,95 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
//
// CalculatorScientificAngleButtons.xaml.h
// Declaration of the CalculatorScientificAngleButtons class
//
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Diagnostics;
using CalculatorApp;
using CalculatorApp.ViewModel;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using Windows.UI.ViewManagement;
using Windows.UI.Core;
namespace CalculatorApp
{
[Windows.Foundation.Metadata.WebHostHidden]
public sealed partial class CalculatorScientificAngleButtons
{
public CalculatorScientificAngleButtons()
{
m_isErrorVisualState = false;
InitializeComponent();
}
public StandardCalculatorViewModel Model
{
get { return (StandardCalculatorViewModel)this.DataContext; }
}
public System.Windows.Input.ICommand ButtonPressed
{
get
{
if (donotuse_ButtonPressed == null)
{
donotuse_ButtonPressed = new CalculatorApp.Common.DelegateCommand<CalculatorScientificAngleButtons>(this, OnAngleButtonPressed);
}
return donotuse_ButtonPressed;
}
}
private System.Windows.Input.ICommand donotuse_ButtonPressed;
public bool IsErrorVisualState { get; set; }
private void OnAngleButtonPressed(object commandParameter)
{
string buttonId = (string)commandParameter;
DegreeButton.Visibility = Visibility.Collapsed;
RadianButton.Visibility = Visibility.Collapsed;
GradsButton.Visibility = Visibility.Collapsed;
if (buttonId == "0")
{
Model.SwitchAngleType(NumbersAndOperatorsEnum.Radians);
RadianButton.Visibility = Visibility.Visible;
RadianButton.Focus(FocusState.Programmatic);
}
else if (buttonId == "1")
{
Model.SwitchAngleType(NumbersAndOperatorsEnum.Grads);
GradsButton.Visibility = Visibility.Visible;
GradsButton.Focus(FocusState.Programmatic);
}
else if (buttonId == "2")
{
Model.SwitchAngleType(NumbersAndOperatorsEnum.Degree);
DegreeButton.Visibility = Visibility.Visible;
DegreeButton.Focus(FocusState.Programmatic);
}
}
private void FToEButton_Toggled(object sender, RoutedEventArgs e)
{
var viewModel = (StandardCalculatorViewModel)this.DataContext;
viewModel.FtoEButtonToggled();
}
private bool m_isErrorVisualState;
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,175 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
//
// CalculatorScientificOperators.xaml.h
// Declaration of the CalculatorScientificOperators class
//
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Diagnostics;
using CalculatorApp;
using CalculatorApp.Common;
using CalculatorApp.ViewModel;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Core;
using Windows.UI.ViewManagement;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using Windows.UI.Core;
namespace CalculatorApp
{
[Windows.Foundation.Metadata.WebHostHidden]
public sealed partial class CalculatorScientificOperators
{
public CalculatorScientificOperators()
{
InitializeComponent();
ExpButton.SetValue(Common.KeyboardShortcutManager.VirtualKeyProperty, Common.MyVirtualKey.E);
}
public StandardCalculatorViewModel Model
{
get { return (StandardCalculatorViewModel)this.DataContext; }
}
public bool IsErrorVisualState
{
get { return (bool)GetValue(IsErrorVisualStateProperty); }
set { SetValue(IsErrorVisualStateProperty, value); }
}
// Using a DependencyProperty as the backing store for IsErrorVisualState. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsErrorVisualStateProperty =
DependencyProperty.Register(nameof(IsErrorVisualState), typeof(bool), typeof(CalculatorScientificOperators), new PropertyMetadata(false, (sender, args) =>
{
var self = (CalculatorScientificOperators)sender;
self.OnIsErrorVisualStatePropertyChanged((bool)args.OldValue, (bool)args.NewValue);
}));
public void OpenParenthesisButton_GotFocus(object sender, RoutedEventArgs e)
{
Model.SetOpenParenthesisCountNarratorAnnouncement();
}
public string ParenthesisCountToString(uint count)
{
return (count == 0) ? "" : count.ToString();
}
private void OnIsErrorVisualStatePropertyChanged(bool oldValue, bool newValue)
{
string newState = newValue ? "ErrorLayout" : "NoErrorLayout";
VisualStateManager.GoToState(this, newState, false);
NumberPad.IsErrorVisualState = newValue;
}
private void ShiftButton_Check(object sender, RoutedEventArgs e)
{
SetOperatorRowVisibility();
}
private void ShiftButton_Uncheck(object sender, RoutedEventArgs e)
{
ShiftButton.IsChecked = false;
SetOperatorRowVisibility();
ShiftButton.Focus(FocusState.Programmatic);
}
private void TrigFlyoutShift_Toggle(object sender, RoutedEventArgs e)
{
SetTrigRowVisibility();
}
private void TrigFlyoutHyp_Toggle(object sender, RoutedEventArgs e)
{
SetTrigRowVisibility();
}
private void FlyoutButton_Clicked(object sender, RoutedEventArgs e)
{
HypButton.IsChecked = false;
TrigShiftButton.IsChecked = false;
Trigflyout.Hide();
FuncFlyout.Hide();
}
private void ShiftButton_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
{
SetOperatorRowVisibility();
}
private void SetOperatorRowVisibility()
{
Visibility rowVis, invRowVis;
if (ShiftButton.IsChecked.Value)
{
rowVis = Visibility.Collapsed;
invRowVis = Visibility.Visible;
}
else
{
rowVis = Visibility.Visible;
invRowVis = Visibility.Collapsed;
}
Row1.Visibility = rowVis;
InvRow1.Visibility = invRowVis;
}
private void SetTrigRowVisibility()
{
bool isShiftChecked = TrigShiftButton.IsChecked.Value;
bool isHypeChecked = HypButton.IsChecked.Value;
InverseHyperbolicTrigFunctions.Visibility = Visibility.Collapsed;
InverseTrigFunctions.Visibility = Visibility.Collapsed;
HyperbolicTrigFunctions.Visibility = Visibility.Collapsed;
TrigFunctions.Visibility = Visibility.Collapsed;
if (isShiftChecked && isHypeChecked)
{
InverseHyperbolicTrigFunctions.Visibility = Visibility.Visible;
}
else if (isShiftChecked && !isHypeChecked)
{
InverseTrigFunctions.Visibility = Visibility.Visible;
}
else if (!isShiftChecked && isHypeChecked)
{
HyperbolicTrigFunctions.Visibility = Visibility.Visible;
}
else
{
TrigFunctions.Visibility = Visibility.Visible;
}
}
private void ClearEntryButton_LostFocus(object sender, RoutedEventArgs e)
{
if (ClearEntryButton.Visibility == Visibility.Collapsed && ClearButton.Visibility == Visibility.Visible)
{
ClearButton.Focus(FocusState.Programmatic);
}
}
private void ClearButton_LostFocus(object sender, RoutedEventArgs e)
{
if (ClearEntryButton.Visibility == Visibility.Visible && ClearButton.Visibility == Visibility.Collapsed)
{
ClearEntryButton.Focus(FocusState.Programmatic);
}
}
}
}

View file

@ -0,0 +1,329 @@
<UserControl x:Class="CalculatorApp.CalculatorStandardOperators"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:common="using:CalculatorApp.Common"
xmlns:controls="using:CalculatorApp.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:CalculatorApp"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:triggers="using:CalculatorApp.Views.StateTriggers"
x:Name="ControlRoot"
XYFocusKeyboardNavigation="Enabled"
mc:Ignorable="d">
<Grid x:Name="Root">
<Grid.RowDefinitions>
<RowDefinition x:Name="R0" Height="1*"/>
<RowDefinition x:Name="R1" Height="1*"/>
<RowDefinition x:Name="R2" Height="1*"/>
<RowDefinition x:Name="R3" Height="1*"/>
<RowDefinition x:Name="R4" Height="1*"/>
<RowDefinition x:Name="R5" Height="1*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="GutterLeft" Width="0"/>
<ColumnDefinition x:Name="C0" Width="0"/>
<ColumnDefinition x:Name="C1" Width="1*"/>
<ColumnDefinition x:Name="C2" Width="1*"/>
<ColumnDefinition x:Name="C3" Width="1*"/>
<ColumnDefinition x:Name="C4" Width="1*"/>
<ColumnDefinition x:Name="GutterRight" Width="0"/>
</Grid.ColumnDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="ErrorVisualStates">
<VisualState x:Name="NoErrorLayout"/>
<VisualState x:Name="ErrorLayout">
<VisualState.Setters>
<Setter Target="PercentButton.IsEnabled" Value="False"/>
<Setter Target="SquareRootButton.IsEnabled" Value="False"/>
<Setter Target="XPower2Button.IsEnabled" Value="False"/>
<Setter Target="InvertButton.IsEnabled" Value="False"/>
<Setter Target="DivideButton.IsEnabled" Value="False"/>
<Setter Target="MultiplyButton.IsEnabled" Value="False"/>
<Setter Target="MinusButton.IsEnabled" Value="False"/>
<Setter Target="PlusButton.IsEnabled" Value="False"/>
<Setter Target="NegateButton.IsEnabled" Value="False"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
<VisualStateGroup>
<VisualState x:Name="Large">
<VisualState.StateTriggers>
<triggers:ControlSizeTrigger MinWidth="780"
MinHeight="814"
Source="{x:Bind Root}"/>
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="PercentButton.FontSize" Value="{StaticResource CalcButtonCaptionSize}"/>
<Setter Target="SquareRootButton.FontSize" Value="{StaticResource CalcButtonCaptionSize}"/>
<Setter Target="XPower2Button.FontSize" Value="{StaticResource CalcButtonCaptionSize}"/>
<Setter Target="InvertButton.FontSize" Value="{StaticResource CalcButtonCaptionSize}"/>
<Setter Target="NegateButton.FontSize" Value="{StaticResource CalcButtonCaptionSize}"/>
<Setter Target="ClearEntryButton.FontSize" Value="{StaticResource CalcButtonCaptionSize}"/>
<Setter Target="ClearButton.FontSize" Value="{StaticResource CalcButtonCaptionSize}"/>
<Setter Target="BackSpaceButton.FontSize" Value="{StaticResource CalcButtonCaptionSize}"/>
<Setter Target="DivideButton.FontSize" Value="{StaticResource CalcButtonCaptionSize}"/>
<Setter Target="MultiplyButton.FontSize" Value="{StaticResource CalcButtonCaptionSize}"/>
<Setter Target="MinusButton.FontSize" Value="{StaticResource CalcButtonCaptionSize}"/>
<Setter Target="PlusButton.FontSize" Value="{StaticResource CalcButtonCaptionSize}"/>
<Setter Target="EqualButton.FontSize" Value="{StaticResource CalcButtonCaptionSize}"/>
<Setter Target="NumberPad.ButtonStyle" Value="{StaticResource NumericButtonStyle38}"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Medium">
<VisualState.StateTriggers>
<triggers:ControlSizeTrigger MinWidth="468"
MinHeight="500"
Source="{x:Bind Root}"/>
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="PercentButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSize}"/>
<Setter Target="SquareRootButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSize}"/>
<Setter Target="XPower2Button.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSize}"/>
<Setter Target="InvertButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSize}"/>
<Setter Target="NegateButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSizeLarge}"/>
<Setter Target="ClearEntryButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSize}"/>
<Setter Target="ClearButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSize}"/>
<Setter Target="BackSpaceButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSize}"/>
<Setter Target="DivideButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSize}"/>
<Setter Target="MultiplyButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSize}"/>
<Setter Target="MinusButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSize}"/>
<Setter Target="PlusButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSize}"/>
<Setter Target="EqualButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSize}"/>
<Setter Target="NumberPad.ButtonStyle" Value="{StaticResource NumericButtonStyle24}"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Small">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowHeight="260" MinWindowWidth="0"/>
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="PercentButton.FontSize" Value="{StaticResource CalcOperatorCaptionSize}"/>
<Setter Target="SquareRootButton.FontSize" Value="{StaticResource CalcOperatorCaptionSize}"/>
<Setter Target="XPower2Button.FontSize" Value="{StaticResource CalcOperatorCaptionSize}"/>
<Setter Target="InvertButton.FontSize" Value="{StaticResource CalcOperatorCaptionSize}"/>
<Setter Target="NegateButton.FontSize" Value="{StaticResource CalcOperatorCaptionSize}"/>
<Setter Target="ClearEntryButton.FontSize" Value="{StaticResource CalcOperatorCaptionSize}"/>
<Setter Target="ClearButton.FontSize" Value="{StaticResource CalcOperatorCaptionSize}"/>
<Setter Target="BackSpaceButton.FontSize" Value="{StaticResource CalcOperatorCaptionSize}"/>
<Setter Target="DivideButton.FontSize" Value="{StaticResource CalcOperatorCaptionSize}"/>
<Setter Target="MultiplyButton.FontSize" Value="{StaticResource CalcOperatorCaptionSize}"/>
<Setter Target="MinusButton.FontSize" Value="{StaticResource CalcOperatorCaptionSize}"/>
<Setter Target="PlusButton.FontSize" Value="{StaticResource CalcOperatorCaptionSize}"/>
<Setter Target="EqualButton.FontSize" Value="{StaticResource CalcOperatorCaptionSize}"/>
<Setter Target="NumberPad.ButtonStyle" Value="{StaticResource NumericButtonStyle18}"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Tiny">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowHeight="0" MinWindowWidth="0"/>
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="PercentButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSizeTiny}"/>
<Setter Target="SquareRootButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSizeTiny}"/>
<Setter Target="XPower2Button.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSizeTiny}"/>
<Setter Target="InvertButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSizeTiny}"/>
<Setter Target="NegateButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSizeTiny}"/>
<Setter Target="ClearEntryButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSizeTiny}"/>
<Setter Target="ClearButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSizeTiny}"/>
<Setter Target="BackSpaceButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSizeTiny}"/>
<Setter Target="DivideButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSizeTiny}"/>
<Setter Target="MultiplyButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSizeTiny}"/>
<Setter Target="MinusButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSizeTiny}"/>
<Setter Target="PlusButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSizeTiny}"/>
<Setter Target="EqualButton.FontSize" Value="{StaticResource CalcStandardOperatorCaptionSizeTiny}"/>
<Setter Target="NumberPad.ButtonStyle" Value="{StaticResource NumericButtonStyle12}"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
<VisualStateGroup>
<VisualState x:Name="ShowStandardFunctions">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowHeight="394" MinWindowWidth="0"/>
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="R1.Height" Value="1*"/>
<Setter Target="StandardFunctions.Visibility" Value="Visible"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="HideStandardFunctions">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowHeight="0" MinWindowWidth="0"/>
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="R1.Height" Value="0*"/>
<Setter Target="StandardFunctions.Visibility" Value="Collapsed"/>
<Setter Target="PercentButton.Visibility" Value="Collapsed"/>
<Setter Target="PercentColumn.Width" Value="0"/>
<Setter Target="DisplayControls.Column" Value="1"/>
<Setter Target="DisplayControls.ColumnSpan" Value="4"/>
<Setter Target="StandardOperators.Row" Value="0"/>
<Setter Target="StandardOperators.RowSpan" Value="6"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid x:Name="DisplayControls"
x:Uid="DisplayControls"
Grid.Row="0"
Grid.Column="2"
Grid.ColumnSpan="4"
AutomationProperties.HeadingLevel="Level1">
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="PercentColumn"/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<controls:CalculatorButton x:Name="PercentButton"
x:Uid="percentButton"
Grid.Column="0"
Style="{StaticResource SymbolOperatorButtonStyle}"
AutomationProperties.AutomationId="percentButton"
ButtonId="Percent"
Content="&#xE94C;"/>
<controls:CalculatorButton x:Name="ClearEntryButton"
x:Uid="clearEntryButton"
Grid.Column="1"
Style="{StaticResource OperatorButtonStyle}"
FontSize="16"
AutomationProperties.AutomationId="clearEntryButton"
ButtonId="ClearEntry"
Content="CE"/>
<controls:CalculatorButton x:Name="ClearButton"
x:Uid="clearButton"
Grid.Column="2"
Style="{StaticResource OperatorButtonStyle}"
FontSize="16"
AutomationProperties.AutomationId="clearButton"
ButtonId="Clear"
Content="C"/>
<controls:CalculatorButton x:Name="BackSpaceButton"
x:Uid="backSpaceButton"
Grid.Column="3"
Style="{StaticResource SymbolOperatorButtonStyle}"
FontSize="16"
AutomationProperties.AutomationId="backSpaceButton"
ButtonId="Backspace"
Content="&#xE94F;"/>
</Grid>
<Grid x:Name="StandardFunctions"
x:Uid="StandardFunctions"
Grid.Row="1"
Grid.Column="2"
Grid.ColumnSpan="4"
AutomationProperties.HeadingLevel="Level1">
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition x:Name="FnR1" Height="0"/>
<RowDefinition x:Name="FnR2" Height="0"/>
<RowDefinition x:Name="FnR3" Height="0"/>
<RowDefinition x:Name="FnR4" Height="0"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition x:Name="FnC1" Width="1*"/>
<ColumnDefinition x:Name="FnC2" Width="1*"/>
<ColumnDefinition x:Name="FnC3" Width="1*"/>
</Grid.ColumnDefinitions>
<controls:CalculatorButton x:Name="InvertButton"
x:Uid="invertButton"
Style="{StaticResource SymbolOperatorButtonStyle}"
FontSize="18"
AutomationProperties.AutomationId="invertButton"
ButtonId="Invert"
Content="&#xf7c9;"/>
<controls:CalculatorButton x:Name="XPower2Button"
x:Uid="xpower2Button"
Grid.Column="1"
Style="{StaticResource SymbolOperatorButtonStyle}"
FontSize="18"
AutomationProperties.AutomationId="xpower2Button"
ButtonId="XPower2"
Content="&#xf7c8;"/>
<controls:CalculatorButton x:Name="SquareRootButton"
x:Uid="squareRootButton"
Grid.Column="2"
Style="{StaticResource SymbolOperatorButtonStyle}"
AutomationProperties.AutomationId="squareRootButton"
ButtonId="Sqrt"
Content="&#xF899;"/>
</Grid>
<Grid x:Name="StandardOperators"
x:Uid="StandardOperators"
Grid.Row="1"
Grid.RowSpan="5"
Grid.Column="5"
AutomationProperties.HeadingLevel="Level1">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<controls:CalculatorButton x:Name="DivideButton"
x:Uid="divideButton"
Grid.Row="0"
Style="{StaticResource SymbolOperatorButtonStyle}"
AutomationProperties.AutomationId="divideButton"
ButtonId="Divide"
Content="&#xE94A;"/>
<controls:CalculatorButton x:Name="MultiplyButton"
x:Uid="multiplyButton"
Grid.Row="1"
Style="{StaticResource SymbolOperatorButtonStyle}"
AutomationProperties.AutomationId="multiplyButton"
ButtonId="Multiply"
Content="&#xE947;"/>
<controls:CalculatorButton x:Name="MinusButton"
x:Uid="minusButton"
Grid.Row="2"
Style="{StaticResource SymbolOperatorButtonStyle}"
AutomationProperties.AutomationId="minusButton"
ButtonId="Subtract"
Content="&#xE949;"/>
<controls:CalculatorButton x:Name="PlusButton"
x:Uid="plusButton"
Grid.Row="3"
Style="{StaticResource SymbolOperatorButtonStyle}"
AutomationProperties.AutomationId="plusButton"
ButtonId="Add"
Content="&#xE948;"/>
<controls:CalculatorButton x:Name="EqualButton"
x:Uid="equalButton"
Grid.Row="4"
Style="{StaticResource AccentEmphasizedCalcButtonStyle}"
AutomationProperties.AutomationId="equalButton"
ButtonId="Equals"
Content="&#xE94E;"/>
</Grid>
<local:NumberPad x:Name="NumberPad"
x:Uid="NumberPad"
Grid.Row="2"
Grid.RowSpan="4"
Grid.Column="2"
Grid.ColumnSpan="3"
AutomationProperties.HeadingLevel="Level1"
ButtonStyle="{StaticResource NumericButtonStyle24}"/>
<controls:CalculatorButton x:Name="NegateButton"
x:Uid="negateButton"
Grid.Row="5"
Grid.Column="2"
Style="{StaticResource SymbolOperatorKeypadButtonStyle}"
FontWeight="Normal"
AutomationProperties.AutomationId="negateButton"
ButtonId="Negate"
Content="&#xF898;"/>
</Grid>
</UserControl>

View file

@ -0,0 +1,52 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
//
// CalculatorStandardOperators.xaml.h
// Declaration of the CalculatorStandardOperators class
//
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Diagnostics;
using CalculatorApp;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
namespace CalculatorApp
{
[Windows.Foundation.Metadata.WebHostHidden]
public sealed partial class CalculatorStandardOperators
{
public CalculatorStandardOperators()
{
m_isErrorVisualState = false;
InitializeComponent();
}
public bool IsErrorVisualState
{
get { return m_isErrorVisualState; }
set
{
if (m_isErrorVisualState != value)
{
m_isErrorVisualState = value;
string newState = m_isErrorVisualState ? "ErrorLayout" : "NoErrorLayout";
VisualStateManager.GoToState(this, newState, false);
NumberPad.IsErrorVisualState = m_isErrorVisualState;
}
}
}
private bool m_isErrorVisualState;
}
}

View file

@ -0,0 +1,589 @@
<UserControl x:Class="CalculatorApp.DateCalculator"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:CalculatorApp.Controls"
xmlns:converters="using:CalculatorApp.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:CalculatorApp"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:DesignHeight="300"
d:DesignWidth="400"
Loaded="OnLoaded"
mc:Ignorable="d">
<UserControl.Resources>
<converters:BooleanNegationConverter x:Key="BooleanNegationConverter"/>
<converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
<converters:BooleanToVisibilityNegationConverter x:Key="BooleanToVisibilityNegationConverter"/>
<DataTemplate x:Key="ComboBoxItemContentTemplate">
<TextBlock Text="{Binding}" TextWrapping="WrapWholeWords"/>
</DataTemplate>
<Style x:Key="DateCalculation_ComboStyle" TargetType="ComboBox">
<Setter Property="Padding" Value="0,0,0,0"/>
<Setter Property="MinHeight" Value="20"/>
<Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseHighBrush}"/>
<Setter Property="Background" Value="{ThemeResource SystemControlBackgroundTransparentBrush}"/>
<Setter Property="BorderBrush" Value="{ThemeResource SystemControlForegroundBaseMediumLowBrush}"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="TabNavigation" Value="Once"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.HorizontalScrollMode" Value="Disabled"/>
<Setter Property="ScrollViewer.VerticalScrollMode" Value="Auto"/>
<Setter Property="ScrollViewer.IsVerticalRailEnabled" Value="True"/>
<Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="False"/>
<Setter Property="ScrollViewer.BringIntoViewOnFocusChange" Value="True"/>
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="VerticalAlignment" Value="Top"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="UseSystemFocusVisuals" Value="True"/>
<Setter Property="FocusVisualMargin" Value="-5,0,0,0"/>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<CarouselPanel/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ComboBox">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="PointerOver">
<VisualState.Setters>
<Setter Target="BackgroundElement.Background" Value="{ThemeResource SystemControlHighlightTransparentBrush}"/>
<Setter Target="SelectedContentPresenter.Foreground" Value="{ThemeResource SystemControlHighlightAltBaseMediumHighBrush}"/>
<Setter Target="DropDownGlyph.Foreground" Value="{ThemeResource SystemControlHighlightAltBaseMediumHighBrush}"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Pressed">
<VisualState.Setters>
<Setter Target="BackgroundElement.Background" Value="{ThemeResource SystemControlHighlightTransparentBrush}"/>
<Setter Target="SelectedContentPresenter.Foreground" Value="{ThemeResource SystemControlHighlightAltBaseMediumBrush}"/>
<Setter Target="DropDownGlyph.Foreground" Value="{ThemeResource SystemControlHighlightAltBaseMediumBrush}"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Disabled"/>
</VisualStateGroup>
<VisualStateGroup x:Name="DropDownStates">
<VisualState x:Name="Opened">
<Storyboard>
<SplitOpenThemeAnimation ClosedTargetName="SelectedContentPresenter"
OffsetFromCenter="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.DropDownOffset}"
OpenedLength="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.DropDownOpenedHeight}"
OpenedTargetName="PopupBorder"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Closed">
<Storyboard>
<SplitCloseThemeAnimation ClosedTargetName="SelectedContentPresenter"
OffsetFromCenter="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.DropDownOffset}"
OpenedLength="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.DropDownOpenedHeight}"
OpenedTargetName="PopupBorder"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter x:Name="ContentPresenter" Opacity="0"/>
<Popup x:Name="Popup">
<Border x:Name="PopupBorder"
Margin="0,-1,0,-1"
HorizontalAlignment="Stretch"
Background="{ThemeResource SystemControlBackgroundChromeMediumLowBrush}"
BorderBrush="{ThemeResource SystemControlForegroundChromeHighBrush}"
BorderThickness="{ThemeResource ComboBoxDropdownBorderThickness}">
<ScrollViewer x:Name="ScrollViewer"
MinWidth="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.DropDownContentMinWidth}"
Foreground="{ThemeResource SystemControlForegroundBaseHighBrush}"
AutomationProperties.AccessibilityView="Raw"
BringIntoViewOnFocusChange="{TemplateBinding ScrollViewer.BringIntoViewOnFocusChange}"
HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}"
IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}"
IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}"
IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}"
VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"
VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}"
VerticalSnapPointsAlignment="Near"
VerticalSnapPointsType="OptionalSingle"
ZoomMode="Disabled">
<ItemsPresenter/>
</ScrollViewer>
</Border>
</Popup>
<Border x:Name="BackgroundElement"
Grid.ColumnSpan="2"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"/>
<TextBlock x:Name="SelectedContentPresenter"
Margin="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Style="{ThemeResource BodyTextBlockStyle}"
FontWeight="SemiBold"
AutomationProperties.AccessibilityView="Raw"
FlowDirection="{TemplateBinding FlowDirection}"
Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=SelectedValue.Content}"
TextWrapping="WrapWholeWords"/>
<TextBlock x:Name="DropDownGlyph"
Grid.Column="1"
Margin="8,3,12,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Foreground="{ThemeResource SystemControlForegroundBaseHighBrush}"
FontFamily="{ThemeResource SymbolThemeFontFamily}"
FontSize="12"
AutomationProperties.AccessibilityView="Raw"
IsHitTestVisible="False"
Text="&#xE0E5;"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="DateCalculation_CalendarPickerStyle" TargetType="CalendarDatePicker">
<Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseHighBrush}"/>
<Setter Property="Background" Value="{ThemeResource SystemControlBackgroundTransparentBrush}"/>
<Setter Property="BorderBrush" Value="{ThemeResource SystemControlForegroundBaseMediumLowBrush}"/>
<Setter Property="BorderThickness" Value="{ThemeResource CalendarDatePickerBorderThemeThickness}"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="UseSystemFocusVisuals" Value="True"/>
<Setter Property="FocusVisualMargin" Value="-5,0,0,0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="CalendarDatePicker">
<Grid x:Name="Root">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="32"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="32"/>
</Grid.RowDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal">
<VisualState.Setters>
<Setter Target="DateText.Foreground" Value="{ThemeResource SystemControlForegroundBaseMediumHighBrush}"/>
<Setter Target="CalendarGlyph.Foreground" Value="{ThemeResource SystemControlForegroundBaseHighBrush}"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="PointerOver">
<VisualState.Setters>
<Setter Target="BorderElement.Background" Value="{ThemeResource SystemControlHighlightTransparentBrush}"/>
<Setter Target="DateText.Foreground" Value="{ThemeResource SystemControlHighlightAltBaseMediumHighBrush}"/>
<Setter Target="CalendarGlyph.Foreground" Value="{ThemeResource SystemControlHighlightAltBaseMediumHighBrush}"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Pressed">
<VisualState.Setters>
<Setter Target="BorderElement.Background" Value="{ThemeResource SystemControlHighlightTransparentBrush}"/>
<Setter Target="DateText.Foreground" Value="{ThemeResource SystemControlHighlightAltBaseMediumBrush}"/>
<Setter Target="CalendarGlyph.Foreground" Value="{ThemeResource SystemControlHighlightAltBaseMediumBrush}"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Disabled"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<FlyoutBase.AttachedFlyout>
<Flyout Placement="Full">
<Flyout.FlyoutPresenterStyle>
<Style TargetType="FlyoutPresenter">
<Setter Property="MaxHeight" Value="9000"/>
<Setter Property="MaxWidth" Value="9000"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="FlyoutPresenter">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="128"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="LeftGutter" Width="0"/>
<ColumnDefinition x:Name="C0" Width="*"/>
<ColumnDefinition x:Name="RightGutter" Width="0"/>
</Grid.ColumnDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="LeftAlignedLayout">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="360"/>
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="LeftGutter.Width" Value="12"/>
<Setter Target="RightGutter.Width" Value="*"/>
<Setter Target="C0.Width" Value="336"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="DefaultLayout">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="0"/>
</VisualState.StateTriggers>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter Grid.Row="1"
Grid.Column="1"
Margin="0,0,0,0"
HorizontalAlignment="Stretch"
VerticalAlignment="Top"
Background="{ThemeResource SystemControlBackgroundChromeMediumLowBrush}"
BorderBrush="{ThemeResource SystemControlForegroundChromeHighBrush}"
BorderThickness="{ThemeResource ComboBoxDropdownBorderThickness}"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
ContentTransitions="{TemplateBinding ContentTransitions}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Flyout.FlyoutPresenterStyle>
<CalendarView x:Name="CalendarView"
Style="{TemplateBinding CalendarViewStyle}"
CalendarIdentifier="{TemplateBinding CalendarIdentifier}"
DayOfWeekFormat="{TemplateBinding DayOfWeekFormat}"
DisplayMode="{TemplateBinding DisplayMode}"
FirstDayOfWeek="{TemplateBinding FirstDayOfWeek}"
IsGroupLabelVisible="{TemplateBinding IsGroupLabelVisible}"
IsOutOfScopeEnabled="{TemplateBinding IsOutOfScopeEnabled}"
IsTodayHighlighted="{TemplateBinding IsTodayHighlighted}"
MaxDate="{TemplateBinding MaxDate}"
MinDate="{TemplateBinding MinDate}"/>
</Flyout>
</FlyoutBase.AttachedFlyout>
<ContentPresenter x:Name="HeaderContentPresenter"
Margin="{ThemeResource ComboBoxHeaderThemeMargin}"
x:DeferLoadStrategy="Lazy"
Content="{TemplateBinding Header}"
ContentTemplate="{TemplateBinding HeaderTemplate}"
Visibility="Collapsed"/>
<Border x:Name="BorderElement"
Grid.Row="1"
Grid.ColumnSpan="2"
Background="{TemplateBinding Background}"
BorderThickness="0"/>
<TextBlock x:Name="DateText"
Grid.Row="1"
Padding="0,0,0,2"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Style="{ThemeResource BaseTextBlockStyle}"
Foreground="{ThemeResource SystemControlForegroundBaseMediumBrush}"
Text="{TemplateBinding PlaceholderText}"/>
<FontIcon x:Name="CalendarGlyph"
Grid.Row="1"
Grid.Column="1"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Foreground="{ThemeResource SystemControlForegroundBaseHighBrush}"
FontFamily="{ThemeResource SymbolThemeFontFamily}"
FontSize="16"
Glyph="&#xE787;"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="DateCalculation_CalendarViewStyle" TargetType="CalendarView">
<Setter Property="FocusBorderBrush" Value="{ThemeResource SystemControlForegroundBaseHighBrush}"/>
<Setter Property="SelectedHoverBorderBrush" Value="{ThemeResource SystemControlHighlightListAccentMediumBrush}"/>
<Setter Property="SelectedPressedBorderBrush" Value="{ThemeResource SystemControlHighlightListAccentHighBrush}"/>
<Setter Property="SelectedBorderBrush" Value="{ThemeResource SystemControlHighlightAccentBrush}"/>
<Setter Property="HoverBorderBrush" Value="{ThemeResource SystemControlHighlightBaseMediumLowBrush}"/>
<Setter Property="PressedBorderBrush" Value="{ThemeResource SystemControlHighlightBaseMediumBrush}"/>
<Setter Property="TodayForeground" Value="{ThemeResource SystemControlHighlightAltChromeWhiteBrush}"/>
<Setter Property="BlackoutForeground" Value="{ThemeResource SystemControlDisabledBaseMediumLowBrush}"/>
<Setter Property="SelectedForeground" Value="{ThemeResource SystemControlHighlightBaseHighBrush}"/>
<Setter Property="PressedForeground" Value="{ThemeResource SystemControlHighlightBaseHighBrush}"/>
<Setter Property="OutOfScopeForeground" Value="{ThemeResource SystemControlForegroundBaseMediumLowBrush}"/>
<Setter Property="CalendarItemForeground" Value="{ThemeResource SystemControlForegroundBaseHighBrush}"/>
<Setter Property="OutOfScopeBackground" Value="Transparent"/>
<Setter Property="CalendarItemBackground" Value="Transparent"/>
<Setter Property="CalendarItemBorderBrush" Value="Transparent"/>
<Setter Property="Foreground" Value="{ThemeResource SystemControlHyperlinkBaseMediumHighBrush}"/>
<Setter Property="Background" Value="{ThemeResource SystemControlBackgroundChromeMediumLowBrush}"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="CalendarItemBorderThickness" Value="2"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="DayItemFontSize" Value="18"/>
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="Margin" Value="0,12,0,12"/>
<Setter Property="IsTabStop" Value="False"/>
</Style>
<MenuFlyout x:Key="ResultsContextMenu" x:Name="ResultsContextMenu">
<MenuFlyoutItem x:Name="CopyMenuItem"
x:Uid="CopyMenuItem"
Click="OnCopyMenuItemClicked"
Icon="Copy"/>
</MenuFlyout>
</UserControl.Resources>
<Grid x:Name="DateCalculatorGrid"
Margin="12,0,12,0"
AutomationProperties.LandmarkType="Main">
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="C0" Width="*"/>
<ColumnDefinition x:Name="C1" Width="0"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="1*"
MinHeight="{StaticResource HamburgerHeight}"
MaxHeight="52"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="8*"/>
</Grid.RowDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup CurrentStateChanged="OnVisualStateChanged">
<VisualState x:Name="LeftAlignedLayout">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="480"/>
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="C0.Width" Value="456"/>
<Setter Target="C1.Width" Value="*"/>
<Setter Target="DateDiffAllUnitsResultLabel.FontSize" Value="24"/>
<Setter Target="DateResultLabel.FontSize" Value="24"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="DefaultLayout">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="0"/>
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="DateDiffAllUnitsResultLabel.FontSize" Value="20"/>
<Setter Target="DateResultLabel.FontSize" Value="20"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<!-- ComboBox for Date Calculation options -->
<ComboBox x:Name="DateCalculationOption"
x:Uid="DateCalculationOption"
Grid.Row="1"
Style="{ThemeResource DateCalculation_ComboStyle}"
SelectedIndex="0">
<ComboBoxItem x:Uid="Date_DifferenceOption"
MinWidth="276"
ContentTemplate="{StaticResource ComboBoxItemContentTemplate}"
IsSelected="{Binding IsDateDiffMode, Mode=TwoWay}"/>
<ComboBoxItem x:Uid="Date_AddSubtractOption"
MinWidth="276"
ContentTemplate="{StaticResource ComboBoxItemContentTemplate}"
IsSelected="{Binding IsDateDiffMode, Converter={StaticResource BooleanNegationConverter}, Mode=TwoWay}"/>
</ComboBox>
<!-- Grid to Calculate Difference between Two Dates -->
<Grid x:Name="DateDiffGrid"
Grid.Row="2"
Visibility="{Binding IsDateDiffMode, Converter={StaticResource BooleanToVisibilityConverter}}">
<Grid.RowDefinitions>
<RowDefinition Height="1*" MaxHeight="17"/>
<RowDefinition Height="Auto" MinHeight="32"/>
<RowDefinition Height="1*" MaxHeight="24"/>
<RowDefinition Height="Auto" MinHeight="32"/>
<RowDefinition Height="1*" MaxHeight="24"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="1*" MaxHeight="8"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- From Date -->
<CalendarDatePicker x:Name="DateDiff_FromDate"
x:Uid="DateDiff_FromHeader"
Grid.Row="1"
Style="{StaticResource DateCalculation_CalendarPickerStyle}"
CalendarViewStyle="{StaticResource DateCalculation_CalendarViewStyle}"
Closed="CalendarFlyoutClosed"
DateChanged="FromDate_DateChanged"/>
<!-- To Date -->
<CalendarDatePicker x:Name="DateDiff_ToDate"
x:Uid="DateDiff_ToHeader"
Grid.Row="3"
Margin="0,0,0,0"
Style="{StaticResource DateCalculation_CalendarPickerStyle}"
CalendarViewStyle="{StaticResource DateCalculation_CalendarViewStyle}"
Closed="CalendarFlyoutClosed"
DateChanged="ToDate_DateChanged"/>
<!-- Difference Result -->
<TextBlock x:Uid="Date_DifferenceLabel"
Grid.Row="5"
Margin="0,0,0,0"
Foreground="{ThemeResource SystemControlPageTextBaseHighBrush}"/>
<TextBlock x:Name="DateDiffAllUnitsResultLabel"
Grid.Row="6"
Style="{ThemeResource SubtitleTextBlockStyle}"
FontWeight="SemiBold"
AutomationProperties.LiveSetting="Polite"
AutomationProperties.Name="{Binding StrDateDiffResultAutomationName}"
ContextFlyout="{StaticResource ResultsContextMenu}"
IsTextSelectionEnabled="True"
Text="{Binding StrDateDiffResult}"/>
<TextBlock Grid.Row="8"
Style="{ThemeResource BaseTextBlockStyle}"
Foreground="{ThemeResource SystemControlPageTextBaseMediumBrush}"
ContextFlyout="{StaticResource ResultsContextMenu}"
IsTextSelectionEnabled="True"
Text="{Binding StrDateDiffResultInDays, Mode=OneWay}"
Visibility="{Binding IsDiffInDays, Converter={StaticResource BooleanToVisibilityNegationConverter}}"/>
</Grid>
<!-- Grid for Add/Subtract Date -->
<Grid x:Name="AddSubtractDateGrid"
Grid.Row="2"
x:DeferLoadStrategy="Lazy"
Loaded="AddSubtractDateGrid_Loaded"
Visibility="{Binding IsDateDiffMode, Converter={StaticResource BooleanToVisibilityNegationConverter}}">
<Grid.RowDefinitions>
<RowDefinition Height="1*" MaxHeight="17"/>
<RowDefinition Height="Auto" MinHeight="32"/>
<RowDefinition Height="1*" MaxHeight="23"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="1*" MaxHeight="29"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="1*" MaxHeight="35"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- From Date -->
<CalendarDatePicker x:Name="AddSubtract_FromDate"
x:Uid="AddSubtract_Date_FromHeader"
Grid.Row="1"
Margin="0,0,0,0"
Style="{StaticResource DateCalculation_CalendarPickerStyle}"
CalendarViewStyle="{StaticResource DateCalculation_CalendarViewStyle}"
Closed="CalendarFlyoutClosed"
DateChanged="AddSubtract_DateChanged"/>
<Grid Grid.Row="3">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<RadioButton x:Name="AddOption"
x:Uid="AddOption"
MinWidth="80"
MaxWidth="160"
VerticalAlignment="Top"
Checked="AddSubtractOption_Checked"
IsChecked="{Binding IsAddMode, Mode=TwoWay}"/>
<RadioButton x:Name="SubtractOption"
x:Uid="SubtractOption"
Grid.Column="1"
MinWidth="80"
MaxWidth="160"
Margin="20,0,0,0"
VerticalAlignment="Top"
Checked="AddSubtractOption_Checked"
IsChecked="{Binding IsAddMode, Converter={StaticResource BooleanNegationConverter}, Mode=TwoWay}"/>
</Grid>
<!-- Date Offset to be Added/Subtracted -->
<Grid x:Name="DateOffsetGrid" Grid.Row="5">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="YearsLabel"
x:Uid="YearsLabel"
Margin="0,0,0,6"
Foreground="{ThemeResource SystemControlPageTextBaseMediumBrush}"
TextWrapping="Wrap"/>
<ComboBox x:Name="YearsValue"
Grid.Row="1"
MinWidth="84"
AutomationProperties.LabeledBy="{Binding ElementName=YearsLabel}"
DropDownClosed="OffsetDropDownClosed"
ItemsSource="{Binding OffsetValues, Mode=OneTime}"
SelectedIndex="{Binding YearsOffset, Mode=TwoWay}"
SelectionChanged="OffsetValue_Changed"/>
<TextBlock x:Name="MonthsLabel"
x:Uid="MonthsLabel"
Grid.Column="1"
Margin="12,0,12,6"
Foreground="{ThemeResource SystemControlPageTextBaseMediumBrush}"
TextWrapping="Wrap"/>
<ComboBox x:Name="MonthsValue"
Grid.Row="1"
Grid.Column="1"
MinWidth="84"
Margin="12,0,12,0"
AutomationProperties.LabeledBy="{Binding ElementName=MonthsLabel}"
DropDownClosed="OffsetDropDownClosed"
ItemsSource="{Binding OffsetValues, Mode=OneTime}"
SelectedIndex="{Binding MonthsOffset, Mode=TwoWay}"
SelectionChanged="OffsetValue_Changed"/>
<TextBlock x:Name="DaysLabel"
x:Uid="DaysLabel"
Grid.Column="2"
Margin="0,0,0,6"
Foreground="{ThemeResource SystemControlPageTextBaseMediumBrush}"
TextWrapping="Wrap"/>
<ComboBox x:Name="DaysValue"
Grid.Row="1"
Grid.Column="2"
MinWidth="84"
AutomationProperties.LabeledBy="{Binding ElementName=DaysLabel}"
DropDownClosed="OffsetDropDownClosed"
ItemsSource="{Binding OffsetValues, Mode=OneTime}"
SelectedIndex="{Binding DaysOffset, Mode=TwoWay}"
SelectionChanged="OffsetValue_Changed"/>
</Grid>
<!-- Resulting Date -->
<TextBlock x:Uid="DateLabel"
Grid.Row="7"
Foreground="{ThemeResource SystemControlPageTextBaseMediumBrush}"/>
<TextBlock x:Name="DateResultLabel"
Grid.Row="8"
Style="{ThemeResource SubtitleTextBlockStyle}"
FontWeight="SemiBold"
AutomationProperties.LiveSetting="Polite"
AutomationProperties.Name="{Binding StrDateResultAutomationName}"
ContextFlyout="{StaticResource ResultsContextMenu}"
IsTextSelectionEnabled="True"
Text="{Binding StrDateResult}"/>
</Grid>
</Grid>
</UserControl>

View file

@ -0,0 +1,269 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
//
// DateCalculator.xaml.h
// Declaration of the DateCalculator class
//
// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Diagnostics;
using CalculatorApp;
using CalculatorApp.Common;
using CalculatorApp.ViewModel;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.Globalization;
using Windows.Globalization.DateTimeFormatting;
using Windows.System.UserProfile;
using Windows.UI.Core;
using Windows.UI.ViewManagement;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Automation;
using Windows.UI.Xaml.Automation.Peers;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
namespace CalculatorApp
{
[Windows.Foundation.Metadata.WebHostHidden]
public sealed partial class DateCalculator
{
public DateCalculator()
{
InitializeComponent();
// Set Calendar Identifier
DateDiff_FromDate.CalendarIdentifier = localizationSettings.GetCalendarIdentifier();
DateDiff_ToDate.CalendarIdentifier = localizationSettings.GetCalendarIdentifier();
// Setting the FirstDayofWeek
DateDiff_FromDate.FirstDayOfWeek = localizationSettings.GetFirstDayOfWeek();
DateDiff_ToDate.FirstDayOfWeek = localizationSettings.GetFirstDayOfWeek();
// Setting the Language explicitly is not required,
// this is a workaround for the bug in the control due to which
// the displayed date is incorrect for non Gregorian Calendar Systems
// The displayed date doesn't honor the shortdate format, on setting the Language the format is refreshed
DateDiff_FromDate.Language = localizationSettings.GetLocaleName();
DateDiff_ToDate.Language = localizationSettings.GetLocaleName();
// Set Min and Max Dates according to the Gregorian Calendar(1601 & 9999)
var calendar = new Calendar();
var today = calendar.GetDateTime();
calendar.ChangeCalendarSystem(CalendarIdentifiers.Gregorian);
calendar.Day = 1;
calendar.Month = 1;
calendar.Year = c_minYear;
var minYear = calendar.GetDateTime(); // 1st January, 1601
DateDiff_FromDate.MinDate = minYear;
DateDiff_ToDate.MinDate = minYear;
calendar.Day = 31;
calendar.Month = 12;
calendar.Year = c_maxYear;
var maxYear = calendar.GetDateTime(); // 31st December, 9878
DateDiff_FromDate.MaxDate = maxYear;
DateDiff_ToDate.MaxDate = maxYear;
// Set the PlaceHolderText for CalendarDatePicker
DateTimeFormatter dateTimeFormatter = LocalizationService.GetInstance().GetRegionalSettingsAwareDateTimeFormatter(
"day month year",
localizationSettings.GetCalendarIdentifier(),
ClockIdentifiers.TwentyFourHour); // Clock Identifier is not used
DateDiff_FromDate.DateFormat = "day month year";
DateDiff_ToDate.DateFormat = "day month year";
var placeholderText = dateTimeFormatter.Format(today);
DateDiff_FromDate.PlaceholderText = placeholderText;
DateDiff_ToDate.PlaceholderText = placeholderText;
CopyMenuItem.Text = AppResourceProvider.GetInstance().GetResourceString("copyMenuItem");
DateCalculationOption.SelectionChanged += DateCalcOption_Changed;
}
public void CloseCalendarFlyout()
{
if (DateDiff_FromDate.IsCalendarOpen)
{
DateDiff_FromDate.IsCalendarOpen = false;
}
if (DateDiff_ToDate.IsCalendarOpen)
{
DateDiff_ToDate.IsCalendarOpen = false;
}
if ((AddSubtract_FromDate != null) && (AddSubtract_FromDate.IsCalendarOpen))
{
AddSubtract_FromDate.IsCalendarOpen = false;
}
}
public void SetDefaultFocus()
{
DateCalculationOption.Focus(FocusState.Programmatic);
}
private void FromDate_DateChanged(CalendarDatePicker sender, CalendarDatePickerDateChangedEventArgs e)
{
if (e.NewDate != null)
{
var dateCalcViewModel = (DateCalculatorViewModel)DataContext;
dateCalcViewModel.FromDate = e.NewDate.Value;
TraceLogger.GetInstance().LogDateCalculationModeUsed(false);
}
else
{
ReselectCalendarDate(sender, e.OldDate.Value);
}
}
private void ToDate_DateChanged(CalendarDatePicker sender, CalendarDatePickerDateChangedEventArgs e)
{
if (e.NewDate != null)
{
var dateCalcViewModel = (DateCalculatorViewModel)this.DataContext;
dateCalcViewModel.ToDate = e.NewDate.Value;
TraceLogger.GetInstance().LogDateCalculationModeUsed(false);
}
else
{
ReselectCalendarDate(sender, e.OldDate.Value);
}
}
private void AddSubtract_DateChanged(CalendarDatePicker sender, CalendarDatePickerDateChangedEventArgs e)
{
if (e.NewDate != null)
{
var dateCalcViewModel = (DateCalculatorViewModel)this.DataContext;
dateCalcViewModel.StartDate = e.NewDate.Value;
TraceLogger.GetInstance().LogDateCalculationModeUsed(true);
}
else
{
ReselectCalendarDate(sender, e.OldDate.Value);
}
}
private void OffsetValue_Changed(object sender, SelectionChangedEventArgs e)
{
var dateCalcViewModel = (DateCalculatorViewModel)this.DataContext;
// do not log diagnostics for no-ops and initialization of combo boxes
if (dateCalcViewModel.DaysOffset != 0 || dateCalcViewModel.MonthsOffset != 0 || dateCalcViewModel.YearsOffset != 0)
{
TraceLogger.GetInstance().LogDateCalculationModeUsed(true);
}
}
private void OnCopyMenuItemClicked(object sender, RoutedEventArgs e)
{
var calcResult = (TextBlock)ResultsContextMenu.Target;
CopyPasteManager.CopyToClipboard(calcResult.Text);
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
}
private void DateCalcOption_Changed(object sender, SelectionChangedEventArgs e)
{
FindName("AddSubtractDateGrid");
var dateCalcViewModel = (DateCalculatorViewModel)this.DataContext;
// From Date Field needs to persist across Date Difference and Add Substract Date Mode.
// So when the mode dropdown changes, update the other datepicker with the latest date.
if (dateCalcViewModel.IsDateDiffMode)
{
if (AddSubtract_FromDate.Date == null)
{
return;
}
DateDiff_FromDate.Date = AddSubtract_FromDate.Date.Value;
}
else
{
if (DateDiff_FromDate.Date == null)
{
// If no date has been picked, then this can be null.
return;
}
AddSubtract_FromDate.Date = DateDiff_FromDate.Date.Value;
}
}
private void AddSubtractDateGrid_Loaded(object sender, RoutedEventArgs e)
{
AddSubtract_FromDate.PlaceholderText = DateDiff_FromDate.PlaceholderText;
AddSubtract_FromDate.CalendarIdentifier = localizationSettings.GetCalendarIdentifier();
AddSubtract_FromDate.FirstDayOfWeek = localizationSettings.GetFirstDayOfWeek();
AddSubtract_FromDate.Language = localizationSettings.GetLocaleName();
AddSubtract_FromDate.MinDate = DateDiff_FromDate.MinDate;
AddSubtract_FromDate.MaxDate = DateDiff_FromDate.MaxDate;
AddSubtract_FromDate.DateFormat = "day month year";
}
private void AddSubtractOption_Checked(object sender, RoutedEventArgs e)
{
RaiseLiveRegionChangedAutomationEvent(false);
}
// CSHARP_MIGRATION: TODO:
// can we change the calendarDatePicker.Date of in arg?
private void ReselectCalendarDate(CalendarDatePicker calendarDatePicker, DateTimeOffset? dateTime)
{
// Reselect the unselected Date
calendarDatePicker.Date = dateTime;
// Dismiss the Calendar flyout
calendarDatePicker.IsCalendarOpen = false;
}
private void OffsetDropDownClosed(object sender, object e)
{
RaiseLiveRegionChangedAutomationEvent(false);
}
private void CalendarFlyoutClosed(object sender, object e)
{
var dateCalcViewModel = (DateCalculatorViewModel)this.DataContext;
RaiseLiveRegionChangedAutomationEvent(dateCalcViewModel.IsDateDiffMode);
}
private void RaiseLiveRegionChangedAutomationEvent(bool isDateDiffMode)
{
TextBlock resultTextBlock = isDateDiffMode ? DateDiffAllUnitsResultLabel : DateResultLabel;
string automationName = AutomationProperties.GetName(resultTextBlock);
TextBlockAutomationPeer.FromElement(resultTextBlock).RaiseAutomationEvent(AutomationEvents.LiveRegionChanged);
}
private void OnVisualStateChanged(object sender, VisualStateChangedEventArgs e)
{
TraceLogger.GetInstance().LogVisualStateChanged(ViewMode.Date, e.NewState.Name, false);
}
// We choose 2550 as the max year because CalendarDatePicker experiences clipping
// issues just after 2558. We would like 9999 but will need to wait for a platform
// fix before we use a higher max year. This platform issue is tracked by
// TODO: MSFT-9273247
private const int c_maxYear = 2550;
private const int c_minYear = 1601;
private static readonly LocalizationSettings localizationSettings = LocalizationSettings.GetInstance();
}
}

View file

@ -0,0 +1,950 @@
<UserControl x:Class="CalculatorApp.EquationInputArea"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:contract7Present="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract,7)"
xmlns:controls="using:CalculatorApp.Controls"
xmlns:converters="using:CalculatorApp.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:CalculatorApp"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:mux="using:Microsoft.UI.Xaml.Controls"
xmlns:vm="using:CalculatorApp.ViewModel"
d:DesignHeight="300"
d:DesignWidth="400"
mc:Ignorable="d">
<UserControl.Resources>
<ResourceDictionary>
<converters:BooleanToVisibilityNegationConverter x:Name="BooleanToVisibilityNegationConverter"/>
<converters:BooleanNegationConverter x:Name="BooleanNegationConverter"/>
<DataTemplate x:Key="VariableDataTemplate" x:DataType="vm:VariableViewModel">
<Grid AutomationProperties.Name="{x:Bind VariableAutomationName}"
DataContext="{x:Bind}"
Tapped="VariableAreaTapped">
<Grid.Resources>
<ResourceDictionary>
<Style x:Key="VariableTextBoxStyle" TargetType="TextBox">
<Setter Property="Margin" Value="1,0,0,0"/>
<Setter Property="Padding" Value="2,6,2,2"/>
<Setter Property="TextAlignment" Value="Center"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0,0,0,1"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="InputScope" Value="Number"/>
<Setter Property="MinWidth" Value="30"/>
</Style>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Default">
<SolidColorBrush x:Key="TextControlBackgroundFocused" Color="Transparent"/>
<SolidColorBrush x:Key="TextControlBackgroundPointerOver" Color="Transparent"/>
<SolidColorBrush x:Key="TextControlForegroundFocused" Color="White"/>
<SolidColorBrush x:Key="SliderLegendBrush" Color="#B2ffffff"/>
<Style x:Key="VariableContainerStyle" TargetType="Border">
<Setter Property="Background" Value="{ThemeResource SystemControlBackgroundAltMediumLowBrush}"/>
</Style>
<Style x:Key="ThemedVariableTextBoxStyle"
BasedOn="{StaticResource VariableTextBoxStyle}"
TargetType="TextBox">
<Setter Property="BorderBrush" Value="#50ffffff"/>
</Style>
</ResourceDictionary>
<ResourceDictionary x:Key="Light">
<SolidColorBrush x:Key="TextControlBackgroundFocused" Color="Transparent"/>
<SolidColorBrush x:Key="TextControlBackgroundPointerOver" Color="Transparent"/>
<SolidColorBrush x:Key="TextControlForegroundFocused" Color="Black"/>
<SolidColorBrush x:Key="SliderLegendBrush" Color="#B2000000"/>
<Style x:Key="VariableContainerStyle" TargetType="Border">
<Setter Property="Background" Value="{ThemeResource SystemControlBackgroundAltMediumLowBrush}"/>
</Style>
<Style x:Key="ThemedVariableTextBoxStyle"
BasedOn="{StaticResource VariableTextBoxStyle}"
TargetType="TextBox">
<Setter Property="BorderBrush" Value="#70000000"/>
</Style>
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast">
<SolidColorBrush x:Key="TextControlBackgroundFocused" Color="{StaticResource SystemColorButtonFaceColor}"/>
<SolidColorBrush x:Key="TextControlBackgroundPointerOver" Color="{StaticResource SystemColorButtonFaceColor}"/>
<SolidColorBrush x:Key="TextControlForegroundFocused" Color="{StaticResource SystemColorButtonTextColor}"/>
<SolidColorBrush x:Key="SliderLegendBrush" Color="{StaticResource SystemColorWindowTextColor}"/>
<Style x:Key="VariableContainerStyle" TargetType="Border">
<Setter Property="Background" Value="{StaticResource SystemColorWindowColor}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="BorderBrush" Value="{StaticResource SystemColorWindowTextColor}"/>
</Style>
<Style x:Key="ThemedVariableTextBoxStyle" TargetType="TextBox">
<Setter Property="Margin" Value="1,0,0,0"/>
<Setter Property="Padding" Value="2,6,2,2"/>
<Setter Property="TextAlignment" Value="Center"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0,0,0,1"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="InputScope" Value="Number"/>
<Setter Property="MinWidth" Value="30"/>
</Style>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</Grid.Resources>
<Border Margin="0,3" Style="{ThemeResource VariableContainerStyle}">
<StackPanel Padding="12,0,12,6">
<Grid HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock MinWidth="16"
Margin="8,8,0,0"
VerticalAlignment="Center"
FontSize="16"
FontStyle="Italic"
Text="{x:Bind Name}"/>
<TextBlock Grid.Column="1"
MinWidth="16"
Margin="6,8,0,0"
VerticalAlignment="Center"
FontSize="16"
FontStyle="Italic"
Text="="/>
<TextBox x:Name="ValueTextBox"
x:Uid="VariableValueTextBox"
Grid.Column="2"
Margin="6,0,0,0"
Padding="0,10,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Style="{StaticResource ThemedVariableTextBoxStyle}"
FontStyle="Italic"
GotFocus="TextBoxGotFocus"
KeyDown="TextBoxKeyDown"
LosingFocus="TextBoxLosingFocus"
Text="{x:Bind Value, Mode=OneWay}">
<TextBox.Resources>
<x:Double x:Key="TextControlThemeMinWidth">32</x:Double>
</TextBox.Resources>
</TextBox>
</Grid>
<Slider x:Uid="VariableValueSlider"
Grid.Column="1"
Margin="8,0,8,-6"
VerticalAlignment="Center"
DataContext="{x:Bind}"
StepFrequency="{x:Bind Step, Mode=TwoWay}"
ValueChanged="Slider_ValueChanged"
Value="{x:Bind Value, Mode=TwoWay}"
Maximum="{x:Bind Max, Mode=TwoWay}"
Minimum="{x:Bind Min, Mode=TwoWay}"/>
<Grid Grid.Row="1"
Padding="8,0,8,8"
HorizontalAlignment="Stretch"
Visibility="{x:Bind SliderSettingsVisible, Mode=OneWay}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid HorizontalAlignment="Left">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock x:Uid="MinTextBlock"
Margin="0,12,4,0"
VerticalAlignment="Center"
FontSize="11"/>
<TextBox x:Name="MinTextBox"
x:Uid="VariableMinTextBox"
Grid.Column="1"
Padding="2,16,2,2"
Style="{StaticResource ThemedVariableTextBoxStyle}"
FontSize="11"
GotFocus="TextBoxGotFocus"
KeyDown="TextBoxKeyDown"
LosingFocus="TextBoxLosingFocus"
Text="{x:Bind Min, Mode=OneWay}">
<TextBox.Resources>
<x:Double x:Key="TextControlThemeMinWidth">18</x:Double>
</TextBox.Resources>
</TextBox>
</Grid>
<Grid Grid.Column="1" HorizontalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock x:Uid="StepTextBlock"
Margin="0,12,4,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="11"/>
<TextBox x:Name="StepTextBox"
x:Uid="VariableStepTextBox"
Grid.Column="1"
Padding="2,16,2,2"
Style="{StaticResource ThemedVariableTextBoxStyle}"
FontSize="11"
GotFocus="TextBoxGotFocus"
KeyDown="TextBoxKeyDown"
LosingFocus="TextBoxLosingFocus"
Text="{x:Bind Step, Mode=OneWay}">
<TextBox.Resources>
<x:Double x:Key="TextControlThemeMinWidth">18</x:Double>
</TextBox.Resources>
</TextBox>
</Grid>
<Grid Grid.Column="2" HorizontalAlignment="Right">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock x:Uid="MaxTextBlock"
Margin="0,12,4,0"
VerticalAlignment="Center"
FontSize="11"/>
<TextBox x:Name="MaxTextBox"
x:Uid="VariableMaxTextBox"
Grid.Column="1"
Padding="2,16,2,2"
Style="{StaticResource ThemedVariableTextBoxStyle}"
FontSize="11"
GotFocus="TextBoxGotFocus"
KeyDown="TextBoxKeyDown"
LosingFocus="TextBoxLosingFocus"
Text="{x:Bind Max, Mode=OneWay}">
<TextBox.Resources>
<x:Double x:Key="TextControlThemeMinWidth">18</x:Double>
</TextBox.Resources>
</TextBox>
</Grid>
</Grid>
<ToggleButton Name="VariableAreaSettings"
x:Uid="VariableAreaSettings"
Margin="0,6,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Click="VariableAreaClicked"
IsChecked="{x:Bind SliderSettingsVisible, Mode=OneWay}"
Tapped="VariableAreaButtonTapped">
<ToggleButton.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Default">
<SolidColorBrush x:Key="ToggleButtonBackground" Color="Transparent"/>
<SolidColorBrush x:Key="ToggleButtonBackgroundChecked" Color="Transparent"/>
<StaticResource x:Key="ToggleButtonBorderBrushChecked" ResourceKey="ToggleButtonBorderBrush"/>
<StaticResource x:Key="ToggleButtonForegroundChecked" ResourceKey="ToggleButtonForeground"/>
<StaticResource x:Key="ToggleButtonBackgroundCheckedPointerOver" ResourceKey="ToggleButtonBackgroundPointerOver"/>
<StaticResource x:Key="ToggleButtonBorderBrushCheckedPointerOver" ResourceKey="ToggleButtonBorderBrushPointerOver"/>
<StaticResource x:Key="ToggleButtonForegroundCheckedPointerOver" ResourceKey="ToggleButtonForegroundPointerOver"/>
<StaticResource x:Key="ToggleButtonBackgroundCheckedPressed" ResourceKey="ToggleButtonBackgroundPressed"/>
<StaticResource x:Key="ToggleButtonBorderBrushCheckedPressed" ResourceKey="ToggleButtonBorderBrushPressed"/>
<StaticResource x:Key="ToggleButtonForegroundCheckedPressed" ResourceKey="ToggleButtonForegroundPressed"/>
</ResourceDictionary>
<ResourceDictionary x:Key="Light">
<SolidColorBrush x:Key="ToggleButtonBackground" Color="Transparent"/>
<SolidColorBrush x:Key="ToggleButtonBackgroundChecked" Color="Transparent"/>
<StaticResource x:Key="ToggleButtonBorderBrushChecked" ResourceKey="ToggleButtonBorderBrush"/>
<StaticResource x:Key="ToggleButtonForegroundChecked" ResourceKey="ToggleButtonForeground"/>
<StaticResource x:Key="ToggleButtonBackgroundCheckedPointerOver" ResourceKey="ToggleButtonBackgroundPointerOver"/>
<StaticResource x:Key="ToggleButtonBorderBrushCheckedPointerOver" ResourceKey="ToggleButtonBorderBrushPointerOver"/>
<StaticResource x:Key="ToggleButtonForegroundCheckedPointerOver" ResourceKey="ToggleButtonForegroundPointerOver"/>
<StaticResource x:Key="ToggleButtonBackgroundCheckedPressed" ResourceKey="ToggleButtonBackgroundPressed"/>
<StaticResource x:Key="ToggleButtonBorderBrushCheckedPressed" ResourceKey="ToggleButtonBorderBrushPressed"/>
<StaticResource x:Key="ToggleButtonForegroundCheckedPressed" ResourceKey="ToggleButtonForegroundPressed"/>
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast"/>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</ToggleButton.Resources>
<FontIcon FontFamily="{StaticResource CalculatorFontFamily}"
FontSize="9"
Glyph="{x:Bind local:EquationInputArea.GetChevronIcon(SliderSettingsVisible), Mode=OneWay}"/>
</ToggleButton>
</StackPanel>
</Border>
</Grid>
</DataTemplate>
<Style x:Key="EquationTextBoxStyle" TargetType="controls:EquationTextBox">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderBrush" Value="{ThemeResource TextControlBorderBrush}"/>
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}"/>
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}"/>
<Setter Property="FontWeight" Value="Normal"/>
<Setter Property="Foreground" Value="{ThemeResource TextBoxForegroundThemeBrush}"/>
<Setter Property="Padding" Value="{ThemeResource TextControlThemePadding}"/>
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="Typography.StylisticSet20" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="controls:EquationTextBox">
<Grid>
<Grid.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Default">
<Visibility x:Key="ColorRectangleVisibility">Collapsed</Visibility>
<SolidColorBrush x:Key="EquationTextBoxBorderBrush" Color="Transparent"/>
<SolidColorBrush x:Key="EquationTextBoxBorderBrushPointerOver" Color="{Binding EquationColor.Color, RelativeSource={RelativeSource TemplatedParent}}"/>
<SolidColorBrush x:Key="EquationTextBoxBorderBrushFocused" Color="{Binding EquationColor.Color, RelativeSource={RelativeSource TemplatedParent}}"/>
<SolidColorBrush x:Key="EquationTextBoxBorderBrushDisabled" Color="{Binding EquationColor.Color, RelativeSource={RelativeSource TemplatedParent}}"/>
<SolidColorBrush x:Key="EquationBoxAddBackgroundBrush" Color="#9d000000"/>
<SolidColorBrush x:Key="EquationBoxErrorBackgroundBrush" Color="#33EB5757"/>
<SolidColorBrush x:Key="EquationBoxErrorBorderBrush" Color="#FFEB5757"/>
<SolidColorBrush x:Key="EquationButtonHideLineForegroundBrush"
Opacity="0.6"
Color="{StaticResource SystemChromeWhiteColor}"/>
<SolidColorBrush x:Key="EquationButtonHideLineBackgroundBrush"
Opacity="0.4"
Color="#FFFFFF"/>
<Thickness x:Key="EquationTextBoxBorderThickness">0,1,1,1</Thickness>
</ResourceDictionary>
<ResourceDictionary x:Key="Light">
<Visibility x:Key="ColorRectangleVisibility">Collapsed</Visibility>
<SolidColorBrush x:Key="EquationTextBoxBorderBrush" Color="Transparent"/>
<SolidColorBrush x:Key="EquationTextBoxBorderBrushPointerOver" Color="{Binding EquationColor.Color, RelativeSource={RelativeSource TemplatedParent}}"/>
<SolidColorBrush x:Key="EquationTextBoxBorderBrushFocused" Color="{Binding EquationColor.Color, RelativeSource={RelativeSource TemplatedParent}}"/>
<SolidColorBrush x:Key="EquationTextBoxBorderBrushDisabled" Color="{Binding EquationColor.Color, RelativeSource={RelativeSource TemplatedParent}}"/>
<SolidColorBrush x:Key="EquationBoxAddBackgroundBrush" Color="#D0FFFFFF"/>
<SolidColorBrush x:Key="EquationBoxErrorBackgroundBrush" Color="#33EB5757"/>
<SolidColorBrush x:Key="EquationBoxErrorBorderBrush" Color="#FFEB5757"/>
<SolidColorBrush x:Key="EquationButtonHideLineForegroundBrush" Color="{StaticResource SystemChromeWhiteColor}"/>
<SolidColorBrush x:Key="EquationButtonHideLineBackgroundBrush"
Opacity="0.4"
Color="#000000"/>
<Thickness x:Key="EquationTextBoxBorderThickness">0,1,1,1</Thickness>
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast">
<Visibility x:Key="ColorRectangleVisibility">Visible</Visibility>
<StaticResource x:Key="EquationTextBoxBorderBrush" ResourceKey="TextControlBorderBrush"/>
<StaticResource x:Key="EquationTextBoxBorderBrushPointerOver" ResourceKey="TextControlBorderBrushPointerOver"/>
<StaticResource x:Key="EquationTextBoxBorderBrushFocused" ResourceKey="TextControlBorderBrushFocused"/>
<StaticResource x:Key="EquationTextBoxBorderBrushDisabled" ResourceKey="TextControlBorderBrushDisabled"/>
<SolidColorBrush x:Key="EquationBoxAddBackgroundBrush" Color="{ThemeResource SystemColorButtonFaceColor}"/>
<SolidColorBrush x:Key="EquationBoxErrorBackgroundBrush" Color="{ThemeResource SystemColorButtonFaceColor}"/>
<SolidColorBrush x:Key="EquationBoxErrorBorderBrush" Color="{ThemeResource SystemColorButtonTextColor}"/>
<Thickness x:Key="EquationTextBoxBorderThickness">1</Thickness>
<SolidColorBrush x:Key="EquationButtonHideLineForegroundBrush" Color="{ThemeResource SystemColorButtonTextColor}"/>
<SolidColorBrush x:Key="EquationButtonHideLineBackgroundBrush" Color="{ThemeResource SystemColorGrayTextColor}"/>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition MinHeight="44"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal">
<VisualState.Setters>
<Setter Target="MathRichEditBox.PlaceholderText" Value=""/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="AddEquation">
<VisualState.Setters>
<Setter Target="FunctionNumberLabelTextBlock.Visibility" Value="Collapsed"/>
<Setter Target="EquationButton.Background" Value="{ThemeResource EquationButtonHideLineBackgroundBrush}"/>
<Setter Target="EquationButton.BorderBrush" Value="{ThemeResource EquationButtonHideLineBackgroundBrush}"/>
<Setter Target="EquationButton.Foreground" Value="{ThemeResource EquationButtonHideLineForegroundBrush}"/>
<Setter Target="EquationButton.IsEnabled" Value="false"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="AddEquationFocused">
<VisualState.Setters>
<Setter Target="FunctionNumberLabelTextBlock.Visibility" Value="Collapsed"/>
<Setter Target="EquationButton.Background" Value="{ThemeResource EquationButtonHideLineBackgroundBrush}"/>
<Setter Target="EquationButton.BorderBrush" Value="{ThemeResource EquationButtonHideLineBackgroundBrush}"/>
<Setter Target="EquationButton.Foreground" Value="{ThemeResource EquationButtonHideLineForegroundBrush}"/>
<Setter Target="EquationButton.IsEnabled" Value="false"/>
<Setter Target="EquationBoxBorder.Background" Value="{ThemeResource TextControlBackgroundFocused}"/>
<Setter Target="EquationBoxBorder.BorderBrush" Value="{ThemeResource EquationButtonHideLineBackgroundBrush}"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Error">
<VisualState.Setters>
<Setter Target="MathRichEditBox.PlaceholderText" Value=""/>
<Setter Target="EquationBoxBorder.BorderThickness" Value="1"/>
<Setter Target="EquationBoxBorder.BorderBrush" Value="{ThemeResource EquationBoxErrorBorderBrush}"/>
<Setter Target="EquationBoxBorder.Background" Value="{ThemeResource EquationBoxErrorBackgroundBrush}"/>
<Setter Target="RemoveButton.Visibility" Value="Visible"/>
<Setter Target="ErrorIcon.Visibility" Value="Visible"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="PointerOver">
<VisualState.Setters>
<Setter Target="EquationBoxBorder.BorderBrush" Value="{ThemeResource EquationTextBoxBorderBrushPointerOver}"/>
<Setter Target="ColorChooserButton.Visibility" Value="Visible"/>
<Setter Target="FunctionButton.Visibility" Value="Visible"/>
<Setter Target="RemoveButton.Visibility" Value="Visible"/>
<Setter Target="ErrorIcon.Visibility" Value="Collapsed"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="PointerOverError">
<VisualState.Setters>
<Setter Target="EquationBoxBorder.BorderBrush" Value="{ThemeResource EquationBoxErrorBorderBrush}"/>
<Setter Target="EquationBoxBorder.BorderThickness" Value="1"/>
<Setter Target="EquationBoxBorder.Background" Value="{ThemeResource EquationBoxErrorBackgroundBrush}"/>
<Setter Target="ColorChooserButton.Visibility" Value="Collapsed"/>
<Setter Target="FunctionButton.Visibility" Value="Collapsed"/>
<Setter Target="RemoveButton.Visibility" Value="Visible"/>
<Setter Target="ErrorIcon.Visibility" Value="Visible"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Target="EquationBoxBorder.Background" Value="{ThemeResource TextBoxDisabledBackgroundThemeBrush}"/>
<Setter Target="EquationBoxBorder.BorderBrush" Value="{ThemeResource EquationTextBoxBorderBrushPointerOver}"/>
<Setter Target="EquationTextBox.Background" Value="{ThemeResource AppControlTransparentButtonBackgroundBrush}"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Focused">
<VisualState.Setters>
<Setter Target="EquationBoxBorder.BorderBrush" Value="{ThemeResource EquationTextBoxBorderBrushFocused}"/>
<Setter Target="EquationBoxBorder.Background" Value="{ThemeResource TextControlBackgroundFocused}"/>
<Setter Target="MathRichEditBox.Foreground" Value="{ThemeResource TextControlForegroundFocused}"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="FocusedError">
<VisualState.Setters>
<Setter Target="EquationBoxBorder.BorderBrush" Value="{ThemeResource EquationBoxErrorBorderBrush}"/>
<Setter Target="EquationBoxBorder.BorderThickness" Value="1"/>
<Setter Target="EquationBoxBorder.Background" Value="{ThemeResource TextControlBackgroundFocused}"/>
<Setter Target="ErrorIcon.Visibility" Value="Collapsed"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="ButtonStates">
<VisualState x:Name="ButtonVisible">
<VisualState.Setters>
<Setter Target="DeleteButton.Visibility" Value="Visible"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="ButtonHideRemove">
<VisualState.Setters>
<Setter Target="RemoveButtonPanel.Visibility" Value="Collapsed"/>
<Setter Target="RemoveFunctionMenuItem.IsEnabled" Value="False"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="ButtonCollapsed"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Rectangle Grid.Column="0"
Width="10"
Margin="0,0,2,0"
Fill="{TemplateBinding EquationColor}"
Visibility="{ThemeResource ColorRectangleVisibility}"/>
<ToggleButton x:Name="EquationButton"
Grid.Column="1"
MinWidth="44"
MinHeight="44"
VerticalAlignment="Stretch"
IsChecked="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=IsEquationLineDisabled, Mode=TwoWay}">
<ToggleButton.Content>
<StackPanel HorizontalAlignment="Center"
VerticalAlignment="Center"
Background="Transparent"
FlowDirection="LeftToRight"
Orientation="Horizontal">
<FontIcon FontFamily="{StaticResource CalculatorFontFamily}" Glyph="&#xF893;"/>
<TextBlock x:Name="FunctionNumberLabelTextBlock"
Margin="-5,19,0,0"
FontSize="11"
Text="{TemplateBinding EquationButtonContentIndex}"/>
</StackPanel>
</ToggleButton.Content>
<ToggleButton.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Default">
<x:Double x:Key="EquationButtonOverlayPointerOverOpacity">0.3</x:Double>
<x:Double x:Key="EquationButtonOverlayPressedOpacity">0.5</x:Double>
<SolidColorBrush x:Key="EquationButtonOverlayBackgroundBrush" Color="White"/>
<SolidColorBrush x:Key="ToggleButtonBackground" Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=EquationColor.Color}"/>
<SolidColorBrush x:Key="ToggleButtonBorderBrush" Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=EquationColor.Color}"/>
<SolidColorBrush x:Key="ToggleButtonForeground" Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=EquationButtonForegroundColor.Color}"/>
<SolidColorBrush x:Key="ToggleButtonBackgroundPointerOver" Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=EquationColor.Color}"/>
<SolidColorBrush x:Key="ToggleButtonForegroundPointerOver" Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=EquationButtonForegroundColor.Color}"/>
<SolidColorBrush x:Key="ToggleButtonBorderBrushPointerOver" Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=EquationColor.Color}"/>
<SolidColorBrush x:Key="ToggleButtonBackgroundPressed" Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=EquationColor.Color}"/>
<SolidColorBrush x:Key="ToggleButtonForegroundPressed" Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=EquationButtonForegroundColor.Color}"/>
<SolidColorBrush x:Key="ToggleButtonBorderBrushPressed" Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=EquationColor.Color}"/>
<StaticResource x:Key="ToggleButtonBackgroundChecked" ResourceKey="EquationButtonHideLineBackgroundBrush"/>
<StaticResource x:Key="ToggleButtonBorderBrushChecked" ResourceKey="EquationButtonHideLineBackgroundBrush"/>
<StaticResource x:Key="ToggleButtonForegroundChecked" ResourceKey="EquationButtonHideLineForegroundBrush"/>
<StaticResource x:Key="ToggleButtonBackgroundCheckedPointerOver" ResourceKey="EquationButtonHideLineBackgroundBrush"/>
<StaticResource x:Key="ToggleButtonBorderBrushCheckedPointerOver" ResourceKey="EquationButtonHideLineBackgroundBrush"/>
<StaticResource x:Key="ToggleButtonForegroundCheckedPointerOver" ResourceKey="EquationButtonHideLineForegroundBrush"/>
<StaticResource x:Key="ToggleButtonBackgroundCheckedPressed" ResourceKey="EquationButtonHideLineBackgroundBrush"/>
<StaticResource x:Key="ToggleButtonBorderBrushCheckedPressed" ResourceKey="EquationButtonHideLineBackgroundBrush"/>
<StaticResource x:Key="ToggleButtonForegroundCheckedPressed" ResourceKey="EquationButtonHideLineForegroundBrush"/>
</ResourceDictionary>
<ResourceDictionary x:Key="Light">
<x:Double x:Key="EquationButtonOverlayPointerOverOpacity">0.2</x:Double>
<x:Double x:Key="EquationButtonOverlayPressedOpacity">0.4</x:Double>
<SolidColorBrush x:Key="EquationButtonOverlayBackgroundBrush" Color="Black"/>
<SolidColorBrush x:Key="ToggleButtonBackground" Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=EquationColor.Color}"/>
<SolidColorBrush x:Key="ToggleButtonBorderBrush" Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=EquationColor.Color}"/>
<SolidColorBrush x:Key="ToggleButtonForeground" Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=EquationButtonForegroundColor.Color}"/>
<SolidColorBrush x:Key="ToggleButtonBackgroundPointerOver" Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=EquationColor.Color}"/>
<SolidColorBrush x:Key="ToggleButtonForegroundPointerOver" Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=EquationButtonForegroundColor.Color}"/>
<SolidColorBrush x:Key="ToggleButtonBorderBrushPointerOver" Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=EquationColor.Color}"/>
<SolidColorBrush x:Key="ToggleButtonBackgroundPressed" Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=EquationColor.Color}"/>
<SolidColorBrush x:Key="ToggleButtonForegroundPressed" Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=EquationButtonForegroundColor.Color}"/>
<SolidColorBrush x:Key="ToggleButtonBorderBrushPressed" Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=EquationColor.Color}"/>
<StaticResource x:Key="ToggleButtonBackgroundChecked" ResourceKey="EquationButtonHideLineBackgroundBrush"/>
<StaticResource x:Key="ToggleButtonBorderBrushChecked" ResourceKey="EquationButtonHideLineBackgroundBrush"/>
<StaticResource x:Key="ToggleButtonForegroundChecked" ResourceKey="EquationButtonHideLineForegroundBrush"/>
<StaticResource x:Key="ToggleButtonBackgroundCheckedPointerOver" ResourceKey="EquationButtonHideLineBackgroundBrush"/>
<StaticResource x:Key="ToggleButtonBorderBrushCheckedPointerOver" ResourceKey="EquationButtonHideLineBackgroundBrush"/>
<StaticResource x:Key="ToggleButtonForegroundCheckedPointerOver" ResourceKey="EquationButtonHideLineForegroundBrush"/>
<StaticResource x:Key="ToggleButtonBackgroundCheckedPressed" ResourceKey="EquationButtonHideLineBackgroundBrush"/>
<StaticResource x:Key="ToggleButtonBorderBrushCheckedPressed" ResourceKey="EquationButtonHideLineBackgroundBrush"/>
<StaticResource x:Key="ToggleButtonForegroundCheckedPressed" ResourceKey="EquationButtonHideLineForegroundBrush"/>
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast">
<x:Double x:Key="EquationButtonOverlayPointerOverOpacity">0</x:Double>
<x:Double x:Key="EquationButtonOverlayPressedOpacity">0</x:Double>
<SolidColorBrush x:Key="EquationButtonOverlayBackgroundBrush" Color="Transparent"/>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</ToggleButton.Resources>
<ToggleButton.Style>
<Style TargetType="ToggleButton">
<Setter Property="Background" Value="{ThemeResource ToggleButtonBackground}"/>
<Setter Property="BorderBrush" Value="{ThemeResource ToggleButtonBorderBrush}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Grid x:Name="RootGrid"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="1">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal">
<VisualState.Setters>
<Setter Target="Overlay.Opacity" Value="0.0"/>
<Setter Target="ContentPresenter.Visibility" Value="Visible"/>
<Setter Target="ShowHideIcon.Visibility" Value="Collapsed"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="PointerOver">
<VisualState.Setters>
<Setter Target="RootGrid.Background" Value="{ThemeResource ToggleButtonBackgroundPointerOver}"/>
<Setter Target="RootGrid.BorderBrush" Value="{ThemeResource ToggleButtonBorderBrushPointerOver}"/>
<Setter Target="ShowHideIcon.Foreground" Value="{ThemeResource ToggleButtonForegroundPointerOver}"/>
<Setter Target="Overlay.Opacity" Value="{StaticResource EquationButtonOverlayPointerOverOpacity}"/>
<Setter Target="ContentPresenter.Visibility" Value="Collapsed"/>
<Setter Target="ShowHideIcon.Visibility" Value="Visible"/>
<Setter Target="ShowHideIcon.Glyph" Value="&#xF6AC;"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Pressed">
<VisualState.Setters>
<Setter Target="RootGrid.Background" Value="{ThemeResource ToggleButtonBackgroundPressed}"/>
<Setter Target="RootGrid.BorderBrush" Value="{ThemeResource ToggleButtonBorderBrush}"/>
<Setter Target="Overlay.Opacity" Value="{StaticResource EquationButtonOverlayPressedOpacity}"/>
<Setter Target="ShowHideIcon.Foreground" Value="{ThemeResource ToggleButtonForegroundPressed}"/>
<Setter Target="ContentPresenter.Visibility" Value="Collapsed"/>
<Setter Target="ShowHideIcon.Visibility" Value="Visible"/>
<Setter Target="ShowHideIcon.Glyph" Value="&#xF6AC;"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Checked">
<VisualState.Setters>
<Setter Target="RootGrid.Background" Value="{ThemeResource ToggleButtonBackgroundChecked}"/>
<Setter Target="RootGrid.BorderBrush" Value="{ThemeResource ToggleButtonBorderBrushChecked}"/>
<Setter Target="ContentPresenter.Foreground" Value="{ThemeResource ToggleButtonForegroundChecked}"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="CheckedPointerOver">
<VisualState.Setters>
<Setter Target="RootGrid.Background" Value="{ThemeResource ToggleButtonBackgroundCheckedPointerOver}"/>
<Setter Target="RootGrid.BorderBrush" Value="{ThemeResource ToggleButtonBorderBrushCheckedPointerOver}"/>
<Setter Target="ShowHideIcon.Foreground" Value="{ThemeResource ToggleButtonForegroundCheckedPointerOver}"/>
<Setter Target="Overlay.Opacity" Value="{StaticResource EquationButtonOverlayPointerOverOpacity}"/>
<Setter Target="ContentPresenter.Visibility" Value="Collapsed"/>
<Setter Target="ShowHideIcon.Visibility" Value="Visible"/>
<Setter Target="ShowHideIcon.Glyph" Value="&#xE890;"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="CheckedPressed">
<VisualState.Setters>
<Setter Target="RootGrid.Background" Value="{ThemeResource ToggleButtonBackgroundCheckedPressed}"/>
<Setter Target="RootGrid.BorderBrush" Value="{ThemeResource ToggleButtonBorderBrushCheckedPressed}"/>
<Setter Target="ShowHideIcon.Foreground" Value="{ThemeResource ToggleButtonForegroundCheckedPressed}"/>
<Setter Target="Overlay.Opacity" Value="{StaticResource EquationButtonOverlayPressedOpacity}"/>
<Setter Target="ContentPresenter.Visibility" Value="Collapsed"/>
<Setter Target="ShowHideIcon.Visibility" Value="Visible"/>
<Setter Target="ShowHideIcon.Glyph" Value="&#xE890;"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Rectangle x:Name="Overlay"
Fill="{ThemeResource EquationButtonOverlayBackgroundBrush}"
Opacity="0"
IsHitTestVisible="False"/>
<ContentPresenter x:Name="ContentPresenter"
AutomationProperties.AccessibilityView="Raw"
IsHitTestVisible="False"/>
<FontIcon x:Name="ShowHideIcon"
FontFamily="{StaticResource CalculatorFontFamily}"
Visibility="Collapsed"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ToggleButton.Style>
</ToggleButton>
<Border x:Name="EquationBoxBorder"
Grid.Column="2"
Background="{ThemeResource TextControlBackground}"
BorderBrush="{ThemeResource EquationTextBoxBorderBrush}"
BorderThickness="{ThemeResource EquationTextBoxBorderThickness}"
contract7Present:BackgroundSizing="OuterBorderEdge">
<Grid contract7Present:Margin="{TemplateBinding BorderThickness}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<controls:MathRichEditBox x:Name="MathRichEditBox"
x:Uid="mathRichEditBox"
MinHeight="44"
Padding="{TemplateBinding Padding}"
VerticalAlignment="Stretch"
Style="{StaticResource MathRichEditBoxStyle}"
BorderThickness="0"
FontFamily="{TemplateBinding FontFamily}"
FontSize="{TemplateBinding FontSize}"
FontWeight="{TemplateBinding FontWeight}"
AcceptsReturn="false"
InputScope="Text"
MathText="{Binding MathEquation, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"
MaxLength="2048"
TextWrapping="NoWrap">
<controls:MathRichEditBox.ContextFlyout>
<MenuFlyout x:Name="MathRichEditContextMenu">
<MenuFlyoutItem x:Name="CutMenuItem"
x:Uid="cutEquationMenuItem"
Icon="Cut"/>
<MenuFlyoutItem x:Name="CopyMenuItem"
x:Uid="copyEquationMenuItem"
Icon="Copy"/>
<MenuFlyoutItem x:Name="PasteMenuItem"
x:Uid="pasteEquationMenuItem"
Icon="Paste"/>
<MenuFlyoutItem x:Name="UndoMenuItem"
x:Uid="undoEquationMenuItem"
Icon="Undo"/>
<MenuFlyoutItem x:Name="SelectAllMenuItem" x:Uid="selectAllEquationMenuItem"/>
<MenuFlyoutSeparator/>
<MenuFlyoutItem x:Name="FunctionAnalysisMenuItem">
<MenuFlyoutItem.Icon>
<FontIcon FontFamily="{StaticResource CalculatorFontFamily}" Glyph="&#xE945;"/>
</MenuFlyoutItem.Icon>
</MenuFlyoutItem>
<MenuFlyoutItem x:Name="ChangeFunctionStyleMenuItem">
<MenuFlyoutItem.Icon>
<FontIcon FontFamily="{StaticResource CalculatorFontFamily}" Glyph="&#xE790;"/>
</MenuFlyoutItem.Icon>
</MenuFlyoutItem>
<MenuFlyoutItem x:Name="RemoveFunctionMenuItem">
<MenuFlyoutItem.Icon>
<FontIcon FontFamily="{StaticResource CalculatorFontFamily}" Glyph="&#xECC9;"/>
</MenuFlyoutItem.Icon>
</MenuFlyoutItem>
</MenuFlyout>
</controls:MathRichEditBox.ContextFlyout>
</controls:MathRichEditBox>
<Button x:Name="FunctionButton"
x:Uid="functionAnalysisButton"
Grid.Column="1"
MinWidth="34"
Margin="1,2"
VerticalAlignment="Stretch"
Style="{ThemeResource ButtonRevealStyle}"
FontFamily="{StaticResource CalculatorFontFamily}"
AutomationProperties.AccessibilityView="Raw"
Content="&#xE945;"
IsTabStop="False"
Visibility="Collapsed">
<Button.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Default">
<SolidColorBrush x:Key="ButtonForegroundPressed" Color="{ThemeResource SystemChromeWhiteColor}"/>
<SolidColorBrush x:Key="ButtonForegroundPointerOver" Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=EquationColor.Color}"/>
<SolidColorBrush x:Key="ButtonRevealBackgroundPointerOver" Color="Transparent"/>
<SolidColorBrush x:Key="ButtonRevealBackgroundPressed" Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=EquationColor.Color}"/>
<SolidColorBrush x:Key="ButtonRevealBackground" Color="Transparent"/>
<SolidColorBrush x:Key="ButtonRevealBackgroundDisabled" Color="Transparent"/>
<RevealBorderBrush x:Key="ButtonRevealBorderBrush"
Opacity="0.33"
FallbackColor="Transparent"
TargetTheme="{ThemeResource CalcApplicationTheme}"
Color="Transparent"/>
<RevealBorderBrush x:Key="ButtonRevealBorderBrushPointerOver"
Opacity="0.33"
FallbackColor="{StaticResource SystemBaseMediumLowColor}"
TargetTheme="{ThemeResource CalcApplicationTheme}"
Color="{StaticResource SystemRevealBaseMediumLowColor}"/>
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast"/>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</Button.Resources>
</Button>
<ToggleButton x:Name="ColorChooserButton"
x:Uid="colorChooserButton"
Grid.Column="2"
MinWidth="34"
Margin="1,2"
VerticalAlignment="Stretch"
Style="{ThemeResource ToggleButtonRevealStyle}"
FontFamily="{StaticResource CalculatorFontFamily}"
AutomationProperties.AccessibilityView="Raw"
Content="&#xE790;"
IsTabStop="False"
Visibility="Collapsed">
<ToggleButton.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Default">
<SolidColorBrush x:Name="ToggleButtonForegroundPressed" Color="{ThemeResource SystemChromeWhiteColor}"/>
<SolidColorBrush x:Name="ToggleButtonForegroundChecked" Color="{ThemeResource SystemChromeWhiteColor}"/>
<SolidColorBrush x:Name="ToggleButtonForegroundPointerOver" Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=EquationColor.Color}"/>
<SolidColorBrush x:Name="ToggleButtonRevealBackground" Color="Transparent"/>
<SolidColorBrush x:Name="ToggleButtonRevealBackgroundChecked" Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=EquationColor.Color}"/>
<SolidColorBrush x:Name="ToggleButtonRevealBackgroundCheckedPointerOver" Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=EquationColor.Color}"/>
<SolidColorBrush x:Name="ToggleButtonRevealBackgroundCheckedPressed" Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=EquationColor.Color}"/>
<SolidColorBrush x:Name="ToggleButtonRevealBackgroundPressed" Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=EquationColor.Color}"/>
<SolidColorBrush x:Name="ToggleButtonRevealBackgroundPointerOver" Color="{ThemeResource AppControlTransparentButtonBackgroundBrush}"/>
<RevealBorderBrush x:Key="ToggleButtonRevealBorderBrush"
Opacity="0.33"
FallbackColor="Transparent"
TargetTheme="{ThemeResource CalcApplicationTheme}"
Color="Transparent"/>
<RevealBorderBrush x:Key="ToggleButtonRevealBorderBrushPointerOver"
Opacity="0.33"
FallbackColor="{StaticResource SystemBaseMediumLowColor}"
TargetTheme="{ThemeResource CalcApplicationTheme}"
Color="{StaticResource SystemRevealBaseMediumLowColor}"/>
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast"/>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</ToggleButton.Resources>
</ToggleButton>
<FontIcon x:Name="ErrorIcon"
Grid.Column="3"
MinWidth="28"
VerticalAlignment="Stretch"
Foreground="{ThemeResource ButtonForeground}"
FontFamily="{ThemeResource SymbolThemeFontFamily}"
FontSize="16"
AutomationProperties.AccessibilityView="Raw"
Glyph="&#xE7BA;"
ToolTipService.ToolTip="{TemplateBinding ErrorText}"
Visibility="Collapsed"/>
<Grid x:Name="RemoveButtonPanel" Grid.Column="4">
<Button x:Name="RemoveButton"
x:Uid="removeButton"
MinWidth="34"
Margin="1,2"
VerticalAlignment="Stretch"
Style="{StaticResource ButtonRevealStyle}"
FontFamily="{StaticResource CalculatorFontFamily}"
AutomationProperties.AccessibilityView="Raw"
Content="&#xECC9;"
IsTabStop="False"
Visibility="Collapsed">
<Button.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Default">
<SolidColorBrush x:Key="ButtonForegroundPressed" Color="{ThemeResource SystemChromeWhiteColor}"/>
<SolidColorBrush x:Key="ButtonForegroundPointerOver" Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=EquationColor.Color}"/>
<SolidColorBrush x:Key="ButtonRevealBackgroundPointerOver" Color="Transparent"/>
<SolidColorBrush x:Key="ButtonRevealBackgroundPressed" Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=EquationColor.Color}"/>
<SolidColorBrush x:Key="ButtonRevealBackground" Color="Transparent"/>
<RevealBorderBrush x:Key="ButtonRevealBorderBrush"
Opacity="0.33"
FallbackColor="Transparent"
TargetTheme="{ThemeResource CalcApplicationTheme}"
Color="Transparent"/>
<RevealBorderBrush x:Key="ButtonRevealBorderBrushPointerOver"
Opacity="0.33"
FallbackColor="{StaticResource SystemBaseMediumLowColor}"
TargetTheme="{ThemeResource CalcApplicationTheme}"
Color="{StaticResource SystemRevealBaseMediumLowColor}"/>
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast"/>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</Button.Resources>
</Button>
</Grid>
<Button x:Name="DeleteButton"
Grid.Column="4"
MinWidth="34"
Margin="1,2"
VerticalAlignment="Stretch"
Style="{StaticResource ButtonRevealStyle}"
Foreground="{ThemeResource TextControlForegroundFocused}"
FontFamily="{ThemeResource SymbolThemeFontFamily}"
FontSize="12"
AutomationProperties.AccessibilityView="Raw"
Content="&#xE10A;"
IsTabStop="False"
Visibility="Collapsed">
<Button.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Default">
<SolidColorBrush x:Key="ButtonForegroundPressed" Color="{ThemeResource SystemChromeWhiteColor}"/>
<SolidColorBrush x:Key="ButtonForegroundPointerOver" Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=EquationColor.Color}"/>
<SolidColorBrush x:Key="ButtonRevealBackgroundPointerOver" Color="Transparent"/>
<SolidColorBrush x:Key="ButtonRevealBackgroundPressed" Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=EquationColor.Color}"/>
<SolidColorBrush x:Key="ButtonRevealBackground" Color="{ThemeResource TextControlBackgroundFocused}"/>
<RevealBorderBrush x:Key="ButtonRevealBorderBrush"
Opacity="0.33"
FallbackColor="Transparent"
TargetTheme="{ThemeResource CalcApplicationTheme}"
Color="Transparent"/>
<RevealBorderBrush x:Key="ButtonRevealBorderBrushPointerOver"
Opacity="0.33"
FallbackColor="{StaticResource SystemBaseMediumLowColor}"
TargetTheme="{ThemeResource CalcApplicationTheme}"
Color="{StaticResource SystemRevealBaseMediumLowColor}"/>
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast"/>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</Button.Resources>
</Button>
</Grid>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
</UserControl.Resources>
<ScrollViewer VerticalScrollBarVisibility="Auto">
<StackPanel x:Uid="EquationInputPanel">
<!-- This ListView and the one below should be replacted by an ItemRepeater once https://github.com/microsoft/microsoft-ui-xaml/issues/2011 is fixed. -->
<ListView x:Name="EquationInputList"
x:Uid="EquationInputList"
IsItemClickEnabled="False"
ItemsSource="{x:Bind Equations}"
SelectionMode="None"
TabFocusNavigation="Local">
<!-- Removes animations from the ListView Style. -->
<ListView.Style>
<Style TargetType="ListView">
<Setter Property="ItemContainerTransitions">
<Setter.Value>
<TransitionCollection/>
</Setter.Value>
</Setter>
</Style>
</ListView.Style>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="Margin" Value="1,0,1,0"/>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate x:DataType="vm:EquationViewModel">
<controls:EquationTextBox x:Name="EquationInputButton"
x:Uid="EquationInputButton"
Margin="1,0,1,2"
Style="{StaticResource EquationTextBoxStyle}"
DataContext="{x:Bind Mode=OneWay}"
DataContextChanged="EquationTextBox_DataContextChanged"
EquationButtonClicked="EquationTextBox_EquationButtonClicked"
EquationButtonContentIndex="{x:Bind FunctionLabelIndex, Mode=OneWay}"
EquationButtonForegroundColor="{x:Bind local:EquationInputArea.GetForegroundColor(LineColor), Mode=OneWay}"
EquationColor="{x:Bind local:EquationInputArea.ToSolidColorBrush(LineColor), Mode=OneWay}"
EquationFormatRequested="EquationTextBox_EquationFormatRequested"
EquationSubmitted="EquationTextBox_Submitted"
ErrorText="{x:Bind vm:EquationViewModel.EquationErrorText(GraphEquation.GraphErrorType, GraphEquation.GraphErrorCode), Mode=OneWay}"
GotFocus="EquationTextBox_GotFocus"
HasError="{x:Bind GraphEquation.HasGraphError, Mode=OneWay}"
IsAddEquationMode="{x:Bind IsLastItemInList, Mode=OneWay}"
IsEquationLineDisabled="{x:Bind IsLineEnabled, Converter={StaticResource BooleanNegationConverter}, Mode=OneWay}"
KeyGraphFeaturesButtonClicked="EquationTextBox_KeyGraphFeaturesButtonClicked"
Loaded="EquationTextBox_Loaded"
LostFocus="EquationTextBox_LostFocus"
MathEquation="{x:Bind Expression, Mode=TwoWay}"
RemoveButtonClicked="EquationTextBox_RemoveButtonClicked">
<controls:EquationTextBox.ColorChooserFlyout>
<Flyout x:Uid="ColorChooserFlyout" Placement="Bottom">
<local:EquationStylePanelControl EnableLineStylePicker="{x:Bind GraphEquation.IsInequality, Converter={StaticResource BooleanNegationConverter}, Mode=OneWay}"
SelectedColor="{x:Bind LineColor, Mode=TwoWay}"
SelectedColorIndex="{x:Bind LineColorIndex, Mode=TwoWay}"
SelectedStyle="{x:Bind GraphEquation.EquationStyle, Mode=TwoWay}"/>
</Flyout>
</controls:EquationTextBox.ColorChooserFlyout>
</controls:EquationTextBox>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<StackPanel x:Name="VariableStackPanel" x:Load="{x:Bind local:EquationInputArea.ManageEditVariablesButtonLoaded(Variables.Count), Mode=OneWay}">
<Rectangle Height="1"
Margin="12"
Fill="{ThemeResource DividerBrush}"/>
<ListView x:Uid="VariableListView"
IsItemClickEnabled="False"
ItemTemplate="{StaticResource VariableDataTemplate}"
ItemsSource="{x:Bind Variables, Mode=OneWay}"
SelectionMode="None"
TabFocusNavigation="Local">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="Margin" Value="1,0,1,0"/>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemContainerTransitions>
<TransitionCollection/>
</ListView.ItemContainerTransitions>
<ListView.Transitions>
<TransitionCollection/>
</ListView.Transitions>
</ListView>
</StackPanel>
</StackPanel>
</ScrollViewer>
</UserControl>

View file

@ -0,0 +1,654 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Threading.Tasks;
using System.Diagnostics;
using CalculatorApp;
using CalculatorApp.Common;
using CalculatorApp.Common.Automation;
using GraphControl;
using CalculatorApp.ViewModel;
using CalculatorApp.Controls;
using Windows.Foundation;
using Windows.System;
using Windows.UI;
using Windows.UI.Core;
using Windows.UI.ViewManagement;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Input;
using Calculator.Utils;
namespace CalculatorApp
{
public sealed partial class EquationInputArea : System.ComponentModel.INotifyPropertyChanged
{
public EquationInputArea()
{
m_lastLineColorIndex = -1;
m_AvailableColors = new ObservableCollection<SolidColorBrush>();
m_accessibilitySettings = new AccessibilitySettings();
m_equationToFocus = null;
m_accessibilitySettings.HighContrastChanged += OnHighContrastChanged;
m_isHighContrast = m_accessibilitySettings.HighContrast;
m_uiSettings = new UISettings();
m_uiSettings.ColorValuesChanged += OnColorValuesChanged;
ReloadAvailableColors(m_accessibilitySettings.HighContrast, true);
InitializeComponent();
}
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
internal void RaisePropertyChanged(string p)
{
PropertyChanged?.Invoke(this, new System.ComponentModel.PropertyChangedEventArgs(p));
OnPropertyChanged(p);
}
public Windows.Foundation.Collections.IObservableVector<ViewModel.EquationViewModel> Equations
{
get { return m_Equations; }
set
{
if (m_Equations != value)
{
m_Equations = value;
RaisePropertyChanged("m_Equations");
}
}
}
private Windows.Foundation.Collections.IObservableVector<ViewModel.EquationViewModel> m_Equations;
public Windows.Foundation.Collections.IObservableVector<ViewModel.VariableViewModel> Variables
{
get { return m_Variables; }
set
{
if (m_Variables != value)
{
m_Variables = value;
RaisePropertyChanged("m_Variables");
}
}
}
private Windows.Foundation.Collections.IObservableVector<ViewModel.VariableViewModel> m_Variables;
public ObservableCollection<SolidColorBrush> AvailableColors
{
get { return m_AvailableColors; }
set
{
if (m_AvailableColors != value)
{
m_AvailableColors = value;
RaisePropertyChanged("m_AvailableColors");
}
}
}
private ObservableCollection<SolidColorBrush> m_AvailableColors;
public bool IsMatchAppTheme
{
get { return m_IsMatchAppTheme; }
set
{
if (m_IsMatchAppTheme != value)
{
m_IsMatchAppTheme = value;
RaisePropertyChanged("m_IsMatchAppTheme");
}
}
}
private bool m_IsMatchAppTheme;
public event System.EventHandler<ViewModel.EquationViewModel> KeyGraphFeaturesRequested;
public event System.EventHandler<CalculatorApp.Controls.MathRichEditBoxFormatRequest> EquationFormatRequested;
public static Visibility ManageEditVariablesButtonVisibility(uint numberOfVariables)
{
return numberOfVariables == 0 ? Visibility.Collapsed : Visibility.Visible;
}
public static bool ManageEditVariablesButtonLoaded(int numberOfVariables)
{
return numberOfVariables != 0;
}
public static string GetChevronIcon(bool isCollapsed)
{
return isCollapsed ? "\uE70E" : "\uE70D";
}
public static SolidColorBrush ToSolidColorBrush(Color color)
{
return new SolidColorBrush(color);
}
public static SolidColorBrush GetForegroundColor(Color lineColor)
{
return Utilities.GetContrastColor(lineColor);
}
public void FocusEquationTextBox(EquationViewModel equation)
{
int index = Equations.IndexOf(equation);
if (index < 0)
{
return;
}
var container = (UIElement)EquationInputList.ContainerFromIndex(index);
if (container != null)
{
container.StartBringIntoView();
var equationInput = VisualTree.FindDescendantByName(container, "EquationInputButton");
if (equationInput == null)
{
return;
}
var equationTextBox = equationInput as EquationTextBox;
if (equationTextBox != null)
{
equationTextBox.FocusTextBox();
}
}
}
private void OnPropertyChanged(string propertyName)
{
if (propertyName == EquationsPropertyName)
{
OnEquationsPropertyChanged();
}
else if (propertyName == IsMatchAppThemePropertyName)
{
ReloadAvailableColors(m_accessibilitySettings.HighContrast, false);
}
}
private void OnEquationsPropertyChanged()
{
if (Equations != null && Equations.Count == 0)
{
AddNewEquation();
}
}
private void AddNewEquation()
{
if (Equations.Count > 0)
{
Equations[Equations.Count - 1].IsLastItemInList = false;
}
// Cap equations at 14
if (Equations.Count >= maxEquationSize)
{
return;
}
int colorIndex;
if (m_accessibilitySettings.HighContrast)
{
m_lastLineColorIndex = (m_lastLineColorIndex + 1) % AvailableColors.Count;
colorIndex = m_lastLineColorIndex;
}
else
{
bool[] colorAssignmentUsed = new bool[colorCount];
foreach (var equation in Equations)
{
colorAssignmentUsed[equation.LineColorIndex] = true;
}
colorIndex = 0;
// If for some reason all of the values in colorAssignmentUsed are true, the check for colorIndex < colorCount - 1 will
// set it to the last color in the list
while (colorIndex < colorCount - 1 && colorAssignmentUsed[colorAssignmentMapping[colorIndex]])
{
colorIndex++;
}
colorIndex = colorAssignmentMapping[colorIndex];
}
var eq = new EquationViewModel(new Equation(), ++m_lastFunctionLabelIndex, AvailableColors[colorIndex].Color, colorIndex);
eq.IsLastItemInList = true;
m_equationToFocus = eq;
Equations.Add(eq);
}
private void EquationTextBox_GotFocus(object sender, RoutedEventArgs e)
{
var eq = GetViewModelFromEquationTextBox(sender);
if (eq != null)
{
eq.GraphEquation.IsSelected = true;
}
}
private void EquationTextBox_LostFocus(object sender, RoutedEventArgs e)
{
var eq = GetViewModelFromEquationTextBox(sender);
if (eq != null)
{
eq.GraphEquation.IsSelected = false;
}
}
private void EquationTextBox_Submitted(object sender, MathRichEditBoxSubmission submission)
{
var eq = GetViewModelFromEquationTextBox(sender);
if (eq == null)
{
return;
}
if (submission.Source == EquationSubmissionSource.ENTER_KEY
|| (submission.Source == EquationSubmissionSource.FOCUS_LOST && submission.HasTextChanged && eq.Expression != null
&& eq.Expression.Length > 0))
{
if (submission.Source == EquationSubmissionSource.ENTER_KEY)
{
eq.IsLineEnabled = true;
}
int index = Equations.IndexOf(eq);
if (index >= 0)
{
if (index == Equations.Count - 1)
{
// If it's the last equation of the list
AddNewEquation();
}
else
{
if (submission.Source == EquationSubmissionSource.ENTER_KEY)
{
var nextEquation = Equations[index + 1];
FocusEquationTextBox(nextEquation);
}
}
}
}
}
private void OnHighContrastChanged(AccessibilitySettings sender, object args)
{
ReloadAvailableColors(sender.HighContrast, true);
m_isHighContrast = sender.HighContrast;
}
private void ReloadAvailableColors(bool isHighContrast, bool reassignColors)
{
m_AvailableColors.Clear();
if (isHighContrast)
{
m_AvailableColors.Add((SolidColorBrush)Application.Current.Resources["EquationBrush1"]);
m_AvailableColors.Add((SolidColorBrush)Application.Current.Resources["EquationBrush2"]);
m_AvailableColors.Add((SolidColorBrush)Application.Current.Resources["EquationBrush3"]);
m_AvailableColors.Add((SolidColorBrush)Application.Current.Resources["EquationBrush4"]);
}
// If this is not high contrast, we have all 16 colors, otherwise we will restrict this to a subset of high contrast colors
else
{
object themeDictionaryName = "Light";
if (IsMatchAppTheme && Application.Current.RequestedTheme == ApplicationTheme.Dark)
{
themeDictionaryName = "Default";
}
var themeDictionary = (ResourceDictionary)Application.Current.Resources.ThemeDictionaries[themeDictionaryName];
m_AvailableColors.Add((SolidColorBrush)themeDictionary["EquationBrush1"]);
m_AvailableColors.Add((SolidColorBrush)themeDictionary["EquationBrush2"]);
m_AvailableColors.Add((SolidColorBrush)themeDictionary["EquationBrush3"]);
m_AvailableColors.Add((SolidColorBrush)themeDictionary["EquationBrush4"]);
m_AvailableColors.Add((SolidColorBrush)themeDictionary["EquationBrush5"]);
m_AvailableColors.Add((SolidColorBrush)themeDictionary["EquationBrush6"]);
m_AvailableColors.Add((SolidColorBrush)themeDictionary["EquationBrush7"]);
m_AvailableColors.Add((SolidColorBrush)themeDictionary["EquationBrush8"]);
m_AvailableColors.Add((SolidColorBrush)themeDictionary["EquationBrush9"]);
m_AvailableColors.Add((SolidColorBrush)themeDictionary["EquationBrush10"]);
m_AvailableColors.Add((SolidColorBrush)themeDictionary["EquationBrush11"]);
m_AvailableColors.Add((SolidColorBrush)themeDictionary["EquationBrush12"]);
m_AvailableColors.Add((SolidColorBrush)themeDictionary["EquationBrush13"]);
m_AvailableColors.Add((SolidColorBrush)themeDictionary["EquationBrush14"]);
}
// If there are no equations to reload, quit early
if (Equations == null || Equations.Count == 0)
{
return;
}
// Reassign colors for each equation
if (reassignColors)
{
m_lastLineColorIndex = -1;
}
foreach (var equationViewModel in Equations)
{
if (reassignColors)
{
m_lastLineColorIndex = (m_lastLineColorIndex + 1) % AvailableColors.Count;
equationViewModel.LineColorIndex = m_lastLineColorIndex;
}
equationViewModel.LineColor = AvailableColors[equationViewModel.LineColorIndex].Color;
}
}
private void OnColorValuesChanged(UISettings sender, object args)
{
WeakReference weakThis = new WeakReference(this);
_ = this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, new DispatchedHandler(() => {
var refThis = weakThis.Target as EquationInputArea;
if (refThis != null && refThis.m_isHighContrast == refThis.m_accessibilitySettings.HighContrast)
{
refThis.ReloadAvailableColors(false, false);
}
}));
}
private void EquationTextBox_RemoveButtonClicked(object sender, RoutedEventArgs e)
{
var eq = GetViewModelFromEquationTextBox(sender);
int index = Equations.IndexOf(eq);
if (index >= 0)
{
// Prevent removing the last equation
if (index == Equations.Count - 1)
{
return;
}
Equations.RemoveAt(index);
var narratorNotifier = new NarratorNotifier();
var announcement =
CalculatorAnnouncement.GetFunctionRemovedAnnouncement(AppResourceProvider.GetInstance().GetResourceString("FunctionRemovedAnnouncement"));
narratorNotifier.Announce(announcement);
int lastIndex = Equations.Count - 1;
if (Equations.Count <= 1)
{
m_lastFunctionLabelIndex = 1;
}
else
{
m_lastFunctionLabelIndex = Equations[lastIndex - 1].FunctionLabelIndex + 1;
}
Equations[lastIndex].FunctionLabelIndex = m_lastFunctionLabelIndex;
// Focus the next equation after the one we just removed. There should always be at least one ghost equation,
// but check to make sure that there is an equation we can focus in the index where we just removed an equation.
if (index < Equations.Count)
{
FocusEquationTextBox(Equations[index]);
}
}
}
private void EquationTextBox_KeyGraphFeaturesButtonClicked(object sender, RoutedEventArgs e)
{
KeyGraphFeaturesRequested(this, GetViewModelFromEquationTextBox(sender));
}
private void EquationTextBox_EquationButtonClicked(object sender, RoutedEventArgs e)
{
var eq = GetViewModelFromEquationTextBox(sender);
eq.IsLineEnabled = !eq.IsLineEnabled;
TraceLogger.GetInstance().LogShowHideButtonClicked(eq.IsLineEnabled ? false : true);
}
private void EquationTextBox_Loaded(object sender, RoutedEventArgs e)
{
var tb = (EquationTextBox)sender;
var colorChooser = (EquationStylePanelControl)tb.ColorChooserFlyout.Content;
colorChooser.AvailableColors = AvailableColors;
if (m_equationToFocus != null && tb.DataContext == m_equationToFocus)
{
var copyEquationToFocus = m_equationToFocus;
m_equationToFocus = null;
tb.FocusTextBox();
int index = Equations.IndexOf(copyEquationToFocus);
if (index >= 0)
{
var container = (UIElement)EquationInputList.ContainerFromIndex(index);
if (container != null)
{
container.StartBringIntoView();
}
}
}
}
private void EquationTextBox_DataContextChanged(FrameworkElement sender, DataContextChangedEventArgs args)
{
var tb = (EquationTextBox)sender;
if (!tb.IsLoaded)
{
return;
}
FocusEquationIfNecessary(tb);
}
private void FocusEquationIfNecessary(EquationTextBox textBox)
{
if (m_equationToFocus != null && textBox.DataContext == m_equationToFocus)
{
m_equationToFocus = null;
textBox.FocusTextBox();
int index = Equations.IndexOf(m_equationToFocus);
if (index >= 0)
{
var container = (UIElement)EquationInputList.ContainerFromIndex(index);
if (container != null)
{
container.StartBringIntoView();
}
}
}
}
private double validateDouble(string value, double defaultValue)
{
double resultValue = 0;
if (double.TryParse(value, out resultValue))
{
return resultValue;
}
return defaultValue;
}
private void TextBoxGotFocus(object sender, RoutedEventArgs e)
{
((TextBox)sender).SelectAll();
}
private void TextBoxLosingFocus(object sender, LosingFocusEventArgs e)
{
SubmitTextbox((TextBox)sender);
}
private void TextBoxKeyDown(object sender, KeyRoutedEventArgs e)
{
if (e.Key == VirtualKey.Enter)
{
SubmitTextbox((TextBox)sender);
}
}
private void SubmitTextbox(TextBox sender)
{
var variableViewModel = (VariableViewModel)sender.DataContext;
double val;
if (sender.Name == "ValueTextBox")
{
val = validateDouble(sender.Text, variableViewModel.Value);
variableViewModel.Value = val;
TraceLogger.GetInstance().LogVariableChanged("ValueTextBox", variableViewModel.Name);
}
else if (sender.Name == "MinTextBox")
{
val = validateDouble(sender.Text, variableViewModel.Min);
variableViewModel.Min = val;
TraceLogger.GetInstance().LogVariableSettingsChanged("MinTextBox");
}
else if (sender.Name == "MaxTextBox")
{
val = validateDouble(sender.Text, variableViewModel.Max);
variableViewModel.Max = val;
TraceLogger.GetInstance().LogVariableSettingsChanged("MaxTextBox");
}
else if (sender.Name == "StepTextBox")
{
val = validateDouble(sender.Text, variableViewModel.Step);
// Don't allow a value less than or equal to 0 as the step
if (val <= 0)
{
val = variableViewModel.Step;
}
variableViewModel.Step = val;
TraceLogger.GetInstance().LogVariableSettingsChanged("StepTextBox");
}
else
{
return;
}
// CSHARP_MIGRATION: TODO:
// Due to different culture, some regions use comma instead of dot as the decimal point
sender.Text = val.ToString("0", System.Globalization.CultureInfo.InvariantCulture);
}
private void VariableAreaClicked(object sender, RoutedEventArgs e)
{
ToggleVariableArea((VariableViewModel)((ToggleButton)sender).DataContext);
}
private void VariableAreaButtonTapped(object sender, TappedRoutedEventArgs e)
{
e.Handled = true;
}
private void VariableAreaTapped(object sender, TappedRoutedEventArgs e)
{
ToggleVariableArea((VariableViewModel)((FrameworkElement)sender).DataContext);
}
private void EquationTextBox_EquationFormatRequested(object sender, MathRichEditBoxFormatRequest e)
{
EquationFormatRequested(sender, e);
}
private void Slider_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
{
if (variableSliders == null)
{
variableSliders = new SortedDictionary<string, DispatcherTimerDelayer>();
}
var slider = (Slider)sender;
// The slider value updates when the user uses the TextBox to change the variable value.
// Check the focus state so that we don't trigger the event when the user used the textbox to change the variable value.
if (slider.FocusState == Windows.UI.Xaml.FocusState.Unfocused)
{
return;
}
var variableVM = (VariableViewModel)slider.DataContext;
if (variableVM == null)
{
return;
}
var name = variableVM.Name;
if (!variableSliders.ContainsKey(name))
{
TimeSpan timeSpan = new TimeSpan(10000000); // 1 tick = 100 nanoseconds, and 10000000 ticks = 1 second.
DispatcherTimerDelayer delayer = new DispatcherTimerDelayer(timeSpan);
delayer.Action += new EventHandler<object>((object s, object arg) => {
TraceLogger.GetInstance().LogVariableChanged("Slider", name);
variableSliders.Remove(name);
});
delayer.Start();
variableSliders.Add(name, delayer);
}
else
{
DispatcherTimerDelayer delayer = variableSliders[name];
delayer.ResetAndStart();
}
}
private EquationViewModel GetViewModelFromEquationTextBox(object sender)
{
var tb = (EquationTextBox)sender;
if (tb == null)
{
return null;
}
var eq = (EquationViewModel)tb.DataContext;
return eq;
}
private void ToggleVariableArea(VariableViewModel selectedVariableViewModel)
{
selectedVariableViewModel.SliderSettingsVisible = !selectedVariableViewModel.SliderSettingsVisible;
// Collapse all other slider settings that are open
foreach (var variableViewModel in Variables)
{
if (variableViewModel != selectedVariableViewModel)
{
variableViewModel.SliderSettingsVisible = false;
}
}
}
private const int maxEquationSize = 14;
private const int colorCount = 14;
private static readonly int[] colorAssignmentMapping = { 0, 3, 7, 10, 1, 4, 8, 11, 2, 5, 9, 12, 6, 13 };
private const string EquationsPropertyName = "Equations";
private const string IsMatchAppThemePropertyName = "IsMatchAppTheme";
private Windows.UI.ViewManagement.AccessibilitySettings m_accessibilitySettings;
private Windows.UI.ViewManagement.UISettings m_uiSettings;
private int m_lastLineColorIndex;
private int m_lastFunctionLabelIndex;
private bool m_isHighContrast;
private ViewModel.EquationViewModel m_equationToFocus;
private SortedDictionary<string, DispatcherTimerDelayer> variableSliders;
}
}

View file

@ -0,0 +1,783 @@
<UserControl x:Class="CalculatorApp.GraphingCalculator"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:contract7Present="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract,7)"
xmlns:contract8Present="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract, 8)"
xmlns:converters="using:CalculatorApp.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:graphControl="using:GraphControl"
xmlns:local="using:CalculatorApp"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
x:Name="Control"
DataContextChanged="GraphingCalculator_DataContextChanged"
mc:Ignorable="d">
<UserControl.Resources>
<ResourceDictionary>
<contract8Present:ThemeShadow x:Name="SharedShadow"/>
<Style x:Key="GraphToggleButtonStyle" TargetType="ToggleButton">
<Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseHighBrush}"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderBrush" Value="{ThemeResource AppControlForegroundTransparentRevealBorderBrush}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Margin" Value="-1"/>
<Setter Property="Padding" Value="8"/>
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="VerticalAlignment" Value="Stretch"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="FontSize" Value="{StaticResource CaptionFontSize}"/>
<Setter Property="FontWeight" Value="Normal"/>
</Style>
<Style x:Key="GraphButtonStyle" TargetType="Button">
<Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseHighBrush}"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderBrush" Value="{ThemeResource AppControlForegroundTransparentRevealBorderBrush}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Margin" Value="-1"/>
<Setter Property="Padding" Value="8"/>
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="VerticalAlignment" Value="Stretch"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="FontSize" Value="{StaticResource CaptionFontSize}"/>
<Setter Property="FontWeight" Value="Normal"/>
</Style>
<Style x:Key="GraphRepeatButtonStyle" TargetType="RepeatButton">
<Setter Property="Background" Value="{ThemeResource AppControlTransparentButtonBackgroundBrush}"/>
<Setter Property="Foreground" Value="{ThemeResource RepeatButtonForeground}"/>
<Setter Property="BorderBrush" Value="{ThemeResource AppControlForegroundTransparentRevealBorderBrush}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Margin" Value="-1"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="VerticalAlignment" Value="Stretch"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Delay" Value="500"/>
<Setter Property="Interval" Value="40"/>
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}"/>
<Setter Property="FontWeight" Value="Normal"/>
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}"/>
<Setter Property="UseSystemFocusVisuals" Value="{StaticResource UseSystemFocusVisuals}"/>
<Setter Property="FocusVisualMargin" Value="-3"/>
</Style>
<Style x:Key="GraphModeToggleSwitchStyle" TargetType="ToggleSwitch">
<Setter Property="Foreground" Value="{ThemeResource ToggleSwitchContentForeground}"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}"/>
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}"/>
<Setter Property="ManipulationMode" Value="System,TranslateX"/>
<Setter Property="UseSystemFocusVisuals" Value="{StaticResource UseSystemFocusVisuals}"/>
<Setter Property="FocusVisualMargin" Value="-6,-10"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleSwitch">
<Grid Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="OuterBorderStroke" Storyboard.TargetProperty="Stroke">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchStrokeOffPointerOver}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobBounds" Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchFillOffPointerOver}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchAreaGrid" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchContainerBackgroundPointerOver}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="OuterBorderStroke" Storyboard.TargetProperty="Stroke">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchStrokeOffPressed}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobBounds" Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchFillOffPressed}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchAreaGrid" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchContainerBackgroundPressed}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="OuterBorderStroke" Storyboard.TargetProperty="Stroke">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchStrokeOffDisabled}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobBounds" Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchFillOffDisabled}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchAreaGrid" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchContainerBackgroundDisabled}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="ToggleStates">
<VisualStateGroup.Transitions>
<VisualTransition x:Name="DraggingToOnTransition"
From="Dragging"
GeneratedDuration="0"
To="On">
<Storyboard>
<RepositionThemeAnimation FromHorizontalOffset="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.KnobCurrentToOnOffset}" TargetName="SwitchKnob"/>
</Storyboard>
</VisualTransition>
<VisualTransition x:Name="DraggingToOffTransition"
From="Dragging"
GeneratedDuration="0"
To="Off">
<Storyboard>
<RepositionThemeAnimation FromHorizontalOffset="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.KnobCurrentToOffOffset}" TargetName="SwitchKnob"/>
</Storyboard>
</VisualTransition>
<VisualTransition x:Name="OnToOffTransition"
From="On"
GeneratedDuration="0"
To="Off">
<Storyboard>
<RepositionThemeAnimation FromHorizontalOffset="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.KnobOnToOffOffset}" TargetName="SwitchKnob"/>
<DoubleAnimation Duration="0:0:0.2"
Storyboard.TargetName="IconsPanelOn"
Storyboard.TargetProperty="Opacity"
To="0"/>
<DoubleAnimation Duration="0:0:0.2"
Storyboard.TargetName="IconsPanelOff"
Storyboard.TargetProperty="Opacity"
To="1"/>
</Storyboard>
</VisualTransition>
<VisualTransition x:Name="OffToOnTransition"
From="Off"
GeneratedDuration="0"
To="On">
<Storyboard>
<RepositionThemeAnimation FromHorizontalOffset="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.KnobOffToOnOffset}" TargetName="SwitchKnob"/>
<DoubleAnimation Duration="0:0:0.2"
Storyboard.TargetName="IconsPanelOn"
Storyboard.TargetProperty="Opacity"
To="1"/>
<DoubleAnimation Duration="0:0:0.2"
Storyboard.TargetName="IconsPanelOff"
Storyboard.TargetProperty="Opacity"
To="0"/>
</Storyboard>
</VisualTransition>
</VisualStateGroup.Transitions>
<VisualState x:Name="Dragging"/>
<VisualState x:Name="Off"/>
<VisualState x:Name="On">
<VisualState.Setters>
<Setter Target="KnobTranslateTransform.X" Value="32"/>
<Setter Target="IconsPanelOn.Opacity" Value="1"/>
<Setter Target="IconsPanelOff.Opacity" Value="0"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="ContentStates">
<VisualState x:Name="OffContent"/>
<VisualState x:Name="OnContent"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid Height="30"
HorizontalAlignment="Left"
VerticalAlignment="Top">
<Grid x:Name="SwitchAreaGrid"
Margin="0,5"
Background="{ThemeResource ToggleSwitchContainerBackground}"
Control.IsTemplateFocusTarget="True"/>
<Rectangle x:Name="SwitchKnobBounds"
Fill="{ThemeResource SwitchToggleBackground}"
RadiusX="4"
RadiusY="4"/>
<Grid x:Name="SwitchKnob" HorizontalAlignment="Left">
<Rectangle Width="32"
Fill="{ThemeResource SystemAccentColor}"
RadiusX="4"
RadiusY="4"/>
<Grid.RenderTransform>
<TranslateTransform x:Name="KnobTranslateTransform"/>
</Grid.RenderTransform>
</Grid>
<Rectangle x:Name="OuterBorderStroke"
Stroke="{ThemeResource SystemAccentColor}"
StrokeThickness="1"
IsHitTestVisible="False"
RadiusX="4"
RadiusY="4"/>
<StackPanel x:Name="IconsPanelOff"
Margin="8,0"
Orientation="Horizontal">
<FontIcon x:Name="GraphIcon"
Margin="0,0,22,0"
VerticalAlignment="Center"
Foreground="White"
FontFamily="{StaticResource CalculatorFontFamily}"
FontSize="14"
Glyph="&#xF770;"/>
<Grid Margin="-2,0,2,0"
VerticalAlignment="Center"
FlowDirection="LeftToRight">
<FontIcon x:Name="EquationsIcon"
VerticalAlignment="Center"
FontFamily="{StaticResource CalculatorFontFamily}"
FontSize="12"
Glyph="&#xF893;"/>
<TextBlock x:Name="EquationsIconX"
Margin="0,8,-1,0"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
FontSize="10"
FontWeight="Light"
Text="x"/>
</Grid>
</StackPanel>
<StackPanel x:Name="IconsPanelOn"
Margin="8,0"
Opacity="0"
Orientation="Horizontal">
<FontIcon Margin="0,0,22,0"
VerticalAlignment="Center"
FontFamily="{StaticResource CalculatorFontFamily}"
FontSize="14"
Glyph="&#xF770;"/>
<Grid Margin="-2,0,2,0" VerticalAlignment="Center">
<FontIcon VerticalAlignment="Center"
Foreground="White"
FontFamily="{StaticResource CalculatorFontFamily}"
FontSize="12"
Glyph="&#xF893;"/>
<TextBlock Margin="0,8,-1,0"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Foreground="White"
FontSize="10"
FontWeight="Light"
Text="x"/>
</Grid>
</StackPanel>
<Thumb x:Name="SwitchThumb" AutomationProperties.AccessibilityView="Raw">
<Thumb.Template>
<ControlTemplate TargetType="Thumb">
<Rectangle Fill="Transparent"/>
</ControlTemplate>
</Thumb.Template>
</Thumb>
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Name="GraphViewToggleButtonStyle"
BasedOn="{StaticResource GraphToggleButtonStyle}"
TargetType="ToggleButton">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<ContentPresenter x:Name="ContentPresenter">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal">
<Storyboard/>
</VisualState>
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonBackgroundPointerOver}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonBorderBrushPointerOver}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonForegroundPointerOver}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonBackgroundPressed}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonBorderBrushPressed}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonForegroundPressed}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Checked"/>
<VisualState x:Name="CheckedPointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonBackgroundPointerOver}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonBorderBrushPointerOver}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonForegroundPointerOver}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="CheckedPressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonBackgroundPressed}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonBorderBrushPressed}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonForegroundPressed}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</ContentPresenter>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Graph Theme Colors -->
<Color x:Key="LightThemeAxisColor">#000000</Color>
<Color x:Key="LightThemeGraphBackgroundColor">#FFFFFF</Color>
<Color x:Key="LightThemeGridLinesColor">#C6C6C6</Color>
<Color x:Key="DarkThemeAxisColor">#FFFFFF</Color>
<Color x:Key="DarkThemeGraphBackgroundColor">#1F1F1F</Color>
<Color x:Key="DarkThemeGridLinesColor">#4F4F4F</Color>
<converters:BooleanToVisibilityNegationConverter x:Name="BooleanToVisibilityNegationConverter"/>
<converters:BooleanNegationConverter x:Name="BooleanNegationConverter"/>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Default">
<Style x:Key="ThemedSwitchModeToggleButtonStyle"
BasedOn="{StaticResource SwitchModeToggleButtonStyle}"
TargetType="ToggleButton"/>
<Style x:Key="GraphControlCommandPanel" TargetType="Border">
<Setter Property="Background" Value="#303030"/>
<Setter Property="BorderBrush" Value="#303030"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="CornerRadius" Value="4"/>
</Style>
<Style x:Key="ThemedGraphRepeatButtonStyle"
BasedOn="{StaticResource GraphRepeatButtonStyle}"
TargetType="RepeatButton">
<Setter Property="Foreground" Value="#FFFFFF"/>
</Style>
<Style x:Key="ThemedGraphButtonStyle"
BasedOn="{StaticResource GraphButtonStyle}"
TargetType="Button">
<Setter Property="Foreground" Value="#FFFFFF"/>
</Style>
<Style x:Key="ThemedGraphToggleButtonStyle"
BasedOn="{StaticResource GraphToggleButtonStyle}"
TargetType="ToggleButton">
<Setter Property="Foreground" Value="#FFFFFF"/>
</Style>
<Style x:Key="ThemedGraphViewToggleButtonStyle"
BasedOn="{StaticResource GraphViewToggleButtonStyle}"
TargetType="ToggleButton">
<Setter Property="Foreground" Value="#FFFFFF"/>
</Style>
<Style x:Key="GraphTooltipStyle" TargetType="Border">
<Setter Property="BorderBrush" Value="#e0e0e0"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="CornerRadius" Value="4"/>
<Setter Property="Background" Value="{ThemeResource SystemControlAcrylicElementBrush}"/>
</Style>
<SolidColorBrush x:Key="SwitchToggleBackground" Color="#40000000"/>
<Style x:Key="TracePointerPathStyle" TargetType="Path">
<Setter Property="Fill" Value="White"/>
<Setter Property="Stroke" Value="Black"/>
<Setter Property="StrokeThickness" Value="1"/>
</Style>
</ResourceDictionary>
<ResourceDictionary x:Key="Light">
<Style x:Key="ThemedSwitchModeToggleButtonStyle"
BasedOn="{StaticResource SwitchModeToggleButtonStyle}"
TargetType="ToggleButton"/>
<Style x:Key="GraphControlCommandPanel" TargetType="Border">
<Setter Property="Background" Value="{StaticResource SystemControlAcrylicElementBrush}"/>
<Setter Property="BorderBrush" Value="#e0e0e0"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="CornerRadius" Value="4"/>
</Style>
<Style x:Key="ThemedGraphRepeatButtonStyle"
BasedOn="{StaticResource GraphRepeatButtonStyle}"
TargetType="RepeatButton"/>
<Style x:Key="ThemedGraphButtonStyle"
BasedOn="{StaticResource GraphButtonStyle}"
TargetType="Button"/>
<Style x:Key="ThemedGraphToggleButtonStyle"
BasedOn="{StaticResource GraphToggleButtonStyle}"
TargetType="ToggleButton"/>
<Style x:Key="ThemedGraphViewToggleButtonStyle"
BasedOn="{StaticResource GraphViewToggleButtonStyle}"
TargetType="ToggleButton"/>
<Style x:Key="GraphTooltipStyle" TargetType="Border">
<Setter Property="Background" Value="{ThemeResource SystemControlAcrylicElementBrush}"/>
<Setter Property="BorderBrush" Value="#e0e0e0"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="CornerRadius" Value="4"/>
</Style>
<Style x:Key="TracePointerPathStyle" TargetType="Path">
<Setter Property="Fill" Value="White"/>
<Setter Property="Stroke" Value="Black"/>
<Setter Property="StrokeThickness" Value="1"/>
</Style>
<SolidColorBrush x:Key="SwitchToggleBackground" Color="#60ffffff"/>
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast">
<Style x:Key="ThemedSwitchModeToggleButtonStyle" TargetType="ToggleButton"/>
<Style x:Key="GraphControlCommandPanel" TargetType="Border"/>
<Style x:Key="ThemedGraphRepeatButtonStyle" TargetType="RepeatButton">
<Setter Property="Margin" Value="1"/>
</Style>
<Style x:Key="ThemedGraphButtonStyle" TargetType="Button">
<Setter Property="Margin" Value="1"/>
</Style>
<Style x:Key="ThemedGraphToggleButtonStyle" TargetType="ToggleButton">
<Setter Property="Margin" Value="1"/>
</Style>
<Style x:Key="ThemedGraphViewToggleButtonStyle" TargetType="ToggleButton">
<Setter Property="Margin" Value="1"/>
</Style>
<Style x:Key="GraphTooltipStyle" TargetType="Border">
<Setter Property="BorderBrush" Value="{ThemeResource ToolTipBorderBrush}"/>
<Setter Property="BorderThickness" Value="{ThemeResource ToolTipBorderThemeThickness}"/>
<Setter Property="Background" Value="{ThemeResource ToolTipBackground}"/>
</Style>
<SolidColorBrush x:Key="SwitchToggleBackground" Color="{ThemeResource SystemColorWindowColor}"/>
<Style x:Key="TracePointerPathStyle" TargetType="Path">
<Setter Property="Fill" Value="{ThemeResource SystemColorHighlightTextColor}"/>
<Setter Property="Stroke" Value="{ThemeResource SystemColorWindowTextColor}"/>
<Setter Property="StrokeThickness" Value="2"/>
</Style>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="{StaticResource HamburgerHeightGridLength}"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="1*"
MinWidth="300"
MaxWidth="420"/>
</Grid.ColumnDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup CurrentStateChanged="OnVisualStateChanged">
<VisualState x:Name="ColumnsState">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="800"/>
</VisualState.StateTriggers>
</VisualState>
<VisualState x:Name="SmallState">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="0"/>
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="Control.IsSmallState" Value="True"/>
<Setter Target="LeftGrid.(Grid.ColumnSpan)" Value="2"/>
<Setter Target="RightGrid.(Grid.ColumnSpan)" Value="2"/>
<Setter Target="RightGrid.(Grid.Column)" Value="0"/>
<Setter Target="SwitchModeToggleButton.Visibility" Value="Visible"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="GrapherThemes">
<VisualState x:Name="GrapherDarkTheme">
<VisualState.Setters>
<Setter Target="GraphingControl.AxesColor" Value="{StaticResource DarkThemeAxisColor}"/>
<Setter Target="GraphingControl.GraphBackground" Value="{StaticResource DarkThemeGraphBackgroundColor}"/>
<Setter Target="GraphingControl.GridLinesColor" Value="{StaticResource DarkThemeGridLinesColor}"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="GrapherLightTheme">
<VisualState.Setters>
<Setter Target="GraphingControl.AxesColor" Value="{StaticResource LightThemeAxisColor}"/>
<Setter Target="GraphingControl.GraphBackground" Value="{StaticResource LightThemeGraphBackgroundColor}"/>
<Setter Target="GraphingControl.GridLinesColor" Value="{StaticResource LightThemeGridLinesColor}"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="GrapherHighContrast">
<VisualState.Setters>
<Setter Target="GraphingControl.AxesColor" Value="{ThemeResource SystemColorWindowTextColor}"/>
<Setter Target="GraphingControl.GraphBackground" Value="{ThemeResource SystemColorWindowColor}"/>
<Setter Target="GraphingControl.GridLinesColor" Value="#FFFFFFFF"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<!-- Top panel -->
<Grid Grid.ColumnSpan="2">
<ToggleSwitch x:Name="SwitchModeToggleButton"
x:Uid="SwitchModeToggleButton"
Margin="0,0,12,2"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Style="{StaticResource GraphModeToggleSwitchStyle}"
AutomationProperties.AutomationId="SwitchModeToggleButton"
AutomationProperties.Name="{x:Bind local:GraphingCalculator.GetInfoForSwitchModeToggleButton(SwitchModeToggleButton.IsOn), Mode=OneWay}"
Toggled="SwitchModeToggleButton_Toggled"
ToolTipService.ToolTip="{x:Bind local:GraphingCalculator.GetInfoForSwitchModeToggleButton(SwitchModeToggleButton.IsOn), Mode=OneWay}"
Visibility="Collapsed"/>
</Grid>
<!-- Left portion of the screen -->
<Grid x:Name="LeftGrid"
Grid.Row="1"
Padding="0,4,0,0"
Visibility="{x:Bind local:GraphingCalculator.ShouldDisplayPanel(IsSmallState, SwitchModeToggleButton.IsOn, x:True), Mode=OneWay}">
<Grid.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Light">
<SolidColorBrush x:Key="ButtonBackgroundPointerOver" Color="#10000000"/>
<SolidColorBrush x:Key="ButtonBackgroundPressed" Color="#20000000"/>
<SolidColorBrush x:Key="RepeatButtonBackgroundPointerOver" Color="#10000000"/>
<SolidColorBrush x:Key="RepeatButtonBackgroundPressed" Color="#20000000"/>
<CornerRadius x:Key="TopButtonCornerRadius">4,4,0,0</CornerRadius>
<CornerRadius x:Key="BottomButtonCornerRadius">0,0,4,4</CornerRadius>
<CornerRadius x:Key="LeftButtonCornerRadius">4,0,0,4</CornerRadius>
<CornerRadius x:Key="RightButtonCornerRadius">0,4,4,0</CornerRadius>
</ResourceDictionary>
<ResourceDictionary x:Key="Dark">
<CornerRadius x:Key="TopButtonCornerRadius">4,4,0,0</CornerRadius>
<CornerRadius x:Key="BottomButtonCornerRadius">0,0,4,4</CornerRadius>
<CornerRadius x:Key="LeftButtonCornerRadius">4,0,0,4</CornerRadius>
<CornerRadius x:Key="RightButtonCornerRadius">0,4,4,0</CornerRadius>
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast">
<CornerRadius x:Key="TopButtonCornerRadius">0</CornerRadius>
<CornerRadius x:Key="BottomButtonCornerRadius">0</CornerRadius>
<CornerRadius x:Key="LeftButtonCornerRadius">0</CornerRadius>
<CornerRadius x:Key="RightButtonCornerRadius">0</CornerRadius>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</Grid.Resources>
<graphControl:Grapher Name="GraphingControl"
AutomationProperties.Name="{x:Bind GraphControlAutomationName, Mode=OneWay}"
ForceProportionalAxes="False"
GraphPlottedEvent="GraphingControl_GraphPlottedEvent"
GraphViewChangedEvent="GraphingControl_GraphViewChangedEvent"
IsKeepCurrentView="{x:Bind IsManualAdjustment, Mode=TwoWay}"
LosingFocus="GraphingControl_LosingFocus"
LostFocus="GraphingControl_LostFocus"
UseSystemFocusVisuals="True"
VariablesUpdated="GraphingControl_VariablesUpdated">
<graphControl:Grapher.ContextFlyout>
<MenuFlyout Placement="Bottom">
<MenuFlyoutItem x:Uid="GraphCopyMenuItem"
Click="GraphMenuFlyoutItem_Click"
Icon="Copy"/>
</MenuFlyout>
</graphControl:Grapher.ContextFlyout>
</graphControl:Grapher>
<Border MinHeight="36"
Margin="0,12,12,0"
HorizontalAlignment="Right"
VerticalAlignment="Top"
Style="{ThemeResource GraphControlCommandPanel}">
<StackPanel Orientation="Horizontal">
<ToggleButton x:Name="ActiveTracing"
MinWidth="40"
Margin="0,-1"
Style="{ThemeResource ThemedGraphToggleButtonStyle}"
contract7Present:CornerRadius="{ThemeResource LeftButtonCornerRadius}"
AutomationProperties.Name="{x:Bind local:GraphingCalculator.GetTracingLegend(GraphingControl.ActiveTracing), Mode=OneWay}"
Checked="ActiveTracing_Checked"
IsChecked="{x:Bind GraphingControl.ActiveTracing, Mode=TwoWay}"
Unchecked="ActiveTracing_Unchecked">
<ToolTipService.ToolTip>
<ToolTip Content="{x:Bind ActiveTracing.(AutomationProperties.Name), Mode=OneWay}"/>
</ToolTipService.ToolTip>
<FontIcon FontFamily="{StaticResource CalculatorFontFamily}"
FontSize="18"
Glyph="&#xE3B3;"/>
</ToggleButton>
<Button x:Uid="shareButton"
MinWidth="40"
Style="{ThemeResource ThemedGraphButtonStyle}"
Click="OnShareClick">
<FontIcon FontFamily="{StaticResource SymbolThemeFontFamily}"
FontSize="18"
Glyph="&#xE72D;"/>
</Button>
<Button x:Name="GraphSettingsButton"
x:Uid="graphSettingsButton"
MinWidth="40"
Style="{ThemeResource ThemedGraphButtonStyle}"
contract7Present:CornerRadius="{ThemeResource RightButtonCornerRadius}"
Click="GraphSettingsButton_Click">
<FontIcon FontFamily="{StaticResource CalculatorFontFamily}"
FontSize="18"
Glyph="&#xE3B4;"/>
</Button>
</StackPanel>
</Border>
<Canvas x:Name="TraceCanvas"
SizeChanged="Canvas_SizeChanged"
x:Load="False">
<Grid x:Name="TracePointer" Visibility="Collapsed">
<Border x:Name="CursorShadow"/>
<Path x:Name="CursorPath"
Width="18"
Height="18"
Style="{ThemeResource TracePointerPathStyle}"
Data="M0 0 l1371 1371 H538 l-538 538 Z"
Stretch="Uniform"/>
</Grid>
</Canvas>
<Border MinWidth="36"
Margin="0,0,12,12"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Style="{ThemeResource GraphControlCommandPanel}">
<StackPanel Orientation="Vertical">
<RepeatButton x:Name="ZoomInButton"
x:Uid="zoomInButton"
MinHeight="40"
HorizontalAlignment="Stretch"
Style="{ThemeResource ThemedGraphRepeatButtonStyle}"
FontFamily="{StaticResource SymbolThemeFontFamily}"
contract7Present:CornerRadius="{ThemeResource TopButtonCornerRadius}"
AutomationProperties.AutomationId="zoomInButton"
Command="{x:Bind ZoomInButtonPressed, Mode=OneTime}">
<FontIcon FontFamily="{StaticResource SymbolThemeFontFamily}"
FontSize="14"
Glyph="&#xE710;"/>
<RepeatButton.KeyboardAccelerators>
<KeyboardAccelerator Key="Add" Modifiers="Control"/>
</RepeatButton.KeyboardAccelerators>
</RepeatButton>
<RepeatButton x:Name="ZoomOutButton"
x:Uid="zoomOutButton"
MinHeight="40"
HorizontalAlignment="Stretch"
Style="{ThemeResource ThemedGraphRepeatButtonStyle}"
FontFamily="{StaticResource SymbolThemeFontFamily}"
AutomationProperties.AutomationId="zoomOutButton"
Command="{x:Bind ZoomOutButtonPressed, Mode=OneTime}">
<FontIcon FontFamily="{StaticResource SymbolThemeFontFamily}"
FontSize="14"
Glyph="&#xE738;"/>
<RepeatButton.KeyboardAccelerators>
<KeyboardAccelerator Key="Subtract" Modifiers="Control"/>
</RepeatButton.KeyboardAccelerators>
</RepeatButton>
<ToggleButton x:Uid="graphViewButton"
MinWidth="40"
MinHeight="40"
Style="{ThemeResource ThemedGraphViewToggleButtonStyle}"
contract7Present:CornerRadius="{ThemeResource BottomButtonCornerRadius}"
AutomationProperties.AutomationId="graphViewButton"
Click="GraphViewButton_Click"
IsChecked="{x:Bind IsManualAdjustment, Mode=TwoWay}">
<ToggleButton.Content>
<Grid>
<FontIcon FontFamily="{StaticResource CalculatorFontFamily}"
FontSize="14"
Glyph="&#xE45E;"/>
<FontIcon FontFamily="{StaticResource CalculatorFontFamily}"
FontSize="14"
Glyph="&#xE45D;"
Visibility="{x:Bind IsManualAdjustment, Mode=OneWay, Converter={StaticResource BooleanToVisibilityNegationConverter}}"/>
</Grid>
</ToggleButton.Content>
<ToggleButton.KeyboardAccelerators>
<KeyboardAccelerator Key="Number0" Modifiers="Control"/>
</ToggleButton.KeyboardAccelerators>
</ToggleButton>
</StackPanel>
</Border>
<Border x:Name="TraceValuePopup"
Padding="{ThemeResource ToolTipBorderThemePadding}"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Style="{ThemeResource GraphTooltipStyle}"
contract8Present:Shadow="{StaticResource SharedShadow}"
contract8Present:Translation="0,0,32"
IsHitTestVisible="False"
SizeChanged="TraceValuePopup_SizeChanged"
Visibility="Collapsed">
<Border.RenderTransform>
<TranslateTransform x:Name="TraceValuePopupTransform"/>
</Border.RenderTransform>
<TextBlock x:Name="TraceValue"
Foreground="{ThemeResource ToolTipForeground}"
FontSize="{ThemeResource ToolTipContentThemeFontSize}"
AutomationProperties.LiveSetting="Polite"/>
</Border>
</Grid>
<!-- Right portion of the screen -->
<Grid x:Name="RightGrid"
Grid.Row="1"
Grid.RowSpan="2"
Grid.Column="1"
Visibility="{x:Bind local:GraphingCalculator.ShouldDisplayPanel(IsSmallState, SwitchModeToggleButton.IsOn, x:False), Mode=OneWay}">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="2.2*" MaxHeight="400"/>
</Grid.RowDefinitions>
<!-- Ideally the KeyGraphFeaturesPanel should be a frame so that navigation to and from the panel could be handled nicely -->
<local:KeyGraphFeaturesPanel x:Name="KeyGraphFeaturesControl"
Grid.RowSpan="2"
Margin="0,4,0,0"
KeyGraphFeaturesClosed="OnKeyGraphFeaturesClosed"
ViewModel="{x:Bind ViewModel.SelectedEquation, Mode=OneWay}"
Visibility="{x:Bind IsKeyGraphFeaturesVisible, Mode=OneWay}"
x:Load="{x:Bind IsKeyGraphFeaturesVisible, Mode=OneWay}"/>
<!-- This control should be within a grid that limits the height to keep the sticky footer functionality from breaking -->
<local:EquationInputArea x:Name="EquationInputAreaControl"
Grid.ColumnSpan="2"
Margin="0,4,0,0"
EquationFormatRequested="OnEquationFormatRequested"
Equations="{x:Bind ViewModel.Equations}"
IsMatchAppTheme="{x:Bind IsMatchAppTheme, Mode=OneWay}"
KeyGraphFeaturesRequested="OnEquationKeyGraphFeaturesRequested"
Variables="{x:Bind ViewModel.Variables}"
Visibility="{x:Bind IsKeyGraphFeaturesVisible, Converter={StaticResource BooleanToVisibilityNegationConverter}, Mode=OneWay}"/>
<local:GraphingNumPad x:Name="GraphingNumPad"
Grid.Row="1"
Margin="2,0,2,2"
Visibility="{x:Bind IsKeyGraphFeaturesVisible, Converter={StaticResource BooleanToVisibilityNegationConverter}, Mode=OneWay}"/>
</Grid>
</Grid>
</UserControl>

View file

@ -0,0 +1,895 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Diagnostics;
using CalculatorApp;
using CalculatorApp.Common;
using CalculatorApp.Common.Automation;
using CalculatorApp.Controls;
using CalculatorApp.ViewModel;
//using CalcManager.NumberFormattingUtils;
using GraphControl;
//using Utils;
using Windows.ApplicationModel.DataTransfer;
using Windows.ApplicationModel.Resources;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.Storage;
using Windows.Storage.Streams;
using Windows.System;
using Windows.UI.Core;
using Windows.UI.Input;
using Windows.UI.ViewManagement;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Automation;
using Windows.UI.Xaml.Automation.Peers;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging;
using Windows.UI.Popups;
namespace CalculatorApp
{
public sealed partial class GraphingCalculator : System.ComponentModel.INotifyPropertyChanged
{
public GraphingCalculator()
{
InitializeComponent();
m_accessibilitySettings = new AccessibilitySettings();
DataTransferManager dataTransferManager = DataTransferManager.GetForCurrentView();
// Register the current control as a share source.
dataTransferManager.DataRequested += OnDataRequested;
// Request notifications when we should be showing the trace values
GraphingControl.TracingChangedEvent += OnShowTracePopupChanged;
// And when the actual trace value changes
GraphingControl.TracingValueChangedEvent += OnTracePointChanged;
// Update where the pointer value is (ie: where the user cursor from keyboard inputs moves the point to)
GraphingControl.PointerValueChangedEvent += OnPointerPointChanged;
GraphingControl.Loaded += OnGraphingCalculatorLoaded;
GraphingControl.UseCommaDecimalSeperator = LocalizationSettings.GetInstance().GetDecimalSeparator() == ',';
// OemMinus and OemAdd aren't declared in the VirtualKey enum, we can't add this accelerator XAML-side
var virtualKey = new KeyboardAccelerator();
virtualKey.Key = (VirtualKey)189; // OemPlus key
virtualKey.Modifiers = VirtualKeyModifiers.Control;
ZoomOutButton.KeyboardAccelerators.Add(virtualKey);
virtualKey = new KeyboardAccelerator();
virtualKey.Key = (VirtualKey)187; // OemAdd key
virtualKey.Modifiers = VirtualKeyModifiers.Control;
ZoomInButton.KeyboardAccelerators.Add(virtualKey);
if (Windows.Foundation.Metadata.ApiInformation.IsTypePresent("Windows.UI.Xaml.Media.ThemeShadow"))
{
SharedShadow.Receivers.Add(GraphingControl);
}
m_accessibilitySettings.HighContrastChanged += OnHighContrastChanged;
m_uiSettings = new UISettings();
m_uiSettings.ColorValuesChanged += OnColorValuesChanged;
ApplicationDataContainer localSettings = ApplicationData.Current.LocalSettings;
if (localSettings != null && localSettings.Values.ContainsKey(sc_IsGraphThemeMatchApp))
{
var isMatchAppLocalSetting = (bool)(localSettings.Values[sc_IsGraphThemeMatchApp]);
if (isMatchAppLocalSetting)
{
IsMatchAppTheme = true;
TraceLogger.GetInstance().LogGraphTheme("IsMatchAppTheme");
}
}
else
{
IsMatchAppTheme = false;
TraceLogger.GetInstance().LogGraphTheme("IsAlwaysLightTheme");
}
}
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
internal void RaisePropertyChanged(string p)
{
#if !UNIT_TESTS
PropertyChanged?.Invoke(this, new System.ComponentModel.PropertyChangedEventArgs(p));
#endif
}
public System.Windows.Input.ICommand ZoomOutButtonPressed
{
get
{
if (donotuse_ZoomOutButtonPressed == null)
{
donotuse_ZoomOutButtonPressed = new DelegateCommand<GraphingCalculator>(this, OnZoomOutCommand);
}
return donotuse_ZoomOutButtonPressed;
}
}
private System.Windows.Input.ICommand donotuse_ZoomOutButtonPressed;
public System.Windows.Input.ICommand ZoomInButtonPressed
{
get
{
if (donotuse_ZoomInButtonPressed == null)
{
donotuse_ZoomInButtonPressed = new DelegateCommand<GraphingCalculator>(this, OnZoomInCommand);
}
return donotuse_ZoomInButtonPressed;
}
}
private System.Windows.Input.ICommand donotuse_ZoomInButtonPressed;
public bool IsKeyGraphFeaturesVisible
{
get { return m_IsKeyGraphFeaturesVisible; }
private set
{
if (m_IsKeyGraphFeaturesVisible != value)
{
m_IsKeyGraphFeaturesVisible = value;
RaisePropertyChanged("IsKeyGraphFeaturesVisible");
}
}
}
private bool m_IsKeyGraphFeaturesVisible;
public bool IsSmallState
{
get { return (bool)GetValue(IsSmallStateProperty); }
set { SetValue(IsSmallStateProperty, value); }
}
// Using a DependencyProperty as the backing store for IsSmallState. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsSmallStateProperty =
DependencyProperty.Register(nameof(IsSmallState), typeof(bool), typeof(GraphingCalculator), new PropertyMetadata(default(bool)));
public string GraphControlAutomationName
{
get { return (string)GetValue(GraphControlAutomationNameProperty); }
set { SetValue(GraphControlAutomationNameProperty, value); }
}
// Using a DependencyProperty as the backing store for GraphControlAutomationName. This enables animation, styling, binding, etc...
public static readonly DependencyProperty GraphControlAutomationNameProperty =
DependencyProperty.Register(nameof(GraphControlAutomationName), typeof(string), typeof(GraphingCalculator), new PropertyMetadata(string.Empty));
public bool IsMatchAppTheme
{
get { return m_IsMatchAppTheme; }
private set
{
if (m_IsMatchAppTheme != value)
{
m_IsMatchAppTheme = value;
RaisePropertyChanged("IsMatchAppTheme");
}
}
}
private bool m_IsMatchAppTheme;
public bool IsManualAdjustment
{
get { return m_IsManualAdjustment; }
set
{
if (m_IsManualAdjustment != value)
{
m_IsManualAdjustment = value;
RaisePropertyChanged("IsManualAdjustment");
}
}
}
private bool m_IsManualAdjustment;
public CalculatorApp.ViewModel.GraphingCalculatorViewModel ViewModel
{
get { return m_viewModel; }
set
{
if (m_viewModel != value)
{
m_viewModel = value;
RaisePropertyChanged(sc_ViewModelPropertyName);
}
}
}
public static Visibility ShouldDisplayPanel(bool isSmallState, bool isEquationModeActivated, bool isGraphPanel)
{
return (!isSmallState || isEquationModeActivated ^ isGraphPanel) ? Visibility.Visible : Visibility.Collapsed;
}
public static string GetInfoForSwitchModeToggleButton(bool isChecked)
{
if (isChecked)
{
return AppResourceProvider.GetInstance().GetResourceString("GraphSwitchToGraphMode");
}
else
{
return AppResourceProvider.GetInstance().GetResourceString("GraphSwitchToEquationMode");
}
}
public static Windows.UI.Xaml.Visibility ManageEditVariablesButtonVisibility(uint numberOfVariables)
{
return numberOfVariables == 0 ? Visibility.Collapsed : Visibility.Visible;
}
public static String GetTracingLegend(bool? isTracing)
{
var resProvider = AppResourceProvider.GetInstance();
return isTracing != null && isTracing.Value ? resProvider.GetResourceString("disableTracingButtonToolTip")
: resProvider.GetResourceString("enableTracingButtonToolTip");
}
public void SetDefaultFocus()
{
if (IsSmallState)
{
SwitchModeToggleButton.Focus(FocusState.Programmatic);
}
else
{
EquationInputAreaControl.Focus(FocusState.Programmatic);
}
}
private void GraphingCalculator_DataContextChanged(FrameworkElement sender, DataContextChangedEventArgs args)
{
if (ViewModel != null)
{
ViewModel.Equations.VectorChanged -= OnEquationsVectorChanged;
ViewModel.VariableUpdated -= OnVariableChanged;
}
ViewModel = args.NewValue as GraphingCalculatorViewModel;
ViewModel.Equations.VectorChanged += OnEquationsVectorChanged;
ViewModel.VariableUpdated += OnVariableChanged;
UpdateGraphAutomationName();
}
private void OnVariableChanged(object sender, VariableChangedEventArgs args)
{
GraphingControl.SetVariable(args.variableName, args.newValue);
}
private void OnEquationsVectorChanged(IObservableVector<EquationViewModel> sender, IVectorChangedEventArgs e)
{
// If an item is already added to the graph, changing it should automatically trigger a graph update
if (e.CollectionChange == CollectionChange.ItemChanged)
{
return;
}
// Do not plot the graph if we are removing an empty equation, just remove it
if (e.CollectionChange == CollectionChange.ItemRemoved)
{
var itemToRemove = GraphingControl.Equations[(int)e.Index];
if (string.IsNullOrEmpty(itemToRemove.Expression))
{
GraphingControl.Equations.RemoveAt((int)e.Index);
if (GraphingControl.Equations.Count == 1 && string.IsNullOrEmpty(GraphingControl.Equations[0].Expression))
{
IsManualAdjustment = false;
}
return;
}
}
// Do not plot the graph if we are adding an empty equation, just add it
if (e.CollectionChange == CollectionChange.ItemInserted)
{
var itemToAdd = sender[(int)e.Index];
if (string.IsNullOrEmpty(itemToAdd.Expression))
{
GraphingControl.Equations.Add(itemToAdd.GraphEquation);
return;
}
}
// We are either adding or removing a valid equation, or resetting the collection. We will need to plot the graph
GraphingControl.Equations.Clear();
foreach (var equationViewModel in ViewModel.Equations)
{
GraphingControl.Equations.Add(equationViewModel.GraphEquation);
}
GraphingControl.PlotGraph(false);
}
private void OnZoomInCommand(object parameter)
{
GraphingControl.ZoomFromCenter(zoomInScale);
TraceLogger.GetInstance().LogGraphButtonClicked(GraphButton.ZoomIn, GraphButtonValue.None);
}
private void OnZoomOutCommand(object parameter)
{
GraphingControl.ZoomFromCenter(zoomOutScale);
TraceLogger.GetInstance().LogGraphButtonClicked(GraphButton.ZoomOut, GraphButtonValue.None);
}
private void OnShareClick(object sender, RoutedEventArgs e)
{
// Ask the OS to start a share action.
try
{
DataTransferManager.ShowShareUI();
TraceLogger.GetInstance().LogGraphButtonClicked(GraphButton.Share, GraphButtonValue.None);
}
catch (System.Runtime.InteropServices.COMException ex)
{
// COMException and HResult, long RPC_E_SERVERCALL_RETRYLATER is out of range of int
// LogPlatformException is internal
long rpc_e_servercall_retrylater = 0x8001010A;
if (ex.HResult == unchecked(rpc_e_servercall_retrylater))
{
ShowShareError();
TraceLogger.GetInstance().LogPlatformException(ViewMode.Graphing, System.Reflection.MethodBase.GetCurrentMethod().Name, ex);
}
else
{
throw;
}
}
}
private void OnShowTracePopupChanged(bool newValue)
{
if ((TraceValuePopup.Visibility == Visibility.Visible) != newValue)
{
TraceValuePopup.Visibility = newValue ? Visibility.Visible : Visibility.Collapsed;
}
}
private void OnTracePointChanged(double xPointValue, double yPointValue)
{
double xAxisMin, xAxisMax, yAxisMin, yAxisMax;
GraphingControl.GetDisplayRanges(out xAxisMin, out xAxisMax, out yAxisMin, out yAxisMax);
TraceValue.Text = "(" + xPointValue.ToString("R") + ", " + yPointValue.ToString("N15") + ")";
var peer = FrameworkElementAutomationPeer.FromElement(TraceValue);
if (peer != null)
{
peer.RaiseAutomationEvent(AutomationEvents.LiveRegionChanged);
}
PositionGraphPopup();
}
private void OnPointerPointChanged(Point newPoint)
{
if (TracePointer != null)
{
// Move the pointer glyph to where it is supposed to be.
Canvas.SetLeft(TracePointer, newPoint.X);
Canvas.SetTop(TracePointer, newPoint.Y);
}
}
// When share is invoked (by the user or programmatically) the event handler we registered will be called to populate the data package with the
// data to be shared. We will request the current graph image from the grapher as a stream that will pass to the share request.
private void OnDataRequested(DataTransferManager sender, DataRequestedEventArgs args)
{
var resourceLoader = ResourceLoader.GetForCurrentView();
try
{
string rawHtml;
string equationHtml;
rawHtml = "<p><img src='graph.png' width='600' alt='" + resourceLoader.GetString("GraphImageAltText") + "'></p>";
var equations = ViewModel.Equations;
bool hasEquations = false;
if (equations.Count > 0)
{
equationHtml = "<span style=\"color: rgb(68, 114, 196); font-style: bold; font-size : 13pt;\">"
+ resourceLoader.GetString("EquationsShareHeader") + "</span>"
+ "<table cellpadding=\"0\" cellspacing=\"0\" >";
foreach (var equation in equations)
{
var expression = equation.Expression;
if (string.IsNullOrEmpty(expression))
{
continue;
}
var color = equation.LineColor;
hasEquations = true;
expression = GraphingControl.ConvertToLinear(expression);
string equationColorHtml;
equationColorHtml = "color:rgb(" + color.R.ToString() + "," + color.G.ToString() + "," + color.B.ToString() + ");";
equationHtml += "<tr style=\"margin: 0pt 0pt 0pt 0pt; padding: 0pt 0pt 0pt 0pt; \"><td><span style=\"font-size: 22pt; line-height: 0;"
+ equationColorHtml + "\">&#x25A0;</span></td><td><div style=\"margin: 4pt 0pt 0pt 6pt;\">"
+ Utilities.EscapeHtmlSpecialCharacters(expression) + "</div></td>";
}
equationHtml += "</table>";
if (hasEquations)
{
rawHtml += equationHtml;
}
}
var variables = ViewModel.Variables;
if (variables.Count > 0)
{
var localizedSeperator = LocalizationSettings.GetInstance().GetListSeparatorWinRT() + " ";
rawHtml += "<br><span style=\"color: rgb(68, 114, 196); font-style: bold; font-size: 13pt;\">"
+ resourceLoader.GetString("VariablesShareHeader")
+ "</span><br><div style=\"margin: 4pt 0pt 0pt 0pt;\">";
for (int i = 0; i < variables.Count; i++)
{
var name = variables[i].Name;
var value = variables[i].Value;
rawHtml += name + "=";
var formattedValue = value.ToString("R");
formattedValue = Utilities.TrimTrailingZeros(formattedValue);
rawHtml += formattedValue;
if (variables.Count - 1 != i)
{
rawHtml += localizedSeperator;
}
}
rawHtml += "</div>";
}
rawHtml += "<br><br>";
// Shortcut to the request data
var requestData = args.Request.Data;
DataPackage dataPackage = new DataPackage();
var html = HtmlFormatHelper.CreateHtmlFormat(rawHtml);
requestData.Properties.Title = resourceLoader.GetString("ShareActionTitle");
requestData.SetHtmlFormat(html);
var bitmapStream = GraphingControl.GetGraphBitmapStream();
requestData.ResourceMap.Add("graph.png", bitmapStream);
requestData.SetBitmap(bitmapStream);
// Set the thumbnail image (in case the share target can't handle HTML)
requestData.Properties.Thumbnail = bitmapStream;
}
catch (Exception ex)
{
ShowShareError();
TraceLogger.GetInstance().LogPlatformException(ViewMode.Graphing,
System.Reflection.MethodBase.GetCurrentMethod().Name, ex);
}
}
private void GraphingControl_LostFocus(object sender, RoutedEventArgs e)
{
// If the graph is losing focus while we are in active tracing we need to turn it off so we don't try to eat keys in other controls.
if (GraphingControl.ActiveTracing)
{
if (ActiveTracing.Equals(FocusManager.GetFocusedElement()) && ActiveTracing.IsPressed)
{
ActiveTracing.PointerCaptureLost += ActiveTracing_PointerCaptureLost;
}
else
{
GraphingControl.ActiveTracing = false;
OnShowTracePopupChanged(false);
}
}
}
private void GraphingControl_LosingFocus(UIElement sender, LosingFocusEventArgs args)
{
var newFocusElement = args.NewFocusedElement as FrameworkElement;
if (newFocusElement == null || newFocusElement.Name == null)
{
// Because clicking on the swap chain panel will try to move focus to a control that can't actually take focus
// we will get a null destination. So we are going to try and cancel that request.
// If the destination is not in our application we will also get a null destination but the cancel will fail so it doesn't hurt to try.
args.TryCancel();
}
}
private void GraphingControl_VariablesUpdated(object sender, object args)
{
m_viewModel.UpdateVariables(GraphingControl.Variables);
}
private void GraphingControl_GraphViewChangedEvent(object sender, GraphViewChangedReason reason)
{
if (reason == GraphViewChangedReason.Manipulation)
{
IsManualAdjustment = true;
}
else
{
IsManualAdjustment = false;
}
UpdateGraphAutomationName();
var announcement = CalculatorAnnouncement.GetGraphViewChangedAnnouncement(GraphControlAutomationName);
var peer = FrameworkElementAutomationPeer.FromElement(GraphingControl);
if (peer != null)
{
peer.RaiseNotificationEvent(announcement.Kind, announcement.Processing, announcement.Announcement, announcement.ActivityId);
}
}
private void GraphingControl_GraphPlottedEvent(object sender, RoutedEventArgs e)
{
UpdateGraphAutomationName();
}
private void OnEquationKeyGraphFeaturesRequested(object sender, EquationViewModel equationViewModel)
{
ViewModel.SetSelectedEquation(equationViewModel);
if (equationViewModel != null)
{
var keyGraphFeatureInfo = GraphingControl.AnalyzeEquation(equationViewModel.GraphEquation);
equationViewModel.PopulateKeyGraphFeatures(keyGraphFeatureInfo);
IsKeyGraphFeaturesVisible = true;
equationViewModel.GraphEquation.IsSelected = true;
}
}
private void OnKeyGraphFeaturesClosed(object sender, RoutedEventArgs e)
{
IsKeyGraphFeaturesVisible = false;
EquationInputAreaControl.FocusEquationTextBox(ViewModel.SelectedEquation);
}
private void TraceValuePopup_SizeChanged(object sender, SizeChangedEventArgs e)
{
PositionGraphPopup();
}
private void PositionGraphPopup()
{
if (GraphingControl.TraceLocation.X + 15 + TraceValuePopup.ActualWidth >= GraphingControl.ActualWidth)
{
TraceValuePopupTransform.X = (int)GraphingControl.TraceLocation.X - 15 - TraceValuePopup.ActualWidth;
}
else
{
TraceValuePopupTransform.X = (int)GraphingControl.TraceLocation.X + 15;
}
if (GraphingControl.TraceLocation.Y >= 30)
{
TraceValuePopupTransform.Y = (int)GraphingControl.TraceLocation.Y - 30;
}
else
{
TraceValuePopupTransform.Y = (int)GraphingControl.TraceLocation.Y;
}
}
private void ActiveTracing_Checked(object sender, RoutedEventArgs e)
{
if (!m_cursorShadowInitialized)
{
this.FindName("TraceCanvas");
// add shadow to the trace pointer
AddTracePointerShadow();
// hide the shadow in high contrast mode
CursorShadow.Visibility = m_accessibilitySettings.HighContrast ? Visibility.Collapsed : Visibility.Visible;
Canvas.SetLeft(TracePointer, TraceCanvas.ActualWidth / 2 + 40);
Canvas.SetTop(TracePointer, TraceCanvas.ActualHeight / 2 - 40);
m_cursorShadowInitialized = true;
}
_ = FocusManager.TryFocusAsync(GraphingControl, FocusState.Programmatic);
Window.Current.CoreWindow.KeyUp += ActiveTracing_KeyUp;
KeyboardShortcutManager.IgnoreEscape(false);
TracePointer.Visibility = Visibility.Visible;
TraceLogger.GetInstance().LogGraphButtonClicked(GraphButton.ActiveTracingChecked, GraphButtonValue.None);
}
private void ActiveTracing_Unchecked(object sender, RoutedEventArgs e)
{
ActiveTracing.PointerCaptureLost -= ActiveTracing_PointerCaptureLost;
Window.Current.CoreWindow.KeyUp -= ActiveTracing_KeyUp;
KeyboardShortcutManager.HonorEscape();
TracePointer.Visibility = Visibility.Collapsed;
TraceLogger.GetInstance().LogGraphButtonClicked(GraphButton.ActiveTracingUnchecked, GraphButtonValue.None);
}
private void ActiveTracing_KeyUp(CoreWindow sender, KeyEventArgs args)
{
if (args.VirtualKey == VirtualKey.Escape)
{
GraphingControl.ActiveTracing = false;
ActiveTracing.Focus(FocusState.Programmatic);
args.Handled = true;
}
}
private void ActiveTracing_PointerCaptureLost(object sender, PointerRoutedEventArgs e)
{
ActiveTracing.PointerCaptureLost -= ActiveTracing_PointerCaptureLost;
if (GraphingControl.ActiveTracing)
{
GraphingControl.ActiveTracing = false;
OnShowTracePopupChanged(false);
}
}
private void GraphSettingsButton_Click(object sender, RoutedEventArgs e)
{
DisplayGraphSettings();
TraceLogger.GetInstance().LogGraphButtonClicked(GraphButton.GraphSettings, GraphButtonValue.None);
}
private void SwitchModeToggleButton_Toggled(object sender, RoutedEventArgs e)
{
var narratorNotifier = new NarratorNotifier();
String announcementText;
if (SwitchModeToggleButton.IsOn)
{
announcementText = AppResourceProvider.GetInstance().GetResourceString("GraphSwitchedToEquationModeAnnouncement");
}
else
{
announcementText = AppResourceProvider.GetInstance().GetResourceString("GraphSwitchedToGraphModeAnnouncement");
}
var announcement = CalculatorAnnouncement.GetGraphModeChangedAnnouncement(announcementText);
narratorNotifier.Announce(announcement);
}
private void DisplayGraphSettings()
{
if (m_graphSettings == null)
{
m_graphSettings = new GraphingSettings();
m_graphSettings.GraphThemeSettingChanged += OnGraphThemeSettingChanged;
}
if (m_graphFlyout == null)
{
m_graphFlyout = new Flyout();
m_graphFlyout.Content = m_graphSettings;
}
m_graphSettings.SetGrapher(this.GraphingControl);
m_graphSettings.IsMatchAppTheme = IsMatchAppTheme;
var options = new FlyoutShowOptions();
options.Placement = FlyoutPlacementMode.BottomEdgeAlignedRight;
m_graphFlyout.ShowAt(GraphSettingsButton, options);
}
private void AddTracePointerShadow()
{
var compositor = Windows.UI.Xaml.Hosting.ElementCompositionPreview.GetElementVisual(CursorPath).Compositor;
var dropShadow = compositor.CreateDropShadow();
dropShadow.BlurRadius = 6;
dropShadow.Opacity = 0.33f;
dropShadow.Offset = new System.Numerics.Vector3(2, 2, 0);
dropShadow.Mask = CursorPath.GetAlphaMask();
var shadowSpriteVisual = compositor.CreateSpriteVisual();
shadowSpriteVisual.Size = new System.Numerics.Vector2(18, 18);
shadowSpriteVisual.Shadow = dropShadow;
Windows.UI.Xaml.Hosting.ElementCompositionPreview.SetElementChildVisual(CursorShadow, shadowSpriteVisual);
}
private void UpdateGraphAutomationName()
{
int numEquations = 0;
double xAxisMin, xAxisMax, yAxisMin, yAxisMax;
// Only count equations that are graphed
foreach (var equation in ViewModel.Equations)
{
if (equation.GraphEquation.IsValidated)
{
numEquations++;
}
}
GraphingControl.GetDisplayRanges(out xAxisMin, out xAxisMax, out yAxisMin, out yAxisMax);
GraphControlAutomationName = LocalizationStringUtil.GetLocalizedString(
AppResourceProvider.GetInstance().GetResourceString("graphAutomationName"),
xAxisMin.ToString(),
xAxisMax.ToString(),
yAxisMin.ToString(),
yAxisMax.ToString(),
numEquations.ToString());
}
private void OnColorValuesChanged(UISettings sender, object args)
{
WeakReference weakThis = new WeakReference(this);
_ = this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, new DispatchedHandler(() => {
GraphingCalculator refThis = weakThis.Target as GraphingCalculator;
if (refThis != null && IsMatchAppTheme)
{
refThis.UpdateGraphTheme();
}
}));
}
private void UpdateGraphTheme()
{
if (m_accessibilitySettings.HighContrast)
{
VisualStateManager.GoToState(this, "GrapherHighContrast", true);
return;
}
if (IsMatchAppTheme && Application.Current.RequestedTheme == ApplicationTheme.Dark)
{
VisualStateManager.GoToState(this, "GrapherDarkTheme", true);
}
else
{
VisualStateManager.GoToState(this, "GrapherLightTheme", true);
}
}
private void OnGraphThemeSettingChanged(object sender, bool isMatchAppTheme)
{
if (IsMatchAppTheme == isMatchAppTheme)
{
return;
}
IsMatchAppTheme = isMatchAppTheme;
WeakReference weakThis = new WeakReference(this);
_ = this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, new DispatchedHandler(() =>
{
var refThis = weakThis.Target as GraphingCalculator;
if (refThis != null)
{
refThis.UpdateGraphTheme();
}
}));
}
private const double zoomInScale = 1 / 1.0625;
private const double zoomOutScale = 1.0625;
private const string sc_ViewModelPropertyName = "ViewModel";
private const string sc_IsGraphThemeMatchApp = "IsGraphThemeMatchApp";
private CalculatorApp.ViewModel.GraphingCalculatorViewModel m_viewModel;
private Windows.UI.ViewManagement.AccessibilitySettings m_accessibilitySettings;
private bool m_cursorShadowInitialized;
private Windows.UI.ViewManagement.UISettings m_uiSettings;
private Windows.UI.Xaml.Controls.Flyout m_graphFlyout;
private CalculatorApp.GraphingSettings m_graphSettings;
private void Canvas_SizeChanged(object sender, SizeChangedEventArgs e)
{
// Initialize the pointer to the correct location to match initial value in GraphControl\DirectX\RenderMain
if (TracePointer != null)
{
Canvas.SetLeft(TracePointer, e.NewSize.Width / 2 + 40);
Canvas.SetTop(TracePointer, e.NewSize.Height / 2 - 40);
}
}
private void OnHighContrastChanged(AccessibilitySettings sender, object args)
{
if (CursorShadow != null)
{
CursorShadow.Visibility = sender.HighContrast ? Visibility.Collapsed : Visibility.Visible;
}
UpdateGraphTheme();
}
private void OnEquationFormatRequested(object sender, MathRichEditBoxFormatRequest e)
{
if (!string.IsNullOrEmpty(e.OriginalText))
{
e.FormattedText = GraphingControl.FormatMathML(e.OriginalText);
}
}
private void GraphMenuFlyoutItem_Click(object sender, RoutedEventArgs e)
{
var dataPackage = new DataPackage();
dataPackage.RequestedOperation = DataPackageOperation.Copy;
var bitmapStream = GraphingControl.GetGraphBitmapStream();
dataPackage.SetBitmap(bitmapStream);
Clipboard.SetContent(dataPackage);
}
private void OnVisualStateChanged(object sender, VisualStateChangedEventArgs e)
{
TraceLogger.GetInstance().LogVisualStateChanged(ViewMode.Graphing, e.NewState.Name, false);
}
private void GraphViewButton_Click(object sender, RoutedEventArgs e)
{
var narratorNotifier = new NarratorNotifier();
string announcementText;
if (IsManualAdjustment)
{
announcementText = AppResourceProvider.GetInstance().GetResourceString("GraphViewManualAdjustmentAnnouncement");
}
else
{
announcementText = AppResourceProvider.GetInstance().GetResourceString("GraphViewAutomaticBestFitAnnouncement");
announcementText += AppResourceProvider.GetInstance().GetResourceString("GridResetAnnouncement");
GraphingControl.ResetGrid();
}
var announcement = CalculatorAnnouncement.GetGraphViewBestFitChangedAnnouncement(announcementText);
narratorNotifier.Announce(announcement);
TraceLogger.GetInstance().LogGraphButtonClicked(
GraphButton.GraphView, IsManualAdjustment ? GraphButtonValue.ManualAdjustment : GraphButtonValue.AutomaticBestFit);
}
private void ShowShareError()
{
// Something went wrong, notify the user.
var resourceLoader = ResourceLoader.GetForCurrentView();
var errDialog = new ContentDialog();
errDialog.Content = resourceLoader.GetString("ShareActionErrorMessage");
errDialog.CloseButtonText = resourceLoader.GetString("ShareActionErrorOk");
_ = errDialog.ShowAsync();
}
private void OnGraphingCalculatorLoaded(object sender, RoutedEventArgs e)
{
GraphingControl.Loaded -= OnGraphingCalculatorLoaded;
// The control needs to be loaded, else the control will override GridLinesColor and ignore the value passed
UpdateGraphTheme();
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,283 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Diagnostics;
using CalculatorApp;
using CalculatorApp.Common;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
namespace CalculatorApp
{
[Windows.Foundation.Metadata.WebHostHidden]
public sealed partial class GraphingNumPad
{
public GraphingNumPad()
{
InitializeComponent();
DecimalSeparatorButton.Content = localizationSettings.GetDecimalSeparator();
Num0Button.Content = localizationSettings.GetDigitSymbolFromEnUsDigit('0');
Num1Button.Content = localizationSettings.GetDigitSymbolFromEnUsDigit('1');
Num2Button.Content = localizationSettings.GetDigitSymbolFromEnUsDigit('2');
Num3Button.Content = localizationSettings.GetDigitSymbolFromEnUsDigit('3');
Num4Button.Content = localizationSettings.GetDigitSymbolFromEnUsDigit('4');
Num5Button.Content = localizationSettings.GetDigitSymbolFromEnUsDigit('5');
Num6Button.Content = localizationSettings.GetDigitSymbolFromEnUsDigit('6');
Num7Button.Content = localizationSettings.GetDigitSymbolFromEnUsDigit('7');
Num8Button.Content = localizationSettings.GetDigitSymbolFromEnUsDigit('8');
Num9Button.Content = localizationSettings.GetDigitSymbolFromEnUsDigit('9');
}
private void ShiftButton_Check(object sender, RoutedEventArgs e)
{
SetOperatorRowVisibility();
}
private void ShiftButton_Uncheck(object sender, RoutedEventArgs e)
{
ShiftButton.IsChecked = false;
SetOperatorRowVisibility();
Button_Clicked(sender, null);
}
private void TrigFlyoutShift_Toggle(object sender, RoutedEventArgs e)
{
SetTrigRowVisibility();
}
private void TrigFlyoutHyp_Toggle(object sender, RoutedEventArgs e)
{
SetTrigRowVisibility();
}
private void FlyoutButton_Clicked(object sender, RoutedEventArgs e)
{
this.HypButton.IsChecked = false;
this.TrigShiftButton.IsChecked = false;
this.Trigflyout.Hide();
this.FuncFlyout.Hide();
this.InequalityFlyout.Hide();
Button_Clicked(sender, null);
}
private void ShiftButton_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
{
SetOperatorRowVisibility();
}
private void SetOperatorRowVisibility()
{
Visibility rowVis, invRowVis;
if (ShiftButton.IsChecked.Value)
{
rowVis = Visibility.Collapsed;
invRowVis = Visibility.Visible;
}
else
{
rowVis = Visibility.Visible;
invRowVis = Visibility.Collapsed;
}
Row1.Visibility = rowVis;
InvRow1.Visibility = invRowVis;
}
private void SetTrigRowVisibility()
{
bool isShiftChecked = TrigShiftButton.IsChecked.Value;
bool isHypeChecked = HypButton.IsChecked.Value;
InverseHyperbolicTrigFunctions.Visibility = Visibility.Collapsed;
InverseTrigFunctions.Visibility = Visibility.Collapsed;
HyperbolicTrigFunctions.Visibility = Visibility.Collapsed;
TrigFunctions.Visibility = Visibility.Collapsed;
if (isShiftChecked && isHypeChecked)
{
InverseHyperbolicTrigFunctions.Visibility = Visibility.Visible;
}
else if (isShiftChecked && !isHypeChecked)
{
InverseTrigFunctions.Visibility = Visibility.Visible;
}
else if (!isShiftChecked && isHypeChecked)
{
HyperbolicTrigFunctions.Visibility = Visibility.Visible;
}
else
{
TrigFunctions.Visibility = Visibility.Visible;
}
}
private void Button_Clicked(object sender, RoutedEventArgs e)
{
var mathRichEdit = GetActiveRichEdit();
var button = sender as CalculatorApp.Controls.CalculatorButton;
if (mathRichEdit != null && sender != null)
{
var id = button.ButtonId;
TraceLogger.GetInstance().UpdateButtonUsage(id, CalculatorApp.Common.ViewMode.Graphing);
Tuple<string, int, int> output = GraphingNumPad.GetButtonOutput(id);
mathRichEdit.InsertText(output.Item1, output.Item2, output.Item3);
}
}
private void SubmitButton_Clicked(object sender, RoutedEventArgs e)
{
var mathRichEdit = GetActiveRichEdit();
if (mathRichEdit != null)
{
mathRichEdit.SubmitEquation(CalculatorApp.Controls.EquationSubmissionSource.ENTER_KEY);
TraceLogger.GetInstance().UpdateButtonUsage(NumbersAndOperatorsEnum.Submit, CalculatorApp.Common.ViewMode.Graphing);
}
}
private void ClearButton_Clicked(object sender, RoutedEventArgs e)
{
var mathRichEdit = GetActiveRichEdit();
if (mathRichEdit != null)
{
string text;
mathRichEdit.TextDocument.GetText(Windows.UI.Text.TextGetOptions.NoHidden, out text);
if (!string.IsNullOrEmpty(text))
{
mathRichEdit.MathText = "<math xmlns=\"http://www.w3.org/1998/Math/MathML\"></math>";
mathRichEdit.SubmitEquation(CalculatorApp.Controls.EquationSubmissionSource.PROGRAMMATIC);
}
TraceLogger.GetInstance().UpdateButtonUsage(NumbersAndOperatorsEnum.Clear, CalculatorApp.Common.ViewMode.Graphing);
}
}
private void BackSpaceButton_Clicked(object sender, RoutedEventArgs e)
{
var mathRichEdit = GetActiveRichEdit();
if (mathRichEdit != null)
{
mathRichEdit.BackSpace();
TraceLogger.GetInstance().UpdateButtonUsage(NumbersAndOperatorsEnum.Backspace, CalculatorApp.Common.ViewMode.Graphing);
}
}
// To avoid focus moving when the space between buttons is clicked, handle click events that make it through the keypad.
private void GraphingNumPad_PointerPressed(object sender, PointerRoutedEventArgs e)
{
e.Handled = true;
}
private CalculatorApp.Controls.MathRichEditBox GetActiveRichEdit()
{
return FocusManager.GetFocusedElement() as Controls.MathRichEditBox;
}
// Adding event because the ShowMode property is ignored in xaml.
private void Flyout_Opening(object sender, object e)
{
var flyout = sender as Flyout;
if (flyout != null)
{
flyout.ShowMode = FlyoutShowMode.Transient;
}
}
private static readonly Dictionary<NumbersAndOperatorsEnum, Tuple<string, int, int>> buttonOutput = new Dictionary<NumbersAndOperatorsEnum, Tuple<string, int, int>>()
{
{ NumbersAndOperatorsEnum.Sin, Tuple.Create("sin()", 4, 0) },
{ NumbersAndOperatorsEnum.Cos, Tuple.Create("cos()", 4, 0) },
{ NumbersAndOperatorsEnum.Tan, Tuple.Create("tan()", 4, 0) },
{ NumbersAndOperatorsEnum.Sec, Tuple.Create("sec()", 4, 0) },
{ NumbersAndOperatorsEnum.Csc, Tuple.Create("csc()", 4, 0) },
{ NumbersAndOperatorsEnum.Cot, Tuple.Create("cot()", 4, 0) },
{ NumbersAndOperatorsEnum.InvSin, Tuple.Create("arcsin()", 7, 0) },
{ NumbersAndOperatorsEnum.InvCos, Tuple.Create("arccos()", 7, 0) },
{ NumbersAndOperatorsEnum.InvTan, Tuple.Create("arctan()", 7, 0) },
{ NumbersAndOperatorsEnum.InvSec, Tuple.Create("arcsec()", 7, 0) },
{ NumbersAndOperatorsEnum.InvCsc, Tuple.Create("arccsc()", 7, 0) },
{ NumbersAndOperatorsEnum.InvCot, Tuple.Create("arccot()", 7, 0) },
{ NumbersAndOperatorsEnum.Sinh, Tuple.Create("sinh()", 5, 0) },
{ NumbersAndOperatorsEnum.Cosh, Tuple.Create("cosh()", 5, 0) },
{ NumbersAndOperatorsEnum.Tanh, Tuple.Create("tanh()", 5, 0) },
{ NumbersAndOperatorsEnum.Sech, Tuple.Create("sech()", 5, 0) },
{ NumbersAndOperatorsEnum.Csch, Tuple.Create("csch()", 5, 0) },
{ NumbersAndOperatorsEnum.Coth, Tuple.Create("coth()", 5, 0) },
{ NumbersAndOperatorsEnum.InvSinh, Tuple.Create("arcsinh()", 8, 0) },
{ NumbersAndOperatorsEnum.InvCosh, Tuple.Create("arccosh()", 8, 0) },
{ NumbersAndOperatorsEnum.InvTanh, Tuple.Create("arctanh()", 8, 0) },
{ NumbersAndOperatorsEnum.InvSech, Tuple.Create("arcsech()", 8, 0) },
{ NumbersAndOperatorsEnum.InvCsch, Tuple.Create("arccsch()", 8, 0) },
{ NumbersAndOperatorsEnum.InvCoth, Tuple.Create("arccoth()", 8, 0) },
{ NumbersAndOperatorsEnum.Abs, Tuple.Create("abs()", 4, 0) },
{ NumbersAndOperatorsEnum.Floor, Tuple.Create("floor()", 6, 0) },
{ NumbersAndOperatorsEnum.Ceil, Tuple.Create("ceiling()", 8, 0) },
{ NumbersAndOperatorsEnum.Pi, Tuple.Create("\u03C0", 1, 0) },
{ NumbersAndOperatorsEnum.Euler, Tuple.Create("e", 1, 0) },
{ NumbersAndOperatorsEnum.XPower2, Tuple.Create("^2", 2, 0) },
{ NumbersAndOperatorsEnum.Cube, Tuple.Create("^3", 2, 0) },
{ NumbersAndOperatorsEnum.XPowerY, Tuple.Create("^", 1, 0) },
{ NumbersAndOperatorsEnum.TenPowerX, Tuple.Create("10^", 3, 0) },
{ NumbersAndOperatorsEnum.LogBase10, Tuple.Create("log()", 4, 0) },
{ NumbersAndOperatorsEnum.LogBaseE, Tuple.Create("ln()", 3, 0) },
{ NumbersAndOperatorsEnum.Sqrt, Tuple.Create("sqrt()", 5, 0) },
{ NumbersAndOperatorsEnum.CubeRoot, Tuple.Create("cbrt()", 5, 0) },
{ NumbersAndOperatorsEnum.YRootX, Tuple.Create("root(x" + LocalizationSettings.GetInstance().GetListSeparatorWinRT().TrimEnd('\0') + "n)", 7, 1) },
{ NumbersAndOperatorsEnum.TwoPowerX, Tuple.Create("2^", 2, 0) },
{ NumbersAndOperatorsEnum.LogBaseY, Tuple.Create("log(b" + LocalizationSettings.GetInstance().GetListSeparatorWinRT().TrimEnd('\0') + " x)", 4, 1) },
{ NumbersAndOperatorsEnum.EPowerX, Tuple.Create("e^", 4, 0) },
{ NumbersAndOperatorsEnum.X, Tuple.Create("x", 1, 0) },
{ NumbersAndOperatorsEnum.Y, Tuple.Create("y", 1, 0) },
{ NumbersAndOperatorsEnum.OpenParenthesis, Tuple.Create("(", 1, 0) },
{ NumbersAndOperatorsEnum.CloseParenthesis, Tuple.Create(")", 1, 0) },
{ NumbersAndOperatorsEnum.Equals, Tuple.Create("=", 1, 0) },
{ NumbersAndOperatorsEnum.Divide, Tuple.Create("/", 1, 0) },
{ NumbersAndOperatorsEnum.Multiply, Tuple.Create("*", 1, 0) },
{ NumbersAndOperatorsEnum.Subtract, Tuple.Create("-", 1, 0) },
{ NumbersAndOperatorsEnum.Add, Tuple.Create("+", 1, 0) },
{ NumbersAndOperatorsEnum.Invert, Tuple.Create("1/", 2, 0) },
{ NumbersAndOperatorsEnum.Negate, Tuple.Create("-", 1, 0) },
{ NumbersAndOperatorsEnum.GreaterThan, Tuple.Create(">", 1, 0) },
{ NumbersAndOperatorsEnum.GreaterThanOrEqualTo, Tuple.Create("\u2265", 1, 0) },
{ NumbersAndOperatorsEnum.LessThan, Tuple.Create("<", 1, 0) },
{ NumbersAndOperatorsEnum.LessThanOrEqualTo, Tuple.Create("\u2264", 1, 0) },
{ NumbersAndOperatorsEnum.Zero, Tuple.Create("0", 1, 0) },
{ NumbersAndOperatorsEnum.One, Tuple.Create("1", 1, 0) },
{ NumbersAndOperatorsEnum.Two, Tuple.Create("2", 1, 0) },
{ NumbersAndOperatorsEnum.Three, Tuple.Create("3", 1, 0) },
{ NumbersAndOperatorsEnum.Four, Tuple.Create("4", 1, 0) },
{ NumbersAndOperatorsEnum.Five, Tuple.Create("5", 1, 0) },
{ NumbersAndOperatorsEnum.Six, Tuple.Create("6", 1, 0) },
{ NumbersAndOperatorsEnum.Seven, Tuple.Create("7", 1, 0) },
{ NumbersAndOperatorsEnum.Eight, Tuple.Create("8", 1, 0) },
{ NumbersAndOperatorsEnum.Nine, Tuple.Create("9", 1, 0) },
{ NumbersAndOperatorsEnum.Decimal, Tuple.Create(LocalizationSettings.GetInstance().GetDecimalSeparatorStrWinRT().TrimEnd('\0'), 1, 0) },
};
private static Tuple<string, int, int> GetButtonOutput(NumbersAndOperatorsEnum id)
{
Tuple<string, int, int> output;
if (buttonOutput.TryGetValue(id, out output))
{
return output;
}
return null;
}
private static readonly LocalizationSettings localizationSettings = LocalizationSettings.GetInstance();
}
}

View file

@ -0,0 +1,245 @@
<UserControl x:Class="CalculatorApp.GraphingSettings"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:contract7Present="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract, 7)"
xmlns:converters="using:CalculatorApp.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:CalculatorApp"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
mc:Ignorable="d">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Default">
<SolidColorBrush x:Key="GraphSettingsErrorBackgroundBrush" Color="#33EB5757"/>
<SolidColorBrush x:Key="GraphSettingsErrorBorderBrush" Color="#FFEB5757"/>
</ResourceDictionary>
<ResourceDictionary x:Key="Light">
<SolidColorBrush x:Key="GraphSettingsErrorBackgroundBrush" Color="#33EB5757"/>
<SolidColorBrush x:Key="GraphSettingsErrorBorderBrush" Color="#FFEB5757"/>
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast">
<SolidColorBrush x:Key="GraphSettingsErrorBackgroundBrush" Color="{ThemeResource SystemColorButtonFaceColor}"/>
<SolidColorBrush x:Key="GraphSettingsErrorBorderBrush" Color="Red"/>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
<Style x:Key="TrigUnitsRadioButtonStyle" TargetType="RadioButton">
<Setter Property="MinHeight" Value="38"/>
<Setter Property="MinWidth" Value="90"/>
<Setter Property="Padding" Value="4,0"/>
<Setter Property="FocusVisualMargin" Value="0"/>
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="RadioButton">
<Grid Name="LayoutRoot"
Background="{ThemeResource ToggleButtonBackground}"
contract7Present:CornerRadius="{TemplateBinding CornerRadius}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="PointerOver">
<VisualState.Setters>
<Setter Target="LayoutRoot.Background" Value="{ThemeResource ToggleButtonBackgroundPointerOver}"/>
<Setter Target="AccessibilityBorder.BorderBrush" Value="{ThemeResource ToggleButtonBorderBrushPointerOver}"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Pressed">
<VisualState.Setters>
<Setter Target="LayoutRoot.Background" Value="{ThemeResource ToggleButtonBackgroundPressed}"/>
<Setter Target="AccessibilityBorder.BorderBrush" Value="{ThemeResource ToggleButtonBorderBrushPressed}"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="CheckStates">
<VisualState x:Name="Checked">
<VisualState.Setters>
<Setter Target="SelectedBackgroundRectangle.Opacity" Value="1"/>
<Setter Target="ContentPresenter.Foreground" Value="{ThemeResource ToggleButtonForegroundChecked}"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Unchecked"/>
<VisualState x:Name="Indeterminate"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border Name="AccessibilityBorder"
BorderBrush="{ThemeResource ToggleButtonBorderBrush}"
BorderThickness="1"
contract7Present:CornerRadius="{TemplateBinding CornerRadius}"/>
<Rectangle Name="SelectedBackgroundRectangle"
Fill="{ThemeResource ToggleButtonBackgroundChecked}"
Opacity="0"/>
<ContentPresenter Name="ContentPresenter"
Grid.Column="1"
Margin="{TemplateBinding Padding}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Foreground="{TemplateBinding Foreground}"
AutomationProperties.AccessibilityView="Raw"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
ContentTransitions="{TemplateBinding ContentTransitions}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="SubTitleTextBoxStyle" TargetType="TextBlock">
<Setter Property="FontSize" Value="16"/>
<Setter Property="FontWeight" Value="Medium"/>
</Style>
<Style x:Key="ErrorTextBoxStyle" TargetType="TextBox">
<Setter Property="BorderBrush" Value="{ThemeResource GraphSettingsErrorBorderBrush}"/>
<Setter Property="Background" Value="{ThemeResource GraphSettingsErrorBackgroundBrush}"/>
</Style>
<DataTemplate x:Key="XYTextBoxHeaderTemplate" x:DataType="x:String">
<TextBlock FontSize="14" Text="{x:Bind}"/>
</DataTemplate>
<converters:BooleanNegationConverter x:Key="BooleanNegationConverter"/>
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<StackPanel Margin="4,0,4,4">
<TextBlock x:Name="GraphOptionsHeading"
x:Uid="GraphOptionsHeading"
FontSize="20"
FontWeight="Medium"
AutomationProperties.HeadingLevel="Level1"/>
<Grid Margin="0,12,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="GridHeading"
x:Uid="GridHeading"
Style="{StaticResource SubTitleTextBoxStyle}"
AutomationProperties.HeadingLevel="Level2"/>
<HyperlinkButton x:Uid="ResetViewButton"
Grid.Column="1"
Click="ResetViewButton_Clicked"/>
</Grid>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="10"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBox x:Name="SettingsXMin"
x:Uid="GraphSettingsXMin"
MaxWidth="160"
Style="{x:Bind SelectTextBoxStyle(ViewModel.XError, ViewModel.XMinError), Mode=OneWay}"
contract7Present:CornerRadius="2"
HeaderTemplate="{StaticResource XYTextBoxHeaderTemplate}"
PreviewKeyDown="GridSettingsTextBox_PreviewKeyDown"
Text="{x:Bind ViewModel.XMin, Mode=TwoWay}"/>
<TextBox x:Name="SettingsXMax"
x:Uid="GraphSettingsXMax"
Grid.Column="2"
MaxWidth="160"
Style="{x:Bind SelectTextBoxStyle(ViewModel.XError, ViewModel.XMaxError), Mode=OneWay}"
contract7Present:CornerRadius="2"
HeaderTemplate="{StaticResource XYTextBoxHeaderTemplate}"
PreviewKeyDown="GridSettingsTextBox_PreviewKeyDown"
Text="{x:Bind ViewModel.XMax, Mode=TwoWay}"/>
<TextBox x:Name="SettingsYMin"
x:Uid="GraphSettingsYMin"
Grid.Row="2"
MaxWidth="160"
Style="{x:Bind SelectTextBoxStyle(ViewModel.YError, ViewModel.YMinError), Mode=OneWay}"
contract7Present:CornerRadius="2"
HeaderTemplate="{StaticResource XYTextBoxHeaderTemplate}"
PreviewKeyDown="GridSettingsTextBox_PreviewKeyDown"
Text="{x:Bind ViewModel.YMin, Mode=TwoWay}"/>
<TextBox x:Name="SettingsYMax"
x:Uid="GraphSettingsYMax"
Grid.Row="2"
Grid.Column="2"
MaxWidth="160"
Style="{x:Bind SelectTextBoxStyle(ViewModel.YError, ViewModel.YMaxError), Mode=OneWay}"
contract7Present:CornerRadius="2"
HeaderTemplate="{StaticResource XYTextBoxHeaderTemplate}"
PreviewKeyDown="GridSettingsTextBox_PreviewKeyDown"
Text="{x:Bind ViewModel.YMax, Mode=TwoWay}"/>
</Grid>
<TextBlock x:Name="UnitsHeading"
x:Uid="UnitsHeading"
Margin="0,16,0,6"
Style="{StaticResource SubTitleTextBoxStyle}"
AutomationProperties.HeadingLevel="Level2"/>
<StackPanel AutomationProperties.LabeledBy="{Binding ElementName=UnitsHeading}" Orientation="Horizontal">
<RadioButton x:Name="Radians"
x:Uid="TrigModeRadians"
Style="{StaticResource TrigUnitsRadioButtonStyle}"
contract7Present:CornerRadius="4,0,0,4"
IsChecked="{x:Bind ViewModel.TrigModeRadians, Mode=TwoWay}"/>
<RadioButton x:Name="Degrees"
x:Uid="TrigModeDegrees"
Margin="1,0"
Style="{StaticResource TrigUnitsRadioButtonStyle}"
IsChecked="{x:Bind ViewModel.TrigModeDegrees, Mode=TwoWay}"/>
<RadioButton x:Name="Gradians"
x:Uid="TrigModeGradians"
Style="{StaticResource TrigUnitsRadioButtonStyle}"
contract7Present:CornerRadius="0,4,4,0"
IsChecked="{x:Bind ViewModel.TrigModeGradians, Mode=TwoWay}"/>
</StackPanel>
<TextBlock x:Uid="LineThicknessBoxHeading"
Margin="0,16,0,6"
Style="{StaticResource SubTitleTextBoxStyle}"
AutomationProperties.HeadingLevel="Level2"/>
<ComboBox MinWidth="200"
HorizontalAlignment="Stretch"
SelectedItem="{x:Bind ViewModel.Graph.LineWidth, Mode=TwoWay}">
<ComboBox.Items>
<x:Double>1.0</x:Double>
<x:Double>2.0</x:Double>
<x:Double>3.0</x:Double>
<x:Double>4.0</x:Double>
</ComboBox.Items>
<ComboBox.ItemTemplate>
<DataTemplate x:DataType="x:Double">
<Grid x:Name="LineGrid"
Height="20"
MaxWidth="200"
AutomationProperties.Name="{x:Bind local:GraphingSettings.GetLineWidthAutomationName((x:Double))}">
<Line VerticalAlignment="Center"
Stroke="{ThemeResource AppControlPageTextBaseHighColorBrush}"
StrokeThickness="{x:Bind}"
X1="0"
X2="200"
Y1="4"
Y2="4"/>
</Grid>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<TextBlock x:Name="GraphThemeHeading"
x:Uid="GraphThemeHeading"
Margin="0,16,0,6"
Style="{StaticResource SubTitleTextBoxStyle}"
AutomationProperties.HeadingLevel="Level2"/>
<StackPanel AutomationProperties.LabeledBy="{Binding ElementName=GraphThemeHeading}">
<RadioButton x:Uid="AlwaysLightTheme" IsChecked="{x:Bind IsMatchAppTheme, Mode=TwoWay, Converter={StaticResource BooleanNegationConverter}}"/>
<RadioButton x:Uid="MatchAppTheme"
Margin="1,0"
IsChecked="{x:Bind IsMatchAppTheme, Mode=TwoWay}"/>
</StackPanel>
</StackPanel>
</Grid>
</UserControl>

View file

@ -0,0 +1,139 @@
//
// MyUserControl.xaml.h
// Declaration of the MyUserControl class
//
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Diagnostics;
//using Graphing;
using GraphControl;
using CalculatorApp;
using CalculatorApp.ViewModel;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.Storage;
using Windows.System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
namespace CalculatorApp
{
[Windows.Foundation.Metadata.WebHostHidden]
public sealed partial class GraphingSettings
{
public GraphingSettings()
{
m_ViewModel = new GraphingSettingsViewModel();
m_IsMatchAppTheme = false;
InitializeComponent();
}
public CalculatorApp.ViewModel.GraphingSettingsViewModel ViewModel
{
get { return m_ViewModel; }
set { m_ViewModel = value; }
}
public bool IsMatchAppTheme
{
get { return m_IsMatchAppTheme; }
set
{
if (m_IsMatchAppTheme == value)
{
return;
}
m_IsMatchAppTheme = value;
SetGraphTheme(m_IsMatchAppTheme);
}
}
public Style SelectTextBoxStyle(bool incorrectRange, bool error)
{
if ((incorrectRange || error) && this.Resources.ContainsKey("ErrorTextBoxStyle"))
{
return (Style)(this.Resources["ErrorTextBoxStyle"]);
}
else
{
return null;
}
}
public void SetGrapher(GraphControl.Grapher grapher)
{
m_ViewModel.SetGrapher(grapher);
}
public void RefreshRanges()
{
ViewModel.ResetView();
}
public static string GetLineWidthAutomationName(double width)
{
var resourceLoader = AppResourceProvider.GetInstance();
if (width == 1.0)
{
return resourceLoader.GetResourceString("SmallLineWidthAutomationName");
}
else if (width == 2.0)
{
return resourceLoader.GetResourceString("MediumLineWidthAutomationName");
}
else if (width == 3.0)
{
return resourceLoader.GetResourceString("LargeLineWidthAutomationName");
}
else
{
return resourceLoader.GetResourceString("ExtraLargeLineWidthAutomationName");
}
}
// Event sends the if the IsMatchAppTheme is selected
public event System.EventHandler<bool> GraphThemeSettingChanged;
private void GridSettingsTextBox_PreviewKeyDown(object sender, KeyRoutedEventArgs e)
{
if (e.Key == VirtualKey.Enter)
{
// CSHARP_MIGRATION: TODO:
// check if condition
if (FocusManager.TryMoveFocusAsync(FocusNavigationDirection.Next).Status != AsyncStatus.Completed)
{
IAsyncOperation<FocusMovementResult> result = FocusManager.TryMoveFocusAsync(FocusNavigationDirection.Previous);
}
e.Handled = true;
}
}
private void ResetViewButton_Clicked(object sender, RoutedEventArgs e)
{
ViewModel.ResetView();
}
private void SetGraphTheme(bool isMatchAppTheme)
{
string propertyName = isMatchAppTheme ? "IsMatchAppTheme" : "IsAlwaysLightTheme";
ApplicationDataContainer localSettings = ApplicationData.Current.LocalSettings;
localSettings.Values.Add("IsGraphThemeMatchApp", isMatchAppTheme);
GraphThemeSettingChanged?.Invoke(this, isMatchAppTheme);
TraceLogger.GetInstance().LogGraphSettingsChanged(GraphSettingsType.Theme, propertyName);
}
private bool m_IsMatchAppTheme;
private CalculatorApp.ViewModel.GraphingSettingsViewModel m_ViewModel;
};
}

View file

@ -0,0 +1,293 @@
<UserControl x:Class="CalculatorApp.KeyGraphFeaturesPanel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:contract7Present="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract,7)"
xmlns:controls="using:CalculatorApp.Controls"
xmlns:converters="using:CalculatorApp.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:CalculatorApp"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ts="using:CalculatorApp.TemplateSelectors"
xmlns:vm="using:CalculatorApp.ViewModel"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
mc:Ignorable="d">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Default">
<!-- Can't be #ffffff due to a bug in RichEditBox considering it as the default value -->
<!-- and replacing it by the system value (#000000) when dark theme is used -->
<SolidColorBrush x:Key="TitleMathRichEditBoxForegroundBrush" Color="#feffff"/>
<x:Double x:Key="EquationButtonOverlayPointerOverOpacity">0.3</x:Double>
<x:Double x:Key="EquationButtonOverlayPressedOpacity">0.5</x:Double>
<SolidColorBrush x:Key="EquationButtonOverlayBackgroundBrush" Color="White"/>
<Style x:Key="ThemedBackButtonStyle"
BasedOn="{StaticResource BackButtonStyle}"
TargetType="Button"/>
</ResourceDictionary>
<ResourceDictionary x:Key="Light">
<SolidColorBrush x:Key="TitleMathRichEditBoxForegroundBrush" Color="Black"/>
<x:Double x:Key="EquationButtonOverlayPointerOverOpacity">0.2</x:Double>
<x:Double x:Key="EquationButtonOverlayPressedOpacity">0.4</x:Double>
<SolidColorBrush x:Key="EquationButtonOverlayBackgroundBrush" Color="Black"/>
<Style x:Key="ThemedBackButtonStyle"
BasedOn="{StaticResource BackButtonStyle}"
TargetType="Button"/>
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast">
<SolidColorBrush x:Key="TitleMathRichEditBoxForegroundBrush" Color="{ThemeResource SystemColorWindowTextColor}"/>
<x:Double x:Key="EquationButtonOverlayPointerOverOpacity">0</x:Double>
<x:Double x:Key="EquationButtonOverlayPressedOpacity">0</x:Double>
<SolidColorBrush x:Key="EquationButtonOverlayBackgroundBrush" Color="Transparent"/>
<Style x:Key="ThemedBackButtonStyle" TargetType="Button"/>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
<!-- EquationButtonBackgroundBrush is only used in Dark and Light theme. -->
<!-- The x:Name property is required for High Contrast theme so the brush is indexed properly. -->
<SolidColorBrush x:Key="EquationButtonBackgroundBrush"
x:Name="EquationButtonBackgroundBrush"
Color="{x:Bind ViewModel.LineColor, Mode=OneWay}"/>
<Style x:Key="BackButtonStyle" TargetType="Button">
<Setter Property="Background" Value="{ThemeResource EquationButtonBackgroundBrush}"/>
<Setter Property="Foreground" Value="{ThemeResource SystemChromeWhiteColor}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid x:Name="RootGrid"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
CornerRadius="{TemplateBinding CornerRadius}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal">
<VisualState.Setters>
<Setter Target="Overlay.Opacity" Value="0.0"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="PointerOver">
<VisualState.Setters>
<Setter Target="Overlay.Opacity" Value="{StaticResource EquationButtonOverlayPointerOverOpacity}"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Pressed">
<VisualState.Setters>
<Setter Target="Overlay.Opacity" Value="{StaticResource EquationButtonOverlayPressedOpacity}"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Rectangle x:Name="Overlay"
Fill="{ThemeResource EquationButtonOverlayBackgroundBrush}"
Opacity="0"
IsHitTestVisible="False"/>
<ContentPresenter x:Name="ContentPresenter"
Padding="{TemplateBinding Padding}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
AutomationProperties.AccessibilityView="Raw"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
ContentTransitions="{TemplateBinding ContentTransitions}"
CornerRadius="{TemplateBinding CornerRadius}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="KGF_RichEditBoxStyle" TargetType="controls:MathRichEditBox">
<Setter Property="FontSize" Value="14"/>
<Setter Property="IsReadOnly" Value="True"/>
<Setter Property="UseSystemFocusVisuals" Value="True"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="Typography.StylisticSet20" Value="True"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="controls:MathRichEditBox">
<ScrollViewer x:Name="ContentElement"
Grid.Row="1"
Margin="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}"
VerticalAlignment="Center"
AutomationProperties.AccessibilityView="Raw"
HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}"
IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}"
IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}"
IsTabStop="False"
IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}"
VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"
VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}"
ZoomMode="Disabled"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Name="KGF_TitleTextBlockStyle" TargetType="TextBlock">
<Setter Property="FontWeight" Value="Medium"/>
<Setter Property="FontSize" Value="16"/>
<Setter Property="TextWrapping" Value="WrapWholeWords"/>
<Setter Property="AutomationProperties.HeadingLevel" Value="Level2"/>
</Style>
<Style x:Name="KGF_TextBlockStyle" TargetType="TextBlock">
<Setter Property="FontSize" Value="14"/>
<Setter Property="IsTextSelectionEnabled" Value="True"/>
<Setter Property="TextWrapping" Value="WrapWholeWords"/>
</Style>
<Style x:Name="KGF_ListViewItemContainerStyle" TargetType="ListViewItem">
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="AutomationProperties.AccessibilityView" Value="Raw"/>
<Setter Property="Padding" Value="0,10"/>
</Style>
<DataTemplate x:Key="KGFRichEditDataTemplate" x:DataType="vm:KeyGraphFeaturesItem">
<StackPanel>
<TextBlock x:Name="TitleTextBlock"
Style="{StaticResource KGF_TitleTextBlockStyle}"
Text="{x:Bind Title, Mode=OneWay}"/>
<ItemsControl ItemsSource="{x:Bind DisplayItems, Mode=OneWay}" UseSystemFocusVisuals="True">
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="x:String">
<controls:MathRichEditBox Style="{StaticResource KGF_RichEditBoxStyle}" MathText="{x:Bind}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="KGFGridDataTemplate" x:DataType="vm:KeyGraphFeaturesItem">
<StackPanel>
<TextBlock x:Name="TitleTextBlock"
Style="{StaticResource KGF_TitleTextBlockStyle}"
Text="{x:Bind Title, Mode=OneWay}"/>
<ItemsControl ItemsSource="{x:Bind GridItems, Mode=OneWay}" UseSystemFocusVisuals="True">
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="vm:GridDisplayItems">
<Grid VerticalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" MinWidth="64"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<controls:MathRichEditBox Style="{StaticResource KGF_RichEditBoxStyle}" MathText="{x:Bind Expression}"/>
<TextBlock Grid.Column="1"
Margin="0,-2,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Style="{StaticResource KGF_TextBlockStyle}"
Text="{x:Bind Direction}"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="KGFTextBlockDataTemplate" x:DataType="vm:KeyGraphFeaturesItem">
<StackPanel>
<TextBlock x:Name="TitleTextBlock"
Style="{StaticResource KGF_TitleTextBlockStyle}"
Text="{x:Bind Title, Mode=OneWay}"/>
<ItemsControl ItemsSource="{x:Bind DisplayItems, Mode=OneWay}" UseSystemFocusVisuals="True">
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="x:String">
<TextBlock Style="{StaticResource KGF_TextBlockStyle}" Text="{x:Bind}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</DataTemplate>
<ts:KeyGraphFeaturesTemplateSelector x:Key="KGFTemplateSelector"
GridTemplate="{StaticResource KGFGridDataTemplate}"
RichEditTemplate="{StaticResource KGFRichEditDataTemplate}"
TextBlockTemplate="{StaticResource KGFTextBlockDataTemplate}"/>
<converters:BooleanToVisibilityNegationConverter x:Name="BooleanToVisibilityNegationConverter"/>
<SolidColorBrush x:Key="TextControlBackgroundPointerOver" Color="Transparent"/>
<SolidColorBrush x:Key="TextControlBackgroundFocused" Color="Transparent"/>
</ResourceDictionary>
</UserControl.Resources>
<Grid x:Uid="FunctionAnalysisGrid">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Margin="0,0,1,0" Background="{ThemeResource TextControlBackground}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button x:Name="BackButton"
x:Uid="equationAnalysisBack"
MinWidth="44"
VerticalAlignment="Stretch"
Style="{ThemeResource ThemedBackButtonStyle}"
contract7Present:CornerRadius="0"
Click="BackButton_Click">
<StackPanel Margin="5,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Orientation="Horizontal">
<FontIcon Margin="0,0,6,0"
VerticalAlignment="Center"
FontFamily="{ThemeResource SymbolThemeFontFamily}"
FontSize="16"
Glyph="&#xE72B;"/>
<StackPanel FlowDirection="LeftToRight" Orientation="Horizontal">
<FontIcon FontFamily="{StaticResource CalculatorFontFamily}" Glyph="&#xF893;"/>
<TextBlock Margin="-5,19,0,0"
FontSize="11"
Text="{x:Bind ViewModel.FunctionLabelIndex}"/>
</StackPanel>
</StackPanel>
</Button>
<controls:MathRichEditBox x:Uid="KGFEquationTextBox"
Grid.Column="1"
Padding="10,0,6,0"
VerticalAlignment="Stretch"
VerticalContentAlignment="Center"
Style="{StaticResource KGF_RichEditBoxStyle}"
Foreground="{ThemeResource TitleMathRichEditBoxForegroundBrush}"
MathText="{x:Bind ViewModel.Expression, Mode=OneWay}"/>
</Grid>
<TextBlock x:Uid="KeyGraphFeaturesLabel"
Grid.Row="1"
Margin="12,12,10,0"
Style="{StaticResource KGF_TitleTextBlockStyle}"
FontSize="20"
AutomationProperties.HeadingLevel="Level1"/>
<ListView x:Name="KeyGraphFeaturesListView"
Grid.Row="2"
Padding="12,10,10,12"
IsItemClickEnabled="False"
ItemContainerStyle="{StaticResource KGF_ListViewItemContainerStyle}"
ItemTemplateSelector="{StaticResource KGFTemplateSelector}"
ItemsSource="{x:Bind ViewModel.KeyGraphFeaturesItems}"
ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollMode="Auto"
SelectionMode="None"
Visibility="{x:Bind ViewModel.AnalysisErrorVisible, Converter={StaticResource BooleanToVisibilityNegationConverter}, Mode=OneWay}"/>
<TextBlock x:Name="AnalysisErrorTextBlock"
Grid.Row="2"
Margin="12,10,10,0"
Style="{StaticResource KGF_TextBlockStyle}"
FontWeight="Normal"
IsTextSelectionEnabled="False"
Text="{x:Bind ViewModel.AnalysisErrorString, Mode=OneWay}"
TextWrapping="Wrap"
Visibility="{x:Bind ViewModel.AnalysisErrorVisible, Mode=OneWay}"/>
</Grid>
</UserControl>

View file

@ -0,0 +1,67 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Diagnostics;
using CalculatorApp;
using CalculatorApp.ViewModel;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using System.ComponentModel;
namespace CalculatorApp
{
public sealed partial class KeyGraphFeaturesPanel : System.ComponentModel.INotifyPropertyChanged
{
public KeyGraphFeaturesPanel()
{
InitializeComponent();
this.Loaded += KeyGraphFeaturesPanel_Loaded;
}
public event PropertyChangedEventHandler PropertyChanged;
internal void RaisePropertyChanged(string p)
{
#if !UNIT_TESTS
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(p));
#endif
}
public CalculatorApp.ViewModel.EquationViewModel ViewModel
{
get { return m_viewModel; }
set
{
if (m_viewModel != value)
{
m_viewModel = value;
RaisePropertyChanged("ViewModel");
}
}
}
public event Windows.UI.Xaml.RoutedEventHandler KeyGraphFeaturesClosed;
public static Windows.UI.Xaml.Media.SolidColorBrush
ToSolidColorBrush(Windows.UI.Color color)
{
return new Windows.UI.Xaml.Media.SolidColorBrush(color);
}
private void KeyGraphFeaturesPanel_Loaded(object sender, RoutedEventArgs e)
{
BackButton.Focus(FocusState.Programmatic);
}
private void BackButton_Click(object sender, RoutedEventArgs e)
{
KeyGraphFeaturesClosed?.Invoke(this, new RoutedEventArgs());
}
private CalculatorApp.ViewModel.EquationViewModel m_viewModel;
}
}