///<summary> /// Create a range facet attribute. ///</summary> ///<param name="name">the name of the facet attribute.</param> ///<param name="facets">The facets in this attribute.</param> ///<param name="descriptions">Descriptions mapped from locales for the attribute.</param> ///<param name="defaultLocale">The default locale for descriptions.</param> public RangeFacetAttribute(String name, IEnumerable <IFacet> facets, Dictionary <string, string> descriptions, string defaultLocale) : base(name, facets, descriptions, defaultLocale) { int count = 0; foreach (IFacet f in facets) { _ordinals[f.Key] = count++; } _rc = new RangeComparer(_ordinals); }
///<summary>Enumerates the tree nodes whose aggregate from left to right is within the given range.</summary> public IEnumerable <Tuple <TKey, TVal, TAggregate> > Range(RangeComparer <Tuple <TKey, TVal, TAggregate> > range = null) { if (_root.IsNilLeaf) { yield break; } range = range ?? (e => 0); // recursive enumeration rewritten to use an explicit stack // (to avoid iterator methods using yield must do work for each recursive level for each item, due to how they are implemented) var callStack = new Stack <Tuple <LeafwardNode, bool, TAggregate> >(); callStack.Push(Tuple.Create(_root, true, default(TAggregate))); while (callStack.Count > 0) { var item = callStack.Pop(); var node = item.Item1; var exploreVsYield = item.Item2; var leftOverhead = item.Item3; if (node.IsNilLeaf) { continue; } var leftOverheadForRightChild = _aggregator(leftOverhead, node.Data.Key, node.Data.Val, node.Left.Aggregate); var cur = Tuple.Create(node.Data.Key, node.Data.Val, leftOverheadForRightChild); if (exploreVsYield) { var c = range(cur); // schedule recurse right when current node is below range maximum if (c <= 0) { callStack.Push(Tuple.Create(node.Right, true, leftOverheadForRightChild)); } // schedule yield self when current node is in range if (c == 0) { callStack.Push(Tuple.Create(node, false, leftOverhead)); } // schedule recurse left when current node is below range minimum if (c >= 0) { callStack.Push(Tuple.Create(node.Left, true, leftOverhead)); } } else { yield return(cur); } } }
private IEnumerable <int> IndexOfOverlap(SelectionRangeWithItems rangeWithItems) { if (rangeWithItems.IsEmpty) { yield break; } var targetRange = rangeWithItems.Range; var comparer = new RangeComparer(targetRange); var index = this.FindIndex(comparer); if (index < 0) { yield break; } while (index > 0) { if (comparer.Compare(m_sortedRanges[index - 1]) != 0) { break; } index--; } for (int i = index; i < m_sortedRanges.Count; i++) { var wrapper = m_sortedRanges[i]; if (comparer.Compare(wrapper) != 0) { break; } var currentRangeWithItems = wrapper.Value; var overlap = targetRange.Intersect(currentRangeWithItems.Range); if (!overlap.IsEmpty && (rangeWithItems.IsItemsEqual(overlap, currentRangeWithItems))) { yield return(wrapper.Index); } } }
public int Compare(SelectionRangeWithItemsWrapper item) { if (item == m_target) { return(0); } var xr = m_target.Value.Range; var yr = item.Value.Range; int xs, xe, ys, ye; ItemComparer.GetBounds(xr, out xs, out xe); ItemComparer.GetBounds(yr, out ys, out ye); if (xs < ys) { Debug.Assert(RangeComparer.Compare(xr, item) <= 0); return(-1); } else if (xs > ys) { Debug.Assert(RangeComparer.Compare(xr, item) >= 0); return(1); } Debug.Assert(RangeComparer.Compare(xr, item) == 0); if (xe < ye) { return(-1); } else if (xe > ye) { return(1); } Debug.Assert(xr == yr); return(m_target.Index - item.Index); }
public int Compare(SelectionRangeWithItemsWrapper item) { return(RangeComparer.Compare(m_target, item)); }
public void OffsetIndex(int startIndex, int offset) { if (m_sortedRanges.Count == 0) { return; } // Used to offset index after an add or remove from the data source of the grid. var offsetRange = new SelectionRange(startIndex, startIndex + System.Math.Abs(offset) - 1); var comparer = new RangeComparer(offsetRange); // Find the first range that is greater or that overlaps the target range. var index = this.FindIndex(comparer); if (index < 0) { index = ~index; } else { while (index > 0) { if (comparer.Compare(m_sortedRanges[index - 1]) != 0) { break; } index--; } } var matches = m_sortedRanges.Skip(index).OrderByDescending(item => item.Index).ToList(); // Adjust the range of all ranges greater or that overlaps the target range. foreach (var currentRangeWithItemsWrapper in matches) { Debug.Assert(comparer.Compare(currentRangeWithItemsWrapper) <= 0); var currentRangeIndex = currentRangeWithItemsWrapper.Index; var currentRangeWithItems = currentRangeWithItemsWrapper.Value; var currentRange = currentRangeWithItems.Range; var currentRangeItems = currentRangeWithItems.Items; Debug.Assert(!(offsetRange > currentRange)); var currentRangeIntersection = currentRange.Intersect(offsetRange); // The range overlaps. if (!currentRangeIntersection.IsEmpty) { // Should only happen when adding since when we remove data from the source, we remove the // the range from the list. Debug.Assert(offset > 0); SelectionRange topRange; SelectionRange bottomRange; if (currentRange.StartIndex > currentRange.EndIndex) { if (currentRangeIntersection.EndIndex == currentRange.EndIndex) { this[currentRangeIndex] = new SelectionRangeWithItems( new SelectionRange(currentRange.StartIndex + offset, currentRange.EndIndex + offset), currentRangeItems); continue; } else { topRange = new SelectionRange(currentRange.StartIndex + offset, startIndex + offset); bottomRange = new SelectionRange(startIndex - 1, currentRange.EndIndex); } } else { if (currentRangeIntersection.StartIndex == currentRange.StartIndex) { this[currentRangeIndex] = new SelectionRangeWithItems( new SelectionRange(currentRange.StartIndex + offset, currentRange.EndIndex + offset), currentRangeItems); continue; } else { topRange = new SelectionRange(currentRange.StartIndex, startIndex - 1); bottomRange = new SelectionRange(startIndex + offset, currentRange.EndIndex + offset); } } object[] topItems = null; object[] bottomItems = null; if (currentRangeItems != null) { topItems = new object[topRange.Length]; Array.Copy(currentRangeItems, 0, topItems, 0, topItems.Length); bottomItems = new object[bottomRange.Length]; Array.Copy(currentRangeItems, topItems.Length, bottomItems, 0, bottomItems.Length); } this[currentRangeIndex] = new SelectionRangeWithItems(topRange, topItems); this.Insert(currentRangeIndex + 1, new SelectionRangeWithItems(bottomRange, bottomItems), true); } // The range is greater. else { this[currentRangeIndex] = new SelectionRangeWithItems( new SelectionRange(currentRange.StartIndex + offset, currentRange.EndIndex + offset), currentRangeItems); } } }