mirror of
https://github.com/AtomUI/AtomUI.git
synced 2026-10-17 05:31:01 +08:00
Refactor tooltip
This commit is contained in:
@@ -939,9 +939,9 @@ internal partial class DataGridColumnHeader : ContentControl
|
||||
{
|
||||
if (IsMotionEnabled)
|
||||
{
|
||||
if (Transitions != null)
|
||||
if (_frame != null)
|
||||
{
|
||||
Transitions = new Transitions()
|
||||
_frame.Transitions = new Transitions()
|
||||
{
|
||||
TransitionUtils.CreateTransition<SolidColorBrushTransition>(BackgroundProperty)
|
||||
};
|
||||
@@ -949,8 +949,11 @@ internal partial class DataGridColumnHeader : ContentControl
|
||||
}
|
||||
else
|
||||
{
|
||||
Transitions?.Clear();
|
||||
Transitions = null;
|
||||
if (_frame != null)
|
||||
{
|
||||
_frame.Transitions?.Clear();
|
||||
_frame.Transitions = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -147,21 +147,28 @@
|
||||
<!-- BuildSortableColumnStyle 开始 -->
|
||||
<Style Selector="^[CanUserSort=True]">
|
||||
<Style Selector="^:sort-ascending, ^:sort-descending">
|
||||
<Setter Property="Background"
|
||||
Value="{DynamicResource {x:Static atom:DataGridTokenKey.HeaderSortActiveBg}}" />
|
||||
<Style Selector="^ /template/ Border#PART_Frame">
|
||||
<Setter Property="Background"
|
||||
Value="{DynamicResource {x:Static atom:DataGridTokenKey.HeaderSortActiveBg}}" />
|
||||
</Style>
|
||||
</Style>
|
||||
|
||||
<Setter Property="Cursor" Value="Hand" />
|
||||
<Style Selector="^:pointerover">
|
||||
<Setter Property="Background"
|
||||
Value="{DynamicResource {x:Static atom:DataGridTokenKey.HeaderSortHoverBg}}" />
|
||||
<Style Selector="^ /template/ Border#PART_Frame">
|
||||
<Setter Property="Background"
|
||||
Value="{DynamicResource {x:Static atom:DataGridTokenKey.HeaderSortHoverBg}}" />
|
||||
</Style>
|
||||
</Style>
|
||||
</Style>
|
||||
|
||||
<!-- BuildSortableColumnStyle 结束 -->
|
||||
|
||||
<Style Selector="^ /template/ Border#PART_Frame">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="^[IsShowFrozenShadow=True]">
|
||||
|
||||
|
||||
<Style Selector="^ /template/ Border#PART_Frame">
|
||||
<Setter Property="Background" Value="{DynamicResource {x:Static atom:DataGridTokenKey.TableHeaderBg}}" />
|
||||
</Style>
|
||||
|
||||
@@ -6,6 +6,7 @@ using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Layout;
|
||||
using Avalonia.Media;
|
||||
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
@@ -226,6 +227,11 @@ public class ArrowDecoratedBox : ContentControl,
|
||||
return CornerRadius;
|
||||
}
|
||||
|
||||
public IBrush? GetMaskBackground()
|
||||
{
|
||||
return Background;
|
||||
}
|
||||
|
||||
public Rect GetMaskBounds()
|
||||
{
|
||||
Debug.Assert(_arrowIndicatorLayout != null && _contentDecorator != null);
|
||||
|
||||
@@ -8,6 +8,7 @@ using Avalonia.Controls;
|
||||
using Avalonia.Controls.Platform;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Media;
|
||||
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
@@ -215,6 +216,11 @@ public class MenuFlyoutPresenter : MenuBase,
|
||||
|
||||
return Bounds;
|
||||
}
|
||||
|
||||
public IBrush? GetMaskBackground()
|
||||
{
|
||||
return _arrowDecoratedBox?.Background;
|
||||
}
|
||||
|
||||
protected override void PrepareContainerForItemOverride(Control container, object? item, int index)
|
||||
{
|
||||
|
||||
@@ -6,6 +6,7 @@ using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Media;
|
||||
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
@@ -157,6 +158,11 @@ public class TreeViewFlyoutPresenter : FloatableTreeView,
|
||||
|
||||
return Bounds;
|
||||
}
|
||||
|
||||
public IBrush? GetMaskBackground()
|
||||
{
|
||||
return _arrowDecoratedBox?.Background;
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Media;
|
||||
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
@@ -6,6 +7,7 @@ internal interface IShadowMaskInfoProvider
|
||||
{
|
||||
CornerRadius GetMaskCornerRadius();
|
||||
Rect GetMaskBounds();
|
||||
IBrush? GetMaskBackground();
|
||||
}
|
||||
|
||||
internal interface IArrowAwareShadowMaskInfoProvider : IShadowMaskInfoProvider
|
||||
|
||||
@@ -564,7 +564,7 @@ public class Popup : AvaloniaPopup,
|
||||
|
||||
public void MotionAwareClose(Action? closed = null)
|
||||
{
|
||||
Debug.Assert(_buddyLayer != null);
|
||||
|
||||
if (_closeAnimating)
|
||||
{
|
||||
return;
|
||||
@@ -580,7 +580,7 @@ public class Popup : AvaloniaPopup,
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Assert(_buddyLayer != null);
|
||||
if (!IsMotionEnabled)
|
||||
{
|
||||
_buddyLayer?.Detach();
|
||||
|
||||
@@ -6,8 +6,10 @@ using AtomUI.MotionScene;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Diagnostics;
|
||||
using Avalonia.Controls.Presenters;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Threading;
|
||||
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
@@ -60,17 +62,25 @@ internal class PopupBuddyDecorator : SceneMotionActorControl
|
||||
{
|
||||
if (_popupHost is PopupRoot oldPopupRoot)
|
||||
{
|
||||
oldPopupRoot.SizeChanged -= HandleBuddyPopupRootSizeChanged;
|
||||
var oldPresenter = oldPopupRoot.Presenter;
|
||||
if (oldPresenter != null)
|
||||
{
|
||||
oldPresenter.SizeChanged -= HandleBuddyPopupRootSizeChanged;
|
||||
}
|
||||
}
|
||||
popupRoot.SizeChanged += HandleBuddyPopupRootSizeChanged;
|
||||
ConfigureDecorator(popupRoot);
|
||||
var presenter = popupRoot.Presenter;
|
||||
if (presenter != null)
|
||||
{
|
||||
presenter.SizeChanged += HandleBuddyPopupRootSizeChanged;
|
||||
}
|
||||
ConfigureDecorator(presenter);
|
||||
CaptureContentControl();
|
||||
}
|
||||
_popupHost = popupHost;
|
||||
}
|
||||
|
||||
private void ConfigureDecorator(IPopupHost popupHost)
|
||||
private void ConfigureDecorator(ContentPresenter? presenter)
|
||||
{
|
||||
var presenter = popupHost.Presenter;
|
||||
if (presenter != null)
|
||||
{
|
||||
var content = presenter.Child;
|
||||
@@ -91,15 +101,15 @@ internal class PopupBuddyDecorator : SceneMotionActorControl
|
||||
_decoratorControl.MaskCornerRadius = templatedControl.CornerRadius;
|
||||
_decoratorControl.MaskSize = templatedControl.Bounds.Size;
|
||||
}
|
||||
CaptureContentControl();
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleBuddyPopupRootSizeChanged(object? sender, SizeChangedEventArgs e)
|
||||
{
|
||||
if (sender is PopupRoot popupRoot)
|
||||
if (sender is ContentPresenter presenter)
|
||||
{
|
||||
ConfigureDecorator(popupRoot);
|
||||
ConfigureDecorator(presenter);
|
||||
ConfigureBlankContentControl();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,19 +135,59 @@ internal class PopupBuddyDecorator : SceneMotionActorControl
|
||||
}
|
||||
}
|
||||
|
||||
internal void HideDecoratorContent()
|
||||
internal void ConfigureBlankContentControl()
|
||||
{
|
||||
if (_decoratorControl.Content != null)
|
||||
if (_popupHost != null && _popupHost.Presenter != null)
|
||||
{
|
||||
_decoratorControl.Content.Opacity = 0.0;
|
||||
}
|
||||
}
|
||||
var content = _popupHost.Presenter.Child;
|
||||
if (content != null)
|
||||
{
|
||||
if (content is IShadowMaskInfoProvider shadowMaskInfoProvider)
|
||||
{
|
||||
var maskBounds = shadowMaskInfoProvider.GetMaskBounds();
|
||||
var offset = maskBounds.Position;
|
||||
|
||||
internal void ShowDecoratorContent()
|
||||
{
|
||||
if (_decoratorControl.Content != null)
|
||||
{
|
||||
_decoratorControl.Content.Opacity = 1.0;
|
||||
var contentWidth = maskBounds.Width;
|
||||
var contentHeight = maskBounds.Height;
|
||||
var blankControl = new Canvas()
|
||||
{
|
||||
Background = Brushes.Transparent,
|
||||
Width = contentWidth + offset.X,
|
||||
Height = contentHeight + offset.Y,
|
||||
};
|
||||
var blankContent = new Border()
|
||||
{
|
||||
Background = shadowMaskInfoProvider.GetMaskBackground(),
|
||||
CornerRadius = shadowMaskInfoProvider.GetMaskCornerRadius(),
|
||||
Width = contentWidth,
|
||||
Height = contentHeight,
|
||||
};
|
||||
blankControl.Children.Add(blankContent);
|
||||
Canvas.SetLeft(blankContent, offset.X);
|
||||
Canvas.SetTop(blankContent, offset.Y);
|
||||
_decoratorControl.Content = blankControl;
|
||||
}
|
||||
else if (content is Border bordered)
|
||||
{
|
||||
_decoratorControl.Content = new Border
|
||||
{
|
||||
Background = bordered.Background,
|
||||
CornerRadius = bordered.CornerRadius,
|
||||
Width = bordered.Bounds.Size.Width,
|
||||
Height = bordered.Bounds.Size.Height
|
||||
};
|
||||
}
|
||||
else if (content is TemplatedControl templatedControl)
|
||||
{
|
||||
_decoratorControl.Content = new Border
|
||||
{
|
||||
Background = templatedControl.Background,
|
||||
CornerRadius = templatedControl.CornerRadius,
|
||||
Width = templatedControl.Bounds.Size.Width,
|
||||
Height = templatedControl.Bounds.Size.Height
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -184,7 +184,6 @@ internal class PopupBuddyLayer : SceneLayer, IPopupBuddyLayer, IShadowAwareLayer
|
||||
}
|
||||
|
||||
SetupPopupHost();
|
||||
_buddyDecorator.HideDecoratorContent();
|
||||
}
|
||||
|
||||
public void Detach()
|
||||
@@ -214,6 +213,7 @@ internal class PopupBuddyLayer : SceneLayer, IPopupBuddyLayer, IShadowAwareLayer
|
||||
motion.Run(_buddyDecorator, null, () =>
|
||||
{
|
||||
completedAction?.Invoke();
|
||||
_buddyDecorator.ConfigureBlankContentControl();
|
||||
NotifyAttachMotionCompleted();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Globalization;
|
||||
using AtomUI.Controls.Themes;
|
||||
using AtomUI.Input;
|
||||
using AtomUI.Media;
|
||||
using AtomUI.Theme;
|
||||
using AtomUI.Theme.Utils;
|
||||
using AtomUI.Utils;
|
||||
@@ -18,6 +19,7 @@ using Avalonia.Interactivity;
|
||||
using Avalonia.Layout;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Utilities;
|
||||
using Avalonia.VisualTree;
|
||||
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
@@ -129,7 +131,7 @@ public class Slider : RangeBase,
|
||||
SliderTrack.MarksProperty.AddOwner<Slider>();
|
||||
|
||||
public static readonly StyledProperty<string> ValueFormatTemplateProperty =
|
||||
AvaloniaProperty.Register<Slider, string>(nameof(ValueFormatTemplate), "{0:0.00}");
|
||||
AvaloniaProperty.Register<Slider, string>(nameof(ValueFormatTemplate), "{0:0}");
|
||||
|
||||
public static readonly StyledProperty<bool> IncludedProperty =
|
||||
SliderTrack.IncludedProperty.AddOwner<Slider>();
|
||||
@@ -232,6 +234,16 @@ public class Slider : RangeBase,
|
||||
string IControlSharedTokenResourcesHost.TokenId => SliderToken.ID;
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the <see cref="Slider" /> is currently being dragged.
|
||||
/// </summary>
|
||||
protected bool IsDragging { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="SliderTrack" /> part of the <see cref="Slider" />.
|
||||
/// </summary>
|
||||
protected SliderTrack? SliderTrack { get; private set; }
|
||||
|
||||
// Slider required parts
|
||||
private bool _isFocusEngaged;
|
||||
@@ -239,6 +251,7 @@ public class Slider : RangeBase,
|
||||
private IDisposable? _pointerMovedDispose;
|
||||
private IDisposable? _pointerPressDispose;
|
||||
private IDisposable? _pointerReleaseDispose;
|
||||
private double _tipHostWidth;
|
||||
|
||||
private const double Tolerance = 0.0001;
|
||||
|
||||
@@ -259,16 +272,6 @@ public class Slider : RangeBase,
|
||||
AutomationProperties.ControlTypeOverrideProperty.OverrideDefaultValue<Slider>(AutomationControlType.Slider);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the <see cref="Slider" /> is currently being dragged.
|
||||
/// </summary>
|
||||
protected bool IsDragging { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="SliderTrack" /> part of the <see cref="Slider" />.
|
||||
/// </summary>
|
||||
protected SliderTrack? SliderTrack { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates a new instance of the <see cref="Slider" /> class.
|
||||
/// </summary>
|
||||
@@ -298,6 +301,7 @@ public class Slider : RangeBase,
|
||||
_pointerReleaseDispose =
|
||||
this.AddDisposableHandler(PointerReleasedEvent, TrackReleased, RoutingStrategies.Tunnel);
|
||||
_pointerMovedDispose = this.AddDisposableHandler(PointerMovedEvent, TrackMoved, RoutingStrategies.Tunnel);
|
||||
ConfigureTipHostWidth();
|
||||
|
||||
if (SliderTrack is not null)
|
||||
{
|
||||
@@ -321,12 +325,11 @@ public class Slider : RangeBase,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SetupSliderThumbPlacement();
|
||||
}
|
||||
|
||||
// TODO 在 rangemode 下可能没有用
|
||||
/// <inheritdoc />
|
||||
protected override void OnKeyDown(KeyEventArgs e)
|
||||
{
|
||||
base.OnKeyDown(e);
|
||||
@@ -674,6 +677,15 @@ public class Slider : RangeBase,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.IsAttachedToVisualTree())
|
||||
{
|
||||
if (change.Property == MaximumProperty ||
|
||||
change.Property == ValueFormatTemplateProperty)
|
||||
{
|
||||
ConfigureTipHostWidth();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string FormatValue(double value)
|
||||
@@ -728,4 +740,33 @@ public class Slider : RangeBase,
|
||||
PseudoClasses.Set(StdPseudoClass.Vertical, o == Orientation.Vertical);
|
||||
PseudoClasses.Set(StdPseudoClass.Horizontal, o == Orientation.Horizontal);
|
||||
}
|
||||
|
||||
private void ConfigureTipHostWidth()
|
||||
{
|
||||
var maxValueText = FormatValue(Maximum);
|
||||
var size = TextUtils.CalculateTextSize(maxValueText, FontSize, FontFamily);
|
||||
_tipHostWidth = size.Width * 1.1;
|
||||
if (SliderTrack is not null)
|
||||
{
|
||||
if (!IsRangeMode)
|
||||
{
|
||||
if (SliderTrack.StartSliderThumb is not null)
|
||||
{
|
||||
ToolTip.SetTipHostWidth(SliderTrack.StartSliderThumb, _tipHostWidth);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (SliderTrack.StartSliderThumb is not null)
|
||||
{
|
||||
ToolTip.SetTipHostWidth(SliderTrack.StartSliderThumb, _tipHostWidth);
|
||||
}
|
||||
|
||||
if (SliderTrack.EndSliderThumb is not null)
|
||||
{
|
||||
ToolTip.SetTipHostWidth(SliderTrack.EndSliderThumb, _tipHostWidth);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,15 @@ internal class TabControlOverflowMenuItem : BaseOverflowMenuItem
|
||||
{
|
||||
var eventArgs = new CloseTabRequestEventArgs(CloseTabEvent, TabItem!);
|
||||
RaiseEvent(eventArgs);
|
||||
Dispatcher.UIThread.Post(() => { menu.Close(); });
|
||||
if (menu is MenuFlyoutPresenter menuFlyoutPresenter)
|
||||
{
|
||||
var menuFlyout = menuFlyoutPresenter.MenuFlyout;
|
||||
menuFlyout?.Items.Remove(this);
|
||||
if (menuFlyout?.Items.Count == 0)
|
||||
{
|
||||
Dispatcher.UIThread.Post(() => { menu.Close(); });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,15 @@ internal class TabStripOverflowMenuItem : BaseOverflowMenuItem
|
||||
{
|
||||
var eventArgs = new CloseTabRequestEventArgs(CloseTabEvent, TabStripItem!);
|
||||
RaiseEvent(eventArgs);
|
||||
Dispatcher.UIThread.Post(() => { menu.Close(); });
|
||||
if (menu is MenuFlyoutPresenter menuFlyoutPresenter)
|
||||
{
|
||||
var menuFlyout = menuFlyoutPresenter.MenuFlyout;
|
||||
menuFlyout?.Items.Remove(this);
|
||||
if (menuFlyout?.Items.Count == 0)
|
||||
{
|
||||
Dispatcher.UIThread.Post(() => { menu.Close(); });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,20 +2,23 @@
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:atom="https://atomui.net">
|
||||
<atom:StringToTextBlockConverter x:Key="StringToTextBlockConverter" VerticalAlignment="Center" />
|
||||
<atom:StringToTextBlockConverter x:Key="StringToTextBlockConverter" VerticalAlignment="Center" HorizontalAlignment="Center" />
|
||||
<ControlTheme x:Key="{x:Type atom:ToolTip}" TargetType="atom:ToolTip">
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<atom:ArrowDecoratedBox Name="{x:Static atom:ToolTipThemeConstants.ToolTipContainerPart}"
|
||||
Content="{TemplateBinding Content, Converter={StaticResource StringToTextBlockConverter}}"
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}"
|
||||
/>
|
||||
Background="{TemplateBinding Background}">
|
||||
<ContentPresenter
|
||||
Name="{x:Static atom:ToolTipThemeConstants.ToolTipContainerPresenterPart}"
|
||||
Content="{TemplateBinding Content, Converter={StaticResource StringToTextBlockConverter}}"
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}"/>
|
||||
</atom:ArrowDecoratedBox>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
<Setter Property="Background" Value="{DynamicResource {x:Static atom:ToolTipTokenKey.ToolTipBackground}}" />
|
||||
<Style Selector="^ /template/ atom|ArrowDecoratedBox#PART_ToolTipContainer">
|
||||
<Setter Property="FontSize" Value="{DynamicResource {x:Static atom:SharedTokenKey.FontSize}}" />
|
||||
<Setter Property="MaxWidth" Value="{DynamicResource {x:Static atom:ToolTipTokenKey.ToolTipMaxWidth}}" />
|
||||
<Setter Property="Background" Value="{DynamicResource {x:Static atom:ToolTipTokenKey.ToolTipBackground}}" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource {x:Static atom:ToolTipTokenKey.ToolTipColor}}" />
|
||||
<Setter Property="MinHeight" Value="{DynamicResource {x:Static atom:SharedTokenKey.ControlHeight}}" />
|
||||
<Setter Property="Padding" Value="{DynamicResource {x:Static atom:ToolTipTokenKey.ToolTipPadding}}" />
|
||||
|
||||
@@ -3,4 +3,5 @@ namespace AtomUI.Controls.Themes;
|
||||
internal class ToolTipThemeConstants
|
||||
{
|
||||
public const string ToolTipContainerPart = "PART_ToolTipContainer";
|
||||
public const string ToolTipContainerPresenterPart = "PART_ToolTipContentPresenter";
|
||||
}
|
||||
@@ -7,6 +7,7 @@ using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Diagnostics;
|
||||
using Avalonia.Controls.Metadata;
|
||||
using Avalonia.Controls.Presenters;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Controls.Primitives.PopupPositioning;
|
||||
using Avalonia.Interactivity;
|
||||
@@ -26,6 +27,9 @@ public class ToolTip : ContentControl,
|
||||
|
||||
public static readonly AttachedProperty<object?> TipProperty =
|
||||
AvaloniaProperty.RegisterAttached<ToolTip, Control, object?>("Tip");
|
||||
|
||||
public static readonly AttachedProperty<double> TipHostWidthProperty =
|
||||
AvaloniaProperty.RegisterAttached<ToolTip, Control, double>("TipHostWidth", double.NaN);
|
||||
|
||||
public static readonly AttachedProperty<bool> IsOpenProperty =
|
||||
AvaloniaProperty.RegisterAttached<ToolTip, Control, bool>("IsOpen");
|
||||
@@ -109,6 +113,16 @@ public class ToolTip : ContentControl,
|
||||
element.SetValue(TipProperty, value);
|
||||
}
|
||||
|
||||
public static double GetTipHostWidth(Control element)
|
||||
{
|
||||
return element.GetValue(TipHostWidthProperty);
|
||||
}
|
||||
|
||||
public static void SetTipHostWidth(Control element, double value)
|
||||
{
|
||||
element.SetValue(TipHostWidthProperty, value);
|
||||
}
|
||||
|
||||
public static bool GetIsOpen(Control element)
|
||||
{
|
||||
return element.GetValue(IsOpenProperty);
|
||||
@@ -316,6 +330,7 @@ public class ToolTip : ContentControl,
|
||||
private Popup? _popup;
|
||||
private Action<IPopupHost?>? _popupHostChangedHandler;
|
||||
private ArrowDecoratedBox? _arrowDecoratedBox;
|
||||
private ContentPresenter? _contentPresenter;
|
||||
private DispatcherTimer? _timer;
|
||||
|
||||
static ToolTip()
|
||||
@@ -340,6 +355,11 @@ public class ToolTip : ContentControl,
|
||||
return _arrowDecoratedBox.GetMaskBounds();
|
||||
}
|
||||
|
||||
public IBrush? GetMaskBackground()
|
||||
{
|
||||
return Background;
|
||||
}
|
||||
|
||||
private void Open(Control control)
|
||||
{
|
||||
StopTimer();
|
||||
@@ -407,6 +427,11 @@ public class ToolTip : ContentControl,
|
||||
if (_arrowDecoratedBox is not null)
|
||||
{
|
||||
SetToolTipColor(control);
|
||||
if (_contentPresenter != null)
|
||||
{
|
||||
_contentPresenter.Width = GetTipHostWidth(control);
|
||||
}
|
||||
|
||||
_arrowDecoratedBox.Bind(ArrowDecoratedBox.IsShowArrowProperty,
|
||||
control.GetBindingObservable(IsShowArrowProperty, flag =>
|
||||
{
|
||||
@@ -475,12 +500,12 @@ public class ToolTip : ContentControl,
|
||||
if (presetColorType is not null)
|
||||
{
|
||||
var presetColor = PresetPrimaryColor.GetColor(presetColorType.Value);
|
||||
_arrowDecoratedBox.Background = new SolidColorBrush(presetColor.Color());
|
||||
Background = new SolidColorBrush(presetColor.Color());
|
||||
InvalidateVisual();
|
||||
}
|
||||
else if (color is not null)
|
||||
{
|
||||
_arrowDecoratedBox.Background = new SolidColorBrush(color.Value);
|
||||
Background = new SolidColorBrush(color.Value);
|
||||
InvalidateVisual();
|
||||
}
|
||||
}
|
||||
@@ -601,6 +626,7 @@ public class ToolTip : ContentControl,
|
||||
{
|
||||
base.OnApplyTemplate(e);
|
||||
_arrowDecoratedBox = e.NameScope.Find<ArrowDecoratedBox>(ToolTipThemeConstants.ToolTipContainerPart);
|
||||
_contentPresenter = e.NameScope.Find<ContentPresenter>(ToolTipThemeConstants.ToolTipContainerPresenterPart);
|
||||
}
|
||||
|
||||
private Point CalculatePopupPositionDelta(Control control,
|
||||
|
||||
Reference in New Issue
Block a user