Refactoring the html editor toolbar.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
@@ -97,16 +98,33 @@ public sealed record class EditorTableCommandArgs(
|
||||
|
||||
public sealed record class EditorColorOption(string Name, string Value)
|
||||
{
|
||||
public SolidColorBrush Brush => new(ParseColor(Value));
|
||||
public SolidColorBrush Brush => new(ParseColorValue(Value));
|
||||
|
||||
private static Color ParseColor(string? value)
|
||||
public static Color ParseColorValue(string? value)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
return Colors.Transparent;
|
||||
}
|
||||
|
||||
var hex = value.Trim().TrimStart('#');
|
||||
var normalizedValue = value.Trim();
|
||||
|
||||
if (string.Equals(normalizedValue, "transparent", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return Colors.Transparent;
|
||||
}
|
||||
|
||||
if (TryParseRgbColor(normalizedValue, out var rgbColor))
|
||||
{
|
||||
return rgbColor;
|
||||
}
|
||||
|
||||
if (TryParseNamedColor(normalizedValue, out var namedColor))
|
||||
{
|
||||
return namedColor;
|
||||
}
|
||||
|
||||
var hex = normalizedValue.TrimStart('#');
|
||||
if (hex.Length == 6)
|
||||
{
|
||||
hex = $"FF{hex}";
|
||||
@@ -123,6 +141,76 @@ public sealed record class EditorColorOption(string Name, string Value)
|
||||
(byte)((argb >> 8) & 0xFF),
|
||||
(byte)(argb & 0xFF));
|
||||
}
|
||||
|
||||
private static bool TryParseRgbColor(string value, out Color color)
|
||||
{
|
||||
color = Colors.Transparent;
|
||||
|
||||
var isRgba = value.StartsWith("rgba(", StringComparison.OrdinalIgnoreCase);
|
||||
var isRgb = value.StartsWith("rgb(", StringComparison.OrdinalIgnoreCase);
|
||||
if (!isRgb && !isRgba)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var startIndex = value.IndexOf('(');
|
||||
var endIndex = value.LastIndexOf(')');
|
||||
if (startIndex < 0 || endIndex <= startIndex)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var segments = value[(startIndex + 1)..endIndex]
|
||||
.Split(',', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
if ((isRgb && segments.Length != 3) || (isRgba && segments.Length != 4))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!byte.TryParse(segments[0], NumberStyles.Integer, CultureInfo.InvariantCulture, out var red) ||
|
||||
!byte.TryParse(segments[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out var green) ||
|
||||
!byte.TryParse(segments[2], NumberStyles.Integer, CultureInfo.InvariantCulture, out var blue))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
byte alpha = 255;
|
||||
if (isRgba)
|
||||
{
|
||||
if (!double.TryParse(segments[3], NumberStyles.Float, CultureInfo.InvariantCulture, out var alphaValue))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
alpha = alphaValue <= 1d
|
||||
? (byte)Math.Clamp(Math.Round(alphaValue * 255d), 0d, 255d)
|
||||
: (byte)Math.Clamp(Math.Round(alphaValue), 0d, 255d);
|
||||
}
|
||||
|
||||
color = Color.FromArgb(alpha, red, green, blue);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool TryParseNamedColor(string value, out Color color)
|
||||
{
|
||||
color = value.ToLowerInvariant() switch
|
||||
{
|
||||
"black" => Colors.Black,
|
||||
"white" => Colors.White,
|
||||
"gray" or "grey" => Colors.Gray,
|
||||
"red" => Colors.Red,
|
||||
"orange" => Colors.Orange,
|
||||
"yellow" => Colors.Yellow,
|
||||
"green" => Colors.Green,
|
||||
"blue" => Colors.Blue,
|
||||
"purple" => Colors.Purple,
|
||||
"pink" => Colors.Pink,
|
||||
_ => Colors.Transparent
|
||||
};
|
||||
|
||||
return !color.Equals(Colors.Transparent) || string.Equals(value, "transparent", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed record class EditorParagraphStyleOption(string Name, string Tag);
|
||||
|
||||
@@ -11,29 +11,47 @@
|
||||
mc:Ignorable="d">
|
||||
|
||||
<UserControl.Resources>
|
||||
<Style x:Key="CompactComboBoxStyle" TargetType="ComboBox">
|
||||
<Setter Property="MinWidth" Value="88" />
|
||||
<Setter Property="MaxWidth" Value="136" />
|
||||
<Style
|
||||
x:Key="CompactComboBoxStyle"
|
||||
BasedOn="{StaticResource DefaultComboBoxStyle}"
|
||||
TargetType="ComboBox">
|
||||
<Setter Property="MinWidth" Value="72" />
|
||||
<Setter Property="MaxWidth" Value="132" />
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="BorderBrush" Value="Transparent" />
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
<Setter Property="Padding" Value="4,0,0,0" />
|
||||
</Style>
|
||||
|
||||
<Style x:Key="CompactPickerContainerStyle" TargetType="AppBarElementContainer">
|
||||
<Setter Property="MinWidth" Value="0" />
|
||||
<Setter Property="Margin" Value="0" />
|
||||
<Setter Property="Margin" Value="0,8,0,0" />
|
||||
</Style>
|
||||
|
||||
<Style x:Key="CompactPickerBorderStyle" TargetType="Border">
|
||||
<!--<Setter Property="Background" Value="{ThemeResource ControlFillColorSecondaryBrush}" />-->
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource ControlStrokeColorDefaultBrush}" />
|
||||
<Setter Property="BorderThickness" Value="1" />
|
||||
<Setter Property="CornerRadius" Value="{StaticResource ControlCornerRadius}" />
|
||||
<Setter Property="Padding" Value="0" />
|
||||
<Setter Property="MinHeight" Value="36" />
|
||||
<Setter Property="Margin" Value="4,0" />
|
||||
</Style>
|
||||
|
||||
<DataTemplate x:Key="ColorOptionTemplate" x:DataType="mail:EditorColorOption">
|
||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||
<Grid Width="14" Height="14">
|
||||
<Rectangle
|
||||
Fill="{x:Bind Brush}"
|
||||
RadiusX="3"
|
||||
RadiusY="3"
|
||||
Fill="{x:Bind Brush}"
|
||||
Stroke="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
StrokeThickness="1" />
|
||||
</Grid>
|
||||
<TextBlock VerticalAlignment="Center" Text="{x:Bind Name}" />
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
|
||||
</UserControl.Resources>
|
||||
|
||||
<toolkit:TabbedCommandBar>
|
||||
@@ -41,6 +59,12 @@
|
||||
<SolidColorBrush x:Key="TabContentContentBorderBackground" Color="Transparent" />
|
||||
<SolidColorBrush x:Key="TabContentContentBorderBorderBrush" Color="Transparent" />
|
||||
<Thickness x:Key="TabContentBorderBorderThickness">0</Thickness>
|
||||
<Style BasedOn="{StaticResource DefaultAppBarToggleButtonStyle}" TargetType="AppBarToggleButton">
|
||||
<Setter Property="Width" Value="50" />
|
||||
</Style>
|
||||
<Style BasedOn="{StaticResource DefaultAppBarButtonStyle}" TargetType="AppBarButton">
|
||||
<Setter Property="Width" Value="50" />
|
||||
</Style>
|
||||
</toolkit:TabbedCommandBar.Resources>
|
||||
|
||||
<toolkit:TabbedCommandBar.PaneCustomContent>
|
||||
@@ -49,25 +73,41 @@
|
||||
|
||||
<toolkit:TabbedCommandBar.MenuItems>
|
||||
<toolkit:TabbedCommandBarItem DefaultLabelPosition="Collapsed" Header="Format">
|
||||
<AppBarToggleButton x:Name="BoldButton" Click="BoldButton_Click" Label="Bold" ToolTipService.ToolTip="Bold (Ctrl+B)">
|
||||
<AppBarToggleButton
|
||||
x:Name="BoldButton"
|
||||
Click="BoldButton_Click"
|
||||
Label="Bold"
|
||||
ToolTipService.ToolTip="Bold (Ctrl+B)">
|
||||
<AppBarToggleButton.Icon>
|
||||
<PathIcon Data="{StaticResource BoldPathIcon}" />
|
||||
</AppBarToggleButton.Icon>
|
||||
</AppBarToggleButton>
|
||||
|
||||
<AppBarToggleButton x:Name="ItalicButton" Click="ItalicButton_Click" Label="Italic" ToolTipService.ToolTip="Italic (Ctrl+I)">
|
||||
<AppBarToggleButton
|
||||
x:Name="ItalicButton"
|
||||
Click="ItalicButton_Click"
|
||||
Label="Italic"
|
||||
ToolTipService.ToolTip="Italic (Ctrl+I)">
|
||||
<AppBarToggleButton.Icon>
|
||||
<PathIcon Data="{StaticResource ItalicPathIcon}" />
|
||||
</AppBarToggleButton.Icon>
|
||||
</AppBarToggleButton>
|
||||
|
||||
<AppBarToggleButton x:Name="UnderlineButton" Click="UnderlineButton_Click" Label="Underline" ToolTipService.ToolTip="Underline (Ctrl+U)">
|
||||
<AppBarToggleButton
|
||||
x:Name="UnderlineButton"
|
||||
Click="UnderlineButton_Click"
|
||||
Label="Underline"
|
||||
ToolTipService.ToolTip="Underline (Ctrl+U)">
|
||||
<AppBarToggleButton.Icon>
|
||||
<PathIcon Data="{StaticResource UnderlinePathIcon}" />
|
||||
</AppBarToggleButton.Icon>
|
||||
</AppBarToggleButton>
|
||||
|
||||
<AppBarToggleButton x:Name="StrikeButton" Click="StrikeButton_Click" Label="Strikethrough" ToolTipService.ToolTip="Strikethrough">
|
||||
<AppBarToggleButton
|
||||
x:Name="StrikeButton"
|
||||
Click="StrikeButton_Click"
|
||||
Label="Strikethrough"
|
||||
ToolTipService.ToolTip="Strikethrough">
|
||||
<AppBarToggleButton.Icon>
|
||||
<PathIcon Data="{StaticResource StrikePathIcon}" />
|
||||
</AppBarToggleButton.Icon>
|
||||
@@ -75,139 +115,254 @@
|
||||
|
||||
<AppBarSeparator />
|
||||
|
||||
<AppBarToggleButton x:Name="BulletListButton" Click="BulletListButton_Click" Label="Bullets" ToolTipService.ToolTip="Bulleted list">
|
||||
<AppBarToggleButton
|
||||
x:Name="BulletListButton"
|
||||
Click="BulletListButton_Click"
|
||||
Label="Bullets"
|
||||
ToolTipService.ToolTip="Bulleted list">
|
||||
<AppBarToggleButton.Icon>
|
||||
<PathIcon Data="{StaticResource BulletedListPathIcon}" />
|
||||
</AppBarToggleButton.Icon>
|
||||
</AppBarToggleButton>
|
||||
|
||||
<AppBarToggleButton x:Name="OrderedListButton" Click="OrderedListButton_Click" Label="Numbered list" ToolTipService.ToolTip="Numbered list">
|
||||
<AppBarToggleButton
|
||||
x:Name="OrderedListButton"
|
||||
Click="OrderedListButton_Click"
|
||||
Label="Numbered list"
|
||||
ToolTipService.ToolTip="Numbered list">
|
||||
<AppBarToggleButton.Icon>
|
||||
<PathIcon Data="{StaticResource OrderedListPathIcon}" />
|
||||
</AppBarToggleButton.Icon>
|
||||
</AppBarToggleButton>
|
||||
|
||||
<AppBarButton x:Name="OutdentButton" Click="OutdentButton_Click" Label="Outdent" ToolTipService.ToolTip="Outdent">
|
||||
<AppBarButton
|
||||
x:Name="OutdentButton"
|
||||
Click="OutdentButton_Click"
|
||||
Label="Outdent"
|
||||
ToolTipService.ToolTip="Outdent">
|
||||
<AppBarButton.Icon>
|
||||
<PathIcon Data="{StaticResource DecreaseIndentPathIcon}" />
|
||||
</AppBarButton.Icon>
|
||||
</AppBarButton>
|
||||
|
||||
<AppBarButton x:Name="IndentButton" Click="IndentButton_Click" Label="Indent" ToolTipService.ToolTip="Indent">
|
||||
<AppBarButton
|
||||
x:Name="IndentButton"
|
||||
Click="IndentButton_Click"
|
||||
Label="Indent"
|
||||
ToolTipService.ToolTip="Indent">
|
||||
<AppBarButton.Icon>
|
||||
<PathIcon Data="{StaticResource IncreaseIndentPathIcon}" />
|
||||
</AppBarButton.Icon>
|
||||
</AppBarButton>
|
||||
|
||||
<AppBarElementContainer Style="{StaticResource CompactPickerContainerStyle}" ToolTipService.ToolTip="Text alignment">
|
||||
<StackPanel Orientation="Horizontal" Spacing="6">
|
||||
<PathIcon
|
||||
Width="14"
|
||||
Height="14"
|
||||
VerticalAlignment="Center"
|
||||
Data="{StaticResource AlignLeftPathIcon}" />
|
||||
<ComboBox
|
||||
x:Name="AlignmentComboBox"
|
||||
Style="{StaticResource CompactComboBoxStyle}"
|
||||
MinWidth="108"
|
||||
SelectionChanged="AlignmentComboBox_SelectionChanged" />
|
||||
</StackPanel>
|
||||
<Border Style="{StaticResource CompactPickerBorderStyle}">
|
||||
<Grid ColumnSpacing="8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="32" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<PathIcon
|
||||
Width="14"
|
||||
Height="14"
|
||||
Margin="10,0,0,0"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Data="{StaticResource AlignLeftPathIcon}"
|
||||
Foreground="{ThemeResource TextFillColorPrimaryBrush}" />
|
||||
<ComboBox
|
||||
x:Name="AlignmentComboBox"
|
||||
Grid.Column="1"
|
||||
MinWidth="94"
|
||||
SelectionChanged="AlignmentComboBox_SelectionChanged"
|
||||
Style="{StaticResource CompactComboBoxStyle}" />
|
||||
</Grid>
|
||||
</Border>
|
||||
</AppBarElementContainer>
|
||||
|
||||
<AppBarElementContainer Style="{StaticResource CompactPickerContainerStyle}" ToolTipService.ToolTip="Font family">
|
||||
<StackPanel Orientation="Horizontal" Spacing="6">
|
||||
<FontIcon VerticalAlignment="Center" FontSize="14" Glyph="" />
|
||||
<ComboBox
|
||||
x:Name="FontFamilyComboBox"
|
||||
Style="{StaticResource CompactComboBoxStyle}"
|
||||
MinWidth="120"
|
||||
PlaceholderText="Font"
|
||||
SelectionChanged="FontFamilyComboBox_SelectionChanged" />
|
||||
</StackPanel>
|
||||
</AppBarElementContainer>
|
||||
|
||||
<AppBarElementContainer Style="{StaticResource CompactPickerContainerStyle}" ToolTipService.ToolTip="Font size">
|
||||
<StackPanel Orientation="Horizontal" Spacing="6">
|
||||
<TextBlock VerticalAlignment="Center" FontWeight="SemiBold" Text="12" />
|
||||
<ComboBox
|
||||
x:Name="FontSizeComboBox"
|
||||
Style="{StaticResource CompactComboBoxStyle}"
|
||||
MinWidth="80"
|
||||
PlaceholderText="Size"
|
||||
SelectionChanged="FontSizeComboBox_SelectionChanged" />
|
||||
</StackPanel>
|
||||
<Border Style="{StaticResource CompactPickerBorderStyle}">
|
||||
<Grid ColumnSpacing="8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="32" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<FontIcon
|
||||
Margin="10,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="14"
|
||||
Glyph="" />
|
||||
<ComboBox
|
||||
x:Name="FontFamilyComboBox"
|
||||
Grid.Column="1"
|
||||
MinWidth="110"
|
||||
PlaceholderText="Font"
|
||||
SelectionChanged="FontFamilyComboBox_SelectionChanged"
|
||||
Style="{StaticResource CompactComboBoxStyle}" />
|
||||
<ComboBox
|
||||
x:Name="FontSizeComboBox"
|
||||
Grid.Column="2"
|
||||
MinWidth="72"
|
||||
HorizontalContentAlignment="Center"
|
||||
PlaceholderText="Size"
|
||||
SelectionChanged="FontSizeComboBox_SelectionChanged"
|
||||
Style="{StaticResource CompactComboBoxStyle}" />
|
||||
</Grid>
|
||||
</Border>
|
||||
</AppBarElementContainer>
|
||||
|
||||
<AppBarElementContainer Style="{StaticResource CompactPickerContainerStyle}" ToolTipService.ToolTip="Paragraph style">
|
||||
<StackPanel Orientation="Horizontal" Spacing="6">
|
||||
<PathIcon
|
||||
Width="14"
|
||||
Height="14"
|
||||
VerticalAlignment="Center"
|
||||
Data="{StaticResource ParagraphPathIcon}" />
|
||||
<ComboBox
|
||||
x:Name="ParagraphStyleComboBox"
|
||||
Style="{StaticResource CompactComboBoxStyle}"
|
||||
MinWidth="110"
|
||||
DisplayMemberPath="Name"
|
||||
PlaceholderText="Paragraph"
|
||||
SelectionChanged="ParagraphStyleComboBox_SelectionChanged" />
|
||||
</StackPanel>
|
||||
<Border Style="{StaticResource CompactPickerBorderStyle}">
|
||||
<Grid ColumnSpacing="8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="32" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<PathIcon
|
||||
Width="14"
|
||||
Height="14"
|
||||
Margin="10,0,0,0"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Data="{StaticResource ParagraphPathIcon}"
|
||||
Foreground="{ThemeResource TextFillColorPrimaryBrush}" />
|
||||
<ComboBox
|
||||
x:Name="ParagraphStyleComboBox"
|
||||
Grid.Column="1"
|
||||
MinWidth="104"
|
||||
DisplayMemberPath="Name"
|
||||
PlaceholderText="Paragraph"
|
||||
SelectionChanged="ParagraphStyleComboBox_SelectionChanged"
|
||||
Style="{StaticResource CompactComboBoxStyle}" />
|
||||
</Grid>
|
||||
</Border>
|
||||
</AppBarElementContainer>
|
||||
|
||||
<AppBarElementContainer Style="{StaticResource CompactPickerContainerStyle}" ToolTipService.ToolTip="Text color">
|
||||
<StackPanel Orientation="Horizontal" Spacing="6">
|
||||
<TextBlock VerticalAlignment="Center" FontWeight="SemiBold" Text="A" />
|
||||
<ComboBox
|
||||
x:Name="TextColorComboBox"
|
||||
Style="{StaticResource CompactComboBoxStyle}"
|
||||
MinWidth="116"
|
||||
ItemTemplate="{StaticResource ColorOptionTemplate}"
|
||||
PlaceholderText="Text"
|
||||
SelectionChanged="TextColorComboBox_SelectionChanged" />
|
||||
</StackPanel>
|
||||
<Border Style="{StaticResource CompactPickerBorderStyle}">
|
||||
<Grid ColumnSpacing="8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="32" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid
|
||||
Width="18"
|
||||
Height="18"
|
||||
Margin="8,0,0,0"
|
||||
VerticalAlignment="Center">
|
||||
<Rectangle
|
||||
Fill="{x:Bind SelectedTextColorBrush, Mode=OneWay}"
|
||||
RadiusX="4"
|
||||
RadiusY="4"
|
||||
Stroke="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
StrokeThickness="1" />
|
||||
<TextBlock
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="11"
|
||||
FontWeight="SemiBold"
|
||||
Text="A" />
|
||||
</Grid>
|
||||
<ComboBox
|
||||
x:Name="TextColorComboBox"
|
||||
Grid.Column="1"
|
||||
MinWidth="104"
|
||||
ItemTemplate="{StaticResource ColorOptionTemplate}"
|
||||
PlaceholderText="Text"
|
||||
SelectionChanged="TextColorComboBox_SelectionChanged"
|
||||
Style="{StaticResource CompactComboBoxStyle}" />
|
||||
</Grid>
|
||||
</Border>
|
||||
</AppBarElementContainer>
|
||||
|
||||
<AppBarElementContainer Style="{StaticResource CompactPickerContainerStyle}" ToolTipService.ToolTip="Highlight color">
|
||||
<StackPanel Orientation="Horizontal" Spacing="6">
|
||||
<FontIcon VerticalAlignment="Center" FontSize="14" Glyph="" />
|
||||
<ComboBox
|
||||
x:Name="HighlightColorComboBox"
|
||||
Style="{StaticResource CompactComboBoxStyle}"
|
||||
MinWidth="122"
|
||||
ItemTemplate="{StaticResource ColorOptionTemplate}"
|
||||
PlaceholderText="Highlight"
|
||||
SelectionChanged="HighlightColorComboBox_SelectionChanged" />
|
||||
</StackPanel>
|
||||
<Border Style="{StaticResource CompactPickerBorderStyle}">
|
||||
<Grid ColumnSpacing="8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="32" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid
|
||||
Width="18"
|
||||
Height="18"
|
||||
Margin="8,0,0,0"
|
||||
VerticalAlignment="Center">
|
||||
<Rectangle
|
||||
Fill="{x:Bind SelectedHighlightColorBrush, Mode=OneWay}"
|
||||
RadiusX="4"
|
||||
RadiusY="4"
|
||||
Stroke="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
StrokeThickness="1" />
|
||||
<Rectangle
|
||||
Width="10"
|
||||
Height="2"
|
||||
Margin="0,0,0,3"
|
||||
VerticalAlignment="Bottom"
|
||||
Fill="{ThemeResource TextFillColorPrimaryBrush}" />
|
||||
</Grid>
|
||||
<ComboBox
|
||||
x:Name="HighlightColorComboBox"
|
||||
Grid.Column="1"
|
||||
MinWidth="108"
|
||||
ItemTemplate="{StaticResource ColorOptionTemplate}"
|
||||
PlaceholderText="Highlight"
|
||||
SelectionChanged="HighlightColorComboBox_SelectionChanged"
|
||||
Style="{StaticResource CompactComboBoxStyle}" />
|
||||
</Grid>
|
||||
</Border>
|
||||
</AppBarElementContainer>
|
||||
|
||||
<AppBarElementContainer Style="{StaticResource CompactPickerContainerStyle}" ToolTipService.ToolTip="Line height">
|
||||
<StackPanel Orientation="Horizontal" Spacing="6">
|
||||
<FontIcon VerticalAlignment="Center" FontSize="14" Glyph="" />
|
||||
<ComboBox
|
||||
x:Name="LineHeightComboBox"
|
||||
Style="{StaticResource CompactComboBoxStyle}"
|
||||
MinWidth="86"
|
||||
PlaceholderText="Line"
|
||||
SelectionChanged="LineHeightComboBox_SelectionChanged" />
|
||||
</StackPanel>
|
||||
<Border Style="{StaticResource CompactPickerBorderStyle}">
|
||||
<Grid ColumnSpacing="8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="32" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<FontIcon
|
||||
Margin="9,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="14"
|
||||
Glyph="" />
|
||||
<ComboBox
|
||||
x:Name="LineHeightComboBox"
|
||||
Grid.Column="1"
|
||||
MinWidth="72"
|
||||
PlaceholderText="Line"
|
||||
SelectionChanged="LineHeightComboBox_SelectionChanged"
|
||||
Style="{StaticResource CompactComboBoxStyle}" />
|
||||
</Grid>
|
||||
</Border>
|
||||
</AppBarElementContainer>
|
||||
</toolkit:TabbedCommandBarItem>
|
||||
|
||||
<toolkit:TabbedCommandBarItem DefaultLabelPosition="Collapsed" Header="Insert">
|
||||
<AppBarButton x:Name="ImageButton" Click="ImageButton_Click" Label="Image" ToolTipService.ToolTip="Insert image">
|
||||
<AppBarButton
|
||||
x:Name="ImageButton"
|
||||
Click="ImageButton_Click"
|
||||
Label="Image"
|
||||
ToolTipService.ToolTip="Insert image">
|
||||
<AppBarButton.Icon>
|
||||
<PathIcon Data="{StaticResource AddPhotoPathIcon}" />
|
||||
</AppBarButton.Icon>
|
||||
</AppBarButton>
|
||||
|
||||
<AppBarButton x:Name="EmojiButton" Click="EmojiButton_Click" Label="Emoji" ToolTipService.ToolTip="Insert emoji">
|
||||
<AppBarButton
|
||||
x:Name="EmojiButton"
|
||||
Click="EmojiButton_Click"
|
||||
Label="Emoji"
|
||||
ToolTipService.ToolTip="Insert emoji">
|
||||
<AppBarButton.Icon>
|
||||
<PathIcon Data="{StaticResource EmojiPathIcon}" />
|
||||
</AppBarButton.Icon>
|
||||
</AppBarButton>
|
||||
|
||||
<AppBarButton x:Name="LinkButton" Click="LinkButton_Click" Label="Link" ToolTipService.ToolTip="Insert or edit link">
|
||||
<AppBarButton
|
||||
x:Name="LinkButton"
|
||||
Click="LinkButton_Click"
|
||||
Label="Link"
|
||||
ToolTipService.ToolTip="Insert or edit link">
|
||||
<AppBarButton.Icon>
|
||||
<PathIcon Data="{StaticResource AddLinkPathIcon}" />
|
||||
</AppBarButton.Icon>
|
||||
@@ -224,7 +379,11 @@
|
||||
</AppBarButton.Icon>
|
||||
</AppBarButton>
|
||||
|
||||
<AppBarButton x:Name="TableButton" Click="TableButton_Click" Label="Table" ToolTipService.ToolTip="Insert table">
|
||||
<AppBarButton
|
||||
x:Name="TableButton"
|
||||
Click="TableButton_Click"
|
||||
Label="Table"
|
||||
ToolTipService.ToolTip="Insert table">
|
||||
<AppBarButton.Icon>
|
||||
<FontIcon Glyph="" />
|
||||
</AppBarButton.Icon>
|
||||
@@ -236,13 +395,21 @@
|
||||
</toolkit:TabbedCommandBarItem>
|
||||
|
||||
<toolkit:TabbedCommandBarItem DefaultLabelPosition="Collapsed" Header="Options">
|
||||
<AppBarToggleButton x:Name="BuiltInToolbarButton" Click="BuiltInToolbarButton_Click" Label="Web toolbar" ToolTipService.ToolTip="Toggle built-in web toolbar">
|
||||
<AppBarToggleButton
|
||||
x:Name="BuiltInToolbarButton"
|
||||
Click="BuiltInToolbarButton_Click"
|
||||
Label="Web toolbar"
|
||||
ToolTipService.ToolTip="Toggle built-in web toolbar">
|
||||
<AppBarToggleButton.Icon>
|
||||
<PathIcon Data="{StaticResource WebviewToolBarPathIcon}" />
|
||||
</AppBarToggleButton.Icon>
|
||||
</AppBarToggleButton>
|
||||
|
||||
<AppBarToggleButton x:Name="SpellCheckButton" Click="SpellCheckButton_Click" Label="Spell check" ToolTipService.ToolTip="Toggle spell check">
|
||||
<AppBarToggleButton
|
||||
x:Name="SpellCheckButton"
|
||||
Click="SpellCheckButton_Click"
|
||||
Label="Spell check"
|
||||
ToolTipService.ToolTip="Toggle spell check">
|
||||
<AppBarToggleButton.Icon>
|
||||
<FontIcon Glyph="" />
|
||||
</AppBarToggleButton.Icon>
|
||||
|
||||
@@ -2,63 +2,42 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using CommunityToolkit.WinUI;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
using Windows.UI;
|
||||
|
||||
namespace Wino.Mail.Controls;
|
||||
|
||||
public sealed partial class EditorTabbedCommandBarControl : UserControl, IEditorCommandControl
|
||||
{
|
||||
public static readonly DependencyProperty CommandTargetProperty = DependencyProperty.Register(
|
||||
nameof(CommandTarget),
|
||||
typeof(IEditorCommandTarget),
|
||||
typeof(EditorTabbedCommandBarControl),
|
||||
new PropertyMetadata(null, OnCommandTargetChanged));
|
||||
[GeneratedDependencyProperty]
|
||||
public partial IEditorCommandTarget? CommandTarget { get; set; }
|
||||
|
||||
public static readonly DependencyProperty PaneCustomContentProperty = DependencyProperty.Register(
|
||||
nameof(PaneCustomContent),
|
||||
typeof(object),
|
||||
typeof(EditorTabbedCommandBarControl),
|
||||
new PropertyMetadata(null));
|
||||
[GeneratedDependencyProperty]
|
||||
public partial object? PaneCustomContent { get; set; }
|
||||
|
||||
public static readonly DependencyProperty InsertCustomContentProperty = DependencyProperty.Register(
|
||||
nameof(InsertCustomContent),
|
||||
typeof(object),
|
||||
typeof(EditorTabbedCommandBarControl),
|
||||
new PropertyMetadata(null));
|
||||
[GeneratedDependencyProperty]
|
||||
public partial object? InsertCustomContent { get; set; }
|
||||
|
||||
public static readonly DependencyProperty OptionsCustomContentProperty = DependencyProperty.Register(
|
||||
nameof(OptionsCustomContent),
|
||||
typeof(object),
|
||||
typeof(EditorTabbedCommandBarControl),
|
||||
new PropertyMetadata(null));
|
||||
[GeneratedDependencyProperty]
|
||||
public partial object? OptionsCustomContent { get; set; }
|
||||
|
||||
[GeneratedDependencyProperty]
|
||||
public partial EditorColorOption? SelectedTextColorOption { get; set; }
|
||||
|
||||
[GeneratedDependencyProperty]
|
||||
public partial EditorColorOption? SelectedHighlightColorOption { get; set; }
|
||||
|
||||
private bool _isApplyingState;
|
||||
private IEditorCommandTarget? _subscribedTarget;
|
||||
private static readonly SolidColorBrush TransparentBrush = new(EditorColorOption.ParseColorValue(null));
|
||||
private IReadOnlyList<EditorColorOption> _textColorOptions = Array.Empty<EditorColorOption>();
|
||||
private IReadOnlyList<EditorColorOption> _highlightColorOptions = Array.Empty<EditorColorOption>();
|
||||
|
||||
public IEditorCommandTarget? CommandTarget
|
||||
{
|
||||
get => (IEditorCommandTarget?)GetValue(CommandTargetProperty);
|
||||
set => SetValue(CommandTargetProperty, value);
|
||||
}
|
||||
|
||||
public object? PaneCustomContent
|
||||
{
|
||||
get => GetValue(PaneCustomContentProperty);
|
||||
set => SetValue(PaneCustomContentProperty, value);
|
||||
}
|
||||
|
||||
public object? InsertCustomContent
|
||||
{
|
||||
get => GetValue(InsertCustomContentProperty);
|
||||
set => SetValue(InsertCustomContentProperty, value);
|
||||
}
|
||||
|
||||
public object? OptionsCustomContent
|
||||
{
|
||||
get => GetValue(OptionsCustomContentProperty);
|
||||
set => SetValue(OptionsCustomContentProperty, value);
|
||||
}
|
||||
public Brush SelectedTextColorBrush => SelectedTextColorOption?.Brush ?? TransparentBrush;
|
||||
public Brush SelectedHighlightColorBrush => SelectedHighlightColorOption?.Brush ?? TransparentBrush;
|
||||
|
||||
public EditorTabbedCommandBarControl()
|
||||
{
|
||||
@@ -104,12 +83,15 @@ public sealed partial class EditorTabbedCommandBarControl : UserControl, IEditor
|
||||
_subscribedTarget = null;
|
||||
}
|
||||
|
||||
private static void OnCommandTargetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
partial void OnCommandTargetChanged(IEditorCommandTarget? newValue)
|
||||
{
|
||||
var control = (EditorTabbedCommandBarControl)d;
|
||||
control.AttachCommandTarget((IEditorCommandTarget?)e.NewValue);
|
||||
AttachCommandTarget(newValue);
|
||||
}
|
||||
|
||||
partial void OnSelectedTextColorOptionChanged(EditorColorOption? newValue) => Bindings.Update();
|
||||
|
||||
partial void OnSelectedHighlightColorOptionChanged(EditorColorOption? newValue) => Bindings.Update();
|
||||
|
||||
private void OnLoaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
AttachCommandTarget(CommandTarget);
|
||||
@@ -136,8 +118,10 @@ public sealed partial class EditorTabbedCommandBarControl : UserControl, IEditor
|
||||
FontSizeComboBox.ItemsSource = capabilities.FontSizes;
|
||||
AlignmentComboBox.ItemsSource = capabilities.Alignments;
|
||||
ParagraphStyleComboBox.ItemsSource = capabilities.ParagraphStyles;
|
||||
TextColorComboBox.ItemsSource = capabilities.TextColors;
|
||||
HighlightColorComboBox.ItemsSource = capabilities.HighlightColors;
|
||||
_textColorOptions = capabilities.TextColors;
|
||||
_highlightColorOptions = capabilities.HighlightColors;
|
||||
TextColorComboBox.ItemsSource = _textColorOptions;
|
||||
HighlightColorComboBox.ItemsSource = _highlightColorOptions;
|
||||
LineHeightComboBox.ItemsSource = capabilities.LineHeights;
|
||||
}
|
||||
|
||||
@@ -163,8 +147,10 @@ public sealed partial class EditorTabbedCommandBarControl : UserControl, IEditor
|
||||
FontSizeComboBox.SelectedItem = MatchValueItem<int>(FontSizeComboBox.ItemsSource, state.FontSize);
|
||||
LineHeightComboBox.SelectedItem = MatchStringItem(LineHeightComboBox.ItemsSource, state.LineHeight);
|
||||
ParagraphStyleComboBox.SelectedItem = MatchParagraphItem(state.ParagraphStyle);
|
||||
TextColorComboBox.SelectedItem = MatchColorItem(TextColorComboBox.ItemsSource, state.TextColor);
|
||||
HighlightColorComboBox.SelectedItem = MatchColorItem(HighlightColorComboBox.ItemsSource, state.HighlightColor);
|
||||
SelectedTextColorOption = ResolveColorOption(_textColorOptions, state.TextColor);
|
||||
SelectedHighlightColorOption = ResolveColorOption(_highlightColorOptions, state.HighlightColor);
|
||||
TextColorComboBox.SelectedItem = SelectedTextColorOption;
|
||||
HighlightColorComboBox.SelectedItem = SelectedHighlightColorOption;
|
||||
|
||||
_isApplyingState = false;
|
||||
}
|
||||
@@ -207,14 +193,54 @@ public sealed partial class EditorTabbedCommandBarControl : UserControl, IEditor
|
||||
return styles.FirstOrDefault(item => string.Equals(item.Tag, tag, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
private static object? MatchColorItem(object? itemsSource, string? value)
|
||||
private static EditorColorOption? MatchColorItem(IEnumerable<EditorColorOption> colors, string? value)
|
||||
{
|
||||
if (itemsSource is not IEnumerable<EditorColorOption> colors)
|
||||
var normalizedValue = value ?? string.Empty;
|
||||
var matchedByValue = colors.FirstOrDefault(item => string.Equals(item.Value, normalizedValue, StringComparison.OrdinalIgnoreCase));
|
||||
if (matchedByValue != null)
|
||||
{
|
||||
return null;
|
||||
return matchedByValue;
|
||||
}
|
||||
|
||||
return colors.FirstOrDefault(item => string.Equals(item.Value, value ?? string.Empty, StringComparison.OrdinalIgnoreCase));
|
||||
var targetColor = EditorColorOption.ParseColorValue(value);
|
||||
return colors.FirstOrDefault(item => item.Brush.Color.Equals(targetColor));
|
||||
}
|
||||
|
||||
private static EditorColorOption? ResolveColorOption(IEnumerable<EditorColorOption> colors, string? value)
|
||||
{
|
||||
var colorOptions = colors.ToList();
|
||||
var matchedColor = MatchColorItem(colors, value);
|
||||
if (matchedColor != null)
|
||||
{
|
||||
return matchedColor;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
return colorOptions.FirstOrDefault(item => string.IsNullOrWhiteSpace(item.Value));
|
||||
}
|
||||
|
||||
var targetColor = EditorColorOption.ParseColorValue(value);
|
||||
var selectableColors = colorOptions
|
||||
.Where(item => !string.IsNullOrWhiteSpace(item.Value))
|
||||
.ToList();
|
||||
|
||||
if (selectableColors.Count == 0)
|
||||
{
|
||||
return colorOptions.FirstOrDefault();
|
||||
}
|
||||
|
||||
return selectableColors
|
||||
.OrderBy(item => GetColorDistance(item.Brush.Color, targetColor))
|
||||
.First();
|
||||
}
|
||||
|
||||
private static int GetColorDistance(Color left, Color right)
|
||||
{
|
||||
var redDiff = left.R - right.R;
|
||||
var greenDiff = left.G - right.G;
|
||||
var blueDiff = left.B - right.B;
|
||||
return (redDiff * redDiff) + (greenDiff * greenDiff) + (blueDiff * blueDiff);
|
||||
}
|
||||
|
||||
private async Task ExecuteAsync(EditorCommand command)
|
||||
@@ -281,22 +307,26 @@ public sealed partial class EditorTabbedCommandBarControl : UserControl, IEditor
|
||||
|
||||
private async void TextColorComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (_isApplyingState || TextColorComboBox.SelectedItem is not EditorColorOption color)
|
||||
SelectedTextColorOption = TextColorComboBox.SelectedItem as EditorColorOption;
|
||||
|
||||
if (_isApplyingState || SelectedTextColorOption == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
await ExecuteAsync(EditorCommand.SetTextColor(color.Value));
|
||||
await ExecuteAsync(EditorCommand.SetTextColor(SelectedTextColorOption.Value));
|
||||
}
|
||||
|
||||
private async void HighlightColorComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (_isApplyingState || HighlightColorComboBox.SelectedItem is not EditorColorOption color)
|
||||
SelectedHighlightColorOption = HighlightColorComboBox.SelectedItem as EditorColorOption;
|
||||
|
||||
if (_isApplyingState || SelectedHighlightColorOption == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
await ExecuteAsync(EditorCommand.SetHighlightColor(color.Value));
|
||||
await ExecuteAsync(EditorCommand.SetHighlightColor(SelectedHighlightColorOption.Value));
|
||||
}
|
||||
|
||||
private async void LineHeightComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
@@ -412,6 +442,7 @@ public sealed partial class EditorTabbedCommandBarControl : UserControl, IEditor
|
||||
await ExecuteAsync(EditorCommand.InsertTable(new EditorTableCommandArgs((int)Math.Max(1, rowsBox.Value), (int)Math.Max(1, columnsBox.Value))));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
@@ -392,7 +393,9 @@ public sealed partial class WebViewEditorControl : Control, IDisposable, IEditor
|
||||
JsonSerializer.Serialize(_preferencesService.ComposerFont, BasicTypesJsonContext.Default.String),
|
||||
JsonSerializer.Serialize(_preferencesService.ComposerFontSize, BasicTypesJsonContext.Default.Int32),
|
||||
JsonSerializer.Serialize(_preferencesService.ReaderFont, BasicTypesJsonContext.Default.String),
|
||||
JsonSerializer.Serialize(_preferencesService.ReaderFontSize, BasicTypesJsonContext.Default.Int32));
|
||||
JsonSerializer.Serialize(_preferencesService.ReaderFontSize, BasicTypesJsonContext.Default.Int32),
|
||||
JsonSerializer.Serialize(DefaultTextColors.Select(option => option.Value).Where(value => !string.IsNullOrWhiteSpace(value)).ToList(), BasicTypesJsonContext.Default.ListString),
|
||||
JsonSerializer.Serialize(DefaultHighlightColors.Select(option => option.Value).Where(value => !string.IsNullOrWhiteSpace(value)).ToList(), BasicTypesJsonContext.Default.ListString));
|
||||
|
||||
UpdateCapabilities(BuildCapabilities(fonts));
|
||||
_editorReadyTask.TrySetResult(true);
|
||||
|
||||
Reference in New Issue
Block a user