///
/// Copyright © 2003-2008 JetBrains s.r.o.
/// You may distribute under the terms of the GNU General Public License, as published by the Free Software Foundation, version 2 (see License.txt in the repository root folder).
///
using System;
using System.Collections;
namespace JetBrains.JetListViewLibrary
{
internal abstract class NodeEnumeratorBase: IVisibleNodeEnumerator
{
protected JetListViewNode _curNode;
protected int _curChildIndex = -1;
private int _minLevel = -1;
private bool _skipCollapsed;
private bool _skipFiltered;
protected NodeEnumeratorBase( bool skipCollapsed, int minLevel )
{
_skipCollapsed = skipCollapsed;
_skipFiltered = true;
_minLevel = minLevel;
}
protected abstract bool MoveNextStep();
public bool MoveNext()
{
while( true )
{
if ( !MoveNextStep() )
return false;
if ( !_skipFiltered )
return true;
JetListViewNode curNode = (JetListViewNode) Current;
if ( _minLevel != -1 && curNode.Level < _minLevel )
return false;
if ( curNode.FiltersAccept )
return true;
}
}
public void Reset()
{
throw new NotImplementedException();
}
public object Current
{
get { return _curNode [_curChildIndex]; }
}
public IViewNode CurrentNode
{
get { return (IViewNode) Current; }
}
protected bool NeedProcessChildren( JetListViewNode node )
{
if ( _skipFiltered && !node.FiltersAccept )
{
return false;
}
if ( _skipCollapsed && node.CollapseState != CollapseState.Expanded )
{
return false;
}
node.RequestChildren( RequestChildrenReason.Enumerate );
return node.ChildCount > 0;
}
}
///
/// Enumerator of visible items in a JetListViewNodeCollection.
///
internal class NodeEnumerator: NodeEnumeratorBase
{
private int _startChildIndex;
public NodeEnumerator( JetListViewNode startNode )
: base( true, -1 )
{
_curNode = startNode;
_startChildIndex = -1;
}
public NodeEnumerator( JetListViewNode startNode, int minLevel )
: base( true, minLevel )
{
_curNode = startNode;
_startChildIndex = -1;
}
public NodeEnumerator( JetListViewNode startNode, int startChildIndex, bool skipCollapsed )
: base( skipCollapsed, -1 )
{
_curNode = startNode;
_startChildIndex = startChildIndex;
}
protected override bool MoveNextStep()
{
if ( _startChildIndex >= 0 )
{
_curChildIndex = _startChildIndex;
_startChildIndex = -1;
return true;
}
if ( _curChildIndex >= 0 && NeedProcessChildren( _curNode [_curChildIndex] ) )
{
_curNode = _curNode [_curChildIndex];
_curChildIndex = -1;
}
_curChildIndex++;
while( _curChildIndex == _curNode.ChildCount )
{
if ( _curNode.Parent == null )
{
// backtrack to keep enumerator positioned on the last item
_curChildIndex--;
return false;
}
_curChildIndex = _curNode.Parent.IndexOf( _curNode ) + 1;
_curNode = _curNode.Parent;
}
return true;
}
}
///
/// Enumerator of visible items in reverse order in a JetListViewNodeCollection.
///
internal class ReverseNodeEnumerator: NodeEnumeratorBase, IEnumerator
{
private int _startChildIndex;
public ReverseNodeEnumerator( JetListViewNode startNode, int startChildIndex, bool skipCollapsed )
: base( skipCollapsed, -1 )
{
_curNode = startNode;
_startChildIndex = startChildIndex;
}
protected override bool MoveNextStep()
{
if ( _startChildIndex >= 0 )
{
_curChildIndex = _startChildIndex;
_startChildIndex = -1;
return true;
}
if ( _curChildIndex == 0 )
{
if ( _curNode.Parent == null )
return false;
int index = _curNode.Parent.IndexOf( _curNode );
if ( index < 0 )
return false;
SetCurNode( _curNode.Parent, index );
}
else
{
_curChildIndex--;
while( NeedProcessChildren( _curNode [_curChildIndex] ) )
{
SetCurNode( _curNode [_curChildIndex], _curNode [_curChildIndex].ChildCount-1 );
}
}
return true;
}
private void SetCurNode( JetListViewNode node, int curIndex )
{
_curNode = node;
_curChildIndex = curIndex;
}
}
}