using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Media; using System.Windows.Media.Imaging; using Dominion.NET_WPF.Caching; namespace Dominion.NET_WPF.Controls { /// /// SmallBrushPicker user control /// This code is open source published with the Code Project Open License (CPOL). /// public partial class ucSmallBrushPicker : UserControl { public static readonly DependencyProperty SelectedIndexProperty; public static readonly DependencyProperty SelectedItemProperty; public static readonly DependencyProperty TextBrushProperty; //private static Dictionary average_hash = new Dictionary(); static ucSmallBrushPicker() { SelectedIndexProperty = DependencyProperty.Register ("SelectedIndex", typeof(int), typeof(ucSmallBrushPicker)); SelectedItemProperty = DependencyProperty.Register ("SelectedItem", typeof(Brush), typeof(ucSmallBrushPicker)); TextBrushProperty = DependencyProperty.Register ("TextBrush", typeof(Brush), typeof(ucSmallBrushPicker)); } public int SelectedIndex { get { return (int)GetValue(SelectedIndexProperty); } set { SetValue(SelectedIndexProperty, value); } } public object SelectedItem { get { return GetValue(SelectedItemProperty) as Brush; } set { SetValue(SelectedItemProperty, value); } } public object TextBrush { get { return GetValue(TextBrushProperty) as Brush; } set { SetValue(TextBrushProperty, value); } } public ObservableCollection ImageBrushes { get; set; } public ucSmallBrushPicker() { ImageBrushes = new ObservableCollection(); TextBrush = Brushes.Black; Clear(); InitializeComponent(); var selectedIndexBinding = new Binding("SelectedIndex") { Source = Content, Mode = BindingMode.TwoWay }; SetBinding(SelectedIndexProperty, selectedIndexBinding); var selectedItemBinding = new Binding("SelectedItem") { Source = Content, Mode = BindingMode.TwoWay }; SetBinding(SelectedItemProperty, selectedItemBinding); } #region Dependency properties public Brush SelectedBrush { get { return (Brush)GetValue(SelectedBrushProperty); } set { SetValue(SelectedBrushProperty, value); } } public static readonly DependencyProperty SelectedBrushProperty = DependencyProperty.Register("SelectedBrush", typeof(Brush), typeof(ucSmallBrushPicker), new FrameworkPropertyMetadata(OnSelectedBrushChanged)); public IEnumerable AvailableBrushes => ImageBrushes.OfType(); private bool ListContains(Brush newBrush) { return Picker.Items.OfType().Contains(newBrush); } private static void OnSelectedBrushChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args) { var bp = obj as ucSmallBrushPicker; Debug.Assert(bp != null); var newBrush = (Brush)args.NewValue; var oldBrush = (Brush)args.OldValue; if (Equals(newBrush, oldBrush)) return; // When the SelectedBrush changes, set the selected value of the combo box if (bp.Picker.SelectedValue == null || !Equals((Brush)bp.Picker.SelectedValue, newBrush)) { // Add the brush if not found if (!bp.ListContains(newBrush)) { bp.AddBrush(newBrush); } } bp.OnBrushChanged(oldBrush, newBrush); } #endregion #region Events public static readonly RoutedEvent BrushChangedEvent = EventManager.RegisterRoutedEvent("BrushChanged", RoutingStrategy.Bubble, typeof(RoutedPropertyChangedEventHandler), typeof(ucSmallBrushPicker)); public event RoutedPropertyChangedEventHandler BrushChanged { add { AddHandler(BrushChangedEvent, value); } remove { RemoveHandler(BrushChangedEvent, value); } } protected virtual void OnBrushChanged(Brush oldValue, Brush newValue) { var args = new RoutedPropertyChangedEventArgs(oldValue, newValue) {RoutedEvent = BrushChangedEvent}; RaiseEvent(args); } #endregion public static Brush CheckerBrush { get; } = CreateCheckerBrush(); public void Clear() { ImageBrushes.Clear(); ImageBrushes.Add(Brushes.Transparent); //this.SelectedItem = Brushes.Transparent; } /// /// Add a brush to the BrushPicker list /// /// public void AddBrush(Brush b) { ImageBrushes.Add(b); } public static Brush CreateCheckerBrush() { // from http://msdn.microsoft.com/en-us/library/aa970904.aspx var checkerBrush = new DrawingBrush(); int width; var height = width = 16; const int size = 4; var backgroundSquare = new GeometryDrawing( Brushes.White, null, new RectangleGeometry(new Rect(0, 0, width, height))); var aGeometryGroup = new GeometryGroup(); for (var x = 0; x < width; x += size) { for (var y = 0; y < height; y += size) { if ((x + y) / size % 2 == 1) continue; aGeometryGroup.Children.Add(new RectangleGeometry(new Rect(x, y, size, size))); } } var checkers = new GeometryDrawing(Brushes.Black, null, aGeometryGroup); var checkersDrawingGroup = new DrawingGroup(); checkersDrawingGroup.Children.Add(backgroundSquare); checkersDrawingGroup.Children.Add(checkers); checkerBrush.Drawing = checkersDrawingGroup; checkerBrush.Viewport = new Rect(0, 0, 0.5, 0.5); checkerBrush.TileMode = TileMode.Tile; return checkerBrush; } private void Picker_SelectionChanged(object sender, SelectionChangedEventArgs e) { var addedBrushes = e.AddedItems.OfType().ToList(); if (addedBrushes.Any()) { var addedImage = addedBrushes.First().ImageSource; var image = addedImage as BitmapImage; if (image != null) { var ir = ImageRepository.Acquire(); TextBrush = ir.GetForegroundBrush(image); ImageRepository.Release(); //BitmapImage image = (BitmapImage)addedImage; //if (!average_hash.ContainsKey(image)) //{ // PixelColor[,] pixels = ImageUtilities.GetPixels(image); // double l_sum = 0; // for (int x = 0; x < pixels.GetLength(0); x++) // { // for (int y = 0; y < pixels.GetLength(1); y++) // { // Color c = Color.FromArgb(pixels[x, y].Alpha, pixels[x, y].Red, pixels[x, y].Green, pixels[x, y].Blue); // double l = 0.2126 * c.ScR + 0.7152 * c.ScG + 0.0722 * c.ScB; // l_sum += l; // } // } // average_hash[image] = l_sum / (pixels.GetLength(0) * pixels.GetLength(1)); //} //if (average_hash[image] < 0.5) // this.TextBrush = Brushes.White; //else // this.TextBrush = Brushes.Black; } else TextBrush = Brushes.Black; } else TextBrush = Brushes.Black; OnBrushChanged(e.RemovedItems.OfType().FirstOrDefault(), e.AddedItems.OfType().FirstOrDefault()); } } public class BindingProxy : Freezable { protected override Freezable CreateInstanceCore() { return new BindingProxy(); } public object Data { get { return GetValue(DataProperty); } set { SetValue(DataProperty, value); } } // Using a DependencyProperty as the backing store for Data. // This enables animation, styling, binding, etc... public static readonly DependencyProperty DataProperty = DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null)); } }