Files
modernkeepass/ModernKeePass/Views/UserControls/PasswordGenerationBox.xaml
Geoffroy BONNEVILLE 3d436c56fa Password generation button with display toggle and indicator is now a user control
SetCredentials user controls now uses PasswordGenerationBox user control
Some layout improvements in EntryDetailsPage
WIP Clipboard suspend issues
2020-05-25 19:23:32 +02:00

385 lines
36 KiB
XML

<UserControl x:Name="UserControl"
x:Class="ModernKeePass.Views.UserControls.PasswordGenerationBox"
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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:controls="using:ModernKeePass.Controls"
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
xmlns:core="using:Microsoft.Xaml.Interactions.Core"
xmlns:converters="using:ModernKeePass.Converters"
xmlns:actions="using:ModernKeePass.Actions"
mc:Ignorable="d"
BorderBrush="{ThemeResource ComboBoxBorderThemeBrush}">
<StackPanel x:Name="StackPanel" Orientation="Vertical" DataContext="{Binding Source={StaticResource Locator}, Path=PasswordGenerationBox}">
<StackPanel.Resources>
<converters:ProgressBarLegalValuesConverter x:Key="ProgressBarLegalValuesConverter" />
<converters:DoubleToSolidColorBrushConverter x:Key="DoubleToForegroundBrushComplexityConverter" />
<converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
<converters:InverseBooleanToVisibilityConverter x:Key="InverseBooleanToVisibilityConverter" />
<Style TargetType="controls:PasswordBoxWithButton" x:Key="PasswordBoxWithButtonStyle">
<Setter Property="Background" Value="{ThemeResource SearchBoxBackgroundThemeBrush}" />
<Setter Property="BorderBrush" Value="{ThemeResource ComboBoxBorderThemeBrush}" />
<Setter Property="BorderThickness" Value="{ThemeResource TextControlBorderThemeThickness}" />
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
<Setter Property="FontWeight" Value="{ThemeResource SearchBoxContentThemeFontWeight}"/>
<Setter Property="Foreground" Value="{ThemeResource SearchBoxForegroundThemeBrush}" />
<Setter Property="Padding" Value="{ThemeResource SearchBoxThemePadding}"/>
<Setter Property="IsTabStop" Value="False" />
<Setter Property="Typography.StylisticSet20" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="controls:PasswordBoxWithButton">
<Grid x:Name="SearchBoxGrid">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchBoxGrid" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Background}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchBoxBorder" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=BorderBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ActionButton" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Foreground}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchBoxGrid" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxPointerOverBackgroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchBoxBorder" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxPointerOverBorderThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ActionButton" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxPointerOverTextThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchBoxGrid" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxDisabledBackgroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchBoxBorder" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxDisabledBorderThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ActionButton" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxDisabledTextThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PasswordBox" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="Transparent" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Focused">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchBoxGrid" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxFocusedBackgroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchBoxBorder" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource MainColor}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ActionButton" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxButtonForegroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ActionButton" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxFocusedBorderThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="FocusedDropDown">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchBoxGrid" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxFocusedBackgroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchBoxBorder" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxFocusedBorderThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ActionButton" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxFocusedTextThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid.Resources>
<Style x:Key="ActionButtonStyle" TargetType="Button">
<Setter Property="IsTabStop" Value="False" />
<Setter Property="VerticalAlignment" Value="Stretch" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid Background="Transparent">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchGlyph" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxButtonPointerOverForegroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ActionButtonBackground" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxButtonPointerOverBackgroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchGlyph" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxFocusedTextThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ActionButtonBackground" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxFocusedBackgroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled" />
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused" />
<VisualState x:Name="Unfocused" />
<VisualState x:Name="PointerFocused" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid x:Name="ActionButtonBackground" Background="{TemplateBinding Background}">
<TextBlock x:Name="SearchGlyph"
AutomationProperties.AccessibilityView="Raw"
FontFamily="{ThemeResource SymbolThemeFontFamily}"
Foreground="{TemplateBinding Foreground}"
HorizontalAlignment="Center"
FontStyle="Italic"
Padding="4,0,4,0"
Text="{TemplateBinding Content}"
VerticalAlignment="Center" />
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="PasswordBoxStyle" TargetType="PasswordBox">
<Setter Property="MinWidth" Value="{ThemeResource TextControlThemeMinWidth}" />
<Setter Property="MinHeight" Value="{ThemeResource TextControlThemeMinHeight}" />
<Setter Property="Foreground" Value="{ThemeResource TextBoxForegroundThemeBrush}" />
<Setter Property="Background" Value="{ThemeResource TextBoxBackgroundThemeBrush}" />
<Setter Property="BorderBrush" Value="{ThemeResource TextBoxBorderThemeBrush}" />
<Setter Property="SelectionHighlightColor" Value="{ThemeResource TextSelectionHighlightColorThemeBrush}" />
<Setter Property="BorderThickness" Value="{ThemeResource TextControlBorderThemeThickness}" />
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Hidden" />
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Hidden" />
<Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="False" />
<Setter Property="Padding" Value="{ThemeResource TextControlThemePadding}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="PasswordBox">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundElement"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledBackgroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement"
Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledBorderThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledForegroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderTextContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledForegroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Normal">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="BackgroundElement"
Storyboard.TargetProperty="Opacity"
Duration="0"
To="{ThemeResource TextControlBackgroundThemeOpacity}" />
<DoubleAnimation Storyboard.TargetName="BorderElement"
Storyboard.TargetProperty="Opacity"
Duration="0"
To="{ThemeResource TextControlBorderThemeOpacity}" />
</Storyboard>
</VisualState>
<VisualState x:Name="PointerOver">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="BackgroundElement"
Storyboard.TargetProperty="Opacity"
Duration="0"
To="{ThemeResource TextControlPointerOverBackgroundThemeOpacity}" />
<DoubleAnimation Storyboard.TargetName="BorderElement"
Storyboard.TargetProperty="Opacity"
Duration="0"
To="{ThemeResource TextControlPointerOverBorderThemeOpacity}" />
</Storyboard>
</VisualState>
<VisualState x:Name="Focused" />
</VisualStateGroup>
<VisualStateGroup x:Name="ButtonStates" />
</VisualStateManager.VisualStateGroups>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Border x:Name="BackgroundElement"
Grid.Row="1"
Background="{TemplateBinding Background}"
Margin="{TemplateBinding BorderThickness}" />
<Border x:Name="BorderElement"
Grid.Row="1"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}" />
<ContentPresenter x:Name="HeaderContentPresenter"
Grid.Row="0"
Foreground="{ThemeResource TextBoxForegroundHeaderThemeBrush}"
Margin="0,4,0,4"
Content="{TemplateBinding Header}"
ContentTemplate="{TemplateBinding HeaderTemplate}"
FontWeight="Semilight" />
<ScrollViewer x:Name="ContentElement"
Grid.Row="1"
HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}"
HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}"
VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"
IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}"
IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}"
IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}"
Margin="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}"
IsTabStop="False"
AutomationProperties.AccessibilityView="Raw"
ZoomMode="Disabled" />
<ContentControl x:Name="PlaceholderTextContentPresenter"
Grid.Row="1"
Foreground="{ThemeResource TextBoxPlaceholderTextThemeBrush}"
Margin="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}"
IsTabStop="False"
Grid.ColumnSpan="2"
Content="{TemplateBinding PlaceholderText}"
IsHitTestVisible="False" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<Border x:Name="SearchBoxBorder"
Background="Transparent"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<PasswordBox x:Name="PasswordBox"
BorderThickness="0"
Background="Transparent"
FontFamily="{TemplateBinding FontFamily}"
FontSize="{TemplateBinding FontSize}"
FontWeight="{TemplateBinding FontWeight}"
Foreground="{TemplateBinding Foreground}"
MaxLength="2048"
MinHeight="{ThemeResource SearchBoxTextBoxThemeMinHeight}"
Padding="{TemplateBinding Padding}"
PlaceholderText="{TemplateBinding PlaceholderText}"
Style="{StaticResource PasswordBoxStyle}"
VerticalAlignment="Stretch"
Margin="0"
Password="{Binding RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay, Path=Password, UpdateSourceTrigger=PropertyChanged}"
IsPasswordRevealButtonEnabled="{TemplateBinding IsPasswordRevealEnabled}"/>
<Button x:Name="ActionButton"
AutomationProperties.AccessibilityView="Raw"
Background="Transparent"
FontWeight="{ThemeResource SearchBoxButtonThemeFontWeight}"
FontSize="12"
Grid.Column="1"
Style="{StaticResource ActionButtonStyle}"
Content="{TemplateBinding ButtonContent}"
IsEnabled="{TemplateBinding IsButtonEnabled}">
<Button.Flyout>
<Flyout>
<interactivity:Interaction.Behaviors>
<core:DataTriggerBehavior Binding="{Binding Password}" ComparisonCondition="NotEqual" Value="" >
<core:CallMethodAction MethodName="Hide" />
</core:DataTriggerBehavior>
</interactivity:Interaction.Behaviors>
<StackPanel>
<TextBlock>
<Run x:Uid="PasswordGeneratorLength" />
<Run Text="{Binding PasswordLength}" />
</TextBlock>
<Slider Value="{Binding PasswordLength, Mode=TwoWay}" Margin="0,-10,0,-20" />
<CheckBox IsChecked="{Binding UpperCasePatternSelected, Mode=TwoWay}" x:Uid="PasswordGeneratorUpper" />
<CheckBox IsChecked="{Binding LowerCasePatternSelected, Mode=TwoWay}" x:Uid="PasswordGeneratorLower" />
<CheckBox IsChecked="{Binding DigitsPatternSelected, Mode=TwoWay}" x:Uid="PasswordGeneratorDigits" />
<CheckBox IsChecked="{Binding MinusPatternSelected, Mode=TwoWay}" x:Uid="PasswordGeneratorMinus" />
<CheckBox IsChecked="{Binding UnderscorePatternSelected, Mode=TwoWay}" x:Uid="PasswordGeneratorUnderscore" />
<CheckBox IsChecked="{Binding SpacePatternSelected, Mode=TwoWay}" x:Uid="PasswordGeneratorSpace" />
<CheckBox IsChecked="{Binding SpecialPatternSelected, Mode=TwoWay}" x:Uid="PasswordGeneratorSpecial" />
<CheckBox IsChecked="{Binding BracketsPatternSelected, Mode=TwoWay}" x:Uid="PasswordGeneratorBrackets" />
<TextBlock x:Uid="PasswordGeneratorAlso" Margin="0,5,0,0"/>
<TextBox Text="{Binding CustomChars, Mode=TwoWay}" />
<Button x:Uid="PasswordGeneratorButton" Command="{Binding GeneratePasswordCommand}" />
</StackPanel>
</Flyout>
</Button.Flyout>
<ToolTipService.ToolTip>
<ToolTip x:Uid="PasswordGeneratorTooltip" />
</ToolTipService.ToolTip>
</Button>
</Grid>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</StackPanel.Resources>
<controls:PasswordBoxWithButton x:Uid="PasswordGenerationButton"
Password="{Binding Password, Mode=TwoWay, ElementName=UserControl}"
IsPasswordRevealEnabled="True"
Style="{StaticResource PasswordBoxWithButtonStyle}"
IsEnabled="{Binding IsEnabled, ElementName=UserControl}"
PlaceholderText="{Binding PlaceholderText, ElementName=UserControl}"
Visibility="{Binding IsRevealPassword, Converter={StaticResource InverseBooleanToVisibilityConverter}}"
BorderBrush="{Binding BorderBrush, ElementName=UserControl}" />
<controls:TextBoxWithButton
x:Uid="PasswordTextBox"
Text="{Binding Password, Mode=TwoWay}"
Visibility="{Binding IsRevealPassword, Converter={StaticResource BooleanToVisibilityConverter}}"
Style="{StaticResource TextBoxWithButtonStyle}"
ButtonContent="&#xE16F;"
IsEnabled="{Binding IsEnabled, ElementName=UserControl}"
BorderBrush="{Binding BorderBrush, ElementName=UserControl}" >
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="ButtonClick">
<actions:ClipboardAction Text="{Binding Password}" />
<actions:ToastAction x:Uid="ToastCopyPassword" Title="Password" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</controls:TextBoxWithButton>
<ProgressBar
Value="{Binding PasswordComplexityIndicator, ConverterParameter=0\,128, Converter={StaticResource ProgressBarLegalValuesConverter}}"
Maximum="128"
Width="{Binding ActualWidth, ElementName=UserControl}"
Foreground="{Binding PasswordComplexityIndicator, ConverterParameter=128, Converter={StaticResource DoubleToForegroundBrushComplexityConverter}}" />
<ToggleSwitch x:Uid="EntryShowPassword" Margin="-3,-10,0,0" IsOn="{Binding IsRevealPassword, Mode=TwoWay}" />
</StackPanel>
</UserControl>