You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
174 lines
5.1 KiB
174 lines
5.1 KiB
using System; |
|
using System.Collections.Generic; |
|
using System.Linq; |
|
using System.Text; |
|
using System.Windows; |
|
using System.Windows.Controls; |
|
using System.Windows.Data; |
|
using System.Windows.Documents; |
|
using System.Windows.Input; |
|
using System.Windows.Media; |
|
using System.Windows.Media.Imaging; |
|
using System.Windows.Navigation; |
|
using System.Windows.Shapes; |
|
using System.Windows.Controls.Primitives; |
|
using System.ComponentModel; |
|
|
|
namespace SharpDevelop.XamlDesigner.PropertyGrid.Editors.BrushEditor |
|
{ |
|
public partial class GradientSlider : UserControl |
|
{ |
|
public GradientSlider() |
|
{ |
|
InitializeComponent(); |
|
|
|
BindingOperations.SetBinding(this, SelectedStopProperty, new Binding("SelectedItem") { |
|
Source = itemsControl, |
|
Mode = BindingMode.TwoWay |
|
}); |
|
|
|
strip.DragStarted += new DragStartedEventHandler(strip_DragStarted); |
|
strip.DragDelta += new DragDeltaEventHandler(strip_DragDelta); |
|
} |
|
|
|
static GradientSlider() |
|
{ |
|
EventManager.RegisterClassHandler(typeof(GradientSlider), |
|
Thumb.DragDeltaEvent, new DragDeltaEventHandler(ClassDragDelta)); |
|
} |
|
|
|
GradientStop newStop; |
|
double startOffset; |
|
|
|
public static readonly DependencyProperty GradientBrushProperty = |
|
DependencyProperty.Register("GradientBrush", typeof(GradientBrush), typeof(GradientSlider), |
|
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault)); |
|
|
|
public GradientBrush GradientBrush |
|
{ |
|
get { return (GradientBrush)GetValue(GradientBrushProperty); } |
|
set { SetValue(GradientBrushProperty, value); } |
|
} |
|
|
|
public static readonly DependencyProperty SelectedStopProperty = |
|
DependencyProperty.Register("SelectedStop", typeof(GradientStop), typeof(GradientSlider)); |
|
|
|
public GradientStop SelectedStop |
|
{ |
|
get { return (GradientStop)GetValue(SelectedStopProperty); } |
|
set { SetValue(SelectedStopProperty, value); } |
|
} |
|
|
|
public static readonly DependencyProperty GradientStopsProperty = |
|
DependencyProperty.Register("GradientStops", typeof(BindingList<GradientStop>), typeof(GradientSlider)); |
|
|
|
public BindingList<GradientStop> GradientStops |
|
{ |
|
get { return (BindingList<GradientStop>)GetValue(GradientStopsProperty); } |
|
set { SetValue(GradientStopsProperty, value); } |
|
} |
|
|
|
public static Color GetColorAtOffset(IList<GradientStop> stops, double offset) |
|
{ |
|
var array = stops.OrderBy(s => s.Offset).ToArray(); |
|
if (array.Length < 2) { |
|
return Colors.White; |
|
} |
|
|
|
GradientStop s1 = array[0]; |
|
GradientStop s2 = array.Last(); |
|
|
|
foreach (var item in array) { |
|
if (item.Offset < offset && item.Offset > s1.Offset) s1 = item; |
|
if (item.Offset > offset && item.Offset < s2.Offset) s2 = item; |
|
} |
|
|
|
return Color.FromArgb( |
|
Interpolate(offset, s1.Color.A, s1.Offset, s2.Color.A, s2.Offset), |
|
Interpolate(offset, s1.Color.R, s1.Offset, s2.Color.R, s2.Offset), |
|
Interpolate(offset, s1.Color.G, s1.Offset, s2.Color.G, s2.Offset), |
|
Interpolate(offset, s1.Color.B, s1.Offset, s2.Color.B, s2.Offset) |
|
); |
|
} |
|
|
|
static byte Interpolate(double offset, byte v1, double offset1, byte v2, double offset2) |
|
{ |
|
if (v1 == v2) return v1; |
|
return (byte)(v1 + (offset - offset1) * (v2 - v1) / (offset2 - offset1)); |
|
} |
|
|
|
static void ClassDragDelta(object sender, DragDeltaEventArgs e) |
|
{ |
|
(sender as GradientSlider).thumb_DragDelta(sender, e); |
|
} |
|
|
|
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) |
|
{ |
|
base.OnPropertyChanged(e); |
|
|
|
if (e.Property == GradientBrushProperty) { |
|
if (GradientBrush != null) { |
|
GradientStops = new BindingList<GradientStop>(GradientBrush.GradientStops); |
|
SelectedStop = GradientStops.FirstOrDefault(); |
|
} |
|
else { |
|
GradientStops = null; |
|
} |
|
} |
|
} |
|
|
|
void strip_DragStarted(object sender, DragStartedEventArgs e) |
|
{ |
|
startOffset = e.HorizontalOffset / strip.ActualWidth; |
|
newStop = new GradientStop(GetColorAtOffset(GradientStops, startOffset), startOffset); |
|
GradientStops.Add(newStop); |
|
SelectedStop = newStop; |
|
e.Handled = true; |
|
} |
|
|
|
void strip_DragDelta(object sender, DragDeltaEventArgs e) |
|
{ |
|
MoveStop(newStop, startOffset, e); |
|
e.Handled = true; |
|
} |
|
|
|
void thumb_DragDelta(object sender, DragDeltaEventArgs e) |
|
{ |
|
var stop = (e.OriginalSource as GradientThumb).GradientStop; |
|
MoveStop(stop, stop.Offset, e); |
|
} |
|
|
|
void MoveStop(GradientStop stop, double oldOffset, DragDeltaEventArgs e) |
|
{ |
|
if (e.VerticalChange > 50 && GradientStops.Count > 2) { |
|
GradientStops.Remove(stop); |
|
SelectedStop = GradientStops.FirstOrDefault(); |
|
return; |
|
} |
|
stop.Offset = (oldOffset + e.HorizontalChange / strip.ActualWidth).Coerce(0, 1); |
|
} |
|
} |
|
|
|
public class GradientItemsControl : Selector |
|
{ |
|
protected override DependencyObject GetContainerForItemOverride() |
|
{ |
|
return new GradientThumb(); |
|
} |
|
} |
|
|
|
public class GradientThumb : Thumb |
|
{ |
|
public GradientStop GradientStop |
|
{ |
|
get { return DataContext as GradientStop; } |
|
} |
|
|
|
protected override void OnPreviewMouseDown(MouseButtonEventArgs e) |
|
{ |
|
base.OnPreviewMouseDown(e); |
|
var itemsControl = ItemsControl.ItemsControlFromItemContainer(this) as GradientItemsControl; |
|
itemsControl.SelectedItem = GradientStop; |
|
} |
|
} |
|
}
|
|
|