Commit cb2ad9ec authored by Olivier Teulière's avatar Olivier Teulière

* skins2 (tree playlist):

     - Fixed a selection bug in CtrlTree
     - Simplified some algorithms using helper methods
     - A few coding style fixes
parent 4ab6e7c7
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#define SCROLL_STEP 0.05 #define SCROLL_STEP 0.05
#define LINE_INTERVAL 1 // Number of pixels inserted between 2 lines #define LINE_INTERVAL 1 // Number of pixels inserted between 2 lines
CtrlTree::CtrlTree( intf_thread_t *pIntf, CtrlTree::CtrlTree( intf_thread_t *pIntf,
VarTree &rTree, VarTree &rTree,
const GenericFont &rFont, const GenericFont &rFont,
...@@ -151,7 +152,7 @@ void CtrlTree::onUpdate( Subject<VarPercent> &rPercent ) ...@@ -151,7 +152,7 @@ void CtrlTree::onUpdate( Subject<VarPercent> &rPercent )
#ifdef _MSC_VER #ifdef _MSC_VER
# define lrint (int) # define lrint (int)
#endif #endif
it = m_rTree.visibleItem(lrint( (1.0 - rVarPos.get()) * (double)excessItems ) + 1); it = m_rTree.getVisibleItem(lrint( (1.0 - rVarPos.get()) * (double)excessItems ) + 1);
} }
if( m_lastPos != it ) if( m_lastPos != it )
{ {
...@@ -180,7 +181,7 @@ void CtrlTree::onResize() ...@@ -180,7 +181,7 @@ void CtrlTree::onResize()
#ifdef _MSC_VER #ifdef _MSC_VER
# define lrint (int) # define lrint (int)
#endif #endif
it = m_rTree.visibleItem(lrint( (1.0 - rVarPos.get()) * (double)excessItems ) + 1); it = m_rTree.getVisibleItem(lrint( (1.0 - rVarPos.get()) * (double)excessItems ) + 1);
} }
// Redraw the control if the position has changed // Redraw the control if the position has changed
m_lastPos = it; m_lastPos = it;
...@@ -206,7 +207,7 @@ void CtrlTree::onResize() ...@@ -206,7 +207,7 @@ void CtrlTree::onResize()
// We cannot keep the current first item // We cannot keep the current first item
m_lastPos = excessItems; m_lastPos = excessItems;
}*/ }*/
it = m_rTree.visibleItem( excessItems ); it = m_rTree.getVisibleItem( excessItems );
} }
makeImage(); makeImage();
notifyLayout(); notifyLayout();
...@@ -219,20 +220,6 @@ void CtrlTree::onPositionChange() ...@@ -219,20 +220,6 @@ void CtrlTree::onPositionChange()
notifyLayout(); notifyLayout();
} }
#define IT_DISP_LOOP_END( a ) \
if( a ->m_expanded && a ->size() ) \
{ \
a = a ->begin(); \
} \
else \
{ \
VarTree::Iterator it_old = a; \
a ++; \
if( it_old->parent() && it_old->parent()->end() == a ) \
{ \
a = it_old->uncle(); \
} \
}
void CtrlTree::handleEvent( EvtGeneric &rEvent ) void CtrlTree::handleEvent( EvtGeneric &rEvent )
{ {
if( rEvent.getAsString().find( "key:down" ) != string::npos ) if( rEvent.getAsString().find( "key:down" ) != string::npos )
...@@ -240,13 +227,13 @@ void CtrlTree::handleEvent( EvtGeneric &rEvent ) ...@@ -240,13 +227,13 @@ void CtrlTree::handleEvent( EvtGeneric &rEvent )
int key = ((EvtKey&)rEvent).getKey(); int key = ((EvtKey&)rEvent).getKey();
VarTree::Iterator it; VarTree::Iterator it;
bool previousWasSelected = false; bool previousWasSelected = false;
for( it = m_rTree.begin(); it != m_rTree.end(); ) for( it = m_rTree.begin(); it != m_rTree.end();
it = m_rTree.getNextVisibleItem( it ) )
{ {
VarTree::Iterator next = it; VarTree::Iterator next = m_rTree.getNextVisibleItem( it );
IT_DISP_LOOP_END( next );
if( key == KEY_UP ) if( key == KEY_UP )
{ {
//Scroll up one item // Scroll up one item
if( ( it->parent() if( ( it->parent()
&& it != it->parent()->begin() ) && it != it->parent()->begin() )
|| &*it != m_pLastSelected ) || &*it != m_pLastSelected )
...@@ -330,7 +317,6 @@ void CtrlTree::handleEvent( EvtGeneric &rEvent ) ...@@ -330,7 +317,6 @@ void CtrlTree::handleEvent( EvtGeneric &rEvent )
m_rTree.action( &*it ); m_rTree.action( &*it );
} }
} }
it = next;
} }
// Redraw the control // Redraw the control
...@@ -345,19 +331,18 @@ void CtrlTree::handleEvent( EvtGeneric &rEvent ) ...@@ -345,19 +331,18 @@ void CtrlTree::handleEvent( EvtGeneric &rEvent )
int yPos = ( rEvtMouse.getYPos() - pos->getTop() ) / itemHeight(); int yPos = ( rEvtMouse.getYPos() - pos->getTop() ) / itemHeight();
int xPos = rEvtMouse.getXPos() - pos->getLeft(); int xPos = rEvtMouse.getXPos() - pos->getLeft();
VarTree::Iterator it; VarTree::Iterator it;
int index = 0;
if( rEvent.getAsString().find( "mouse:left:down:ctrl,shift" ) != if( rEvent.getAsString().find( "mouse:left:down:ctrl,shift" ) !=
string::npos ) string::npos )
{ {
// Flag to know if the currend item must be selected VarTree::Iterator itClicked = findItemAtPos( yPos );
// Flag to know if the current item must be selected
bool select = false; bool select = false;
index = -1; for( it = m_rTree.begin(); it != m_rTree.end();
for( it = m_rTree.begin(); it != m_rTree.end(); ) it = m_rTree.getNextVisibleItem( it ) )
{ {
bool nextSelect = select; bool nextSelect = select;
if( it == m_lastPos ) index = 0; if( it == itClicked || &*it == m_pLastSelected )
if( index == yPos || &*it == m_pLastSelected )
{ {
if( select ) if( select )
{ {
...@@ -371,37 +356,30 @@ void CtrlTree::handleEvent( EvtGeneric &rEvent ) ...@@ -371,37 +356,30 @@ void CtrlTree::handleEvent( EvtGeneric &rEvent )
} }
it->m_selected = (*it).m_selected || select; it->m_selected = (*it).m_selected || select;
select = nextSelect; select = nextSelect;
if( index != -1 )
index++;
IT_DISP_LOOP_END( it );
} }
} }
else if( rEvent.getAsString().find( "mouse:left:down:ctrl" ) != else if( rEvent.getAsString().find( "mouse:left:down:ctrl" ) !=
string::npos ) string::npos )
{ {
for( it = m_lastPos; it != m_rTree.end(); ) // Invert the selection of the item
{ it = findItemAtPos( yPos );
if( index == yPos ) if( it != m_rTree.end() )
{ {
it->m_selected = !it->m_selected; it->m_selected = !it->m_selected;
m_pLastSelected = &*it; m_pLastSelected = &*it;
break;
}
index++;
IT_DISP_LOOP_END( it );
} }
} }
else if( rEvent.getAsString().find( "mouse:left:down:shift" ) != else if( rEvent.getAsString().find( "mouse:left:down:shift" ) !=
string::npos ) string::npos )
{ {
// Flag to know if the currend item must be selected VarTree::Iterator itClicked = findItemAtPos( yPos );
// Flag to know if the current item must be selected
bool select = false; bool select = false;
index = -1; for( it = m_rTree.begin(); it != m_rTree.end();
for( it = m_rTree.begin(); it != m_rTree.end(); ) it = m_rTree.getNextVisibleItem( it ) )
{ {
bool nextSelect = select; bool nextSelect = select;
if( it == m_lastPos ) index = 0; if( it == itClicked || &*it == m_pLastSelected )
if( index == yPos || &*it == m_pLastSelected )
{ {
if( select ) if( select )
{ {
...@@ -415,36 +393,31 @@ void CtrlTree::handleEvent( EvtGeneric &rEvent ) ...@@ -415,36 +393,31 @@ void CtrlTree::handleEvent( EvtGeneric &rEvent )
} }
it->m_selected = select; it->m_selected = select;
select = nextSelect; select = nextSelect;
if( index != -1 )
index++;
IT_DISP_LOOP_END( it );
} }
} }
else if( rEvent.getAsString().find( "mouse:left:down" ) != else if( rEvent.getAsString().find( "mouse:left:down" ) !=
string::npos ) string::npos )
{ {
for( it = m_lastPos; it != m_rTree.end(); ) // Unselect any previously selected item
for( it = m_rTree.begin(); it != m_rTree.end();
it = m_rTree.getNextVisibleItem( it ) )
{ {
if( index == yPos ) it->m_selected = false;
}
// Select the new item
it = findItemAtPos(yPos);
if( it != m_rTree.end() )
{ {
it->m_selected = true; it->m_selected = true;
m_pLastSelected = &*it; m_pLastSelected = &*it;
} }
else
{
it->m_selected = false;
}
index ++;
IT_DISP_LOOP_END( it );
}
} }
else if( rEvent.getAsString().find( "mouse:left:dblclick" ) != else if( rEvent.getAsString().find( "mouse:left:dblclick" ) !=
string::npos ) string::npos )
{ {
for( it = m_lastPos; it != m_rTree.end(); ) it = findItemAtPos(yPos);
{ if( it != m_rTree.end() )
if( index == yPos )
{ {
if( it->size() && xPos < it->depth() * itemImageWidth() ) if( it->size() && xPos < it->depth() * itemImageWidth() )
{ {
...@@ -452,19 +425,10 @@ void CtrlTree::handleEvent( EvtGeneric &rEvent ) ...@@ -452,19 +425,10 @@ void CtrlTree::handleEvent( EvtGeneric &rEvent )
} }
else else
{ {
it->m_selected = true;
m_pLastSelected = &*it;
// Execute the action associated to this item // Execute the action associated to this item
m_rTree.action( &*it ); m_rTree.action( &*it );
} }
} }
else
{
it->m_selected = false;
}
index ++;
IT_DISP_LOOP_END( it );
}
} }
// Redraw the control // Redraw the control
...@@ -511,22 +475,22 @@ void CtrlTree::autoScroll() ...@@ -511,22 +475,22 @@ void CtrlTree::autoScroll()
// Find the current playing stream // Find the current playing stream
int playIndex = 0; int playIndex = 0;
VarTree::Iterator it; VarTree::Iterator it;
for( it = m_rTree.begin(); it != m_rTree.end(); ) for( it = m_rTree.begin(); it != m_rTree.end();
it = m_rTree.getNextVisibleItem( it ) )
{ {
if( it->m_playing ) break; if( it->m_playing ) break;
playIndex++; playIndex++;
IT_DISP_LOOP_END( it );
} }
if( it == m_rTree.end() ) return; if( it == m_rTree.end() ) return;
// Find m_lastPos // Find m_lastPos
int lastPosIndex = 0; int lastPosIndex = 0;
for( it = m_rTree.begin(); it != m_rTree.end(); ) for( it = m_rTree.begin(); it != m_rTree.end();
it = m_rTree.getNextVisibleItem( it ) )
{ {
if( it == m_lastPos ) break; if( it == m_lastPos ) break;
lastPosIndex++; lastPosIndex++;
IT_DISP_LOOP_END( it );
} }
if( it == m_rTree.end() ) return; if( it == m_rTree.end() ) return;
...@@ -579,15 +543,15 @@ void CtrlTree::makeImage() ...@@ -579,15 +543,15 @@ void CtrlTree::makeImage()
for( int yPos = 0; yPos < height; yPos += i_itemHeight ) for( int yPos = 0; yPos < height; yPos += i_itemHeight )
{ {
int rectHeight = __MIN( i_itemHeight, height - yPos );
if( it != m_rTree.end() ) if( it != m_rTree.end() )
{ {
if( (*it).m_selected ) if( (*it).m_selected )
{ {
int rectHeight = __MIN( i_itemHeight, height - yPos );
m_pImage->fillRect( 0, yPos, width, rectHeight, m_pImage->fillRect( 0, yPos, width, rectHeight,
m_selColor ); m_selColor );
} }
IT_DISP_LOOP_END( it ); it = m_rTree.getNextVisibleItem( it );
} }
} }
} }
...@@ -604,7 +568,7 @@ void CtrlTree::makeImage() ...@@ -604,7 +568,7 @@ void CtrlTree::makeImage()
{ {
uint32_t color = ( it->m_selected ? m_selColor : bgColor ); uint32_t color = ( it->m_selected ? m_selColor : bgColor );
m_pImage->fillRect( 0, yPos, width, rectHeight, color ); m_pImage->fillRect( 0, yPos, width, rectHeight, color );
IT_DISP_LOOP_END( it ); it = m_rTree.getNextVisibleItem( it );
} }
else else
{ {
...@@ -625,18 +589,27 @@ void CtrlTree::makeImage() ...@@ -625,18 +589,27 @@ void CtrlTree::makeImage()
UString *pStr = (UString*)(it->m_cString.get()); UString *pStr = (UString*)(it->m_cString.get());
uint32_t color = ( it->m_playing ? m_playColor : m_fgColor ); uint32_t color = ( it->m_playing ? m_playColor : m_fgColor );
// Draw the text // Draw the text
if( pStr != NULL ){ if( pStr != NULL )
{
int depth = it->depth(); int depth = it->depth();
GenericBitmap *pText = m_rFont.drawString( *pStr, color, width - bitmapWidth * depth ); GenericBitmap *pText = m_rFont.drawString( *pStr, color, width - bitmapWidth * depth );
if( !pText ) if( !pText )
{ {
return; return;
} }
m_pCurBitmap = it->size() ? ( it->m_expanded ? m_pOpenBitmap : m_pClosedBitmap ) : m_pItemBitmap ; if( it->size() )
m_pCurBitmap = it->m_expanded ? m_pOpenBitmap : m_pClosedBitmap;
else
m_pCurBitmap = m_pItemBitmap;
if( m_pCurBitmap ) if( m_pCurBitmap )
{ {
int yPos2 = yPos+(i_itemHeight-m_pCurBitmap->getHeight()+1)/2; int yPos2 = yPos+(i_itemHeight-m_pCurBitmap->getHeight()+1)/2;
m_pImage->drawBitmap( *m_pCurBitmap, 0, 0, bitmapWidth * (depth - 1 ), yPos2, m_pCurBitmap->getWidth(), __MIN( m_pCurBitmap->getHeight(), height - yPos2), true ); m_pImage->drawBitmap( *m_pCurBitmap, 0, 0,
bitmapWidth * (depth - 1 ), yPos2,
m_pCurBitmap->getWidth(),
__MIN( m_pCurBitmap->getHeight(),
height - yPos2), true );
} }
else else
{ {
...@@ -656,6 +629,21 @@ void CtrlTree::makeImage() ...@@ -656,6 +629,21 @@ void CtrlTree::makeImage()
yPos += (pText->getHeight() - ySrc ); yPos += (pText->getHeight() - ySrc );
delete pText; delete pText;
} }
IT_DISP_LOOP_END( it ); it = m_rTree.getNextVisibleItem( it );
} }
} }
VarTree::Iterator CtrlTree::findItemAtPos( int pos )
{
// The first item is m_lastPos.
// We decrement pos as we try the other items, until pos == 0.
VarTree::Iterator it;
for( it = m_lastPos; it != m_rTree.end() && pos != 0;
it = m_rTree.getNextVisibleItem( it ) )
{
pos--;
}
return it;
}
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* ctrl_tree.hpp * ctrl_tree.hpp
***************************************************************************** *****************************************************************************
* Copyright (C) 2003 VideoLAN * Copyright (C) 2003 VideoLAN
* $Id: ctrl_list.hpp 11009 2005-05-14 14:39:05Z ipkiss $ * $Id$
* *
* Authors: Antoine Cellerier * Authors: Antoine Cellerier
* *
...@@ -124,6 +124,13 @@ class CtrlTree: public CtrlGeneric, public Observer<VarTree>, ...@@ -124,6 +124,13 @@ class CtrlTree: public CtrlGeneric, public Observer<VarTree>,
/// Draw the image of the control /// Draw the image of the control
void makeImage(); void makeImage();
/// Return the n'th displayed item (starting at position 0)
/**
* Return m_rTree.end() if such an item cannot be found (n < 0, or
* n too big)
*/
VarTree::Iterator findItemAtPos( int n );
}; };
#endif #endif
...@@ -23,16 +23,17 @@ ...@@ -23,16 +23,17 @@
#include "var_tree.hpp" #include "var_tree.hpp"
const string VarTree::m_type = "tree"; const string VarTree::m_type = "tree";
VarTree::VarTree( intf_thread_t *pIntf, VarTree *m_pParent2 ) VarTree::VarTree( intf_thread_t *pIntf, VarTree *pParent )
:Variable( pIntf ) : Variable( pIntf )
{ {
m_selected = false; m_selected = false;
m_playing = false; m_playing = false;
m_expanded = true; m_expanded = true;
m_pData = NULL; m_pData = NULL;
m_pParent = m_pParent2; m_pParent = pParent;
// Create the position variable // Create the position variable
m_cPosition = VariablePtr( new VarPercent( pIntf ) ); m_cPosition = VariablePtr( new VarPercent( pIntf ) );
...@@ -44,7 +45,11 @@ VarTree::~VarTree() ...@@ -44,7 +45,11 @@ VarTree::~VarTree()
// TODO : check that children are deleted // TODO : check that children are deleted
} }
void VarTree::add( const UStringPtr &rcString, bool selected, bool playing, bool expanded, void *pData ) void VarTree::add( const UStringPtr &rcString,
bool selected,
bool playing,
bool expanded,
void *pData )
{ {
m_children.push_back( VarTree( getIntf(), this ) ); m_children.push_back( VarTree( getIntf(), this ) );
back().m_cString = rcString; back().m_cString = rcString;
...@@ -107,7 +112,6 @@ VarTree::ConstIterator VarTree::operator[]( int n ) const ...@@ -107,7 +112,6 @@ VarTree::ConstIterator VarTree::operator[]( int n ) const
* ... which means parent++ or grandparent++ or grandgrandparent++ ... */ * ... which means parent++ or grandparent++ or grandgrandparent++ ... */
VarTree::Iterator VarTree::uncle() VarTree::Iterator VarTree::uncle()
{ {
// fprintf( stderr, "trying to find uncle\n");
VarTree *p_parent = parent(); VarTree *p_parent = parent();
if( p_parent != NULL ) if( p_parent != NULL )
{ {
...@@ -115,7 +119,7 @@ VarTree::Iterator VarTree::uncle() ...@@ -115,7 +119,7 @@ VarTree::Iterator VarTree::uncle()
while( p_grandparent != NULL ) while( p_grandparent != NULL )
{ {
Iterator it = p_grandparent->begin(); Iterator it = p_grandparent->begin();
while( !(it == p_grandparent->end()) && &(*it) != p_parent ) it++; while( it != p_grandparent->end() && &(*it) != p_parent ) it++;
if( it != p_grandparent->end() ) if( it != p_grandparent->end() )
{ {
it++; it++;
...@@ -138,11 +142,11 @@ VarTree::Iterator VarTree::uncle() ...@@ -138,11 +142,11 @@ VarTree::Iterator VarTree::uncle()
return root()->end(); return root()->end();
} }
void VarTree::checkParents( VarTree *m_pParent2 ) void VarTree::checkParents( VarTree *pParent )
{ {
m_pParent = m_pParent2; m_pParent = pParent;
Iterator it = begin(); Iterator it = begin();
while( it!=end() ) while( it != end() )
{ {
it->checkParents( this ); it->checkParents( this );
it++; it++;
...@@ -164,7 +168,7 @@ int VarTree::visibleItems() ...@@ -164,7 +168,7 @@ int VarTree::visibleItems()
return i_count; return i_count;
} }
VarTree::Iterator VarTree::visibleItem( int n ) VarTree::Iterator VarTree::getVisibleItem( int n )
{ {
Iterator it = begin(); Iterator it = begin();
while( it != end() ) while( it != end() )
...@@ -174,10 +178,30 @@ VarTree::Iterator VarTree::visibleItem( int n ) ...@@ -174,10 +178,30 @@ VarTree::Iterator VarTree::visibleItem( int n )
if( it->m_expanded ) if( it->m_expanded )
{ {
int i = n - it->visibleItems(); int i = n - it->visibleItems();
if( i <= 0 ) return it->visibleItem( n ); if( i <= 0 ) return it->getVisibleItem( n );
n = i; n = i;
} }
it++; it++;
} }
return end(); return end();
} }
VarTree::Iterator VarTree::getNextVisibleItem( Iterator it )
{
if( it->m_expanded && it->size() )
{
it = it->begin();
}
else
{
VarTree::Iterator it_old = it;
it++;
// Was 'it' the last brother? If so, look for uncles
if( it_old->parent() && it_old->parent()->end() == it )
{
it = it_old->uncle();
}
}
return it;
}
...@@ -35,14 +35,18 @@ ...@@ -35,14 +35,18 @@
class VarTree: public Variable, public Subject<VarTree> class VarTree: public Variable, public Subject<VarTree>
{ {
public: public:
VarTree( intf_thread_t *pIntf, VarTree *m_pParent2 ); VarTree( intf_thread_t *pIntf, VarTree *pParent );
virtual ~VarTree(); virtual ~VarTree();
/// Get the variable type /// Get the variable type
virtual const string &getType() const { return m_type; } virtual const string &getType() const { return m_type; }
/// Add a pointer on string in the children's list /// Add a pointer on string in the children's list
virtual void add( const UStringPtr &rcString, bool selected=true, bool playing=true, bool expanded=true, void *pData=NULL ); virtual void add( const UStringPtr &rcString,
bool selected = true,
bool playing = true,
bool expanded = true,
void *pData = NULL );
/// Remove the selected item from the children's list /// Remove the selected item from the children's list
virtual void delSelected(); virtual void delSelected();
...@@ -80,15 +84,28 @@ class VarTree: public Variable, public Subject<VarTree> ...@@ -80,15 +84,28 @@ class VarTree: public Variable, public Subject<VarTree>
/// Parent node /// Parent node
VarTree *parent() { return m_pParent; } VarTree *parent() { return m_pParent; }
void VarTree::checkParents( VarTree *m_pParent2 ); void VarTree::checkParents( VarTree *pParent );
Iterator uncle(); Iterator uncle();
/// Get root node /// Get root node
VarTree *root() { VarTree *parent=this; while( parent->parent() != NULL ) parent = parent->parent(); return parent; } VarTree *root()
{
VarTree *parent = this;
while( parent->parent() != NULL )
parent = parent->parent();
return parent;
}
/// Get depth (root depth is 0) /// Get depth (root depth is 0)
int depth() { VarTree *parent=this; int depth=0; while( ( parent = parent->parent() ) != NULL ) depth++; return depth; } int depth()
{
VarTree *parent = this;
int depth = 0;
while( ( parent = parent->parent() ) != NULL )
depth++;
return depth;
}
/// Execute the action associated to this item /// Execute the action associated to this item
virtual void action( VarTree *pItem ) {} virtual void action( VarTree *pItem ) {}
...@@ -104,18 +121,21 @@ class VarTree: public Variable, public Subject<VarTree> ...@@ -104,18 +121,21 @@ class VarTree: public Variable, public Subject<VarTree>
int visibleItems(); int visibleItems();
/// Return iterator to the n'th visible item /// Return iterator to the n'th visible item
Iterator visibleItem( int n ); Iterator getVisibleItem( int n );
/// Given an iterator to a visible item, return the next visible item
Iterator getNextVisibleItem( Iterator it );
private: private:
// intf_thread_t *pIntf; // intf_thread_t *pIntf;
///list of children /// List of children
list<VarTree> m_children; list<VarTree> m_children;
///Pointer to parent node /// Pointer to parent node
VarTree *m_pParent; VarTree *m_pParent;
///Variable type /// Variable type
static const string m_type; static const string m_type;
/// Position variable /// Position variable
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment