e6d8c1159f49faa922f65fa33a0700ab69f5ce70
[vlc.git] / modules / gui / skins2 / utils / var_tree.cpp
1 /*****************************************************************************
2  * var_tree.cpp
3  *****************************************************************************
4  * Copyright (C) 2005 VideoLAN
5  * $Id$
6  *
7  * Authors: Antoine Cellerier <dionoea@videolan.org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 #include "var_tree.hpp"
25
26
27 const string VarTree::m_type = "tree";
28
29 VarTree::VarTree( intf_thread_t *pIntf )
30     : Variable( pIntf ), m_id( 0 ), m_selected( false ), m_playing( false ),
31     m_expanded( false ), m_pData( NULL ), m_pParent( NULL )
32 {
33     // Create the position variable
34     m_cPosition = VariablePtr( new VarPercent( pIntf ) );
35     getPositionVar().set( 1.0 );
36 }
37
38 VarTree::VarTree( intf_thread_t *pIntf, VarTree *pParent, int id,
39                   const UStringPtr &rcString, bool selected, bool playing,
40                   bool expanded, void *pData )
41     : Variable( pIntf ), m_id( id ), m_cString( rcString ),
42     m_selected( selected ), m_playing( playing ), m_expanded( expanded ),
43     m_pData( pData ), m_pParent( pParent )
44 {
45     // Create the position variable
46     m_cPosition = VariablePtr( new VarPercent( pIntf ) );
47     getPositionVar().set( 1.0 );
48 }
49
50 VarTree::~VarTree()
51 {
52 /// \todo check that children are deleted
53 }
54
55 void VarTree::add( int id, const UStringPtr &rcString, bool selected,
56                    bool playing, bool expanded, void *pData )
57 {
58     m_children.push_back( VarTree( getIntf(), this, id, rcString, selected,
59                                    playing, expanded, pData ) );
60 }
61
62 void VarTree::delSelected()
63 {
64     Iterator it = begin();
65     while( it != end() )
66     {
67         //dig down the tree
68         if( size() ) it->delSelected();
69         //stay on some level
70         if( it->m_selected )
71         {
72             Iterator oldIt = it;
73             it++;
74             m_children.erase( oldIt );
75         }
76         else
77         {
78             it++;
79         }
80     }
81 }
82
83 void VarTree::clear()
84 {
85     m_children.clear();
86 }
87
88 VarTree::Iterator VarTree::operator[]( int n )
89 {
90     Iterator it;
91     int i;
92     for( it = begin(), i = 0;
93          i < n && it != end();
94          it++, i++ );
95     return it;
96 }
97
98 VarTree::ConstIterator VarTree::operator[]( int n ) const
99 {
100     ConstIterator it;
101     int i;
102     for( it = begin(), i = 0;
103          i < n && it != end();
104          it++, i++ );
105     return it;
106 }
107
108 /* find iterator to next ancestor
109  * ... which means parent++ or grandparent++ or grandgrandparent++ ... */
110 VarTree::Iterator VarTree::next_uncle()
111 {
112     VarTree *p_parent = parent();
113     if( p_parent != NULL )
114     {
115         VarTree *p_grandparent = p_parent->parent();
116         while( p_grandparent != NULL )
117         {
118             Iterator it = p_grandparent->begin();
119             while( it != p_grandparent->end() && &(*it) != p_parent ) it++;
120             if( it != p_grandparent->end() )
121             {
122                 it++;
123                 if( it != p_grandparent->end() )
124                 {
125                     return it;
126                 }
127             }
128             if( p_grandparent->parent() )
129             {
130                 p_parent = p_grandparent;
131                 p_grandparent = p_parent->parent();
132             }
133             else
134                 p_grandparent = NULL;
135         }
136     }
137
138     /* if we didn't return before, it means that we've reached the end */
139     return root()->end();
140 }
141
142 VarTree::Iterator VarTree::prev_uncle()
143 {
144     VarTree *p_parent = parent();
145     if( p_parent != NULL )
146     {
147         VarTree *p_grandparent = p_parent->parent();
148         while( p_grandparent != NULL )
149         {
150             Iterator it = p_grandparent->end();
151             while( it != p_grandparent->begin() && &(*it) != p_parent ) it--;
152             if( it != p_grandparent->begin() )
153             {
154                 it--;
155                 if( it != p_grandparent->begin() )
156                 {
157                     return it;
158                 }
159             }
160             if( p_grandparent->parent() )
161             {
162                 p_parent = p_grandparent;
163                 p_grandparent = p_parent->parent();
164             }
165             else
166                 p_grandparent = NULL;
167         }
168     }
169
170     /* if we didn't return before, it means that we've reached the end */
171     return root()->begin();
172 }
173
174
175 void VarTree::checkParents( VarTree *pParent )
176 {
177     m_pParent = pParent;
178     Iterator it = begin();
179     while( it != end() )
180     {
181         it->checkParents( this );
182         it++;
183     }
184 }
185
186 int VarTree::visibleItems()
187 {
188     int i_count = size();
189     Iterator it = begin();
190     while( it != end() )
191     {
192         if( it->m_expanded )
193         {
194             i_count += it->visibleItems();
195         }
196         it++;
197     }
198     return i_count;
199 }
200
201 VarTree::Iterator VarTree::getVisibleItem( int n )
202 {
203     Iterator it = begin();
204     while( it != end() )
205     {
206         n--;
207         if( n <= 0 ) return it;
208         if( it->m_expanded )
209         {
210             int i = n - it->visibleItems();
211             if( i <= 0 ) return it->getVisibleItem( n );
212             n = i;
213         }
214         it++;
215     }
216     return end();
217 }
218
219 VarTree::Iterator VarTree::getNextVisibleItem( Iterator it )
220 {
221     if( it->m_expanded && it->size() )
222     {
223         it = it->begin();
224     }
225     else
226     {
227         VarTree::Iterator it_old = it;
228         it++;
229         // Was 'it' the last brother? If so, look for uncles
230         if( it_old->parent() && it_old->parent()->end() == it )
231         {
232             it = it_old->next_uncle();
233         }
234     }
235     return it;
236 }
237
238 VarTree::Iterator VarTree::getPrevVisibleItem( Iterator it )
239 {
240     VarTree::Iterator it_old = it;
241     if( it == root()->begin() || it == ++(root()->begin()) ) return it;
242     if( it->parent() )
243     {
244     }
245     /* Was it the first child of its parent ? */
246     if( it->parent() && it == it->parent()->begin() )
247     {
248         /* Yes, get previous uncle */
249         it = it_old->prev_uncle();
250    }
251     else
252         it--;
253
254     /* We have found an expanded uncle, take its last child */
255     while( it != root()->begin() && it->size() && it->m_expanded )
256     {
257             it = it->end();
258             it--;
259     }
260     return it;
261 }
262
263 VarTree::Iterator VarTree::getNextItem( Iterator it )
264 {
265     if( it->size() )
266     {
267         it = it->begin();
268     }
269     else
270     {
271         VarTree::Iterator it_old = it;
272         it++;
273         // Was 'it' the last brother? If so, look for uncles
274         if( it_old->parent() && it_old->parent()->end() == it )
275         {
276             it = it_old->next_uncle();
277         }
278     }
279     return it;
280 }
281
282
283 VarTree::Iterator VarTree::findById( int id )
284 {
285     for (Iterator it = begin(); it != end(); ++it )
286     {
287         if( it->m_id == id )
288         {
289             return it;
290         }
291         Iterator result = it->findById( id );
292         if( result != it->end() ) return result;
293     }
294     return end();
295 }
296
297
298 void VarTree::ensureExpanded( VarTree::Iterator it )
299 {
300     /// Don't expand ourselves, only our parents
301     VarTree *current = &(*it);
302     current = current->parent();
303     while( current->parent() != NULL )
304     {
305         current->m_expanded = true;
306         current = current->parent();
307     }
308 }