source: synfigstudio/trunk/fuentes/src/gui/trees/keyframetreestore.cpp @ 481

Last change on this file since 481 was 481, checked in by jrpelegrina, 4 years ago

First release to xenial

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