/**************************************************************************** Copyright (c) 2010-2012 cocos2d-x.org Copyright (c) 2012 NetGragon http://www.cocos2d-x.org Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "CCListView.h" //#include "../cocos2dx_support/LuaEngineImpl.h" #include "cocos2d.h" using namespace std; NS_CC_EXT_BEGIN #define ND_LISTVIEW_ACTION_INTERVAL 0.6666f /****************************************** **************Public Functions************* *******************************************/ CCListView* CCListView::viewWithMode(CCListViewMode mode) { CCListView *pRet = new CCListView(); if (pRet && pRet->initWithMode(mode)) { pRet->autorelease(); return pRet; } else { CC_SAFE_DELETE(pRet); return NULL; } } bool CCListView::initWithMode(CCListViewMode mode) { bool bRet = false; m_nMode = mode; m_layerPanel = CCLayer::node(); this->addChild(m_layerPanel); bRet = CCLayerColor::initWithColor(ccc4(255, 255, 255, 0), 0, 0); setIsTouchEnabled(true); return bRet; } CCListView::CCListView(void) :m_nMode(CCListViewModeVertical) ,m_nState(CCListViewStateWatting) ,m_nSlideDir(CCListViewSlideDirNone) ,m_layerPanel(NULL) ,m_nSeparatorStyle(CCListViewCellSeparatorStyleSingleLine) ,m_nSelectedRow(-1) ,m_nCurrentRow(-1) ,m_fActionDuration(ND_LISTVIEW_ACTION_INTERVAL) ,m_pListViewParent(NULL) ,m_bIsEnabled(true) ,m_pDelegate(NULL) ,m_nNumberOfRows(0) ,m_bIsOnTouch(false) { m_drawedRows = CCRangeMake(0, 0); m_visibleRows = CCRangeMake(0, 0); m_bIsTouchEnabled = true; } CCListView::~CCListView(void) { } void CCListView::setDelegateName(const char* pszName) { if (pszName) { this->m_strDeletegate = string(pszName) + "."; } else { this->m_strDeletegate.clear(); } } void CCListView::selectCellAtRow(unsigned int nRow) { CCListViewCell *cell = cellAtRow(nRow); if (cell) { cell->selected(); } } void CCListView::unselectCellAtRow(unsigned int nRow) { if (nRow == m_nSelectedRow) { m_nSelectedRow = -1; } CCListViewCell *cell = cellAtRow(nRow); if (cell) { cell->unselected(); } } void CCListView::reload(void) { m_layerPanel->removeAllChildrenWithCleanup(true); m_layerPanel->setPosition(CCPointZero); m_visibleRows = CCRangeMake(0, 0); m_drawedRows = CCRangeMake(0, 0); m_nNumberOfRows = triggerNumberOfCells(); this->displayVisibleRows(); } void CCListView::insertCellsAtRow(unsigned int nRow, unsigned int nCount) { if (nRow >= m_nNumberOfRows) { if (m_nNumberOfRows > 0) { nRow = m_nNumberOfRows - 1; } else { nRow = 0; } } m_layerPanel->pauseSchedulerAndActions(); if (m_nNumberOfRows == 0) { m_nNumberOfRows = this->triggerNumberOfCells(); this->displayVisibleRows(); } else { m_nNumberOfRows = this->triggerNumberOfCells(); if (!this->isFullFill()) { this->displayVisibleRows(); } } m_layerPanel->resumeSchedulerAndActions(); } void CCListView::deleteCellsAtRow(unsigned int nRow, unsigned int nCount) { if (m_nNumberOfRows == 0) { return; } if (nRow >= m_nNumberOfRows) { if (m_nNumberOfRows > 0) { nRow = m_nNumberOfRows - 1; } else { nRow = 0; } } m_layerPanel->pauseSchedulerAndActions(); m_nNumberOfRows = this->triggerNumberOfCells(); for (unsigned int n = nRow;n < nRow + nCount; n++) { if (n >= m_drawedRows.location && n <= CCRange::CCMaxRange(m_drawedRows)) { CCListViewCell *cell = this->cellAtRow(n); if (cell) { CCPoint pos = cell->getPosition(); pos.y += cell->getContentSize().height; m_layerPanel->removeChild(cell, true); for (unsigned int i = n +1; i <= CCRange::CCMaxRange(m_drawedRows); i++) { cell = this->cellAtRow(i); if (cell) { int tag = cell->getTag(); cell->setTag(tag - 1); if (CCListViewModeHorizontal == m_nMode) { cell->setPosition(pos); pos.x += cell->getContentSize().width; } else if (CCListViewModeVertical == m_nMode) { pos.y -= cell->getContentSize().height; cell->setPosition(pos); } } } if (m_drawedRows.length > 0) { m_drawedRows.length--; unsigned int nLastRow = CCRange::CCMaxRange(m_drawedRows); this->appendRowToBack(nLastRow + 1); } } } else { for (unsigned int i = m_drawedRows.location; i <= CCRange::CCMaxRange(m_drawedRows); i++) { CCListViewCell *cell = this->cellAtRow(i); if (cell) { int tag = cell->getTag(); cell->setTag(tag - 1); } } if (m_drawedRows.location > 0) { m_drawedRows.location--; } } } m_layerPanel->resumeSchedulerAndActions(); } void CCListView::scrollCellToFront(unsigned int nRow, bool bAnimated) { if (!isFullFill()) { return; } if (m_nNumberOfRows == 0) { return; } if (CCListViewStateWatting != m_nState) { this->stopActionImmediately(); } if (nRow >= m_nNumberOfRows) { nRow = m_nNumberOfRows - 1; } float disX = 0; float disY = 0; m_nSlideDir = CCListViewSlideDirNone; if (CCListViewModeHorizontal == m_nMode) { float dis = 0; unsigned int nCount = 0; CCListViewCell *cell = NULL; if (nRow > m_visibleRows.location) { m_nSlideDir = CCListViewSlideDirLeft; } else { m_nSlideDir = CCListViewSlideDirRight; } while(1) { if (dis >= this->getContentSize().width || nRow + nCount >= m_nNumberOfRows) { break; } if (CCListViewSlideDirRight == m_nSlideDir) { cell = appendRowToFront(nRow + nCount); } else if (CCListViewSlideDirLeft == m_nSlideDir) { cell = appendRowToBack(nRow + nCount); } if (cell) { nCount++; dis += cell->getContentSize().width; } else { CCLog("CCListView cell == NULL at line %d", __LINE__); } } if (CCListViewSlideDirLeft == m_nSlideDir && dis < this->getContentSize().width) { // at last while(1) { if (dis >= this->getContentSize().width) { break; } cell = appendRowToBack(nRow - 1); if (cell) { nRow--; dis += cell->getContentSize().width; nCount++; } else { CCLog("CCListView cell == NULL at line %d", __LINE__); } } } if (CCListViewSlideDirRight == m_nSlideDir) { CCListViewCell* cell = NULL; unsigned nLast = 0; if (CCRange::CCLocationInRange(nRow + nCount - 1, m_visibleRows)) { cell = cellAtRow(nRow + nCount - 1); nLast = nRow + nCount - 2; } else { cell = cellAtRow(m_visibleRows.location); nLast = nRow + nCount - 1; } if (cell) { CCPoint pos = cell->getPosition(); for (int i = nLast; i >= (int)nRow; i--) { cell = cellAtRow(i); if (cell) { pos.x -= cell->getContentSize().width; cell->setPosition(pos); } else { CCLog("CCListView cell == NULL at line %d", __LINE__); } } } else { CCLog("CCListView cell == NULL at line %d", __LINE__); } } else if (CCListViewSlideDirLeft == m_nSlideDir) { CCListViewCell* cell = NULL; unsigned nFirst = 0; if (CCRange::CCLocationInRange(nRow, m_visibleRows)) { cell = cellAtRow(nRow); nFirst = nRow + 1; } else { cell = cellAtRow(CCRange::CCMaxRange(m_visibleRows)); nFirst = nRow; } if (cell) { CCPoint pos = cell->getPosition(); pos.x += cell->getContentSize().width; for (unsigned int i = nFirst; i < nRow + nCount; i++) { cell = cellAtRow(i); if (cell) { cell->setPosition(pos); pos.x += cell->getContentSize().width; } else { CCLog("CCListView cell == NULL at line %d", __LINE__); } } } else { CCLog("CCListView cell == NULL at line %d", __LINE__); } } cell = cellAtRow(nRow); CCPoint ptCell = cell->convertToWorldSpace(CCPointZero); CCPoint ptView = this->convertToWorldSpace(CCPointZero); disX = ptView.x - ptCell.x; } else if (CCListViewModeVertical == m_nMode) { float dis = 0; unsigned int nCount = 0; CCListViewCell *cell = NULL; if (nRow > m_visibleRows.location) { m_nSlideDir = CCListViewSlideDirUp; } else { m_nSlideDir = CCListViewSlideDirDown; } while(1) { if (dis >= this->getContentSize().height || nRow + nCount >= m_nNumberOfRows) { break; } if (CCListViewSlideDirDown == m_nSlideDir) { cell = appendRowToFront(nRow + nCount); } else if (CCListViewSlideDirUp == m_nSlideDir) { cell = appendRowToBack(nRow + nCount); } if (cell) { nCount++; dis += cell->getContentSize().height; } else { CCLog("CCListView cell == NULL at line %d", __LINE__); } } if (CCListViewSlideDirUp == m_nSlideDir && dis < this->getContentSize().height) { // at last while(1) { if (dis >= this->getContentSize().height) { break; } cell = appendRowToBack(nRow - 1); if (cell) { nRow--; dis += cell->getContentSize().height; nCount++; } else { CCLog("CCListView cell == NULL at line %d", __LINE__); } } } if (CCListViewSlideDirDown == m_nSlideDir) { CCListViewCell* cell = NULL; unsigned nLast = 0; if (CCRange::CCLocationInRange(nRow + nCount - 1, m_visibleRows)) { cell = cellAtRow(nRow + nCount - 1); nLast = nRow + nCount - 2; } else { cell = cellAtRow(m_visibleRows.location); nLast = nRow + nCount - 1; } if (cell) { CCPoint pos = cell->getPosition(); pos.y += cell->getContentSize().height; for (int i = nLast; i >= (int)nRow; i--) { cell = cellAtRow(i); if (cell) { cell->setPosition(pos); pos.y += cell->getContentSize().height; } else { CCLog("CCListView cell == NULL at line %d", __LINE__); } } } else { CCLog("CCListView cell == NULL at line %d", __LINE__); } } else if (CCListViewSlideDirUp == m_nSlideDir) { CCListViewCell* cell = NULL; unsigned nFirst = 0; if (CCRange::CCLocationInRange(nRow, m_visibleRows)) { cell = cellAtRow(nRow); nFirst = nRow + 1; } else { cell = cellAtRow(CCRange::CCMaxRange(m_visibleRows)); nFirst = nRow; } if (cell) { CCPoint pos = cell->getPosition(); for (unsigned int i = nFirst; i < nRow + nCount; i++) { cell = cellAtRow(i); if (cell) { pos.y -= cell->getContentSize().height; cell->setPosition(pos); } else { CCLog("CCListView cell == NULL at line %d", __LINE__); } } } else { CCLog("CCListView cell == NULL at line %d", __LINE__); } } cell = cellAtRow(nRow); CCPoint ptCell = cell->convertToWorldSpace(CCPointZero); CCPoint ptView = this->convertToWorldSpace(CCPointZero); disY = ptView.y + this->getContentSize().height - (ptCell.y + cell->getContentSize().height); } m_ptDestination = m_layerPanel->getPosition(); m_ptDestination.x += disX; m_ptDestination.y += disY; m_nState = CCListViewStateScroll; if (bAnimated) { CCMoveBy *moveBy = CCMoveBy::actionWithDuration(m_fActionDuration, CCPointMake(disX, disY)); CCEaseOut *ease = CCEaseOut::actionWithAction(moveBy, 3); CCFiniteTimeAction *actions = CCSequence::actions(ease, CCCallFunc::actionWithTarget(this, callfunc_selector(CCListView::finishScroll)), NULL); m_layerPanel->runAction(actions); } else { stopActionImmediately(); } } void CCListView::scrollCellToBack(unsigned int nRow, bool bAnimated) { if (!isFullFill()) { return; } if (m_nNumberOfRows == 0) { return; } if (CCListViewStateWatting != m_nState) { this->stopActionImmediately(); } if (nRow >= m_nNumberOfRows) { nRow = m_nNumberOfRows - 1; } float disX = 0; float disY = 0; m_nSlideDir = CCListViewSlideDirNone; if (CCListViewModeHorizontal == m_nMode) { float dis = 0; int nCount = 0; CCListViewCell *cell = NULL; if (nRow > CCRange::CCMaxRange(m_visibleRows)) { m_nSlideDir = CCListViewSlideDirLeft; } else { m_nSlideDir = CCListViewSlideDirRight; } while(1) { if (dis >= this->getContentSize().width || (int)nRow - nCount < 0) { break; } if (CCListViewSlideDirRight == m_nSlideDir) { cell = appendRowToFront(nRow - nCount); } else if (CCListViewSlideDirLeft == m_nSlideDir) { cell = appendRowToBack(nRow - nCount); } if (cell) { nCount++; dis += cell->getContentSize().width; } else { CCLog("CCListView cell == NULL at line %d", __LINE__); } } if (CCListViewSlideDirRight == m_nSlideDir && dis < this->getContentSize().width) { // at first while(1) { if (dis >= this->getContentSize().width) { break; } cell = appendRowToBack(nRow + 1); if (cell) { nRow++; dis += cell->getContentSize().width; nCount++; } else { CCLog("CCListView cell == NULL at line %d", __LINE__); } } } if (CCListViewSlideDirRight == m_nSlideDir) { CCListViewCell* cell = NULL; unsigned nLast = 0; if (CCRange::CCLocationInRange(nRow, m_visibleRows)) { cell = cellAtRow(nRow); nLast = nRow - 1; } else { cell = cellAtRow(m_visibleRows.location); nLast = nRow; } if (cell) { CCPoint pos = cell->getPosition(); for (int i = nLast; i >= (int)(nRow - nCount + 1); i--) { cell = cellAtRow(i); if (cell) { pos.x -= cell->getContentSize().width; cell->setPosition(pos); } else { CCLog("CCListView cell == NULL at line %d", __LINE__); } } } else { CCLog("CCListView cell == NULL at line %d", __LINE__); } } else if (CCListViewSlideDirLeft == m_nSlideDir) { CCListViewCell* cell = NULL; unsigned nFirst = 0; if (CCRange::CCLocationInRange(nRow - nCount + 1, m_visibleRows)) { cell = cellAtRow(nRow - nCount + 1); nFirst = nRow - nCount + 2; nCount--; } else { cell = cellAtRow(CCRange::CCMaxRange(m_visibleRows)); nFirst = nRow - nCount + 1; } if (cell) { CCPoint pos = cell->getPosition(); pos.x += cell->getContentSize().width; for (unsigned int i = nFirst; i < nFirst + nCount; i++) { cell = cellAtRow(i); if (cell) { cell->setPosition(pos); pos.x += cell->getContentSize().width; } else { CCLog("CCListView cell == NULL at line %d", __LINE__); } } } else { CCLog("CCListView cell == NULL at line %d", __LINE__); } } cell = cellAtRow(nRow); CCPoint ptCell = cell->convertToWorldSpace(CCPointZero); CCPoint ptView = this->convertToWorldSpace(CCPointZero); disX = ptView.x + this->getContentSize().width - (ptCell.x + cell->getContentSize().width); } else if (CCListViewModeVertical == m_nMode) { float dis = 0; int nCount = 0; CCListViewCell *cell = NULL; if (nRow > CCRange::CCMaxRange(m_visibleRows)) { m_nSlideDir = CCListViewSlideDirUp; } else { m_nSlideDir = CCListViewSlideDirDown; } while(1) { if (dis >= this->getContentSize().height || (int)nRow - nCount < 0) { break; } if (CCListViewSlideDirDown == m_nSlideDir) { cell = appendRowToFront(nRow - nCount); } else if (CCListViewSlideDirUp == m_nSlideDir) { cell = appendRowToBack(nRow - nCount); } if (cell) { nCount++; dis += cell->getContentSize().height; } else { CCLog("CCListView cell == NULL at line %d", __LINE__); } } if (CCListViewSlideDirDown == m_nSlideDir && dis < this->getContentSize().height) { // at first while(1) { if (dis >= this->getContentSize().height) { break; } cell = appendRowToBack(nRow + 1); if (cell) { nRow++; dis += cell->getContentSize().height; nCount++; } else { CCLog("CCListView cell == NULL at line %d", __LINE__); } } } if (CCListViewSlideDirDown == m_nSlideDir) { CCListViewCell* cell = NULL; unsigned nLast = 0; if (CCRange::CCLocationInRange(nRow, m_visibleRows)) { cell = cellAtRow(nRow); nLast = nRow - 1; } else { cell = cellAtRow(m_visibleRows.location); nLast = nRow; } if (cell) { CCPoint pos = cell->getPosition(); pos.y += cell->getContentSize().height; for (int i = nLast; i >= (int)(nRow - nCount + 1); i--) { cell = cellAtRow(i); if (cell) { cell->setPosition(pos); pos.y += cell->getContentSize().height; } else { CCLog("CCListView cell == NULL at line %d", __LINE__); } } } else { CCLog("CCListView cell == NULL at line %d", __LINE__); } } else if (CCListViewSlideDirUp == m_nSlideDir) { CCListViewCell* cell = NULL; unsigned nFirst = 0; if (CCRange::CCLocationInRange(nRow - nCount + 1, m_visibleRows)) { cell = cellAtRow(nRow - nCount + 1); nFirst = nRow - nCount + 2; nCount--; } else { cell = cellAtRow(CCRange::CCMaxRange(m_visibleRows)); nFirst = nRow - nCount + 1; } if (cell) { CCPoint pos = cell->getPosition(); for (unsigned int i = nFirst; i < nFirst + nCount; i++) { cell = cellAtRow(i); if (cell) { pos.y -= cell->getContentSize().height; cell->setPosition(pos); } else { CCLog("CCListView cell == NULL at line %d", __LINE__); } } } else { CCLog("CCListView cell == NULL at line %d", __LINE__); } } cell = cellAtRow(nRow); CCPoint ptCell = cell->convertToWorldSpace(CCPointZero); CCPoint ptView = this->convertToWorldSpace(CCPointZero); disY = ptView.y - ptCell.y; } m_ptDestination = m_layerPanel->getPosition(); m_ptDestination.x += disX; m_ptDestination.y += disY; m_nState = CCListViewStateScroll; if (bAnimated) { CCMoveBy *moveBy = CCMoveBy::actionWithDuration(m_fActionDuration, CCPointMake(disX, disY)); CCEaseOut *ease = CCEaseOut::actionWithAction(moveBy, 3); CCFiniteTimeAction *actions = CCSequence::actions(ease, CCCallFunc::actionWithTarget(this, callfunc_selector(CCListView::finishScroll)), NULL); m_layerPanel->runAction(actions); } else { stopActionImmediately(); } } CCListViewSlideDir CCListView::getSlideDir(CCPoint ptTouchBegan, CCPoint ptTouchEnd) { CCListViewSlideDir nSlideDir = CCListViewSlideDirNone; int nOffsetX = ptTouchEnd.x - ptTouchBegan.x; int nOffsetY = ptTouchEnd.y - ptTouchBegan.y; int disMin = CCDirector::sharedDirector()->getWinSize().height / 100; if(CCListViewModeHorizontal == m_nMode) { if(nOffsetX >= disMin) { nSlideDir = CCListViewSlideDirRight; } else if (nOffsetX <= -disMin) { nSlideDir = CCListViewSlideDirLeft; } } else if (CCListViewModeVertical == m_nMode) { if(nOffsetY >= disMin) { nSlideDir = CCListViewSlideDirUp; } else if (nOffsetY <= -disMin) { nSlideDir = CCListViewSlideDirDown; } } return nSlideDir; } /****************************************** **************Private Functions************ *******************************************/ int CCListView::rowForTouch(cocos2d::CCTouch *touch) { CCPoint touchLocation = touch->locationInView(); touchLocation = CCDirector::sharedDirector()->convertToGL(touchLocation); CCArray *pChildren = m_layerPanel->getChildren(); if (pChildren && pChildren->count() > 0) { CCObject* pObject = NULL; CCARRAY_FOREACH(pChildren, pObject) { CCNode* pChild = (CCNode*) pObject; if (pChild && pChild->getIsVisible()) { CCPoint local = pChild->convertToNodeSpace(touchLocation); CCRect r = CCRectZero; r.size = pChild->getContentSize(); if (CCRect::CCRectContainsPoint(r, local)) { return pChild->getTag(); } } } } return -1; } void CCListView::finishFix(void) { if(m_pListViewParent) { m_pListViewParent->setIsEnabled(true); } m_nState = CCListViewStateWatting; m_nSlideDir = CCListViewSlideDirNone; clearUnvisibleRows(); triggerDidScrollToRow(m_visibleRows.location); CCArray *children = m_layerPanel->getChildren(); int nCount = 0; if (children) { nCount = children->count(); } //CCLog("row num left:%d [%d, %d]", nCount, m_drawedRows.location, CCRange::CCMaxRange(m_drawedRows)); } void CCListView::finishScroll(void) { finishFix(); } void CCListView::finishEaseOut(void) { bool bNeedFix = false; if (CCListViewModeHorizontal == m_nMode) { bool bFullFill = isFullFill(); if (CCListViewSlideDirLeft == m_nSlideDir && bFullFill) { CCListViewCell *cell = cellAtRow(m_nNumberOfRows - 1); if (cell) { CCPoint ptCell = cell->convertToWorldSpace(CCPointZero); CCPoint ptView = this->convertToWorldSpace(CCPointZero); if (ptCell.x + cell->getContentSize().width < ptView.x + this->getContentSize().width) { bNeedFix = true; fixLastRow(); } } } else { CCListViewCell *cell = cellAtRow(0); if (cell) { CCPoint ptCell = cell->convertToWorldSpace(CCPointZero); CCPoint ptView = this->convertToWorldSpace(CCPointZero); if (ptCell.x > ptView.x || !bFullFill) { bNeedFix = true; fixFirstRow(); } } } } else if (CCListViewModeVertical == m_nMode) { bool bFullFill = this->isFullFill(); if (CCListViewSlideDirUp == m_nSlideDir && bFullFill) { CCListViewCell *cell = cellAtRow(m_nNumberOfRows - 1); if (cell) { CCPoint ptCell = cell->convertToWorldSpace(CCPointZero); CCPoint ptView = this->convertToWorldSpace(CCPointZero); if (ptCell.y > ptView.y) { bNeedFix = true; fixLastRow(); } } } else { CCListViewCell *cell = cellAtRow(0); if (cell) { CCPoint ptCell = cell->convertToWorldSpace(CCPointZero); CCPoint ptView = this->convertToWorldSpace(CCPointZero); if (ptCell.y + cell->getContentSize().height < ptView.y + this->getContentSize().height || !bFullFill) { bNeedFix = true; fixFirstRow(); } } } } if (!bNeedFix) { finishFix(); } } bool CCListView::isTouchInside(CCTouch *touch) { CCPoint point; if (m_pListViewParent) { point = m_pListViewParent->convertTouchToNodeSpace(touch); } else { point = this->convertTouchToNodeSpace(touch); } CCRect bounds = CCRectMake(0, 0, this->getContentSize().width, this->getContentSize().height); bool bIn = CCRect::CCRectContainsPoint(bounds, point); return bIn; } bool CCListView::isFullFill(void) { bool bRet = false; float length = 0; for (unsigned int i = m_drawedRows.location; i <= CCRange::CCMaxRange(m_drawedRows); i++) { CCListViewCell *cell = cellAtRow(i); if (cell) { if (CCListViewModeHorizontal == m_nMode) { length += cell->getContentSize().width; if (length >= this->getContentSize().width) { bRet = true; break; } } else if (CCListViewModeVertical == m_nMode) { length += cell->getContentSize().height; if (length >= this->getContentSize().height) { bRet = true; break; } } } } return bRet; } CCListViewCell *CCListView::cellAtRow(unsigned int nRow) { CCListViewCell *cell = (CCListViewCell*)m_layerPanel->getChildByTag(nRow); return cell; } void CCListView::stopActionImmediately(void) { m_layerPanel->stopAllActions(); if (CCListViewStateScroll == m_nState) { m_layerPanel->setPosition(m_ptDestination); finishScroll(); } } unsigned int CCListView::triggerNumberOfCells(void) { unsigned int nRow = 0; CCListViewProtrolData data; data.nNumberOfRows = 0; data.nRow = 0; data.cell = NULL; if (m_strDeletegate.size() > 0) { CCScriptEngineProtocol* scriptEngine = CCScriptEngineManager::sharedManager()->getScriptEngine(); if (scriptEngine) { std::string script; script = m_strDeletegate + "CCListView_numberOfCells"; //TODO: scriptEngine->executeCallFuncNTDT(script.c_str(), this, "NdCxControl::CCListView", &data, "NdCxControl::CCListViewProtrolData"); nRow = data.nNumberOfRows; } } if (m_pDelegate) { m_pDelegate->CCListView_numberOfCells(this, &data); nRow = data.nNumberOfRows; } return nRow; } CCListViewCell *CCListView::triggerCellForRow(unsigned int nRow) { CCListViewCell *cell = NULL; CCListViewProtrolData data; data.nRow = nRow; data.cell = NULL; if (m_strDeletegate.size() > 0) { CCScriptEngineProtocol* scriptEngine = CCScriptEngineManager::sharedManager()->getScriptEngine(); if (scriptEngine) { std::string script; script = m_strDeletegate + "CCListView_cellForRow"; //TODO: scriptEngine->executeCallFuncNTDT(script.c_str(), this, "NdCxControl::CCListView", &data, "NdCxControl::CCListViewProtrolData"); cell = data.cell; } } if (m_pDelegate) { m_pDelegate->CCListView_cellForRow(this, &data); cell = data.cell; } return cell; } void CCListView::triggerDidClickCellAtRow(unsigned int nRow) { CCListViewProtrolData data; data.nRow = nRow; if (m_strDeletegate.size() > 0) { CCScriptEngineProtocol* scriptEngine = CCScriptEngineManager::sharedManager()->getScriptEngine(); if (scriptEngine) { std::string script; script = m_strDeletegate + "CCListView_didClickCellAtRow"; //TODO: scriptEngine->executeCallFuncNTDT(script.c_str(), this, "NdCxControl::CCListView", &data, "NdCxControl::CCListViewProtrolData"); } } if (m_pDelegate) { m_pDelegate->CCListView_didClickCellAtRow(this, &data); } } void CCListView::triggerDidScrollToRow(unsigned int nRow) { CCListViewProtrolData data; data.nRow = nRow; if (m_strDeletegate.size() > 0) { CCScriptEngineProtocol* scriptEngine = CCScriptEngineManager::sharedManager()->getScriptEngine(); if (scriptEngine) { std::string script; script = m_strDeletegate + "CCListView_didScrollToRow"; //TODO: scriptEngine->executeCallFuncNTDT(script.c_str(), this, "NdCxControl::CCListView", &data, "NdCxControl::CCListViewProtrolData"); } } if (m_pDelegate) { m_pDelegate->CCListView_didScrollToRow(this, &data); } } void CCListView::displayVisibleRows(void) { CCSize size = getContentSize(); float posPannel, boundPannel; unsigned int rowCount = m_drawedRows.location; CCListViewCell *cell = cellAtRow(rowCount); if (m_nMode == CCListViewModeHorizontal) { if (cell) { posPannel = cell->getPosition().x; } else { posPannel = m_layerPanel->getPosition().x; } boundPannel = posPannel + size.width; } else if (m_nMode == CCListViewModeVertical) { if (cell) { posPannel = cell->getPosition().y + cell->getContentSize().height; } else { posPannel = size.height - m_layerPanel->getPosition().y; } boundPannel = posPannel - size.height; } CCListViewCell *lastCell = NULL; while(1) { // row condition if (rowCount >= m_nNumberOfRows) break; // size condition if (m_nMode == CCListViewModeHorizontal) { if (posPannel >= boundPannel) break; } else if (m_nMode == CCListViewModeVertical) { if (posPannel <= boundPannel) break; } // get cell CCListViewCell *cell = cellAtRow(rowCount); if (NULL == cell) { cell = triggerCellForRow(rowCount); if (cell) { CCSize cellSize = cell->getContentSize(); if (m_nMode == CCListViewModeHorizontal) { cell->setPosition(CCPointMake(posPannel, 0)); cell->setContentSize(CCSizeMake(cellSize.width, size.height)); } else if (m_nMode == CCListViewModeVertical) { cell->setPosition(CCPointMake(0, posPannel - cellSize.height)); cell->setContentSize(CCSizeMake(size.width, cellSize.height)); } m_layerPanel->addChild(cell, rowCount, rowCount); } } if (cell) { if (m_nMode == CCListViewModeHorizontal) { posPannel += cell->getContentSize().width; } else if (m_nMode == CCListViewModeVertical) { posPannel -= cell->getContentSize().height; } cell->setSeparatorStyle(m_nSeparatorStyle); lastCell = cell; } ++rowCount; } m_drawedRows.length = rowCount - m_drawedRows.location; // set visible range m_visibleRows = m_drawedRows; if (lastCell) { lastCell->setSeparatorStyle(CCListViewCellSeparatorStyleNone); } } CCListViewCell* CCListView::appendRowToBack(unsigned int nRow) { if (nRow >= m_nNumberOfRows) { return NULL; } CCListViewCell *cell = cellAtRow(nRow); if (cell == NULL) { cell = triggerCellForRow(nRow); if (cell) { CCSize size = this->getContentSize(); CCSize cellSize = cell->getContentSize(); float pos; unsigned int nLastRow = CCRange::CCMaxRange(m_drawedRows); CCListViewCell *lastCell = cellAtRow(nLastRow); if (lastCell) { if (m_nMode == CCListViewModeHorizontal) { pos = lastCell->getPosition().x + lastCell->getContentSize().width; cell->setPosition(CCPointMake(pos, 0)); cell->setContentSize(CCSizeMake(cellSize.width, size.height)); } else if (m_nMode == CCListViewModeVertical) { pos = lastCell->getPosition().y - cell->getContentSize().height; cell->setPosition(CCPointMake(0, pos)); cell->setContentSize(CCSizeMake(size.width, cellSize.height)); } if (nRow == m_nSelectedRow) { cell->selected(); } m_layerPanel->addChild(cell, nRow, nRow); if (nRow > CCRange::CCMaxRange(m_drawedRows)) { cell->setSeparatorStyle(CCListViewCellSeparatorStyleNone); lastCell->setSeparatorStyle(m_nSeparatorStyle); m_drawedRows.length += nRow - CCRange::CCMaxRange(m_drawedRows); } else { cell->setSeparatorStyle(m_nSeparatorStyle); } } else { CCLog("CCListView cell == NULL at line %d", __LINE__); } } else { CCLog("CCListView cell == NULL at line %d", __LINE__); } } return cell; } CCListViewCell* CCListView::appendRowToFront(unsigned int nRow) { CCListViewCell *cell = cellAtRow(nRow); if (cell == NULL) { cell = triggerCellForRow(nRow); if (cell) { CCSize size = this->getContentSize(); CCSize cellSize = cell->getContentSize(); float pos; unsigned int nFirstRow = m_drawedRows.location; CCListViewCell *firstCell = cellAtRow(nFirstRow); if (firstCell) { if (m_nMode == CCListViewModeHorizontal) { pos = firstCell->getPosition().x - cell->getContentSize().width; cell->setPosition(CCPointMake(pos, 0)); cell->setContentSize(CCSizeMake(cellSize.width, size.height)); } else if (m_nMode == CCListViewModeVertical) { pos = firstCell->getPosition().y + firstCell->getContentSize().height; cell->setPosition(CCPointMake(0, pos)); cell->setContentSize(CCSizeMake(size.width, cellSize.height)); } cell->setSeparatorStyle(m_nSeparatorStyle); if (nRow == m_nSelectedRow) { cell->selected(); } m_layerPanel->addChild(cell, nRow, nRow); if (nRow < m_drawedRows.location) { m_drawedRows.length += m_drawedRows.location - nRow; m_drawedRows.location = nRow; } } else { CCLog("CCListView cell == NULL at line %d", __LINE__); } } else { CCLog("CCListView cell == NULL at line %d", __LINE__); } } return cell; } // align first row void CCListView::fixFirstRow(void) { unsigned int location = m_drawedRows.location; CCListViewCell *cell = cellAtRow(location); if (cell) { float disX = 0; float disY = 0; CCPoint posCell = cell->convertToWorldSpace(CCPointZero); CCPoint posView = this->convertToWorldSpace(CCPointZero); if (CCListViewModeHorizontal == m_nMode) { float dis = posCell.x - posView.x; dis = -dis; disX = dis; disY = 0; } else if (CCListViewModeVertical == m_nMode) { float dis = posCell.y + cell->getContentSize().height - (posView.y + this->getContentSize().height); dis = -dis; disX = 0; disY = dis; } m_nState = CCListViewStateFix; CCMoveBy *moveBy = CCMoveBy::actionWithDuration(m_fActionDuration, CCPointMake(disX, disY)); CCEaseInOut *ease = CCEaseInOut::actionWithAction(moveBy, 2); CCFiniteTimeAction *actions = CCSequence::actions(ease, CCCallFunc::actionWithTarget(this, callfunc_selector(CCListView::finishFix)), NULL); m_layerPanel->runAction(actions); } else { this->finishFix(); } } // align last row void CCListView::fixLastRow(void) { unsigned int nLastRow = CCRange::CCMaxRange(m_drawedRows); CCListViewCell *cell = cellAtRow(nLastRow); if (cell) { float disX = 0; float disY = 0; CCPoint posCell = cell->convertToWorldSpace(CCPointZero); CCPoint posView = this->convertToWorldSpace(CCPointZero); if (CCListViewModeHorizontal == m_nMode) { float dis = posCell.x + cell->getContentSize().width - (posView.x + this->getContentSize().width); dis = -dis; disX = dis; disY = 0; } else if (CCListViewModeVertical == m_nMode) { float dis = posCell.y - posView.y; dis = -dis; disX = 0; disY = dis; } m_nState = CCListViewStateFix; CCMoveBy *moveBy = CCMoveBy::actionWithDuration(m_fActionDuration, CCPointMake(disX, disY)); CCEaseInOut *ease = CCEaseInOut::actionWithAction(moveBy, 2); CCFiniteTimeAction *actions = CCSequence::actions(ease, CCCallFunc::actionWithTarget(this, callfunc_selector(CCListView::finishFix)), NULL); m_layerPanel->runAction(actions); } else { finishFix(); } } void CCListView::easeOutWithDistance(float dis) { float disX = 0; float disY = 0; if (CCListViewModeHorizontal == m_nMode) { if (CCListViewSlideDirLeft == m_nSlideDir) { // drag Left while(1) { unsigned int nLastRow = CCRange::CCMaxRange(m_drawedRows); CCListViewCell *cell = cellAtRow(nLastRow); if (cell) { CCPoint ptCell = cell->convertToWorldSpace(CCPointZero); CCPoint ptView = this->convertToWorldSpace(CCPointZero); if (nLastRow < m_nNumberOfRows - 1) { float offset = ptView.x + this->getContentSize().width - (ptCell.x + cell->getContentSize().width); if (offset > dis) { appendRowToBack(nLastRow + 1); } else { dis = offset; break; } } else { // already is the last row float leftMin = cell->getContentSize().width / 5; float offset = ptCell.x + cell->getContentSize().width + dis - ptView.x; if (offset < -leftMin) { dis = ptView.x + leftMin - (ptCell.x + cell->getContentSize().width); } offset = ptCell.x + cell->getContentSize().width + dis - (ptView.x + this->getContentSize().width) ; if (offset > 0) { dis = ptView.x + this->getContentSize().width - (ptCell.x + cell->getContentSize().width); } break; } } else { break; } } } else { // drag right while(1) { unsigned int nFirstRow = m_drawedRows.location; CCListViewCell *cell = cellAtRow(nFirstRow); if (cell) { CCPoint ptCell = cell->convertToWorldSpace(CCPointZero); CCPoint ptView = this->convertToWorldSpace(CCPointZero); if (nFirstRow > 0) { float offset = ptView.x - ptCell.x; if (offset < dis) { appendRowToFront(nFirstRow - 1); } else { dis = offset; break; } } else { // already is the first row float leftMin = cell->getContentSize().width / 5; float offset = ptCell.x + dis - (ptView.x + this->getContentSize().width); if (offset > leftMin) { dis = ptView.x + this->getContentSize().width - leftMin - ptCell.x; } offset = ptView.x - ptCell.x; if (offset > 0) { dis = offset; } break; } } else { } } } disX = dis; disY = 0; } else if (CCListViewModeVertical == m_nMode) { if (CCListViewSlideDirUp == m_nSlideDir) { // drag up while(1) { unsigned int nLastRow = CCRange::CCMaxRange(m_drawedRows); CCListViewCell *cell = cellAtRow(nLastRow); if (cell) { CCPoint ptCell = cell->convertToWorldSpace(CCPointZero); CCPoint ptView = this->convertToWorldSpace(CCPointZero); if (nLastRow < m_nNumberOfRows - 1) { float offset = ptView.y - ptCell.y; if (offset < dis) { appendRowToBack(nLastRow + 1); } else { dis = offset; break; } } else { // already is the last row m_fActionDuration *= 0.5; float leftMin = cell->getContentSize().height / 5; float offset = ptCell.y + dis - (ptView.y + this->getContentSize().height); if (offset > -leftMin) { dis = ptView.y + this->getContentSize().height - leftMin - ptCell.y; } break; } } else { break; } } } else { // drag down while(1) { unsigned int nFirstRow = m_drawedRows.location; CCListViewCell *cell = cellAtRow(nFirstRow); if (cell) { CCPoint ptCell = cell->convertToWorldSpace(CCPointZero); CCPoint ptView = this->convertToWorldSpace(CCPointZero); if (nFirstRow > 0) { float offset = ptView.y + this->getContentSize().height - (ptCell.y + cell->getContentSize().height); if (offset > dis) { appendRowToFront(nFirstRow - 1); } else { dis = offset; break; } } else { // already is the first row m_fActionDuration *= 0.5; float leftMin = cell->getContentSize().height / 5; float offset = ptCell.y + cell->getContentSize().height + dis - ptView.y; if (offset < leftMin) { dis = ptView.y + leftMin - (ptCell.y + cell->getContentSize().height); } break; } } else { } } } disX = 0; disY = dis; } m_nState = CCListViewStateEaseOut; CCMoveBy *moveBy = CCMoveBy::actionWithDuration(m_fActionDuration, CCPointMake(disX, disY)); CCEaseOut *ease = CCEaseOut::actionWithAction(moveBy, 3); CCFiniteTimeAction *actions = CCSequence::actions(ease, CCCallFunc::actionWithTarget(this, callfunc_selector(CCListView::finishEaseOut)), NULL); m_layerPanel->runAction(actions); } void CCListView::clearUnvisibleRows(void) { CCRange oldRange = m_drawedRows; for (unsigned int i = oldRange.location; i < oldRange.location + oldRange.length; i++) { CCListViewCell *cell = cellAtRow(i); if (cell) { CCPoint posCell = cell->convertToWorldSpace(CCPointZero); CCPoint posView = this->convertToWorldSpace(CCPointZero); if (CCListViewModeHorizontal == m_nMode) { if (posCell.x + cell->getContentSize().width <= posView.x) { m_layerPanel->removeChild(cell, true); } else { break; } } else if (CCListViewModeVertical == m_nMode) { if (posCell.y >= posView.y + this->getContentSize().height) { m_layerPanel->removeChild(cell, true); } else { break; } } } m_drawedRows.location++; m_drawedRows.length--; } oldRange = m_drawedRows; for (int i = oldRange.location + oldRange.length - 1; i >= (int)oldRange.location; i--) { CCListViewCell *cell = cellAtRow(i); if (cell) { CCPoint posCell = cell->convertToWorldSpace(CCPointZero); CCPoint posView = this->convertToWorldSpace(CCPointZero); if (CCListViewModeHorizontal == m_nMode) { if (posCell.x >= posView.x + this->getContentSize().width) { m_layerPanel->removeChild(cell, true); } else { break; } } else if (CCListViewModeVertical == m_nMode) { if (posCell.y + cell->getContentSize().height <= posView.y) { m_layerPanel->removeChild(cell, true); } else { break; } } } m_drawedRows.length--; } m_visibleRows = m_drawedRows; } /****************************************** **************Virturl Functions************ *******************************************/ void CCListView::registerWithTouchDispatcher() { CCDirector* pDirector = CCDirector::sharedDirector(); if (m_pListViewParent) { pDirector->getTouchDispatcher()->addTargetedDelegate(this, kCCMenuHandlerPriority - 1, false); } else { pDirector->getTouchDispatcher()->addTargetedDelegate(this, kCCMenuHandlerPriority - 2, false); } } void CCListView::onEnter(void) { if (0 == m_nNumberOfRows) { m_layerPanel->setPosition(CCPointZero); m_layerPanel->setContentSize(this->getContentSize()); // get number of rows m_nNumberOfRows = triggerNumberOfCells(); displayVisibleRows(); } CCLayerColor::onEnter(); } void CCListView::onExit(void) { CCLayerColor::onExit(); } void CCListView::visit(void) { if (!m_pListViewParent) { CCRect rectSelf; float factor = CC_CONTENT_SCALE_FACTOR(); rectSelf.origin = convertToWorldSpace(CCPoint(0,0)); rectSelf.origin.x *= factor; rectSelf.origin.y *= factor; rectSelf.size = this->getContentSize(); rectSelf.size.width *= factor; rectSelf.size.height *= factor; glScissor((GLsizei)rectSelf.origin.x, (GLsizei)rectSelf.origin.y, (GLsizei)rectSelf.size.width , (GLsizei)rectSelf.size.height); glEnable(GL_SCISSOR_TEST); } CCLayerColor::visit(); if (!m_pListViewParent) { glDisable(GL_SCISSOR_TEST); } } bool CCListView::ccTouchBegan(CCTouch* touch, CCEvent* event) { CC_UNUSED_PARAM(event); if (!isTouchInside(touch) || !getIsVisible() || !m_bIsEnabled) { return false; } if (m_pListViewParent && CCListViewSlideDirNone != m_pListViewParent->getSlideDir()) { return false; } CCArray *children = this->getChildren(); if (!m_bIsVisible || !children || children->count() == 0) { return false; } if (m_bIsOnTouch) { return false; } CCPoint touchPoint = touch->locationInView(); m_ptTouchBegan = m_ptTouchEnd = CCDirector::sharedDirector()->convertToGL(touchPoint); m_ptPanelOffset = m_layerPanel->getPosition(); m_timeTouchBegan = clock(); m_nCurrentRow = this->rowForTouch(touch); if (m_nCurrentRow != -1) { if (CCListViewStateWatting != m_nState) { stopActionImmediately(); } m_nState = CCListViewStateTrackingTouch; if (CCListViewSlideDirNone == m_nSlideDir) { this->selectCellAtRow(m_nCurrentRow); } else { m_nCurrentRow = -1; } m_bIsOnTouch = true; return true; } return false; } void CCListView::ccTouchMoved(CCTouch* touch, CCEvent* event) { CC_UNUSED_PARAM(event); if (CCListViewStateTrackingTouch != m_nState || !isTouchInside(touch) || !m_bIsEnabled) { return; } CCPoint touchPoint = touch->locationInView(); m_ptTouchEnd = CCDirector::sharedDirector()->convertToGL(touchPoint); CCListViewSlideDir nsliderDir = CCListViewSlideDirNone; if (m_pListViewParent && CCListViewSlideDirNone != m_pListViewParent->getSlideDir(m_ptTouchBegan, m_ptTouchEnd)) { return; } else { nsliderDir = getSlideDir(m_ptTouchBegan, m_ptTouchEnd); } if(CCListViewModeHorizontal == m_nMode && CCListViewSlideDirNone != nsliderDir) { m_nSlideDir = nsliderDir; m_layerPanel->setPosition(CCPointMake(m_ptPanelOffset.x + (m_ptTouchEnd.x - m_ptTouchBegan.x),m_ptPanelOffset.y)); if (CCListViewSlideDirLeft == m_nSlideDir) { // drag left unsigned int nLastRow = CCRange::CCMaxRange(m_drawedRows); if (nLastRow < m_nNumberOfRows - 1) { CCListViewCell *cell = cellAtRow(nLastRow); if (cell) { CCPoint posCell = cell->convertToWorldSpace(CCPointZero); CCPoint posView = this->convertToWorldSpace(CCPointZero); if (posCell.x + cell->getContentSize().width <= posView.x + this->getContentSize().width) { appendRowToBack(nLastRow + 1); } } } } else { // drag right unsigned int nFirstRow = m_drawedRows.location; if (nFirstRow > 0) { CCListViewCell *cell = cellAtRow(nFirstRow); CCPoint posCell = cell->convertToWorldSpace(CCPointZero); CCPoint posView = this->convertToWorldSpace(CCPointZero); if (posCell.x >= posView.x) { appendRowToFront(nFirstRow - 1); } } } } else if (CCListViewModeVertical == m_nMode && CCListViewSlideDirNone != nsliderDir) { m_nSlideDir = nsliderDir; m_layerPanel->setPosition(CCPointMake(m_ptPanelOffset.x, m_ptPanelOffset.y + (m_ptTouchEnd.y - m_ptTouchBegan.y))); if (CCListViewSlideDirUp == m_nSlideDir) { // drag up unsigned int nLastRow = CCRange::CCMaxRange(m_drawedRows); if (nLastRow < m_nNumberOfRows - 1) { CCListViewCell *cell = cellAtRow(nLastRow); CCPoint posCell = cell->convertToWorldSpace(CCPointZero); CCPoint posView = this->convertToWorldSpace(CCPointZero); if (posCell.y >= posView.y) { appendRowToBack(nLastRow + 1); } } } else { // drag down unsigned int nFirstRow = m_drawedRows.location; if (nFirstRow > 0) { CCListViewCell *cell = cellAtRow(nFirstRow); CCPoint posCell = cell->convertToWorldSpace(CCPointZero); CCPoint posView = this->convertToWorldSpace(CCPointZero); if (posCell.y + cell->getContentSize().height <= posView.y + this->getContentSize().height) { appendRowToFront(nFirstRow - 1); } } } } if (CCListViewSlideDirNone != m_nSlideDir && m_nCurrentRow != -1 && m_nCurrentRow != m_nSelectedRow) { this->unselectCellAtRow(m_nCurrentRow); } if (CCListViewSlideDirNone != m_nSlideDir && m_pListViewParent) { m_pListViewParent->setIsEnabled(false); } } void CCListView::ccTouchEnded(CCTouch* touch, CCEvent* event) { CC_UNUSED_PARAM(touch); CC_UNUSED_PARAM(event); if(m_nState != CCListViewStateTrackingTouch || !m_bIsEnabled) { m_bIsOnTouch = false; return; } m_fActionDuration = ND_LISTVIEW_ACTION_INTERVAL; clock_t timeElapse = clock() - m_timeTouchBegan; #if (CC_TARGET_PLATFORM != CC_PLATFORM_WIN32) && (CC_TARGET_PLATFORM != CC_PLATFORM_MAC) // It will take more time on mobile platform, this parameter may need to be adjusted according to the platform you use. timeElapse /= 200; #endif if(CCListViewSlideDirLeft == m_nSlideDir || CCListViewSlideDirRight == m_nSlideDir) { float dis = m_ptTouchEnd.x - m_ptTouchBegan.x; float speed = dis / timeElapse; if (fabs(speed) > 0.1 && timeElapse < 300) { easeOutWithDistance(dis * 3); } else { if (CCListViewSlideDirLeft == m_nSlideDir && isFullFill()) { // drag up fixLastRow(); } else { // drag down fixFirstRow(); } } } else if (CCListViewSlideDirUp == m_nSlideDir || CCListViewSlideDirDown == m_nSlideDir) { float dis = m_ptTouchEnd.y - m_ptTouchBegan.y; float speed = dis / timeElapse; if (fabs(speed) > 0.1 && timeElapse < 300) { easeOutWithDistance(dis * 3); } else { if (CCListViewSlideDirUp == m_nSlideDir && isFullFill()) { // drag up fixLastRow(); } else { // drag down fixFirstRow(); } } } else { finishFix(); } int currentRow = this->rowForTouch(touch); if (currentRow != -1 && isTouchInside(touch)) { if (currentRow == m_nCurrentRow) { if (CCListViewSlideDirNone == m_nSlideDir) { if (m_pListViewParent == NULL || (m_pListViewParent && CCListViewSlideDirNone == m_pListViewParent->getSlideDir())) { if (m_nSelectedRow != -1 && m_nSelectedRow != m_nCurrentRow) { this->unselectCellAtRow(m_nSelectedRow); } m_nSelectedRow = m_nCurrentRow; if (!this->isMenuTouch(touch, this->cellAtRow(m_nSelectedRow))) { triggerDidClickCellAtRow(m_nSelectedRow); } } } else { if (m_nSelectedRow != m_nCurrentRow) { this->unselectCellAtRow(m_nCurrentRow); } } } else { if (-1 != m_nCurrentRow) { this->unselectCellAtRow(m_nCurrentRow); } } } else { if (-1 != m_nCurrentRow) { this->unselectCellAtRow(m_nCurrentRow); m_nCurrentRow = -1; } } m_bIsOnTouch = false; } bool CCListView::isMenuTouch(CCTouch *touch, CCNode *parent) { if (dynamic_cast(parent)) { CCPoint touchPoint = touch->locationInView(); touchPoint.y = cocos2d::CCDirector::sharedDirector()->getWinSize().height - touchPoint.y; touchPoint = parent->convertToNodeSpace(touchPoint); CCRect rect = CCRectZero; rect.size = parent->getContentSize(); return CCRect::CCRectContainsPoint(rect, touchPoint); } else { CCArray *pChildrens = parent->getChildren(); if (pChildrens && pChildrens->count() > 0) { for (unsigned int i = 0; i < pChildrens->count(); i++) { CCNode *pChildren = (CCNode*)pChildrens->objectAtIndex(i); if (this->isMenuTouch(touch, pChildren)) { return true; } } } } return false; } void CCListView::ccTouchCancelled(CCTouch *touch, CCEvent *event) { CC_UNUSED_PARAM(touch); CC_UNUSED_PARAM(event); CCAssert(m_nState == CCListViewStateTrackingTouch, "[NdListview ccTouchCancelled] -- invalid state"); finishFix(); m_bIsOnTouch = false; } NS_CC_EXT_END