Dreamine.UI.Wpf.Controls 1.0.1
Dreamine.UI.Wpf.Controls 사용자 인터페이스 기능과 구성 요소를 제공합니다.
로딩중...
검색중...
일치하는것 없음
DreamineCheckLed.cs
이 파일의 문서화 페이지로 가기
1using Microsoft.Xaml.Behaviors.Layout;
2using System;
3using System.ComponentModel;
4using System.Windows;
5using System.Windows.Controls;
6using System.Windows.Data;
7using System.Windows.Documents;
8using System.Windows.Media;
9using System.Windows.Media.Animation;
10
12{
21 public class DreamineCheckLed : Control
22 {
31 private static readonly Brush _onOuter = Freeze(CreateRadial(
32 new[] { ("#FF1FD36B", 0.00), ("#FFA7F0C1", 0.60), ("#00FFFFFF", 1.00) }, 0.6, 0.6));
41 private static readonly Brush _onInner = Freeze(CreateRadial(
42 new[] { ("#FF6E6E6E", 0.00), ("#FF4B4B4B", 1.00) }, 0.65, 0.65));
43 // Off 상태는 "링"만 보여야 하므로 Fill은 투명으로 둡니다.
52 private static readonly Brush _offOuter = Brushes.Transparent;
61 private static readonly Brush _offInner = Brushes.Transparent;
62
111 private static RadialGradientBrush CreateRadial((string color, double offset)[] stops, double rx, double ry)
112 {
113 var b = new RadialGradientBrush
114 {
115 Center = new Point(0.5, 0.5),
116 GradientOrigin = new Point(0.5, 0.5),
117 RadiusX = rx,
118 RadiusY = ry
119 };
120 foreach (var (c, off) in stops)
121 b.GradientStops.Add(new GradientStop((Color)ColorConverter.ConvertFromString(c), off));
122 if (b.CanFreeze) b.Freeze();
123 return b;
124 }
125
149 private static Brush Freeze(Brush b) { if (b.CanFreeze) b.Freeze(); return b; }
150
160 {
161 DefaultStyleKeyProperty.OverrideMetadata(
162 typeof(DreamineCheckLed),
163 new FrameworkPropertyMetadata(typeof(DreamineCheckLed)));
164
165 try
166 {
167 // ⬇️ HitTest 기본값을 false로 고정
168 IsHitTestVisibleProperty.OverrideMetadata(
169 typeof(DreamineCheckLed),
170 new FrameworkPropertyMetadata(false));
171
172 // (권장) 포커스/탭정지도 기본 비활성화
173 FocusableProperty.OverrideMetadata(
174 typeof(DreamineCheckLed),
175 new FrameworkPropertyMetadata(false));
176 IsTabStopProperty.OverrideMetadata(
177 typeof(DreamineCheckLed),
178 new FrameworkPropertyMetadata(false));
179
180 var uri = new Uri("/Dreamine.UI.Wpf.Themes;component/DreamineCheckLedStyle.xaml",
181 UriKind.RelativeOrAbsolute);
182 var app = Application.Current;
183 if (app != null)
184 {
185 bool alreadyAdded = app.Resources.MergedDictionaries
186 .OfType<ResourceDictionary>()
187 .Any(x => x.Source != null && x.Source.Equals(uri));
188
189 if (!alreadyAdded)
190 {
191 var dict = new ResourceDictionary { Source = uri };
192 app.Resources.MergedDictionaries.Add(dict);
193 }
194 }
195 }
196 catch
197 {
198 // Guard for design-time or missing resource scenarios.
199 }
200 }
201
202
211 public static readonly DependencyProperty IsOnProperty =
212 DependencyProperty.Register(nameof(IsOn), typeof(bool), typeof(DreamineCheckLed),
213 new PropertyMetadata(false, OnPulseStateChanged));
214
223 public static readonly DependencyProperty IsPulseProperty =
224 DependencyProperty.Register(nameof(IsPulse), typeof(bool), typeof(DreamineCheckLed),
225 new PropertyMetadata(false, OnPulseStateChanged));
226
251 private static void OnPulseStateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
252 {
253 if (d is not DreamineCheckLed led) return;
254
255 if (led.IsOn && led.IsPulse)
256 {
257 var pulse = new DoubleAnimation
258 {
259 From = 0.15,
260 To = 1.0,
261 Duration = TimeSpan.FromSeconds(0.4),
262 AutoReverse = true,
263 RepeatBehavior = RepeatBehavior.Forever
264 };
265 led.BeginAnimation(OpacityProperty, pulse);
266 }
267 else
268 {
269 led.BeginAnimation(OpacityProperty, null);
270 led.Opacity = 1.0;
271 }
272 }
273
282 public static readonly DependencyProperty CornerProperty =
283 DependencyProperty.Register(nameof(Corner), typeof(LedCorner), typeof(DreamineCheckLed),
284 new PropertyMetadata(LedCorner.TopRight));
285
294 public static readonly DependencyProperty DiameterProperty =
295 DependencyProperty.Register(nameof(Diameter), typeof(double), typeof(DreamineCheckLed),
296 new PropertyMetadata(18.0));
297
306 public static readonly DependencyProperty EdgeOffsetProperty =
307 DependencyProperty.Register(nameof(EdgeOffset), typeof(double), typeof(DreamineCheckLed),
308 new PropertyMetadata(6.0));
309
318 public static readonly DependencyProperty InnerScaleProperty =
319 DependencyProperty.Register(nameof(InnerScale), typeof(double), typeof(DreamineCheckLed),
320 new PropertyMetadata(0.45));
321
330 public static readonly DependencyProperty OnOuterFillProperty =
331 DependencyProperty.Register(nameof(OnOuterFill), typeof(Brush), typeof(DreamineCheckLed),
332 new PropertyMetadata(_onOuter));
341 public static readonly DependencyProperty OnInnerFillProperty =
342 DependencyProperty.Register(nameof(OnInnerFill), typeof(Brush), typeof(DreamineCheckLed),
343 new PropertyMetadata(_onInner));
352 public static readonly DependencyProperty OffOuterFillProperty =
353 DependencyProperty.Register(nameof(OffOuterFill), typeof(Brush), typeof(DreamineCheckLed),
354 new PropertyMetadata(_offOuter));
363 public static readonly DependencyProperty OffInnerFillProperty =
364 DependencyProperty.Register(nameof(OffInnerFill), typeof(Brush), typeof(DreamineCheckLed),
365 new PropertyMetadata(_offInner));
366
375 public static readonly DependencyProperty StrokeBrushProperty =
376 DependencyProperty.Register(nameof(StrokeBrush), typeof(Brush), typeof(DreamineCheckLed),
377 new PropertyMetadata(Brushes.White));
386 public static readonly DependencyProperty StrokeThicknessProperty =
387 DependencyProperty.Register(nameof(StrokeThickness), typeof(double), typeof(DreamineCheckLed),
388 new PropertyMetadata(1.2));
389
398 public bool IsOn { get => (bool)GetValue(IsOnProperty); set => SetValue(IsOnProperty, value); }
407 public bool IsPulse { get => (bool)GetValue(IsPulseProperty); set => SetValue(IsPulseProperty, value); }
416 public LedCorner Corner { get => (LedCorner)GetValue(CornerProperty); set => SetValue(CornerProperty, value); }
425 public double Diameter { get => (double)GetValue(DiameterProperty); set => SetValue(DiameterProperty, value); }
434 public double EdgeOffset { get => (double)GetValue(EdgeOffsetProperty); set => SetValue(EdgeOffsetProperty, value); }
443 public double InnerScale { get => (double)GetValue(InnerScaleProperty); set => SetValue(InnerScaleProperty, value); }
452 public Brush OnOuterFill { get => (Brush)GetValue(OnOuterFillProperty); set => SetValue(OnOuterFillProperty, value); }
461 public Brush OnInnerFill { get => (Brush)GetValue(OnInnerFillProperty); set => SetValue(OnInnerFillProperty, value); }
470 public Brush OffOuterFill { get => (Brush)GetValue(OffOuterFillProperty); set => SetValue(OffOuterFillProperty, value); }
479 public Brush OffInnerFill { get => (Brush)GetValue(OffInnerFillProperty); set => SetValue(OffInnerFillProperty, value); }
488 public Brush StrokeBrush { get => (Brush)GetValue(StrokeBrushProperty); set => SetValue(StrokeBrushProperty, value); }
497 public double StrokeThickness { get => (double)GetValue(StrokeThicknessProperty); set => SetValue(StrokeThicknessProperty, value); }
498 }
499
500
501
510 public static class DreamineCheckLedAttach
511 {
512 #region Public Attached DPs
513
522 public static readonly DependencyProperty IsEnabledProperty =
523 DependencyProperty.RegisterAttached("IsEnabled", typeof(bool), typeof(DreamineCheckLedAttach),
524 new PropertyMetadata(false, OnAnyPropertyChanged));
525
534 public static readonly DependencyProperty IsOnProperty =
535 DependencyProperty.RegisterAttached("IsOn", typeof(bool), typeof(DreamineCheckLedAttach),
536 new PropertyMetadata(false, OnAnyPropertyChanged));
537
546 public static readonly DependencyProperty IsPulseProperty =
547 DependencyProperty.RegisterAttached("IsPulse", typeof(bool), typeof(DreamineCheckLedAttach),
548 new PropertyMetadata(false, OnAnyPropertyChanged));
549
558 public static readonly DependencyProperty CornerProperty =
559 DependencyProperty.RegisterAttached("Corner", typeof(LedCorner), typeof(DreamineCheckLedAttach),
560 new PropertyMetadata(LedCorner.TopRight, OnAnyPropertyChanged));
561
570 public static readonly DependencyProperty DiameterProperty =
571 DependencyProperty.RegisterAttached("Diameter", typeof(double), typeof(DreamineCheckLedAttach),
572 new PropertyMetadata(18.0, OnAnyPropertyChanged));
573
582 public static readonly DependencyProperty MarginProperty =
583 DependencyProperty.RegisterAttached("Margin", typeof(double), typeof(DreamineCheckLedAttach),
584 new PropertyMetadata(6.0, OnAnyPropertyChanged));
585
594 public static readonly DependencyProperty InnerScaleProperty =
595 DependencyProperty.RegisterAttached("InnerScale", typeof(double), typeof(DreamineCheckLedAttach),
596 new PropertyMetadata(0.45, OnAnyPropertyChanged));
597
606 public static readonly DependencyProperty OnOuterFillProperty =
607 DependencyProperty.RegisterAttached("OnOuterFill", typeof(Brush), typeof(DreamineCheckLedAttach),
608 new PropertyMetadata(null, OnAnyPropertyChanged));
617 public static readonly DependencyProperty OnInnerFillProperty =
618 DependencyProperty.RegisterAttached("OnInnerFill", typeof(Brush), typeof(DreamineCheckLedAttach),
619 new PropertyMetadata(null, OnAnyPropertyChanged));
628 public static readonly DependencyProperty OffOuterFillProperty =
629 DependencyProperty.RegisterAttached("OffOuterFill", typeof(Brush), typeof(DreamineCheckLedAttach),
630 new PropertyMetadata(null, OnAnyPropertyChanged));
639 public static readonly DependencyProperty OffInnerFillProperty =
640 DependencyProperty.RegisterAttached("OffInnerFill", typeof(Brush), typeof(DreamineCheckLedAttach),
641 new PropertyMetadata(null, OnAnyPropertyChanged));
642
651 public static readonly DependencyProperty StrokeBrushProperty =
652 DependencyProperty.RegisterAttached("StrokeBrush", typeof(Brush), typeof(DreamineCheckLedAttach),
653 new PropertyMetadata(Brushes.White, OnAnyPropertyChanged));
662 public static readonly DependencyProperty StrokeThicknessProperty =
663 DependencyProperty.RegisterAttached("StrokeThickness", typeof(double), typeof(DreamineCheckLedAttach),
664 new PropertyMetadata(1.2, OnAnyPropertyChanged));
665
666 // Get/Set
699 public static void SetIsEnabled(DependencyObject o, bool v) => o.SetValue(IsEnabledProperty, v);
732 public static bool GetIsEnabled(DependencyObject o) => (bool)o.GetValue(IsEnabledProperty);
733
766 public static void SetIsOn(DependencyObject o, bool v) => o.SetValue(IsOnProperty, v);
799 public static bool GetIsOn(DependencyObject o) => (bool)o.GetValue(IsOnProperty);
800
833 public static void SetIsPulse(DependencyObject o, bool v) => o.SetValue(IsPulseProperty, v);
866 public static bool GetIsPulse(DependencyObject o) => (bool)o.GetValue(IsPulseProperty);
867
900 public static void SetCorner(DependencyObject o, LedCorner v) => o.SetValue(CornerProperty, v);
933 public static LedCorner GetCorner(DependencyObject o) => (LedCorner)o.GetValue(CornerProperty);
934
967 public static void SetDiameter(DependencyObject o, double v) => o.SetValue(DiameterProperty, v);
1000 public static double GetDiameter(DependencyObject o) => (double)o.GetValue(DiameterProperty);
1001
1034 public static void SetMargin(DependencyObject o, double v) => o.SetValue(MarginProperty, v);
1067 public static double GetMargin(DependencyObject o) => (double)o.GetValue(MarginProperty);
1068
1101 public static void SetInnerScale(DependencyObject o, double v) => o.SetValue(InnerScaleProperty, v);
1134 public static double GetInnerScale(DependencyObject o) => (double)o.GetValue(InnerScaleProperty);
1135
1160 public static void SetOnOuterFill(DependencyObject o, Brush v) => o.SetValue(OnOuterFillProperty, v);
1185 public static Brush GetOnOuterFill(DependencyObject o) => (Brush)o.GetValue(OnOuterFillProperty);
1210 public static void SetOnInnerFill(DependencyObject o, Brush v) => o.SetValue(OnInnerFillProperty, v);
1235 public static Brush GetOnInnerFill(DependencyObject o) => (Brush)o.GetValue(OnInnerFillProperty);
1260 public static void SetOffOuterFill(DependencyObject o, Brush v) => o.SetValue(OffOuterFillProperty, v);
1285 public static Brush GetOffOuterFill(DependencyObject o) => (Brush)o.GetValue(OffOuterFillProperty);
1310 public static void SetOffInnerFill(DependencyObject o, Brush v) => o.SetValue(OffInnerFillProperty, v);
1335 public static Brush GetOffInnerFill(DependencyObject o) => (Brush)o.GetValue(OffInnerFillProperty);
1336
1361 public static void SetStrokeBrush(DependencyObject o, Brush v) => o.SetValue(StrokeBrushProperty, v);
1386 public static Brush GetStrokeBrush(DependencyObject o) => (Brush)o.GetValue(StrokeBrushProperty);
1411 public static void SetStrokeThickness(DependencyObject o, double v) => o.SetValue(StrokeThicknessProperty, v);
1436 public static double GetStrokeThickness(DependencyObject o) => (double)o.GetValue(StrokeThicknessProperty);
1437
1438 #endregion
1439
1440 #region Private state
1449 private static readonly DependencyProperty AdornerContainerProperty =
1450 DependencyProperty.RegisterAttached("AdornerContainer", typeof(AdornerContainer), typeof(DreamineCheckLedAttach),
1451 new PropertyMetadata(null));
1476 private static void SetAdornerContainer(DependencyObject o, AdornerContainer? v) => o.SetValue(AdornerContainerProperty, v);
1501 private static AdornerContainer? GetAdornerContainer(DependencyObject o) => (AdornerContainer?)o.GetValue(AdornerContainerProperty);
1502 #endregion
1503
1504 #region Lifecycle
1529 private static void OnAnyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
1530 {
1531 if (d is not FrameworkElement fe) return;
1532
1533 if (DesignerProperties.GetIsInDesignMode(fe))
1534 {
1535 fe.Loaded -= OnLoaded;
1536 fe.Loaded += OnLoaded;
1537 return;
1538 }
1539
1540 fe.Loaded -= OnLoaded;
1541 fe.Unloaded -= OnUnloaded;
1542 fe.SizeChanged -= OnSizeChanged;
1543
1544 fe.Loaded += OnLoaded;
1545 fe.Unloaded += OnUnloaded;
1546 fe.SizeChanged += OnSizeChanged;
1547
1548 if (GetIsEnabled(fe)) EnsureAdorner(fe);
1549 else RemoveAdorner(fe);
1550 }
1551
1576 private static void OnLoaded(object? s, RoutedEventArgs e)
1577 {
1578 if (s is FrameworkElement fe && GetIsEnabled(fe)) EnsureAdorner(fe);
1579 }
1580
1605 private static void OnUnloaded(object? s, RoutedEventArgs e)
1606 {
1607 if (s is FrameworkElement fe) RemoveAdorner(fe);
1608 }
1609
1634 private static void OnSizeChanged(object? s, SizeChangedEventArgs e) { }
1635
1660 private static void EnsureAdorner(FrameworkElement fe)
1661 {
1662 var layer = AdornerLayer.GetAdornerLayer(fe);
1663 if (layer is null) return;
1664
1665 var container = GetAdornerContainer(fe);
1666 if (container is null)
1667 {
1668 var led = new DreamineCheckLed { IsHitTestVisible = false };
1669
1670 BindingOperations.SetBinding(led, FrameworkElement.WidthProperty, new Binding("ActualWidth") { Source = fe });
1671 BindingOperations.SetBinding(led, FrameworkElement.HeightProperty, new Binding("ActualHeight") { Source = fe });
1672
1685
1686 container = new AdornerContainer(fe) { Child = led, IsHitTestVisible = false };
1687 layer.Add(container);
1688 SetAdornerContainer(fe, container);
1689 }
1690 }
1691
1708 private static void RemoveAdorner(FrameworkElement fe)
1709 {
1710 var layer = AdornerLayer.GetAdornerLayer(fe);
1711 var container = GetAdornerContainer(fe);
1712 if (container != null && layer != null)
1713 {
1714 layer.Remove(container);
1715 SetAdornerContainer(fe, null);
1716 }
1717 }
1718
1767 private static void Bind(DependencyObject target, DependencyProperty targetDp,
1768 DependencyObject source, DependencyProperty attachedDp)
1769 {
1770 var path = new PropertyPath("(0)", attachedDp);
1771 BindingOperations.SetBinding(target, targetDp, new Binding { Source = source, Path = path });
1772 }
1773 #endregion
1774 }
1775}
static readonly DependencyProperty CornerProperty
static readonly DependencyProperty InnerScaleProperty
static readonly DependencyProperty OffInnerFillProperty
static readonly DependencyProperty OffOuterFillProperty
static readonly DependencyProperty OnOuterFillProperty
static readonly DependencyProperty IsOnProperty
static readonly DependencyProperty StrokeThicknessProperty
static readonly DependencyProperty IsPulseProperty
static readonly DependencyProperty EdgeOffsetProperty
static readonly DependencyProperty StrokeBrushProperty
static void OnPulseStateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
static readonly DependencyProperty OnInnerFillProperty
static readonly DependencyProperty DiameterProperty
static RadialGradientBrush CreateRadial((string color, double offset)[] stops, double rx, double ry)
static readonly DependencyProperty InnerScaleProperty
static void SetIsOn(DependencyObject o, bool v)
static void SetCorner(DependencyObject o, LedCorner v)
static readonly DependencyProperty OffInnerFillProperty
static readonly DependencyProperty IsPulseProperty
static double GetInnerScale(DependencyObject o)
static readonly DependencyProperty DiameterProperty
static Brush GetStrokeBrush(DependencyObject o)
static void EnsureAdorner(FrameworkElement fe)
static void SetOffOuterFill(DependencyObject o, Brush v)
static void SetStrokeBrush(DependencyObject o, Brush v)
static void OnUnloaded(object? s, RoutedEventArgs e)
static readonly DependencyProperty IsEnabledProperty
static void OnLoaded(object? s, RoutedEventArgs e)
static readonly DependencyProperty StrokeBrushProperty
static readonly DependencyProperty StrokeThicknessProperty
static void SetAdornerContainer(DependencyObject o, AdornerContainer? v)
static void SetOnOuterFill(DependencyObject o, Brush v)
static void SetMargin(DependencyObject o, double v)
static void SetDiameter(DependencyObject o, double v)
static readonly DependencyProperty IsOnProperty
static readonly DependencyProperty MarginProperty
static ? AdornerContainer GetAdornerContainer(DependencyObject o)
static double GetDiameter(DependencyObject o)
static Brush GetOnInnerFill(DependencyObject o)
static readonly DependencyProperty OffOuterFillProperty
static double GetStrokeThickness(DependencyObject o)
static Brush GetOffOuterFill(DependencyObject o)
static double GetMargin(DependencyObject o)
static readonly DependencyProperty CornerProperty
static void SetStrokeThickness(DependencyObject o, double v)
static void SetIsEnabled(DependencyObject o, bool v)
static readonly DependencyProperty AdornerContainerProperty
static void SetInnerScale(DependencyObject o, double v)
static void Bind(DependencyObject target, DependencyProperty targetDp, DependencyObject source, DependencyProperty attachedDp)
static Brush GetOnOuterFill(DependencyObject o)
static void RemoveAdorner(FrameworkElement fe)
static readonly DependencyProperty OnOuterFillProperty
static void SetOnInnerFill(DependencyObject o, Brush v)
static void OnSizeChanged(object? s, SizeChangedEventArgs e)
static Brush GetOffInnerFill(DependencyObject o)
static readonly DependencyProperty OnInnerFillProperty
static void OnAnyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
static void SetIsPulse(DependencyObject o, bool v)
static LedCorner GetCorner(DependencyObject o)
static void SetOffInnerFill(DependencyObject o, Brush v)