Remove .gitignore do nothing is ignored.
[synfig.git] / synfig-core / trunk / src / synfig / canvas.cpp
index 5592aa0..2bbb743 100644 (file)
@@ -39,6 +39,7 @@
 #include "time.h"
 #include "context.h"
 #include "layer_pastecanvas.h"
+#include "loadcanvas.h"
 #include <sigc++/bind.h>
 
 #endif
@@ -47,10 +48,12 @@ using namespace synfig;
 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;
@@ -399,7 +402,8 @@ Canvas::find_value_node(const String &id)const
        //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
@@ -421,7 +425,8 @@ Canvas::surefind_value_node(const String &id)
        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
@@ -506,11 +511,11 @@ Canvas::remove_value_node(ValueNode::Handle x)
        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;
@@ -522,7 +527,7 @@ Canvas::surefind_canvas(const String &id)
                // 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('#'));
@@ -532,23 +537,22 @@ Canvas::surefind_canvas(const String &id)
 
                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 Exception::FileNotFound(file_name);
+                               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
@@ -571,7 +575,7 @@ Canvas::surefind_canvas(const String &id)
        // 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
@@ -579,24 +583,25 @@ Canvas::surefind_canvas(const String &id)
 
        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);
+       if(is_inline() && parent_)
+               return parent_->find_canvas(id, warnings);
 
        if(id.empty())
                return this;
@@ -608,7 +613,7 @@ Canvas::find_canvas(const String &id)const
                // 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('#'));
@@ -618,23 +623,22 @@ Canvas::find_canvas(const String &id)const
 
                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 Exception::FileNotFound(file_name);
+                               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
@@ -654,8 +658,8 @@ Canvas::find_canvas(const String &id)const
 
        // If the first character is the separator, then
        // this references the root canvas.
-       if(id.find_first_of(':')==0)
-               return get_root()->find_canvas(string(id,1));
+       if(id[0]==':')
+               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
@@ -663,9 +667,9 @@ Canvas::find_canvas(const String &id)const
 
        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
@@ -777,7 +781,9 @@ Canvas::clone(const GUID& deriv_guid)const
        {
                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));
@@ -913,7 +919,8 @@ Canvas::add_child_canvas(Canvas::Handle child_canvas, const synfig::String& id)
 
        try
        {
-               find_canvas(id);
+               String warnings;
+               find_canvas(id, warnings);
                throw Exception::IDAlreadyExists(id);
        }
        catch(Exception::IDNotFound)
@@ -952,8 +959,24 @@ Canvas::set_file_name(const String &file_name)
                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_();
+               }
        }
 }
 
@@ -961,7 +984,7 @@ sigc::signal<void>&
 Canvas::signal_file_name_changed()
 {
        if(parent())
-               return signal_file_name_changed();
+               return parent()->signal_file_name_changed();
        else
                return signal_file_name_changed_;
 }
@@ -1211,7 +1234,8 @@ synfig::optimize_layers(Time time, Context context, Canvas::Handle op_canvas, bo
                                !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()));
@@ -1359,3 +1383,26 @@ Canvas::rename_group(const String&old_name,const String&new_name)
                (*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