1 /* === S Y N F I G ========================================================= */
2 /*! \file layerduplicate.cpp
3 ** \brief Template File
4 **
5 ** $Id$
6 **
7 ** \legal
8 ** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 ** Copyright (c) 2008 Chris Moore
10 **
11 ** This package is free software; you can redistribute it and/or
12 ** modify it under the terms of the GNU General Public License as
13 ** published by the Free Software Foundation; either version 2 of
14 ** the License, or (at your option) any later version.
15 **
16 ** This package is distributed in the hope that it will be useful,
17 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 ** General Public License for more details.
20 ** \endlegal
21 */
22 /* ========================================================================= */
23
24 /* === H E A D E R S ======================================================= */
25
26 #ifdef USING_PCH
27 # include "pch.h"
28 #else
29 #ifdef HAVE_CONFIG_H
30 # include <config.h>
31 #endif
32
33 #include <synfig/general.h>
34
35 #include "layerduplicate.h"
36 #include "layeradd.h"
37 #include <synfig/context.h>
38 #include <synfigapp/canvasinterface.h>
39
40 #include <synfigapp/localization.h>
41
42 #endif
43
44 using namespace std;
45 using namespace etl;
46 using namespace synfig;
47 using namespace synfigapp;
48 using namespace Action;
49
50 /* === M A C R O S ========================================================= */
51
52 ACTION_INIT_NO_GET_LOCAL_NAME(Action::LayerDuplicate);
53 ACTION_SET_NAME(Action::LayerDuplicate,"LayerDuplicate");
54 ACTION_SET_LOCAL_NAME(Action::LayerDuplicate,N_("Duplicate Layer"));
55 ACTION_SET_TASK(Action::LayerDuplicate,"duplicate");
56 ACTION_SET_CATEGORY(Action::LayerDuplicate,Action::CATEGORY_LAYER);
57 ACTION_SET_PRIORITY(Action::LayerDuplicate,0);
58 ACTION_SET_VERSION(Action::LayerDuplicate,"0.0");
59 ACTION_SET_CVS_ID(Action::LayerDuplicate,"$Id$");
60
61 /* === G L O B A L S ======================================================= */
62
63 /* === P R O C E D U R E S ================================================= */
64
65 /* === M E T H O D S ======================================================= */
66
LayerDuplicate()67 Action::LayerDuplicate::LayerDuplicate()
68 {
69 }
70
71 synfig::String
get_local_name() const72 Action::LayerDuplicate::get_local_name()const
73 {
74 return get_layer_descriptions(layers, _("Duplicate Layer"), _("Duplicate Layers"));
75 }
76
77 Action::ParamVocab
get_param_vocab()78 Action::LayerDuplicate::get_param_vocab()
79 {
80 ParamVocab ret(Action::CanvasSpecific::get_param_vocab());
81
82 ret.push_back(ParamDesc("layer",Param::TYPE_LAYER)
83 .set_local_name(_("Layer"))
84 .set_desc(_("Layer to be duplicated"))
85 .set_supports_multiple()
86 );
87
88 return ret;
89 }
90
91 bool
is_candidate(const ParamList & x)92 Action::LayerDuplicate::is_candidate(const ParamList &x)
93 {
94 return candidate_check(get_param_vocab(),x);
95 }
96
97 bool
set_param(const synfig::String & name,const Action::Param & param)98 Action::LayerDuplicate::set_param(const synfig::String& name, const Action::Param ¶m)
99 {
100 if(name=="layer" && param.get_type()==Param::TYPE_LAYER)
101 {
102 layers.push_back(param.get_layer());
103
104 return true;
105 }
106
107 return Action::CanvasSpecific::set_param(name,param);
108 }
109
110 bool
is_ready() const111 Action::LayerDuplicate::is_ready()const
112 {
113 if(layers.empty())
114 return false;
115 return Action::CanvasSpecific::is_ready();
116 }
117
118 void
prepare()119 Action::LayerDuplicate::prepare()
120 {
121 if(!first_time())
122 return;
123
124 std::list<synfig::Layer::Handle>::const_iterator iter;
125
126 for(iter=layers.begin();iter!=layers.end();++iter)
127 {
128 Layer::Handle layer(*iter);
129
130 Canvas::Handle subcanvas(layer->get_canvas());
131
132 // Find the iterator for the layer
133 Canvas::iterator iter=find(subcanvas->begin(),subcanvas->end(),layer);
134
135 // If we couldn't find the layer in the canvas, then bail
136 if(*iter!=layer)
137 throw Error(_("This layer doesn't exist anymore."));
138
139 // If the subcanvas isn't the same as the canvas,
140 // then it had better be an inline canvas. If not,
141 // bail
142 if(get_canvas()!=subcanvas && !subcanvas->is_inline())
143 throw Error(_("This layer doesn't belong to this canvas anymore"));
144
145 // todo: which canvas should we use? subcanvas is the layer's canvas, get_canvas() is the canvas set in the action
146 Layer::Handle new_layer(layer->clone(subcanvas, guid));
147
148 {
149 Action::Handle action(Action::create("LayerMove"));
150
151 action->set_param("canvas",subcanvas);
152 action->set_param("canvas_interface",get_canvas_interface());
153 action->set_param("layer",new_layer);
154 action->set_param("new_index",layers.front()->get_depth());
155
156 add_action_front(action);
157 }
158 {
159 Action::Handle action(Action::create("LayerAdd"));
160
161 action->set_param("canvas",subcanvas);
162 action->set_param("canvas_interface",get_canvas_interface());
163 action->set_param("new",new_layer);
164
165 add_action_front(action);
166 }
167
168 // automatically export the Index parameter of Duplicate layers when duplicating
169 int index = 1;
170 export_dup_nodes(new_layer, subcanvas, index);
171 }
172 }
173
174 void
export_dup_nodes(synfig::Layer::Handle layer,Canvas::Handle canvas,int & index)175 Action::LayerDuplicate::export_dup_nodes(synfig::Layer::Handle layer, Canvas::Handle canvas, int &index)
176 {
177 // automatically export the Index parameter of Duplicate layers when duplicating
178 if (layer->get_name() == "duplicate")
179 while (true)
180 {
181 String name = strprintf(_("Index %d"), index++);
182 try
183 {
184 canvas->find_value_node(name, true);
185 }
186 catch (Exception::IDNotFound x)
187 {
188 Action::Handle action(Action::create("ValueNodeAdd"));
189
190 action->set_param("canvas",canvas);
191 action->set_param("canvas_interface",get_canvas_interface());
192 action->set_param("new",layer->dynamic_param_list().find("index")->second);
193 action->set_param("name",name);
194
195 add_action_front(action);
196
197 break;
198 }
199 }
200 else
201 {
202 Layer::ParamList param_list(layer->get_param_list());
203 for (Layer::ParamList::const_iterator iter(param_list.begin())
204 ; iter != param_list.end()
205 ; iter++)
206 if (layer->dynamic_param_list().count(iter->first)==0 && iter->second.get_type()==type_canvas)
207 {
208 Canvas::Handle subcanvas(iter->second.get(Canvas::Handle()));
209 if (subcanvas && subcanvas->is_inline())
210 for (IndependentContext iter = subcanvas->get_independent_context(); iter != subcanvas->end(); iter++)
211 export_dup_nodes(*iter, canvas, index);
212 }
213
214 for (Layer::DynamicParamList::const_iterator iter(layer->dynamic_param_list().begin())
215 ; iter != layer->dynamic_param_list().end()
216 ; iter++)
217 if (iter->second->get_type()==type_canvas)
218 {
219 Canvas::Handle canvas((*iter->second)(0).get(Canvas::Handle()));
220 if (canvas->is_inline())
221 //! \todo do we need to implement this? and if so, shouldn't we check all canvases, not just the one at t=0s?
222 warning("%s:%d not yet implemented - do we need to export duplicate valuenodes in dynamic canvas parameters?", __FILE__, __LINE__);
223 }
224 }
225 }
226