void CtrlTree::makeImage() { stats_TimerStart( getIntf(), "[Skins] Playlist image", STATS_TIMER_SKINS_PLAYTREE_IMAGE ); delete m_pImage; // Get the size of the control const Position *pPos = getPosition(); if( !pPos ) { stats_TimerStop( getIntf(), STATS_TIMER_SKINS_PLAYTREE_IMAGE ); return; } int width = pPos->getWidth(); int height = pPos->getHeight(); int i_itemHeight = itemHeight(); // Create an image OSFactory *pOsFactory = OSFactory::instance( getIntf() ); m_pImage = pOsFactory->createOSGraphics( width, height ); VarTree::Iterator it = m_firstPos; if( m_pBgBitmap ) { // Draw the background bitmap if( !m_pScaledBitmap || m_pScaledBitmap->getWidth() != width || m_pScaledBitmap->getHeight() != height ) { delete m_pScaledBitmap; m_pScaledBitmap = new ScaledBitmap( getIntf(), *m_pBgBitmap, width, height ); } m_pImage->drawBitmap( *m_pScaledBitmap, 0, 0 ); for( int yPos = 0; yPos < height; yPos += i_itemHeight ) { if( it != m_rTree.end() ) { if( it->isSelected() ) { int rectHeight = __MIN( i_itemHeight, height - yPos ); m_pImage->fillRect( 0, yPos, width, rectHeight, m_selColor ); } do { it = m_flat ? m_rTree.getNextLeaf( it ) : m_rTree.getNextVisibleItem( it ); } while( it != m_rTree.end() && it->isDeleted() ); } } } else { // FIXME (TRYME) // Fill background with background color uint32_t bgColor = m_bgColor1; m_pImage->fillRect( 0, 0, width, height, bgColor ); for( int yPos = 0; yPos < height; yPos += i_itemHeight ) { int rectHeight = __MIN( i_itemHeight, height - yPos ); if( it == m_rTree.end() ) m_pImage->fillRect( 0, yPos, width, rectHeight, bgColor ); else { uint32_t color = ( it->isSelected() ? m_selColor : bgColor ); m_pImage->fillRect( 0, yPos, width, rectHeight, color ); do { it = m_flat ? m_rTree.getNextLeaf( it ) : m_rTree.getNextVisibleItem( it ); } while( it != m_rTree.end() && it->isDeleted() ); } bgColor = ( bgColor == m_bgColor1 ? m_bgColor2 : m_bgColor1 ); } } int bitmapWidth = itemImageWidth(); int yPos = 0; it = m_firstPos; while( it != m_rTree.end() && yPos < height ) { const GenericBitmap *m_pCurBitmap; UString *pStr = it->getString(); uint32_t color = ( it->isPlaying() ? m_playColor : m_fgColor ); // Draw the text if( pStr != NULL ) { 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() ) m_pCurBitmap = it->isExpanded() ? m_pOpenBitmap : m_pClosedBitmap; else m_pCurBitmap = m_pItemBitmap; if( m_pCurBitmap ) { // Make sure we are centered on the line int yPos2 = yPos+(i_itemHeight-m_pCurBitmap->getHeight()+1)/2; if( yPos2 >= height ) { delete pText; break; } m_pImage->drawBitmap( *m_pCurBitmap, 0, 0, bitmapWidth * (depth - 1 ), yPos2, m_pCurBitmap->getWidth(), __MIN( m_pCurBitmap->getHeight(), height - yPos2), true ); } yPos += i_itemHeight - pText->getHeight(); int ySrc = 0; if( yPos < 0 ) { ySrc = - yPos; yPos = 0; } int lineHeight = __MIN( pText->getHeight() - ySrc, height - yPos ); m_pImage->drawBitmap( *pText, 0, ySrc, bitmapWidth * depth, yPos, pText->getWidth(), lineHeight, true ); yPos += (pText->getHeight() - ySrc ); delete pText; } do { it = m_flat ? m_rTree.getNextLeaf( it ) : m_rTree.getNextVisibleItem( it ); } while( it != m_rTree.end() && it->isDeleted() ); } stats_TimerStop( getIntf(), STATS_TIMER_SKINS_PLAYTREE_IMAGE ); }
void CtrlTree::handleEvent( EvtGeneric &rEvent ) { bool bChangedPosition = false; VarTree::Iterator toShow; bool needShow = false; if( rEvent.getAsString().find( "key:down" ) != string::npos ) { int key = ((EvtKey&)rEvent).getKey(); VarTree::Iterator it; bool previousWasSelected = false; /* 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->isSelected() ) it_sel = it; } /* Delete selected stuff */ m_rTree.delSelected(); /* Verify if there is still sthg selected (e.g read-only items) */ m_pLastSelected = NULL; 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->isSelected() ) m_pLastSelected = &*it; } /* if everything was deleted, use it_sel as last selection */ if( !m_pLastSelected ) { it_sel->setSelected( true ); m_pLastSelected = &*it_sel; } // Redraw the control makeImage(); notifyLayout(); } else if( key == KEY_PAGEDOWN ) { it = m_firstPos; int i = (int)(maxItems()*1.5); while( i >= 0 ) { VarTree::Iterator it_old = it; it = m_flat ? m_rTree.getNextLeaf( it ) : m_rTree.getNextVisibleItem( it ); /* End is already visible, dont' scroll */ if( it == m_rTree.end() ) { it = it_old; break; } needShow = true; i--; } if( needShow ) { ensureVisible( it ); makeImage(); notifyLayout(); } } else if (key == KEY_PAGEUP ) { it = m_firstPos; int i = maxItems(); while( i >= maxItems()/2 ) { it = m_flat ? m_rTree.getPrevLeaf( it ) : m_rTree.getPrevVisibleItem( it ); /* End is already visible, dont' scroll */ if( it == ( m_flat ? m_rTree.firstLeaf() : m_rTree.begin() ) ) { break; } i--; } ensureVisible( it ); makeImage(); notifyLayout(); } else if ( key == KEY_UP || key == KEY_DOWN || key == KEY_LEFT || key == KEY_RIGHT || key == KEY_ENTER || key == ' ' ) { 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_flat ? m_rTree.getNextLeaf( it ) : m_rTree.getNextVisibleItem( it ); if( key == KEY_UP ) { // Scroll up one item if( ( it->parent() && it != it->parent()->begin() ) || &*it != m_pLastSelected ) { bool nextWasSelected = ( &*next == m_pLastSelected ); it->setSelected( nextWasSelected ); if( nextWasSelected ) { m_pLastSelected = &*it; needShow = true; toShow = it; } } } else if( key == KEY_DOWN ) { // Scroll down one item if( ( it->parent() && next != it->parent()->end() ) || &*it != m_pLastSelected ) { it->setSelected( previousWasSelected ); } if( previousWasSelected ) { m_pLastSelected = &*it; needShow = true; toShow = it; previousWasSelected = false; } else { 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->setSelected( true ); } } else if( key == KEY_RIGHT ) { // Go down one level (and expand node) if( &*it == m_pLastSelected ) { if( it->isExpanded() ) { if( it->size() ) { it->setSelected( false ); it->begin()->setSelected( true ); m_pLastSelected = &*(it->begin()); } else { m_rTree.action( &*it ); } } else { it->setExpanded( true ); bChangedPosition = true; } } } else if( key == KEY_LEFT ) { // Go up one level (and close node) if( &*it == m_pLastSelected ) { if( it->isExpanded() && it->size() ) { it->setExpanded( false ); bChangedPosition = true; } else { if( it->parent() && it->parent() != &m_rTree) { it->setSelected( false ); m_pLastSelected = it->parent(); m_pLastSelected->setSelected( true ); } } } } else if( key == KEY_ENTER || key == ' ' ) { // Go up one level (and close node) if( &*it == m_pLastSelected ) { m_rTree.action( &*it ); } } } if( needShow ) ensureVisible( toShow ); // Redraw the control makeImage(); notifyLayout(); } else { // other keys to be forwarded to vlc core EvtKey& rEvtKey = (EvtKey&)rEvent; var_SetInteger( getIntf()->p_libvlc, "key-pressed", rEvtKey.getModKey() ); } } else if( rEvent.getAsString().find( "mouse:left" ) != string::npos ) { EvtMouse &rEvtMouse = (EvtMouse&)rEvent; const Position *pos = getPosition(); int yPos = ( rEvtMouse.getYPos() - pos->getTop() ) / itemHeight(); int xPos = rEvtMouse.getXPos() - pos->getLeft(); VarTree::Iterator it; if( rEvent.getAsString().find( "mouse:left:down:ctrl,shift" ) != string::npos ) { VarTree::Iterator itClicked = findItemAtPos( yPos ); // Flag to know if the current item must be selected bool select = false; 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 ) { if( select ) { nextSelect = false; } else { select = true; nextSelect = true; } } it->setSelected( it->isSelected() || select ); select = nextSelect; } // Redraw the control makeImage(); notifyLayout(); } else if( rEvent.getAsString().find( "mouse:left:down:ctrl" ) != string::npos ) { // Invert the selection of the item it = findItemAtPos( yPos ); if( it != m_rTree.end() ) { it->toggleSelected(); m_pLastSelected = &*it; } // Redraw the control makeImage(); notifyLayout(); } else if( rEvent.getAsString().find( "mouse:left:down:shift" ) != string::npos ) { VarTree::Iterator itClicked = findItemAtPos( yPos ); // Flag to know if the current item must be selected bool select = false; 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 ) { if( select ) { nextSelect = false; } else { select = true; nextSelect = true; } } it->setSelected( select ); select = nextSelect; } // Redraw the control makeImage(); notifyLayout(); } else if( rEvent.getAsString().find( "mouse:left:down" ) != string::npos ) { it = findItemAtPos(yPos); if( it != m_rTree.end() ) { if( ( it->size() && xPos > (it->depth() - 1) * itemImageWidth() && xPos < it->depth() * itemImageWidth() ) && !m_flat ) { // Fold/unfold the item it->toggleExpanded(); bChangedPosition = true; } else { // 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->setSelected( false ); } // Select the new item if( it != m_rTree.end() ) { it->setSelected( true ); m_pLastSelected = &*it; } } } // Redraw the control makeImage(); notifyLayout(); } else if( rEvent.getAsString().find( "mouse:left:dblclick" ) != string::npos ) { it = findItemAtPos(yPos); if( it != m_rTree.end() ) { // Execute the action associated to this item m_rTree.action( &*it ); } // Redraw the control makeImage(); notifyLayout(); } } else if( rEvent.getAsString().find( "scroll" ) != string::npos ) { // XXX ctrl_slider.cpp has two more (but slightly different) // XXX implementations of `scroll'. Figure out where it belongs. int direction = static_cast<EvtScroll&>(rEvent).getDirection(); double percentage = m_rTree.getPositionVar().get(); double step = 2.0 / (double)( m_flat ? m_rTree.countLeafs() : m_rTree.visibleItems() ); if( direction == EvtScroll::kUp ) { percentage += step; } else { percentage -= step; } m_rTree.getPositionVar().set( percentage ); } /* We changed the nodes, let's fix the position var */ if( bChangedPosition ) { VarTree::Iterator it; 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 ) ) { if( it == m_firstPos ) break; iFirst++; } int indexMax = ( m_flat ? m_rTree.countLeafs() : m_rTree.visibleItems() ) - 1; float f_new = (float)iFirst / (float)indexMax; m_dontMove = true; m_rTree.getPositionVar().set( 1.0 - f_new ); m_dontMove = false; } }
void CtrlTree::handleEvent( EvtGeneric &rEvent ) { bool needShow = false; bool needRefresh = false; Iterator toShow = m_firstPos; if( rEvent.getAsString().find( "key:down" ) != string::npos ) { int key = ((EvtKey&)rEvent).getKey(); /* Delete the selection */ if( key == KEY_DELETE ) { /* Delete selected stuff */ m_rTree.delSelected(); } else if( key == KEY_PAGEDOWN ) { int numSteps = (int)m_capacity / 2; VarPercent &rVarPos = m_rTree.getPositionVar(); rVarPos.increment( -numSteps ); } else if( key == KEY_PAGEUP ) { int numSteps = (int)m_capacity / 2; VarPercent &rVarPos = m_rTree.getPositionVar(); rVarPos.increment( numSteps ); } else if( key == KEY_UP ) { // Scroll up one item m_rTree.unselectTree(); if( m_lastClicked != m_rTree.end() ) { if( --m_lastClicked != m_rTree.end() ) { m_lastClicked->setSelected( true ); } } if( m_lastClicked == m_rTree.end() ) { m_lastClicked = m_firstPos; if( m_lastClicked != m_rTree.end() ) m_lastClicked->setSelected( true ); } needRefresh = true; needShow = true; toShow = m_lastClicked; } else if( key == KEY_DOWN ) { // Scroll down one item m_rTree.unselectTree(); if( m_lastClicked != m_rTree.end() ) { Iterator it_old = m_lastClicked; if( ++m_lastClicked != m_rTree.end() ) { m_lastClicked->setSelected( true ); } else { it_old->setSelected( true ); m_lastClicked = it_old; } } else { m_lastClicked = m_firstPos; if( m_lastClicked != m_rTree.end() ) m_lastClicked->setSelected( true ); } needRefresh = true; needShow = true; toShow = m_lastClicked; } else if( key == KEY_RIGHT ) { // Go down one level (and expand node) Iterator& it = m_lastClicked; if( it != m_rTree.end() ) { if( !m_flat && !it->isExpanded() && it->size() ) { it->setExpanded( true ); needRefresh = true; } else { m_rTree.unselectTree(); Iterator it_old = m_lastClicked; if( ++m_lastClicked != m_rTree.end() ) { m_lastClicked->setSelected( true ); } else { it_old->setSelected( true ); m_lastClicked = it_old; } needRefresh = true; needShow = true; toShow = m_lastClicked; } } } else if( key == KEY_LEFT ) { // Go up one level (and close node) Iterator& it = m_lastClicked; if( it != m_rTree.end() ) { if( m_flat ) { m_rTree.unselectTree(); if( --m_lastClicked != m_rTree.end() ) { m_lastClicked->setSelected( true ); } else { m_lastClicked = m_firstPos; if( m_lastClicked != m_rTree.end() ) m_lastClicked->setSelected( true ); } needRefresh = true; needShow = true; toShow = m_lastClicked; } else { if( it->isExpanded() ) { it->setExpanded( false ); needRefresh = true; } else { Iterator it_parent = it.getParent(); if( it_parent != m_rTree.end() ) { it->setSelected( false ); m_lastClicked = it_parent; m_lastClicked->setSelected( true ); needRefresh = true; needShow = true; toShow = m_lastClicked; } } } } } else if( key == KEY_ENTER || key == ' ' ) { // Go up one level (and close node) if( m_lastClicked != m_rTree.end() ) { m_rTree.action( &*m_lastClicked ); } } else { // other keys to be forwarded to vlc core EvtKey& rEvtKey = (EvtKey&)rEvent; var_SetInteger( getIntf()->p_libvlc, "key-pressed", rEvtKey.getModKey() ); } } else if( rEvent.getAsString().find( "mouse:left" ) != string::npos ) { EvtMouse &rEvtMouse = (EvtMouse&)rEvent; const Position *pos = getPosition(); int xPos = rEvtMouse.getXPos() - pos->getLeft(); int yPos = ( rEvtMouse.getYPos() - pos->getTop() ) / itemHeight(); Iterator itClicked = findItemAtPos( yPos ); if( itClicked != m_rTree.end() ) { if( rEvent.getAsString().find( "mouse:left:down:ctrl,shift" ) != string::npos ) { // Flag to know if the current item must be selected bool select = false; for( Iterator it = m_firstPos; it != m_rTree.end(); ++it ) { bool nextSelect = select; if( it == itClicked || it == m_lastClicked ) { if( select ) { nextSelect = false; } else { select = true; if( itClicked != m_lastClicked ) nextSelect = true; } } it->setSelected( it->isSelected() || select ); select = nextSelect; needRefresh = true; } } else if( rEvent.getAsString().find( "mouse:left:down:ctrl" ) != string::npos ) { // Invert the selection of the item itClicked->toggleSelected(); m_lastClicked = itClicked; needRefresh = true; } else if( rEvent.getAsString().find( "mouse:left:down:shift" ) != string::npos ) { bool select = false; for( Iterator it = m_firstPos; it != m_rTree.end(); ++it ) { bool nextSelect = select; if( it == itClicked || it == m_lastClicked ) { if( select ) { nextSelect = false; } else { select = true; if( itClicked != m_lastClicked ) nextSelect = true; } } it->setSelected( select ); select = nextSelect; } needRefresh = true; } else if( rEvent.getAsString().find( "mouse:left:down" ) != string::npos ) { if( !m_flat && itClicked->size() && xPos > (itClicked->depth() - 1) * itemImageWidth() && xPos < itClicked->depth() * itemImageWidth() ) { // Fold/unfold the item itClicked->toggleExpanded(); } else { // Unselect any previously selected item m_rTree.unselectTree(); // Select the new item itClicked->setSelected( true ); m_lastClicked = itClicked; } needRefresh = true; } else if( rEvent.getAsString().find( "mouse:left:dblclick" ) != string::npos ) { // Execute the action associated to this item m_rTree.action( &*itClicked ); } } } else if( rEvent.getAsString().find( "scroll" ) != string::npos ) { int direction = static_cast<EvtScroll&>(rEvent).getDirection(); if( direction == EvtScroll::kUp ) m_rTree.getPositionVar().increment( +1 ); else m_rTree.getPositionVar().increment( -1 ); } else if( rEvent.getAsString().find( "drag:over" ) != string::npos ) { EvtDragOver& evt = static_cast<EvtDragOver&>(rEvent); const Position *pos = getPosition(); int yPos = ( evt.getYPos() - pos->getTop() ) / itemHeight(); Iterator it = findItemAtPos( yPos ); if( it != m_itOver ) { m_itOver = it; needRefresh = true; } } else if( rEvent.getAsString().find( "drag:drop" ) != string::npos ) { EvtDragDrop& evt = static_cast<EvtDragDrop&>(rEvent); Playtree& rPlaytree = static_cast<Playtree&>(m_rTree); VarTree& item = ( m_itOver != m_rTree.end() ) ? *m_itOver : m_rTree; rPlaytree.insertItems( item, evt.getFiles(), false ); m_itOver = m_rTree.end(); needRefresh = true; } else if( rEvent.getAsString().find( "drag:leave" ) != string::npos ) { m_itOver = m_rTree.end(); needRefresh = true; } if( needShow ) { if( toShow == m_rTree.end() || !ensureVisible( toShow ) ) needRefresh = true; } if( needRefresh ) { setSliderFromFirst(); makeImage(); notifyLayout(); } }
void CtrlTree::handleEvent( EvtGeneric &rEvent ) { bool bChangedPosition = false; VarTree::Iterator toShow; bool needShow = false; if( rEvent.getAsString().find( "key:down" ) != string::npos ) { int key = ((EvtKey&)rEvent).getKey(); VarTree::Iterator it; bool previousWasSelected = false; /* 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 = (int)(maxItems()*1.5); while( i >= 0 ) { VarTree::Iterator it_old = it; it = m_flat ? m_rTree.getNextLeaf( it ) : m_rTree.getNextVisibleItem( it ); /* End is already visible, dont' scroll */ if( it == m_rTree.end() ) { it = it_old; break; } needShow = true; i--; } if( needShow ) { ensureVisible( it ); makeImage(); notifyLayout(); return; } } else if (key == KEY_PAGEUP ) { it = m_firstPos; int i = maxItems(); while( i >= maxItems()/2 ) { it = m_flat ? m_rTree.getPrevLeaf( it ) : m_rTree.getPrevVisibleItem( it ); /* End is already visible, dont' scroll */ if( it == ( m_flat ? m_rTree.firstLeaf() : m_rTree.begin() ) ) { break; } i--; } ensureVisible( it ); makeImage(); notifyLayout(); return; } 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_flat ? m_rTree.getNextLeaf( it ) : m_rTree.getNextVisibleItem( it ); if( key == KEY_UP ) { // Scroll up one item if( ( it->parent() && it != it->parent()->begin() ) || &*it != m_pLastSelected ) { bool nextWasSelected = ( &*next == m_pLastSelected ); it->m_selected = nextWasSelected; if( nextWasSelected ) { m_pLastSelected = &*it; needShow = true; toShow = it; } } } else if( key == KEY_DOWN ) { // Scroll down one item if( ( it->parent() && next != it->parent()->end() ) || &*it != m_pLastSelected ) { (*it).m_selected = previousWasSelected; } if( previousWasSelected ) { m_pLastSelected = &*it; needShow = true; toShow = it; previousWasSelected = false; } else { 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 ) { // Go down one level (and expand node) if( &*it == m_pLastSelected ) { if( it->m_expanded ) { if( it->size() ) { it->m_selected = false; it->begin()->m_selected = true; m_pLastSelected = &*(it->begin()); } else { m_rTree.action( &*it ); } } else { it->m_expanded = true; bChangedPosition = true; } } } else if( key == KEY_LEFT ) { // Go up one level (and close node) if( &*it == m_pLastSelected ) { if( it->m_expanded && it->size() ) { it->m_expanded = false; bChangedPosition = true; } else { if( it->parent() && it->parent() != &m_rTree) { it->m_selected = false; m_pLastSelected = it->parent(); m_pLastSelected->m_selected = true; } } } } else if( key == KEY_ENTER || key == ' ' ) { // Go up one level (and close node) if( &*it == m_pLastSelected ) { m_rTree.action( &*it ); } } } if( needShow ) ensureVisible( toShow ); // Redraw the control makeImage(); notifyLayout(); } else if( rEvent.getAsString().find( "mouse:left" ) != string::npos ) { EvtMouse &rEvtMouse = (EvtMouse&)rEvent; const Position *pos = getPosition(); int yPos = ( rEvtMouse.getYPos() - pos->getTop() ) / itemHeight(); int xPos = rEvtMouse.getXPos() - pos->getLeft(); VarTree::Iterator it; if( rEvent.getAsString().find( "mouse:left:down:ctrl,shift" ) != string::npos ) { VarTree::Iterator itClicked = findItemAtPos( yPos ); // Flag to know if the current item must be selected bool select = false; 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 ) { if( select ) { nextSelect = false; } else { select = true; nextSelect = true; } } it->m_selected = (*it).m_selected || select; select = nextSelect; } } else if( rEvent.getAsString().find( "mouse:left:down:ctrl" ) != string::npos ) { // Invert the selection of the item it = findItemAtPos( yPos ); if( it != m_rTree.end() ) { it->m_selected = !it->m_selected; m_pLastSelected = &*it; } } else if( rEvent.getAsString().find( "mouse:left:down:shift" ) != string::npos ) { VarTree::Iterator itClicked = findItemAtPos( yPos ); // Flag to know if the current item must be selected bool select = false; 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 ) { if( select ) { nextSelect = false; } else { select = true; nextSelect = true; } } it->m_selected = select; select = nextSelect; } } else if( rEvent.getAsString().find( "mouse:left:down" ) != string::npos ) { it = findItemAtPos(yPos); if( it != m_rTree.end() ) { if( ( it->size() && xPos > (it->depth() - 1) * itemImageWidth() && xPos < it->depth() * itemImageWidth() ) && !m_flat ) { // Fold/unfold the item it->m_expanded = !it->m_expanded; bChangedPosition = true; } else { // 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; } } } } else if( rEvent.getAsString().find( "mouse:left:dblclick" ) != string::npos ) { it = findItemAtPos(yPos); if( it != m_rTree.end() ) { // Execute the action associated to this item m_rTree.action( &*it ); } } // Redraw the control makeImage(); notifyLayout(); } else if( rEvent.getAsString().find( "scroll" ) != string::npos ) { int direction = ((EvtScroll&)rEvent).getDirection(); double percentage = m_rTree.getPositionVar().get(); double step = 2.0 / (double)( m_flat ? m_rTree.countLeafs() : m_rTree.visibleItems() ); if( direction == EvtScroll::kUp ) { percentage += step; } else { percentage -= step; } 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; } }
void CtrlTree::makeImage() { delete m_pImage; // Get the size of the control const Position *pPos = getPosition(); if( !pPos ) return; int width = pPos->getWidth(); int height = pPos->getHeight(); int i_itemHeight = itemHeight(); // Create an image OSFactory *pOsFactory = OSFactory::instance( getIntf() ); m_pImage = pOsFactory->createOSGraphics( width, height ); Iterator it = m_firstPos; if( m_pBgBitmap ) { // Draw the background bitmap if( !m_pScaledBitmap || m_pScaledBitmap->getWidth() != width || m_pScaledBitmap->getHeight() != height ) { delete m_pScaledBitmap; m_pScaledBitmap = new ScaledBitmap( getIntf(), *m_pBgBitmap, width, height ); } m_pImage->drawBitmap( *m_pScaledBitmap, 0, 0 ); for( int yPos = 0; yPos < height && it != m_rTree.end(); yPos += i_itemHeight, ++it ) { if( it->isSelected() ) { int rectHeight = __MIN( i_itemHeight, height - yPos ); m_pImage->fillRect( 0, yPos, width, rectHeight, m_selColor ); } } } else { // Fill background with background color uint32_t bgColor = m_bgColor1; m_pImage->fillRect( 0, 0, width, height, bgColor ); // Overwrite with alternate colors (bgColor1, bgColor2) for( int yPos = 0; yPos < height; yPos += i_itemHeight ) { int rectHeight = __MIN( i_itemHeight, height - yPos ); if( it == m_rTree.end() ) m_pImage->fillRect( 0, yPos, width, rectHeight, bgColor ); else { uint32_t color = ( it->isSelected() ? m_selColor : bgColor ); m_pImage->fillRect( 0, yPos, width, rectHeight, color ); ++it; } bgColor = ( bgColor == m_bgColor1 ? m_bgColor2 : m_bgColor1 ); } } int bitmapWidth = itemImageWidth(); it = m_firstPos; for( int yPos = 0; yPos < height && it != m_rTree.end(); ++it ) { const GenericBitmap *m_pCurBitmap; UString *pStr = it->getString(); if( pStr != NULL ) { uint32_t color = it->isPlaying() ? m_playColor : m_fgColor; int depth = m_flat ? 1 : it->depth(); GenericBitmap *pText = m_rFont.drawString( *pStr, color, width-bitmapWidth*depth ); if( !pText ) { return; } if( it->size() ) m_pCurBitmap = it->isExpanded() ? m_pOpenBitmap : m_pClosedBitmap; else m_pCurBitmap = m_pItemBitmap; if( m_pCurBitmap ) { // Make sure we are centered on the line int yPos2 = yPos+(i_itemHeight-m_pCurBitmap->getHeight()+1)/2; if( yPos2 >= height ) { delete pText; break; } // Draw the icon in front of the text m_pImage->drawBitmap( *m_pCurBitmap, 0, 0, bitmapWidth * (depth - 1 ), yPos2, m_pCurBitmap->getWidth(), __MIN( m_pCurBitmap->getHeight(), height - yPos2), true ); } yPos += i_itemHeight - pText->getHeight(); int ySrc = 0; if( yPos < 0 ) { ySrc = - yPos; yPos = 0; } int lineHeight = __MIN( pText->getHeight() - ySrc, height - yPos ); // Draw the text m_pImage->drawBitmap( *pText, 0, ySrc, bitmapWidth * depth, yPos, pText->getWidth(), lineHeight, true ); yPos += (pText->getHeight() - ySrc ); if( it == m_itOver ) { // Draw the underline bar below the text for drag&drop m_pImage->fillRect( bitmapWidth * (depth - 1 ), yPos - 2, bitmapWidth + pText->getWidth(), __MAX( lineHeight/5, 3 ), m_selColor ); } delete pText; } } }