using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows.Media; using System.ComponentModel; using System.Windows.Markup; using Microsoft.Research.DynamicDataDisplay.Common.Auxiliary; using System.Collections.ObjectModel; using System.Diagnostics.CodeAnalysis; namespace Microsoft.Research.DynamicDataDisplay.Common.Palettes { [ContentProperty("ColorSteps")] public sealed class UniformLinearPalette : IPalette, ISupportInitialize { private double[] points; private ObservableCollection colors = new ObservableCollection(); public ObservableCollection Colors { get { return colors; } } private List colorSteps = new List(); [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] [EditorBrowsable(EditorBrowsableState.Never)] public List ColorSteps { get { return colorSteps; } } [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] private void RaiseChanged() { Changed.Raise(this); } public event EventHandler Changed; public UniformLinearPalette() { } public UniformLinearPalette(params Color[] colors) { if (colors == null) throw new ArgumentNullException("colors"); if (colors.Length < 2) throw new ArgumentException(Strings.Exceptions.PaletteTooFewColors); this.colors = new ObservableCollection(colors); FillPoints(colors.Length); } private void FillPoints(int size) { points = new double[size]; for (int i = 0; i < size; i++) { points[i] = i / (double)(size - 1); } } private bool increaseBrightness = true; [DefaultValue(true)] public bool IncreaseBrightness { get { return increaseBrightness; } set { increaseBrightness = value; } } public Color GetColor(double t) { Verify.AssertIsFinite(t); Verify.IsTrue(0 <= t && t <= 1); if (t <= 0) return colors[0]; else if (t >= 1) return colors[colors.Count - 1]; else { int i = 0; while (points[i] < t) i++; double ratio = (points[i] - t) / (points[i] - points[i - 1]); Verify.IsTrue(0 <= ratio && ratio <= 1); Color c0 = colors[i - 1]; Color c1 = colors[i]; Color res = Color.FromRgb( (byte)(c0.R * ratio + c1.R * (1 - ratio)), (byte)(c0.G * ratio + c1.G * (1 - ratio)), (byte)(c0.B * ratio + c1.B * (1 - ratio))); // Increasing saturation and brightness if (increaseBrightness) { HsbColor hsb = res.ToHsbColor(); //hsb.Saturation = 0.5 * (1 + hsb.Saturation); hsb.Brightness = 0.5 * (1 + hsb.Brightness); return hsb.ToArgbColor(); } else { return res; } } } #region ISupportInitialize Members bool beganInit = false; public void BeginInit() { beganInit = true; } public void EndInit() { if (beganInit) { colors = new ObservableCollection(colorSteps.Select(step => step.Color)); FillPoints(colors.Count); } } #endregion } }