Remove .gitignore do nothing is ignored.
[synfig.git] / synfig-studio / trunk / src / gtkmm / instance.cpp
index a82c89b..9a247cb 100644 (file)
@@ -6,6 +6,8 @@
 **
 **     \legal
 **     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+**     Copyright (c) 2007, 2008 Chris Moore
+**  Copyright (c) 2008 Carlos López
 **
 **     This package is free software; you can redistribute it and/or
 **     modify it under the terms of the GNU General Public License as
 #include <sigc++/adaptors/hide.h>
 #include "toolbox.h"
 #include "onemoment.h"
+#include <synfig/savecanvas.h>
 
 #include "autorecover.h"
 #include <sigc++/retype_return.h>
 #include <sigc++/retype.h>
 //#include <sigc++/hide.h>
 #include <synfig/valuenode_composite.h>
+#include <synfig/valuenode_duplicate.h>
 #include "widget_waypointmodel.h"
 #include <gtkmm/actiongroup.h>
-#include "iconcontroler.h"
+#include "iconcontroller.h"
+#include "workarea.h"
 #include <sys/stat.h>
 #include <errno.h>
+#include <ETL/stringf>
+
+#include "general.h"
 
 #endif
 
@@ -59,7 +67,7 @@ using namespace std;
 using namespace etl;
 using namespace synfig;
 using namespace studio;
-using namespace SigC;
+using namespace sigc;
 
 /* === M A C R O S ========================================================= */
 
@@ -71,7 +79,7 @@ int studio::Instance::instance_count_=0;
 
 /* === M E T H O D S ======================================================= */
 
-Instance::Instance(Canvas::Handle canvas):
+Instance::Instance(synfig::Canvas::Handle canvas):
        synfigapp::Instance             (canvas),
 //     canvas_tree_store_              (Gtk::TreeStore::create(CanvasTreeModel())),
 //     canvas_tree_store_              (Gtk::TreeStore::create()),
@@ -119,7 +127,7 @@ Instance::get_visible_canvases()const
 }
 
 handle<Instance>
-Instance::create(Canvas::Handle canvas)
+Instance::create(synfig::Canvas::Handle canvas)
 {
        // Construct a new instance
        handle<Instance> instance(new Instance(canvas));
@@ -143,7 +151,7 @@ Instance::create(Canvas::Handle canvas)
 }
 
 handle<CanvasView>
-Instance::find_canvas_view(Canvas::Handle canvas)
+Instance::find_canvas_view(etl::handle<synfig::Canvas> canvas)
 {
        if(!canvas)
                return 0;
@@ -161,7 +169,7 @@ Instance::find_canvas_view(Canvas::Handle canvas)
 }
 
 void
-Instance::focus(Canvas::Handle canvas)
+Instance::focus(etl::handle<synfig::Canvas> canvas)
 {
        handle<CanvasView> canvas_view=find_canvas_view(canvas);
        assert(canvas_view);
@@ -189,31 +197,57 @@ studio::Instance::save_as(const synfig::String &file_name)
 {
        if(synfigapp::Instance::save_as(file_name))
        {
-               App::add_recent_file(file_name);
+               // after changing the filename, update the render settings with the new filename
+               list<handle<CanvasView> >::iterator iter;
+               for(iter=canvas_view_list().begin();iter!=canvas_view_list().end();iter++)
+                       (*iter)->render_settings.set_entry_filename();
+               App::add_recent_file(etl::handle<Instance>(this));
                return true;
        }
        return false;
 }
 
-bool
+void
+studio::Instance::open()
+{
+       App::dialog_open(get_file_name());
+}
+
+Instance::Status
 studio::Instance::save()
 {
-       // the filename will be set to "Synfig Animation 1" or some such when first created
-       // and will be changed to an absolute path once it has been saved
-       // so if it still begins with "Synfig Animation " then we need to ask where to save it
-       if(get_file_name().find(DEFAULT_FILENAME_PREFIX)==0)
+       // if we don't have a real filename yet then we need to ask where to save it
+       if (!has_real_filename())
        {
-               dialog_save_as();
-               return true;
+               if (dialog_save_as())
+                       return STATUS_OK;
+               else
+                       return STATUS_CANCEL;
        }
 
-       return synfigapp::Instance::save();
+       if (synfigapp::Instance::save())
+       {
+               App::add_recent_file(etl::handle<Instance>(this));
+               return STATUS_OK;
+       }
+       string msg(strprintf(_("Unable to save to '%s'"), get_file_name().c_str()));
+       App::dialog_error_blocking(_("Save - Error"), msg.c_str());
+       return STATUS_ERROR;
 }
 
-void
+// the filename will be set to "Synfig Animation 1" or some such when first created
+// and will be changed to an absolute path once it has been saved
+// so if it still begins with "Synfig Animation " then we don't have a real filename yet
+bool
+studio::Instance::has_real_filename()
+{
+       return get_file_name().find(App::custom_filename_prefix.c_str()) != 0;
+}
+
+bool
 studio::Instance::dialog_save_as()
 {
-       string filename=basename(get_file_name());
+       string filename = get_file_name();
        Canvas::Handle canvas(get_canvas());
 
        {
@@ -227,14 +261,13 @@ studio::Instance::dialog_save_as()
                                Layer::Handle parent_layer(dynamic_cast<Layer*>(node));
                                if(parent_layer && parent_layer->get_canvas()->get_root()!=get_canvas())
                                {
-                                       App::dialog_error_blocking("SaveAs - Error",
-                                               "There is currently a bug when using \"SaveAs\"\n"
+                                       string msg(strprintf(_("There is currently a bug when using \"SaveAs\"\n"
                                                "on a composition that is being referenced by other\n"
                                                "files that are currently open. Close these\n"
-                                               "other files first before trying to use \"SaveAs\"."
-                                       );
+                                               "other files first before trying to use \"SaveAs\".")));
+                                       App::dialog_error_blocking(_("SaveAs - Error"), msg.c_str());
 
-                                       return;
+                                       return false;
                                }
                                if(parent_layer)
                                        break;
@@ -242,31 +275,31 @@ studio::Instance::dialog_save_as()
                }
        }
 
+       if (has_real_filename())
+               filename = absolute_path(filename);
+
        // show the canvas' name if it has one, else its ID
-       while(App::dialog_save_file(_("Choose a Filename to Save As") +
-                                                               String(" (") +
-                                                               (canvas->get_name().empty()
-                                                                ? canvas->get_id()
-                                                                : canvas->get_name()) +
-                                                               ") ...", filename))
+       while (App::dialog_save_file((_("Choose a Filename to Save As") +
+                                                                 String(" (") +
+                                                                 (canvas->get_name().empty() ? canvas->get_id() : canvas->get_name()) +
+                                                                 ") ..."),
+                                                                filename, ANIMATION_DIR_PREFERENCE))
        {
                // If the filename still has wildcards, then we should
                // continue looking for the file we want
-               if(find(filename.begin(),filename.end(),'*')!=filename.end())
+               string base_filename = basename(filename);
+               if (find(base_filename.begin(),base_filename.end(),'*')!=base_filename.end())
                        continue;
 
-               std::string base = basename(filename);
-               if(find(base.begin(),base.end(),'.')==base.end())
+               if (filename_extension(filename) == "")
                        filename+=".sifz";
 
                try
                {
-                       String ext(String(filename.begin()+filename.find_last_of('.')+1,filename.end()));
-                       if(ext!="sif" && ext!="sifz" && !App::dialog_yes_no(_("Unknown extension"),
-                               _("You have given the file name an extension\nwhich I do not recognise. Are you sure this is what you want?")))
-                       {
+                       String ext(filename_extension(filename));
+                       if(ext!=".sif" && ext!=".sifz" && !App::dialog_yes_no(_("Unknown extension"),
+                               _("You have given the file name an extension\nwhich I do not recognize. Are you sure this is what you want?")))
                                continue;
-                       }
                }
                catch(...)
                {
@@ -275,22 +308,36 @@ studio::Instance::dialog_save_as()
 
                {
                        struct stat     s;
-                       // if stat() succeeds, or it fails with something other than 'file doesn't exist', the file exists
+                       int stat_return = stat(filename.c_str(), &s);
+
+                       // if stat() fails with something other than 'file doesn't exist', there's been a real
+                       // error of some kind.  let's give up now and ask for a new path.
+                       if (stat_return == -1 && errno != ENOENT)
+                       {
+                               perror(filename.c_str());
+                               string msg(strprintf(_("Unable to check whether '%s' exists."), filename.c_str()));
+                               App::dialog_error_blocking(_("SaveAs - Error"),msg.c_str());
+                               continue;
+                       }
+
                        // if the file exists and the user doesn't want to overwrite it, keep prompting for a filename
-                       if ((stat(filename.c_str(), &s) != -1 || errno != ENOENT) &&
-                               !App::dialog_yes_no("File exists",
-                                                                       "A file named '" +
-                                                                       filename +
-                                                                       "' already exists.\n\n"
-                                                                       "Do you want to replace it with the file you are saving?"))
+                       string msg(strprintf(_("A file named '%s' already exists.\n\n"
+                                                                       "Do you want to replace it with the file you are saving?"), filename.c_str()));
+                       if ((stat_return == 0) &&
+                               !App::dialog_yes_no(_("File exists"),msg.c_str()))
                                continue;
                }
 
                if(save_as(filename))
-                       break;
-
-               App::dialog_error_blocking("SaveAs - Error","Unable to save file");
+               {
+                       synfig::set_file_version(ReleaseVersion(RELEASE_VERSION_END-1));
+                       return true;
+               }
+               string msg(strprintf(_("Unable to save to '%s'"), filename.c_str()));
+               App::dialog_error_blocking(_("SaveAs - Error"),msg.c_str());
        }
+
+       return false;
 }
 
 void
@@ -345,15 +392,11 @@ Instance::close()
                studio::App::set_selected_instance(0);
        }
        else
-       {
-               studio::App::set_selected_canvas_view(studio::App::instance_list.front()->canvas_view_list().front());
-               //studio::App::set_selected_instance(studio::App::instance_list.front());
-       }
+               studio::App::instance_list.front()->canvas_view_list().front()->present();
 }
 
-
 void
-Instance::insert_canvas(Gtk::TreeRow row,Canvas::Handle canvas)
+Instance::insert_canvas(Gtk::TreeRow row, synfig::Canvas::Handle canvas)
 {
        CanvasTreeModel canvas_tree_model;
        assert(canvas);
@@ -403,7 +446,6 @@ Instance::insert_canvas(Gtk::TreeRow row,Canvas::Handle canvas)
        */
 }
 
-
 /*
 void
 Instance::insert_value_node(Gtk::TreeRow row,Canvas::Handle canvas,etl::handle<synfig::ValueNode> value_node)
@@ -465,7 +507,7 @@ Instance::dialog_cvs_commit()
        }
        catch(...)
        {
-               App::dialog_error_blocking(_("Error"),_("An error has occured when trying to COMMIT"));
+               App::dialog_error_blocking(_("Error"),_("An error has occurred when trying to COMMIT"));
        }
        update_all_titles();
 }
@@ -490,7 +532,7 @@ Instance::dialog_cvs_add()
        }
        catch(...)
        {
-               App::dialog_error_blocking(_("Error"),_("An error has occured when trying to ADD"));
+               App::dialog_error_blocking(_("Error"),_("An error has occurred when trying to ADD"));
        }
        update_all_titles();
 }
@@ -531,7 +573,7 @@ Instance::dialog_cvs_update()
        }
        catch(...)
        {
-               App::dialog_error_blocking(_("Error"),_("An error has occured when trying to UPDATE"));
+               App::dialog_error_blocking(_("Error"),_("An error has occurred when trying to UPDATE"));
        }
        //update_all_titles();
 }
@@ -567,7 +609,7 @@ Instance::dialog_cvs_revert()
        }
        catch(...)
        {
-               App::dialog_error_blocking(_("Error"),_("An error has occured when trying to UPDATE"));
+               App::dialog_error_blocking(_("Error"),_("An error has occurred when trying to UPDATE"));
        }
        //update_all_titles();
 }
@@ -623,18 +665,33 @@ Instance::safe_revert()
 bool
 Instance::safe_close()
 {
-       handle<synfigapp::UIInterface> uim;
-       uim=find_canvas_view(get_canvas())->get_ui_interface();
+       handle<CanvasView> canvas_view = find_canvas_view(get_canvas());
+       handle<synfigapp::UIInterface> uim=canvas_view->get_ui_interface();
 
-       if(get_action_count())
+       // if the animation is currently playing, closing the window will cause a crash,
+       // so don't allow it
+       if (canvas_view->is_playing())
        {
-               string str=strprintf(_("Would you like to save your changes to %s?"),basename(get_file_name()).c_str() );
-               int answer=uim->yes_no_cancel(get_canvas()->get_name(),str,synfigapp::UIInterface::RESPONSE_YES);
-               if(answer==synfigapp::UIInterface::RESPONSE_YES)
-                       save();
-               if(answer==synfigapp::UIInterface::RESPONSE_CANCEL)
-                       return false;
+               canvas_view->present();
+               App::dialog_error_blocking("Close Error", "The animation is currently playing so the window cannot be closed.");
+               return false;
        }
+       if(get_action_count())
+               do
+               {
+                       string str=strprintf(_("Would you like to save your changes to %s?"),basename(get_file_name()).c_str() );
+                       int answer=uim->yes_no_cancel(get_canvas()->get_name(),str,synfigapp::UIInterface::RESPONSE_YES);
+                       if(answer==synfigapp::UIInterface::RESPONSE_YES)
+                       {
+                               enum Status status = save();
+                               if (status == STATUS_OK) break;
+                               else if (status == STATUS_CANCEL) return false;
+                       }
+                       if(answer==synfigapp::UIInterface::RESPONSE_NO)
+                               break;
+                       if(answer==synfigapp::UIInterface::RESPONSE_CANCEL)
+                               return false;
+               } while (true);
 
        if(is_modified())
        {
@@ -652,7 +709,6 @@ Instance::safe_close()
        return true;
 }
 
-
 void
 Instance::add_actions_to_group(const Glib::RefPtr<Gtk::ActionGroup>& action_group, synfig::String& ui_info,   const synfigapp::Action::ParamList &param_list, synfigapp::Action::Category category)const
 {
@@ -663,8 +719,8 @@ Instance::add_actions_to_group(const Glib::RefPtr<Gtk::ActionGroup>& action_grou
 
        candidate_list.sort();
 
-       if(candidate_list.empty())
-               synfig::warning("Action CandidateList is empty!");
+       // if(candidate_list.empty())
+       //      synfig::warning("%s:%d Action CandidateList is empty!", __FILE__, __LINE__);
 
        for(iter=candidate_list.begin();iter!=candidate_list.end();++iter)
        {
@@ -704,7 +760,7 @@ Instance::add_actions_to_menu(Gtk::Menu *menu, const synfigapp::Action::ParamLis
        candidate_list.sort();
 
        if(candidate_list.empty())
-               synfig::warning("Action CandidateList is empty!");
+               synfig::warning("%s:%d Action CandidateList is empty!", __FILE__, __LINE__);
 
        for(iter=candidate_list.begin();iter!=candidate_list.end();++iter)
        {
@@ -773,11 +829,11 @@ Instance::add_actions_to_menu(Gtk::Menu *menu, const synfigapp::Action::ParamLis
        candidate_list.sort();
 
        if(candidate_list.empty())
-               synfig::warning("Action CandidateList is empty!");
+               synfig::warning("%s:%d Action CandidateList is empty!", __FILE__, __LINE__);
        if(candidate_list2.empty())
-               synfig::warning("Action CandidateList2 is empty!");
+               synfig::warning("%s:%d Action CandidateList2 is empty!", __FILE__, __LINE__);
 
-       // Seperate out the candidate lists so that there are no conflicts
+       // Separate out the candidate lists so that there are no conflicts
        for(iter=candidate_list.begin();iter!=candidate_list.end();++iter)
        {
                synfigapp::Action::CandidateList::iterator iter2(candidate_list2.find(iter->name));
@@ -888,8 +944,11 @@ Instance::add_actions_to_menu(Gtk::Menu *menu, const synfigapp::Action::ParamLis
 }
 
 void
-Instance::process_action(String name, synfigapp::Action::ParamList param_list)
+Instance::process_action(synfig::String name, synfigapp::Action::ParamList param_list)
 {
+       //// debug actions
+       // synfig::info("%s:%d process_action: '%s'", __FILE__, __LINE__, name.c_str());
+
        assert(synfigapp::Action::book().count(name));
 
        synfigapp::Action::BookEntry entry(synfigapp::Action::book().find(name)->second);
@@ -923,7 +982,7 @@ Instance::process_action(String name, synfigapp::Action::ParamList param_list)
                        case synfigapp::Action::Param::TYPE_STRING:
                        {
                                String str;
-                               if(!studio::App::dialog_entry(entry.local_name, iter->get_local_name()+":"+iter->get_desc(),str))
+                               if(!studio::App::dialog_entry(entry.local_name, iter->get_local_name()+": "+iter->get_desc(),str))
                                        return;
                                action->set_param(iter->get_name(),str);
                                break;
@@ -946,7 +1005,7 @@ Instance::process_action(String name, synfigapp::Action::ParamList param_list)
 }
 
 void
-Instance::make_param_menu(Gtk::Menu *menu,synfig::Canvas::Handle canvas, synfigapp::ValueDesc value_desc, float location)
+Instance::make_param_menu(Gtk::Menu *menu,synfig::Canvas::Handle canvas, synfigapp::ValueDesc value_desc, float location, bool bezier)
 {
        Gtk::Menu& parammenu(*menu);
 
@@ -959,6 +1018,7 @@ Instance::make_param_menu(Gtk::Menu *menu,synfig::Canvas::Handle canvas, synfiga
        param_list=canvas_interface->generate_param_list(value_desc);
        param_list.add("origin",location);
 
+#ifdef BLINEPOINT_MENU_IS_VERTEX_MENU
        if(value_desc.get_value_type()==ValueBase::TYPE_BLINEPOINT && value_desc.is_value_node() && ValueNode_Composite::Handle::cast_dynamic(value_desc.get_value_node()))
        {
                param_list2=canvas_interface->generate_param_list(
@@ -969,11 +1029,23 @@ Instance::make_param_menu(Gtk::Menu *menu,synfig::Canvas::Handle canvas, synfiga
                );
                param_list2.add("origin",location);
        }
-
+#endif // BLINEPOINT_MENU_IS_VERTEX_MENU
 
        // Populate the convert menu by looping through
        // the ValueNode book and find the ones that are
        // relevant.
+
+       // show the 'Convert' sub-menu if this valuedesc is anything other than either:
+       //   the 'Index' parameter of a Duplicate layer
+       // or
+       //   a Duplicate ValueNode whose parent is not a (layer or ValueNode)
+       if (!((value_desc.parent_is_layer_param() &&
+                  value_desc.get_layer()->get_name() == "duplicate" &&
+                  value_desc.get_param_name() == "index") ||
+                 (value_desc.is_value_node() &&
+                  ValueNode_Duplicate::Handle::cast_dynamic(value_desc.get_value_node()) &&
+                  !(value_desc.parent_is_layer_param() ||
+                        value_desc.parent_is_value_node()))))
        {
                Gtk::Menu *convert_menu=manage(new Gtk::Menu());
                LinkableValueNode::Book::const_iterator iter;
@@ -998,10 +1070,24 @@ Instance::make_param_menu(Gtk::Menu *menu,synfig::Canvas::Handle canvas, synfiga
                parammenu.items().push_back(Gtk::Menu_Helpers::StockMenuElem(Gtk::Stock::CONVERT,*convert_menu));
        }
 
+       synfigapp::Action::Category categories = synfigapp::Action::CATEGORY_VALUEDESC|synfigapp::Action::CATEGORY_VALUENODE;
+       if (bezier)
+       {
+               categories = categories|synfigapp::Action::CATEGORY_BEZIER;
+
+               const DuckList selected_ducks(find_canvas_view(canvas)->get_work_area()->get_selected_ducks());
+               for(DuckList::const_iterator iter=selected_ducks.begin();iter!=selected_ducks.end();++iter)
+               {
+                       synfigapp::ValueDesc value_desc((*iter)->get_value_desc());
+                       if(value_desc.is_valid())
+                               param_list.add("selected_value_desc",value_desc);
+               }
+       }
+
        if(param_list2.empty())
-               add_actions_to_menu(&parammenu, param_list,synfigapp::Action::CATEGORY_VALUEDESC|synfigapp::Action::CATEGORY_VALUENODE);
+               add_actions_to_menu(&parammenu, param_list,categories);
        else
-               add_actions_to_menu(&parammenu, param_list2,param_list,synfigapp::Action::CATEGORY_VALUEDESC|synfigapp::Action::CATEGORY_VALUENODE);
+               add_actions_to_menu(&parammenu, param_list2,param_list,categories);
 
        if(value_desc.get_value_type()==ValueBase::TYPE_BLINEPOINT && value_desc.is_value_node() && ValueNode_Composite::Handle::cast_dynamic(value_desc.get_value_node()))
        {
@@ -1014,15 +1100,20 @@ Instance::make_param_menu(Gtk::Menu *menu,synfig::Canvas::Handle canvas, synfiga
 
                try
                {
+                       // try to find a waypoint at the current time - if we
+                       // can't, we don't want the menu entry - an exception is thrown
                        WaypointList::iterator iter(value_node->find(canvas->get_time()));
+                       std::set<synfig::Waypoint, std::less<UniqueID> > waypoint_set;
+                       waypoint_set.insert(*iter);
+
                        parammenu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("Edit Waypoint"),
                                sigc::bind(
                                        sigc::bind(
                                                sigc::bind(
-                                                       sigc::mem_fun(*find_canvas_view(canvas),&studio::CanvasView::on_waypoint_clicked),
+                                                       sigc::mem_fun(*find_canvas_view(canvas),&studio::CanvasView::on_waypoint_clicked_canvasview),
                                                        -1
                                                ),
-                                               *iter
+                                               waypoint_set
                                        ),
                                        value_desc
                                )
@@ -1050,15 +1141,12 @@ edit_several_waypoints(etl::handle<CanvasView> canvas_view, std::list<synfigapp:
 
        dialog.get_vbox()->pack_start(widget_waypoint_model);
 
-
        dialog.add_button(Gtk::StockID("gtk-apply"),1);
        dialog.add_button(Gtk::StockID("gtk-cancel"),0);
        dialog.show();
 
-       DEBUGPOINT();
        if(dialog.run()==0 || widget_waypoint_model.get_waypoint_model().is_trivial())
                return;
-       DEBUGPOINT();
        synfigapp::Action::PassiveGrouper group(canvas_interface->get_instance().get(),_("Set Waypoints"));
 
        std::list<synfigapp::ValueDesc>::iterator iter;
@@ -1088,13 +1176,13 @@ edit_several_waypoints(etl::handle<CanvasView> canvas_view, std::list<synfigapp:
 
                        if(!value_desc.is_value_node())
                        {
-                               action=synfigapp::Action::create("value_desc_connect");
+                               action=synfigapp::Action::create("ValueDescConnect");
                                action->set_param("dest",value_desc);
                                action->set_param("src",ValueNode::Handle(value_node));
                        }
                        else
                        {
-                               action=synfigapp::Action::create("value_node_replace");
+                               action=synfigapp::Action::create("ValueNodeReplace");
                                action->set_param("dest",value_desc.get_value_node());
                                action->set_param("src",ValueNode::Handle(value_node));
                        }
@@ -1102,7 +1190,6 @@ edit_several_waypoints(etl::handle<CanvasView> canvas_view, std::list<synfigapp:
                        action->set_param("canvas",canvas_view->get_canvas());
                        action->set_param("canvas_interface",canvas_interface);
 
-
                        if(!canvas_interface->get_instance()->perform_action(action))
                        {
                                canvas_view->get_ui_interface()->error(_("Unable to convert to animated waypoint"));
@@ -1116,20 +1203,17 @@ edit_several_waypoints(etl::handle<CanvasView> canvas_view, std::list<synfigapp:
                                value_node=ValueNode_Animated::Handle::cast_dynamic(value_desc.get_value_node());
                }
 
-
                if(value_node)
                {
-
-                       synfigapp::Action::Handle action(synfigapp::Action::create("waypoint_set_smart"));
+                       synfigapp::Action::Handle action(synfigapp::Action::create("WaypointSetSmart"));
 
                        if(!action)
                        {
-                               canvas_view->get_ui_interface()->error(_("Unable to find waypoint_set_smart action"));
+                               canvas_view->get_ui_interface()->error(_("Unable to find WaypointSetSmart action"));
                                group.cancel();
                                return;
                        }
 
-
                        action->set_param("canvas",canvas_view->get_canvas());
                        action->set_param("canvas_interface",canvas_interface);
                        action->set_param("value_node",ValueNode::Handle(value_node));