my log
[synfig.git] / synfig-studio / trunk / src / synfigapp / actions / activepointset.cpp
1 /* === S Y N F I G ========================================================= */
2 /*!     \file activepointset.cpp
3 **      \brief Template File
4 **
5 **      $Id: activepointset.cpp,v 1.1.1.1 2005/01/07 03:34:37 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 "activepointset.h"
32 #include <synfigapp/canvasinterface.h>
33
34 #endif
35
36 using namespace std;
37 using namespace etl;
38 using namespace synfig;
39 using namespace synfigapp;
40 using namespace Action;
41
42 /* === M A C R O S ========================================================= */
43
44 ACTION_INIT(Action::ActivepointSet);
45 ACTION_SET_NAME(Action::ActivepointSet,"activepoint_set");
46 ACTION_SET_LOCAL_NAME(Action::ActivepointSet,"Set Activepoint");
47 ACTION_SET_TASK(Action::ActivepointSet,"set");
48 ACTION_SET_CATEGORY(Action::ActivepointSet,Action::CATEGORY_ACTIVEPOINT);
49 ACTION_SET_PRIORITY(Action::ActivepointSet,0);
50 ACTION_SET_VERSION(Action::ActivepointSet,"0.0");
51 ACTION_SET_CVS_ID(Action::ActivepointSet,"$Id: activepointset.cpp,v 1.1.1.1 2005/01/07 03:34:37 darco Exp $");
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 Action::ActivepointSet::ActivepointSet()
60 {
61         set_dirty(true);
62 }
63
64 Action::ParamVocab
65 Action::ActivepointSet::get_param_vocab()
66 {
67         ParamVocab ret(Action::CanvasSpecific::get_param_vocab());
68         
69         ret.push_back(ParamDesc("value_desc",Param::TYPE_VALUEDESC)
70                 .set_local_name(_("ValueDesc"))
71         );
72
73         ret.push_back(ParamDesc("activepoint",Param::TYPE_ACTIVEPOINT)
74                 .set_local_name(_("Activepoint"))
75                 .set_desc(_("Activepoint to be changed"))
76                 .set_supports_multiple()
77         );
78
79         return ret;
80 }
81
82 bool
83 Action::ActivepointSet::is_canidate(const ParamList &x)
84 {
85         if(canidate_check(get_param_vocab(),x))
86         {
87                 ValueDesc value_desc(x.find("value_desc")->second.get_value_desc());
88                 if(!value_desc.parent_is_value_node() || !ValueNode_DynamicList::Handle::cast_dynamic(value_desc.get_parent_value_node()))
89                         return false;
90
91                 return true;
92         }
93         return false;
94 }
95
96 bool
97 Action::ActivepointSet::set_param(const synfig::String& name, const Action::Param &param)
98 {
99         if(name=="value_desc" && param.get_type()==Param::TYPE_VALUEDESC)
100         {
101                 ValueDesc value_desc(param.get_value_desc());
102                 
103                 if(!value_desc.parent_is_value_node())
104                         return false;
105                 
106                 value_node=ValueNode_DynamicList::Handle::cast_dynamic(value_desc.get_parent_value_node());
107                 
108                 if(!value_node)
109                         return false;
110                 
111                 index=value_desc.get_index();
112                 
113                 return true;
114         }
115         if(name=="activepoint" && param.get_type()==Param::TYPE_ACTIVEPOINT)
116         {
117                 //NOTE: there is no duplication checking at the moment
118                 activepoints.push_back(param.get_activepoint());
119                 
120                 return true;
121         }
122
123         return Action::CanvasSpecific::set_param(name,param);
124 }
125
126 bool
127 Action::ActivepointSet::is_ready()const
128 {
129         if(!value_node || activepoints.empty())
130                 return false;
131         return Action::CanvasSpecific::is_ready();
132 }
133
134 void
135 Action::ActivepointSet::perform()
136 {       
137         typedef ValueNode_DynamicList::ListEntry::ActivepointList AList;
138         AList::iterator iter;
139
140 #if 1   
141         vector<AList::iterator> iters;
142         vector<Activepoint>::iterator i = activepoints.begin(), end = activepoints.end();       
143         
144         for(; i != end; ++i)
145         {
146                 try { iters.push_back(value_node->list[index].find(*i)); }
147                 catch(synfig::Exception::NotFound)
148                 {
149                         throw Error(_("Unable to find activepoint"));
150                 }
151         }
152         
153         //check to see which valuenodes are going to override because of the time...
154         ValueNode_DynamicList::ListEntry::findresult timeiter;
155         
156         for(i = activepoints.begin(); i != end; ++i)
157         {
158                 timeiter = value_node->list[index].find_time(i->get_time());
159                 
160                 bool candelete = timeiter.second;
161         
162                 //we only want to track overwrites (not activepoints that are also being modified)
163                 if(candelete)
164                 {
165                         for(vector<AList::iterator>::iterator ii = iters.begin(); ii != iters.end(); ++ii)
166                         {
167                                 if(timeiter.first == *ii)
168                                 {
169                                         candelete = false;
170                                         break;
171                                 }
172                         }
173                 }
174                 
175                 //if we can still delete it after checking, record it, and then remove them all later
176                 if(candelete)
177                 {
178                         Activepoint a = *timeiter.first;
179                         overwritten_activepoints.push_back(a);
180                 }
181         }
182         
183         //overwrite all the valuenodes we're supposed to set
184         {
185                 i = activepoints.begin();
186                 for(vector<AList::iterator>::iterator ii = iters.begin(); ii != iters.end() && i != end; ++ii, ++i)
187                 {
188                         old_activepoints.push_back(**ii);
189                         **ii = *i; //set the point to the corresponding point in the normal waypoint list
190                 }
191         }
192         
193         //remove all the points we're supposed to be overwritting
194         {
195                 vector<Activepoint>::iterator   oi = overwritten_activepoints.begin(),
196                                                                                 oend = overwritten_activepoints.end();
197                 for(; oi != oend; ++oi)
198                 {
199                         value_node->list[index].erase(*oi);
200                 }
201         }
202
203 #else   
204         try { iter=value_node->list[index].find(activepoint); }
205         catch(synfig::Exception::NotFound)
206         {
207                 throw Error(_("Unable to find activepoint"));
208         }       
209
210         //find the value at the old time before we replace it
211         ValueNode_DynamicList::ListEntry::findresult timeiter;
212         timeiter = value_node->list[index].find_time(activepoint.get_time());
213         
214         //we only want to track overwrites (not inplace modifications)
215         if(timeiter.second && activepoint.get_uid() == timeiter.first->get_uid())
216         {
217                 timeiter.second = false;
218         }
219                 
220         old_activepoint=*iter;
221         *iter=activepoint;
222         
223         if(timeiter.second)
224         {
225                 synfig::info("Erasing the found activepoint");
226                 time_overwrite = true;
227                 overwritten_ap = *timeiter.first;
228                 
229                 value_node->list[index].erase(overwritten_ap);
230         }
231         
232 #endif
233         
234         value_node->list[index].timing_info.sort();
235         
236         // Signal that a valuenode has been changed
237         value_node->changed();
238 }
239
240 void
241 Action::ActivepointSet::undo()
242 {
243         ValueNode_DynamicList::ListEntry::ActivepointList::iterator iter;
244
245 #if 1   
246         vector<Activepoint>::iterator i = old_activepoints.begin(), end = old_activepoints.end();       
247         
248         for(; i != end; ++i)
249         {
250                 try { iter = value_node->list[index].find(*i); }
251                 catch(synfig::Exception::NotFound)
252                 {
253                         throw Error(_("Unable to find activepoint"));
254                 }
255                 
256                 //overwrite with old one
257                 *iter = *i;
258         }
259                 
260         //add back in all the points that we removed before...
261         {
262                 vector<Activepoint>::iterator   oi = overwritten_activepoints.begin(),
263                                                                                 oend = overwritten_activepoints.end();
264                 for(; oi != oend; ++oi)
265                 {
266                         value_node->list[index].add(*oi);
267                 }
268         }
269
270 #else   
271         try { iter=value_node->list[index].find(activepoint); }
272         catch(synfig::Exception::NotFound)
273         {
274                 throw Error(_("Unable to find activepoint"));
275         }       
276
277         *iter=old_activepoint;
278                 
279         if(time_overwrite)
280         {
281                 value_node->list[index].add(overwritten_ap);
282         }
283 #endif
284         
285         value_node->list[index].timing_info.sort();
286         
287         // Signal that a valuenode has been changed
288         value_node->changed();
289 }