Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Propagate the isExpanded value for all children in the hierarchy #275

Closed
wants to merge 10 commits into from
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,11 @@ public void Dispose()
GC.SuppressFinalize(this);
}

public void Expand(IndexPath index) => GetOrCreateRows().Expand(index);
public void Collapse(IndexPath index) => GetOrCreateRows().Collapse(index);
public void CollapseAll() => GetOrCreateRows().CollapseAll();
public void Expand(IndexPath index) => GetOrCreateRows().Expand(index);
public void ExpandAll() => GetOrCreateRows().ExpandRecursive(null);
public void ExpandRecursive(Func<TModel, bool> filter) => GetOrCreateRows().ExpandRecursive(filter);

public bool TryGetModelAt(IndexPath index, [NotNullWhen(true)] out TModel? result)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,15 @@ public HierarchicalRow(
Model = model;
}

/// <summary>
/// Gets the row's child rows.
/// </summary>
public IReadOnlyList<HierarchicalRow<TModel>>? AllChildRows => _childRows;

/// <summary>
/// Gets the row's visible child rows.
/// </summary>
public IReadOnlyList<HierarchicalRow<TModel>>? Children => _isExpanded ? _childRows : null;
public IReadOnlyList<HierarchicalRow<TModel>>? VisibleChildren => _isExpanded ? _childRows : null;

/// <summary>
/// Gets the index of the model relative to its parent.
Expand Down Expand Up @@ -137,17 +142,8 @@ internal void SortChildren(Comparison<TModel>? comparison)
}
}

private void Expand()
internal void CreateChildRows()
{
if (!_expanderColumn.HasChildren(Model))
{
_expanderColumn.SetModelIsExpanded(this);
return;
}

_controller.OnBeginExpandCollapse(this);

var oldExpanded = _isExpanded;
var childModels = _expanderColumn.GetChildModels(Model);

if (_childModels != childModels)
Expand All @@ -159,6 +155,21 @@ private void Expand()
TreeDataGridItemsSourceView<TModel>.GetOrCreate(childModels),
_comparison);
}
}

private void Expand()
{
if (!_expanderColumn.HasChildren(Model))
{
_expanderColumn.SetModelIsExpanded(this);
return;
}

_controller.OnBeginExpandCollapse(this);

var oldExpanded = _isExpanded;

CreateChildRows();

if (_childRows?.Count > 0)
_isExpanded = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public class HierarchicalRows<TModel> : ReadOnlyListBase<HierarchicalRow<TModel>
private readonly IExpanderColumn<TModel> _expanderColumn;
private readonly List<HierarchicalRow<TModel>> _flattenedRows;
private Comparison<TModel>? _comparison;
private bool _ignoreCollectionChanges;

public HierarchicalRows(
IExpanderRowController<TModel> controller,
Expand All @@ -25,11 +26,11 @@ public HierarchicalRows(
Comparison<TModel>? comparison)
{
_controller = controller;
_flattenedRows = new List<HierarchicalRow<TModel>>();
_roots = new RootRows(this, items, comparison);
_roots.CollectionChanged += OnRootsCollectionChanged;
_expanderColumn = expanderColumn;
_comparison = comparison;
_flattenedRows = new List<HierarchicalRow<TModel>>();
InitializeRows();
}

Expand All @@ -39,6 +40,7 @@ public HierarchicalRows(

public void Dispose()
{
_ignoreCollectionChanges = true;
_roots.Dispose();
GC.SuppressFinalize(this);
}
Expand All @@ -61,7 +63,7 @@ public void Expand(IndexPath index)
if (row.ModelIndex == modelIndex)
{
row.IsExpanded = true;
rows = row.Children;
rows = row.VisibleChildren;
found = true;
break;
}
Expand All @@ -72,6 +74,39 @@ public void Expand(IndexPath index)
}
}

internal void ExpandRecursive(Func<TModel, bool>? filter)
{
static void Expand(IReadOnlyList<HierarchicalRow<TModel>> rows, Func<TModel, bool>? filter)
{
for (int i = 0; i < rows.Count; i++)
{
var row = rows[i];

if (filter is null || filter(row.Model))
{
row.IsExpanded = true;
if (row.VisibleChildren is { } children)
Expand(children, filter);
}
else
{
row.CreateChildRows();
if (row.AllChildRows is { } children)
Expand(children, filter);
}
}
}

_ignoreCollectionChanges = true;

try { Expand(_roots, filter); }
finally { _ignoreCollectionChanges = false; }

_flattenedRows.Clear();
InitializeRows();
CollectionChanged?.Invoke(this, CollectionExtensions.ResetEvent);
}

public void Collapse(IndexPath index)
{
var count = index.Count;
Expand All @@ -91,7 +126,7 @@ public void Collapse(IndexPath index)
{
if (i == count - 1)
row.IsExpanded = false;
rows = row.Children;
rows = row.VisibleChildren;
found = true;
break;
}
Expand All @@ -102,6 +137,31 @@ public void Collapse(IndexPath index)
}
}

internal void CollapseAll()
{
static void Collapse(IReadOnlyList<HierarchicalRow<TModel>> rows)
{
for (var i = 0; i < rows.Count; ++i)
{
var row = rows[i];

if (row.VisibleChildren is { } children)
Collapse(children);

row.IsExpanded = false;
}
}

_ignoreCollectionChanges = true;

try { Collapse(_roots); }
finally { _ignoreCollectionChanges = false; }

_flattenedRows.Clear();
InitializeRows();
CollectionChanged?.Invoke(this, CollectionExtensions.ResetEvent);
}

public (int index, double y) GetRowAt(double y)
{
if (MathUtilities.IsZero(y))
Expand All @@ -119,7 +179,14 @@ public ICell RealizeCell(IColumn column, int columnIndex, int rowIndex)

public void SetItems(TreeDataGridItemsSourceView<TModel> items)
{
_roots.SetItems(items);
_ignoreCollectionChanges = true;

try {_roots.SetItems(items); }
finally { _ignoreCollectionChanges = false; }

_flattenedRows.Clear();
InitializeRows();
CollectionChanged?.Invoke(this, CollectionExtensions.ResetEvent);
}

public void Sort(Comparison<TModel>? comparison)
Expand Down Expand Up @@ -186,6 +253,9 @@ void IExpanderRowController<TModel>.OnChildCollectionChanged(
IExpanderRow<TModel> row,
NotifyCollectionChangedEventArgs e)
{
if (_ignoreCollectionChanges)
return;

if (row is HierarchicalRow<TModel> h)
OnCollectionChanged(h.ModelIndexPath, e);
else
Expand Down Expand Up @@ -228,9 +298,9 @@ private int AddRowsAndDescendants(int index, HierarchicalRow<TModel> row)
var i = index;
_flattenedRows.Insert(i++, row);

if (row.Children is object)
if (row.VisibleChildren is object)
{
foreach (var childRow in row.Children)
foreach (var childRow in row.VisibleChildren)
{
i += AddRowsAndDescendants(i, childRow);
}
Expand All @@ -241,6 +311,9 @@ private int AddRowsAndDescendants(int index, HierarchicalRow<TModel> row)

private void OnCollectionChanged(in IndexPath parentIndex, NotifyCollectionChangedEventArgs e)
{
if (_ignoreCollectionChanges)
return;

void Add(int index, IEnumerable? items, bool raise)
{
if (items is null)
Expand Down Expand Up @@ -299,8 +372,8 @@ int Advance(int rowIndex, int count)
while (count > 0)
{
var row = _flattenedRows[i];
if (row.Children?.Count > 0)
i = Advance(i + 1, row.Children.Count);
if (row.VisibleChildren?.Count > 0)
i = Advance(i + 1, row.VisibleChildren.Count);
else
i += + 1;
--count;
Expand Down Expand Up @@ -363,7 +436,7 @@ int GetDescendentRowCount(int rowIndex)
case NotifyCollectionChangedAction.Reset:
if (TryGetRowIndex(parentIndex, out parentRowIndex))
{
var children = parentRowIndex >= 0 ? _flattenedRows[parentRowIndex].Children : _roots;
var children = parentRowIndex >= 0 ? _flattenedRows[parentRowIndex].VisibleChildren : _roots;
var count = GetDescendentRowCount(parentRowIndex);
Remove(parentRowIndex + 1, count, true);
Add(parentRowIndex + 1, children, true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ public override TRow this[int index]
{
get
{
GetOrCreateRows();

if (_sortedIndexes is null)
return UnsortedRows[index];
else
Expand Down
Loading
Loading