X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fgui%2Fskins2%2Fcontrols%2Fctrl_tree.cpp;h=0c27d34d6312fde6cac0a071c2191558aef67df3;hb=54e69dcc62db81fc16c1174761e06699b1e4c2c7;hp=3b48965fd5051b74897250dc672921014655751c;hpb=6adad42ae834d30560526e316e1083b5b7081a6c;p=vlc diff --git a/modules/gui/skins2/controls/ctrl_tree.cpp b/modules/gui/skins2/controls/ctrl_tree.cpp index 3b48965fd5..0c27d34d63 100644 --- a/modules/gui/skins2/controls/ctrl_tree.cpp +++ b/modules/gui/skins2/controls/ctrl_tree.cpp @@ -1,10 +1,11 @@ /***************************************************************************** * ctrl_tree.cpp ***************************************************************************** - * Copyright (C) 2003 VideoLAN + * Copyright (C) 2003 the VideoLAN team * $Id$ * * Authors: Antoine Cellerier + * Clément Stenac * * 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 @@ -22,6 +23,7 @@ *****************************************************************************/ #include +#include "../utils/var_bool.hpp" #include "ctrl_tree.hpp" #include "../src/os_factory.hpp" #include "../src/os_graphics.hpp" @@ -55,19 +57,22 @@ CtrlTree::CtrlTree( intf_thread_t *pIntf, uint32_t bgColor2, uint32_t selColor, const UString &rHelp, - VarBool *pVisible ): + VarBool *pVisible, + VarBool *pFlat ): CtrlGeneric( pIntf,rHelp, pVisible), m_rTree( rTree), m_rFont( rFont ), m_pBgBitmap( pBgBitmap ), m_pItemBitmap( pItemBitmap ), m_pOpenBitmap( pOpenBitmap ), m_pClosedBitmap( pClosedBitmap ), m_fgColor( fgColor ), m_playColor( playColor ), m_bgColor1( bgColor1 ), m_bgColor2( bgColor2 ), m_selColor( selColor ), - m_pLastSelected( NULL ), m_pImage( NULL ) + m_pLastSelected( NULL ), m_pImage( NULL ), m_dontMove( false ) { // Observe the tree and position variables m_rTree.addObserver( this ); m_rTree.getPositionVar().addObserver( this ); - m_firstPos = m_rTree.begin(); + m_flat = pFlat->get(); + + m_firstPos = m_flat ? m_rTree.firstLeaf() : m_rTree.begin(); makeImage(); } @@ -85,13 +90,16 @@ CtrlTree::~CtrlTree() int CtrlTree::itemHeight() { int itemHeight = m_rFont.getSize(); - if( m_pClosedBitmap ) - { - itemHeight = __MAX( m_pClosedBitmap->getHeight(), itemHeight ); - } - if( m_pOpenBitmap ) + if( !m_flat ) { - itemHeight = __MAX( m_pOpenBitmap->getHeight(), itemHeight ); + if( m_pClosedBitmap ) + { + itemHeight = __MAX( m_pClosedBitmap->getHeight(), itemHeight ); + } + if( m_pOpenBitmap ) + { + itemHeight = __MAX( m_pOpenBitmap->getHeight(), itemHeight ); + } } if( m_pItemBitmap ) { @@ -104,13 +112,16 @@ int CtrlTree::itemHeight() int CtrlTree::itemImageWidth() { int bitmapWidth = 5; - if( m_pClosedBitmap ) + if( !m_flat ) { - bitmapWidth = __MAX( m_pClosedBitmap->getWidth(), bitmapWidth ); - } - if( m_pOpenBitmap ) - { - bitmapWidth = __MAX( m_pOpenBitmap->getWidth(), bitmapWidth ); + if( m_pClosedBitmap ) + { + bitmapWidth = __MAX( m_pClosedBitmap->getWidth(), bitmapWidth ); + } + if( m_pOpenBitmap ) + { + bitmapWidth = __MAX( m_pOpenBitmap->getWidth(), bitmapWidth ); + } } if( m_pItemBitmap ) { @@ -130,24 +141,47 @@ int CtrlTree::maxItems() } -void CtrlTree::onUpdate( Subject &rTree, +void CtrlTree::onUpdate( Subject &rTree, tree_update *arg ) { if( arg->i_type == 0 ) // Item update { - if( arg->b_active_item && arg->b_visible ) + if( arg->b_active_item ) + { autoScroll(); - makeImage(); + ///\todo We should make image if we are visible in the view + makeImage(); + } } /// \todo handle delete in a more clever way else if ( arg->i_type == 1 ) // Global change or deletion { - m_firstPos = m_rTree.begin(); + m_firstPos = m_flat ? m_rTree.firstLeaf() : m_rTree.begin(); makeImage(); } else if ( arg->i_type == 2 ) // Item-append { - /// \todo Check if the item is really visible in the view (we only check if it in the document) + if( m_flat && m_firstPos->size() ) + m_firstPos = m_rTree.getNextLeaf( m_firstPos ); + /// \todo Check if the item is really visible in the view + // (we only check if it in the document) + if( arg->b_visible == true ) + { + makeImage(); + } + } + else if( arg->i_type == 3 ) // item-del + { + /* Make sure firstPos and lastSelected are still valid */ + while( m_firstPos->m_deleted && m_firstPos != m_rTree.root()->begin() ) + { + m_firstPos = m_flat ? m_rTree.getPrevLeaf( m_firstPos ) + : m_rTree.getPrevVisibleItem( m_firstPos ); + } + if( m_firstPos->m_deleted ) + m_firstPos = m_flat ? m_rTree.firstLeaf() + : m_rTree.root()->begin(); + if( arg->b_visible == true ) { makeImage(); @@ -156,12 +190,18 @@ void CtrlTree::onUpdate( Subject &rTree, notifyLayout(); } -void CtrlTree::onUpdate( Subject &rPercent, void* arg) +void CtrlTree::onUpdate( Subject &rPercent, void* arg) { // Determine what is the first item to display - VarTree::Iterator it = m_rTree.begin(); + VarTree::Iterator it = m_flat ? m_rTree.firstLeaf() : m_rTree.begin(); - int excessItems = m_rTree.visibleItems() - maxItems(); + if( m_dontMove ) return; + + int excessItems; + if( m_flat ) + excessItems = m_rTree.countLeafs() - maxItems(); + else + excessItems = m_rTree.visibleItems() - maxItems(); if( excessItems > 0) { @@ -170,7 +210,10 @@ void CtrlTree::onUpdate( Subject &rPercent, void* arg) #ifdef _MSC_VER # define lrint (int) #endif - it = m_rTree.getVisibleItem(lrint( (1.0 - rVarPos.get()) * (double)excessItems ) + 1); + if( m_flat ) + it = m_rTree.getLeaf(lrint( (1.0 - rVarPos.get()) * (double)excessItems ) + 1 ); + else + it = m_rTree.getVisibleItem(lrint( (1.0 - rVarPos.get()) * (double)excessItems ) + 1 ); } if( m_firstPos != it ) { @@ -184,9 +227,13 @@ void CtrlTree::onUpdate( Subject &rPercent, void* arg) void CtrlTree::onResize() { // Determine what is the first item to display - VarTree::Iterator it = m_rTree.begin(); + VarTree::Iterator it = m_flat ? m_rTree.firstLeaf() : m_rTree.begin(); - int excessItems = m_rTree.visibleItems() - maxItems(); + int excessItems; + if( m_flat ) + excessItems = m_rTree.countLeafs() - maxItems(); + else + excessItems = m_rTree.visibleItems() - maxItems(); if( excessItems > 0) { @@ -195,7 +242,10 @@ void CtrlTree::onResize() #ifdef _MSC_VER # define lrint (int) #endif - it = m_rTree.getVisibleItem(lrint( (1.0 - rVarPos.get()) * (double)excessItems ) + 1); + if( m_flat ) + it = m_rTree.getLeaf(lrint( (1.0 - rVarPos.get()) * (double)excessItems ) + 1 ); + else + it = m_rTree.getVisibleItem(lrint( (1.0 - rVarPos.get()) * (double)excessItems ) + 1 ); } // Redraw the control if the position has changed m_firstPos = it; @@ -211,6 +261,7 @@ void CtrlTree::onPositionChange() void CtrlTree::handleEvent( EvtGeneric &rEvent ) { + bool bChangedPosition = false; VarTree::Iterator toShow; bool needShow = false; if( rEvent.getAsString().find( "key:down" ) != string::npos ) { @@ -221,16 +272,34 @@ void CtrlTree::handleEvent( EvtGeneric &rEvent ) /* Delete the selection */ if( key == KEY_DELETE ) { + /* Find first non selected item before m_pLastSelected */ + VarTree::Iterator it_sel = m_flat ? m_rTree.firstLeaf() + : m_rTree.begin(); + for( it = m_flat ? m_rTree.firstLeaf() : m_rTree.begin(); + it != m_rTree.end(); + it = m_flat ? m_rTree.getNextLeaf( it ) + : m_rTree.getNextVisibleItem( it ) ) + { + if( &*it == m_pLastSelected ) break; + if( !it->m_selected ) it_sel = it; + } + + /* Delete selected stuff */ m_rTree.delSelected(); + + /* Select it_sel */ + it_sel->m_selected = true; + m_pLastSelected = &*it_sel; } else if( key == KEY_PAGEDOWN ) { it = m_firstPos; - int i = maxItems()*1.5; + int i = (int)(maxItems()*1.5); while( i >= 0 ) { VarTree::Iterator it_old = it; - it = m_rTree.getNextVisibleItem( it ); + it = m_flat ? m_rTree.getNextLeaf( it ) + : m_rTree.getNextVisibleItem( it ); /* End is already visible, dont' scroll */ if( it == m_rTree.end() ) { @@ -254,9 +323,10 @@ void CtrlTree::handleEvent( EvtGeneric &rEvent ) int i = maxItems(); while( i >= maxItems()/2 ) { - it = m_rTree.getPrevVisibleItem( it ); + it = m_flat ? m_rTree.getPrevLeaf( it ) + : m_rTree.getPrevVisibleItem( it ); /* End is already visible, dont' scroll */ - if( it == m_rTree.begin() ) + if( it == ( m_flat ? m_rTree.firstLeaf() : m_rTree.begin() ) ) { break; } @@ -269,10 +339,13 @@ void CtrlTree::handleEvent( EvtGeneric &rEvent ) } - for( it = m_rTree.begin(); it != m_rTree.end(); - it = m_rTree.getNextVisibleItem( it ) ) + for( it = m_flat ? m_rTree.firstLeaf() : m_rTree.begin(); + it != m_rTree.end(); + it = m_flat ? m_rTree.getNextLeaf( it ) + : m_rTree.getNextVisibleItem( it ) ) { - VarTree::Iterator next = m_rTree.getNextVisibleItem( it ); + VarTree::Iterator next = m_flat ? m_rTree.getNextLeaf( it ) + : m_rTree.getNextVisibleItem( it ); if( key == KEY_UP ) { // Scroll up one item @@ -308,6 +381,14 @@ void CtrlTree::handleEvent( EvtGeneric &rEvent ) { previousWasSelected = ( &*it == m_pLastSelected ); } + + // Fix last tree item selection + if( ( m_flat ? m_rTree.getNextLeaf( it ) + : m_rTree.getNextVisibleItem( it ) ) == m_rTree.end() + && &*it == m_pLastSelected ) + { + (*it).m_selected = true; + } } else if( key == KEY_RIGHT ) { @@ -330,6 +411,7 @@ void CtrlTree::handleEvent( EvtGeneric &rEvent ) else { it->m_expanded = true; + bChangedPosition = true; } } } @@ -341,6 +423,7 @@ void CtrlTree::handleEvent( EvtGeneric &rEvent ) if( it->m_expanded && it->size() ) { it->m_expanded = false; + bChangedPosition = true; } else { @@ -384,8 +467,10 @@ void CtrlTree::handleEvent( EvtGeneric &rEvent ) VarTree::Iterator itClicked = findItemAtPos( yPos ); // Flag to know if the current item must be selected bool select = false; - for( it = m_rTree.begin(); it != m_rTree.end(); - it = m_rTree.getNextVisibleItem( it ) ) + for( it = m_flat ? m_rTree.firstLeaf() : m_rTree.begin(); + it != m_rTree.end(); + it = m_flat ? m_rTree.getNextLeaf( it ) + : m_rTree.getNextVisibleItem( it ) ) { bool nextSelect = select; if( it == itClicked || &*it == m_pLastSelected ) @@ -421,8 +506,10 @@ void CtrlTree::handleEvent( EvtGeneric &rEvent ) VarTree::Iterator itClicked = findItemAtPos( yPos ); // Flag to know if the current item must be selected bool select = false; - for( it = m_rTree.begin(); it != m_rTree.end(); - it = m_rTree.getNextVisibleItem( it ) ) + for( it = m_flat ? m_rTree.firstLeaf() : m_rTree.begin(); + it != m_rTree.end(); + it = m_flat ? m_rTree.getNextLeaf( it ) + : m_rTree.getNextVisibleItem( it ) ) { bool nextSelect = select; if( it == itClicked || &*it == m_pLastSelected ) @@ -445,26 +532,33 @@ void CtrlTree::handleEvent( EvtGeneric &rEvent ) string::npos ) { it = findItemAtPos(yPos); - if( it->size() && xPos > (it->depth() - 1) * itemImageWidth() - && xPos < it->depth() * itemImageWidth() ) - { - // Fold/unfold the item - it->m_expanded = !it->m_expanded; - } - else + if( it != m_rTree.end() ) { - // Unselect any previously selected item - VarTree::Iterator it2; - for( it2 = m_rTree.begin(); it2 != m_rTree.end(); - it2 = m_rTree.getNextVisibleItem( it2 ) ) + if( ( it->size() && xPos > (it->depth() - 1) * itemImageWidth() + && xPos < it->depth() * itemImageWidth() ) + && !m_flat ) { - it2->m_selected = false; + // Fold/unfold the item + it->m_expanded = !it->m_expanded; + bChangedPosition = true; } - // Select the new item - if( it != m_rTree.end() ) + else { - it->m_selected = true; - m_pLastSelected = &*it; + // Unselect any previously selected item + VarTree::Iterator it2; + for( it2 = m_flat ? m_rTree.firstLeaf() : m_rTree.begin(); + it2 != m_rTree.end(); + it2 = m_flat ? m_rTree.getNextLeaf( it2 ) + : m_rTree.getNextVisibleItem( it2 ) ) + { + it2->m_selected = false; + } + // Select the new item + if( it != m_rTree.end() ) + { + it->m_selected = true; + m_pLastSelected = &*it; + } } } } @@ -489,7 +583,8 @@ void CtrlTree::handleEvent( EvtGeneric &rEvent ) int direction = ((EvtScroll&)rEvent).getDirection(); double percentage = m_rTree.getPositionVar().get(); - double step = 2.0 / (double)m_rTree.visibleItems(); + double step = 2.0 / (double)( m_flat ? m_rTree.countLeafs() + : m_rTree.visibleItems() ); if( direction == EvtScroll::kUp ) { percentage += step; @@ -500,6 +595,34 @@ void CtrlTree::handleEvent( EvtGeneric &rEvent ) } m_rTree.getPositionVar().set( percentage ); } + + /* We changed the nodes, let's fix teh position var */ + if( bChangedPosition ) + { + VarTree::Iterator it; + int i = 0; + int iFirst = 0; + for( it = m_flat ? m_rTree.firstLeaf() : m_rTree.begin(); + it != m_rTree.end(); + it = m_flat ? m_rTree.getNextLeaf( it ) + : m_rTree.getNextVisibleItem( it ) ) + { + i++; + if( it == m_firstPos ) + { + iFirst = i; + break; + } + } + iFirst += maxItems(); + if( iFirst >= m_flat ? m_rTree.countLeafs() : m_rTree.visibleItems() ) + iFirst = m_flat ? m_rTree.countLeafs() : m_rTree.visibleItems(); + float f_new = (float)iFirst / (float)( m_flat ? m_rTree.countLeafs() + :m_rTree.visibleItems() ); + m_dontMove = true; + m_rTree.getPositionVar().set( 1.0 - f_new ); + m_dontMove = false; + } } bool CtrlTree::mouseOver( int x, int y ) const @@ -526,8 +649,10 @@ bool CtrlTree::ensureVisible( VarTree::Iterator item ) m_rTree.ensureExpanded( item ); - for( it = m_rTree.begin(); it != m_rTree.end(); - it = m_rTree.getNextVisibleItem( it ) ) + for( it = m_flat ? m_rTree.firstLeaf() : m_rTree.begin(); + it != m_rTree.end(); + it = m_flat ? m_rTree.getNextLeaf( it ) + : m_rTree.getNextVisibleItem( it ) ) { if( it->m_id == item->m_id ) break; focusItemIndex++; @@ -540,8 +665,10 @@ bool CtrlTree::ensureVisible( int focusItemIndex ) // Find m_firstPos VarTree::Iterator it; int firstPosIndex = 0; - for( it = m_rTree.begin(); it != m_rTree.end(); - it = m_rTree.getNextVisibleItem( it ) ) + for( it = m_flat ? m_rTree.firstLeaf() : m_rTree.begin(); + it != m_rTree.end(); + it = m_flat ? m_rTree.getNextLeaf( it ) + : m_rTree.getNextVisibleItem( it ) ) { if( it == m_firstPos ) break; firstPosIndex++; @@ -557,7 +684,8 @@ bool CtrlTree::ensureVisible( int focusItemIndex ) // Scroll to have the wanted stream visible VarPercent &rVarPos = m_rTree.getPositionVar(); rVarPos.set( 1.0 - (double)focusItemIndex / - (double)m_rTree.visibleItems() ); + (double)( m_flat ? m_rTree.countLeafs() + : m_rTree.visibleItems() ) ); return true; } return false; @@ -569,8 +697,10 @@ void CtrlTree::autoScroll() int playIndex = 0; VarTree::Iterator it; - for( it = m_rTree.begin(); it != m_rTree.end(); - it = m_rTree.getNextItem( it ) ) + for( it = m_flat ? m_rTree.firstLeaf() : m_rTree.begin(); + it != m_rTree.end(); + it = m_flat ? m_rTree.getNextLeaf( it ) + : m_rTree.getNextItem( it ) ) { if( it->m_playing ) { @@ -578,8 +708,10 @@ void CtrlTree::autoScroll() break; } } - for( it = m_rTree.begin(); it != m_rTree.end(); - it = m_rTree.getNextVisibleItem( it ) ) + for( it = m_flat ? m_rTree.firstLeaf() : m_rTree.begin(); + it != m_rTree.end(); + it = m_flat ? m_rTree.getNextLeaf( it ) + : m_rTree.getNextVisibleItem( it ) ) { if( it->m_playing ) break; @@ -595,6 +727,8 @@ void CtrlTree::autoScroll() void CtrlTree::makeImage() { + stats_TimerStart( getIntf(), "[Skins] Playlist image", + STATS_TIMER_SKINS_PLAYTREE_IMAGE ); if( m_pImage ) { delete m_pImage; @@ -604,6 +738,7 @@ void CtrlTree::makeImage() const Position *pPos = getPosition(); if( !pPos ) { + stats_TimerStop( getIntf(), STATS_TIMER_SKINS_PLAYTREE_IMAGE ); return; } int width = pPos->getWidth(); @@ -633,7 +768,11 @@ void CtrlTree::makeImage() m_pImage->fillRect( 0, yPos, width, rectHeight, m_selColor ); } - it = m_rTree.getNextVisibleItem( it ); + do + { + it = m_flat ? m_rTree.getNextLeaf( it ) + : m_rTree.getNextVisibleItem( it ); + } while( it != m_rTree.end() && it->m_deleted ); } } } @@ -650,7 +789,11 @@ void CtrlTree::makeImage() { uint32_t color = ( it->m_selected ? m_selColor : bgColor ); m_pImage->fillRect( 0, yPos, width, rectHeight, color ); - it = m_rTree.getNextVisibleItem( it ); + do + { + it = m_flat ? m_rTree.getNextLeaf( it ) + : m_rTree.getNextVisibleItem( it ); + } while( it != m_rTree.end() && it->m_deleted ); } else { @@ -673,10 +816,11 @@ void CtrlTree::makeImage() // Draw the text if( pStr != NULL ) { - int depth = it->depth(); + int depth = m_flat ? 1 : it->depth(); GenericBitmap *pText = m_rFont.drawString( *pStr, color, width - bitmapWidth * depth ); if( !pText ) { + stats_TimerStop( getIntf(), STATS_TIMER_SKINS_PLAYTREE_IMAGE ); return; } if( it->size() ) @@ -713,9 +857,13 @@ void CtrlTree::makeImage() yPos += (pText->getHeight() - ySrc ); delete pText; } - it = m_rTree.getNextVisibleItem( it ); + do + { + it = m_flat ? m_rTree.getNextLeaf( it ) + : m_rTree.getNextVisibleItem( it ); + } while( it != m_rTree.end() && it->m_deleted ); } - /// \todo Reposition percentage var to accomodate if it's not suitable anymore (if we expanded a node) + stats_TimerStop( getIntf(), STATS_TIMER_SKINS_PLAYTREE_IMAGE ); } VarTree::Iterator CtrlTree::findItemAtPos( int pos ) @@ -724,7 +872,8 @@ VarTree::Iterator CtrlTree::findItemAtPos( int pos ) // We decrement pos as we try the other items, until pos == 0. VarTree::Iterator it; for( it = m_firstPos; it != m_rTree.end() && pos != 0; - it = m_rTree.getNextVisibleItem( it ) ) + it = m_flat ? m_rTree.getNextLeaf( it ) + : m_rTree.getNextVisibleItem( it ) ) { pos--; }