lightweight variant (#1)
Reviewed-on: #1 Co-authored-by: Aleksandr Neychev <alexnejchev73@gmail.com>
This commit was merged in pull request #1.
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
using System.Globalization;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Media;
|
||||
using DrawingColor = System.Drawing.Color;
|
||||
|
||||
namespace CursorLang.Settings.Views;
|
||||
|
||||
/// <summary>
|
||||
/// Shows an element when the value matches one of those listed in the parameter,
|
||||
/// separated by commas. Needed so that the anchor point settings and the screen
|
||||
/// settings are not shown at the same time.
|
||||
/// </summary>
|
||||
public sealed class EnumToVisibilityConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
|
||||
{
|
||||
string? current = value?.ToString();
|
||||
bool matches = parameter?.ToString()?
|
||||
.Split(',', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries)
|
||||
.Any(expected => expected == current) ?? false;
|
||||
|
||||
return matches ? Visibility.Visible : Visibility.Collapsed;
|
||||
}
|
||||
|
||||
public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) =>
|
||||
Binding.DoNothing;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A colour into a "#RRGGBB" notation: the alpha is not shown, because
|
||||
/// transparency is a separate setting.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The settings hold their colours as <see cref="System.Drawing.Color"/> — the agent
|
||||
/// reads the same file and must not be made to load WindowsBase for a colour. Turning
|
||||
/// them into something WPF can paint with is the job of this file and of
|
||||
/// <see cref="ColorToBrushConverter"/>, and of nothing else.
|
||||
/// </remarks>
|
||||
public sealed class ColorToHexConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture) =>
|
||||
value is DrawingColor color ? $"#{color.R:X2}{color.G:X2}{color.B:X2}" : string.Empty;
|
||||
|
||||
public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) =>
|
||||
Binding.DoNothing;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A colour into a brush — for the palette swatches in the list.
|
||||
/// </summary>
|
||||
public sealed class ColorToBrushConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture) =>
|
||||
value is DrawingColor color
|
||||
? new SolidColorBrush(Color.FromArgb(color.A, color.R, color.G, color.B))
|
||||
: Brushes.Transparent;
|
||||
|
||||
public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) =>
|
||||
value is SolidColorBrush brush
|
||||
? DrawingColor.FromArgb(brush.Color.A, brush.Color.R, brush.Color.G, brush.Color.B)
|
||||
: Binding.DoNothing;
|
||||
}
|
||||
@@ -0,0 +1,468 @@
|
||||
<Window x:Class="CursorLang.Settings.Views.MainWindow"
|
||||
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:local="clr-namespace:CursorLang.Settings.Views"
|
||||
xmlns:vm="clr-namespace:CursorLang.Settings.ViewModels"
|
||||
mc:Ignorable="d"
|
||||
d:DataContext="{d:DesignInstance Type=vm:SettingsViewModel}"
|
||||
Title="{Binding Localization[SettingsTitle]}"
|
||||
Width="1000" SizeToContent="Height" MaxHeight="900"
|
||||
ResizeMode="CanMinimize"
|
||||
Background="{DynamicResource Theme.WindowBackground}"
|
||||
Foreground="{DynamicResource Theme.Foreground}">
|
||||
<Window.Resources>
|
||||
<local:EnumToVisibilityConverter x:Key="EnumToVisibility" />
|
||||
<local:ColorToBrushConverter x:Key="ColorToBrush" />
|
||||
<local:ColorToHexConverter x:Key="ColorToHex" />
|
||||
<BooleanToVisibilityConverter x:Key="BooleanToVisibility" />
|
||||
|
||||
<DataTemplate x:Key="EnumOptionTemplate">
|
||||
<TextBlock Text="{Binding Display}" />
|
||||
</DataTemplate>
|
||||
|
||||
<!-- A colour swatch with a caption: the same for the background and for the text -->
|
||||
<DataTemplate x:Key="ColorSwatchTemplate">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Border Width="32" Height="16" CornerRadius="2"
|
||||
BorderBrush="#888" BorderThickness="1"
|
||||
Background="{Binding Converter={StaticResource ColorToBrush}}" />
|
||||
<TextBlock Margin="8,0,0,0"
|
||||
Text="{Binding Converter={StaticResource ColorToHex}}" />
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
|
||||
<Style TargetType="TextBlock" x:Key="FieldLabel">
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="Margin" Value="0,0,12,0" />
|
||||
<!-- The caption column is narrow, and a translation may not fit into it:
|
||||
such a caption is better wrapped onto a second line than cut off -->
|
||||
<Setter Property="TextWrapping" Value="Wrap" />
|
||||
</Style>
|
||||
<Style TargetType="TextBlock" x:Key="FieldValue">
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="Margin" Value="12,0,0,0" />
|
||||
<Setter Property="MinWidth" Value="48" />
|
||||
<Setter Property="TextAlignment" Value="Right" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource Theme.SecondaryForeground}" />
|
||||
</Style>
|
||||
</Window.Resources>
|
||||
|
||||
<!-- The settings are laid out in two columns: this way the window fits on the
|
||||
screen entirely and does without scrolling. Scrolling is kept for the case of
|
||||
a large system font, with which the content is taller than the monitor after all -->
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto" Padding="16">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<StackPanel>
|
||||
|
||||
<GroupBox Header="{Binding Localization[SectionInterface]}">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="164" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock Style="{StaticResource FieldLabel}"
|
||||
Text="{Binding Localization[LanguageLabel]}" />
|
||||
<ComboBox Grid.Column="1"
|
||||
ItemsSource="{Binding Localization.AvailableLanguages}"
|
||||
DisplayMemberPath="DisplayName"
|
||||
SelectedValuePath="Code"
|
||||
SelectedValue="{Binding Settings.Language}" />
|
||||
|
||||
<TextBlock Grid.Row="1" Margin="0,12,12,0"
|
||||
Style="{StaticResource FieldLabel}"
|
||||
Text="{Binding Localization[ThemeLabel]}" />
|
||||
<ComboBox Grid.Row="1" Grid.Column="1" Margin="0,12,0,0"
|
||||
ItemsSource="{Binding Themes}"
|
||||
ItemTemplate="{StaticResource EnumOptionTemplate}"
|
||||
SelectedValuePath="Value"
|
||||
SelectedValue="{Binding Settings.Theme}" />
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Header="{Binding Localization[SectionPlacement]}">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="164" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock Style="{StaticResource FieldLabel}"
|
||||
Text="{Binding Localization[PlacementModeLabel]}" />
|
||||
<ComboBox Grid.Column="1" Grid.ColumnSpan="2"
|
||||
ItemsSource="{Binding PlacementModes}"
|
||||
ItemTemplate="{StaticResource EnumOptionTemplate}"
|
||||
SelectedValuePath="Value"
|
||||
SelectedValue="{Binding Settings.PlacementMode}" />
|
||||
|
||||
<!-- The "at cursor" mode: a side and an offset of its own -->
|
||||
<TextBlock Grid.Row="1" Margin="0,12,12,0"
|
||||
Style="{StaticResource FieldLabel}"
|
||||
Text="{Binding Localization[CursorCornerLabel]}"
|
||||
Visibility="{Binding Settings.PlacementMode,
|
||||
Converter={StaticResource EnumToVisibility},
|
||||
ConverterParameter=AtCursor}" />
|
||||
<ComboBox Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" Margin="0,12,0,0"
|
||||
ItemsSource="{Binding AnchorSides}"
|
||||
ItemTemplate="{StaticResource EnumOptionTemplate}"
|
||||
SelectedValuePath="Value"
|
||||
SelectedValue="{Binding Settings.CursorSide}"
|
||||
Visibility="{Binding Settings.PlacementMode,
|
||||
Converter={StaticResource EnumToVisibility},
|
||||
ConverterParameter=AtCursor}" />
|
||||
|
||||
<TextBlock Grid.Row="2" Margin="0,12,12,0"
|
||||
Style="{StaticResource FieldLabel}"
|
||||
Text="{Binding Localization[CursorOffsetLabel]}"
|
||||
Visibility="{Binding Settings.PlacementMode,
|
||||
Converter={StaticResource EnumToVisibility},
|
||||
ConverterParameter=AtCursor}" />
|
||||
<Slider Grid.Row="2" Grid.Column="1" Margin="0,12,0,0"
|
||||
Minimum="0" Maximum="80" TickFrequency="1"
|
||||
Value="{Binding Settings.CursorOffset}"
|
||||
Visibility="{Binding Settings.PlacementMode,
|
||||
Converter={StaticResource EnumToVisibility},
|
||||
ConverterParameter=AtCursor}" />
|
||||
<TextBlock Grid.Row="2" Grid.Column="2" Margin="12,12,0,0"
|
||||
Style="{StaticResource FieldValue}"
|
||||
Text="{Binding Settings.CursorOffset, StringFormat={}{0:F0}}"
|
||||
Visibility="{Binding Settings.PlacementMode,
|
||||
Converter={StaticResource EnumToVisibility},
|
||||
ConverterParameter=AtCursor}" />
|
||||
|
||||
<!-- The "at caret" mode: a side and an offset of its own -->
|
||||
<TextBlock Grid.Row="3" Margin="0,12,12,0"
|
||||
Style="{StaticResource FieldLabel}"
|
||||
Text="{Binding Localization[CursorCornerLabel]}"
|
||||
Visibility="{Binding Settings.PlacementMode,
|
||||
Converter={StaticResource EnumToVisibility},
|
||||
ConverterParameter=AtCaret}" />
|
||||
<ComboBox Grid.Row="3" Grid.Column="1" Grid.ColumnSpan="2" Margin="0,12,0,0"
|
||||
ItemsSource="{Binding AnchorSides}"
|
||||
ItemTemplate="{StaticResource EnumOptionTemplate}"
|
||||
SelectedValuePath="Value"
|
||||
SelectedValue="{Binding Settings.CaretSide}"
|
||||
Visibility="{Binding Settings.PlacementMode,
|
||||
Converter={StaticResource EnumToVisibility},
|
||||
ConverterParameter=AtCaret}" />
|
||||
|
||||
<TextBlock Grid.Row="4" Margin="0,12,12,0"
|
||||
Style="{StaticResource FieldLabel}"
|
||||
Text="{Binding Localization[CursorOffsetLabel]}"
|
||||
Visibility="{Binding Settings.PlacementMode,
|
||||
Converter={StaticResource EnumToVisibility},
|
||||
ConverterParameter=AtCaret}" />
|
||||
<Slider Grid.Row="4" Grid.Column="1" Margin="0,12,0,0"
|
||||
Minimum="0" Maximum="80" TickFrequency="1"
|
||||
Value="{Binding Settings.CaretOffset}"
|
||||
Visibility="{Binding Settings.PlacementMode,
|
||||
Converter={StaticResource EnumToVisibility},
|
||||
ConverterParameter=AtCaret}" />
|
||||
<TextBlock Grid.Row="4" Grid.Column="2" Margin="12,12,0,0"
|
||||
Style="{StaticResource FieldValue}"
|
||||
Text="{Binding Settings.CaretOffset, StringFormat={}{0:F0}}"
|
||||
Visibility="{Binding Settings.PlacementMode,
|
||||
Converter={StaticResource EnumToVisibility},
|
||||
ConverterParameter=AtCaret}" />
|
||||
|
||||
<!-- The "fixed point" mode -->
|
||||
<TextBlock Grid.Row="5" Margin="0,12,12,0"
|
||||
Style="{StaticResource FieldLabel}"
|
||||
Text="{Binding Localization[ScreenPositionLabel]}"
|
||||
Visibility="{Binding Settings.PlacementMode,
|
||||
Converter={StaticResource EnumToVisibility},
|
||||
ConverterParameter=FixedPoint}" />
|
||||
<ComboBox Grid.Row="5" Grid.Column="1" Grid.ColumnSpan="2" Margin="0,12,0,0"
|
||||
ItemsSource="{Binding ScreenPositions}"
|
||||
ItemTemplate="{StaticResource EnumOptionTemplate}"
|
||||
SelectedValuePath="Value"
|
||||
SelectedValue="{Binding Settings.ScreenPosition}"
|
||||
Visibility="{Binding Settings.PlacementMode,
|
||||
Converter={StaticResource EnumToVisibility},
|
||||
ConverterParameter=FixedPoint}" />
|
||||
|
||||
<TextBlock Grid.Row="6" Margin="0,12,12,0"
|
||||
Style="{StaticResource FieldLabel}"
|
||||
Text="{Binding Localization[ScreenMarginLabel]}"
|
||||
Visibility="{Binding Settings.PlacementMode,
|
||||
Converter={StaticResource EnumToVisibility},
|
||||
ConverterParameter=FixedPoint}" />
|
||||
<Slider Grid.Row="6" Grid.Column="1" Margin="0,12,0,0"
|
||||
Minimum="0" Maximum="200" TickFrequency="1"
|
||||
Value="{Binding Settings.ScreenMargin}"
|
||||
Visibility="{Binding Settings.PlacementMode,
|
||||
Converter={StaticResource EnumToVisibility},
|
||||
ConverterParameter=FixedPoint}" />
|
||||
<TextBlock Grid.Row="6" Grid.Column="2" Margin="12,12,0,0"
|
||||
Style="{StaticResource FieldValue}"
|
||||
Text="{Binding Settings.ScreenMargin, StringFormat={}{0:F0}}"
|
||||
Visibility="{Binding Settings.PlacementMode,
|
||||
Converter={StaticResource EnumToVisibility},
|
||||
ConverterParameter=FixedPoint}" />
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Header="{Binding Localization[SectionBehavior]}">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="164" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock Style="{StaticResource FieldLabel}"
|
||||
Text="{Binding Localization[DurationLabel]}" />
|
||||
<Slider Grid.Column="1" Minimum="200" Maximum="5000" TickFrequency="100"
|
||||
Value="{Binding Settings.DurationMilliseconds}" />
|
||||
<StackPanel Grid.Column="2" Orientation="Horizontal" VerticalAlignment="Center">
|
||||
<TextBlock Style="{StaticResource FieldValue}"
|
||||
Text="{Binding Settings.DurationMilliseconds, StringFormat={}{0:F0}}" />
|
||||
<TextBlock Margin="4,0,0,0"
|
||||
Foreground="{DynamicResource Theme.SecondaryForeground}"
|
||||
Text="{Binding Localization[MillisecondsSuffix]}" />
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock Grid.Row="1" Margin="0,12,12,0"
|
||||
Style="{StaticResource FieldLabel}"
|
||||
Text="{Binding Localization[CapsLockLabel]}" />
|
||||
<CheckBox Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" Margin="0,12,0,0"
|
||||
IsChecked="{Binding Settings.UseCapsLockHotkey}"
|
||||
Content="{Binding Localization[CapsLockHotkeyCheck]}" />
|
||||
|
||||
<TextBlock Grid.Row="2" Margin="0,12,12,0"
|
||||
Style="{StaticResource FieldLabel}"
|
||||
Text="{Binding Localization[CapsLockHoldLabel]}" />
|
||||
<Slider Grid.Row="2" Grid.Column="1" Margin="0,12,0,0"
|
||||
Minimum="150" Maximum="1500" TickFrequency="50"
|
||||
Value="{Binding Settings.CapsLockHoldMilliseconds}"
|
||||
IsEnabled="{Binding Settings.UseCapsLockHotkey}" />
|
||||
<StackPanel Grid.Row="2" Grid.Column="2" Margin="0,12,0,0"
|
||||
Orientation="Horizontal" VerticalAlignment="Center">
|
||||
<TextBlock Style="{StaticResource FieldValue}"
|
||||
Text="{Binding Settings.CapsLockHoldMilliseconds, StringFormat={}{0:F0}}" />
|
||||
<TextBlock Margin="4,0,0,0"
|
||||
Foreground="{DynamicResource Theme.SecondaryForeground}"
|
||||
Text="{Binding Localization[MillisecondsSuffix]}" />
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock Grid.Row="3" Grid.Column="1" Grid.ColumnSpan="2"
|
||||
Margin="0,6,0,0" TextWrapping="Wrap"
|
||||
Foreground="{DynamicResource Theme.SecondaryForeground}">
|
||||
<Run Text="{Binding Localization[CapsLockHoldHint], Mode=OneWay}" />
|
||||
<InlineUIContainer BaselineAlignment="Baseline">
|
||||
<!-- The elevation caveat lives in the tooltip to keep the section compact -->
|
||||
<TextBlock Text="{Binding Localization[MoreInfoLink]}"
|
||||
Foreground="{DynamicResource Theme.Accent}"
|
||||
TextDecorations="Underline"
|
||||
Cursor="Help"
|
||||
ToolTipService.InitialShowDelay="200"
|
||||
ToolTipService.ShowDuration="60000"
|
||||
Visibility="{Binding Settings.UseCapsLockHotkey, Converter={StaticResource BooleanToVisibility}}">
|
||||
<TextBlock.ToolTip>
|
||||
<ToolTip>
|
||||
<TextBlock TextWrapping="Wrap"
|
||||
Text="{Binding Localization[CapsLockElevationHint]}" />
|
||||
</ToolTip>
|
||||
</TextBlock.ToolTip>
|
||||
</TextBlock>
|
||||
</InlineUIContainer>
|
||||
</TextBlock>
|
||||
|
||||
<TextBlock Grid.Row="4" Margin="0,12,12,0"
|
||||
Style="{StaticResource FieldLabel}"
|
||||
Visibility="{Binding IsStartupAvailable, Converter={StaticResource BooleanToVisibility}}"
|
||||
Text="{Binding Localization[StartupLabel]}" />
|
||||
<CheckBox Grid.Row="4" Grid.Column="1" Grid.ColumnSpan="2" Margin="0,12,0,0"
|
||||
Visibility="{Binding IsStartupAvailable, Converter={StaticResource BooleanToVisibility}}"
|
||||
IsEnabled="{Binding CanChangeStartup}"
|
||||
IsChecked="{Binding RunAtStartup}"
|
||||
Content="{Binding Localization[StartupCheck]}" />
|
||||
|
||||
<TextBlock Grid.Row="5" Grid.Column="1" Grid.ColumnSpan="2"
|
||||
Margin="0,6,0,0" TextWrapping="Wrap"
|
||||
Foreground="{DynamicResource Theme.SecondaryForeground}"
|
||||
Visibility="{Binding IsStartupLocked, Converter={StaticResource BooleanToVisibility}}"
|
||||
Text="{Binding Localization[StartupLockedHint]}" />
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Grid.Column="1" Margin="16,0,0,0">
|
||||
|
||||
<GroupBox Header="{Binding Localization[SectionAppearance]}">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="164" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock Style="{StaticResource FieldLabel}"
|
||||
Text="{Binding Localization[FontSizeLabel]}" />
|
||||
<Slider Grid.Column="1" Minimum="10" Maximum="72" TickFrequency="1"
|
||||
Value="{Binding Settings.FontSize}" />
|
||||
<TextBlock Grid.Column="2" Style="{StaticResource FieldValue}"
|
||||
Text="{Binding Settings.FontSize, StringFormat={}{0:F0}}" />
|
||||
|
||||
<TextBlock Grid.Row="1" Margin="0,12,12,0"
|
||||
Style="{StaticResource FieldLabel}"
|
||||
Text="{Binding Localization[OpacityLabel]}" />
|
||||
<Slider Grid.Row="1" Grid.Column="1" Margin="0,12,0,0"
|
||||
Minimum="0.1" Maximum="1" TickFrequency="0.05"
|
||||
Value="{Binding Settings.Opacity}" />
|
||||
<TextBlock Grid.Row="1" Grid.Column="2" Margin="12,12,0,0"
|
||||
Style="{StaticResource FieldValue}"
|
||||
Text="{Binding Settings.Opacity, StringFormat={}{0:P0}}" />
|
||||
|
||||
<TextBlock Grid.Row="2" Margin="0,12,12,0"
|
||||
Style="{StaticResource FieldLabel}"
|
||||
Text="{Binding Localization[BackgroundColorLabel]}" />
|
||||
<ComboBox Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2" Margin="0,12,0,0"
|
||||
ItemsSource="{Binding BackgroundPalette}"
|
||||
ItemTemplate="{StaticResource ColorSwatchTemplate}"
|
||||
SelectedItem="{Binding Settings.BackgroundColor}" />
|
||||
|
||||
<TextBlock Grid.Row="3" Margin="0,12,12,0"
|
||||
Style="{StaticResource FieldLabel}"
|
||||
Text="{Binding Localization[TextColorLabel]}" />
|
||||
<ComboBox Grid.Row="3" Grid.Column="1" Grid.ColumnSpan="2" Margin="0,12,0,0"
|
||||
ItemsSource="{Binding TextPalette}"
|
||||
ItemTemplate="{StaticResource ColorSwatchTemplate}"
|
||||
SelectedItem="{Binding Settings.ForegroundColor}" />
|
||||
|
||||
<TextBlock Grid.Row="4" Margin="0,12,12,0"
|
||||
Style="{StaticResource FieldLabel}"
|
||||
Text="{Binding Localization[PreviewLabel]}" />
|
||||
<!-- The height of the area is sized for the largest font
|
||||
available: the sample text is fully visible at any
|
||||
position of the slider -->
|
||||
<Border Grid.Row="4" Grid.Column="1" Grid.ColumnSpan="2"
|
||||
Margin="0,12,0,0" Padding="16"
|
||||
Height="152" ClipToBounds="True"
|
||||
Background="{DynamicResource Theme.SurfaceStrong}" CornerRadius="4"
|
||||
HorizontalAlignment="Stretch">
|
||||
<Border CornerRadius="4" Padding="10,4"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Center"
|
||||
Opacity="{Binding Settings.Opacity}"
|
||||
Background="{Binding Settings.BackgroundColor,
|
||||
Converter={StaticResource ColorToBrush}}">
|
||||
<TextBlock Text="RU" FontWeight="SemiBold"
|
||||
FontSize="{Binding Settings.FontSize}"
|
||||
Foreground="{Binding Settings.ForegroundColor,
|
||||
Converter={StaticResource ColorToBrush}}" />
|
||||
</Border>
|
||||
</Border>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
<!-- The section is absent for an app from the Store: the Store updates it itself -->
|
||||
<GroupBox Header="{Binding Localization[SectionUpdates]}"
|
||||
Visibility="{Binding Updates.IsSupported, Converter={StaticResource BooleanToVisibility}}">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="164" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock Style="{StaticResource FieldLabel}"
|
||||
Text="{Binding Localization[CurrentVersionLabel]}" />
|
||||
<TextBlock Grid.Column="1" VerticalAlignment="Center"
|
||||
Text="{Binding Updates.CurrentVersion}" />
|
||||
<Button Grid.Column="2" Padding="12,4"
|
||||
Command="{Binding Updates.CheckCommand}"
|
||||
IsEnabled="{Binding Updates.CanCheck}"
|
||||
Content="{Binding Localization[CheckUpdatesButton]}" />
|
||||
|
||||
<CheckBox Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" Margin="0,12,0,0"
|
||||
IsChecked="{Binding Updates.CheckAutomatically}"
|
||||
Content="{Binding Localization[UpdateAutoCheck]}" />
|
||||
|
||||
<TextBlock Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2"
|
||||
Margin="0,12,0,0" TextWrapping="Wrap"
|
||||
Visibility="{Binding Updates.HasStatus, Converter={StaticResource BooleanToVisibility}}"
|
||||
Text="{Binding Updates.StatusText}" />
|
||||
|
||||
<!-- The downloaded fraction is not always known: not every hosting reports the file size -->
|
||||
<ProgressBar Grid.Row="3" Grid.Column="1" Grid.ColumnSpan="2"
|
||||
Margin="0,8,0,0" Height="4" Maximum="1"
|
||||
Value="{Binding Updates.Progress, Mode=OneWay}"
|
||||
IsIndeterminate="{Binding Updates.IsProgressUnknown}"
|
||||
Visibility="{Binding Updates.IsProgressShown, Converter={StaticResource BooleanToVisibility}}" />
|
||||
|
||||
<StackPanel Grid.Row="4" Grid.Column="1" Grid.ColumnSpan="2"
|
||||
Margin="0,12,0,0" Orientation="Horizontal">
|
||||
<Button Padding="12,4"
|
||||
Command="{Binding Updates.DownloadCommand}"
|
||||
Visibility="{Binding Updates.IsDownloadOffered, Converter={StaticResource BooleanToVisibility}}"
|
||||
Content="{Binding Localization[DownloadUpdateButton]}" />
|
||||
<Button Padding="12,4"
|
||||
Command="{Binding Updates.InstallCommand}"
|
||||
Visibility="{Binding Updates.IsInstallOffered, Converter={StaticResource BooleanToVisibility}}"
|
||||
Content="{Binding Localization[InstallUpdateButton]}" />
|
||||
<TextBlock Margin="12,0,0,0" VerticalAlignment="Center"
|
||||
Visibility="{Binding Updates.IsReleaseLinkShown, Converter={StaticResource BooleanToVisibility}}">
|
||||
<Hyperlink NavigateUri="{Binding Updates.ReleaseUrl}"
|
||||
RequestNavigate="OnReleaseLinkNavigate">
|
||||
<Run Text="{Binding Localization[ReleasePageLink], Mode=OneWay}" />
|
||||
</Hyperlink>
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock Grid.Row="5" Grid.Column="1" Grid.ColumnSpan="2"
|
||||
Margin="0,6,0,0" TextWrapping="Wrap"
|
||||
Foreground="{DynamicResource Theme.SecondaryForeground}"
|
||||
Visibility="{Binding Updates.IsInstallOffered, Converter={StaticResource BooleanToVisibility}}"
|
||||
Text="{Binding Localization[UpdateInstallHint]}" />
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</Window>
|
||||
@@ -0,0 +1,50 @@
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Windows;
|
||||
using System.Windows.Navigation;
|
||||
using CursorLang.Settings.Services;
|
||||
using CursorLang.Settings.ViewModels;
|
||||
|
||||
namespace CursorLang.Settings.Views;
|
||||
|
||||
/// <summary>
|
||||
/// The settings window of the application.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Both buttons in the title bar mean what they say now: the window used to hide into
|
||||
/// the tray, because closing it would have thrown away the visual tree the background
|
||||
/// half was still using. The background half is a separate process and no longer cares,
|
||||
/// so closing closes and the process ends with it.
|
||||
/// </remarks>
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
public MainWindow(
|
||||
SettingsViewModel viewModel,
|
||||
IThemeService theme,
|
||||
MainWindowPlacement placement)
|
||||
{
|
||||
InitializeComponent();
|
||||
DataContext = viewModel;
|
||||
theme.Register(this);
|
||||
placement.Attach(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens the release page in a browser. A link in WPF leads nowhere on its own:
|
||||
/// where to hand it over is up to the application.
|
||||
/// </summary>
|
||||
private void OnReleaseLinkNavigate(object sender, RequestNavigateEventArgs e)
|
||||
{
|
||||
e.Handled = true;
|
||||
|
||||
try
|
||||
{
|
||||
Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri) { UseShellExecute = true })?.Dispose();
|
||||
}
|
||||
catch (Exception exception) when (exception is Win32Exception or InvalidOperationException)
|
||||
{
|
||||
// There is no browser in the system — that does not get in the way of the
|
||||
// update, which is downloaded by the button next to it anyway
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user