/*****************************************************************************
* var_tree.cpp
*****************************************************************************
- * Copyright (C) 2005 VideoLAN
+ * Copyright (C) 2005 the VideoLAN team
* $Id$
*
* Authors: Antoine Cellerier <dionoea@videolan.org>
+ * Clément Stenac <zorglub@videolan.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
VarTree::VarTree( intf_thread_t *pIntf )
: Variable( pIntf ), m_id( 0 ), m_selected( false ), m_playing( false ),
- m_expanded( false ), m_pData( NULL ), m_pParent( NULL )
+ m_expanded( false ), m_deleted( false ),
+ m_pData( NULL ), m_pParent( NULL ), m_readonly( false )
{
// Create the position variable
m_cPosition = VariablePtr( new VarPercent( pIntf ) );
VarTree::VarTree( intf_thread_t *pIntf, VarTree *pParent, int id,
const UStringPtr &rcString, bool selected, bool playing,
- bool expanded, void *pData )
+ bool expanded, bool readonly,
+ void *pData )
: Variable( pIntf ), m_id( id ), m_cString( rcString ),
m_selected( selected ), m_playing( playing ), m_expanded( expanded ),
- m_pData( pData ), m_pParent( pParent )
+ m_deleted( false ), m_pData( pData ), m_pParent( pParent ),
+ m_readonly( readonly )
{
// Create the position variable
m_cPosition = VariablePtr( new VarPercent( pIntf ) );
}
void VarTree::add( int id, const UStringPtr &rcString, bool selected,
- bool playing, bool expanded, void *pData )
+ bool playing, bool expanded, bool readonly,
+ void *pData )
{
m_children.push_back( VarTree( getIntf(), this, id, rcString, selected,
- playing, expanded, pData ) );
+ playing, expanded, readonly,
+ pData ) );
}
void VarTree::delSelected()
return it;
}
+VarTree::Iterator VarTree::getNextSiblingOrUncle()
+{
+ VarTree *p_parent = parent();
+ if( p_parent )
+ {
+ Iterator it = p_parent->begin();
+ while( it != p_parent->end() && &(*it) != this ) ++it;
+ if( it != p_parent->end() )
+ {
+ Iterator current = it;
+ ++it;
+ if( it != p_parent->end() )
+ return it;
+ else
+ return current->next_uncle();
+ }
+ else
+ {
+ msg_Err( getIntf(), "should never occur" );
+ return end();
+ }
+ }
+ return end();
+}
+
/* find iterator to next ancestor
* ... which means parent++ or grandparent++ or grandgrandparent++ ... */
-VarTree::Iterator VarTree::uncle()
+VarTree::Iterator VarTree::next_uncle()
{
VarTree *p_parent = parent();
if( p_parent != NULL )
return root()->end();
}
-void VarTree::checkParents( VarTree *pParent )
+VarTree::Iterator VarTree::prev_uncle()
{
- m_pParent = pParent;
- Iterator it = begin();
- while( it != end() )
+ VarTree *p_parent = parent();
+ if( p_parent != NULL )
{
- it->checkParents( this );
- it++;
+ VarTree *p_grandparent = p_parent->parent();
+ while( p_grandparent != NULL )
+ {
+ Iterator it = p_grandparent->end();
+ while( it != p_grandparent->begin() && &(*it) != p_parent ) it--;
+ if( it != p_grandparent->begin() )
+ {
+ it--;
+ if( it != p_grandparent->begin() )
+ {
+ return it;
+ }
+ }
+ if( p_grandparent->parent() )
+ {
+ p_parent = p_grandparent;
+ p_grandparent = p_parent->parent();
+ }
+ else
+ p_grandparent = NULL;
+ }
}
+
+ /* if we didn't return before, it means that we've reached the end */
+ return root()->begin();
}
int VarTree::visibleItems()
while( it != end() )
{
n--;
- if( n <= 0 ) return it;
+ if( n <= 0 )
+ return it;
if( it->m_expanded )
{
- int i = n - it->visibleItems();
+ int i;
+ i = n - it->visibleItems();
if( i <= 0 ) return it->getVisibleItem( n );
n = i;
}
return end();
}
+VarTree::Iterator VarTree::getLeaf( int n )
+{
+ Iterator it = begin();
+ while( it != end() )
+ {
+ if( it->size() )
+ {
+ int i;
+ i = n - it->countLeafs();
+ if( i <= 0 ) return it->getLeaf( n );
+ n = i;
+ }
+ else
+ {
+ n--;
+ if( n <= 0 )
+ return it;
+ }
+ it++;
+ }
+ return end();
+}
+
VarTree::Iterator VarTree::getNextVisibleItem( Iterator it )
{
if( it->m_expanded && it->size() )
// Was 'it' the last brother? If so, look for uncles
if( it_old->parent() && it_old->parent()->end() == it )
{
- it = it_old->uncle();
+ it = it_old->next_uncle();
}
}
return it;
}
+VarTree::Iterator VarTree::getPrevVisibleItem( Iterator it )
+{
+ VarTree::Iterator it_old = it;
+ if( it == root()->begin() || it == ++(root()->begin()) ) return it;
+
+ /* Was it the first child of its parent ? */
+ if( it->parent() && it == it->parent()->begin() )
+ {
+ /* Yes, get previous uncle */
+ it = it_old->prev_uncle();
+ }
+ else
+ it--;
+
+ /* We have found an expanded uncle, take its last child */
+ while( it != root()->begin() && it->size() && it->m_expanded )
+ {
+ it = it->end();
+ it--;
+ }
+ return it;
+}
+
VarTree::Iterator VarTree::getNextItem( Iterator it )
{
if( it->size() )
// Was 'it' the last brother? If so, look for uncles
if( it_old->parent() && it_old->parent()->end() == it )
{
- it = it_old->uncle();
+ it = it_old->next_uncle();
}
}
return it;
}
+VarTree::Iterator VarTree::getPrevItem( Iterator it )
+{
+ VarTree::Iterator it_old = it;
+ if( it == root()->begin() || it == ++(root()->begin()) ) return it;
+
+ /* Was it the first child of its parent ? */
+ if( it->parent() && it == it->parent()->begin() )
+ {
+ /* Yes, get previous uncle */
+ it = it_old->prev_uncle();
+ }
+ else
+ it--;
+
+ /* We have found an expanded uncle, take its last child */
+ while( it != root()->begin() && it->size() )
+ {
+ it = it->end();
+ it--;
+ }
+ return it;
+}
+
+VarTree::Iterator VarTree::getNextLeaf( Iterator it )
+{
+ do
+ {
+ it = getNextItem( it );
+ }
+ while( it != root()->end() && it->size() );
+ return it;
+}
+
+VarTree::Iterator VarTree::getPrevLeaf( Iterator it )
+{
+ do
+ {
+ it = getPrevItem( it );
+ }
+ while( it != root()->begin() && it->size() ); /* FIXME ? */
+ if( it == root()->begin() ) it = firstLeaf();
+ return it;
+}
VarTree::Iterator VarTree::findById( int id )
{
current = current->parent();
}
}
+
+int VarTree::countLeafs()
+{
+ if( size() == 0 ) return 1;
+
+ int i_count = 0;
+ Iterator it = begin();
+ while( it != end() )
+ {
+ i_count += it->countLeafs();
+ it++;
+ }
+ return i_count;
+}
+
+VarTree::Iterator VarTree::firstLeaf()
+{
+ Iterator b = root()->begin();
+ if( b->size() ) return getNextLeaf( b );
+ return b;
+}
+
+void VarTree::cascadeDelete()
+{
+ m_deleted = true;
+ for( Iterator it = begin(); it != end(); ++it )
+ {
+ it->cascadeDelete();
+ }
+}