PageRenderTime 64ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/modules/gui/skins2/utils/var_tree.cpp

https://gitlab.com/evilbinary/vlc
C++ | 472 lines | 382 code | 49 blank | 41 comment | 71 complexity | 3d5cfdbdcbf3e5eb88f5b0241541dc16 MD5 | raw file
  1. /*****************************************************************************
  2. * var_tree.cpp
  3. *****************************************************************************
  4. * Copyright (C) 2005 the VideoLAN team
  5. * $Id: b77985a7acb6aeed9f1ac86dc552bd678bfd6bfb $
  6. *
  7. * Authors: Antoine Cellerier <dionoea@videolan.org>
  8. * Clément Stenac <zorglub@videolan.org>
  9. * Erwan Tulou <erwan10@videolan.org>
  10. *
  11. * This program is free software; you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License as published by
  13. * the Free Software Foundation; either version 2 of the License, or
  14. * (at your option) any later version.
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License
  22. * along with this program; if not, write to the Free Software
  23. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  24. *****************************************************************************/
  25. #include "var_tree.hpp"
  26. #include <math.h>
  27. const std::string VarTree::m_type = "tree";
  28. VarTree::VarTree( intf_thread_t *pIntf )
  29. : Variable( pIntf ), m_pParent( NULL ), m_id( 0 ),
  30. m_readonly( false ), m_selected( false ),
  31. m_playing( false ), m_expanded( false ),
  32. m_flat( false ), m_dontMove( false )
  33. {
  34. // Create the position variable
  35. m_cPosition = VariablePtr( new VarPercent( pIntf ) );
  36. getPositionVar().set( 1.0 );
  37. getPositionVar().addObserver( this );
  38. }
  39. VarTree::VarTree( intf_thread_t *pIntf, VarTree *pParent, int id,
  40. const UStringPtr &rcString, bool selected, bool playing,
  41. bool expanded, bool readonly )
  42. : Variable( pIntf ), m_pParent( pParent ),
  43. m_id( id ), m_cString( rcString ),
  44. m_readonly( readonly ), m_selected( selected ),
  45. m_playing( playing ), m_expanded( expanded ),
  46. m_flat( false ), m_dontMove( false )
  47. {
  48. // Create the position variable
  49. m_cPosition = VariablePtr( new VarPercent( pIntf ) );
  50. getPositionVar().set( 1.0 );
  51. getPositionVar().addObserver( this );
  52. }
  53. VarTree::VarTree( const VarTree& v )
  54. : Variable( v.getIntf() ),
  55. m_children( v.m_children), m_pParent( v.m_pParent ),
  56. m_id( v.m_id ), m_cString( v.m_cString ),
  57. m_readonly( v.m_readonly ), m_selected( v.m_selected ),
  58. m_playing( v.m_playing ), m_expanded( v.m_expanded ),
  59. m_flat( false ), m_dontMove( false )
  60. {
  61. // Create the position variable
  62. m_cPosition = VariablePtr( new VarPercent( getIntf() ) );
  63. getPositionVar().set( 1.0 );
  64. getPositionVar().addObserver( this );
  65. }
  66. VarTree::~VarTree()
  67. {
  68. getPositionVar().delObserver( this );
  69. }
  70. VarTree::Iterator VarTree::add( int id, const UStringPtr &rcString,
  71. bool selected, bool playing, bool expanded, bool readonly,
  72. int pos )
  73. {
  74. Iterator it;
  75. if( pos == -1 )
  76. {
  77. it = m_children.end();
  78. }
  79. else
  80. {
  81. it = m_children.begin();
  82. for( int i = 0; i < pos && it != m_children.end(); ++it, i++ );
  83. }
  84. return m_children.insert( it,
  85. VarTree( getIntf(), this, id, rcString,
  86. selected, playing,
  87. expanded, readonly ) );
  88. }
  89. void VarTree::delSelected()
  90. {
  91. for( Iterator it = m_children.begin(); it != m_children.end(); )
  92. {
  93. if( it->m_selected )
  94. {
  95. Iterator oldIt = it;
  96. ++it;
  97. m_children.erase( oldIt );
  98. }
  99. }
  100. }
  101. void VarTree::clear()
  102. {
  103. m_children.clear();
  104. }
  105. VarTree::Iterator VarTree::getNextSiblingOrUncle()
  106. {
  107. VarTree *p_parent = parent();
  108. if( p_parent )
  109. {
  110. Iterator it = ++(getSelf());
  111. if( it != p_parent->m_children.end() )
  112. return it;
  113. else
  114. return next_uncle();
  115. }
  116. return root()->m_children.end();
  117. }
  118. VarTree::Iterator VarTree::getPrevSiblingOrUncle()
  119. {
  120. VarTree *p_parent = parent();
  121. if( p_parent )
  122. {
  123. Iterator it = getSelf();
  124. if( it != p_parent->m_children.begin() )
  125. return --it;
  126. else
  127. return prev_uncle();
  128. }
  129. return root()->m_children.end();
  130. }
  131. /* find iterator to next ancestor
  132. * ... which means parent++ or grandparent++ or grandgrandparent++ ... */
  133. VarTree::Iterator VarTree::next_uncle()
  134. {
  135. VarTree *p_parent = parent();
  136. if( p_parent )
  137. {
  138. VarTree *p_grandparent = p_parent->parent();
  139. while( p_grandparent )
  140. {
  141. Iterator it = ++(p_parent->getSelf());
  142. if( it != p_grandparent->m_children.end() )
  143. return it;
  144. p_parent = p_grandparent;
  145. p_grandparent = p_parent->parent();
  146. }
  147. }
  148. /* if we didn't return before, it means that we've reached the end */
  149. return root()->m_children.end();
  150. }
  151. VarTree::Iterator VarTree::prev_uncle()
  152. {
  153. VarTree *p_parent = parent();
  154. if( p_parent )
  155. {
  156. VarTree *p_grandparent = p_parent->parent();
  157. while( p_grandparent )
  158. {
  159. Iterator it = p_parent->getSelf();
  160. if( it != p_grandparent->m_children.begin() )
  161. return --it;
  162. p_parent = p_grandparent;
  163. p_grandparent = p_parent->parent();
  164. }
  165. }
  166. /* if we didn't return before, it means that we've reached the end */
  167. return root()->m_children.end();
  168. }
  169. int VarTree::visibleItems()
  170. {
  171. int i_count = size();
  172. for( Iterator it = m_children.begin(); it != m_children.end(); ++it )
  173. {
  174. if( it->m_expanded )
  175. {
  176. i_count += it->visibleItems();
  177. }
  178. }
  179. return i_count;
  180. }
  181. VarTree::Iterator VarTree::getVisibleItem( int n )
  182. {
  183. Iterator it = m_children.begin();
  184. while( it != m_children.end() )
  185. {
  186. n--;
  187. if( n <= 0 )
  188. return it;
  189. if( it->m_expanded )
  190. {
  191. int i;
  192. i = n - it->visibleItems();
  193. if( i <= 0 ) return it->getVisibleItem( n );
  194. n = i;
  195. }
  196. ++it;
  197. }
  198. return m_children.end();
  199. }
  200. VarTree::Iterator VarTree::getLeaf( int n )
  201. {
  202. Iterator it = m_children.begin();
  203. while( it != m_children.end() )
  204. {
  205. if( it->size() )
  206. {
  207. int i;
  208. i = n - it->countLeafs();
  209. if( i <= 0 ) return it->getLeaf( n );
  210. n = i;
  211. }
  212. else
  213. {
  214. n--;
  215. if( n <= 0 )
  216. return it;
  217. }
  218. ++it;
  219. }
  220. return m_children.end();
  221. }
  222. VarTree::Iterator VarTree::getNextVisibleItem( Iterator it )
  223. {
  224. if( it->m_expanded && it->size() )
  225. {
  226. it = it->m_children.begin();
  227. }
  228. else
  229. {
  230. Iterator it_old = it;
  231. ++it;
  232. // Was 'it' the last brother? If so, look for uncles
  233. if( it_old->parent() && it_old->parent()->m_children.end() == it )
  234. {
  235. it = it_old->next_uncle();
  236. }
  237. }
  238. return it;
  239. }
  240. VarTree::Iterator VarTree::getPrevVisibleItem( Iterator it )
  241. {
  242. if( it == root()->m_children.begin() )
  243. return it;
  244. if( it == root()->m_children.end() )
  245. {
  246. --it;
  247. while( it->size() && it->m_expanded )
  248. it = --(it->m_children.end());
  249. return it;
  250. }
  251. /* Was it the first child of its parent ? */
  252. VarTree *p_parent = it->parent();
  253. if( it == p_parent->m_children.begin() )
  254. {
  255. /* Yes, get its parent's it */
  256. it = p_parent->getSelf();
  257. }
  258. else
  259. {
  260. --it;
  261. /* We have found an older brother, take its last visible child */
  262. while( it->size() && it->m_expanded )
  263. it = --(it->m_children.end());
  264. }
  265. return it;
  266. }
  267. VarTree::Iterator VarTree::getNextItem( Iterator it )
  268. {
  269. if( it->size() )
  270. {
  271. it = it->m_children.begin();
  272. }
  273. else
  274. {
  275. Iterator it_old = it;
  276. ++it;
  277. // Was 'it' the last brother? If so, look for uncles
  278. if( it_old->parent() && it_old->parent()->m_children.end() == it )
  279. {
  280. it = it_old->next_uncle();
  281. }
  282. }
  283. return it;
  284. }
  285. VarTree::Iterator VarTree::getPrevItem( Iterator it )
  286. {
  287. if( it == root()->m_children.begin() )
  288. return it;
  289. if( it == root()->m_children.end() )
  290. {
  291. --it;
  292. while( it->size() )
  293. it = --(it->m_children.end());
  294. return it;
  295. }
  296. /* Was it the first child of its parent ? */
  297. VarTree *p_parent = it->parent();
  298. if( it == p_parent->m_children.begin() )
  299. {
  300. /* Yes, get its parent's it */
  301. it = p_parent->getSelf();
  302. }
  303. else
  304. {
  305. --it;
  306. /* We have found an older brother, take its last child */
  307. while( it->size() )
  308. it = --(it->m_children.end());
  309. }
  310. return it;
  311. }
  312. VarTree::Iterator VarTree::getNextLeaf( Iterator it )
  313. {
  314. do
  315. {
  316. it = getNextItem( it );
  317. }
  318. while( it != root()->m_children.end() && it->size() );
  319. return it;
  320. }
  321. VarTree::Iterator VarTree::getPrevLeaf( Iterator it )
  322. {
  323. Iterator it_new = it->getPrevSiblingOrUncle();
  324. if( it_new == root()->end() )
  325. return it_new;
  326. while( it_new->size() )
  327. it_new = --(it_new->m_children.end());
  328. return it_new;
  329. }
  330. VarTree::Iterator VarTree::getParent( Iterator it )
  331. {
  332. if( it->parent() )
  333. {
  334. return it->parent()->getSelf();
  335. }
  336. return m_children.end();
  337. }
  338. void VarTree::ensureExpanded( const Iterator& it )
  339. {
  340. /// Don't expand ourselves, only our parents
  341. VarTree *current = &(*it);
  342. current = current->parent();
  343. while( current->parent() )
  344. {
  345. current->m_expanded = true;
  346. current = current->parent();
  347. }
  348. }
  349. int VarTree::countLeafs()
  350. {
  351. if( size() == 0 )
  352. return 1;
  353. int i_count = 0;
  354. for( Iterator it = m_children.begin(); it != m_children.end(); ++it )
  355. {
  356. i_count += it->countLeafs();
  357. }
  358. return i_count;
  359. }
  360. VarTree::Iterator VarTree::firstLeaf()
  361. {
  362. Iterator b = root()->m_children.begin();
  363. if( b->size() ) return getNextLeaf( b );
  364. return b;
  365. }
  366. int VarTree::getIndex( const Iterator& item )
  367. {
  368. int index = 0;
  369. Iterator it;
  370. for( it = m_flat ? firstLeaf() : m_children.begin();
  371. it != m_children.end();
  372. it = m_flat ? getNextLeaf( it ) : getNextVisibleItem( it ) )
  373. {
  374. if( it == item )
  375. break;
  376. index++;
  377. }
  378. return (it == item) ? index : -1;
  379. }
  380. VarTree::Iterator VarTree::getItemFromSlider()
  381. {
  382. // a simple (int)(...) causes rounding errors !
  383. #ifdef _MSC_VER
  384. # define lrint (int)
  385. #endif
  386. VarPercent &rVarPos = getPositionVar();
  387. double percentage = rVarPos.get();
  388. int indexMax = m_flat ? (countLeafs() - 1)
  389. : (visibleItems() - 1);
  390. int index = lrint( (1.0 - percentage)*(double)indexMax );
  391. Iterator it_first = m_flat ? getLeaf( index + 1 )
  392. : getVisibleItem( index + 1 );
  393. return it_first;
  394. }
  395. void VarTree::setSliderFromItem( const Iterator& it )
  396. {
  397. VarPercent &rVarPos = getPositionVar();
  398. int indexMax = m_flat ? (countLeafs() - 1)
  399. : (visibleItems() - 1);
  400. int index = getIndex( it );
  401. double percentage = (1.0 - (double)index/(double)indexMax);
  402. m_dontMove = true;
  403. rVarPos.set( (float)percentage );
  404. m_dontMove = false;
  405. }
  406. void VarTree::onUpdate( Subject<VarPercent> &rPercent, void* arg )
  407. {
  408. (void)rPercent; (void)arg;
  409. onUpdateSlider();
  410. }
  411. void VarTree::unselectTree()
  412. {
  413. m_selected = false;
  414. for( Iterator it = m_children.begin(); it != m_children.end(); ++it )
  415. it->unselectTree();
  416. }
  417. VarTree::IteratorVisible VarTree::getItem( int index )
  418. {
  419. Iterator it =
  420. m_flat ? getLeaf( index + 1 )
  421. : getVisibleItem( index + 1 );
  422. return IteratorVisible( it, this );
  423. }