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
}
}