using System; using System.Collections.Specialized; using System.ComponentModel; using System.Runtime.CompilerServices; using System.Windows; using System.Windows.Input; using System.Windows.Media; using Artemis.Core; using Artemis.UI.Shared.Properties; using Artemis.UI.Shared.Services; using Stylet; namespace Artemis.UI.Shared { /// /// Interaction logic for GradientPicker.xaml /// public partial class GradientPicker : INotifyPropertyChanged { private static IColorPickerService? _colorPickerService; private bool _inCallback; private ColorGradientToGradientStopsConverter _gradientConverter; /// /// Creates a new instance of the class /// public GradientPicker() { _gradientConverter = new ColorGradientToGradientStopsConverter(); InitializeComponent(); Unloaded += OnUnloaded; } /// /// Gets or sets the color gradient /// public ColorGradient ColorGradient { get => (ColorGradient) GetValue(ColorGradientProperty); set => SetValue(ColorGradientProperty, value); } /// /// Gets or sets the dialog host in which to show the gradient dialog /// public string DialogHost { get => (string) GetValue(DialogHostProperty); set => SetValue(DialogHostProperty, value); } /// /// Used by the gradient picker to load saved gradients, do not touch or it'll just throw an exception /// internal static IColorPickerService ColorPickerService { set { if (_colorPickerService != null) throw new AccessViolationException("This is not for you to touch"); _colorPickerService = value; } } /// /// Occurs when the dialog has opened /// public event EventHandler? DialogOpened; /// /// Occurs when the dialog has closed /// public event EventHandler? DialogClosed; /// /// Invokes the event /// [NotifyPropertyChangedInvocator] protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } /// /// Invokes the event /// protected virtual void OnDialogOpened() { DialogOpened?.Invoke(this, EventArgs.Empty); } /// /// Invokes the event /// protected virtual void OnDialogClosed() { DialogClosed?.Invoke(this, EventArgs.Empty); } private static void ColorGradientPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) { GradientPicker gradientPicker = (GradientPicker) d; if (gradientPicker._inCallback) return; gradientPicker._inCallback = true; if (e.OldValue is ColorGradient oldGradient) oldGradient.CollectionChanged -= gradientPicker.GradientChanged; if (e.NewValue is ColorGradient newGradient) newGradient.CollectionChanged += gradientPicker.GradientChanged; gradientPicker.UpdateGradientStops(); gradientPicker.OnPropertyChanged(nameof(ColorGradient)); gradientPicker._inCallback = false; } private void GradientChanged(object? sender, NotifyCollectionChangedEventArgs e) { Dispatcher.Invoke(UpdateGradientStops); } private void UpdateGradientStops() { GradientPreview.GradientStops = (GradientStopCollection) _gradientConverter.Convert(ColorGradient, null!, null!, null!); } private void UIElement_OnMouseUp(object sender, MouseButtonEventArgs e) { if (_colorPickerService == null) return; Execute.OnUIThread(async () => { OnDialogOpened(); await _colorPickerService.ShowGradientPicker(ColorGradient, DialogHost); OnDialogClosed(); }); } private void OnUnloaded(object sender, RoutedEventArgs e) { ColorGradient.CollectionChanged -= GradientChanged; } /// public event PropertyChangedEventHandler? PropertyChanged; #region Static WPF fields /// /// Gets or sets the color gradient /// public static readonly DependencyProperty ColorGradientProperty = DependencyProperty.Register(nameof(ColorGradient), typeof(ColorGradient), typeof(GradientPicker), new FrameworkPropertyMetadata(default(ColorGradient), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, ColorGradientPropertyChangedCallback)); /// /// Gets or sets the dialog host in which to show the gradient dialog /// public static readonly DependencyProperty DialogHostProperty = DependencyProperty.Register(nameof(DialogHost), typeof(string), typeof(GradientPicker), new FrameworkPropertyMetadata(default(string))); /// /// Occurs when the color gradient has changed /// public static readonly RoutedEvent ColorGradientChangedEvent = EventManager.RegisterRoutedEvent(nameof(ColorGradient), RoutingStrategy.Bubble, typeof(RoutedPropertyChangedEventHandler), typeof(GradientPicker)); #endregion } }