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