Added copyright lines for files I've edited this year.
[synfig.git] / synfig-core / trunk / src / synfig / valuenode_dynamiclist.cpp
1 /* === S Y N F I G ========================================================= */
2 /*!     \file valuenode_dynamiclist.cpp
3 **      \brief Implementation of the "Dynamic List" valuenode conversion.
4 **
5 **      $Id$
6 **
7 **      \legal
8 **      Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 **      Copyright (c) 2008 Chris Moore
10 **
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.
15 **
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.
20 **      \endlegal
21 */
22 /* ========================================================================= */
23
24 /* === H E A D E R S ======================================================= */
25
26 #ifdef USING_PCH
27 #       include "pch.h"
28 #else
29 #ifdef HAVE_CONFIG_H
30 #       include <config.h>
31 #endif
32
33 #include "valuenode_dynamiclist.h"
34 #include "valuenode_const.h"
35 #include "valuenode_composite.h"
36 #include "general.h"
37 #include "exception.h"
38 #include <vector>
39 #include <list>
40 #include <algorithm>
41 #include "canvas.h"
42
43 #endif
44
45 /* === U S I N G =========================================================== */
46
47 using namespace std;
48 using namespace etl;
49 using namespace synfig;
50
51 /* === M A C R O S ========================================================= */
52
53 /* === G L O B A L S ======================================================= */
54
55 /* === P R O C E D U R E S ================================================= */
56
57 /* === M E T H O D S ======================================================= */
58
59 ValueNode_DynamicList::ListEntry::ListEntry():
60         index(0)
61 {
62 }
63
64 ValueNode_DynamicList::ListEntry::ListEntry(const ValueNode::Handle &value_node):
65         value_node(value_node),
66         index(0)
67 {
68 }
69
70 ValueNode_DynamicList::ListEntry::ListEntry(const ValueNode::Handle &value_node,Time begin, Time end):
71         value_node(value_node)
72 {
73         add(begin,false);
74         add(end,false);
75         add((begin+end)*0.5,true);
76 }
77
78 ValueNode_DynamicList::ListEntry::ActivepointList::iterator
79 ValueNode_DynamicList::ListEntry::add(Time time, bool status, int priority)
80 {
81         typedef synfig::ValueNode_DynamicList::ListEntry::ActivepointList::iterator iterator;
82
83         //! \optimize
84         Activepoint ap(time,status,priority);
85         ap.set_parent_index(get_index());
86         ap.set_parent_value_node(get_parent_value_node());
87         timing_info.push_back(ap);
88         iterator iter(--iterator(timing_info.end()));
89         timing_info.sort();
90
91         return iter;
92 }
93
94 ValueNode_DynamicList::ListEntry::ActivepointList::iterator
95 ValueNode_DynamicList::ListEntry::add(const Activepoint &x)
96 {
97         typedef synfig::ValueNode_DynamicList::ListEntry::ActivepointList::iterator iterator;
98
99         //! \optimize
100         Activepoint ap(x);
101         ap.set_parent_index(get_index());
102         ap.set_parent_value_node(get_parent_value_node());
103         timing_info.push_back(ap);
104         iterator iter(--iterator(timing_info.end()));
105         timing_info.sort();
106
107         return iter;
108 }
109
110 void
111 ValueNode_DynamicList::reindex()
112 {
113         int i(0);
114
115         std::vector<ListEntry>::iterator iter;
116
117         for(iter=list.begin();iter!=list.end();++iter)
118         {
119                 assert(iter->value_node);
120                 if(iter->index!=i || iter->get_parent_value_node().get()!=this)
121                 {
122                         ActivepointList::iterator iter2;
123
124                         if(iter->timing_info.size()) // is this line really necessary?
125                         for(iter2=iter->timing_info.begin();iter2!=iter->timing_info.end();++iter2)
126                         {
127                                 iter2->set_parent_index(i);
128                                 iter2->set_parent_value_node(this);
129                         }
130                         iter->index=i;
131                         iter->set_parent_value_node(this);
132                 }
133         }
134 }
135
136 ValueNode_DynamicList::ListEntry
137 ValueNode_DynamicList::create_list_entry(int index, Time time, Real origin)
138 {
139         ValueNode_DynamicList::ListEntry ret;
140
141
142         synfig::ValueBase prev,next;
143
144         index=index%link_count();
145
146         assert(index>=0);
147
148         ret.index=index;
149         ret.set_parent_value_node(this);
150
151         next=(*list[index].value_node)(time);
152
153         if(index!=0)
154                 prev=(*list[index-1].value_node)(time);
155         else
156         {
157                 if(get_loop())
158                         prev=(*list[link_count()-1].value_node)(time);
159                 else
160                 {
161                         prev=next;
162                 }
163         }
164
165
166         switch(get_contained_type())
167         {
168         case ValueBase::TYPE_VECTOR:
169         {
170                 Vector a(prev.get(Vector())), b(next.get(Vector()));
171                 ret.value_node=ValueNode_Const::create((b-a)*origin+a);
172                 break;
173         }
174         case ValueBase::TYPE_REAL:
175         {
176                 Real a(prev.get(Real())), b(next.get(Real()));
177                 ret.value_node=ValueNode_Const::create((b-a)*origin+a);
178                 break;
179         }
180         case ValueBase::TYPE_COLOR:
181         {
182                 Color a(prev.get(Color())), b(next.get(Color()));
183                 ret.value_node=ValueNode_Composite::create((b-a)*origin+a);
184                 break;
185         }
186         case ValueBase::TYPE_ANGLE:
187         {
188                 Angle a(prev.get(Angle())), b(next.get(Angle()));
189                 ret.value_node=ValueNode_Const::create((b-a)*origin+a);
190                 break;
191         }
192         case ValueBase::TYPE_TIME:
193         {
194                 Time a(prev.get(Time())), b(next.get(Time()));
195                 ret.value_node=ValueNode_Const::create((b-a)*origin+a);
196                 break;
197         }
198         default:
199                 ret.value_node=ValueNode_Const::create(get_contained_type());
200                 break;
201         }
202
203
204         return ret;
205 }
206
207 ValueNode_DynamicList::ListEntry::ActivepointList::iterator
208 ValueNode_DynamicList::ListEntry::find(const UniqueID& x)
209 {
210         return std::find(timing_info.begin(),timing_info.end(),x);
211 }
212
213 ValueNode_DynamicList::ListEntry::ActivepointList::const_iterator
214 ValueNode_DynamicList::ListEntry::find(const UniqueID& x)const
215 {
216         return std::find(timing_info.begin(),timing_info.end(),x);
217 }
218
219 void
220 ValueNode_DynamicList::ListEntry::erase(const UniqueID& x)
221 {
222         timing_info.erase(find(x));
223 }
224
225 ValueNode_DynamicList::ListEntry::ActivepointList::iterator
226 ValueNode_DynamicList::ListEntry::find(const Time& x)
227 {
228         typedef synfig::ValueNode_DynamicList::ListEntry::ActivepointList ActivepointList;
229
230         ActivepointList::iterator iter;
231
232         for(iter=timing_info.begin();iter!=timing_info.end();++iter)
233                 if(iter->time==x)
234                         return iter;
235
236         throw Exception::NotFound("ValueNode_DynamicList::ListEntry::find():"+x.get_string());
237 }
238
239 ValueNode_DynamicList::ListEntry::ActivepointList::const_iterator
240 ValueNode_DynamicList::ListEntry::find(const Time& x)const
241 {
242         typedef synfig::ValueNode_DynamicList::ListEntry::ActivepointList ActivepointList;
243
244         ActivepointList::const_iterator iter;
245
246         for(iter=timing_info.begin();iter!=timing_info.end();++iter)
247                 if(iter->time==x)
248                         return iter;
249
250         throw Exception::NotFound("ValueNode_DynamicList::ListEntry::find()const:"+x.get_string());
251 }
252
253 ValueNode_DynamicList::ListEntry::ActivepointList::iterator
254 ValueNode_DynamicList::ListEntry::find_next(const Time& x)
255 {
256         typedef synfig::ValueNode_DynamicList::ListEntry::ActivepointList ActivepointList;
257
258         ActivepointList::iterator iter;
259
260         for(iter=timing_info.begin();iter!=timing_info.end();++iter)
261                 if(iter->time>x)
262                         return iter;
263
264         throw Exception::NotFound("ValueNode_DynamicList::ListEntry::find_next():"+x.get_string());
265 }
266
267 ValueNode_DynamicList::ListEntry::ActivepointList::const_iterator
268 ValueNode_DynamicList::ListEntry::find_next(const Time& x)const
269 {
270         typedef synfig::ValueNode_DynamicList::ListEntry::ActivepointList ActivepointList;
271
272         ActivepointList::const_iterator iter;
273
274         for(iter=timing_info.begin();iter!=timing_info.end();++iter)
275                 if(iter->time>x)
276                         return iter;
277
278         throw Exception::NotFound("ValueNode_DynamicList::ListEntry::find_next()const:"+x.get_string());
279 }
280
281 ValueNode_DynamicList::ListEntry::ActivepointList::iterator
282 ValueNode_DynamicList::ListEntry::find_prev(const Time& x)
283 {
284         typedef synfig::ValueNode_DynamicList::ListEntry::ActivepointList ActivepointList;
285
286         ActivepointList::iterator iter;
287         iter=timing_info.end();
288         do
289         {
290                 --iter;
291                 if(iter->time<x)
292                         return iter;
293         }
294         while(iter!=timing_info.begin());
295
296         throw Exception::NotFound("ValueNode_DynamicList::ListEntry::find_prev():"+x.get_string());
297 }
298
299 ValueNode_DynamicList::ListEntry::ActivepointList::const_iterator
300 ValueNode_DynamicList::ListEntry::find_prev(const Time& x)const
301 {
302         typedef synfig::ValueNode_DynamicList::ListEntry::ActivepointList ActivepointList;
303
304         ActivepointList::const_iterator iter;
305         iter=timing_info.end();
306         do
307         {
308                 --iter;
309                 if(iter->time<x)
310                         return iter;
311         }
312         while(iter!=timing_info.begin());
313
314         throw Exception::NotFound("ValueNode_DynamicList::ListEntry::find_prev()const:"+x.get_string());
315 }
316
317 int
318 ValueNode_DynamicList::ListEntry::find(const Time& begin,const Time& end,std::vector<Activepoint*>& selected)
319 {
320         Time curr_time(begin);
321         int ret(0);
322
323         // try to grab first waypoint
324         try
325         {
326                 ActivepointList::iterator iter;
327                 iter=find(curr_time);
328                 selected.push_back(&*iter);
329                 ret++;
330         }
331         catch(...) { }
332
333         try
334         {
335                 ActivepointList::iterator iter;
336                 while(true)
337                 {
338                         iter=find_next(curr_time);
339                         curr_time=iter->get_time();
340                         if(curr_time>=end)
341                                 break;
342                         selected.push_back(&*iter);
343                         ret++;
344                 }
345         }
346         catch(...) { }
347
348         return ret;
349 }
350
351 float
352 ValueNode_DynamicList::ListEntry::amount_at_time(const Time &t,bool *rising)const
353 {
354         typedef synfig::ValueNode_DynamicList::ListEntry::Activepoint Activepoint;
355         typedef synfig::ValueNode_DynamicList::ListEntry::ActivepointList ActivepointList;
356
357         if(timing_info.empty())
358                 return 1.0f;
359
360         try
361         {
362                 ActivepointList::const_iterator iter;
363                 iter=find(t);
364                 return iter->state?1.0f:0.0f;
365         }
366         catch(...) { }
367
368         ActivepointList::const_iterator prev_iter;
369         ActivepointList::const_iterator next_iter;
370
371         try     { prev_iter=find_prev(t); }
372         catch(...) { return find_next(t)->state?1.0f:0.0f; }
373
374         try     { next_iter=find_next(t); }
375         catch(...) { return prev_iter->state?1.0f:0.0f; }
376
377         if(next_iter->state==prev_iter->state)
378                 return next_iter->state?1.0f:0.0f;
379
380         if(rising)*rising=next_iter->state;
381
382         if(next_iter->state==true)
383                 return float((t-prev_iter->time)/(next_iter->time-prev_iter->time));
384
385         return float((next_iter->time-t)/(next_iter->time-prev_iter->time));
386 }
387
388 Activepoint
389 ValueNode_DynamicList::ListEntry::new_activepoint_at_time(const Time& time)const
390 {
391         Activepoint activepoint;
392
393         activepoint.set_state(status_at_time(time));
394         activepoint.set_priority(0);
395
396         return activepoint;
397 }
398
399 bool
400 ValueNode_DynamicList::ListEntry::status_at_time(const Time &t)const
401 {
402         typedef synfig::ValueNode_DynamicList::ListEntry::Activepoint Activepoint;
403         typedef synfig::ValueNode_DynamicList::ListEntry::ActivepointList ActivepointList;
404
405         ActivepointList::const_iterator entry_iter;
406         ActivepointList::const_iterator prev_iter;
407         bool state(true);
408
409         // New "symmetric" state mechanism
410         if(!timing_info.empty())
411         {
412                 if(timing_info.size()==1)
413                         state=timing_info.front().state;
414                 else
415                 {
416                         //! \optimize Perhaps we should use a binary search...?
417                         // This will give us the first activepoint that is after t.
418                         for(entry_iter=timing_info.begin();entry_iter!=timing_info.end();++entry_iter)
419                         {
420                                 if(entry_iter->time==t)
421                                 {
422                                         // If we hit the entry right on the nose, then we don't
423                                         // have to do anything more
424                                         return entry_iter->state;
425                                 }
426                                 if(entry_iter->time>t)
427                                         break;
428
429                         }
430                         prev_iter=entry_iter;
431                         prev_iter--;
432
433                         // ie:
434                         //
435                         //              |-------|---t---|-------|
436                         //         prev_iter^           ^entry_iter
437
438                         if(entry_iter==timing_info.end())
439                         {
440                                 state=prev_iter->state;
441                         }
442                         else
443                         if(entry_iter==timing_info.begin())
444                         {
445                                 state=entry_iter->state;
446                         }
447                         else
448                         if(entry_iter->priority==prev_iter->priority)
449                         {
450                                 state=entry_iter->state || prev_iter->state;
451                         }
452                         else
453                         if(entry_iter->priority>prev_iter->priority)
454                         {
455                                 state=entry_iter->state;
456                         }
457                         else
458                         {
459                                 state=prev_iter->state;
460                         }
461                 }
462         }
463         return state;
464 }
465
466
467
468
469 void
470 ValueNode_DynamicList::add(const ValueNode::Handle &value_node, int index)
471 {
472         ListEntry list_entry(value_node);
473         list_entry.timing_info.size();
474
475         if(index<0 || index>=(int)list.size())
476         {
477                 list.push_back(list_entry);
478         }
479         else
480         {
481                 list.insert(list.begin()+index,list_entry);
482         }
483
484         add_child(value_node.get());
485         reindex();
486         //changed();
487
488         if(get_parent_canvas())
489                 get_parent_canvas()->signal_value_node_child_added()(this,value_node);
490         else if(get_root_canvas() && get_parent_canvas())
491                 get_root_canvas()->signal_value_node_child_added()(this,value_node);
492 }
493
494 void
495 ValueNode_DynamicList::add(const ListEntry &list_entry, int index)
496 {
497         if(index<0 || index>=(int)list.size())
498                 list.push_back(list_entry);
499         else
500                 list.insert(list.begin()+index,list_entry);
501         add_child(list_entry.value_node.get());
502
503         reindex();
504         //changed();
505
506         if(get_parent_canvas())
507                 get_parent_canvas()->signal_value_node_child_added()(this,list_entry.value_node);
508         else if(get_root_canvas() && get_parent_canvas())
509                 get_root_canvas()->signal_value_node_child_added()(this,list_entry.value_node);
510 }
511
512 void
513 ValueNode_DynamicList::erase(const ValueNode::Handle &value_node_)
514 {
515         ValueNode::Handle value_node(value_node_);
516
517         assert(value_node);
518         if(!value_node)
519                 throw String("ValueNode_DynamicList::erase(): Passed bad value node");
520
521         std::vector<ListEntry>::iterator iter;
522         for(iter=list.begin();iter!=list.end();++iter)
523                 if(iter->value_node==value_node)
524                 {
525                         list.erase(iter);
526                         if(value_node)
527                         {
528                                 remove_child(value_node.get());
529                                 // changed to fix bug 1420091 - it seems that when a .sif file containing a bline layer encapsulated inside
530                                 // another layer, get_parent_canvas() is false and get_root_canvas() is true, but when we come to erase a
531                                 // vertex, both are true.  So the signal is sent to the parent, but the signal wasn't sent to the parent
532                                 // when it was added.  This probably isn't the right fix, but it seems to work for now.  Note that the same
533                                 // strange "if (X) else if (Y && X)" code is also present in the two previous functions, above.
534
535                                 // if(get_parent_canvas())
536                                 //      get_parent_canvas()->signal_value_node_child_removed()(this,value_node);
537                                 // else if(get_root_canvas() && get_parent_canvas())
538                                 //      get_root_canvas()->signal_value_node_child_removed()(this,value_node);
539                                 if(get_root_canvas())
540                                         get_root_canvas()->signal_value_node_child_removed()(this,value_node);
541                         }
542                         break;
543                 }
544         reindex();
545 }
546
547
548 ValueNode_DynamicList::ValueNode_DynamicList(ValueBase::Type container_type):
549         LinkableValueNode(ValueBase::TYPE_LIST),
550         container_type  (container_type),
551         loop_(false)
552 {
553         DCAST_HACK_ENABLE();
554 }
555
556 ValueNode_DynamicList::Handle
557 ValueNode_DynamicList::create(ValueBase::Type id)
558 {
559         return new ValueNode_DynamicList(id);
560 }
561
562 ValueNode_DynamicList::~ValueNode_DynamicList()
563 {
564         unlink_all();
565 }
566
567 ValueNode_DynamicList*
568 ValueNode_DynamicList::create_from(const ValueBase &value)
569 {
570         //vector<ValueBase> value_list(value.operator vector<ValueBase>());
571         vector<ValueBase> value_list(value.get_list());
572
573         vector<ValueBase>::iterator iter;
574
575         if(value_list.empty())
576                 return 0;
577
578         ValueNode_DynamicList* value_node(new ValueNode_DynamicList(value_list.front().get_type()));
579
580         for(iter=value_list.begin();iter!=value_list.end();++iter)
581         {
582                 ValueNode::Handle item(ValueNode_Const::create(*iter));
583                 value_node->add(ListEntry(item));
584                 assert(value_node->list.back().value_node);
585         }
586         return value_node;
587 }
588
589 ValueBase
590 ValueNode_DynamicList::operator()(Time t)const
591 {
592         std::vector<ValueBase> ret_list;
593         std::vector<ListEntry>::const_iterator iter;
594
595         assert(container_type);
596
597         for(iter=list.begin();iter!=list.end();++iter)
598         {
599                 bool state(iter->status_at_time(t));
600
601                 if(state)
602                 {
603                         if(iter->value_node->get_type()==container_type)
604                                 ret_list.push_back((*iter->value_node)(t));
605                         else
606                         {
607                                 synfig::warning(string("ValueNode_DynamicList::operator()():")+_("List type/item type mismatch, throwing away mismatch"));
608                         }
609                 }
610         }
611
612         if(list.empty())
613                 synfig::warning(string("ValueNode_DynamicList::operator()():")+_("No entries in list"));
614         else
615         if(ret_list.empty())
616                 synfig::warning(string("ValueNode_DynamicList::operator()():")+_("No entries in ret_list"));
617
618         return ret_list;
619 }
620
621 bool
622 ValueNode_DynamicList::set_link_vfunc(int i,ValueNode::Handle x)
623 {
624         assert(i>=0);
625
626         if((unsigned)i>=list.size())
627                 return false;
628         if(x->get_type()!=container_type)
629                 return false;
630         list[i].value_node=x;
631         return true;
632 }
633
634 ValueNode::LooseHandle
635 ValueNode_DynamicList::get_link_vfunc(int i)const
636 {
637         assert(i>=0);
638
639         if((unsigned)i>=list.size())
640                 return 0;
641         return list[i].value_node;
642 }
643
644 int
645 ValueNode_DynamicList::link_count()const
646 {
647         return list.size();
648 }
649
650 String
651 ValueNode_DynamicList::link_local_name(int i)const
652 {
653         assert(i>=0 && i<link_count());
654
655         return etl::strprintf(_("Item %03d"),i+1);
656 }
657
658 ValueNode*
659 ValueNode_DynamicList::clone(const GUID& deriv_guid)const
660 {
661         { ValueNode* x(find_value_node(get_guid()^deriv_guid).get()); if(x)return x; }
662
663         ValueNode_DynamicList* ret=new ValueNode_DynamicList(container_type);
664         ret->set_guid(get_guid()^deriv_guid);
665
666         std::vector<ListEntry>::const_iterator iter;
667
668         for(iter=list.begin();iter!=list.end();++iter)
669         {
670                 if(iter->value_node->is_exported())
671                         ret->add(*iter);
672                 else
673                 {
674                         ListEntry list_entry(*iter);
675                         //list_entry.value_node=find_value_node(iter->value_node->get_guid()^deriv_guid).get();
676                         //if(!list_entry.value_node)
677                                 list_entry.value_node=iter->value_node->clone(deriv_guid);
678                         ret->add(list_entry);
679                         //ret->list.back().value_node=iter->value_node.clone();
680                 }
681         }
682         ret->set_loop(get_loop());
683         return ret;
684 }
685
686 String
687 ValueNode_DynamicList::link_name(int i)const
688 {
689         return strprintf("item%04d",i);
690 }
691
692 int
693 ValueNode_DynamicList::get_link_index_from_name(const String &name)const
694 {
695         throw Exception::BadLinkName(name);
696 }
697
698 String
699 ValueNode_DynamicList::get_name()const
700 {
701         return "dynamic_list";
702 }
703
704 String
705 ValueNode_DynamicList::get_local_name()const
706 {
707         return _("Dynamic List");
708 }
709
710 bool
711 ValueNode_DynamicList::check_type(ValueBase::Type type)
712 {
713         return type==ValueBase::TYPE_LIST;
714 }
715
716 ValueBase::Type
717 ValueNode_DynamicList::get_contained_type()const
718 {
719         return container_type;
720 }
721
722 LinkableValueNode*
723 ValueNode_DynamicList::create_new()const
724 {
725         assert(0);
726
727         return 0;
728 }
729
730 int
731 ValueNode_DynamicList::find_next_valid_entry(int orig_item, Time t)const
732 {
733         int curr_item;
734
735         for(curr_item=orig_item+1;curr_item!=orig_item;curr_item++)
736         {
737                 if(curr_item==(int)list.size())
738                 {
739                         curr_item=0;
740                         continue;
741                 }
742                 if(list[curr_item].status_at_time(t))
743                         return curr_item;
744         }
745         return curr_item;
746 }
747
748 int
749 ValueNode_DynamicList::find_prev_valid_entry(int orig_item, Time t)const
750 {
751         int curr_item;
752
753         for(curr_item=orig_item-1;curr_item!=orig_item;curr_item--)
754         {
755                 if(curr_item==-1)
756                 {
757                         curr_item=list.size();
758                         continue;
759                 }
760                 if(list[curr_item].status_at_time(t))
761                         return curr_item;
762         }
763         return curr_item;
764 }
765
766 const synfig::Node::time_set    & ValueNode_DynamicList::ListEntry::get_times() const
767 {
768         synfig::ActivepointList::const_iterator         j = timing_info.begin(),
769                                                                                         end = timing_info.end();
770
771         //must remerge with all the other values because we don't know if we've changed...
772         times = value_node->get_times();
773
774         for(; j != end; ++j)
775         {
776                 TimePoint t;
777                 t.set_time(j->get_time());
778                 t.set_guid(j->get_guid());
779
780                 times.insert(t);
781         }
782
783         return times;
784 }
785
786 void ValueNode_DynamicList::get_times_vfunc(Node::time_set &set) const
787 {
788         //add in the active points
789         int size = list.size();
790
791         //rebuild all the info...
792         for(int i = 0; i < size; ++i)
793         {
794                 const Node::time_set & tset= list[i].get_times();
795                 set.insert(tset.begin(),tset.end());
796         }
797 }
798
799
800 //new find functions that don't throw
801 struct timecmp
802 {
803         Time t;
804
805         timecmp(const Time &c) :t(c) {}
806
807         bool operator()(const Activepoint &rhs) const
808         {
809                 return t.is_equal(rhs.get_time());
810         }
811 };
812
813 ValueNode_DynamicList::ListEntry::findresult ValueNode_DynamicList::ListEntry::find_uid(const UniqueID& x)
814 {
815         findresult f;
816         f.second = false;
817
818         f.first = std::find(timing_info.begin(),timing_info.end(),x);
819
820         if(f.first != timing_info.end())
821         {
822                 f.second = true;
823         }
824
825         return f;
826 }
827
828 ValueNode_DynamicList::ListEntry::const_findresult ValueNode_DynamicList::ListEntry::find_uid(const UniqueID& x) const
829 {
830         const_findresult f;
831         f.second = false;
832
833         f.first = std::find(timing_info.begin(),timing_info.end(),x);
834
835         if(f.first != timing_info.end())
836         {
837                 f.second = true;
838         }
839
840         return f;
841 }
842
843 ValueNode_DynamicList::ListEntry::findresult ValueNode_DynamicList::ListEntry::find_time(const Time& x)
844 {
845         findresult f;
846         f.second = false;
847
848         f.first = std::find_if(timing_info.begin(),timing_info.end(),timecmp(x));
849
850         if(f.first != timing_info.end())
851         {
852                 f.second = true;
853         }
854
855         return f;
856 }
857
858 ValueNode_DynamicList::ListEntry::const_findresult ValueNode_DynamicList::ListEntry::find_time(const Time& x)const
859 {
860         const_findresult f;
861         f.second = false;
862
863         f.first = std::find_if(timing_info.begin(),timing_info.end(),timecmp(x));
864
865         if(f.first != timing_info.end())
866         {
867                 f.second = true;
868         }
869
870         return f;
871 }
872
873 void
874 ValueNode_DynamicList::insert_time(const Time& location, const Time& delta)
875 {
876         if(!delta)
877                 return;
878
879         std::vector<ListEntry>::iterator iter(list.begin());
880         for(;iter!=list.end();++iter)
881         {
882                 try
883                 {
884                         ListEntry& item(*iter);
885
886                         ActivepointList::iterator iter(item.find_next(location));
887                         for(;iter!=item.timing_info.end();++iter)
888                         {
889                                 iter->set_time(iter->get_time()+delta);
890                         }
891                 }
892                 catch(Exception::NotFound) { }
893         }
894         changed();
895 }