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 &param)
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