Remove .gitignore do nothing is ignored.
[synfig.git] / synfig-core / trunk / src / synfig / valuenode_dynamiclist.cpp
index d3fec2d..a8c253a 100644 (file)
@@ -1,20 +1,22 @@
 /* === S Y N F I G ========================================================= */
 /*!    \file valuenode_dynamiclist.cpp
-**     \brief Template File
+**     \brief Implementation of the "Dynamic List" valuenode conversion.
 **
-**     $Id: valuenode_dynamiclist.cpp,v 1.1.1.1 2005/01/04 01:23:15 darco Exp $
+**     $Id$
 **
 **     \legal
-**     Copyright (c) 2002 Robert B. Quattlebaum Jr.
+**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+**     Copyright (c) 2008 Chris Moore
 **
-**     This software and associated documentation
-**     are CONFIDENTIAL and PROPRIETARY property of
-**     the above-mentioned copyright holder.
+**     This package is free software; you can redistribute it and/or
+**     modify it under the terms of the GNU General Public License as
+**     published by the Free Software Foundation; either version 2 of
+**     the License, or (at your option) any later version.
 **
-**     You may not copy, print, publish, or in any
-**     other way distribute this software without
-**     a prior written agreement with
-**     the copyright holder.
+**     This package is distributed in the hope that it will be useful,
+**     but WITHOUT ANY WARRANTY; without even the implied warranty of
+**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+**     General Public License for more details.
 **     \endlegal
 */
 /* ========================================================================= */
@@ -77,7 +79,7 @@ ValueNode_DynamicList::ListEntry::ActivepointList::iterator
 ValueNode_DynamicList::ListEntry::add(Time time, bool status, int priority)
 {
        typedef synfig::ValueNode_DynamicList::ListEntry::ActivepointList::iterator iterator;
-       
+
        //! \optimize
        Activepoint ap(time,status,priority);
        ap.set_parent_index(get_index());
@@ -85,7 +87,7 @@ ValueNode_DynamicList::ListEntry::add(Time time, bool status, int priority)
        timing_info.push_back(ap);
        iterator iter(--iterator(timing_info.end()));
        timing_info.sort();
-       
+
        return iter;
 }
 
@@ -93,7 +95,7 @@ ValueNode_DynamicList::ListEntry::ActivepointList::iterator
 ValueNode_DynamicList::ListEntry::add(const Activepoint &x)
 {
        typedef synfig::ValueNode_DynamicList::ListEntry::ActivepointList::iterator iterator;
-       
+
        //! \optimize
        Activepoint ap(x);
        ap.set_parent_index(get_index());
@@ -101,7 +103,7 @@ ValueNode_DynamicList::ListEntry::add(const Activepoint &x)
        timing_info.push_back(ap);
        iterator iter(--iterator(timing_info.end()));
        timing_info.sort();
-       
+
        return iter;
 }
 
@@ -109,7 +111,7 @@ void
 ValueNode_DynamicList::reindex()
 {
        int i(0);
-       
+
        std::vector<ListEntry>::iterator iter;
 
        for(iter=list.begin();iter!=list.end();++iter)
@@ -125,7 +127,7 @@ ValueNode_DynamicList::reindex()
                                iter2->set_parent_index(i);
                                iter2->set_parent_value_node(this);
                        }
-                       iter->index=i;          
+                       iter->index=i;
                        iter->set_parent_value_node(this);
                }
        }
@@ -135,19 +137,19 @@ ValueNode_DynamicList::ListEntry
 ValueNode_DynamicList::create_list_entry(int index, Time time, Real origin)
 {
        ValueNode_DynamicList::ListEntry ret;
-       
-       
+
+
        synfig::ValueBase prev,next;
 
        index=index%link_count();
 
        assert(index>=0);
-       
+
        ret.index=index;
        ret.set_parent_value_node(this);
-       
+
        next=(*list[index].value_node)(time);
-       
+
        if(index!=0)
                prev=(*list[index-1].value_node)(time);
        else
@@ -159,8 +161,8 @@ ValueNode_DynamicList::create_list_entry(int index, Time time, Real origin)
                        prev=next;
                }
        }
-       
-       
+
+
        switch(get_contained_type())
        {
        case ValueBase::TYPE_VECTOR:
@@ -198,7 +200,7 @@ ValueNode_DynamicList::create_list_entry(int index, Time time, Real origin)
                break;
        }
 
-       
+
        return ret;
 }
 
@@ -224,63 +226,63 @@ ValueNode_DynamicList::ListEntry::ActivepointList::iterator
 ValueNode_DynamicList::ListEntry::find(const Time& x)
 {
        typedef synfig::ValueNode_DynamicList::ListEntry::ActivepointList ActivepointList;
-       
+
        ActivepointList::iterator iter;
 
        for(iter=timing_info.begin();iter!=timing_info.end();++iter)
                if(iter->time==x)
                        return iter;
 
-       throw Exception::NotFound("ValueNode_DynamicList::ListEntry::find():"+x.get_string());  
+       throw Exception::NotFound("ValueNode_DynamicList::ListEntry::find():"+x.get_string());
 }
 
 ValueNode_DynamicList::ListEntry::ActivepointList::const_iterator
 ValueNode_DynamicList::ListEntry::find(const Time& x)const
 {
        typedef synfig::ValueNode_DynamicList::ListEntry::ActivepointList ActivepointList;
-       
+
        ActivepointList::const_iterator iter;
 
        for(iter=timing_info.begin();iter!=timing_info.end();++iter)
                if(iter->time==x)
                        return iter;
 
-       throw Exception::NotFound("ValueNode_DynamicList::ListEntry::find()const:"+x.get_string());     
+       throw Exception::NotFound("ValueNode_DynamicList::ListEntry::find()const:"+x.get_string());
 }
 
 ValueNode_DynamicList::ListEntry::ActivepointList::iterator
 ValueNode_DynamicList::ListEntry::find_next(const Time& x)
 {
        typedef synfig::ValueNode_DynamicList::ListEntry::ActivepointList ActivepointList;
-       
+
        ActivepointList::iterator iter;
 
        for(iter=timing_info.begin();iter!=timing_info.end();++iter)
                if(iter->time>x)
                        return iter;
 
-       throw Exception::NotFound("ValueNode_DynamicList::ListEntry::find_next():"+x.get_string());     
+       throw Exception::NotFound("ValueNode_DynamicList::ListEntry::find_next():"+x.get_string());
 }
 
 ValueNode_DynamicList::ListEntry::ActivepointList::const_iterator
 ValueNode_DynamicList::ListEntry::find_next(const Time& x)const
 {
        typedef synfig::ValueNode_DynamicList::ListEntry::ActivepointList ActivepointList;
-       
+
        ActivepointList::const_iterator iter;
 
        for(iter=timing_info.begin();iter!=timing_info.end();++iter)
                if(iter->time>x)
                        return iter;
 
-       throw Exception::NotFound("ValueNode_DynamicList::ListEntry::find_next()const:"+x.get_string());        
+       throw Exception::NotFound("ValueNode_DynamicList::ListEntry::find_next()const:"+x.get_string());
 }
 
 ValueNode_DynamicList::ListEntry::ActivepointList::iterator
 ValueNode_DynamicList::ListEntry::find_prev(const Time& x)
 {
        typedef synfig::ValueNode_DynamicList::ListEntry::ActivepointList ActivepointList;
-       
+
        ActivepointList::iterator iter;
        iter=timing_info.end();
        do
@@ -291,14 +293,14 @@ ValueNode_DynamicList::ListEntry::find_prev(const Time& x)
        }
        while(iter!=timing_info.begin());
 
-       throw Exception::NotFound("ValueNode_DynamicList::ListEntry::find_prev():"+x.get_string());     
+       throw Exception::NotFound("ValueNode_DynamicList::ListEntry::find_prev():"+x.get_string());
 }
 
 ValueNode_DynamicList::ListEntry::ActivepointList::const_iterator
 ValueNode_DynamicList::ListEntry::find_prev(const Time& x)const
 {
        typedef synfig::ValueNode_DynamicList::ListEntry::ActivepointList ActivepointList;
-       
+
        ActivepointList::const_iterator iter;
        iter=timing_info.end();
        do
@@ -309,7 +311,7 @@ ValueNode_DynamicList::ListEntry::find_prev(const Time& x)const
        }
        while(iter!=timing_info.begin());
 
-       throw Exception::NotFound("ValueNode_DynamicList::ListEntry::find_prev()const:"+x.get_string());        
+       throw Exception::NotFound("ValueNode_DynamicList::ListEntry::find_prev()const:"+x.get_string());
 }
 
 int
@@ -317,7 +319,7 @@ ValueNode_DynamicList::ListEntry::find(const Time& begin,const Time& end,std::ve
 {
        Time curr_time(begin);
        int ret(0);
-       
+
        // try to grab first waypoint
        try
        {
@@ -327,7 +329,7 @@ ValueNode_DynamicList::ListEntry::find(const Time& begin,const Time& end,std::ve
                ret++;
        }
        catch(...) { }
-       
+
        try
        {
                ActivepointList::iterator iter;
@@ -342,7 +344,7 @@ ValueNode_DynamicList::ListEntry::find(const Time& begin,const Time& end,std::ve
                }
        }
        catch(...) { }
-       
+
        return ret;
 }
 
@@ -351,10 +353,10 @@ ValueNode_DynamicList::ListEntry::amount_at_time(const Time &t,bool *rising)cons
 {
        typedef synfig::ValueNode_DynamicList::ListEntry::Activepoint Activepoint;
        typedef synfig::ValueNode_DynamicList::ListEntry::ActivepointList ActivepointList;
-       
+
        if(timing_info.empty())
                return 1.0f;
-               
+
        try
        {
                ActivepointList::const_iterator iter;
@@ -368,13 +370,13 @@ ValueNode_DynamicList::ListEntry::amount_at_time(const Time &t,bool *rising)cons
 
        try     { prev_iter=find_prev(t); }
        catch(...) { return find_next(t)->state?1.0f:0.0f; }
-       
+
        try     { next_iter=find_next(t); }
        catch(...) { return prev_iter->state?1.0f:0.0f; }
-       
+
        if(next_iter->state==prev_iter->state)
                return next_iter->state?1.0f:0.0f;
-       
+
        if(rising)*rising=next_iter->state;
 
        if(next_iter->state==true)
@@ -387,10 +389,10 @@ Activepoint
 ValueNode_DynamicList::ListEntry::new_activepoint_at_time(const Time& time)const
 {
        Activepoint activepoint;
-       
+
        activepoint.set_state(status_at_time(time));
        activepoint.set_priority(0);
-       
+
        return activepoint;
 }
 
@@ -399,12 +401,12 @@ ValueNode_DynamicList::ListEntry::status_at_time(const Time &t)const
 {
        typedef synfig::ValueNode_DynamicList::ListEntry::Activepoint Activepoint;
        typedef synfig::ValueNode_DynamicList::ListEntry::ActivepointList ActivepointList;
-       
+
        ActivepointList::const_iterator entry_iter;
        ActivepointList::const_iterator prev_iter;
        bool state(true);
 
-       // New "symetric" state mechanism
+       // New "symmetric" state mechanism
        if(!timing_info.empty())
        {
                if(timing_info.size()==1)
@@ -423,16 +425,16 @@ ValueNode_DynamicList::ListEntry::status_at_time(const Time &t)const
                                }
                                if(entry_iter->time>t)
                                        break;
-                               
+
                        }
                        prev_iter=entry_iter;
                        prev_iter--;
-                       
+
                        // ie:
                        //
                        //              |-------|---t---|-------|
                        //         prev_iter^           ^entry_iter
-                       
+
                        if(entry_iter==timing_info.end())
                        {
                                state=prev_iter->state;
@@ -454,8 +456,8 @@ ValueNode_DynamicList::ListEntry::status_at_time(const Time &t)const
                        }
                        else
                        {
-                               state=prev_iter->state;                         
-                       }                               
+                               state=prev_iter->state;
+                       }
                }
        }
        return state;
@@ -469,7 +471,7 @@ ValueNode_DynamicList::add(const ValueNode::Handle &value_node, int index)
 {
        ListEntry list_entry(value_node);
        list_entry.timing_info.size();
-       
+
        if(index<0 || index>=(int)list.size())
        {
                list.push_back(list_entry);
@@ -511,11 +513,11 @@ void
 ValueNode_DynamicList::erase(const ValueNode::Handle &value_node_)
 {
        ValueNode::Handle value_node(value_node_);
-       
+
        assert(value_node);
        if(!value_node)
                throw String("ValueNode_DynamicList::erase(): Passed bad value node");
-       
+
        std::vector<ListEntry>::iterator iter;
        for(iter=list.begin();iter!=list.end();++iter)
                if(iter->value_node==value_node)
@@ -524,9 +526,17 @@ ValueNode_DynamicList::erase(const ValueNode::Handle &value_node_)
                        if(value_node)
                        {
                                remove_child(value_node.get());
-                               if(get_parent_canvas())
-                                       get_parent_canvas()->signal_value_node_child_removed()(this,value_node);
-                               else if(get_root_canvas() && get_parent_canvas())
+                               // changed to fix bug 1420091 - it seems that when a .sif file containing a bline layer encapsulated inside
+                               // another layer, get_parent_canvas() is false and get_root_canvas() is true, but when we come to erase a
+                               // vertex, both are true.  So the signal is sent to the parent, but the signal wasn't sent to the parent
+                               // when it was added.  This probably isn't the right fix, but it seems to work for now.  Note that the same
+                               // strange "if (X) else if (Y && X)" code is also present in the two previous functions, above.
+
+                               // if(get_parent_canvas())
+                               //      get_parent_canvas()->signal_value_node_child_removed()(this,value_node);
+                               // else if(get_root_canvas() && get_parent_canvas())
+                               //      get_root_canvas()->signal_value_node_child_removed()(this,value_node);
+                               if(get_root_canvas())
                                        get_root_canvas()->signal_value_node_child_removed()(this,value_node);
                        }
                        break;
@@ -564,9 +574,15 @@ ValueNode_DynamicList::create_from(const ValueBase &value)
 
        if(value_list.empty())
                return 0;
-       
+
        ValueNode_DynamicList* value_node(new ValueNode_DynamicList(value_list.front().get_type()));
-       
+
+       // when creating a list of vectors, start it off being looped.
+       // I think the only time this is used if for creating polygons,
+       // and we want them to be looped by default
+       if (value_node->get_contained_type() == ValueBase::TYPE_VECTOR)
+               value_node->set_loop(true);
+
        for(iter=value_list.begin();iter!=value_list.end();++iter)
        {
                ValueNode::Handle item(ValueNode_Const::create(*iter));
@@ -579,6 +595,9 @@ ValueNode_DynamicList::create_from(const ValueBase &value)
 ValueBase
 ValueNode_DynamicList::operator()(Time t)const
 {
+       if (getenv("SYNFIG_DEBUG_VALUENODE_OPERATORS"))
+               printf("%s:%d operator()\n", __FILE__, __LINE__);
+
        std::vector<ValueBase> ret_list;
        std::vector<ListEntry>::const_iterator iter;
 
@@ -587,7 +606,7 @@ ValueNode_DynamicList::operator()(Time t)const
        for(iter=list.begin();iter!=list.end();++iter)
        {
                bool state(iter->status_at_time(t));
-               
+
                if(state)
                {
                        if(iter->value_node->get_type()==container_type)
@@ -598,7 +617,7 @@ ValueNode_DynamicList::operator()(Time t)const
                        }
                }
        }
-       
+
        if(list.empty())
                synfig::warning(string("ValueNode_DynamicList::operator()():")+_("No entries in list"));
        else
@@ -612,6 +631,7 @@ bool
 ValueNode_DynamicList::set_link_vfunc(int i,ValueNode::Handle x)
 {
        assert(i>=0);
+
        if((unsigned)i>=list.size())
                return false;
        if(x->get_type()!=container_type)
@@ -624,6 +644,7 @@ ValueNode::LooseHandle
 ValueNode_DynamicList::get_link_vfunc(int i)const
 {
        assert(i>=0);
+
        if((unsigned)i>=list.size())
                return 0;
        return list[i].value_node;
@@ -638,16 +659,17 @@ ValueNode_DynamicList::link_count()const
 String
 ValueNode_DynamicList::link_local_name(int i)const
 {
-       assert(i>=0 && (unsigned)i<list.size());
+       assert(i>=0 && i<link_count());
+
        return etl::strprintf(_("Item %03d"),i+1);
-}      
+}
 
 ValueNode*
 ValueNode_DynamicList::clone(const GUID& deriv_guid)const
 {
        { ValueNode* x(find_value_node(get_guid()^deriv_guid).get()); if(x)return x; }
 
-       ValueNode_DynamicList* ret=new ValueNode_DynamicList(container_type);
+       ValueNode_DynamicList* ret=dynamic_cast<ValueNode_DynamicList*>(create_new());
        ret->set_guid(get_guid()^deriv_guid);
 
        std::vector<ListEntry>::const_iterator iter;
@@ -657,11 +679,11 @@ ValueNode_DynamicList::clone(const GUID& deriv_guid)const
                if(iter->value_node->is_exported())
                        ret->add(*iter);
                else
-               {               
+               {
                        ListEntry list_entry(*iter);
                        //list_entry.value_node=find_value_node(iter->value_node->get_guid()^deriv_guid).get();
                        //if(!list_entry.value_node)
-                               list_entry.value_node=iter->value_node->clone(deriv_guid);
+                       list_entry.value_node=iter->value_node->clone(deriv_guid);
                        ret->add(list_entry);
                        //ret->list.back().value_node=iter->value_node.clone();
                }
@@ -700,6 +722,13 @@ ValueNode_DynamicList::check_type(ValueBase::Type type)
        return type==ValueBase::TYPE_LIST;
 }
 
+void
+ValueNode_DynamicList::set_member_canvas(etl::loose_handle<Canvas> canvas)
+{
+       for (vector<ListEntry>::iterator iter = list.begin(); iter != list.end(); iter++)
+               iter->value_node->set_parent_canvas(canvas);
+}
+
 ValueBase::Type
 ValueNode_DynamicList::get_contained_type()const
 {
@@ -709,15 +738,14 @@ ValueNode_DynamicList::get_contained_type()const
 LinkableValueNode*
 ValueNode_DynamicList::create_new()const
 {
-       assert(0);
-       return 0;
+       return new ValueNode_DynamicList(container_type);
 }
 
 int
 ValueNode_DynamicList::find_next_valid_entry(int orig_item, Time t)const
 {
        int curr_item;
-       
+
        for(curr_item=orig_item+1;curr_item!=orig_item;curr_item++)
        {
                if(curr_item==(int)list.size())
@@ -735,7 +763,7 @@ int
 ValueNode_DynamicList::find_prev_valid_entry(int orig_item, Time t)const
 {
        int curr_item;
-       
+
        for(curr_item=orig_item-1;curr_item!=orig_item;curr_item--)
        {
                if(curr_item==-1)
@@ -753,10 +781,10 @@ const synfig::Node::time_set      & ValueNode_DynamicList::ListEntry::get_times() con
 {
        synfig::ActivepointList::const_iterator         j = timing_info.begin(),
                                                                                        end = timing_info.end();
-               
+
        //must remerge with all the other values because we don't know if we've changed...
        times = value_node->get_times();
-       
+
        for(; j != end; ++j)
        {
                TimePoint t;
@@ -765,7 +793,7 @@ const synfig::Node::time_set        & ValueNode_DynamicList::ListEntry::get_times() con
 
                times.insert(t);
        }
-       
+
        return times;
 }
 
@@ -773,7 +801,7 @@ void ValueNode_DynamicList::get_times_vfunc(Node::time_set &set) const
 {
        //add in the active points
        int size = list.size();
-       
+
        //rebuild all the info...
        for(int i = 0; i < size; ++i)
        {
@@ -800,14 +828,14 @@ ValueNode_DynamicList::ListEntry::findresult ValueNode_DynamicList::ListEntry::f
 {
        findresult f;
        f.second = false;
-       
+
        f.first = std::find(timing_info.begin(),timing_info.end(),x);
-       
+
        if(f.first != timing_info.end())
        {
                f.second = true;
        }
-       
+
        return f;
 }
 
@@ -815,14 +843,14 @@ ValueNode_DynamicList::ListEntry::const_findresult ValueNode_DynamicList::ListEn
 {
        const_findresult f;
        f.second = false;
-       
+
        f.first = std::find(timing_info.begin(),timing_info.end(),x);
-       
+
        if(f.first != timing_info.end())
        {
                f.second = true;
        }
-       
+
        return f;
 }
 
@@ -830,14 +858,14 @@ ValueNode_DynamicList::ListEntry::findresult ValueNode_DynamicList::ListEntry::f
 {
        findresult f;
        f.second = false;
-       
+
        f.first = std::find_if(timing_info.begin(),timing_info.end(),timecmp(x));
-       
+
        if(f.first != timing_info.end())
        {
                f.second = true;
        }
-       
+
        return f;
 }
 
@@ -845,14 +873,14 @@ ValueNode_DynamicList::ListEntry::const_findresult ValueNode_DynamicList::ListEn
 {
        const_findresult f;
        f.second = false;
-       
+
        f.first = std::find_if(timing_info.begin(),timing_info.end(),timecmp(x));
-       
+
        if(f.first != timing_info.end())
        {
                f.second = true;
        }
-       
+
        return f;
 }
 
@@ -868,7 +896,7 @@ ValueNode_DynamicList::insert_time(const Time& location, const Time& delta)
                try
                {
                        ListEntry& item(*iter);
-                       
+
                        ActivepointList::iterator iter(item.find_next(location));
                        for(;iter!=item.timing_info.end();++iter)
                        {