Fix bugs in previous commit that caused FTBFS in synfig and ETL FTBFS with older...
[synfig.git] / synfig-studio / tags / synfigstudio_0_61_03 / synfig-studio / src / gtkmm / keyframetreestore.cpp
1 /* === S Y N F I G ========================================================= */
2 /*!     \file keyframetreestore.cpp
3 **      \brief Template File
4 **
5 **      $Id: keyframetreestore.cpp,v 1.1.1.1 2005/01/07 03:34:36 darco Exp $
6 **
7 **      \legal
8 **      Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 **
10 **      This package is free software; you can redistribute it and/or
11 **      modify it under the terms of the GNU General Public License as
12 **      published by the Free Software Foundation; either version 2 of
13 **      the License, or (at your option) any later version.
14 **
15 **      This package is distributed in the hope that it will be useful,
16 **      but WITHOUT ANY WARRANTY; without even the implied warranty of
17 **      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 **      General Public License for more details.
19 **      \endlegal
20 */
21 /* ========================================================================= */
22
23 /* === H E A D E R S ======================================================= */
24
25 #ifdef USING_PCH
26 #       include "pch.h"
27 #else
28 #ifdef HAVE_CONFIG_H
29 #       include <config.h>
30 #endif
31
32 #include "keyframetreestore.h"
33 #include <synfig/valuenode.h>
34 #include "iconcontroler.h"
35 #include <synfig/valuenode_timedswap.h>
36 #include <gtkmm/button.h>
37 #include <gtkmm/treerowreference.h>
38 #include <synfig/canvas.h>
39 #include <synfig/keyframe.h>
40 #include <time.h>
41 #include <cstdlib>
42 #include <ETL/smart_ptr>
43 #include <synfigapp/action.h>
44 #include <synfigapp/instance.h>
45 #include "onemoment.h"
46 #include <synfig/exception.h>
47
48 #endif
49
50 /* === U S I N G =========================================================== */
51
52 using namespace std;
53 using namespace etl;
54 using namespace synfig;
55 using namespace studio;
56
57 /* === M A C R O S ========================================================= */
58
59 /* === G L O B A L S ======================================================= */
60
61 KeyframeTreeStore_Class KeyframeTreeStore::keyframe_tree_store_class_;
62
63 /* === C L A S S E S & S T R U C T S ======================================= */
64
65 struct _keyframe_iterator
66 {
67         synfig::KeyframeList::iterator iter;
68         int ref_count;
69         int index;
70 };
71
72 /*
73 Gtk::TreeModel::iterator keyframe_iter_2_model_iter(synfig::KeyframeList::iterator iter,int index)
74 {
75         Gtk::TreeModel::iterator ret;
76         
77         _keyframe_iterator*& data(static_cast<_keyframe_iterator*&>(ret->gobj()->user_data));
78         data=new _keyframe_iterator();
79         data->ref_count=1;
80         data->iter=iter;
81         data->index=index;
82         
83         return ret;
84 }
85 */
86
87 synfig::KeyframeList::iterator model_iter_2_keyframe_iter(Gtk::TreeModel::iterator iter)
88 {
89         _keyframe_iterator* data(static_cast<_keyframe_iterator*>(iter->gobj()->user_data));
90         if(!data)
91                 throw std::runtime_error("bad data");
92         return data->iter;
93 }
94
95 int get_index_from_model_iter(Gtk::TreeModel::iterator iter)
96 {
97         _keyframe_iterator* data(static_cast<_keyframe_iterator*>(iter->gobj()->user_data));
98         if(!data)
99                 throw std::runtime_error("bad data");
100         return data->index;
101 }
102
103
104 /*
105 #ifndef TreeRowReferenceHack
106 class TreeRowReferenceHack
107 {
108         GtkTreeRowReference *gobject_;
109 public:
110         TreeRowReferenceHack():
111                 gobject_(0)
112         {
113         }
114         
115         TreeRowReferenceHack(const Glib::RefPtr<Gtk::TreeModel>& model, const Gtk::TreeModel::Path& path):
116                 gobject_ ( gtk_tree_row_reference_new(model->gobj(), const_cast<GtkTreePath*>(path.gobj())) )
117         {
118         }
119
120         TreeRowReferenceHack(const TreeRowReferenceHack &x):
121                 gobject_ ( x.gobject_?gtk_tree_row_reference_copy(x.gobject_):0 )
122         {
123                 
124         }
125
126         void swap(TreeRowReferenceHack & other)
127         {
128                 GtkTreeRowReference *const temp = gobject_;
129                 gobject_ = other.gobject_;
130                 other.gobject_ = temp;
131         }
132
133         const TreeRowReferenceHack &
134         operator=(const TreeRowReferenceHack &rhs)
135         {
136                 TreeRowReferenceHack temp (rhs);
137                 swap(temp);
138                 return *this;
139         }
140         
141         ~TreeRowReferenceHack()
142         {
143                 if(gobject_)
144                         gtk_tree_row_reference_free(gobject_);
145         }
146         
147         Gtk::TreeModel::Path get_path() { return Gtk::TreeModel::Path(gtk_tree_row_reference_get_path(gobject_),false); }
148         GtkTreeRowReference *gobj() { return gobject_; }
149 };
150 #endif
151 */
152
153 /* === P R O C E D U R E S ================================================= */
154
155 void clear_iterator(GtkTreeIter* iter)
156 {
157         iter->stamp=0;
158         iter->user_data=iter->user_data2=iter->user_data3=0;
159 }
160
161 /* === M E T H O D S ======================================================= */
162
163 const Glib::Class&
164 KeyframeTreeStore_Class::init()
165 {
166         if(!gtype_)
167         {
168                 class_init_func_ = &KeyframeTreeStore_Class::class_init_function;
169                 
170                 const GTypeInfo derived_info =
171                 {
172                         sizeof(GObjectClass),
173                         NULL,
174                         NULL,
175                         class_init_func_,
176                         NULL,
177                         NULL,
178                         sizeof(GObject),
179                         0,
180                         0,
181                         NULL
182                 };
183                 
184                 gtype_ = g_type_register_static(G_TYPE_OBJECT, "KeyframeTreeStore", &derived_info, GTypeFlags(0));
185                 Gtk::TreeModel::add_interface(get_type());
186         }
187         return *this;
188 }
189
190 void
191 KeyframeTreeStore_Class::class_init_function(gpointer g_class, gpointer class_data)
192 {
193         // ???
194 }
195
196 KeyframeTreeStore::KeyframeTreeStore(etl::loose_handle<synfigapp::CanvasInterface> canvas_interface_):
197         Glib::ObjectBase        ("KeyframeTreeStore"),
198         Glib::Object            (Glib::ConstructParams(keyframe_tree_store_class_.init(), (char*) 0)),
199         canvas_interface_       (canvas_interface_)
200 {
201         reset_stamp();
202         //reset_path_table();
203
204         canvas_interface()->signal_keyframe_added().connect(sigc::mem_fun(*this,&studio::KeyframeTreeStore::add_keyframe));
205         canvas_interface()->signal_keyframe_removed().connect(sigc::mem_fun(*this,&studio::KeyframeTreeStore::remove_keyframe));
206         canvas_interface()->signal_keyframe_changed().connect(sigc::mem_fun(*this,&studio::KeyframeTreeStore::change_keyframe));
207 }
208
209 KeyframeTreeStore::~KeyframeTreeStore()
210 {
211         synfig::info("KeyframeTreeStore::~KeyframeTreeStore(): Deleted");
212 }
213
214 Glib::RefPtr<KeyframeTreeStore>
215 KeyframeTreeStore::create(etl::loose_handle<synfigapp::CanvasInterface> canvas_interface_)
216 {
217         KeyframeTreeStore *store(new KeyframeTreeStore(canvas_interface_));
218         Glib::RefPtr<KeyframeTreeStore> ret(store);
219         assert(ret);
220         return ret;
221 }
222
223 void
224 KeyframeTreeStore::reset_stamp()
225 {
226         stamp_=time(0)+reinterpret_cast<int>(this);
227 }
228
229 /*
230 void
231 KeyframeTreeStore::reset_path_table()
232 {
233         Gtk::TreeModel::Children::iterator iter;
234         const Gtk::TreeModel::Children children(children());
235         path_table_.clear();    
236         for(iter = children.begin(); iter != children.end(); ++iter)
237         {
238                 Gtk::TreeModel::Row row(*iter);
239                 path_table_[(Keyframe)row[model.keyframe]]=TreeRowReferenceHack(Glib::RefPtr<KeyframeTreeStore>(this),Gtk::TreePath(row));
240         }
241 }
242 */
243
244
245 inline bool
246 KeyframeTreeStore::iterator_sane(const GtkTreeIter* iter)const
247 {
248         if(iter && iter->stamp==stamp_)
249                 return true;
250         g_warning("KeyframeTreeStore::iterator_sane(): Bad iterator stamp");
251         return false;
252 }
253
254 inline bool
255 KeyframeTreeStore::iterator_sane(const Gtk::TreeModel::iterator& iter)const
256 {
257         return iterator_sane(iter->gobj());
258 }
259
260 inline void
261 KeyframeTreeStore::dump_iterator(const GtkTreeIter* gtk_iter, const Glib::ustring &name)const
262 {
263 #if 0
264         if(!gtk_iter)
265         {
266                 g_warning("KeyframeTreeStore::dump_iterator: \"%s\" is NULL (Root?)",name.c_str());
267                 return;
268         }
269
270         _keyframe_iterator *iter(static_cast<_keyframe_iterator*>(gtk_iter->user_data));
271
272         if(gtk_iter->stamp!=stamp_ || !iter)
273         {
274                 g_warning("KeyframeTreeStore::dump_iterator: \"%s\" is INVALID",name.c_str());
275                 return;
276         }
277
278         if((unsigned)iter->index>=canvas_interface()->get_canvas()->keyframe_list().size())
279                 g_warning("KeyframeTreeStore::dump_iterator: \"%s\"(%p) has bad index(index:%d)",name.c_str(),gtk_iter,iter->index);
280
281         g_warning("KeyframeTreeStore::dump_iterator: \"%s\"(%p) ref:%d, index:%d, time:%s",name.c_str(),gtk_iter,iter->ref_count,iter->index,iter->iter->get_time().get_string().c_str());
282 #endif
283 }
284
285 inline void
286 KeyframeTreeStore::dump_iterator(const Gtk::TreeModel::iterator& iter, const Glib::ustring &name)const
287 {
288         dump_iterator(iter->gobj(),name);
289 }
290
291 int
292 KeyframeTreeStore::time_sorter(const Gtk::TreeModel::iterator &rhs,const Gtk::TreeModel::iterator &lhs)
293 {
294         const Model model;
295         
296         _keyframe_iterator *rhs_iter(static_cast<_keyframe_iterator*>(rhs->gobj()->user_data));
297         _keyframe_iterator *lhs_iter(static_cast<_keyframe_iterator*>(lhs->gobj()->user_data));
298         
299         Time diff(rhs_iter->iter->get_time()-lhs_iter->iter->get_time());
300         if(diff<0)
301                 return -1;
302         if(diff>0)
303                 return 1;
304         return 0;
305 }
306
307 void
308 KeyframeTreeStore::set_value_impl(const Gtk::TreeModel::iterator& row, int column, const Glib::ValueBase& value)
309 {
310         if(!iterator_sane(row))
311                 return;
312
313         if(column>=get_n_columns_vfunc())
314         {
315                 g_warning("KeyframeTreeStore::set_value_impl: Bad column (%d)",column);
316                 return;
317         }
318
319         if(!g_value_type_compatible(G_VALUE_TYPE(value.gobj()),get_column_type_vfunc(column)))
320         {
321                 g_warning("KeyframeTreeStore::set_value_impl: Bad value type");
322                 return;
323         }
324
325         _keyframe_iterator *iter(static_cast<_keyframe_iterator*>(row.gobj()->user_data));
326         
327         try
328         {
329                 if(column==model.time_delta.index())
330                 {                       
331                         Glib::Value<synfig::Time> x;
332                         g_value_init(x.gobj(),model.time.type());
333                         g_value_copy(value.gobj(),x.gobj());
334                         
335                         Time new_delta(x.get());
336                         if(new_delta<=Time::zero()+Time::epsilon())
337                         {
338                                 // Bad value
339                                 return;
340                         }
341                         
342                         Time old_delta((*row)[model.time_delta]);
343                         if(old_delta<=Time::zero()+Time::epsilon())
344                         {
345                                 // Bad old delta
346                                 return;
347                         }
348                         //Gtk::TreeModel::iterator row(row);
349                         //row++;
350                         //if(!row)return;
351                         
352                         Time change_delta(new_delta-old_delta);
353                         
354                         if(change_delta<=Time::zero()+Time::epsilon() &&change_delta>=Time::zero()-Time::epsilon())
355                         {
356                                 // Not an error, just no change
357                                 return;
358                         }
359                         
360                         // New Method
361                         {
362                                 Keyframe keyframe((*row)[model.keyframe]);
363                                 synfigapp::Action::Handle action(synfigapp::Action::create("keyframe_set_delta"));
364         
365                                 if(!action)return;
366                                 
367                                 action->set_param("canvas",canvas_interface()->get_canvas());
368                                 action->set_param("canvas_interface",canvas_interface());
369                                 action->set_param("keyframe",keyframe);
370                                 action->set_param("delta",change_delta);
371                                 
372                                 canvas_interface()->get_instance()->perform_action(action);
373                         }
374                         
375                         
376                         if(0)
377                         {       // Old Method The slowest method EVER!!!
378                                 OneMoment one_moment;
379                                 
380                                 // Create the action group
381                                 synfigapp::Action::PassiveGrouper group(canvas_interface()->get_instance().get(),_("Adjust Time"));
382                                 synfigapp::PushMode push_mode(canvas_interface(), synfigapp::MODE_NORMAL);
383                                 
384                                 Gtk::TreeModel::iterator iter(row);
385                                 if(change_delta<0)
386                                 {
387                                         //DEBUGPOINT();
388                                         KeyframeList keyframe_list(get_canvas()->keyframe_list());
389                                         synfig::KeyframeList::iterator iter(keyframe_list.find((*row)[model.keyframe]));
390                                         //DEBUGPOINT();
391                                         for(;iter!=keyframe_list.end();++iter)
392                                         {
393                                         //DEBUGPOINT();
394                                                 synfig::Keyframe keyframe(*iter);
395
396                                                 keyframe.set_time(keyframe.get_time()+change_delta);
397                         
398                                                 synfigapp::Action::Handle action(synfigapp::Action::create("keyframe_set"));
399                         
400                                                 if(!action)return;
401                                                 
402                                                 action->set_param("canvas",canvas_interface()->get_canvas());
403                                                 action->set_param("canvas_interface",canvas_interface());
404                                                 action->set_param("keyframe",keyframe);
405                                                 
406                                                 canvas_interface()->get_instance()->perform_action(action);
407                                         }
408                                 }
409                                 else
410                                 {
411                                         //DEBUGPOINT();
412                                         KeyframeList keyframe_list(get_canvas()->keyframe_list());
413                                         synfig::KeyframeList::reverse_iterator end(keyframe_list.find((*row)[model.keyframe]));
414                                         synfig::KeyframeList::reverse_iterator iter(keyframe_list.rbegin());
415                                         //end++;
416                                         //DEBUGPOINT();
417                                         for(;iter!=end;++iter)
418                                         {
419                                         //DEBUGPOINT();
420                                                 synfig::Keyframe keyframe(*iter);
421
422                                                 keyframe.set_time(keyframe.get_time()+change_delta);
423                         
424                                                 synfigapp::Action::Handle action(synfigapp::Action::create("keyframe_set"));
425                         
426                                                 if(!action)return;
427                                                 
428                                                 action->set_param("canvas",canvas_interface()->get_canvas());
429                                                 action->set_param("canvas_interface",canvas_interface());
430                                                 action->set_param("keyframe",keyframe);
431                                                 
432                                                 canvas_interface()->get_instance()->perform_action(action);
433                                         }
434                                 }
435                         }
436                         
437                         return;
438                 }
439                 else
440                 if(column==model.time.index())
441                 {
442                         OneMoment one_moment;
443
444                         Glib::Value<synfig::Time> x;
445                         g_value_init(x.gobj(),model.time.type());
446                         g_value_copy(value.gobj(),x.gobj());
447                         synfig::Keyframe keyframe(*iter->iter);
448
449                         synfig::info("KeyframeTreeStore::set_value_impl():old_time=%s",keyframe.get_time().get_string().c_str());
450                         keyframe.set_time(x.get());
451                         synfig::info("KeyframeTreeStore::set_value_impl():new_time=%s",keyframe.get_time().get_string().c_str());
452                         
453                         synfigapp::Action::Handle action(synfigapp::Action::create("keyframe_set"));
454                         
455                         if(!action)
456                                 return;
457                         
458                         action->set_param("canvas",canvas_interface()->get_canvas());
459                         action->set_param("canvas_interface",canvas_interface());
460                         action->set_param("keyframe",keyframe);
461                         
462                         canvas_interface()->get_instance()->perform_action(action);
463                 }
464                 else if(column==model.description.index())
465                 {
466                         Glib::Value<Glib::ustring> x;
467                         g_value_init(x.gobj(),model.description.type());
468                         g_value_copy(value.gobj(),x.gobj());
469                         synfig::Keyframe keyframe(*iter->iter);
470                         keyframe.set_description(x.get());
471
472                         synfigapp::Action::Handle action(synfigapp::Action::create("keyframe_set"));
473                         
474                         if(!action)
475                                 return;
476                         
477                         action->set_param("canvas",canvas_interface()->get_canvas());
478                         action->set_param("canvas_interface",canvas_interface());
479                         action->set_param("keyframe",keyframe);
480                         
481                         canvas_interface()->get_instance()->perform_action(action);
482                 }
483                 else if(column==model.keyframe.index())
484                 {
485                         g_warning("KeyframeTreeStore::set_value_impl: This column is read-only");
486                 }
487                 else
488                 {
489                         assert(0);
490                 }
491         }
492         catch(std::exception x)
493         {
494                 g_warning(x.what());
495         }       
496 }
497
498 Gtk::TreeModelFlags
499 KeyframeTreeStore::get_flags_vfunc ()
500 {
501         return Gtk::TREE_MODEL_LIST_ONLY;
502 }
503
504 int
505 KeyframeTreeStore::get_n_columns_vfunc ()
506 {
507         return model.size();
508 }
509
510 GType
511 KeyframeTreeStore::get_column_type_vfunc (int index)
512 {
513         return model.types()[index];
514 }
515
516 bool
517 KeyframeTreeStore::iter_next_vfunc (const iterator& xiter, iterator& iter_next) const
518 {
519         if(!iterator_sane(xiter)) return false;
520
521         _keyframe_iterator *iter(static_cast<_keyframe_iterator*>(xiter.gobj()->user_data));
522
523         if(iter->iter==canvas_interface()->get_canvas()->keyframe_list().end())
524                 return false;
525
526         _keyframe_iterator *next(new _keyframe_iterator());
527         iter_next.gobj()->user_data=static_cast<gpointer>(next);        
528         next->ref_count=1;
529         next->index=iter->index+1;
530         next->iter=iter->iter;
531         ++next->iter;
532
533         if(next->iter==canvas_interface()->get_canvas()->keyframe_list().end())
534                 return false;
535         
536         iter_next.gobj()->stamp=stamp_;         
537
538         return true;
539 }
540
541 /*
542 bool
543 KeyframeTreeStore::iter_next_vfunc (GtkTreeIter* gtk_iter)
544 {
545         if(!iterator_sane(gtk_iter)) return false;
546
547         _keyframe_iterator *iter(static_cast<_keyframe_iterator*>(gtk_iter->user_data));
548
549         // If we are already at the end, then we are very invalid
550         if(iter->iter==canvas_interface()->get_canvas()->keyframe_list().end())
551                 return false;
552         
553         ++(iter->iter);
554         
555         if(iter->iter==canvas_interface()->get_canvas()->keyframe_list().end())
556         {
557                 --(iter->iter);
558                 return false;
559         }
560         (iter->index)++;
561         return true;
562 }
563
564 bool
565 KeyframeTreeStore::iter_children_vfunc (GtkTreeIter* gtk_iter, const GtkTreeIter* parent)
566 {
567         dump_iterator(gtk_iter,"gtk_iter");
568         dump_iterator(parent,"parent");
569
570         if(!parent || !iterator_sane(parent))
571         {
572                 clear_iterator(gtk_iter);
573                 return false;
574         }
575         
576         _keyframe_iterator *iter(new _keyframe_iterator());
577         iter->ref_count=1;
578         iter->index=0;
579         iter->iter=canvas_interface()->get_canvas()->keyframe_list().begin();
580         
581         gtk_iter->user_data=static_cast<gpointer>(iter);
582         gtk_iter->stamp=stamp_;         
583
584         return true;    
585 }
586
587 bool
588 KeyframeTreeStore::iter_has_child_vfunc (const GtkTreeIter*parent)
589 {
590         dump_iterator(parent,"parent");
591
592         if(parent)
593                 return false;
594
595         return true;
596 }
597
598 int
599 KeyframeTreeStore::iter_n_children_vfunc (const GtkTreeIter* parent)
600 {
601         dump_iterator(parent,"parent");
602
603         if(parent)
604                 return 0;
605         
606         return canvas_interface()->get_canvas()->keyframe_list().size();
607 }
608 */
609
610 int
611 KeyframeTreeStore::iter_n_root_children_vfunc () const
612 {
613         return canvas_interface()->get_canvas()->keyframe_list().size();
614 }
615
616 bool
617 KeyframeTreeStore::iter_nth_root_child_vfunc (int n, iterator& xiter)const
618 {
619         if(canvas_interface()->get_canvas()->keyframe_list().size()==0)
620         {
621                 return false;
622         }
623
624         if(n<0)
625         {
626                 g_warning("KeyframeTreeStore::iter_nth_root_child_vfunc: Out of range (negative index)");
627                 return false;
628         }
629         if(n && (unsigned)n>=canvas_interface()->get_canvas()->keyframe_list().size())
630         {
631                 g_warning("KeyframeTreeStore::iter_nth_child_vfunc: Out of range (large index)");
632                 return false;
633         }
634
635         _keyframe_iterator *iter(new _keyframe_iterator());
636         iter->ref_count=1;
637         iter->index=n;
638         iter->iter=canvas_interface()->get_canvas()->keyframe_list().begin();
639         while(n--)
640         {
641                 if(iter->iter==canvas_interface()->get_canvas()->keyframe_list().end())
642                 {
643                         g_warning("KeyframeTreeStore::iter_nth_child_vfunc: >>>BUG<<< in %s on line %d",__FILE__,__LINE__);
644                         delete iter;
645                         return false;
646                 }
647                 ++iter->iter;
648         }
649         xiter.gobj()->user_data=static_cast<gpointer>(iter);    
650         xiter.gobj()->stamp=stamp_;     
651         return true;
652 }
653
654 /*
655 bool
656 KeyframeTreeStore::iter_nth_child_vfunc (GtkTreeIter* gtk_iter, const GtkTreeIter* parent, int n)
657 {
658         dump_iterator(parent,"parent");
659
660         if(parent)
661         {
662                 g_warning("KeyframeTreeStore::iter_nth_child_vfunc: I am a list");
663                 clear_iterator(gtk_iter);
664                 return false;
665         }
666
667
668         
669         _keyframe_iterator *iter(new _keyframe_iterator());
670         iter->ref_count=1;
671         iter->index=n;
672         iter->iter=canvas_interface()->get_canvas()->keyframe_list().begin();
673         while(n--)
674         {
675                 if(iter->iter==canvas_interface()->get_canvas()->keyframe_list().end())
676                 {
677                         g_warning("KeyframeTreeStore::iter_nth_child_vfunc: >>>BUG<<< in %s on line %d",__FILE__,__LINE__);
678                         delete iter;
679                         clear_iterator(gtk_iter);
680                         return false;
681                 }
682                 ++iter->iter;
683         }
684         
685         gtk_iter->user_data=static_cast<gpointer>(iter);
686         gtk_iter->stamp=stamp_;         
687         return true;
688 }
689
690 bool
691 KeyframeTreeStore::iter_parent_vfunc (GtkTreeIter* gtk_iter, const GtkTreeIter* child)
692 {
693         dump_iterator(child,"child");
694         iterator_sane(child);
695         clear_iterator(gtk_iter);
696         return false;
697 }
698 */
699
700 void
701 KeyframeTreeStore::ref_node_vfunc (iterator& xiter)const
702 {
703         GtkTreeIter* gtk_iter(xiter.gobj());
704         if(!gtk_iter || !iterator_sane(gtk_iter)) return;
705
706         _keyframe_iterator *iter(static_cast<_keyframe_iterator*>(gtk_iter->user_data));
707         iter->ref_count++;
708 }
709
710 void
711 KeyframeTreeStore::unref_node_vfunc (iterator& xiter)const
712 {
713         GtkTreeIter* gtk_iter(xiter.gobj());
714         if(!gtk_iter || !iterator_sane(gtk_iter)) return;
715
716         _keyframe_iterator *iter(static_cast<_keyframe_iterator*>(gtk_iter->user_data));
717         iter->ref_count--;
718         if(!iter->ref_count)
719         {
720                 delete iter;
721                 
722                 // Make this iterator invalid
723                 gtk_iter->stamp=0;
724         }
725 }
726
727 Gtk::TreeModel::Path
728 KeyframeTreeStore::get_path_vfunc (const TreeModel::iterator& gtk_iter)const
729 {
730         Gtk::TreeModel::Path path;
731
732         // If this is the root node, then return
733         // a root path
734         if(!iterator_sane(gtk_iter))
735                 return path;
736
737         _keyframe_iterator *iter(static_cast<_keyframe_iterator*>(gtk_iter->gobj()->user_data));
738         
739         path.append_index(iter->index);
740
741         return path;
742 }
743
744 bool
745 KeyframeTreeStore::get_iter_vfunc (const Gtk::TreeModel::Path& path, iterator& iter)const
746 {
747         if(path.get_depth()>=1)
748                 return iter_nth_root_child_vfunc(path.front(),iter);
749
750         // Error case
751         g_warning("KeyframeTreeStore::get_iter_vfunc(): Bad path \"%s\"",path.to_string().c_str());
752         //clear_iterator(iter);
753         return false;
754 }
755
756 bool
757 KeyframeTreeStore::iter_is_valid (const iterator& iter) const
758 {
759         return iterator_sane(iter);
760 }
761
762 void
763 KeyframeTreeStore::get_value_vfunc (const Gtk::TreeModel::iterator& gtk_iter, int column, Glib::ValueBase& value)const
764 {
765         dump_iterator(gtk_iter,"gtk_iter");
766         if(!iterator_sane(gtk_iter))
767                 return;
768
769         _keyframe_iterator *iter(static_cast<_keyframe_iterator*>(gtk_iter->gobj()->user_data));
770
771         switch(column)
772         {
773         case 0:         // Time
774         {
775                 Glib::Value<synfig::Time> x;
776                 g_value_init(x.gobj(),x.value_type());
777                 x.set(iter->iter->get_time());
778                 g_value_init(value.gobj(),x.value_type());
779                 g_value_copy(x.gobj(),value.gobj());
780                 return;
781         }
782         case 3:         // Time Delta
783         {
784                 Glib::Value<synfig::Time> x;
785                 g_value_init(x.gobj(),x.value_type());
786                 
787                 synfig::Keyframe prev_keyframe(*iter->iter);
788                 synfig::Keyframe keyframe;
789                 {
790                         KeyframeList::iterator tmp(iter->iter);
791                         tmp++;
792                         if(tmp==get_canvas()->keyframe_list().end())
793                         {
794                                 x.set(Time(0));
795                                 g_value_init(value.gobj(),x.value_type());
796                                 g_value_copy(x.gobj(),value.gobj());
797                                 return;
798                         }
799                         keyframe=*tmp;
800                 }
801                 
802                 Time delta(0);
803                 try {
804                         delta=keyframe.get_time()-prev_keyframe.get_time();
805                 }catch(...) { }
806                 x.set(delta);
807                 g_value_init(value.gobj(),x.value_type());
808                 g_value_copy(x.gobj(),value.gobj());
809                 return;
810         }
811         case 1:         // Description
812         {
813                 g_value_init(value.gobj(),G_TYPE_STRING);
814                 g_value_set_string(value.gobj(),iter->iter->get_description().c_str());
815                 return;
816         }
817         case 2:         // Keyframe
818         {
819                 Glib::Value<synfig::Keyframe> x;
820                 g_value_init(x.gobj(),x.value_type());
821                 x.set(*iter->iter);
822                 g_value_init(value.gobj(),x.value_type());
823                 g_value_copy(x.gobj(),value.gobj());
824                 return;
825         }
826         default:
827                 break;
828         }
829 }
830
831 Gtk::TreeModel::Row
832 KeyframeTreeStore::find_row(const synfig::Keyframe &keyframe)
833 {
834         Gtk::TreeModel::Row row(*(children().begin()));
835         dump_iterator(row,"find_row,begin");
836         const GtkTreeIter *gtk_iter(row.gobj());
837         if(!iterator_sane(gtk_iter))
838                 throw std::runtime_error(_("Unable to find Keyframe in table"));
839                 
840         _keyframe_iterator *iter(static_cast<_keyframe_iterator*>(gtk_iter->user_data));
841         
842         synfig::KeyframeList &keyframe_list(canvas_interface()->get_canvas()->keyframe_list());
843         if(keyframe_list.empty())
844                 throw std::runtime_error(_("There are no keyframes n this canvas"));
845
846         iter->index=0;
847                 
848         for(iter->iter=keyframe_list.begin();iter->iter!=keyframe_list.end() && *iter->iter!=keyframe;++iter->iter)
849         {
850                 iter->index++;
851         }
852         if(iter->iter==keyframe_list.end())
853                 throw std::runtime_error(_("Unable to find Keyframe in table"));
854         return row;
855 }
856
857 void
858 KeyframeTreeStore::add_keyframe(Keyframe keyframe)
859 {
860         try
861         {
862                 Gtk::TreeRow row(find_row(keyframe));
863                 dump_iterator(row.gobj(),"add_keyframe,row");
864                 Gtk::TreePath path(get_path(row));
865                 
866                 row_inserted(path,row);
867
868                 old_keyframe_list=get_canvas()->keyframe_list();
869                 //old_keyframe_list.add(keyframe);
870                 //old_keyframe_list.sort();
871         }
872         catch(std::exception x)
873         {
874                 g_warning(x.what());
875         }       
876 }
877
878 void
879 KeyframeTreeStore::remove_keyframe(Keyframe keyframe)
880 {
881         try
882         {
883                 if(1)
884                 {       
885                         Gtk::TreeRow row(find_row(keyframe));
886                         dump_iterator(row,"remove_keyframe,row");
887                         Gtk::TreePath path(get_path(row));
888                         row_deleted(path);
889
890                         old_keyframe_list.erase(keyframe);
891                 }
892                 else
893                 {
894                         g_warning("KeyframeTreeStore::remove_keyframe: Keyframe not in table");
895                 }
896         }
897         catch(std::exception x)
898         {
899                 DEBUGPOINT();
900                 g_warning(x.what());
901         }       
902 }
903
904 void
905 KeyframeTreeStore::change_keyframe(Keyframe keyframe)
906 {
907         try
908         {
909                 Gtk::TreeRow row(find_row(keyframe));
910
911                 unsigned int new_index(get_index_from_model_iter(row));
912                 unsigned int old_index(0);
913                 synfig::KeyframeList::iterator iter;
914                 for(old_index=0,iter=old_keyframe_list.begin();iter!=old_keyframe_list.end() && (UniqueID)*iter!=(UniqueID)keyframe;++iter,old_index++);
915                 
916                 if(iter!=old_keyframe_list.end() && new_index!=old_index)
917                 {
918                         DEBUGPOINT();
919                         std::vector<int> new_order;
920                         for(unsigned int i=0;i<old_keyframe_list.size();i++)
921                         {
922                                 new_order.push_back(i);
923                         }
924                         if(new_order.size()>new_index)
925                         {
926                                 new_order.erase(new_order.begin()+new_index);
927                                 new_order.insert(new_order.begin()+old_index,new_index);
928                                 
929                                 //new_order[old_index]=
930                                 
931                                 rows_reordered (Path(), iterator(), &new_order[0]);
932                         }
933                         old_keyframe_list=get_canvas()->keyframe_list();
934                                 
935                         row=find_row(keyframe);
936                 }
937
938                 dump_iterator(row,"change_keyframe,row");
939                 row_changed(get_path(row),row); 
940         }
941         catch(std::exception x)
942         {
943                 DEBUGPOINT();
944                 g_warning(x.what());
945         }       
946 }