123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377 |
- using System;
- using System.Windows;
- using System.Windows.Controls;
- using System.Windows.Controls.Primitives;
- using System.Windows.Data;
- using System.Windows.Input;
- using System.Windows.Threading;
- using HandyControl.Data;
- using HandyControl.Data.Enum;
- using HandyControl.Expression.Drawing;
- using HandyControl.Tools;
- namespace HandyControl.Controls;
- public class Poptip : AdornerElement
- {
- private readonly Popup _popup;
- private DispatcherTimer _openTimer;
- public Poptip()
- {
- _popup = new Popup
- {
- AllowsTransparency = true,
- Child = this,
- Placement = PlacementMode.Relative
- };
- _popup.SetBinding(DataContextProperty, new Binding(DataContextProperty.Name) { Source = this });
- }
- public static readonly DependencyProperty HitModeProperty = DependencyProperty.RegisterAttached(
- "HitMode", typeof(HitMode), typeof(Poptip), new PropertyMetadata(HitMode.Hover));
- public static void SetHitMode(DependencyObject element, HitMode value)
- => element.SetValue(HitModeProperty, value);
- public static HitMode GetHitMode(DependencyObject element)
- => (HitMode) element.GetValue(HitModeProperty);
- public HitMode HitMode
- {
- get => (HitMode) GetValue(HitModeProperty);
- set => SetValue(HitModeProperty, value);
- }
- public static readonly DependencyProperty ContentProperty = DependencyProperty.RegisterAttached(
- "Content", typeof(object), typeof(Poptip), new PropertyMetadata(default, OnContentChanged));
- private static void OnContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- if (d is Poptip) return;
- if (GetInstance(d) == null)
- {
- SetInstance(d, Default);
- SetIsInstance(d, false);
- }
- }
- public static void SetContent(DependencyObject element, object value)
- => element.SetValue(ContentProperty, value);
- public static object GetContent(DependencyObject element)
- => element.GetValue(ContentProperty);
- public object Content
- {
- get => GetValue(ContentProperty);
- set => SetValue(ContentProperty, value);
- }
- public static readonly DependencyProperty ContentTemplateProperty = DependencyProperty.Register(
- nameof(ContentTemplate), typeof(DataTemplate), typeof(Poptip), new PropertyMetadata(default(DataTemplate)));
- public DataTemplate ContentTemplate
- {
- get => (DataTemplate) GetValue(ContentTemplateProperty);
- set => SetValue(ContentTemplateProperty, value);
- }
- public static readonly DependencyProperty ContentStringFormatProperty = DependencyProperty.Register(
- nameof(ContentStringFormat), typeof(string), typeof(Poptip), new PropertyMetadata(default(string)));
- public string ContentStringFormat
- {
- get => (string) GetValue(ContentStringFormatProperty);
- set => SetValue(ContentStringFormatProperty, value);
- }
- public static readonly DependencyProperty ContentTemplateSelectorProperty = DependencyProperty.Register(
- nameof(ContentTemplateSelector), typeof(DataTemplateSelector), typeof(Poptip), new PropertyMetadata(default(DataTemplateSelector)));
- public DataTemplateSelector ContentTemplateSelector
- {
- get => (DataTemplateSelector) GetValue(ContentTemplateSelectorProperty);
- set => SetValue(ContentTemplateSelectorProperty, value);
- }
- public static readonly DependencyProperty VerticalOffsetProperty = DependencyProperty.RegisterAttached(
- "VerticalOffset", typeof(double), typeof(Poptip), new PropertyMetadata(ValueBoxes.Double0Box));
- public static void SetVerticalOffset(DependencyObject element, double value)
- {
- element.SetValue(VerticalOffsetProperty, value);
- }
- public static double GetVerticalOffset(DependencyObject element)
- {
- return (double) element.GetValue(VerticalOffsetProperty);
- }
- public double VerticalOffset
- {
- get => (double) GetValue(VerticalOffsetProperty);
- set => SetValue(VerticalOffsetProperty, value);
- }
- public static readonly DependencyProperty HorizontalOffsetProperty = DependencyProperty.RegisterAttached(
- "HorizontalOffset", typeof(double), typeof(Poptip), new PropertyMetadata(ValueBoxes.Double0Box));
- public static void SetHorizontalOffset(DependencyObject element, double value)
- {
- element.SetValue(HorizontalOffsetProperty, value);
- }
- public static double GetHorizontalOffset(DependencyObject element)
- {
- return (double) element.GetValue(HorizontalOffsetProperty);
- }
- public double HorizontalOffset
- {
- get => (double) GetValue(HorizontalOffsetProperty);
- set => SetValue(HorizontalOffsetProperty, value);
- }
- public static readonly DependencyProperty PlacementTypeProperty = DependencyProperty.RegisterAttached(
- "PlacementType", typeof(PlacementType), typeof(Poptip), new PropertyMetadata(PlacementType.Top));
- public static void SetPlacement(DependencyObject element, PlacementType value)
- => element.SetValue(PlacementTypeProperty, value);
- public static PlacementType GetPlacement(DependencyObject element)
- => (PlacementType) element.GetValue(PlacementTypeProperty);
- public PlacementType PlacementType
- {
- get => (PlacementType) GetValue(PlacementTypeProperty);
- set => SetValue(PlacementTypeProperty, value);
- }
- public static readonly DependencyProperty IsOpenProperty = DependencyProperty.RegisterAttached(
- "IsOpen", typeof(bool), typeof(Poptip), new PropertyMetadata(ValueBoxes.FalseBox, OnIsOpenChanged));
- private static void OnIsOpenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- if (d is Poptip poptip)
- {
- poptip.SwitchPoptip((bool) e.NewValue);
- }
- else
- {
- ((Poptip) GetInstance(d))?.SwitchPoptip((bool) e.NewValue);
- }
- }
- public static void SetIsOpen(DependencyObject element, bool value)
- => element.SetValue(IsOpenProperty, ValueBoxes.BooleanBox(value));
- public static bool GetIsOpen(DependencyObject element)
- => (bool) element.GetValue(IsOpenProperty);
- public bool IsOpen
- {
- get => (bool) GetValue(IsOpenProperty);
- set => SetValue(IsOpenProperty, ValueBoxes.BooleanBox(value));
- }
- public static readonly DependencyProperty DelayProperty = DependencyProperty.Register(
- nameof(Delay), typeof(double), typeof(Poptip), new PropertyMetadata(1000.0), ValidateHelper.IsInRangeOfPosDoubleIncludeZero);
- public double Delay
- {
- get => (double) GetValue(DelayProperty);
- set => SetValue(DelayProperty, value);
- }
- public static Poptip Default => new();
- protected sealed override void OnTargetChanged(FrameworkElement element, bool isNew)
- {
- base.OnTargetChanged(element, isNew);
- if (element == null) return;
- if (!isNew)
- {
- element.MouseEnter -= Element_MouseEnter;
- element.MouseLeave -= Element_MouseLeave;
- element.GotFocus -= Element_GotFocus;
- element.LostFocus -= Element_LostFocus;
- ElementTarget = null;
- }
- else
- {
- element.MouseEnter += Element_MouseEnter;
- element.MouseLeave += Element_MouseLeave;
- element.GotFocus += Element_GotFocus;
- element.LostFocus += Element_LostFocus;
- ElementTarget = element;
- _popup.PlacementTarget = ElementTarget;
- }
- }
- protected override void Dispose() => SwitchPoptip(false);
- private void UpdateLocation()
- {
- var targetWidth = Target.RenderSize.Width;
- var targetHeight = Target.RenderSize.Height;
- Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
- var size = DesiredSize;
- var width = size.Width;
- var height = size.Height;
- var offsetX = .0;
- var offsetY = .0;
- var poptip = (Poptip) GetInstance(Target);
- var popupPlacement = poptip.PlacementType;
- var popupOffsetX = poptip.HorizontalOffset;
- var popupOffsetY = poptip.VerticalOffset;
- switch (popupPlacement)
- {
- case PlacementType.LeftTop:
- break;
- case PlacementType.Left:
- offsetY = -(height - targetHeight) * 0.5;
- break;
- case PlacementType.LeftBottom:
- offsetY = -(height - targetHeight);
- break;
- case PlacementType.TopLeft:
- offsetX = width;
- offsetY = -height;
- break;
- case PlacementType.Top:
- offsetX = (width + targetWidth) * 0.5;
- offsetY = -height;
- break;
- case PlacementType.TopRight:
- offsetX = targetWidth;
- offsetY = -height;
- break;
- case PlacementType.RightTop:
- offsetX = width + targetWidth;
- break;
- case PlacementType.Right:
- offsetX = width + targetWidth;
- offsetY = -(height - targetHeight) * 0.5;
- break;
- case PlacementType.RightBottom:
- offsetX = width + targetWidth;
- offsetY = -(height - targetHeight);
- break;
- case PlacementType.BottomLeft:
- offsetX = width;
- offsetY = targetHeight;
- break;
- case PlacementType.Bottom:
- offsetX = (width + targetWidth) * 0.5;
- offsetY = targetHeight;
- break;
- case PlacementType.BottomRight:
- offsetX = targetWidth;
- offsetY = targetHeight;
- break;
- default:
- throw new ArgumentOutOfRangeException();
- }
- _popup.HorizontalOffset = offsetX + popupOffsetX;
- _popup.VerticalOffset = offsetY + popupOffsetY;
- }
- private void SwitchPoptip(bool isShow)
- {
- if (isShow)
- {
- if (!GetIsInstance(Target))
- {
- SetCurrentValue(ContentProperty, GetContent(Target));
- SetCurrentValue(PlacementTypeProperty, GetPlacement(Target));
- SetCurrentValue(HitModeProperty, GetHitMode(Target));
- SetCurrentValue(HorizontalOffsetProperty, GetHorizontalOffset(Target));
- SetCurrentValue(VerticalOffsetProperty, GetVerticalOffset(Target));
- SetCurrentValue(IsOpenProperty, GetIsOpen(Target));
- }
- _popup.PlacementTarget = Target;
- UpdateLocation();
- }
- ResetTimer();
- var delay = Delay;
- if (!isShow || HitMode != HitMode.Hover || MathHelper.IsVerySmall(delay))
- {
- _popup.IsOpen = isShow;
- Target.SetCurrentValue(IsOpenProperty, isShow);
- }
- else
- {
- _openTimer = new DispatcherTimer
- {
- Interval = TimeSpan.FromMilliseconds(delay)
- };
- _openTimer.Tick += OpenTimer_Tick;
- _openTimer.Start();
- }
- }
- private void ResetTimer()
- {
- if (_openTimer != null)
- {
- _openTimer.Stop();
- _openTimer = null;
- }
- }
- private void OpenTimer_Tick(object sender, EventArgs e)
- {
- _popup.IsOpen = true;
- Target.SetCurrentValue(IsOpenProperty, true);
- ResetTimer();
- }
- private void Element_MouseEnter(object sender, MouseEventArgs e)
- {
- var hitMode = GetIsInstance(Target) ? HitMode : GetHitMode(Target);
- if (hitMode != HitMode.Hover) return;
- SwitchPoptip(true);
- }
- private void Element_MouseLeave(object sender, MouseEventArgs e)
- {
- var hitMode = GetIsInstance(Target) ? HitMode : GetHitMode(Target);
- if (hitMode != HitMode.Hover) return;
- SwitchPoptip(false);
- }
- private void Element_GotFocus(object sender, RoutedEventArgs e)
- {
- var hitMode = GetIsInstance(Target) ? HitMode : GetHitMode(Target);
- if (hitMode != HitMode.Focus) return;
- SwitchPoptip(true);
- }
- private void Element_LostFocus(object sender, RoutedEventArgs e)
- {
- var hitMode = GetIsInstance(Target) ? HitMode : GetHitMode(Target);
- if (hitMode != HitMode.Focus) return;
- SwitchPoptip(false);
- }
- }
|