#include "time.h"
#include "context.h"
#include "layer_pastecanvas.h"
+#include "loadcanvas.h"
#include <sigc++/bind.h>
#endif
using namespace etl;
using namespace std;
-namespace synfig { extern Canvas::Handle open_canvas(const String &filename, String &errors); };
+namespace synfig { extern Canvas::Handle open_canvas(const String &filename, String &errors, String &warnings); };
/* === M A C R O S ========================================================= */
+#define ALLOW_CLONE_NON_INLINE_CANVASES
+
struct _CanvasCounter
{
static int counter;
//synfig::warning("constfind:value_node_id: "+value_node_id);
//synfig::warning("constfind:canvas_id: "+canvas_id);
- return find_canvas(canvas_id)->value_node_list_.find(value_node_id);
+ String warnings;
+ return find_canvas(canvas_id, warnings)->value_node_list_.find(value_node_id);
}
ValueNode::Handle
if(canvas_id.empty())
canvas_id=':';
- return surefind_canvas(canvas_id)->value_node_list_.surefind(value_node_id);
+ String warnings;
+ return surefind_canvas(canvas_id,warnings)->value_node_list_.surefind(value_node_id);
}
void
x->set_id("");
}
-etl::handle<Canvas>
-Canvas::surefind_canvas(const String &id)
+Canvas::Handle
+Canvas::surefind_canvas(const String &id, String &warnings)
{
if(is_inline() && parent_)
- return parent_->surefind_canvas(id);
+ return parent_->surefind_canvas(id,warnings);
if(id.empty())
return this;
// If '#' is the first character, remove it
// and attempt to parse the ID again.
if(id[0]=='#')
- return surefind_canvas(String(id,1));
+ return surefind_canvas(String(id,1),warnings);
//! \todo This needs a lot more optimization
String file_name(id,0,id.find_first_of('#'));
Canvas::Handle external_canvas;
+ if(!is_absolute_path(file_name))
+ file_name = get_file_path()+ETL_DIRECTORY_SEPARATOR+file_name;
+
// If the composition is already open, then use it.
if(externals_.count(file_name))
external_canvas=externals_[file_name];
else
{
String errors;
- if(is_absolute_path(file_name))
- external_canvas=open_canvas(file_name, errors);
- else
- external_canvas=open_canvas(get_file_path()+ETL_DIRECTORY_SEPARATOR+file_name, errors);
-
+ external_canvas=open_canvas(file_name, errors, warnings);
if(!external_canvas)
throw runtime_error(errors);
externals_[file_name]=external_canvas;
}
- return Handle::cast_const(external_canvas.constant()->find_canvas(external_id));
+ return Handle::cast_const(external_canvas.constant()->find_canvas(external_id, warnings));
}
// If we do not have any resolution, then we assume that the
// If the first character is the separator, then
// this references the root canvas.
if(id[0]==':')
- return get_root()->surefind_canvas(string(id,1));
+ return get_root()->surefind_canvas(string(id,1),warnings);
// Now we know that the requested Canvas is in a child
// of this canvas. We have to find that canvas and
String canvas_name=string(id,0,id.find_first_of(':'));
- Canvas::Handle child_canvas=surefind_canvas(canvas_name);
+ Canvas::Handle child_canvas=surefind_canvas(canvas_name,warnings);
- return child_canvas->surefind_canvas(string(id,id.find_first_of(':')+1));
+ return child_canvas->surefind_canvas(string(id,id.find_first_of(':')+1),warnings);
}
Canvas::Handle
-Canvas::find_canvas(const String &id)
+Canvas::find_canvas(const String &id, String &warnings)
{
return
Canvas::Handle::cast_const(
- const_cast<const Canvas*>(this)->find_canvas(id)
+ const_cast<const Canvas*>(this)->find_canvas(id, warnings)
);
}
Canvas::ConstHandle
-Canvas::find_canvas(const String &id)const
+Canvas::find_canvas(const String &id, String &warnings)const
{
if(is_inline() && parent_)
- return parent_->find_canvas(id);
+ return parent_->find_canvas(id, warnings);
if(id.empty())
return this;
// If '#' is the first character, remove it
// and attempt to parse the ID again.
if(id[0]=='#')
- return find_canvas(String(id,1));
+ return find_canvas(String(id,1), warnings);
//! \todo This needs a lot more optimization
String file_name(id,0,id.find_first_of('#'));
Canvas::Handle external_canvas;
+ if(!is_absolute_path(file_name))
+ file_name = get_file_path()+ETL_DIRECTORY_SEPARATOR+file_name;
+
// If the composition is already open, then use it.
if(externals_.count(file_name))
external_canvas=externals_[file_name];
else
{
- String errors;
- if(is_absolute_path(file_name))
- external_canvas=open_canvas(file_name, errors);
- else
- external_canvas=open_canvas(get_file_path()+ETL_DIRECTORY_SEPARATOR+file_name, errors);
-
+ String errors, warnings;
+ external_canvas=open_canvas(file_name, errors, warnings);
if(!external_canvas)
throw runtime_error(errors);
externals_[file_name]=external_canvas;
}
- return Handle::cast_const(external_canvas.constant()->find_canvas(external_id));
+ return Handle::cast_const(external_canvas.constant()->find_canvas(external_id, warnings));
}
// If we do not have any resolution, then we assume that the
// If the first character is the separator, then
// this references the root canvas.
if(id[0]==':')
- return get_root()->find_canvas(string(id,1));
+ return get_root()->find_canvas(string(id,1), warnings);
// Now we know that the requested Canvas is in a child
// of this canvas. We have to find that canvas and
String canvas_name=string(id,0,id.find_first_of(':'));
- Canvas::ConstHandle child_canvas=find_canvas(canvas_name);
+ Canvas::ConstHandle child_canvas=find_canvas(canvas_name, warnings);
- return child_canvas->find_canvas(string(id,id.find_first_of(':')+1));
+ return child_canvas->find_canvas(string(id,id.find_first_of(':')+1), warnings);
}
Canvas::Handle
{
name=get_id()+"_CLONE";
+#ifndef ALLOW_CLONE_NON_INLINE_CANVASES
throw runtime_error("Cloning of non-inline canvases is not yet supported");
+#endif // ALLOW_CLONE_NON_INLINE_CANVASES
}
Handle canvas(new Canvas(name));
try
{
- find_canvas(id);
+ String warnings;
+ find_canvas(id, warnings);
throw Exception::IDAlreadyExists(id);
}
catch(Exception::IDNotFound)
parent()->set_file_name(file_name);
else
{
+ String old_name(file_name_);
file_name_=file_name;
- signal_file_name_changed_();
+
+ // when a canvas is made, its name is ""
+ // then, before it's saved or even edited, it gets a name like "Synfig Animation 23", in the local language
+ // we don't want to register the canvas' filename in the canvas map until it gets a real filename
+ if (old_name != "")
+ {
+ file_name_=file_name;
+ std::map<synfig::String, etl::loose_handle<Canvas> >::iterator iter;
+ for(iter=get_open_canvas_map().begin();iter!=get_open_canvas_map().end();++iter)
+ if(iter->second==this)
+ break;
+ if (iter == get_open_canvas_map().end())
+ CanvasParser::register_canvas_in_map(this, file_name);
+ else
+ signal_file_name_changed_();
+ }
}
}
Canvas::signal_file_name_changed()
{
if(parent())
- return signal_file_name_changed();
+ return parent()->signal_file_name_changed();
else
return signal_file_name_changed_;
}
!composite->reads_context())
{
Canvas::Handle sub_canvas(Canvas::create_inline(op_canvas));
- sub_canvas->push_back(composite = composite->clone());
+ // don't use clone() because it re-randomizes the seeds of any random valuenodes
+ sub_canvas->push_back(composite = composite->simple_clone());
layer = Layer::create("PasteCanvas");
composite->set_description(strprintf("Wrapped clone of '%s'", composite->get_non_empty_description().c_str()));
layer->set_description(strprintf("PasteCanvas wrapper for '%s'", composite->get_non_empty_description().c_str()));
(*iter)->add_to_group(new_name);
}
}
+
+void
+Canvas::register_external_canvas(String file_name, Handle canvas)
+{
+ if(!is_absolute_path(file_name)) file_name = get_file_path()+ETL_DIRECTORY_SEPARATOR+file_name;
+ externals_[file_name] = canvas;
+}
+
+#ifdef _DEBUG
+void
+Canvas::show_externals(String file, int line, String text) const
+{
+ printf(" .----- (externals for %lx '%s')\n | %s:%d %s\n", ulong(this), get_name().c_str(), file.c_str(), line, text.c_str());
+ std::map<String, Handle>::iterator iter;
+ for (iter = externals_.begin(); iter != externals_.end(); iter++)
+ {
+ synfig::String first(iter->first);
+ etl::loose_handle<Canvas> second(iter->second);
+ printf(" | %40s : %lx (%d)\n", first.c_str(), ulong(&*second), second->count());
+ }
+ printf(" `-----\n\n");
+}
+#endif // _DEBUG