1 /* === S Y N F I G ========================================================= */
2 /*! \file keyframetreestore.cpp
3 ** \brief Template File
5 ** $Id: keyframetreestore.cpp,v 1.1.1.1 2005/01/07 03:34:36 darco Exp $
8 ** Copyright (c) 2002 Robert B. Quattlebaum Jr.
10 ** This software and associated documentation
11 ** are CONFIDENTIAL and PROPRIETARY property of
12 ** the above-mentioned copyright holder.
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.
20 /* ========================================================================= */
22 /* === H E A D E R S ======================================================= */
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>
41 #include <ETL/smart_ptr>
42 #include <synfigapp/action.h>
43 #include <synfigapp/instance.h>
44 #include "onemoment.h"
45 #include <synfig/exception.h>
49 /* === U S I N G =========================================================== */
53 using namespace synfig;
54 using namespace studio;
56 /* === M A C R O S ========================================================= */
58 /* === G L O B A L S ======================================================= */
60 KeyframeTreeStore_Class KeyframeTreeStore::keyframe_tree_store_class_;
62 /* === C L A S S E S & S T R U C T S ======================================= */
64 struct _keyframe_iterator
66 synfig::KeyframeList::iterator iter;
72 Gtk::TreeModel::iterator keyframe_iter_2_model_iter(synfig::KeyframeList::iterator iter,int index)
74 Gtk::TreeModel::iterator ret;
76 _keyframe_iterator*& data(static_cast<_keyframe_iterator*&>(ret->gobj()->user_data));
77 data=new _keyframe_iterator();
86 synfig::KeyframeList::iterator model_iter_2_keyframe_iter(Gtk::TreeModel::iterator iter)
88 _keyframe_iterator* data(static_cast<_keyframe_iterator*>(iter->gobj()->user_data));
90 throw std::runtime_error("bad data");
94 int get_index_from_model_iter(Gtk::TreeModel::iterator iter)
96 _keyframe_iterator* data(static_cast<_keyframe_iterator*>(iter->gobj()->user_data));
98 throw std::runtime_error("bad data");
104 #ifndef TreeRowReferenceHack
105 class TreeRowReferenceHack
107 GtkTreeRowReference *gobject_;
109 TreeRowReferenceHack():
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())) )
119 TreeRowReferenceHack(const TreeRowReferenceHack &x):
120 gobject_ ( x.gobject_?gtk_tree_row_reference_copy(x.gobject_):0 )
125 void swap(TreeRowReferenceHack & other)
127 GtkTreeRowReference *const temp = gobject_;
128 gobject_ = other.gobject_;
129 other.gobject_ = temp;
132 const TreeRowReferenceHack &
133 operator=(const TreeRowReferenceHack &rhs)
135 TreeRowReferenceHack temp (rhs);
140 ~TreeRowReferenceHack()
143 gtk_tree_row_reference_free(gobject_);
146 Gtk::TreeModel::Path get_path() { return Gtk::TreeModel::Path(gtk_tree_row_reference_get_path(gobject_),false); }
147 GtkTreeRowReference *gobj() { return gobject_; }
152 /* === P R O C E D U R E S ================================================= */
154 void clear_iterator(GtkTreeIter* iter)
157 iter->user_data=iter->user_data2=iter->user_data3=0;
160 /* === M E T H O D S ======================================================= */
163 KeyframeTreeStore_Class::init()
167 class_init_func_ = &KeyframeTreeStore_Class::class_init_function;
169 const GTypeInfo derived_info =
171 sizeof(GObjectClass),
183 gtype_ = g_type_register_static(G_TYPE_OBJECT, "KeyframeTreeStore", &derived_info, GTypeFlags(0));
184 Gtk::TreeModel::add_interface(get_type());
190 KeyframeTreeStore_Class::class_init_function(gpointer g_class, gpointer class_data)
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_)
201 //reset_path_table();
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));
208 KeyframeTreeStore::~KeyframeTreeStore()
210 synfig::info("KeyframeTreeStore::~KeyframeTreeStore(): Deleted");
213 Glib::RefPtr<KeyframeTreeStore>
214 KeyframeTreeStore::create(etl::loose_handle<synfigapp::CanvasInterface> canvas_interface_)
216 KeyframeTreeStore *store(new KeyframeTreeStore(canvas_interface_));
217 Glib::RefPtr<KeyframeTreeStore> ret(store);
223 KeyframeTreeStore::reset_stamp()
225 stamp_=time(0)+reinterpret_cast<int>(this);
230 KeyframeTreeStore::reset_path_table()
232 Gtk::TreeModel::Children::iterator iter;
233 const Gtk::TreeModel::Children children(children());
235 for(iter = children.begin(); iter != children.end(); ++iter)
237 Gtk::TreeModel::Row row(*iter);
238 path_table_[(Keyframe)row[model.keyframe]]=TreeRowReferenceHack(Glib::RefPtr<KeyframeTreeStore>(this),Gtk::TreePath(row));
245 KeyframeTreeStore::iterator_sane(const GtkTreeIter* iter)const
247 if(iter && iter->stamp==stamp_)
249 g_warning("KeyframeTreeStore::iterator_sane(): Bad iterator stamp");
254 KeyframeTreeStore::iterator_sane(const Gtk::TreeModel::iterator& iter)const
256 return iterator_sane(iter->gobj());
260 KeyframeTreeStore::dump_iterator(const GtkTreeIter* gtk_iter, const Glib::ustring &name)const
265 g_warning("KeyframeTreeStore::dump_iterator: \"%s\" is NULL (Root?)",name.c_str());
269 _keyframe_iterator *iter(static_cast<_keyframe_iterator*>(gtk_iter->user_data));
271 if(gtk_iter->stamp!=stamp_ || !iter)
273 g_warning("KeyframeTreeStore::dump_iterator: \"%s\" is INVALID",name.c_str());
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);
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());
285 KeyframeTreeStore::dump_iterator(const Gtk::TreeModel::iterator& iter, const Glib::ustring &name)const
287 dump_iterator(iter->gobj(),name);
291 KeyframeTreeStore::time_sorter(const Gtk::TreeModel::iterator &rhs,const Gtk::TreeModel::iterator &lhs)
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));
298 Time diff(rhs_iter->iter->get_time()-lhs_iter->iter->get_time());
307 KeyframeTreeStore::set_value_impl(const Gtk::TreeModel::iterator& row, int column, const Glib::ValueBase& value)
309 if(!iterator_sane(row))
312 if(column>=get_n_columns_vfunc())
314 g_warning("KeyframeTreeStore::set_value_impl: Bad column (%d)",column);
318 if(!g_value_type_compatible(G_VALUE_TYPE(value.gobj()),get_column_type_vfunc(column)))
320 g_warning("KeyframeTreeStore::set_value_impl: Bad value type");
324 _keyframe_iterator *iter(static_cast<_keyframe_iterator*>(row.gobj()->user_data));
328 if(column==model.time_delta.index())
330 Glib::Value<synfig::Time> x;
331 g_value_init(x.gobj(),model.time.type());
332 g_value_copy(value.gobj(),x.gobj());
334 Time new_delta(x.get());
335 if(new_delta<=Time::zero()+Time::epsilon())
341 Time old_delta((*row)[model.time_delta]);
342 if(old_delta<=Time::zero()+Time::epsilon())
347 //Gtk::TreeModel::iterator row(row);
351 Time change_delta(new_delta-old_delta);
353 if(change_delta<=Time::zero()+Time::epsilon() &&change_delta>=Time::zero()-Time::epsilon())
355 // Not an error, just no change
361 Keyframe keyframe((*row)[model.keyframe]);
362 synfigapp::Action::Handle action(synfigapp::Action::create("keyframe_set_delta"));
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);
371 canvas_interface()->get_instance()->perform_action(action);
376 { // Old Method The slowest method EVER!!!
377 OneMoment one_moment;
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);
383 Gtk::TreeModel::iterator iter(row);
387 KeyframeList keyframe_list(get_canvas()->keyframe_list());
388 synfig::KeyframeList::iterator iter(keyframe_list.find((*row)[model.keyframe]));
390 for(;iter!=keyframe_list.end();++iter)
393 synfig::Keyframe keyframe(*iter);
395 keyframe.set_time(keyframe.get_time()+change_delta);
397 synfigapp::Action::Handle action(synfigapp::Action::create("keyframe_set"));
401 action->set_param("canvas",canvas_interface()->get_canvas());
402 action->set_param("canvas_interface",canvas_interface());
403 action->set_param("keyframe",keyframe);
405 canvas_interface()->get_instance()->perform_action(action);
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());
416 for(;iter!=end;++iter)
419 synfig::Keyframe keyframe(*iter);
421 keyframe.set_time(keyframe.get_time()+change_delta);
423 synfigapp::Action::Handle action(synfigapp::Action::create("keyframe_set"));
427 action->set_param("canvas",canvas_interface()->get_canvas());
428 action->set_param("canvas_interface",canvas_interface());
429 action->set_param("keyframe",keyframe);
431 canvas_interface()->get_instance()->perform_action(action);
439 if(column==model.time.index())
441 OneMoment one_moment;
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);
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());
452 synfigapp::Action::Handle action(synfigapp::Action::create("keyframe_set"));
457 action->set_param("canvas",canvas_interface()->get_canvas());
458 action->set_param("canvas_interface",canvas_interface());
459 action->set_param("keyframe",keyframe);
461 canvas_interface()->get_instance()->perform_action(action);
463 else if(column==model.description.index())
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());
471 synfigapp::Action::Handle action(synfigapp::Action::create("keyframe_set"));
476 action->set_param("canvas",canvas_interface()->get_canvas());
477 action->set_param("canvas_interface",canvas_interface());
478 action->set_param("keyframe",keyframe);
480 canvas_interface()->get_instance()->perform_action(action);
482 else if(column==model.keyframe.index())
484 g_warning("KeyframeTreeStore::set_value_impl: This column is read-only");
491 catch(std::exception x)
498 KeyframeTreeStore::get_flags_vfunc ()
500 return Gtk::TREE_MODEL_LIST_ONLY;
504 KeyframeTreeStore::get_n_columns_vfunc ()
510 KeyframeTreeStore::get_column_type_vfunc (int index)
512 return model.types()[index];
516 KeyframeTreeStore::iter_next_vfunc (const iterator& xiter, iterator& iter_next) const
518 if(!iterator_sane(xiter)) return false;
520 _keyframe_iterator *iter(static_cast<_keyframe_iterator*>(xiter.gobj()->user_data));
522 if(iter->iter==canvas_interface()->get_canvas()->keyframe_list().end())
525 _keyframe_iterator *next(new _keyframe_iterator());
526 iter_next.gobj()->user_data=static_cast<gpointer>(next);
528 next->index=iter->index+1;
529 next->iter=iter->iter;
532 if(next->iter==canvas_interface()->get_canvas()->keyframe_list().end())
535 iter_next.gobj()->stamp=stamp_;
542 KeyframeTreeStore::iter_next_vfunc (GtkTreeIter* gtk_iter)
544 if(!iterator_sane(gtk_iter)) return false;
546 _keyframe_iterator *iter(static_cast<_keyframe_iterator*>(gtk_iter->user_data));
548 // If we are already at the end, then we are very invalid
549 if(iter->iter==canvas_interface()->get_canvas()->keyframe_list().end())
554 if(iter->iter==canvas_interface()->get_canvas()->keyframe_list().end())
564 KeyframeTreeStore::iter_children_vfunc (GtkTreeIter* gtk_iter, const GtkTreeIter* parent)
566 dump_iterator(gtk_iter,"gtk_iter");
567 dump_iterator(parent,"parent");
569 if(!parent || !iterator_sane(parent))
571 clear_iterator(gtk_iter);
575 _keyframe_iterator *iter(new _keyframe_iterator());
578 iter->iter=canvas_interface()->get_canvas()->keyframe_list().begin();
580 gtk_iter->user_data=static_cast<gpointer>(iter);
581 gtk_iter->stamp=stamp_;
587 KeyframeTreeStore::iter_has_child_vfunc (const GtkTreeIter*parent)
589 dump_iterator(parent,"parent");
598 KeyframeTreeStore::iter_n_children_vfunc (const GtkTreeIter* parent)
600 dump_iterator(parent,"parent");
605 return canvas_interface()->get_canvas()->keyframe_list().size();
610 KeyframeTreeStore::iter_n_root_children_vfunc () const
612 return canvas_interface()->get_canvas()->keyframe_list().size();
616 KeyframeTreeStore::iter_nth_root_child_vfunc (int n, iterator& xiter)const
618 if(canvas_interface()->get_canvas()->keyframe_list().size()==0)
625 g_warning("KeyframeTreeStore::iter_nth_root_child_vfunc: Out of range (negative index)");
628 if(n && (unsigned)n>=canvas_interface()->get_canvas()->keyframe_list().size())
630 g_warning("KeyframeTreeStore::iter_nth_child_vfunc: Out of range (large index)");
634 _keyframe_iterator *iter(new _keyframe_iterator());
637 iter->iter=canvas_interface()->get_canvas()->keyframe_list().begin();
640 if(iter->iter==canvas_interface()->get_canvas()->keyframe_list().end())
642 g_warning("KeyframeTreeStore::iter_nth_child_vfunc: >>>BUG<<< in %s on line %d",__FILE__,__LINE__);
648 xiter.gobj()->user_data=static_cast<gpointer>(iter);
649 xiter.gobj()->stamp=stamp_;
655 KeyframeTreeStore::iter_nth_child_vfunc (GtkTreeIter* gtk_iter, const GtkTreeIter* parent, int n)
657 dump_iterator(parent,"parent");
661 g_warning("KeyframeTreeStore::iter_nth_child_vfunc: I am a list");
662 clear_iterator(gtk_iter);
668 _keyframe_iterator *iter(new _keyframe_iterator());
671 iter->iter=canvas_interface()->get_canvas()->keyframe_list().begin();
674 if(iter->iter==canvas_interface()->get_canvas()->keyframe_list().end())
676 g_warning("KeyframeTreeStore::iter_nth_child_vfunc: >>>BUG<<< in %s on line %d",__FILE__,__LINE__);
678 clear_iterator(gtk_iter);
684 gtk_iter->user_data=static_cast<gpointer>(iter);
685 gtk_iter->stamp=stamp_;
690 KeyframeTreeStore::iter_parent_vfunc (GtkTreeIter* gtk_iter, const GtkTreeIter* child)
692 dump_iterator(child,"child");
693 iterator_sane(child);
694 clear_iterator(gtk_iter);
700 KeyframeTreeStore::ref_node_vfunc (iterator& xiter)const
702 GtkTreeIter* gtk_iter(xiter.gobj());
703 if(!gtk_iter || !iterator_sane(gtk_iter)) return;
705 _keyframe_iterator *iter(static_cast<_keyframe_iterator*>(gtk_iter->user_data));
710 KeyframeTreeStore::unref_node_vfunc (iterator& xiter)const
712 GtkTreeIter* gtk_iter(xiter.gobj());
713 if(!gtk_iter || !iterator_sane(gtk_iter)) return;
715 _keyframe_iterator *iter(static_cast<_keyframe_iterator*>(gtk_iter->user_data));
721 // Make this iterator invalid
727 KeyframeTreeStore::get_path_vfunc (const TreeModel::iterator& gtk_iter)const
729 Gtk::TreeModel::Path path;
731 // If this is the root node, then return
733 if(!iterator_sane(gtk_iter))
736 _keyframe_iterator *iter(static_cast<_keyframe_iterator*>(gtk_iter->gobj()->user_data));
738 path.append_index(iter->index);
744 KeyframeTreeStore::get_iter_vfunc (const Gtk::TreeModel::Path& path, iterator& iter)const
746 if(path.get_depth()>=1)
747 return iter_nth_root_child_vfunc(path.front(),iter);
750 g_warning("KeyframeTreeStore::get_iter_vfunc(): Bad path \"%s\"",path.to_string().c_str());
751 //clear_iterator(iter);
756 KeyframeTreeStore::iter_is_valid (const iterator& iter) const
758 return iterator_sane(iter);
762 KeyframeTreeStore::get_value_vfunc (const Gtk::TreeModel::iterator& gtk_iter, int column, Glib::ValueBase& value)const
764 dump_iterator(gtk_iter,"gtk_iter");
765 if(!iterator_sane(gtk_iter))
768 _keyframe_iterator *iter(static_cast<_keyframe_iterator*>(gtk_iter->gobj()->user_data));
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());
781 case 3: // Time Delta
783 Glib::Value<synfig::Time> x;
784 g_value_init(x.gobj(),x.value_type());
786 synfig::Keyframe prev_keyframe(*iter->iter);
787 synfig::Keyframe keyframe;
789 KeyframeList::iterator tmp(iter->iter);
791 if(tmp==get_canvas()->keyframe_list().end())
794 g_value_init(value.gobj(),x.value_type());
795 g_value_copy(x.gobj(),value.gobj());
803 delta=keyframe.get_time()-prev_keyframe.get_time();
806 g_value_init(value.gobj(),x.value_type());
807 g_value_copy(x.gobj(),value.gobj());
810 case 1: // Description
812 g_value_init(value.gobj(),G_TYPE_STRING);
813 g_value_set_string(value.gobj(),iter->iter->get_description().c_str());
818 Glib::Value<synfig::Keyframe> x;
819 g_value_init(x.gobj(),x.value_type());
821 g_value_init(value.gobj(),x.value_type());
822 g_value_copy(x.gobj(),value.gobj());
831 KeyframeTreeStore::find_row(const synfig::Keyframe &keyframe)
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"));
839 _keyframe_iterator *iter(static_cast<_keyframe_iterator*>(gtk_iter->user_data));
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"));
847 for(iter->iter=keyframe_list.begin();iter->iter!=keyframe_list.end() && *iter->iter!=keyframe;++iter->iter)
851 if(iter->iter==keyframe_list.end())
852 throw std::runtime_error(_("Unable to find Keyframe in table"));
857 KeyframeTreeStore::add_keyframe(Keyframe keyframe)
861 Gtk::TreeRow row(find_row(keyframe));
862 dump_iterator(row.gobj(),"add_keyframe,row");
863 Gtk::TreePath path(get_path(row));
865 row_inserted(path,row);
867 old_keyframe_list=get_canvas()->keyframe_list();
868 //old_keyframe_list.add(keyframe);
869 //old_keyframe_list.sort();
871 catch(std::exception x)
878 KeyframeTreeStore::remove_keyframe(Keyframe keyframe)
884 Gtk::TreeRow row(find_row(keyframe));
885 dump_iterator(row,"remove_keyframe,row");
886 Gtk::TreePath path(get_path(row));
889 old_keyframe_list.erase(keyframe);
893 g_warning("KeyframeTreeStore::remove_keyframe: Keyframe not in table");
896 catch(std::exception x)
904 KeyframeTreeStore::change_keyframe(Keyframe keyframe)
908 Gtk::TreeRow row(find_row(keyframe));
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++);
915 if(iter!=old_keyframe_list.end() && new_index!=old_index)
918 std::vector<int> new_order;
919 for(unsigned int i=0;i<old_keyframe_list.size();i++)
921 new_order.push_back(i);
923 if(new_order.size()>new_index)
925 new_order.erase(new_order.begin()+new_index);
926 new_order.insert(new_order.begin()+old_index,new_index);
928 //new_order[old_index]=
930 rows_reordered (Path(), iterator(), &new_order[0]);
932 old_keyframe_list=get_canvas()->keyframe_list();
934 row=find_row(keyframe);
937 dump_iterator(row,"change_keyframe,row");
938 row_changed(get_path(row),row);
940 catch(std::exception x)