mirror of
https://github.com/AtomUI/AtomUI.git
synced 2026-10-22 00:46:48 +08:00
Add Resize support for TextArea
This commit is contained in:
+2
@@ -392,6 +392,8 @@ namespace AtomUI.Controls.DesignTokens
|
||||
public static readonly TokenResourceKey FontSize = new TokenResourceKey("TextArea.FontSize");
|
||||
public static readonly TokenResourceKey FontSizeLG = new TokenResourceKey("TextArea.FontSizeLG");
|
||||
public static readonly TokenResourceKey FontSizeSM = new TokenResourceKey("TextArea.FontSizeSM");
|
||||
public static readonly TokenResourceKey ResizeHandleSize = new TokenResourceKey("TextArea.ResizeHandleSize");
|
||||
public static readonly TokenResourceKey ResizeIndicatorLineColor = new TokenResourceKey("TextArea.ResizeIndicatorLineColor");
|
||||
}
|
||||
|
||||
public static class ListTokenKey
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Input;
|
||||
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
internal class ResizeHandle : TemplatedControl
|
||||
{
|
||||
internal TextArea? Owner { get; set; }
|
||||
|
||||
private Point? _lastPoint;
|
||||
private bool _dragging;
|
||||
|
||||
protected override void OnPointerPressed(PointerPressedEventArgs e)
|
||||
{
|
||||
base.OnPointerPressed(e);
|
||||
e.Handled = true;
|
||||
_lastPoint = e.GetPosition(TopLevel.GetTopLevel(this));
|
||||
}
|
||||
|
||||
protected override void OnPointerReleased(PointerReleasedEventArgs e)
|
||||
{
|
||||
base.OnPointerReleased(e);
|
||||
if (_lastPoint.HasValue)
|
||||
{
|
||||
Owner?.NotifyResizeCompleted();
|
||||
e.Handled = true;
|
||||
_lastPoint = null;
|
||||
_dragging = false;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnPointerMoved(PointerEventArgs e)
|
||||
{
|
||||
base.OnPointerMoved(e);
|
||||
if (_lastPoint.HasValue && e.Properties.IsLeftButtonPressed)
|
||||
{
|
||||
var delta = e.GetPosition(TopLevel.GetTopLevel(this)) - _lastPoint.Value;
|
||||
var manhattanDistance = Math.Abs(delta.X) + Math.Abs(delta.Y);
|
||||
if (manhattanDistance > Constants.DragThreshold)
|
||||
{
|
||||
if (!_dragging)
|
||||
{
|
||||
Owner?.NotifyAboutToResize();
|
||||
_dragging = true;
|
||||
}
|
||||
Owner?.NotifyResizing(delta);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Controls.Templates;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Media.TextFormatting;
|
||||
|
||||
@@ -25,7 +26,13 @@ public class TextArea : AvaloniaTextBox,
|
||||
|
||||
public static readonly StyledProperty<bool> IsAutoSizeProperty =
|
||||
AvaloniaProperty.Register<TextArea, bool>(nameof(IsAutoSize), false);
|
||||
|
||||
public static readonly StyledProperty<bool> IsShowCountProperty =
|
||||
AvaloniaProperty.Register<TextArea, bool>(nameof(IsShowCount));
|
||||
|
||||
public static readonly StyledProperty<bool> IsResizableProperty =
|
||||
AvaloniaProperty.Register<TextArea, bool>(nameof(IsResizable));
|
||||
|
||||
public static readonly StyledProperty<AddOnDecoratedVariant> StyleVariantProperty =
|
||||
AddOnDecoratedBox.StyleVariantProperty.AddOwner<TextArea>();
|
||||
|
||||
@@ -65,6 +72,18 @@ public class TextArea : AvaloniaTextBox,
|
||||
get => GetValue(IsAutoSizeProperty);
|
||||
set => SetValue(IsAutoSizeProperty, value);
|
||||
}
|
||||
|
||||
public bool IsShowCount
|
||||
{
|
||||
get => GetValue(IsShowCountProperty);
|
||||
set => SetValue(IsShowCountProperty, value);
|
||||
}
|
||||
|
||||
public bool IsResizable
|
||||
{
|
||||
get => GetValue(IsResizableProperty);
|
||||
set => SetValue(IsResizableProperty, value);
|
||||
}
|
||||
|
||||
public AddOnDecoratedVariant StyleVariant
|
||||
{
|
||||
@@ -122,6 +141,11 @@ public class TextArea : AvaloniaTextBox,
|
||||
AvaloniaProperty.RegisterDirect<TextArea, bool>(nameof(IsEffectiveShowClearButton),
|
||||
o => o.IsEffectiveShowClearButton,
|
||||
(o, v) => o.IsEffectiveShowClearButton = v);
|
||||
|
||||
internal static readonly DirectProperty<TextArea, string?> CountTextProperty =
|
||||
AvaloniaProperty.RegisterDirect<TextArea, string?>(nameof(CountText),
|
||||
o => o.CountText,
|
||||
(o, v) => o.CountText = v);
|
||||
|
||||
private bool _isEffectiveShowClearButton;
|
||||
|
||||
@@ -130,7 +154,15 @@ public class TextArea : AvaloniaTextBox,
|
||||
get => _isEffectiveShowClearButton;
|
||||
set => SetAndRaise(IsEffectiveShowClearButtonProperty, ref _isEffectiveShowClearButton, value);
|
||||
}
|
||||
|
||||
private string? _countText;
|
||||
|
||||
internal string? CountText
|
||||
{
|
||||
get => _countText;
|
||||
set => SetAndRaise(CountTextProperty, ref _countText, value);
|
||||
}
|
||||
|
||||
Control IControlSharedTokenResourcesHost.HostControl => this;
|
||||
string IControlSharedTokenResourcesHost.TokenId => LineEditToken.ID;
|
||||
Control IMotionAwareControl.PropertyBindTarget => this;
|
||||
@@ -139,6 +171,8 @@ public class TextArea : AvaloniaTextBox,
|
||||
|
||||
private ScrollViewer? _scrollViewer;
|
||||
private IconButton? _clearButton;
|
||||
private ResizeHandle? _resizeHandle;
|
||||
private double? _originHeight; // 拖动改变高度的初始值
|
||||
|
||||
static TextArea()
|
||||
{
|
||||
@@ -174,6 +208,10 @@ public class TextArea : AvaloniaTextBox,
|
||||
{
|
||||
ConfigureEffectiveShowClearButton();
|
||||
}
|
||||
else if (change.Property == IsShowCountProperty)
|
||||
{
|
||||
HandleInputChanged(Text);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
@@ -190,8 +228,16 @@ public class TextArea : AvaloniaTextBox,
|
||||
{
|
||||
_clearButton.Click += (sender, args) => { NotifyClearButtonClicked(); };
|
||||
}
|
||||
|
||||
_resizeHandle = e.NameScope.Find<ResizeHandle>(TextAreaThemeConstants.ResizeHandle);
|
||||
if (_resizeHandle is not null)
|
||||
{
|
||||
_resizeHandle.Owner = this;
|
||||
}
|
||||
|
||||
UpdatePseudoClasses();
|
||||
ConfigureEffectiveShowClearButton();
|
||||
HandleInputChanged(Text);
|
||||
}
|
||||
|
||||
internal void NotifyScrollViewerCreated(ScrollViewer scrollViewer)
|
||||
@@ -274,4 +320,54 @@ public class TextArea : AvaloniaTextBox,
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
protected override void OnTextInput(TextInputEventArgs e)
|
||||
{
|
||||
base.OnTextInput(e);
|
||||
HandleInputChanged(Text);
|
||||
}
|
||||
|
||||
private void HandleInputChanged(string? text)
|
||||
{
|
||||
if (IsShowCount)
|
||||
{
|
||||
SetCurrentValue(CountTextProperty, $"{text?.Length ?? 0} / {MaxLength}");
|
||||
}
|
||||
}
|
||||
|
||||
internal void NotifyAboutToResize()
|
||||
{
|
||||
if (_scrollViewer != null)
|
||||
{
|
||||
if (!double.IsNaN(Height))
|
||||
{
|
||||
_scrollViewer.SetCurrentValue(HeightProperty, _scrollViewer.Bounds.Height);
|
||||
}
|
||||
var minHeight = _scrollViewer.MinHeight;
|
||||
var height = _scrollViewer.Height;
|
||||
if (double.IsNaN(height))
|
||||
{
|
||||
height = minHeight;
|
||||
}
|
||||
_originHeight = height;
|
||||
SetCurrentValue(HeightProperty, double.NaN);
|
||||
}
|
||||
}
|
||||
|
||||
internal void NotifyResizing(Point delta)
|
||||
{
|
||||
if (_scrollViewer != null && _originHeight != null)
|
||||
{
|
||||
var minHeight = _scrollViewer.MinHeight;
|
||||
var maxHeight = _scrollViewer.MaxHeight;
|
||||
var height = _originHeight.Value + delta.Y;
|
||||
height = Math.Max(minHeight, Math.Min(height, maxHeight));
|
||||
_scrollViewer.SetCurrentValue(HeightProperty, height);
|
||||
}
|
||||
}
|
||||
|
||||
internal void NotifyResizeCompleted()
|
||||
{
|
||||
_originHeight = null;
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ using AtomUI.Controls.Themes;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Media;
|
||||
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
@@ -25,6 +26,10 @@ internal class TextAreaDecoratedBox : AddOnDecoratedBox
|
||||
AvaloniaProperty.Register<TextAreaDecoratedBox, bool>(
|
||||
nameof(IsScrollChainingEnabled), true);
|
||||
|
||||
public static readonly StyledProperty<IBrush?> ResizeIndicatorLineBrushProperty =
|
||||
AvaloniaProperty.Register<TextAreaDecoratedBox, IBrush?>(
|
||||
nameof(ResizeIndicatorLineBrush));
|
||||
|
||||
public bool IsAllowAutoHide
|
||||
{
|
||||
get => GetValue(IsAllowAutoHideProperty);
|
||||
@@ -48,7 +53,35 @@ internal class TextAreaDecoratedBox : AddOnDecoratedBox
|
||||
get => GetValue(IsScrollChainingEnabledProperty);
|
||||
set => SetValue(IsScrollChainingEnabledProperty, value);
|
||||
}
|
||||
|
||||
public IBrush? ResizeIndicatorLineBrush
|
||||
{
|
||||
get => GetValue(ResizeIndicatorLineBrushProperty);
|
||||
set => SetValue(ResizeIndicatorLineBrushProperty, value);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 内部属性定义
|
||||
|
||||
internal static readonly DirectProperty<TextAreaDecoratedBox, bool> IsResizableProperty =
|
||||
AvaloniaProperty.RegisterDirect<TextAreaDecoratedBox, bool>(nameof(IsResizable),
|
||||
o => o.IsResizable,
|
||||
(o, v) => o.IsResizable = v);
|
||||
|
||||
private bool _isResizable;
|
||||
|
||||
internal bool IsResizable
|
||||
{
|
||||
get => _isResizable;
|
||||
set => SetAndRaise(IsResizableProperty, ref _isResizable, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
static TextAreaDecoratedBox()
|
||||
{
|
||||
AffectsRender<TextAreaDecoratedBox>(ResizeIndicatorLineBrushProperty, IsResizableProperty);
|
||||
}
|
||||
|
||||
internal ScrollViewer? ScrollViewer { get; set; }
|
||||
internal TextArea? Owner { get; set; }
|
||||
@@ -62,4 +95,29 @@ internal class TextAreaDecoratedBox : AddOnDecoratedBox
|
||||
Owner?.NotifyScrollViewerCreated(ScrollViewer);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Render(DrawingContext context)
|
||||
{
|
||||
if (IsResizable)
|
||||
{
|
||||
var bounds = Bounds.Deflate(new Thickness(2));
|
||||
var sideLength = 7d;
|
||||
var (line1Start, line1End) = CalculateResizeLine(bounds, sideLength);
|
||||
var (line2Start, line2End) = CalculateResizeLine(bounds, sideLength - 3);
|
||||
var pen = new Pen(ResizeIndicatorLineBrush);
|
||||
|
||||
context.DrawLine(pen, line1Start, line1End);
|
||||
context.DrawLine(pen, line2Start, line2End);
|
||||
}
|
||||
}
|
||||
|
||||
private (Point, Point) CalculateResizeLine(Rect bounds, double sideLength)
|
||||
{
|
||||
double right = bounds.Right;
|
||||
double bottom = bounds.Bottom;
|
||||
Point rightSidePoint = new Point(right, bottom - sideLength);
|
||||
Point bottomSidePoint = new Point(right - sideLength, bottom);
|
||||
|
||||
return (rightSidePoint, bottomSidePoint);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using AtomUI.Theme.TokenSystem;
|
||||
using Avalonia.Media;
|
||||
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
@@ -26,12 +27,24 @@ internal class TextAreaToken : AbstractControlDesignToken
|
||||
/// 小号字体大小
|
||||
/// </summary>
|
||||
public double FontSizeSM { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Resize 指示器颜色
|
||||
/// </summary>
|
||||
public Color ResizeIndicatorLineColor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Resize 指示器大小
|
||||
/// </summary>
|
||||
public double ResizeHandleSize { get; set; }
|
||||
|
||||
public override void CalculateTokenValues()
|
||||
{
|
||||
base.CalculateTokenValues();
|
||||
FontSize = SharedToken.FontSize;
|
||||
FontSizeLG = SharedToken.FontSizeLG;
|
||||
FontSizeSM = SharedToken.FontSizeSM;
|
||||
FontSize = SharedToken.FontSize;
|
||||
FontSizeLG = SharedToken.FontSizeLG;
|
||||
FontSizeSM = SharedToken.FontSizeSM;
|
||||
ResizeIndicatorLineColor = SharedToken.ColorTextDescription;
|
||||
ResizeHandleSize = SharedToken.SizeXS;
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ using AtomUI.Theme.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Media;
|
||||
|
||||
namespace AtomUI.Controls;
|
||||
@@ -29,6 +30,9 @@ public class TextBox : AvaloniaTextBox,
|
||||
public static readonly StyledProperty<bool> IsCustomFontSizeProperty =
|
||||
AvaloniaProperty.Register<TextBox, bool>(nameof(IsCustomFontSize));
|
||||
|
||||
public static readonly StyledProperty<bool> IsShowCountProperty =
|
||||
AvaloniaProperty.Register<TextBox, bool>(nameof(IsShowCount));
|
||||
|
||||
public static readonly StyledProperty<IBrush?> WatermarkForegroundProperty =
|
||||
AvaloniaProperty.Register<TextBox, IBrush?>(nameof(WatermarkForeground));
|
||||
|
||||
@@ -58,6 +62,12 @@ public class TextBox : AvaloniaTextBox,
|
||||
get => GetValue(IsCustomFontSizeProperty);
|
||||
set => SetValue(IsCustomFontSizeProperty, value);
|
||||
}
|
||||
|
||||
public bool IsShowCount
|
||||
{
|
||||
get => GetValue(IsShowCountProperty);
|
||||
set => SetValue(IsShowCountProperty, value);
|
||||
}
|
||||
|
||||
public IBrush? WatermarkForeground
|
||||
{
|
||||
@@ -78,6 +88,11 @@ public class TextBox : AvaloniaTextBox,
|
||||
AvaloniaProperty.RegisterDirect<TextBox, bool>(nameof(IsEffectiveShowClearButton),
|
||||
o => o.IsEffectiveShowClearButton,
|
||||
(o, v) => o.IsEffectiveShowClearButton = v);
|
||||
|
||||
internal static readonly DirectProperty<TextBox, string?> CountTextProperty =
|
||||
AvaloniaProperty.RegisterDirect<TextBox, string?>(nameof(CountText),
|
||||
o => o.CountText,
|
||||
(o, v) => o.CountText = v);
|
||||
|
||||
private bool _isEffectiveShowClearButton;
|
||||
|
||||
@@ -87,6 +102,14 @@ public class TextBox : AvaloniaTextBox,
|
||||
set => SetAndRaise(IsEffectiveShowClearButtonProperty, ref _isEffectiveShowClearButton, value);
|
||||
}
|
||||
|
||||
private string? _countText;
|
||||
|
||||
internal string? CountText
|
||||
{
|
||||
get => _countText;
|
||||
set => SetAndRaise(CountTextProperty, ref _countText, value);
|
||||
}
|
||||
|
||||
Control IControlSharedTokenResourcesHost.HostControl => this;
|
||||
string IControlSharedTokenResourcesHost.TokenId => LineEditToken.ID;
|
||||
Control IMotionAwareControl.PropertyBindTarget => this;
|
||||
@@ -110,6 +133,10 @@ public class TextBox : AvaloniaTextBox,
|
||||
{
|
||||
ConfigureEffectiveShowClearButton();
|
||||
}
|
||||
else if (change.Property == IsShowCountProperty)
|
||||
{
|
||||
HandleInputChanged(Text);
|
||||
}
|
||||
}
|
||||
|
||||
private void ConfigureEffectiveShowClearButton()
|
||||
@@ -132,10 +159,25 @@ public class TextBox : AvaloniaTextBox,
|
||||
_clearButton.Click += (sender, args) => { NotifyClearButtonClicked(); };
|
||||
}
|
||||
ConfigureEffectiveShowClearButton();
|
||||
HandleInputChanged(Text);
|
||||
}
|
||||
|
||||
protected virtual void NotifyClearButtonClicked()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
protected override void OnTextInput(TextInputEventArgs e)
|
||||
{
|
||||
base.OnTextInput(e);
|
||||
HandleInputChanged(Text);
|
||||
}
|
||||
|
||||
private void HandleInputChanged(string? text)
|
||||
{
|
||||
if (IsShowCount)
|
||||
{
|
||||
SetCurrentValue(CountTextProperty, $"{text?.Length ?? 0} / {MaxLength}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ internal static class TextBoxThemeConstants
|
||||
|
||||
internal static class TextAreaThemeConstants
|
||||
{
|
||||
public const string ResizeHandle = "PART_ResizeHandle";
|
||||
public const string ScrollViewerPart = "PART_ScrollViewer";
|
||||
public const string ClearButtonPart = "PART_ClearButton";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
<ResourceInclude Source="SearchEditDecoratedBoxTheme.axaml" />
|
||||
<ResourceInclude Source="TextAreaDecoratedBoxTheme.axaml" />
|
||||
<ResourceInclude Source="SearchEditTheme.axaml" />
|
||||
<ResourceInclude Source="ResizeHandleTheme.axaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
<themes:TextBoxTheme x:Key="{x:Type atom:TextBox}" TargetType="atom:TextBox"/>
|
||||
<themes:LineEditTheme x:Key="{x:Type atom:LineEdit}" TargetType="atom:LineEdit"/>
|
||||
|
||||
@@ -53,6 +53,11 @@
|
||||
Focusable="False"
|
||||
Content="{Binding InnerRightContent, RelativeSource={RelativeSource AncestorType=atom:LineEdit}}"
|
||||
IsVisible="{Binding InnerRightContent, RelativeSource={RelativeSource AncestorType=atom:LineEdit}, Converter={x:Static ObjectConverters.IsNotNull}}" />
|
||||
<atom:TextBlock Name="TextCountIndicator"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{DynamicResource {x:Static atom:SharedTokenKey.ColorTextPlaceholder}}"
|
||||
Text="{Binding CountText, RelativeSource={RelativeSource AncestorType=atom:LineEdit}}"
|
||||
IsVisible="{Binding IsShowCount, RelativeSource={RelativeSource AncestorType=atom:LineEdit}}"/>
|
||||
</StackPanel>
|
||||
</atom:AddOnDecoratedBox.ContentRightAddOn>
|
||||
|
||||
@@ -128,7 +133,5 @@
|
||||
</Style>
|
||||
</Style>
|
||||
</Style>
|
||||
|
||||
</Style>
|
||||
|
||||
</ControlTheme>
|
||||
@@ -0,0 +1,18 @@
|
||||
<ResourceDictionary
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:atom="https://atomui.net"
|
||||
x:ClassModifier="internal">
|
||||
<ControlTheme x:Key="{x:Type atom:ResizeHandle}" TargetType="atom:ResizeHandle">
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<Border Name="Frame" Background="{TemplateBinding Background}"/>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="Height" Value="8" />
|
||||
<Setter Property="Width" Value="8" />
|
||||
|
||||
</ControlTheme>
|
||||
</ResourceDictionary>
|
||||
@@ -16,49 +16,52 @@
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
Background="{TemplateBinding Background}"
|
||||
BackgroundSizing="OuterBorderEdge">
|
||||
<ScrollViewer
|
||||
Name="{x:Static atom:TextAreaThemeConstants.ScrollViewerPart}"
|
||||
AllowAutoHide="{TemplateBinding IsAllowAutoHide}"
|
||||
HorizontalScrollBarVisibility="{TemplateBinding HorizontalScrollBarVisibility}"
|
||||
VerticalScrollBarVisibility="{TemplateBinding VerticalScrollBarVisibility}"
|
||||
IsScrollChainingEnabled="{TemplateBinding IsScrollChainingEnabled}">
|
||||
<Border Name="ScrollViewerContent">
|
||||
<DockPanel Name="ContentLayout" LastChildFill="True">
|
||||
<ContentPresenter
|
||||
Name="{x:Static atom:AddOnDecoratedBoxThemeConstants.ContentLeftAddOnPart}"
|
||||
DockPanel.Dock="Left"
|
||||
VerticalAlignment="Top"
|
||||
VerticalContentAlignment="Center"
|
||||
HorizontalAlignment="Left"
|
||||
Focusable="False"
|
||||
Content="{TemplateBinding ContentLeftAddOn}"
|
||||
ContentTemplate="{TemplateBinding ContentLeftAddOnTemplate}"
|
||||
IsVisible="{TemplateBinding ContentLeftAddOn, Converter={x:Static ObjectConverters.IsNotNull}}" />
|
||||
<ScrollViewer
|
||||
Name="{x:Static atom:TextAreaThemeConstants.ScrollViewerPart}"
|
||||
AllowAutoHide="{TemplateBinding IsAllowAutoHide}"
|
||||
HorizontalScrollBarVisibility="{TemplateBinding HorizontalScrollBarVisibility}"
|
||||
VerticalScrollBarVisibility="{TemplateBinding VerticalScrollBarVisibility}"
|
||||
IsScrollChainingEnabled="{TemplateBinding IsScrollChainingEnabled}">
|
||||
<Border Name="ScrollViewerContent">
|
||||
<DockPanel Name="ContentLayout" LastChildFill="True">
|
||||
<ContentPresenter
|
||||
Name="{x:Static atom:AddOnDecoratedBoxThemeConstants.ContentLeftAddOnPart}"
|
||||
DockPanel.Dock="Left"
|
||||
VerticalAlignment="Top"
|
||||
VerticalContentAlignment="Center"
|
||||
HorizontalAlignment="Left"
|
||||
Focusable="False"
|
||||
Content="{TemplateBinding ContentLeftAddOn}"
|
||||
ContentTemplate="{TemplateBinding ContentLeftAddOnTemplate}"
|
||||
IsVisible="{TemplateBinding ContentLeftAddOn, Converter={x:Static ObjectConverters.IsNotNull}}" />
|
||||
|
||||
<ContentPresenter
|
||||
DockPanel.Dock="Right"
|
||||
Name="{x:Static atom:AddOnDecoratedBoxThemeConstants.ContentRightAddOnPart}"
|
||||
VerticalAlignment="Top"
|
||||
VerticalContentAlignment="Center"
|
||||
HorizontalAlignment="Right"
|
||||
Focusable="False"
|
||||
Content="{TemplateBinding ContentRightAddOn}"
|
||||
ContentTemplate="{TemplateBinding ContentRightAddOnTemplate}"
|
||||
IsVisible="{TemplateBinding ContentRightAddOn, Converter={x:Static ObjectConverters.IsNotNull}}" />
|
||||
<ContentPresenter
|
||||
DockPanel.Dock="Right"
|
||||
Name="{x:Static atom:AddOnDecoratedBoxThemeConstants.ContentRightAddOnPart}"
|
||||
VerticalAlignment="Top"
|
||||
VerticalContentAlignment="Center"
|
||||
HorizontalAlignment="Right"
|
||||
Focusable="False"
|
||||
Content="{TemplateBinding ContentRightAddOn}"
|
||||
ContentTemplate="{TemplateBinding ContentRightAddOnTemplate}"
|
||||
IsVisible="{TemplateBinding ContentRightAddOn, Converter={x:Static ObjectConverters.IsNotNull}}" />
|
||||
|
||||
<ContentPresenter
|
||||
Name="{x:Static atom:AddOnDecoratedBoxThemeConstants.ContentPresenterPart}"
|
||||
Content="{TemplateBinding Content}"
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}" />
|
||||
</DockPanel>
|
||||
</Border>
|
||||
</ScrollViewer>
|
||||
<ContentPresenter
|
||||
Name="{x:Static atom:AddOnDecoratedBoxThemeConstants.ContentPresenterPart}"
|
||||
Content="{TemplateBinding Content}"
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}" />
|
||||
</DockPanel>
|
||||
</Border>
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
|
||||
<Style Selector="^:is(atom|TextAreaDecoratedBox)">
|
||||
|
||||
<Setter Property="VerticalAlignment" Value="Stretch" />
|
||||
<Setter Property="ClipToBounds" Value="True" />
|
||||
<Setter Property="ResizeIndicatorLineBrush"
|
||||
Value="{DynamicResource {x:Static atom:TextAreaTokenKey.ResizeIndicatorLineColor}}" />
|
||||
<Style Selector="^[SizeType=Large]">
|
||||
<Style Selector="^ /template/ Border#PART_ContentFrame">
|
||||
<Setter Property="Padding" Value="0" />
|
||||
|
||||
@@ -7,71 +7,87 @@
|
||||
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="atom:TextArea">
|
||||
<atom:TextAreaDecoratedBox
|
||||
Name="{x:Static atom:AddOnDecoratedBox.AddOnDecoratedBoxPart}"
|
||||
ContentLeftAddOn="{TemplateBinding InnerLeftContent}"
|
||||
ContentLeftAddOnTemplate="{TemplateBinding InnerLeftContentTemplate}"
|
||||
StyleVariant="{TemplateBinding StyleVariant}"
|
||||
SizeType="{TemplateBinding SizeType}"
|
||||
Status="{TemplateBinding Status}"
|
||||
Focusable="True"
|
||||
IsAllowAutoHide="{TemplateBinding ScrollViewer.AllowAutoHide}"
|
||||
HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
|
||||
VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"
|
||||
IsScrollChainingEnabled="{TemplateBinding ScrollViewer.IsScrollChainingEnabled}">
|
||||
<atom:TextAreaDecoratedBox.ContentRightAddOn>
|
||||
<StackPanel Orientation="Horizontal"
|
||||
Spacing="{DynamicResource {x:Static atom:SharedTokenKey.UniformlyPaddingXXS}}">
|
||||
<atom:IconButton
|
||||
Name="{x:Static atom:TextAreaThemeConstants.ClearButtonPart}"
|
||||
Icon="{atom:IconProvider CloseCircleFilled}"
|
||||
IconWidth="{DynamicResource {x:Static atom:SharedTokenKey.IconSize}}"
|
||||
IconHeight="{DynamicResource {x:Static atom:SharedTokenKey.IconSize}}"
|
||||
NormalIconBrush="{DynamicResource {x:Static atom:SharedTokenKey.ColorTextQuaternary}}"
|
||||
ActiveIconBrush="{DynamicResource {x:Static atom:SharedTokenKey.ColorTextTertiary}}"
|
||||
SelectedIconBrush="{DynamicResource {x:Static atom:SharedTokenKey.ColorText}}"
|
||||
IsMotionEnabled="{Binding IsMotionEnabled, RelativeSource={RelativeSource AncestorType=atom:TextArea}}"
|
||||
IsVisible="{Binding IsEffectiveShowClearButton, RelativeSource={RelativeSource AncestorType=atom:TextArea}}" />
|
||||
<ContentPresenter
|
||||
VerticalAlignment="Stretch"
|
||||
VerticalContentAlignment="Center"
|
||||
HorizontalAlignment="Right"
|
||||
Focusable="False"
|
||||
Content="{Binding InnerRightContent, RelativeSource={RelativeSource AncestorType=atom:TextArea}}"
|
||||
IsVisible="{Binding InnerRightContent, RelativeSource={RelativeSource AncestorType=atom:TextArea}, Converter={x:Static ObjectConverters.IsNotNull}}" />
|
||||
</StackPanel>
|
||||
</atom:TextAreaDecoratedBox.ContentRightAddOn>
|
||||
<DockPanel LastChildFill="True"
|
||||
Height="{TemplateBinding Height}">
|
||||
<atom:TextBlock Name="TextCountIndicator"
|
||||
DockPanel.Dock="Bottom"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Right"
|
||||
Text="{TemplateBinding CountText}"
|
||||
IsVisible="{TemplateBinding IsShowCount}" />
|
||||
<Panel>
|
||||
<atom:TextAreaDecoratedBox
|
||||
Name="{x:Static atom:AddOnDecoratedBox.AddOnDecoratedBoxPart}"
|
||||
ContentLeftAddOn="{TemplateBinding InnerLeftContent}"
|
||||
ContentLeftAddOnTemplate="{TemplateBinding InnerLeftContentTemplate}"
|
||||
StyleVariant="{TemplateBinding StyleVariant}"
|
||||
SizeType="{TemplateBinding SizeType}"
|
||||
Status="{TemplateBinding Status}"
|
||||
Focusable="True"
|
||||
IsResizable="{TemplateBinding IsResizable}"
|
||||
IsAllowAutoHide="{TemplateBinding ScrollViewer.AllowAutoHide}"
|
||||
HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
|
||||
VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"
|
||||
IsScrollChainingEnabled="{TemplateBinding ScrollViewer.IsScrollChainingEnabled}">
|
||||
<atom:TextAreaDecoratedBox.ContentRightAddOn>
|
||||
<StackPanel Orientation="Horizontal"
|
||||
Spacing="{DynamicResource {x:Static atom:SharedTokenKey.UniformlyPaddingXXS}}">
|
||||
<atom:IconButton
|
||||
Name="{x:Static atom:TextAreaThemeConstants.ClearButtonPart}"
|
||||
Icon="{atom:IconProvider CloseCircleFilled}"
|
||||
IconWidth="{DynamicResource {x:Static atom:SharedTokenKey.IconSize}}"
|
||||
IconHeight="{DynamicResource {x:Static atom:SharedTokenKey.IconSize}}"
|
||||
NormalIconBrush="{DynamicResource {x:Static atom:SharedTokenKey.ColorTextQuaternary}}"
|
||||
ActiveIconBrush="{DynamicResource {x:Static atom:SharedTokenKey.ColorTextTertiary}}"
|
||||
SelectedIconBrush="{DynamicResource {x:Static atom:SharedTokenKey.ColorText}}"
|
||||
IsMotionEnabled="{Binding IsMotionEnabled, RelativeSource={RelativeSource AncestorType=atom:TextArea}}"
|
||||
IsVisible="{Binding IsEffectiveShowClearButton, RelativeSource={RelativeSource AncestorType=atom:TextArea}}" />
|
||||
<ContentPresenter
|
||||
VerticalAlignment="Stretch"
|
||||
VerticalContentAlignment="Center"
|
||||
HorizontalAlignment="Right"
|
||||
Focusable="False"
|
||||
Content="{Binding InnerRightContent, RelativeSource={RelativeSource AncestorType=atom:TextArea}}"
|
||||
IsVisible="{Binding InnerRightContent, RelativeSource={RelativeSource AncestorType=atom:TextArea}, Converter={x:Static ObjectConverters.IsNotNull}}" />
|
||||
</StackPanel>
|
||||
</atom:TextAreaDecoratedBox.ContentRightAddOn>
|
||||
|
||||
<Panel Name="ContentLayout">
|
||||
<atom:TextBlock
|
||||
Name="Watermark"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
Text="{TemplateBinding Watermark}"
|
||||
Foreground="{TemplateBinding WatermarkForeground}"
|
||||
LineHeight="{TemplateBinding LineHeight}"
|
||||
TextAlignment="{TemplateBinding TextAlignment}"
|
||||
TextWrapping="{TemplateBinding TextWrapping}"
|
||||
IsVisible="{TemplateBinding Text, Converter={x:Static StringConverters.IsNullOrEmpty}}" />
|
||||
<TextPresenter
|
||||
Name="PART_TextPresenter"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
CaretBlinkInterval="{TemplateBinding CaretBlinkInterval}"
|
||||
CaretBrush="{TemplateBinding CaretBrush}"
|
||||
CaretIndex="{TemplateBinding CaretIndex}"
|
||||
LineHeight="{TemplateBinding LineHeight}"
|
||||
PasswordChar="{TemplateBinding PasswordChar}"
|
||||
RevealPassword="{TemplateBinding RevealPassword}"
|
||||
SelectionBrush="{TemplateBinding SelectionBrush}"
|
||||
SelectionStart="{TemplateBinding SelectionStart}"
|
||||
SelectionEnd="{TemplateBinding SelectionEnd}"
|
||||
SelectionForegroundBrush="{TemplateBinding SelectionForegroundBrush}"
|
||||
Text="{TemplateBinding Text, Mode=TwoWay}"
|
||||
TextAlignment="{TemplateBinding TextAlignment}"
|
||||
TextWrapping="{TemplateBinding TextWrapping}" />
|
||||
<Panel Name="ContentLayout">
|
||||
<atom:TextBlock
|
||||
Name="Watermark"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
Text="{TemplateBinding Watermark}"
|
||||
Foreground="{TemplateBinding WatermarkForeground}"
|
||||
LineHeight="{TemplateBinding LineHeight}"
|
||||
TextAlignment="{TemplateBinding TextAlignment}"
|
||||
TextWrapping="{TemplateBinding TextWrapping}"
|
||||
IsVisible="{TemplateBinding Text, Converter={x:Static StringConverters.IsNullOrEmpty}}" />
|
||||
<TextPresenter
|
||||
Name="PART_TextPresenter"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
CaretBlinkInterval="{TemplateBinding CaretBlinkInterval}"
|
||||
CaretBrush="{TemplateBinding CaretBrush}"
|
||||
CaretIndex="{TemplateBinding CaretIndex}"
|
||||
LineHeight="{TemplateBinding LineHeight}"
|
||||
PasswordChar="{TemplateBinding PasswordChar}"
|
||||
RevealPassword="{TemplateBinding RevealPassword}"
|
||||
SelectionBrush="{TemplateBinding SelectionBrush}"
|
||||
SelectionStart="{TemplateBinding SelectionStart}"
|
||||
SelectionEnd="{TemplateBinding SelectionEnd}"
|
||||
SelectionForegroundBrush="{TemplateBinding SelectionForegroundBrush}"
|
||||
Text="{TemplateBinding Text, Mode=TwoWay}"
|
||||
TextAlignment="{TemplateBinding TextAlignment}"
|
||||
TextWrapping="{TemplateBinding TextWrapping}" />
|
||||
</Panel>
|
||||
</atom:TextAreaDecoratedBox>
|
||||
<atom:ResizeHandle Name="{x:Static atom:TextAreaThemeConstants.ResizeHandle}"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Bottom"
|
||||
Cursor="SizeNorthSouth" />
|
||||
</Panel>
|
||||
</atom:TextAreaDecoratedBox>
|
||||
</DockPanel>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
|
||||
@@ -166,6 +182,10 @@
|
||||
<Setter Property="SelectedIconBrush" Value="{DynamicResource {x:Static atom:SharedTokenKey.ColorText}}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="^ /template/ atom|TextBlock#TextCountIndicator">
|
||||
<Setter Property="Foreground" Value="{DynamicResource {x:Static atom:SharedTokenKey.ColorTextPlaceholder}}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:disabled">
|
||||
<Setter Property="Foreground"
|
||||
Value="{DynamicResource {x:Static atom:SharedTokenKey.ColorTextDisabled}}" />
|
||||
|
||||
@@ -47,8 +47,11 @@
|
||||
VerticalAlignment="Stretch"
|
||||
VerticalContentAlignment="Center"
|
||||
HorizontalAlignment="Right"
|
||||
Focusable="False"
|
||||
Content="{TemplateBinding InnerRightContent}"/>
|
||||
<atom:TextBlock Name="TextCountIndicator"
|
||||
VerticalAlignment="Center"
|
||||
Text="{TemplateBinding CountText}"
|
||||
IsVisible="{TemplateBinding IsShowCount}"/>
|
||||
</StackPanel>
|
||||
|
||||
<ScrollViewer
|
||||
@@ -159,6 +162,10 @@
|
||||
<Setter Property="SelectedIconBrush" Value="{DynamicResource {x:Static atom:SharedTokenKey.ColorText}}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="^ /template/ atom|TextBlock#TextCountIndicator">
|
||||
<Setter Property="Foreground" Value="{DynamicResource {x:Static atom:SharedTokenKey.ColorTextPlaceholder}}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:disabled">
|
||||
<Style Selector="^ /template/ ScrollViewer#PART_ScrollViewer">
|
||||
<Setter Property="Foreground" Value="{DynamicResource {x:Static atom:SharedTokenKey.ColorTextDisabled}}" />
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Reactive.Disposables;
|
||||
using System.Diagnostics;
|
||||
using System.Reactive.Disposables;
|
||||
using AtomUI.Data;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
@@ -66,6 +67,8 @@ internal class TimePickerFlyout : Flyout
|
||||
|
||||
protected override Control CreatePresenter()
|
||||
{
|
||||
var flyoutPresenter = base.CreatePresenter() as FlyoutPresenter;
|
||||
Debug.Assert(flyoutPresenter != null);
|
||||
TimePickerPresenter = new TimePickerPresenter();
|
||||
_presenterBindingDisposables?.Dispose();
|
||||
_presenterBindingDisposables = new CompositeDisposable(8);
|
||||
@@ -77,14 +80,7 @@ internal class TimePickerFlyout : Flyout
|
||||
_presenterBindingDisposables.Add(BindUtils.RelayBind(this, IsNeedConfirmProperty, TimePickerPresenter, TimePickerPresenter.IsNeedConfirmProperty));
|
||||
_presenterBindingDisposables.Add(BindUtils.RelayBind(this, IsShowNowProperty, TimePickerPresenter, TimePickerPresenter.IsShowNowProperty));
|
||||
|
||||
var flyoutPresenter = new FlyoutPresenter
|
||||
{
|
||||
Content = TimePickerPresenter
|
||||
};
|
||||
_presenterBindingDisposables.Add(BindUtils.RelayBind(this, IsShowArrowEffectiveProperty, flyoutPresenter, IsShowArrowProperty));
|
||||
|
||||
ConfigureShowArrowEffective();
|
||||
// SetupArrowPosition(flyoutPresenter);
|
||||
flyoutPresenter.Content = TimePickerPresenter;
|
||||
return flyoutPresenter;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user