201 lines
7.3 KiB
C#
201 lines
7.3 KiB
C#
using AuroraUIComponent.UserControls.KeyValueBase;
|
|
using Microsoft.Xaml.Behaviors;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Windows;
|
|
using System.Windows.Controls;
|
|
using System.Windows.Media;
|
|
using System.Windows.Media.Animation;
|
|
|
|
namespace AuroraUIComponent.UserControls.Behavior
|
|
{
|
|
public class BlinkHighlightBehavior : Behavior<UCKeyValueBase>
|
|
{
|
|
// 외부에서 직접 바인딩할 필요 없는 내부 상태
|
|
public static readonly DependencyProperty IsActiveProperty =
|
|
DependencyProperty.Register(nameof(IsActive), typeof(bool), typeof(BlinkHighlightBehavior),
|
|
new PropertyMetadata(false, OnIsActiveChanged));
|
|
|
|
public bool IsActive {
|
|
get => (bool)GetValue(IsActiveProperty);
|
|
private set => SetValue(IsActiveProperty, value); // ← set을 private로
|
|
}
|
|
|
|
// 하이라이트 색/속도 파라미터
|
|
public static readonly DependencyProperty HighlightColorProperty =
|
|
DependencyProperty.Register(nameof(HighlightColor), typeof(Color), typeof(BlinkHighlightBehavior),
|
|
new PropertyMetadata(Colors.Orange, OnAnimParamChanged));
|
|
public Color HighlightColor {
|
|
get => (Color)GetValue(HighlightColorProperty);
|
|
set => SetValue(HighlightColorProperty, value);
|
|
}
|
|
|
|
public static readonly DependencyProperty DurationMillisProperty =
|
|
DependencyProperty.Register(nameof(DurationMillis), typeof(int), typeof(BlinkHighlightBehavior),
|
|
new PropertyMetadata(400, OnAnimParamChanged));
|
|
public int DurationMillis {
|
|
get => (int)GetValue(DurationMillisProperty);
|
|
set => SetValue(DurationMillisProperty, value);
|
|
}
|
|
|
|
// ★ 이벤트 소스 주입 (컨버터 대신)
|
|
public static readonly DependencyProperty HoverSourceProperty =
|
|
DependencyProperty.Register(nameof(HoverSource), typeof(FrameworkElement), typeof(BlinkHighlightBehavior),
|
|
new PropertyMetadata(null, OnSourceChanged));
|
|
public FrameworkElement HoverSource {
|
|
get => (FrameworkElement)GetValue(HoverSourceProperty);
|
|
set => SetValue(HoverSourceProperty, value);
|
|
}
|
|
|
|
public static readonly DependencyProperty ToolTipSourceProperty =
|
|
DependencyProperty.Register(nameof(ToolTipSource), typeof(ToolTip), typeof(BlinkHighlightBehavior),
|
|
new PropertyMetadata(null, OnSourceChanged));
|
|
public ToolTip ToolTipSource {
|
|
get => (ToolTip)GetValue(ToolTipSourceProperty);
|
|
set => SetValue(ToolTipSourceProperty, value);
|
|
}
|
|
|
|
// 내부 상태
|
|
bool _hover;
|
|
bool _open;
|
|
|
|
SolidColorBrush _keyBgBrush;
|
|
SolidColorBrush _valueBgBrush;
|
|
Color _originKeyColor;
|
|
Color _originValueColor;
|
|
ColorAnimation _anim;
|
|
|
|
protected override void OnAttached()
|
|
{
|
|
base.OnAttached();
|
|
_keyBgBrush = EnsureRuntimeBrush(AssociatedObject.KeyTextBgColor, out _originKeyColor);
|
|
_valueBgBrush = EnsureRuntimeBrush(AssociatedObject.ValueTextBgColor, out _originValueColor);
|
|
AssociatedObject.KeyTextBgColor = _keyBgBrush;
|
|
AssociatedObject.ValueTextBgColor = _valueBgBrush;
|
|
|
|
RebuildAnimation();
|
|
HookSources(); // ★ 이벤트 연결
|
|
UpdateIsActive(); // 현재 상태 반영
|
|
}
|
|
|
|
protected override void OnDetaching()
|
|
{
|
|
UnhookSources();
|
|
Stop();
|
|
base.OnDetaching();
|
|
}
|
|
|
|
static void OnIsActiveChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
|
{
|
|
var bh = (BlinkHighlightBehavior)d;
|
|
if (bh.AssociatedObject == null) return;
|
|
if ((bool)e.NewValue) bh.Start();
|
|
else bh.Stop();
|
|
}
|
|
|
|
static void OnAnimParamChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
|
{
|
|
var bh = (BlinkHighlightBehavior)d;
|
|
if (bh.AssociatedObject == null) return;
|
|
bh.RebuildAnimation();
|
|
if (bh.IsActive) bh.Start();
|
|
}
|
|
|
|
static void OnSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
|
{
|
|
var bh = (BlinkHighlightBehavior)d;
|
|
if (bh.AssociatedObject == null) return;
|
|
bh.UnhookSources();
|
|
bh.HookSources();
|
|
bh.UpdateIsActive();
|
|
}
|
|
|
|
SolidColorBrush EnsureRuntimeBrush(SolidColorBrush source, out Color original)
|
|
{
|
|
var color = (source as SolidColorBrush)?.Color ?? Colors.Transparent;
|
|
original = color;
|
|
return new SolidColorBrush(color); // 동결되지 않은 브러시
|
|
}
|
|
|
|
void RebuildAnimation()
|
|
{
|
|
_anim = new ColorAnimation {
|
|
To = HighlightColor,
|
|
Duration = TimeSpan.FromMilliseconds(Math.Max(1, DurationMillis)),
|
|
AutoReverse = true,
|
|
RepeatBehavior = RepeatBehavior.Forever
|
|
};
|
|
}
|
|
|
|
void Start()
|
|
{
|
|
_keyBgBrush?.BeginAnimation(SolidColorBrush.ColorProperty, _anim);
|
|
_valueBgBrush?.BeginAnimation(SolidColorBrush.ColorProperty, _anim);
|
|
}
|
|
|
|
void Stop()
|
|
{
|
|
if (_keyBgBrush != null) {
|
|
_keyBgBrush.BeginAnimation(SolidColorBrush.ColorProperty, null);
|
|
_keyBgBrush.Color = _originKeyColor;
|
|
}
|
|
if (_valueBgBrush != null) {
|
|
_valueBgBrush.BeginAnimation(SolidColorBrush.ColorProperty, null);
|
|
_valueBgBrush.Color = _originValueColor;
|
|
}
|
|
}
|
|
|
|
// ===== 이벤트 소스 처리 =====
|
|
void HookSources()
|
|
{
|
|
if (HoverSource != null) {
|
|
HoverSource.MouseEnter += HoverSource_MouseEnter;
|
|
HoverSource.MouseLeave += HoverSource_MouseLeave;
|
|
_hover = HoverSource.IsMouseOver;
|
|
}
|
|
if (ToolTipSource != null) {
|
|
ToolTipSource.Opened += ToolTipSource_Opened;
|
|
ToolTipSource.Closed += ToolTipSource_Closed;
|
|
_open = ToolTipSource.IsOpen;
|
|
}
|
|
}
|
|
|
|
void UnhookSources()
|
|
{
|
|
if (HoverSource != null) {
|
|
HoverSource.MouseEnter -= HoverSource_MouseEnter;
|
|
HoverSource.MouseLeave -= HoverSource_MouseLeave;
|
|
}
|
|
if (ToolTipSource != null) {
|
|
ToolTipSource.Opened -= ToolTipSource_Opened;
|
|
ToolTipSource.Closed -= ToolTipSource_Closed;
|
|
}
|
|
}
|
|
|
|
void HoverSource_MouseEnter(object s, System.Windows.Input.MouseEventArgs e)
|
|
{
|
|
_hover = true; UpdateIsActive();
|
|
}
|
|
void HoverSource_MouseLeave(object s, System.Windows.Input.MouseEventArgs e)
|
|
{
|
|
_hover = false; UpdateIsActive();
|
|
}
|
|
void ToolTipSource_Opened(object s, RoutedEventArgs e)
|
|
{
|
|
_open = true; UpdateIsActive();
|
|
}
|
|
void ToolTipSource_Closed(object s, RoutedEventArgs e)
|
|
{
|
|
_open = false; UpdateIsActive();
|
|
}
|
|
|
|
void UpdateIsActive()
|
|
{
|
|
IsActive = _hover || _open; // ★ OR 연산을 내부에서 처리
|
|
}
|
|
}
|
|
}
|