/* * Copyright 2019 faddenSoft * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Windows.Controls; using CommonUtil; namespace SourceGen { /// /// Tracks the items selected in the DisplayList, using forwarded SelectionChanged events. /// When enumerated, provides an ordered list of selected indices. /// /// /// In WPF you can't get indices, only items, so we have to store the item index in the /// item itself. /// public class DisplayListSelection : IEnumerable { private BitArray mSelection; /// /// Retrieves the total number of boolean values in the set. This is NOT the /// number of selected items. /// public int Length { get { return mSelection.Length; } } /// /// Retrieves the number of values that are set. /// public int Count { get; private set; } /// /// Sets or gets the Nth element. True means the line is selected. /// public bool this[int key] { get { return mSelection[key]; } set { // If an entry has changed, update the count of set items. if (mSelection[key] != value) { Count += value ? 1 : -1; mSelection[key] = value; } Debug.Assert(Count >= 0 && Count <= Length); } } /// /// Constructs an empty list. /// public DisplayListSelection() { mSelection = new BitArray(0); } /// /// Constructs a list of the specified length. /// /// Number of elements. public DisplayListSelection(int length) { mSelection = new BitArray(length); } /// /// Returns an enumeration of selected indices, in ascending order. /// public IEnumerator GetEnumerator() { for (int i = 0; i < mSelection.Length; i++) { if (mSelection[i]) { yield return i; } } } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } /// /// Sets the length of the selection array. /// /// If the new length is longer, the new elements are initialized to false. If the /// new length is shorter, the excess elements are discarded. /// /// New length. //public void SetLength(int length) { // mSelection.Length = length; //} /// /// Handles selection change. /// /// Argument from SelectionChanged event. public void SelectionChanged(SelectionChangedEventArgs e) { //Debug.WriteLine("SelectionChanged event: Add=" + e.AddedItems.Count + // " Rem=" + e.RemovedItems.Count); foreach (DisplayList.FormattedParts parts in e.AddedItems) { Debug.Assert(parts.ListIndex >= 0 && parts.ListIndex < mSelection.Length); this[parts.ListIndex] = true; } foreach (DisplayList.FormattedParts parts in e.RemovedItems) { Debug.Assert(parts.ListIndex >= 0); if (parts.ListIndex < mSelection.Length) { this[parts.ListIndex] = false; } else { Debug.WriteLine("Attempted to remove selected item off end of list: " + parts); } } } /// /// Returns the index of the first selected item, or -1 if nothing is selected. /// public int GetFirstSelectedIndex() { int idx; for (idx = 0; idx < mSelection.Length; idx++) { if (mSelection[idx]) { break; } } if (idx == mSelection.Length) { idx = -1; } return idx; } /// /// Returns the index of the last selected item, or -1 if nothing is selected. /// public int GetLastSelectedIndex() { int idx; for (idx = mSelection.Length - 1; idx >= 0; idx--) { if (mSelection[idx]) { break; } } return idx; } /// /// Returns true if all items are selected. /// public bool IsAllSelected() { return Count == Length; } /// /// Confirms that the selection count matches the number of set bits. Pass /// in {ListView}.SelectedIndices.Count. /// /// Expected number of selected entries. /// True if count matches. public bool DebugValidateSelectionCount(int expected) { if (Count != expected) { Debug.WriteLine("SelectionCount expected " + expected + ", count=" + Count); } int computed = 0; foreach (bool bit in mSelection) { if (bit) { computed++; } } if (Count != computed) { Debug.WriteLine("SelectionCount internal error: computed=" + computed + ", count=" + Count); } return (Count == expected); } public void DebugDump() { RangeSet rangeSet = new RangeSet(); for (int i = 0; i < mSelection.Length; i++) { if (mSelection[i]) { rangeSet.Add(i); } } Debug.WriteLine("DisplayListSelection ranges:"); IEnumerator iter = rangeSet.RangeListIterator; while (iter.MoveNext()) { RangeSet.Range range = iter.Current; Debug.WriteLine(" [" + range.Low.ToString() + "," + range.High.ToString() + "]"); } } } }