@ -1,5 +1,6 @@
using System ;
using System.Collections.Generic ;
using System.Data ;
using Avalonia.Controls.Documents ;
using Avalonia.Controls.Primitives ;
using Avalonia.Interactivity ;
@ -34,6 +35,9 @@ namespace Avalonia.Controls.Presenters
public static readonly StyledProperty < IBrush ? > CaretBrushProperty =
AvaloniaProperty . Register < TextPresenter , IBrush ? > ( nameof ( CaretBrush ) ) ;
public static readonly StyledProperty < TimeSpan > CaretBlinkIntervalProperty =
TextBox . CaretBlinkIntervalProperty . AddOwner < TextPresenter > ( ) ;
public static readonly StyledProperty < int > SelectionStartProperty =
TextBox . SelectionStartProperty . AddOwner < TextPresenter > ( new ( coerce : TextBox . CoerceCaretIndex ) ) ;
@ -88,7 +92,7 @@ namespace Avalonia.Controls.Presenters
public static readonly StyledProperty < IBrush ? > BackgroundProperty =
Border . BackgroundProperty . AddOwner < TextPresenter > ( ) ;
private readonly DispatcherTimer _ caretTimer ;
private DispatcherTimer ? _ caretTimer ;
private bool _ caretBlink ;
private TextLayout ? _ textLayout ;
private Size _ constraint ;
@ -104,10 +108,7 @@ namespace Avalonia.Controls.Presenters
AffectsRender < TextPresenter > ( CaretBrushProperty , SelectionBrushProperty , TextElement . ForegroundProperty ) ;
}
public TextPresenter ( )
{
_ caretTimer = new DispatcherTimer { Interval = TimeSpan . FromMilliseconds ( 5 0 0 ) } ;
}
public TextPresenter ( ) { }
public event EventHandler ? CaretBoundsChanged ;
@ -288,6 +289,15 @@ namespace Avalonia.Controls.Presenters
set = > SetValue ( CaretBrushProperty , value ) ;
}
/// <summary>
/// Gets or sets the caret blink rate
/// </summary>
public TimeSpan CaretBlinkInterval
{
get = > GetValue ( CaretBlinkIntervalProperty ) ;
set = > SetValue ( CaretBlinkIntervalProperty , value ) ;
}
public int SelectionStart
{
get = > GetValue ( SelectionStartProperty ) ;
@ -443,7 +453,7 @@ namespace Avalonia.Controls.Presenters
public void ShowCaret ( )
{
_ caretBlink = true ;
_ caretTimer . Start ( ) ;
_ caretTimer ? . Start ( ) ;
InvalidateVisual ( ) ;
}
@ -454,7 +464,7 @@ namespace Avalonia.Controls.Presenters
{
TextSelectionHandleCanvas . ShowHandles = false ;
}
_ caretTimer . Stop ( ) ;
_ caretTimer ? . Stop ( ) ;
InvalidateVisual ( ) ;
}
@ -465,18 +475,18 @@ namespace Avalonia.Controls.Presenters
return ;
}
if ( _ caretTimer . IsEnabled )
if ( _ caretTimer ? . IsEnabled ? ? false )
{
_ caretBlink = true ;
_ caretTimer . Stop ( ) ;
_ caretTimer . Start ( ) ;
_ caretTimer ? . Stop ( ) ;
_ caretTimer ? . Start ( ) ;
InvalidateVisual ( ) ;
}
else
{
_ caretTimer . Start ( ) ;
_ caretTimer ? . Start ( ) ;
InvalidateVisual ( ) ;
_ caretTimer . Stop ( ) ;
_ caretTimer ? . Stop ( ) ;
}
if ( IsMeasureValid )
@ -716,6 +726,33 @@ namespace Avalonia.Controls.Presenters
CaretChanged ( ) ;
}
private void ResetCaretTimer ( )
{
bool isEnabled = false ;
if ( _ caretTimer ! = null )
{
_ caretTimer . Tick - = CaretTimerTick ;
if ( _ caretTimer . IsEnabled )
{
_ caretTimer . Stop ( ) ;
isEnabled = true ;
}
_ caretTimer = null ;
}
if ( CaretBlinkInterval . TotalMilliseconds > 0 )
{
_ caretTimer = new DispatcherTimer { Interval = CaretBlinkInterval } ;
_ caretTimer . Tick + = CaretTimerTick ;
if ( isEnabled )
_ caretTimer . Start ( ) ;
}
}
public CharacterHit GetNextCharacterHit ( LogicalDirection direction = LogicalDirection . Forward )
{
if ( Text is null )
@ -855,7 +892,7 @@ namespace Avalonia.Controls.Presenters
{
base . OnAttachedToVisualTree ( e ) ;
_ caretTimer . Tick + = CaretTimerTick ;
ResetCaretTimer ( ) ;
if ( TextSelectionHandleCanvas is { } canvas & & _l ayer ! = null & & ! _l ayer . Children . Contains ( canvas ) )
_l ayer ? . Add ( TextSelectionHandleCanvas ) ;
@ -882,9 +919,11 @@ namespace Avalonia.Controls.Presenters
c . SetPresenter ( null ) ;
}
_ caretTimer . Stop ( ) ;
_ caretTimer . Tick - = CaretTimerTick ;
if ( _ caretTimer ! = null )
{
_ caretTimer . Stop ( ) ;
_ caretTimer . Tick - = CaretTimerTick ;
}
}
private void OnPreeditChanged ( string? preeditText , int? cursorPosition )
@ -939,6 +978,11 @@ namespace Avalonia.Controls.Presenters
}
}
if ( change . Property = = CaretBlinkIntervalProperty )
{
ResetCaretTimer ( ) ;
}
switch ( change . Property . Name )
{
case nameof ( PreeditText ) :