]> git.sesse.net Git - vlc/blob - modules/gui/skins2/utils/var_tree.cpp
931e06db36b7b0c70b97d6a4289d163c6ff40157
[vlc] / 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_deleted( false ), m_readonly( false),
32     m_pData( NULL ), m_pParent( NULL )
33 {
34     // Create the position variable
35     m_cPosition = VariablePtr( new VarPercent( pIntf ) );
36     getPositionVar().set( 1.0 );
37 }
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                   void *pData )
43     : Variable( pIntf ), m_id( id ), m_cString( rcString ),
44     m_selected( selected ), m_playing( playing ), m_expanded( expanded ),
45     m_deleted( false ), m_readonly( readonly ),
46     m_pData( pData ), m_pParent( pParent )
47 {
48     // Create the position variable
49     m_cPosition = VariablePtr( new VarPercent( pIntf ) );
50     getPositionVar().set( 1.0 );
51 }
52
53 VarTree::~VarTree()
54 {
55 /// \todo check that children are deleted
56 }
57
58 void VarTree::add( int id, const UStringPtr &rcString, bool selected,
59                    bool playing, bool expanded, bool readonly,
60                    void *pData )
61 {
62     m_children.push_back( VarTree( getIntf(), this, id, rcString, selected,
63                                    playing, expanded, readonly,
64                                    pData ) );
65 }
66
67 void VarTree::delSelected()
68 {
69     Iterator it = begin();
70     while( it != end() )
71     {
72         //dig down the tree
73         if( size() ) it->delSelected();
74         //stay on some level
75         if( it->m_selected )
76         {
77             Iterator oldIt = it;
78             it++;
79             m_children.erase( oldIt );
80         }
81         else
82         {
83             it++;
84         }
85     }
86 }
87
88 void VarTree::clear()
89 {
90     m_children.clear();
91 }
92
93 VarTree::Iterator VarTree::operator[]( int n )
94 {
95     Iterator it;
96     int i;
97     for( it = begin(), i = 0;
98          i < n && it != end();
99          it++, i++ );
100     return it;
101 }
102
103 VarTree::ConstIterator VarTree::operator[]( int n ) const
104 {
105     ConstIterator it;
106     int i;
107     for( it = begin(), i = 0;
108          i < n && it != end();
109          it++, i++ );
110     return it;
111 }
112
113 VarTree::Iterator VarTree::getNextSibling( VarTree::Iterator current )
114 {
115     VarTree *p_parent = current->parent();
116     if( p_parent  && current != p_parent->end() )
117     {
118         Iterator it = current->parent()->begin();
119         while( it != p_parent->end() && it != current ) it++;
120         if( it != p_parent->end() )
121         {
122             it++;
123         }
124         return root()->end();
125     }
126     return root()->end();
127 }
128
129 /* find iterator to next ancestor
130  * ... which means parent++ or grandparent++ or grandgrandparent++ ... */
131 VarTree::Iterator VarTree::next_uncle()
132 {
133     VarTree *p_parent = parent();
134     if( p_parent != NULL )
135     {
136         VarTree *p_grandparent = p_parent->parent();
137         while( p_grandparent != NULL )
138         {
139             Iterator it = p_grandparent->begin();
140             while( it != p_grandparent->end() && &(*it) != p_parent ) it++;
141             if( it != p_grandparent->end() )
142             {
143                 it++;
144                 if( it != p_grandparent->end() )
145                 {
146                     return it;
147                 }
148             }
149             if( p_grandparent->parent() )
150             {
151                 p_parent = p_grandparent;
152                 p_grandparent = p_parent->parent();
153             }
154             else
155                 p_grandparent = NULL;
156         }
157     }
158
159     /* if we didn't return before, it means that we've reached the end */
160     return root()->end();
161 }
162
163 VarTree::Iterator VarTree::prev_uncle()
164 {
165     VarTree *p_parent = parent();
166     if( p_parent != NULL )
167     {
168         VarTree *p_grandparent = p_parent->parent();
169         while( p_grandparent != NULL )
170         {
171             Iterator it = p_grandparent->end();
172             while( it != p_grandparent->begin() && &(*it) != p_parent ) it--;
173             if( it != p_grandparent->begin() )
174             {
175                 it--;
176                 if( it != p_grandparent->begin() )
177                 {
178                     return it;
179                 }
180             }
181             if( p_grandparent->parent() )
182             {
183                 p_parent = p_grandparent;
184                 p_grandparent = p_parent->parent();
185             }
186             else
187                 p_grandparent = NULL;
188         }
189     }
190
191     /* if we didn't return before, it means that we've reached the end */
192     return root()->begin();
193 }
194
195
196 void VarTree::checkParents( VarTree *pParent )
197 {
198     m_pParent = pParent;
199     Iterator it = begin();
200     while( it != end() )
201     {
202         it->checkParents( this );
203         it++;
204     }
205 }
206
207 int VarTree::visibleItems()
208 {
209     int i_count = size();
210     Iterator it = begin();
211     while( it != end() )
212     {
213         if( it->m_expanded )
214         {
215             i_count += it->visibleItems();
216         }
217         it++;
218     }
219     return i_count;
220 }
221
222 VarTree::Iterator VarTree::getVisibleItem( int n )
223 {
224     Iterator it = begin();
225     while( it != end() )
226     {
227         n--;
228         if( n <= 0 ) return it;
229         if( it->m_expanded )
230         {
231             int i = n - it->visibleItems();
232             if( i <= 0 ) return it->getVisibleItem( n );
233             n = i;
234         }
235         it++;
236     }
237     return end();
238 }
239
240 VarTree::Iterator VarTree::getNextVisibleItem( Iterator it )
241 {
242     if( it->m_expanded && it->size() )
243     {
244         it = it->begin();
245     }
246     else
247     {
248         VarTree::Iterator it_old = it;
249         it++;
250         // Was 'it' the last brother? If so, look for uncles
251         if( it_old->parent() && it_old->parent()->end() == it )
252         {
253             it = it_old->next_uncle();
254         }
255     }
256     return it;
257 }
258
259 VarTree::Iterator VarTree::getPrevVisibleItem( Iterator it )
260 {
261     VarTree::Iterator it_old = it;
262     if( it == root()->begin() || it == ++(root()->begin()) ) return it;
263     if( it->parent() )
264     {
265     }
266     /* Was it the first child of its parent ? */
267     if( it->parent() && it == it->parent()->begin() )
268     {
269         /* Yes, get previous uncle */
270         it = it_old->prev_uncle();
271    }
272     else
273         it--;
274
275     /* We have found an expanded uncle, take its last child */
276     while( it != root()->begin() && it->size() && it->m_expanded )
277     {
278             it = it->end();
279             it--;
280     }
281     return it;
282 }
283
284 VarTree::Iterator VarTree::getNextItem( Iterator it )
285 {
286     if( it->size() )
287     {
288         it = it->begin();
289     }
290     else
291     {
292         VarTree::Iterator it_old = it;
293         it++;
294         // Was 'it' the last brother? If so, look for uncles
295         if( it_old->parent() && it_old->parent()->end() == it )
296         {
297             it = it_old->next_uncle();
298         }
299     }
300     return it;
301 }
302
303
304 VarTree::Iterator VarTree::findById( int id )
305 {
306     for (Iterator it = begin(); it != end(); ++it )
307     {
308         if( it->m_id == id )
309         {
310             return it;
311         }
312         Iterator result = it->findById( id );
313         if( result != it->end() ) return result;
314     }
315     return end();
316 }
317
318
319 void VarTree::ensureExpanded( VarTree::Iterator it )
320 {
321     /// Don't expand ourselves, only our parents
322     VarTree *current = &(*it);
323     current = current->parent();
324     while( current->parent() != NULL )
325     {
326         current->m_expanded = true;
327         current = current->parent();
328     }
329 }