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