@ -0,0 +1,5 @@ |
|||
<ProjectConfiguration> |
|||
<Settings> |
|||
<IgnoreThisComponentCompletely>False</IgnoreThisComponentCompletely> |
|||
</Settings> |
|||
</ProjectConfiguration> |
|||
@ -0,0 +1,8 @@ |
|||
<ProjectConfiguration> |
|||
<Settings> |
|||
<CustomBuildProperties> |
|||
<Value>TargetFramework = netstandard2.0</Value> |
|||
</CustomBuildProperties> |
|||
<IgnoreThisComponentCompletely>False</IgnoreThisComponentCompletely> |
|||
</Settings> |
|||
</ProjectConfiguration> |
|||
@ -0,0 +1,5 @@ |
|||
<ProjectConfiguration> |
|||
<Settings> |
|||
<IgnoreThisComponentCompletely>False</IgnoreThisComponentCompletely> |
|||
</Settings> |
|||
</ProjectConfiguration> |
|||
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 9.9 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 361 KiB |
|
After Width: | Height: | Size: 820 B |
|
Before Width: | Height: | Size: 172 KiB After Width: | Height: | Size: 361 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 124 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 118 KiB |
|
After Width: | Height: | Size: 82 KiB |
|
After Width: | Height: | Size: 91 KiB |
|
After Width: | Height: | Size: 165 KiB |
|
Before Width: | Height: | Size: 172 KiB |
@ -0,0 +1,24 @@ |
|||
using System; |
|||
using System.Globalization; |
|||
using Avalonia; |
|||
using Avalonia.Data.Converters; |
|||
|
|||
namespace ControlCatalog.Converter |
|||
{ |
|||
internal sealed class FlexDemoNumberToThicknessConverter : IValueConverter |
|||
{ |
|||
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) |
|||
{ |
|||
if (value is int x && targetType.IsAssignableFrom(typeof(Thickness))) |
|||
{ |
|||
var y = 16 + 2 * ((x * 5) % 9); |
|||
return new Thickness(2 * y, y); |
|||
} |
|||
|
|||
throw new NotSupportedException(); |
|||
} |
|||
|
|||
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) => |
|||
throw new NotSupportedException(); |
|||
} |
|||
} |
|||
@ -0,0 +1,10 @@ |
|||
using System.Collections.Generic; |
|||
using ControlCatalog.ViewModels; |
|||
|
|||
namespace ControlCatalog.Models; |
|||
|
|||
public class HomeSection(string title, IReadOnlyList<PageItem> items) |
|||
{ |
|||
public string Title { get; } = title; |
|||
public IReadOnlyList<PageItem> Items { get; } = items; |
|||
} |
|||
@ -0,0 +1,53 @@ |
|||
using System; |
|||
using System.Globalization; |
|||
using System.Text; |
|||
using Avalonia.Controls; |
|||
using Avalonia.Media; |
|||
|
|||
namespace ControlCatalog.Models; |
|||
|
|||
public class PageItem(string header, Func<Page> factory, StreamGeometry iconData, string description, string section) |
|||
{ |
|||
public string Header { get; } = header; |
|||
public StreamGeometry? IconData { get; } = iconData; |
|||
public string? Description { get; } = description; |
|||
private string SearchKey { get; } = CreateSearchKey(header, section); |
|||
|
|||
public bool IsVisible { get; set; } = true; |
|||
|
|||
public Page CreatePage() => factory(); |
|||
|
|||
public bool MatchesSearch(string searchKey) |
|||
{ |
|||
return SearchKey.Contains(searchKey, StringComparison.Ordinal); |
|||
} |
|||
|
|||
public static string CreateSearchKey(params ReadOnlySpan<string> values) |
|||
{ |
|||
var builder = new StringBuilder(256); |
|||
|
|||
foreach (var value in values) |
|||
{ |
|||
var normalizedValue = value.Normalize(NormalizationForm.FormKD); |
|||
|
|||
foreach (var c in normalizedValue) |
|||
{ |
|||
var category = CharUnicodeInfo.GetUnicodeCategory(c); |
|||
|
|||
if (category is UnicodeCategory.NonSpacingMark or |
|||
UnicodeCategory.SpacingCombiningMark or |
|||
UnicodeCategory.EnclosingMark) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
if (char.IsLetterOrDigit(c)) |
|||
{ |
|||
builder.Append(char.ToUpperInvariant(c)); |
|||
} |
|||
} |
|||
} |
|||
|
|||
return builder.ToString(); |
|||
} |
|||
} |
|||
@ -0,0 +1,218 @@ |
|||
<ContentPage xmlns="https://github.com/avaloniaui" |
|||
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:conv="using:ControlCatalog.Converter" |
|||
xmlns:vm="using:ControlCatalog.ViewModels" |
|||
mc:Ignorable="d" |
|||
d:DesignWidth="800" |
|||
d:DesignHeight="450" |
|||
x:DataType="vm:FlexViewModel" |
|||
HorizontalContentAlignment="Stretch" |
|||
VerticalContentAlignment="Stretch" |
|||
x:Class="ControlCatalog.Pages.FlexPage"> |
|||
<ContentPage.Resources> |
|||
<conv:FlexDemoNumberToThicknessConverter x:Key="NumberToThicknessConverter" /> |
|||
<DataTemplate x:Key="ItemTemplate" |
|||
x:DataType="vm:FlexItemViewModel"> |
|||
<ListBoxItem Padding="{Binding Value, Converter={StaticResource NumberToThicknessConverter}}" |
|||
IsSelected="{Binding IsSelected}" |
|||
Background="{Binding Color}" |
|||
Tapped="OnItemTapped"> |
|||
<ListBoxItem.Styles> |
|||
<Style Selector="ListBoxItem:selected"> |
|||
<Setter Property="Background" Value="DodgerBlue" /> |
|||
</Style> |
|||
</ListBoxItem.Styles> |
|||
<TextBlock HorizontalAlignment="Center" |
|||
VerticalAlignment="Center" |
|||
Text="{Binding Value}" /> |
|||
</ListBoxItem> |
|||
</DataTemplate> |
|||
</ContentPage.Resources> |
|||
<ContentPage.Styles> |
|||
<Style Selector="CheckBox"> |
|||
<Setter Property="MinWidth" Value="0" /> |
|||
<Setter Property="Padding" Value="8,0,0,0" /> |
|||
<Setter Property="VerticalContentAlignment" Value="Center" /> |
|||
</Style> |
|||
<Style Selector="ComboBox"> |
|||
<Setter Property="HorizontalAlignment" Value="Stretch" /> |
|||
</Style> |
|||
<Style Selector="RadioButton"> |
|||
<Setter Property="MinWidth" Value="0" /> |
|||
<Setter Property="Padding" Value="8,0,0,0" /> |
|||
<Setter Property="VerticalContentAlignment" Value="Center" /> |
|||
</Style> |
|||
</ContentPage.Styles> |
|||
|
|||
<DockPanel Margin="16"> |
|||
|
|||
<ScrollViewer HorizontalScrollBarVisibility="Disabled" |
|||
Padding="0,0,16,0" |
|||
MinWidth="200"> |
|||
|
|||
<StackPanel Spacing="16"> |
|||
|
|||
<TextBlock FontSize="16" |
|||
Text="Properties" /> |
|||
|
|||
<!--<panels:FlexPanel ColumnSpacing="16"> |
|||
<RadioButton IsChecked="{Binding IsItemsControl}" |
|||
Content="ItemsControl" /> |
|||
<RadioButton IsChecked="{Binding IsItemsRepeater}" |
|||
Content="ItemsRepeater" /> |
|||
</panels:FlexPanel>--> |
|||
|
|||
<StackPanel Spacing="8"> |
|||
<TextBlock Text="Direction:" /> |
|||
<ComboBox ItemsSource="{Binding DirectionValues}" |
|||
SelectedItem="{Binding Direction}" /> |
|||
</StackPanel> |
|||
|
|||
<StackPanel Spacing="8"> |
|||
<TextBlock Text="JustifyContent:" /> |
|||
<ComboBox ItemsSource="{Binding JustifyContentValues}" |
|||
SelectedItem="{Binding JustifyContent}" /> |
|||
</StackPanel> |
|||
|
|||
<StackPanel Spacing="8"> |
|||
<TextBlock Text="AlignItems:" /> |
|||
<ComboBox ItemsSource="{Binding AlignItemsValues}" |
|||
SelectedItem="{Binding AlignItems}" /> |
|||
</StackPanel> |
|||
|
|||
<StackPanel Spacing="8"> |
|||
<TextBlock Text="AlignContent:" /> |
|||
<ComboBox ItemsSource="{Binding AlignContentValues}" |
|||
SelectedItem="{Binding AlignContent}" /> |
|||
</StackPanel> |
|||
|
|||
<StackPanel Spacing="8"> |
|||
<TextBlock Text="Wrap:" /> |
|||
<ComboBox ItemsSource="{Binding WrapValues}" |
|||
SelectedItem="{Binding Wrap}" /> |
|||
</StackPanel> |
|||
|
|||
<StackPanel Spacing="8"> |
|||
<TextBlock Text="ColumnSpacing:" /> |
|||
<NumericUpDown Minimum="0" |
|||
Value="{Binding ColumnSpacing}" /> |
|||
</StackPanel> |
|||
|
|||
<StackPanel Spacing="8"> |
|||
<TextBlock Text="RowSpacing:" /> |
|||
<NumericUpDown Minimum="0" |
|||
Value="{Binding RowSpacing}" /> |
|||
</StackPanel> |
|||
|
|||
<CheckBox IsEnabled="{Binding SelectedItem, Converter={x:Static ObjectConverters.IsNotNull}}" |
|||
Content="SelectedItem IsVisible" |
|||
IsChecked="{Binding SelectedItem.IsVisible}" /> |
|||
|
|||
<StackPanel Spacing="8"> |
|||
<TextBlock Text="SelectedItem AlignSelf:" /> |
|||
<ComboBox IsEnabled="{Binding SelectedItem, Converter={x:Static ObjectConverters.IsNotNull}}" |
|||
ItemsSource="{Binding AlignSelfValues}" |
|||
SelectedItem="{Binding SelectedItem.AlignSelfItem}" /> |
|||
</StackPanel> |
|||
|
|||
<StackPanel Spacing="8"> |
|||
<TextBlock Text="SelectedItem Order:" /> |
|||
<NumericUpDown IsEnabled="{Binding SelectedItem, Converter={x:Static ObjectConverters.IsNotNull}}" |
|||
Value="{Binding SelectedItem.Order}" /> |
|||
</StackPanel> |
|||
|
|||
<StackPanel Spacing="8"> |
|||
<TextBlock Text="SelectedItem Shrink:" /> |
|||
<NumericUpDown Minimum="0.0" |
|||
IsEnabled="{Binding SelectedItem, Converter={x:Static ObjectConverters.IsNotNull}}" |
|||
Value="{Binding SelectedItem.Shrink}" /> |
|||
</StackPanel> |
|||
|
|||
<StackPanel Spacing="8"> |
|||
<TextBlock Text="SelectedItem Grow:" /> |
|||
<NumericUpDown Minimum="0.0" |
|||
IsEnabled="{Binding SelectedItem, Converter={x:Static ObjectConverters.IsNotNull}}" |
|||
Value="{Binding SelectedItem.Grow}" /> |
|||
</StackPanel> |
|||
|
|||
<StackPanel Spacing="8"> |
|||
<TextBlock Text="SelectedItem Basis:" /> |
|||
<ComboBox IsEnabled="{Binding SelectedItem, Converter={x:Static ObjectConverters.IsNotNull}}" |
|||
ItemsSource="{Binding FlexBasisKindValues}" |
|||
SelectedItem="{Binding SelectedItem.BasisKind}" /> |
|||
<NumericUpDown Minimum="0.0" |
|||
IsEnabled="{Binding SelectedItem, Converter={x:Static ObjectConverters.IsNotNull}}" |
|||
Value="{Binding SelectedItem.BasisValue}" /> |
|||
</StackPanel> |
|||
|
|||
<StackPanel Spacing="8"> |
|||
<TextBlock Text="SelectedItem HorizontalAlignment:" /> |
|||
<ComboBox IsEnabled="{Binding SelectedItem, Converter={x:Static ObjectConverters.IsNotNull}}" |
|||
ItemsSource="{Binding HorizontalAlignmentValues}" |
|||
SelectedItem="{Binding SelectedItem.HorizontalAlignment}" /> |
|||
</StackPanel> |
|||
|
|||
<StackPanel Spacing="8"> |
|||
<TextBlock Text="SelectedItem VerticalAlignment:" /> |
|||
<ComboBox IsEnabled="{Binding SelectedItem, Converter={x:Static ObjectConverters.IsNotNull}}" |
|||
ItemsSource="{Binding VerticalAlignmentValues}" |
|||
SelectedItem="{Binding SelectedItem.VerticalAlignment}" /> |
|||
</StackPanel> |
|||
|
|||
<Grid ColumnDefinitions="*,8,*"> |
|||
|
|||
<Button Grid.Column="0" |
|||
HorizontalAlignment="Stretch" |
|||
HorizontalContentAlignment="Center" |
|||
Command="{Binding AddItemCommand}" |
|||
Content="Add Item" /> |
|||
|
|||
<Button Grid.Column="2" |
|||
HorizontalAlignment="Stretch" |
|||
HorizontalContentAlignment="Center" |
|||
Command="{Binding RemoveItemCommand}" |
|||
Content="Remove Item" /> |
|||
|
|||
</Grid> |
|||
|
|||
</StackPanel> |
|||
|
|||
</ScrollViewer> |
|||
|
|||
<ItemsControl BorderBrush="#777" |
|||
BorderThickness="1" |
|||
ItemsSource="{Binding Numbers}" |
|||
ItemTemplate="{StaticResource ItemTemplate}"> |
|||
<ItemsControl.Styles> |
|||
<Style Selector="ContentPresenter" |
|||
x:DataType="vm:FlexItemViewModel"> |
|||
<Setter Property="Flex.AlignSelf" Value="{Binding AlignSelf}" /> |
|||
<Setter Property="Flex.Order" Value="{Binding Order}" /> |
|||
<Setter Property="Flex.Shrink" Value="{Binding Shrink}" /> |
|||
<Setter Property="Flex.Grow" Value="{Binding Grow}" /> |
|||
<Setter Property="Flex.Basis" Value="{Binding Basis}" /> |
|||
<Setter Property="HorizontalAlignment" Value="{Binding HorizontalAlignment}" /> |
|||
<Setter Property="VerticalAlignment" Value="{Binding VerticalAlignment}" /> |
|||
<Setter Property="IsVisible" Value="{Binding IsVisible}" /> |
|||
</Style> |
|||
</ItemsControl.Styles> |
|||
<ItemsControl.ItemsPanel> |
|||
<ItemsPanelTemplate> |
|||
<FlexPanel Direction="{Binding Direction}" |
|||
JustifyContent="{Binding JustifyContent}" |
|||
AlignItems="{Binding AlignItems}" |
|||
AlignContent="{Binding AlignContent}" |
|||
Wrap="{Binding Wrap}" |
|||
ColumnSpacing="{Binding ColumnSpacing}" |
|||
RowSpacing="{Binding RowSpacing}" /> |
|||
</ItemsPanelTemplate> |
|||
</ItemsControl.ItemsPanel> |
|||
</ItemsControl> |
|||
|
|||
</DockPanel> |
|||
|
|||
|
|||
|
|||
</ContentPage> |
|||
@ -0,0 +1,37 @@ |
|||
using Avalonia.Controls; |
|||
using Avalonia.Interactivity; |
|||
using ControlCatalog.ViewModels; |
|||
|
|||
namespace ControlCatalog.Pages |
|||
{ |
|||
public partial class FlexPage : ContentPage |
|||
{ |
|||
public FlexPage() |
|||
{ |
|||
InitializeComponent(); |
|||
|
|||
DataContext = new FlexViewModel(); |
|||
} |
|||
|
|||
private void OnItemTapped(object? sender, RoutedEventArgs e) |
|||
{ |
|||
if (sender is ListBoxItem control && DataContext is FlexViewModel vm && control.DataContext is FlexItemViewModel item) |
|||
{ |
|||
if (vm.SelectedItem != null) |
|||
{ |
|||
vm.SelectedItem.IsSelected = false; |
|||
} |
|||
|
|||
if (vm.SelectedItem == item) |
|||
{ |
|||
vm.SelectedItem = null; |
|||
} |
|||
else |
|||
{ |
|||
vm.SelectedItem = item; |
|||
vm.SelectedItem.IsSelected = true; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,152 @@ |
|||
<ContentPage Theme="{StaticResource ScrollPage}" |
|||
xmlns="https://github.com/avaloniaui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
|||
xmlns:viewModels="using:ControlCatalog.ViewModels" |
|||
xmlns:controlCatalog="using:ControlCatalog" |
|||
xmlns:models="clr-namespace:ControlCatalog.Models" |
|||
x:Class="ControlCatalog.Pages.HomePage" |
|||
Header="Home"> |
|||
|
|||
<ContentPage.Resources> |
|||
<ResourceDictionary> |
|||
<ResourceDictionary.ThemeDictionaries> |
|||
<ResourceDictionary x:Key="Default"> |
|||
<SolidColorBrush x:Key="HomeCardBackground" Color="#FFFFFF" /> |
|||
<SolidColorBrush x:Key="HomeCardBorderBrush" Color="#E5E5EA" /> |
|||
<SolidColorBrush x:Key="HomeCardBorderBrushHover" Color="#3E6DF3" /> |
|||
<SolidColorBrush x:Key="HomeSubtleForeground" Color="#64646E" /> |
|||
<SolidColorBrush x:Key="HomeBadgeBackground" Color="#E8EFFD" /> |
|||
<SolidColorBrush x:Key="HomeBadgeForeground" Color="#3462D9" /> |
|||
</ResourceDictionary> |
|||
<ResourceDictionary x:Key="Dark"> |
|||
<SolidColorBrush x:Key="HomeCardBackground" Color="#2B2B33" /> |
|||
<SolidColorBrush x:Key="HomeCardBorderBrush" Color="#3A3A45" /> |
|||
<SolidColorBrush x:Key="HomeCardBorderBrushHover" Color="#8AB4FF" /> |
|||
<SolidColorBrush x:Key="HomeSubtleForeground" Color="#9C9CAB" /> |
|||
<SolidColorBrush x:Key="HomeBadgeBackground" Color="#31395A" /> |
|||
<SolidColorBrush x:Key="HomeBadgeForeground" Color="#8AB4FF" /> |
|||
</ResourceDictionary> |
|||
</ResourceDictionary.ThemeDictionaries> |
|||
|
|||
<ControlTheme x:Key="ButtonCardTheme" TargetType="Button"> |
|||
<Setter Property="HorizontalAlignment" Value="Stretch" /> |
|||
<Setter Property="VerticalAlignment" Value="Stretch" /> |
|||
<Setter Property="Background" Value="{DynamicResource HomeCardBackground}" /> |
|||
<Setter Property="BorderBrush" Value="{DynamicResource HomeCardBorderBrush}" /> |
|||
<Setter Property="BorderThickness" Value="1" /> |
|||
<Setter Property="CornerRadius" Value="10" /> |
|||
<Setter Property="Padding" Value="16, 14" /> |
|||
<Setter Property="MinHeight" Value="118" /> |
|||
<Setter Property="Cursor" Value="Hand" /> |
|||
|
|||
<Style Selector="^ /template/ ContentPresenter"> |
|||
<Setter Property="BoxShadow" Value="0 1 3 0 #0D000000" /> |
|||
<Setter Property="Transitions"> |
|||
<Transitions> |
|||
<BrushTransition Property="BorderBrush" Duration="0:0:0.1" /> |
|||
</Transitions> |
|||
</Setter> |
|||
</Style> |
|||
|
|||
<Style Selector="^:pointerover /template/ ContentPresenter"> |
|||
<Setter Property="BorderBrush" Value="{DynamicResource HomeCardBorderBrushHover}" /> |
|||
</Style> |
|||
|
|||
</ControlTheme> |
|||
</ResourceDictionary> |
|||
</ContentPage.Resources> |
|||
|
|||
<StackPanel Spacing="28" Margin="0,0,15,20" HorizontalAlignment="Stretch" |
|||
DataContext="{Binding $parent[controlCatalog:MainView].((viewModels:MainWindowViewModel)DataContext)}"> |
|||
|
|||
<!-- Hero banner (1:1 from the Accelerate demo dashboard) --> |
|||
<Border CornerRadius="20" ClipToBounds="True" HorizontalAlignment="Stretch" Height="220"> |
|||
<Grid ClipToBounds="True"> |
|||
<Image Source="/Assets/banner-bg.png" |
|||
Stretch="UniformToFill" /> |
|||
<Canvas IsHitTestVisible="False"> |
|||
<Image x:Name="BannerLogo1" |
|||
Source="/Assets/logo1.png" |
|||
Width="230" |
|||
Stretch="Uniform" |
|||
Canvas.Left="-60" |
|||
Canvas.Bottom="-50" /> |
|||
<Image x:Name="BannerLogo2" |
|||
Source="/Assets/logo2.png" |
|||
Width="150" |
|||
Stretch="Uniform" |
|||
Canvas.Left="240" |
|||
Canvas.Top="-60" /> |
|||
<Image x:Name="BannerLogo3" |
|||
Source="/Assets/logo3.png" |
|||
Width="210" |
|||
Stretch="Uniform" |
|||
Canvas.Right="-70" |
|||
Canvas.Top="-50" /> |
|||
<Image x:Name="BannerLogo4" |
|||
Source="/Assets/logo4.png" |
|||
Width="170" |
|||
Stretch="Uniform" |
|||
Canvas.Right="40" |
|||
Canvas.Bottom="-60" /> |
|||
</Canvas> |
|||
<Image Source="/Assets/banner-logo.png" |
|||
Width="220" |
|||
HorizontalAlignment="Center" |
|||
VerticalAlignment="Center" /> |
|||
</Grid> |
|||
</Border> |
|||
|
|||
<!-- Card sections --> |
|||
<ItemsControl ItemsSource="{Binding HomeSections}"> |
|||
<ItemsControl.ItemTemplate> |
|||
<DataTemplate DataType="models:HomeSection"> |
|||
<StackPanel Spacing="14" Margin="0,0,0,26"> |
|||
<TextBlock Text="{Binding Title}" |
|||
FontSize="19" FontWeight="Bold" /> |
|||
<ItemsControl ItemsSource="{Binding Items}"> |
|||
<ItemsControl.ItemsPanel> |
|||
<ItemsPanelTemplate> |
|||
<UniformGrid RowSpacing="12" ColumnSpacing="12" |
|||
Margin="0, 0, 1, 0" |
|||
SizeChanged="UniformGrid_OnSizeChanged" /> |
|||
</ItemsPanelTemplate> |
|||
</ItemsControl.ItemsPanel> |
|||
<ItemsControl.ItemTemplate> |
|||
<DataTemplate DataType="models:PageItem"> |
|||
<Button Theme="{StaticResource ButtonCardTheme}" |
|||
Command="{Binding $parent[controlCatalog:MainView].((viewModels:MainWindowViewModel)DataContext).NavigateToPageCommand}" |
|||
CommandParameter="{Binding}"> |
|||
<StackPanel Spacing="10"> |
|||
<Border Background="{DynamicResource HomeBadgeBackground}" |
|||
CornerRadius="8" |
|||
Width="36" Height="36" |
|||
HorizontalAlignment="Left"> |
|||
<PathIcon Data="{Binding IconData}" |
|||
Foreground="{DynamicResource HomeBadgeForeground}" |
|||
Width="18" Height="18" |
|||
HorizontalAlignment="Center" |
|||
VerticalAlignment="Center" /> |
|||
</Border> |
|||
<StackPanel Spacing="3"> |
|||
<TextBlock Text="{Binding Header}" |
|||
FontSize="14" FontWeight="SemiBold" /> |
|||
<TextBlock Text="{Binding Description}" |
|||
FontSize="12" |
|||
Foreground="{DynamicResource HomeSubtleForeground}" |
|||
TextWrapping="Wrap" |
|||
TextTrimming="CharacterEllipsis" |
|||
MaxLines="2" /> |
|||
</StackPanel> |
|||
</StackPanel> |
|||
</Button> |
|||
</DataTemplate> |
|||
</ItemsControl.ItemTemplate> |
|||
</ItemsControl> |
|||
</StackPanel> |
|||
</DataTemplate> |
|||
</ItemsControl.ItemTemplate> |
|||
</ItemsControl> |
|||
|
|||
</StackPanel> |
|||
</ContentPage> |
|||
@ -0,0 +1,82 @@ |
|||
using System; |
|||
using Avalonia; |
|||
using Avalonia.Animation; |
|||
using Avalonia.Controls; |
|||
using Avalonia.Controls.Primitives; |
|||
using Avalonia.Media; |
|||
using Avalonia.Styling; |
|||
|
|||
namespace ControlCatalog.Pages; |
|||
|
|||
public partial class HomePage : ContentPage |
|||
{ |
|||
public HomePage() |
|||
{ |
|||
InitializeComponent(); |
|||
} |
|||
|
|||
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) |
|||
{ |
|||
base.OnAttachedToVisualTree(e); |
|||
|
|||
StartFloatingAnimation(BannerLogo1, 12, 8, TimeSpan.FromSeconds(12)); |
|||
StartFloatingAnimation(BannerLogo2, -14, 8, TimeSpan.FromSeconds(10)); |
|||
StartFloatingAnimation(BannerLogo3, -12, -12, TimeSpan.FromSeconds(14)); |
|||
StartFloatingAnimation(BannerLogo4, 12, -8, TimeSpan.FromSeconds(11)); |
|||
} |
|||
|
|||
private static void StartFloatingAnimation(Control target, double dx, double dy, TimeSpan duration) |
|||
{ |
|||
var transform = new TranslateTransform(); |
|||
target.RenderTransform = transform; |
|||
|
|||
var animation = new Animation |
|||
{ |
|||
Duration = duration, |
|||
IterationCount = IterationCount.Infinite, |
|||
Children = |
|||
{ |
|||
new KeyFrame |
|||
{ |
|||
Cue = new Cue(0d), |
|||
Setters = |
|||
{ |
|||
new Setter(TranslateTransform.XProperty, 0d), |
|||
new Setter(TranslateTransform.YProperty, 0d), |
|||
} |
|||
}, |
|||
new KeyFrame |
|||
{ |
|||
Cue = new Cue(0.5d), |
|||
Setters = |
|||
{ |
|||
new Setter(TranslateTransform.XProperty, dx), |
|||
new Setter(TranslateTransform.YProperty, dy), |
|||
} |
|||
}, |
|||
new KeyFrame |
|||
{ |
|||
Cue = new Cue(1d), |
|||
Setters = |
|||
{ |
|||
new Setter(TranslateTransform.XProperty, 0d), |
|||
new Setter(TranslateTransform.YProperty, 0d), |
|||
} |
|||
}, |
|||
} |
|||
}; |
|||
|
|||
_ = animation.RunAsync(target); |
|||
} |
|||
|
|||
private void UniformGrid_OnSizeChanged(object? sender, SizeChangedEventArgs e) |
|||
{ |
|||
if (sender is not UniformGrid grid) |
|||
return; |
|||
|
|||
const int minItemWidth = 248; |
|||
grid.Columns = Math.Max( |
|||
1, |
|||
(int)((e.NewSize.Width + grid.ColumnSpacing) / (minItemWidth + grid.ColumnSpacing))); |
|||
} |
|||
} |
|||
@ -0,0 +1,136 @@ |
|||
<ContentPage Theme="{StaticResource ScrollPage}" x:Class="ControlCatalog.Pages.PlatformSettingsPage" |
|||
xmlns="https://github.com/avaloniaui" |
|||
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:viewModels="using:ControlCatalog.ViewModels" |
|||
d:DesignHeight="800" |
|||
d:DesignWidth="600" |
|||
mc:Ignorable="d" |
|||
Header="Platform Settings" |
|||
x:DataType="viewModels:PlatformSettingsViewModel"> |
|||
|
|||
<StackPanel Spacing="20"> |
|||
|
|||
<TextBlock Text="This page displays IPlatformSettings values which may change at runtime based on system settings." |
|||
TextWrapping="Wrap" |
|||
Opacity="0.7" /> |
|||
|
|||
<GroupBox Header="System Color Values"> |
|||
<StackPanel Spacing="15"> |
|||
<Grid ColumnDefinitions="180,*" RowDefinitions="Auto,Auto"> |
|||
<TextBlock Grid.Column="0" Grid.Row="0" Text="Theme Variant:" VerticalAlignment="Center" /> |
|||
<TextBlock Grid.Column="1" Grid.Row="0" Text="{Binding ThemeVariant}" FontWeight="Bold" VerticalAlignment="Center" /> |
|||
|
|||
<TextBlock Grid.Column="0" Grid.Row="1" Text="Contrast Preference:" VerticalAlignment="Center" Margin="0,10,0,0" /> |
|||
<TextBlock Grid.Column="1" Grid.Row="1" Text="{Binding ContrastPreference}" FontWeight="Bold" VerticalAlignment="Center" Margin="0,10,0,0" /> |
|||
</Grid> |
|||
|
|||
<StackPanel Spacing="10"> |
|||
<Grid ColumnDefinitions="180,120,*"> |
|||
<TextBlock Grid.Column="0" Text="Accent Color 1:" VerticalAlignment="Center" /> |
|||
<Border Grid.Column="1" |
|||
Width="100" |
|||
Height="40" |
|||
BorderBrush="Black" |
|||
BorderThickness="1" |
|||
CornerRadius="4" |
|||
HorizontalAlignment="Left"> |
|||
<Border.Background> |
|||
<SolidColorBrush Color="{Binding AccentColor1}" /> |
|||
</Border.Background> |
|||
</Border> |
|||
<TextBlock Grid.Column="2" |
|||
Text="{Binding AccentColor1}" |
|||
VerticalAlignment="Center" |
|||
Margin="10,0,0,0" /> |
|||
</Grid> |
|||
|
|||
<Grid ColumnDefinitions="180,120,*"> |
|||
<TextBlock Grid.Column="0" Text="Accent Color 2:" VerticalAlignment="Center" /> |
|||
<Border Grid.Column="1" |
|||
Width="100" |
|||
Height="40" |
|||
BorderBrush="Black" |
|||
BorderThickness="1" |
|||
CornerRadius="4" |
|||
HorizontalAlignment="Left"> |
|||
<Border.Background> |
|||
<SolidColorBrush Color="{Binding AccentColor2}" /> |
|||
</Border.Background> |
|||
</Border> |
|||
<TextBlock Grid.Column="2" |
|||
Text="{Binding AccentColor2}" |
|||
VerticalAlignment="Center" |
|||
Margin="10,0,0,0" /> |
|||
</Grid> |
|||
|
|||
<Grid ColumnDefinitions="180,120,*"> |
|||
<TextBlock Grid.Column="0" Text="Accent Color 3:" VerticalAlignment="Center" /> |
|||
<Border Grid.Column="1" |
|||
Width="100" |
|||
Height="40" |
|||
BorderBrush="Black" |
|||
BorderThickness="1" |
|||
CornerRadius="4" |
|||
HorizontalAlignment="Left"> |
|||
<Border.Background> |
|||
<SolidColorBrush Color="{Binding AccentColor3}" /> |
|||
</Border.Background> |
|||
</Border> |
|||
<TextBlock Grid.Column="2" |
|||
Text="{Binding AccentColor3}" |
|||
VerticalAlignment="Center" |
|||
Margin="10,0,0,0" /> |
|||
</Grid> |
|||
</StackPanel> |
|||
</StackPanel> |
|||
</GroupBox> |
|||
|
|||
<GroupBox Header="Language Settings"> |
|||
<StackPanel Spacing="10"> |
|||
<TextBlock Text="This reflects the preferred application language as specified in OS settings." |
|||
TextWrapping="Wrap" |
|||
Opacity="0.7" |
|||
FontSize="12" /> |
|||
<Grid ColumnDefinitions="180,*"> |
|||
<TextBlock Grid.Column="0" Text="Preferred Language:" VerticalAlignment="Center" /> |
|||
<TextBlock Grid.Column="1" Text="{Binding PreferredLanguage}" FontWeight="Bold" VerticalAlignment="Center" /> |
|||
</Grid> |
|||
</StackPanel> |
|||
</GroupBox> |
|||
|
|||
<GroupBox Header="Other Platform Settings"> |
|||
<StackPanel Spacing="10"> |
|||
<TextBlock Text="These settings are less commonly changed and are platform-specific." |
|||
TextWrapping="Wrap" |
|||
Opacity="0.7" |
|||
FontSize="12" /> |
|||
|
|||
<Grid ColumnDefinitions="180,*" RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto"> |
|||
<TextBlock Grid.Column="0" Grid.Row="0" Text="Hold Wait Duration:" VerticalAlignment="Center" /> |
|||
<TextBlock Grid.Column="1" Grid.Row="0" Text="{Binding HoldWaitDuration}" VerticalAlignment="Center" /> |
|||
|
|||
<TextBlock Grid.Column="0" Grid.Row="1" Text="Tap Size (Touch):" VerticalAlignment="Center" Margin="0,5,0,0" /> |
|||
<TextBlock Grid.Column="1" Grid.Row="1" Text="{Binding TapSizeTouch}" VerticalAlignment="Center" Margin="0,5,0,0" /> |
|||
|
|||
<TextBlock Grid.Column="0" Grid.Row="2" Text="Tap Size (Mouse):" VerticalAlignment="Center" Margin="0,5,0,0" /> |
|||
<TextBlock Grid.Column="1" Grid.Row="2" Text="{Binding TapSizeMouse}" VerticalAlignment="Center" Margin="0,5,0,0" /> |
|||
|
|||
<TextBlock Grid.Column="0" Grid.Row="3" Text="Double-Tap Size (Touch):" VerticalAlignment="Center" Margin="0,5,0,0" /> |
|||
<TextBlock Grid.Column="1" Grid.Row="3" Text="{Binding DoubleTapSizeTouch}" VerticalAlignment="Center" Margin="0,5,0,0" /> |
|||
|
|||
<TextBlock Grid.Column="0" Grid.Row="4" Text="Double-Tap Size (Mouse):" VerticalAlignment="Center" Margin="0,5,0,0" /> |
|||
<TextBlock Grid.Column="1" Grid.Row="4" Text="{Binding DoubleTapSizeMouse}" VerticalAlignment="Center" Margin="0,5,0,0" /> |
|||
|
|||
<TextBlock Grid.Column="0" Grid.Row="5" Text="Double-Tap Time (Touch):" VerticalAlignment="Center" Margin="0,5,0,0" /> |
|||
<TextBlock Grid.Column="1" Grid.Row="5" Text="{Binding DoubleTapTimeTouch}" VerticalAlignment="Center" Margin="0,5,0,0" /> |
|||
|
|||
<TextBlock Grid.Column="0" Grid.Row="6" Text="Double-Tap Time (Mouse):" VerticalAlignment="Center" Margin="0,5,0,0" /> |
|||
<TextBlock Grid.Column="1" Grid.Row="6" Text="{Binding DoubleTapTimeMouse}" VerticalAlignment="Center" Margin="0,5,0,0" /> |
|||
</Grid> |
|||
</StackPanel> |
|||
</GroupBox> |
|||
|
|||
</StackPanel> |
|||
</ContentPage> |
|||
@ -0,0 +1,30 @@ |
|||
using Avalonia; |
|||
using Avalonia.Controls; |
|||
using Avalonia.VisualTree; |
|||
using ControlCatalog.ViewModels; |
|||
|
|||
namespace ControlCatalog.Pages |
|||
{ |
|||
public partial class PlatformSettingsPage : ContentPage |
|||
{ |
|||
private readonly PlatformSettingsViewModel _viewModel = new(); |
|||
|
|||
public PlatformSettingsPage() |
|||
{ |
|||
InitializeComponent(); |
|||
DataContext = _viewModel; |
|||
} |
|||
|
|||
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) |
|||
{ |
|||
base.OnAttachedToVisualTree(e); |
|||
_viewModel.Subscribe(this.GetPlatformSettings() ?? Application.Current?.PlatformSettings); |
|||
} |
|||
|
|||
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e) |
|||
{ |
|||
_viewModel.Unsubscribe(); |
|||
base.OnDetachedFromVisualTree(e); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,118 @@ |
|||
using System; |
|||
using Avalonia.Controls; |
|||
using Avalonia.Layout; |
|||
using Avalonia.Media; |
|||
using MiniMvvm; |
|||
|
|||
namespace ControlCatalog.ViewModels |
|||
{ |
|||
public sealed class FlexItemViewModel : ViewModelBase |
|||
{ |
|||
internal const FlexAlignItems AlignSelfAuto = (FlexAlignItems)(-1); |
|||
|
|||
private FlexAlignItems _alignSelf; |
|||
|
|||
private bool _isSelected; |
|||
private bool _isVisible = true; |
|||
|
|||
private FlexAlignItems _alignSelfItem = AlignSelfAuto; |
|||
private int _order; |
|||
private double _shrink = 1.0; |
|||
private double _grow; |
|||
private double _basisValue = 100.0; |
|||
private FlexBasisKind _basisKind; |
|||
private HorizontalAlignment _horizontalAlignment; |
|||
private VerticalAlignment _verticalAlignment; |
|||
|
|||
public FlexItemViewModel(int value) |
|||
{ |
|||
Value = value; |
|||
|
|||
_alignSelf = AlignSelfItem == AlignSelfAuto ? default(FlexAlignItems) : AlignSelfItem; |
|||
|
|||
var color = Random.Shared.Next(); |
|||
|
|||
Color = new SolidColorBrush((uint)color); |
|||
} |
|||
|
|||
public int Value { get; } |
|||
|
|||
public Brush Color { get; } |
|||
|
|||
public bool IsSelected |
|||
{ |
|||
get => _isSelected; |
|||
set => this.RaiseAndSetIfChanged(ref _isSelected, value); |
|||
} |
|||
|
|||
public bool IsVisible |
|||
{ |
|||
get => _isVisible; |
|||
set => this.RaiseAndSetIfChanged(ref _isVisible, value); |
|||
} |
|||
|
|||
public FlexAlignItems AlignSelfItem |
|||
{ |
|||
get => _alignSelfItem; |
|||
set |
|||
{ |
|||
this.RaiseAndSetIfChanged(ref _alignSelfItem, value); |
|||
this.RaisePropertyChanged(nameof(AlignSelf)); |
|||
} |
|||
} |
|||
|
|||
public FlexAlignItems? AlignSelf => _alignSelf; |
|||
|
|||
public int Order |
|||
{ |
|||
get => _order; |
|||
set => this.RaiseAndSetIfChanged(ref _order, value); |
|||
} |
|||
|
|||
public double Shrink |
|||
{ |
|||
get => _shrink; |
|||
set => this.RaiseAndSetIfChanged(ref _shrink, value); |
|||
} |
|||
|
|||
public double Grow |
|||
{ |
|||
get => _grow; |
|||
set => this.RaiseAndSetIfChanged(ref _grow, value); |
|||
} |
|||
|
|||
public double BasisValue |
|||
{ |
|||
get => _basisValue; |
|||
set |
|||
{ |
|||
this.RaiseAndSetIfChanged(ref _basisValue, value); |
|||
this.RaisePropertyChanged(nameof(Basis)); |
|||
} |
|||
} |
|||
|
|||
public FlexBasisKind BasisKind |
|||
{ |
|||
get => _basisKind; |
|||
set |
|||
{ |
|||
this.RaiseAndSetIfChanged(ref _basisKind, value); |
|||
this.RaisePropertyChanged(nameof(Basis)); |
|||
} |
|||
} |
|||
|
|||
public FlexBasis Basis => new(_basisValue, _basisKind); |
|||
|
|||
public HorizontalAlignment HorizontalAlignment |
|||
{ |
|||
get => _horizontalAlignment; |
|||
set => this.RaiseAndSetIfChanged(ref _horizontalAlignment, value); |
|||
} |
|||
|
|||
public VerticalAlignment VerticalAlignment |
|||
{ |
|||
get => _verticalAlignment; |
|||
set => this.RaiseAndSetIfChanged(ref _verticalAlignment, value); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,126 @@ |
|||
using System; |
|||
using System.Collections; |
|||
using System.Collections.ObjectModel; |
|||
using System.Linq; |
|||
using System.Windows.Input; |
|||
using Avalonia.Controls; |
|||
using Avalonia.Layout; |
|||
using MiniMvvm; |
|||
|
|||
namespace ControlCatalog.ViewModels |
|||
{ |
|||
public sealed class FlexViewModel : ViewModelBase |
|||
{ |
|||
private readonly ObservableCollection<FlexItemViewModel> _numbers; |
|||
|
|||
private FlexDirection _direction = FlexDirection.Row; |
|||
private FlexJustifyContent _justifyContent = FlexJustifyContent.FlexStart; |
|||
private FlexAlignItems _alignItems = FlexAlignItems.FlexStart; |
|||
private FlexAlignContent _alignContent = FlexAlignContent.FlexStart; |
|||
private FlexWrap _wrap = FlexWrap.Wrap; |
|||
|
|||
private int _columnSpacing = 64; |
|||
private int _rowSpacing = 32; |
|||
|
|||
private int _currentNumber = 41; |
|||
|
|||
private FlexItemViewModel? _selectedItem; |
|||
|
|||
public FlexViewModel() |
|||
{ |
|||
_numbers = new ObservableCollection<FlexItemViewModel>(Enumerable.Range(1, 40).Select(x => new FlexItemViewModel(x))); |
|||
|
|||
Numbers = new ReadOnlyObservableCollection<FlexItemViewModel>(_numbers); |
|||
|
|||
AddItemCommand = MiniCommand.Create(AddItem); |
|||
RemoveItemCommand = MiniCommand.Create(RemoveItem); |
|||
} |
|||
|
|||
public IEnumerable DirectionValues { get; } = Enum.GetValues<FlexDirection>(); |
|||
|
|||
public IEnumerable JustifyContentValues { get; } = Enum.GetValues<FlexJustifyContent>(); |
|||
|
|||
public IEnumerable AlignItemsValues { get; } = Enum.GetValues<FlexAlignItems>(); |
|||
|
|||
public IEnumerable AlignContentValues { get; } = Enum.GetValues<FlexAlignContent>(); |
|||
|
|||
public IEnumerable WrapValues { get; } = Enum.GetValues<FlexWrap>(); |
|||
|
|||
public IEnumerable FlexBasisKindValues { get; } = Enum.GetValues<FlexBasisKind>(); |
|||
|
|||
public IEnumerable HorizontalAlignmentValues { get; } = Enum.GetValues<HorizontalAlignment>(); |
|||
|
|||
public IEnumerable VerticalAlignmentValues { get; } = Enum.GetValues<VerticalAlignment>(); |
|||
|
|||
public IEnumerable AlignSelfValues { get; } = Enum.GetValues<FlexAlignItems>().Cast<FlexAlignItems>().Prepend(FlexItemViewModel.AlignSelfAuto); |
|||
|
|||
public FlexDirection Direction |
|||
{ |
|||
get => _direction; |
|||
set => this.RaiseAndSetIfChanged(ref _direction, value); |
|||
} |
|||
|
|||
public FlexJustifyContent JustifyContent |
|||
{ |
|||
get => _justifyContent; |
|||
set => this.RaiseAndSetIfChanged(ref _justifyContent, value); |
|||
} |
|||
|
|||
public FlexAlignItems AlignItems |
|||
{ |
|||
get => _alignItems; |
|||
set => this.RaiseAndSetIfChanged(ref _alignItems, value); |
|||
} |
|||
|
|||
public FlexAlignContent AlignContent |
|||
{ |
|||
get => _alignContent; |
|||
set => this.RaiseAndSetIfChanged(ref _alignContent, value); |
|||
} |
|||
|
|||
public FlexWrap Wrap |
|||
{ |
|||
get => _wrap; |
|||
set => this.RaiseAndSetIfChanged(ref _wrap, value); |
|||
} |
|||
|
|||
public int ColumnSpacing |
|||
{ |
|||
get => _columnSpacing; |
|||
set => this.RaiseAndSetIfChanged(ref _columnSpacing, value); |
|||
} |
|||
|
|||
public int RowSpacing |
|||
{ |
|||
get => _rowSpacing; |
|||
set => this.RaiseAndSetIfChanged(ref _rowSpacing, value); |
|||
} |
|||
|
|||
public ReadOnlyObservableCollection<FlexItemViewModel> Numbers { get; } |
|||
|
|||
public FlexItemViewModel? SelectedItem |
|||
{ |
|||
get => _selectedItem; |
|||
set => this.RaiseAndSetIfChanged(ref _selectedItem, value); |
|||
} |
|||
|
|||
public ICommand AddItemCommand { get; } |
|||
|
|||
public ICommand RemoveItemCommand { get; } |
|||
|
|||
private void AddItem() => _numbers.Add(new FlexItemViewModel(_currentNumber++)); |
|||
|
|||
private void RemoveItem() |
|||
{ |
|||
if (SelectedItem is null) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
_numbers.Remove(SelectedItem); |
|||
|
|||
SelectedItem.IsSelected = false; |
|||
SelectedItem = null; |
|||
} |
|||
} |
|||
} |
|||
@ -1,249 +1,141 @@ |
|||
using Avalonia.Controls; |
|||
using Avalonia.Controls.ApplicationLifetimes; |
|||
using Avalonia.Dialogs; |
|||
using System; |
|||
using System.ComponentModel.DataAnnotations; |
|||
using Avalonia; |
|||
using MiniMvvm; |
|||
using Avalonia.Collections; |
|||
using ControlCatalog.Pages; |
|||
using System.Globalization; |
|||
using System.Text; |
|||
using System.Threading.Tasks; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using Avalonia.Controls; |
|||
using ControlCatalog.Pages; |
|||
using Avalonia.Media; |
|||
using ControlCatalog.Models; |
|||
|
|||
namespace ControlCatalog.ViewModels |
|||
{ |
|||
partial class MainWindowViewModel |
|||
{ |
|||
private int _selectedPageIndex; |
|||
private bool _isDrawerOpened = true; |
|||
private bool _ignoreListChange = false; |
|||
private string? _query = ""; |
|||
private PageItem? _currentItem; |
|||
private SplitViewDisplayMode _displayMode; |
|||
namespace ControlCatalog.ViewModels; |
|||
|
|||
private List<PageItem> _items = new() |
|||
partial class MainWindowViewModel |
|||
{ |
|||
private readonly HomeSection[] _pageSections = |
|||
[ |
|||
Section("", s => |
|||
{ |
|||
new PageItem("Composition", () => new CompositionPage(), Icons.Layers), |
|||
new PageItem("Accelerator", () => new AcceleratorPage(), Icons.Keyboard), |
|||
new PageItem("Acrylic", () => new AcrylicPage(), Icons.Blur), |
|||
new PageItem("AdornerLayer", () => new AdornerLayerPage(), Icons.Sparkle), |
|||
new PageItem("AutoCompleteBox",() => new AutoCompleteBoxPage(), Icons.TextInput), |
|||
new PageItem("Border",() => new BorderPage(), Icons.Border), |
|||
new PageItem("BitmapCache",() => new BitmapCachePage(), Icons.Lightning), |
|||
new PageItem("Buttons",() => new ButtonsPage(), Icons.CursorClick), |
|||
new PageItem("ButtonSpinner",() => new ButtonSpinnerPage(), Icons.Spinner), |
|||
new PageItem("Calendar",() => new CalendarPage(), Icons.Calendar), |
|||
new PageItem("Canvas",() => new CanvasPage(), Icons.Canvas), |
|||
new PageItem("CommandBar",() => new CommandBarPage(), Icons.Terminal), |
|||
new PageItem("Carousel",() => new Pages.CarouselPage(), Icons.Slides), |
|||
new PageItem("CarouselPage",() => new CarouselDemoPage(), Icons.Slides), |
|||
new PageItem("CheckBox",() => new CheckBoxPage(), Icons.Checkbox), |
|||
new PageItem("Clipboard",() => new ClipboardPage(), Icons.Clipboard), |
|||
new PageItem("ColorPicker",() => new ColorPickerPage(), Icons.Palette), |
|||
new PageItem("ComboBox",() => new ComboBoxPage(), Icons.Dropdown), |
|||
new PageItem("Container Queries",() => new ContainerQueryPage(), Icons.Container), |
|||
new PageItem("ContentPage",() => new ContentDemoPage(), Icons.Document), |
|||
new PageItem("ContextFlyout",() => new ContextFlyoutPage(), Icons.Menu), |
|||
new PageItem("ContextMenu",() => new ContextMenuPage(), Icons.Menu), |
|||
new PageItem("Cursor",() => new CursorPage(), Icons.Cursor), |
|||
new PageItem("Custom Drawing",() => new CustomDrawing(), Icons.Brush), |
|||
new PageItem("Data Validation",() => new DataValidationPage(), Icons.Shield), |
|||
new PageItem("Date/Time Picker",() => new DateTimePickerPage(), Icons.Clock), |
|||
new PageItem("CalendarDatePicker",() => new CalendarDatePickerPage(), Icons.Calendar), |
|||
new PageItem("Dialogs",() => new DialogsPage(), Icons.Dialog), |
|||
new PageItem("Drag+Drop",() => new DragAndDropPage(), Icons.DragDrop), |
|||
new PageItem("DrawerPage",() => new DrawerDemoPage(), Icons.Drawer), |
|||
new PageItem("Expander",() => new ExpanderPage(), Icons.Expand), |
|||
new PageItem("Flyouts",() => new FlyoutsPage(), Icons.Flyout), |
|||
new PageItem("Focus",() => new FocusPage(), Icons.Target), |
|||
new PageItem("Gestures",() => new GesturePage(), Icons.Gesture), |
|||
new PageItem("Image",() => new ImagePage(), Icons.Image), |
|||
new PageItem("Label",() => new LabelsPage(), Icons.Tag), |
|||
new PageItem("LayoutTransformControl",() => new LayoutTransformControlPage(), Icons.Transform), |
|||
new PageItem("ListBox",() => new ListBoxPage(), Icons.List), |
|||
new PageItem("Menu",() => new MenuPage(), Icons.Menu), |
|||
new PageItem("NavigationPage",() => new NavigationDemoPage(), Icons.Navigation), |
|||
new PageItem("Notifications",() => new NotificationsPage(), Icons.Bell), |
|||
new PageItem("NumericUpDown",() => new NumericUpDownPage(), Icons.Number), |
|||
new PageItem("OpenGL",() => new OpenGlPage(), Icons.Cube3D), |
|||
new PageItem("OpenGL Lease",() => new OpenGlLeasePage(), Icons.Cube3D), |
|||
new PageItem("PipsPager",() => new PipsPagerPage(), Icons.HorizontalDots), |
|||
new PageItem("Platform Information",() => new PlatformInfoPage(), Icons.Info), |
|||
new PageItem("Pointers",() => new PointersPage(), Icons.Cursor), |
|||
new PageItem("ProgressBar",() => new ProgressBarPage(), Icons.Progress), |
|||
new PageItem("RadioButton",() => new RadioButtonPage(), Icons.Radio), |
|||
new PageItem("RefreshContainer",() => new RefreshContainerPage(), Icons.Refresh), |
|||
new PageItem("RelativePanel",() => new RelativePanelPage(), Icons.Layout), |
|||
new PageItem("ScrollViewer",() => new ScrollViewerPage(), Icons.Scroll), |
|||
new PageItem("Slider",() => new SliderPage(), Icons.Tune), |
|||
new PageItem("SplitView",() => new SplitViewPage(), Icons.Split), |
|||
new PageItem("TabbedPage",() => new TabbedDemoPage(), Icons.Tab), |
|||
new PageItem("TabControl",() => new TabControlPage(), Icons.Tab), |
|||
new PageItem("TabStrip",() => new TabStripPage(), Icons.Tab), |
|||
new PageItem("TableView",() => new TableViewPage(), Icons.Grid), |
|||
new PageItem("TextBox",() => new TextBoxPage(), Icons.TextInput), |
|||
new PageItem("TextBlock",() => new TextBlockPage(), Icons.TextInput), |
|||
new PageItem("Theme Variants",() => new ThemePage(), Icons.Theme), |
|||
new PageItem("ToggleSwitch",() => new ToggleSwitchPage(), Icons.Toggle), |
|||
new PageItem("ToolTip",() => new ToolTipPage(), Icons.Tooltip), |
|||
new PageItem("TransitioningContentControl",() => new TransitioningContentControlPage(), Icons.Transition), |
|||
new PageItem("TreeView",() => new TreeViewPage(), Icons.Tree), |
|||
new PageItem("Viewbox",() => new ViewboxPage(), Icons.Viewbox), |
|||
new PageItem("WrapPanel",() => new WrapPanelPage(), Icons.Layout), |
|||
new PageItem("Native Embed",() => new NativeEmbedPage(), Icons.Puzzle), |
|||
new PageItem("Window Customizations",() => new WindowCustomizationsPage(), Icons.Window), |
|||
new PageItem("HeaderedContentControl",() => new HeaderedContentPage(), Icons.Header), |
|||
new PageItem("Screens",() => new ScreenPage(), Icons.Monitor), |
|||
}; |
|||
|
|||
public AvaloniaList<PageItem> Pages { get; } = new AvaloniaList<PageItem>(); |
|||
|
|||
public void Filter(string? query = "") |
|||
s.Add<HomePage>("Home", Icons.Home, "Overview of everything in the catalog"); |
|||
}), |
|||
Section("Basic Input", s => |
|||
{ |
|||
try |
|||
{ |
|||
_ignoreListChange = true; |
|||
Pages.Clear(); |
|||
|
|||
if (string.IsNullOrWhiteSpace(query)) |
|||
{ |
|||
Pages.AddRange(_items); |
|||
} |
|||
else |
|||
{ |
|||
var querySearchKey = PageItem.CreateSearchKey(query); |
|||
|
|||
if (querySearchKey.Length == 0) |
|||
{ |
|||
Pages.AddRange(_items); |
|||
} |
|||
else |
|||
{ |
|||
foreach (var item in _items) |
|||
{ |
|||
if (item.MatchesSearch(querySearchKey)) |
|||
{ |
|||
Pages.Add(item); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
finally |
|||
{ |
|||
_ignoreListChange = false; |
|||
if (_currentItem != null) |
|||
{ |
|||
var newIndex = Pages.IndexOf(_currentItem); |
|||
if (newIndex != -1) |
|||
{ |
|||
SelectedPageIndex = newIndex; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
public INavigation? Navigator { get; internal set; } |
|||
|
|||
public int SelectedPageIndex |
|||
s.Add<ButtonsPage>("Buttons", Icons.CursorClick, "Button, RepeatButton, ToggleButton and friends"); |
|||
s.Add<ButtonSpinnerPage>("ButtonSpinner", Icons.Spinner, "Content with increment and decrement buttons"); |
|||
s.Add<CheckBoxPage>("CheckBox", Icons.Checkbox, "Two- and three-state check boxes"); |
|||
s.Add<ColorPickerPage>("ColorPicker", Icons.Palette, "Pick colors from spectrum and palette views"); |
|||
s.Add<ComboBoxPage>("ComboBox", Icons.Dropdown, "A drop-down list of selectable items"); |
|||
s.Add<NumericUpDownPage>("NumericUpDown", Icons.Number, "Numeric input with spinner buttons"); |
|||
s.Add<RadioButtonPage>("RadioButton", Icons.Radio, "Mutually exclusive option groups"); |
|||
s.Add<SliderPage>("Slider", Icons.Tune, "Select a value from a continuous range"); |
|||
s.Add<ToggleSwitchPage>("ToggleSwitch", Icons.Toggle, "An on/off switch with a sliding knob"); |
|||
}), |
|||
Section("Text", s => |
|||
{ |
|||
get { return _selectedPageIndex; } |
|||
set |
|||
{ |
|||
RaiseAndSetIfChanged(ref _selectedPageIndex, value); |
|||
|
|||
if (!_ignoreListChange) |
|||
{ |
|||
NavigateTo(_selectedPageIndex); |
|||
|
|||
if (DisplayMode == SplitViewDisplayMode.CompactOverlay || DisplayMode == SplitViewDisplayMode.Overlay) |
|||
IsDrawerOpened = false; |
|||
} |
|||
} |
|||
} |
|||
|
|||
public bool IsDrawerOpened |
|||
s.Add<AutoCompleteBoxPage>("AutoCompleteBox", Icons.TextInput, "Text input with completion suggestions"); |
|||
s.Add<LabelsPage>("Label", Icons.Tag, "Captions with access keys for other controls"); |
|||
s.Add<TextBoxPage>("TextBox", Icons.TextInput, "Single- and multi-line text editing"); |
|||
s.Add<TextBlockPage>("TextBlock", Icons.TextInput, "Styled read-only text display"); |
|||
}), |
|||
Section("Collections & Data", s => |
|||
{ |
|||
get { return _isDrawerOpened; } |
|||
set { RaiseAndSetIfChanged(ref _isDrawerOpened, value); } |
|||
} |
|||
|
|||
public SplitViewDisplayMode DisplayMode |
|||
s.Add<Pages.CarouselPage>("Carousel", Icons.Slides, "Cycle through a collection of items"); |
|||
s.Add<ListBoxPage>("ListBox", Icons.List, "A selectable, virtualized list of items"); |
|||
s.Add<PipsPagerPage>("PipsPager", Icons.HorizontalDots, "Dot-style pager for paginated content"); |
|||
s.Add<RefreshContainerPage>("RefreshContainer", Icons.Refresh, "Pull-to-refresh for scrollable content"); |
|||
s.Add<TableViewPage>("TableView", Icons.Grid, "Tabular data with resizable, sortable columns"); |
|||
s.Add<TreeViewPage>("TreeView", Icons.Tree, "Hierarchical data with expandable nodes"); |
|||
}), |
|||
Section("Date & Time", s => |
|||
{ |
|||
get { return _displayMode; } |
|||
set { RaiseAndSetIfChanged(ref _displayMode, value); } |
|||
} |
|||
|
|||
public string? Query |
|||
s.Add<CalendarPage>("Calendar", Icons.Calendar, "A month calendar for selecting dates"); |
|||
s.Add<CalendarDatePickerPage>("CalendarDatePicker", Icons.Calendar, "A date picker with a drop-down calendar"); |
|||
s.Add<DateTimePickerPage>("Date/Time Picker", Icons.Clock, "Spinner-style date and time pickers"); |
|||
}), |
|||
Section("Menus & Flyouts", s => |
|||
{ |
|||
get { return _query; } |
|||
set |
|||
{ |
|||
RaiseAndSetIfChanged(ref _query, value); |
|||
|
|||
Filter(value); |
|||
} |
|||
} |
|||
|
|||
private async void NavigateTo(int pageIndex) |
|||
s.Add<CommandBarPage>("CommandBar", Icons.Terminal, "A toolbar of commands with an overflow menu"); |
|||
s.Add<ContextFlyoutPage>("ContextFlyout", Icons.Menu, "Attach flyouts shown on right-click"); |
|||
s.Add<ContextMenuPage>("ContextMenu", Icons.Menu, "Traditional right-click context menus"); |
|||
s.Add<FlyoutsPage>("Flyouts", Icons.Flyout, "Lightweight popups anchored to controls"); |
|||
s.Add<MenuPage>("Menu", Icons.Menu, "Menu bars with nested menu items"); |
|||
}), |
|||
Section("Navigation & Pages", s => |
|||
{ |
|||
if (pageIndex < 0 || pageIndex >= Pages.Count || Navigator is null) |
|||
return; |
|||
|
|||
var item = Pages[pageIndex]; |
|||
|
|||
if (item != null) |
|||
{ |
|||
var view = item.Factory(); |
|||
if (view is Page page && view.GetType() != Navigator.NavigationStack.LastOrDefault()?.GetType()) |
|||
{ |
|||
_currentItem = item; |
|||
await Navigator.ReplaceAsync(page); |
|||
} |
|||
} |
|||
} |
|||
s.Add<CarouselDemoPage>("CarouselPage", Icons.Slides, "Swipeable page-based navigation"); |
|||
s.Add<ContentDemoPage>("ContentPage", Icons.Document, "A page that hosts a single content view"); |
|||
s.Add<DrawerDemoPage>("DrawerPage", Icons.Drawer, "A page with a sliding navigation drawer"); |
|||
s.Add<NavigationDemoPage>("NavigationPage", Icons.Navigation, "Stack-based page navigation"); |
|||
s.Add<SplitViewPage>("SplitView", Icons.Split, "A collapsible pane beside content"); |
|||
s.Add<TabbedDemoPage>("TabbedPage", Icons.Tab, "Tab-based page navigation"); |
|||
s.Add<TabControlPage>("TabControl", Icons.Tab, "Switch between tabbed content views"); |
|||
s.Add<TabStripPage>("TabStrip", Icons.Tab, "A standalone strip of selectable tabs"); |
|||
}), |
|||
Section("Layout", s => |
|||
{ |
|||
s.Add<BorderPage>("Border", Icons.Border, "Decorate elements with borders and corner radii"); |
|||
s.Add<CanvasPage>("Canvas", Icons.Canvas, "Position children at explicit coordinates"); |
|||
s.Add<ContainerQueryPage>("Container Queries", Icons.Container, "Styles that respond to container size"); |
|||
s.Add<ExpanderPage>("Expander", Icons.Expand, "A header that expands to reveal content"); |
|||
s.Add<FlexPage>("Flex Panel", Icons.Grid, "Flexible, CSS-style child layout"); |
|||
s.Add<HeaderedContentPage>("HeaderedContentControl", Icons.Header, "Content paired with a header"); |
|||
s.Add<LayoutTransformControlPage>("LayoutTransformControl", Icons.Transform, "Apply transforms that affect layout"); |
|||
s.Add<RelativePanelPage>("RelativePanel", Icons.Layout, "Arrange children relative to each other"); |
|||
s.Add<ScrollViewerPage>("ScrollViewer", Icons.Scroll, "Scrollable viewport over large content"); |
|||
s.Add<ViewboxPage>("Viewbox", Icons.Viewbox, "Scale content to fit available space"); |
|||
s.Add<WrapPanelPage>("WrapPanel", Icons.Layout, "Wrap children onto multiple lines"); |
|||
}), |
|||
Section("Media & Graphics", s => |
|||
{ |
|||
s.Add<AcrylicPage>("Acrylic", Icons.Blur, "Translucent acrylic window materials"); |
|||
s.Add<BitmapCachePage>("BitmapCache", Icons.Lightning, "Cache visuals as bitmaps for performance"); |
|||
s.Add<CompositionPage>("Composition", Icons.Layers, "Composition-layer animations and effects"); |
|||
s.Add<CustomDrawing>("Custom Drawing", Icons.Brush, "Render custom geometry in code"); |
|||
s.Add<ImagePage>("Image", Icons.Image, "Display bitmaps with different stretch modes"); |
|||
s.Add<OpenGlPage>("OpenGL", Icons.Cube3D, "Embed custom OpenGL rendering"); |
|||
s.Add<OpenGlLeasePage>("OpenGL Lease", Icons.Cube3D, "Low-level access to the OpenGL context"); |
|||
s.Add<TransitioningContentControlPage>("TransitioningContentControl", Icons.Transition, "Animate between content changes"); |
|||
}), |
|||
Section("Status & Feedback", s => |
|||
{ |
|||
s.Add<AdornerLayerPage>("AdornerLayer", Icons.Sparkle, "Overlay visuals on top of other controls"); |
|||
s.Add<DataValidationPage>("Data Validation", Icons.Shield, "Display validation errors from bindings"); |
|||
s.Add<DialogsPage>("Dialogs", Icons.Dialog, "File pickers and modal dialog windows"); |
|||
s.Add<NotificationsPage>("Notifications", Icons.Bell, "Toast-style in-app notifications"); |
|||
s.Add<ProgressBarPage>("ProgressBar", Icons.Progress, "Determinate and indeterminate progress"); |
|||
s.Add<ToolTipPage>("ToolTip", Icons.Tooltip, "Hover hints for any control"); |
|||
}), |
|||
Section("Interaction", s => |
|||
{ |
|||
s.Add<AcceleratorPage>("Accelerator", Icons.Keyboard, "Keyboard shortcuts that invoke commands"); |
|||
s.Add<ClipboardPage>("Clipboard", Icons.Clipboard, "Read from and write to the system clipboard"); |
|||
s.Add<CursorPage>("Cursor", Icons.Cursor, "Change the pointer cursor over elements"); |
|||
s.Add<DragAndDropPage>("Drag+Drop", Icons.DragDrop, "Drag data within and between applications"); |
|||
s.Add<FocusPage>("Focus", Icons.Target, "Track and control keyboard focus"); |
|||
s.Add<GesturePage>("Gestures", Icons.Gesture, "Tap, scroll and pinch gesture recognition"); |
|||
s.Add<PointersPage>("Pointers", Icons.Cursor, "Raw pointer input and capture"); |
|||
}), |
|||
Section("Window & Platform", s => |
|||
{ |
|||
s.Add<NativeEmbedPage>("Native Embed", Icons.Puzzle, "Host native platform controls"); |
|||
s.Add<PlatformInfoPage>("Platform Information", Icons.Info, "Runtime platform and capability info"); |
|||
s.Add<PlatformSettingsPage>("Platform Settings", Icons.Tune, "Platform-specific system settings"); |
|||
s.Add<ScreenPage>("Screens", Icons.Monitor, "Enumerate displays and their bounds"); |
|||
s.Add<ThemePage>("Theme Variants", Icons.Theme, "Switch between light and dark variants"); |
|||
s.Add<WindowCustomizationsPage>("Window Customizations", Icons.Window, "Custom chrome, decorations and sizing"); |
|||
}) |
|||
]; |
|||
|
|||
private static HomeSection Section(string title, Action<HomeSectionBuilder> builderCallback) |
|||
{ |
|||
var builder = new HomeSectionBuilder(title); |
|||
builderCallback(builder); |
|||
return new HomeSection(title, builder.ToArray()); |
|||
} |
|||
|
|||
class PageItem(string header, Func<object> factory, string? iconData = null) |
|||
private class HomeSectionBuilder(string title) : List<PageItem> |
|||
{ |
|||
public string Header { get; } = header; |
|||
public Func<object> Factory { get; } = factory; |
|||
public string? IconData { get; } = iconData; |
|||
private string SearchKey { get; } = CreateSearchKey(header); |
|||
|
|||
public bool IsVisible { get; set; } = true; |
|||
|
|||
public bool MatchesSearch(string searchKey) |
|||
{ |
|||
return SearchKey.Contains(searchKey, StringComparison.Ordinal); |
|||
} |
|||
|
|||
public static string CreateSearchKey(string value) |
|||
public void Add<TPageType>(string header, string iconPath, string description) where TPageType : Page, new() |
|||
{ |
|||
var normalizedValue = value.Normalize(NormalizationForm.FormKD); |
|||
var builder = new StringBuilder(normalizedValue.Length); |
|||
|
|||
foreach (var c in normalizedValue) |
|||
{ |
|||
var category = CharUnicodeInfo.GetUnicodeCategory(c); |
|||
|
|||
if (category is UnicodeCategory.NonSpacingMark or |
|||
UnicodeCategory.SpacingCombiningMark or |
|||
UnicodeCategory.EnclosingMark) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
if (char.IsLetterOrDigit(c)) |
|||
{ |
|||
builder.Append(char.ToUpperInvariant(c)); |
|||
} |
|||
} |
|||
|
|||
return builder.ToString(); |
|||
var iconGeometry = StreamGeometry.Parse(iconPath); |
|||
Add(new PageItem(header, () => new TPageType(), iconGeometry, description, title)); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,80 @@ |
|||
using System; |
|||
using Avalonia.Input; |
|||
using Avalonia.Media; |
|||
using Avalonia.Platform; |
|||
using MiniMvvm; |
|||
|
|||
namespace ControlCatalog.ViewModels; |
|||
|
|||
public class PlatformSettingsViewModel : ViewModelBase |
|||
{ |
|||
private IPlatformSettings? _platformSettings; |
|||
private PlatformColorValues? _colorValues; |
|||
private string? _preferredLanguage; |
|||
|
|||
public void Subscribe(IPlatformSettings? platformSettings) |
|||
{ |
|||
_platformSettings = platformSettings; |
|||
|
|||
if (platformSettings is not null) |
|||
{ |
|||
OnColorValuesChanged(platformSettings, platformSettings.GetColorValues()); |
|||
OnPreferredLanguageChanged(platformSettings, EventArgs.Empty); |
|||
|
|||
platformSettings?.ColorValuesChanged += OnColorValuesChanged; |
|||
platformSettings?.PreferredApplicationLanguageChanged += OnPreferredLanguageChanged; |
|||
} |
|||
} |
|||
|
|||
public void Unsubscribe() |
|||
{ |
|||
if (_platformSettings != null) |
|||
{ |
|||
_platformSettings.ColorValuesChanged -= OnColorValuesChanged; |
|||
_platformSettings.PreferredApplicationLanguageChanged -= OnPreferredLanguageChanged; |
|||
_platformSettings = null; |
|||
} |
|||
} |
|||
|
|||
private void OnColorValuesChanged(object? sender, PlatformColorValues e) |
|||
{ |
|||
_colorValues = e; |
|||
RaisePropertyChanged(nameof(ThemeVariant)); |
|||
RaisePropertyChanged(nameof(ContrastPreference)); |
|||
RaisePropertyChanged(nameof(AccentColor1)); |
|||
RaisePropertyChanged(nameof(AccentColor2)); |
|||
RaisePropertyChanged(nameof(AccentColor3)); |
|||
} |
|||
|
|||
private void OnPreferredLanguageChanged(object? sender, EventArgs e) |
|||
{ |
|||
_preferredLanguage = ((IPlatformSettings)sender!).PreferredApplicationLanguage; |
|||
RaisePropertyChanged(nameof(PreferredLanguage)); |
|||
} |
|||
|
|||
public string PreferredLanguage => _preferredLanguage ?? "Not available"; |
|||
|
|||
public string ThemeVariant => _colorValues?.ThemeVariant.ToString() ?? "Not available"; |
|||
|
|||
public string ContrastPreference => _colorValues?.ContrastPreference.ToString() ?? "Not available"; |
|||
|
|||
public Color AccentColor1 => _colorValues?.AccentColor1 ?? Colors.Gray; |
|||
|
|||
public Color AccentColor2 => _colorValues?.AccentColor2 ?? Colors.Gray; |
|||
|
|||
public Color AccentColor3 => _colorValues?.AccentColor3 ?? Colors.Gray; |
|||
|
|||
public string HoldWaitDuration => _platformSettings?.HoldWaitDuration.ToString() ?? "Not available"; |
|||
|
|||
public string TapSizeTouch => _platformSettings?.GetTapSize(PointerType.Touch).ToString() ?? "Not available"; |
|||
|
|||
public string TapSizeMouse => _platformSettings?.GetTapSize(PointerType.Mouse).ToString() ?? "Not available"; |
|||
|
|||
public string DoubleTapSizeTouch => _platformSettings?.GetDoubleTapSize(PointerType.Touch).ToString() ?? "Not available"; |
|||
|
|||
public string DoubleTapSizeMouse => _platformSettings?.GetDoubleTapSize(PointerType.Mouse).ToString() ?? "Not available"; |
|||
|
|||
public string DoubleTapTimeTouch => _platformSettings?.GetDoubleTapTime(PointerType.Touch).ToString() ?? "Not available"; |
|||
|
|||
public string DoubleTapTimeMouse => _platformSettings?.GetDoubleTapTime(PointerType.Mouse).ToString() ?? "Not available"; |
|||
} |
|||
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 172 KiB |
@ -0,0 +1,45 @@ |
|||
<UserControl xmlns="https://github.com/avaloniaui" |
|||
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" |
|||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" |
|||
x:Class="IntegrationTestApp.Pages.KeyboardPage"> |
|||
<StackPanel Margin="8" Spacing="8"> |
|||
<Border Name="GestureScope" Padding="8" BorderThickness="1" BorderBrush="Gray"> |
|||
<StackPanel Spacing="4"> |
|||
<TextBlock>Key bindings in scope: Space, A, Ctrl+G</TextBlock> |
|||
<TextBox Name="GestureTextBox"/> |
|||
</StackPanel> |
|||
</Border> |
|||
|
|||
<StackPanel Orientation="Horizontal" Spacing="4"> |
|||
<TextBlock>Gesture text box content:</TextBlock> |
|||
<TextBlock Name="GestureTextBoxContent" Text="{Binding #GestureTextBox.Text}"/> |
|||
</StackPanel> |
|||
|
|||
<StackPanel Orientation="Horizontal" Spacing="4"> |
|||
<TextBlock>Last key binding:</TextBlock> |
|||
<TextBlock Name="LastKeyBinding"/> |
|||
</StackPanel> |
|||
|
|||
<TextBlock Margin="0,8,0,0">No key bindings in scope, used to inspect raw key downs:</TextBlock> |
|||
<TextBox Name="KeyDownTextBox"/> |
|||
|
|||
<StackPanel Orientation="Horizontal" Spacing="4"> |
|||
<TextBlock>Last key down:</TextBlock> |
|||
<TextBlock Name="LastKeyDown"/> |
|||
</StackPanel> |
|||
|
|||
<StackPanel Orientation="Horizontal" Spacing="4"> |
|||
<TextBlock>Key down count:</TextBlock> |
|||
<TextBlock Name="KeyDownCount"/> |
|||
</StackPanel> |
|||
|
|||
<StackPanel Orientation="Horizontal" Spacing="4"> |
|||
<TextBlock>Last text input:</TextBlock> |
|||
<TextBlock Name="LastTextInput"/> |
|||
</StackPanel> |
|||
|
|||
<Button Name="ResetKeyboard" Click="ResetKeyboard_Click" HorizontalAlignment="Left">Reset</Button> |
|||
</StackPanel> |
|||
</UserControl> |
|||
@ -0,0 +1,63 @@ |
|||
using Avalonia.Controls; |
|||
using Avalonia.Input; |
|||
using Avalonia.Interactivity; |
|||
|
|||
namespace IntegrationTestApp.Pages; |
|||
|
|||
public partial class KeyboardPage : UserControl |
|||
{ |
|||
private int _keyDownCount; |
|||
|
|||
public KeyboardPage() |
|||
{ |
|||
InitializeComponent(); |
|||
|
|||
// Gestures without a modifier are the interesting case: on macOS the key down used to be
|
|||
// swallowed by the input context while a text input client was active.
|
|||
AddKeyBinding(new KeyGesture(Key.Space), "Space"); |
|||
AddKeyBinding(new KeyGesture(Key.A), "A"); |
|||
AddKeyBinding(new KeyGesture(Key.G, KeyModifiers.Control), "Ctrl+G"); |
|||
|
|||
// TextBox handles TextInput, and KeyDown for keys like Backspace and the arrows, in a
|
|||
// class handler that runs before instance handlers. Subscribe with handledEventsToo so
|
|||
// those keys stay visible here.
|
|||
KeyDownTextBox.AddHandler(KeyDownEvent, KeyDownTextBox_KeyDown, handledEventsToo: true); |
|||
KeyDownTextBox.AddHandler(TextInputEvent, KeyDownTextBox_TextInput, handledEventsToo: true); |
|||
} |
|||
|
|||
private void AddKeyBinding(KeyGesture gesture, string name) |
|||
{ |
|||
GestureScope.KeyBindings.Add(new KeyBinding |
|||
{ |
|||
Gesture = gesture, |
|||
Command = new DelegateCommand(() => LastKeyBinding.Text = name) |
|||
}); |
|||
} |
|||
|
|||
private void KeyDownTextBox_KeyDown(object? sender, KeyEventArgs e) |
|||
{ |
|||
// While an input method is composing, the key is masked as Key.ImeProcessed but the
|
|||
// physical key and the key symbol keep their real values. The key symbol is bracketed
|
|||
// to keep whitespace symbols like the space key's visible and assertable.
|
|||
LastKeyDown.Text = $"{e.Key}|{e.PhysicalKey}|[{e.KeySymbol}]"; |
|||
|
|||
// Counts every key down, including the ones flagsChanged raises for modifier keys.
|
|||
KeyDownCount.Text = (++_keyDownCount).ToString(); |
|||
} |
|||
|
|||
private void KeyDownTextBox_TextInput(object? sender, TextInputEventArgs e) |
|||
{ |
|||
LastTextInput.Text = $"[{e.Text}]"; |
|||
} |
|||
|
|||
private void ResetKeyboard_Click(object? sender, RoutedEventArgs e) |
|||
{ |
|||
_keyDownCount = 0; |
|||
KeyDownCount.Text = string.Empty; |
|||
LastKeyBinding.Text = string.Empty; |
|||
LastKeyDown.Text = string.Empty; |
|||
LastTextInput.Text = string.Empty; |
|||
GestureTextBox.Text = string.Empty; |
|||
KeyDownTextBox.Text = string.Empty; |
|||
} |
|||
} |
|||
|
Before Width: | Height: | Size: 172 KiB |
|
Before Width: | Height: | Size: 172 KiB After Width: | Height: | Size: 361 KiB |
@ -0,0 +1,60 @@ |
|||
using System; |
|||
using Avalonia.Data; |
|||
|
|||
namespace Avalonia; |
|||
|
|||
/// <summary>
|
|||
/// Instructs the Avalonia property source generator to emit an <see cref="AttachedProperty{TValue}"/>
|
|||
/// registration and accessor methods for the annotated partial <c>Get</c> method.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// <para>
|
|||
/// Apply to a <c>static partial T Get{Name}(THost element)</c> method declared on a <c>partial</c> class.
|
|||
/// </para>
|
|||
/// </remarks>
|
|||
[AttributeUsage(AttributeTargets.Method, Inherited = false)] |
|||
public sealed class GeneratedAttachedPropertyAttribute : Attribute |
|||
{ |
|||
/// <summary>
|
|||
/// Re-owns an existing attached property from the specified base type instead of registering a new property.
|
|||
/// The source property must be a static <c>{Name}Property</c> member of the given type.
|
|||
/// Metadata may still be overridden with <see cref="DefaultValue"/>, <see cref="DefaultBindingMode"/> and <see cref="CoerceMethodName"/>.
|
|||
/// </summary>
|
|||
public Type? AddOwnerFrom { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// The default value of the property. Must be a compile-time constant.
|
|||
/// For non-constant defaults, call <c>{Name}Property.OverrideDefaultValue(...)</c> in a static constructor instead.
|
|||
/// </summary>
|
|||
public object? DefaultValue { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// The default binding mode for the property.
|
|||
/// </summary>
|
|||
public BindingMode DefaultBindingMode { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Whether the property inherits its value down the logical tree.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// Cannot be used with <see cref="AddOwnerFrom"/>.
|
|||
/// </remarks>
|
|||
public bool Inherits { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// The name of the validation method, with signature
|
|||
/// <c>static bool {Method}(T value)</c>. Pass via <c>nameof(...)</c>.
|
|||
/// Declare it as an <c>private static</c> method on the same type.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// Cannot be used with <see cref="AddOwnerFrom"/>.
|
|||
/// </remarks>
|
|||
public string? ValidateMethodName { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// The name of the coercion method, with signature
|
|||
/// <c>static T {Method}(AvaloniaObject sender, T value)</c>.
|
|||
/// Declare it as an <c>private static</c> method on the same type.
|
|||
/// </summary>
|
|||
public string? CoerceMethodName { get; set; } |
|||
} |
|||
@ -0,0 +1,41 @@ |
|||
using System; |
|||
using Avalonia.Data; |
|||
|
|||
namespace Avalonia; |
|||
|
|||
/// <summary>
|
|||
/// Instructs the Avalonia property source generator to emit a <see cref="DirectProperty{TOwner, TValue}"/>
|
|||
/// registration and accessor bodies for the annotated partial property.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// <para>
|
|||
/// Apply to a <c>partial</c> instance property with both <c>get</c> and <c>set</c> accessors,
|
|||
/// declared on a <c>partial</c> class deriving from <see cref="AvaloniaObject"/>.
|
|||
/// </para>
|
|||
/// </remarks>
|
|||
[AttributeUsage(AttributeTargets.Property, Inherited = false)] |
|||
public sealed class GeneratedDirectPropertyAttribute : Attribute |
|||
{ |
|||
/// <summary>
|
|||
/// Re-owns an existing direct property from the specified base type instead of registering a new property.
|
|||
/// The source property must be a static <c>{Name}Property</c> member of the given type.
|
|||
/// </summary>
|
|||
public Type? AddOwnerFrom { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// The value returned when the property is cleared (e.g. by <c>ClearValue</c>)
|
|||
/// or when a binding produces an invalid value.
|
|||
/// The initial value of the property comes from the property initializer.
|
|||
/// </summary>
|
|||
public object? UnsetValue { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// The default binding mode for the property.
|
|||
/// </summary>
|
|||
public BindingMode DefaultBindingMode { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Whether the property is interested in data validation.
|
|||
/// </summary>
|
|||
public bool EnableDataValidation { get; set; } |
|||
} |
|||
@ -0,0 +1,66 @@ |
|||
using System; |
|||
using Avalonia.Data; |
|||
|
|||
namespace Avalonia; |
|||
|
|||
/// <summary>
|
|||
/// Instructs the Avalonia property source generator to emit a <see cref="StyledProperty{TValue}"/>
|
|||
/// registration and accessor bodies for the annotated partial property.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// <para>
|
|||
/// Apply to a <c>partial</c> instance property with both <c>get</c> and <c>set</c> accessors,
|
|||
/// declared on a <c>partial</c> class deriving from <see cref="AvaloniaObject"/>.
|
|||
/// </para>
|
|||
/// </remarks>
|
|||
[AttributeUsage(AttributeTargets.Property, Inherited = false)] |
|||
public sealed class GeneratedStyledPropertyAttribute : Attribute |
|||
{ |
|||
/// <summary>
|
|||
/// Re-owns an existing styled property from the specified base type instead of registering a new property.
|
|||
/// The source property must be a static <c>{Name}Property</c> member of the given type.
|
|||
/// Metadata may still be overridden with <see cref="DefaultValue"/>, <see cref="DefaultBindingMode"/> and <see cref="CoerceMethodName"/>.
|
|||
/// </summary>
|
|||
public Type? AddOwnerFrom { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// The default value of the property. Must be a compile-time constant.
|
|||
/// For non-constant defaults, call <c>{Name}Property.OverrideDefaultValue(...)</c> in a static constructor instead.
|
|||
/// </summary>
|
|||
public object? DefaultValue { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// The default binding mode for the property.
|
|||
/// </summary>
|
|||
public BindingMode DefaultBindingMode { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Whether the property inherits its value down the logical tree.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// Cannot be used with <see cref="AddOwnerFrom"/>.
|
|||
/// </remarks>
|
|||
public bool Inherits { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Whether the property is interested in data validation.
|
|||
/// </summary>
|
|||
public bool EnableDataValidation { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// The name of the validation method, with signature
|
|||
/// <c>static bool {Method}(T value)</c>.
|
|||
/// Declare it as an <c>private static</c> method on the same type.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// Cannot be used with <see cref="AddOwnerFrom"/>.
|
|||
/// </remarks>
|
|||
public string? ValidateMethodName { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// The name of the coercion method, with signature
|
|||
/// <c>static T {Method}(AvaloniaObject sender, T value)</c>.
|
|||
/// Declare it as an <c>private static</c> method on the same type.
|
|||
/// </summary>
|
|||
public string? CoerceMethodName { get; set; } |
|||
} |
|||