Browse Source

1. implemented Label control (again)

2. changed implementation of ControlPresenter to be same as WPF one. Added additional prebuild DataTemplate (for ContentPresenter)
3. added default style for Label control (both Default and Fluent themes)
4. Added sample to TextBox page (not sure needed other sample)
5. Added styles for Label in ControlCatalog/App.xaml
pull/4904/head
Mikhail Poliudov 5 years ago
parent
commit
5f3d81bbfc
  1. 10
      samples/ControlCatalog/App.xaml
  2. 36
      samples/ControlCatalog/Pages/TextBoxPage.xaml
  3. 74
      src/Avalonia.Controls/Label.cs
  4. 25
      src/Avalonia.Controls/Presenters/ContentPresenter.cs
  5. 28
      src/Avalonia.Controls/Templates/FuncDataTemplate.cs
  6. 3
      src/Avalonia.Themes.Default/DefaultTheme.xaml
  7. 17
      src/Avalonia.Themes.Default/Label.xaml
  8. 3
      src/Avalonia.Themes.Fluent/FluentTheme.xaml
  9. 17
      src/Avalonia.Themes.Fluent/Label.xaml

10
samples/ControlCatalog/App.xaml

@ -12,6 +12,16 @@
<Style Selector="TextBlock.h3">
<Setter Property="FontSize" Value="12" />
</Style>
<Style Selector="Label.h1">
<Setter Property="FontSize" Value="16" />
<Setter Property="FontWeight" Value="Medium" />
</Style>
<Style Selector="Label.h2">
<Setter Property="FontSize" Value="14" />
</Style>
<Style Selector="Label.h3">
<Setter Property="FontSize" Value="12" />
</Style>
<StyleInclude Source="/SideBar.xaml"/>
</Application.Styles>
</Application>

36
samples/ControlCatalog/Pages/TextBoxPage.xaml

@ -2,8 +2,8 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="ControlCatalog.Pages.TextBoxPage">
<StackPanel Orientation="Vertical" Spacing="4">
<TextBlock Classes="h1">TextBox</TextBlock>
<TextBlock Classes="h2">A control into which the user can input text</TextBlock>
<Label Classes="h1">TextBox</Label>
<Label Classes="h2">A control into which the user can input text</Label>
<StackPanel Orientation="Horizontal"
Margin="0,16,0,0"
@ -38,24 +38,24 @@
Text="Multiline TextBox with TextWrapping.&#xD;&#xD;Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus magna. Cras in mi at felis aliquet congue. Ut a est eget ligula molestie gravida. Curabitur massa. Donec eleifend, libero at sagittis mollis, tellus est malesuada tellus, at luctus turpis elit sit amet quam. Vivamus pretium ornare est." />
<TextBox AcceptsReturn="True" Width="200" Height="125"
Text="Multiline TextBox with no TextWrapping.&#xD;&#xD;Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus magna. Cras in mi at felis aliquet congue. Ut a est eget ligula molestie gravida. Curabitur massa. Donec eleifend, libero at sagittis mollis, tellus est malesuada tellus, at luctus turpis elit sit amet quam. Vivamus pretium ornare est." />
<TextBox Classes="clearButton" Text="Clear Content" Width="200" FontWeight="Normal" FontStyle="Normal" Watermark="Watermark" FontFamily="avares://ControlCatalog/Assets/Fonts#Source Sans Pro"/>
</StackPanel>
<StackPanel Orientation="Vertical" Spacing="8">
<TextBlock Classes="h2">resm fonts</TextBlock>
<TextBox Width="200" Text="Custom font regular" FontWeight="Normal" FontStyle="Normal" FontFamily="resm:ControlCatalog.Assets.Fonts?assembly=ControlCatalog#Source Sans Pro"/>
<TextBox Width="200" Text="Custom font bold" FontWeight="Bold" FontStyle="Normal" FontFamily="resm:ControlCatalog.Assets.Fonts?assembly=ControlCatalog#Source Sans Pro"/>
<TextBox Width="200" Text="Custom font italic" FontWeight="Normal" FontStyle="Italic" FontFamily="resm:ControlCatalog.Assets.Fonts.SourceSansPro-Italic.ttf?assembly=ControlCatalog#Source Sans Pro"/>
<TextBox Width="200" Text="Custom font italic bold" FontWeight="Bold" FontStyle="Italic" FontFamily="resm:ControlCatalog.Assets.Fonts.SourceSansPro-*.ttf?assembly=ControlCatalog#Source Sans Pro"/>
</StackPanel>
<StackPanel Orientation="Vertical" Spacing="8">
<TextBlock Classes="h2">res fonts</TextBlock>
<TextBox Width="200" Text="Custom font regular" FontWeight="Normal" FontStyle="Normal" FontFamily="avares://ControlCatalog/Assets/Fonts#Source Sans Pro"/>
<TextBox Width="200" Text="Custom font bold" FontWeight="Bold" FontStyle="Normal" FontFamily="avares://ControlCatalog/Assets/Fonts#Source Sans Pro"/>
<TextBox Width="200" Text="Custom font italic" FontWeight="Normal" FontStyle="Italic" FontFamily="/Assets/Fonts/SourceSansPro-Italic.ttf#Source Sans Pro"/>
<TextBox Width="200" Text="Custom font italic bold" FontWeight="Bold" FontStyle="Italic" FontFamily="/Assets/Fonts/SourceSansPro-*.ttf#Source Sans Pro"/>
</StackPanel>
<StackPanel Orientation="Vertical" Spacing="8">
<Label Classes="h2" Target="{Binding #firstResMFont}">res_m fonts</Label>
<TextBox Width="200" x:Name="firstResMFont" Text="Custom font regular" FontWeight="Normal" FontStyle="Normal" FontFamily="resm:ControlCatalog.Assets.Fonts?assembly=ControlCatalog#Source Sans Pro"/>
<TextBox Width="200" Text="Custom font bold" FontWeight="Bold" FontStyle="Normal" FontFamily="resm:ControlCatalog.Assets.Fonts?assembly=ControlCatalog#Source Sans Pro"/>
<TextBox Width="200" Text="Custom font italic" FontWeight="Normal" FontStyle="Italic" FontFamily="resm:ControlCatalog.Assets.Fonts.SourceSansPro-Italic.ttf?assembly=ControlCatalog#Source Sans Pro"/>
<TextBox Width="200" Text="Custom font italic bold" FontWeight="Bold" FontStyle="Italic" FontFamily="resm:ControlCatalog.Assets.Fonts.SourceSansPro-*.ttf?assembly=ControlCatalog#Source Sans Pro"/>
</StackPanel>
<StackPanel Orientation="Vertical" Spacing="8">
<Label Classes="h2" Target="{Binding #firstResFont}">_res fonts</Label>
<TextBox Width="200" x:Name="firstResFont" Text="Custom font regular" FontWeight="Normal" FontStyle="Normal" FontFamily="avares://ControlCatalog/Assets/Fonts#Source Sans Pro"/>
<TextBox Width="200" Text="Custom font bold" FontWeight="Bold" FontStyle="Normal" FontFamily="avares://ControlCatalog/Assets/Fonts#Source Sans Pro"/>
<TextBox Width="200" Text="Custom font italic" FontWeight="Normal" FontStyle="Italic" FontFamily="/Assets/Fonts/SourceSansPro-Italic.ttf#Source Sans Pro"/>
<TextBox Width="200" Text="Custom font italic bold" FontWeight="Bold" FontStyle="Italic" FontFamily="/Assets/Fonts/SourceSansPro-*.ttf#Source Sans Pro"/>
</StackPanel>
</StackPanel>
</StackPanel>
</UserControl>

74
src/Avalonia.Controls/Label.cs

@ -0,0 +1,74 @@
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Text;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates;
using Avalonia.Data;
using Avalonia.Input;
using Avalonia.Interactivity;
namespace Avalonia.Controls
{
/// <summary>
/// Label control. Focuses <see cref="Target"/> on pointer click or access key press (Alt + accessKey)
/// </summary>
public class Label : ContentControl
{
/// <summary>
/// Defines the <see cref="Target"/> Direct property
/// </summary>
public static readonly DirectProperty<Label, IInputElement> TargetProperty =
AvaloniaProperty.RegisterDirect<Label, IInputElement>(nameof(Target), lbl => lbl.Target, (lbl, inp) => lbl.Target = inp);
/// <summary>
/// Label focus target storage field
/// </summary>
private IInputElement _target;
/// <summary>
/// Label focus Target
/// </summary>
public IInputElement Target
{
get => _target;
set => SetAndRaise(TargetProperty, ref _target, value);
}
static Label()
{
AccessKeyHandler.AccessKeyPressedEvent.AddClassHandler<Label>((lbl, args) => lbl.LabelActivated(args));
// IsTabStopProperty.OverrideDefaultValue<Label>(false)
FocusableProperty.OverrideDefaultValue<Label>(false);
}
/// <summary>
/// Initializes instance of <see cref="Label"/> control
/// </summary>
public Label()
{
}
/// <summary>
/// Method which focuses <see cref="Target"/> input element
/// </summary>
private void LabelActivated(RoutedEventArgs args)
{
Target?.Focus();
args.Handled = Target != null;
}
/// <summary>
/// Handler of <see cref="IInputElement.PointerPressed"/> event
/// </summary>
/// <param name="e">Event Arguments</param>
protected override void OnPointerPressed(PointerPressedEventArgs e)
{
if (e.GetCurrentPoint(this).Properties.PointerUpdateKind == PointerUpdateKind.LeftButtonPressed)
{
LabelActivated(e);
}
base.OnPointerPressed(e);
}
}
}

25
src/Avalonia.Controls/Presenters/ContentPresenter.cs

@ -85,10 +85,19 @@ namespace Avalonia.Controls.Presenters
public static readonly StyledProperty<Thickness> PaddingProperty =
Decorator.PaddingProperty.AddOwner<ContentPresenter>();
/// <summary>
/// Defines the <see cref="RecognizesAccessKey"/> property
/// </summary>
public static readonly DirectProperty<ContentPresenter, bool> RecognizesAccessKeyProperty =
AvaloniaProperty.RegisterDirect<ContentPresenter, bool>(
nameof(RecognizesAccessKey),
cp => cp.RecognizesAccessKey, (cp, value) => cp.RecognizesAccessKey = value);
private IControl _child;
private bool _createdChild;
private IRecyclingDataTemplate _recyclingDataTemplate;
private readonly BorderRenderHelper _borderRenderer = new BorderRenderHelper();
private bool _recognizesAccessKey;
/// <summary>
/// Initializes static members of the <see cref="ContentPresenter"/> class.
@ -208,6 +217,15 @@ namespace Avalonia.Controls.Presenters
set { SetValue(PaddingProperty, value); }
}
/// <summary>
/// Determine if <see cref="ContentPresenter"/> should use <see cref="AccessText"/> in its style
/// </summary>
public bool RecognizesAccessKey
{
get => _recognizesAccessKey;
set => SetAndRaise(RecognizesAccessKeyProperty, ref _recognizesAccessKey, value);
}
/// <summary>
/// Gets the host content control.
/// </summary>
@ -311,7 +329,12 @@ namespace Avalonia.Controls.Presenters
if (content != null && newChild == null)
{
var dataTemplate = this.FindDataTemplate(content, ContentTemplate) ?? FuncDataTemplate.Default;
var dataTemplate = this.FindDataTemplate(content, ContentTemplate) ??
(
RecognizesAccessKey
? FuncDataTemplate.Access
: FuncDataTemplate.Default
);
if (dataTemplate is IRecyclingDataTemplate rdt)
{

28
src/Avalonia.Controls/Templates/FuncDataTemplate.cs

@ -1,5 +1,6 @@
using System;
using System.Reactive.Linq;
using Avalonia.Controls.Primitives;
namespace Avalonia.Controls.Templates
{
@ -30,6 +31,31 @@ namespace Avalonia.Controls.Templates
},
true);
/// <summary>
/// The default data template used in the case where no matching data template is found
/// but <see cref="AccessText"/> should be used.
/// </summary>
public static readonly FuncDataTemplate Access =
new FuncDataTemplate<object>(
(data, s) =>
{
if (data != null)
{
var result = new AccessText();
result.Bind(TextBlock.TextProperty,
result.GetObservable(Control.DataContextProperty).Select(x => x?.ToString()));
return result;
}
else
{
return null;
}
},
true);
/// <summary>
/// The implementation of the <see cref="Match"/> method.
/// </summary>
private readonly Func<object, bool> _match;
private readonly bool _supportsRecycling;
@ -42,7 +68,7 @@ namespace Avalonia.Controls.Templates
/// </param>
/// <param name="supportsRecycling">Whether the control can be recycled.</param>
public FuncDataTemplate(
Type type,
Type type,
Func<object, INameScope, IControl> build,
bool supportsRecycling = false)
: this(o => IsInstance(o, type), build, supportsRecycling)

3
src/Avalonia.Themes.Default/DefaultTheme.xaml

@ -12,7 +12,8 @@
<StyleInclude Source="resm:Avalonia.Themes.Default.CaptionButtons.xaml?assembly=Avalonia.Themes.Default"/>
<StyleInclude Source="resm:Avalonia.Themes.Default.ComboBox.xaml?assembly=Avalonia.Themes.Default"/>
<StyleInclude Source="resm:Avalonia.Themes.Default.ComboBoxItem.xaml?assembly=Avalonia.Themes.Default"/>
<StyleInclude Source="resm:Avalonia.Themes.Default.ContentControl.xaml?assembly=Avalonia.Themes.Default"/>
<StyleInclude Source="resm:Avalonia.Themes.Default.ContentControl.xaml?assembly=Avalonia.Themes.Default"/>
<StyleInclude Source="resm:Avalonia.Themes.Default.Label.xaml?assembly=Avalonia.Themes.Default"/>
<StyleInclude Source="resm:Avalonia.Themes.Default.GridSplitter.xaml?assembly=Avalonia.Themes.Default"/>
<StyleInclude Source="resm:Avalonia.Themes.Default.ItemsControl.xaml?assembly=Avalonia.Themes.Default"/>
<StyleInclude Source="resm:Avalonia.Themes.Default.ListBox.xaml?assembly=Avalonia.Themes.Default"/>

17
src/Avalonia.Themes.Default/Label.xaml

@ -0,0 +1,17 @@
<Style xmlns="https://github.com/avaloniaui" Selector="Label">
<Setter Property="Padding" Value="3"/>
<Setter Property="Template">
<ControlTemplate>
<ContentPresenter Name="PART_ContentPresenter"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
ContentTemplate="{TemplateBinding ContentTemplate}"
Content="{TemplateBinding Content}"
Padding="{TemplateBinding Padding}"
RecognizesAccessKey="True"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"/>
</ControlTemplate>
</Setter>
</Style>

3
src/Avalonia.Themes.Fluent/FluentTheme.xaml

@ -11,7 +11,8 @@
<StyleInclude Source="avares://Avalonia.Themes.Fluent/CheckBox.xaml"/>
<StyleInclude Source="avares://Avalonia.Themes.Fluent/ComboBox.xaml"/>
<StyleInclude Source="avares://Avalonia.Themes.Fluent/ComboBoxItem.xaml"/>
<StyleInclude Source="avares://Avalonia.Themes.Fluent/ContentControl.xaml"/>
<StyleInclude Source="avares://Avalonia.Themes.Fluent/ContentControl.xaml"/>
<StyleInclude Source="avares://Avalonia.Themes.Fluent/Label.xaml"/>
<StyleInclude Source="avares://Avalonia.Themes.Fluent/GridSplitter.xaml"/>
<StyleInclude Source="avares://Avalonia.Themes.Fluent/ItemsControl.xaml"/>
<StyleInclude Source="avares://Avalonia.Themes.Fluent/ListBox.xaml"/>

17
src/Avalonia.Themes.Fluent/Label.xaml

@ -0,0 +1,17 @@
<Style xmlns="https://github.com/avaloniaui" Selector="Label">
<Setter Property="Padding" Value="3"/>
<Setter Property="Template">
<ControlTemplate>
<ContentPresenter Name="PART_ContentPresenter"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
ContentTemplate="{TemplateBinding ContentTemplate}"
Content="{TemplateBinding Content}"
Padding="{TemplateBinding Padding}"
RecognizesAccessKey="True"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"/>
</ControlTemplate>
</Setter>
</Style>
Loading…
Cancel
Save