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