1 /* === S Y N F I G ========================================================= */
2 /*! \file keyframetreestore.cpp
3 ** \brief Template File
8 ** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 ** Copyright (c) 2007 Chris Moore
11 ** This package is free software; you can redistribute it and/or
12 ** modify it under the terms of the GNU General Public License as
13 ** published by the Free Software Foundation; either version 2 of
14 ** the License, or (at your option) any later version.
16 ** This package is distributed in the hope that it will be useful,
17 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 ** General Public License for more details.
22 /* ========================================================================= */
24 /* === H E A D E R S ======================================================= */
33 #include "keyframetreestore.h"
34 #include <synfig/valuenode.h>
35 #include "iconcontroller.h"
36 #include <synfig/valuenode_timedswap.h>
37 #include <gtkmm/button.h>
38 #include <gtkmm/treerowreference.h>
39 #include <synfig/canvas.h>
40 #include <synfig/keyframe.h>
43 #include <ETL/smart_ptr>
44 #include <synfigapp/action.h>
45 #include <synfigapp/instance.h>
46 #include "onemoment.h"
47 #include <synfig/exception.h>
53 /* === U S I N G =========================================================== */
57 using namespace synfig;
58 using namespace studio;
60 /* === M A C R O S ========================================================= */
62 /* === G L O B A L S ======================================================= */
64 // KeyframeTreeStore_Class KeyframeTreeStore::keyframe_tree_store_class_;
66 /* === C L A S S E S & S T R U C T S ======================================= */
68 struct _keyframe_iterator
70 synfig::KeyframeList::iterator iter;
76 Gtk::TreeModel::iterator keyframe_iter_2_model_iter(synfig::KeyframeList::iterator iter,int index)
78 Gtk::TreeModel::iterator ret;
80 _keyframe_iterator*& data(static_cast<_keyframe_iterator*&>(ret->gobj()->user_data));
81 data=new _keyframe_iterator();
90 synfig::KeyframeList::iterator model_iter_2_keyframe_iter(Gtk::TreeModel::iterator iter)
92 _keyframe_iterator* data(static_cast<_keyframe_iterator*>(iter->gobj()->user_data));
94 throw std::runtime_error("bad data");
98 int get_index_from_model_iter(Gtk::TreeModel::iterator iter)
100 _keyframe_iterator* data(static_cast<_keyframe_iterator*>(iter->gobj()->user_data));
102 throw std::runtime_error("bad data");
108 #ifndef TreeRowReferenceHack
109 class TreeRowReferenceHack
111 GtkTreeRowReference *gobject_;
113 TreeRowReferenceHack():
118 TreeRowReferenceHack(const Glib::RefPtr<Gtk::TreeModel>& model, const Gtk::TreeModel::Path& path):
119 gobject_ ( gtk_tree_row_reference_new(model->gobj(), const_cast<GtkTreePath*>(path.gobj())) )
123 TreeRowReferenceHack(const TreeRowReferenceHack &x):
124 gobject_ ( x.gobject_?gtk_tree_row_reference_copy(x.gobject_):0 )
129 void swap(TreeRowReferenceHack & other)
131 GtkTreeRowReference *const temp = gobject_;
132 gobject_ = other.gobject_;
133 other.gobject_ = temp;
136 const TreeRowReferenceHack &
137 operator=(const TreeRowReferenceHack &rhs)
139 TreeRowReferenceHack temp (rhs);
144 ~TreeRowReferenceHack()
147 gtk_tree_row_reference_free(gobject_);
150 Gtk::TreeModel::Path get_path() { return Gtk::TreeModel::Path(gtk_tree_row_reference_get_path(gobject_),false); }
151 GtkTreeRowReference *gobj() { return gobject_; }
156 /* === P R O C E D U R E S ================================================= */
158 void clear_iterator(GtkTreeIter* iter)
161 iter->user_data=iter->user_data2=iter->user_data3=0;
164 /* === M E T H O D S ======================================================= */
167 KeyframeTreeStore_Class::init()
171 class_init_func_ = &KeyframeTreeStore_Class::class_init_function;
173 const GTypeInfo derived_info =
175 sizeof(GObjectClass),
187 gtype_ = g_type_register_static(G_TYPE_OBJECT, "KeyframeTreeStore", &derived_info, GTypeFlags(0));
188 Gtk::TreeModel::add_interface(get_type());
194 KeyframeTreeStore_Class::class_init_function(gpointer /*g_class*/, gpointer /*class_data*/)
199 KeyframeTreeStore::KeyframeTreeStore(etl::loose_handle<synfigapp::CanvasInterface> canvas_interface_):
200 Glib::ObjectBase ("KeyframeTreeStore"),
201 //! \todo what is going on here? why the need for this KeyframeTreeStore_Class at all?
202 // Glib::Object (Glib::ConstructParams(keyframe_tree_store_class_.init(), (char*) 0, (char*) 0)),
203 canvas_interface_ (canvas_interface_)
206 //reset_path_table();
208 canvas_interface()->signal_keyframe_added().connect(sigc::mem_fun(*this,&studio::KeyframeTreeStore::add_keyframe));
209 canvas_interface()->signal_keyframe_removed().connect(sigc::mem_fun(*this,&studio::KeyframeTreeStore::remove_keyframe));
210 canvas_interface()->signal_keyframe_changed().connect(sigc::mem_fun(*this,&studio::KeyframeTreeStore::change_keyframe));
213 KeyframeTreeStore::~KeyframeTreeStore()
215 if (getenv("SYNFIG_DEBUG_DESTRUCTORS"))
216 synfig::info("KeyframeTreeStore::~KeyframeTreeStore(): Deleted");
219 Glib::RefPtr<KeyframeTreeStore>
220 KeyframeTreeStore::create(etl::loose_handle<synfigapp::CanvasInterface> canvas_interface_)
222 KeyframeTreeStore *store(new KeyframeTreeStore(canvas_interface_));
223 Glib::RefPtr<KeyframeTreeStore> ret(store);
229 KeyframeTreeStore::reset_stamp()
231 stamp_=time(0)+reinterpret_cast<long>(this);
236 KeyframeTreeStore::reset_path_table()
238 Gtk::TreeModel::Children::iterator iter;
239 const Gtk::TreeModel::Children children(children());
241 for(iter = children.begin(); iter != children.end(); ++iter)
243 Gtk::TreeModel::Row row(*iter);
244 path_table_[(Keyframe)row[model.keyframe]]=TreeRowReferenceHack(Glib::RefPtr<KeyframeTreeStore>(this),Gtk::TreePath(row));
251 KeyframeTreeStore::iterator_sane(const GtkTreeIter* iter)const
253 if(iter && iter->stamp==stamp_)
255 g_warning("KeyframeTreeStore::iterator_sane(): Bad iterator stamp");
260 KeyframeTreeStore::iterator_sane(const Gtk::TreeModel::iterator& iter)const
262 return iterator_sane(iter->gobj());
266 KeyframeTreeStore::dump_iterator(const GtkTreeIter* /*gtk_iter*/, const Glib::ustring &/*name*/)const
271 g_warning("KeyframeTreeStore::dump_iterator: \"%s\" is NULL (Root?)",name.c_str());
275 _keyframe_iterator *iter(static_cast<_keyframe_iterator*>(gtk_iter->user_data));
277 if(gtk_iter->stamp!=stamp_ || !iter)
279 g_warning("KeyframeTreeStore::dump_iterator: \"%s\" is INVALID",name.c_str());
283 if((unsigned)iter->index>=canvas_interface()->get_canvas()->keyframe_list().size())
284 g_warning("KeyframeTreeStore::dump_iterator: \"%s\"(%p) has bad index(index:%d)",name.c_str(),gtk_iter,iter->index);
286 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());
291 KeyframeTreeStore::dump_iterator(const Gtk::TreeModel::iterator& iter, const Glib::ustring &name)const
293 dump_iterator(iter->gobj(),name);
297 KeyframeTreeStore::time_sorter(const Gtk::TreeModel::iterator &rhs,const Gtk::TreeModel::iterator &lhs)
301 _keyframe_iterator *rhs_iter(static_cast<_keyframe_iterator*>(rhs->gobj()->user_data));
302 _keyframe_iterator *lhs_iter(static_cast<_keyframe_iterator*>(lhs->gobj()->user_data));
304 Time diff(rhs_iter->iter->get_time()-lhs_iter->iter->get_time());
313 KeyframeTreeStore::description_sorter(const Gtk::TreeModel::iterator &rhs,const Gtk::TreeModel::iterator &lhs)
317 _keyframe_iterator *rhs_iter(static_cast<_keyframe_iterator*>(rhs->gobj()->user_data));
318 _keyframe_iterator *lhs_iter(static_cast<_keyframe_iterator*>(lhs->gobj()->user_data));
320 int comp = rhs_iter->iter->get_description().compare(lhs_iter->iter->get_description());
321 if (comp > 0) return 1;
322 if (comp < 0) return -1;
327 KeyframeTreeStore::set_value_impl(const Gtk::TreeModel::iterator& row, int column, const Glib::ValueBase& value)
329 if(!iterator_sane(row))
332 if(column>=get_n_columns_vfunc())
334 g_warning("KeyframeTreeStore::set_value_impl: Bad column (%d)",column);
338 if(!g_value_type_compatible(G_VALUE_TYPE(value.gobj()),get_column_type_vfunc(column)))
340 g_warning("KeyframeTreeStore::set_value_impl: Bad value type");
344 _keyframe_iterator *iter(static_cast<_keyframe_iterator*>(row.gobj()->user_data));
348 if(column==model.time_delta.index())
350 Glib::Value<synfig::Time> x;
351 g_value_init(x.gobj(),model.time.type());
352 g_value_copy(value.gobj(),x.gobj());
354 Time new_delta(x.get());
355 if(new_delta<=Time::zero()+Time::epsilon())
361 Time old_delta((*row)[model.time_delta]);
362 if(old_delta<=Time::zero()+Time::epsilon())
367 // row(row) on the next line is bad - don't use it, because it leaves 'row' uninitialized
368 //Gtk::TreeModel::iterator row(row);
372 Time change_delta(new_delta-old_delta);
374 if(change_delta<=Time::zero()+Time::epsilon() &&change_delta>=Time::zero()-Time::epsilon())
376 // Not an error, just no change
381 Keyframe keyframe((*row)[model.keyframe]);
382 synfigapp::Action::Handle action(synfigapp::Action::create("keyframe_set_delta"));
386 action->set_param("canvas",canvas_interface()->get_canvas());
387 action->set_param("canvas_interface",canvas_interface());
388 action->set_param("keyframe",keyframe);
389 action->set_param("delta",change_delta);
391 canvas_interface()->get_instance()->perform_action(action);
397 if(column==model.time.index())
399 OneMoment one_moment;
401 Glib::Value<synfig::Time> x;
402 g_value_init(x.gobj(),model.time.type());
403 g_value_copy(value.gobj(),x.gobj());
404 synfig::Keyframe keyframe(*iter->iter);
406 synfig::info("KeyframeTreeStore::set_value_impl():old_time=%s",keyframe.get_time().get_string().c_str());
407 keyframe.set_time(x.get());
408 synfig::info("KeyframeTreeStore::set_value_impl():new_time=%s",keyframe.get_time().get_string().c_str());
410 synfigapp::Action::Handle action(synfigapp::Action::create("keyframe_set"));
415 action->set_param("canvas",canvas_interface()->get_canvas());
416 action->set_param("canvas_interface",canvas_interface());
417 action->set_param("keyframe",keyframe);
419 canvas_interface()->get_instance()->perform_action(action);
421 else if(column==model.description.index())
423 Glib::Value<Glib::ustring> x;
424 g_value_init(x.gobj(),model.description.type());
425 g_value_copy(value.gobj(),x.gobj());
426 synfig::Keyframe keyframe(*iter->iter);
427 keyframe.set_description(x.get());
429 synfigapp::Action::Handle action(synfigapp::Action::create("keyframe_set"));
434 action->set_param("canvas",canvas_interface()->get_canvas());
435 action->set_param("canvas_interface",canvas_interface());
436 action->set_param("keyframe",keyframe);
438 canvas_interface()->get_instance()->perform_action(action);
440 else if(column==model.keyframe.index())
442 g_warning("KeyframeTreeStore::set_value_impl: This column is read-only");
449 catch(std::exception x)
456 KeyframeTreeStore::get_flags_vfunc ()
458 return Gtk::TREE_MODEL_LIST_ONLY;
462 KeyframeTreeStore::get_n_columns_vfunc ()
468 KeyframeTreeStore::get_column_type_vfunc (int index)
470 return model.types()[index];
474 KeyframeTreeStore::iter_next_vfunc (const iterator& xiter, iterator& iter_next) const
476 if(!iterator_sane(xiter)) return false;
478 _keyframe_iterator *iter(static_cast<_keyframe_iterator*>(xiter.gobj()->user_data));
480 if(iter->iter==canvas_interface()->get_canvas()->keyframe_list().end())
483 _keyframe_iterator *next(new _keyframe_iterator());
484 iter_next.gobj()->user_data=static_cast<gpointer>(next);
486 next->index=iter->index+1;
487 next->iter=iter->iter;
490 if(next->iter==canvas_interface()->get_canvas()->keyframe_list().end())
493 iter_next.gobj()->stamp=stamp_;
500 KeyframeTreeStore::iter_next_vfunc (GtkTreeIter* gtk_iter)
502 if(!iterator_sane(gtk_iter)) return false;
504 _keyframe_iterator *iter(static_cast<_keyframe_iterator*>(gtk_iter->user_data));
506 // If we are already at the end, then we are very invalid
507 if(iter->iter==canvas_interface()->get_canvas()->keyframe_list().end())
512 if(iter->iter==canvas_interface()->get_canvas()->keyframe_list().end())
522 KeyframeTreeStore::iter_children_vfunc (GtkTreeIter* gtk_iter, const GtkTreeIter* parent)
524 dump_iterator(gtk_iter,"gtk_iter");
525 dump_iterator(parent,"parent");
527 if(!parent || !iterator_sane(parent))
529 clear_iterator(gtk_iter);
533 _keyframe_iterator *iter(new _keyframe_iterator());
536 iter->iter=canvas_interface()->get_canvas()->keyframe_list().begin();
538 gtk_iter->user_data=static_cast<gpointer>(iter);
539 gtk_iter->stamp=stamp_;
545 KeyframeTreeStore::iter_has_child_vfunc (const GtkTreeIter*parent)
547 dump_iterator(parent,"parent");
556 KeyframeTreeStore::iter_n_children_vfunc (const GtkTreeIter* parent)
558 dump_iterator(parent,"parent");
563 return canvas_interface()->get_canvas()->keyframe_list().size();
568 KeyframeTreeStore::iter_n_root_children_vfunc () const
570 return canvas_interface()->get_canvas()->keyframe_list().size();
574 KeyframeTreeStore::iter_nth_root_child_vfunc (int n, iterator& xiter)const
576 if(canvas_interface()->get_canvas()->keyframe_list().size()==0)
583 g_warning("KeyframeTreeStore::iter_nth_root_child_vfunc: Out of range (negative index)");
586 if(n && (unsigned)n>=canvas_interface()->get_canvas()->keyframe_list().size())
588 g_warning("KeyframeTreeStore::iter_nth_child_vfunc: Out of range (large index)");
592 _keyframe_iterator *iter(new _keyframe_iterator());
595 iter->iter=canvas_interface()->get_canvas()->keyframe_list().begin();
598 if(iter->iter==canvas_interface()->get_canvas()->keyframe_list().end())
600 g_warning("KeyframeTreeStore::iter_nth_child_vfunc: >>>BUG<<< in %s on line %d",__FILE__,__LINE__);
606 xiter.gobj()->user_data=static_cast<gpointer>(iter);
607 xiter.gobj()->stamp=stamp_;
613 KeyframeTreeStore::iter_nth_child_vfunc (GtkTreeIter* gtk_iter, const GtkTreeIter* parent, int n)
615 dump_iterator(parent,"parent");
619 g_warning("KeyframeTreeStore::iter_nth_child_vfunc: I am a list");
620 clear_iterator(gtk_iter);
626 _keyframe_iterator *iter(new _keyframe_iterator());
629 iter->iter=canvas_interface()->get_canvas()->keyframe_list().begin();
632 if(iter->iter==canvas_interface()->get_canvas()->keyframe_list().end())
634 g_warning("KeyframeTreeStore::iter_nth_child_vfunc: >>>BUG<<< in %s on line %d",__FILE__,__LINE__);
636 clear_iterator(gtk_iter);
642 gtk_iter->user_data=static_cast<gpointer>(iter);
643 gtk_iter->stamp=stamp_;
648 KeyframeTreeStore::iter_parent_vfunc (GtkTreeIter* gtk_iter, const GtkTreeIter* child)
650 dump_iterator(child,"child");
651 iterator_sane(child);
652 clear_iterator(gtk_iter);
658 KeyframeTreeStore::ref_node_vfunc (iterator& xiter)const
660 GtkTreeIter* gtk_iter(xiter.gobj());
661 if(!gtk_iter || !iterator_sane(gtk_iter)) return;
663 _keyframe_iterator *iter(static_cast<_keyframe_iterator*>(gtk_iter->user_data));
668 KeyframeTreeStore::unref_node_vfunc (iterator& xiter)const
670 GtkTreeIter* gtk_iter(xiter.gobj());
671 if(!gtk_iter || !iterator_sane(gtk_iter)) return;
673 _keyframe_iterator *iter(static_cast<_keyframe_iterator*>(gtk_iter->user_data));
679 // Make this iterator invalid
685 KeyframeTreeStore::get_path_vfunc (const iterator& gtk_iter)const
687 Gtk::TreeModel::Path path;
689 // If this is the root node, then return
691 if(!iterator_sane(gtk_iter))
694 _keyframe_iterator *iter(static_cast<_keyframe_iterator*>(gtk_iter->gobj()->user_data));
696 path.append_index(iter->index);
702 KeyframeTreeStore::get_iter_vfunc (const Gtk::TreeModel::Path& path, iterator& iter)const
704 if(path.get_depth()>=1)
705 return iter_nth_root_child_vfunc(path.front(),iter);
708 g_warning("KeyframeTreeStore::get_iter_vfunc(): Bad path \"%s\"",path.to_string().c_str());
709 //clear_iterator(iter);
714 KeyframeTreeStore::iter_is_valid (const iterator& iter) const
716 return iterator_sane(iter);
720 KeyframeTreeStore::get_value_vfunc (const Gtk::TreeModel::iterator& gtk_iter, int column, Glib::ValueBase& value)const
722 dump_iterator(gtk_iter,"gtk_iter");
723 if(!iterator_sane(gtk_iter))
726 _keyframe_iterator *iter(static_cast<_keyframe_iterator*>(gtk_iter->gobj()->user_data));
732 Glib::Value<synfig::Time> x;
733 g_value_init(x.gobj(),x.value_type());
734 x.set(iter->iter->get_time());
735 g_value_init(value.gobj(),x.value_type());
736 g_value_copy(x.gobj(),value.gobj());
739 case 3: // Time Delta
741 Glib::Value<synfig::Time> x;
742 g_value_init(x.gobj(),x.value_type());
744 synfig::Keyframe prev_keyframe(*iter->iter);
745 synfig::Keyframe keyframe;
747 KeyframeList::iterator tmp(iter->iter);
749 if(tmp==get_canvas()->keyframe_list().end())
752 g_value_init(value.gobj(),x.value_type());
753 g_value_copy(x.gobj(),value.gobj());
761 delta=keyframe.get_time()-prev_keyframe.get_time();
764 g_value_init(value.gobj(),x.value_type());
765 g_value_copy(x.gobj(),value.gobj());
768 case 1: // Description
770 g_value_init(value.gobj(),G_TYPE_STRING);
771 g_value_set_string(value.gobj(),iter->iter->get_description().c_str());
776 Glib::Value<synfig::Keyframe> x;
777 g_value_init(x.gobj(),x.value_type());
779 g_value_init(value.gobj(),x.value_type());
780 g_value_copy(x.gobj(),value.gobj());
789 KeyframeTreeStore::find_row(const synfig::Keyframe &keyframe)
791 Gtk::TreeModel::Row row(*(children().begin()));
792 dump_iterator(row,"find_row,begin");
793 const GtkTreeIter *gtk_iter(row.gobj());
794 if(!iterator_sane(gtk_iter))
795 throw std::runtime_error(_("Unable to find Keyframe in table"));
797 _keyframe_iterator *iter(static_cast<_keyframe_iterator*>(gtk_iter->user_data));
799 synfig::KeyframeList &keyframe_list(canvas_interface()->get_canvas()->keyframe_list());
800 if(keyframe_list.empty())
801 throw std::runtime_error(_("There are no keyframes n this canvas"));
805 for(iter->iter=keyframe_list.begin();iter->iter!=keyframe_list.end() && *iter->iter!=keyframe;++iter->iter)
809 if(iter->iter==keyframe_list.end())
810 throw std::runtime_error(_("Unable to find Keyframe in table"));
815 KeyframeTreeStore::add_keyframe(synfig::Keyframe keyframe)
819 Gtk::TreeRow row(find_row(keyframe));
820 dump_iterator(row.gobj(),"add_keyframe,row");
821 Gtk::TreePath path(get_path(row));
823 row_inserted(path,row);
825 old_keyframe_list=get_canvas()->keyframe_list();
826 //old_keyframe_list.add(keyframe);
827 //old_keyframe_list.sort();
829 catch(std::exception x)
836 KeyframeTreeStore::remove_keyframe(synfig::Keyframe keyframe)
842 Gtk::TreeRow row(find_row(keyframe));
843 dump_iterator(row,"remove_keyframe,row");
844 Gtk::TreePath path(get_path(row));
847 old_keyframe_list.erase(keyframe);
851 g_warning("KeyframeTreeStore::remove_keyframe: Keyframe not in table");
854 catch(std::exception x)
861 KeyframeTreeStore::change_keyframe(synfig::Keyframe keyframe)
865 Gtk::TreeRow row(find_row(keyframe));
867 unsigned int new_index(get_index_from_model_iter(row));
868 unsigned int old_index(0);
869 synfig::KeyframeList::iterator iter;
870 for(old_index=0,iter=old_keyframe_list.begin();iter!=old_keyframe_list.end() && (UniqueID)*iter!=(UniqueID)keyframe;++iter,old_index++)
873 if(iter!=old_keyframe_list.end() && new_index!=old_index)
875 std::vector<int> new_order;
876 for(unsigned int i=0;i<old_keyframe_list.size();i++)
878 new_order.push_back(i);
880 if(new_order.size()>new_index)
882 new_order.erase(new_order.begin()+new_index);
883 new_order.insert(new_order.begin()+old_index,new_index);
885 //new_order[old_index]=
887 rows_reordered (Path(), iterator(), &new_order[0]);
889 old_keyframe_list=get_canvas()->keyframe_list();
891 row=find_row(keyframe);
894 dump_iterator(row,"change_keyframe,row");
895 row_changed(get_path(row),row);
897 catch(std::exception x)