Iteration Mechanisms

yFiles uses the concept of a bidirectional cursor to iterate over the elements of a container or sequence. A cursor is an object that points to a current element which can be accessed. The cursor location can be moved to the first or last location and can be moved one step to the previous or next location. Additionally a method is provided to check whether or not the cursor points to a valid location or is "out of range". Hence a forward and backward iteration over all accessible elements can be performed.

Additionally a cursor provides the number of elements that it can access.

An element cannot be removed from an underlying container by a mere cursor reference. The underlying container itself must always be accessibe to remove an element from it. Therefore a cursor can be considered as a read-only view of an underlying container. See Iteration and Element Removal for more details.

The YCursor interface and it's typed sub-interfaces NodeCursor and EdgeCursor are provided to iterate over objects, nodes and edges in a uniform fashion.


Cursor Hierarchy

Depicted below are the most prominent yFiles classes that provide cursors to iterate over object, node or edge sequences. These classes are YList, NodeList, EdgeList, GraphInterface, Graph and Node.


Classes that provide cursors

Sample Code

In the examples below list always denotes an object of type YList and graph an object of type Graph.

Forward Iteration

	for( YCursor c = list.cursor(); c.ok(); c.next() )
	{
	  Object obj = c.current();
        }
    

	for( NodeCursor nc = graph.nodes(); nc.ok(); nc.next() )
	{
	  Node n = nc.node();
        }
    

	for( EdgeCursor ec = graph.edges(); ec.ok(); ec.next() )
	{
	  Edge e = ec.edge();
        }
    

Backward Iteration

        YCursor c = list.cursor();
	for( c.toLast(); c.ok(); c.prev() )
	{
	  Object obj = c.current();
        }
    

Iteration & Element Removal

The YCursor interface does not provide a method to remove an element from an underlying container. Elements must be removed from the container directly. How to remove an element does therefore depend on the interface of the underlying container.

A Cursor does not change state if an element currently pointed at by the cursor gets removed from the underlying container. That means that immediatelly after the element was removed from a container the cursor still points to the same, now removed, element. The cursor methods next() and prev() still have the same effect as if the element was in the container. But once a cursor was moved away from a removed element location, there is no way to return to that location afterwards. Hence, a call sequence of the kind cursor.next();cursor.prev() does not necessarily leave the cursor at an unchanged location.

	for( YCursor c = list.cursor(); c.ok(); c.next() )
	{
          if( isUnwanted( c.current() ) )
          {
             list.removeAt( c );
          }
        }
    

	for( NodeCursor c = graph.nodes(); nc.ok(); nc.next() )
	{
          if( isUnwanted( nc.node() ) )
          {
             graph.removeNode( nc.node() );
          }
        }