add new sigc++2 directory
[ardour.git] / libs / gtkmm2 / gtk / gtkmm / treeiter.cc
1 // Generated by gtkmmproc -- DO NOT MODIFY!
2
3
4 #include <gtkmm/treeiter.h>
5 #include <gtkmm/private/treeiter_p.h>
6
7 // -*- c++ -*-
8 /* $Id$ */
9
10 /* Copyright 1998-2002 The gtkmm Development Team
11  *
12  * This library is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Library General Public
14  * License as published by the Free Software Foundation; either
15  * version 2 of the License, or (at your option) any later version.
16  *
17  * This library is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Library General Public License for more details.
21  *
22  * You should have received a copy of the GNU Library General Public
23  * License along with this library; if not, write to the Free
24  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25  */
26
27 #include <gtkmm/treemodel.h>
28
29 namespace
30 {
31
32 // This is copied from Totem. In future there might be a version in GTK+ itself - see bug #
33 static void gtkmm_gtk_tree_model_iter_previous(GtkTreeModel* tree_model, GtkTreeIter* iter)
34 {
35   GtkTreePath *const path = gtk_tree_model_get_path(tree_model, iter);
36
37   if(gtk_tree_path_prev(path))
38     gtk_tree_model_get_iter(tree_model, iter, path);
39   else
40     g_assert_not_reached();
41
42   gtk_tree_path_free(path);
43 }
44
45 } // anonymous namespace
46
47
48 namespace Gtk
49 {
50
51 /**** Gtk::TreeIter ********************************************************/
52
53 TreeIter::TreeIter()
54 :
55   TreeIterBase(),
56   model_      (0),
57   is_end_     (false)
58 {}
59
60 TreeIter::TreeIter(TreeModel* model)
61 :
62   TreeIterBase(),
63   model_      (model),
64   is_end_     (false)
65 {}
66
67 TreeIter::TreeIter(GtkTreeModel* model, const GtkTreeIter* iter)
68 :
69   TreeIterBase(iter),
70   model_      (dynamic_cast<TreeModel*>(Glib::wrap_auto((GObject*) model))),
71   is_end_     (iter == 0)
72 {}
73
74 TreeIter& TreeIter::operator++()
75 {
76   g_assert(!is_end_);
77
78   GtkTreeIter previous = gobject_;
79
80   if(!gtk_tree_model_iter_next(model_->gobj(), &gobject_))
81   {
82     is_end_ = true;
83     gtk_tree_model_iter_parent(model_->gobj(), &gobject_, &previous);
84   }
85
86   return *this;
87 }
88
89 const TreeIter TreeIter::operator++(int)
90 {
91   g_assert(!is_end_);
92
93   TreeIter previous (*this);
94
95   if(!gtk_tree_model_iter_next(model_->gobj(), &gobject_))
96   {
97     is_end_ = true;
98     gtk_tree_model_iter_parent(model_->gobj(), &gobject_, &previous.gobject_);
99   }
100
101   return previous;
102 }
103
104 TreeIter& TreeIter::operator--()
105 {
106   if(!is_end_)
107   {
108     gtkmm_gtk_tree_model_iter_previous(model_->gobj(), &gobject_);
109   }
110   else // --end yields last
111   {
112     GtkTreeIter next = gobject_;
113     GtkTreeIter *const parent = (next.stamp != 0) ? &next : 0;
114
115     const int index = gtk_tree_model_iter_n_children(model_->gobj(), parent) - 1;
116     is_end_ = !gtk_tree_model_iter_nth_child(model_->gobj(), &gobject_, parent, index);
117
118     g_assert(!is_end_);
119   }
120
121   return *this;
122 }
123
124 const TreeIter TreeIter::operator--(int)
125 {
126   TreeIter next (*this);
127
128   if(!is_end_)
129   {
130     gtkmm_gtk_tree_model_iter_previous(model_->gobj(), &gobject_);
131   }
132   else // --end yields last
133   {
134     GtkTreeIter *const parent = (next.gobject_.stamp != 0) ? &next.gobject_ : 0;
135
136     const int index = gtk_tree_model_iter_n_children(model_->gobj(), parent) - 1;
137     is_end_ = !gtk_tree_model_iter_nth_child(model_->gobj(), &gobject_, parent, index);
138
139     g_assert(!is_end_);
140   }
141
142   return next;
143 }
144
145 /* There is no public gtk_tree_iter_equal(), so we must write our own.
146  */
147 bool TreeIter::equal(const TreeIter& other) const
148 {
149   g_assert(model_ == other.model_);
150
151   // A GtkTreeIter has the same stamp value as its model.
152   g_assert(gobject_.stamp == other.gobject_.stamp || is_end_ || other.is_end_);
153
154   // If all user_data pointers are equal we can assume the iterators to be
155   // equal.  This should be safe since GtkTreeIter lacks destroy notification,
156   // thus there is no way to attach more data fields to the iterator.
157   return (is_end_ == other.is_end_) &&
158          (gobject_.user_data  == other.gobject_.user_data)  &&
159          (gobject_.user_data2 == other.gobject_.user_data2) &&
160          (gobject_.user_data3 == other.gobject_.user_data3);
161 }
162
163 TreeIter::operator bool() const
164 {
165   // Test whether the GtkTreeIter is valid and not an end iterator.  This check
166   // is almost the same as the private VALID_ITER() macro in gtkliststore.c and
167   // gtktreestore.c.
168   return (!is_end_ && gobject_.stamp != 0);
169 }
170
171 void TreeIter::setup_end_iterator(const TreeIter& last_valid)
172 {
173   g_assert(model_ == last_valid.model_);
174
175   if(last_valid.is_end_)
176     gobject_ = last_valid.gobject_;
177   else
178     gtk_tree_model_iter_parent(model_->gobj(), &gobject_, const_cast<GtkTreeIter*>(&last_valid.gobject_));
179
180   is_end_ = true;
181 }
182
183 void TreeIter::set_model_refptr(const Glib::RefPtr<TreeModel>& model)
184 {
185   model_ = model.operator->();
186 }
187
188 void TreeIter::set_model_gobject(GtkTreeModel* model)
189 {
190   model_ = dynamic_cast<TreeModel*>(Glib::wrap_auto((GObject*) model));
191 }
192
193 GtkTreeModel* TreeIter::get_model_gobject() const
194 {
195   return (model_) ? model_->gobj() : 0;
196 }
197
198
199 int TreeIter::get_stamp() const
200 {
201   return gobj()->stamp;
202 }
203
204 void TreeIter::set_stamp(int stamp)
205 {
206   gobj()->stamp = stamp;
207
208
209
210 /**** Gtk::TreeRow *********************************************************/
211
212 const TreeNodeChildren& TreeRow::children() const
213 {
214   g_assert(!is_end_);
215
216   return static_cast<const TreeNodeChildren&>(static_cast<const TreeIter&>(*this));
217 }
218
219 TreeIter TreeRow::parent() const
220 {
221   TreeIter iter (model_);
222
223   if(is_end_)
224     iter.gobject_ = gobject_;
225   else
226     gtk_tree_model_iter_parent(model_->gobj(), iter.gobj(), const_cast<GtkTreeIter*>(&gobject_));
227
228   return iter;
229 }
230
231 void TreeRow::set_value_impl(int column, const Glib::ValueBase& value) const
232 {
233   model_->set_value_impl(*this, column, value);
234 }
235
236 void TreeRow::get_value_impl(int column, Glib::ValueBase& value) const
237 {
238   model_->get_value_impl(*this, column, value);
239 }
240
241 TreeRow::operator bool() const
242 {
243   return TreeIter::operator bool();
244 }
245
246
247 /**** Gtk::TreeNodeChildren ************************************************/
248
249 TreeNodeChildren::iterator TreeNodeChildren::begin()
250 {
251   iterator iter (model_);
252
253   // If the iterator is invalid (stamp == 0), assume a 'virtual' toplevel
254   // node.  This behaviour is needed to implement Gtk::TreeModel::children().
255
256   if(gobject_.stamp != 0)
257   {
258     if(!gtk_tree_model_iter_children(model_->gobj(), iter.gobj(), const_cast<GtkTreeIter*>(&gobject_)))
259     {
260       // Assign the already known parent, in order to create an end iterator.
261       iter.gobject_ = gobject_;
262       iter.is_end_ = true;
263     }
264   }
265   else
266   {
267     if(!gtk_tree_model_get_iter_first(model_->gobj(), iter.gobj()))
268     {
269       // No need to copy the GtkTreeIter, since iter.gobject_ is already empty.
270       iter.is_end_ = true;
271     }
272   }
273
274   return iter;
275 }
276
277 TreeNodeChildren::const_iterator TreeNodeChildren::begin() const
278 {
279   //TODO: Reduce the copy/paste from the non-const begin()?
280   
281   const_iterator iter (model_);
282
283   // If the iterator is invalid (stamp == 0), assume a 'virtual' toplevel
284   // node.  This behaviour is needed to implement Gtk::TreeModel::children().
285
286   if(gobject_.stamp != 0)
287   {
288     if(!gtk_tree_model_iter_children(model_->gobj(), iter.gobj(), const_cast<GtkTreeIter*>(&gobject_)))
289     {
290       // Assign the already known parent, in order to create an end iterator.
291       iter.gobject_ = gobject_;
292       iter.is_end_ = true;
293     }
294   }
295   else
296   {
297     if(!gtk_tree_model_get_iter_first(model_->gobj(), iter.gobj()))
298     {
299       // No need to copy the GtkTreeIter, since iter.gobject_ is already empty.
300       iter.is_end_ = true;
301     }
302   }
303
304   return iter;
305 }
306
307 TreeNodeChildren::iterator TreeNodeChildren::end()
308 {
309   // Just copy the parent, and turn it into an end iterator.
310   iterator iter (*this);
311   iter.is_end_ = true;
312   return iter;
313 }
314
315 TreeNodeChildren::const_iterator TreeNodeChildren::end() const
316 {
317   // Just copy the parent, and turn it into an end iterator.
318   const_iterator iter (*this);
319   iter.is_end_ = true;
320   return iter;
321 }
322
323 TreeNodeChildren::value_type TreeNodeChildren::operator[](TreeNodeChildren::size_type index) const
324 {
325   iterator iter (model_);
326
327   GtkTreeIter *const parent = const_cast<GtkTreeIter*>(get_parent_gobject());
328
329   if(!gtk_tree_model_iter_nth_child(model_->gobj(), iter.gobj(), parent, index))
330   {
331     // Assign the already known parent, in order to create an end iterator.
332     iter.gobject_ = gobject_;
333     iter.is_end_ = true;
334   }
335
336   return *iter;
337 }
338
339 TreeNodeChildren::size_type TreeNodeChildren::size() const
340 {
341   GtkTreeIter *const parent = const_cast<GtkTreeIter*>(get_parent_gobject());
342
343   return gtk_tree_model_iter_n_children(model_->gobj(), parent);
344 }
345
346 bool TreeNodeChildren::empty() const
347 {
348   // If the iterator is invalid (stamp == 0), assume a 'virtual' toplevel
349   // node.  This behaviour is needed to implement Gtk::TreeModel::children().
350
351   if(gobject_.stamp == 0)
352   {
353     GtkTreeIter dummy;
354     return !gtk_tree_model_get_iter_first(model_->gobj(), &dummy);
355   }
356
357   return !gtk_tree_model_iter_has_child(model_->gobj(), const_cast<GtkTreeIter*>(&gobject_));
358 }
359
360 } // namespace Gtk
361
362
363 namespace
364 {
365 } // anonymous namespace
366
367
368 namespace Gtk
369 {
370
371
372 // static
373 GType TreeIterBase::get_type()
374 {
375   return gtk_tree_iter_get_type();
376 }
377
378 TreeIterBase::TreeIterBase()
379 {
380   GLIBMM_INITIALIZE_STRUCT(gobject_, GtkTreeIter);
381 }
382
383 TreeIterBase::TreeIterBase(const GtkTreeIter* gobject)
384 {
385   if(gobject)
386     gobject_ = *gobject;
387   else
388     GLIBMM_INITIALIZE_STRUCT(gobject_, GtkTreeIter);
389 }
390
391
392 } // namespace Gtk
393
394