Browse Source

Merge pull request #5250 from AvaloniaUI/tooltip-position-recalculation

Tooltip position recalculation
pull/5299/head
Max Katz 6 years ago
committed by GitHub
parent
commit
a2652f7c2a
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 14
      samples/ControlCatalog/Pages/SliderPage.xaml
  2. 27
      samples/ControlCatalog/Pages/ToolTipPage.xaml
  3. 40
      src/Avalonia.Controls/ToolTip.cs
  4. 10
      src/Avalonia.Controls/ToolTipService.cs

14
samples/ControlCatalog/Pages/SliderPage.xaml

@ -22,6 +22,20 @@
IsSnapToTickEnabled="True" IsSnapToTickEnabled="True"
Ticks="0,20,25,40,75,100" Ticks="0,20,25,40,75,100"
Width="300" /> Width="300" />
<Slider Name="SliderWithTooltip"
Value="0"
Minimum="0"
Maximum="100"
Width="300">
<Slider.Styles>
<Style Selector="Slider /template/ Thumb">
<Setter Property="ToolTip.Tip" Value="{Binding $parent[Slider].Value, Mode=OneWay, StringFormat='Value \{0:f\}'}" />
<Setter Property="ToolTip.Placement" Value="Top" />
<Setter Property="ToolTip.VerticalOffset" Value="-10" />
<Setter Property="ToolTip.HorizontalOffset" Value="-30" />
</Style>
</Slider.Styles>
</Slider>
<Slider Value="0" <Slider Value="0"
Minimum="0" Minimum="0"
Maximum="100" Maximum="100"

27
samples/ControlCatalog/Pages/ToolTipPage.xaml

@ -6,7 +6,7 @@
<TextBlock Classes="h1">ToolTip</TextBlock> <TextBlock Classes="h1">ToolTip</TextBlock>
<TextBlock Classes="h2">A control which pops up a hint when a control is hovered</TextBlock> <TextBlock Classes="h2">A control which pops up a hint when a control is hovered</TextBlock>
<Grid RowDefinitions="Auto,Auto" <Grid RowDefinitions="Auto,Auto,Auto"
ColumnDefinitions="Auto,Auto" ColumnDefinitions="Auto,Auto"
Margin="0,16,0,0" Margin="0,16,0,0"
HorizontalAlignment="Center"> HorizontalAlignment="Center">
@ -38,6 +38,31 @@
</ToolTip.Tip> </ToolTip.Tip>
<TextBlock>ToolTip bottom placement</TextBlock> <TextBlock>ToolTip bottom placement</TextBlock>
</Border> </Border>
<Border Grid.Row="2"
Grid.ColumnSpan="2"
Background="{DynamicResource SystemAccentColor}"
Margin="5"
Padding="50"
ToolTip.Tip="Hello"
ToolTip.Placement="Top">
<Border.Styles>
<Style Selector="Border">
<Style.Animations>
<Animation Duration="0:0:2" IterationCount="Infinite">
<KeyFrame KeyTime="0:0:0">
<Setter Property="ToolTip.HorizontalOffset" Value="0" />
<Setter Property="ToolTip.VerticalOffset" Value="-50" />
</KeyFrame>
<KeyFrame KeyTime="0:0:2" >
<Setter Property="ToolTip.HorizontalOffset" Value="100" />
<Setter Property="ToolTip.VerticalOffset" Value="50" />
</KeyFrame>
</Animation>
</Style.Animations>
</Style>
</Border.Styles>
<TextBlock>Moving offset</TextBlock>
</Border>
</Grid> </Grid>
</StackPanel> </StackPanel>
</UserControl> </UserControl>

40
src/Avalonia.Controls/ToolTip.cs

@ -1,3 +1,4 @@
#nullable enable
using System; using System;
using System.Reactive.Linq; using System.Reactive.Linq;
using Avalonia.Controls.Metadata; using Avalonia.Controls.Metadata;
@ -21,8 +22,8 @@ namespace Avalonia.Controls
/// <summary> /// <summary>
/// Defines the ToolTip.Tip attached property. /// Defines the ToolTip.Tip attached property.
/// </summary> /// </summary>
public static readonly AttachedProperty<object> TipProperty = public static readonly AttachedProperty<object?> TipProperty =
AvaloniaProperty.RegisterAttached<ToolTip, Control, object>("Tip"); AvaloniaProperty.RegisterAttached<ToolTip, Control, object?>("Tip");
/// <summary> /// <summary>
/// Defines the ToolTip.IsOpen attached property. /// Defines the ToolTip.IsOpen attached property.
@ -57,10 +58,10 @@ namespace Avalonia.Controls
/// <summary> /// <summary>
/// Stores the current <see cref="ToolTip"/> instance in the control. /// Stores the current <see cref="ToolTip"/> instance in the control.
/// </summary> /// </summary>
internal static readonly AttachedProperty<ToolTip> ToolTipProperty = internal static readonly AttachedProperty<ToolTip?> ToolTipProperty =
AvaloniaProperty.RegisterAttached<ToolTip, Control, ToolTip>("ToolTip"); AvaloniaProperty.RegisterAttached<ToolTip, Control, ToolTip?>("ToolTip");
private IPopupHost _popup; private IPopupHost? _popup;
/// <summary> /// <summary>
/// Initializes static members of the <see cref="ToolTip"/> class. /// Initializes static members of the <see cref="ToolTip"/> class.
@ -70,6 +71,10 @@ namespace Avalonia.Controls
TipProperty.Changed.Subscribe(ToolTipService.Instance.TipChanged); TipProperty.Changed.Subscribe(ToolTipService.Instance.TipChanged);
IsOpenProperty.Changed.Subscribe(ToolTipService.Instance.TipOpenChanged); IsOpenProperty.Changed.Subscribe(ToolTipService.Instance.TipOpenChanged);
IsOpenProperty.Changed.Subscribe(IsOpenChanged); IsOpenProperty.Changed.Subscribe(IsOpenChanged);
HorizontalOffsetProperty.Changed.Subscribe(RecalculatePositionOnPropertyChanged);
VerticalOffsetProperty.Changed.Subscribe(RecalculatePositionOnPropertyChanged);
PlacementProperty.Changed.Subscribe(RecalculatePositionOnPropertyChanged);
} }
/// <summary> /// <summary>
@ -79,7 +84,7 @@ namespace Avalonia.Controls
/// <returns> /// <returns>
/// The content to be displayed in the control's tooltip. /// The content to be displayed in the control's tooltip.
/// </returns> /// </returns>
public static object GetTip(Control element) public static object? GetTip(Control element)
{ {
return element.GetValue(TipProperty); return element.GetValue(TipProperty);
} }
@ -89,7 +94,7 @@ namespace Avalonia.Controls
/// </summary> /// </summary>
/// <param name="element">The control to get the property from.</param> /// <param name="element">The control to get the property from.</param>
/// <param name="value">The content to be displayed in the control's tooltip.</param> /// <param name="value">The content to be displayed in the control's tooltip.</param>
public static void SetTip(Control element, object value) public static void SetTip(Control element, object? value)
{ {
element.SetValue(TipProperty, value); element.SetValue(TipProperty, value);
} }
@ -207,8 +212,8 @@ namespace Avalonia.Controls
private static void IsOpenChanged(AvaloniaPropertyChangedEventArgs e) private static void IsOpenChanged(AvaloniaPropertyChangedEventArgs e)
{ {
var control = (Control)e.Sender; var control = (Control)e.Sender;
var newValue = (bool)e.NewValue; var newValue = (bool)e.NewValue!;
ToolTip toolTip; ToolTip? toolTip;
if (newValue) if (newValue)
{ {
@ -235,6 +240,23 @@ namespace Avalonia.Controls
toolTip?.UpdatePseudoClasses(newValue); toolTip?.UpdatePseudoClasses(newValue);
} }
private static void RecalculatePositionOnPropertyChanged(AvaloniaPropertyChangedEventArgs args)
{
var control = (Control)args.Sender;
var tooltip = control.GetValue(ToolTipProperty);
if (tooltip == null)
{
return;
}
tooltip.RecalculatePosition(control);
}
internal void RecalculatePosition(Control control)
{
_popup?.ConfigurePosition(control, GetPlacement(control), new Point(GetHorizontalOffset(control), GetVerticalOffset(control)));
}
private void Open(Control control) private void Open(Control control)
{ {
Close(); Close();

10
src/Avalonia.Controls/ToolTipService.cs

@ -51,10 +51,12 @@ namespace Avalonia.Controls
if (e.OldValue is false && e.NewValue is true) if (e.OldValue is false && e.NewValue is true)
{ {
control.DetachedFromVisualTree += ControlDetaching; control.DetachedFromVisualTree += ControlDetaching;
control.EffectiveViewportChanged += ControlEffectiveViewportChanged;
} }
else if(e.OldValue is true && e.NewValue is false) else if(e.OldValue is true && e.NewValue is false)
{ {
control.DetachedFromVisualTree -= ControlDetaching; control.DetachedFromVisualTree -= ControlDetaching;
control.EffectiveViewportChanged -= ControlEffectiveViewportChanged;
} }
} }
@ -62,6 +64,7 @@ namespace Avalonia.Controls
{ {
var control = (Control)sender; var control = (Control)sender;
control.DetachedFromVisualTree -= ControlDetaching; control.DetachedFromVisualTree -= ControlDetaching;
control.EffectiveViewportChanged -= ControlEffectiveViewportChanged;
Close(control); Close(control);
} }
@ -97,6 +100,13 @@ namespace Avalonia.Controls
Close(control); Close(control);
} }
private void ControlEffectiveViewportChanged(object sender, Layout.EffectiveViewportChangedEventArgs e)
{
var control = (Control)sender;
var toolTip = control.GetValue(ToolTip.ToolTipProperty);
toolTip?.RecalculatePosition(control);
}
private void StartShowTimer(int showDelay, Control control) private void StartShowTimer(int showDelay, Control control)
{ {
_timer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(showDelay) }; _timer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(showDelay) };

Loading…
Cancel
Save