Skip to content

Commit f430339

Browse files
committed
Fix #1455 Custom tracker strings can cause exception in histogram chart
1 parent af6ac8a commit f430339

3 files changed

Lines changed: 60 additions & 76 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ All notable changes to this project will be documented in this file.
3838
- Exception when rendering polygon with no points (#1410)
3939
- ErrorBarSeries, IntervalBarSeries and TornadoBarSeries work correctly in transposed mode (#1402)
4040
- OxyPlot.WindowsForms package description (#1457)
41+
- Custom tracker strings can cause exception in histogram chart (#1455)
4142

4243
## [2.0.0] - 2019-10-19
4344
### Added

Source/Examples/ExampleLibrary/Series/HistogramSeriesExamples.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,32 @@ public static PlotModel IndividualBinColors()
8585
return CreateIndividualBinColors();
8686
}
8787

88+
[Example("Custom Item Mapping")]
89+
public static PlotModel CustomItemMapping()
90+
{
91+
var model = new PlotModel { Title = "Custom Item Mapping" };
92+
93+
var s = new HistogramSeries { Mapping = obj => (HistogramItem)obj, TrackerFormatString = "{Description}"};
94+
s.Items.Add(new CustomHistogramItem(1, 2, 4, 4, "Item 1"));
95+
s.Items.Add(new CustomHistogramItem(2, 3, -4, 4, "Item 2"));
96+
s.Items.Add(new CustomHistogramItem(3, 4, 2, 2, "Item 3"));
97+
s.Items.Add(new CustomHistogramItem(4, 5, -2, 2, "Item 4"));
98+
model.Series.Add(s);
99+
100+
return model;
101+
}
102+
103+
public class CustomHistogramItem : HistogramItem
104+
{
105+
public CustomHistogramItem(double rangeStart, double rangeEnd, double area, int count, string description)
106+
: base(rangeStart, rangeEnd, area, count)
107+
{
108+
this.Description = description;
109+
}
110+
111+
public string Description { get; }
112+
}
113+
88114
public static PlotModel CreateExponentialDistribution(double mean = 1, int n = 10000)
89115
{
90116
var model = new PlotModel { Title = "Exponential Distribution", Subtitle = "Uniformly distributed bins (" + n + " samples)" };

Source/OxyPlot/Series/HistogramSeries.cs

Lines changed: 33 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,6 @@ public class HistogramSeries : XYAxisSeries
3838
/// </summary>
3939
private bool ownsActualItems;
4040

41-
/// <summary>
42-
/// The default color mapping.
43-
/// </summary>
44-
private OxyColor defaultColorMapping(HistogramItem item) => this.ActualFillColor;
45-
4641
/// <summary>
4742
/// Initializes a new instance of the <see cref="HistogramSeries" /> class.
4843
/// </summary>
@@ -54,7 +49,7 @@ public HistogramSeries()
5449
this.TrackerFormatString = DefaultTrackerFormatString;
5550
this.LabelFormatString = null;
5651
this.LabelPlacement = LabelPlacement.Outside;
57-
this.ColorMapping = this.defaultColorMapping;
52+
this.ColorMapping = this.GetDefaultColor;
5853
}
5954

6055
/// <summary>
@@ -67,16 +62,7 @@ public HistogramSeries()
6762
/// Gets the actual fill color.
6863
/// </summary>
6964
/// <value>The actual color.</value>
70-
public OxyColor ActualFillColor
71-
{
72-
get { return this.FillColor.GetActualColor(this.defaultFillColor); }
73-
}
74-
75-
/// <summary>
76-
/// Gets or sets the color of the interior of the bars when the value is negative.
77-
/// </summary>
78-
/// <value>The color.</value>
79-
public OxyColor NegativeFillColor { get; set; }
65+
public OxyColor ActualFillColor => this.FillColor.GetActualColor(this.defaultFillColor);
8066

8167
/// <summary>
8268
/// Gets or sets the color of the border around the bars.
@@ -116,11 +102,6 @@ public OxyColor ActualFillColor
116102
/// </summary>
117103
public LabelPlacement LabelPlacement { get; set; }
118104

119-
/// <summary>
120-
/// Gets or sets a value indicating whether the tracker can interpolate points.
121-
/// </summary>
122-
public bool CanTrackerInterpolatePoints { get; set; }
123-
124105
/// <summary>
125106
/// Gets or sets the delegate used to map from histogram item to color.
126107
/// </summary>
@@ -178,24 +159,29 @@ public override TrackerHitResult GetNearestPoint(ScreenPoint point, bool interpo
178159
return null;
179160
}
180161

181-
if (this.ActualItems != null)
162+
if (this.ActualItems == null)
163+
{
164+
return null;
165+
}
166+
167+
// iterate through the HistogramItems and return the first one that contains the point
168+
for (var i = 0; i < this.ActualItems.Count; i++)
182169
{
183-
// iterate through the HistogramItems and return the first one that contains the point
184-
foreach (var item in this.ActualItems)
170+
var item = this.ActualItems[i];
171+
if (item.Contains(p))
185172
{
186-
if (item.Contains(p))
173+
var itemsSourceItem = this.GetItem(i);
174+
return new TrackerHitResult
187175
{
188-
return new TrackerHitResult
189-
{
190-
Series = this,
191-
DataPoint = p,
192-
Position = point,
193-
Item = null,
194-
Index = -1,
195-
Text = StringHelper.Format(
176+
Series = this,
177+
DataPoint = p,
178+
Position = point,
179+
Item = itemsSourceItem,
180+
Index = i,
181+
Text = StringHelper.Format(
196182
this.ActualCulture,
197183
this.TrackerFormatString,
198-
null,
184+
itemsSourceItem,
199185
this.Title,
200186
this.XAxis.Title ?? DefaultXAxisTitle,
201187
this.XAxis.GetValue(p.X),
@@ -206,8 +192,7 @@ public override TrackerHitResult GetNearestPoint(ScreenPoint point, bool interpo
206192
item.Value,
207193
item.Area,
208194
item.Count),
209-
};
210-
}
195+
};
211196
}
212197
}
213198

@@ -257,14 +242,6 @@ protected internal override void SetDefaultValues()
257242
}
258243
}
259244

260-
/// <summary>
261-
/// Ensures that the axes of the series is defined.
262-
/// </summary>
263-
protected internal override void EnsureAxes()
264-
{
265-
base.EnsureAxes();
266-
}
267-
268245
/// <summary>
269246
/// Updates the maximum and minimum values of the series for the x and y dimensions only.
270247
/// </summary>
@@ -300,26 +277,6 @@ protected internal override void UpdateMaxMin()
300277
}
301278
}
302279

303-
/// <summary>
304-
/// Updates the axes to include the max and min of this series.
305-
/// </summary>
306-
protected internal override void UpdateAxisMaxMin()
307-
{
308-
base.UpdateAxisMaxMin();
309-
}
310-
311-
/// <summary>
312-
/// Gets the label for the specified cell.
313-
/// </summary>
314-
/// <param name="v">The value of the cell.</param>
315-
/// <param name="i">The first index.</param>
316-
/// <param name="j">The second index.</param>
317-
/// <returns>The label string.</returns>
318-
protected virtual string GetLabel(double v, int i, int j)
319-
{
320-
return v.ToString(this.LabelFormatString, this.ActualCulture);
321-
}
322-
323280
/// <summary>
324281
/// Gets the item at the specified index.
325282
/// </summary>
@@ -370,14 +327,7 @@ protected void RenderBins(IRenderContext rc, OxyRect clippingRect, ICollection<H
370327
/// <returns>The fill color of the item.</returns>
371328
protected OxyColor GetItemFillColor(HistogramItem item)
372329
{
373-
if (!item.Color.IsAutomatic())
374-
{
375-
return item.Color;
376-
}
377-
else
378-
{
379-
return this.ColorMapping(item);
380-
}
330+
return item.Color.IsAutomatic() ? this.ColorMapping(item) : item.Color;
381331
}
382332

383333
/// <summary>
@@ -469,6 +419,15 @@ private void ClearActualItems()
469419
this.ownsActualItems = true;
470420
}
471421

422+
/// <summary>
423+
/// Gets the default color for a HistogramItem.
424+
/// </summary>
425+
/// <returns>The default color.</returns>
426+
private OxyColor GetDefaultColor(HistogramItem item)
427+
{
428+
return this.ActualFillColor;
429+
}
430+
472431
/// <summary>
473432
/// Updates the points from the <see cref="ItemsSeries.ItemsSource" />.
474433
/// </summary>
@@ -486,8 +445,7 @@ private void UpdateActualItems()
486445
return;
487446
}
488447

489-
var sourceAsListOfHistogramItems = this.ItemsSource as List<HistogramItem>;
490-
if (sourceAsListOfHistogramItems != null)
448+
if (this.ItemsSource is List<HistogramItem> sourceAsListOfHistogramItems)
491449
{
492450
this.actualItems = sourceAsListOfHistogramItems;
493451
this.ownsActualItems = false;
@@ -496,8 +454,7 @@ private void UpdateActualItems()
496454

497455
this.ClearActualItems();
498456

499-
var sourceAsEnumerableHistogramItems = this.ItemsSource as IEnumerable<HistogramItem>;
500-
if (sourceAsEnumerableHistogramItems != null)
457+
if (this.ItemsSource is IEnumerable<HistogramItem> sourceAsEnumerableHistogramItems)
501458
{
502459
this.actualItems.AddRange(sourceAsEnumerableHistogramItems);
503460
}

0 commit comments

Comments
 (0)