RUTableView.cpp 28 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093
  1. #include "RUTableView.h"
  2. NS_RU_BEGIN
  3. RUTableView* RUTableView::create(cocos2d::extension::TableViewDataSourceSmooth* dataSource, cocos2d::Size size)
  4. {
  5. return RUTableView::create(dataSource, size, nullptr);
  6. }
  7. RUTableView* RUTableView::create(cocos2d::extension::TableViewDataSourceSmooth *dataSource, cocos2d::Size size, cocos2d::Node *container)
  8. {
  9. RUTableView *table_view = new (std::nothrow) RUTableView();
  10. table_view->initWithViewSize(size, container);
  11. table_view->autorelease();
  12. table_view->setDataSource(dataSource);
  13. ///yjz_add
  14. RUTableDataModel* m = dynamic_cast<RUTableDataModel*>(dataSource) ;
  15. if(m)
  16. {
  17. bool opacity = m->cascadeOpacity() ;
  18. table_view->setCascadeOpacityEnabled(opacity) ;
  19. table_view->_container->setCascadeOpacityEnabled(opacity) ;
  20. }
  21. ///
  22. table_view->_updateCellPositions();
  23. table_view->_updateContentSize();
  24. return table_view;
  25. }
  26. void RUTableView::reloadData(bool cleanUp)
  27. {
  28. _oldDirection = Direction::NONE;
  29. for(const auto &cell : _cellsUsed) {
  30. if(_tableViewDelegate != nullptr) {
  31. _tableViewDelegate->tableCellWillRecycle(this, cell);
  32. }
  33. _cellsFreed.pushBack(cell);
  34. cell->reset();
  35. if (cell->getParent() == this->getContainer())
  36. {
  37. this->getContainer()->removeChild(cell, cleanUp);
  38. }
  39. }
  40. _indices->clear();
  41. _cellsUsed.clear();
  42. this->_updateCellPositions();
  43. this->_updateContentSize();
  44. if (_dataSource->numberOfCellsInTableView(this) > 0)
  45. {
  46. this->scrollViewDidScroll(this);
  47. }
  48. }
  49. void RUTableView::setVerticalFillOrder(VerticalFillOrder fillOrder,bool cleanUp)
  50. {
  51. if (_vordering != fillOrder)
  52. {
  53. _vordering = fillOrder;
  54. if (!_cellsUsed.empty())
  55. {
  56. this->reloadData(cleanUp);
  57. }
  58. }
  59. }
  60. void RUTableView::safeSetContentOffset(Vec2 offset)
  61. {
  62. // if(_bounceable && checkIsCanMove(offset))return;
  63. if(_bounceable) return;
  64. if (!_bounceable)
  65. {
  66. const Vec2 minOffset = this->minContainerOffset();
  67. const Vec2 maxOffset = this->maxContainerOffset();
  68. offset.x = MAX(minOffset.x, MIN(maxOffset.x, offset.x));
  69. offset.y = MAX(minOffset.y, MIN(maxOffset.y, offset.y));
  70. }
  71. _container->setPosition(offset);
  72. safeScrollViewDidScroll() ;
  73. }
  74. void RUTableView::safeScrollViewDidScroll()
  75. {
  76. long countOfItems = _dataSource->numberOfCellsInTableView(this);
  77. if (0 == countOfItems)
  78. {
  79. return;
  80. }
  81. if (_isUsedCellsDirty)
  82. {
  83. _isUsedCellsDirty = false;
  84. std::sort(_cellsUsed.begin(), _cellsUsed.end(), [](TableViewCell *a, TableViewCell *b) -> bool{
  85. return a->getIdx() < b->getIdx();
  86. });
  87. }
  88. ssize_t startIdx = 0, endIdx = 0, idx = 0, maxIdx = 0;
  89. Vec2 offset = this->getContentOffset() * -1;
  90. maxIdx = MAX(countOfItems-1, 0);
  91. if (_vordering == VerticalFillOrder::TOP_DOWN)
  92. {
  93. offset.y = offset.y + _viewSize.height/this->getContainer()->getScaleY();
  94. }
  95. startIdx = this->_indexFromOffset(offset);
  96. if (startIdx == CC_INVALID_INDEX)
  97. {
  98. startIdx = countOfItems - 1;
  99. }
  100. if (_vordering == VerticalFillOrder::TOP_DOWN)
  101. {
  102. offset.y -= _viewSize.height/this->getContainer()->getScaleY();
  103. }
  104. else
  105. {
  106. offset.y += _viewSize.height/this->getContainer()->getScaleY();
  107. }
  108. offset.x += _viewSize.width/this->getContainer()->getScaleX();
  109. endIdx = this->_indexFromOffset(offset);
  110. if (endIdx == CC_INVALID_INDEX)
  111. {
  112. endIdx = countOfItems - 1;
  113. }
  114. if (!_cellsUsed.empty())
  115. {
  116. auto cell = _cellsUsed.at(0);
  117. idx = cell->getIdx();
  118. while(idx < startIdx)
  119. {
  120. this->_moveCellOutOfSight(cell);
  121. if (!_cellsUsed.empty())
  122. {
  123. cell = _cellsUsed.at(0);
  124. idx = cell->getIdx();
  125. }
  126. else
  127. {
  128. break;
  129. }
  130. }
  131. }
  132. if (!_cellsUsed.empty())
  133. {
  134. auto cell = _cellsUsed.back();
  135. idx = cell->getIdx();
  136. while(idx <= maxIdx && idx > endIdx)
  137. {
  138. this->_moveCellOutOfSight(cell);
  139. if (!_cellsUsed.empty())
  140. {
  141. cell = _cellsUsed.back();
  142. idx = cell->getIdx();
  143. }
  144. else
  145. {
  146. break;
  147. }
  148. }
  149. }
  150. for (long i = startIdx; i <= endIdx; i++)
  151. {
  152. if (_indices->find(i) != _indices->end())
  153. {
  154. continue;
  155. }
  156. this->updateCellAtIndex(i);
  157. }
  158. ///注释了ScrollViewDidScroll的此处
  159. // if(_tableViewDelegate != nullptr) {
  160. // _tableViewDelegate->scrollViewDidScroll(this);
  161. // }
  162. }
  163. int RUTableView::getVisibleCellIndex()
  164. {
  165. cocos2d::Rect viewRect = this->getViewRect();
  166. cocos2d::Vec2 point = getContainer()
  167. ->convertToNodeSpace(cocos2d::Vec2(viewRect.getMidX(),viewRect.getMidY())) ;
  168. int index = (int)this->_indexFromOffset(point);
  169. if(index<0)
  170. {
  171. int maxIndex = (int)_dataSource->numberOfCellsInTableView(this)-1;
  172. index = maxIndex ;
  173. }
  174. return index ;
  175. }
  176. Size RUTableView::tableSize()
  177. {
  178. return getContainer()->getContentSize() ;
  179. }
  180. Size RUTableView::maxCellSize()
  181. {
  182. return _dataSource->cellSizeForTable(this) ;
  183. }
  184. #pragma mark - 吸附
  185. void RUTableView::setAbsorb(bool absorb,bool bounced, bool bFixedIndex)
  186. {
  187. _absorb = absorb ;
  188. _absordBounced = bounced ;
  189. _fixedIndex4Absorb = bFixedIndex;
  190. if(_absorb)
  191. {
  192. scheduleUpdate() ;
  193. }
  194. else
  195. {
  196. unscheduleUpdate() ;
  197. }
  198. };
  199. int RUTableView::recycleIndex()
  200. {
  201. if(_recycle)
  202. {
  203. int total = (int)_dataSource->numberOfCellsInTableView(this) ;
  204. if(total%2==1)
  205. {
  206. //循环时,cell个数必须是偶数
  207. assert(0) ;
  208. }
  209. return total/ 2 - 1 ;
  210. }
  211. else
  212. {
  213. return INT_MIN ;
  214. }
  215. };
  216. Vec2 RUTableView::localDistanceToPercentViewSize(Vec2 worldPos,float percentX,float percentY)
  217. {
  218. Vec2 posInView(_viewSize.width*percentX/100,_viewSize.height*percentY/100) ;
  219. Vec2 worldPosInView ;
  220. worldPosInView = convertToWorldSpace(posInView) ;
  221. Vec2 viewPosInContainer ;
  222. Vec2 userPosInContaner ;
  223. AffineTransform toContainerSpace = _container->getWorldToNodeAffineTransform() ;
  224. viewPosInContainer = __CCPointApplyAffineTransform(viewPosInContainer, toContainerSpace) ;
  225. userPosInContaner = __CCPointApplyAffineTransform(worldPos,toContainerSpace) ;
  226. Vec2 distance = viewPosInContainer - userPosInContaner ;
  227. return distance ;
  228. }
  229. Vec2 RUTableView::offsetFromIndex(ssize_t cellIndex)
  230. {
  231. return _offsetFromIndex(cellIndex) ;
  232. }
  233. void RUTableView::setRecycle(bool recycle)
  234. {
  235. _recycle = recycle ;
  236. }
  237. #pragma mark - 自制
  238. void RUTableView::updateCellAtIndex(int cellIndex)
  239. {
  240. if (_indices->find(cellIndex) == _indices->end())
  241. {
  242. this->TableViewSmooth::updateCellAtIndex(cellIndex);
  243. }
  244. }
  245. float RUTableView::scrollToNodeInView(int cellIndex,Vec2 posInCell,Vec2 percentInView,float duration)
  246. {
  247. if (_indices->find(cellIndex) == _indices->end())
  248. {
  249. this->updateCellAtIndex(cellIndex);
  250. }
  251. float percentXInView = percentInView.x ;
  252. float percentYInView = percentInView.y ;
  253. Size viewSize = getViewSize() ;
  254. Vec2 posInView(viewSize.width*percentXInView/100,viewSize.height*percentYInView/100);
  255. Vec2 cellFloorOffset = _offsetFromIndex(cellIndex) ; //已包含对BOTTOM_UP和TOP_DOWN的判断
  256. Vec2 nodePos = cellFloorOffset + posInCell ;
  257. Vec2 offset ;
  258. if(_direction == cocos2d::extension::ScrollViewSmooth::Direction::VERTICAL)
  259. {
  260. float offsetY = nodePos.y - posInView.y ;
  261. offset.set(0, -offsetY) ;
  262. }
  263. setContentOffsetInDuration(offset,duration) ;
  264. return duration ;
  265. }
  266. float RUTableView::scrollToNodeInView(int cellIndex,Node* node,Vec2 percentInView,float duration,bool strict)
  267. {
  268. if (_indices->find(cellIndex) == _indices->end())
  269. {
  270. this->updateCellAtIndex(cellIndex);
  271. }
  272. float percentXInView = percentInView.x ;
  273. float percentYInView = percentInView.y ;
  274. Size viewSize = getViewSize() ;
  275. Vec2 posInView(viewSize.width*percentXInView/100,viewSize.height*percentYInView/100);
  276. Vec2 worldPos = node->convertToWorldSpaceAR(Vec2::ZERO) ;
  277. Vec2 nodePos = getContainer()->convertToNodeSpaceAR(worldPos) ;
  278. Vec2 offset ;
  279. if(_direction == cocos2d::extension::ScrollViewSmooth::Direction::VERTICAL)
  280. {
  281. float offsetY = nodePos.y - posInView.y ;
  282. offset.set(0, -offsetY) ;
  283. }
  284. if(duration<MATH_EPSILON)
  285. {
  286. if(strict)
  287. {
  288. const Vec2 minOffset = this->minContainerOffset();
  289. const Vec2 maxOffset = this->maxContainerOffset();
  290. offset.x = MAX(minOffset.x, MIN(maxOffset.x, offset.x));
  291. offset.y = MAX(minOffset.y, MIN(maxOffset.y, offset.y));
  292. }
  293. safeSetContentOffset(offset) ;
  294. }
  295. else
  296. {
  297. setContentOffsetInDuration(offset,duration) ;
  298. }
  299. return duration ;
  300. }
  301. bool RUTableView::scrollToPosInView(int index,Vec2 percentInCell,Vec2 percentInView,float duration,bool bounced)
  302. {
  303. stopDeaccelerateScrolling() ;
  304. float percentXInCell = percentInCell.x ;
  305. float percentYInCell = percentInCell.y ;
  306. float percentXInView = percentInView.x ;
  307. float percentYInView = percentInView.y ;
  308. Vec2 cellFloorOffset = _offsetFromIndex(index) ; //已包含对BOTTOM_UP和TOP_DOWN的判断
  309. auto cellSize = _dataSource->tableCellSizeForIndex(this, index) ;
  310. Vec2 posInCell(cellSize.width*percentXInCell/100,cellSize.height*percentYInCell/100) ;
  311. Vec2 posInContainer = cellFloorOffset + posInCell ;
  312. Vec2 posInViewSize(_viewSize.width*percentXInView/100,_viewSize.height*percentYInView/100);
  313. Vec2 offset ;
  314. if(_direction == cocos2d::extension::ScrollViewSmooth::Direction::VERTICAL)
  315. {
  316. float offsetY = posInContainer.y - posInViewSize.y ;
  317. offset.set(0, -offsetY) ;
  318. }
  319. Vec2 contentOffset = getContentOffset() ;
  320. if(std::fabs(contentOffset.y - offset.y)<MATH_EPSILON)
  321. {
  322. return false ;
  323. }
  324. if(duration<0)
  325. {
  326. safeSetContentOffset(offset) ;
  327. }
  328. else
  329. {
  330. if(bounced)
  331. {
  332. setContentOffsetInDurationByBounce(offset, duration,_AbsorbBounceDuration) ;
  333. }
  334. else
  335. {
  336. setContentOffsetInDuration(offset, duration) ;
  337. }
  338. }
  339. return true ;
  340. }
  341. RUTableView* RUTableView::clone()
  342. {
  343. auto forkSize = tableSize() ;
  344. auto fork = RUTableView::create(_dataSource,forkSize) ;
  345. fork->setDelegate(_tableViewDelegate);
  346. fork->setDirection(_direction) ;
  347. fork->TableViewSmooth::setVerticalFillOrder(_vordering);
  348. fork->setBounceable(false);
  349. fork->setAbsorb(false);
  350. Vec2 offset ;
  351. if(_direction == cocos2d::extension::ScrollViewSmooth::Direction::VERTICAL)
  352. {
  353. }
  354. if(_vordering == cocos2d::extension::TableViewSmooth::VerticalFillOrder::BOTTOM_UP)
  355. {
  356. offset = maxContainerOffset() ;
  357. }
  358. fork->setContentOffset(offset);
  359. // fork->setSwallowTouches(false) ;
  360. return fork ;
  361. }
  362. bool RUTableView::scrollToCellIndex(int index,float duration,bool bounced)
  363. {
  364. bool toScroll = scrollToPosInView(index, Vec2(50,100), Vec2(100,100), duration, bounced) ;
  365. return toScroll ;
  366. }
  367. void RUTableView::recycleScrollTo(int index)
  368. {
  369. if(_recycle )
  370. {
  371. _recycleScrollIndex = index % (recycleIndex()+1) ;
  372. }
  373. }
  374. void RUTableView::recycleScrollToInDuration(int index,float duration,bool bounced)
  375. {
  376. int targetCellIndex = index;
  377. int visualIndex = getVisibleCellIndex() ;
  378. if(targetCellIndex == visualIndex) return ;
  379. if(visualIndex > recycleIndex())
  380. {
  381. targetCellIndex += recycleIndex()+1 ;
  382. }
  383. bool toScroll = scrollToCellIndex(targetCellIndex,duration, bounced) ;
  384. if(toScroll)
  385. {
  386. scheduleOnce([this](float)
  387. {
  388. _recycleScrollIndex = INT_MIN ;
  389. }, duration, "recycleScroll") ;
  390. }
  391. }
  392. void RUTableView::recycleScrollTo(int index,float perCellDuration,bool bounced)
  393. {
  394. float duration ;
  395. {
  396. int targetCellIndex = index;
  397. int visualIndex = getVisibleCellIndex() ;
  398. if(targetCellIndex == visualIndex) return ;
  399. if(visualIndex > recycleIndex())
  400. {
  401. targetCellIndex += recycleIndex()+1 ;
  402. }
  403. int delta = std::abs(visualIndex-targetCellIndex);
  404. duration = delta * perCellDuration ;
  405. }
  406. recycleScrollToInDuration(index,duration,bounced) ;
  407. }
  408. #pragma mark - Proteced
  409. bool RUTableView::onTouchBegan(Touch *pTouch, Event *pEvent)
  410. {
  411. if (!_bScrollable) {
  412. return false;
  413. }
  414. if (TableViewSmooth::onTouchBegan(pTouch, pEvent)) {
  415. if (_cbWhileTouchedBegin) {
  416. _cbWhileTouchedBegin();
  417. }
  418. return true;
  419. }
  420. return false;
  421. }
  422. void RUTableView::onTouchMoved(Touch *pTouch, Event *pEvent)
  423. {
  424. TableViewSmooth::onTouchMoved(pTouch, pEvent) ;
  425. if (_cbWhileTouchedMoved) {
  426. _cbWhileTouchedMoved(_animatedScrollAction && !_animatedScrollAction->isDone());
  427. }
  428. }
  429. void RUTableView::onTouchEnded(Touch *pTouch, Event *pEvent)
  430. {
  431. TableViewSmooth::onTouchEnded(pTouch, pEvent) ;
  432. if (_cbWhileTouchedEnd) {
  433. _cbWhileTouchedEnd(_autoScrolling);
  434. }
  435. }
  436. void RUTableView::onTouchCancelled(Touch *pTouch, Event *pEvent)
  437. {
  438. TableViewSmooth::onTouchCancelled(pTouch, pEvent) ;
  439. if (_cbWhileTouchedEnd) {
  440. _cbWhileTouchedEnd(_autoScrolling);
  441. }
  442. }
  443. void RUTableView::absorbCell(bool byAni)
  444. {
  445. int visualIndex = _fixedIndex4Absorb == -1 ? getVisibleCellIndex() : _fixedIndex4Absorb;
  446. float distanceThreshold = .0f ;
  447. bool scroll = false ;
  448. if(_direction == cocos2d::extension::ScrollViewSmooth::Direction::VERTICAL)
  449. {
  450. distanceThreshold = _dataSource->tableCellSizeForIndex(this, visualIndex).height*_AbsorbDistanceFactor ;
  451. bool b1 = scrollDistanceFbs().y<distanceThreshold ;
  452. bool b2 = !isRecycleScrollAniRun() ;
  453. bool b3 = !_dragging ;
  454. bool b4 = !isAbsorbAniRun() ;
  455. if(b1 && b2 && b3 && b4)
  456. {
  457. scroll = true ;
  458. }
  459. else
  460. {
  461. scroll = false ;
  462. }
  463. }
  464. if(scroll)
  465. {
  466. if(byAni)
  467. {
  468. bool toScroll = scrollToCellIndex(visualIndex, _AbsorbDuration,_absordBounced) ;
  469. if(toScroll)
  470. {
  471. scheduleOnce([](float){}, _AbsorbDuration, "absorbCell") ;
  472. }
  473. }
  474. else
  475. {
  476. scrollToCellIndex(visualIndex, -1,false) ;
  477. }
  478. }
  479. }
  480. bool RUTableView::isAbsorbAniRun()
  481. {
  482. return isScheduled("absorbCell") ;
  483. }
  484. bool RUTableView::isRecycleScrollAniRun()
  485. {
  486. return isScheduled("recycleScroll") ;
  487. }
  488. void RUTableView::update(float dt)
  489. {
  490. if(isDraging())
  491. {
  492. unschedule("absorbCell") ;
  493. unschedule("recycleScroll") ;
  494. }
  495. if(_absorb)
  496. {
  497. absorbCell(true);
  498. }
  499. if( _recycleScrollIndex > INT_MIN && _absorb && _recycleScrollIndex <= recycleIndex())
  500. {
  501. if(!isAbsorbAniRun() && !isDraging() && !isRecycleScrollAniRun())
  502. {
  503. recycleScrollToInDuration(_recycleScrollIndex,_RecycleScrollDuration , true) ;
  504. }
  505. }
  506. ScrollViewSmooth::update(dt);
  507. }
  508. void RUTableView::setContentOffsetInDurationByBounce(Vec2 offset, float dt,float bounceDuration)
  509. {
  510. FiniteTimeAction *scroll, *expire;
  511. if (_animatedScrollAction) {
  512. stopAnimatedContentOffset();
  513. }
  514. scroll = MoveTo::create(dt, offset);
  515. EaseElasticOut* outBounce = EaseElasticOut::create(dynamic_cast<ActionInterval*>(scroll),bounceDuration) ;
  516. expire = CallFuncN::create(CC_CALLBACK_1(RUTableView::stoppedAnimatedScroll,this));
  517. _animatedScrollAction = _container->runAction(Sequence::create(outBounce, expire, nullptr));
  518. _animatedScrollAction->retain();
  519. this->schedule(CC_SCHEDULE_SELECTOR(RUTableView::performedAnimatedScroll));
  520. }
  521. void RUTableView::stopDeaccelerateScrolling()
  522. {
  523. scrollDistance(Vec2::ZERO) ;
  524. }
  525. RUTableView::~RUTableView()
  526. {
  527. //yjz_fix,model处
  528. // class model* model = dynamic_cast<class model*>(_dataSource) ;
  529. // if(model)
  530. // {
  531. // model->clear() ;
  532. // }
  533. }
  534. #pragma mark - 开放TableView/ScorllView变量的访问
  535. Action* RUTableView::animatedScrollAction()
  536. {
  537. return _animatedScrollAction ;
  538. }
  539. Vec2 RUTableView::scrollDistanceFbs()
  540. {
  541. return Vec2(std::fabs(_scrollDistance.x),std::fabs(_scrollDistance.y)); ;
  542. }
  543. void RUTableView::scrollDistance(Vec2 customDistance)
  544. {
  545. _scrollDistance = customDistance ;
  546. }
  547. bool RUTableView::isDraging()
  548. {
  549. return _dragging ;
  550. }
  551. bool RUTableView::isScrolling()
  552. {
  553. if(_animatedScrollAction)
  554. {
  555. if (!_animatedScrollAction->isDone()) {
  556. return true;
  557. }
  558. }
  559. return _autoScrolling;
  560. }
  561. Vector<TableViewCell*> RUTableView::getUsedCell()
  562. {
  563. return _cellsUsed ;
  564. }
  565. Vector<TableViewCell*> RUTableView::getFreeCell()
  566. {
  567. return _cellsFreed ;
  568. }
  569. #pragma mark - TableModel
  570. RUTableDataModel::~RUTableDataModel()
  571. {
  572. clear() ;
  573. }
  574. void RUTableDataModel::clear()
  575. {
  576. for(auto iter : _cellMap)
  577. {
  578. iter.second->release() ;
  579. }
  580. _cellMap.clear() ;
  581. }
  582. Node* RUTableDataModel::getCell(int index)
  583. {
  584. if(_cellMap.find(index) == _cellMap.end()) return NULL;
  585. return _cellMap[index] ;
  586. }
  587. void RUTableDataModel::insertCell(int index,Node* cell)
  588. {
  589. if(_cellMap.find(index) != _cellMap.end())
  590. {
  591. _cellMap[index]->release() ;
  592. _cellMap.erase(index) ;
  593. }
  594. _cellMap[index] = cell ;
  595. cell->retain() ;
  596. }
  597. void RUTableDataModel::setCascadeOpacity(bool cascadeOpacity)
  598. {
  599. _cascadeOpacity = cascadeOpacity;
  600. }
  601. bool RUTableDataModel::cascadeOpacity()
  602. {
  603. return _cascadeOpacity ;
  604. }
  605. void RUTableDataModel::scrollViewDidScroll(ScrollViewSmooth* scrollView)
  606. {
  607. RUTableView* view = dynamic_cast<RUTableView*>(scrollView) ;
  608. RUTableDataModel* model = dynamic_cast<RUTableDataModel*>(view->getDataSource()) ;
  609. if(view && model)
  610. {
  611. if(view->recycleIndex() != INT_MIN)
  612. {
  613. if(view->getDirection() == cocos2d::extension::ScrollViewSmooth::Direction::VERTICAL)
  614. {
  615. Size viewSize = view->getViewSize() ;
  616. Vec2 minContainerOffset = view->minContainerOffset() ;
  617. Vec2 maxContainerOffset = view->maxContainerOffset() ;
  618. Vec2 contentOffset = view->getContentOffset() ;
  619. float cellHeight = model->tableCellSizeForIndex(view, view->recycleIndex()).height ;
  620. Vec2 boardCellFloorOffset = view->offsetFromIndex(view->recycleIndex()) ;
  621. //cell上边界偏移
  622. Vec2 cellCeilOffset = boardCellFloorOffset + Vec2(0, cellHeight) ;
  623. //cell与ViewSize顶对齐时,container的偏移
  624. Vec2 cellAlignViewCeilOffset(cellCeilOffset.x,cellCeilOffset.y - viewSize.height );
  625. if(contentOffset.y >= maxContainerOffset.y )
  626. {
  627. float deltaY = contentOffset.y - maxContainerOffset.y ;
  628. cellCeilOffset.y -= deltaY ;
  629. view->safeSetContentOffset(-cellCeilOffset) ;
  630. }
  631. if(contentOffset.y <= minContainerOffset.y)
  632. {
  633. float deltaY = contentOffset.y - minContainerOffset.y ;
  634. cellAlignViewCeilOffset.y+=deltaY ;
  635. view->safeSetContentOffset(-cellAlignViewCeilOffset) ;
  636. }
  637. }
  638. }
  639. }
  640. if(_scrollViewDidScroll)
  641. {
  642. _scrollViewDidScroll(scrollView) ;
  643. }
  644. // CCLOG("tableCellAtIndex %f,%f",scrollView->getContentOffset().x,scrollView->getContentOffset().y);
  645. }
  646. #pragma mark - TableViewDataSource
  647. Size RUTableDataModel::cellSizeForTable(TableViewSmooth* table)
  648. {
  649. if(_cellSizeForTable)
  650. return _cellSizeForTable(table) ;
  651. return Size() ;
  652. }
  653. ssize_t RUTableDataModel::numberOfCellsInTableView(TableViewSmooth *table)
  654. {
  655. if(_numberOfCellsInTableView)
  656. return _numberOfCellsInTableView(table) ;
  657. else
  658. {
  659. return _cellMap.size() ;
  660. }
  661. return 0 ;
  662. }
  663. Size RUTableDataModel::tableCellSizeForIndex(TableViewSmooth* table, ssize_t idx)
  664. {
  665. if(_tableCellSizeForIndex)
  666. return _tableCellSizeForIndex(table,idx) ;
  667. return Size() ;
  668. }
  669. TableViewCell* RUTableDataModel::tableCellAtIndex(TableViewSmooth *table, ssize_t idx)
  670. {
  671. if(_tableCellAtIndex)
  672. return _tableCellAtIndex(table,idx) ;
  673. else
  674. {
  675. // CCLOG("tableCellAtIndex:%d",(int)idx) ;
  676. TableViewCell *cell = table->dequeueCell();
  677. if (cell == nullptr)
  678. {
  679. cell = new (std::nothrow) TableViewCell();
  680. cell -> autorelease() ;
  681. }
  682. else
  683. {
  684. cell->removeAllChildrenWithCleanup(false) ;
  685. }
  686. auto iter = _cellMap.find((int)idx) ;
  687. if(iter != _cellMap.end())
  688. {
  689. Node*& cellLayer = iter->second ;
  690. cellLayer->removeFromParentAndCleanup(false);
  691. cell->addChild(cellLayer) ;
  692. cell->setLocalZOrder(cellLayer->getLocalZOrder()) ;
  693. }
  694. cell->setCascadeOpacityEnabled(_cascadeOpacity) ;
  695. return cell ;
  696. }
  697. return NULL;
  698. }
  699. #pragma mark - TableViewDelegate
  700. void RUTableDataModel::tableCellTouched(TableViewSmooth* table, TableViewCell* cell)
  701. {
  702. if(_tableCellTouched)
  703. _tableCellTouched(table,cell) ;
  704. }
  705. void RUTableDataModel::tableCellTouchedHandle(TableViewSmooth* table, TableViewCell* cell, Touch *pTouch)
  706. {
  707. }
  708. void RUTableDataModel::singleCycle(int i_max,std::function<bool(int i)> callback)
  709. {
  710. for(int i=0; i<=i_max ; ++i)
  711. {
  712. if(!callback(i))
  713. {
  714. break ;
  715. }
  716. }
  717. }
  718. void RUTableDataModel::mutiCycle(int i_max,std::function<bool(int i,int cumulate_i)> callback)
  719. {
  720. for(int i=0,cumulate_i=0 ;; i_max==i ? i=-1:0, ++i,++cumulate_i)
  721. {
  722. if(!callback(i,cumulate_i))
  723. {
  724. break ;
  725. }
  726. }
  727. }
  728. void RUTableDataModel::checkLegality()
  729. {
  730. int cycle_body_count = 0 ;
  731. for(auto& iter : table_regular)
  732. {
  733. int count = std::get<1>(iter) ;
  734. if(count >= 0 )
  735. {
  736. continue;
  737. }
  738. if(count == -1 )
  739. {
  740. ++cycle_body_count ;
  741. }
  742. else
  743. {
  744. assert(0);
  745. }
  746. }
  747. if(cycle_body_count>1)
  748. {
  749. assert(0);
  750. }
  751. }
  752. void RUTableDataModel::expandConfig()
  753. {
  754. int level_max = _config.level_count ;
  755. for(auto iter : table_regular)
  756. {
  757. int cycle_count = std::abs(std::get<1>(iter)) ;
  758. for(int i=0; i<cycle_count ; ++i)
  759. {
  760. CA.insert( CA.end(),
  761. std::get<0>(iter).begin(),
  762. std::get<0>(iter).end()) ;
  763. if((int)CA.size() >= level_max)
  764. {
  765. CA.resize(level_max) ;
  766. return ;
  767. }
  768. }
  769. }
  770. }
  771. cocos2d::Size RUTableDataModel::TableSize()
  772. {
  773. cocos2d::Size total ;
  774. if(total.equals(cocos2d::Size::ZERO) || _dirty)
  775. {
  776. if(_config.layOut == LayOut::HORIZONTAL)
  777. {
  778. total.height = CA[0].cell_size.height ;
  779. for(auto& iter : CA)
  780. {
  781. total.width += iter.cell_size.width ;
  782. }
  783. }
  784. else
  785. {
  786. total.width = CA[0].cell_size.width ;
  787. for(auto& iter : CA)
  788. {
  789. total.height += iter.cell_size.height ;
  790. }
  791. }
  792. }
  793. return total ;
  794. }
  795. int RUTableDataModel::FrameCount()
  796. {
  797. int total = 0 ;
  798. if(total == 0 || _dirty)
  799. {
  800. for(auto& iter : CA)
  801. {
  802. total+=iter.frame_count ;
  803. }
  804. }
  805. return total ;
  806. }
  807. int RUTableDataModel::CellCount()
  808. {
  809. int total = 0 ;
  810. if(total == 0 || _dirty)
  811. {
  812. total = (int)CA.size() ;
  813. }
  814. return total ;
  815. }
  816. int RUTableDataModel::CellCount(int in_frameGlobalIndex)
  817. {
  818. int out_cellCnt=0 ;
  819. singleCycle((int)CA.size()-1, [&](int i)->bool
  820. {
  821. in_frameGlobalIndex -= CA[i].frame_count ;
  822. ++out_cellCnt ;
  823. if(in_frameGlobalIndex<=0)
  824. {
  825. return false;
  826. }
  827. return true ;
  828. });
  829. if(in_frameGlobalIndex<=0)
  830. {
  831. return out_cellCnt;
  832. }
  833. else
  834. {
  835. assert(0) ;
  836. }
  837. }
  838. bool RUTableDataModel::checkCellExist(int cellIndex)
  839. {
  840. if(cellIndex+1>CellCount())
  841. {
  842. CCLOG("指定cell不存在");
  843. assert(0) ;
  844. return false;
  845. }
  846. return true ;
  847. }
  848. bool RUTableDataModel::checkFrameExist(int frameIndex)
  849. {
  850. if(frameIndex+1>FrameCount())
  851. {
  852. CCLOG("指定frame不存在");
  853. assert(0) ;
  854. return false;
  855. }
  856. return true ;
  857. }
  858. int RUTableDataModel::FrameNeedCountForFullCell(int in_visibleFrames)
  859. {
  860. // checkFrameExist(in_visibleFrames-1) ;
  861. int out_add2FullCell = 0 ;
  862. singleCycle((int)CA.size()-1, [&](int i)->bool
  863. {
  864. CCLOG("get_add2FullCell_head");
  865. in_visibleFrames -= CA[i].frame_count ;
  866. if(in_visibleFrames<0)
  867. {
  868. out_add2FullCell = -in_visibleFrames ;
  869. return false ;
  870. }
  871. return true ;
  872. }) ;
  873. if(in_visibleFrames>=0)
  874. {
  875. assert(0);
  876. }
  877. return out_add2FullCell;
  878. }
  879. void RUTableDataModel::get_cell_and_localFrameIndex_by_globalFrameIndex(int& cellIndex,int& localFrameIndex,int globalFrameIndex)
  880. {
  881. checkFrameExist(globalFrameIndex) ;
  882. singleCycle((int)CA.size()-1, [&](int i)->bool
  883. {
  884. CCLOG("get_cellIndex_and_fIdx");
  885. int remain = (globalFrameIndex -= CA[i].frame_count);
  886. if(remain < 0 )
  887. {
  888. cellIndex = i ;
  889. localFrameIndex = CA[i].frame_count + remain ;
  890. return false ;
  891. }
  892. return true ;
  893. }) ;
  894. };
  895. void RUTableDataModel::getOffsetByCellGlobalIndex(int cellGlobalIndex,float& out_offsetX)
  896. {
  897. checkCellExist(cellGlobalIndex) ;
  898. out_offsetX = .0f ;
  899. singleCycle((int)CA.size()-1, [&](int i)->bool
  900. {
  901. if(i>cellGlobalIndex)
  902. {
  903. return false ;
  904. }
  905. out_offsetX += CA[i].cell_size.width;
  906. return true;
  907. });
  908. }
  909. void RUTableDataModel::getCellWidth(int cellGlobalIndex,float& out_cellWidth)
  910. {
  911. checkCellExist(cellGlobalIndex) ;
  912. out_cellWidth = .0f ;
  913. out_cellWidth = CA[cellGlobalIndex].cell_size.width ;
  914. }
  915. void RUTableDataModel::getGlobalIndexForFirstFrameInCell(int idx,int& out_startIdx)
  916. {
  917. checkCellExist(idx) ;
  918. out_startIdx= 0 ;
  919. int temp_idx = -1 ;
  920. singleCycle((int)CA.size()-1, [&](int i)->bool
  921. {
  922. ++temp_idx ;
  923. if(temp_idx==idx)
  924. {
  925. return false;
  926. }
  927. else
  928. {
  929. out_startIdx += CA[i].frame_count ;
  930. }
  931. return true ;
  932. });
  933. }
  934. void RUTableDataModel::getCellIndexByFrameGlobalIndex(int in_frameGlobalIndex,int& out_cellIndex)
  935. {
  936. out_cellIndex = 0 ;
  937. singleCycle((int)CA.size()-1, [&](int i)->bool{
  938. in_frameGlobalIndex -= CA[i].frame_count ;
  939. if(in_frameGlobalIndex<0)
  940. {
  941. ++out_cellIndex ;
  942. return false ;
  943. }
  944. else
  945. {
  946. ++out_cellIndex ;
  947. }
  948. return true ;
  949. }) ;
  950. }
  951. void RUTableDataModel::get_type_and_count_by_cellIdx(int cellGlobalIndex,int& out_frameCount,std::string & out_frameType)
  952. {
  953. checkCellExist(cellGlobalIndex) ;
  954. out_frameCount = 0 ;
  955. out_frameType = CA[cellGlobalIndex].frameType ;
  956. out_frameCount = (int)CA[cellGlobalIndex].frame_count;
  957. }
  958. std::string RUTableDataModel::getCellCCB(int cellGlobalIndex)
  959. {
  960. checkCellExist(cellGlobalIndex);
  961. return CA[cellGlobalIndex].cellCCB ;
  962. }
  963. NS_RU_END