Move states into subfolder
authorNikita Kitaev <nikitakit@gmail.com>
Sat, 17 Apr 2010 03:56:51 +0000 (20:56 -0700)
committerNikita Kitaev <nikitakit@gmail.com>
Sat, 17 Apr 2010 03:56:51 +0000 (20:56 -0700)
79 files changed:
synfig-studio/src/gui/Makefile.am
synfig-studio/src/gui/app.cpp
synfig-studio/src/gui/canvasview.cpp
synfig-studio/src/gui/state_bline.cpp [deleted file]
synfig-studio/src/gui/state_bline.h [deleted file]
synfig-studio/src/gui/state_circle.cpp [deleted file]
synfig-studio/src/gui/state_circle.h [deleted file]
synfig-studio/src/gui/state_draw.cpp [deleted file]
synfig-studio/src/gui/state_draw.h [deleted file]
synfig-studio/src/gui/state_eyedrop.cpp [deleted file]
synfig-studio/src/gui/state_eyedrop.h [deleted file]
synfig-studio/src/gui/state_fill.cpp [deleted file]
synfig-studio/src/gui/state_fill.h [deleted file]
synfig-studio/src/gui/state_gradient.cpp [deleted file]
synfig-studio/src/gui/state_gradient.h [deleted file]
synfig-studio/src/gui/state_mirror.cpp [deleted file]
synfig-studio/src/gui/state_mirror.h [deleted file]
synfig-studio/src/gui/state_normal.cpp [deleted file]
synfig-studio/src/gui/state_normal.h [deleted file]
synfig-studio/src/gui/state_polygon.cpp [deleted file]
synfig-studio/src/gui/state_polygon.h [deleted file]
synfig-studio/src/gui/state_rectangle.cpp [deleted file]
synfig-studio/src/gui/state_rectangle.h [deleted file]
synfig-studio/src/gui/state_rotate.cpp [deleted file]
synfig-studio/src/gui/state_rotate.h [deleted file]
synfig-studio/src/gui/state_scale.cpp [deleted file]
synfig-studio/src/gui/state_scale.h [deleted file]
synfig-studio/src/gui/state_sketch.cpp [deleted file]
synfig-studio/src/gui/state_sketch.h [deleted file]
synfig-studio/src/gui/state_smoothmove.cpp [deleted file]
synfig-studio/src/gui/state_smoothmove.h [deleted file]
synfig-studio/src/gui/state_star.cpp [deleted file]
synfig-studio/src/gui/state_star.h [deleted file]
synfig-studio/src/gui/state_stroke.cpp [deleted file]
synfig-studio/src/gui/state_stroke.h [deleted file]
synfig-studio/src/gui/state_text.cpp [deleted file]
synfig-studio/src/gui/state_text.h [deleted file]
synfig-studio/src/gui/state_width.cpp [deleted file]
synfig-studio/src/gui/state_width.h [deleted file]
synfig-studio/src/gui/state_zoom.cpp [deleted file]
synfig-studio/src/gui/state_zoom.h [deleted file]
synfig-studio/src/gui/states/state_bline.cpp [new file with mode: 0644]
synfig-studio/src/gui/states/state_bline.h [new file with mode: 0644]
synfig-studio/src/gui/states/state_circle.cpp [new file with mode: 0644]
synfig-studio/src/gui/states/state_circle.h [new file with mode: 0644]
synfig-studio/src/gui/states/state_draw.cpp [new file with mode: 0644]
synfig-studio/src/gui/states/state_draw.h [new file with mode: 0644]
synfig-studio/src/gui/states/state_eyedrop.cpp [new file with mode: 0644]
synfig-studio/src/gui/states/state_eyedrop.h [new file with mode: 0644]
synfig-studio/src/gui/states/state_fill.cpp [new file with mode: 0644]
synfig-studio/src/gui/states/state_fill.h [new file with mode: 0644]
synfig-studio/src/gui/states/state_gradient.cpp [new file with mode: 0644]
synfig-studio/src/gui/states/state_gradient.h [new file with mode: 0644]
synfig-studio/src/gui/states/state_mirror.cpp [new file with mode: 0644]
synfig-studio/src/gui/states/state_mirror.h [new file with mode: 0644]
synfig-studio/src/gui/states/state_normal.cpp [new file with mode: 0644]
synfig-studio/src/gui/states/state_normal.h [new file with mode: 0644]
synfig-studio/src/gui/states/state_polygon.cpp [new file with mode: 0644]
synfig-studio/src/gui/states/state_polygon.h [new file with mode: 0644]
synfig-studio/src/gui/states/state_rectangle.cpp [new file with mode: 0644]
synfig-studio/src/gui/states/state_rectangle.h [new file with mode: 0644]
synfig-studio/src/gui/states/state_rotate.cpp [new file with mode: 0644]
synfig-studio/src/gui/states/state_rotate.h [new file with mode: 0644]
synfig-studio/src/gui/states/state_scale.cpp [new file with mode: 0644]
synfig-studio/src/gui/states/state_scale.h [new file with mode: 0644]
synfig-studio/src/gui/states/state_sketch.cpp [new file with mode: 0644]
synfig-studio/src/gui/states/state_sketch.h [new file with mode: 0644]
synfig-studio/src/gui/states/state_smoothmove.cpp [new file with mode: 0644]
synfig-studio/src/gui/states/state_smoothmove.h [new file with mode: 0644]
synfig-studio/src/gui/states/state_star.cpp [new file with mode: 0644]
synfig-studio/src/gui/states/state_star.h [new file with mode: 0644]
synfig-studio/src/gui/states/state_stroke.cpp [new file with mode: 0644]
synfig-studio/src/gui/states/state_stroke.h [new file with mode: 0644]
synfig-studio/src/gui/states/state_text.cpp [new file with mode: 0644]
synfig-studio/src/gui/states/state_text.h [new file with mode: 0644]
synfig-studio/src/gui/states/state_width.cpp [new file with mode: 0644]
synfig-studio/src/gui/states/state_width.h [new file with mode: 0644]
synfig-studio/src/gui/states/state_zoom.cpp [new file with mode: 0644]
synfig-studio/src/gui/states/state_zoom.h [new file with mode: 0644]

index 0260a3c..f4442d3 100644 (file)
@@ -156,46 +156,46 @@ WIDGET_CC = \
 
 
 STATE_HH = \
-       state_bline.h \
-       state_circle.h \
-       state_draw.h \
-       state_eyedrop.h \
-       state_fill.h \
-       state_gradient.h \
-       state_mirror.h \
-       state_normal.h \
-       state_polygon.h \
-       state_rectangle.h \
-       state_rotate.h \
-       state_scale.h \
-       state_sketch.h \
-       state_smoothmove.h \
-       state_star.h \
-       state_stroke.h \
-       state_text.h \
-       state_width.h \
-       state_zoom.h
+       states/state_bline.h \
+       states/state_circle.h \
+       states/state_draw.h \
+       states/state_eyedrop.h \
+       states/state_fill.h \
+       states/state_gradient.h \
+       states/state_mirror.h \
+       states/state_normal.h \
+       states/state_polygon.h \
+       states/state_rectangle.h \
+       states/state_rotate.h \
+       states/state_scale.h \
+       states/state_sketch.h \
+       states/state_smoothmove.h \
+       states/state_star.h \
+       states/state_stroke.h \
+       states/state_text.h \
+       states/state_width.h \
+       states/state_zoom.h
 
 STATE_CC = \
-       state_bline.cpp \
-       state_circle.cpp \
-       state_draw.cpp \
-       state_eyedrop.cpp \
-       state_fill.cpp \
-       state_gradient.cpp \
-       state_mirror.cpp \
-       state_normal.cpp \
-       state_polygon.cpp \
-       state_rectangle.cpp \
-       state_rotate.cpp \
-       state_scale.cpp \
-       state_sketch.cpp \
-       state_smoothmove.cpp \
-       state_star.cpp \
-       state_stroke.cpp \
-       state_text.cpp \
-       state_width.cpp \
-       state_zoom.cpp
+       states/state_bline.cpp \
+       states/state_circle.cpp \
+       states/state_draw.cpp \
+       states/state_eyedrop.cpp \
+       states/state_fill.cpp \
+       states/state_gradient.cpp \
+       states/state_mirror.cpp \
+       states/state_normal.cpp \
+       states/state_polygon.cpp \
+       states/state_rectangle.cpp \
+       states/state_rotate.cpp \
+       states/state_scale.cpp \
+       states/state_sketch.cpp \
+       states/state_smoothmove.cpp \
+       states/state_star.cpp \
+       states/state_stroke.cpp \
+       states/state_text.cpp \
+       states/state_width.cpp \
+       states/state_zoom.cpp
 
 
 TREEVIEW_HH = \
index 719aec2..c27f7fc 100644 (file)
 
 #include "dockmanager.h"
 
-#include "state_eyedrop.h"
-#include "state_normal.h"
-#include "state_mirror.h"
-#include "state_draw.h"
-#include "state_fill.h"
-#include "state_bline.h"
-#include "state_polygon.h"
-#include "state_sketch.h"
-#include "state_gradient.h"
-#include "state_circle.h"
-#include "state_rectangle.h"
-#include "state_smoothmove.h"
-#include "state_scale.h"
-#include "state_star.h"
-#include "state_text.h"
-#include "state_width.h"
-#include "state_rotate.h"
-#include "state_zoom.h"
+#include "states/state_eyedrop.h"
+#include "states/state_normal.h"
+#include "states/state_mirror.h"
+#include "states/state_draw.h"
+#include "states/state_fill.h"
+#include "states/state_bline.h"
+#include "states/state_polygon.h"
+#include "states/state_sketch.h"
+#include "states/state_gradient.h"
+#include "states/state_circle.h"
+#include "states/state_rectangle.h"
+#include "states/state_smoothmove.h"
+#include "states/state_scale.h"
+#include "states/state_star.h"
+#include "states/state_text.h"
+#include "states/state_width.h"
+#include "states/state_rotate.h"
+#include "states/state_zoom.h"
 
 #include "devicetracker.h"
 #include "dialog_tooloptions.h"
index b421bf9..8fdd889 100644 (file)
 #include "dialogs/dialog_color.h"
 #include "eventkey.h"
 
-#include "state_polygon.h"
-#include "state_bline.h"
-#include "state_normal.h"
-#include "state_eyedrop.h"
+#include "states/state_polygon.h"
+#include "states/state_bline.h"
+#include "states/state_normal.h"
+#include "states/state_eyedrop.h"
 
 #include "ducktransform_scale.h"
 #include "ducktransform_translate.h"
diff --git a/synfig-studio/src/gui/state_bline.cpp b/synfig-studio/src/gui/state_bline.cpp
deleted file mode 100644 (file)
index ee0ca20..0000000
+++ /dev/null
@@ -1,1414 +0,0 @@
-/* === S Y N F I G ========================================================= */
-/*!    \file state_bline.cpp
-**     \brief Template File
-**
-**     $Id$
-**
-**     \legal
-**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
-**     Copyright (c) 2007, 2008 Chris Moore
-**
-**     This package is free software; you can redistribute it and/or
-**     modify it under the terms of the GNU General Public License as
-**     published by the Free Software Foundation; either version 2 of
-**     the License, or (at your option) any later version.
-**
-**     This package is distributed in the hope that it will be useful,
-**     but WITHOUT ANY WARRANTY; without even the implied warranty of
-**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-**     General Public License for more details.
-**     \endlegal
-*/
-/* ========================================================================= */
-
-/* === H E A D E R S ======================================================= */
-
-#ifdef USING_PCH
-#      include "pch.h"
-#else
-#ifdef HAVE_CONFIG_H
-#      include <config.h>
-#endif
-
-#include <gtkmm/dialog.h>
-#include <gtkmm/entry.h>
-
-#include <synfig/valuenode_dynamiclist.h>
-
-#include "state_bline.h"
-#include "state_normal.h"
-#include "canvasview.h"
-#include "workarea.h"
-#include "app.h"
-#include <synfig/valuenode_bline.h>
-#include <ETL/hermite>
-#include <ETL/calculus>
-#include <utility>
-#include "event_mouse.h"
-#include "event_layerclick.h"
-#include "toolbox.h"
-#include "dialog_tooloptions.h"
-#include <gtkmm/spinbutton.h>
-#include <synfig/transform.h>
-#include <synfigapp/main.h>
-
-#include "general.h"
-
-#endif
-
-/* === U S I N G =========================================================== */
-
-using namespace std;
-using namespace etl;
-using namespace synfig;
-using namespace studio;
-
-/* === M A C R O S ========================================================= */
-
-// if defined, show the first duck as green while drawing
-#define DISTINGUISH_FIRST_DUCK
-
-/* === G L O B A L S ======================================================= */
-
-StateBLine studio::state_bline;
-
-/* === C L A S S E S & S T R U C T S ======================================= */
-
-class studio::StateBLine_Context : public sigc::trackable
-{
-       etl::handle<CanvasView> canvas_view_;
-       CanvasView::IsWorking is_working;
-
-       bool prev_table_status;
-       bool loop_;
-       bool prev_workarea_layer_status_;
-
-       int depth;
-       Canvas::Handle canvas;
-
-       Gtk::Menu menu;
-
-       Duckmatic::Push duckmatic_push;
-
-       etl::handle<Duck> curr_duck;
-
-       etl::handle<Duck> next_duck;
-
-       std::list<synfig::ValueNode_Const::Handle> bline_point_list;
-       synfigapp::Settings& settings;
-
-       bool on_vertex_change(const synfig::Point &point, synfig::ValueNode_Const::Handle value_node);
-       bool on_tangent1_change(const synfig::Point &point, synfig::ValueNode_Const::Handle value_node);
-       bool on_tangent2_change(const synfig::Point &point, synfig::ValueNode_Const::Handle value_node);
-
-
-       void popup_handle_menu(synfig::ValueNode_Const::Handle value_node);
-       void popup_vertex_menu(synfig::ValueNode_Const::Handle value_node);
-       void popup_bezier_menu(float location, synfig::ValueNode_Const::Handle value_node);
-
-       void bline_detach_handle(synfig::ValueNode_Const::Handle value_node);
-       void bline_attach_handle(synfig::ValueNode_Const::Handle value_node);
-       void bline_delete_vertex(synfig::ValueNode_Const::Handle value_node);
-       void bline_insert_vertex(synfig::ValueNode_Const::Handle value_node,float origin=0.5);
-       void loop_bline();
-       void unloop_bline();
-
-       void refresh_ducks(bool x=true);
-
-       Gtk::Table options_table;
-       Gtk::Entry entry_id;
-       Gtk::CheckButton checkbutton_layer_region;
-       Gtk::CheckButton checkbutton_layer_outline;
-       Gtk::CheckButton checkbutton_layer_curve_gradient;
-       Gtk::CheckButton checkbutton_layer_plant;
-       Gtk::CheckButton checkbutton_layer_link_origins;
-       Gtk::CheckButton checkbutton_auto_export;
-       Gtk::Button button_make;
-       Gtk::Button button_clear;
-       Gtk::Adjustment  adj_feather;
-       Gtk::SpinButton  spin_feather;
-
-
-
-public:
-
-       int layers_to_create()const
-       {
-               return
-                       get_layer_region_flag() +
-                       get_layer_outline_flag() +
-                       get_layer_curve_gradient_flag() +
-                       get_layer_plant_flag();
-       }
-
-       void sanity_check()
-       {
-               if(layers_to_create()==0)
-                       set_layer_region_flag(true);
-       }
-
-       bool get_auto_export_flag()const { return checkbutton_auto_export.get_active(); }
-       void set_auto_export_flag(bool x) { return checkbutton_auto_export.set_active(x); }
-
-       bool get_layer_region_flag()const { return checkbutton_layer_region.get_active(); }
-       void set_layer_region_flag(bool x) { return checkbutton_layer_region.set_active(x); }
-
-       bool get_layer_outline_flag()const { return checkbutton_layer_outline.get_active(); }
-       void set_layer_outline_flag(bool x) { return checkbutton_layer_outline.set_active(x); }
-
-       bool get_layer_curve_gradient_flag()const { return checkbutton_layer_curve_gradient.get_active(); }
-       void set_layer_curve_gradient_flag(bool x) { return checkbutton_layer_curve_gradient.set_active(x); }
-
-       bool get_layer_plant_flag()const { return checkbutton_layer_plant.get_active(); }
-       void set_layer_plant_flag(bool x) { return checkbutton_layer_plant.set_active(x); }
-
-       bool get_layer_link_origins_flag()const { return checkbutton_layer_link_origins.get_active(); }
-       void set_layer_link_origins_flag(bool x) { return checkbutton_layer_link_origins.set_active(x); }
-
-       Real get_feather() const { return adj_feather.get_value(); }
-       void set_feather(Real x) { return adj_feather.set_value(x); }
-       synfig::String get_id()const { return entry_id.get_text(); }
-       void set_id(const synfig::String& x) { return entry_id.set_text(x); }
-
-       Smach::event_result event_stop_handler(const Smach::event& x);
-
-       Smach::event_result event_refresh_handler(const Smach::event& x);
-
-       Smach::event_result event_mouse_click_handler(const Smach::event& x);
-       Smach::event_result event_mouse_release_handler(const Smach::event& x);
-       Smach::event_result event_mouse_motion_handler(const Smach::event& x);
-       Smach::event_result event_refresh_tool_options(const Smach::event& x);
-
-       Smach::event_result event_hijack(const Smach::event& /*x*/) { return Smach::RESULT_ACCEPT; }
-
-       void refresh_tool_options();
-
-       StateBLine_Context(CanvasView* canvas_view);
-
-       ~StateBLine_Context();
-
-       const etl::handle<CanvasView>& get_canvas_view()const{return canvas_view_;}
-       etl::handle<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view_->canvas_interface();}
-       synfig::Canvas::Handle get_canvas()const{return canvas_view_->get_canvas();}
-       WorkArea * get_work_area()const{return canvas_view_->get_work_area();}
-       const synfig::TransformStack& get_transform_stack()const { return canvas_view_->get_curr_transform_stack(); }
-
-       void load_settings();
-       void save_settings();
-       void reset();
-       void increment_id();
-       //void on_user_click(synfig::Point point);
-
-       bool run_();
-       bool run();
-
-       bool egress_on_selection_change;
-       Smach::event_result event_layer_selection_changed_handler(const Smach::event& /*x*/)
-       {
-               if(egress_on_selection_change)
-                       throw &state_normal; //throw Smach::egress_exception();
-               return Smach::RESULT_OK;
-       }
-
-};     // END of class StateBLine_Context
-
-
-/* === M E T H O D S ======================================================= */
-
-StateBLine::StateBLine():
-       Smach::state<StateBLine_Context>("bline")
-{
-       insert(event_def(EVENT_LAYER_SELECTION_CHANGED,         &StateBLine_Context::event_layer_selection_changed_handler));
-       insert(event_def(EVENT_STOP,                                            &StateBLine_Context::event_stop_handler));
-       insert(event_def(EVENT_REFRESH,                                         &StateBLine_Context::event_refresh_handler));
-       insert(event_def(EVENT_REFRESH_DUCKS,                           &StateBLine_Context::event_hijack));
-       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,      &StateBLine_Context::event_mouse_click_handler));
-       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_UP,        &StateBLine_Context::event_mouse_release_handler));
-       insert(event_def(EVENT_WORKAREA_MOUSE_MOTION,           &StateBLine_Context::event_mouse_motion_handler));
-       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DRAG,      &StateBLine_Context::event_mouse_motion_handler));
-       insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,            &StateBLine_Context::event_refresh_tool_options));
-}
-
-StateBLine::~StateBLine()
-{
-}
-
-void
-StateBLine_Context::load_settings()
-{
-       String value;
-
-       if(settings.get_value("bline.layer_region",value) && value=="0")
-               set_layer_region_flag(false);
-       else
-               set_layer_region_flag(true);
-
-       if(settings.get_value("bline.layer_outline",value) && value=="0")
-               set_layer_outline_flag(false);
-       else
-               set_layer_outline_flag(true);
-
-       if(settings.get_value("bline.layer_curve_gradient",value) && value=="1")
-               set_layer_curve_gradient_flag(true);
-       else
-               set_layer_curve_gradient_flag(false);
-
-       if(settings.get_value("bline.layer_plant",value) && value=="1")
-               set_layer_plant_flag(true);
-       else
-               set_layer_plant_flag(false);
-
-       if(settings.get_value("bline.layer_link_origins",value) && value=="0")
-               set_layer_link_origins_flag(false);
-       else
-               set_layer_link_origins_flag(true);
-
-       if(settings.get_value("bline.auto_export",value) && value=="1")
-               set_auto_export_flag(true);
-       else
-               set_auto_export_flag(false);
-
-       if(settings.get_value("bline.id",value))
-               set_id(value);
-       else
-               set_id("NewBLine");
-
-       if(settings.get_value("bline.feather",value))
-       {
-               Real n = atof(value.c_str());
-               set_feather(n);
-       }
-
-       sanity_check();
-}
-
-void
-StateBLine_Context::save_settings()
-{
-       sanity_check();
-       settings.set_value("bline.layer_outline",get_layer_outline_flag()?"1":"0");
-       settings.set_value("bline.layer_region",get_layer_region_flag()?"1":"0");
-       settings.set_value("bline.layer_curve_gradient",get_layer_curve_gradient_flag()?"1":"0");
-       settings.set_value("bline.layer_plant",get_layer_plant_flag()?"1":"0");
-       settings.set_value("bline.layer_link_origins",get_layer_link_origins_flag()?"1":"0");
-       settings.set_value("bline.auto_export",get_auto_export_flag()?"1":"0");
-       settings.set_value("bline.id",get_id().c_str());
-       settings.set_value("bline.feather",strprintf("%f",get_feather()));
-}
-
-void
-StateBLine_Context::reset()
-{
-       loop_=false;
-       bline_point_list.clear();
-       refresh_ducks();
-}
-
-void
-StateBLine_Context::increment_id()
-{
-       String id(get_id());
-       int number=1;
-       int digits=0;
-
-       if(id.empty())
-               id="NewBLine";
-
-       // If there is a number
-       // already at the end of the
-       // id, then remove it.
-       if(id[id.size()-1]<='9' && id[id.size()-1]>='0')
-       {
-               // figure out how many digits it is
-               for (digits = 0;
-                        (int)id.size()-1 >= digits && id[id.size()-1-digits] <= '9' && id[id.size()-1-digits] >= '0';
-                        digits++)
-                       ;
-
-               String str_number;
-               str_number=String(id,id.size()-digits,id.size());
-               id=String(id,0,id.size()-digits);
-               // synfig::info("---------------- \"%s\"",str_number.c_str());
-
-               number=atoi(str_number.c_str());
-       }
-       else
-       {
-               number=1;
-               digits=3;
-       }
-
-       number++;
-
-       // Add the number back onto the id
-       {
-               const String format(strprintf("%%0%dd",digits));
-               id+=strprintf(format.c_str(),number);
-       }
-
-       // Set the ID
-       set_id(id);
-}
-
-
-StateBLine_Context::StateBLine_Context(CanvasView* canvas_view):
-       canvas_view_(canvas_view),
-       is_working(*canvas_view),
-       loop_(false),
-       prev_workarea_layer_status_(get_work_area()->get_allow_layer_clicks()),
-       duckmatic_push(get_work_area()),
-       settings(synfigapp::Main::get_selected_input_device()->settings()),
-       entry_id(),
-       checkbutton_layer_region(_("Create Region BLine")),
-       checkbutton_layer_outline(_("Create Outline BLine")),
-       checkbutton_layer_curve_gradient(_("Create Curve Gradient BLine")),
-       checkbutton_layer_plant(_("Create Plant BLine")),
-       checkbutton_layer_link_origins(_("Link Origins")),
-       checkbutton_auto_export(_("Auto Export")),
-       button_make(_("Make")),
-       button_clear(_("Clear")),
-       adj_feather(0,0,10000,0.01,0.1),
-       spin_feather(adj_feather,0.01,4)
-{
-       depth=-1;
-       egress_on_selection_change=true;
-       load_settings();
-
-       // Set up the tool options dialog
-       options_table.attach(*manage(new Gtk::Label(_("BLine Tool"))),  0, 2,  0,  1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(entry_id,                                                                  0, 2,  1,  2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(checkbutton_layer_outline,                                 0, 2,  2,  3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(checkbutton_layer_region,                                  0, 2,  3,  4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(checkbutton_layer_plant,                                   0, 2,  4,  5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(checkbutton_layer_curve_gradient,                  0, 2,  5,  6, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(checkbutton_layer_link_origins,                    0, 2,  6,  7, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(checkbutton_auto_export,                                   0, 2,  7,  8, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(*manage(new Gtk::Label(_("Feather"))),     0, 1, 10, 11, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(spin_feather,                                                              1, 2, 10, 11, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       //options_table.attach(button_make, 0, 2, 5, 6, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       //button_make.signal_pressed().connect(sigc::mem_fun(*this,&StateBLine_Context::run));
-       options_table.show_all();
-       refresh_tool_options();
-       App::dialog_tool_options->present();
-
-       // Turn off layer clicking
-       get_work_area()->set_allow_layer_clicks(false);
-
-       // clear out the ducks
-       get_work_area()->clear_ducks();
-
-       // Refresh the work area
-       get_work_area()->queue_draw();
-
-       // Hide the tables if they are showing
-       prev_table_status=get_canvas_view()->tables_are_visible();
-       if(prev_table_status)get_canvas_view()->hide_tables();
-
-       // Disable the time bar
-       get_canvas_view()->set_sensitive_timebar(false);
-
-       // Connect a signal
-       //get_work_area()->signal_user_click().connect(sigc::mem_fun(*this,&studio::StateBLine_Context::on_user_click));
-       get_work_area()->set_cursor(Gdk::CROSSHAIR);
-
-       App::toolbox->refresh();
-}
-
-void
-StateBLine_Context::refresh_tool_options()
-{
-       App::dialog_tool_options->clear();
-       App::dialog_tool_options->set_widget(options_table);
-       App::dialog_tool_options->set_local_name(_("BLine Tool"));
-       App::dialog_tool_options->set_name("bline");
-
-       App::dialog_tool_options->add_button(
-               Gtk::StockID("gtk-execute"),
-               _("Make BLine and/or Region")
-       )->signal_clicked().connect(
-               sigc::hide_return(sigc::mem_fun(
-                       *this,
-                       &StateBLine_Context::run
-               ))
-       );
-
-       App::dialog_tool_options->add_button(
-               Gtk::StockID("gtk-clear"),
-               _("Clear current BLine")
-       )->signal_clicked().connect(
-               sigc::mem_fun(
-                       *this,
-                       &StateBLine_Context::reset
-               )
-       );
-}
-
-Smach::event_result
-StateBLine_Context::event_refresh_tool_options(const Smach::event& /*x*/)
-{
-       refresh_tool_options();
-       return Smach::RESULT_ACCEPT;
-}
-
-StateBLine_Context::~StateBLine_Context()
-{
-       run();
-
-       save_settings();
-       App::dialog_tool_options->clear();
-
-       get_work_area()->reset_cursor();
-
-       // Restore layer clicking
-       get_work_area()->set_allow_layer_clicks(prev_workarea_layer_status_);
-
-       // Enable the time bar
-       get_canvas_view()->set_sensitive_timebar(true);
-
-       // Bring back the tables if they were out before
-       if(prev_table_status)get_canvas_view()->show_tables();
-
-//     get_canvas_view()->get_smach().process_event(EVENT_REFRESH_DUCKS);
-
-       // Refresh the work area
-       get_work_area()->queue_draw();
-
-       App::toolbox->refresh();
-}
-
-Smach::event_result
-StateBLine_Context::event_stop_handler(const Smach::event& /*x*/)
-{
-//     synfig::info("STATE RotoBLine: Received Stop Event");
-//     run();
-       reset();
-//     throw Smach::egress_exception();
-//     get_canvas_view()->get_smach().pop_state();
-       return Smach::RESULT_ACCEPT;
-}
-
-Smach::event_result
-StateBLine_Context::event_refresh_handler(const Smach::event& /*x*/)
-{
-//     synfig::info("STATE RotoBLine: Received Refresh Event");
-       refresh_ducks();
-       return Smach::RESULT_ACCEPT;
-}
-
-bool
-StateBLine_Context::run()
-{
-       sanity_check();
-
-       String err;
-       bool success(false);
-       for(int i=5;i>0 && !success;i--)try
-       {
-               success=run_();
-       }
-       catch(String s)
-       {
-               err=s;
-       }
-       if(!success && !err.empty())
-       {
-               get_canvas_view()->get_ui_interface()->error(err);
-       }
-       return success;
-}
-
-bool
-StateBLine_Context::run_()
-{
-       curr_duck=0;
-       next_duck=0;
-
-       // Now we need to generate it
-
-       if(bline_point_list.empty())
-       {
-               return false;
-       }
-       if(bline_point_list.size()<2)
-       {
-               //get_canvas_view()->get_ui_interface()->error(_("You need at least two (2) points to create a BLine"));
-               return false;
-       }
-
-       do
-       {
-
-               // Create the action group
-               synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("New BLine"));
-
-               std::vector<BLinePoint> new_list;
-               std::list<synfig::ValueNode_Const::Handle>::iterator iter;
-               const synfig::TransformStack& transform(get_transform_stack());
-
-               for(iter=bline_point_list.begin();iter!=bline_point_list.end();++iter)
-               {
-                       BLinePoint bline_point((*iter)->get_value().get(BLinePoint()));
-                       Point new_vertex(transform.unperform(bline_point.get_vertex()));
-
-                       bline_point.set_tangent1(
-                               transform.unperform(
-                                       bline_point.get_tangent1()+bline_point.get_vertex()
-                               ) -new_vertex
-                       );
-
-                       bline_point.set_tangent2(
-                               transform.unperform(
-                                       bline_point.get_tangent2()+bline_point.get_vertex()
-                               ) -new_vertex
-                       );
-
-                       bline_point.set_vertex(new_vertex);
-
-                       new_list.push_back(bline_point);
-               }
-
-               ValueNode_BLine::Handle value_node_bline(ValueNode_BLine::create(new_list));
-               assert(value_node_bline);
-
-               ValueNode_Const::Handle value_node_origin(ValueNode_Const::create(Vector()));
-               assert(value_node_origin);
-
-               // Set the looping flag
-               value_node_bline->set_loop(loop_);
-
-               // Add the BLine to the canvas
-               if(get_auto_export_flag() && !get_canvas_interface()->add_value_node(value_node_bline,get_id()))
-               {
-                       //get_canvas_view()->get_ui_interface()->error(_("Unable to add value node"));
-                       group.cancel();
-                       increment_id();
-                       throw String(_("Unable to add value node"));
-                       return false;
-               }
-
-               Layer::Handle layer;
-
-               // we are temporarily using the layer to hold something
-               layer=get_canvas_view()->get_selection_manager()->get_selected_layer();
-
-               if(layer)
-               {
-                       if(depth<0)
-                               depth=layer->get_depth();
-                       if(!canvas)
-                               canvas=layer->get_canvas();
-               }
-               else
-                       depth=0;
-
-               if(!canvas)
-                       canvas=get_canvas_view()->get_canvas();
-
-               value_node_bline->set_member_canvas(canvas);
-
-               synfigapp::SelectionManager::LayerList layer_selection;
-               if (!getenv("SYNFIG_TOOLS_CLEAR_SELECTION"))
-                       layer_selection = get_canvas_view()->get_selection_manager()->get_selected_layers();
-
-               // count how many layers we're going to be creating
-               int layers_to_create = this->layers_to_create();
-
-               ///////////////////////////////////////////////////////////////////////////
-               //   C U R V E   G R A D I E N T
-               ///////////////////////////////////////////////////////////////////////////
-
-               if(get_layer_curve_gradient_flag())
-               {
-                       synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
-
-                       Layer::Handle layer(get_canvas_interface()->add_layer_to("curve_gradient",canvas,depth));
-                       if (!layer)
-                       {
-                               group.cancel();
-                               throw String(_("Unable to create layer"));
-                       }
-                       layer_selection.push_back(layer);
-                       layer->set_description(get_id()+_(" Gradient"));
-                       get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
-
-                       {
-                               synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
-                               assert(action);
-
-                               action->set_param("canvas",get_canvas());
-                               action->set_param("canvas_interface",get_canvas_interface());
-                               action->set_param("layer",layer);
-                               if(!action->set_param("param",String("bline")))
-                                       synfig::error("LayerParamConnect didn't like \"param\"");
-                               if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
-                                       synfig::error("LayerParamConnect didn't like \"value_node\"");
-
-                               if(!get_canvas_interface()->get_instance()->perform_action(action))
-                               {
-                                       //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
-                                       group.cancel();
-                                       throw String(_("Unable to create Gradient layer"));
-                                       return false;
-                               }
-                       }
-
-                       // only link the curve gradient's origin parameter if the option is selected and we're creating more than one layer
-                       if (get_layer_link_origins_flag() && layers_to_create > 1)
-                       {
-                               synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
-                               assert(action);
-
-                               action->set_param("canvas",get_canvas());
-                               action->set_param("canvas_interface",get_canvas_interface());
-                               action->set_param("layer",layer);
-                               if(!action->set_param("param",String("origin")))
-                                       synfig::error("LayerParamConnect didn't like \"param\"");
-                               if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
-                                       synfig::error("LayerParamConnect didn't like \"value_node\"");
-
-                               if(!get_canvas_interface()->get_instance()->perform_action(action))
-                               {
-                                       //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
-                                       group.cancel();
-                                       throw String(_("Unable to create Gradient layer"));
-                                       return false;
-                               }
-                       }
-               }
-
-               ///////////////////////////////////////////////////////////////////////////
-               //   P L A N T
-               ///////////////////////////////////////////////////////////////////////////
-
-               if(get_layer_plant_flag())
-               {
-                       synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
-
-                       Layer::Handle layer(get_canvas_interface()->add_layer_to("plant",canvas,depth));
-                       if (!layer)
-                       {
-                               group.cancel();
-                               throw String(_("Unable to create layer"));
-                       }
-                       layer_selection.push_back(layer);
-                       layer->set_description(get_id()+_(" Plant"));
-                       get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
-
-                       {
-                               synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
-                               assert(action);
-
-                               action->set_param("canvas",get_canvas());
-                               action->set_param("canvas_interface",get_canvas_interface());
-                               action->set_param("layer",layer);
-                               if(!action->set_param("param",String("bline")))
-                                       synfig::error("LayerParamConnect didn't like \"param\"");
-                               if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
-                                       synfig::error("LayerParamConnect didn't like \"value_node\"");
-
-                               if(!get_canvas_interface()->get_instance()->perform_action(action))
-                               {
-                                       //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
-                                       group.cancel();
-                                       throw String(_("Unable to create Plant layer"));
-                                       return false;
-                               }
-                       }
-
-                       // only link the plant's origin parameter if the option is selected and we're creating more than one layer
-                       if (get_layer_link_origins_flag() && layers_to_create > 1)
-                       {
-                               synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
-                               assert(action);
-
-                               action->set_param("canvas",get_canvas());
-                               action->set_param("canvas_interface",get_canvas_interface());
-                               action->set_param("layer",layer);
-                               if(!action->set_param("param",String("origin")))
-                                       synfig::error("LayerParamConnect didn't like \"param\"");
-                               if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
-                                       synfig::error("LayerParamConnect didn't like \"value_node\"");
-
-                               if(!get_canvas_interface()->get_instance()->perform_action(action))
-                               {
-                                       //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
-                                       group.cancel();
-                                       throw String(_("Unable to create Plant layer"));
-                                       return false;
-                               }
-                       }
-               }
-
-               ///////////////////////////////////////////////////////////////////////////
-               //   R E G I O N
-               ///////////////////////////////////////////////////////////////////////////
-
-               if(get_layer_region_flag())
-               {
-                       synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
-
-                       Layer::Handle layer(get_canvas_interface()->add_layer_to("region",canvas,depth));
-                       if (!layer)
-                       {
-                               group.cancel();
-                               throw String(_("Unable to create layer"));
-                       }
-                       layer_selection.push_back(layer);
-                       layer->set_description(get_id()+_(" Region"));
-                       get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
-
-                       if(get_feather())
-                       {
-                               layer->set_param("feather",get_feather());
-                               get_canvas_interface()->signal_layer_param_changed()(layer,"feather");
-                       }
-
-                       // I don't know if it's safe to reuse the same LayerParamConnect action, so I'm
-                       // using 2 separate ones.
-                       {
-                               synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
-                               assert(action);
-
-                               action->set_param("canvas",get_canvas());
-                               action->set_param("canvas_interface",get_canvas_interface());
-                               action->set_param("layer",layer);
-                               if(!action->set_param("param",String("bline")))
-                                       synfig::error("LayerParamConnect didn't like \"param\"");
-                               if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
-                                       synfig::error("LayerParamConnect didn't like \"value_node\"");
-
-                               if(!get_canvas_interface()->get_instance()->perform_action(action))
-                               {
-                                       //get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer"));
-                                       group.cancel();
-                                       throw String(_("Unable to create Region layer"));
-                                       return false;
-                               }
-                       }
-
-                       // only link the region's origin parameter if the option is selected and we're creating more than one layer
-                       if (get_layer_link_origins_flag() && layers_to_create > 1)
-                       {
-                               synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
-                               assert(action);
-
-                               action->set_param("canvas",get_canvas());
-                               action->set_param("canvas_interface",get_canvas_interface());
-                               action->set_param("layer",layer);
-                               if(!action->set_param("param",String("origin")))
-                                       synfig::error("LayerParamConnect didn't like \"param\"");
-                               if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
-                                       synfig::error("LayerParamConnect didn't like \"value_node\"");
-
-                               if(!get_canvas_interface()->get_instance()->perform_action(action))
-                               {
-                                       //get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer"));
-                                       group.cancel();
-                                       throw String(_("Unable to create Region layer"));
-                                       return false;
-                               }
-                       }
-               }
-
-               ///////////////////////////////////////////////////////////////////////////
-               //   O U T L I N E
-               ///////////////////////////////////////////////////////////////////////////
-
-               if(get_layer_outline_flag())
-               {
-                       synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
-
-                       Layer::Handle layer(get_canvas_interface()->add_layer_to("outline",canvas,depth));
-                       if (!layer)
-                       {
-                               group.cancel();
-                               throw String(_("Unable to create layer"));
-                       }
-                       layer_selection.push_back(layer);
-                       layer->set_description(get_id()+_(" Outline"));
-                       get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
-                       if(get_feather())
-                       {
-                               layer->set_param("feather",get_feather());
-                               get_canvas_interface()->signal_layer_param_changed()(layer,"feather");
-                       }
-
-                       {
-                               synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
-                               assert(action);
-
-                               action->set_param("canvas",get_canvas());
-                               action->set_param("canvas_interface",get_canvas_interface());
-                               action->set_param("layer",layer);
-                               if(!action->set_param("param",String("bline")))
-                                       synfig::error("LayerParamConnect didn't like \"param\"");
-                               if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
-                                       synfig::error("LayerParamConnect didn't like \"value_node\"");
-
-                               if(!get_canvas_interface()->get_instance()->perform_action(action))
-                               {
-                                       //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
-                                       group.cancel();
-                                       throw String(_("Unable to create Outline layer"));
-                                       return false;
-                               }
-                       }
-
-                       // only link the outline's origin parameter if the option is selected and we're creating more than one layer
-                       if (get_layer_link_origins_flag() && layers_to_create > 1)
-                       {
-                               synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
-                               assert(action);
-
-                               action->set_param("canvas",get_canvas());
-                               action->set_param("canvas_interface",get_canvas_interface());
-                               action->set_param("layer",layer);
-                               if(!action->set_param("param",String("origin")))
-                                       synfig::error("LayerParamConnect didn't like \"param\"");
-                               if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
-                                       synfig::error("LayerParamConnect didn't like \"value_node\"");
-
-                               if(!get_canvas_interface()->get_instance()->perform_action(action))
-                               {
-                                       //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
-                                       group.cancel();
-                                       throw String(_("Unable to create Outline layer"));
-                                       return false;
-                               }
-                       }
-               }
-
-               egress_on_selection_change=false;
-               get_canvas_interface()->get_selection_manager()->clear_selected_layers();
-               get_canvas_interface()->get_selection_manager()->set_selected_layers(layer_selection);
-               egress_on_selection_change=true;
-
-               //if(finish_bline_dialog.get_region_flag() || finish_bline_dialog.get_bline_flag())
-               //      get_canvas_interface()->signal_dirty_preview()();
-
-       } while(0);
-
-       reset();
-       increment_id();
-       return true;
-}
-
-Smach::event_result
-StateBLine_Context::event_mouse_motion_handler(const Smach::event& x)
-{
-       const EventMouse& event(*reinterpret_cast<const EventMouse*>(&x));
-
-       if(curr_duck)
-       {
-               //synfig::info("Moved Duck");
-               Point p(get_work_area()->snap_point_to_grid(event.pos));
-               curr_duck->set_trans_point(p);
-               if(next_duck)
-                       next_duck->set_trans_point(p);
-               get_work_area()->queue_draw();
-               return Smach::RESULT_ACCEPT;
-       }
-
-       return Smach::RESULT_OK;
-}
-
-Smach::event_result
-StateBLine_Context::event_mouse_release_handler(const Smach::event& /*x*/)
-{
-       if(curr_duck)
-       {
-               //synfig::info("Released current duck");
-               curr_duck->signal_edited()(curr_duck->get_point());
-               if(next_duck)
-               {
-                       //synfig::info("grabbing next duck");
-                       curr_duck=next_duck;
-                       next_duck=0;
-               }
-               return Smach::RESULT_ACCEPT;
-       }
-       return Smach::RESULT_OK;
-}
-
-Smach::event_result
-StateBLine_Context::event_mouse_click_handler(const Smach::event& x)
-{
-       // synfig::info("STATE BLINE: Received mouse button down Event");
-       const EventMouse& event(*reinterpret_cast<const EventMouse*>(&x));
-       switch(event.button)
-       {
-       case BUTTON_LEFT:
-               {
-                       // If we are already looped up, then don't try to add anything else
-                       if(loop_)
-                               return Smach::RESULT_OK;
-
-                       BLinePoint bline_point;
-
-                       bline_point.set_vertex(get_work_area()->snap_point_to_grid(event.pos));
-                       //bline_point.set_width(synfigapp::Main::get_bline_width());
-                       bline_point.set_width(1.0f);
-                       bline_point.set_origin(0.5f);
-                       bline_point.set_split_tangent_flag(false);
-                       bline_point.set_tangent1(Vector(0,0));
-
-                       // set the tangent
-                       /*
-                       if(bline_point_list.empty())
-                       {
-                               bline_point.set_tangent1(Vector(1,1));
-                       }
-                       else
-                       {
-                               const Vector t(event.pos-bline_point_list.back()->get_value().get(BLinePoint()).get_vertex());
-                               bline_point.set_tangent1(t);
-                       }
-
-                       if(bline_point_list.size()>1)
-                       {
-                               std::list<synfig::ValueNode_Const::Handle>::iterator iter;
-                               iter=bline_point_list.end();
-                               iter--;iter--;
-                               BLinePoint prev(bline_point_list.back()->get_value().get(BLinePoint()));
-                               prev.set_tangent1(event.pos-(*iter)->get_value().get(BLinePoint()).get_vertex());
-                               bline_point_list.back()->set_value(prev);
-                       };
-                       */
-
-                       bline_point_list.push_back(ValueNode_Const::create(bline_point));
-
-                       refresh_ducks();
-                       return Smach::RESULT_ACCEPT;
-               }
-
-       default:
-               return Smach::RESULT_OK;
-       }
-}
-
-void
-StateBLine_Context::refresh_ducks(bool button_down)
-{
-       get_work_area()->clear_ducks();
-       get_work_area()->queue_draw();
-
-       if(bline_point_list.empty())
-               return;
-
-       list<ValueNode_Const::Handle>::iterator iter;
-
-       handle<WorkArea::Bezier> bezier;
-       handle<WorkArea::Duck> duck,tduck;
-       BLinePoint bline_point;
-
-       for(iter=bline_point_list.begin();iter!=bline_point_list.end();++iter)
-       {
-               ValueNode_Const::Handle value_node(*iter);
-               bline_point=(value_node->get_value().get(BLinePoint()));
-               assert(value_node);
-
-
-               // First add the duck associated with this vertex
-               duck=new WorkArea::Duck(bline_point.get_vertex());
-               duck->set_editable(true);
-#ifdef DISTINGUISH_FIRST_DUCK
-               if (iter!=bline_point_list.begin())
-                       duck->set_type(Duck::TYPE_VERTEX);
-#else
-               duck->set_type(Duck::TYPE_VERTEX);
-#endif
-               duck->set_name(strprintf("%x-vertex",value_node.get()));
-               duck->signal_edited().connect(
-                       sigc::bind(sigc::mem_fun(*this,&studio::StateBLine_Context::on_vertex_change),value_node)
-               );
-               duck->signal_user_click(2).connect(
-                       sigc::bind(sigc::mem_fun(*this,&studio::StateBLine_Context::popup_vertex_menu),value_node)
-               );
-               duck->set_guid(value_node->get_guid()^synfig::GUID::hasher(0));
-
-               get_work_area()->add_duck(duck);
-
-               // Add the tangent1 duck
-               tduck=new WorkArea::Duck(bline_point.get_tangent1());
-               tduck->set_editable(true);
-               tduck->set_name(strprintf("%x-tangent1",value_node.get()));
-               tduck->set_origin(duck);
-               tduck->set_scalar(-0.33333333333333333);
-               tduck->set_tangent(true);
-               tduck->set_guid(value_node->get_guid()^synfig::GUID::hasher(3));
-               tduck->signal_edited().connect(
-                       sigc::bind(sigc::mem_fun(*this,&studio::StateBLine_Context::on_tangent1_change),value_node)
-               );
-               tduck->signal_user_click(2).connect(
-                       sigc::bind(sigc::mem_fun(*this,&studio::StateBLine_Context::popup_handle_menu),value_node)
-               );
-
-               // See if we need to add that duck to the previous bezier
-               if(bezier)
-               {
-                       get_work_area()->add_duck(tduck);
-                       bezier->p2=duck;
-                       bezier->c2=tduck;
-
-                       bezier->signal_user_click(2).connect(
-                               sigc::bind(
-                                       sigc::mem_fun(
-                                               *this,
-                                               &studio::StateBLine_Context::popup_bezier_menu
-                                       ),
-                                       value_node
-                               )
-                       );
-
-                       //get_work_area()->add_duck(bezier->c1);
-                       //get_work_area()->add_duck(bezier->c2);
-                       get_work_area()->add_bezier(bezier);
-
-                       bezier=0;
-               }
-
-               // Now we see if we need to create a bezier
-               list<ValueNode_Const::Handle>::iterator next(iter);
-               next++;
-
-               // If our next iterator is the end, then we don't need
-               // to add a bezier.
-               //if(next==bline_point_list.end() && !loop_)
-               //      continue;
-
-               bezier=new WorkArea::Bezier();
-
-               // Add the tangent2 duck
-               tduck=new WorkArea::Duck(bline_point.get_tangent2());
-               tduck->set_editable(true);
-               tduck->set_origin(duck);
-               tduck->set_scalar(0.33333333333333333);
-               tduck->set_tangent(true);
-               if(bline_point.get_split_tangent_flag())
-               {
-                       tduck->set_name(strprintf("%x-tangent2",value_node.get()));
-                       tduck->signal_edited().connect(
-                               sigc::bind(sigc::mem_fun(*this,&studio::StateBLine_Context::on_tangent2_change),value_node)
-                       );
-               }
-               else
-               {
-                       tduck->set_name(strprintf("%x-tangent1",value_node.get()));
-                       tduck->signal_edited().connect(
-                               sigc::bind(sigc::mem_fun(*this,&studio::StateBLine_Context::on_tangent1_change),value_node)
-                       );
-               }
-               tduck->set_guid(value_node->get_guid()^synfig::GUID::hasher(4));
-               tduck->signal_user_click(2).connect(
-                       sigc::bind(sigc::mem_fun(*this,&studio::StateBLine_Context::popup_handle_menu),value_node)
-               );
-
-               // Setup the next bezier
-               bezier->p1=duck;
-               bezier->c1=tduck;
-
-               get_work_area()->add_duck(tduck);
-               curr_duck=tduck;
-       }
-
-       // Add the loop, if requested
-       if(bezier && loop_)
-       {
-               curr_duck=0;
-               BLinePoint bline_point(bline_point_list.front()->get_value().get(BLinePoint()));
-
-               duck=new WorkArea::Duck(bline_point.get_vertex());
-               duck->set_editable(true);
-#ifndef DISTINGUISH_FIRST_DUCK
-               duck->set_type(Duck::TYPE_VERTEX);
-#endif
-               duck->set_name(strprintf("%x-vertex",bline_point_list.front().get()));
-               duck->signal_edited().connect(
-                       sigc::bind(sigc::mem_fun(*this,&studio::StateBLine_Context::on_vertex_change),bline_point_list.front())
-               );
-               duck->signal_user_click(2).connect(
-                       sigc::bind(sigc::mem_fun(*this,&studio::StateBLine_Context::popup_vertex_menu),bline_point_list.front())
-               );
-               get_work_area()->add_duck(duck);
-
-               // Add the tangent1 duck
-               tduck=new WorkArea::Duck(bline_point.get_tangent1());
-               tduck->set_editable(true);
-               tduck->set_name(strprintf("%x-tangent1",bline_point_list.front().get()));
-               tduck->set_origin(duck);
-               tduck->set_scalar(-0.33333333333333333);
-               tduck->set_tangent(true);
-               tduck->signal_edited().connect(
-                       sigc::bind(sigc::mem_fun(*this,&studio::StateBLine_Context::on_tangent1_change),bline_point_list.front())
-               );
-               tduck->signal_user_click(2).connect(
-                       sigc::bind(sigc::mem_fun(*this,&studio::StateBLine_Context::popup_handle_menu),bline_point_list.front())
-               );
-               get_work_area()->add_duck(tduck);
-
-               bezier->p2=duck;
-               bezier->c2=tduck;
-
-               bezier->signal_user_click(2).connect(
-                       sigc::bind(
-                               sigc::mem_fun(
-                                       *this,
-                                       &studio::StateBLine_Context::popup_bezier_menu
-                               ),
-                               bline_point_list.front()
-                       )
-               );
-
-               //get_work_area()->add_duck(bezier->c1);
-               get_work_area()->add_bezier(bezier);
-       }
-       if(bezier && !loop_)
-       {
-               duck=new WorkArea::Duck(bline_point.get_vertex());
-               duck->set_ignore(true);
-               duck->set_name("temp");
-
-               // Add the tangent1 duck
-               tduck=new WorkArea::Duck(Vector(0,0));
-               tduck->set_ignore(true);
-               tduck->set_name("ttemp");
-               tduck->set_origin(duck);
-               tduck->set_scalar(-0.33333333333333333);
-
-               tduck->set_tangent(true);
-               bezier->p2=duck;
-               bezier->c2=tduck;
-
-               get_work_area()->add_duck(bezier->p2);
-               //get_work_area()->add_duck(bezier->c2);
-               get_work_area()->add_bezier(bezier);
-
-               duck->set_guid(synfig::GUID());
-               tduck->set_guid(synfig::GUID());
-
-               next_duck=duck;
-       }
-
-       if(!button_down)
-       {
-               if(curr_duck)
-               {
-                       if(next_duck)
-                       {
-                               curr_duck=next_duck;
-                               next_duck=0;
-                       }
-               }
-       }
-       get_work_area()->queue_draw();
-}
-
-
-bool
-StateBLine_Context::on_vertex_change(const synfig::Point &point, synfig::ValueNode_Const::Handle value_node)
-{
-       BLinePoint bline_point(value_node->get_value().get(BLinePoint()));
-       bline_point.set_vertex(point);
-       value_node->set_value(bline_point);
-       //refresh_ducks();
-       return true;
-}
-
-bool
-StateBLine_Context::on_tangent1_change(const synfig::Point &point, synfig::ValueNode_Const::Handle value_node)
-{
-       BLinePoint bline_point(value_node->get_value().get(BLinePoint()));
-       bline_point.set_tangent1(point);
-       value_node->set_value(bline_point);
-       //refresh_ducks();
-       return true;
-}
-
-bool
-StateBLine_Context::on_tangent2_change(const synfig::Point &point, synfig::ValueNode_Const::Handle value_node)
-{
-       BLinePoint bline_point(value_node->get_value().get(BLinePoint()));
-       bline_point.set_tangent2(point);
-       value_node->set_value(bline_point);
-       //refresh_ducks();
-       return true;
-}
-
-void
-StateBLine_Context::loop_bline()
-{
-       loop_=true;
-
-       refresh_ducks(false);
-}
-
-void
-StateBLine_Context::unloop_bline()
-{
-       loop_=false;
-
-       refresh_ducks(false);
-}
-
-void
-StateBLine_Context::popup_vertex_menu(synfig::ValueNode_Const::Handle value_node)
-{
-       menu.items().clear();
-
-       if(loop_)
-       {
-               menu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("Unloop BLine"),
-                               sigc::mem_fun(*this,&studio::StateBLine_Context::unloop_bline)
-               ));
-       } else {
-               menu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("Loop BLine"),
-                               sigc::mem_fun(*this,&studio::StateBLine_Context::loop_bline)
-               ));
-       }
-
-       menu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("Delete Vertex"),
-               sigc::bind(
-                       sigc::mem_fun(*this,&studio::StateBLine_Context::bline_delete_vertex),
-                       value_node
-               )
-       ));
-
-       menu.popup(0,0);
-}
-
-void
-StateBLine_Context::popup_bezier_menu(float location, synfig::ValueNode_Const::Handle value_node)
-{
-       menu.items().clear();
-
-       menu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("Insert Vertex"),
-               sigc::bind(
-                       sigc::bind(
-                               sigc::mem_fun(*this,&studio::StateBLine_Context::bline_insert_vertex),
-                               location
-                       ),
-                       value_node
-               )
-       ));
-
-       menu.popup(0,0);
-}
-
-void
-StateBLine_Context::bline_insert_vertex(synfig::ValueNode_Const::Handle value_node, float origin)
-{
-       list<ValueNode_Const::Handle>::iterator iter;
-
-       for(iter=bline_point_list.begin();iter!=bline_point_list.end();++iter)
-               if(*iter==value_node)
-               {
-                       BLinePoint bline_point;
-                       BLinePoint next_bline_point((*iter)->get_value().get(BLinePoint()));
-                       BLinePoint prev_bline_point;
-
-                       list<ValueNode_Const::Handle>::iterator prev(iter);
-                       if(iter==bline_point_list.begin())
-                       {
-                               assert(loop_);
-                               prev = bline_point_list.end();
-                       }
-                       prev--;
-
-                       prev_bline_point=(*prev)->get_value().get(BLinePoint());
-
-                       etl::hermite<Vector> curve(prev_bline_point.get_vertex(),
-                                                                          next_bline_point.get_vertex(),
-                                                                          prev_bline_point.get_tangent2(),
-                                                                          next_bline_point.get_tangent1());
-                       etl::derivative< etl::hermite<Vector> > deriv(curve);
-
-                       bline_point.set_vertex(curve(origin));
-                       bline_point.set_width((next_bline_point.get_width()-prev_bline_point.get_width())*origin+prev_bline_point.get_width());
-                       bline_point.set_tangent1(deriv(origin)*std::min(1.0f-origin,origin));
-                       bline_point.set_tangent2(bline_point.get_tangent1());
-                       bline_point.set_split_tangent_flag(false);
-                       bline_point.set_origin(origin);
-
-/*
-                       bline_point.set_vertex((next_bline_point.get_vertex()+prev_bline_point.get_vertex())*0.5);
-                       bline_point.set_width((next_bline_point.get_width()+prev_bline_point.get_width())*0.5);
-                       bline_point.set_origin(origin);
-                       bline_point.set_split_tangent_flag(false);
-                       bline_point.set_tangent1((next_bline_point.get_vertex()-prev_bline_point.get_vertex())*0.5);
-*/
-
-                       bline_point_list.insert(iter,ValueNode_Const::create(bline_point));
-                       break;
-               }
-
-       if(iter==bline_point_list.end())
-       {
-               get_canvas_view()->get_ui_interface()->error(_("Unable to find where to insert vertex, internal error, please report this bug"));
-       }
-
-       refresh_ducks(false);
-}
-
-void
-StateBLine_Context::bline_delete_vertex(synfig::ValueNode_Const::Handle value_node)
-{
-       list<ValueNode_Const::Handle>::iterator iter;
-
-       for(iter=bline_point_list.begin();iter!=bline_point_list.end();++iter)
-               if(*iter==value_node)
-               {
-                       bline_point_list.erase(iter);
-                       break;
-               }
-       if(iter==bline_point_list.end())
-       {
-               get_canvas_view()->get_ui_interface()->error(_("Unable to remove vertex, internal error, please report this bug"));
-       }
-
-       refresh_ducks(false);
-}
-
-void
-StateBLine_Context::popup_handle_menu(synfig::ValueNode_Const::Handle value_node)
-{
-       menu.items().clear();
-
-       BLinePoint bline_point(value_node->get_value().get(BLinePoint()));
-
-       if(bline_point.get_split_tangent_flag())
-               menu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("Merge Tangents"),
-                       sigc::bind(
-                               sigc::mem_fun(*this,&studio::StateBLine_Context::bline_attach_handle),
-                               value_node
-                       )
-               ));
-       else
-               menu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("Split Tangents"),
-                       sigc::bind(
-                               sigc::mem_fun(*this,&studio::StateBLine_Context::bline_detach_handle),
-                               value_node
-                       )
-               ));
-
-       menu.popup(0,0);
-}
-
-void
-StateBLine_Context::bline_detach_handle(synfig::ValueNode_Const::Handle value_node)
-{
-       BLinePoint bline_point(value_node->get_value().get(BLinePoint()));
-       bline_point.set_split_tangent_flag(true);
-       bline_point.set_tangent2(bline_point.get_tangent1());
-       value_node->set_value(bline_point);
-       refresh_ducks(false);
-}
-
-void
-StateBLine_Context::bline_attach_handle(synfig::ValueNode_Const::Handle value_node)
-{
-       BLinePoint bline_point(value_node->get_value().get(BLinePoint()));
-       bline_point.set_tangent1((bline_point.get_tangent1()+bline_point.get_tangent2())*0.5);
-       bline_point.set_split_tangent_flag(false);
-       value_node->set_value(bline_point);
-       refresh_ducks(false);
-}
diff --git a/synfig-studio/src/gui/state_bline.h b/synfig-studio/src/gui/state_bline.h
deleted file mode 100644 (file)
index 0f3ce0d..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/* === S Y N F I G ========================================================= */
-/*!    \file state_bline.h
-**     \brief Template Header
-**
-**     $Id$
-**
-**     \legal
-**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
-**
-**     This package is free software; you can redistribute it and/or
-**     modify it under the terms of the GNU General Public License as
-**     published by the Free Software Foundation; either version 2 of
-**     the License, or (at your option) any later version.
-**
-**     This package is distributed in the hope that it will be useful,
-**     but WITHOUT ANY WARRANTY; without even the implied warranty of
-**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-**     General Public License for more details.
-**     \endlegal
-*/
-/* ========================================================================= */
-
-/* === S T A R T =========================================================== */
-
-#ifndef __SYNFIG_STUDIO_ROTOSCOPE_BLINE_H
-#define __SYNFIG_STUDIO_ROTOSCOPE_BLINE_H
-
-/* === H E A D E R S ======================================================= */
-
-#include "smach.h"
-
-/* === M A C R O S ========================================================= */
-
-/* === T Y P E D E F S ===================================================== */
-
-/* === C L A S S E S & S T R U C T S ======================================= */
-
-namespace studio {
-
-class StateBLine_Context;
-
-class StateBLine : public Smach::state<StateBLine_Context>
-{
-public:
-       StateBLine();
-       ~StateBLine();
-}; // END of class StateBLine
-
-extern StateBLine state_bline;
-
-}; // END of namespace studio
-
-/* === E N D =============================================================== */
-
-#endif
diff --git a/synfig-studio/src/gui/state_circle.cpp b/synfig-studio/src/gui/state_circle.cpp
deleted file mode 100644 (file)
index 5ef611b..0000000
+++ /dev/null
@@ -1,1066 +0,0 @@
-/* === S Y N F I G ========================================================= */
-/*!    \file state_circle.cpp
-**     \brief Template File
-**
-**     $Id$
-**
-**     \legal
-**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
-**     Copyright (c) 2008 Chris Moore
-**
-**     This package is free software; you can redistribute it and/or
-**     modify it under the terms of the GNU General Public License as
-**     published by the Free Software Foundation; either version 2 of
-**     the License, or (at your option) any later version.
-**
-**     This package is distributed in the hope that it will be useful,
-**     but WITHOUT ANY WARRANTY; without even the implied warranty of
-**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-**     General Public License for more details.
-**     \endlegal
-*/
-/* ========================================================================= */
-
-/* === H E A D E R S ======================================================= */
-
-#ifdef USING_PCH
-#      include "pch.h"
-#else
-#ifdef HAVE_CONFIG_H
-#      include <config.h>
-#endif
-
-#include <gtkmm/dialog.h>
-#include <gtkmm/entry.h>
-
-#include <synfig/valuenode_dynamiclist.h>
-#include <synfigapp/action_system.h>
-#include <synfig/valuenode_bline.h>
-
-#include "state_circle.h"
-#include "state_normal.h"
-#include "canvasview.h"
-#include "workarea.h"
-#include "app.h"
-
-#include <synfigapp/action.h>
-#include "event_mouse.h"
-#include "event_layerclick.h"
-#include "toolbox.h"
-#include "dialog_tooloptions.h"
-#include <gtkmm/optionmenu.h>
-#include "duck.h"
-#include "widgets/widget_enum.h"
-#include <synfigapp/main.h>
-
-#include "general.h"
-
-#endif
-
-/* === U S I N G =========================================================== */
-
-using namespace std;
-using namespace etl;
-using namespace synfig;
-using namespace studio;
-
-/* === M A C R O S ========================================================= */
-enum CircleFalloff
-{
-       CIRCLE_SQUARED  =0,
-       CIRCLE_INTERPOLATION_LINEAR     =1,
-       CIRCLE_COSINE   =2,
-       CIRCLE_SIGMOND  =3,
-       CIRCLE_SQRT             =4,
-       CIRCLE_NUM_FALLOFF
-};
-
-/* === G L O B A L S ======================================================= */
-
-StateCircle studio::state_circle;
-
-/* === C L A S S E S & S T R U C T S ======================================= */
-
-class studio::StateCircle_Context : public sigc::trackable
-{
-       etl::handle<CanvasView> canvas_view_;
-       CanvasView::IsWorking is_working;
-
-       Duckmatic::Push duckmatic_push;
-
-       Point point_holder;
-
-       etl::handle<Duck> point2_duck;
-
-       void refresh_ducks();
-
-       bool prev_workarea_layer_status_;
-
-       //Toolbox settings
-       synfigapp::Settings& settings;
-
-       //Toolbox display
-       Gtk::Table options_table;
-
-       Gtk::Entry              entry_id; //what to name the layer
-
-       Widget_Enum             enum_falloff;
-#ifdef BLEND_METHOD_IN_TOOL_OPTIONS
-       Widget_Enum             enum_blend;
-#endif // BLEND_METHOD_IN_TOOL_OPTIONS
-
-       Gtk::Adjustment adj_feather;
-       Gtk::Adjustment adj_number_of_bline_points;
-       Gtk::Adjustment adj_bline_point_angle_offset;
-       Gtk::SpinButton spin_feather;
-       Gtk::SpinButton spin_number_of_bline_points;
-       Gtk::SpinButton spin_bline_point_angle_offset;
-
-       Gtk::CheckButton checkbutton_invert;
-       Gtk::CheckButton checkbutton_layer_circle;
-       Gtk::CheckButton checkbutton_layer_region;
-       Gtk::CheckButton checkbutton_layer_outline;
-       Gtk::CheckButton checkbutton_layer_curve_gradient;
-       Gtk::CheckButton checkbutton_layer_plant;
-       Gtk::CheckButton checkbutton_layer_link_origins;
-       Gtk::CheckButton checkbutton_layer_origins_at_center;
-
-public:
-
-       // this only counts the layers which will have their origins linked
-       int layers_to_create()const
-       {
-               return
-                       (get_layer_circle_flag() && get_layer_origins_at_center_flag()) +
-                       get_layer_region_flag() +
-                       get_layer_outline_flag() +
-                       get_layer_curve_gradient_flag() +
-                       get_layer_plant_flag();
-       }
-
-       synfig::String get_id()const { return entry_id.get_text(); }
-       void set_id(const synfig::String& x) { return entry_id.set_text(x); }
-
-       int get_falloff()const { return enum_falloff.get_value(); }
-       void set_falloff(int x) { return enum_falloff.set_value(x); }
-
-#ifdef BLEND_METHOD_IN_TOOL_OPTIONS
-       int get_blend()const { return enum_blend.get_value(); }
-       void set_blend(int x) { return enum_blend.set_value(x); }
-#endif // BLEND_METHOD_IN_TOOL_OPTIONS
-
-       Real get_feather()const { return adj_feather.get_value(); }
-       void set_feather(Real f) { adj_feather.set_value(f); }
-
-       Real get_number_of_bline_points()const { return adj_number_of_bline_points.get_value(); }
-       void set_number_of_bline_points(Real f) { adj_number_of_bline_points.set_value(f); }
-
-       Real get_bline_point_angle_offset()const { return adj_bline_point_angle_offset.get_value(); }
-       void set_bline_point_angle_offset(Real f) { adj_bline_point_angle_offset.set_value(f); }
-
-       bool get_invert()const { return checkbutton_invert.get_active(); }
-       void set_invert(bool i) { checkbutton_invert.set_active(i); }
-
-       bool get_layer_circle_flag()const { return checkbutton_layer_circle.get_active(); }
-       void set_layer_circle_flag(bool x) { return checkbutton_layer_circle.set_active(x); }
-
-       bool get_layer_region_flag()const { return checkbutton_layer_region.get_active(); }
-       void set_layer_region_flag(bool x) { return checkbutton_layer_region.set_active(x); }
-
-       bool get_layer_outline_flag()const { return checkbutton_layer_outline.get_active(); }
-       void set_layer_outline_flag(bool x) { return checkbutton_layer_outline.set_active(x); }
-
-       bool get_layer_curve_gradient_flag()const { return checkbutton_layer_curve_gradient.get_active(); }
-       void set_layer_curve_gradient_flag(bool x) { return checkbutton_layer_curve_gradient.set_active(x); }
-
-       bool get_layer_plant_flag()const { return checkbutton_layer_plant.get_active(); }
-       void set_layer_plant_flag(bool x) { return checkbutton_layer_plant.set_active(x); }
-
-       bool get_layer_link_origins_flag()const { return checkbutton_layer_link_origins.get_active(); }
-       void set_layer_link_origins_flag(bool x) { return checkbutton_layer_link_origins.set_active(x); }
-
-       bool get_layer_origins_at_center_flag()const { return checkbutton_layer_origins_at_center.get_active(); }
-       void set_layer_origins_at_center_flag(bool x) { return checkbutton_layer_origins_at_center.set_active(x); }
-
-       void refresh_tool_options(); //to refresh the toolbox
-
-       //events
-       Smach::event_result event_stop_handler(const Smach::event& x);
-       Smach::event_result event_refresh_handler(const Smach::event& x);
-       Smach::event_result event_mouse_click_handler(const Smach::event& x);
-       Smach::event_result event_refresh_tool_options(const Smach::event& x);
-
-       //constructor destructor
-       StateCircle_Context(CanvasView* canvas_view);
-       ~StateCircle_Context();
-
-       //Canvas interaction
-       const etl::handle<CanvasView>& get_canvas_view()const{return canvas_view_;}
-       etl::handle<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view_->canvas_interface();}
-       synfig::Canvas::Handle get_canvas()const{return canvas_view_->get_canvas();}
-       WorkArea * get_work_area()const{return canvas_view_->get_work_area();}
-
-       //Modifying settings etc.
-       void load_settings();
-       void save_settings();
-       void reset();
-       void increment_id();
-       bool egress_on_selection_change;
-       Smach::event_result event_layer_selection_changed_handler(const Smach::event& /*x*/)
-       {
-               if(egress_on_selection_change)
-                       throw &state_normal; //throw Smach::egress_exception();
-               return Smach::RESULT_OK;
-       }
-
-       void make_circle(const Point& p1, const Point& p2);
-
-};     // END of class StateCircle_Context
-
-/* === M E T H O D S ======================================================= */
-
-StateCircle::StateCircle():
-       Smach::state<StateCircle_Context>("circle")
-{
-       insert(event_def(EVENT_LAYER_SELECTION_CHANGED,&StateCircle_Context::event_layer_selection_changed_handler));
-       insert(event_def(EVENT_STOP,&StateCircle_Context::event_stop_handler));
-       insert(event_def(EVENT_REFRESH,&StateCircle_Context::event_refresh_handler));
-       insert(event_def(EVENT_REFRESH_DUCKS,&StateCircle_Context::event_refresh_handler));
-       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateCircle_Context::event_mouse_click_handler));
-       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DRAG,&StateCircle_Context::event_mouse_click_handler));
-       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_UP,&StateCircle_Context::event_mouse_click_handler));
-       insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateCircle_Context::event_refresh_tool_options));
-}
-
-StateCircle::~StateCircle()
-{
-}
-
-void
-StateCircle_Context::load_settings()
-{
-       String value;
-
-       //parse the arguments yargh!
-       if(settings.get_value("circle.id",value))
-               set_id(value);
-       else
-               set_id("Circle");
-
-       if(settings.get_value("circle.fallofftype",value) && value != "")
-               set_falloff(atoi(value.c_str()));
-       else
-               set_falloff(2);
-
-#ifdef BLEND_METHOD_IN_TOOL_OPTIONS
-       if(settings.get_value("circle.blend",value) && value != "")
-               set_blend(atoi(value.c_str()));
-       else
-               set_blend(0);//(int)Color::BLEND_COMPOSITE); //0 should be blend composites value
-#endif // BLEND_METHOD_IN_TOOL_OPTIONS
-
-       if(settings.get_value("circle.feather",value))
-               set_feather(atof(value.c_str()));
-       else
-               set_feather(0);
-
-       if(settings.get_value("circle.number_of_bline_points",value))
-               set_number_of_bline_points(atof(value.c_str()));
-       else
-               set_number_of_bline_points(4);
-
-       if(settings.get_value("circle.bline_point_angle_offset",value))
-               set_bline_point_angle_offset(atof(value.c_str()));
-       else
-               set_bline_point_angle_offset(0);
-
-       if(settings.get_value("circle.invert",value) && value != "0")
-               set_invert(true);
-       else
-               set_invert(false);
-
-       if(settings.get_value("circle.layer_circle",value) && value=="0")
-               set_layer_circle_flag(false);
-       else
-               set_layer_circle_flag(true);
-
-       if(settings.get_value("circle.layer_region",value) && value=="1")
-               set_layer_region_flag(true);
-       else
-               set_layer_region_flag(false);
-
-       if(settings.get_value("circle.layer_outline",value) && value=="1")
-               set_layer_outline_flag(true);
-       else
-               set_layer_outline_flag(false);
-
-       if(settings.get_value("circle.layer_curve_gradient",value) && value=="1")
-               set_layer_curve_gradient_flag(true);
-       else
-               set_layer_curve_gradient_flag(false);
-
-       if(settings.get_value("circle.layer_plant",value) && value=="1")
-               set_layer_plant_flag(true);
-       else
-               set_layer_plant_flag(false);
-
-       if(settings.get_value("circle.layer_link_origins",value) && value=="0")
-               set_layer_link_origins_flag(false);
-       else
-               set_layer_link_origins_flag(true);
-
-       if(settings.get_value("circle.layer_origins_at_center",value) && value=="0")
-               set_layer_origins_at_center_flag(false);
-       else
-               set_layer_origins_at_center_flag(true);
-}
-
-void
-StateCircle_Context::save_settings()
-{
-       settings.set_value("circle.id",get_id());
-       settings.set_value("circle.fallofftype",strprintf("%d",get_falloff()));
-#ifdef BLEND_METHOD_IN_TOOL_OPTIONS
-       settings.set_value("circle.blend",strprintf("%d",get_blend()));
-#endif // BLEND_METHOD_IN_TOOL_OPTIONS
-       settings.set_value("circle.feather",strprintf("%f",(float)get_feather()));
-       settings.set_value("circle.number_of_bline_points",strprintf("%d",(int)(get_number_of_bline_points() + 0.5)));
-       settings.set_value("circle.bline_point_angle_offset",strprintf("%f",(float)get_bline_point_angle_offset()));
-       settings.set_value("circle.invert",get_invert()?"1":"0");
-       settings.set_value("circle.layer_circle",get_layer_circle_flag()?"1":"0");
-       settings.set_value("circle.layer_outline",get_layer_outline_flag()?"1":"0");
-       settings.set_value("circle.layer_region",get_layer_region_flag()?"1":"0");
-       settings.set_value("circle.layer_curve_gradient",get_layer_curve_gradient_flag()?"1":"0");
-       settings.set_value("circle.layer_plant",get_layer_plant_flag()?"1":"0");
-       settings.set_value("circle.layer_link_origins",get_layer_link_origins_flag()?"1":"0");
-       settings.set_value("circle.layer_origins_at_center",get_layer_origins_at_center_flag()?"1":"0");
-}
-
-void
-StateCircle_Context::reset()
-{
-       refresh_ducks();
-}
-
-void
-StateCircle_Context::increment_id()
-{
-       String id(get_id());
-       int number=1;
-       int digits=0;
-
-       if(id.empty())
-               id="Circle";
-
-       // If there is a number
-       // already at the end of the
-       // id, then remove it.
-       if(id[id.size()-1]<='9' && id[id.size()-1]>='0')
-       {
-               // figure out how many digits it is
-               for (digits = 0;
-                        (int)id.size()-1 >= digits && id[id.size()-1-digits] <= '9' && id[id.size()-1-digits] >= '0';
-                        digits++)
-                       ;
-
-               String str_number;
-               str_number=String(id,id.size()-digits,id.size());
-               id=String(id,0,id.size()-digits);
-
-               number=atoi(str_number.c_str());
-       }
-       else
-       {
-               number=1;
-               digits=3;
-       }
-
-       number++;
-
-       // Add the number back onto the id
-       {
-               const String format(strprintf("%%0%dd",digits));
-               id+=strprintf(format.c_str(),number);
-       }
-
-       // Set the ID
-       set_id(id);
-}
-
-StateCircle_Context::StateCircle_Context(CanvasView* canvas_view):
-       canvas_view_(canvas_view),
-       is_working(*canvas_view),
-       duckmatic_push(get_work_area()),
-       prev_workarea_layer_status_(get_work_area()->get_allow_layer_clicks()),
-       settings(synfigapp::Main::get_selected_input_device()->settings()),
-       entry_id(),                             //   value lower upper  step page
-       adj_feather(                                    0,    0,    1, 0.01, 0.1),
-       adj_number_of_bline_points(             0,    2,  120, 1   , 1  ),
-       adj_bline_point_angle_offset(   0, -360,  360, 0.1 , 1  ),
-       spin_feather(adj_feather,0.1,3),
-       spin_number_of_bline_points(adj_number_of_bline_points,1,0),
-       spin_bline_point_angle_offset(adj_bline_point_angle_offset,1,1),
-       checkbutton_invert(_("Invert")),
-       checkbutton_layer_circle(_("Create Circle Layer")),
-       checkbutton_layer_region(_("Create Region BLine")),
-       checkbutton_layer_outline(_("Create Outline BLine")),
-       checkbutton_layer_curve_gradient(_("Create Curve Gradient BLine")),
-       checkbutton_layer_plant(_("Create Plant BLine")),
-       checkbutton_layer_link_origins(_("Link Origins")),
-       checkbutton_layer_origins_at_center(_("BLine Origins at Center"))
-{
-       egress_on_selection_change=true;
-
-       // Set up the tool options dialog
-       enum_falloff.set_param_desc(ParamDesc("falloff")
-               .set_local_name(_("Falloff"))
-               .set_description(_("Determines the falloff function for the feather"))
-               .set_hint("enum")
-               .add_enum_value(CIRCLE_INTERPOLATION_LINEAR,"linear",_("Linear"))
-               .add_enum_value(CIRCLE_SQUARED,"squared",_("Squared"))
-               .add_enum_value(CIRCLE_SQRT,"sqrt",_("Square Root"))
-               .add_enum_value(CIRCLE_SIGMOND,"sigmond",_("Sigmond"))
-               .add_enum_value(CIRCLE_COSINE,"cosine",_("Cosine")));
-
-#ifdef BLEND_METHOD_IN_TOOL_OPTIONS
-       enum_blend.set_param_desc(ParamDesc(Color::BLEND_COMPOSITE,"blend_method")
-               .set_local_name(_("Blend Method"))
-               .set_description(_("Defines the blend method to be used for circles")));
-#endif // BLEND_METHOD_IN_TOOL_OPTIONS
-
-       load_settings();
-
-       options_table.attach(*manage(new Gtk::Label(_("Circle Tool"))),         0, 2,  0,  1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(entry_id,                                                                          0, 2,  1,  2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-
-       options_table.attach(checkbutton_layer_circle,                                          0, 2,  2,  3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(checkbutton_layer_outline,                                         0, 2,  3,  4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(checkbutton_layer_region,                                          0, 2,  4,  5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(checkbutton_layer_plant,                                           0, 2,  5,  6, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(checkbutton_layer_curve_gradient,                          0, 2,  6,  7, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(checkbutton_layer_link_origins,                            0, 2,  7,  8, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(checkbutton_layer_origins_at_center,                       0, 2,  8,  9, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-
-       //invert flag
-       options_table.attach(checkbutton_invert,                                                0, 2,  9, 10, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-
-       options_table.attach(*manage(new Gtk::Label(_("Falloff:"))),            0, 1, 10, 11, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(enum_falloff,                                      1, 2, 10, 11, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-
-       //feather stuff
-       options_table.attach(*manage(new Gtk::Label(_("Feather:"))),            0, 1, 11, 12, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(spin_feather,                                                              1, 2, 11, 12, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-
-#ifdef BLEND_METHOD_IN_TOOL_OPTIONS
-       options_table.attach(enum_blend,                                        0, 2, 12, 13, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-#endif // BLEND_METHOD_IN_TOOL_OPTIONS
-
-       options_table.attach(*manage(new Gtk::Label(_("BLine Points:"))),       0, 1, 13, 14, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(spin_number_of_bline_points,                                       1, 2, 13, 14, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-
-options_table.attach(*manage(new Gtk::Label(_("Point Angle Offset:"))),        0, 1, 14, 15, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(spin_bline_point_angle_offset,                                     1, 2, 14, 15, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-
-       options_table.show_all();
-
-       refresh_tool_options();
-       App::dialog_tool_options->present();
-
-       // Turn off layer clicking
-       get_work_area()->set_allow_layer_clicks(false);
-
-       // clear out the ducks
-       get_work_area()->clear_ducks();
-
-       // Refresh the work area
-       get_work_area()->queue_draw();
-
-       // Hide the tables if they are showing
-       //prev_table_status=get_canvas_view()->tables_are_visible();
-       //if(prev_table_status)get_canvas_view()->hide_tables();
-
-       // Disable the time bar
-       //get_canvas_view()->set_sensitive_timebar(false);
-
-       // Connect a signal
-       //get_work_area()->signal_user_click().connect(sigc::mem_fun(*this,&studio::StateCircle_Context::on_user_click));
-       get_work_area()->set_cursor(Gdk::CROSSHAIR);
-
-       App::toolbox->refresh();
-}
-
-void
-StateCircle_Context::refresh_tool_options()
-{
-       App::dialog_tool_options->clear();
-       App::dialog_tool_options->set_widget(options_table);
-       App::dialog_tool_options->set_local_name(_("Circle Tool"));
-       App::dialog_tool_options->set_name("circle");
-}
-
-Smach::event_result
-StateCircle_Context::event_refresh_tool_options(const Smach::event& /*x*/)
-{
-       refresh_tool_options();
-       return Smach::RESULT_ACCEPT;
-}
-
-StateCircle_Context::~StateCircle_Context()
-{
-       save_settings();
-
-       // Restore layer clicking
-       get_work_area()->set_allow_layer_clicks(prev_workarea_layer_status_);
-       get_work_area()->reset_cursor();
-
-       App::dialog_tool_options->clear();
-
-       // Enable the time bar
-       //get_canvas_view()->set_sensitive_timebar(true);
-
-       // Bring back the tables if they were out before
-       //if(prev_table_status)get_canvas_view()->show_tables();
-
-       // Refresh the work area
-       get_work_area()->queue_draw();
-
-       get_canvas_view()->queue_rebuild_ducks();
-
-       App::toolbox->refresh();
-}
-
-Smach::event_result
-StateCircle_Context::event_stop_handler(const Smach::event& /*x*/)
-{
-       //throw Smach::egress_exception();
-       throw &state_normal;
-       return Smach::RESULT_OK;
-}
-
-Smach::event_result
-StateCircle_Context::event_refresh_handler(const Smach::event& /*x*/)
-{
-       refresh_ducks();
-       return Smach::RESULT_ACCEPT;
-}
-
-void
-StateCircle_Context::make_circle(const Point& _p1, const Point& _p2)
-{
-       synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("New Circle"));
-       synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
-
-       Layer::Handle layer;
-
-       Canvas::Handle canvas;
-       int depth(0);
-
-       // we are temporarily using the layer to hold something
-       layer=get_canvas_view()->get_selection_manager()->get_selected_layer();
-       if(layer)
-       {
-               depth=layer->get_depth();
-               canvas=layer->get_canvas();
-       }
-
-       synfigapp::SelectionManager::LayerList layer_selection;
-       if (!getenv("SYNFIG_TOOLS_CLEAR_SELECTION"))
-               layer_selection = get_canvas_view()->get_selection_manager()->get_selected_layers();
-
-       const synfig::TransformStack& transform(get_canvas_view()->get_curr_transform_stack());
-       const Point p1(transform.unperform(_p1));
-       const Point p2(transform.unperform(_p2));
-
-       Real radius((p2-p1).mag());
-       int points = get_number_of_bline_points();
-       Angle::deg offset(get_bline_point_angle_offset());
-       Angle::deg angle(360.0/points);
-       Real tangent(4 * ((points == 2)
-                                         ? 1
-                                         : ((2 * Angle::cos(angle/2).get() - Angle::cos(angle).get() - 1) / Angle::sin(angle).get())));
-       Vector origin;
-       Real x, y;
-
-       if (get_layer_origins_at_center_flag())
-       {
-               x = y = 0;
-               origin = p1;
-       }
-       else
-       {
-               x = p1[0];
-               y = p1[1];
-       }
-
-       std::vector<BLinePoint> new_list;
-       for (int i = 0; i < points; i++)
-       {
-               new_list.push_back(*(new BLinePoint));
-               new_list[i].set_width(1);
-               new_list[i].set_vertex(Point(radius*Angle::cos(angle*i + offset).get() + x,
-                                                                        radius*Angle::sin(angle*i + offset).get() + y));
-               new_list[i].set_tangent(Point(-radius*tangent*Angle::sin(angle*i + offset).get(),
-                                                                          radius*tangent*Angle::cos(angle*i + offset).get()));
-       }
-
-       ValueNode_BLine::Handle value_node_bline(ValueNode_BLine::create(new_list));
-       assert(value_node_bline);
-
-       ValueNode_Const::Handle value_node_origin(ValueNode_Const::create(origin));
-       assert(value_node_origin);
-
-       // Set the looping flag
-       value_node_bline->set_loop(true);
-
-       if(!canvas)
-               canvas=get_canvas_view()->get_canvas();
-
-       value_node_bline->set_member_canvas(canvas);
-
-       // count how many layers we're going to be creating
-       int layers_to_create = this->layers_to_create();
-
-       ///////////////////////////////////////////////////////////////////////////
-       //   C I R C L E
-       ///////////////////////////////////////////////////////////////////////////
-
-       if (get_layer_circle_flag() &&
-               get_falloff() >= 0 && get_falloff() < CIRCLE_NUM_FALLOFF)
-       {
-               layer=get_canvas_interface()->add_layer_to("circle",canvas,depth);
-               if (!layer)
-               {
-                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
-                       group.cancel();
-                       return;
-               }
-               layer_selection.push_back(layer);
-
-               layer->set_param("radius",(p2-p1).mag());
-               get_canvas_interface()->signal_layer_param_changed()(layer,"radius");
-
-               layer->set_param("falloff",get_falloff());
-               get_canvas_interface()->signal_layer_param_changed()(layer,"falloff");
-
-               layer->set_param("feather",get_feather());
-               get_canvas_interface()->signal_layer_param_changed()(layer,"feather");
-
-               layer->set_param("invert",get_invert());
-               get_canvas_interface()->signal_layer_param_changed()(layer,"invert");
-
-#ifdef BLEND_METHOD_IN_TOOL_OPTIONS
-               layer->set_param("blend_method",get_blend());
-               get_canvas_interface()->signal_layer_param_changed()(layer,"blend_method");
-#endif // BLEND_METHOD_IN_TOOL_OPTIONS
-
-               layer->set_description(get_id());
-               get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
-
-               // only link the circle's origin parameter if the option is selected, we're putting bline
-               // origins at their centers, and we're creating more than one layer
-               if (get_layer_link_origins_flag() && get_layer_origins_at_center_flag() && layers_to_create > 1)
-               {
-                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
-                       assert(action);
-
-                       action->set_param("canvas",get_canvas());
-                       action->set_param("canvas_interface",get_canvas_interface());
-                       action->set_param("layer",layer);
-                       if(!action->set_param("param",String("origin")))
-                               synfig::error("LayerParamConnect didn't like \"param\"");
-                       if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
-                               synfig::error("LayerParamConnect didn't like \"value_node\"");
-
-                       if(!get_canvas_interface()->get_instance()->perform_action(action))
-                       {
-                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create Circle layer"));
-                               group.cancel();
-                               throw String(_("Unable to create Circle layer"));
-                               return;
-                       }
-               }
-               else
-               {
-                       layer->set_param("origin",p1);
-                       get_canvas_interface()->signal_layer_param_changed()(layer,"origin");
-               }
-       }
-
-       ///////////////////////////////////////////////////////////////////////////
-       //   C U R V E   G R A D I E N T
-       ///////////////////////////////////////////////////////////////////////////
-
-       if(get_layer_curve_gradient_flag())
-       {
-               synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
-
-               Layer::Handle layer(get_canvas_interface()->add_layer_to("curve_gradient",canvas,depth));
-               if (!layer)
-               {
-                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
-                       group.cancel();
-                       return;
-               }
-               layer_selection.push_back(layer);
-               layer->set_description(get_id()+_(" Gradient"));
-               get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
-
-#ifdef BLEND_METHOD_IN_TOOL_OPTIONS
-               layer->set_param("blend_method",get_blend());
-               get_canvas_interface()->signal_layer_param_changed()(layer,"blend_method");
-#endif // BLEND_METHOD_IN_TOOL_OPTIONS
-
-               {
-                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
-                       assert(action);
-
-                       action->set_param("canvas",get_canvas());
-                       action->set_param("canvas_interface",get_canvas_interface());
-                       action->set_param("layer",layer);
-                       if(!action->set_param("param",String("bline")))
-                               synfig::error("LayerParamConnect didn't like \"param\"");
-                       if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
-                               synfig::error("LayerParamConnect didn't like \"value_node\"");
-
-                       if(!get_canvas_interface()->get_instance()->perform_action(action))
-                       {
-                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
-                               group.cancel();
-                               throw String(_("Unable to create Gradient layer"));
-                               return;
-                       }
-               }
-
-               // only link the curve gradient's origin parameter if the option is selected and we're creating more than one layer
-               if (get_layer_link_origins_flag() && layers_to_create > 1)
-               {
-                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
-                       assert(action);
-
-                       action->set_param("canvas",get_canvas());
-                       action->set_param("canvas_interface",get_canvas_interface());
-                       action->set_param("layer",layer);
-                       if(!action->set_param("param",String("origin")))
-                               synfig::error("LayerParamConnect didn't like \"param\"");
-                       if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
-                               synfig::error("LayerParamConnect didn't like \"value_node\"");
-
-                       if(!get_canvas_interface()->get_instance()->perform_action(action))
-                       {
-                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
-                               group.cancel();
-                               throw String(_("Unable to create Gradient layer"));
-                               return;
-                       }
-               }
-               else
-               {
-                       layer->set_param("origin",origin);
-                       get_canvas_interface()->signal_layer_param_changed()(layer,"origin");
-               }
-       }
-
-       ///////////////////////////////////////////////////////////////////////////
-       //   P L A N T
-       ///////////////////////////////////////////////////////////////////////////
-
-       if(get_layer_plant_flag())
-       {
-               synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
-
-               Layer::Handle layer(get_canvas_interface()->add_layer_to("plant",canvas,depth));
-               if (!layer)
-               {
-                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
-                       group.cancel();
-                       return;
-               }
-               layer_selection.push_back(layer);
-               layer->set_description(get_id()+_(" Plant"));
-               get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
-
-#ifdef BLEND_METHOD_IN_TOOL_OPTIONS
-               layer->set_param("blend_method",get_blend());
-               get_canvas_interface()->signal_layer_param_changed()(layer,"blend_method");
-#endif // BLEND_METHOD_IN_TOOL_OPTIONS
-
-               {
-                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
-                       assert(action);
-
-                       action->set_param("canvas",get_canvas());
-                       action->set_param("canvas_interface",get_canvas_interface());
-                       action->set_param("layer",layer);
-                       if(!action->set_param("param",String("bline")))
-                               synfig::error("LayerParamConnect didn't like \"param\"");
-                       if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
-                               synfig::error("LayerParamConnect didn't like \"value_node\"");
-
-                       if(!get_canvas_interface()->get_instance()->perform_action(action))
-                       {
-                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
-                               group.cancel();
-                               throw String(_("Unable to create Plant layer"));
-                               return;
-                       }
-               }
-
-               // only link the plant's origin parameter if the option is selected and we're creating more than one layer
-               if (get_layer_link_origins_flag() && layers_to_create > 1)
-               {
-                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
-                       assert(action);
-
-                       action->set_param("canvas",get_canvas());
-                       action->set_param("canvas_interface",get_canvas_interface());
-                       action->set_param("layer",layer);
-                       if(!action->set_param("param",String("origin")))
-                               synfig::error("LayerParamConnect didn't like \"param\"");
-                       if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
-                               synfig::error("LayerParamConnect didn't like \"value_node\"");
-
-                       if(!get_canvas_interface()->get_instance()->perform_action(action))
-                       {
-                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
-                               group.cancel();
-                               throw String(_("Unable to create Plant layer"));
-                               return;
-                       }
-               }
-               else
-               {
-                       layer->set_param("origin",origin);
-                       get_canvas_interface()->signal_layer_param_changed()(layer,"origin");
-               }
-       }
-
-       ///////////////////////////////////////////////////////////////////////////
-       //   R E G I O N
-       ///////////////////////////////////////////////////////////////////////////
-
-       if(get_layer_region_flag())
-       {
-               synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
-
-               Layer::Handle layer(get_canvas_interface()->add_layer_to("region",canvas,depth));
-               if (!layer)
-               {
-                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
-                       group.cancel();
-                       return;
-               }
-               layer_selection.push_back(layer);
-               layer->set_description(get_id()+_(" Region"));
-               get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
-
-#ifdef BLEND_METHOD_IN_TOOL_OPTIONS
-               layer->set_param("blend_method",get_blend());
-               get_canvas_interface()->signal_layer_param_changed()(layer,"blend_method");
-#endif // BLEND_METHOD_IN_TOOL_OPTIONS
-
-               layer->set_param("feather",get_feather());
-               get_canvas_interface()->signal_layer_param_changed()(layer,"feather");
-
-               layer->set_param("invert",get_invert());
-               get_canvas_interface()->signal_layer_param_changed()(layer,"invert");
-
-               // I don't know if it's safe to reuse the same LayerParamConnect action, so I'm
-               // using 2 separate ones.
-               {
-                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
-                       assert(action);
-
-                       action->set_param("canvas",get_canvas());
-                       action->set_param("canvas_interface",get_canvas_interface());
-                       action->set_param("layer",layer);
-                       if(!action->set_param("param",String("bline")))
-                               synfig::error("LayerParamConnect didn't like \"param\"");
-                       if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
-                               synfig::error("LayerParamConnect didn't like \"value_node\"");
-
-                       if(!get_canvas_interface()->get_instance()->perform_action(action))
-                       {
-                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer"));
-                               group.cancel();
-                               throw String(_("Unable to create Region layer"));
-                               return;
-                       }
-               }
-
-               // only link the region's origin parameter if the option is selected and we're creating more than one layer
-               if (get_layer_link_origins_flag() && layers_to_create > 1)
-               {
-                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
-                       assert(action);
-
-                       action->set_param("canvas",get_canvas());
-                       action->set_param("canvas_interface",get_canvas_interface());
-                       action->set_param("layer",layer);
-                       if(!action->set_param("param",String("origin")))
-                               synfig::error("LayerParamConnect didn't like \"param\"");
-                       if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
-                               synfig::error("LayerParamConnect didn't like \"value_node\"");
-
-                       if(!get_canvas_interface()->get_instance()->perform_action(action))
-                       {
-                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer"));
-                               group.cancel();
-                               throw String(_("Unable to create Region layer"));
-                               return;
-                       }
-               }
-               else
-               {
-                       layer->set_param("origin",origin);
-                       get_canvas_interface()->signal_layer_param_changed()(layer,"origin");
-               }
-       }
-
-       ///////////////////////////////////////////////////////////////////////////
-       //   O U T L I N E
-       ///////////////////////////////////////////////////////////////////////////
-
-       if (get_layer_outline_flag())
-       {
-               Layer::Handle layer(get_canvas_interface()->add_layer_to("outline",canvas,depth));
-               if (!layer)
-               {
-                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
-                       group.cancel();
-                       return;
-               }
-               layer_selection.push_back(layer);
-               layer->set_description(get_id()+_(" Outline"));
-               get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
-
-#ifdef BLEND_METHOD_IN_TOOL_OPTIONS
-               layer->set_param("blend_method",get_blend());
-               get_canvas_interface()->signal_layer_param_changed()(layer,"blend_method");
-#endif // BLEND_METHOD_IN_TOOL_OPTIONS
-
-               layer->set_param("feather",get_feather());
-               get_canvas_interface()->signal_layer_param_changed()(layer,"feather");
-
-               layer->set_param("invert",get_invert());
-               get_canvas_interface()->signal_layer_param_changed()(layer,"invert");
-
-               {
-                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
-                       assert(action);
-
-                       action->set_param("canvas",get_canvas());
-                       action->set_param("canvas_interface",get_canvas_interface());
-                       action->set_param("layer",layer);
-                       if(!action->set_param("param",String("bline")))
-                               synfig::error("LayerParamConnect didn't like \"param\"");
-                       if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
-                               synfig::error("LayerParamConnect didn't like \"value_node\"");
-
-                       if(!get_canvas_interface()->get_instance()->perform_action(action))
-                       {
-                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
-                               group.cancel();
-                               throw String(_("Unable to create Outline layer"));
-                               return;
-                       }
-               }
-
-               // only link the outline's origin parameter if the option is selected and we're creating more than one layer
-               if (get_layer_link_origins_flag() && layers_to_create > 1)
-               {
-                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
-                       assert(action);
-
-                       action->set_param("canvas",get_canvas());
-                       action->set_param("canvas_interface",get_canvas_interface());
-                       action->set_param("layer",layer);
-                       if(!action->set_param("param",String("origin")))
-                               synfig::error("LayerParamConnect didn't like \"param\"");
-                       if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
-                               synfig::error("LayerParamConnect didn't like \"value_node\"");
-
-                       if(!get_canvas_interface()->get_instance()->perform_action(action))
-                       {
-                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
-                               group.cancel();
-                               throw String(_("Unable to create Outline layer"));
-                               return;
-                       }
-               }
-               else
-               {
-                       layer->set_param("origin",origin);
-                       get_canvas_interface()->signal_layer_param_changed()(layer,"origin");
-               }
-       }
-
-       egress_on_selection_change=false;
-       get_canvas_interface()->get_selection_manager()->clear_selected_layers();
-       get_canvas_interface()->get_selection_manager()->set_selected_layers(layer_selection);
-       egress_on_selection_change=true;
-
-       reset();
-       increment_id();
-}
-
-Smach::event_result
-StateCircle_Context::event_mouse_click_handler(const Smach::event& x)
-{
-       const EventMouse& event(*reinterpret_cast<const EventMouse*>(&x));
-
-       if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_DOWN && event.button==BUTTON_LEFT)
-       {
-               point_holder=get_work_area()->snap_point_to_grid(event.pos);
-               etl::handle<Duck> duck=new Duck();
-               duck->set_point(point_holder);
-               duck->set_name("p1");
-               duck->set_type(Duck::TYPE_POSITION);
-               duck->set_editable(false);
-               get_work_area()->add_duck(duck);
-
-               point2_duck=new Duck();
-               point2_duck->set_point(Vector(0,0));
-               point2_duck->set_name("radius");
-               point2_duck->set_origin(duck);
-               point2_duck->set_radius(true);
-               point2_duck->set_scalar(-1);
-               point2_duck->set_type(Duck::TYPE_RADIUS);
-               point2_duck->set_hover(true);
-               get_work_area()->add_duck(point2_duck);
-
-               return Smach::RESULT_ACCEPT;
-       }
-
-       if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_DRAG && event.button==BUTTON_LEFT)
-       {
-               if (!point2_duck) return Smach::RESULT_OK;
-               point2_duck->set_point(point_holder-get_work_area()->snap_point_to_grid(event.pos));
-               get_work_area()->queue_draw();
-               return Smach::RESULT_ACCEPT;
-       }
-
-       if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_UP && event.button==BUTTON_LEFT)
-       {
-               Point point(get_work_area()->snap_point_to_grid(event.pos));
-
-               if (App::restrict_radius_ducks)
-               {
-                       if ((point[0] - point_holder[0]) < 0) point[0] = point_holder[0];
-                       if ((point[1] - point_holder[1]) < 0) point[1] = point_holder[1];
-               }
-
-               make_circle(point_holder, point);
-               get_work_area()->clear_ducks();
-               return Smach::RESULT_ACCEPT;
-       }
-
-       return Smach::RESULT_OK;
-}
-
-
-void
-StateCircle_Context::refresh_ducks()
-{
-       get_work_area()->clear_ducks();
-       get_work_area()->queue_draw();
-}
diff --git a/synfig-studio/src/gui/state_circle.h b/synfig-studio/src/gui/state_circle.h
deleted file mode 100644 (file)
index b33ccf3..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/* === S Y N F I G ========================================================= */
-/*!    \file state_circle.h
-**     \brief Circle creation state
-**
-**     $Id$
-**
-**     \legal
-**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
-**
-**     This package is free software; you can redistribute it and/or
-**     modify it under the terms of the GNU General Public License as
-**     published by the Free Software Foundation; either version 2 of
-**     the License, or (at your option) any later version.
-**
-**     This package is distributed in the hope that it will be useful,
-**     but WITHOUT ANY WARRANTY; without even the implied warranty of
-**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-**     General Public License for more details.
-**     \endlegal
-*/
-/* ========================================================================= */
-
-/* === S T A R T =========================================================== */
-
-#ifndef __SYNFIG_STUDIO_STATE_CIRCLE_H
-#define __SYNFIG_STUDIO_STATE_CIRCLE_H
-
-/* === H E A D E R S ======================================================= */
-
-#include "smach.h"
-
-
-/* === M A C R O S ========================================================= */
-
-/* === T Y P E D E F S ===================================================== */
-
-/* === C L A S S E S & S T R U C T S ======================================= */
-
-namespace studio {
-
-class StateCircle_Context;
-
-class StateCircle : public Smach::state<StateCircle_Context>
-{
-public:
-       StateCircle();
-       ~StateCircle();
-}; // END of class StateCircle
-
-extern StateCircle state_circle;
-
-}; // END of namespace studio
-
-/* === E N D =============================================================== */
-
-#endif
diff --git a/synfig-studio/src/gui/state_draw.cpp b/synfig-studio/src/gui/state_draw.cpp
deleted file mode 100644 (file)
index 4482045..0000000
+++ /dev/null
@@ -1,2036 +0,0 @@
-/* === S Y N F I G ========================================================= */
-/*!    \file state_draw.cpp
-**     \brief Template File
-**
-**     $Id$
-**
-**     \legal
-**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
-**     Copyright (c) 2007 Chris Moore
-**     Copyright (c) 2009 Nikita Kitaev
-**
-**     This package is free software; you can redistribute it and/or
-**     modify it under the terms of the GNU General Public License as
-**     published by the Free Software Foundation; either version 2 of
-**     the License, or (at your option) any later version.
-**
-**     This package is distributed in the hope that it will be useful,
-**     but WITHOUT ANY WARRANTY; without even the implied warranty of
-**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-**     General Public License for more details.
-**     \endlegal
-*/
-/* ========================================================================= */
-
-/* === H E A D E R S ======================================================= */
-
-#ifdef USING_PCH
-#      include "pch.h"
-#else
-#ifdef HAVE_CONFIG_H
-#      include <config.h>
-#endif
-
-#include <gtkmm/dialog.h>
-#include <gtkmm/entry.h>
-
-#include <synfig/valuenode_dynamiclist.h>
-
-#include "state_draw.h"
-#include "state_stroke.h"
-#include "state_normal.h"
-#include "canvasview.h"
-#include "workarea.h"
-#include "app.h"
-#include <synfig/valuenode_bline.h>
-#include <synfig/valuenode_composite.h>
-#include <ETL/hermite>
-#include <ETL/calculus>
-#include <utility>
-#include "event_mouse.h"
-#include "event_layerclick.h"
-#include "toolbox.h"
-
-#include <synfigapp/blineconvert.h>
-#include <synfigapp/main.h>
-
-#include <ETL/gaussian>
-#include "dialog_tooloptions.h"
-
-#include <gtkmm/table.h>
-#include <gtkmm/label.h>
-#include <gtkmm/button.h>
-#include <gtkmm/checkbutton.h>
-#include <gtkmm/scale.h>
-#include <sigc++/connection.h>
-
-#include "general.h"
-
-#endif
-
-/* === U S I N G =========================================================== */
-
-using namespace std;
-using namespace etl;
-using namespace synfig;
-using namespace studio;
-
-/* === M A C R O S ========================================================= */
-
-/* === G L O B A L S ======================================================= */
-
-StateDraw studio::state_draw;
-
-/* === C L A S S E S & S T R U C T S ======================================= */
-
-class studio::StateDraw_Context : public sigc::trackable
-{
-       typedef etl::smart_ptr<std::list<synfig::Point> > StrokeData;
-       typedef etl::smart_ptr<std::list<synfig::Real> > WidthData;
-
-       typedef list< pair<StrokeData,WidthData> > StrokeQueue;
-
-       StrokeQueue stroke_queue;
-
-
-       etl::handle<CanvasView> canvas_view_;
-       CanvasView::IsWorking is_working;
-
-       bool prev_table_status;
-       bool loop_;
-       bool prev_workarea_layer_status_;
-
-       int nested;
-       sigc::connection process_queue_connection;
-
-       ValueNode_BLine::Handle last_stroke;
-       synfig::String last_stroke_id;
-
-       Gtk::Menu menu;
-
-       //Duckmatic::Push duckmatic_push;
-
-       std::list< etl::smart_ptr<std::list<synfig::Point> > > stroke_list;
-
-       void refresh_ducks();
-
-       Duckmatic::Type old_duckmask;
-
-       void fill_last_stroke();
-       Smach::event_result fill_last_stroke_and_unselect_other_layers();
-
-       Smach::event_result new_bline(std::list<synfig::BLinePoint> bline,bool loop_bline_flag,float radius);
-
-       Smach::event_result new_region(std::list<synfig::BLinePoint> bline,synfig::Real radius);
-
-       Smach::event_result extend_bline_from_begin(ValueNode_BLine::Handle value_node,std::list<synfig::BLinePoint> bline,bool complete_loop);
-       Smach::event_result extend_bline_from_end(ValueNode_BLine::Handle value_node,std::list<synfig::BLinePoint> bline,bool complete_loop);
-       void reverse_bline(std::list<synfig::BLinePoint> &bline);
-
-       synfigapp::Settings& settings;
-
-       Gtk::Table options_table;
-       Gtk::Entry entry_id;
-       Gtk::CheckButton checkbutton_pressure_width;
-       Gtk::CheckButton checkbutton_round_ends;
-       Gtk::CheckButton checkbutton_auto_loop;   // whether to loop new strokes which start and end in the same place
-       Gtk::CheckButton checkbutton_auto_extend; // whether to extend existing lines
-       Gtk::CheckButton checkbutton_auto_link;   // whether to link new ducks to existing ducks
-       Gtk::CheckButton checkbutton_region;      // whether to create regions
-       Gtk::CheckButton checkbutton_outline;     // whether to create outlines
-       Gtk::CheckButton checkbutton_auto_export;
-       Gtk::Button button_fill_last_stroke;
-
-       //pressure spinner and such
-       Gtk::Adjustment  adj_min_pressure;
-       Gtk::SpinButton  spin_min_pressure;
-       Gtk::CheckButton check_min_pressure;
-
-       Gtk::Adjustment  adj_feather;
-       Gtk::SpinButton  spin_feather;
-
-       Gtk::Adjustment  adj_globalthres;
-       Gtk::SpinButton  spin_globalthres;
-
-       Gtk::Adjustment  adj_localthres;
-       Gtk::CheckButton check_localerror;
-       void UpdateErrorBox();  //switches the stuff if need be :)
-
-       //Added by Adrian - data drive HOOOOO
-       synfigapp::BLineConverter blineconv;
-
-public:
-       synfig::String get_id()const { return entry_id.get_text(); }
-       void set_id(const synfig::String& x) { return entry_id.set_text(x); }
-
-       bool get_pressure_width_flag()const { return checkbutton_pressure_width.get_active(); }
-       void set_pressure_width_flag(bool x) { return checkbutton_pressure_width.set_active(x); }
-
-       bool get_auto_loop_flag()const { return checkbutton_auto_loop.get_active(); }
-       void set_auto_loop_flag(bool x) { return checkbutton_auto_loop.set_active(x); }
-
-       bool get_auto_extend_flag()const { return checkbutton_auto_extend.get_active(); }
-       void set_auto_extend_flag(bool x) { return checkbutton_auto_extend.set_active(x); }
-
-       bool get_auto_link_flag()const { return checkbutton_auto_link.get_active(); }
-       void set_auto_link_flag(bool x) { return checkbutton_auto_link.set_active(x); }
-
-       bool get_region_flag()const { return checkbutton_region.get_active(); }
-       void set_region_flag(bool x) { return checkbutton_region.set_active(x); }
-
-       bool get_outline_flag()const { return checkbutton_outline.get_active(); }
-       void set_outline_flag(bool x) { return checkbutton_outline.set_active(x); }
-
-       bool get_auto_export_flag()const { return checkbutton_auto_export.get_active(); }
-       void set_auto_export_flag(bool x) { return checkbutton_auto_export.set_active(x); }
-
-       Real get_min_pressure() const { return adj_min_pressure.get_value(); }
-       void set_min_pressure(Real x) { return adj_min_pressure.set_value(x); }
-
-       Real get_feather() const { return adj_feather.get_value(); }
-       void set_feather(Real x) { return adj_feather.set_value(x); }
-
-       Real get_gthres() const { return adj_globalthres.get_value(); }
-       void set_gthres(Real x) { return adj_globalthres.set_value(x); }
-
-       Real get_lthres() const { return adj_localthres.get_value(); }
-       void set_lthres(Real x) { return adj_localthres.set_value(x); }
-
-       bool get_local_error_flag() const { return check_localerror.get_active(); }
-       void set_local_error_flag(bool x) { check_localerror.set_active(x); }
-
-       bool get_min_pressure_flag()const { return check_min_pressure.get_active(); }
-       void set_min_pressure_flag(bool x) { check_min_pressure.set_active(x); }
-
-       void load_settings();
-       void save_settings();
-       void increment_id();
-
-       Smach::event_result event_stop_handler(const Smach::event& x);
-
-       Smach::event_result event_refresh_handler(const Smach::event& x);
-
-       Smach::event_result event_mouse_down_handler(const Smach::event& x);
-
-       Smach::event_result event_stroke(const Smach::event& x);
-       Smach::event_result event_refresh_tool_options(const Smach::event& x);
-       void refresh_tool_options();
-
-       Smach::event_result process_stroke(StrokeData stroke_data, WidthData width_data, bool region_flag=false);
-
-       bool process_queue();
-
-
-       StateDraw_Context(CanvasView* canvas_view);
-
-       ~StateDraw_Context();
-
-       const etl::handle<CanvasView>& get_canvas_view()const{return canvas_view_;}
-       etl::handle<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view_->canvas_interface();}
-       synfig::Time get_time()const { return get_canvas_interface()->get_time(); }
-       synfig::Canvas::Handle get_canvas()const{return canvas_view_->get_canvas();}
-       WorkArea * get_work_area()const{return canvas_view_->get_work_area();}
-
-       //void on_user_click(synfig::Point point);
-
-//     bool run();
-};     // END of class StateDraw_Context
-
-
-/* === M E T H O D S ======================================================= */
-
-StateDraw::StateDraw():
-       Smach::state<StateDraw_Context>("draw")
-{
-       insert(event_def(EVENT_STOP,&StateDraw_Context::event_stop_handler));
-       insert(event_def(EVENT_REFRESH,&StateDraw_Context::event_refresh_handler));
-       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateDraw_Context::event_mouse_down_handler));
-       insert(event_def(EVENT_WORKAREA_STROKE,&StateDraw_Context::event_stroke));
-       insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateDraw_Context::event_refresh_tool_options));
-}
-
-StateDraw::~StateDraw()
-{
-}
-
-
-void
-StateDraw_Context::load_settings()
-{
-       String value;
-
-       if(settings.get_value("draw.id",value))
-               set_id(value);
-       else
-               set_id("NewDrawing");
-
-       if(settings.get_value("draw.pressure_width",value) && value=="0")
-               set_pressure_width_flag(false);
-       else
-               set_pressure_width_flag(true);
-
-       if(settings.get_value("draw.auto_loop",value) && value=="0")
-               set_auto_loop_flag(false);
-       else
-               set_auto_loop_flag(true);
-
-       if(settings.get_value("draw.auto_extend",value) && value=="0")
-               set_auto_extend_flag(false);
-       else
-               set_auto_extend_flag(true);
-
-       if(settings.get_value("draw.auto_link",value) && value=="0")
-               set_auto_link_flag(false);
-       else
-               set_auto_link_flag(true);
-
-       if(settings.get_value("draw.region",value) && value=="0")
-               set_region_flag(false);
-       else
-               set_region_flag(true);
-
-       if(settings.get_value("draw.outline",value) && value=="0")
-               set_outline_flag(false);
-       else
-               set_outline_flag(true);
-
-       if(settings.get_value("draw.auto_export",value) && value=="1")
-               set_auto_export_flag(true);
-       else
-               set_auto_export_flag(false);
-
-       if(settings.get_value("draw.min_pressure_on",value) && value=="0")
-               set_min_pressure_flag(false);
-       else
-               set_min_pressure_flag(true);
-
-       if(settings.get_value("draw.min_pressure",value))
-       {
-               Real n = atof(value.c_str());
-               set_min_pressure(n);
-       }else
-               set_min_pressure(0);
-
-       if(settings.get_value("draw.feather",value))
-       {
-               Real n = atof(value.c_str());
-               set_feather(n);
-       }else
-               set_feather(0);
-
-       if(settings.get_value("draw.gthreshold",value))
-       {
-               Real n = atof(value.c_str());
-               set_gthres(n);
-       }
-
-       if(settings.get_value("draw.lthreshold",value))
-       {
-               Real n = atof(value.c_str());
-               set_lthres(n);
-       }
-
-       if(settings.get_value("draw.localize",value) && value == "1")
-               set_local_error_flag(true);
-       else
-               set_local_error_flag(false);
-}
-
-void
-StateDraw_Context::save_settings()
-{
-       settings.set_value("draw.id",get_id().c_str());
-       settings.set_value("draw.pressure_width",get_pressure_width_flag()?"1":"0");
-       settings.set_value("draw.auto_loop",get_auto_loop_flag()?"1":"0");
-       settings.set_value("draw.auto_extend",get_auto_extend_flag()?"1":"0");
-       settings.set_value("draw.auto_link",get_auto_link_flag()?"1":"0");
-       settings.set_value("draw.region",get_region_flag()?"1":"0");
-       settings.set_value("draw.outline",get_outline_flag()?"1":"0");
-       settings.set_value("draw.auto_export",get_auto_export_flag()?"1":"0");
-       settings.set_value("draw.min_pressure",strprintf("%f",get_min_pressure()));
-       settings.set_value("draw.feather",strprintf("%f",get_feather()));
-       settings.set_value("draw.min_pressure_on",get_min_pressure_flag()?"1":"0");
-       settings.set_value("draw.gthreshold",strprintf("%f",get_gthres()));
-       settings.set_value("draw.lthreshold",strprintf("%f",get_lthres()));
-       settings.set_value("draw.localize",get_local_error_flag()?"1":"0");
-}
-
-void
-StateDraw_Context::increment_id()
-{
-       String id(get_id());
-       int number=1;
-       int digits=0;
-
-       if(id.empty())
-               id="Drawing";
-
-       // If there is a number
-       // already at the end of the
-       // id, then remove it.
-       if(id[id.size()-1]<='9' && id[id.size()-1]>='0')
-       {
-               // figure out how many digits it is
-               for (digits = 0;
-                        (int)id.size()-1 >= digits && id[id.size()-1-digits] <= '9' && id[id.size()-1-digits] >= '0';
-                        digits++)
-                       ;
-
-               String str_number;
-               str_number=String(id,id.size()-digits,id.size());
-               id=String(id,0,id.size()-digits);
-               // synfig::info("---------------- \"%s\"",str_number.c_str());
-
-               number=atoi(str_number.c_str());
-       }
-       else
-       {
-               number=1;
-               digits=3;
-       }
-
-       number++;
-
-       // Add the number back onto the id
-       {
-               const String format(strprintf("%%0%dd",digits));
-               id+=strprintf(format.c_str(),number);
-       }
-
-       // Set the ID
-       set_id(id);
-}
-
-StateDraw_Context::StateDraw_Context(CanvasView* canvas_view):
-       canvas_view_(canvas_view),
-       is_working(*canvas_view),
-       loop_(false),
-       prev_workarea_layer_status_(get_work_area()->get_allow_layer_clicks()),
-       settings(synfigapp::Main::get_selected_input_device()->settings()),
-       entry_id(),
-       checkbutton_pressure_width(_("Pressure Width")),
-       checkbutton_auto_loop(_("Auto Loop")),
-       checkbutton_auto_extend(_("Auto Extend")),
-       checkbutton_auto_link(_("Auto Link")),
-       checkbutton_region(_("Create Region BLine")),
-       checkbutton_outline(_("Create Outline BLine")),
-       checkbutton_auto_export(_("Auto Export")),
-       button_fill_last_stroke(_("Fill Last Stroke")),
-       adj_min_pressure(0,0,1,0.01,0.1),
-       spin_min_pressure(adj_min_pressure,0.1,3),
-       check_min_pressure(_("Min Pressure")),
-       adj_feather(0,0,10000,0.01,0.1),
-       spin_feather(adj_feather,0.01,4),
-       adj_globalthres(.70f,0.01,10000,0.01,0.1),
-       spin_globalthres(adj_globalthres,0.01,3),
-       adj_localthres(20,1,100000,0.1,1),
-       check_localerror(_("LocalError"))
-
-{
-       nested=0;
-       load_settings();
-
-       UpdateErrorBox();
-
-       options_table.attach(*manage(new Gtk::Label(_("Draw Tool"))),   0, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(entry_id,                                                                  0, 2,  1,  2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(checkbutton_outline,                                               0, 2,  2,  3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(checkbutton_region,                                                0, 2,  3,  4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(checkbutton_auto_loop,                                             0, 2,  4,  5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(checkbutton_auto_extend,                                   0, 2,  5,  6, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(checkbutton_auto_link,                                             0, 2,  6,  7, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(checkbutton_auto_export,                                   0, 2,  7,  8, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(checkbutton_pressure_width,                                0, 2,  8,  9, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(check_localerror,                                                  0, 2,  9, 10, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-
-       options_table.attach(check_min_pressure,                                                0, 1, 10, 11, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(spin_min_pressure,                                                 1, 2, 10, 11, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-
-       options_table.attach(*manage(new Gtk::Label(_("Smooth"))),              0, 1, 11, 12, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(spin_globalthres,                                                  1, 2, 11, 12, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-
-       options_table.attach(*manage(new Gtk::Label(_("Feather"))),     0, 1, 12, 13, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(spin_feather,                                                              1, 2, 12, 13, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-
-       //options_table.attach(button_fill_last_stroke, 0, 2, 13, 14, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-
-       button_fill_last_stroke.signal_pressed().connect(sigc::mem_fun(*this,&StateDraw_Context::fill_last_stroke));
-       check_localerror.signal_toggled().connect(sigc::mem_fun(*this,&StateDraw_Context::UpdateErrorBox));
-
-       options_table.show_all();
-       refresh_tool_options();
-       //App::dialog_tool_options->set_widget(options_table);
-       App::dialog_tool_options->present();
-
-
-       old_duckmask=get_work_area()->get_type_mask();
-       get_work_area()->set_type_mask(Duck::TYPE_ALL-Duck::TYPE_TANGENT-Duck::TYPE_WIDTH);
-
-       // Turn off layer clicking
-       get_work_area()->set_allow_layer_clicks(false);
-
-       // Turn off duck clicking
-       get_work_area()->set_allow_duck_clicks(false);
-
-       // clear out the ducks
-       //get_work_area()->clear_ducks();
-
-       // Refresh the work area
-       //get_work_area()->queue_draw();
-
-       // Hide the tables if they are showing
-       prev_table_status=get_canvas_view()->tables_are_visible();
-       //if(prev_table_status)get_canvas_view()->hide_tables();
-
-       // Disable the time bar
-       get_canvas_view()->set_sensitive_timebar(false);
-
-       // Connect a signal
-       //get_work_area()->signal_user_click().connect(sigc::mem_fun(*this,&studio::StateDraw_Context::on_user_click));
-
-       get_work_area()->set_cursor(Gdk::PENCIL);
-
-       App::toolbox->refresh();
-
-       refresh_ducks();
-}
-
-
-void StateDraw_Context::UpdateErrorBox()
-{
-       if(get_local_error_flag())
-       {
-               spin_globalthres.set_adjustment(adj_localthres);
-               spin_globalthres.set_value(adj_localthres.get_value());
-               spin_globalthres.set_increments(0.1,1);
-       }else
-       {
-               spin_globalthres.set_adjustment(adj_globalthres);
-               spin_globalthres.set_value(adj_globalthres.get_value());
-               spin_globalthres.set_increments(0.01,.1);
-       }
-
-       spin_globalthres.update();
-}
-
-void
-StateDraw_Context::refresh_tool_options()
-{
-       App::dialog_tool_options->clear();
-       App::dialog_tool_options->set_widget(options_table);
-       App::dialog_tool_options->set_local_name(_("Draw Tool"));
-       App::dialog_tool_options->set_name("draw");
-
-       App::dialog_tool_options->add_button(
-               Gtk::StockID("synfig-fill"),
-               _("Fill Last Stroke")
-       )->signal_clicked().connect(
-               sigc::mem_fun(
-                       *this,
-                       &StateDraw_Context::fill_last_stroke));
-}
-
-Smach::event_result
-StateDraw_Context::event_refresh_tool_options(const Smach::event& /*x*/)
-{
-       refresh_tool_options();
-       return Smach::RESULT_ACCEPT;
-}
-
-StateDraw_Context::~StateDraw_Context()
-{
-       save_settings();
-
-       App::dialog_tool_options->clear();
-
-       get_work_area()->set_type_mask(old_duckmask);
-
-       get_work_area()->reset_cursor();
-
-       // Restore layer clicking
-       get_work_area()->set_allow_layer_clicks(prev_workarea_layer_status_);
-
-       // Restore duck clicking
-       get_work_area()->set_allow_duck_clicks(true);
-
-       // Enable the time bar
-       get_canvas_view()->set_sensitive_timebar(true);
-
-       // Bring back the tables if they were out before
-       if(prev_table_status)get_canvas_view()->show_tables();
-
-       // Refresh the work area
-       get_work_area()->queue_draw();
-
-       App::toolbox->refresh();
-}
-
-Smach::event_result
-StateDraw_Context::event_stop_handler(const Smach::event& /*x*/)
-{
-       //throw Smach::egress_exception();
-       throw &state_normal;
-       return Smach::RESULT_OK;
-}
-
-Smach::event_result
-StateDraw_Context::event_refresh_handler(const Smach::event& /*x*/)
-{
-       refresh_ducks();
-       return Smach::RESULT_ACCEPT;
-}
-
-Smach::event_result
-StateDraw_Context::event_mouse_down_handler(const Smach::event& x)
-{
-       const EventMouse& event(*reinterpret_cast<const EventMouse*>(&x));
-       switch(event.button)
-       {
-       case BUTTON_LEFT:
-               {
-                       // Enter the stroke state to get the stroke
-                       get_canvas_view()->get_smach().push_state(&state_stroke);
-                       return Smach::RESULT_ACCEPT;
-               }
-
-       default:
-               return Smach::RESULT_OK;
-       }
-}
-
-#define SIMILAR_TANGENT_THRESHOLD      (0.2)
-
-struct debugclass
-{
-       synfig::String x;
-       debugclass(const synfig::String &x):x(x)
-       {
-//             synfig::warning(">>>>>>>>>>>>>>>>>>> "+x);
-       }
-       ~debugclass()
-       {
-//             synfig::warning("<<<<<<<<<<<<<<<<<<< "+x);
-       }
-};
-
-struct DepthCounter
-{
-       int &i;
-       DepthCounter(int &i):i(i) { i++; }
-       ~DepthCounter() { i--; }
-};
-
-Smach::event_result
-StateDraw_Context::event_stroke(const Smach::event& x)
-{
-//     debugclass debugger("StateDraw_Context::event_stroke(const Smach::event& x)");
-
-       const EventStroke& event(*reinterpret_cast<const EventStroke*>(&x));
-
-       assert(event.stroke_data);
-
-       get_work_area()->add_stroke(event.stroke_data,synfigapp::Main::get_outline_color());
-
-       if(nested==0)
-       {
-               DirtyTrap dirty_trap(get_work_area());
-               Smach::event_result result;
-               result=process_stroke(event.stroke_data,event.width_data,event.modifier&Gdk::CONTROL_MASK || event.modifier&Gdk::BUTTON2_MASK);
-               process_queue();
-               return result;
-       }
-
-       stroke_queue.push_back(pair<StrokeData,WidthData>(event.stroke_data,event.width_data));
-
-       return Smach::RESULT_ACCEPT;
-}
-
-bool
-StateDraw_Context::process_queue()
-{
-//     debugclass debugger("StateDraw_Context::process_queue()");
-       if(nested)
-               return true;
-       DepthCounter depth_counter(nested);
-       while(!stroke_queue.empty())
-       {
-               pair<StrokeData,WidthData> front(stroke_queue.front());
-               process_stroke(front.first,front.second);
-               stroke_queue.pop_front();
-       }
-       return false;
-}
-
-Smach::event_result
-StateDraw_Context::process_stroke(StrokeData stroke_data, WidthData width_data, bool region_flag)
-{
-//     debugclass debugger("StateDraw_Context::process_stroke");
-       DepthCounter depth_counter(nested);
-
-       const float radius(synfigapp::Main::get_bline_width().units(get_canvas()->rend_desc())+(abs(get_work_area()->get_pw())+abs(get_work_area()->get_ph()))*5);
-
-
-       // If we aren't using pressure width,
-       // then set all the width to 1
-       if(!get_pressure_width_flag())
-       {
-               std::list<synfig::Real>::iterator iter;
-               for(iter=width_data->begin();iter!=width_data->end();++iter)
-               {
-                       *iter=1.0;
-               }
-       }
-
-       //get_work_area()->add_stroke(event.stroke_data,synfigapp::Main::get_outline_color());
-       //stroke_list.push_back(event.stroke_data);
-       //refresh_ducks();
-
-       std::list<synfig::BLinePoint> bline;
-       bool loop_bline_flag(false);
-
-       //Changed by Adrian - use resident class :)
-       //synfigapp::convert_stroke_to_bline(bline, *event.stroke_data,*event.width_data, synfigapp::Main::get_bline_width());
-       blineconv.width = synfigapp::Main::get_bline_width().units(get_canvas()->rend_desc());
-
-       if(get_local_error_flag())
-       {
-               float pw = get_work_area()->get_pw();
-               float ph = get_work_area()->get_ph();
-
-               blineconv.pixelwidth = sqrt(pw*pw+ph*ph);
-               blineconv.smoothness = get_lthres();
-       }else
-       {
-               blineconv.pixelwidth = 1;
-               blineconv.smoothness = get_gthres();
-       }
-
-       blineconv(bline,*stroke_data,*width_data);
-
-       //Postprocess to require minimum pressure
-       if(get_min_pressure_flag())
-       {
-               synfigapp::BLineConverter::EnforceMinWidth(bline,get_min_pressure());
-       }
-
-       // If the start and end points are similar, then make them the same point
-       if (get_auto_loop_flag() &&
-               bline.size() > 2 &&
-               (bline.front().get_vertex() - bline.back().get_vertex()).mag() <= radius)
-       {
-               loop_bline_flag=true;
-               Vector tangent;
-               Real width(0);
-
-               while (bline.size() > 2 &&
-                          (bline.front().get_vertex() - bline.back().get_vertex()).mag() <= radius)
-               {
-                       tangent=bline.back().get_tangent1();
-                       width=bline.back().get_width();
-                       bline.pop_back();
-               }
-
-               if(abs(bline.front().get_tangent1().norm()*tangent.norm().perp())>SIMILAR_TANGENT_THRESHOLD)
-               {
-                       // If the tangents are not similar, then
-                       // split the tangents
-                       bline.front().set_split_tangent_flag(true);
-                       bline.front().set_tangent1(tangent);
-               }
-               else
-               {
-                       // If the tangents are similar, then set the tangent
-                       // to the average of the two
-                       bline.front().set_tangent((tangent+bline.front().get_tangent1())*0.5f);
-               }
-
-               // Add the widths of the two points
-               {
-                       Real tmp_width(bline.front().get_width()+width);
-                       tmp_width=tmp_width<=1?tmp_width:1;
-                       bline.front().set_width(tmp_width);
-               }
-       }
-
-       // If the bline only has one blinepoint, then there is nothing to do.
-       if(bline.size() < 2)
-       {
-               // hide the 'stroke' line we were drawing, unless the user
-               // explicitly requests that they are kept
-               if (!getenv("SYNFIG_KEEP_ABORTED_DRAW_LINES"))
-                       refresh_ducks();
-
-               return Smach::RESULT_OK;
-       }
-
-       if(region_flag)
-               return new_region(bline,radius);
-
-       return new_bline(bline,loop_bline_flag,radius);
-}
-
-Smach::event_result
-StateDraw_Context::new_bline(std::list<synfig::BLinePoint> bline,bool loop_bline_flag,float radius)
-{
-       synfigapp::SelectionManager::LayerList layer_list = get_canvas_view()->get_selection_manager()->get_selected_layers();
-
-       // Create the action group
-       synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Sketch BLine"));
-
-       bool shift_origin = false;
-       Vector shift_origin_vector;
-       bool join_start_no_extend=false,join_finish_no_extend=false;
-       synfigapp::ValueDesc start_duck_value_desc,finish_duck_value_desc;
-       bool extend_start=false,extend_finish=false,complete_loop=false;
-       bool extend_start_join_same=false,extend_start_join_different=false;
-       bool extend_finish_join_same=false,extend_finish_join_different=false;
-       int start_duck_index = 0,finish_duck_index = 0; // initialized to keep the compiler happy; shouldn't be needed though
-       ValueNode_BLine::Handle start_duck_value_node_bline=NULL,finish_duck_value_node_bline=NULL;
-
-       // Find any ducks at the start or end that we might attach to
-       // (this used to only run if we didn't just draw a loop - ie. !loop_bline_flag
-       // but having loops auto-connect can be useful as well)
-       if(get_auto_extend_flag() || get_auto_link_flag())
-       {
-               etl::handle<Duck> start_duck(get_work_area()->find_duck(bline.front().get_vertex(),radius,Duck::TYPE_VERTEX));
-               etl::handle<Duck> finish_duck(get_work_area()->find_duck(bline.back().get_vertex(),radius,Duck::TYPE_VERTEX));
-
-               // check whether the start of the new line extends an
-               // existing line.  this is only the case if the new
-               // line isn't a self-contained loop, and if the new
-               // line starts at one of the ends of an existing line
-               if(start_duck)do
-               {
-                       if(!(start_duck_value_desc=start_duck->get_value_desc()))break;
-                       if(loop_bline_flag)break; // loops don't extend anything
-                       if(!start_duck_value_desc.parent_is_value_node())break;
-                       start_duck_index=start_duck_value_desc.get_index(); // which point on the line did we start drawing at
-                       start_duck_value_node_bline=ValueNode_BLine::Handle::cast_dynamic(start_duck_value_desc.get_parent_value_node());
-                       if(!get_auto_extend_flag())break;
-
-                       // don't extend looped blines
-                       if(start_duck_value_node_bline&&!start_duck_value_node_bline->get_loop()&&
-                          // did we start drawing at either end of the line?
-                          (start_duck_index==0||start_duck_index==start_duck_value_node_bline->link_count()-1))
-                       {
-                               extend_start=true;
-                               shift_origin=true;
-                               shift_origin_vector=start_duck->get_origin();
-                       }
-               }while(0);
-
-               // check whether the end of the new line extends an
-               // existing line.  this is only the case if the new
-               // line isn't a self-contained loop, and if the new
-               // line ends at one of the ends of an existing line
-               if(finish_duck)do
-               {
-                       if(!(finish_duck_value_desc=finish_duck->get_value_desc()))break;
-                       if(loop_bline_flag)break;
-                       if(!finish_duck_value_desc.parent_is_value_node())break;
-                       finish_duck_index=finish_duck_value_desc.get_index();
-                       finish_duck_value_node_bline=ValueNode_BLine::Handle::cast_dynamic(finish_duck_value_desc.get_parent_value_node());
-                       if(!get_auto_extend_flag())break;
-
-                       // don't extend looped blines
-                       if(finish_duck_value_node_bline&&!finish_duck_value_node_bline->get_loop()&&
-                          (finish_duck_index==0||finish_duck_index==finish_duck_value_node_bline->link_count()-1))
-                       {
-                               if(extend_start)
-                               {
-                                       // we've started and finished drawing at the end of a bline.  we can't
-                                       // extend both blines, so unless we started and finished at the 2 ends
-                                       // of the same bline, only extend the one we started on
-                                       if(start_duck_value_node_bline==finish_duck_value_node_bline)
-                                               complete_loop=extend_finish=true;
-                               }else{
-                                       extend_finish=true;
-                                       shift_origin=true;
-                                       shift_origin_vector=finish_duck->get_origin();
-                               }
-                       }
-               }while(0);
-
-               // if the new line's start didn't extend an existing line,
-               // check whether it needs to be linked to an existing duck
-               if(!extend_start&&get_auto_link_flag()&&start_duck&&start_duck_value_desc)
-                       switch(start_duck_value_desc.get_value_type())
-                       {
-                       case synfig::ValueBase::TYPE_BLINEPOINT:
-                               start_duck_value_desc=synfigapp::ValueDesc(LinkableValueNode::Handle::cast_dynamic(start_duck_value_desc.get_value_node()),0);
-                               // fall through
-                       case synfig::ValueBase::TYPE_VECTOR:
-                               if (shift_origin && shift_origin_vector != start_duck->get_origin())
-                                       break;
-                               shift_origin = true;
-                               shift_origin_vector = start_duck->get_origin();
-                               get_canvas_interface()->auto_export(start_duck_value_desc);
-                               if (extend_finish)
-                                       if(start_duck_value_node_bline&&start_duck_value_node_bline==finish_duck_value_node_bline)
-                                               extend_finish_join_same=true;
-                                       else
-                                               extend_finish_join_different=true;
-                               else
-                                       join_start_no_extend=true;
-                               // fall through
-                       default:break;
-                       }
-
-               // if the new line's end didn't extend an existing line,
-               // check whether it needs to be linked to an existing duck
-               if(!extend_finish&&get_auto_link_flag()&&finish_duck&&finish_duck_value_desc)
-                       switch(finish_duck_value_desc.get_value_type())
-                       {
-                       case synfig::ValueBase::TYPE_BLINEPOINT:
-                               finish_duck_value_desc=synfigapp::ValueDesc(LinkableValueNode::Handle::cast_dynamic(finish_duck_value_desc.get_value_node()),0);
-                               // fall through
-                       case synfig::ValueBase::TYPE_VECTOR:
-                               if (shift_origin && shift_origin_vector != finish_duck->get_origin())
-                                       break;
-                               shift_origin = true;
-                               shift_origin_vector = finish_duck->get_origin();
-                               get_canvas_interface()->auto_export(finish_duck_value_desc);
-                               if(extend_start)
-                                       if(finish_duck_value_node_bline&&start_duck_value_node_bline==finish_duck_value_node_bline)
-                                               extend_start_join_same=true;
-                                       else
-                                               extend_start_join_different=true;
-                               else
-                                       join_finish_no_extend=true;
-                               // fall through
-                       default:break;
-                       }
-       }
-
-       ValueNode_BLine::Handle value_node;
-       std::list<synfig::BLinePoint> trans_bline;
-
-       {
-               std::list<synfig::BLinePoint>::iterator iter;
-               const synfig::TransformStack& transform(get_canvas_view()->get_curr_transform_stack());
-
-               for(iter=bline.begin();iter!=bline.end();++iter)
-               {
-                       BLinePoint bline_point(*iter);
-                       Point new_vertex(transform.unperform(bline_point.get_vertex()));
-
-                       bline_point.set_tangent1(
-                               transform.unperform(
-                                       bline_point.get_tangent1()+bline_point.get_vertex()
-                               ) -new_vertex
-                       );
-
-                       bline_point.set_tangent2(
-                               transform.unperform(
-                                       bline_point.get_tangent2()+bline_point.get_vertex()
-                               ) -new_vertex
-                       );
-
-                       if (shift_origin)
-                               new_vertex=new_vertex-shift_origin_vector;
-
-                       bline_point.set_vertex(new_vertex);
-
-                       trans_bline.push_back(bline_point);
-               }
-               value_node=ValueNode_BLine::create(synfig::ValueBase(trans_bline,loop_bline_flag));
-
-               Canvas::Handle canvas(get_canvas_view()->get_canvas());
-               Layer::Handle layer(get_canvas_view()->get_selection_manager()->get_selected_layer());
-               if (layer) canvas=layer->get_canvas();
-               value_node->set_member_canvas(canvas);
-       }
-
-       Smach::event_result result;
-       synfig::ValueNode_DynamicList::ListEntry source;
-
-       // the new line's start extends an existing line
-       if(extend_start)
-       {
-               int target_offset = 0;
-               if(complete_loop)trans_bline.pop_back();
-               trans_bline.pop_front();
-               if(start_duck_index==0)
-               {       // We need to reverse the BLine first.
-                       reverse_bline(trans_bline);
-                       result=extend_bline_from_begin(start_duck_value_node_bline,trans_bline,complete_loop);
-                       source=start_duck_value_node_bline->list.front();
-                       target_offset=trans_bline.size();
-               }
-               else
-               {
-                       result=extend_bline_from_end(start_duck_value_node_bline,trans_bline,complete_loop);
-                       source=start_duck_value_node_bline->list.back();
-               }
-
-               if(extend_start_join_different)
-                       LinkableValueNode::Handle::cast_dynamic(source.value_node)->
-                               set_link("point",finish_duck_value_desc.get_value_node());
-               else if(extend_start_join_same)
-                       LinkableValueNode::Handle::cast_dynamic(source.value_node)->
-                               set_link("point",synfigapp::ValueDesc(LinkableValueNode::Handle::cast_dynamic(start_duck_value_node_bline->
-                                                                                                       list[target_offset+finish_duck_index].value_node),0).get_value_node());
-               return result;
-       }
-
-       // the new line's end extends an existing line
-       if(extend_finish)
-       {
-               int target_offset = 0;
-               trans_bline.pop_back();
-               if(finish_duck_index==0)
-               {
-                       result=extend_bline_from_begin(finish_duck_value_node_bline,trans_bline,false);
-                       source=finish_duck_value_node_bline->list.front();
-                       target_offset=trans_bline.size();
-               }
-               else
-               {       // We need to reverse the BLine first.
-                       reverse_bline(trans_bline);
-                       result=extend_bline_from_end(finish_duck_value_node_bline,trans_bline,false);
-                       source=finish_duck_value_node_bline->list.back();
-               }
-
-               if(extend_finish_join_different)
-                       LinkableValueNode::Handle::cast_dynamic(source.value_node)->
-                               set_link("point",start_duck_value_desc.get_value_node());
-               else if(extend_finish_join_same)
-                       LinkableValueNode::Handle::cast_dynamic(source.value_node)->
-                               set_link("point",synfigapp::ValueDesc(LinkableValueNode::Handle::cast_dynamic(finish_duck_value_node_bline->
-                                                                                                       list[target_offset+start_duck_index].value_node),0).get_value_node());
-               return result;
-       }
-
-       if (join_start_no_extend)
-               LinkableValueNode::Handle::cast_dynamic(value_node->list.front().value_node)->
-                 set_link("point",start_duck_value_desc.get_value_node());
-
-       if (join_finish_no_extend)
-               LinkableValueNode::Handle::cast_dynamic(value_node->list.back().value_node)->
-                 set_link("point",finish_duck_value_desc.get_value_node());
-
-       if(get_auto_export_flag())
-               if (!get_canvas_interface()->add_value_node(value_node,get_id()))
-               {
-                       /* it's no big deal, is it?  let's keep the shape anyway */
-                       // get_canvas_view()->get_ui_interface()->error(_("Unable to add value node"));
-                       // group.cancel();
-                       // increment_id();
-                       // return Smach::RESULT_ERROR;
-               }
-
-       last_stroke=value_node;
-       last_stroke_id=get_id();
-
-       {
-               // Create the layer(s)
-               Layer::Handle layer;
-               Canvas::Handle canvas(get_canvas_view()->get_canvas());
-               int depth(0);
-
-               // we are temporarily using the layer to hold something
-               layer=get_canvas_view()->get_selection_manager()->get_selected_layer();
-               if(layer)
-               {
-                       depth=layer->get_depth();
-                       canvas=layer->get_canvas();
-               }
-
-               // fill_last_stroke() will take care of clearing the selection if we're calling it
-               if(get_outline_flag() && get_region_flag())
-               {
-                       if (fill_last_stroke_and_unselect_other_layers() == Smach::RESULT_ERROR)
-                       {
-                               get_canvas_view()->get_selection_manager()->set_selected_layers(layer_list);
-                               get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
-                               group.cancel();
-                               return Smach::RESULT_ERROR;
-                       }
-               }
-               else
-                       get_canvas_interface()->get_selection_manager()->clear_selected_layers();
-
-               //int number(synfig::UniqueID().get_uid());
-
-               synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
-
-               // if they're both defined, we'll add the region later
-               if(get_outline_flag())
-               {
-                       layer=get_canvas_interface()->add_layer_to("outline",canvas,depth);
-                       if (!layer)
-                       {
-                               get_canvas_view()->get_selection_manager()->set_selected_layers(layer_list);
-                               get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
-                               group.cancel();
-                               return Smach::RESULT_ERROR;
-                       }
-                       layer->set_description(get_id()+_(" Outline"));
-               }
-               else
-               {
-                       layer=get_canvas_interface()->add_layer_to("region",canvas,depth);
-                       if (!layer)
-                       {
-                               get_canvas_view()->get_selection_manager()->set_selected_layers(layer_list);
-                               get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
-                               group.cancel();
-                               return Smach::RESULT_ERROR;
-                       }
-                       layer->set_description(get_id()+_(" Region"));
-               }
-
-               if(get_feather())
-               {
-                       layer->set_param("feather",get_feather());
-                       get_canvas_interface()->signal_layer_param_changed()(layer,"feather");
-               }
-               assert(layer);
-               //layer->set_description(strprintf("Stroke %d",number));
-               //get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
-
-               if (shift_origin)
-                       get_canvas_interface()->
-                         change_value(synfigapp::ValueDesc(layer,"origin"),shift_origin_vector);
-
-               synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
-
-               assert(action);
-
-               action->set_param("canvas",get_canvas());
-               action->set_param("canvas_interface",get_canvas_interface());
-               action->set_param("layer",layer);
-               if(!action->set_param("param",String("bline")))
-                       synfig::error("LayerParamConnect didn't like \"param\"");
-               if(!action->set_param("value_node",ValueNode::Handle(value_node)))
-                       synfig::error("LayerParamConnect didn't like \"value_node\"");
-
-               if(!get_canvas_interface()->get_instance()->perform_action(action))
-               {
-                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
-                       group.cancel();
-                       increment_id();
-                       //refresh_ducks();
-                       return Smach::RESULT_ERROR;
-               }
-               layer_list.push_back(layer);
-               get_canvas_view()->get_selection_manager()->set_selected_layers(layer_list);
-               //refresh_ducks();
-       }
-
-       increment_id();
-       return Smach::RESULT_ACCEPT;
-}
-
-#ifdef _DEBUG
-static void
-debug_show_vertex_list(int iteration, std::list<synfigapp::ValueDesc>& vertex_list,
-                                          std::string title, int current)
-{
-       std::list<synfigapp::ValueDesc>::iterator i = vertex_list.begin();
-       printf("\n%s\n  ----- iter %d : ", title.c_str(), iteration);
-       int c = 0;
-       synfig::LinkableValueNode::Handle last = 0;
-       int start = -1;
-       int index;
-       int prev;
-       int dir = 0;
-       bool started = false;
-       for(;i!=vertex_list.end();i++,c++)
-       {
-               synfigapp::ValueDesc value_desc(*i);
-
-               if (value_desc.parent_is_value_node()) {
-                       if(value_desc.parent_is_linkable_value_node())
-                       {
-                               index = value_desc.get_index();
-                               // printf("<%d>", index);
-                               if (last == synfig::LinkableValueNode::Handle::cast_reinterpret(value_desc.get_parent_value_node()))
-                               {
-                                       // printf("\n%s:%d\n", __FILE__, __LINE__);
-                                       if (start != -1)
-                                       {
-                                               // printf("\n%s:%d\n", __FILE__, __LINE__);
-                                               if (c == current)
-                                               {
-                                                       // printf("\n%s:%d\n", __FILE__, __LINE__);
-                                                       if (dir)
-                                                       {
-                                                               if (started) printf(", "); else started = true;
-                                                               printf("%d--%d", start, prev);
-                                                       }
-                                                       else
-                                                       {
-                                                               if (started) printf(", "); else started = true;
-                                                               printf("%d", start);
-                                                       }
-                                                       printf(", *%d*", index);
-                                                       start = -1;
-                                               }
-                                               else if (dir == 0)
-                                               {
-                                                       // printf("\n%s:%d\n", __FILE__, __LINE__);
-                                                       if (index == start + 1)
-                                                       {
-                                                               // printf("\n%s:%d\n", __FILE__, __LINE__);
-                                                               dir = 1;
-                                                               prev = index;
-                                                       }
-                                                       else if (index == start - 1)
-                                                       {
-                                                               // printf("\n%s:%d\n", __FILE__, __LINE__);
-                                                               dir = -1;
-                                                               prev = index;
-                                                       }
-                                                       else
-                                                       {
-                                                               if (started) printf(", "); else started = true;
-                                                               printf("%d", start);
-                                                               start = index;
-                                                       }
-                                               }
-                                               else if (index == prev + dir)
-                                               {
-                                                       // printf("\n%s:%d\n", __FILE__, __LINE__);
-                                                       prev = index;
-                                               }
-                                               else
-                                               {
-                                                       // printf("\n%s:%d\n", __FILE__, __LINE__);
-                                                       if (started) printf(", "); else started = true;
-                                                       if (prev != start)
-                                                               printf("%d--%d", start, prev);
-                                                       else
-                                                               printf("%d", start);
-                                                       // printf("\n%s:%d\n", __FILE__, __LINE__);
-                                                       start = index;
-                                                       dir = 0;
-                                               }
-                                       }
-                                       else
-                                       {
-                                               // printf("\n%s:%d\n", __FILE__, __LINE__);
-                                               if (c == current)
-                                               {
-                                                       if (started) printf(", "); else started = true;
-                                                       printf("*%d*", index);
-                                               }
-                                               else
-                                               {
-                                                       // printf("\n%s:%d\n", __FILE__, __LINE__);
-                                                       start = index;
-                                                       dir = 0;
-                                               }
-                                       }
-                               }
-                               else
-                               {
-                                       // printf("\n%s:%d\n", __FILE__, __LINE__);
-                                       if (last)
-                                       {
-                                               // printf("\n%s:%d\n", __FILE__, __LINE__);
-                                               if (start != -1)
-                                               {
-                                                       if (started) printf(", "); else started = true;
-                                                       if (dir != 0)
-                                                               printf("%d--%d", start, prev);
-                                                       else
-                                                               printf("%d", start);
-                                               }
-                                               // printf("\n%s:%d\n", __FILE__, __LINE__);
-                                               printf(") ");
-                                       }
-                                       // printf("\n%s:%d\n", __FILE__, __LINE__);
-                                       last = synfig::LinkableValueNode::Handle::cast_reinterpret(value_desc.get_parent_value_node());
-                                       printf("%d:(", synfig::LinkableValueNode::Handle::cast_reinterpret(value_desc.get_parent_value_node())->link_count());
-                                       started = false;
-                                       // printf("\n%s:%d\n", __FILE__, __LINE__);
-                                       if (c == current)
-                                       {
-                                               start = -1;
-                                               printf("*%d*", index);
-                                       }
-                                       else
-                                       {
-                                               // printf("\n%s:%d\n", __FILE__, __LINE__);
-                                               start = index;
-                                               dir = 0;
-                                       }
-                                       // printf("\n%s:%d\n", __FILE__, __LINE__);
-                               }
-                               // printf("\n%s:%d\n", __FILE__, __LINE__);
-                       }
-                       else if (last)
-                               if (last) printf("?!) ");
-               }
-               else
-               {
-                       last = 0;
-                       printf("? ");
-               }
-       }
-       if (last)
-       {
-               if (started) printf(", "); else started = true;
-               if (start != -1)
-               {
-                       if (dir != 0)
-                               printf("%d--%d", start, prev);
-                       else
-                               printf("%d", start);
-               }
-               printf(")");
-       }
-       printf("\n");
-}
-#else  // _DEBUG
-#define debug_show_vertex_list(a,b,c,d)
-#endif // _DEBUG
-
-Smach::event_result
-StateDraw_Context::new_region(std::list<synfig::BLinePoint> bline, synfig::Real radius)
-{
-       // Create the action group
-       synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Define Region"));
-
-       std::list<synfigapp::ValueDesc> vertex_list;
-
-       printf("new_region with %zd bline points\n", bline.size());
-
-       // First we need to come up with a rough list of
-       // BLinePoints that we are going to be using to
-       // define our region.
-       {
-               std::list<synfig::BLinePoint>::iterator iter;
-               for(iter=bline.begin();iter!=bline.end();++iter)
-               {
-                       etl::handle<Duck> duck(get_work_area()->find_duck(iter->get_vertex(),0,Duck::TYPE_VERTEX));
-
-                       if(!duck)
-                       {
-                               synfig::info(__FILE__":%d: Nothing to enclose!",__LINE__);
-                               return Smach::RESULT_OK;
-                       }
-
-                       assert(duck->get_type()==Duck::TYPE_VERTEX);
-
-                       synfigapp::ValueDesc value_desc(duck->get_value_desc());
-
-                       if(!value_desc)
-                       {
-                               synfig::info(__FILE__":%d: Got a hit, but no ValueDesc on this duck",__LINE__);
-                               continue;
-                       }
-
-                       switch(value_desc.get_value_type())
-                       {
-                       case synfig::ValueBase::TYPE_BLINEPOINT:
-                               //if(vertex_list.empty() || value_desc!=vertex_list.back())
-                               vertex_list.push_back(value_desc);
-                               assert(vertex_list.back().is_valid());
-
-                               break;
-                       default:
-                               break;
-                       }
-               }
-       }
-
-       assert(vertex_list.back().is_valid());
-
-       printf("vertex list with %zd bline points\n", vertex_list.size());
-
-       // Remove any duplicates
-       {
-       }
-
-       ValueNode_BLine::Handle value_node_bline;
-
-       // Now we need to test for the trivial case,
-       // which is where all of the vertices
-       // come from one BLine.
-       if(vertex_list.front().parent_is_linkable_value_node())
-       {
-               bool trivial_case(true);
-               ValueNode::Handle trivial_case_value_node;
-
-               trivial_case_value_node=vertex_list.front().get_parent_value_node();
-
-               std::list<synfigapp::ValueDesc>::iterator iter;
-               for(iter=vertex_list.begin();iter!=vertex_list.end();++iter)
-               {
-                       if(trivial_case_value_node!=iter->get_parent_value_node())
-                       {
-                               trivial_case=false;
-                               break;
-                       }
-               }
-
-               // \todo - re-enable this code
-               if(trivial_case && false)
-               {
-                       synfig::info("all points are on the same bline, so just fill that line");
-                       value_node_bline=ValueNode_BLine::Handle::cast_dynamic(trivial_case_value_node);
-
-                       synfig::info("the line has %d vertices", value_node_bline->link_count());
-
-                       if(value_node_bline->link_count() <= 2)
-                       {
-                               synfig::info(__FILE__":%d: Vertex list too small to make region.",__LINE__);
-                               return Smach::RESULT_OK;
-                       }
-               }
-       }
-
-       if(!value_node_bline)
-               if(vertex_list.size()<=2)
-               {
-                       synfig::info(__FILE__":%d: Vertex list too small to make region.",__LINE__);
-                       return Smach::RESULT_OK;
-               }
-
-       // Now we need to clean the list of vertices up
-       // a bit. This includes inserting missing vertices
-       // and removing extraneous ones.
-       // We can do this in multiple passes.
-       if(!value_node_bline)
-       {
-               debug_show_vertex_list(0, vertex_list, "before shifting stuff", -1);
-               // rearrange the list so that the first and last node are on different blines
-               std::list<synfigapp::ValueDesc>::iterator iter, start;
-               ValueNode::Handle last_value_node = vertex_list.back().get_parent_value_node();
-               for(iter = vertex_list.begin(); iter!=vertex_list.end(); iter++)
-                       if (iter->get_parent_value_node() != last_value_node)
-                       {
-                               vertex_list.insert(vertex_list.end(), vertex_list.begin(), iter);
-                               vertex_list.erase(vertex_list.begin(), iter);
-                               break;
-                       }
-
-               debug_show_vertex_list(0, vertex_list, "before detecting direction and limits", -1);
-               // rearrange the list so that the first and last node are on different blines
-               iter = vertex_list.begin();
-               while (iter!=vertex_list.end())
-               {
-                       // make a note of which bline we're looking at
-                       ValueNode::Handle parent_value_node = iter->get_parent_value_node();
-                       start = iter;
-                       int points_in_line = synfig::LinkableValueNode::Handle::cast_reinterpret(parent_value_node)->link_count();
-                       bool looped = (*parent_value_node)(get_time()).get_loop();
-                       int this_index, last_index = iter->get_index();
-                       int min_index = last_index, max_index = last_index;
-                       bool whole;
-                       int direction = 0;
-
-                       // printf("there are %d points in this line - first is index %d\n", points_in_line, last_index);
-
-                       // while we're looking at the same bline, keep going
-                       iter++;
-                       while (iter != vertex_list.end() && iter->get_parent_value_node() == parent_value_node)
-                       {
-                               this_index = iter->get_index();
-                               // printf("index went from %d to %d\n", last_index, this_index);
-                               if (looped)
-                               {
-                                       if (this_index - last_index > points_in_line/2)
-                                               while (this_index - last_index > points_in_line/2)
-                                                       this_index -= points_in_line;
-                                       else if (last_index - this_index > points_in_line/2)
-                                               while (last_index - this_index > points_in_line/2)
-                                                       this_index += points_in_line;
-                               }
-
-                               if (this_index < min_index) min_index = this_index;
-                               if (this_index > max_index) max_index = this_index;
-
-                               // printf("so let's imagine index went from %d to %d\n", last_index, this_index);
-                               if (this_index > last_index)
-                                       direction++;
-                               else if (this_index < last_index)
-                                       direction--;
-
-                               last_index = this_index;
-                               iter++;
-                       }
-
-                       // printf("min %d and max %d\n", min_index, max_index);
-                       whole = max_index - min_index >= points_in_line;
-                       min_index = (min_index % points_in_line + points_in_line) % points_in_line;
-                       max_index = (max_index % points_in_line + points_in_line) % points_in_line;
-                       // they drew around a shape more than once - what's the start/end point?  does it matter?
-                       if (whole) min_index = max_index = (min_index + max_index) / 2;
-                       // printf("processed min %d max %d whole %d\n", min_index, max_index, whole);
-
-                       if (direction < 0)
-                       {
-                               if (whole)
-                               {
-                                       // printf("whole (down) (%d) ", min_index);
-                                       for (int i = min_index; i >= 0; i--)
-                                       {
-                                               // printf("%d ", i);
-                                               vertex_list.insert(start, synfigapp::ValueDesc(parent_value_node, i));
-                                       }
-                                       for (int i = points_in_line - 1; i >= min_index; i--)
-                                       {
-                                               // printf("%d ", i);
-                                               vertex_list.insert(start, synfigapp::ValueDesc(parent_value_node, i));
-                                       }
-                               }
-                               else
-                               {
-                                       // printf("part (down) (%d -> %d) ", max_index, min_index);
-                                       for (int i = max_index; i != min_index; i--)
-                                       {
-                                               if (i == -1) i = points_in_line - 1;
-                                               // printf("%d ", i);
-                                               vertex_list.insert(start, synfigapp::ValueDesc(parent_value_node, i));
-                                       }
-                                       vertex_list.insert(start, synfigapp::ValueDesc(parent_value_node, min_index));
-                               }
-                       }
-                       else
-                       {
-                               if (whole)
-                               {
-                                       // printf("whole (%d) ", min_index);
-                                       for (int i = min_index; i < points_in_line; i++)
-                                       {
-                                               // printf("%d ", i);
-                                               vertex_list.insert(start, synfigapp::ValueDesc(parent_value_node, i));
-                                       }
-                                       for (int i = 0; i <= min_index; i++)
-                                       {
-                                               // printf("%d ", i);
-                                               vertex_list.insert(start, synfigapp::ValueDesc(parent_value_node, i));
-                                       }
-                               }
-                               else
-                               {
-                                       // printf("part (%d -> %d) ", min_index, max_index);
-                                       for (int i = min_index; i != max_index; i++)
-                                       {
-                                               if (i == points_in_line) i = 0;
-                                               // printf("%d ", i);
-                                               vertex_list.insert(start, synfigapp::ValueDesc(parent_value_node, i));
-                                       }
-                                       vertex_list.insert(start, synfigapp::ValueDesc(parent_value_node, max_index));
-                               }
-                       }
-                       // printf("\n");
-                       // debug_show_vertex_list(0, vertex_list, "after insert", -1);
-                       vertex_list.erase(start, iter);
-                       // debug_show_vertex_list(0, vertex_list, "after delete", -1);
-               }
-
-               debug_show_vertex_list(0, vertex_list, "continuous vertices", -1);
-
-               // \todo reenable or delete this section
-               int i=100;
-               for(bool done=false;!done && i<30;i++)
-               {
-                       debug_show_vertex_list(i, vertex_list, "in big loop", -1);
-
-                       // Set done to "true" for now. If
-                       // any updates are performed, we will
-                       // change it back to false.
-                       done=true;
-
-                       std::list<synfigapp::ValueDesc>::iterator prev,next;
-                       prev=vertex_list.end();prev--;  // Set prev to the last ValueDesc
-                       next=vertex_list.begin();
-                       iter=next++; // Set iter to the first value desc, and next to the second
-
-                       int current = 0;
-                       for(;iter!=vertex_list.end();prev=iter,iter++,next++,current++)
-                       {
-                               // we need to be able to erase(next) and can't do that if next is end()
-                               if (next == vertex_list.end()) next = vertex_list.begin();
-                               debug_show_vertex_list(i, vertex_list, "in loop around vertices", current);
-                               synfigapp::ValueDesc value_prev(*prev);
-                               synfigapp::ValueDesc value_desc(*iter);
-                               synfigapp::ValueDesc value_next(*next);
-
-                               assert(value_desc.is_valid());
-                               assert(value_next.is_valid());
-                               assert(value_prev.is_valid());
-
-                               // synfig::info("-------");
-                               // synfig::info(__FILE__":%d: value_prev 0x%08X:%d",__LINE__,value_prev.get_parent_value_node().get(),value_prev.get_index());
-                               // synfig::info(__FILE__":%d: value_desc 0x%08X:%d",__LINE__,value_desc.get_parent_value_node().get(),value_desc.get_index());
-                               // synfig::info(__FILE__":%d: value_next 0x%08X:%d",__LINE__,value_next.get_parent_value_node().get(),value_next.get_index());
-
-                               /*
-                                 if(value_prev.parent_is_value_node() && value_desc.parent_is_value_node() && value_next.parent_is_value_node())
-                                 {
-                                 // Remove random extraneous vertices
-                                 if(value_prev.get_parent_value_node()==value_next.get_parent_value_node() &&
-                                 value_prev.get_parent_value_node()!=value_desc.get_parent_value_node())
-                                 {
-                                 vertex_list.erase(iter);
-                                 done=false;
-                                 break;
-                                 }
-                                 }
-                               */
-
-                               // // Remove duplicate vertices
-
-                               // // if previous is the same as current or
-                               // //    current is the same as next, remove current
-                               // if(value_prev.get_value_node()==value_desc.get_value_node() ||
-                               //    value_desc.get_value_node()==value_next.get_value_node())
-                               // {
-                               //      vertex_list.erase(iter);
-                               //      done=false;
-                               //      printf("erased node - i = %d\n", i);
-                               //      break;
-                               // }
-
-                               // // if previous is the same as next, remove previous?  or next?
-                               // if(value_prev.get_value_node()==value_next.get_value_node())
-                               // {
-                               //      vertex_list.erase(next);
-                               //      // vertex_list.erase(prev);
-                               //      done=false;
-                               //      printf("erased node - i = %d\n", i);
-                               //      break;
-                               // }
-
-                               // if 'this' and 'next' both have parents
-                               if (value_desc.parent_is_value_node() && value_next.parent_is_value_node())
-                               {
-                                       // if they are both on the same bline - this has been handled by new code above
-                                       if (value_desc.get_parent_value_node() == value_next.get_parent_value_node())
-                                       {
-                                               // // if (next != vertex_list.end())
-                                               // {
-                                               //      printf("parent loop is %d and node loop is ??\n",
-                                               //                 (*(value_desc.get_parent_value_node()))(get_time()).get_loop()
-                                               //                 // value_desc.get_value_node().get_loop(),
-                                               //              );
-                                               //
-                                               //      // Fill in missing vertices
-                                               //      // \todo take loops into account: seeing (15, 2, 3, 4) probably means that (0, 1) is missing, not 14 through 3
-                                               //      if(value_desc.get_index()<value_next.get_index()-1)
-                                               //      {
-                                               //              debug_show_vertex_list(i, vertex_list,
-                                               //                                                         strprintf("same parent, different points this %d < next-1 %d",
-                                               //                                                                               value_desc.get_index(), ((value_next.get_index()-1))),
-                                               //                                                         current);
-                                               //              for (int index = value_desc.get_index()+1; index < value_next.get_index(); index++)
-                                               //              {
-                                               //                      printf("inserting up %d\n", index);
-                                               //                      vertex_list.insert(next, synfigapp::ValueDesc(value_desc.get_parent_value_node(), index));
-                                               //              }
-                                               //              debug_show_vertex_list(i, vertex_list, "new list", current);
-                                               //              done=false;
-                                               //              break;
-                                               //      }
-                                               //      if(value_next.get_index()<value_desc.get_index()-1)
-                                               //      {
-                                               //              debug_show_vertex_list(i, vertex_list,
-                                               //                                                         strprintf("same parent, different points next %d < this-1 %d",
-                                               //                                                                               value_next.get_index(), ((value_desc.get_index()-1))),
-                                               //                                                         current);
-                                               //              for (int index = value_desc.get_index()-1; index > value_next.get_index(); index--)
-                                               //              {
-                                               //                      printf("inserting down %d\n", index);
-                                               //                      vertex_list.insert(next, synfigapp::ValueDesc(value_desc.get_parent_value_node(), index));
-                                               //              }
-                                               //              debug_show_vertex_list(i, vertex_list, "new list", current);
-                                               //              done=false;
-                                               //              break;
-                                               //      }
-                                               // }
-                                       }
-                                       // 'this' and 'next' have different parents
-                                       else
-                                       {
-                                               ValueNode::Handle v1 = value_desc.get_value_node();
-                                               ValueNode::Handle v2 = value_desc.get_parent_value_node();
-                                               if (v1 == v2)
-                                                       printf("same\n");
-                                               else
-                                                       printf("different\n");
-
-                                               if (value_desc.get_value_node() != value_next.get_value_node())
-                                               {
-                                                       // Ensure that connections between blines are properly connected
-                                                       BLinePoint vertex(value_desc.get_value(get_time()).get(BLinePoint()));
-                                                       BLinePoint vertex_next(value_next.get_value(get_time()).get(BLinePoint()));
-
-                                                       //synfig::info("--------");
-                                                       //synfig::info(__FILE__":%d: vertex: [%f, %f]",__LINE__,vertex.get_vertex()[0],vertex.get_vertex()[1]);
-                                                       //synfig::info(__FILE__":%d: vertex_next: [%f, %f]",__LINE__,vertex_next.get_vertex()[0],vertex_next.get_vertex()[1]);
-
-                                                       // if this vertex is close to the next one, replace this vertex with a new one
-                                                       // and erase the next one
-                                                       printf("this point is %5.2f from the next point - compare with %5.2f\n",
-                                                                  (vertex.get_vertex()-vertex_next.get_vertex()).mag_squared(),
-                                                                  radius*radius);
-                                                       if((vertex.get_vertex()-vertex_next.get_vertex()).mag_squared()<radius*radius)
-                                                       {
-                                                               printf("in one - it's close\n");
-                                                               ValueNode_Composite::Handle value_node;
-                                                               ValueNode_Composite::Handle value_node_next;
-                                                               value_node=ValueNode_Composite::Handle::cast_dynamic(value_desc.get_value_node().clone());
-                                                               value_node_next=ValueNode_Composite::Handle::cast_dynamic(value_next.get_value_node().clone());
-                                                               if(!value_node || !value_node_next)
-                                                               {
-                                                                       synfig::info(__FILE__":%d: Unable to properly connect blines.",__LINE__);
-                                                                       continue;
-                                                               }
-                                                               // \todo if next isn't split, don't we want to copy its 'Tangent 1' instead?
-                                                               value_node->set_link("t2",value_node_next->get_link("t2"));
-                                                               value_node->set_link("split",ValueNode_Const::create(true));
-
-                                                               // get_canvas_interface()->auto_export(value_node);
-                                                               printf("exporting\n");
-                                                               get_canvas_interface()->add_value_node(value_node,value_node->get_id() + strprintf("foo %d", rand()));
-
-                                                               assert(value_node->is_exported());
-                                                               // replace 'this' with the new valuenode
-                                                               *iter=synfigapp::ValueDesc(get_canvas(),value_node->get_id());
-                                                               printf("erasing next\n");
-                                                               printf("erasing next point\n");
-                                                               vertex_list.erase(next);
-                                                               done=false;
-                                                               break;
-                                                       } // this vertex isn't close to the next one
-                                                       else if (value_prev.parent_is_value_node())
-                                                       {
-                                                               printf("in two - it's far\n");
-                                                               // \todo this only makes sense if prev is on the same bline
-                                                               printf("this is index %d\n", value_desc.get_index());
-                                                               printf("prev is index %d\n", value_prev.get_index());
-                                                               bool positive_trend(value_desc.get_index()>value_prev.get_index());
-
-                                                               if(positive_trend)
-                                                               {
-                                                                       printf("positive trend\n");
-                                                                       printf("comparing index %d < link_count()-1 = %d-1 = %d\n",
-                                                                                  value_desc.get_index(),
-                                                                                  LinkableValueNode::Handle::cast_static(value_desc.get_parent_value_node())->link_count(),
-                                                                                  LinkableValueNode::Handle::cast_static(value_desc.get_parent_value_node())->link_count()-1);
-                                                                       if (value_desc.get_index()<LinkableValueNode::Handle::cast_static(value_desc.get_parent_value_node())->link_count()-1)
-                                                                       {
-                                                                               printf("in two - b\n");
-                                                                               printf("inserting node with index %d\n", value_desc.get_index()+1);
-                                                                               vertex_list.insert(next,
-                                                                                                                  synfigapp::ValueDesc(value_desc.get_parent_value_node(),
-                                                                                                                                                               value_desc.get_index()+1));
-                                                                               done=false;
-                                                                               break;
-                                                                       }
-                                                               }
-                                                               else // !positive_trend
-                                                               {
-                                                                       printf("negative trend\n");
-                                                                       if(value_desc.get_index()>0)
-                                                                       {
-                                                                               printf("in two - a\n");
-                                                                               printf("inserting node on this line with index %d\n",
-                                                                                          value_desc.get_index()-1);
-                                                                               vertex_list.insert(next,
-                                                                                                                  synfigapp::ValueDesc(value_desc.get_parent_value_node(),
-                                                                                                                                                               value_desc.get_index()-1));
-                                                                               done=false;
-                                                                               break;
-                                                                       }
-                                                               }
-                                                       }
-                                               }
-                                       }
-                               }
-                       }
-               }
-
-               if(vertex_list.size()<=2)
-               {
-                       synfig::info(__FILE__":%d: Vertex list too small to make region.",__LINE__);
-                       return Smach::RESULT_OK;
-               }
-
-               debug_show_vertex_list(i, vertex_list, "finished tidying list", -1);
-       }
-
-       // If we aren't the trivial case,
-       // then go ahead and create the new
-       // BLine value node
-       if(!value_node_bline)
-       {
-               synfig::info("not all points are on the same bline");
-               value_node_bline=ValueNode_BLine::create();
-
-               std::list<synfigapp::ValueDesc>::iterator iter;
-               for(iter=vertex_list.begin();iter!=vertex_list.end();++iter)
-               {
-                       // Ensure that the vertex is exported.
-                       get_canvas_interface()->auto_export(*iter);
-
-                       value_node_bline->add(iter->get_value_node());
-                       //value_node_bline->add(ValueNode_BLine::ListEntry(iter->get_value_node()));
-               }
-
-               value_node_bline->set_loop(true);
-       }
-
-       get_canvas_interface()->auto_export(value_node_bline);
-
-       // Now we create the region layer
-       // Create the layer
-       {
-               Layer::Handle layer;
-               Canvas::Handle canvas(get_canvas_view()->get_canvas());
-               int depth(0);
-
-               // we are temporarily using the layer to hold something
-               layer=get_canvas_view()->get_selection_manager()->get_selected_layer();
-               if(layer)
-               {
-                       depth=layer->get_depth();
-                       canvas=layer->get_canvas();
-               }
-
-               synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
-
-               layer=get_canvas_interface()->add_layer_to("region",canvas,depth);
-               if (!layer)
-               {
-                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
-                       group.cancel();
-                       return Smach::RESULT_ERROR;
-               }
-
-               if(get_feather())
-               {
-                       layer->set_param("feather",get_feather());
-                       get_canvas_interface()->signal_layer_param_changed()(layer,"feather");
-               }
-               get_canvas_interface()->signal_layer_param_changed()(layer,"color");
-
-               synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
-
-               assert(action);
-
-               action->set_param("canvas",get_canvas());
-               action->set_param("canvas_interface",get_canvas_interface());
-               action->set_param("layer",layer);
-               if(!action->set_param("param",String("bline")))
-                       synfig::error("LayerParamConnect didn't like \"param\"");
-               if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
-                       synfig::error("LayerParamConnect didn't like \"value_node\"");
-
-               if(!get_canvas_interface()->get_instance()->perform_action(action))
-               {
-                       get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer"));
-                       group.cancel();
-                       return Smach::RESULT_ERROR;
-               }
-               get_canvas_view()->get_selection_manager()->set_selected_layer(layer);
-       }
-
-       return Smach::RESULT_ACCEPT;
-}
-
-void
-StateDraw_Context::refresh_ducks()
-{
-       get_canvas_view()->queue_rebuild_ducks();
-/*
-       get_work_area()->clear_ducks();
-
-
-       std::list< etl::smart_ptr<std::list<synfig::Point> > >::iterator iter;
-
-       for(iter=stroke_list.begin();iter!=stroke_list.end();++iter)
-       {
-               get_work_area()->add_stroke(*iter);
-       }
-
-       get_work_area()->queue_draw();
-*/
-}
-
-
-Smach::event_result
-StateDraw_Context::extend_bline_from_begin(ValueNode_BLine::Handle value_node,std::list<synfig::BLinePoint> bline,bool complete_loop)
-{
-       // Create the action group
-       synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Extend BLine"));
-
-       if (complete_loop)
-       {
-               synfigapp::Action::Handle action(synfigapp::Action::create("ValueNodeDynamicListLoop"));
-               assert(action);
-
-               action->set_param("canvas",get_canvas());
-               action->set_param("canvas_interface",get_canvas_interface());
-               action->set_param("value_node",ValueNode::Handle(value_node));
-
-               if(!get_canvas_interface()->get_instance()->perform_action(action))
-               {
-                       get_canvas_view()->get_ui_interface()->error(_("Unable to set loop for bline"));
-                       group.cancel();
-                       return Smach::RESULT_ERROR;
-               }
-       }
-
-       std::list<synfig::BLinePoint>::reverse_iterator iter;
-       for(iter=bline.rbegin();!(iter==bline.rend());++iter)
-       {
-               ValueNode_Composite::Handle composite(ValueNode_Composite::create(*iter));
-
-               synfigapp::Action::Handle action(synfigapp::Action::create("ValueNodeDynamicListInsert"));
-
-               assert(action);
-               synfigapp::ValueDesc value_desc(value_node,0);
-
-               action->set_param("canvas",get_canvas());
-               action->set_param("canvas_interface",get_canvas_interface());
-               action->set_param("value_desc",value_desc);
-               if(!action->set_param("item",ValueNode::Handle(composite)))
-                       synfig::error("ACTION didn't like \"item\"");
-
-               if(!get_canvas_interface()->get_instance()->perform_action(action))
-               {
-                       get_canvas_view()->get_ui_interface()->error(_("Unable to insert item"));
-                       group.cancel();
-                       //refresh_ducks();
-                       return Smach::RESULT_ERROR;
-               }
-       }
-       last_stroke=value_node;
-       return Smach::RESULT_ACCEPT;
-}
-
-Smach::event_result
-StateDraw_Context::extend_bline_from_end(ValueNode_BLine::Handle value_node,std::list<synfig::BLinePoint> bline,bool complete_loop)
-{
-       // Create the action group
-       synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Extend BLine"));
-
-       if (complete_loop)
-       {
-               synfigapp::Action::Handle action(synfigapp::Action::create("ValueNodeDynamicListLoop"));
-               assert(action);
-
-               action->set_param("canvas",get_canvas());
-               action->set_param("canvas_interface",get_canvas_interface());
-               action->set_param("value_node",ValueNode::Handle(value_node));
-
-               if(!get_canvas_interface()->get_instance()->perform_action(action))
-               {
-                       get_canvas_view()->get_ui_interface()->error(_("Unable to set loop for bline"));
-                       group.cancel();
-                       return Smach::RESULT_ERROR;
-               }
-       }
-
-       std::list<synfig::BLinePoint>::iterator iter;
-       for(iter=bline.begin();iter!=bline.end();++iter)
-       {
-               ValueNode_Composite::Handle composite(ValueNode_Composite::create(*iter));
-
-               synfigapp::Action::Handle action(synfigapp::Action::create("ValueNodeDynamicListInsert"));
-
-               assert(action);
-               synfigapp::ValueDesc value_desc(value_node,value_node->link_count());
-
-               action->set_param("canvas",get_canvas());
-               action->set_param("canvas_interface",get_canvas_interface());
-               action->set_param("value_desc",value_desc);
-               if(!action->set_param("item",ValueNode::Handle(composite)))
-                       synfig::error("ACTION didn't like \"item\"");
-
-               if(!get_canvas_interface()->get_instance()->perform_action(action))
-               {
-                       get_canvas_view()->get_ui_interface()->error(_("Unable to insert item"));
-                       group.cancel();
-                       //refresh_ducks();
-                       return Smach::RESULT_ERROR;
-               }
-       }
-       last_stroke=value_node;
-       return Smach::RESULT_ACCEPT;
-}
-
-void
-StateDraw_Context::reverse_bline(std::list<synfig::BLinePoint> &bline)
-{
-       int i;
-
-       std::list<synfig::BLinePoint>::iterator iter,eiter;
-       iter=bline.begin();
-       eiter=bline.end();
-       eiter--;
-       for(i=0;i<(int)bline.size()/2;++iter,--eiter,i++)
-       {
-               iter_swap(iter,eiter);
-               iter->reverse();
-               eiter->reverse();
-       }
-}
-
-Smach::event_result
-StateDraw_Context::fill_last_stroke_and_unselect_other_layers()
-{
-       if(!last_stroke)
-               return Smach::RESULT_OK;
-
-       synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Fill Stroke"));
-
-       Layer::Handle layer;
-
-       get_canvas_interface()->auto_export(last_stroke);
-
-       synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
-
-       Canvas::Handle canvas(get_canvas_view()->get_canvas());
-       int depth(0);
-
-       layer=get_canvas_view()->get_selection_manager()->get_selected_layer();
-       if(layer)
-       {
-               depth=layer->get_depth();
-               canvas=layer->get_canvas();
-       }
-
-       get_canvas_interface()->get_selection_manager()->clear_selected_layers();
-       layer=get_canvas_interface()->add_layer_to("region", canvas, depth);
-       if (!layer) return Smach::RESULT_ERROR;
-       layer->set_description(last_stroke_id + _(" Region"));
-
-       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
-
-       assert(action);
-
-       action->set_param("canvas",get_canvas());
-       action->set_param("canvas_interface",get_canvas_interface());
-       action->set_param("layer",layer);
-       if(!action->set_param("param",String("bline")))
-               synfig::error("LayerParamConnect didn't like \"param\"");
-       if(!action->set_param("value_node",ValueNode::Handle(last_stroke)))
-               synfig::error("LayerParamConnect didn't like \"value_node\"");
-
-       if(!get_canvas_interface()->get_instance()->perform_action(action))
-       {
-               get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer"));
-               group.cancel();
-               return Smach::RESULT_OK;
-       }
-       get_canvas_view()->get_selection_manager()->set_selected_layer(layer);
-       return Smach::RESULT_OK;
-}
-
-void
-StateDraw_Context::fill_last_stroke()
-{
-       if(!last_stroke)
-               return;
-
-       synfigapp::SelectionManager::LayerList layer_list = get_canvas_view()->get_selection_manager()->get_selected_layers();
-       fill_last_stroke_and_unselect_other_layers();
-       get_canvas_view()->get_selection_manager()->set_selected_layers(layer_list);
-}
diff --git a/synfig-studio/src/gui/state_draw.h b/synfig-studio/src/gui/state_draw.h
deleted file mode 100644 (file)
index 2c074a5..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/* === S Y N F I G ========================================================= */
-/*!    \file state_draw.h
-**     \brief Template Header
-**
-**     $Id$
-**
-**     \legal
-**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
-**
-**     This package is free software; you can redistribute it and/or
-**     modify it under the terms of the GNU General Public License as
-**     published by the Free Software Foundation; either version 2 of
-**     the License, or (at your option) any later version.
-**
-**     This package is distributed in the hope that it will be useful,
-**     but WITHOUT ANY WARRANTY; without even the implied warranty of
-**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-**     General Public License for more details.
-**     \endlegal
-*/
-/* ========================================================================= */
-
-/* === S T A R T =========================================================== */
-
-#ifndef __SYNFIG_STUDIO_STATE_ROTOSCOPE_H
-#define __SYNFIG_STUDIO_STATE_ROTOSCOPE_H
-
-/* === H E A D E R S ======================================================= */
-
-#include "smach.h"
-
-
-/* === M A C R O S ========================================================= */
-
-/* === T Y P E D E F S ===================================================== */
-
-/* === C L A S S E S & S T R U C T S ======================================= */
-
-namespace studio {
-
-class StateDraw_Context;
-
-class StateDraw : public Smach::state<StateDraw_Context>
-{
-public:
-       StateDraw();
-       ~StateDraw();
-}; // END of class StateDraw
-
-extern StateDraw state_draw;
-
-}; // END of namespace studio
-
-/* === E N D =============================================================== */
-
-#endif
diff --git a/synfig-studio/src/gui/state_eyedrop.cpp b/synfig-studio/src/gui/state_eyedrop.cpp
deleted file mode 100644 (file)
index e7cf4bb..0000000
+++ /dev/null
@@ -1,146 +0,0 @@
-/* === S Y N F I G ========================================================= */
-/*!    \file state_eyedrop.cpp
-**     \brief Template File
-**
-**     $Id$
-**
-**     \legal
-**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
-**
-**     This package is free software; you can redistribute it and/or
-**     modify it under the terms of the GNU General Public License as
-**     published by the Free Software Foundation; either version 2 of
-**     the License, or (at your option) any later version.
-**
-**     This package is distributed in the hope that it will be useful,
-**     but WITHOUT ANY WARRANTY; without even the implied warranty of
-**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-**     General Public License for more details.
-**     \endlegal
-*/
-/* ========================================================================= */
-
-/* === H E A D E R S ======================================================= */
-
-#ifdef USING_PCH
-#      include "pch.h"
-#else
-#ifdef HAVE_CONFIG_H
-#      include <config.h>
-#endif
-
-#include "state_eyedrop.h"
-#include "state_normal.h"
-#include "workarea.h"
-#include <synfig/context.h>
-#include "app.h"
-#include "dialogs/dialog_color.h"
-#include "event_mouse.h"
-#include "event_layerclick.h"
-#include "toolbox.h"
-#include "canvasview.h"
-#include <synfigapp/main.h>
-
-#include "general.h"
-
-#endif
-
-/* === U S I N G =========================================================== */
-
-using namespace std;
-using namespace etl;
-using namespace synfig;
-using namespace studio;
-
-/* === M A C R O S ========================================================= */
-
-/* === C L A S S E S & S T R U C T S ======================================= */
-
-class studio::StateEyedrop_Context
-{
-       CanvasView *canvas_view;
-       CanvasView::IsWorking is_working;
-
-public:
-       StateEyedrop_Context(CanvasView *canvas_view);
-       ~StateEyedrop_Context();
-
-       Smach::event_result event_stop_handler(const Smach::event& x);
-
-       Smach::event_result event_refresh_handler(const Smach::event& x);
-
-       Smach::event_result event_workarea_mouse_button_down_handler(const Smach::event& x);
-
-}; // END of class StateEyedrop_Context
-
-/* === G L O B A L S ======================================================= */
-
-StateEyedrop studio::state_eyedrop;
-
-/* === P R O C E D U R E S ================================================= */
-
-/* === M E T H O D S ======================================================= */
-
-StateEyedrop::StateEyedrop():
-       Smach::state<StateEyedrop_Context>("eyedrop")
-{
-       insert(event_def(EVENT_LAYER_SELECTION_CHANGED,&StateEyedrop_Context::event_stop_handler));
-       insert(event_def(EVENT_STOP,&StateEyedrop_Context::event_stop_handler));
-       insert(event_def(EVENT_REFRESH,&StateEyedrop_Context::event_refresh_handler));
-       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateEyedrop_Context::event_workarea_mouse_button_down_handler));
-}
-
-StateEyedrop::~StateEyedrop()
-{
-}
-
-StateEyedrop_Context::StateEyedrop_Context(CanvasView *canvas_view):
-       canvas_view(canvas_view),
-       is_working(*canvas_view)
-{
-       synfig::info("Entered Eyedrop State");
-       canvas_view->work_area->set_cursor(Gdk::Cursor(Gdk::CROSSHAIR));
-
-       App::toolbox->refresh();
-}
-
-StateEyedrop_Context::~StateEyedrop_Context()
-{
-       synfig::info("Left Eyedrop State");
-       canvas_view->work_area->reset_cursor();
-       App::toolbox->refresh();
-}
-
-Smach::event_result
-StateEyedrop_Context::event_stop_handler(const Smach::event& /*x*/)
-{
-       //synfig::info("STATE EYEDROP: Received Stop Event");
-       //throw Smach::egress_exception();
-       throw &state_normal;
-       return Smach::RESULT_OK;
-//     canvas_view->get_smach().pop_state();
-//     return Smach::RESULT_ACCEPT;
-}
-
-Smach::event_result
-StateEyedrop_Context::event_refresh_handler(const Smach::event& /*x*/)
-{
-       synfig::info("STATE EYEDROP: Received Refresh Event");
-       canvas_view->work_area->queue_render_preview();
-       return Smach::RESULT_ACCEPT;
-}
-
-Smach::event_result
-StateEyedrop_Context::event_workarea_mouse_button_down_handler(const Smach::event& x)
-{
-       synfig::info("STATE EYEDROP: Received mouse button down Event");
-       const EventMouse& event(*reinterpret_cast<const EventMouse*>(&x));
-       if(event.button==BUTTON_LEFT)
-       {
-               Color color(canvas_view->get_canvas()->get_context().get_color(event.pos));
-               synfigapp::Main::set_outline_color(color);
-               studio::App::dialog_color->set_color(color);
-               return Smach::RESULT_ACCEPT;
-       }
-       return Smach::RESULT_OK;
-}
diff --git a/synfig-studio/src/gui/state_eyedrop.h b/synfig-studio/src/gui/state_eyedrop.h
deleted file mode 100644 (file)
index 4a90021..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/* === S Y N F I G ========================================================= */
-/*!    \file state_eyedrop.h
-**     \brief Template Header
-**
-**     $Id$
-**
-**     \legal
-**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
-**
-**     This package is free software; you can redistribute it and/or
-**     modify it under the terms of the GNU General Public License as
-**     published by the Free Software Foundation; either version 2 of
-**     the License, or (at your option) any later version.
-**
-**     This package is distributed in the hope that it will be useful,
-**     but WITHOUT ANY WARRANTY; without even the implied warranty of
-**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-**     General Public License for more details.
-**     \endlegal
-*/
-/* ========================================================================= */
-
-/* === S T A R T =========================================================== */
-
-#ifndef __SYNFIG_STATE_EYEDROP_H
-#define __SYNFIG_STATE_EYEDROP_H
-
-/* === H E A D E R S ======================================================= */
-
-#include "smach.h"
-
-
-/* === M A C R O S ========================================================= */
-
-/* === T Y P E D E F S ===================================================== */
-
-/* === C L A S S E S & S T R U C T S ======================================= */
-
-namespace studio {
-
-class StateEyedrop_Context;
-
-class StateEyedrop : public Smach::state<StateEyedrop_Context>
-{
-public:
-       StateEyedrop();
-       ~StateEyedrop();
-}; // END of class StateEyedrop
-
-extern StateEyedrop state_eyedrop;
-
-}; // END of namespace studio
-
-/* === E N D =============================================================== */
-
-#endif
diff --git a/synfig-studio/src/gui/state_fill.cpp b/synfig-studio/src/gui/state_fill.cpp
deleted file mode 100644 (file)
index cf6c750..0000000
+++ /dev/null
@@ -1,182 +0,0 @@
-/* === S Y N F I G ========================================================= */
-/*!    \file state_fill.cpp
-**     \brief Template File
-**
-**     $Id$
-**
-**     \legal
-**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
-**
-**     This package is free software; you can redistribute it and/or
-**     modify it under the terms of the GNU General Public License as
-**     published by the Free Software Foundation; either version 2 of
-**     the License, or (at your option) any later version.
-**
-**     This package is distributed in the hope that it will be useful,
-**     but WITHOUT ANY WARRANTY; without even the implied warranty of
-**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-**     General Public License for more details.
-**     \endlegal
-*/
-/* ========================================================================= */
-
-/* === H E A D E R S ======================================================= */
-
-#ifdef USING_PCH
-#      include "pch.h"
-#else
-#ifdef HAVE_CONFIG_H
-#      include <config.h>
-#endif
-
-#include "state_fill.h"
-#include "state_normal.h"
-#include "workarea.h"
-#include <synfig/context.h>
-#include "app.h"
-#include "dialogs/dialog_color.h"
-#include "event_mouse.h"
-#include "event_layerclick.h"
-#include "toolbox.h"
-#include "canvasview.h"
-#include <synfigapp/main.h>
-
-#include "general.h"
-
-#endif
-
-/* === U S I N G =========================================================== */
-
-using namespace std;
-using namespace etl;
-using namespace synfig;
-using namespace studio;
-
-/* === M A C R O S ========================================================= */
-
-/* === C L A S S E S & S T R U C T S ======================================= */
-
-class studio::StateFill_Context
-{
-       CanvasView *canvas_view;
-       CanvasView::IsWorking is_working;
-
-public:
-       StateFill_Context(CanvasView *canvas_view);
-       ~StateFill_Context();
-
-       Smach::event_result event_stop_handler(const Smach::event& x);
-
-       Smach::event_result event_refresh_handler(const Smach::event& x);
-
-       Smach::event_result event_workarea_layer_clicked_handler(const Smach::event& x);
-
-
-       etl::handle<CanvasView> get_canvas_view()const{return canvas_view;}
-       etl::handle<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view->canvas_interface();}
-       synfig::Canvas::Handle get_canvas()const{return canvas_view->get_canvas();}
-       WorkArea * get_work_area()const{return canvas_view->get_work_area();}
-
-
-}; // END of class StateFill_Context
-
-/* === G L O B A L S ======================================================= */
-
-StateFill studio::state_fill;
-
-/* === P R O C E D U R E S ================================================= */
-
-/* === M E T H O D S ======================================================= */
-
-StateFill::StateFill():
-       Smach::state<StateFill_Context>("fill")
-{
-       insert(event_def(EVENT_LAYER_SELECTION_CHANGED,&StateFill_Context::event_stop_handler));
-       insert(event_def(EVENT_STOP,&StateFill_Context::event_stop_handler));
-       insert(event_def(EVENT_REFRESH,&StateFill_Context::event_refresh_handler));
-       insert(event_def(EVENT_WORKAREA_LAYER_CLICKED,&StateFill_Context::event_workarea_layer_clicked_handler));
-}
-
-StateFill::~StateFill()
-{
-}
-
-StateFill_Context::StateFill_Context(CanvasView *canvas_view):
-       canvas_view(canvas_view),
-       is_working(*canvas_view)
-{
-       synfig::info("Entered Fill State");
-       canvas_view->work_area->set_cursor(Gdk::CROSSHAIR);
-
-       App::toolbox->refresh();
-}
-
-StateFill_Context::~StateFill_Context()
-{
-       synfig::info("Left Fill State");
-       canvas_view->work_area->reset_cursor();
-       App::toolbox->refresh();
-}
-
-Smach::event_result
-StateFill_Context::event_stop_handler(const Smach::event& /*x*/)
-{
-       synfig::info("STATE FILL: Received Stop Event");
-       //throw Smach::egress_exception();
-       throw &state_normal;
-       return Smach::RESULT_OK;
-//     canvas_view->get_smach().pop_state();
-//     return Smach::RESULT_ACCEPT;
-}
-
-Smach::event_result
-StateFill_Context::event_refresh_handler(const Smach::event& /*x*/)
-{
-       synfig::info("STATE FILL: Received Refresh Event");
-       canvas_view->work_area->queue_render_preview();
-       return Smach::RESULT_ACCEPT;
-}
-
-Smach::event_result
-StateFill_Context::event_workarea_layer_clicked_handler(const Smach::event& x)
-{
-       synfig::info("STATE FILL: Received layer clicked Event");
-       const EventLayerClick& event(*reinterpret_cast<const EventLayerClick*>(&x));
-
-       if(!event.layer)
-       {
-               get_canvas_view()->get_ui_interface()->warning(_("No layer here"));
-               return Smach::RESULT_ACCEPT;
-       }
-
-
-       //synfigapp::Action::Handle action(synfigapp::Action::create("ValueDescSet"));
-       synfigapp::ValueDesc value_desc(event.layer,"color");
-
-       if(!get_canvas_interface()->change_value(value_desc,ValueBase(synfigapp::Main::get_fill_color())))
-       {
-               get_canvas_view()->get_ui_interface()->warning(_("Unable to set layer color"));
-               return Smach::RESULT_ERROR;
-       }
-       /*
-       assert(action);
-
-       action->set_param("canvas",get_canvas());
-       action->set_param("canvas_interface",get_canvas_interface());
-       action->set_param("value_desc",value_desc);
-       action->set_param("time",get_canvas_interface()->get_time());
-       //action->set_param("layer",event.layer);
-       //if(!action->set_param("param",String("color")))
-       //      synfig::error("LayerParamConnect didn't like \"param\"");
-       if(!action->set_param("new_value",ValueBase(synfigapp::Main::get_fill_color())))
-               synfig::error("LayerParamConnect didn't like \"fill_color\"");
-
-       if(!get_canvas_interface()->get_instance()->perform_action(action))
-       {
-               get_canvas_view()->get_ui_interface()->warning(_("Unable to set layer color"));
-               return Smach::RESULT_ERROR;
-       }
-       get_canvas_view()->get_ui_interface()->task(_("Idle"));
-       */
-       return Smach::RESULT_ACCEPT;
-}
diff --git a/synfig-studio/src/gui/state_fill.h b/synfig-studio/src/gui/state_fill.h
deleted file mode 100644 (file)
index 349a1ce..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/* === S Y N F I G ========================================================= */
-/*!    \file state_fill.h
-**     \brief Template Header
-**
-**     $Id$
-**
-**     \legal
-**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
-**
-**     This package is free software; you can redistribute it and/or
-**     modify it under the terms of the GNU General Public License as
-**     published by the Free Software Foundation; either version 2 of
-**     the License, or (at your option) any later version.
-**
-**     This package is distributed in the hope that it will be useful,
-**     but WITHOUT ANY WARRANTY; without even the implied warranty of
-**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-**     General Public License for more details.
-**     \endlegal
-*/
-/* ========================================================================= */
-
-/* === S T A R T =========================================================== */
-
-#ifndef __SYNFIG_STATE_FILL_H
-#define __SYNFIG_STATE_FILL_H
-
-/* === H E A D E R S ======================================================= */
-
-#include "smach.h"
-
-
-/* === M A C R O S ========================================================= */
-
-/* === T Y P E D E F S ===================================================== */
-
-/* === C L A S S E S & S T R U C T S ======================================= */
-
-namespace studio {
-
-class StateFill_Context;
-
-class StateFill : public Smach::state<StateFill_Context>
-{
-public:
-       StateFill();
-       ~StateFill();
-}; // END of class StateFill
-
-extern StateFill state_fill;
-
-}; // END of namespace studio
-
-/* === E N D =============================================================== */
-
-#endif
diff --git a/synfig-studio/src/gui/state_gradient.cpp b/synfig-studio/src/gui/state_gradient.cpp
deleted file mode 100644 (file)
index 68f35c0..0000000
+++ /dev/null
@@ -1,546 +0,0 @@
-/* === S Y N F I G ========================================================= */
-/*!    \file state_gradient.cpp
-**     \brief Template File
-**
-**     $Id$
-**
-**     \legal
-**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
-**  Copyright (c) 2008 Chris Moore
-**
-**     This package is free software; you can redistribute it and/or
-**     modify it under the terms of the GNU General Public License as
-**     published by the Free Software Foundation; either version 2 of
-**     the License, or (at your option) any later version.
-**
-**     This package is distributed in the hope that it will be useful,
-**     but WITHOUT ANY WARRANTY; without even the implied warranty of
-**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-**     General Public License for more details.
-**     \endlegal
-*/
-/* ========================================================================= */
-
-/* === H E A D E R S ======================================================= */
-
-#ifdef USING_PCH
-#      include "pch.h"
-#else
-#ifdef HAVE_CONFIG_H
-#      include <config.h>
-#endif
-
-#include <gtkmm/dialog.h>
-#include <gtkmm/entry.h>
-
-#include <synfig/valuenode_dynamiclist.h>
-#include <synfigapp/action_system.h>
-
-#include "state_gradient.h"
-#include "state_normal.h"
-#include "canvasview.h"
-#include "workarea.h"
-#include "app.h"
-
-#include <synfigapp/action.h>
-#include "event_mouse.h"
-#include "event_layerclick.h"
-#include "toolbox.h"
-#include "dialog_tooloptions.h"
-#include <gtkmm/optionmenu.h>
-#include "duck.h"
-
-#include "widgets/widget_enum.h"
-#include <synfigapp/main.h>
-
-#include "general.h"
-
-#endif
-
-/* === U S I N G =========================================================== */
-
-using namespace std;
-using namespace etl;
-using namespace synfig;
-using namespace studio;
-
-/* === M A C R O S ========================================================= */
-
-enum
-{
-       GRADIENT_INTERPOLATION_LINEAR=0,
-       GRADIENT_RADIAL=1,
-       GRADIENT_CONICAL=2,
-       GRADIENT_SPIRAL=3
-};
-
-/* === G L O B A L S ======================================================= */
-
-StateGradient studio::state_gradient;
-
-/* === C L A S S E S & S T R U C T S ======================================= */
-
-class studio::StateGradient_Context : public sigc::trackable
-{
-       etl::handle<CanvasView> canvas_view_;
-       CanvasView::IsWorking is_working;
-
-       Duckmatic::Push duckmatic_push;
-
-       synfigapp::Settings& settings;
-
-       Point point_holder;
-
-       etl::handle<Duck> point2_duck;
-
-       void refresh_ducks();
-
-       bool prev_workarea_layer_status_;
-
-       Gtk::Table options_table;
-       Gtk::Entry entry_id;
-       Widget_Enum enum_type;
-#ifdef BLEND_METHOD_IN_TOOL_OPTIONS
-       Widget_Enum     enum_blend;
-#endif // BLEND_METHOD_IN_TOOL_OPTIONS
-
-public:
-       synfig::String get_id()const { return entry_id.get_text(); }
-       void set_id(const synfig::String& x) { return entry_id.set_text(x); }
-
-       int get_type()const { return enum_type.get_value(); }
-       void set_type(int x) { return enum_type.set_value(x); }
-
-#ifdef BLEND_METHOD_IN_TOOL_OPTIONS
-       int get_blend()const { return enum_blend.get_value(); }
-       void set_blend(int x) { return enum_blend.set_value(x); }
-#endif // BLEND_METHOD_IN_TOOL_OPTIONS
-
-       Smach::event_result event_stop_handler(const Smach::event& x);
-
-       Smach::event_result event_refresh_handler(const Smach::event& x);
-
-       Smach::event_result event_mouse_click_handler(const Smach::event& x);
-       Smach::event_result event_refresh_tool_options(const Smach::event& x);
-
-       void refresh_tool_options();
-
-       StateGradient_Context(CanvasView* canvas_view);
-
-       ~StateGradient_Context();
-
-       const etl::handle<CanvasView>& get_canvas_view()const{return canvas_view_;}
-       etl::handle<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view_->canvas_interface();}
-       synfig::Canvas::Handle get_canvas()const{return canvas_view_->get_canvas();}
-       WorkArea * get_work_area()const{return canvas_view_->get_work_area();}
-
-       //void on_user_click(synfig::Point point);
-       void load_settings();
-       void save_settings();
-       void reset();
-       void increment_id();
-
-       void make_gradient(const Point& p1, const Point& p2);
-       bool egress_on_selection_change;
-       Smach::event_result event_layer_selection_changed_handler(const Smach::event& /*x*/)
-       {
-               if(egress_on_selection_change)
-                       throw &state_normal; //throw Smach::egress_exception();
-               return Smach::RESULT_OK;
-       }
-
-};     // END of class StateGradient_Context
-
-/* === M E T H O D S ======================================================= */
-
-StateGradient::StateGradient():
-       Smach::state<StateGradient_Context>("gradient")
-{
-       insert(event_def(EVENT_LAYER_SELECTION_CHANGED,&StateGradient_Context::event_layer_selection_changed_handler));
-       insert(event_def(EVENT_STOP,&StateGradient_Context::event_stop_handler));
-       insert(event_def(EVENT_TABLES_SHOW,&StateGradient_Context::event_stop_handler));
-       insert(event_def(EVENT_REFRESH,&StateGradient_Context::event_refresh_handler));
-       insert(event_def(EVENT_REFRESH_DUCKS,&StateGradient_Context::event_refresh_handler));
-       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateGradient_Context::event_mouse_click_handler));
-       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DRAG,&StateGradient_Context::event_mouse_click_handler));
-       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_UP,&StateGradient_Context::event_mouse_click_handler));
-       insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateGradient_Context::event_refresh_tool_options));
-}
-
-StateGradient::~StateGradient()
-{
-}
-
-void
-StateGradient_Context::load_settings()
-{
-       String value;
-
-       if(settings.get_value("gradient.id",value))
-               set_id(value);
-       else
-               set_id("Gradient");
-
-       if(settings.get_value("gradient.type",value))
-               set_type(atoi(value.c_str()));
-       else
-               set_type(GRADIENT_INTERPOLATION_LINEAR);
-
-#ifdef BLEND_METHOD_IN_TOOL_OPTIONS
-       if(settings.get_value("gradient.blend",value))
-               set_blend(atoi(value.c_str()));
-       else
-               set_blend(Color::BLEND_COMPOSITE);
-#endif // BLEND_METHOD_IN_TOOL_OPTIONS
-}
-
-void
-StateGradient_Context::save_settings()
-{
-       settings.set_value("gradient.id",get_id().c_str());
-       settings.set_value("gradient.type",strprintf("%d",get_type()));
-#ifdef BLEND_METHOD_IN_TOOL_OPTIONS
-       settings.set_value("gradient.blend",strprintf("%d",get_blend()));
-#endif // BLEND_METHOD_IN_TOOL_OPTIONS
-}
-
-void
-StateGradient_Context::reset()
-{
-       refresh_ducks();
-}
-
-void
-StateGradient_Context::increment_id()
-{
-       String id(get_id());
-       int number=1;
-       int digits=0;
-
-       if(id.empty())
-               id="Gradient";
-
-       // If there is a number
-       // already at the end of the
-       // id, then remove it.
-       if(id[id.size()-1]<='9' && id[id.size()-1]>='0')
-       {
-               // figure out how many digits it is
-               for (digits = 0;
-                        (int)id.size()-1 >= digits && id[id.size()-1-digits] <= '9' && id[id.size()-1-digits] >= '0';
-                        digits++)
-                       ;
-
-               String str_number;
-               str_number=String(id,id.size()-digits,id.size());
-               id=String(id,0,id.size()-digits);
-
-               number=atoi(str_number.c_str());
-       }
-       else
-       {
-               number=1;
-               digits=3;
-       }
-
-       number++;
-
-       // Add the number back onto the id
-       {
-               const String format(strprintf("%%0%dd",digits));
-               id+=strprintf(format.c_str(),number);
-       }
-
-       // Set the ID
-       set_id(id);
-}
-
-StateGradient_Context::StateGradient_Context(CanvasView* canvas_view):
-       canvas_view_(canvas_view),
-       is_working(*canvas_view),
-       duckmatic_push(get_work_area()),
-       settings(synfigapp::Main::get_selected_input_device()->settings()),
-       prev_workarea_layer_status_(get_work_area()->get_allow_layer_clicks()),
-       entry_id()
-{
-       egress_on_selection_change=true;
-       // Set up the tool options dialog
-       options_table.attach(*manage(new Gtk::Label(_("Gradient Tool"))),       0, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(entry_id,                                                                          0, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-
-       enum_type.set_param_desc(ParamDesc("type")
-               .set_local_name(_("Gradient Type"))
-               .set_description(_("Determines the type of Gradient used"))
-               .set_hint("enum")
-               .add_enum_value(GRADIENT_INTERPOLATION_LINEAR,"linear",_("Linear"))
-               .add_enum_value(GRADIENT_RADIAL,"radial",_("Radial"))
-               .add_enum_value(GRADIENT_CONICAL,"conical",_("Conical"))
-               .add_enum_value(GRADIENT_SPIRAL,"spiral",_("Spiral")));
-
-#ifdef BLEND_METHOD_IN_TOOL_OPTIONS
-       enum_blend.set_param_desc(ParamDesc(Color::BLEND_COMPOSITE,"blend_method")
-               .set_local_name(_("Blend Method"))
-               .set_description(_("The blend method the gradient will use")));
-#endif // BLEND_METHOD_IN_TOOL_OPTIONS
-
-       load_settings();
-
-       options_table.attach(enum_type, 0, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-#ifdef BLEND_METHOD_IN_TOOL_OPTIONS
-       options_table.attach(enum_blend, 0, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-#endif // BLEND_METHOD_IN_TOOL_OPTIONS
-
-       options_table.show_all();
-       refresh_tool_options();
-       App::dialog_tool_options->present();
-
-
-       // Turn off layer clicking
-       get_work_area()->set_allow_layer_clicks(false);
-
-       get_work_area()->set_cursor(Gdk::CROSSHAIR);
-
-       // clear out the ducks
-       get_work_area()->clear_ducks();
-
-       // Refresh the work area
-       get_work_area()->queue_draw();
-
-       get_work_area()->refresh_cursor();
-
-       // Hide the tables if they are showing
-       get_canvas_view()->hide_tables();
-
-       // Disable the time bar
-       //get_canvas_view()->set_sensitive_timebar(false);
-
-       // Connect a signal
-       //get_work_area()->signal_user_click().connect(sigc::mem_fun(*this,&studio::StateGradient_Context::on_user_click));
-
-       App::toolbox->refresh();
-}
-
-void
-StateGradient_Context::refresh_tool_options()
-{
-       App::dialog_tool_options->clear();
-       App::dialog_tool_options->set_widget(options_table);
-       App::dialog_tool_options->set_local_name(_("Gradient Tool"));
-       App::dialog_tool_options->set_name("gradient");
-}
-
-Smach::event_result
-StateGradient_Context::event_refresh_tool_options(const Smach::event& /*x*/)
-{
-       refresh_tool_options();
-       return Smach::RESULT_ACCEPT;
-}
-
-StateGradient_Context::~StateGradient_Context()
-{
-       save_settings();
-
-       // Restore layer clicking
-//     get_work_area()->set_allow_layer_clicks(prev_workarea_layer_status_);
-       get_work_area()->set_allow_layer_clicks(true);
-       get_work_area()->reset_cursor();
-
-       App::dialog_tool_options->clear();
-
-       // Enable the time bar
-       //get_canvas_view()->set_sensitive_timebar(true);
-
-       // Bring back the tables if they were out before
-       //if(prev_table_status)get_canvas_view()->show_tables();
-
-       // Refresh the work area
-       get_work_area()->queue_draw();
-
-       get_canvas_view()->queue_rebuild_ducks();
-
-       //get_canvas_view()->show_tables();
-
-       get_work_area()->refresh_cursor();
-
-       App::toolbox->refresh();
-}
-
-Smach::event_result
-StateGradient_Context::event_stop_handler(const Smach::event& /*x*/)
-{
-       //throw Smach::egress_exception();
-       throw &state_normal;
-       return Smach::RESULT_OK;
-}
-
-Smach::event_result
-StateGradient_Context::event_refresh_handler(const Smach::event& /*x*/)
-{
-       refresh_ducks();
-       return Smach::RESULT_ACCEPT;
-}
-
-void
-StateGradient_Context::make_gradient(const Point& _p1, const Point& _p2)
-{
-       synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("New Gradient"));
-       synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
-
-       Layer::Handle layer;
-
-       Canvas::Handle canvas(get_canvas_view()->get_canvas());
-       int depth(0);
-
-       // we are temporarily using the layer to hold something
-       layer=get_canvas_view()->get_selection_manager()->get_selected_layer();
-       if(layer)
-       {
-               depth=layer->get_depth();
-               canvas=layer->get_canvas();
-       }
-       const synfig::TransformStack& transform(get_canvas_view()->get_curr_transform_stack());
-       const Point p1(transform.unperform(_p1));
-       const Point p2(transform.unperform(_p2));
-
-       switch(get_type())
-       {
-       case GRADIENT_INTERPOLATION_LINEAR:
-
-               layer=get_canvas_interface()->add_layer_to("linear_gradient",canvas,depth);
-               if (!layer)
-               {
-                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
-                       group.cancel();
-                       return;
-               }
-               layer->set_param("p1",p1);
-               get_canvas_interface()->signal_layer_param_changed()(layer,"p1");
-               layer->set_param("p2",p2);
-               get_canvas_interface()->signal_layer_param_changed()(layer,"p2");
-               break;
-       case GRADIENT_RADIAL:
-               layer=get_canvas_interface()->add_layer_to("radial_gradient",canvas,depth);
-               if (!layer)
-               {
-                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
-                       group.cancel();
-                       return;
-               }
-               layer->set_param("center",p1);
-               get_canvas_interface()->signal_layer_param_changed()(layer,"center");
-               layer->set_param("radius",(p2-p1).mag());
-               get_canvas_interface()->signal_layer_param_changed()(layer,"radius");
-               break;
-       case GRADIENT_CONICAL:
-               layer=get_canvas_interface()->add_layer_to("conical_gradient",canvas,depth);
-               if (!layer)
-               {
-                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
-                       group.cancel();
-                       return;
-               }
-               layer->set_param("center",p1);
-               get_canvas_interface()->signal_layer_param_changed()(layer,"center");
-               {
-                       Vector diff(p2-p1);
-                       layer->set_param("angle",Angle::tan(diff[1],diff[0]));
-                       get_canvas_interface()->signal_layer_param_changed()(layer,"angle");
-               }
-               break;
-       case GRADIENT_SPIRAL:
-               layer=get_canvas_interface()->add_layer_to("spiral_gradient",canvas,depth);
-               if (!layer)
-               {
-                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
-                       group.cancel();
-                       return;
-               }
-               layer->set_param("center",p1);
-               get_canvas_interface()->signal_layer_param_changed()(layer,"center");
-               layer->set_param("radius",(p2-p1).mag());
-               get_canvas_interface()->signal_layer_param_changed()(layer,"radius");
-               {
-                       Vector diff(p2-p1);
-                       layer->set_param("angle",Angle::tan(diff[1],diff[0]));
-                       get_canvas_interface()->signal_layer_param_changed()(layer,"angle");
-               }
-               break;
-
-       default:
-               return;
-       }
-
-#ifdef BLEND_METHOD_IN_TOOL_OPTIONS
-       layer->set_param("blend_method",get_blend());
-       get_canvas_interface()->signal_layer_param_changed()(layer,"blend_method");
-#endif // BLEND_METHOD_IN_TOOL_OPTIONS
-
-       layer->set_description(get_id());
-       get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
-
-       egress_on_selection_change=false;
-       synfigapp::SelectionManager::LayerList layer_selection;
-       if (!getenv("SYNFIG_TOOLS_CLEAR_SELECTION"))
-               layer_selection = get_canvas_view()->get_selection_manager()->get_selected_layers();
-       get_canvas_interface()->get_selection_manager()->clear_selected_layers();
-       layer_selection.push_back(layer);
-       get_canvas_interface()->get_selection_manager()->set_selected_layers(layer_selection);
-       egress_on_selection_change=true;
-
-       reset();
-       increment_id();
-}
-
-Smach::event_result
-StateGradient_Context::event_mouse_click_handler(const Smach::event& x)
-{
-       const EventMouse& event(*reinterpret_cast<const EventMouse*>(&x));
-
-       if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_DOWN && event.button==BUTTON_LEFT)
-       {
-               point_holder=get_work_area()->snap_point_to_grid(event.pos);
-               etl::handle<Duck> duck=new Duck();
-               duck->set_point(point_holder);
-               duck->set_name("p1");
-               duck->set_type(Duck::TYPE_POSITION);
-               get_work_area()->add_duck(duck);
-
-               point2_duck=new Duck();
-               point2_duck->set_point(point_holder);
-               point2_duck->set_name("p2");
-               point2_duck->set_type(Duck::TYPE_POSITION);
-               get_work_area()->add_duck(point2_duck);
-
-               handle<Duckmatic::Bezier> bezier(new Duckmatic::Bezier());
-               bezier->p1=bezier->c1=duck;
-               bezier->p2=bezier->c2=point2_duck;
-               get_work_area()->add_bezier(bezier);
-
-               return Smach::RESULT_ACCEPT;
-       }
-
-       if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_DRAG && event.button==BUTTON_LEFT)
-       {
-               if (!point2_duck) return Smach::RESULT_OK;
-               point2_duck->set_point(get_work_area()->snap_point_to_grid(event.pos));
-               get_work_area()->queue_draw();
-               return Smach::RESULT_ACCEPT;
-       }
-
-       if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_UP && event.button==BUTTON_LEFT)
-       {
-               make_gradient(point_holder, get_work_area()->snap_point_to_grid(event.pos));
-               get_work_area()->clear_ducks();
-               return Smach::RESULT_ACCEPT;
-       }
-
-       return Smach::RESULT_OK;
-}
-
-
-void
-StateGradient_Context::refresh_ducks()
-{
-       get_work_area()->clear_ducks();
-       get_work_area()->queue_draw();
-}
diff --git a/synfig-studio/src/gui/state_gradient.h b/synfig-studio/src/gui/state_gradient.h
deleted file mode 100644 (file)
index 308b5ee..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/* === S Y N F I G ========================================================= */
-/*!    \file state_gradient.h
-**     \brief Template Header
-**
-**     $Id$
-**
-**     \legal
-**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
-**
-**     This package is free software; you can redistribute it and/or
-**     modify it under the terms of the GNU General Public License as
-**     published by the Free Software Foundation; either version 2 of
-**     the License, or (at your option) any later version.
-**
-**     This package is distributed in the hope that it will be useful,
-**     but WITHOUT ANY WARRANTY; without even the implied warranty of
-**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-**     General Public License for more details.
-**     \endlegal
-*/
-/* ========================================================================= */
-
-/* === S T A R T =========================================================== */
-
-#ifndef __SYNFIG_STUDIO_STATE_GRADIENT_H
-#define __SYNFIG_STUDIO_STATE_GRADIENT_H
-
-/* === H E A D E R S ======================================================= */
-
-#include "smach.h"
-
-
-/* === M A C R O S ========================================================= */
-
-/* === T Y P E D E F S ===================================================== */
-
-/* === C L A S S E S & S T R U C T S ======================================= */
-
-namespace studio {
-
-class StateGradient_Context;
-
-class StateGradient : public Smach::state<StateGradient_Context>
-{
-public:
-       StateGradient();
-       ~StateGradient();
-}; // END of class StateGradient
-
-extern StateGradient state_gradient;
-
-}; // END of namespace studio
-
-/* === E N D =============================================================== */
-
-#endif
diff --git a/synfig-studio/src/gui/state_mirror.cpp b/synfig-studio/src/gui/state_mirror.cpp
deleted file mode 100644 (file)
index 59fc759..0000000
+++ /dev/null
@@ -1,336 +0,0 @@
-/* === S Y N F I G ========================================================= */
-/*!    \file state_mirror.cpp
-**     \brief Template File
-**
-**     $Id$
-**
-**     \legal
-**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
-**     Copyright (c) 2009 Nikita Kitaev
-**
-**     This package is free software; you can redistribute it and/or
-**     modify it under the terms of the GNU General Public License as
-**     published by the Free Software Foundation; either version 2 of
-**     the License, or (at your option) any later version.
-**
-**     This package is distributed in the hope that it will be useful,
-**     but WITHOUT ANY WARRANTY; without even the implied warranty of
-**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-**     General Public License for more details.
-**     \endlegal
-*/
-/* ========================================================================= */
-
-/* === H E A D E R S ======================================================= */
-
-#ifdef USING_PCH
-#      include "pch.h"
-#else
-#ifdef HAVE_CONFIG_H
-#      include <config.h>
-#endif
-
-#include <gtkmm/dialog.h>
-#include <gtkmm/entry.h>
-
-#include <synfig/valuenode_dynamiclist.h>
-#include <synfigapp/action_system.h>
-
-#include "state_mirror.h"
-#include "state_normal.h"
-#include "canvasview.h"
-#include "workarea.h"
-#include "app.h"
-
-#include <synfigapp/action.h>
-#include "event_mouse.h"
-#include "event_layerclick.h"
-#include "toolbox.h"
-#include "dialog_tooloptions.h"
-#include <gtkmm/optionmenu.h>
-#include "duck.h"
-#include <synfigapp/main.h>
-
-#include "general.h"
-
-#endif
-
-/* === U S I N G =========================================================== */
-
-using namespace std;
-using namespace etl;
-using namespace synfig;
-using namespace studio;
-
-/* === M A C R O S ========================================================= */
-
-enum Axis {
-       AXIS_X,
-       AXIS_Y
-} ;
-
-/* === G L O B A L S ======================================================= */
-
-StateMirror studio::state_mirror;
-
-/* === C L A S S E S & S T R U C T S ======================================= */
-
-class DuckDrag_Mirror : public DuckDrag_Base
-{
-       synfig::Vector center;
-
-       std::vector<synfig::Vector> positions;
-
-public:
-       Axis axis;
-
-       DuckDrag_Mirror();
-       void begin_duck_drag(Duckmatic* duckmatic, const synfig::Vector& begin);
-       bool end_duck_drag(Duckmatic* duckmatic);
-       void duck_drag(Duckmatic* duckmatic, const synfig::Vector& vector);
-};
-
-class studio::StateMirror_Context : public sigc::trackable
-{
-       etl::handle<CanvasView> canvas_view_;
-       CanvasView::IsWorking is_working;
-
-       synfigapp::Settings& settings;
-
-       sigc::connection keypress_connect;
-       sigc::connection keyrelease_connect;
-
-       etl::handle<DuckDrag_Mirror> duck_dragger_;
-
-       Gtk::Table options_table;
-
-       Gtk::RadioButton::Group radiobutton_group;
-       Gtk::RadioButton radiobutton_axis_x;
-       Gtk::RadioButton radiobutton_axis_y;
-
-public:
-
-       Axis get_axis()const { return radiobutton_axis_x.get_active()?AXIS_X:AXIS_Y; }
-       void set_axis(Axis a)
-       {
-               if(a==AXIS_X)
-                       radiobutton_axis_x.set_active(true);
-               else
-                       radiobutton_axis_y.set_active(true);
-
-               duck_dragger_->axis=get_axis();
-       }
-
-       void update_axes()
-       {
-               duck_dragger_->axis=get_axis();
-               get_work_area()->set_cursor(get_axis() == AXIS_X?Gdk::SB_H_DOUBLE_ARROW:Gdk::SB_V_DOUBLE_ARROW);
-       }
-
-       Smach::event_result event_stop_handler(const Smach::event& x);
-       Smach::event_result event_refresh_tool_options(const Smach::event& x);
-
-       void refresh_tool_options();
-
-       StateMirror_Context(CanvasView* canvas_view);
-
-       ~StateMirror_Context();
-
-       const etl::handle<CanvasView>& get_canvas_view()const{return canvas_view_;}
-       etl::handle<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view_->canvas_interface();}
-       synfig::Canvas::Handle get_canvas()const{return canvas_view_->get_canvas();}
-       WorkArea * get_work_area()const{return canvas_view_->get_work_area();}
-
-       void load_settings();
-       void save_settings();
-
-       bool key_event(GdkEventKey *event);
-};     // END of class StateMirror_Context
-
-/* === M E T H O D S ======================================================= */
-
-StateMirror::StateMirror():
-       Smach::state<StateMirror_Context>("mirror")
-{
-       insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateMirror_Context::event_refresh_tool_options));
-       insert(event_def(EVENT_STOP,&StateMirror_Context::event_stop_handler));
-}
-
-StateMirror::~StateMirror()
-{
-}
-
-void
-StateMirror_Context::load_settings()
-{
-       String value;
-
-       settings.get_value("mirror.axis",value);
-       set_axis((Axis)atoi(value.c_str()));
-}
-
-void
-StateMirror_Context::save_settings()
-{
-       settings.set_value("mirror.lock_aspect",strprintf("%d",(int)get_axis()));
-}
-
-StateMirror_Context::StateMirror_Context(CanvasView* canvas_view):
-       canvas_view_(canvas_view),
-       is_working(*canvas_view),
-       settings(synfigapp::Main::get_selected_input_device()->settings()),
-       duck_dragger_(new DuckDrag_Mirror()),
-       radiobutton_axis_x(radiobutton_group,_("Horizontal")),
-       radiobutton_axis_y(radiobutton_group,_("Vertical"))
-{
-       // Set up the tool options dialog
-       options_table.attach(*manage(new Gtk::Label(_("Mirror Tool"))), 0, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(radiobutton_axis_x, 0, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(radiobutton_axis_y, 0, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(*manage(new Gtk::Label(_("(Shift key toggles axis)"))), 0, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-
-       radiobutton_axis_x.signal_toggled().connect(sigc::mem_fun(*this,&StateMirror_Context::update_axes));
-       radiobutton_axis_y.signal_toggled().connect(sigc::mem_fun(*this,&StateMirror_Context::update_axes));
-
-       options_table.show_all();
-       refresh_tool_options();
-       App::dialog_tool_options->present();
-
-       get_work_area()->set_allow_layer_clicks(true);
-       get_work_area()->set_duck_dragger(duck_dragger_);
-
-       keypress_connect=get_work_area()->signal_key_press_event().connect(sigc::mem_fun(*this,&StateMirror_Context::key_event),false);
-       keyrelease_connect=get_work_area()->signal_key_release_event().connect(sigc::mem_fun(*this,&StateMirror_Context::key_event),false);
-
-       get_work_area()->set_cursor(Gdk::SB_H_DOUBLE_ARROW);
-//     get_work_area()->reset_cursor();
-
-       App::toolbox->refresh();
-
-       set_axis(AXIS_X);
-       load_settings();
-}
-
-bool
-StateMirror_Context::key_event(GdkEventKey *event)
-{
-       if (event->keyval==GDK_Shift_L || event->keyval==GDK_Shift_R )
-       {
-               set_axis(get_axis()==AXIS_X ? AXIS_Y:AXIS_X);
-               get_work_area()->set_cursor(get_axis() == AXIS_X?Gdk::SB_H_DOUBLE_ARROW:Gdk::SB_V_DOUBLE_ARROW);
-       }
-
-       return false; //Pass on the event to other handlers, just in case
-}
-
-void
-StateMirror_Context::refresh_tool_options()
-{
-       App::dialog_tool_options->clear();
-       App::dialog_tool_options->set_widget(options_table);
-       App::dialog_tool_options->set_local_name(_("Mirror Tool"));
-       App::dialog_tool_options->set_name("mirror");
-}
-
-Smach::event_result
-StateMirror_Context::event_refresh_tool_options(const Smach::event& /*x*/)
-{
-       refresh_tool_options();
-       return Smach::RESULT_ACCEPT;
-}
-
-Smach::event_result
-StateMirror_Context::event_stop_handler(const Smach::event& /*x*/)
-{
-       throw &state_normal;
-       return Smach::RESULT_OK;
-}
-
-StateMirror_Context::~StateMirror_Context()
-{
-       save_settings();
-
-       get_work_area()->clear_duck_dragger();
-       get_work_area()->reset_cursor();
-
-       keypress_connect.disconnect();
-       keyrelease_connect.disconnect();
-
-       App::dialog_tool_options->clear();
-
-       App::toolbox->refresh();
-}
-
-DuckDrag_Mirror::DuckDrag_Mirror():
-       axis(AXIS_X)
-{
-}
-
-#ifndef EPSILON
-#define EPSILON        0.0000001
-#endif
-
-void
-DuckDrag_Mirror::begin_duck_drag(Duckmatic* duckmatic, const synfig::Vector& /*offset*/)
-{
-       const DuckList selected_ducks(duckmatic->get_selected_ducks());
-       DuckList::const_iterator iter;
-
-       positions.clear();
-       int i;
-       for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
-       {
-               Point p((*iter)->get_trans_point());
-               positions.push_back(p);
-       }
-
-}
-
-void
-DuckDrag_Mirror::duck_drag(Duckmatic* duckmatic, const synfig::Vector& vector)
-{
-       center=vector;
-       int i;
-
-       const DuckList selected_ducks(duckmatic->get_selected_ducks());
-       DuckList::const_iterator iter;
-
-       Time time(duckmatic->get_time());
-
-       // do the Vertex and Position ducks first
-       for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
-               if ((*iter)->get_type() == Duck::TYPE_VERTEX ||
-                       (*iter)->get_type() == Duck::TYPE_POSITION)
-               {
-                       Vector p(positions[i]);
-
-                       if              (axis==AXIS_X) p[0] = -(p[0]-center[0]) + center[0];
-                       else if (axis==AXIS_Y) p[1] = -(p[1]-center[1]) + center[1];
-
-                       (*iter)->set_trans_point(p);
-               }
-
-       // then do the other ducks
-       for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
-               if ((*iter)->get_type() != Duck::TYPE_VERTEX &&
-                       (*iter)->get_type() != Duck::TYPE_POSITION)
-               {
-                       // we don't need to mirror radius ducks - they're one-dimensional
-                       if ((*iter)->is_radius())
-                               continue;
-
-                       Vector p(positions[i]);
-
-                       if              (axis==AXIS_X) p[0] = -(p[0]-center[0]) + center[0];
-                       else if (axis==AXIS_Y) p[1] = -(p[1]-center[1]) + center[1];
-
-                       (*iter)->set_trans_point(p);
-               }
-}
-
-bool
-DuckDrag_Mirror::end_duck_drag(Duckmatic* duckmatic)
-{
-       duckmatic->signal_edited_selected_ducks();
-       return true;
-}
diff --git a/synfig-studio/src/gui/state_mirror.h b/synfig-studio/src/gui/state_mirror.h
deleted file mode 100644 (file)
index 4ac878e..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/* === S Y N F I G ========================================================= */
-/*!    \file state_mirror.h
-**     \brief Template Header
-**
-**     $Id$
-**
-**     \legal
-**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
-**
-**     This package is free software; you can redistribute it and/or
-**     modify it under the terms of the GNU General Public License as
-**     published by the Free Software Foundation; either version 2 of
-**     the License, or (at your option) any later version.
-**
-**     This package is distributed in the hope that it will be useful,
-**     but WITHOUT ANY WARRANTY; without even the implied warranty of
-**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-**     General Public License for more details.
-**     \endlegal
-*/
-/* ========================================================================= */
-
-/* === S T A R T =========================================================== */
-
-#ifndef __SYNFIG_STUDIO_STATE_MIRROR_H
-#define __SYNFIG_STUDIO_STATE_MIRROR_H
-
-/* === H E A D E R S ======================================================= */
-
-#include "smach.h"
-
-/* === M A C R O S ========================================================= */
-
-/* === T Y P E D E F S ===================================================== */
-
-/* === C L A S S E S & S T R U C T S ======================================= */
-
-namespace studio {
-
-class StateMirror_Context;
-
-class StateMirror : public Smach::state<StateMirror_Context>
-{
-public:
-       StateMirror();
-       ~StateMirror();
-}; // END of class StateMirror
-
-extern StateMirror state_mirror;
-
-}; // END of namespace studio
-
-/* === E N D =============================================================== */
-
-#endif
diff --git a/synfig-studio/src/gui/state_normal.cpp b/synfig-studio/src/gui/state_normal.cpp
deleted file mode 100644 (file)
index c763022..0000000
+++ /dev/null
@@ -1,824 +0,0 @@
-/* === S Y N F I G ========================================================= */
-/*!    \file state_normal.cpp
-**     \brief Template File
-**
-**     $Id$
-**
-**     \legal
-**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
-**     Copyright (c) 2007, 2008 Chris Moore
-**     Copyright (c) 2009 Nikita Kitaev
-**
-**     This package is free software; you can redistribute it and/or
-**     modify it under the terms of the GNU General Public License as
-**     published by the Free Software Foundation; either version 2 of
-**     the License, or (at your option) any later version.
-**
-**     This package is distributed in the hope that it will be useful,
-**     but WITHOUT ANY WARRANTY; without even the implied warranty of
-**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-**     General Public License for more details.
-**     \endlegal
-*/
-/* ========================================================================= */
-
-/* === H E A D E R S ======================================================= */
-
-#ifdef USING_PCH
-#      include "pch.h"
-#else
-#ifdef HAVE_CONFIG_H
-#      include <config.h>
-#endif
-
-#include <gtkmm/dialog.h>
-#include <gtkmm/entry.h>
-
-#include <synfig/valuenode_animated.h>
-#include <synfig/valuenode_blinecalcvertex.h>
-#include <synfig/valuenode_composite.h>
-#include <synfig/valuenode_const.h>
-#include <synfig/valuenode_dynamiclist.h>
-#include <synfigapp/action_system.h>
-
-#include "state_normal.h"
-#include "canvasview.h"
-#include "workarea.h"
-#include "app.h"
-
-#include <synfigapp/action.h>
-#include "event_mouse.h"
-#include "event_layerclick.h"
-#include "toolbox.h"
-#include "dialog_tooloptions.h"
-#include <gtkmm/optionmenu.h>
-#include "duck.h"
-#include <synfig/angle.h>
-#include <synfigapp/main.h>
-
-#include "general.h"
-#endif
-
-/* === U S I N G =========================================================== */
-
-using namespace std;
-using namespace etl;
-using namespace synfig;
-using namespace studio;
-
-/* === M A C R O S ========================================================= */
-
-#ifndef EPSILON
-#define EPSILON        0.0000001
-#endif
-
-/* === G L O B A L S ======================================================= */
-
-StateNormal studio::state_normal;
-
-/* === C L A S S E S & S T R U C T S ======================================= */
-
-class DuckDrag_Combo : public DuckDrag_Base
-{
-       synfig::Vector last_move;
-       synfig::Vector drag_offset;
-       synfig::Vector center;
-       synfig::Vector snap;
-
-       synfig::Angle original_angle;
-       synfig::Real original_mag;
-
-       std::vector<synfig::Vector> last_;
-       std::vector<synfig::Vector> positions;
-
-
-       bool bad_drag;
-       bool move_only;
-
-public:
-       etl::handle<CanvasView> canvas_view_;
-       bool scale;
-       bool rotate;
-       bool constrain;
-       DuckDrag_Combo();
-       void begin_duck_drag(Duckmatic* duckmatic, const synfig::Vector& begin);
-       bool end_duck_drag(Duckmatic* duckmatic);
-       void duck_drag(Duckmatic* duckmatic, const synfig::Vector& vector);
-
-       etl::handle<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view_->canvas_interface();}
-};
-
-
-class studio::StateNormal_Context : public sigc::trackable
-{
-       etl::handle<CanvasView> canvas_view_;
-
-       synfigapp::Settings& settings;
-
-       sigc::connection keypress_connect;
-       sigc::connection keyrelease_connect;
-
-       etl::handle<DuckDrag_Combo> duck_dragger_;
-
-       Gtk::Table options_table;
-
-       Gtk::CheckButton checkbutton_rotate;
-       Gtk::CheckButton checkbutton_scale;
-       Gtk::CheckButton checkbutton_constrain;
-
-public:
-
-       bool get_rotate_flag()const { return checkbutton_rotate.get_active(); }
-       void set_rotate_flag(bool x) { checkbutton_rotate.set_active(x); refresh_rotate_flag(); }
-       void refresh_rotate_flag() { if(duck_dragger_)duck_dragger_->rotate=get_rotate_flag(); }
-
-       bool get_scale_flag()const { return checkbutton_scale.get_active(); }
-       void set_scale_flag(bool x) { checkbutton_scale.set_active(x); refresh_scale_flag(); }
-       void refresh_scale_flag() { if(duck_dragger_)duck_dragger_->scale=get_scale_flag(); }
-
-       bool get_constrain_flag()const { return checkbutton_constrain.get_active(); }
-       void set_constrain_flag(bool x) { checkbutton_constrain.set_active(x); refresh_constrain_flag(); }
-       void refresh_constrain_flag() { if(duck_dragger_)duck_dragger_->constrain=get_constrain_flag(); }
-
-       StateNormal_Context(CanvasView* canvas_view);
-
-       ~StateNormal_Context();
-
-       const etl::handle<CanvasView>& get_canvas_view()const{return canvas_view_;}
-       etl::handle<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view_->canvas_interface();}
-       synfig::Canvas::Handle get_canvas()const{return canvas_view_->get_canvas();}
-       WorkArea * get_work_area()const{return canvas_view_->get_work_area();}
-
-       void load_settings();
-       void save_settings();
-
-       bool key_pressed(GdkEventKey *event);
-       bool key_released(GdkEventKey *event);
-
-       Smach::event_result event_stop_handler(const Smach::event& x);
-       Smach::event_result event_refresh_handler(const Smach::event& x);
-       Smach::event_result event_refresh_ducks_handler(const Smach::event& x);
-       Smach::event_result event_undo_handler(const Smach::event& x);
-       Smach::event_result event_redo_handler(const Smach::event& x);
-       Smach::event_result event_mouse_button_down_handler(const Smach::event& x);
-       Smach::event_result event_multiple_ducks_clicked_handler(const Smach::event& x);
-       Smach::event_result event_refresh_tool_options(const Smach::event& x);
-       void refresh_tool_options();
-       Smach::event_result event_layer_click(const Smach::event& x);
-
-
-};     // END of class StateNormal_Context
-
-/* === M E T H O D S ======================================================= */
-
-StateNormal::StateNormal():
-       Smach::state<StateNormal_Context>("normal")
-{
-       insert(event_def(EVENT_STOP,&StateNormal_Context::event_stop_handler));
-       insert(event_def(EVENT_REFRESH,&StateNormal_Context::event_refresh_handler));
-       insert(event_def(EVENT_REFRESH_DUCKS,&StateNormal_Context::event_refresh_ducks_handler));
-       insert(event_def(EVENT_UNDO,&StateNormal_Context::event_undo_handler));
-       insert(event_def(EVENT_REDO,&StateNormal_Context::event_redo_handler));
-       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateNormal_Context::event_mouse_button_down_handler));
-       insert(event_def(EVENT_WORKAREA_MULTIPLE_DUCKS_CLICKED,&StateNormal_Context::event_multiple_ducks_clicked_handler));
-       insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateNormal_Context::event_refresh_tool_options));
-       insert(event_def(EVENT_WORKAREA_LAYER_CLICKED,&StateNormal_Context::event_layer_click));
-
-}
-
-StateNormal::~StateNormal()
-{
-}
-
-void
-StateNormal_Context::load_settings()
-{
-       String value;
-
-       if(settings.get_value("normal.rotate",value) && value=="1")
-               set_rotate_flag(true);
-       else
-               set_rotate_flag(false);
-
-       if(settings.get_value("normal.scale",value) && value=="1")
-               set_scale_flag(true);
-       else
-               set_scale_flag(false);
-
-       if(settings.get_value("normal.constrain",value) && value=="1")
-               set_constrain_flag(true);
-       else
-               set_constrain_flag(false);
-
-}
-
-void
-StateNormal_Context::save_settings()
-{
-       settings.set_value("normal.rotate",get_rotate_flag()?"1":"0");
-       settings.set_value("normal.scale",get_scale_flag()?"1":"0");
-       settings.set_value("normal.constrain",get_constrain_flag()?"1":"0");
-}
-
-StateNormal_Context::StateNormal_Context(CanvasView* canvas_view):
-       canvas_view_(canvas_view),
-       settings(synfigapp::Main::get_selected_input_device()->settings()),
-       duck_dragger_(new DuckDrag_Combo()),
-       checkbutton_rotate(_("Rotate (Ctrl)")),
-       checkbutton_scale(_("Scale (Alt)")),
-       checkbutton_constrain(_("Constrain (Shift)"))
-{
-       duck_dragger_->canvas_view_=get_canvas_view();
-
-       // Set up the tool options dialog
-       options_table.attach(*manage(new Gtk::Label(_("Normal Tool"))), 0, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(checkbutton_rotate,                                                        0, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(checkbutton_scale,                                                 0, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(checkbutton_constrain,                                                     0, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-
-       checkbutton_rotate.signal_toggled().connect(sigc::mem_fun(*this,&StateNormal_Context::refresh_rotate_flag));
-       checkbutton_scale.signal_toggled().connect(sigc::mem_fun(*this,&StateNormal_Context::refresh_scale_flag));
-       checkbutton_constrain.signal_toggled().connect(sigc::mem_fun(*this,&StateNormal_Context::refresh_constrain_flag));
-
-
-       options_table.show_all();
-       refresh_tool_options();
-       //App::dialog_tool_options->set_widget(options_table);
-       //App::dialog_tool_options->present();
-
-       get_work_area()->set_allow_layer_clicks(true);
-       get_work_area()->set_duck_dragger(duck_dragger_);
-
-       keypress_connect=get_work_area()->signal_key_press_event().connect(sigc::mem_fun(*this,&StateNormal_Context::key_pressed),false);
-       keyrelease_connect=get_work_area()->signal_key_release_event().connect(sigc::mem_fun(*this,&StateNormal_Context::key_released),false);
-
-       //these will segfault
-//     get_work_area()->set_cursor(Gdk::CROSSHAIR);
-//     get_work_area()->reset_cursor();
-
-       App::toolbox->refresh();
-
-       load_settings();
-       refresh_scale_flag();
-}
-
-bool
-StateNormal_Context::key_pressed(GdkEventKey *event)
-{
-       switch(event->keyval)
-       {
-               case GDK_Control_L:
-               case GDK_Control_R:
-                       set_rotate_flag(true);
-                       break;
-               case GDK_Alt_L:
-               case GDK_Alt_R:
-                       set_scale_flag(true);
-                       break;
-               case GDK_Shift_L:
-               case GDK_Shift_R:
-                       set_constrain_flag(true);
-                       break;
-               default:
-                       break;
-       }
-       return false; //Pass on the event to other handlers, just in case
-}
-
-bool
-StateNormal_Context::key_released(GdkEventKey *event)
-{
-       switch(event->keyval)
-       {
-               case GDK_Control_L:
-               case GDK_Control_R:
-                       set_rotate_flag(false);
-                       break;
-               case GDK_Alt_L:
-               case GDK_Alt_R:
-                       set_scale_flag(false);
-                       break;
-               case GDK_Shift_L:
-               case GDK_Shift_R:
-                       set_constrain_flag(false);
-                       break;
-               default:
-                       break;
-       }
-       return false; //Pass on the event to other handlers
-}
-
-void
-StateNormal_Context::refresh_tool_options()
-{
-       App::dialog_tool_options->clear();
-       App::dialog_tool_options->set_widget(options_table);
-       App::dialog_tool_options->set_local_name(_("Normal Tool"));
-       App::dialog_tool_options->set_name("normal");
-}
-
-
-
-StateNormal_Context::~StateNormal_Context()
-{
-       save_settings();
-
-       get_work_area()->clear_duck_dragger();
-       get_work_area()->reset_cursor();
-
-       keypress_connect.disconnect();
-       keyrelease_connect.disconnect();
-
-       App::dialog_tool_options->clear();
-
-       App::toolbox->refresh();
-}
-
-DuckDrag_Combo::DuckDrag_Combo():
-       scale(false),
-       rotate(false),
-       constrain(false) // Lock aspect for scale; smooth move for translate
-{
-}
-
-void
-DuckDrag_Combo::begin_duck_drag(Duckmatic* duckmatic, const synfig::Vector& offset)
-{
-       last_move=Vector(1,1);
-
-       const DuckList selected_ducks(duckmatic->get_selected_ducks());
-       DuckList::const_iterator iter;
-
-       bad_drag=false;
-
-               drag_offset=duckmatic->find_duck(offset)->get_trans_point();
-
-               //snap=drag_offset-duckmatic->snap_point_to_grid(drag_offset);
-               //snap=offset-drag_offset_;
-               snap=Vector(0,0);
-
-       // Calculate center
-       Point vmin(100000000,100000000);
-       Point vmax(-100000000,-100000000);
-       //std::set<etl::handle<Duck> >::iterator iter;
-       positions.clear();
-       int i;
-       for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
-       {
-               Point p((*iter)->get_trans_point());
-               vmin[0]=min(vmin[0],p[0]);
-               vmin[1]=min(vmin[1],p[1]);
-               vmax[0]=max(vmax[0],p[0]);
-               vmax[1]=max(vmax[1],p[1]);
-               positions.push_back(p);
-       }
-       center=(vmin+vmax)*0.5;
-       if((vmin-vmax).mag()<=EPSILON)
-               move_only=true;
-       else
-               move_only=false;
-
-
-       synfig::Vector vect(offset-center);
-       original_angle=Angle::tan(vect[1],vect[0]);
-       original_mag=vect.mag();
-}
-
-
-void
-DuckDrag_Combo::duck_drag(Duckmatic* duckmatic, const synfig::Vector& vector)
-{
-       if (!duckmatic) return;
-
-       if(bad_drag)
-               return;
-
-       //Override axis lock set in workarea when holding down the shift key
-       if (!move_only && (scale || rotate))
-               duckmatic->set_axis_lock(false);
-
-       synfig::Vector vect;
-       if (move_only || (!scale && !rotate))
-               vect= duckmatic->snap_point_to_grid(vector)-drag_offset+snap;
-       else
-               vect= duckmatic->snap_point_to_grid(vector)-center+snap;
-
-       last_move=vect;
-
-       const DuckList selected_ducks(duckmatic->get_selected_ducks());
-       DuckList::const_iterator iter;
-
-       Time time(duckmatic->get_time());
-
-       int i;
-       if( move_only || (!scale && !rotate) )
-       {
-               for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
-               {
-                       if((*iter)->get_type()==Duck::TYPE_VERTEX || (*iter)->get_type()==Duck::TYPE_POSITION)
-                               (*iter)->set_trans_point(positions[i]+vect, time);
-               }
-               for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
-               {
-                       if((*iter)->get_type()!=Duck::TYPE_VERTEX&&(*iter)->get_type()!=Duck::TYPE_POSITION)
-                               (*iter)->set_trans_point(positions[i]+vect, time);
-               }
-       }
-
-       if (rotate)
-       {
-               Angle::deg angle(Angle::tan(vect[1],vect[0]));
-               angle=original_angle-angle;
-               if (constrain)
-               {
-                       float degrees = angle.get()/15;
-                       angle= Angle::deg (degrees>0?std::floor(degrees)*15:std::ceil(degrees)*15);
-               }
-               Real mag(vect.mag()/original_mag);
-               Real sine(Angle::sin(angle).get());
-               Real cosine(Angle::cos(angle).get());
-
-               for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
-               {
-                       if((*iter)->get_type()!=Duck::TYPE_VERTEX&&(*iter)->get_type()!=Duck::TYPE_POSITION)continue;
-
-                       Vector x(positions[i]-center),p;
-
-                       p[0]=cosine*x[0]+sine*x[1];
-                       p[1]=-sine*x[0]+cosine*x[1];
-                       if(scale)p*=mag;
-                       p+=center;
-                       (*iter)->set_trans_point(p, time);
-               }
-               for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
-               {
-                       if(!((*iter)->get_type()!=Duck::TYPE_VERTEX&&(*iter)->get_type()!=Duck::TYPE_POSITION))continue;
-
-                       Vector x(positions[i]-center),p;
-
-                       p[0]=cosine*x[0]+sine*x[1];
-                       p[1]=-sine*x[0]+cosine*x[1];
-                       if(scale)p*=mag;
-                       p+=center;
-                       (*iter)->set_trans_point(p, time);
-               }
-       } else if (scale)
-       {
-               if(!constrain)
-               {
-                       if(abs(drag_offset[0]-center[0])>EPSILON)
-                               vect[0]/=drag_offset[0]-center[0];
-                       else
-                               vect[0]=1;
-                       if(abs(drag_offset[1]-center[1])>EPSILON)
-                               vect[1]/=drag_offset[1]-center[1];
-                       else
-                               vect[1]=1;
-                       }
-               else
-               {
-                       //vect[0]=vect[1]=vect.mag()*0.707106781;
-                       Real amount(vect.mag()/(drag_offset-center).mag());
-                       vect[0]=vect[1]=amount;
-               }
-
-               if(vect[0]<EPSILON && vect[0]>-EPSILON)
-                       vect[0]=1;
-               if(vect[1]<EPSILON && vect[1]>-EPSILON)
-                       vect[1]=1;
-
-               for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
-               {
-                       if(((*iter)->get_type()!=Duck::TYPE_VERTEX&&(*iter)->get_type()!=Duck::TYPE_POSITION))continue;
-
-                       Vector p(positions[i]-center);
-
-                       p[0]*=vect[0];
-                       p[1]*=vect[1];
-                       p+=center;
-                       (*iter)->set_trans_point(p, time);
-               }
-               for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
-               {
-                       if(!((*iter)->get_type()!=Duck::TYPE_VERTEX&&(*iter)->get_type()!=Duck::TYPE_POSITION))continue;
-
-                       Vector p(positions[i]-center);
-
-                       p[0]*=vect[0];
-                       p[1]*=vect[1];
-                       p+=center;
-                       (*iter)->set_trans_point(p, time);
-               }
-       }
-
-       // then patch up the tangents for the vertices we've moved
-       duckmatic->update_ducks();
-
-       last_move=vect;
-}
-
-bool
-DuckDrag_Combo::end_duck_drag(Duckmatic* duckmatic)
-{
-       if(bad_drag)return false;
-
-       //synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Rotate Ducks"));
-
-       if((last_move-Vector(1,1)).mag()>0.0001)
-       {
-               duckmatic->signal_edited_selected_ducks();
-               return true;
-       }
-       else
-       {
-               duckmatic->signal_user_click_selected_ducks(0);
-               return false;
-       }
-}
-
-Smach::event_result
-StateNormal_Context::event_refresh_tool_options(const Smach::event& /*x*/)
-{
-       refresh_tool_options();
-       return Smach::RESULT_ACCEPT;
-}
-
-Smach::event_result
-StateNormal_Context::event_stop_handler(const Smach::event& /*x*/)
-{
-       // synfig::info("STATE NORMAL: Received Stop Event");
-       canvas_view_->stop();
-       return Smach::RESULT_ACCEPT;
-}
-
-Smach::event_result
-StateNormal_Context::event_refresh_handler(const Smach::event& /*x*/)
-{
-       // synfig::info("STATE NORMAL: Received Refresh Event");
-       canvas_view_->rebuild_tables();
-       canvas_view_->work_area->queue_render_preview();
-       return Smach::RESULT_ACCEPT;
-}
-
-Smach::event_result
-StateNormal_Context::event_refresh_ducks_handler(const Smach::event& /*x*/)
-{
-       // synfig::info("STATE NORMAL: Received Refresh Ducks");
-       canvas_view_->queue_rebuild_ducks();
-       return Smach::RESULT_ACCEPT;
-}
-
-Smach::event_result
-StateNormal_Context::event_undo_handler(const Smach::event& /*x*/)
-{
-       // synfig::info("STATE NORMAL: Received Undo Event");
-       canvas_view_->get_instance()->undo();
-       return Smach::RESULT_ACCEPT;
-}
-
-Smach::event_result
-StateNormal_Context::event_redo_handler(const Smach::event& /*x*/)
-{
-       // synfig::info("STATE NORMAL: Received Redo Event");
-       canvas_view_->get_instance()->redo();
-       return Smach::RESULT_ACCEPT;
-}
-
-Smach::event_result
-StateNormal_Context::event_mouse_button_down_handler(const Smach::event& x)
-{
-       // synfig::info("STATE NORMAL: Received mouse button down Event");
-
-       const EventMouse& event(*reinterpret_cast<const EventMouse*>(&x));
-
-       switch(event.button)
-       {
-       case BUTTON_RIGHT:
-               canvas_view_->popup_main_menu();
-               return Smach::RESULT_ACCEPT;
-       default:
-               return Smach::RESULT_OK;
-       }
-}
-
-Smach::event_result
-StateNormal_Context::event_layer_click(const Smach::event& x)
-{
-       const EventLayerClick& event(*reinterpret_cast<const EventLayerClick*>(&x));
-
-       if(event.layer)
-       {
-               // synfig::info("STATE NORMAL: Received layer click Event, \"%s\"",event.layer->get_name().c_str());
-       }
-       else
-       {
-               // synfig::info("STATE NORMAL: Received layer click Event with an empty layer.");
-       }
-
-       switch(event.button)
-       {
-       case BUTTON_LEFT:
-               if(!(event.modifier&Gdk::CONTROL_MASK))
-                       canvas_view_->get_selection_manager()->clear_selected_layers();
-               if(event.layer)
-               {
-                       std::list<Layer::Handle> layer_list(canvas_view_->get_selection_manager()->get_selected_layers());
-                       std::set<Layer::Handle> layers(layer_list.begin(),layer_list.end());
-                       if(layers.count(event.layer))
-                       {
-                               layers.erase(event.layer);
-                               layer_list=std::list<Layer::Handle>(layers.begin(),layers.end());
-                               canvas_view_->get_selection_manager()->clear_selected_layers();
-                               canvas_view_->get_selection_manager()->set_selected_layers(layer_list);
-                       }
-                       else
-                       {
-                               canvas_view_->get_selection_manager()->set_selected_layer(event.layer);
-                       }
-               }
-               return Smach::RESULT_ACCEPT;
-       case BUTTON_RIGHT:
-               canvas_view_->popup_layer_menu(event.layer);
-               return Smach::RESULT_ACCEPT;
-       default:
-               return Smach::RESULT_OK;
-       }
-}
-
-/*
-void
-StateNormal_Context::edit_several_waypoints(std::list<synfigapp::ValueDesc> value_desc_list)
-{
-       Gtk::Dialog dialog(
-               "Edit Multiple Waypoints",              // Title
-               true,           // Modal
-               true            // use_separator
-       );
-
-       Widget_WaypointModel widget_waypoint_model;
-       widget_waypoint_model.show();
-
-       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();
-
-       if(dialog.run()==0)
-               return;
-       synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Set Waypoints"));
-
-       std::list<synfigapp::ValueDesc>::iterator iter;
-       for(iter=value_desc_list.begin();iter!=value_desc_list.end();++iter)
-       {
-               synfigapp::ValueDesc value_desc(*iter);
-
-               if(!value_desc.is_valid())
-                       continue;
-
-               ValueNode_Animated::Handle value_node;
-
-               // If this value isn't a ValueNode_Animated, but
-               // it is somewhat constant, then go ahead and convert
-               // it to a ValueNode_Animated.
-               if(!value_desc.is_value_node() || ValueNode_Const::Handle::cast_dynamic(value_desc.get_value_node()))
-               {
-                       ValueBase value;
-                       if(value_desc.is_value_node())
-                               value=ValueNode_Const::Handle::cast_dynamic(value_desc.get_value_node())->get_value();
-                       else
-                               value=value_desc.get_value();
-
-                       value_node=ValueNode_Animated::create(value,get_canvas()->get_time());
-
-                       synfigapp::Action::Handle action;
-
-                       if(!value_desc.is_value_node())
-                       {
-                               action=synfigapp::Action::create("ValueDescConnect");
-                               action->set_param("dest",value_desc);
-                               action->set_param("src",ValueNode::Handle(value_node));
-                       }
-                       else
-                       {
-                               action=synfigapp::Action::create("ValueNodeReplace");
-                               action->set_param("dest",value_desc.get_value_node());
-                               action->set_param("src",ValueNode::Handle(value_node));
-                       }
-
-                       action->set_param("canvas",get_canvas());
-                       action->set_param("canvas_interface",get_canvas_interface());
-
-
-                       if(!get_canvas_interface()->get_instance()->perform_action(action))
-                       {
-                               get_canvas_view()->get_ui_interface()->error(_("Unable to convert to animated waypoint"));
-                               group.cancel();
-                               return;
-                       }
-               }
-               else
-               {
-                       if(value_desc.is_value_node())
-                               value_node=ValueNode_Animated::Handle::cast_dynamic(value_desc.get_value_node());
-               }
-
-
-               if(value_node)
-               {
-
-                       synfigapp::Action::Handle action(synfigapp::Action::create("WaypointSetSmart"));
-
-                       if(!action)
-                       {
-                               get_canvas_view()->get_ui_interface()->error(_("Unable to find WaypointSetSmart action"));
-                               group.cancel();
-                               return;
-                       }
-
-
-                       action->set_param("canvas",get_canvas());
-                       action->set_param("canvas_interface",get_canvas_interface());
-                       action->set_param("value_node",ValueNode::Handle(value_node));
-                       action->set_param("time",get_canvas()->get_time());
-                       action->set_param("model",widget_waypoint_model.get_waypoint_model());
-
-                       if(!get_canvas_interface()->get_instance()->perform_action(action))
-                       {
-                               get_canvas_view()->get_ui_interface()->error(_("Unable to set a specific waypoint"));
-                               group.cancel();
-                               return;
-                       }
-               }
-               else
-               {
-                       //get_canvas_view()->get_ui_interface()->error(_("Unable to animate a specific valuedesc"));
-                       //group.cancel();
-                       //return;
-               }
-
-       }
-}
-*/
-
-Smach::event_result
-StateNormal_Context::event_multiple_ducks_clicked_handler(const Smach::event& /*x*/)
-{
-       // synfig::info("STATE NORMAL: Received multiple duck click event");
-
-       //const EventMouse& event(*reinterpret_cast<const EventMouse*>(&x));
-
-       std::list<synfigapp::ValueDesc> value_desc_list;
-
-       // Create a list of value_descs associated with selection
-       const DuckList selected_ducks(get_work_area()->get_selected_ducks());
-       DuckList::const_iterator iter;
-       for(iter=selected_ducks.begin();iter!=selected_ducks.end();++iter)
-       {
-               synfigapp::ValueDesc value_desc((*iter)->get_value_desc());
-
-               if(!value_desc.is_valid())
-                       continue;
-
-               if(value_desc.get_value_type()==ValueBase::TYPE_BLINEPOINT && value_desc.is_value_node() && ValueNode_Composite::Handle::cast_dynamic(value_desc.get_value_node()))
-               {
-                       value_desc_list.push_back(
-                               synfigapp::ValueDesc(
-                                       ValueNode_Composite::Handle::cast_dynamic(value_desc.get_value_node())
-                                       ,ValueNode_Composite::Handle::cast_dynamic(value_desc.get_value_node())
-                                                               ->get_link_index_from_name("point")
-                               )
-                       );
-               }
-               else
-                       value_desc_list.push_back(value_desc);
-       }
-
-       Gtk::Menu *menu=manage(new Gtk::Menu());
-       menu->signal_hide().connect(sigc::bind(sigc::ptr_fun(&delete_widget), menu));
-
-       canvas_view_->get_instance()->make_param_menu(menu,canvas_view_->get_canvas(),value_desc_list);
-
-       /*
-       synfigapp::Action::ParamList param_list;
-       param_list=get_canvas_interface()->generate_param_list(value_desc_list);
-
-       canvas_view_->add_actions_to_menu(menu, param_list,synfigapp::Action::CATEGORY_VALUEDESC|synfigapp::Action::CATEGORY_VALUENODE);
-
-       menu->items().push_back(Gtk::Menu_Helpers::MenuElem(_("Edit Waypoints"),
-               sigc::bind(
-                       sigc::mem_fun(
-                               *this,
-                               &studio::StateNormal_Context::edit_several_waypoints
-                       ),
-                       value_desc_list
-               )
-       ));
-       */
-       menu->popup(3,gtk_get_current_event_time());
-
-       return Smach::RESULT_ACCEPT;
-}
-
-
diff --git a/synfig-studio/src/gui/state_normal.h b/synfig-studio/src/gui/state_normal.h
deleted file mode 100644 (file)
index 01b040b..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/* === S Y N F I G ========================================================= */
-/*!    \file state_normal.h
-**     \brief Template Header
-**
-**     $Id$
-**
-**     \legal
-**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
-**     Copyright (c) 2009 Nikita Kitaev
-**
-**     This package is free software; you can redistribute it and/or
-**     modify it under the terms of the GNU General Public License as
-**     published by the Free Software Foundation; either version 2 of
-**     the License, or (at your option) any later version.
-**
-**     This package is distributed in the hope that it will be useful,
-**     but WITHOUT ANY WARRANTY; without even the implied warranty of
-**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-**     General Public License for more details.
-**     \endlegal
-*/
-/* ========================================================================= */
-
-/* === S T A R T =========================================================== */
-
-#ifndef __SYNFIG_STUDIO_STATE_NORMAL_H
-#define __SYNFIG_STUDIO_STATE_NORMAL_H
-
-/* === H E A D E R S ======================================================= */
-
-#include "smach.h"
-
-
-/* === M A C R O S ========================================================= */
-
-/* === T Y P E D E F S ===================================================== */
-
-/* === C L A S S E S & S T R U C T S ======================================= */
-
-namespace studio {
-
-class StateNormal_Context;
-
-class StateNormal : public Smach::state<StateNormal_Context>
-{
-public:
-       StateNormal();
-       ~StateNormal();
-}; // END of class StateNormal
-
-extern StateNormal state_normal;
-
-}; // END of namespace studio
-
-/* === E N D =============================================================== */
-
-#endif
diff --git a/synfig-studio/src/gui/state_polygon.cpp b/synfig-studio/src/gui/state_polygon.cpp
deleted file mode 100644 (file)
index 7c11c05..0000000
+++ /dev/null
@@ -1,945 +0,0 @@
-/* === S Y N F I G ========================================================= */
-/*!    \file state_polygon.cpp
-**     \brief Template File
-**
-**     $Id$
-**
-**     \legal
-**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
-**     Copyright (c) 2007, 2008 Chris Moore
-**
-**     This package is free software; you can redistribute it and/or
-**     modify it under the terms of the GNU General Public License as
-**     published by the Free Software Foundation; either version 2 of
-**     the License, or (at your option) any later version.
-**
-**     This package is distributed in the hope that it will be useful,
-**     but WITHOUT ANY WARRANTY; without even the implied warranty of
-**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-**     General Public License for more details.
-**     \endlegal
-*/
-/* ========================================================================= */
-
-/* === H E A D E R S ======================================================= */
-
-#ifdef USING_PCH
-#      include "pch.h"
-#else
-#ifdef HAVE_CONFIG_H
-#      include <config.h>
-#endif
-
-#include <gtkmm/dialog.h>
-#include <gtkmm/entry.h>
-
-#include <synfig/valuenode_dynamiclist.h>
-#include <synfigapp/action_system.h>
-#include <synfig/valuenode_bline.h>
-
-#include "state_polygon.h"
-#include "state_normal.h"
-#include "canvasview.h"
-#include "workarea.h"
-#include "app.h"
-
-#include <synfigapp/action.h>
-#include "event_mouse.h"
-#include "event_layerclick.h"
-#include "toolbox.h"
-#include "dialog_tooloptions.h"
-#include <synfigapp/main.h>
-
-#include "general.h"
-
-#endif
-
-/* === U S I N G =========================================================== */
-
-using namespace std;
-using namespace etl;
-using namespace synfig;
-using namespace studio;
-
-/* === M A C R O S ========================================================= */
-
-/* === G L O B A L S ======================================================= */
-
-StatePolygon studio::state_polygon;
-
-/* === C L A S S E S & S T R U C T S ======================================= */
-
-class studio::StatePolygon_Context : public sigc::trackable
-{
-       etl::handle<CanvasView> canvas_view_;
-       CanvasView::IsWorking is_working;
-
-       bool prev_table_status;
-       bool prev_workarea_layer_status_;
-
-       Gtk::Menu menu;
-
-       Duckmatic::Push duckmatic_push;
-
-       std::list<synfig::Point> polygon_point_list;
-       synfigapp::Settings& settings;
-
-
-       bool on_polygon_duck_change(const synfig::Point &point, std::list<synfig::Point>::iterator iter);
-
-
-       void popup_handle_menu(synfigapp::ValueDesc value_desc);
-
-
-       void refresh_ducks();
-
-       Gtk::Table options_table;
-       Gtk::Entry entry_id;
-       Gtk::CheckButton checkbutton_invert;
-       Gtk::CheckButton checkbutton_layer_polygon;
-       Gtk::CheckButton checkbutton_layer_region;
-       Gtk::CheckButton checkbutton_layer_outline;
-       Gtk::CheckButton checkbutton_layer_curve_gradient;
-       Gtk::CheckButton checkbutton_layer_plant;
-       Gtk::CheckButton checkbutton_layer_link_origins;
-       Gtk::Button button_make;
-       Gtk::Adjustment  adj_feather;
-       Gtk::SpinButton  spin_feather;
-
-public:
-
-       // this counts the layers we create - they all have origins we can link
-       int layers_to_create()const
-       {
-               return
-                       get_layer_polygon_flag() +
-                       get_layer_region_flag() +
-                       get_layer_outline_flag() +
-                       get_layer_curve_gradient_flag() +
-                       get_layer_plant_flag();
-       }
-
-       synfig::String get_id()const { return entry_id.get_text(); }
-       void set_id(const synfig::String& x) { return entry_id.set_text(x); }
-
-       bool get_invert()const { return checkbutton_invert.get_active(); }
-       void set_invert(bool i) { checkbutton_invert.set_active(i); }
-
-       bool get_layer_polygon_flag()const { return checkbutton_layer_polygon.get_active(); }
-       void set_layer_polygon_flag(bool x) { return checkbutton_layer_polygon.set_active(x); }
-
-       bool get_layer_region_flag()const { return checkbutton_layer_region.get_active(); }
-       void set_layer_region_flag(bool x) { return checkbutton_layer_region.set_active(x); }
-
-       bool get_layer_outline_flag()const { return checkbutton_layer_outline.get_active(); }
-       void set_layer_outline_flag(bool x) { return checkbutton_layer_outline.set_active(x); }
-
-       bool get_layer_curve_gradient_flag()const { return checkbutton_layer_curve_gradient.get_active(); }
-       void set_layer_curve_gradient_flag(bool x) { return checkbutton_layer_curve_gradient.set_active(x); }
-
-       bool get_layer_plant_flag()const { return checkbutton_layer_plant.get_active(); }
-       void set_layer_plant_flag(bool x) { return checkbutton_layer_plant.set_active(x); }
-
-       bool get_layer_link_origins_flag()const { return checkbutton_layer_link_origins.get_active(); }
-       void set_layer_link_origins_flag(bool x) { return checkbutton_layer_link_origins.set_active(x); }
-
-       Real get_feather() const { return adj_feather.get_value(); }
-       void set_feather(Real x) { return adj_feather.set_value(x); }
-
-       Smach::event_result event_stop_handler(const Smach::event& x);
-
-       Smach::event_result event_refresh_handler(const Smach::event& x);
-
-       Smach::event_result event_mouse_click_handler(const Smach::event& x);
-       Smach::event_result event_refresh_tool_options(const Smach::event& x);
-       void refresh_tool_options();
-
-       StatePolygon_Context(CanvasView* canvas_view);
-
-       ~StatePolygon_Context();
-
-       const etl::handle<CanvasView>& get_canvas_view()const{return canvas_view_;}
-       etl::handle<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view_->canvas_interface();}
-       synfig::Canvas::Handle get_canvas()const{return canvas_view_->get_canvas();}
-       WorkArea * get_work_area()const{return canvas_view_->get_work_area();}
-
-       //void on_user_click(synfig::Point point);
-       void load_settings();
-       void save_settings();
-       void reset();
-       void increment_id();
-       bool egress_on_selection_change;
-       Smach::event_result event_layer_selection_changed_handler(const Smach::event& /*x*/)
-       {
-               if(egress_on_selection_change)
-                       throw &state_normal; //throw Smach::egress_exception();
-               return Smach::RESULT_OK;
-       }
-
-       void run();
-};     // END of class StatePolygon_Context
-
-/* === M E T H O D S ======================================================= */
-
-StatePolygon::StatePolygon():
-       Smach::state<StatePolygon_Context>("polygon")
-{
-       insert(event_def(EVENT_LAYER_SELECTION_CHANGED,&StatePolygon_Context::event_layer_selection_changed_handler));
-       insert(event_def(EVENT_STOP,&StatePolygon_Context::event_stop_handler));
-       insert(event_def(EVENT_REFRESH,&StatePolygon_Context::event_refresh_handler));
-       insert(event_def(EVENT_REFRESH_DUCKS,&StatePolygon_Context::event_refresh_handler));
-       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StatePolygon_Context::event_mouse_click_handler));
-       insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StatePolygon_Context::event_refresh_tool_options));
-}
-
-StatePolygon::~StatePolygon()
-{
-}
-
-void
-StatePolygon_Context::load_settings()
-{
-       String value;
-
-       if(settings.get_value("polygon.id",value))
-               set_id(value);
-       else
-               set_id("Polygon");
-
-       if(settings.get_value("polygon.invert",value) && value != "0")
-               set_invert(true);
-       else
-               set_invert(false);
-
-       if(settings.get_value("polygon.layer_polygon",value) && value=="0")
-               set_layer_polygon_flag(false);
-       else
-               set_layer_polygon_flag(true);
-
-       if(settings.get_value("polygon.layer_region",value) && value=="1")
-               set_layer_region_flag(true);
-       else
-               set_layer_region_flag(false);
-
-       if(settings.get_value("polygon.layer_outline",value) && value=="1")
-               set_layer_outline_flag(true);
-       else
-               set_layer_outline_flag(false);
-
-       if(settings.get_value("polygon.layer_curve_gradient",value) && value=="1")
-               set_layer_curve_gradient_flag(true);
-       else
-               set_layer_curve_gradient_flag(false);
-
-       if(settings.get_value("polygon.layer_plant",value) && value=="1")
-               set_layer_plant_flag(true);
-       else
-               set_layer_plant_flag(false);
-
-       if(settings.get_value("polygon.layer_link_origins",value) && value=="0")
-               set_layer_link_origins_flag(false);
-       else
-               set_layer_link_origins_flag(true);
-
-       if(settings.get_value("polygon.feather",value))
-       {
-               Real n = atof(value.c_str());
-               set_feather(n);
-       }
-}
-
-void
-StatePolygon_Context::save_settings()
-{
-       settings.set_value("polygon.id",get_id().c_str());
-       settings.set_value("polygon.invert",get_invert()?"1":"0");
-       settings.set_value("polygon.layer_polygon",get_layer_polygon_flag()?"1":"0");
-       settings.set_value("polygon.layer_outline",get_layer_outline_flag()?"1":"0");
-       settings.set_value("polygon.layer_region",get_layer_region_flag()?"1":"0");
-       settings.set_value("polygon.layer_curve_gradient",get_layer_curve_gradient_flag()?"1":"0");
-       settings.set_value("polygon.layer_plant",get_layer_plant_flag()?"1":"0");
-       settings.set_value("polygon.layer_link_origins",get_layer_link_origins_flag()?"1":"0");
-       settings.set_value("polygon.feather",strprintf("%f",get_feather()));
-}
-
-void
-StatePolygon_Context::reset()
-{
-       polygon_point_list.clear();
-       refresh_ducks();
-}
-
-void
-StatePolygon_Context::increment_id()
-{
-       String id(get_id());
-       int number=1;
-       int digits=0;
-
-       if(id.empty())
-               id="Polygon";
-
-       // If there is a number
-       // already at the end of the
-       // id, then remove it.
-       if(id[id.size()-1]<='9' && id[id.size()-1]>='0')
-       {
-               // figure out how many digits it is
-               for (digits = 0;
-                        (int)id.size()-1 >= digits && id[id.size()-1-digits] <= '9' && id[id.size()-1-digits] >= '0';
-                        digits++)
-                       ;
-
-               String str_number;
-               str_number=String(id,id.size()-digits,id.size());
-               id=String(id,0,id.size()-digits);
-
-               number=atoi(str_number.c_str());
-       }
-       else
-       {
-               number=1;
-               digits=3;
-       }
-
-       number++;
-
-       // Add the number back onto the id
-       {
-               const String format(strprintf("%%0%dd",digits));
-               id+=strprintf(format.c_str(),number);
-       }
-
-       // Set the ID
-       set_id(id);
-}
-
-StatePolygon_Context::StatePolygon_Context(CanvasView* canvas_view):
-       canvas_view_(canvas_view),
-       is_working(*canvas_view),
-       prev_workarea_layer_status_(get_work_area()->get_allow_layer_clicks()),
-       duckmatic_push(get_work_area()),
-       settings(synfigapp::Main::get_selected_input_device()->settings()),
-       entry_id(),
-       checkbutton_invert(_("Invert")),
-       checkbutton_layer_polygon(_("Create Polygon Layer")),
-       checkbutton_layer_region(_("Create Region BLine")),
-       checkbutton_layer_outline(_("Create Outline BLine")),
-       checkbutton_layer_curve_gradient(_("Create Curve Gradient BLine")),
-       checkbutton_layer_plant(_("Create Plant BLine")),
-       checkbutton_layer_link_origins(_("Link Origins")),
-       button_make(_("Make")),
-       adj_feather(0,0,10000,0.01,0.1),
-       spin_feather(adj_feather,0.01,4)
-{
-       egress_on_selection_change=true;
-       load_settings();
-
-       // Set up the tool options dialog
-       options_table.attach(*manage(new Gtk::Label(_("Polygon Tool"))),        0, 2, 0,  1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(entry_id,                                                                          0, 2, 1,  2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-
-       options_table.attach(checkbutton_layer_polygon,                                         0, 2, 2,  3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(checkbutton_layer_outline,                                         0, 2, 3,  4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(checkbutton_layer_region,                                          0, 2, 4,  5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(checkbutton_layer_plant,                                           0, 2, 5,  6, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(checkbutton_layer_curve_gradient,                          0, 2, 6,  7, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(checkbutton_layer_link_origins,                            0, 2, 7,  8, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-
-       //invert flag
-       options_table.attach(checkbutton_invert,                                                        0, 2, 8,  9, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-
-       //feather stuff
-       options_table.attach(*manage(new Gtk::Label(_("Feather"))),             0, 1, 9, 10, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(spin_feather,                                                                      1, 2, 9, 10, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-
-       //options_table.attach(button_make, 0, 2, 4, 5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       button_make.signal_pressed().connect(sigc::mem_fun(*this,&StatePolygon_Context::run));
-       options_table.show_all();
-       refresh_tool_options();
-       App::dialog_tool_options->present();
-
-
-       // Turn off layer clicking
-       get_work_area()->set_allow_layer_clicks(false);
-
-       // clear out the ducks
-       get_work_area()->clear_ducks();
-
-       // Refresh the work area
-       get_work_area()->queue_draw();
-
-       get_work_area()->set_cursor(Gdk::CROSSHAIR);
-
-       // Hide the tables if they are showing
-       prev_table_status=get_canvas_view()->tables_are_visible();
-       if(prev_table_status)get_canvas_view()->hide_tables();
-
-       // Disable the time bar
-       get_canvas_view()->set_sensitive_timebar(false);
-
-       // Connect a signal
-       //get_work_area()->signal_user_click().connect(sigc::mem_fun(*this,&studio::StatePolygon_Context::on_user_click));
-
-       App::toolbox->refresh();
-}
-
-void
-StatePolygon_Context::refresh_tool_options()
-{
-       App::dialog_tool_options->clear();
-       App::dialog_tool_options->set_widget(options_table);
-
-       App::dialog_tool_options->set_local_name(_("Polygon Tool"));
-       App::dialog_tool_options->set_name("polygon");
-
-       App::dialog_tool_options->add_button(
-               Gtk::StockID("gtk-execute"),
-               _("Make Polygon")
-       )->signal_clicked().connect(
-               sigc::mem_fun(
-                       *this,
-                       &StatePolygon_Context::run
-               )
-       );
-
-       App::dialog_tool_options->add_button(
-               Gtk::StockID("gtk-clear"),
-               _("Clear current Polygon")
-       )->signal_clicked().connect(
-               sigc::mem_fun(
-                       *this,
-                       &StatePolygon_Context::reset
-               )
-       );
-}
-
-Smach::event_result
-StatePolygon_Context::event_refresh_tool_options(const Smach::event& /*x*/)
-{
-       refresh_tool_options();
-       return Smach::RESULT_ACCEPT;
-}
-
-StatePolygon_Context::~StatePolygon_Context()
-{
-       run();
-
-       save_settings();
-       // Restore layer clicking
-       get_work_area()->set_allow_layer_clicks(prev_workarea_layer_status_);
-
-       App::dialog_tool_options->clear();
-
-       get_work_area()->reset_cursor();
-
-       // Enable the time bar
-       get_canvas_view()->set_sensitive_timebar(true);
-
-       // Bring back the tables if they were out before
-       if(prev_table_status)get_canvas_view()->show_tables();
-
-       // Refresh the work area
-       get_work_area()->queue_draw();
-
-       App::toolbox->refresh();
-}
-
-Smach::event_result
-StatePolygon_Context::event_stop_handler(const Smach::event& /*x*/)
-{
-       synfig::info("STATE RotoPolygon: Received Stop Event");
-       //throw Smach::egress_exception();
-       reset();
-       return Smach::RESULT_ACCEPT;
-
-}
-
-Smach::event_result
-StatePolygon_Context::event_refresh_handler(const Smach::event& /*x*/)
-{
-       synfig::info("STATE RotoPolygon: Received Refresh Event");
-       refresh_ducks();
-       return Smach::RESULT_ACCEPT;
-}
-
-void
-StatePolygon_Context::run()
-{
-       if(polygon_point_list.empty())
-               return;
-
-       if(polygon_point_list.size()<3)
-       {
-               get_canvas_view()->get_ui_interface()->error("You need at least 3 points to create a polygon");
-               return;
-       }
-
-       synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("New Polygon"));
-
-       Layer::Handle layer;
-
-       Canvas::Handle canvas;
-       int depth(0);
-
-       // we are temporarily using the layer to hold something
-       layer=get_canvas_view()->get_selection_manager()->get_selected_layer();
-       if(layer)
-       {
-               depth=layer->get_depth();
-               canvas=layer->get_canvas();
-       }
-
-       synfigapp::SelectionManager::LayerList layer_selection;
-       if (!getenv("SYNFIG_TOOLS_CLEAR_SELECTION"))
-               layer_selection = get_canvas_view()->get_selection_manager()->get_selected_layers();
-
-       const synfig::TransformStack& transform(get_canvas_view()->get_curr_transform_stack());
-
-       std::vector<BLinePoint> new_list;
-       std::list<synfig::Point>::iterator iter;
-       int i;
-       for(i=0,iter=polygon_point_list.begin();iter!=polygon_point_list.end();++iter,++i)
-       {
-               *iter = transform.unperform(*iter);
-               new_list.push_back(*(new BLinePoint));
-               new_list[i].set_width(1);
-               new_list[i].set_vertex(*iter);
-               new_list[i].set_tangent(Point(0,0));
-       }
-
-       ValueNode_BLine::Handle value_node_bline(ValueNode_BLine::create(new_list));
-       assert(value_node_bline);
-
-       ValueNode_Const::Handle value_node_origin(ValueNode_Const::create(Vector()));
-       assert(value_node_origin);
-
-       // Set the looping flag
-       value_node_bline->set_loop(true);
-
-       if(!canvas)
-               canvas=get_canvas_view()->get_canvas();
-
-       value_node_bline->set_member_canvas(canvas);
-
-       // count how many layers we're going to be creating
-       int layers_to_create = this->layers_to_create();
-
-       ///////////////////////////////////////////////////////////////////////////
-       //   P O L Y G O N
-       ///////////////////////////////////////////////////////////////////////////
-
-       if (get_layer_polygon_flag())
-       {
-               layer=get_canvas_interface()->add_layer_to("polygon",canvas,depth);
-               if (!layer)
-               {
-                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
-                       group.cancel();
-                       return;
-               }
-               layer_selection.push_back(layer);
-
-               layer->set_param("invert",get_invert());
-               get_canvas_interface()->signal_layer_param_changed()(layer,"invert");
-
-               if(get_feather())
-               {
-                       layer->set_param("feather",get_feather());
-                       get_canvas_interface()->signal_layer_param_changed()(layer,"feather");
-               }
-
-               layer->set_description(get_id());
-               get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
-
-               layer->disconnect_dynamic_param("vector_list");
-               if(!layer->set_param("vector_list",polygon_point_list))
-               {
-                       group.cancel();
-                       get_canvas_view()->get_ui_interface()->error("Unable to set layer parameter");
-                       return;
-               }
-
-               {
-                       synfigapp::Action::Handle action(synfigapp::Action::create("ValueDescConvert"));
-                       synfigapp::ValueDesc value_desc(layer,"vector_list");
-                       action->set_param("canvas",get_canvas());
-                       action->set_param("canvas_interface",get_canvas_interface());
-                       action->set_param("value_desc",value_desc);
-                       action->set_param("type","dynamic_list");
-                       action->set_param("time",get_canvas_interface()->get_time());
-                       if(!get_canvas_interface()->get_instance()->perform_action(action))
-                       {
-                               group.cancel();
-                               get_canvas_view()->get_ui_interface()->error("Unable to execute action \"ValueDescConvert\"");
-                               return;
-                       }
-               }
-
-               // only link the polygon's origin parameter if the option is selected and we're creating more than one layer
-               if (get_layer_link_origins_flag() && layers_to_create > 1)
-               {
-                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
-                       assert(action);
-
-                       action->set_param("canvas",get_canvas());
-                       action->set_param("canvas_interface",get_canvas_interface());
-                       action->set_param("layer",layer);
-                       if(!action->set_param("param",String("origin")))
-                               synfig::error("LayerParamConnect didn't like \"param\"");
-                       if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
-                               synfig::error("LayerParamConnect didn't like \"value_node\"");
-
-                       if(!get_canvas_interface()->get_instance()->perform_action(action))
-                       {
-                               get_canvas_view()->get_ui_interface()->error(_("Unable to create Polygon layer"));
-                               group.cancel();
-                               throw String(_("Unable to create Polygon layer"));
-                               return;
-                       }
-               }
-       }
-
-       ///////////////////////////////////////////////////////////////////////////
-       //   C U R V E   G R A D I E N T
-       ///////////////////////////////////////////////////////////////////////////
-
-       if(get_layer_curve_gradient_flag())
-       {
-               synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
-
-               Layer::Handle layer(get_canvas_interface()->add_layer_to("curve_gradient",canvas,depth));
-               if (!layer)
-               {
-                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
-                       group.cancel();
-                       return;
-               }
-               layer_selection.push_back(layer);
-               layer->set_description(get_id()+_(" Gradient"));
-               get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
-
-               {
-                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
-                       assert(action);
-
-                       action->set_param("canvas",get_canvas());
-                       action->set_param("canvas_interface",get_canvas_interface());
-                       action->set_param("layer",layer);
-                       if(!action->set_param("param",String("bline")))
-                               synfig::error("LayerParamConnect didn't like \"param\"");
-                       if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
-                               synfig::error("LayerParamConnect didn't like \"value_node\"");
-
-                       if(!get_canvas_interface()->get_instance()->perform_action(action))
-                       {
-                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
-                               group.cancel();
-                               throw String(_("Unable to create Gradient layer"));
-                               return;
-                       }
-               }
-
-               // only link the curve gradient's origin parameter if the option is selected and we're creating more than one layer
-               if (get_layer_link_origins_flag() && layers_to_create > 1)
-               {
-                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
-                       assert(action);
-
-                       action->set_param("canvas",get_canvas());
-                       action->set_param("canvas_interface",get_canvas_interface());
-                       action->set_param("layer",layer);
-                       if(!action->set_param("param",String("origin")))
-                               synfig::error("LayerParamConnect didn't like \"param\"");
-                       if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
-                               synfig::error("LayerParamConnect didn't like \"value_node\"");
-
-                       if(!get_canvas_interface()->get_instance()->perform_action(action))
-                       {
-                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
-                               group.cancel();
-                               throw String(_("Unable to create Gradient layer"));
-                               return;
-                       }
-               }
-       }
-
-       ///////////////////////////////////////////////////////////////////////////
-       //   P L A N T
-       ///////////////////////////////////////////////////////////////////////////
-
-       if(get_layer_plant_flag())
-       {
-               synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
-
-               Layer::Handle layer(get_canvas_interface()->add_layer_to("plant",canvas,depth));
-               if (!layer)
-               {
-                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
-                       group.cancel();
-                       return;
-               }
-               layer_selection.push_back(layer);
-               layer->set_description(get_id()+_(" Plant"));
-               get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
-
-               {
-                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
-                       assert(action);
-
-                       action->set_param("canvas",get_canvas());
-                       action->set_param("canvas_interface",get_canvas_interface());
-                       action->set_param("layer",layer);
-                       if(!action->set_param("param",String("bline")))
-                               synfig::error("LayerParamConnect didn't like \"param\"");
-                       if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
-                               synfig::error("LayerParamConnect didn't like \"value_node\"");
-
-                       if(!get_canvas_interface()->get_instance()->perform_action(action))
-                       {
-                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
-                               group.cancel();
-                               throw String(_("Unable to create Plant layer"));
-                               return;
-                       }
-               }
-
-               // only link the plant's origin parameter if the option is selected and we're creating more than one layer
-               if (get_layer_link_origins_flag() && layers_to_create > 1)
-               {
-                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
-                       assert(action);
-
-                       action->set_param("canvas",get_canvas());
-                       action->set_param("canvas_interface",get_canvas_interface());
-                       action->set_param("layer",layer);
-                       if(!action->set_param("param",String("origin")))
-                               synfig::error("LayerParamConnect didn't like \"param\"");
-                       if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
-                               synfig::error("LayerParamConnect didn't like \"value_node\"");
-
-                       if(!get_canvas_interface()->get_instance()->perform_action(action))
-                       {
-                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
-                               group.cancel();
-                               throw String(_("Unable to create Plant layer"));
-                               return;
-                       }
-               }
-       }
-
-       ///////////////////////////////////////////////////////////////////////////
-       //   R E G I O N
-       ///////////////////////////////////////////////////////////////////////////
-
-       if(get_layer_region_flag())
-       {
-               synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
-
-               Layer::Handle layer(get_canvas_interface()->add_layer_to("region",canvas,depth));
-               if (!layer)
-               {
-                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
-                       group.cancel();
-                       return;
-               }
-               layer_selection.push_back(layer);
-               layer->set_description(get_id()+_(" Region"));
-               get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
-
-               layer->set_param("feather",get_feather());
-               get_canvas_interface()->signal_layer_param_changed()(layer,"feather");
-
-               layer->set_param("invert",get_invert());
-               get_canvas_interface()->signal_layer_param_changed()(layer,"invert");
-
-               // I don't know if it's safe to reuse the same LayerParamConnect action, so I'm
-               // using 2 separate ones.
-               {
-                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
-                       assert(action);
-
-                       action->set_param("canvas",get_canvas());
-                       action->set_param("canvas_interface",get_canvas_interface());
-                       action->set_param("layer",layer);
-                       if(!action->set_param("param",String("bline")))
-                               synfig::error("LayerParamConnect didn't like \"param\"");
-                       if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
-                               synfig::error("LayerParamConnect didn't like \"value_node\"");
-
-                       if(!get_canvas_interface()->get_instance()->perform_action(action))
-                       {
-                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer"));
-                               group.cancel();
-                               throw String(_("Unable to create Region layer"));
-                               return;
-                       }
-               }
-
-               // only link the region's origin parameter if the option is selected and we're creating more than one layer
-               if (get_layer_link_origins_flag() && layers_to_create > 1)
-               {
-                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
-                       assert(action);
-
-                       action->set_param("canvas",get_canvas());
-                       action->set_param("canvas_interface",get_canvas_interface());
-                       action->set_param("layer",layer);
-                       if(!action->set_param("param",String("origin")))
-                               synfig::error("LayerParamConnect didn't like \"param\"");
-                       if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
-                               synfig::error("LayerParamConnect didn't like \"value_node\"");
-
-                       if(!get_canvas_interface()->get_instance()->perform_action(action))
-                       {
-                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer"));
-                               group.cancel();
-                               throw String(_("Unable to create Region layer"));
-                               return;
-                       }
-               }
-       }
-
-       ///////////////////////////////////////////////////////////////////////////
-       //   O U T L I N E
-       ///////////////////////////////////////////////////////////////////////////
-
-       if (get_layer_outline_flag())
-       {
-               Layer::Handle layer(get_canvas_interface()->add_layer_to("outline",canvas,depth));
-               if (!layer)
-               {
-                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
-                       group.cancel();
-                       return;
-               }
-               layer_selection.push_back(layer);
-               layer->set_description(get_id()+_(" Outline"));
-               get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
-
-               layer->set_param("feather",get_feather());
-               get_canvas_interface()->signal_layer_param_changed()(layer,"feather");
-
-               layer->set_param("invert",get_invert());
-               get_canvas_interface()->signal_layer_param_changed()(layer,"invert");
-
-               {
-                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
-                       assert(action);
-
-                       action->set_param("canvas",get_canvas());
-                       action->set_param("canvas_interface",get_canvas_interface());
-                       action->set_param("layer",layer);
-                       if(!action->set_param("param",String("bline")))
-                               synfig::error("LayerParamConnect didn't like \"param\"");
-                       if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
-                               synfig::error("LayerParamConnect didn't like \"value_node\"");
-
-                       if(!get_canvas_interface()->get_instance()->perform_action(action))
-                       {
-                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
-                               group.cancel();
-                               throw String(_("Unable to create Outline layer"));
-                               return;
-                       }
-               }
-
-               // only link the outline's origin parameter if the option is selected and we're creating more than one layer
-               if (get_layer_link_origins_flag() && layers_to_create > 1)
-               {
-                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
-                       assert(action);
-
-                       action->set_param("canvas",get_canvas());
-                       action->set_param("canvas_interface",get_canvas_interface());
-                       action->set_param("layer",layer);
-                       if(!action->set_param("param",String("origin")))
-                               synfig::error("LayerParamConnect didn't like \"param\"");
-                       if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
-                               synfig::error("LayerParamConnect didn't like \"value_node\"");
-
-                       if(!get_canvas_interface()->get_instance()->perform_action(action))
-                       {
-                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
-                               group.cancel();
-                               throw String(_("Unable to create Outline layer"));
-                               return;
-                       }
-               }
-       }
-
-       egress_on_selection_change=false;
-       get_canvas_interface()->get_selection_manager()->clear_selected_layers();
-       get_canvas_interface()->get_selection_manager()->set_selected_layers(layer_selection);
-       egress_on_selection_change=true;
-
-       //post clean up stuff...
-       reset();
-       increment_id();
-}
-
-Smach::event_result
-StatePolygon_Context::event_mouse_click_handler(const Smach::event& x)
-{
-       synfig::info("STATE ROTOPOLYGON: Received mouse button down Event");
-       const EventMouse& event(*reinterpret_cast<const EventMouse*>(&x));
-       switch(event.button)
-       {
-       case BUTTON_LEFT:
-               polygon_point_list.push_back(get_work_area()->snap_point_to_grid(event.pos));
-               refresh_ducks();
-               return Smach::RESULT_ACCEPT;
-
-       default:
-               return Smach::RESULT_OK;
-       }
-}
-
-
-void
-StatePolygon_Context::refresh_ducks()
-{
-       get_work_area()->clear_ducks();
-       get_work_area()->queue_draw();
-
-       if(polygon_point_list.empty()) return;
-
-       std::list<synfig::Point>::iterator iter=polygon_point_list.begin();
-
-       etl::handle<WorkArea::Duck> duck;
-       duck=new WorkArea::Duck(*iter);
-       duck->set_editable(true);
-       duck->signal_edited().connect(
-               sigc::bind(sigc::mem_fun(*this,&studio::StatePolygon_Context::on_polygon_duck_change),iter)
-       );
-       duck->signal_user_click(0).connect(sigc::mem_fun(*this,&StatePolygon_Context::run));
-
-       get_work_area()->add_duck(duck);
-
-       for(++iter;iter!=polygon_point_list.end();++iter)
-       {
-               etl::handle<WorkArea::Bezier> bezier(new WorkArea::Bezier());
-               bezier->p1=bezier->c1=duck;
-
-               duck=new WorkArea::Duck(*iter);
-               duck->set_editable(true);
-               duck->set_name(strprintf("%x",&*iter));
-               duck->signal_edited().connect(
-                       sigc::bind(sigc::mem_fun(*this,&studio::StatePolygon_Context::on_polygon_duck_change),iter)
-               );
-
-               get_work_area()->add_duck(duck);
-
-               bezier->p2=bezier->c2=duck;
-               get_work_area()->add_bezier(bezier);
-       }
-       get_work_area()->queue_draw();
-}
-
-
-bool
-StatePolygon_Context::on_polygon_duck_change(const synfig::Point &point, std::list<synfig::Point>::iterator iter)
-{
-       *iter=point;
-       return true;
-}
diff --git a/synfig-studio/src/gui/state_polygon.h b/synfig-studio/src/gui/state_polygon.h
deleted file mode 100644 (file)
index c633c4e..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/* === S Y N F I G ========================================================= */
-/*!    \file state_polygon.h
-**     \brief Template Header
-**
-**     $Id$
-**
-**     \legal
-**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
-**
-**     This package is free software; you can redistribute it and/or
-**     modify it under the terms of the GNU General Public License as
-**     published by the Free Software Foundation; either version 2 of
-**     the License, or (at your option) any later version.
-**
-**     This package is distributed in the hope that it will be useful,
-**     but WITHOUT ANY WARRANTY; without even the implied warranty of
-**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-**     General Public License for more details.
-**     \endlegal
-*/
-/* ========================================================================= */
-
-/* === S T A R T =========================================================== */
-
-#ifndef __SYNFIG_STUDIO_ROTOSCOPE_POLYGON_H
-#define __SYNFIG_STUDIO_ROTOSCOPE_POLYGON_H
-
-/* === H E A D E R S ======================================================= */
-
-#include "smach.h"
-
-/* === M A C R O S ========================================================= */
-
-/* === T Y P E D E F S ===================================================== */
-
-/* === C L A S S E S & S T R U C T S ======================================= */
-
-namespace studio {
-
-class StatePolygon_Context;
-
-class StatePolygon : public Smach::state<StatePolygon_Context>
-{
-public:
-       StatePolygon();
-       ~StatePolygon();
-}; // END of class StatePolygon
-
-extern StatePolygon state_polygon;
-
-}; // END of namespace studio
-
-/* === E N D =============================================================== */
-
-#endif
diff --git a/synfig-studio/src/gui/state_rectangle.cpp b/synfig-studio/src/gui/state_rectangle.cpp
deleted file mode 100644 (file)
index 4f3eccb..0000000
+++ /dev/null
@@ -1,875 +0,0 @@
-/* === S Y N F I G ========================================================= */
-/*!    \file state_rectangle.cpp
-**     \brief Template File
-**
-**     $Id$
-**
-**     \legal
-**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
-**  Copyright (c) 2008 Chris Moore
-**
-**     This package is free software; you can redistribute it and/or
-**     modify it under the terms of the GNU General Public License as
-**     published by the Free Software Foundation; either version 2 of
-**     the License, or (at your option) any later version.
-**
-**     This package is distributed in the hope that it will be useful,
-**     but WITHOUT ANY WARRANTY; without even the implied warranty of
-**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-**     General Public License for more details.
-**     \endlegal
-*/
-/* ========================================================================= */
-
-/* === H E A D E R S ======================================================= */
-
-#ifdef USING_PCH
-#      include "pch.h"
-#else
-#ifdef HAVE_CONFIG_H
-#      include <config.h>
-#endif
-
-#include <gtkmm/dialog.h>
-#include <gtkmm/entry.h>
-
-#include <synfig/valuenode_dynamiclist.h>
-#include <synfigapp/action_system.h>
-#include <synfig/valuenode_bline.h>
-
-#include "state_rectangle.h"
-#include "state_normal.h"
-#include "canvasview.h"
-#include "workarea.h"
-#include "app.h"
-
-#include <synfigapp/action.h>
-#include "event_mouse.h"
-#include "event_layerclick.h"
-#include "toolbox.h"
-#include "dialog_tooloptions.h"
-#include <gtkmm/optionmenu.h>
-#include "duck.h"
-#include <synfigapp/main.h>
-
-#include "general.h"
-
-#endif
-
-/* === U S I N G =========================================================== */
-
-using namespace std;
-using namespace etl;
-using namespace synfig;
-using namespace studio;
-
-/* === M A C R O S ========================================================= */
-
-/* === G L O B A L S ======================================================= */
-
-StateRectangle studio::state_rectangle;
-
-/* === C L A S S E S & S T R U C T S ======================================= */
-
-class studio::StateRectangle_Context : public sigc::trackable
-{
-       etl::handle<CanvasView> canvas_view_;
-       CanvasView::IsWorking is_working;
-
-       Duckmatic::Push duckmatic_push;
-
-       Point point_holder;
-
-       etl::handle<Duck> point2_duck;
-
-       void refresh_ducks();
-
-       bool prev_workarea_layer_status_;
-
-       //Toolbox settings
-       synfigapp::Settings& settings;
-
-       //Toolbox display
-       Gtk::Table options_table;
-
-       Gtk::Entry              entry_id; //what to name the layer
-
-       Gtk::Adjustment adj_expand;
-       Gtk::Adjustment adj_feather;
-       Gtk::SpinButton spin_expand;
-       Gtk::SpinButton spin_feather;
-
-       Gtk::CheckButton checkbutton_invert;
-       Gtk::CheckButton checkbutton_layer_rectangle;
-       Gtk::CheckButton checkbutton_layer_region;
-       Gtk::CheckButton checkbutton_layer_outline;
-       Gtk::CheckButton checkbutton_layer_curve_gradient;
-       Gtk::CheckButton checkbutton_layer_plant;
-       Gtk::CheckButton checkbutton_layer_link_origins;
-
-public:
-
-       // this only counts the layers which use blines - they're the only
-       // ones we link the origins for
-       int layers_to_create()const
-       {
-               return
-                       get_layer_region_flag() +
-                       get_layer_outline_flag() +
-                       get_layer_curve_gradient_flag() +
-                       get_layer_plant_flag();
-       }
-
-       synfig::String get_id()const { return entry_id.get_text(); }
-       void set_id(const synfig::String& x) { return entry_id.set_text(x); }
-
-       Real get_expand()const { return adj_expand.get_value(); }
-       void set_expand(Real f) { adj_expand.set_value(f); }
-
-       Real get_feather()const { return adj_feather.get_value(); }
-       void set_feather(Real f) { adj_feather.set_value(f); }
-
-       bool get_invert()const { return checkbutton_invert.get_active(); }
-       void set_invert(bool i) { checkbutton_invert.set_active(i); }
-
-       bool get_layer_rectangle_flag()const { return checkbutton_layer_rectangle.get_active(); }
-       void set_layer_rectangle_flag(bool x) { return checkbutton_layer_rectangle.set_active(x); }
-
-       bool get_layer_region_flag()const { return checkbutton_layer_region.get_active(); }
-       void set_layer_region_flag(bool x) { return checkbutton_layer_region.set_active(x); }
-
-       bool get_layer_outline_flag()const { return checkbutton_layer_outline.get_active(); }
-       void set_layer_outline_flag(bool x) { return checkbutton_layer_outline.set_active(x); }
-
-       bool get_layer_curve_gradient_flag()const { return checkbutton_layer_curve_gradient.get_active(); }
-       void set_layer_curve_gradient_flag(bool x) { return checkbutton_layer_curve_gradient.set_active(x); }
-
-       bool get_layer_plant_flag()const { return checkbutton_layer_plant.get_active(); }
-       void set_layer_plant_flag(bool x) { return checkbutton_layer_plant.set_active(x); }
-
-       bool get_layer_link_origins_flag()const { return checkbutton_layer_link_origins.get_active(); }
-       void set_layer_link_origins_flag(bool x) { return checkbutton_layer_link_origins.set_active(x); }
-
-       void refresh_tool_options(); //to refresh the toolbox
-
-       //events
-       Smach::event_result event_stop_handler(const Smach::event& x);
-       Smach::event_result event_refresh_handler(const Smach::event& x);
-       Smach::event_result event_mouse_click_handler(const Smach::event& x);
-       Smach::event_result event_refresh_tool_options(const Smach::event& x);
-
-       //constructor destructor
-       StateRectangle_Context(CanvasView* canvas_view);
-       ~StateRectangle_Context();
-
-       //Canvas interaction
-       const etl::handle<CanvasView>& get_canvas_view()const{return canvas_view_;}
-       etl::handle<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view_->canvas_interface();}
-       synfig::Canvas::Handle get_canvas()const{return canvas_view_->get_canvas();}
-       WorkArea * get_work_area()const{return canvas_view_->get_work_area();}
-
-       //Modifying settings etc.
-       void load_settings();
-       void save_settings();
-       void reset();
-       void increment_id();
-       bool egress_on_selection_change;
-       Smach::event_result event_layer_selection_changed_handler(const Smach::event& /*x*/)
-       {
-               if(egress_on_selection_change)
-                       throw &state_normal; //throw Smach::egress_exception();
-               return Smach::RESULT_OK;
-       }
-
-       void make_rectangle(const Point& p1, const Point& p2);
-
-};     // END of class StateGradient_Context
-
-/* === M E T H O D S ======================================================= */
-
-StateRectangle::StateRectangle():
-       Smach::state<StateRectangle_Context>("rectangle")
-{
-       insert(event_def(EVENT_STOP,&StateRectangle_Context::event_stop_handler));
-       insert(event_def(EVENT_LAYER_SELECTION_CHANGED,&StateRectangle_Context::event_layer_selection_changed_handler));
-       insert(event_def(EVENT_REFRESH,&StateRectangle_Context::event_refresh_handler));
-       insert(event_def(EVENT_REFRESH_DUCKS,&StateRectangle_Context::event_refresh_handler));
-       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateRectangle_Context::event_mouse_click_handler));
-       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DRAG,&StateRectangle_Context::event_mouse_click_handler));
-       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_UP,&StateRectangle_Context::event_mouse_click_handler));
-       insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateRectangle_Context::event_refresh_tool_options));
-}
-
-StateRectangle::~StateRectangle()
-{
-}
-
-void
-StateRectangle_Context::load_settings()
-{
-       String value;
-
-       //parse the arguments yargh!
-       if(settings.get_value("rectangle.id",value))
-               set_id(value);
-       else
-               set_id("Rectangle");
-
-       if(settings.get_value("rectangle.expand",value))
-               set_expand(atof(value.c_str()));
-       else
-               set_expand(0);
-
-       if(settings.get_value("rectangle.feather",value))
-               set_feather(atof(value.c_str()));
-       else
-               set_feather(0);
-
-       if(settings.get_value("rectangle.invert",value) && value != "0")
-               set_invert(true);
-       else
-               set_invert(false);
-
-       if(settings.get_value("rectangle.layer_rectangle",value) && value=="0")
-               set_layer_rectangle_flag(false);
-       else
-               set_layer_rectangle_flag(true);
-
-       if(settings.get_value("rectangle.layer_region",value) && value=="1")
-               set_layer_region_flag(true);
-       else
-               set_layer_region_flag(false);
-
-       if(settings.get_value("rectangle.layer_outline",value) && value=="1")
-               set_layer_outline_flag(true);
-       else
-               set_layer_outline_flag(false);
-
-       if(settings.get_value("rectangle.layer_curve_gradient",value) && value=="1")
-               set_layer_curve_gradient_flag(true);
-       else
-               set_layer_curve_gradient_flag(false);
-
-       if(settings.get_value("rectangle.layer_plant",value) && value=="1")
-               set_layer_plant_flag(true);
-       else
-               set_layer_plant_flag(false);
-
-       if(settings.get_value("rectangle.layer_link_origins",value) && value=="0")
-               set_layer_link_origins_flag(false);
-       else
-               set_layer_link_origins_flag(true);
-}
-
-void
-StateRectangle_Context::save_settings()
-{
-       settings.set_value("rectangle.id",get_id().c_str());
-       settings.set_value("rectangle.expand",strprintf("%f",get_expand()));
-       settings.set_value("rectangle.feather",strprintf("%f",(float)get_feather()));
-       settings.set_value("rectangle.invert",get_invert()?"1":"0");
-       settings.set_value("rectangle.layer_rectangle",get_layer_rectangle_flag()?"1":"0");
-       settings.set_value("rectangle.layer_outline",get_layer_outline_flag()?"1":"0");
-       settings.set_value("rectangle.layer_region",get_layer_region_flag()?"1":"0");
-       settings.set_value("rectangle.layer_curve_gradient",get_layer_curve_gradient_flag()?"1":"0");
-       settings.set_value("rectangle.layer_plant",get_layer_plant_flag()?"1":"0");
-       settings.set_value("rectangle.layer_link_origins",get_layer_link_origins_flag()?"1":"0");
-}
-
-void
-StateRectangle_Context::reset()
-{
-       refresh_ducks();
-}
-
-void
-StateRectangle_Context::increment_id()
-{
-       String id(get_id());
-       int number=1;
-       int digits=0;
-
-       if(id.empty())
-               id="Rectangle";
-
-       // If there is a number
-       // already at the end of the
-       // id, then remove it.
-       if(id[id.size()-1]<='9' && id[id.size()-1]>='0')
-       {
-               // figure out how many digits it is
-               for (digits = 0;
-                        (int)id.size()-1 >= digits && id[id.size()-1-digits] <= '9' && id[id.size()-1-digits] >= '0';
-                        digits++)
-                       ;
-
-               String str_number;
-               str_number=String(id,id.size()-digits,id.size());
-               id=String(id,0,id.size()-digits);
-
-               number=atoi(str_number.c_str());
-       }
-       else
-       {
-               number=1;
-               digits=3;
-       }
-
-       number++;
-
-       // Add the number back onto the id
-       {
-               const String format(strprintf("%%0%dd",digits));
-               id+=strprintf(format.c_str(),number);
-       }
-
-       // Set the ID
-       set_id(id);
-}
-
-StateRectangle_Context::StateRectangle_Context(CanvasView* canvas_view):
-       canvas_view_(canvas_view),
-       is_working(*canvas_view),
-       duckmatic_push(get_work_area()),
-       prev_workarea_layer_status_(get_work_area()->get_allow_layer_clicks()),
-       settings(synfigapp::Main::get_selected_input_device()->settings()),
-       entry_id(),
-       adj_expand(0,0,1,0.01,0.1),
-       adj_feather(0,0,1,0.01,0.1),
-       spin_expand(adj_expand,0.1,3),
-       spin_feather(adj_feather,0.1,3),
-       checkbutton_invert(_("Invert")),
-       checkbutton_layer_rectangle(_("Create Rectangle Layer")),
-       checkbutton_layer_region(_("Create Region BLine")),
-       checkbutton_layer_outline(_("Create Outline BLine")),
-       checkbutton_layer_curve_gradient(_("Create Curve Gradient BLine")),
-       checkbutton_layer_plant(_("Create Plant BLine")),
-       checkbutton_layer_link_origins(_("Link BLine Origins"))
-{
-       egress_on_selection_change=true;
-       load_settings();
-
-       // Set up the tool options dialog
-       options_table.attach(*manage(new Gtk::Label(_("Rectangle Tool"))),      0, 2,  0,  1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(entry_id,                                                                          0, 2,  1,  2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-
-       options_table.attach(checkbutton_layer_rectangle,                                       0, 2,  2,  3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(checkbutton_layer_outline,                                         0, 2,  3,  4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(checkbutton_layer_region,                                          0, 2,  4,  5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(checkbutton_layer_plant,                                           0, 2,  5,  6, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(checkbutton_layer_curve_gradient,                          0, 2,  6,  7, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(checkbutton_layer_link_origins,                            0, 2,  7,  8, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-
-       //invert flag
-       options_table.attach(checkbutton_invert,                                                        0, 2,  8,  9, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-
-       //expand stuff
-       options_table.attach(*manage(new Gtk::Label(_("Expansion:"))),          0, 1,  9, 10, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(spin_expand,                                                                       1, 2,  9, 10, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-
-       //feather stuff
-       options_table.attach(*manage(new Gtk::Label(_("Feather:"))),            0, 1, 10, 11, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(spin_feather,                                                                      1, 2, 10, 11, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-
-       options_table.show_all();
-
-       //App::dialog_tool_options->set_widget(options_table);
-       refresh_tool_options();
-       App::dialog_tool_options->present();
-
-       // Turn off layer clicking
-       get_work_area()->set_allow_layer_clicks(false);
-
-       // clear out the ducks
-       get_work_area()->clear_ducks();
-
-       // Refresh the work area
-       get_work_area()->queue_draw();
-
-       get_work_area()->set_cursor(Gdk::DOTBOX);
-
-       // Hide the tables if they are showing
-       //prev_table_status=get_canvas_view()->tables_are_visible();
-       //if(prev_table_status)get_canvas_view()->hide_tables();
-
-       // Disable the time bar
-       //get_canvas_view()->set_sensitive_timebar(false);
-
-       // Connect a signal
-       //get_work_area()->signal_user_click().connect(sigc::mem_fun(*this,&studio::StateRectangle_Context::on_user_click));
-
-       App::toolbox->refresh();
-}
-
-void
-StateRectangle_Context::refresh_tool_options()
-{
-       App::dialog_tool_options->clear();
-       App::dialog_tool_options->set_widget(options_table);
-       App::dialog_tool_options->set_local_name(_("Rectangle Tool"));
-       App::dialog_tool_options->set_name("rectangle");
-}
-
-Smach::event_result
-StateRectangle_Context::event_refresh_tool_options(const Smach::event& /*x*/)
-{
-       refresh_tool_options();
-       return Smach::RESULT_ACCEPT;
-}
-
-StateRectangle_Context::~StateRectangle_Context()
-{
-       save_settings();
-
-       // Restore layer clicking
-       get_work_area()->set_allow_layer_clicks(prev_workarea_layer_status_);
-
-       get_work_area()->reset_cursor();
-
-       App::dialog_tool_options->clear();
-
-       // Enable the time bar
-       //get_canvas_view()->set_sensitive_timebar(true);
-
-       // Bring back the tables if they were out before
-       //if(prev_table_status)get_canvas_view()->show_tables();
-
-       // Refresh the work area
-       get_work_area()->queue_draw();
-
-       get_canvas_view()->queue_rebuild_ducks();
-
-       App::toolbox->refresh();
-}
-
-Smach::event_result
-StateRectangle_Context::event_stop_handler(const Smach::event& /*x*/)
-{
-       //throw Smach::egress_exception();
-       throw &state_normal;
-       return Smach::RESULT_OK;
-}
-
-Smach::event_result
-StateRectangle_Context::event_refresh_handler(const Smach::event& /*x*/)
-{
-       refresh_ducks();
-       return Smach::RESULT_ACCEPT;
-}
-
-void
-StateRectangle_Context::make_rectangle(const Point& _p1, const Point& _p2)
-{
-       synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("New Rectangle"));
-       synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
-
-       Layer::Handle layer;
-
-       Canvas::Handle canvas;
-       int depth(0);
-
-       // we are temporarily using the layer to hold something
-       layer=get_canvas_view()->get_selection_manager()->get_selected_layer();
-       if(layer)
-       {
-               depth=layer->get_depth();
-               canvas=layer->get_canvas();
-       }
-
-       synfigapp::SelectionManager::LayerList layer_selection;
-       if (!getenv("SYNFIG_TOOLS_CLEAR_SELECTION"))
-               layer_selection = get_canvas_view()->get_selection_manager()->get_selected_layers();
-
-       const synfig::TransformStack& transform(get_canvas_view()->get_curr_transform_stack());
-       const Point p1(transform.unperform(_p1));
-       const Point p2(transform.unperform(_p2));
-       Real x_min, x_max, y_min, y_max;
-       if (p1[0] < p2[0]) { x_min = p1[0]; x_max = p2[0]; } else { x_min = p2[0]; x_max = p1[0]; }
-       if (p1[1] < p2[1]) { y_min = p1[1]; y_max = p2[1]; } else { y_min = p2[1]; y_max = p1[1]; }
-       x_min -= get_expand(); x_max += get_expand(); y_min -= get_expand(); y_max += get_expand();
-
-       std::vector<BLinePoint> new_list;
-       for (int i = 0; i < 4; i++)
-       {
-               new_list.push_back(*(new BLinePoint));
-               new_list[i].set_width(1);
-               new_list[i].set_vertex(Point((i==0||i==3)?x_min:x_max,
-                                                                        (i==0||i==1)?y_min:y_max));
-               new_list[i].set_tangent(Point(0,0));
-       }
-
-       ValueNode_BLine::Handle value_node_bline(ValueNode_BLine::create(new_list));
-       assert(value_node_bline);
-
-       ValueNode_Const::Handle value_node_origin(ValueNode_Const::create(Vector()));
-       assert(value_node_origin);
-
-       // Set the looping flag
-       value_node_bline->set_loop(true);
-
-       if(!canvas)
-               canvas=get_canvas_view()->get_canvas();
-
-       value_node_bline->set_member_canvas(canvas);
-
-       // count how many layers we're going to be creating
-       int layers_to_create = this->layers_to_create();
-
-       ///////////////////////////////////////////////////////////////////////////
-       //   R E C T A N G L E
-       ///////////////////////////////////////////////////////////////////////////
-
-       if (get_layer_rectangle_flag())
-       {
-               layer=get_canvas_interface()->add_layer_to("rectangle",canvas,depth);
-               if (!layer)
-               {
-                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
-                       group.cancel();
-                       return;
-               }
-               layer_selection.push_back(layer);
-
-               layer->set_param("point1",p1);
-               get_canvas_interface()->signal_layer_param_changed()(layer,"point1");
-
-               layer->set_param("point2",p2);
-               get_canvas_interface()->signal_layer_param_changed()(layer,"point2");
-
-               layer->set_param("expand",get_expand());
-               get_canvas_interface()->signal_layer_param_changed()(layer,"expand");
-
-               layer->set_param("invert",get_invert());
-               get_canvas_interface()->signal_layer_param_changed()(layer,"invert");
-
-               layer->set_description(get_id());
-               get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
-       }
-
-       ///////////////////////////////////////////////////////////////////////////
-       //   C U R V E   G R A D I E N T
-       ///////////////////////////////////////////////////////////////////////////
-
-       if(get_layer_curve_gradient_flag())
-       {
-               synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
-
-               Layer::Handle layer(get_canvas_interface()->add_layer_to("curve_gradient",canvas,depth));
-               if (!layer)
-               {
-                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
-                       group.cancel();
-                       return;
-               }
-               layer_selection.push_back(layer);
-               layer->set_description(get_id()+_(" Gradient"));
-               get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
-
-               {
-                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
-                       assert(action);
-
-                       action->set_param("canvas",get_canvas());
-                       action->set_param("canvas_interface",get_canvas_interface());
-                       action->set_param("layer",layer);
-                       if(!action->set_param("param",String("bline")))
-                               synfig::error("LayerParamConnect didn't like \"param\"");
-                       if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
-                               synfig::error("LayerParamConnect didn't like \"value_node\"");
-
-                       if(!get_canvas_interface()->get_instance()->perform_action(action))
-                       {
-                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
-                               group.cancel();
-                               throw String(_("Unable to create Gradient layer"));
-                               return;
-                       }
-               }
-
-               // only link the curve gradient's origin parameter if the option is selected and we're creating more than one layer
-               if (get_layer_link_origins_flag() && layers_to_create > 1)
-               {
-                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
-                       assert(action);
-
-                       action->set_param("canvas",get_canvas());
-                       action->set_param("canvas_interface",get_canvas_interface());
-                       action->set_param("layer",layer);
-                       if(!action->set_param("param",String("origin")))
-                               synfig::error("LayerParamConnect didn't like \"param\"");
-                       if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
-                               synfig::error("LayerParamConnect didn't like \"value_node\"");
-
-                       if(!get_canvas_interface()->get_instance()->perform_action(action))
-                       {
-                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
-                               group.cancel();
-                               throw String(_("Unable to create Gradient layer"));
-                               return;
-                       }
-               }
-       }
-
-       ///////////////////////////////////////////////////////////////////////////
-       //   P L A N T
-       ///////////////////////////////////////////////////////////////////////////
-
-       if(get_layer_plant_flag())
-       {
-               synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
-
-               Layer::Handle layer(get_canvas_interface()->add_layer_to("plant",canvas,depth));
-               if (!layer)
-               {
-                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
-                       group.cancel();
-                       return;
-               }
-               layer_selection.push_back(layer);
-               layer->set_description(get_id()+_(" Plant"));
-               get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
-
-               {
-                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
-                       assert(action);
-
-                       action->set_param("canvas",get_canvas());
-                       action->set_param("canvas_interface",get_canvas_interface());
-                       action->set_param("layer",layer);
-                       if(!action->set_param("param",String("bline")))
-                               synfig::error("LayerParamConnect didn't like \"param\"");
-                       if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
-                               synfig::error("LayerParamConnect didn't like \"value_node\"");
-
-                       if(!get_canvas_interface()->get_instance()->perform_action(action))
-                       {
-                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
-                               group.cancel();
-                               throw String(_("Unable to create Plant layer"));
-                               return;
-                       }
-               }
-
-               // only link the plant's origin parameter if the option is selected and we're creating more than one layer
-               if (get_layer_link_origins_flag() && layers_to_create > 1)
-               {
-                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
-                       assert(action);
-
-                       action->set_param("canvas",get_canvas());
-                       action->set_param("canvas_interface",get_canvas_interface());
-                       action->set_param("layer",layer);
-                       if(!action->set_param("param",String("origin")))
-                               synfig::error("LayerParamConnect didn't like \"param\"");
-                       if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
-                               synfig::error("LayerParamConnect didn't like \"value_node\"");
-
-                       if(!get_canvas_interface()->get_instance()->perform_action(action))
-                       {
-                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
-                               group.cancel();
-                               throw String(_("Unable to create Plant layer"));
-                               return;
-                       }
-               }
-       }
-
-       ///////////////////////////////////////////////////////////////////////////
-       //   R E G I O N
-       ///////////////////////////////////////////////////////////////////////////
-
-       if(get_layer_region_flag())
-       {
-               synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
-
-               Layer::Handle layer(get_canvas_interface()->add_layer_to("region",canvas,depth));
-               if (!layer)
-               {
-                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
-                       group.cancel();
-                       return;
-               }
-               layer_selection.push_back(layer);
-               layer->set_description(get_id()+_(" Region"));
-               get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
-
-               layer->set_param("feather",get_feather());
-               get_canvas_interface()->signal_layer_param_changed()(layer,"feather");
-
-               layer->set_param("invert",get_invert());
-               get_canvas_interface()->signal_layer_param_changed()(layer,"invert");
-
-               // I don't know if it's safe to reuse the same LayerParamConnect action, so I'm
-               // using 2 separate ones.
-               {
-                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
-                       assert(action);
-
-                       action->set_param("canvas",get_canvas());
-                       action->set_param("canvas_interface",get_canvas_interface());
-                       action->set_param("layer",layer);
-                       if(!action->set_param("param",String("bline")))
-                               synfig::error("LayerParamConnect didn't like \"param\"");
-                       if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
-                               synfig::error("LayerParamConnect didn't like \"value_node\"");
-
-                       if(!get_canvas_interface()->get_instance()->perform_action(action))
-                       {
-                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer"));
-                               group.cancel();
-                               throw String(_("Unable to create Region layer"));
-                               return;
-                       }
-               }
-
-               // only link the region's origin parameter if the option is selected and we're creating more than one layer
-               if (get_layer_link_origins_flag() && layers_to_create > 1)
-               {
-                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
-                       assert(action);
-
-                       action->set_param("canvas",get_canvas());
-                       action->set_param("canvas_interface",get_canvas_interface());
-                       action->set_param("layer",layer);
-                       if(!action->set_param("param",String("origin")))
-                               synfig::error("LayerParamConnect didn't like \"param\"");
-                       if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
-                               synfig::error("LayerParamConnect didn't like \"value_node\"");
-
-                       if(!get_canvas_interface()->get_instance()->perform_action(action))
-                       {
-                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer"));
-                               group.cancel();
-                               throw String(_("Unable to create Region layer"));
-                               return;
-                       }
-               }
-       }
-
-       ///////////////////////////////////////////////////////////////////////////
-       //   O U T L I N E
-       ///////////////////////////////////////////////////////////////////////////
-
-       if (get_layer_outline_flag())
-       {
-               Layer::Handle layer(get_canvas_interface()->add_layer_to("outline",canvas,depth));
-               if (!layer)
-               {
-                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
-                       group.cancel();
-                       return;
-               }
-               layer_selection.push_back(layer);
-               layer->set_description(get_id()+_(" Outline"));
-               get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
-
-               layer->set_param("feather",get_feather());
-               get_canvas_interface()->signal_layer_param_changed()(layer,"feather");
-
-               layer->set_param("invert",get_invert());
-               get_canvas_interface()->signal_layer_param_changed()(layer,"invert");
-
-               {
-                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
-                       assert(action);
-
-                       action->set_param("canvas",get_canvas());
-                       action->set_param("canvas_interface",get_canvas_interface());
-                       action->set_param("layer",layer);
-                       if(!action->set_param("param",String("bline")))
-                               synfig::error("LayerParamConnect didn't like \"param\"");
-                       if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
-                               synfig::error("LayerParamConnect didn't like \"value_node\"");
-
-                       if(!get_canvas_interface()->get_instance()->perform_action(action))
-                       {
-                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
-                               group.cancel();
-                               throw String(_("Unable to create Outline layer"));
-                               return;
-                       }
-               }
-
-               // only link the outline's origin parameter if the option is selected and we're creating more than one layer
-               if (get_layer_link_origins_flag() && layers_to_create > 1)
-               {
-                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
-                       assert(action);
-
-                       action->set_param("canvas",get_canvas());
-                       action->set_param("canvas_interface",get_canvas_interface());
-                       action->set_param("layer",layer);
-                       if(!action->set_param("param",String("origin")))
-                               synfig::error("LayerParamConnect didn't like \"param\"");
-                       if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
-                               synfig::error("LayerParamConnect didn't like \"value_node\"");
-
-                       if(!get_canvas_interface()->get_instance()->perform_action(action))
-                       {
-                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
-                               group.cancel();
-                               throw String(_("Unable to create Outline layer"));
-                               return;
-                       }
-               }
-       }
-
-       egress_on_selection_change=false;
-       get_canvas_interface()->get_selection_manager()->clear_selected_layers();
-       get_canvas_interface()->get_selection_manager()->set_selected_layers(layer_selection);
-       egress_on_selection_change=true;
-
-       //post clean up stuff...
-       reset();
-       increment_id();
-}
-
-Smach::event_result
-StateRectangle_Context::event_mouse_click_handler(const Smach::event& x)
-{
-       const EventMouse& event(*reinterpret_cast<const EventMouse*>(&x));
-
-       if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_DOWN && event.button==BUTTON_LEFT)
-       {
-               point_holder=get_work_area()->snap_point_to_grid(event.pos);
-               etl::handle<Duck> duck=new Duck();
-               duck->set_point(point_holder);
-               duck->set_name("p1");
-               duck->set_type(Duck::TYPE_POSITION);
-               get_work_area()->add_duck(duck);
-
-               point2_duck=new Duck();
-               point2_duck->set_point(point_holder);
-               point2_duck->set_name("p2");
-               point2_duck->set_type(Duck::TYPE_POSITION);
-               point2_duck->set_box_duck(duck);
-               get_work_area()->add_duck(point2_duck);
-
-               return Smach::RESULT_ACCEPT;
-       }
-
-       if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_DRAG && event.button==BUTTON_LEFT)
-       {
-               if (!point2_duck) return Smach::RESULT_OK;
-               point2_duck->set_point(get_work_area()->snap_point_to_grid(event.pos));
-               get_work_area()->queue_draw();
-               return Smach::RESULT_ACCEPT;
-       }
-
-       if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_UP && event.button==BUTTON_LEFT)
-       {
-               make_rectangle(point_holder, get_work_area()->snap_point_to_grid(event.pos));
-               get_work_area()->clear_ducks();
-               return Smach::RESULT_ACCEPT;
-       }
-
-       return Smach::RESULT_OK;
-}
-
-
-void
-StateRectangle_Context::refresh_ducks()
-{
-       get_work_area()->clear_ducks();
-       get_work_area()->queue_draw();
-}
diff --git a/synfig-studio/src/gui/state_rectangle.h b/synfig-studio/src/gui/state_rectangle.h
deleted file mode 100644 (file)
index 131dd40..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/* === S Y N F I G ========================================================= */
-/*!    \file state_rectangle.h
-**     \brief Rectangle creation state
-**
-**     $Id$
-**
-**     \legal
-**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
-**
-**     This package is free software; you can redistribute it and/or
-**     modify it under the terms of the GNU General Public License as
-**     published by the Free Software Foundation; either version 2 of
-**     the License, or (at your option) any later version.
-**
-**     This package is distributed in the hope that it will be useful,
-**     but WITHOUT ANY WARRANTY; without even the implied warranty of
-**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-**     General Public License for more details.
-**     \endlegal
-*/
-/* ========================================================================= */
-
-/* === S T A R T =========================================================== */
-
-#ifndef __SYNFIG_STUDIO_STATE_RECTANGLE_H
-#define __SYNFIG_STUDIO_STATE_RECTANGLE_H
-
-/* === H E A D E R S ======================================================= */
-
-#include "smach.h"
-
-
-/* === M A C R O S ========================================================= */
-
-/* === T Y P E D E F S ===================================================== */
-
-/* === C L A S S E S & S T R U C T S ======================================= */
-
-namespace studio {
-
-class StateRectangle_Context;
-
-class StateRectangle : public Smach::state<StateRectangle_Context>
-{
-public:
-       StateRectangle();
-       ~StateRectangle();
-}; // END of class StateRectangle
-
-extern StateRectangle state_rectangle;
-
-}; // END of namespace studio
-
-/* === E N D =============================================================== */
-
-#endif
diff --git a/synfig-studio/src/gui/state_rotate.cpp b/synfig-studio/src/gui/state_rotate.cpp
deleted file mode 100644 (file)
index 5463a41..0000000
+++ /dev/null
@@ -1,398 +0,0 @@
-/* === S Y N F I G ========================================================= */
-/*!    \file state_rotate.cpp
-**     \brief Template File
-**
-**     $Id$
-**
-**     \legal
-**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
-**  Copyright (c) 2008 Chris Moore
-**
-**     This package is free software; you can redistribute it and/or
-**     modify it under the terms of the GNU General Public License as
-**     published by the Free Software Foundation; either version 2 of
-**     the License, or (at your option) any later version.
-**
-**     This package is distributed in the hope that it will be useful,
-**     but WITHOUT ANY WARRANTY; without even the implied warranty of
-**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-**     General Public License for more details.
-**     \endlegal
-*/
-/* ========================================================================= */
-
-/* === H E A D E R S ======================================================= */
-
-#ifdef USING_PCH
-#      include "pch.h"
-#else
-#ifdef HAVE_CONFIG_H
-#      include <config.h>
-#endif
-
-#include <gtkmm/dialog.h>
-#include <gtkmm/entry.h>
-
-#include <synfig/valuenode_dynamiclist.h>
-#include <synfigapp/action_system.h>
-
-#include "state_rotate.h"
-#include "state_normal.h"
-#include "canvasview.h"
-#include "workarea.h"
-#include "app.h"
-
-#include <synfigapp/action.h>
-#include "event_mouse.h"
-#include "event_layerclick.h"
-#include "toolbox.h"
-#include "dialog_tooloptions.h"
-#include <gtkmm/optionmenu.h>
-#include "duck.h"
-#include <synfig/angle.h>
-#include <synfigapp/main.h>
-
-#include "general.h"
-
-#endif
-
-/* === U S I N G =========================================================== */
-
-using namespace std;
-using namespace etl;
-using namespace synfig;
-using namespace studio;
-
-/* === M A C R O S ========================================================= */
-
-#ifndef EPSILON
-#define EPSILON        0.0000001
-#endif
-
-/* === G L O B A L S ======================================================= */
-
-StateRotate studio::state_rotate;
-
-/* === C L A S S E S & S T R U C T S ======================================= */
-
-class DuckDrag_Rotate : public DuckDrag_Base
-{
-
-       synfig::Vector last_rotate;
-       synfig::Vector drag_offset;
-       synfig::Vector center;
-       synfig::Vector snap;
-
-       Angle original_angle;
-       Real original_mag;
-
-       std::vector<synfig::Vector> positions;
-
-
-       bool bad_drag;
-       bool move_only;
-
-public:
-       etl::handle<CanvasView> canvas_view_;
-       bool use_magnitude;
-       DuckDrag_Rotate();
-       void begin_duck_drag(Duckmatic* duckmatic, const synfig::Vector& begin);
-       bool end_duck_drag(Duckmatic* duckmatic);
-       void duck_drag(Duckmatic* duckmatic, const synfig::Vector& vector);
-
-       etl::handle<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view_->canvas_interface();}
-};
-
-
-class studio::StateRotate_Context : public sigc::trackable
-{
-       etl::handle<CanvasView> canvas_view_;
-       CanvasView::IsWorking is_working;
-
-       synfigapp::Settings& settings;
-
-       etl::handle<DuckDrag_Rotate> duck_dragger_;
-
-       Gtk::Table options_table;
-
-       Gtk::CheckButton checkbutton_scale;
-
-public:
-
-       bool get_scale_flag()const { return checkbutton_scale.get_active(); }
-       void set_scale_flag(bool x) { return checkbutton_scale.set_active(x); refresh_scale_flag(); }
-
-       Smach::event_result event_stop_handler(const Smach::event& x);
-       Smach::event_result event_refresh_tool_options(const Smach::event& x);
-
-       void refresh_tool_options();
-
-       void refresh_scale_flag() { if(duck_dragger_)duck_dragger_->use_magnitude=get_scale_flag(); }
-
-       StateRotate_Context(CanvasView* canvas_view);
-
-       ~StateRotate_Context();
-
-       const etl::handle<CanvasView>& get_canvas_view()const{return canvas_view_;}
-       etl::handle<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view_->canvas_interface();}
-       synfig::Canvas::Handle get_canvas()const{return canvas_view_->get_canvas();}
-       WorkArea * get_work_area()const{return canvas_view_->get_work_area();}
-
-       void load_settings();
-       void save_settings();
-};     // END of class StateRotate_Context
-
-/* === M E T H O D S ======================================================= */
-
-StateRotate::StateRotate():
-       Smach::state<StateRotate_Context>("rotate")
-{
-       insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateRotate_Context::event_refresh_tool_options));
-       insert(event_def(EVENT_STOP,&StateRotate_Context::event_stop_handler));
-}
-
-StateRotate::~StateRotate()
-{
-}
-
-void
-StateRotate_Context::load_settings()
-{
-       String value;
-
-       if(settings.get_value("rotate.scale",value) && value=="0")
-               set_scale_flag(false);
-       else
-               set_scale_flag(true);
-}
-
-void
-StateRotate_Context::save_settings()
-{
-       settings.set_value("rotate.scale",get_scale_flag()?"1":"0");
-}
-
-StateRotate_Context::StateRotate_Context(CanvasView* canvas_view):
-       canvas_view_(canvas_view),
-       is_working(*canvas_view),
-       settings(synfigapp::Main::get_selected_input_device()->settings()),
-       duck_dragger_(new DuckDrag_Rotate()),
-       checkbutton_scale(_("Allow Scale"))
-{
-       duck_dragger_->canvas_view_=get_canvas_view();
-
-       // Set up the tool options dialog
-       options_table.attach(*manage(new Gtk::Label(_("Rotate Tool"))), 0, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(checkbutton_scale,                                                 0, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-
-       checkbutton_scale.signal_toggled().connect(sigc::mem_fun(*this,&StateRotate_Context::refresh_scale_flag));
-
-       options_table.show_all();
-       refresh_tool_options();
-       //App::dialog_tool_options->set_widget(options_table);
-       App::dialog_tool_options->present();
-
-       get_work_area()->set_allow_layer_clicks(true);
-       get_work_area()->set_duck_dragger(duck_dragger_);
-
-       get_work_area()->set_cursor(Gdk::EXCHANGE);
-//     get_work_area()->reset_cursor();
-
-       App::toolbox->refresh();
-
-       load_settings();
-       refresh_scale_flag();
-}
-
-void
-StateRotate_Context::refresh_tool_options()
-{
-       App::dialog_tool_options->clear();
-       App::dialog_tool_options->set_widget(options_table);
-       App::dialog_tool_options->set_local_name(_("Rotate Tool"));
-       App::dialog_tool_options->set_name("rotate");
-}
-
-Smach::event_result
-StateRotate_Context::event_refresh_tool_options(const Smach::event& /*x*/)
-{
-       refresh_tool_options();
-       return Smach::RESULT_ACCEPT;
-}
-
-Smach::event_result
-StateRotate_Context::event_stop_handler(const Smach::event& /*x*/)
-{
-       throw &state_normal;
-       return Smach::RESULT_OK;
-}
-
-StateRotate_Context::~StateRotate_Context()
-{
-       save_settings();
-
-       get_work_area()->clear_duck_dragger();
-       get_work_area()->reset_cursor();
-
-       App::dialog_tool_options->clear();
-
-       App::toolbox->refresh();
-}
-
-
-
-
-DuckDrag_Rotate::DuckDrag_Rotate()
-{
-       use_magnitude=true;
-}
-
-void
-DuckDrag_Rotate::begin_duck_drag(Duckmatic* duckmatic, const synfig::Vector& offset)
-{
-       last_rotate=Vector(1,1);
-
-       const DuckList selected_ducks(duckmatic->get_selected_ducks());
-       DuckList::const_iterator iter;
-
-/*
-       if(duckmatic->get_selected_ducks().size()<2)
-       {
-               bad_drag=true;
-               return;
-       }
-*/
-       bad_drag=false;
-
-               drag_offset=duckmatic->find_duck(offset)->get_trans_point();
-
-               //snap=drag_offset-duckmatic->snap_point_to_grid(drag_offset);
-               //snap=offset-drag_offset;
-               snap=Vector(0,0);
-
-       // Calculate center
-       Point vmin(100000000,100000000);
-       Point vmax(-100000000,-100000000);
-       //std::set<etl::handle<Duck> >::iterator iter;
-       positions.clear();
-       int i;
-       for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
-       {
-               Point p((*iter)->get_trans_point());
-               vmin[0]=min(vmin[0],p[0]);
-               vmin[1]=min(vmin[1],p[1]);
-               vmax[0]=max(vmax[0],p[0]);
-               vmax[1]=max(vmax[1],p[1]);
-               positions.push_back(p);
-       }
-       center=(vmin+vmax)*0.5;
-       if((vmin-vmax).mag()<=EPSILON)
-               move_only=true;
-       else
-               move_only=false;
-
-
-       synfig::Vector vect(offset-center);
-       original_angle=Angle::tan(vect[1],vect[0]);
-       original_mag=vect.mag();
-}
-
-
-void
-DuckDrag_Rotate::duck_drag(Duckmatic* duckmatic, const synfig::Vector& vector)
-{
-       if(bad_drag)
-               return;
-
-       //std::set<etl::handle<Duck> >::iterator iter;
-       synfig::Vector vect(duckmatic->snap_point_to_grid(vector)-center+snap);
-
-       const DuckList selected_ducks(duckmatic->get_selected_ducks());
-       DuckList::const_iterator iter;
-
-       if(move_only)
-       {
-               int i;
-               for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
-               {
-                       if((*iter)->get_type()!=Duck::TYPE_VERTEX&&(*iter)->get_type()!=Duck::TYPE_POSITION)continue;
-
-                       Vector p(positions[i]);
-
-                       p[0]+=vect[0];
-                       p[1]+=vect[1];
-                       (*iter)->set_trans_point(p);
-               }
-               for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
-               {
-                       if(!((*iter)->get_type()!=Duck::TYPE_VERTEX&&(*iter)->get_type()!=Duck::TYPE_POSITION))continue;
-
-                       Vector p(positions[i]);
-
-                       p[0]+=vect[0];
-                       p[1]+=vect[1];
-                       (*iter)->set_trans_point(p);
-               }
-               return;
-       }
-
-       Angle::tan angle(vect[1],vect[0]);
-       angle=original_angle-angle;
-       Real mag(vect.mag()/original_mag);
-       Real sine(Angle::sin(angle).get());
-       Real cosine(Angle::cos(angle).get());
-
-       int i;
-       for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
-       {
-               if((*iter)->get_type()!=Duck::TYPE_VERTEX&&(*iter)->get_type()!=Duck::TYPE_POSITION)continue;
-
-               Vector x(positions[i]-center),p;
-
-               p[0]=cosine*x[0]+sine*x[1];
-               p[1]=-sine*x[0]+cosine*x[1];
-               if(use_magnitude)p*=mag;
-               p+=center;
-               (*iter)->set_trans_point(p);
-       }
-       for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
-       {
-               if(!((*iter)->get_type()!=Duck::TYPE_VERTEX&&(*iter)->get_type()!=Duck::TYPE_POSITION))continue;
-
-               Vector x(positions[i]-center),p;
-
-               p[0]=cosine*x[0]+sine*x[1];
-               p[1]=-sine*x[0]+cosine*x[1];
-               if(use_magnitude)p*=mag;
-               p+=center;
-               (*iter)->set_trans_point(p);
-       }
-
-       last_rotate=vect;
-       //snap=Vector(0,0);
-}
-
-bool
-DuckDrag_Rotate::end_duck_drag(Duckmatic* duckmatic)
-{
-       if(bad_drag)return false;
-       if(move_only)
-       {
-               synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Move Duck"));
-               duckmatic->signal_edited_selected_ducks();
-               return true;
-       }
-
-       synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Rotate Ducks"));
-
-       if((last_rotate-Vector(1,1)).mag()>0.0001)
-       {
-               duckmatic->signal_edited_selected_ducks();
-               return true;
-       }
-       else
-       {
-               duckmatic->signal_user_click_selected_ducks(0);
-               return false;
-       }
-}
diff --git a/synfig-studio/src/gui/state_rotate.h b/synfig-studio/src/gui/state_rotate.h
deleted file mode 100644 (file)
index e2caafe..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/* === S Y N F I G ========================================================= */
-/*!    \file state_rotate.h
-**     \brief Template Header
-**
-**     $Id$
-**
-**     \legal
-**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
-**
-**     This package is free software; you can redistribute it and/or
-**     modify it under the terms of the GNU General Public License as
-**     published by the Free Software Foundation; either version 2 of
-**     the License, or (at your option) any later version.
-**
-**     This package is distributed in the hope that it will be useful,
-**     but WITHOUT ANY WARRANTY; without even the implied warranty of
-**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-**     General Public License for more details.
-**     \endlegal
-*/
-/* ========================================================================= */
-
-/* === S T A R T =========================================================== */
-
-#ifndef __SYNFIG_STUDIO_STATE_ROTATE_H
-#define __SYNFIG_STUDIO_STATE_ROTATE_H
-
-/* === H E A D E R S ======================================================= */
-
-#include "smach.h"
-
-
-/* === M A C R O S ========================================================= */
-
-/* === T Y P E D E F S ===================================================== */
-
-/* === C L A S S E S & S T R U C T S ======================================= */
-
-namespace studio {
-
-class StateRotate_Context;
-
-class StateRotate : public Smach::state<StateRotate_Context>
-{
-public:
-       StateRotate();
-       ~StateRotate();
-}; // END of class StateRotate
-
-extern StateRotate state_rotate;
-
-}; // END of namespace studio
-
-/* === E N D =============================================================== */
-
-#endif
diff --git a/synfig-studio/src/gui/state_scale.cpp b/synfig-studio/src/gui/state_scale.cpp
deleted file mode 100644 (file)
index edfb89b..0000000
+++ /dev/null
@@ -1,389 +0,0 @@
-/* === S Y N F I G ========================================================= */
-/*!    \file state_scale.cpp
-**     \brief Template File
-**
-**     $Id$
-**
-**     \legal
-**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
-**  Copyright (c) 2008 Chris Moore
-**
-**     This package is free software; you can redistribute it and/or
-**     modify it under the terms of the GNU General Public License as
-**     published by the Free Software Foundation; either version 2 of
-**     the License, or (at your option) any later version.
-**
-**     This package is distributed in the hope that it will be useful,
-**     but WITHOUT ANY WARRANTY; without even the implied warranty of
-**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-**     General Public License for more details.
-**     \endlegal
-*/
-/* ========================================================================= */
-
-/* === H E A D E R S ======================================================= */
-
-#ifdef USING_PCH
-#      include "pch.h"
-#else
-#ifdef HAVE_CONFIG_H
-#      include <config.h>
-#endif
-
-#include <gtkmm/dialog.h>
-#include <gtkmm/entry.h>
-
-#include <synfig/valuenode_dynamiclist.h>
-#include <synfigapp/action_system.h>
-
-#include "state_scale.h"
-#include "state_normal.h"
-#include "canvasview.h"
-#include "workarea.h"
-#include "app.h"
-
-#include <synfigapp/action.h>
-#include "event_mouse.h"
-#include "event_layerclick.h"
-#include "toolbox.h"
-#include "dialog_tooloptions.h"
-#include <gtkmm/optionmenu.h>
-#include "duck.h"
-#include <synfigapp/main.h>
-
-#include "general.h"
-
-#endif
-
-/* === U S I N G =========================================================== */
-
-using namespace std;
-using namespace etl;
-using namespace synfig;
-using namespace studio;
-
-/* === M A C R O S ========================================================= */
-
-/* === G L O B A L S ======================================================= */
-
-StateScale studio::state_scale;
-
-/* === C L A S S E S & S T R U C T S ======================================= */
-
-class DuckDrag_Scale : public DuckDrag_Base
-{
-
-       synfig::Vector last_scale;
-       synfig::Vector drag_offset;
-       synfig::Vector center;
-       synfig::Vector snap;
-
-       std::vector<synfig::Vector> positions;
-
-       bool move_only;
-
-       bool bad_drag;
-public:
-       bool lock_aspect;
-       DuckDrag_Scale();
-       void begin_duck_drag(Duckmatic* duckmatic, const synfig::Vector& begin);
-       bool end_duck_drag(Duckmatic* duckmatic);
-       void duck_drag(Duckmatic* duckmatic, const synfig::Vector& vector);
-};
-
-
-class studio::StateScale_Context : public sigc::trackable
-{
-       etl::handle<CanvasView> canvas_view_;
-       CanvasView::IsWorking is_working;
-
-       synfigapp::Settings& settings;
-
-       etl::handle<DuckDrag_Scale> duck_dragger_;
-
-       Gtk::Table options_table;
-
-
-       Gtk::CheckButton checkbutton_aspect_lock;
-
-public:
-
-       bool get_aspect_lock_flag()const { return checkbutton_aspect_lock.get_active(); }
-       void set_aspect_lock_flag(bool x) { return checkbutton_aspect_lock.set_active(x); refresh_aspect_lock_flag(); }
-
-       void refresh_aspect_lock_flag() { if(duck_dragger_)duck_dragger_->lock_aspect=get_aspect_lock_flag(); }
-
-       Smach::event_result event_stop_handler(const Smach::event& x);
-       Smach::event_result event_refresh_tool_options(const Smach::event& x);
-
-       void refresh_tool_options();
-
-       StateScale_Context(CanvasView* canvas_view);
-
-       ~StateScale_Context();
-
-       const etl::handle<CanvasView>& get_canvas_view()const{return canvas_view_;}
-       etl::handle<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view_->canvas_interface();}
-       synfig::Canvas::Handle get_canvas()const{return canvas_view_->get_canvas();}
-       WorkArea * get_work_area()const{return canvas_view_->get_work_area();}
-
-       void load_settings();
-       void save_settings();
-};     // END of class StateScale_Context
-
-/* === M E T H O D S ======================================================= */
-
-StateScale::StateScale():
-       Smach::state<StateScale_Context>("scale")
-{
-       insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateScale_Context::event_refresh_tool_options));
-       insert(event_def(EVENT_STOP,&StateScale_Context::event_stop_handler));
-}
-
-StateScale::~StateScale()
-{
-}
-
-void
-StateScale_Context::load_settings()
-{
-       String value;
-
-       if(settings.get_value("scale.lock_aspect",value) && value=="0")
-               set_aspect_lock_flag(false);
-       else
-               set_aspect_lock_flag(true);
-}
-
-void
-StateScale_Context::save_settings()
-{
-       settings.set_value("scale.lock_aspect",get_aspect_lock_flag()?"1":"0");
-}
-
-StateScale_Context::StateScale_Context(CanvasView* canvas_view):
-       canvas_view_(canvas_view),
-       is_working(*canvas_view),
-       settings(synfigapp::Main::get_selected_input_device()->settings()),
-       duck_dragger_(new DuckDrag_Scale()),
-       checkbutton_aspect_lock(_("Lock Aspect Ratio"))
-{
-       // Set up the tool options dialog
-       options_table.attach(*manage(new Gtk::Label(_("Scale Tool"))),  0, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(checkbutton_aspect_lock,                                   0, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-
-       checkbutton_aspect_lock.signal_toggled().connect(sigc::mem_fun(*this,&StateScale_Context::refresh_aspect_lock_flag));
-
-       options_table.show_all();
-       refresh_tool_options();
-       App::dialog_tool_options->present();
-
-       get_work_area()->set_allow_layer_clicks(true);
-       get_work_area()->set_duck_dragger(duck_dragger_);
-
-       get_work_area()->set_cursor(Gdk::SIZING);
-//     get_work_area()->reset_cursor();
-
-       App::toolbox->refresh();
-
-       set_aspect_lock_flag(true);
-       load_settings();
-}
-
-void
-StateScale_Context::refresh_tool_options()
-{
-       App::dialog_tool_options->clear();
-       App::dialog_tool_options->set_widget(options_table);
-       App::dialog_tool_options->set_local_name(_("Scale Tool"));
-       App::dialog_tool_options->set_name("scale");
-}
-
-Smach::event_result
-StateScale_Context::event_refresh_tool_options(const Smach::event& /*x*/)
-{
-       refresh_tool_options();
-       return Smach::RESULT_ACCEPT;
-}
-
-Smach::event_result
-StateScale_Context::event_stop_handler(const Smach::event& /*x*/)
-{
-       throw &state_normal;
-       return Smach::RESULT_OK;
-}
-
-StateScale_Context::~StateScale_Context()
-{
-       save_settings();
-
-       get_work_area()->clear_duck_dragger();
-       get_work_area()->reset_cursor();
-
-       App::dialog_tool_options->clear();
-
-       App::toolbox->refresh();
-}
-
-
-
-
-DuckDrag_Scale::DuckDrag_Scale():
-       lock_aspect(true)
-{
-}
-
-#ifndef EPSILON
-#define EPSILON        0.0000001
-#endif
-
-void
-DuckDrag_Scale::begin_duck_drag(Duckmatic* duckmatic, const synfig::Vector& offset)
-{
-       last_scale=Vector(1,1);
-       const DuckList selected_ducks(duckmatic->get_selected_ducks());
-       DuckList::const_iterator iter;
-
-       //if(duckmatic->get_selected_ducks().size()<2)
-       //{
-       //      bad_drag=true;
-//             return;
-//     }
-       bad_drag=false;
-
-               drag_offset=duckmatic->find_duck(offset)->get_trans_point();
-
-               //snap=drag_offset-duckmatic->snap_point_to_grid(drag_offset);
-               //snap=offset-drag_offset;
-               snap=Vector(0,0);
-
-       // Calculate center
-       Point vmin(100000000,100000000);
-       Point vmax(-100000000,-100000000);
-       //std::set<etl::handle<Duck> >::iterator iter;
-       positions.clear();
-       int i;
-       for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
-       {
-               Point p((*iter)->get_trans_point());
-               vmin[0]=min(vmin[0],p[0]);
-               vmin[1]=min(vmin[1],p[1]);
-               vmax[0]=max(vmax[0],p[0]);
-               vmax[1]=max(vmax[1],p[1]);
-               positions.push_back(p);
-       }
-       if((vmin-vmax).mag()<=EPSILON)
-               move_only=true;
-       else
-               move_only=false;
-
-       center=(vmin+vmax)*0.5;
-}
-
-
-void
-DuckDrag_Scale::duck_drag(Duckmatic* duckmatic, const synfig::Vector& vector)
-{
-       const DuckList selected_ducks(duckmatic->get_selected_ducks());
-       DuckList::const_iterator iter;
-
-       if(bad_drag)
-               return;
-
-       //std::set<etl::handle<Duck> >::iterator iter;
-       synfig::Vector vect(duckmatic->snap_point_to_grid(vector)-center);
-       last_scale=vect;
-
-       if(move_only)
-       {
-               int i;
-               for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
-               {
-                       if(((*iter)->get_type()!=Duck::TYPE_VERTEX&&(*iter)->get_type()!=Duck::TYPE_POSITION))continue;
-
-                       Vector p(positions[i]);
-
-                       p[0]+=vect[0];
-                       p[1]+=vect[1];
-                       (*iter)->set_trans_point(p);
-               }
-               for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
-               {
-                       if(!((*iter)->get_type()!=Duck::TYPE_VERTEX&&(*iter)->get_type()!=Duck::TYPE_POSITION))continue;
-
-                       Vector p(positions[i]);
-
-                       p[0]+=vect[0];
-                       p[1]+=vect[1];
-                       (*iter)->set_trans_point(p);
-               }
-               return;
-       }
-
-       if(!lock_aspect)
-       {
-               if(abs(drag_offset[0]-center[0])>EPSILON)
-                       vect[0]/=drag_offset[0]-center[0];
-               else
-                       vect[0]=1;
-               if(abs(drag_offset[1]-center[1])>EPSILON)
-                       vect[1]/=drag_offset[1]-center[1];
-               else
-                       vect[1]=1;
-               }
-       else
-       {
-               //vect[0]=vect[1]=vect.mag()*0.707106781;
-               Real amount(vect.mag()/(drag_offset-center).mag());
-               vect[0]=vect[1]=amount;
-       }
-
-       if(vect[0]<EPSILON && vect[0]>-EPSILON)
-               vect[0]=1;
-       if(vect[1]<EPSILON && vect[1]>-EPSILON)
-               vect[1]=1;
-
-       int i;
-       for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
-       {
-               if(((*iter)->get_type()!=Duck::TYPE_VERTEX&&(*iter)->get_type()!=Duck::TYPE_POSITION))continue;
-
-               Vector p(positions[i]-center);
-
-               p[0]*=vect[0];
-               p[1]*=vect[1];
-               p+=center;
-               (*iter)->set_trans_point(p);
-       }
-       for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
-       {
-               if(!((*iter)->get_type()!=Duck::TYPE_VERTEX&&(*iter)->get_type()!=Duck::TYPE_POSITION))continue;
-
-               Vector p(positions[i]-center);
-
-               p[0]*=vect[0];
-               p[1]*=vect[1];
-               p+=center;
-               (*iter)->set_trans_point(p);
-       }
-
-       last_scale=vect;
-       //snap=Vector(0,0);
-}
-
-bool
-DuckDrag_Scale::end_duck_drag(Duckmatic* duckmatic)
-{
-       if(bad_drag)return false;
-
-       if((last_scale-Vector(1,1)).mag()>0.0001)
-       {
-               duckmatic->signal_edited_selected_ducks();
-               return true;
-       }
-       else
-       {
-               duckmatic->signal_user_click_selected_ducks(0);
-               return false;
-       }
-}
diff --git a/synfig-studio/src/gui/state_scale.h b/synfig-studio/src/gui/state_scale.h
deleted file mode 100644 (file)
index f351c12..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/* === S Y N F I G ========================================================= */
-/*!    \file state_scale.h
-**     \brief Template Header
-**
-**     $Id$
-**
-**     \legal
-**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
-**
-**     This package is free software; you can redistribute it and/or
-**     modify it under the terms of the GNU General Public License as
-**     published by the Free Software Foundation; either version 2 of
-**     the License, or (at your option) any later version.
-**
-**     This package is distributed in the hope that it will be useful,
-**     but WITHOUT ANY WARRANTY; without even the implied warranty of
-**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-**     General Public License for more details.
-**     \endlegal
-*/
-/* ========================================================================= */
-
-/* === S T A R T =========================================================== */
-
-#ifndef __SYNFIG_STUDIO_STATE_SCALE_H
-#define __SYNFIG_STUDIO_STATE_SCALE_H
-
-/* === H E A D E R S ======================================================= */
-
-#include "smach.h"
-
-/* === M A C R O S ========================================================= */
-
-/* === T Y P E D E F S ===================================================== */
-
-/* === C L A S S E S & S T R U C T S ======================================= */
-
-namespace studio {
-
-class StateScale_Context;
-
-class StateScale : public Smach::state<StateScale_Context>
-{
-public:
-       StateScale();
-       ~StateScale();
-}; // END of class StateScale
-
-extern StateScale state_scale;
-
-}; // END of namespace studio
-
-/* === E N D =============================================================== */
-
-#endif
diff --git a/synfig-studio/src/gui/state_sketch.cpp b/synfig-studio/src/gui/state_sketch.cpp
deleted file mode 100644 (file)
index f8b77a3..0000000
+++ /dev/null
@@ -1,508 +0,0 @@
-/* === S Y N F I G ========================================================= */
-/*!    \file state_sketch.cpp
-**     \brief Template File
-**
-**     $Id$
-**
-**     \legal
-**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
-**     Copyright (c) 2007, 2008 Chris Moore
-**
-**     This package is free software; you can redistribute it and/or
-**     modify it under the terms of the GNU General Public License as
-**     published by the Free Software Foundation; either version 2 of
-**     the License, or (at your option) any later version.
-**
-**     This package is distributed in the hope that it will be useful,
-**     but WITHOUT ANY WARRANTY; without even the implied warranty of
-**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-**     General Public License for more details.
-**     \endlegal
-*/
-/* ========================================================================= */
-
-/* === H E A D E R S ======================================================= */
-
-#ifdef USING_PCH
-#      include "pch.h"
-#else
-#ifdef HAVE_CONFIG_H
-#      include <config.h>
-#endif
-
-#include <gtkmm/dialog.h>
-#include <gtkmm/entry.h>
-
-#include <synfig/valuenode_dynamiclist.h>
-
-#include "state_sketch.h"
-#include "state_normal.h"
-#include "state_stroke.h"
-#include "canvasview.h"
-#include "workarea.h"
-#include "app.h"
-#include <synfig/valuenode_bline.h>
-#include <ETL/hermite>
-#include <ETL/calculus>
-#include <utility>
-#include "event_mouse.h"
-#include "event_layerclick.h"
-#include "toolbox.h"
-
-#include <synfigapp/blineconvert.h>
-#include <synfigapp/main.h>
-
-#include <ETL/gaussian>
-
-#include "dialog_tooloptions.h"
-
-#include <gtkmm/table.h>
-#include <gtkmm/label.h>
-#include <gtkmm/button.h>
-#include <gtkmm/checkbutton.h>
-#include <gtkmm/actiongroup.h>
-
-#include "general.h"
-
-#endif
-
-/* === U S I N G =========================================================== */
-
-using namespace std;
-using namespace etl;
-using namespace synfig;
-using namespace studio;
-
-/* === M A C R O S ========================================================= */
-
-/* === G L O B A L S ======================================================= */
-
-StateSketch studio::state_sketch;
-
-/* === C L A S S E S & S T R U C T S ======================================= */
-
-class studio::StateSketch_Context : public sigc::trackable
-{
-       Glib::RefPtr<Gtk::ActionGroup> action_group;
-
-       etl::handle<CanvasView> canvas_view_;
-       CanvasView::IsWorking is_working;
-
-       bool prev_table_status;
-       bool prev_workarea_layer_status_;
-
-       Gtk::Table options_table;
-       Gtk::Button button_clear_sketch;
-       Gtk::Button button_undo_stroke;
-       Gtk::Button button_save_sketch;
-       Gtk::Button button_load_sketch;
-       Gtk::CheckButton checkbutton_show_sketch;
-
-       void clear_sketch();
-       void save_sketch();
-       void load_sketch();
-       void undo_stroke();
-       void toggle_show_sketch();
-
-public:
-
-       Smach::event_result event_stop_handler(const Smach::event& x);
-
-       Smach::event_result event_refresh_handler(const Smach::event& x);
-
-       Smach::event_result event_mouse_down_handler(const Smach::event& x);
-
-       Smach::event_result event_stroke(const Smach::event& x);
-
-       Smach::event_result event_refresh_tool_options(const Smach::event& x);
-       Smach::event_result event_yield_tool_options(const Smach::event& x);
-
-       void refresh_tool_options();
-       void yield_tool_options();
-
-       StateSketch_Context(CanvasView* canvas_view);
-
-       ~StateSketch_Context();
-
-       const etl::handle<CanvasView>& get_canvas_view()const{return canvas_view_;}
-       etl::handle<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view_->canvas_interface();}
-       synfig::Time get_time()const { return get_canvas_interface()->get_time(); }
-       synfig::Canvas::Handle get_canvas()const{return canvas_view_->get_canvas();}
-       WorkArea * get_work_area()const{return canvas_view_->get_work_area();}
-
-};     // END of class StateSketch_Context
-
-
-/* === M E T H O D S ======================================================= */
-
-StateSketch::StateSketch():
-       Smach::state<StateSketch_Context>("sketch")
-{
-       insert(event_def(EVENT_STOP,&StateSketch_Context::event_stop_handler));
-       //insert(event_def(EVENT_REFRESH,&StateSketch_Context::event_refresh_handler));
-       insert(event_def(EVENT_REFRESH_DUCKS,&StateSketch_Context::event_refresh_handler));
-       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateSketch_Context::event_mouse_down_handler));
-       insert(event_def(EVENT_WORKAREA_STROKE,&StateSketch_Context::event_stroke));
-       insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateSketch_Context::event_refresh_tool_options));
-       insert(event_def(EVENT_YIELD_TOOL_OPTIONS,&StateSketch_Context::event_yield_tool_options));
-}
-
-StateSketch::~StateSketch()
-{
-}
-
-void
-StateSketch_Context::save_sketch()
-{
-       synfig::String filename(basename(get_canvas()->get_file_name())+".sketch");
-
-       while(App::dialog_save_file(_("Save Sketch"), filename, SKETCH_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())
-                       continue;
-
-               if(get_work_area()->save_sketch(filename))
-                       break;
-
-               get_canvas_view()->get_ui_interface()->error(_("Unable to save sketch"));
-       }
-}
-
-void
-StateSketch_Context::load_sketch()
-{
-       synfig::String filename(basename(get_canvas()->get_file_name())+".sketch");
-
-       while(App::dialog_open_file(_("Load Sketch"), filename, SKETCH_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())
-                       continue;
-
-               if(get_work_area()->load_sketch(filename))
-                       break;
-
-               get_canvas_view()->get_ui_interface()->error(_("Unable to load sketch"));
-       }
-       get_work_area()->queue_draw();
-}
-
-void
-StateSketch_Context::clear_sketch()
-{
-       get_work_area()->clear_persistent_strokes();
-
-       // if the sketch is currently shown, make sure it is updated
-       //! \todo is there a better way than this of getting Duckmatic to update its stroke_list_?
-       if (checkbutton_show_sketch.get_active())
-       {
-               get_work_area()->set_show_persistent_strokes(false);
-               get_work_area()->set_show_persistent_strokes(true);
-               get_canvas_view()->get_smach().process_event(EVENT_REFRESH);
-       }
-}
-
-void
-StateSketch_Context::undo_stroke()
-{
-       if(!get_work_area()->persistent_stroke_list().empty())
-       {
-               get_work_area()->persistent_stroke_list().pop_back();
-
-               // if the sketch is currently shown, make sure it is updated
-               //! \todo is there a better way than this of getting Duckmatic to update its stroke_list_?
-               if (checkbutton_show_sketch.get_active())
-               {
-                       get_work_area()->set_show_persistent_strokes(false);
-                       get_work_area()->set_show_persistent_strokes(true);
-                       get_canvas_view()->get_smach().process_event(EVENT_REFRESH);
-               }
-       }
-}
-
-void
-StateSketch_Context::toggle_show_sketch()
-{
-       get_work_area()->set_show_persistent_strokes(checkbutton_show_sketch.get_active());
-       get_work_area()->queue_draw();
-}
-
-StateSketch_Context::StateSketch_Context(CanvasView* canvas_view):
-       action_group(Gtk::ActionGroup::create("action_group_state_sketch")),
-       canvas_view_(canvas_view),
-       is_working(*canvas_view),
-       prev_workarea_layer_status_(get_work_area()->get_allow_layer_clicks()),
-       button_clear_sketch(_("Clear Sketch")),
-       button_undo_stroke(_("Undo Stroke")),
-       button_save_sketch(_("Save Sketch")),
-       button_load_sketch(_("Load Sketch")),
-       checkbutton_show_sketch(_("Show Sketch"))
-{
-    Glib::ustring ui_info =
-       "<ui>"
-       "       <toolbar action='toolbar-sketch'>"
-       "       <toolitem action='sketch-undo' />"
-       "       <toolitem action='sketch-clear' />"
-       "       <toolitem action='sketch-save-as' />"
-       "       <toolitem action='sketch-open' />"
-       "       </toolbar>"
-       "</ui>";
-
-       action_group->add(Gtk::Action::create(
-               "sketch-undo",
-               Gtk::StockID("gtk-undo"),
-               _("Undo Last Stroke"),
-               _("Undo Last Stroke")
-       ),
-               sigc::mem_fun(
-                       *this,
-                       &studio::StateSketch_Context::undo_stroke
-               )
-       );
-
-       action_group->add(Gtk::Action::create(
-               "sketch-clear",
-               Gtk::StockID("gtk-clear"),
-               _("Clear Sketch"),
-               _("Clear Sketch")
-       ),
-               sigc::mem_fun(
-                       *this,
-                       &studio::StateSketch_Context::clear_sketch
-               )
-       );
-
-       action_group->add(Gtk::Action::create(
-               "sketch-save-as",
-               Gtk::StockID("gtk-save-as"),
-               _("Save Sketch As..."),
-               _("Save Sketch As...")
-       ),
-               sigc::mem_fun(
-                       *this,
-                       &studio::StateSketch_Context::save_sketch
-               )
-       );
-
-       action_group->add(Gtk::Action::create(
-               "sketch-save-as",
-               Gtk::StockID("gtk-save-as"),
-               _("Save Sketch As..."),
-               _("Save Sketch As...")
-       ),
-               sigc::mem_fun(
-                       *this,
-                       &studio::StateSketch_Context::save_sketch
-               )
-       );
-
-       action_group->add(Gtk::Action::create(
-               "sketch-open",
-               Gtk::StockID("gtk-open"),
-               _("Open a Sketch"),
-               _("Open a Sketch")
-       ),
-               sigc::mem_fun(
-                       *this,
-                       &studio::StateSketch_Context::load_sketch
-               )
-       );
-
-       action_group->add( Gtk::Action::create("toolbar-sketch", "Sketch Toolbar") );
-
-       App::ui_manager()->add_ui_from_string(ui_info);
-
-       checkbutton_show_sketch.set_active(get_work_area()->get_show_persistent_strokes());
-
-       button_clear_sketch.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::clear_sketch));
-       button_undo_stroke.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::undo_stroke));
-       button_save_sketch.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::save_sketch));
-       button_load_sketch.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::load_sketch));
-       checkbutton_show_sketch.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::toggle_show_sketch));
-
-       options_table.attach(*manage(new Gtk::Label(_("Sketch Tool"))), 0, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(checkbutton_show_sketch,                                   0, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       //options_table.attach(button_undo_stroke, 0, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       //options_table.attach(button_clear_sketch, 0, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       //options_table.attach(button_save_sketch, 0, 1, 4, 5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       //options_table.attach(button_load_sketch, 1, 2, 4, 5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-
-       options_table.show_all();
-       refresh_tool_options();
-       App::dialog_tool_options->present();
-
-       // Turn off layer clicking
-       get_work_area()->set_allow_layer_clicks(false);
-
-       get_work_area()->set_cursor(Gdk::PENCIL);
-
-       // Turn off duck clicking
-       get_work_area()->set_allow_duck_clicks(false);
-
-       // clear out the ducks
-       //get_work_area()->clear_ducks();
-
-       // Refresh the work area
-       //get_work_area()->queue_draw();
-
-       // Hide the tables if they are showing
-       prev_table_status=get_canvas_view()->tables_are_visible();
-       //if(prev_table_status)get_canvas_view()->hide_tables();
-
-       // Disable the time bar
-       //get_canvas_view()->set_sensitive_timebar(false);
-
-       // Connect a signal
-       //get_work_area()->signal_user_click().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::on_user_click));
-
-       App::toolbox->refresh();
-}
-
-StateSketch_Context::~StateSketch_Context()
-{
-       get_work_area()->reset_cursor();
-
-       App::dialog_tool_options->clear();
-
-       // Restore layer clicking
-       get_work_area()->set_allow_layer_clicks(prev_workarea_layer_status_);
-
-       // Restore duck clicking
-       get_work_area()->set_allow_duck_clicks(true);
-
-       // Enable the time bar
-       //get_canvas_view()->set_sensitive_timebar(true);
-
-       // Bring back the tables if they were out before
-       if(prev_table_status)get_canvas_view()->show_tables();
-
-       // Refresh the work area
-       //get_work_area()->queue_draw();
-
-       App::toolbox->refresh();
-}
-
-void
-StateSketch_Context::yield_tool_options()
-{
-       App::dialog_tool_options->clear();
-       App::ui_manager()->remove_action_group(action_group);
-}
-
-void
-StateSketch_Context::refresh_tool_options()
-{
-       App::dialog_tool_options->clear();
-       App::dialog_tool_options->set_widget(options_table);
-       App::dialog_tool_options->set_local_name(_("Sketch Tool"));
-       App::dialog_tool_options->set_name("sketch");
-
-       App::ui_manager()->insert_action_group(action_group);
-       App::dialog_tool_options->set_toolbar(*dynamic_cast<Gtk::Toolbar*>(App::ui_manager()->get_widget("/toolbar-sketch")));
-
-       /*
-       App::dialog_tool_options->add_button(
-               Gtk::StockID("gtk-undo"),
-               _("Undo Last Stroke")
-       )->signal_clicked().connect(
-               sigc::mem_fun(
-                       *this,
-                       &studio::StateSketch_Context::undo_stroke
-               )
-       );
-       App::dialog_tool_options->add_button(
-               Gtk::StockID("gtk-clear"),
-               _("Clear Sketch")
-       )->signal_clicked().connect(
-               sigc::mem_fun(
-                       *this,
-                       &studio::StateSketch_Context::clear_sketch
-               )
-       );
-       App::dialog_tool_options->add_button(
-               Gtk::StockID("gtk-save"),
-               _("Save Sketch to a File")
-       )->signal_clicked().connect(
-               sigc::mem_fun(
-                       *this,
-                       &studio::StateSketch_Context::save_sketch
-               )
-       );
-
-       App::dialog_tool_options->add_button(
-               Gtk::StockID("gtk-open"),
-               _("Open a Sketch")
-       )->signal_clicked().connect(
-               sigc::mem_fun(
-                       *this,
-                       &studio::StateSketch_Context::load_sketch
-               )
-       );
-       */
-       //button_clear_sketch.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::clear_sketch));
-       //button_undo_stroke.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::undo_stroke));
-       //button_save_sketch.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::save_sketch));
-       //button_load_sketch.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::load_sketch));
-       //checkbutton_show_sketch.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::toggle_show_sketch));
-}
-
-Smach::event_result
-StateSketch_Context::event_refresh_tool_options(const Smach::event& /*x*/)
-{
-       refresh_tool_options();
-       return Smach::RESULT_ACCEPT;
-}
-
-Smach::event_result
-StateSketch_Context::event_yield_tool_options(const Smach::event& /*x*/)
-{
-       yield_tool_options();
-       return Smach::RESULT_ACCEPT;
-}
-
-Smach::event_result
-StateSketch_Context::event_stop_handler(const Smach::event& /*x*/)
-{
-       //throw Smach::egress_exception();
-       throw &state_normal;
-       return Smach::RESULT_OK;
-}
-
-Smach::event_result
-StateSketch_Context::event_refresh_handler(const Smach::event& /*x*/)
-{
-       return Smach::RESULT_ACCEPT;
-}
-
-Smach::event_result
-StateSketch_Context::event_mouse_down_handler(const Smach::event& x)
-{
-       const EventMouse& event(*reinterpret_cast<const EventMouse*>(&x));
-       switch(event.button)
-       {
-       case BUTTON_LEFT:
-               {
-                       // Enter the stroke state to get the stroke
-                       get_canvas_view()->get_smach().push_state(&state_stroke);
-                       return Smach::RESULT_ACCEPT;
-               }
-
-       default:
-               return Smach::RESULT_OK;
-       }
-}
-
-Smach::event_result
-StateSketch_Context::event_stroke(const Smach::event& x)
-{
-       const EventStroke& event(*reinterpret_cast<const EventStroke*>(&x));
-
-       assert(event.stroke_data);
-
-       get_work_area()->add_persistent_stroke(event.stroke_data,synfigapp::Main::get_outline_color());
-
-       return Smach::RESULT_ACCEPT;
-}
diff --git a/synfig-studio/src/gui/state_sketch.h b/synfig-studio/src/gui/state_sketch.h
deleted file mode 100644 (file)
index 301c81d..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/* === S Y N F I G ========================================================= */
-/*!    \file state_sketch.h
-**     \brief Template Header
-**
-**     $Id$
-**
-**     \legal
-**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
-**
-**     This package is free software; you can redistribute it and/or
-**     modify it under the terms of the GNU General Public License as
-**     published by the Free Software Foundation; either version 2 of
-**     the License, or (at your option) any later version.
-**
-**     This package is distributed in the hope that it will be useful,
-**     but WITHOUT ANY WARRANTY; without even the implied warranty of
-**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-**     General Public License for more details.
-**     \endlegal
-*/
-/* ========================================================================= */
-
-/* === S T A R T =========================================================== */
-
-#ifndef __SYNFIG_STUDIO_STATE_SKETCH_H
-#define __SYNFIG_STUDIO_STATE_SKETCH_H
-
-/* === H E A D E R S ======================================================= */
-
-#include "smach.h"
-
-/* === M A C R O S ========================================================= */
-
-/* === T Y P E D E F S ===================================================== */
-
-/* === C L A S S E S & S T R U C T S ======================================= */
-
-namespace studio {
-
-class StateSketch_Context;
-
-class StateSketch : public Smach::state<StateSketch_Context>
-{
-public:
-       StateSketch();
-       ~StateSketch();
-}; // END of class StateSketch
-
-extern StateSketch state_sketch;
-
-}; // END of namespace studio
-
-/* === E N D =============================================================== */
-
-#endif
diff --git a/synfig-studio/src/gui/state_smoothmove.cpp b/synfig-studio/src/gui/state_smoothmove.cpp
deleted file mode 100644 (file)
index f42df35..0000000
+++ /dev/null
@@ -1,388 +0,0 @@
-/* === S Y N F I G ========================================================= */
-/*!    \file state_smoothmove.cpp
-**     \brief Template File
-**
-**     $Id$
-**
-**     \legal
-**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
-**  Copyright (c) 2008 Chris Moore
-**     Copyright (c) 2009 Nikita Kitaev
-**
-**     This package is free software; you can redistribute it and/or
-**     modify it under the terms of the GNU General Public License as
-**     published by the Free Software Foundation; either version 2 of
-**     the License, or (at your option) any later version.
-**
-**     This package is distributed in the hope that it will be useful,
-**     but WITHOUT ANY WARRANTY; without even the implied warranty of
-**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-**     General Public License for more details.
-**     \endlegal
-*/
-/* ========================================================================= */
-
-/* === H E A D E R S ======================================================= */
-
-#ifdef USING_PCH
-#      include "pch.h"
-#else
-#ifdef HAVE_CONFIG_H
-#      include <config.h>
-#endif
-
-#include <gtkmm/dialog.h>
-#include <gtkmm/entry.h>
-
-#include <synfig/valuenode_blinecalcvertex.h>
-#include <synfig/valuenode_composite.h>
-#include <synfig/valuenode_dynamiclist.h>
-#include <synfigapp/action_system.h>
-
-#include "state_smoothmove.h"
-#include "state_normal.h"
-#include "canvasview.h"
-#include "workarea.h"
-#include "app.h"
-
-#include <synfigapp/action.h>
-#include "event_mouse.h"
-#include "event_layerclick.h"
-#include "toolbox.h"
-#include "dialog_tooloptions.h"
-#include <gtkmm/optionmenu.h>
-#include "duck.h"
-#include "onemoment.h"
-#include <synfigapp/main.h>
-
-#include "general.h"
-
-#endif
-
-/* === U S I N G =========================================================== */
-
-using namespace std;
-using namespace etl;
-using namespace synfig;
-using namespace studio;
-
-/* === M A C R O S ========================================================= */
-
-/* === G L O B A L S ======================================================= */
-
-StateSmoothMove studio::state_smooth_move;
-
-/* === C L A S S E S & S T R U C T S ======================================= */
-
-class DuckDrag_SmoothMove : public DuckDrag_Base
-{
-       float radius;
-
-       synfig::Vector last_translate_;
-       synfig::Vector drag_offset_;
-       synfig::Vector snap;
-
-       std::vector<synfig::Vector> last_;
-       std::vector<synfig::Vector> positions;
-
-public:
-       DuckDrag_SmoothMove();
-       void begin_duck_drag(Duckmatic* duckmatic, const synfig::Vector& begin);
-       bool end_duck_drag(Duckmatic* duckmatic);
-       void duck_drag(Duckmatic* duckmatic, const synfig::Vector& vector);
-
-       void set_radius(float x) { radius=x; }
-       float get_radius()const { return radius; }
-};
-
-
-class studio::StateSmoothMove_Context : public sigc::trackable
-{
-       etl::handle<CanvasView> canvas_view_;
-       CanvasView::IsWorking is_working;
-
-       //Duckmatic::Push duckmatic_push;
-
-       synfigapp::Settings& settings;
-
-       etl::handle<DuckDrag_SmoothMove> duck_dragger_;
-
-       Gtk::Table options_table;
-
-       Gtk::Adjustment  adj_radius;
-       Gtk::SpinButton  spin_radius;
-
-       float pressure;
-
-public:
-       float get_radius()const { return adj_radius.get_value(); }
-       void set_radius(float x) { return adj_radius.set_value(x); }
-
-       void refresh_radius() { duck_dragger_->set_radius(get_radius()*pressure); }
-
-       Smach::event_result event_stop_handler(const Smach::event& x);
-
-       Smach::event_result event_refresh_tool_options(const Smach::event& x);
-
-       void refresh_tool_options();
-
-       StateSmoothMove_Context(CanvasView* canvas_view);
-
-       ~StateSmoothMove_Context();
-
-       const etl::handle<CanvasView>& get_canvas_view()const{return canvas_view_;}
-       etl::handle<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view_->canvas_interface();}
-       synfig::Canvas::Handle get_canvas()const{return canvas_view_->get_canvas();}
-       WorkArea * get_work_area()const{return canvas_view_->get_work_area();}
-
-       void load_settings();
-       void save_settings();
-};     // END of class StateSmoothMove_Context
-
-/* === M E T H O D S ======================================================= */
-
-StateSmoothMove::StateSmoothMove():
-       Smach::state<StateSmoothMove_Context>("smooth_move")
-{
-       insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateSmoothMove_Context::event_refresh_tool_options));
-       insert(event_def(EVENT_STOP,&StateSmoothMove_Context::event_stop_handler));
-}
-
-StateSmoothMove::~StateSmoothMove()
-{
-}
-
-void
-StateSmoothMove_Context::load_settings()
-{
-       String value;
-
-       if(settings.get_value("smooth_move.radius",value))
-               set_radius(atof(value.c_str()));
-       else
-               set_radius(1.0f);
-}
-
-void
-StateSmoothMove_Context::save_settings()
-{
-       settings.set_value("smooth_move.radius",strprintf("%f",get_radius()));
-}
-
-StateSmoothMove_Context::StateSmoothMove_Context(CanvasView* canvas_view):
-       canvas_view_(canvas_view),
-       is_working(*canvas_view),
-//     duckmatic_push(get_work_area()),
-       settings(synfigapp::Main::get_selected_input_device()->settings()),
-       duck_dragger_(new DuckDrag_SmoothMove()),
-       adj_radius(1,0,100000,0.01,0.1),
-       spin_radius(adj_radius,0.1,3)
-{
-       pressure=1.0f;
-
-       // Set up the tool options dialog
-       options_table.attach(*manage(new Gtk::Label(_("SmoothMove Tool"))),     0, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(*manage(new Gtk::Label(_("Radius"))),                      0, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(spin_radius,                                                                       0, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-
-       spin_radius.signal_value_changed().connect(sigc::mem_fun(*this,&StateSmoothMove_Context::refresh_radius));
-
-       options_table.show_all();
-       refresh_tool_options();
-       //App::dialog_tool_options->set_widget(options_table);
-       App::dialog_tool_options->present();
-
-       get_work_area()->set_allow_layer_clicks(true);
-       get_work_area()->set_duck_dragger(duck_dragger_);
-
-       App::toolbox->refresh();
-
-       get_work_area()->set_cursor(Gdk::FLEUR);
-       //get_work_area()->reset_cursor();
-
-       load_settings();
-}
-
-void
-StateSmoothMove_Context::refresh_tool_options()
-{
-       App::dialog_tool_options->clear();
-       App::dialog_tool_options->set_widget(options_table);
-       App::dialog_tool_options->set_local_name(_("Smooth Move"));
-       App::dialog_tool_options->set_name("smooth_move");
-}
-
-Smach::event_result
-StateSmoothMove_Context::event_refresh_tool_options(const Smach::event& /*x*/)
-{
-       refresh_tool_options();
-       return Smach::RESULT_ACCEPT;
-}
-
-Smach::event_result
-StateSmoothMove_Context::event_stop_handler(const Smach::event& /*x*/)
-{
-       throw &state_normal;
-       return Smach::RESULT_OK;
-}
-
-StateSmoothMove_Context::~StateSmoothMove_Context()
-{
-       save_settings();
-
-       get_work_area()->clear_duck_dragger();
-       get_work_area()->reset_cursor();
-
-       App::dialog_tool_options->clear();
-
-       App::toolbox->refresh();
-}
-
-
-
-
-DuckDrag_SmoothMove::DuckDrag_SmoothMove():radius(1.0f)
-{
-}
-
-void
-DuckDrag_SmoothMove::begin_duck_drag(Duckmatic* duckmatic, const synfig::Vector& offset)
-{
-       last_translate_=Vector(0,0);
-               drag_offset_=duckmatic->find_duck(offset)->get_trans_point();
-
-               //snap=drag_offset-duckmatic->snap_point_to_grid(drag_offset);
-               //snap=offset-drag_offset_;
-               snap=Vector(0,0);
-
-       last_.clear();
-       positions.clear();
-       const DuckList selected_ducks(duckmatic->get_selected_ducks());
-       DuckList::const_iterator iter;
-       int i;
-       for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
-       {
-               last_.push_back(Vector(0,0));
-               positions.push_back((*iter)->get_trans_point());
-       }
-}
-
-void
-DuckDrag_SmoothMove::duck_drag(Duckmatic* duckmatic, const synfig::Vector& vector)
-{
-       const DuckList selected_ducks(duckmatic->get_selected_ducks());
-       DuckList::const_iterator iter;
-       synfig::Vector vect(duckmatic->snap_point_to_grid(vector)-drag_offset_+snap);
-
-       int i;
-
-       Time time(duckmatic->get_time());
-
-       // process vertex and position ducks first
-       for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
-       {
-               // skip this duck if it is NOT a vertex or a position
-               if (((*iter)->get_type() != Duck::TYPE_VERTEX &&
-                        (*iter)->get_type() != Duck::TYPE_POSITION))
-                       continue;
-               Point p(positions[i]);
-
-               float dist(1.0f-(p-drag_offset_).mag()/get_radius());
-               if(dist<0)
-                       dist=0;
-
-               last_[i]=vect*dist;
-               (*iter)->set_trans_point(p+last_[i], time);
-       }
-
-       // then process non vertex and non position ducks
-       for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
-       {
-               // skip this duck if it IS a vertex or a position
-               if (!((*iter)->get_type() != Duck::TYPE_VERTEX &&
-                        (*iter)->get_type() != Duck::TYPE_POSITION))
-                       continue;
-               Point p(positions[i]);
-
-               float dist(1.0f-(p-drag_offset_).mag()/get_radius());
-               if(dist<0)
-                       dist=0;
-
-               last_[i]=vect*dist;
-               (*iter)->set_trans_point(p+last_[i], time);
-       }
-
-       // then patch up the tangents for the vertices we've moved
-       duckmatic->update_ducks();
-
-       last_translate_=vect;
-       //snap=Vector(0,0);
-}
-
-bool
-DuckDrag_SmoothMove::end_duck_drag(Duckmatic* duckmatic)
-{
-       //synfig::info("end_duck_drag(): Diff= %f",last_translate_.mag());
-       if(last_translate_.mag()>0.0001)
-       {
-               const DuckList selected_ducks(duckmatic->get_selected_ducks());
-               DuckList::const_iterator iter;
-
-               int i;
-
-               smart_ptr<OneMoment> wait;if(selected_ducks.size()>20)wait.spawn();
-
-               for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
-               {
-                       if(last_[i].mag()>0.0001)
-                               {
-                               if ((*iter)->get_type() == Duck::TYPE_ANGLE)
-                                       {
-                                               if(!(*iter)->signal_edited_angle()((*iter)->get_rotations()))
-                                               {
-                                                       throw String("Bad edit");
-                                               }
-                                       }
-                                       else if (App::restrict_radius_ducks &&
-                                                        (*iter)->is_radius())
-                                       {
-                                               Point point((*iter)->get_point());
-                                               bool changed = false;
-
-                                               if (point[0] < 0)
-                                               {
-                                                       point[0] = 0;
-                                                       changed = true;
-                                               }
-                                               if (point[1] < 0)
-                                               {
-                                                       point[1] = 0;
-                                                       changed = true;
-                                               }
-
-                                               if (changed) (*iter)->set_point(point);
-
-                                               if(!(*iter)->signal_edited()(point))
-                                               {
-                                                       throw String("Bad edit");
-                                               }
-                                       }
-                                       else
-                                       {
-                                               if(!(*iter)->signal_edited()((*iter)->get_point()))
-                                               {
-                                                       throw String("Bad edit");
-                                               }
-                                       }
-                               }
-               }
-               //duckmatic->get_selected_ducks()=new_set;
-               //duckmatic->refresh_selected_ducks();
-               return true;
-       }
-       else
-       {
-               duckmatic->signal_user_click_selected_ducks(0);
-               return false;
-       }
-}
diff --git a/synfig-studio/src/gui/state_smoothmove.h b/synfig-studio/src/gui/state_smoothmove.h
deleted file mode 100644 (file)
index 07442af..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/* === S Y N F I G ========================================================= */
-/*!    \file state_smoothmove.h
-**     \brief Template Header
-**
-**     $Id$
-**
-**     \legal
-**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
-**
-**     This package is free software; you can redistribute it and/or
-**     modify it under the terms of the GNU General Public License as
-**     published by the Free Software Foundation; either version 2 of
-**     the License, or (at your option) any later version.
-**
-**     This package is distributed in the hope that it will be useful,
-**     but WITHOUT ANY WARRANTY; without even the implied warranty of
-**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-**     General Public License for more details.
-**     \endlegal
-*/
-/* ========================================================================= */
-
-/* === S T A R T =========================================================== */
-
-#ifndef __SYNFIG_STUDIO_STATE_SMOOTHMOVE_H
-#define __SYNFIG_STUDIO_STATE_SMOOTHMOVE_H
-
-/* === H E A D E R S ======================================================= */
-
-#include "smach.h"
-
-
-/* === M A C R O S ========================================================= */
-
-/* === T Y P E D E F S ===================================================== */
-
-/* === C L A S S E S & S T R U C T S ======================================= */
-
-namespace studio {
-
-class StateSmoothMove_Context;
-
-class StateSmoothMove : public Smach::state<StateSmoothMove_Context>
-{
-public:
-       StateSmoothMove();
-       ~StateSmoothMove();
-}; // END of class StateSmoothMove
-
-extern StateSmoothMove state_smooth_move;
-
-}; // END of namespace studio
-
-/* === E N D =============================================================== */
-
-#endif
diff --git a/synfig-studio/src/gui/state_star.cpp b/synfig-studio/src/gui/state_star.cpp
deleted file mode 100644 (file)
index 3be4b53..0000000
+++ /dev/null
@@ -1,1091 +0,0 @@
-/* === S Y N F I G ========================================================= */
-/*!    \file state_star.cpp
-**     \brief Template File
-**
-**     $Id$
-**
-**     \legal
-**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
-**     Copyright (c) 2008 Chris Moore
-**
-**     This package is free software; you can redistribute it and/or
-**     modify it under the terms of the GNU General Public License as
-**     published by the Free Software Foundation; either version 2 of
-**     the License, or (at your option) any later version.
-**
-**     This package is distributed in the hope that it will be useful,
-**     but WITHOUT ANY WARRANTY; without even the implied warranty of
-**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-**     General Public License for more details.
-**     \endlegal
-*/
-/* ========================================================================= */
-
-/* === H E A D E R S ======================================================= */
-
-#ifdef USING_PCH
-#      include "pch.h"
-#else
-#ifdef HAVE_CONFIG_H
-#      include <config.h>
-#endif
-
-#include <gtkmm/dialog.h>
-#include <gtkmm/entry.h>
-
-#include <synfig/valuenode_dynamiclist.h>
-#include <synfigapp/action_system.h>
-#include <synfig/valuenode_bline.h>
-
-#include "state_star.h"
-#include "state_normal.h"
-#include "canvasview.h"
-#include "workarea.h"
-#include "app.h"
-
-#include <synfigapp/action.h>
-#include "event_mouse.h"
-#include "event_layerclick.h"
-#include "toolbox.h"
-#include "dialog_tooloptions.h"
-#include <gtkmm/optionmenu.h>
-#include "duck.h"
-#include "widgets/widget_enum.h"
-#include <synfigapp/main.h>
-
-#include "general.h"
-
-#endif
-
-/* === U S I N G =========================================================== */
-
-using namespace std;
-using namespace etl;
-using namespace synfig;
-using namespace studio;
-
-/* === M A C R O S ========================================================= */
-
-/* === G L O B A L S ======================================================= */
-
-StateStar studio::state_star;
-
-/* === C L A S S E S & S T R U C T S ======================================= */
-
-class studio::StateStar_Context : public sigc::trackable
-{
-       etl::handle<CanvasView> canvas_view_;
-       CanvasView::IsWorking is_working;
-
-       Duckmatic::Push duckmatic_push;
-
-       Point point_holder;
-
-       etl::handle<Duck> point2_duck;
-
-       void refresh_ducks();
-
-       bool prev_workarea_layer_status_;
-
-       //Toolbox settings
-       synfigapp::Settings& settings;
-
-       //Toolbox display
-       Gtk::Table options_table;
-
-       Gtk::Entry              entry_id; //what to name the layer
-
-       Gtk::Adjustment adj_feather;
-       Gtk::Adjustment adj_number_of_points;
-       Gtk::Adjustment adj_inner_tangent;
-       Gtk::Adjustment adj_outer_tangent;
-       Gtk::Adjustment adj_inner_width;
-       Gtk::Adjustment adj_outer_width;
-       Gtk::Adjustment adj_radius_ratio;
-       Gtk::Adjustment adj_angle_offset;
-       Gtk::SpinButton spin_feather;
-       Gtk::SpinButton spin_number_of_points;
-       Gtk::SpinButton spin_inner_tangent;
-       Gtk::SpinButton spin_outer_tangent;
-       Gtk::SpinButton spin_inner_width;
-       Gtk::SpinButton spin_outer_width;
-       Gtk::SpinButton spin_radius_ratio;
-       Gtk::SpinButton spin_angle_offset;
-
-       Gtk::CheckButton checkbutton_invert;
-       Gtk::CheckButton checkbutton_regular_polygon;
-       Gtk::CheckButton checkbutton_layer_star;
-       Gtk::CheckButton checkbutton_layer_region;
-       Gtk::CheckButton checkbutton_layer_outline;
-       Gtk::CheckButton checkbutton_layer_curve_gradient;
-       Gtk::CheckButton checkbutton_layer_plant;
-       Gtk::CheckButton checkbutton_layer_link_origins;
-       Gtk::CheckButton checkbutton_layer_origins_at_center;
-
-public:
-
-       // this only counts the layers which will have their origins linked
-       int layers_to_create()const
-       {
-               return
-                       (get_layer_star_flag() && get_layer_origins_at_center_flag()) +
-                       get_layer_region_flag() +
-                       get_layer_outline_flag() +
-                       get_layer_curve_gradient_flag() +
-                       get_layer_plant_flag();
-       }
-
-       synfig::String get_id()const { return entry_id.get_text(); }
-       void set_id(const synfig::String& x) { return entry_id.set_text(x); }
-
-       Real get_feather()const { return adj_feather.get_value(); }
-       void set_feather(Real f) { adj_feather.set_value(f); }
-
-       Real get_number_of_points()const { return adj_number_of_points.get_value(); }
-       void set_number_of_points(Real f) { adj_number_of_points.set_value(f); }
-
-       Real get_inner_tangent()const { return adj_inner_tangent.get_value(); }
-       void set_inner_tangent(Real f) { adj_inner_tangent.set_value(f); }
-
-       Real get_outer_tangent()const { return adj_outer_tangent.get_value(); }
-       void set_outer_tangent(Real f) { adj_outer_tangent.set_value(f); }
-
-       Real get_inner_width()const { return adj_inner_width.get_value(); }
-       void set_inner_width(Real f) { adj_inner_width.set_value(f); }
-
-       Real get_outer_width()const { return adj_outer_width.get_value(); }
-       void set_outer_width(Real f) { adj_outer_width.set_value(f); }
-
-       Real get_radius_ratio()const { return adj_radius_ratio.get_value(); }
-       void set_radius_ratio(Real f) { adj_radius_ratio.set_value(f); }
-
-       Real get_angle_offset()const { return adj_angle_offset.get_value(); }
-       void set_angle_offset(Real f) { adj_angle_offset.set_value(f); }
-
-       bool get_invert()const { return checkbutton_invert.get_active(); }
-       void set_invert(bool i) { checkbutton_invert.set_active(i); }
-
-       bool get_regular_polygon()const { return checkbutton_regular_polygon.get_active(); }
-       void set_regular_polygon(bool i) { checkbutton_regular_polygon.set_active(i); }
-
-       bool get_layer_star_flag()const { return checkbutton_layer_star.get_active(); }
-       void set_layer_star_flag(bool x) { return checkbutton_layer_star.set_active(x); }
-
-       bool get_layer_region_flag()const { return checkbutton_layer_region.get_active(); }
-       void set_layer_region_flag(bool x) { return checkbutton_layer_region.set_active(x); }
-
-       bool get_layer_outline_flag()const { return checkbutton_layer_outline.get_active(); }
-       void set_layer_outline_flag(bool x) { return checkbutton_layer_outline.set_active(x); }
-
-       bool get_layer_curve_gradient_flag()const { return checkbutton_layer_curve_gradient.get_active(); }
-       void set_layer_curve_gradient_flag(bool x) { return checkbutton_layer_curve_gradient.set_active(x); }
-
-       bool get_layer_plant_flag()const { return checkbutton_layer_plant.get_active(); }
-       void set_layer_plant_flag(bool x) { return checkbutton_layer_plant.set_active(x); }
-
-       bool get_layer_link_origins_flag()const { return checkbutton_layer_link_origins.get_active(); }
-       void set_layer_link_origins_flag(bool x) { return checkbutton_layer_link_origins.set_active(x); }
-
-       bool get_layer_origins_at_center_flag()const { return checkbutton_layer_origins_at_center.get_active(); }
-       void set_layer_origins_at_center_flag(bool x) { return checkbutton_layer_origins_at_center.set_active(x); }
-
-       void refresh_tool_options(); //to refresh the toolbox
-
-       //events
-       Smach::event_result event_stop_handler(const Smach::event& x);
-       Smach::event_result event_refresh_handler(const Smach::event& x);
-       Smach::event_result event_mouse_click_handler(const Smach::event& x);
-       Smach::event_result event_refresh_tool_options(const Smach::event& x);
-
-       //constructor destructor
-       StateStar_Context(CanvasView* canvas_view);
-       ~StateStar_Context();
-
-       //Canvas interaction
-       const etl::handle<CanvasView>& get_canvas_view()const{return canvas_view_;}
-       etl::handle<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view_->canvas_interface();}
-       synfig::Canvas::Handle get_canvas()const{return canvas_view_->get_canvas();}
-       WorkArea * get_work_area()const{return canvas_view_->get_work_area();}
-
-       //Modifying settings etc.
-       void load_settings();
-       void save_settings();
-       void reset();
-       void increment_id();
-       bool egress_on_selection_change;
-       Smach::event_result event_layer_selection_changed_handler(const Smach::event& /*x*/)
-       {
-               if(egress_on_selection_change)
-                       throw &state_normal; //throw Smach::egress_exception();
-               return Smach::RESULT_OK;
-       }
-
-       void make_star(const Point& p1, const Point& p2);
-
-};     // END of class StateStar_Context
-
-/* === M E T H O D S ======================================================= */
-
-StateStar::StateStar():
-       Smach::state<StateStar_Context>("star")
-{
-       insert(event_def(EVENT_LAYER_SELECTION_CHANGED,&StateStar_Context::event_layer_selection_changed_handler));
-       insert(event_def(EVENT_STOP,&StateStar_Context::event_stop_handler));
-       insert(event_def(EVENT_REFRESH,&StateStar_Context::event_refresh_handler));
-       insert(event_def(EVENT_REFRESH_DUCKS,&StateStar_Context::event_refresh_handler));
-       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateStar_Context::event_mouse_click_handler));
-       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DRAG,&StateStar_Context::event_mouse_click_handler));
-       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_UP,&StateStar_Context::event_mouse_click_handler));
-       insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateStar_Context::event_refresh_tool_options));
-}
-
-StateStar::~StateStar()
-{
-}
-
-void
-StateStar_Context::load_settings()
-{
-       String value;
-
-       //parse the arguments yargh!
-       if(settings.get_value("star.id",value))
-               set_id(value);
-       else
-               set_id("Star");
-
-       if(settings.get_value("star.feather",value))
-               set_feather(atof(value.c_str()));
-       else
-               set_feather(0);
-
-       if(settings.get_value("star.number_of_points",value))
-               set_number_of_points(atof(value.c_str()));
-       else
-               set_number_of_points(5);
-
-       if(settings.get_value("star.inner_tangent",value))
-               set_inner_tangent(atof(value.c_str()));
-       else
-               set_inner_tangent(0);
-
-       if(settings.get_value("star.outer_tangent",value))
-               set_outer_tangent(atof(value.c_str()));
-       else
-               set_outer_tangent(0);
-
-       if(settings.get_value("star.inner_width",value))
-               set_inner_width(atof(value.c_str()));
-       else
-               set_inner_width(1);
-
-       if(settings.get_value("star.outer_width",value))
-               set_outer_width(atof(value.c_str()));
-       else
-               set_outer_width(1);
-
-       if(settings.get_value("star.radius_ratio",value))
-               set_radius_ratio(atof(value.c_str()));
-       else
-               set_radius_ratio(0.5);
-
-       if(settings.get_value("star.angle_offset",value))
-               set_angle_offset(atof(value.c_str()));
-       else
-               set_angle_offset(0);
-
-       if(settings.get_value("star.invert",value) && value != "0")
-               set_invert(true);
-       else
-               set_invert(false);
-
-       if(settings.get_value("star.regular_polygon",value) && value != "0")
-               set_regular_polygon(true);
-       else
-               set_regular_polygon(false);
-
-       if(settings.get_value("star.layer_star",value) && value=="0")
-               set_layer_star_flag(false);
-       else
-               set_layer_star_flag(true);
-
-       if(settings.get_value("star.layer_region",value) && value=="1")
-               set_layer_region_flag(true);
-       else
-               set_layer_region_flag(false);
-
-       if(settings.get_value("star.layer_outline",value) && value=="1")
-               set_layer_outline_flag(true);
-       else
-               set_layer_outline_flag(false);
-
-       if(settings.get_value("star.layer_curve_gradient",value) && value=="1")
-               set_layer_curve_gradient_flag(true);
-       else
-               set_layer_curve_gradient_flag(false);
-
-       if(settings.get_value("star.layer_plant",value) && value=="1")
-               set_layer_plant_flag(true);
-       else
-               set_layer_plant_flag(false);
-
-       if(settings.get_value("star.layer_link_origins",value) && value=="0")
-               set_layer_link_origins_flag(false);
-       else
-               set_layer_link_origins_flag(true);
-
-       if(settings.get_value("star.layer_origins_at_center",value) && value=="0")
-               set_layer_origins_at_center_flag(false);
-       else
-               set_layer_origins_at_center_flag(true);
-}
-
-void
-StateStar_Context::save_settings()
-{
-       settings.set_value("star.id",get_id());
-       settings.set_value("star.feather",strprintf("%f",(float)get_feather()));
-       settings.set_value("star.number_of_points",strprintf("%d",(int)(get_number_of_points() + 0.5)));
-       settings.set_value("star.inner_tangent",strprintf("%f",(float)get_inner_tangent()));
-       settings.set_value("star.outer_tangent",strprintf("%f",(float)get_outer_tangent()));
-       settings.set_value("star.inner_width",strprintf("%f",(float)get_inner_width()));
-       settings.set_value("star.outer_width",strprintf("%f",(float)get_outer_width()));
-       settings.set_value("star.radius_ratio",strprintf("%f",(float)get_radius_ratio()));
-       settings.set_value("star.angle_offset",strprintf("%f",(float)get_angle_offset()));
-       settings.set_value("star.invert",get_invert()?"1":"0");
-       settings.set_value("star.regular_polygon",get_regular_polygon()?"1":"0");
-       settings.set_value("star.layer_star",get_layer_star_flag()?"1":"0");
-       settings.set_value("star.layer_outline",get_layer_outline_flag()?"1":"0");
-       settings.set_value("star.layer_region",get_layer_region_flag()?"1":"0");
-       settings.set_value("star.layer_curve_gradient",get_layer_curve_gradient_flag()?"1":"0");
-       settings.set_value("star.layer_plant",get_layer_plant_flag()?"1":"0");
-       settings.set_value("star.layer_link_origins",get_layer_link_origins_flag()?"1":"0");
-       settings.set_value("star.layer_origins_at_center",get_layer_origins_at_center_flag()?"1":"0");
-}
-
-void
-StateStar_Context::reset()
-{
-       refresh_ducks();
-}
-
-void
-StateStar_Context::increment_id()
-{
-       String id(get_id());
-       int number=1;
-       int digits=0;
-
-       if(id.empty())
-               id="Star";
-
-       // If there is a number
-       // already at the end of the
-       // id, then remove it.
-       if(id[id.size()-1]<='9' && id[id.size()-1]>='0')
-       {
-               // figure out how many digits it is
-               for (digits = 0;
-                        (int)id.size()-1 >= digits && id[id.size()-1-digits] <= '9' && id[id.size()-1-digits] >= '0';
-                        digits++)
-                       ;
-
-               String str_number;
-               str_number=String(id,id.size()-digits,id.size());
-               id=String(id,0,id.size()-digits);
-
-               number=atoi(str_number.c_str());
-       }
-       else
-       {
-               number=1;
-               digits=3;
-       }
-
-       number++;
-
-       // Add the number back onto the id
-       {
-               const String format(strprintf("%%0%dd",digits));
-               id+=strprintf(format.c_str(),number);
-       }
-
-       // Set the ID
-       set_id(id);
-}
-
-StateStar_Context::StateStar_Context(CanvasView* canvas_view):
-       canvas_view_(canvas_view),
-       is_working(*canvas_view),
-       duckmatic_push(get_work_area()),
-       prev_workarea_layer_status_(get_work_area()->get_allow_layer_clicks()),
-       settings(synfigapp::Main::get_selected_input_device()->settings()),
-       entry_id(),             //   value lower upper  step page
-       adj_feather(                    0,    0,    1, 0.01, 0.1),
-       adj_number_of_points(   0,    2,  120, 1   , 1  ),
-       adj_inner_tangent(              0,  -10,   10, 0.01, 0.1),
-       adj_outer_tangent(              0,  -10,   10, 0.01, 0.1),
-       adj_inner_width(                0,  -10,   10, 0.01, 0.1),
-       adj_outer_width(                0,  -10,   10, 0.01, 0.1),
-       adj_radius_ratio(               0,  -10,   10, 0.01, 0.1),
-       adj_angle_offset(               0, -360,  360, 0.1 , 1  ),
-       spin_feather(adj_feather,0.1,3),
-       spin_number_of_points(adj_number_of_points,1,0),
-       spin_inner_tangent(adj_inner_tangent,1,2),
-       spin_outer_tangent(adj_outer_tangent,1,2),
-       spin_inner_width(adj_inner_width,1,2),
-       spin_outer_width(adj_outer_width,1,2),
-       spin_radius_ratio(adj_radius_ratio,1,2),
-       spin_angle_offset(adj_angle_offset,1,1),
-       checkbutton_invert(_("Invert")),
-       checkbutton_regular_polygon(_("Regular Polygon")),
-       checkbutton_layer_star(_("Create Star Layer")),
-       checkbutton_layer_region(_("Create Region BLine")),
-       checkbutton_layer_outline(_("Create Outline BLine")),
-       checkbutton_layer_curve_gradient(_("Create Curve Gradient BLine")),
-       checkbutton_layer_plant(_("Create Plant BLine")),
-       checkbutton_layer_link_origins(_("Link Origins")),
-       checkbutton_layer_origins_at_center(_("BLine Origins at Center"))
-{
-       egress_on_selection_change=true;
-
-       load_settings();
-
-       // Set up the tool options dialog
-       options_table.attach(*manage(new Gtk::Label(_("Star Tool"))),                   0, 2,  0,  1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(entry_id,                                                                                  0, 2,  1,  2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(checkbutton_layer_star,                                                    0, 2,  2,  3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(checkbutton_layer_outline,                                                 0, 2,  3,  4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(checkbutton_layer_region,                                                  0, 2,  4,  5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(checkbutton_layer_plant,                                                   0, 2,  5,  6, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(checkbutton_layer_curve_gradient,                                  0, 2,  6,  7, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(checkbutton_layer_link_origins,                                    0, 2,  7,  8, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(checkbutton_layer_origins_at_center,                               0, 2,  8,  9, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(checkbutton_invert,                                                                0, 2,  9, 10, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(checkbutton_regular_polygon,                                               0, 2, 10, 11, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-
-       options_table.attach(*manage(new Gtk::Label(_("Feather:"))),                    0, 1, 11, 12, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(spin_feather,                                                                              1, 2, 11, 12, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-
-       options_table.attach(*manage(new Gtk::Label(_("Number of Points:"))),   0, 1, 12, 13, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(spin_number_of_points,                                                             1, 2, 12, 13, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-
-       options_table.attach(*manage(new Gtk::Label(_("Inner Tangent:"))),              0, 1, 13, 14, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(spin_inner_tangent,                                                                1, 2, 13, 14, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-
-       options_table.attach(*manage(new Gtk::Label(_("Outer Tangent:"))),              0, 1, 14, 15, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(spin_outer_tangent,                                                                1, 2, 14, 15, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-
-       options_table.attach(*manage(new Gtk::Label(_("Inner Width:"))),                0, 1, 15, 16, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(spin_inner_width,                                                                  1, 2, 15, 16, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-
-       options_table.attach(*manage(new Gtk::Label(_("Outer Width:"))),                0, 1, 16, 17, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(spin_outer_width,                                                                  1, 2, 16, 17, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-
-       options_table.attach(*manage(new Gtk::Label(_("Radius Ratio:"))),               0, 1, 17, 18, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(spin_radius_ratio,                                                                 1, 2, 17, 18, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-
-       options_table.attach(*manage(new Gtk::Label(_("Angle Offset:"))),               0, 1, 18, 19, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(spin_angle_offset,                                                                 1, 2, 18, 19, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-
-       options_table.show_all();
-
-       refresh_tool_options();
-       App::dialog_tool_options->present();
-
-       // Turn off layer clicking
-       get_work_area()->set_allow_layer_clicks(false);
-
-       // clear out the ducks
-       get_work_area()->clear_ducks();
-
-       // Refresh the work area
-       get_work_area()->queue_draw();
-
-       // Hide the tables if they are showing
-       //prev_table_status=get_canvas_view()->tables_are_visible();
-       //if(prev_table_status)get_canvas_view()->hide_tables();
-
-       // Disable the time bar
-       //get_canvas_view()->set_sensitive_timebar(false);
-
-       // Connect a signal
-       //get_work_area()->signal_user_click().connect(sigc::mem_fun(*this,&studio::StateStar_Context::on_user_click));
-       get_work_area()->set_cursor(Gdk::STAR);
-
-       App::toolbox->refresh();
-}
-
-void
-StateStar_Context::refresh_tool_options()
-{
-       App::dialog_tool_options->clear();
-       App::dialog_tool_options->set_widget(options_table);
-       App::dialog_tool_options->set_local_name(_("Star Tool"));
-       App::dialog_tool_options->set_name("star");
-}
-
-Smach::event_result
-StateStar_Context::event_refresh_tool_options(const Smach::event& /*x*/)
-{
-       refresh_tool_options();
-       return Smach::RESULT_ACCEPT;
-}
-
-StateStar_Context::~StateStar_Context()
-{
-       save_settings();
-
-       // Restore layer clicking
-       get_work_area()->set_allow_layer_clicks(prev_workarea_layer_status_);
-       get_work_area()->reset_cursor();
-
-       App::dialog_tool_options->clear();
-
-       // Enable the time bar
-       //get_canvas_view()->set_sensitive_timebar(true);
-
-       // Bring back the tables if they were out before
-       //if(prev_table_status)get_canvas_view()->show_tables();
-
-       // Refresh the work area
-       get_work_area()->queue_draw();
-
-       get_canvas_view()->queue_rebuild_ducks();
-
-       App::toolbox->refresh();
-}
-
-Smach::event_result
-StateStar_Context::event_stop_handler(const Smach::event& /*x*/)
-{
-       //throw Smach::egress_exception();
-       throw &state_normal;
-       return Smach::RESULT_OK;
-}
-
-Smach::event_result
-StateStar_Context::event_refresh_handler(const Smach::event& /*x*/)
-{
-       refresh_ducks();
-       return Smach::RESULT_ACCEPT;
-}
-
-void
-StateStar_Context::make_star(const Point& _p1, const Point& _p2)
-{
-       synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("New Star"));
-       synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
-
-       Layer::Handle layer;
-
-       Canvas::Handle canvas;
-       int depth(0);
-
-       // we are temporarily using the layer to hold something
-       layer=get_canvas_view()->get_selection_manager()->get_selected_layer();
-       if(layer)
-       {
-               depth=layer->get_depth();
-               canvas=layer->get_canvas();
-       }
-
-       synfigapp::SelectionManager::LayerList layer_selection;
-       if (!getenv("SYNFIG_TOOLS_CLEAR_SELECTION"))
-               layer_selection = get_canvas_view()->get_selection_manager()->get_selected_layers();
-
-       const synfig::TransformStack& transform(get_canvas_view()->get_curr_transform_stack());
-       const Point p1(transform.unperform(_p1));
-       const Point p2(transform.unperform(_p2));
-
-       Real radius_ratio(get_radius_ratio());
-       Real radius1((p2-p1).mag());
-       Real radius2(radius1 * radius_ratio);
-       int points = get_number_of_points();
-       Real inner_tangent = get_inner_tangent() * radius1;
-       Real outer_tangent = get_outer_tangent() * radius2;
-       Real inner_width = get_inner_width();
-       Real outer_width = get_outer_width();
-       Angle::deg offset(get_angle_offset());
-       bool regular(get_regular_polygon());
-       Angle::deg angle(360.0/points);
-       Vector origin;
-       Real x, y;
-
-       if (get_layer_origins_at_center_flag())
-       {
-               x = y = 0;
-               origin = p1;
-       }
-       else
-       {
-               x = p1[0];
-               y = p1[1];
-       }
-
-       std::vector<BLinePoint> new_list;
-       int point(0);
-       for (int i = 0; i < points; i++)
-       {
-               new_list.push_back(*(new BLinePoint));
-               new_list[point].set_width(outer_width);
-               new_list[point].set_vertex(Point(radius1*Angle::cos(angle*i + offset).get() + x,
-                                                                                radius1*Angle::sin(angle*i + offset).get() + y));
-               new_list[point++].set_tangent(Point(-Angle::sin(angle*i + offset).get(),
-                                                                                        Angle::cos(angle*i + offset).get()) * outer_tangent);
-
-               if (!regular)
-               {
-                       new_list.push_back(*(new BLinePoint));
-                       new_list[point].set_width(inner_width);
-                       new_list[point].set_vertex(Point(radius2*Angle::cos(angle*i + angle/2 + offset).get() + x,
-                                                                                        radius2*Angle::sin(angle*i + angle/2 + offset).get() + y));
-                       new_list[point++].set_tangent(Point(-Angle::sin(angle*i + angle/2 + offset).get(),
-                                                                                                Angle::cos(angle*i + angle/2 + offset).get()) * inner_tangent);
-               }
-       }
-
-       ValueNode_BLine::Handle value_node_bline(ValueNode_BLine::create(new_list));
-       assert(value_node_bline);
-
-       ValueNode_Const::Handle value_node_origin(ValueNode_Const::create(origin));
-       assert(value_node_origin);
-
-       // Set the looping flag
-       value_node_bline->set_loop(true);
-
-       if(!canvas)
-               canvas=get_canvas_view()->get_canvas();
-
-       value_node_bline->set_member_canvas(canvas);
-
-       // count how many layers we're going to be creating
-       int layers_to_create = this->layers_to_create();
-
-       ///////////////////////////////////////////////////////////////////////////
-       //   S T A R
-       ///////////////////////////////////////////////////////////////////////////
-
-       if (get_layer_star_flag())
-       {
-               layer=get_canvas_interface()->add_layer_to("star",canvas,depth);
-               if (!layer)
-               {
-                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
-                       group.cancel();
-                       return;
-               }
-               layer_selection.push_back(layer);
-
-               layer->set_param("radius1",radius1);
-               get_canvas_interface()->signal_layer_param_changed()(layer,"radius1");
-
-               layer->set_param("radius2",radius2);
-               get_canvas_interface()->signal_layer_param_changed()(layer,"radius2");
-
-               layer->set_param("angle",offset);
-               get_canvas_interface()->signal_layer_param_changed()(layer,"angle");
-
-               layer->set_param("points",points);
-               get_canvas_interface()->signal_layer_param_changed()(layer,"points");
-
-               layer->set_param("regular_polygon",regular);
-               get_canvas_interface()->signal_layer_param_changed()(layer,"regular_polygon");
-
-               layer->set_param("feather",get_feather());
-               get_canvas_interface()->signal_layer_param_changed()(layer,"feather");
-
-               layer->set_param("invert",get_invert());
-               get_canvas_interface()->signal_layer_param_changed()(layer,"invert");
-
-               layer->set_description(get_id());
-               get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
-
-               // only link the star's origin parameter if the option is selected, we're putting bline
-               // origins at their centers, and we're creating more than one layer
-               if (get_layer_link_origins_flag() && get_layer_origins_at_center_flag() && layers_to_create > 1)
-               {
-                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
-                       assert(action);
-
-                       action->set_param("canvas",get_canvas());
-                       action->set_param("canvas_interface",get_canvas_interface());
-                       action->set_param("layer",layer);
-                       if(!action->set_param("param",String("origin")))
-                               synfig::error("LayerParamConnect didn't like \"param\"");
-                       if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
-                               synfig::error("LayerParamConnect didn't like \"value_node\"");
-
-                       if(!get_canvas_interface()->get_instance()->perform_action(action))
-                       {
-                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create Star layer"));
-                               group.cancel();
-                               throw String(_("Unable to create Star layer"));
-                               return;
-                       }
-               }
-               else
-               {
-                       layer->set_param("origin",p1);
-                       get_canvas_interface()->signal_layer_param_changed()(layer,"origin");
-               }
-       }
-
-       ///////////////////////////////////////////////////////////////////////////
-       //   C U R V E   G R A D I E N T
-       ///////////////////////////////////////////////////////////////////////////
-
-       if(get_layer_curve_gradient_flag())
-       {
-               synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
-
-               Layer::Handle layer(get_canvas_interface()->add_layer_to("curve_gradient",canvas,depth));
-               if (!layer)
-               {
-                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
-                       group.cancel();
-                       return;
-               }
-               layer_selection.push_back(layer);
-               layer->set_description(get_id()+_(" Gradient"));
-               get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
-
-               {
-                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
-                       assert(action);
-
-                       action->set_param("canvas",get_canvas());
-                       action->set_param("canvas_interface",get_canvas_interface());
-                       action->set_param("layer",layer);
-                       if(!action->set_param("param",String("bline")))
-                               synfig::error("LayerParamConnect didn't like \"param\"");
-                       if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
-                               synfig::error("LayerParamConnect didn't like \"value_node\"");
-
-                       if(!get_canvas_interface()->get_instance()->perform_action(action))
-                       {
-                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
-                               group.cancel();
-                               throw String(_("Unable to create Gradient layer"));
-                               return;
-                       }
-               }
-
-               // only link the curve gradient's origin parameter if the option is selected and we're creating more than one layer
-               if (get_layer_link_origins_flag() && layers_to_create > 1)
-               {
-                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
-                       assert(action);
-
-                       action->set_param("canvas",get_canvas());
-                       action->set_param("canvas_interface",get_canvas_interface());
-                       action->set_param("layer",layer);
-                       if(!action->set_param("param",String("origin")))
-                               synfig::error("LayerParamConnect didn't like \"param\"");
-                       if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
-                               synfig::error("LayerParamConnect didn't like \"value_node\"");
-
-                       if(!get_canvas_interface()->get_instance()->perform_action(action))
-                       {
-                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
-                               group.cancel();
-                               throw String(_("Unable to create Gradient layer"));
-                               return;
-                       }
-               }
-               else
-               {
-                       layer->set_param("origin",origin);
-                       get_canvas_interface()->signal_layer_param_changed()(layer,"origin");
-               }
-       }
-
-       ///////////////////////////////////////////////////////////////////////////
-       //   P L A N T
-       ///////////////////////////////////////////////////////////////////////////
-
-       if(get_layer_plant_flag())
-       {
-               synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
-
-               Layer::Handle layer(get_canvas_interface()->add_layer_to("plant",canvas,depth));
-               if (!layer)
-               {
-                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
-                       group.cancel();
-                       return;
-               }
-               layer_selection.push_back(layer);
-               layer->set_description(get_id()+_(" Plant"));
-               get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
-
-               {
-                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
-                       assert(action);
-
-                       action->set_param("canvas",get_canvas());
-                       action->set_param("canvas_interface",get_canvas_interface());
-                       action->set_param("layer",layer);
-                       if(!action->set_param("param",String("bline")))
-                               synfig::error("LayerParamConnect didn't like \"param\"");
-                       if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
-                               synfig::error("LayerParamConnect didn't like \"value_node\"");
-
-                       if(!get_canvas_interface()->get_instance()->perform_action(action))
-                       {
-                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
-                               group.cancel();
-                               throw String(_("Unable to create Plant layer"));
-                               return;
-                       }
-               }
-
-               // only link the plant's origin parameter if the option is selected and we're creating more than one layer
-               if (get_layer_link_origins_flag() && layers_to_create > 1)
-               {
-                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
-                       assert(action);
-
-                       action->set_param("canvas",get_canvas());
-                       action->set_param("canvas_interface",get_canvas_interface());
-                       action->set_param("layer",layer);
-                       if(!action->set_param("param",String("origin")))
-                               synfig::error("LayerParamConnect didn't like \"param\"");
-                       if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
-                               synfig::error("LayerParamConnect didn't like \"value_node\"");
-
-                       if(!get_canvas_interface()->get_instance()->perform_action(action))
-                       {
-                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
-                               group.cancel();
-                               throw String(_("Unable to create Plant layer"));
-                               return;
-                       }
-               }
-               else
-               {
-                       layer->set_param("origin",origin);
-                       get_canvas_interface()->signal_layer_param_changed()(layer,"origin");
-               }
-       }
-
-       ///////////////////////////////////////////////////////////////////////////
-       //   R E G I O N
-       ///////////////////////////////////////////////////////////////////////////
-
-       if(get_layer_region_flag())
-       {
-               synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
-
-               Layer::Handle layer(get_canvas_interface()->add_layer_to("region",canvas,depth));
-               if (!layer)
-               {
-                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
-                       group.cancel();
-                       return;
-               }
-               layer_selection.push_back(layer);
-               layer->set_description(get_id()+_(" Region"));
-               get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
-
-               layer->set_param("feather",get_feather());
-               get_canvas_interface()->signal_layer_param_changed()(layer,"feather");
-
-               layer->set_param("invert",get_invert());
-               get_canvas_interface()->signal_layer_param_changed()(layer,"invert");
-
-               // I don't know if it's safe to reuse the same LayerParamConnect action, so I'm
-               // using 2 separate ones.
-               {
-                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
-                       assert(action);
-
-                       action->set_param("canvas",get_canvas());
-                       action->set_param("canvas_interface",get_canvas_interface());
-                       action->set_param("layer",layer);
-                       if(!action->set_param("param",String("bline")))
-                               synfig::error("LayerParamConnect didn't like \"param\"");
-                       if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
-                               synfig::error("LayerParamConnect didn't like \"value_node\"");
-
-                       if(!get_canvas_interface()->get_instance()->perform_action(action))
-                       {
-                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer"));
-                               group.cancel();
-                               throw String(_("Unable to create Region layer"));
-                               return;
-                       }
-               }
-
-               // only link the region's origin parameter if the option is selected and we're creating more than one layer
-               if (get_layer_link_origins_flag() && layers_to_create > 1)
-               {
-                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
-                       assert(action);
-
-                       action->set_param("canvas",get_canvas());
-                       action->set_param("canvas_interface",get_canvas_interface());
-                       action->set_param("layer",layer);
-                       if(!action->set_param("param",String("origin")))
-                               synfig::error("LayerParamConnect didn't like \"param\"");
-                       if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
-                               synfig::error("LayerParamConnect didn't like \"value_node\"");
-
-                       if(!get_canvas_interface()->get_instance()->perform_action(action))
-                       {
-                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer"));
-                               group.cancel();
-                               throw String(_("Unable to create Region layer"));
-                               return;
-                       }
-               }
-               else
-               {
-                       layer->set_param("origin",origin);
-                       get_canvas_interface()->signal_layer_param_changed()(layer,"origin");
-               }
-       }
-
-       ///////////////////////////////////////////////////////////////////////////
-       //   O U T L I N E
-       ///////////////////////////////////////////////////////////////////////////
-
-       if (get_layer_outline_flag())
-       {
-               Layer::Handle layer(get_canvas_interface()->add_layer_to("outline",canvas,depth));
-               if (!layer)
-               {
-                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
-                       group.cancel();
-                       return;
-               }
-               layer_selection.push_back(layer);
-               layer->set_description(get_id()+_(" Outline"));
-               get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
-
-               layer->set_param("feather",get_feather());
-               get_canvas_interface()->signal_layer_param_changed()(layer,"feather");
-
-               layer->set_param("invert",get_invert());
-               get_canvas_interface()->signal_layer_param_changed()(layer,"invert");
-
-               {
-                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
-                       assert(action);
-
-                       action->set_param("canvas",get_canvas());
-                       action->set_param("canvas_interface",get_canvas_interface());
-                       action->set_param("layer",layer);
-                       if(!action->set_param("param",String("bline")))
-                               synfig::error("LayerParamConnect didn't like \"param\"");
-                       if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
-                               synfig::error("LayerParamConnect didn't like \"value_node\"");
-
-                       if(!get_canvas_interface()->get_instance()->perform_action(action))
-                       {
-                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
-                               group.cancel();
-                               throw String(_("Unable to create Outline layer"));
-                               return;
-                       }
-               }
-
-               // only link the outline's origin parameter if the option is selected and we're creating more than one layer
-               if (get_layer_link_origins_flag() && layers_to_create > 1)
-               {
-                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
-                       assert(action);
-
-                       action->set_param("canvas",get_canvas());
-                       action->set_param("canvas_interface",get_canvas_interface());
-                       action->set_param("layer",layer);
-                       if(!action->set_param("param",String("origin")))
-                               synfig::error("LayerParamConnect didn't like \"param\"");
-                       if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
-                               synfig::error("LayerParamConnect didn't like \"value_node\"");
-
-                       if(!get_canvas_interface()->get_instance()->perform_action(action))
-                       {
-                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
-                               group.cancel();
-                               throw String(_("Unable to create Outline layer"));
-                               return;
-                       }
-               }
-               else
-               {
-                       layer->set_param("origin",origin);
-                       get_canvas_interface()->signal_layer_param_changed()(layer,"origin");
-               }
-       }
-
-       egress_on_selection_change=false;
-       get_canvas_interface()->get_selection_manager()->clear_selected_layers();
-       get_canvas_interface()->get_selection_manager()->set_selected_layers(layer_selection);
-       egress_on_selection_change=true;
-
-       reset();
-       increment_id();
-}
-
-Smach::event_result
-StateStar_Context::event_mouse_click_handler(const Smach::event& x)
-{
-       const EventMouse& event(*reinterpret_cast<const EventMouse*>(&x));
-
-       if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_DOWN && event.button==BUTTON_LEFT)
-       {
-               point_holder=get_work_area()->snap_point_to_grid(event.pos);
-               etl::handle<Duck> duck=new Duck();
-               duck->set_point(point_holder);
-               duck->set_name("p1");
-               duck->set_type(Duck::TYPE_POSITION);
-               duck->set_editable(false);
-               get_work_area()->add_duck(duck);
-
-               point2_duck=new Duck();
-               point2_duck->set_point(Vector(0,0));
-               point2_duck->set_name("radius");
-               point2_duck->set_origin(duck);
-               point2_duck->set_radius(true);
-               point2_duck->set_scalar(-1);
-               point2_duck->set_type(Duck::TYPE_RADIUS);
-               point2_duck->set_hover(true);
-               get_work_area()->add_duck(point2_duck);
-
-               return Smach::RESULT_ACCEPT;
-       }
-
-       if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_DRAG && event.button==BUTTON_LEFT)
-       {
-               if (!point2_duck) return Smach::RESULT_OK;
-               point2_duck->set_point(point_holder-get_work_area()->snap_point_to_grid(event.pos));
-               get_work_area()->queue_draw();
-               return Smach::RESULT_ACCEPT;
-       }
-
-       if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_UP && event.button==BUTTON_LEFT)
-       {
-               Point point(get_work_area()->snap_point_to_grid(event.pos));
-
-               if (App::restrict_radius_ducks)
-               {
-                       if ((point[0] - point_holder[0]) < 0) point[0] = point_holder[0];
-                       if ((point[1] - point_holder[1]) < 0) point[1] = point_holder[1];
-               }
-
-               make_star(point_holder, point);
-               get_work_area()->clear_ducks();
-               return Smach::RESULT_ACCEPT;
-       }
-
-       return Smach::RESULT_OK;
-}
-
-
-void
-StateStar_Context::refresh_ducks()
-{
-       get_work_area()->clear_ducks();
-       get_work_area()->queue_draw();
-}
diff --git a/synfig-studio/src/gui/state_star.h b/synfig-studio/src/gui/state_star.h
deleted file mode 100644 (file)
index 606f77d..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/* === S Y N F I G ========================================================= */
-/*!    \file state_star.h
-**     \brief Star creation state
-**
-**     $Id$
-**
-**     \legal
-**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
-**  Copyright (c) 2008 Chris Moore
-**
-**     This package is free software; you can redistribute it and/or
-**     modify it under the terms of the GNU General Public License as
-**     published by the Free Software Foundation; either version 2 of
-**     the License, or (at your option) any later version.
-**
-**     This package is distributed in the hope that it will be useful,
-**     but WITHOUT ANY WARRANTY; without even the implied warranty of
-**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-**     General Public License for more details.
-**     \endlegal
-*/
-/* ========================================================================= */
-
-/* === S T A R T =========================================================== */
-
-#ifndef __SYNFIG_STUDIO_STATE_STAR_H
-#define __SYNFIG_STUDIO_STATE_STAR_H
-
-/* === H E A D E R S ======================================================= */
-
-#include "smach.h"
-
-
-/* === M A C R O S ========================================================= */
-
-/* === T Y P E D E F S ===================================================== */
-
-/* === C L A S S E S & S T R U C T S ======================================= */
-
-namespace studio {
-
-class StateStar_Context;
-
-class StateStar : public Smach::state<StateStar_Context>
-{
-public:
-       StateStar();
-       ~StateStar();
-}; // END of class StateStar
-
-extern StateStar state_star;
-
-}; // END of namespace studio
-
-/* === E N D =============================================================== */
-
-#endif
diff --git a/synfig-studio/src/gui/state_stroke.cpp b/synfig-studio/src/gui/state_stroke.cpp
deleted file mode 100644 (file)
index a0f7eca..0000000
+++ /dev/null
@@ -1,198 +0,0 @@
-/* === S Y N F I G ========================================================= */
-/*!    \file state_stroke.cpp
-**     \brief Template File
-**
-**     $Id$
-**
-**     \legal
-**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
-**     Copyright (c) 2007 Chris Moore
-**
-**     This package is free software; you can redistribute it and/or
-**     modify it under the terms of the GNU General Public License as
-**     published by the Free Software Foundation; either version 2 of
-**     the License, or (at your option) any later version.
-**
-**     This package is distributed in the hope that it will be useful,
-**     but WITHOUT ANY WARRANTY; without even the implied warranty of
-**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-**     General Public License for more details.
-**     \endlegal
-*/
-/* ========================================================================= */
-
-/* === H E A D E R S ======================================================= */
-
-#ifdef USING_PCH
-#      include "pch.h"
-#else
-#ifdef HAVE_CONFIG_H
-#      include <config.h>
-#endif
-
-#include <gtkmm/dialog.h>
-#include <gtkmm/entry.h>
-
-#include <synfig/valuenode_dynamiclist.h>
-
-#include "state_stroke.h"
-#include "canvasview.h"
-#include "workarea.h"
-#include "app.h"
-#include <synfig/valuenode_bline.h>
-#include <ETL/hermite>
-#include <ETL/calculus>
-#include <utility>
-#include "event_mouse.h"
-#include "event_layerclick.h"
-#include "toolbox.h"
-#include <synfigapp/main.h>
-
-#include "general.h"
-
-#endif
-
-/* === U S I N G =========================================================== */
-
-using namespace std;
-using namespace etl;
-using namespace synfig;
-using namespace studio;
-
-/* === M A C R O S ========================================================= */
-
-/* === G L O B A L S ======================================================= */
-
-StateStroke studio::state_stroke;
-
-/* === C L A S S E S & S T R U C T S ======================================= */
-
-class studio::StateStroke_Context : public sigc::trackable
-{
-       etl::handle<CanvasView> canvas_view_;
-       CanvasView::IsWorking is_working;
-
-       Duckmatic::Push duckmatic_push;
-
-       etl::smart_ptr<std::list<synfig::Point> > stroke_data;
-
-       etl::smart_ptr<std::list<synfig::Real> > width_data;
-
-       Gdk::ModifierType modifier;
-
-public:
-
-       Smach::event_result event_stop_handler(const Smach::event& x);
-
-       Smach::event_result event_refresh_handler(const Smach::event& x);
-
-       Smach::event_result event_mouse_up_handler(const Smach::event& x);
-
-       Smach::event_result event_mouse_draw_handler(const Smach::event& x);
-       Smach::event_result event_refresh_tool_options(const Smach::event& x);
-
-       StateStroke_Context(CanvasView* canvas_view);
-
-       ~StateStroke_Context();
-
-       const etl::handle<CanvasView>& get_canvas_view()const{return canvas_view_;}
-       etl::handle<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view_->canvas_interface();}
-       synfig::Canvas::Handle get_canvas()const{return canvas_view_->get_canvas();}
-       WorkArea * get_work_area()const{return canvas_view_->get_work_area();}
-
-};     // END of class StateStroke_Context
-
-
-/* === M E T H O D S ======================================================= */
-
-StateStroke::StateStroke():
-       Smach::state<StateStroke_Context>("stroke")
-{
-       insert(event_def(EVENT_STOP,&StateStroke_Context::event_stop_handler));
-       insert(event_def(EVENT_REFRESH,&StateStroke_Context::event_refresh_handler));
-//     insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateStroke_Context::event_mouse_down_handler));
-       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_UP,&StateStroke_Context::event_mouse_up_handler));
-       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DRAG,&StateStroke_Context::event_mouse_draw_handler));
-       insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateStroke_Context::event_refresh_tool_options));
-}
-
-StateStroke::~StateStroke()
-{
-}
-
-
-StateStroke_Context::StateStroke_Context(CanvasView* canvas_view):
-       canvas_view_(canvas_view),
-       is_working(*canvas_view),
-       duckmatic_push(get_work_area())
-{
-       width_data.spawn();
-       stroke_data.spawn();
-
-       get_work_area()->add_stroke(stroke_data, synfigapp::Main::get_outline_color());
-}
-
-StateStroke_Context::~StateStroke_Context()
-{
-       duckmatic_push.restore();
-
-       App::toolbox->refresh();
-
-       // Send the stroke data to whatever previously called this state.
-       if(stroke_data->size()>=2)
-               get_canvas_view()->get_smach().process_event(EventStroke(stroke_data,width_data,modifier));
-}
-
-Smach::event_result
-StateStroke_Context::event_refresh_tool_options(const Smach::event& /*x*/)
-{
-       return Smach::RESULT_ACCEPT;
-}
-
-Smach::event_result
-StateStroke_Context::event_stop_handler(const Smach::event& /*x*/)
-{
-       throw Smach::pop_exception();
-}
-
-Smach::event_result
-StateStroke_Context::event_refresh_handler(const Smach::event& /*x*/)
-{
-       return Smach::RESULT_ACCEPT;
-}
-
-Smach::event_result
-StateStroke_Context::event_mouse_up_handler(const Smach::event& x)
-{
-       const EventMouse& event(*reinterpret_cast<const EventMouse*>(&x));
-       switch(event.button)
-       {
-       case BUTTON_LEFT:
-               {
-                       modifier=event.modifier;
-                       throw Smach::pop_exception();
-               }
-
-       default:
-               return Smach::RESULT_OK;
-       }
-}
-
-Smach::event_result
-StateStroke_Context::event_mouse_draw_handler(const Smach::event& x)
-{
-       const EventMouse& event(*reinterpret_cast<const EventMouse*>(&x));
-       switch(event.button)
-       {
-       case BUTTON_LEFT:
-               {
-                       stroke_data->push_back(event.pos);
-                       width_data->push_back(event.pressure);
-                       get_work_area()->queue_draw();
-                       return Smach::RESULT_ACCEPT;
-               }
-
-       default:
-               return Smach::RESULT_OK;
-       }
-}
diff --git a/synfig-studio/src/gui/state_stroke.h b/synfig-studio/src/gui/state_stroke.h
deleted file mode 100644 (file)
index 0beade5..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/* === S Y N F I G ========================================================= */
-/*!    \file state_stroke.h
-**     \brief Template Header
-**
-**     $Id$
-**
-**     \legal
-**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
-**
-**     This package is free software; you can redistribute it and/or
-**     modify it under the terms of the GNU General Public License as
-**     published by the Free Software Foundation; either version 2 of
-**     the License, or (at your option) any later version.
-**
-**     This package is distributed in the hope that it will be useful,
-**     but WITHOUT ANY WARRANTY; without even the implied warranty of
-**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-**     General Public License for more details.
-**     \endlegal
-*/
-/* ========================================================================= */
-
-/* === S T A R T =========================================================== */
-
-#ifndef __SYNFIG_STUDIO_STATE_STROKE_H
-#define __SYNFIG_STUDIO_STATE_STROKE_H
-
-/* === H E A D E R S ======================================================= */
-
-#include "canvasview.h"
-#include "workarea.h"
-#include <sigc++/object.h>
-#include "duckmatic.h"
-#include <synfig/blinepoint.h>
-#include <list>
-#include <ETL/smart_ptr>
-#include "eventkey.h"
-#include <gdkmm/types.h>
-
-/* === M A C R O S ========================================================= */
-
-/* === T Y P E D E F S ===================================================== */
-
-/* === C L A S S E S & S T R U C T S ======================================= */
-
-namespace studio {
-
-class StateStroke_Context;
-
-class StateStroke : public Smach::state<StateStroke_Context>
-{
-public:
-       StateStroke();
-       ~StateStroke();
-}; // END of class StateStroke
-
-extern StateStroke state_stroke;
-
-struct EventStroke : public Smach::event
-{
-       etl::smart_ptr<std::list<synfig::Point> > stroke_data;
-       etl::smart_ptr<std::list<synfig::Real> > width_data;
-       Gdk::ModifierType modifier;
-
-       EventStroke(etl::smart_ptr<std::list<synfig::Point> > stroke_data,
-                       etl::smart_ptr<std::list<synfig::Real> > width_data,
-                       Gdk::ModifierType modifier=Gdk::ModifierType(0)
-       ):
-               Smach::event(EVENT_WORKAREA_STROKE),
-               stroke_data(stroke_data),
-               width_data(width_data),
-               modifier(modifier)
-       { }
-}; // END of EventStroke
-
-}; // END of namespace studio
-
-/* === E N D =============================================================== */
-
-#endif
diff --git a/synfig-studio/src/gui/state_text.cpp b/synfig-studio/src/gui/state_text.cpp
deleted file mode 100644 (file)
index 733f907..0000000
+++ /dev/null
@@ -1,460 +0,0 @@
-/* === S Y N F I G ========================================================= */
-/*!    \file state_text.cpp
-**     \brief Template File
-**
-**     $Id$
-**
-**     \legal
-**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
-**  Copyright (c) 2008 Chris Moore
-**
-**     This package is free software; you can redistribute it and/or
-**     modify it under the terms of the GNU General Public License as
-**     published by the Free Software Foundation; either version 2 of
-**     the License, or (at your option) any later version.
-**
-**     This package is distributed in the hope that it will be useful,
-**     but WITHOUT ANY WARRANTY; without even the implied warranty of
-**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-**     General Public License for more details.
-**     \endlegal
-*/
-/* ========================================================================= */
-
-/* === H E A D E R S ======================================================= */
-
-#ifdef USING_PCH
-#      include "pch.h"
-#else
-#ifdef HAVE_CONFIG_H
-#      include <config.h>
-#endif
-
-#include <gtkmm/dialog.h>
-#include <gtkmm/entry.h>
-
-#include "state_text.h"
-#include "state_normal.h"
-#include "canvasview.h"
-#include "workarea.h"
-#include "app.h"
-
-#include <synfigapp/action.h>
-#include "event_mouse.h"
-#include "event_layerclick.h"
-#include "toolbox.h"
-#include "dialog_tooloptions.h"
-#include <gtkmm/optionmenu.h>
-#include "duck.h"
-#include "widgets/widget_enum.h"
-#include <synfigapp/main.h>
-
-#include "general.h"
-
-#endif
-
-/* === U S I N G =========================================================== */
-
-using namespace std;
-using namespace etl;
-using namespace synfig;
-using namespace studio;
-
-/* === M A C R O S ========================================================= */
-
-/* === G L O B A L S ======================================================= */
-
-StateText studio::state_text;
-
-/* === C L A S S E S & S T R U C T S ======================================= */
-
-class studio::StateText_Context
-{
-       etl::handle<CanvasView> canvas_view;
-       CanvasView::IsWorking is_working;
-
-       Duckmatic::Push duckmatic_push;
-
-       void refresh_ducks();
-
-       bool prev_workarea_layer_status_;
-
-       //Toolbox settings
-       synfigapp::Settings& settings;
-
-       //Toolbox display
-       Gtk::Table options_table;
-
-       Gtk::Entry              entry_id; //what to name the layer
-       Gtk::Entry              entry_family;
-       Widget_Vector   widget_size;
-       Widget_Vector   widget_orientation;
-       Gtk::CheckButton checkbutton_paragraph;
-
-public:
-       synfig::String get_id()const { return entry_id.get_text(); }
-       void set_id(const synfig::String& x) { return entry_id.set_text(x); }
-
-       bool get_paragraph_flag()const { return checkbutton_paragraph.get_active(); }
-       void set_paragraph_flag(bool x) { return checkbutton_paragraph.set_active(x); }
-
-       Vector get_size() { return widget_size.get_value(); }
-       void set_size(Vector s) { return widget_size.set_value(s); }
-
-       Vector get_orientation() { return widget_orientation.get_value(); }
-       void set_orientation(Vector s) { return widget_orientation.set_value(s); }
-
-       String get_family()const { return entry_family.get_text(); }
-       void set_family(String s) { return entry_family.set_text(s); }
-
-       void refresh_tool_options(); //to refresh the toolbox
-
-       //events
-       Smach::event_result event_stop_handler(const Smach::event& x);
-       Smach::event_result event_refresh_handler(const Smach::event& x);
-       Smach::event_result event_mouse_click_handler(const Smach::event& x);
-       Smach::event_result event_refresh_tool_options(const Smach::event& x);
-       Smach::event_result event_workarea_mouse_button_down_handler(const Smach::event& x);
-
-       //constructor destructor
-       StateText_Context(CanvasView *canvas_view);
-       ~StateText_Context();
-
-       const etl::handle<CanvasView>& get_canvas_view()const{return canvas_view;}
-       etl::handle<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view->canvas_interface();}
-       WorkArea * get_work_area()const{return canvas_view->get_work_area();}
-
-       //Modifying settings etc.
-       void load_settings();
-       void save_settings();
-       void reset();
-       void increment_id();
-       bool egress_on_selection_change;
-       Smach::event_result event_layer_selection_changed_handler(const Smach::event& /*x*/)
-       {
-               if(egress_on_selection_change)
-                       throw &state_normal; //throw Smach::egress_exception();
-               return Smach::RESULT_OK;
-       }
-
-       void make_text(const Point& point);
-
-}; // END of class StateText_Context
-
-/* === P R O C E D U R E S ================================================= */
-
-/* === M E T H O D S ======================================================= */
-
-StateText::StateText():
-       Smach::state<StateText_Context>("text")
-{
-       insert(event_def(EVENT_LAYER_SELECTION_CHANGED,&StateText_Context::event_layer_selection_changed_handler));
-       insert(event_def(EVENT_STOP,&StateText_Context::event_stop_handler));
-       insert(event_def(EVENT_REFRESH,&StateText_Context::event_refresh_handler));
-       insert(event_def(EVENT_REFRESH_DUCKS,&StateText_Context::event_refresh_handler));
-       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateText_Context::event_workarea_mouse_button_down_handler));
-       insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateText_Context::event_refresh_tool_options));
-}
-
-StateText::~StateText()
-{
-}
-
-void
-StateText_Context::load_settings()
-{
-       String value;
-       Vector v;
-
-       //parse the arguments yargh!
-       if(settings.get_value("text.id",value))
-               set_id(value);
-       else
-               set_id("Text");
-
-       if(settings.get_value("text.paragraph",value) && value=="1")
-               set_paragraph_flag(true);
-       else
-               set_paragraph_flag(false);
-
-       if(settings.get_value("text.size_x",value))
-               v[0] = atof(value.c_str());
-       else
-               v[0] = 0.25;
-       if(settings.get_value("text.size_y",value))
-               v[1] = atof(value.c_str());
-       else
-               v[1] = 0.25;
-       set_size(v);
-
-       if(settings.get_value("text.orient_x",value))
-               v[0] = atof(value.c_str());
-       else
-               v[0] = 0.5;
-       if(settings.get_value("text.orient_y",value))
-               v[1] = atof(value.c_str());
-       else
-               v[1] = 0.5;
-       set_orientation(v);
-
-       if(settings.get_value("text.family",value))
-               set_family(value);
-       else
-               set_family("Sans Serif");
-}
-
-void
-StateText_Context::save_settings()
-{
-       settings.set_value("text.id",get_id());
-       settings.set_value("text.paragraph",get_paragraph_flag()?"1":"0");
-       settings.set_value("text.size_x",strprintf("%f",(float)get_size()[0]));
-       settings.set_value("text.size_y",strprintf("%f",(float)get_size()[1]));
-       settings.set_value("text.orient_x",strprintf("%f",(float)get_orientation()[0]));
-       settings.set_value("text.orient_y",strprintf("%f",(float)get_orientation()[1]));
-       settings.set_value("text.family",get_family());
-}
-
-void
-StateText_Context::reset()
-{
-       refresh_ducks();
-}
-
-void
-StateText_Context::increment_id()
-{
-       String id(get_id());
-       int number=1;
-       int digits=0;
-
-       if(id.empty())
-               id="Text";
-
-       // If there is a number
-       // already at the end of the
-       // id, then remove it.
-       if(id[id.size()-1]<='9' && id[id.size()-1]>='0')
-       {
-               // figure out how many digits it is
-               for (digits = 0;
-                        (int)id.size()-1 >= digits && id[id.size()-1-digits] <= '9' && id[id.size()-1-digits] >= '0';
-                        digits++)
-                       ;
-
-               String str_number;
-               str_number=String(id,id.size()-digits,id.size());
-               id=String(id,0,id.size()-digits);
-
-               number=atoi(str_number.c_str());
-       }
-       else
-       {
-               number=1;
-               digits=3;
-       }
-
-       number++;
-
-       // Add the number back onto the id
-       {
-               const String format(strprintf("%%0%dd",digits));
-               id+=strprintf(format.c_str(),number);
-       }
-
-       // Set the ID
-       set_id(id);
-}
-
-StateText_Context::StateText_Context(CanvasView *canvas_view):
-       canvas_view(canvas_view),
-       is_working(*canvas_view),
-       duckmatic_push(get_work_area()),
-       prev_workarea_layer_status_(get_work_area()->get_allow_layer_clicks()),
-       settings(synfigapp::Main::get_selected_input_device()->settings()),
-       entry_id(),
-       checkbutton_paragraph(_("Multiline Editor"))
-{
-       egress_on_selection_change=true;
-
-       widget_size.set_digits(2);
-       widget_size.set_canvas(canvas_view->get_canvas());
-
-       widget_orientation.set_digits(2);
-
-       options_table.attach(*manage(new Gtk::Label(_("Text Tool"))),           0, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(entry_id,                                                                          0, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(checkbutton_paragraph,                                                     0, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(*manage(new Gtk::Label(_("Size:"))),                       0, 1, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(widget_size,                                                                       1, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(*manage(new Gtk::Label(_("Orientation:"))),        0, 1, 4, 5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(widget_orientation,                                                        1, 2, 4, 5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(*manage(new Gtk::Label(_("Family:"))),                     0, 1, 5, 6, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(entry_family,                                                                      1, 2, 5, 6, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-
-       load_settings();
-
-       options_table.show_all();
-
-       refresh_tool_options();
-       App::dialog_tool_options->present();
-
-       // Turn off layer clicking
-       get_work_area()->set_allow_layer_clicks(false);
-
-       // clear out the ducks
-       get_work_area()->clear_ducks();
-
-       // Refresh the work area
-       get_work_area()->queue_draw();
-
-       // Hide the tables if they are showing
-       //prev_table_status=get_canvas_view()->tables_are_visible();
-       //if(prev_table_status)get_canvas_view()->hide_tables();
-
-       // Disable the time bar
-       //get_canvas_view()->set_sensitive_timebar(false);
-
-       // Connect a signal
-       //get_work_area()->signal_user_click().connect(sigc::mem_fun(*this,&studio::StateText_Context::on_user_click));
-       get_work_area()->set_cursor(Gdk::XTERM);
-
-       App::toolbox->refresh();
-}
-
-void
-StateText_Context::refresh_tool_options()
-{
-       App::dialog_tool_options->clear();
-       App::dialog_tool_options->set_widget(options_table);
-       App::dialog_tool_options->set_local_name(_("Text Tool"));
-       App::dialog_tool_options->set_name("text");
-}
-
-Smach::event_result
-StateText_Context::event_refresh_tool_options(const Smach::event& /*x*/)
-{
-       refresh_tool_options();
-       return Smach::RESULT_ACCEPT;
-}
-
-StateText_Context::~StateText_Context()
-{
-       save_settings();
-
-       // Restore layer clicking
-       get_work_area()->set_allow_layer_clicks(prev_workarea_layer_status_);
-       get_work_area()->reset_cursor();
-
-       App::dialog_tool_options->clear();
-
-       get_work_area()->queue_draw();
-
-       get_canvas_view()->queue_rebuild_ducks();
-
-       App::toolbox->refresh();
-}
-
-Smach::event_result
-StateText_Context::event_stop_handler(const Smach::event& /*x*/)
-{
-       //throw Smach::egress_exception();
-       throw &state_normal;
-       return Smach::RESULT_OK;
-}
-
-Smach::event_result
-StateText_Context::event_refresh_handler(const Smach::event& /*x*/)
-{
-       refresh_ducks();
-       return Smach::RESULT_ACCEPT;
-}
-
-void
-StateText_Context::make_text(const Point& _point)
-{
-       synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("New Text"));
-       synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
-
-       Layer::Handle layer;
-
-       Canvas::Handle canvas(get_canvas_view()->get_canvas());
-       int depth(0);
-
-       // we are temporarily using the layer to hold something
-       layer=get_canvas_view()->get_selection_manager()->get_selected_layer();
-       if(layer)
-       {
-               depth=layer->get_depth();
-               canvas=layer->get_canvas();
-       }
-
-       synfigapp::SelectionManager::LayerList layer_selection;
-       if (!getenv("SYNFIG_TOOLS_CLEAR_SELECTION"))
-               layer_selection = get_canvas_view()->get_selection_manager()->get_selected_layers();
-
-       const synfig::TransformStack& transform(get_canvas_view()->get_curr_transform_stack());
-       const Point point(transform.unperform(_point));
-
-       String text;
-       if (get_paragraph_flag())
-               App::dialog_paragraph(_("Text Paragraph"), _("Enter text here:"), text);
-       else
-               App::dialog_entry(_("Text Entry"), _("Enter text here:"), text);
-
-       layer=get_canvas_interface()->add_layer_to("text",canvas,depth);
-       if (!layer)
-       {
-               get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
-               group.cancel();
-               return;
-       }
-       layer_selection.push_back(layer);
-
-       layer->set_param("origin",point);
-       get_canvas_interface()->signal_layer_param_changed()(layer,"origin");
-
-       layer->set_param("text",text);
-       get_canvas_interface()->signal_layer_param_changed()(layer,"text");
-
-       layer->set_param("size",get_size());
-       get_canvas_interface()->signal_layer_param_changed()(layer,"size");
-
-       layer->set_param("orient",get_orientation());
-       get_canvas_interface()->signal_layer_param_changed()(layer,"orient");
-
-       layer->set_param("family",get_family());
-       get_canvas_interface()->signal_layer_param_changed()(layer,"family");
-
-       layer->set_description(get_id());
-       get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
-
-       egress_on_selection_change=false;
-       get_canvas_interface()->get_selection_manager()->clear_selected_layers();
-       get_canvas_interface()->get_selection_manager()->set_selected_layers(layer_selection);
-       egress_on_selection_change=true;
-
-       reset();
-       increment_id();
-}
-
-Smach::event_result
-StateText_Context::event_workarea_mouse_button_down_handler(const Smach::event& x)
-{
-       const EventMouse& event(*reinterpret_cast<const EventMouse*>(&x));
-       if(event.button==BUTTON_LEFT)
-       {
-               make_text(get_work_area()->snap_point_to_grid(event.pos));
-
-               get_work_area()->clear_ducks();
-               return Smach::RESULT_ACCEPT;
-       }
-       return Smach::RESULT_OK;
-}
-
-void
-StateText_Context::refresh_ducks()
-{
-       get_work_area()->clear_ducks();
-       get_work_area()->queue_draw();
-}
diff --git a/synfig-studio/src/gui/state_text.h b/synfig-studio/src/gui/state_text.h
deleted file mode 100644 (file)
index 4b05db5..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/* === S Y N F I G ========================================================= */
-/*!    \file state_text.h
-**     \brief Template Header
-**
-**     $Id$
-**
-**     \legal
-**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
-**  Copyright (c) 2008 Chris Moore
-**
-**     This package is free software; you can redistribute it and/or
-**     modify it under the terms of the GNU General Public License as
-**     published by the Free Software Foundation; either version 2 of
-**     the License, or (at your option) any later version.
-**
-**     This package is distributed in the hope that it will be useful,
-**     but WITHOUT ANY WARRANTY; without even the implied warranty of
-**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-**     General Public License for more details.
-**     \endlegal
-*/
-/* ========================================================================= */
-
-/* === S T A R T =========================================================== */
-
-#ifndef __SYNFIG_STATE_TEXT_H
-#define __SYNFIG_STATE_TEXT_H
-
-/* === H E A D E R S ======================================================= */
-
-#include "smach.h"
-
-
-/* === M A C R O S ========================================================= */
-
-/* === T Y P E D E F S ===================================================== */
-
-/* === C L A S S E S & S T R U C T S ======================================= */
-
-namespace studio {
-
-class StateText_Context;
-
-class StateText : public Smach::state<StateText_Context>
-{
-public:
-       StateText();
-       ~StateText();
-}; // END of class StateText
-
-extern StateText state_text;
-
-}; // END of namespace studio
-
-/* === E N D =============================================================== */
-
-#endif
diff --git a/synfig-studio/src/gui/state_width.cpp b/synfig-studio/src/gui/state_width.cpp
deleted file mode 100644 (file)
index 8c74daa..0000000
+++ /dev/null
@@ -1,606 +0,0 @@
-/* === S Y N F I G ========================================================= */
-/*!    \file state_width.cpp
-**     \brief Template File
-**
-**     $Id$
-**
-**     \legal
-**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
-**  Copyright (c) 2008 Chris Moore
-**
-**     This package is free software; you can redistribute it and/or
-**     modify it under the terms of the GNU General Public License as
-**     published by the Free Software Foundation; either version 2 of
-**     the License, or (at your option) any later version.
-**
-**     This package is distributed in the hope that it will be useful,
-**     but WITHOUT ANY WARRANTY; without even the implied warranty of
-**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-**     General Public License for more details.
-**     \endlegal
-*/
-/* ========================================================================= */
-
-/* === H E A D E R S ======================================================= */
-
-#ifdef USING_PCH
-#      include "pch.h"
-#else
-#ifdef HAVE_CONFIG_H
-#      include <config.h>
-#endif
-
-#include <gtkmm/dialog.h>
-#include <gtkmm/entry.h>
-
-#include <ETL/bezier>
-
-#include <synfig/valuenode_dynamiclist.h>
-#include <synfigapp/action_system.h>
-
-#include "state_width.h"
-#include "state_normal.h"
-#include "canvasview.h"
-#include "workarea.h"
-#include "app.h"
-
-#include <synfigapp/action.h>
-#include "event_mouse.h"
-#include "event_layerclick.h"
-#include "toolbox.h"
-#include "dialog_tooloptions.h"
-#include <gtkmm/optionmenu.h>
-#include "duck.h"
-
-//#include <synfigapp/value_desc.h>
-#include <synfigapp/main.h>
-
-#include <ETL/clock>
-
-#include "general.h"
-
-#endif
-
-/* === U S I N G =========================================================== */
-
-using namespace std;
-using namespace etl;
-using namespace synfig;
-using namespace synfigapp;
-using namespace studio;
-
-/* === M A C R O S ========================================================= */
-
-/* === G L O B A L S ======================================================= */
-
-StateWidth studio::state_width;
-
-/* === C L A S S E S & S T R U C T S ======================================= */
-
-class studio::StateWidth_Context : public sigc::trackable
-{
-       etl::handle<CanvasView> canvas_view_;
-       CanvasView::IsWorking is_working;
-
-       //Point mouse_pos;
-
-       handle<Duck> center;
-       handle<Duck> radius;
-       handle<Duck> closestpoint;
-
-       map<handle<Duck>,Real>  changetable;
-
-       etl::clock      clocktime;
-       Real            lastt;
-
-       bool added;
-
-       void refresh_ducks();
-
-       bool prev_workarea_layer_clicking;
-       bool prev_workarea_duck_clicking;
-       Duckmatic::Type old_duckmask;
-
-       //Toolbox settings
-       synfigapp::Settings& settings;
-
-       //Toolbox display
-       Gtk::Table options_table;
-
-       Gtk::Adjustment adj_delta;
-       Gtk::SpinButton spin_delta;
-
-       Gtk::Adjustment adj_radius;
-       Gtk::SpinButton spin_radius;
-
-       Gtk::CheckButton check_relative;
-
-       void AdjustWidth(handle<Duckmatic::Bezier> c, float t, Real mult, bool invert);
-
-public:
-
-       Real get_delta()const { return adj_delta.get_value(); }
-       void set_delta(Real f) { adj_delta.set_value(f); }
-
-       Real get_radius()const { return adj_radius.get_value(); }
-       void set_radius(Real f) { adj_radius.set_value(f); }
-
-       bool get_relative() const { return check_relative.get_active(); }
-       void set_relative(bool r) { check_relative.set_active(r); }
-
-       void refresh_tool_options(); //to refresh the toolbox
-
-       //events
-       Smach::event_result event_stop_handler(const Smach::event& x);
-       Smach::event_result event_refresh_handler(const Smach::event& x);
-       Smach::event_result event_mouse_handler(const Smach::event& x);
-       Smach::event_result event_refresh_tool_options(const Smach::event& x);
-
-       //constructor destructor
-       StateWidth_Context(CanvasView* canvas_view);
-       ~StateWidth_Context();
-
-       //Canvas interaction
-       const etl::handle<CanvasView>& get_canvas_view()const{return canvas_view_;}
-       etl::handle<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view_->canvas_interface();}
-       synfig::Canvas::Handle get_canvas()const{return canvas_view_->get_canvas();}
-       WorkArea * get_work_area()const{return canvas_view_->get_work_area();}
-
-       //Modifying settings etc.
-       void load_settings();
-       void save_settings();
-       void reset();
-
-};     // END of class StateWidth_Context
-
-/* === M E T H O D S ======================================================= */
-
-StateWidth::StateWidth():
-       Smach::state<StateWidth_Context>("width")
-{
-       insert(event_def(EVENT_STOP,&StateWidth_Context::event_stop_handler));
-       insert(event_def(EVENT_REFRESH,&StateWidth_Context::event_refresh_handler));
-       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateWidth_Context::event_mouse_handler));
-       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DRAG,&StateWidth_Context::event_mouse_handler));
-       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_UP,&StateWidth_Context::event_mouse_handler));
-       insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateWidth_Context::event_refresh_tool_options));
-}
-
-StateWidth::~StateWidth()
-{
-}
-
-void
-StateWidth_Context::load_settings()
-{
-       String value;
-
-       //parse the arguments yargh!
-       if(settings.get_value("width.delta",value))
-               set_delta(atof(value.c_str()));
-       else
-               set_delta(6);
-
-       if(settings.get_value("width.radius",value))
-               set_radius(atof(value.c_str()));
-       else
-               set_radius(15);
-
-       //defaults to false
-       if(settings.get_value("width.relative",value) && value == "1")
-               set_relative(true);
-       else
-               set_relative(false);
-}
-
-void
-StateWidth_Context::save_settings()
-{
-       settings.set_value("width.delta",strprintf("%f",get_delta()));
-       settings.set_value("width.radius",strprintf("%f",get_radius()));
-       settings.set_value("width.relative",get_relative()?"1":"0");
-}
-
-void
-StateWidth_Context::reset()
-{
-       refresh_ducks();
-}
-
-StateWidth_Context::StateWidth_Context(CanvasView* canvas_view):
-       canvas_view_(canvas_view),
-       is_working(*canvas_view),
-       prev_workarea_layer_clicking(get_work_area()->get_allow_layer_clicks()),
-       prev_workarea_duck_clicking(get_work_area()->get_allow_duck_clicks()),
-       old_duckmask(get_work_area()->get_type_mask()),
-
-       settings(synfigapp::Main::get_selected_input_device()->settings()),
-
-       adj_delta(6,0,20,0.01,0.1),
-       spin_delta(adj_delta,0.01,3),
-
-       adj_radius(200,0,1e50,1,10),
-       spin_radius(adj_radius,1,1),
-
-       check_relative(_("Relative Growth"))
-{
-       load_settings();
-
-       // Set up the tool options dialog
-       options_table.attach(*manage(new Gtk::Label(_("Width Tool"))),  0, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-
-       //expand stuff
-       options_table.attach(*manage(new Gtk::Label(_("Growth:"))),             0, 1, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(spin_delta,                                                                1, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-
-       options_table.attach(*manage(new Gtk::Label(_("Radius:"))),             0, 1, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-       options_table.attach(spin_radius,                                                               1, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-
-       options_table.attach(check_relative,                                                    0, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
-
-       options_table.show_all();
-
-       refresh_tool_options();
-       App::dialog_tool_options->present();
-
-       // Turn off layer clicking
-       get_work_area()->set_allow_layer_clicks(false);
-
-       // clear out the ducks
-       //get_work_area()->clear_ducks();
-
-       // Refresh the work area
-       get_work_area()->queue_draw();
-
-       //Create the new ducks
-       added = false;
-
-       if(!center)
-       {
-               center = new Duck();
-               center->set_name("p1");
-               center->set_type(Duck::TYPE_POSITION);
-       }
-
-       if(!radius)
-       {
-               radius = new Duck();
-               radius->set_origin(center);
-               radius->set_radius(true);
-               radius->set_type(Duck::TYPE_RADIUS);
-               radius->set_name("radius");
-       }
-
-       if(!closestpoint)
-       {
-               closestpoint = new Duck();
-               closestpoint->set_name("closest");
-               closestpoint->set_type(Duck::TYPE_POSITION);
-       }
-
-       //Disable duck clicking for the maximum coolness :)
-       get_work_area()->set_allow_duck_clicks(false);
-       get_work_area()->set_type_mask((Duck::Type)((int)Duck::TYPE_WIDTH + (int)Duck::TYPE_RADIUS));
-
-       // Turn the mouse pointer to crosshairs
-       get_work_area()->set_cursor(Gdk::CROSSHAIR);
-
-       // Hide the tables if they are showing
-       //prev_table_status=get_canvas_view()->tables_are_visible();
-       //if(prev_table_status)get_canvas_view()->hide_tables();
-
-       // Disable the time bar
-       //get_canvas_view()->set_sensitive_timebar(false);
-
-       // Connect a signal
-       //get_work_area()->signal_user_click().connect(sigc::mem_fun(*this,&studio::StateWidth_Context::on_user_click));
-
-       App::toolbox->refresh();
-}
-
-void
-StateWidth_Context::refresh_tool_options()
-{
-       App::dialog_tool_options->clear();
-       App::dialog_tool_options->set_widget(options_table);
-       App::dialog_tool_options->set_local_name(_("Width Tool"));
-       App::dialog_tool_options->set_name("width");
-}
-
-Smach::event_result
-StateWidth_Context::event_refresh_tool_options(const Smach::event& /*x*/)
-{
-       refresh_tool_options();
-       return Smach::RESULT_ACCEPT;
-}
-
-StateWidth_Context::~StateWidth_Context()
-{
-       save_settings();
-
-       //remove ducks if need be
-       if(added)
-       {
-               get_work_area()->erase_duck(center);
-               get_work_area()->erase_duck(radius);
-               get_work_area()->erase_duck(closestpoint);
-               added = false;
-       }
-
-       // Restore Duck clicking
-       get_work_area()->set_allow_duck_clicks(prev_workarea_duck_clicking);
-
-       // Restore layer clicking
-       get_work_area()->set_allow_layer_clicks(prev_workarea_layer_clicking);
-
-       // Restore the mouse pointer
-       get_work_area()->reset_cursor();
-
-       // Restore duck masking
-       get_work_area()->set_type_mask(old_duckmask);
-
-       // Tool options be rid of ye!!
-       App::dialog_tool_options->clear();
-
-       // Enable the time bar
-       //get_canvas_view()->set_sensitive_timebar(true);
-
-       // Bring back the tables if they were out before
-       //if(prev_table_status)get_canvas_view()->show_tables();
-
-       // Refresh the work area
-       get_work_area()->queue_draw();
-
-       App::toolbox->refresh();
-}
-
-Smach::event_result
-StateWidth_Context::event_stop_handler(const Smach::event& /*x*/)
-{
-       //throw Smach::egress_exception();
-       throw &state_normal;
-       return Smach::RESULT_OK;
-}
-
-Smach::event_result
-StateWidth_Context::event_refresh_handler(const Smach::event& /*x*/)
-{
-       refresh_ducks();
-       return Smach::RESULT_ACCEPT;
-}
-
-void
-StateWidth_Context::AdjustWidth(handle<Duckmatic::Bezier> c, float t, Real mult, bool invert)
-{
-       //Leave the function if there is no curve
-       if(!c)return;
-
-       Real amount1=0,amount2=0;
-
-       //decide how much to change each width
-       /*
-       t \in [0,1]
-
-       both pressure and multiply amount are in mult
-               (may want to change this to allow different types of falloff)
-
-       rsq is the squared distance from the point on the curve (also part of the falloff)
-
-
-       */
-       //may want to provide a different falloff function...
-       if(t <= 0.2)
-               amount1 = mult;
-       else if(t >= 0.8)
-               amount2 = mult;
-       else
-       {
-               t = (t-0.2)/0.6;
-               amount1 = (1-t)*mult;
-               amount2 = t*mult;
-       }
-
-       if(invert)
-       {
-               amount1 *= -1;
-               amount2 *= -1;
-       }
-
-       handle<Duck>    p1 = c->p1;
-       handle<Duck>    p2 = c->p2;
-
-       handle<Duck>    w1,w2;
-
-       //find w1,w2
-       {
-               const DuckList dl = get_work_area()->get_duck_list();
-
-               DuckList::const_iterator i = dl.begin();
-
-               for(;i != dl.end(); ++i)
-               {
-                       if((*i)->get_type() == Duck::TYPE_WIDTH)
-                       {
-                               if((*i)->get_origin_duck() == p1)
-                               {
-                                       w1 = *i;
-                               }
-
-                               if((*i)->get_origin_duck() == p2)
-                               {
-                                       w2 = *i;
-                               }
-                       }
-               }
-       }
-
-       if(amount1 != 0 && w1)
-       {
-               Real width = w1->get_point().mag();
-
-               width += amount1;
-               w1->set_point(Vector(width,0));
-
-               //log in the list of changes...
-               //to truly be changed after everything is said and done
-               changetable[w1] = width;
-       }
-
-       if(amount2 != 0 && w2)
-       {
-               Real width = w2->get_point().mag();
-
-               width += amount2;
-               w2->set_point(Vector(width,0));
-
-               //log in the list of changes...
-               //to truly be changed after everything is said and done
-               changetable[w2] = width;
-       }
-}
-
-Smach::event_result
-StateWidth_Context::event_mouse_handler(const Smach::event& x)
-{
-       const EventMouse& event(*reinterpret_cast<const EventMouse*>(&x));
-
-       //handle the click
-       if( (event.key == EVENT_WORKAREA_MOUSE_BUTTON_DOWN || event.key == EVENT_WORKAREA_MOUSE_BUTTON_DRAG)
-                       && event.button == BUTTON_LEFT )
-       {
-               const Real pw = get_work_area()->get_pw();
-               const Real ph = get_work_area()->get_ph();
-               const Real scale = sqrt(pw*pw+ph*ph);
-               const Real rad = get_relative() ? scale * get_radius() : get_radius();
-
-               bool invert = (event.modifier&Gdk::CONTROL_MASK);
-
-               const Real threshold = 0.08;
-
-               float t = 0;
-               Real rsq = 0;
-
-               Real dtime = 1/60.0;
-
-               //if we're dragging get the difference in time between now and then
-               if(event.key == EVENT_WORKAREA_MOUSE_BUTTON_DRAG)
-               {
-                       dtime = min(1/15.0,clocktime());
-               }
-               clocktime.reset();
-
-               //make way for new ducks
-               //get_work_area()->clear_ducks();
-
-               //update positions
-               //mouse_pos = event.pos;
-
-               center->set_point(event.pos);
-               if(!added)get_work_area()->add_duck(center);
-
-               radius->set_scalar(rad);
-               if(!added)get_work_area()->add_duck(radius);
-
-               //the other duck is at the current duck
-               closestpoint->set_point(event.pos);
-               if(!added)get_work_area()->add_duck(closestpoint);
-
-               //get the closest curve...
-               handle<Duckmatic::Bezier>       c;
-               if(event.pressure >= threshold)
-                       c = get_work_area()->find_bezier(event.pos,scale*8,rad,&t);
-
-               //run algorithm on event.pos to get 2nd placement
-               if(!c.empty())
-               {
-                       bezier<Point> curve;
-                       Point p;
-
-                       curve[0] = c->p1->get_trans_point();
-                       curve[1] = c->c1->get_trans_point();
-                       curve[2] = c->c2->get_trans_point();
-                       curve[3] = c->p2->get_trans_point();
-
-                       p = curve(t);
-                       rsq = (p-event.pos).mag_squared();
-
-                       const Real r = rad*rad;
-
-                       if(rsq < r)
-                       {
-                               closestpoint->set_point(curve(t));
-
-                               //adjust the width...
-                               //squared falloff for radius... [0,1]
-
-                               Real ri = (r - rsq)/r;
-                               AdjustWidth(c,t,ri*event.pressure*get_delta()*dtime,invert);
-                       }
-               }
-
-               //the points have been added
-               added = true;
-
-               //draw where it is yo!
-               get_work_area()->queue_draw();
-
-               return Smach::RESULT_ACCEPT;
-       }
-
-       if(event.key == EVENT_WORKAREA_MOUSE_BUTTON_UP && event.button == BUTTON_LEFT)
-       {
-               if(added)
-               {
-                       get_work_area()->erase_duck(center);
-                       get_work_area()->erase_duck(radius);
-                       get_work_area()->erase_duck(closestpoint);
-                       added = false;
-               }
-
-               //Affect the width changes here...
-               map<handle<Duck>,Real>::iterator i = changetable.begin();
-
-               synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Sketch Width"));
-               for(; i != changetable.end(); ++i)
-               {
-                       //for each duck modify IT!!!
-                       ValueDesc desc = i->first->get_value_desc();
-
-                       if(     desc.get_value_type() == ValueBase::TYPE_REAL )
-                       {
-                               Action::Handle action(Action::create("ValueDescSet"));
-                               assert(action);
-
-                               action->set_param("canvas",get_canvas());
-                               action->set_param("canvas_interface",get_canvas_interface());
-
-                               action->set_param("value_desc",desc);
-                               action->set_param("new_value",ValueBase(i->second));
-                               action->set_param("time",get_canvas_view()->get_time());
-
-                               if(!action->is_ready() || !get_canvas_view()->get_instance()->perform_action(action))
-                               {
-                                       group.cancel();
-                                       synfig::warning("Changing the width action has failed");
-                                       return Smach::RESULT_ERROR;
-                               }
-                       }
-               }
-
-               changetable.clear();
-
-               get_work_area()->queue_draw();
-
-               return Smach::RESULT_ACCEPT;
-       }
-
-       return Smach::RESULT_OK;
-}
-
-
-void
-StateWidth_Context::refresh_ducks()
-{
-       get_work_area()->clear_ducks();
-       get_work_area()->queue_draw();
-}
diff --git a/synfig-studio/src/gui/state_width.h b/synfig-studio/src/gui/state_width.h
deleted file mode 100644 (file)
index f649140..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/* === S Y N F I G ========================================================= */
-/*!    \file state_width.h
-**     \brief Width creation state
-**
-**     $Id$
-**
-**     \legal
-**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
-**
-**     This package is free software; you can redistribute it and/or
-**     modify it under the terms of the GNU General Public License as
-**     published by the Free Software Foundation; either version 2 of
-**     the License, or (at your option) any later version.
-**
-**     This package is distributed in the hope that it will be useful,
-**     but WITHOUT ANY WARRANTY; without even the implied warranty of
-**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-**     General Public License for more details.
-**     \endlegal
-*/
-/* ========================================================================= */
-
-/* === S T A R T =========================================================== */
-
-#ifndef __SYNFIG_STUDIO_STATE_WIDTH_H
-#define __SYNFIG_STUDIO_STATE_WIDTH_H
-
-/* === H E A D E R S ======================================================= */
-
-#include "smach.h"
-
-
-/* === M A C R O S ========================================================= */
-
-/* === T Y P E D E F S ===================================================== */
-
-/* === C L A S S E S & S T R U C T S ======================================= */
-
-namespace studio {
-
-class StateWidth_Context;
-
-class StateWidth : public Smach::state<StateWidth_Context>
-{
-public:
-       StateWidth();
-       ~StateWidth();
-}; // END of class StateWidth
-
-extern StateWidth state_width;
-
-}; // END of namespace studio
-
-/* === E N D =============================================================== */
-
-#endif
diff --git a/synfig-studio/src/gui/state_zoom.cpp b/synfig-studio/src/gui/state_zoom.cpp
deleted file mode 100644 (file)
index 56363e6..0000000
+++ /dev/null
@@ -1,263 +0,0 @@
-/* === S Y N F I G ========================================================= */
-/*!    \file state_zoom.cpp
-**     \brief Zoom Tool Implementation File
-**
-**     $Id$
-**
-**     \legal
-**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
-**  Copyright (c) 2008 Chris Moore
-**
-**     This package is free software; you can redistribute it and/or
-**     modify it under the terms of the GNU General Public License as
-**     published by the Free Software Foundation; either version 2 of
-**     the License, or (at your option) any later version.
-**
-**     This package is distributed in the hope that it will be useful,
-**     but WITHOUT ANY WARRANTY; without even the implied warranty of
-**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-**     General Public License for more details.
-**     \endlegal
-*/
-/* ========================================================================= */
-
-/* === H E A D E R S ======================================================= */
-
-#ifdef USING_PCH
-#      include "pch.h"
-#else
-#ifdef HAVE_CONFIG_H
-#      include <config.h>
-#endif
-
-#include <sigc++/signal.h>
-#include <sigc++/object.h>
-
-#include <ETL/handle>
-#include <synfig/vector.h>
-
-
-#include "state_zoom.h"
-#include "state_normal.h"
-#include "event_mouse.h"
-#include "canvasview.h"
-#include "workarea.h"
-#include "app.h"
-#include "toolbox.h"
-#include <synfigapp/main.h>
-
-#include "general.h"
-
-#endif
-
-/* === U S I N G =========================================================== */
-
-using namespace std;
-using namespace etl;
-using namespace synfig;
-using namespace studio;
-
-/* === M A C R O S ========================================================= */
-
-/* === G L O B A L S ======================================================= */
-StateZoom studio::state_zoom;
-
-const float ZOOMFACTOR = 1.25f;
-
-/* === C L A S S E S & S T R U C T S ======================================= */
-
-class studio::StateZoom_Context : public sigc::trackable
-{
-       etl::handle<CanvasView> canvas_view_;
-       CanvasView::IsWorking is_working;
-
-       Point p1,p2;
-
-       bool prev_workarea_layer_status_;
-
-public:
-
-       //events
-       Smach::event_result event_stop_handler(const Smach::event& x);
-       Smach::event_result event_refresh_handler(const Smach::event& x);
-       Smach::event_result event_mouse_click_handler(const Smach::event& x);
-
-       //constructor destructor
-       StateZoom_Context(CanvasView* canvas_view);
-       ~StateZoom_Context();
-
-       //Canvas interaction
-       const etl::handle<CanvasView>& get_canvas_view()const{return canvas_view_;}
-       etl::handle<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view_->canvas_interface();}
-       synfig::Canvas::Handle get_canvas()const{return canvas_view_->get_canvas();}
-       WorkArea * get_work_area()const{return canvas_view_->get_work_area();}
-
-       //void zoom(const Point& p1, const Point& p2);
-
-};     // END of class StateZoom_Context
-
-/* === M E T H O D S ======================================================= */
-
-StateZoom::StateZoom():
-       Smach::state<StateZoom_Context>("zoom")
-{
-       insert(event_def(EVENT_STOP,&StateZoom_Context::event_stop_handler));
-       insert(event_def(EVENT_REFRESH,&StateZoom_Context::event_refresh_handler));
-       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateZoom_Context::event_mouse_click_handler));
-       //insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DRAG,&StateZoom_Context::event_mouse_click_handler));
-       insert(event_def(EVENT_WORKAREA_BOX,&StateZoom_Context::event_mouse_click_handler));
-       //insert(event_def(EVENT_WORKAREA_BUTTON_CLICK,&StateZoom_Context::event_mouse_click_handler));
-       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_UP,&StateZoom_Context::event_mouse_click_handler));
-}
-
-StateZoom::~StateZoom()
-{
-}
-
-StateZoom_Context::StateZoom_Context(CanvasView* canvas_view):
-       canvas_view_(canvas_view),
-       is_working(*canvas_view),
-       prev_workarea_layer_status_(get_work_area()->get_allow_layer_clicks())
-{
-       // Turn off layer clicking
-       get_work_area()->set_allow_layer_clicks(false);
-
-       // clear out the ducks
-       get_work_area()->clear_ducks(); //???
-
-       // Refresh the work area
-       get_work_area()->queue_draw();
-
-       // Hide the tables if they are showing
-       //prev_table_status=get_canvas_view()->tables_are_visible();
-       //if(prev_table_status)get_canvas_view()->hide_tables();
-
-       // Disable the time bar
-       //get_canvas_view()->set_sensitive_timebar(false);
-
-       // Connect a signal
-       //get_work_area()->signal_user_click().connect(sigc::mem_fun(*this,&studio::StateZoom_Context::on_user_click));
-       get_work_area()->set_cursor(Gdk::CROSSHAIR);
-
-       App::toolbox->refresh();
-}
-
-StateZoom_Context::~StateZoom_Context()
-{
-       // Restore layer clicking
-       get_work_area()->set_allow_layer_clicks(prev_workarea_layer_status_);
-       get_work_area()->reset_cursor();
-
-       // Enable the time bar
-       //get_canvas_view()->set_sensitive_timebar(true);
-
-       // Bring back the tables if they were out before
-       //if(prev_table_status)get_canvas_view()->show_tables();
-
-       // Refresh the work area
-       get_work_area()->queue_draw();
-
-       App::toolbox->refresh();
-
-       get_canvas_view()->get_smach().process_event(EVENT_REFRESH_DUCKS);
-}
-
-Smach::event_result
-StateZoom_Context::event_stop_handler(const Smach::event& /*x*/)
-{
-       //throw Smach::egress_exception();
-       throw &state_normal;
-       return Smach::RESULT_OK;
-}
-
-Smach::event_result
-StateZoom_Context::event_refresh_handler(const Smach::event& /*x*/)
-{
-       return Smach::RESULT_ACCEPT;
-}
-
-Smach::event_result
-StateZoom_Context::event_mouse_click_handler(const Smach::event& x)
-{
-       if(x.key==EVENT_WORKAREA_BOX)
-       {
-               const EventBox& event(*reinterpret_cast<const EventBox*>(&x));
-
-               if(event.button==BUTTON_LEFT)
-               {
-                       Point tl = get_work_area()->get_window_tl();
-                       Point br = get_work_area()->get_window_br();
-                       Vector  window_span = br - tl, window_middle = (br+tl)/2;
-                       Vector  box_span = event.p2 - event.p1, box_middle = (event.p1+event.p2)/2;
-                       Point newpos;
-                       float zoom;
-
-                       if(event.modifier & Gdk::CONTROL_MASK) //zoom out...
-                       {
-                               if (window_span[0] == 0 || window_span[1] == 0) zoom = 1;
-                               else zoom = max(abs(box_span[0]/window_span[0]), abs(box_span[1]/window_span[1]));
-
-                               // focus_point is -1 times the real position for some reason...
-                               // center the window so the old contents fill the drawn box
-                               newpos = -((window_middle - box_middle)/zoom + window_middle);
-                       }
-                       else                            // zoom in
-                       {
-                               if (box_span[0] == 0 || box_span[1] == 0) zoom = 1;
-                               else zoom = min(abs(window_span[0]/box_span[0]), abs(window_span[1]/box_span[1]));
-
-                               // center the window at the center of the box
-                               newpos = -(-get_work_area()->get_focus_point() + (box_middle - window_middle));
-                       }
-
-                       get_work_area()->set_focus_point(newpos);
-                       get_work_area()->set_zoom(get_work_area()->get_zoom()*zoom);
-
-                       return Smach::RESULT_ACCEPT;
-               }
-       }
-
-       if(x.key==EVENT_WORKAREA_MOUSE_BUTTON_UP)
-       {
-               const EventMouse& event(*reinterpret_cast<const EventMouse*>(&x));
-
-               if(event.button==BUTTON_LEFT)
-               {
-                       Point evpos;
-
-                       //make the event pos be in the same space...
-                       //   The weird ass inverted center normalized space...
-                       {
-                               const Point realcenter = (get_work_area()->get_window_tl() + get_work_area()->get_window_br())/2;
-                               evpos = -(event.pos - realcenter) + get_work_area()->get_focus_point();
-                       }
-
-                       /*      Zooming:
-                               focus point must zoom about the point evpos...
-
-                               trans about an origin not 0:
-                               p' = A(p - o) + o
-                       */
-
-                       Vector v = get_work_area()->get_focus_point() - evpos;
-
-                       if(event.modifier & Gdk::CONTROL_MASK) //zoom out...
-                       {
-                               v*=ZOOMFACTOR;
-                               //get_work_area()->zoom_out();
-                               get_work_area()->set_focus_point(evpos + v);
-                               get_work_area()->set_zoom(get_work_area()->get_zoom()/ZOOMFACTOR);
-                       }else //zoom in
-                       {
-                               v/=ZOOMFACTOR;
-                               //get_work_area()->zoom_in();
-                               get_work_area()->set_focus_point(evpos + v);
-                               get_work_area()->set_zoom(get_work_area()->get_zoom()*ZOOMFACTOR);
-                       }
-
-                       return Smach::RESULT_ACCEPT;
-               }
-       }
-
-       return Smach::RESULT_OK;
-}
diff --git a/synfig-studio/src/gui/state_zoom.h b/synfig-studio/src/gui/state_zoom.h
deleted file mode 100644 (file)
index e5e7260..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/* === S Y N F I G ========================================================= */
-/*!    \file state_zoom.h
-**     \brief Zoom tool Header
-**
-**     $Id$
-**
-**     \legal
-**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
-**
-**     This package is free software; you can redistribute it and/or
-**     modify it under the terms of the GNU General Public License as
-**     published by the Free Software Foundation; either version 2 of
-**     the License, or (at your option) any later version.
-**
-**     This package is distributed in the hope that it will be useful,
-**     but WITHOUT ANY WARRANTY; without even the implied warranty of
-**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-**     General Public License for more details.
-**     \endlegal
-*/
-/* ========================================================================= */
-
-/* === S T A R T =========================================================== */
-
-#ifndef __SYNFIG_STATE_ZOOM_H
-#define __SYNFIG_STATE_ZOOM_H
-
-/* === H E A D E R S ======================================================= */
-#include "smach.h"
-
-
-/* === M A C R O S ========================================================= */
-
-/* === T Y P E D E F S ===================================================== */
-
-/* === C L A S S E S & S T R U C T S ======================================= */
-
-namespace studio {
-
-class StateZoom_Context;
-
-class StateZoom : public Smach::state<StateZoom_Context>
-{
-public:
-       StateZoom();
-       ~StateZoom();
-}; // END of class StateZoom
-
-extern StateZoom state_zoom;
-
-}; // END of namespace studio
-
-/* === E N D =============================================================== */
-
-#endif
diff --git a/synfig-studio/src/gui/states/state_bline.cpp b/synfig-studio/src/gui/states/state_bline.cpp
new file mode 100644 (file)
index 0000000..ee0ca20
--- /dev/null
@@ -0,0 +1,1414 @@
+/* === S Y N F I G ========================================================= */
+/*!    \file state_bline.cpp
+**     \brief Template File
+**
+**     $Id$
+**
+**     \legal
+**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+**     Copyright (c) 2007, 2008 Chris Moore
+**
+**     This package is free software; you can redistribute it and/or
+**     modify it under the terms of the GNU General Public License as
+**     published by the Free Software Foundation; either version 2 of
+**     the License, or (at your option) any later version.
+**
+**     This package is distributed in the hope that it will be useful,
+**     but WITHOUT ANY WARRANTY; without even the implied warranty of
+**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+**     General Public License for more details.
+**     \endlegal
+*/
+/* ========================================================================= */
+
+/* === H E A D E R S ======================================================= */
+
+#ifdef USING_PCH
+#      include "pch.h"
+#else
+#ifdef HAVE_CONFIG_H
+#      include <config.h>
+#endif
+
+#include <gtkmm/dialog.h>
+#include <gtkmm/entry.h>
+
+#include <synfig/valuenode_dynamiclist.h>
+
+#include "state_bline.h"
+#include "state_normal.h"
+#include "canvasview.h"
+#include "workarea.h"
+#include "app.h"
+#include <synfig/valuenode_bline.h>
+#include <ETL/hermite>
+#include <ETL/calculus>
+#include <utility>
+#include "event_mouse.h"
+#include "event_layerclick.h"
+#include "toolbox.h"
+#include "dialog_tooloptions.h"
+#include <gtkmm/spinbutton.h>
+#include <synfig/transform.h>
+#include <synfigapp/main.h>
+
+#include "general.h"
+
+#endif
+
+/* === U S I N G =========================================================== */
+
+using namespace std;
+using namespace etl;
+using namespace synfig;
+using namespace studio;
+
+/* === M A C R O S ========================================================= */
+
+// if defined, show the first duck as green while drawing
+#define DISTINGUISH_FIRST_DUCK
+
+/* === G L O B A L S ======================================================= */
+
+StateBLine studio::state_bline;
+
+/* === C L A S S E S & S T R U C T S ======================================= */
+
+class studio::StateBLine_Context : public sigc::trackable
+{
+       etl::handle<CanvasView> canvas_view_;
+       CanvasView::IsWorking is_working;
+
+       bool prev_table_status;
+       bool loop_;
+       bool prev_workarea_layer_status_;
+
+       int depth;
+       Canvas::Handle canvas;
+
+       Gtk::Menu menu;
+
+       Duckmatic::Push duckmatic_push;
+
+       etl::handle<Duck> curr_duck;
+
+       etl::handle<Duck> next_duck;
+
+       std::list<synfig::ValueNode_Const::Handle> bline_point_list;
+       synfigapp::Settings& settings;
+
+       bool on_vertex_change(const synfig::Point &point, synfig::ValueNode_Const::Handle value_node);
+       bool on_tangent1_change(const synfig::Point &point, synfig::ValueNode_Const::Handle value_node);
+       bool on_tangent2_change(const synfig::Point &point, synfig::ValueNode_Const::Handle value_node);
+
+
+       void popup_handle_menu(synfig::ValueNode_Const::Handle value_node);
+       void popup_vertex_menu(synfig::ValueNode_Const::Handle value_node);
+       void popup_bezier_menu(float location, synfig::ValueNode_Const::Handle value_node);
+
+       void bline_detach_handle(synfig::ValueNode_Const::Handle value_node);
+       void bline_attach_handle(synfig::ValueNode_Const::Handle value_node);
+       void bline_delete_vertex(synfig::ValueNode_Const::Handle value_node);
+       void bline_insert_vertex(synfig::ValueNode_Const::Handle value_node,float origin=0.5);
+       void loop_bline();
+       void unloop_bline();
+
+       void refresh_ducks(bool x=true);
+
+       Gtk::Table options_table;
+       Gtk::Entry entry_id;
+       Gtk::CheckButton checkbutton_layer_region;
+       Gtk::CheckButton checkbutton_layer_outline;
+       Gtk::CheckButton checkbutton_layer_curve_gradient;
+       Gtk::CheckButton checkbutton_layer_plant;
+       Gtk::CheckButton checkbutton_layer_link_origins;
+       Gtk::CheckButton checkbutton_auto_export;
+       Gtk::Button button_make;
+       Gtk::Button button_clear;
+       Gtk::Adjustment  adj_feather;
+       Gtk::SpinButton  spin_feather;
+
+
+
+public:
+
+       int layers_to_create()const
+       {
+               return
+                       get_layer_region_flag() +
+                       get_layer_outline_flag() +
+                       get_layer_curve_gradient_flag() +
+                       get_layer_plant_flag();
+       }
+
+       void sanity_check()
+       {
+               if(layers_to_create()==0)
+                       set_layer_region_flag(true);
+       }
+
+       bool get_auto_export_flag()const { return checkbutton_auto_export.get_active(); }
+       void set_auto_export_flag(bool x) { return checkbutton_auto_export.set_active(x); }
+
+       bool get_layer_region_flag()const { return checkbutton_layer_region.get_active(); }
+       void set_layer_region_flag(bool x) { return checkbutton_layer_region.set_active(x); }
+
+       bool get_layer_outline_flag()const { return checkbutton_layer_outline.get_active(); }
+       void set_layer_outline_flag(bool x) { return checkbutton_layer_outline.set_active(x); }
+
+       bool get_layer_curve_gradient_flag()const { return checkbutton_layer_curve_gradient.get_active(); }
+       void set_layer_curve_gradient_flag(bool x) { return checkbutton_layer_curve_gradient.set_active(x); }
+
+       bool get_layer_plant_flag()const { return checkbutton_layer_plant.get_active(); }
+       void set_layer_plant_flag(bool x) { return checkbutton_layer_plant.set_active(x); }
+
+       bool get_layer_link_origins_flag()const { return checkbutton_layer_link_origins.get_active(); }
+       void set_layer_link_origins_flag(bool x) { return checkbutton_layer_link_origins.set_active(x); }
+
+       Real get_feather() const { return adj_feather.get_value(); }
+       void set_feather(Real x) { return adj_feather.set_value(x); }
+       synfig::String get_id()const { return entry_id.get_text(); }
+       void set_id(const synfig::String& x) { return entry_id.set_text(x); }
+
+       Smach::event_result event_stop_handler(const Smach::event& x);
+
+       Smach::event_result event_refresh_handler(const Smach::event& x);
+
+       Smach::event_result event_mouse_click_handler(const Smach::event& x);
+       Smach::event_result event_mouse_release_handler(const Smach::event& x);
+       Smach::event_result event_mouse_motion_handler(const Smach::event& x);
+       Smach::event_result event_refresh_tool_options(const Smach::event& x);
+
+       Smach::event_result event_hijack(const Smach::event& /*x*/) { return Smach::RESULT_ACCEPT; }
+
+       void refresh_tool_options();
+
+       StateBLine_Context(CanvasView* canvas_view);
+
+       ~StateBLine_Context();
+
+       const etl::handle<CanvasView>& get_canvas_view()const{return canvas_view_;}
+       etl::handle<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view_->canvas_interface();}
+       synfig::Canvas::Handle get_canvas()const{return canvas_view_->get_canvas();}
+       WorkArea * get_work_area()const{return canvas_view_->get_work_area();}
+       const synfig::TransformStack& get_transform_stack()const { return canvas_view_->get_curr_transform_stack(); }
+
+       void load_settings();
+       void save_settings();
+       void reset();
+       void increment_id();
+       //void on_user_click(synfig::Point point);
+
+       bool run_();
+       bool run();
+
+       bool egress_on_selection_change;
+       Smach::event_result event_layer_selection_changed_handler(const Smach::event& /*x*/)
+       {
+               if(egress_on_selection_change)
+                       throw &state_normal; //throw Smach::egress_exception();
+               return Smach::RESULT_OK;
+       }
+
+};     // END of class StateBLine_Context
+
+
+/* === M E T H O D S ======================================================= */
+
+StateBLine::StateBLine():
+       Smach::state<StateBLine_Context>("bline")
+{
+       insert(event_def(EVENT_LAYER_SELECTION_CHANGED,         &StateBLine_Context::event_layer_selection_changed_handler));
+       insert(event_def(EVENT_STOP,                                            &StateBLine_Context::event_stop_handler));
+       insert(event_def(EVENT_REFRESH,                                         &StateBLine_Context::event_refresh_handler));
+       insert(event_def(EVENT_REFRESH_DUCKS,                           &StateBLine_Context::event_hijack));
+       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,      &StateBLine_Context::event_mouse_click_handler));
+       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_UP,        &StateBLine_Context::event_mouse_release_handler));
+       insert(event_def(EVENT_WORKAREA_MOUSE_MOTION,           &StateBLine_Context::event_mouse_motion_handler));
+       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DRAG,      &StateBLine_Context::event_mouse_motion_handler));
+       insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,            &StateBLine_Context::event_refresh_tool_options));
+}
+
+StateBLine::~StateBLine()
+{
+}
+
+void
+StateBLine_Context::load_settings()
+{
+       String value;
+
+       if(settings.get_value("bline.layer_region",value) && value=="0")
+               set_layer_region_flag(false);
+       else
+               set_layer_region_flag(true);
+
+       if(settings.get_value("bline.layer_outline",value) && value=="0")
+               set_layer_outline_flag(false);
+       else
+               set_layer_outline_flag(true);
+
+       if(settings.get_value("bline.layer_curve_gradient",value) && value=="1")
+               set_layer_curve_gradient_flag(true);
+       else
+               set_layer_curve_gradient_flag(false);
+
+       if(settings.get_value("bline.layer_plant",value) && value=="1")
+               set_layer_plant_flag(true);
+       else
+               set_layer_plant_flag(false);
+
+       if(settings.get_value("bline.layer_link_origins",value) && value=="0")
+               set_layer_link_origins_flag(false);
+       else
+               set_layer_link_origins_flag(true);
+
+       if(settings.get_value("bline.auto_export",value) && value=="1")
+               set_auto_export_flag(true);
+       else
+               set_auto_export_flag(false);
+
+       if(settings.get_value("bline.id",value))
+               set_id(value);
+       else
+               set_id("NewBLine");
+
+       if(settings.get_value("bline.feather",value))
+       {
+               Real n = atof(value.c_str());
+               set_feather(n);
+       }
+
+       sanity_check();
+}
+
+void
+StateBLine_Context::save_settings()
+{
+       sanity_check();
+       settings.set_value("bline.layer_outline",get_layer_outline_flag()?"1":"0");
+       settings.set_value("bline.layer_region",get_layer_region_flag()?"1":"0");
+       settings.set_value("bline.layer_curve_gradient",get_layer_curve_gradient_flag()?"1":"0");
+       settings.set_value("bline.layer_plant",get_layer_plant_flag()?"1":"0");
+       settings.set_value("bline.layer_link_origins",get_layer_link_origins_flag()?"1":"0");
+       settings.set_value("bline.auto_export",get_auto_export_flag()?"1":"0");
+       settings.set_value("bline.id",get_id().c_str());
+       settings.set_value("bline.feather",strprintf("%f",get_feather()));
+}
+
+void
+StateBLine_Context::reset()
+{
+       loop_=false;
+       bline_point_list.clear();
+       refresh_ducks();
+}
+
+void
+StateBLine_Context::increment_id()
+{
+       String id(get_id());
+       int number=1;
+       int digits=0;
+
+       if(id.empty())
+               id="NewBLine";
+
+       // If there is a number
+       // already at the end of the
+       // id, then remove it.
+       if(id[id.size()-1]<='9' && id[id.size()-1]>='0')
+       {
+               // figure out how many digits it is
+               for (digits = 0;
+                        (int)id.size()-1 >= digits && id[id.size()-1-digits] <= '9' && id[id.size()-1-digits] >= '0';
+                        digits++)
+                       ;
+
+               String str_number;
+               str_number=String(id,id.size()-digits,id.size());
+               id=String(id,0,id.size()-digits);
+               // synfig::info("---------------- \"%s\"",str_number.c_str());
+
+               number=atoi(str_number.c_str());
+       }
+       else
+       {
+               number=1;
+               digits=3;
+       }
+
+       number++;
+
+       // Add the number back onto the id
+       {
+               const String format(strprintf("%%0%dd",digits));
+               id+=strprintf(format.c_str(),number);
+       }
+
+       // Set the ID
+       set_id(id);
+}
+
+
+StateBLine_Context::StateBLine_Context(CanvasView* canvas_view):
+       canvas_view_(canvas_view),
+       is_working(*canvas_view),
+       loop_(false),
+       prev_workarea_layer_status_(get_work_area()->get_allow_layer_clicks()),
+       duckmatic_push(get_work_area()),
+       settings(synfigapp::Main::get_selected_input_device()->settings()),
+       entry_id(),
+       checkbutton_layer_region(_("Create Region BLine")),
+       checkbutton_layer_outline(_("Create Outline BLine")),
+       checkbutton_layer_curve_gradient(_("Create Curve Gradient BLine")),
+       checkbutton_layer_plant(_("Create Plant BLine")),
+       checkbutton_layer_link_origins(_("Link Origins")),
+       checkbutton_auto_export(_("Auto Export")),
+       button_make(_("Make")),
+       button_clear(_("Clear")),
+       adj_feather(0,0,10000,0.01,0.1),
+       spin_feather(adj_feather,0.01,4)
+{
+       depth=-1;
+       egress_on_selection_change=true;
+       load_settings();
+
+       // Set up the tool options dialog
+       options_table.attach(*manage(new Gtk::Label(_("BLine Tool"))),  0, 2,  0,  1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(entry_id,                                                                  0, 2,  1,  2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(checkbutton_layer_outline,                                 0, 2,  2,  3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(checkbutton_layer_region,                                  0, 2,  3,  4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(checkbutton_layer_plant,                                   0, 2,  4,  5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(checkbutton_layer_curve_gradient,                  0, 2,  5,  6, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(checkbutton_layer_link_origins,                    0, 2,  6,  7, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(checkbutton_auto_export,                                   0, 2,  7,  8, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(*manage(new Gtk::Label(_("Feather"))),     0, 1, 10, 11, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(spin_feather,                                                              1, 2, 10, 11, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       //options_table.attach(button_make, 0, 2, 5, 6, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       //button_make.signal_pressed().connect(sigc::mem_fun(*this,&StateBLine_Context::run));
+       options_table.show_all();
+       refresh_tool_options();
+       App::dialog_tool_options->present();
+
+       // Turn off layer clicking
+       get_work_area()->set_allow_layer_clicks(false);
+
+       // clear out the ducks
+       get_work_area()->clear_ducks();
+
+       // Refresh the work area
+       get_work_area()->queue_draw();
+
+       // Hide the tables if they are showing
+       prev_table_status=get_canvas_view()->tables_are_visible();
+       if(prev_table_status)get_canvas_view()->hide_tables();
+
+       // Disable the time bar
+       get_canvas_view()->set_sensitive_timebar(false);
+
+       // Connect a signal
+       //get_work_area()->signal_user_click().connect(sigc::mem_fun(*this,&studio::StateBLine_Context::on_user_click));
+       get_work_area()->set_cursor(Gdk::CROSSHAIR);
+
+       App::toolbox->refresh();
+}
+
+void
+StateBLine_Context::refresh_tool_options()
+{
+       App::dialog_tool_options->clear();
+       App::dialog_tool_options->set_widget(options_table);
+       App::dialog_tool_options->set_local_name(_("BLine Tool"));
+       App::dialog_tool_options->set_name("bline");
+
+       App::dialog_tool_options->add_button(
+               Gtk::StockID("gtk-execute"),
+               _("Make BLine and/or Region")
+       )->signal_clicked().connect(
+               sigc::hide_return(sigc::mem_fun(
+                       *this,
+                       &StateBLine_Context::run
+               ))
+       );
+
+       App::dialog_tool_options->add_button(
+               Gtk::StockID("gtk-clear"),
+               _("Clear current BLine")
+       )->signal_clicked().connect(
+               sigc::mem_fun(
+                       *this,
+                       &StateBLine_Context::reset
+               )
+       );
+}
+
+Smach::event_result
+StateBLine_Context::event_refresh_tool_options(const Smach::event& /*x*/)
+{
+       refresh_tool_options();
+       return Smach::RESULT_ACCEPT;
+}
+
+StateBLine_Context::~StateBLine_Context()
+{
+       run();
+
+       save_settings();
+       App::dialog_tool_options->clear();
+
+       get_work_area()->reset_cursor();
+
+       // Restore layer clicking
+       get_work_area()->set_allow_layer_clicks(prev_workarea_layer_status_);
+
+       // Enable the time bar
+       get_canvas_view()->set_sensitive_timebar(true);
+
+       // Bring back the tables if they were out before
+       if(prev_table_status)get_canvas_view()->show_tables();
+
+//     get_canvas_view()->get_smach().process_event(EVENT_REFRESH_DUCKS);
+
+       // Refresh the work area
+       get_work_area()->queue_draw();
+
+       App::toolbox->refresh();
+}
+
+Smach::event_result
+StateBLine_Context::event_stop_handler(const Smach::event& /*x*/)
+{
+//     synfig::info("STATE RotoBLine: Received Stop Event");
+//     run();
+       reset();
+//     throw Smach::egress_exception();
+//     get_canvas_view()->get_smach().pop_state();
+       return Smach::RESULT_ACCEPT;
+}
+
+Smach::event_result
+StateBLine_Context::event_refresh_handler(const Smach::event& /*x*/)
+{
+//     synfig::info("STATE RotoBLine: Received Refresh Event");
+       refresh_ducks();
+       return Smach::RESULT_ACCEPT;
+}
+
+bool
+StateBLine_Context::run()
+{
+       sanity_check();
+
+       String err;
+       bool success(false);
+       for(int i=5;i>0 && !success;i--)try
+       {
+               success=run_();
+       }
+       catch(String s)
+       {
+               err=s;
+       }
+       if(!success && !err.empty())
+       {
+               get_canvas_view()->get_ui_interface()->error(err);
+       }
+       return success;
+}
+
+bool
+StateBLine_Context::run_()
+{
+       curr_duck=0;
+       next_duck=0;
+
+       // Now we need to generate it
+
+       if(bline_point_list.empty())
+       {
+               return false;
+       }
+       if(bline_point_list.size()<2)
+       {
+               //get_canvas_view()->get_ui_interface()->error(_("You need at least two (2) points to create a BLine"));
+               return false;
+       }
+
+       do
+       {
+
+               // Create the action group
+               synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("New BLine"));
+
+               std::vector<BLinePoint> new_list;
+               std::list<synfig::ValueNode_Const::Handle>::iterator iter;
+               const synfig::TransformStack& transform(get_transform_stack());
+
+               for(iter=bline_point_list.begin();iter!=bline_point_list.end();++iter)
+               {
+                       BLinePoint bline_point((*iter)->get_value().get(BLinePoint()));
+                       Point new_vertex(transform.unperform(bline_point.get_vertex()));
+
+                       bline_point.set_tangent1(
+                               transform.unperform(
+                                       bline_point.get_tangent1()+bline_point.get_vertex()
+                               ) -new_vertex
+                       );
+
+                       bline_point.set_tangent2(
+                               transform.unperform(
+                                       bline_point.get_tangent2()+bline_point.get_vertex()
+                               ) -new_vertex
+                       );
+
+                       bline_point.set_vertex(new_vertex);
+
+                       new_list.push_back(bline_point);
+               }
+
+               ValueNode_BLine::Handle value_node_bline(ValueNode_BLine::create(new_list));
+               assert(value_node_bline);
+
+               ValueNode_Const::Handle value_node_origin(ValueNode_Const::create(Vector()));
+               assert(value_node_origin);
+
+               // Set the looping flag
+               value_node_bline->set_loop(loop_);
+
+               // Add the BLine to the canvas
+               if(get_auto_export_flag() && !get_canvas_interface()->add_value_node(value_node_bline,get_id()))
+               {
+                       //get_canvas_view()->get_ui_interface()->error(_("Unable to add value node"));
+                       group.cancel();
+                       increment_id();
+                       throw String(_("Unable to add value node"));
+                       return false;
+               }
+
+               Layer::Handle layer;
+
+               // we are temporarily using the layer to hold something
+               layer=get_canvas_view()->get_selection_manager()->get_selected_layer();
+
+               if(layer)
+               {
+                       if(depth<0)
+                               depth=layer->get_depth();
+                       if(!canvas)
+                               canvas=layer->get_canvas();
+               }
+               else
+                       depth=0;
+
+               if(!canvas)
+                       canvas=get_canvas_view()->get_canvas();
+
+               value_node_bline->set_member_canvas(canvas);
+
+               synfigapp::SelectionManager::LayerList layer_selection;
+               if (!getenv("SYNFIG_TOOLS_CLEAR_SELECTION"))
+                       layer_selection = get_canvas_view()->get_selection_manager()->get_selected_layers();
+
+               // count how many layers we're going to be creating
+               int layers_to_create = this->layers_to_create();
+
+               ///////////////////////////////////////////////////////////////////////////
+               //   C U R V E   G R A D I E N T
+               ///////////////////////////////////////////////////////////////////////////
+
+               if(get_layer_curve_gradient_flag())
+               {
+                       synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
+
+                       Layer::Handle layer(get_canvas_interface()->add_layer_to("curve_gradient",canvas,depth));
+                       if (!layer)
+                       {
+                               group.cancel();
+                               throw String(_("Unable to create layer"));
+                       }
+                       layer_selection.push_back(layer);
+                       layer->set_description(get_id()+_(" Gradient"));
+                       get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
+
+                       {
+                               synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
+                               assert(action);
+
+                               action->set_param("canvas",get_canvas());
+                               action->set_param("canvas_interface",get_canvas_interface());
+                               action->set_param("layer",layer);
+                               if(!action->set_param("param",String("bline")))
+                                       synfig::error("LayerParamConnect didn't like \"param\"");
+                               if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
+                                       synfig::error("LayerParamConnect didn't like \"value_node\"");
+
+                               if(!get_canvas_interface()->get_instance()->perform_action(action))
+                               {
+                                       //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
+                                       group.cancel();
+                                       throw String(_("Unable to create Gradient layer"));
+                                       return false;
+                               }
+                       }
+
+                       // only link the curve gradient's origin parameter if the option is selected and we're creating more than one layer
+                       if (get_layer_link_origins_flag() && layers_to_create > 1)
+                       {
+                               synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
+                               assert(action);
+
+                               action->set_param("canvas",get_canvas());
+                               action->set_param("canvas_interface",get_canvas_interface());
+                               action->set_param("layer",layer);
+                               if(!action->set_param("param",String("origin")))
+                                       synfig::error("LayerParamConnect didn't like \"param\"");
+                               if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
+                                       synfig::error("LayerParamConnect didn't like \"value_node\"");
+
+                               if(!get_canvas_interface()->get_instance()->perform_action(action))
+                               {
+                                       //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
+                                       group.cancel();
+                                       throw String(_("Unable to create Gradient layer"));
+                                       return false;
+                               }
+                       }
+               }
+
+               ///////////////////////////////////////////////////////////////////////////
+               //   P L A N T
+               ///////////////////////////////////////////////////////////////////////////
+
+               if(get_layer_plant_flag())
+               {
+                       synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
+
+                       Layer::Handle layer(get_canvas_interface()->add_layer_to("plant",canvas,depth));
+                       if (!layer)
+                       {
+                               group.cancel();
+                               throw String(_("Unable to create layer"));
+                       }
+                       layer_selection.push_back(layer);
+                       layer->set_description(get_id()+_(" Plant"));
+                       get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
+
+                       {
+                               synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
+                               assert(action);
+
+                               action->set_param("canvas",get_canvas());
+                               action->set_param("canvas_interface",get_canvas_interface());
+                               action->set_param("layer",layer);
+                               if(!action->set_param("param",String("bline")))
+                                       synfig::error("LayerParamConnect didn't like \"param\"");
+                               if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
+                                       synfig::error("LayerParamConnect didn't like \"value_node\"");
+
+                               if(!get_canvas_interface()->get_instance()->perform_action(action))
+                               {
+                                       //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
+                                       group.cancel();
+                                       throw String(_("Unable to create Plant layer"));
+                                       return false;
+                               }
+                       }
+
+                       // only link the plant's origin parameter if the option is selected and we're creating more than one layer
+                       if (get_layer_link_origins_flag() && layers_to_create > 1)
+                       {
+                               synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
+                               assert(action);
+
+                               action->set_param("canvas",get_canvas());
+                               action->set_param("canvas_interface",get_canvas_interface());
+                               action->set_param("layer",layer);
+                               if(!action->set_param("param",String("origin")))
+                                       synfig::error("LayerParamConnect didn't like \"param\"");
+                               if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
+                                       synfig::error("LayerParamConnect didn't like \"value_node\"");
+
+                               if(!get_canvas_interface()->get_instance()->perform_action(action))
+                               {
+                                       //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
+                                       group.cancel();
+                                       throw String(_("Unable to create Plant layer"));
+                                       return false;
+                               }
+                       }
+               }
+
+               ///////////////////////////////////////////////////////////////////////////
+               //   R E G I O N
+               ///////////////////////////////////////////////////////////////////////////
+
+               if(get_layer_region_flag())
+               {
+                       synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
+
+                       Layer::Handle layer(get_canvas_interface()->add_layer_to("region",canvas,depth));
+                       if (!layer)
+                       {
+                               group.cancel();
+                               throw String(_("Unable to create layer"));
+                       }
+                       layer_selection.push_back(layer);
+                       layer->set_description(get_id()+_(" Region"));
+                       get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
+
+                       if(get_feather())
+                       {
+                               layer->set_param("feather",get_feather());
+                               get_canvas_interface()->signal_layer_param_changed()(layer,"feather");
+                       }
+
+                       // I don't know if it's safe to reuse the same LayerParamConnect action, so I'm
+                       // using 2 separate ones.
+                       {
+                               synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
+                               assert(action);
+
+                               action->set_param("canvas",get_canvas());
+                               action->set_param("canvas_interface",get_canvas_interface());
+                               action->set_param("layer",layer);
+                               if(!action->set_param("param",String("bline")))
+                                       synfig::error("LayerParamConnect didn't like \"param\"");
+                               if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
+                                       synfig::error("LayerParamConnect didn't like \"value_node\"");
+
+                               if(!get_canvas_interface()->get_instance()->perform_action(action))
+                               {
+                                       //get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer"));
+                                       group.cancel();
+                                       throw String(_("Unable to create Region layer"));
+                                       return false;
+                               }
+                       }
+
+                       // only link the region's origin parameter if the option is selected and we're creating more than one layer
+                       if (get_layer_link_origins_flag() && layers_to_create > 1)
+                       {
+                               synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
+                               assert(action);
+
+                               action->set_param("canvas",get_canvas());
+                               action->set_param("canvas_interface",get_canvas_interface());
+                               action->set_param("layer",layer);
+                               if(!action->set_param("param",String("origin")))
+                                       synfig::error("LayerParamConnect didn't like \"param\"");
+                               if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
+                                       synfig::error("LayerParamConnect didn't like \"value_node\"");
+
+                               if(!get_canvas_interface()->get_instance()->perform_action(action))
+                               {
+                                       //get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer"));
+                                       group.cancel();
+                                       throw String(_("Unable to create Region layer"));
+                                       return false;
+                               }
+                       }
+               }
+
+               ///////////////////////////////////////////////////////////////////////////
+               //   O U T L I N E
+               ///////////////////////////////////////////////////////////////////////////
+
+               if(get_layer_outline_flag())
+               {
+                       synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
+
+                       Layer::Handle layer(get_canvas_interface()->add_layer_to("outline",canvas,depth));
+                       if (!layer)
+                       {
+                               group.cancel();
+                               throw String(_("Unable to create layer"));
+                       }
+                       layer_selection.push_back(layer);
+                       layer->set_description(get_id()+_(" Outline"));
+                       get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
+                       if(get_feather())
+                       {
+                               layer->set_param("feather",get_feather());
+                               get_canvas_interface()->signal_layer_param_changed()(layer,"feather");
+                       }
+
+                       {
+                               synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
+                               assert(action);
+
+                               action->set_param("canvas",get_canvas());
+                               action->set_param("canvas_interface",get_canvas_interface());
+                               action->set_param("layer",layer);
+                               if(!action->set_param("param",String("bline")))
+                                       synfig::error("LayerParamConnect didn't like \"param\"");
+                               if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
+                                       synfig::error("LayerParamConnect didn't like \"value_node\"");
+
+                               if(!get_canvas_interface()->get_instance()->perform_action(action))
+                               {
+                                       //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
+                                       group.cancel();
+                                       throw String(_("Unable to create Outline layer"));
+                                       return false;
+                               }
+                       }
+
+                       // only link the outline's origin parameter if the option is selected and we're creating more than one layer
+                       if (get_layer_link_origins_flag() && layers_to_create > 1)
+                       {
+                               synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
+                               assert(action);
+
+                               action->set_param("canvas",get_canvas());
+                               action->set_param("canvas_interface",get_canvas_interface());
+                               action->set_param("layer",layer);
+                               if(!action->set_param("param",String("origin")))
+                                       synfig::error("LayerParamConnect didn't like \"param\"");
+                               if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
+                                       synfig::error("LayerParamConnect didn't like \"value_node\"");
+
+                               if(!get_canvas_interface()->get_instance()->perform_action(action))
+                               {
+                                       //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
+                                       group.cancel();
+                                       throw String(_("Unable to create Outline layer"));
+                                       return false;
+                               }
+                       }
+               }
+
+               egress_on_selection_change=false;
+               get_canvas_interface()->get_selection_manager()->clear_selected_layers();
+               get_canvas_interface()->get_selection_manager()->set_selected_layers(layer_selection);
+               egress_on_selection_change=true;
+
+               //if(finish_bline_dialog.get_region_flag() || finish_bline_dialog.get_bline_flag())
+               //      get_canvas_interface()->signal_dirty_preview()();
+
+       } while(0);
+
+       reset();
+       increment_id();
+       return true;
+}
+
+Smach::event_result
+StateBLine_Context::event_mouse_motion_handler(const Smach::event& x)
+{
+       const EventMouse& event(*reinterpret_cast<const EventMouse*>(&x));
+
+       if(curr_duck)
+       {
+               //synfig::info("Moved Duck");
+               Point p(get_work_area()->snap_point_to_grid(event.pos));
+               curr_duck->set_trans_point(p);
+               if(next_duck)
+                       next_duck->set_trans_point(p);
+               get_work_area()->queue_draw();
+               return Smach::RESULT_ACCEPT;
+       }
+
+       return Smach::RESULT_OK;
+}
+
+Smach::event_result
+StateBLine_Context::event_mouse_release_handler(const Smach::event& /*x*/)
+{
+       if(curr_duck)
+       {
+               //synfig::info("Released current duck");
+               curr_duck->signal_edited()(curr_duck->get_point());
+               if(next_duck)
+               {
+                       //synfig::info("grabbing next duck");
+                       curr_duck=next_duck;
+                       next_duck=0;
+               }
+               return Smach::RESULT_ACCEPT;
+       }
+       return Smach::RESULT_OK;
+}
+
+Smach::event_result
+StateBLine_Context::event_mouse_click_handler(const Smach::event& x)
+{
+       // synfig::info("STATE BLINE: Received mouse button down Event");
+       const EventMouse& event(*reinterpret_cast<const EventMouse*>(&x));
+       switch(event.button)
+       {
+       case BUTTON_LEFT:
+               {
+                       // If we are already looped up, then don't try to add anything else
+                       if(loop_)
+                               return Smach::RESULT_OK;
+
+                       BLinePoint bline_point;
+
+                       bline_point.set_vertex(get_work_area()->snap_point_to_grid(event.pos));
+                       //bline_point.set_width(synfigapp::Main::get_bline_width());
+                       bline_point.set_width(1.0f);
+                       bline_point.set_origin(0.5f);
+                       bline_point.set_split_tangent_flag(false);
+                       bline_point.set_tangent1(Vector(0,0));
+
+                       // set the tangent
+                       /*
+                       if(bline_point_list.empty())
+                       {
+                               bline_point.set_tangent1(Vector(1,1));
+                       }
+                       else
+                       {
+                               const Vector t(event.pos-bline_point_list.back()->get_value().get(BLinePoint()).get_vertex());
+                               bline_point.set_tangent1(t);
+                       }
+
+                       if(bline_point_list.size()>1)
+                       {
+                               std::list<synfig::ValueNode_Const::Handle>::iterator iter;
+                               iter=bline_point_list.end();
+                               iter--;iter--;
+                               BLinePoint prev(bline_point_list.back()->get_value().get(BLinePoint()));
+                               prev.set_tangent1(event.pos-(*iter)->get_value().get(BLinePoint()).get_vertex());
+                               bline_point_list.back()->set_value(prev);
+                       };
+                       */
+
+                       bline_point_list.push_back(ValueNode_Const::create(bline_point));
+
+                       refresh_ducks();
+                       return Smach::RESULT_ACCEPT;
+               }
+
+       default:
+               return Smach::RESULT_OK;
+       }
+}
+
+void
+StateBLine_Context::refresh_ducks(bool button_down)
+{
+       get_work_area()->clear_ducks();
+       get_work_area()->queue_draw();
+
+       if(bline_point_list.empty())
+               return;
+
+       list<ValueNode_Const::Handle>::iterator iter;
+
+       handle<WorkArea::Bezier> bezier;
+       handle<WorkArea::Duck> duck,tduck;
+       BLinePoint bline_point;
+
+       for(iter=bline_point_list.begin();iter!=bline_point_list.end();++iter)
+       {
+               ValueNode_Const::Handle value_node(*iter);
+               bline_point=(value_node->get_value().get(BLinePoint()));
+               assert(value_node);
+
+
+               // First add the duck associated with this vertex
+               duck=new WorkArea::Duck(bline_point.get_vertex());
+               duck->set_editable(true);
+#ifdef DISTINGUISH_FIRST_DUCK
+               if (iter!=bline_point_list.begin())
+                       duck->set_type(Duck::TYPE_VERTEX);
+#else
+               duck->set_type(Duck::TYPE_VERTEX);
+#endif
+               duck->set_name(strprintf("%x-vertex",value_node.get()));
+               duck->signal_edited().connect(
+                       sigc::bind(sigc::mem_fun(*this,&studio::StateBLine_Context::on_vertex_change),value_node)
+               );
+               duck->signal_user_click(2).connect(
+                       sigc::bind(sigc::mem_fun(*this,&studio::StateBLine_Context::popup_vertex_menu),value_node)
+               );
+               duck->set_guid(value_node->get_guid()^synfig::GUID::hasher(0));
+
+               get_work_area()->add_duck(duck);
+
+               // Add the tangent1 duck
+               tduck=new WorkArea::Duck(bline_point.get_tangent1());
+               tduck->set_editable(true);
+               tduck->set_name(strprintf("%x-tangent1",value_node.get()));
+               tduck->set_origin(duck);
+               tduck->set_scalar(-0.33333333333333333);
+               tduck->set_tangent(true);
+               tduck->set_guid(value_node->get_guid()^synfig::GUID::hasher(3));
+               tduck->signal_edited().connect(
+                       sigc::bind(sigc::mem_fun(*this,&studio::StateBLine_Context::on_tangent1_change),value_node)
+               );
+               tduck->signal_user_click(2).connect(
+                       sigc::bind(sigc::mem_fun(*this,&studio::StateBLine_Context::popup_handle_menu),value_node)
+               );
+
+               // See if we need to add that duck to the previous bezier
+               if(bezier)
+               {
+                       get_work_area()->add_duck(tduck);
+                       bezier->p2=duck;
+                       bezier->c2=tduck;
+
+                       bezier->signal_user_click(2).connect(
+                               sigc::bind(
+                                       sigc::mem_fun(
+                                               *this,
+                                               &studio::StateBLine_Context::popup_bezier_menu
+                                       ),
+                                       value_node
+                               )
+                       );
+
+                       //get_work_area()->add_duck(bezier->c1);
+                       //get_work_area()->add_duck(bezier->c2);
+                       get_work_area()->add_bezier(bezier);
+
+                       bezier=0;
+               }
+
+               // Now we see if we need to create a bezier
+               list<ValueNode_Const::Handle>::iterator next(iter);
+               next++;
+
+               // If our next iterator is the end, then we don't need
+               // to add a bezier.
+               //if(next==bline_point_list.end() && !loop_)
+               //      continue;
+
+               bezier=new WorkArea::Bezier();
+
+               // Add the tangent2 duck
+               tduck=new WorkArea::Duck(bline_point.get_tangent2());
+               tduck->set_editable(true);
+               tduck->set_origin(duck);
+               tduck->set_scalar(0.33333333333333333);
+               tduck->set_tangent(true);
+               if(bline_point.get_split_tangent_flag())
+               {
+                       tduck->set_name(strprintf("%x-tangent2",value_node.get()));
+                       tduck->signal_edited().connect(
+                               sigc::bind(sigc::mem_fun(*this,&studio::StateBLine_Context::on_tangent2_change),value_node)
+                       );
+               }
+               else
+               {
+                       tduck->set_name(strprintf("%x-tangent1",value_node.get()));
+                       tduck->signal_edited().connect(
+                               sigc::bind(sigc::mem_fun(*this,&studio::StateBLine_Context::on_tangent1_change),value_node)
+                       );
+               }
+               tduck->set_guid(value_node->get_guid()^synfig::GUID::hasher(4));
+               tduck->signal_user_click(2).connect(
+                       sigc::bind(sigc::mem_fun(*this,&studio::StateBLine_Context::popup_handle_menu),value_node)
+               );
+
+               // Setup the next bezier
+               bezier->p1=duck;
+               bezier->c1=tduck;
+
+               get_work_area()->add_duck(tduck);
+               curr_duck=tduck;
+       }
+
+       // Add the loop, if requested
+       if(bezier && loop_)
+       {
+               curr_duck=0;
+               BLinePoint bline_point(bline_point_list.front()->get_value().get(BLinePoint()));
+
+               duck=new WorkArea::Duck(bline_point.get_vertex());
+               duck->set_editable(true);
+#ifndef DISTINGUISH_FIRST_DUCK
+               duck->set_type(Duck::TYPE_VERTEX);
+#endif
+               duck->set_name(strprintf("%x-vertex",bline_point_list.front().get()));
+               duck->signal_edited().connect(
+                       sigc::bind(sigc::mem_fun(*this,&studio::StateBLine_Context::on_vertex_change),bline_point_list.front())
+               );
+               duck->signal_user_click(2).connect(
+                       sigc::bind(sigc::mem_fun(*this,&studio::StateBLine_Context::popup_vertex_menu),bline_point_list.front())
+               );
+               get_work_area()->add_duck(duck);
+
+               // Add the tangent1 duck
+               tduck=new WorkArea::Duck(bline_point.get_tangent1());
+               tduck->set_editable(true);
+               tduck->set_name(strprintf("%x-tangent1",bline_point_list.front().get()));
+               tduck->set_origin(duck);
+               tduck->set_scalar(-0.33333333333333333);
+               tduck->set_tangent(true);
+               tduck->signal_edited().connect(
+                       sigc::bind(sigc::mem_fun(*this,&studio::StateBLine_Context::on_tangent1_change),bline_point_list.front())
+               );
+               tduck->signal_user_click(2).connect(
+                       sigc::bind(sigc::mem_fun(*this,&studio::StateBLine_Context::popup_handle_menu),bline_point_list.front())
+               );
+               get_work_area()->add_duck(tduck);
+
+               bezier->p2=duck;
+               bezier->c2=tduck;
+
+               bezier->signal_user_click(2).connect(
+                       sigc::bind(
+                               sigc::mem_fun(
+                                       *this,
+                                       &studio::StateBLine_Context::popup_bezier_menu
+                               ),
+                               bline_point_list.front()
+                       )
+               );
+
+               //get_work_area()->add_duck(bezier->c1);
+               get_work_area()->add_bezier(bezier);
+       }
+       if(bezier && !loop_)
+       {
+               duck=new WorkArea::Duck(bline_point.get_vertex());
+               duck->set_ignore(true);
+               duck->set_name("temp");
+
+               // Add the tangent1 duck
+               tduck=new WorkArea::Duck(Vector(0,0));
+               tduck->set_ignore(true);
+               tduck->set_name("ttemp");
+               tduck->set_origin(duck);
+               tduck->set_scalar(-0.33333333333333333);
+
+               tduck->set_tangent(true);
+               bezier->p2=duck;
+               bezier->c2=tduck;
+
+               get_work_area()->add_duck(bezier->p2);
+               //get_work_area()->add_duck(bezier->c2);
+               get_work_area()->add_bezier(bezier);
+
+               duck->set_guid(synfig::GUID());
+               tduck->set_guid(synfig::GUID());
+
+               next_duck=duck;
+       }
+
+       if(!button_down)
+       {
+               if(curr_duck)
+               {
+                       if(next_duck)
+                       {
+                               curr_duck=next_duck;
+                               next_duck=0;
+                       }
+               }
+       }
+       get_work_area()->queue_draw();
+}
+
+
+bool
+StateBLine_Context::on_vertex_change(const synfig::Point &point, synfig::ValueNode_Const::Handle value_node)
+{
+       BLinePoint bline_point(value_node->get_value().get(BLinePoint()));
+       bline_point.set_vertex(point);
+       value_node->set_value(bline_point);
+       //refresh_ducks();
+       return true;
+}
+
+bool
+StateBLine_Context::on_tangent1_change(const synfig::Point &point, synfig::ValueNode_Const::Handle value_node)
+{
+       BLinePoint bline_point(value_node->get_value().get(BLinePoint()));
+       bline_point.set_tangent1(point);
+       value_node->set_value(bline_point);
+       //refresh_ducks();
+       return true;
+}
+
+bool
+StateBLine_Context::on_tangent2_change(const synfig::Point &point, synfig::ValueNode_Const::Handle value_node)
+{
+       BLinePoint bline_point(value_node->get_value().get(BLinePoint()));
+       bline_point.set_tangent2(point);
+       value_node->set_value(bline_point);
+       //refresh_ducks();
+       return true;
+}
+
+void
+StateBLine_Context::loop_bline()
+{
+       loop_=true;
+
+       refresh_ducks(false);
+}
+
+void
+StateBLine_Context::unloop_bline()
+{
+       loop_=false;
+
+       refresh_ducks(false);
+}
+
+void
+StateBLine_Context::popup_vertex_menu(synfig::ValueNode_Const::Handle value_node)
+{
+       menu.items().clear();
+
+       if(loop_)
+       {
+               menu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("Unloop BLine"),
+                               sigc::mem_fun(*this,&studio::StateBLine_Context::unloop_bline)
+               ));
+       } else {
+               menu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("Loop BLine"),
+                               sigc::mem_fun(*this,&studio::StateBLine_Context::loop_bline)
+               ));
+       }
+
+       menu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("Delete Vertex"),
+               sigc::bind(
+                       sigc::mem_fun(*this,&studio::StateBLine_Context::bline_delete_vertex),
+                       value_node
+               )
+       ));
+
+       menu.popup(0,0);
+}
+
+void
+StateBLine_Context::popup_bezier_menu(float location, synfig::ValueNode_Const::Handle value_node)
+{
+       menu.items().clear();
+
+       menu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("Insert Vertex"),
+               sigc::bind(
+                       sigc::bind(
+                               sigc::mem_fun(*this,&studio::StateBLine_Context::bline_insert_vertex),
+                               location
+                       ),
+                       value_node
+               )
+       ));
+
+       menu.popup(0,0);
+}
+
+void
+StateBLine_Context::bline_insert_vertex(synfig::ValueNode_Const::Handle value_node, float origin)
+{
+       list<ValueNode_Const::Handle>::iterator iter;
+
+       for(iter=bline_point_list.begin();iter!=bline_point_list.end();++iter)
+               if(*iter==value_node)
+               {
+                       BLinePoint bline_point;
+                       BLinePoint next_bline_point((*iter)->get_value().get(BLinePoint()));
+                       BLinePoint prev_bline_point;
+
+                       list<ValueNode_Const::Handle>::iterator prev(iter);
+                       if(iter==bline_point_list.begin())
+                       {
+                               assert(loop_);
+                               prev = bline_point_list.end();
+                       }
+                       prev--;
+
+                       prev_bline_point=(*prev)->get_value().get(BLinePoint());
+
+                       etl::hermite<Vector> curve(prev_bline_point.get_vertex(),
+                                                                          next_bline_point.get_vertex(),
+                                                                          prev_bline_point.get_tangent2(),
+                                                                          next_bline_point.get_tangent1());
+                       etl::derivative< etl::hermite<Vector> > deriv(curve);
+
+                       bline_point.set_vertex(curve(origin));
+                       bline_point.set_width((next_bline_point.get_width()-prev_bline_point.get_width())*origin+prev_bline_point.get_width());
+                       bline_point.set_tangent1(deriv(origin)*std::min(1.0f-origin,origin));
+                       bline_point.set_tangent2(bline_point.get_tangent1());
+                       bline_point.set_split_tangent_flag(false);
+                       bline_point.set_origin(origin);
+
+/*
+                       bline_point.set_vertex((next_bline_point.get_vertex()+prev_bline_point.get_vertex())*0.5);
+                       bline_point.set_width((next_bline_point.get_width()+prev_bline_point.get_width())*0.5);
+                       bline_point.set_origin(origin);
+                       bline_point.set_split_tangent_flag(false);
+                       bline_point.set_tangent1((next_bline_point.get_vertex()-prev_bline_point.get_vertex())*0.5);
+*/
+
+                       bline_point_list.insert(iter,ValueNode_Const::create(bline_point));
+                       break;
+               }
+
+       if(iter==bline_point_list.end())
+       {
+               get_canvas_view()->get_ui_interface()->error(_("Unable to find where to insert vertex, internal error, please report this bug"));
+       }
+
+       refresh_ducks(false);
+}
+
+void
+StateBLine_Context::bline_delete_vertex(synfig::ValueNode_Const::Handle value_node)
+{
+       list<ValueNode_Const::Handle>::iterator iter;
+
+       for(iter=bline_point_list.begin();iter!=bline_point_list.end();++iter)
+               if(*iter==value_node)
+               {
+                       bline_point_list.erase(iter);
+                       break;
+               }
+       if(iter==bline_point_list.end())
+       {
+               get_canvas_view()->get_ui_interface()->error(_("Unable to remove vertex, internal error, please report this bug"));
+       }
+
+       refresh_ducks(false);
+}
+
+void
+StateBLine_Context::popup_handle_menu(synfig::ValueNode_Const::Handle value_node)
+{
+       menu.items().clear();
+
+       BLinePoint bline_point(value_node->get_value().get(BLinePoint()));
+
+       if(bline_point.get_split_tangent_flag())
+               menu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("Merge Tangents"),
+                       sigc::bind(
+                               sigc::mem_fun(*this,&studio::StateBLine_Context::bline_attach_handle),
+                               value_node
+                       )
+               ));
+       else
+               menu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("Split Tangents"),
+                       sigc::bind(
+                               sigc::mem_fun(*this,&studio::StateBLine_Context::bline_detach_handle),
+                               value_node
+                       )
+               ));
+
+       menu.popup(0,0);
+}
+
+void
+StateBLine_Context::bline_detach_handle(synfig::ValueNode_Const::Handle value_node)
+{
+       BLinePoint bline_point(value_node->get_value().get(BLinePoint()));
+       bline_point.set_split_tangent_flag(true);
+       bline_point.set_tangent2(bline_point.get_tangent1());
+       value_node->set_value(bline_point);
+       refresh_ducks(false);
+}
+
+void
+StateBLine_Context::bline_attach_handle(synfig::ValueNode_Const::Handle value_node)
+{
+       BLinePoint bline_point(value_node->get_value().get(BLinePoint()));
+       bline_point.set_tangent1((bline_point.get_tangent1()+bline_point.get_tangent2())*0.5);
+       bline_point.set_split_tangent_flag(false);
+       value_node->set_value(bline_point);
+       refresh_ducks(false);
+}
diff --git a/synfig-studio/src/gui/states/state_bline.h b/synfig-studio/src/gui/states/state_bline.h
new file mode 100644 (file)
index 0000000..0f3ce0d
--- /dev/null
@@ -0,0 +1,55 @@
+/* === S Y N F I G ========================================================= */
+/*!    \file state_bline.h
+**     \brief Template Header
+**
+**     $Id$
+**
+**     \legal
+**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+**
+**     This package is free software; you can redistribute it and/or
+**     modify it under the terms of the GNU General Public License as
+**     published by the Free Software Foundation; either version 2 of
+**     the License, or (at your option) any later version.
+**
+**     This package is distributed in the hope that it will be useful,
+**     but WITHOUT ANY WARRANTY; without even the implied warranty of
+**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+**     General Public License for more details.
+**     \endlegal
+*/
+/* ========================================================================= */
+
+/* === S T A R T =========================================================== */
+
+#ifndef __SYNFIG_STUDIO_ROTOSCOPE_BLINE_H
+#define __SYNFIG_STUDIO_ROTOSCOPE_BLINE_H
+
+/* === H E A D E R S ======================================================= */
+
+#include "smach.h"
+
+/* === M A C R O S ========================================================= */
+
+/* === T Y P E D E F S ===================================================== */
+
+/* === C L A S S E S & S T R U C T S ======================================= */
+
+namespace studio {
+
+class StateBLine_Context;
+
+class StateBLine : public Smach::state<StateBLine_Context>
+{
+public:
+       StateBLine();
+       ~StateBLine();
+}; // END of class StateBLine
+
+extern StateBLine state_bline;
+
+}; // END of namespace studio
+
+/* === E N D =============================================================== */
+
+#endif
diff --git a/synfig-studio/src/gui/states/state_circle.cpp b/synfig-studio/src/gui/states/state_circle.cpp
new file mode 100644 (file)
index 0000000..5ef611b
--- /dev/null
@@ -0,0 +1,1066 @@
+/* === S Y N F I G ========================================================= */
+/*!    \file state_circle.cpp
+**     \brief Template File
+**
+**     $Id$
+**
+**     \legal
+**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+**     Copyright (c) 2008 Chris Moore
+**
+**     This package is free software; you can redistribute it and/or
+**     modify it under the terms of the GNU General Public License as
+**     published by the Free Software Foundation; either version 2 of
+**     the License, or (at your option) any later version.
+**
+**     This package is distributed in the hope that it will be useful,
+**     but WITHOUT ANY WARRANTY; without even the implied warranty of
+**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+**     General Public License for more details.
+**     \endlegal
+*/
+/* ========================================================================= */
+
+/* === H E A D E R S ======================================================= */
+
+#ifdef USING_PCH
+#      include "pch.h"
+#else
+#ifdef HAVE_CONFIG_H
+#      include <config.h>
+#endif
+
+#include <gtkmm/dialog.h>
+#include <gtkmm/entry.h>
+
+#include <synfig/valuenode_dynamiclist.h>
+#include <synfigapp/action_system.h>
+#include <synfig/valuenode_bline.h>
+
+#include "state_circle.h"
+#include "state_normal.h"
+#include "canvasview.h"
+#include "workarea.h"
+#include "app.h"
+
+#include <synfigapp/action.h>
+#include "event_mouse.h"
+#include "event_layerclick.h"
+#include "toolbox.h"
+#include "dialog_tooloptions.h"
+#include <gtkmm/optionmenu.h>
+#include "duck.h"
+#include "widgets/widget_enum.h"
+#include <synfigapp/main.h>
+
+#include "general.h"
+
+#endif
+
+/* === U S I N G =========================================================== */
+
+using namespace std;
+using namespace etl;
+using namespace synfig;
+using namespace studio;
+
+/* === M A C R O S ========================================================= */
+enum CircleFalloff
+{
+       CIRCLE_SQUARED  =0,
+       CIRCLE_INTERPOLATION_LINEAR     =1,
+       CIRCLE_COSINE   =2,
+       CIRCLE_SIGMOND  =3,
+       CIRCLE_SQRT             =4,
+       CIRCLE_NUM_FALLOFF
+};
+
+/* === G L O B A L S ======================================================= */
+
+StateCircle studio::state_circle;
+
+/* === C L A S S E S & S T R U C T S ======================================= */
+
+class studio::StateCircle_Context : public sigc::trackable
+{
+       etl::handle<CanvasView> canvas_view_;
+       CanvasView::IsWorking is_working;
+
+       Duckmatic::Push duckmatic_push;
+
+       Point point_holder;
+
+       etl::handle<Duck> point2_duck;
+
+       void refresh_ducks();
+
+       bool prev_workarea_layer_status_;
+
+       //Toolbox settings
+       synfigapp::Settings& settings;
+
+       //Toolbox display
+       Gtk::Table options_table;
+
+       Gtk::Entry              entry_id; //what to name the layer
+
+       Widget_Enum             enum_falloff;
+#ifdef BLEND_METHOD_IN_TOOL_OPTIONS
+       Widget_Enum             enum_blend;
+#endif // BLEND_METHOD_IN_TOOL_OPTIONS
+
+       Gtk::Adjustment adj_feather;
+       Gtk::Adjustment adj_number_of_bline_points;
+       Gtk::Adjustment adj_bline_point_angle_offset;
+       Gtk::SpinButton spin_feather;
+       Gtk::SpinButton spin_number_of_bline_points;
+       Gtk::SpinButton spin_bline_point_angle_offset;
+
+       Gtk::CheckButton checkbutton_invert;
+       Gtk::CheckButton checkbutton_layer_circle;
+       Gtk::CheckButton checkbutton_layer_region;
+       Gtk::CheckButton checkbutton_layer_outline;
+       Gtk::CheckButton checkbutton_layer_curve_gradient;
+       Gtk::CheckButton checkbutton_layer_plant;
+       Gtk::CheckButton checkbutton_layer_link_origins;
+       Gtk::CheckButton checkbutton_layer_origins_at_center;
+
+public:
+
+       // this only counts the layers which will have their origins linked
+       int layers_to_create()const
+       {
+               return
+                       (get_layer_circle_flag() && get_layer_origins_at_center_flag()) +
+                       get_layer_region_flag() +
+                       get_layer_outline_flag() +
+                       get_layer_curve_gradient_flag() +
+                       get_layer_plant_flag();
+       }
+
+       synfig::String get_id()const { return entry_id.get_text(); }
+       void set_id(const synfig::String& x) { return entry_id.set_text(x); }
+
+       int get_falloff()const { return enum_falloff.get_value(); }
+       void set_falloff(int x) { return enum_falloff.set_value(x); }
+
+#ifdef BLEND_METHOD_IN_TOOL_OPTIONS
+       int get_blend()const { return enum_blend.get_value(); }
+       void set_blend(int x) { return enum_blend.set_value(x); }
+#endif // BLEND_METHOD_IN_TOOL_OPTIONS
+
+       Real get_feather()const { return adj_feather.get_value(); }
+       void set_feather(Real f) { adj_feather.set_value(f); }
+
+       Real get_number_of_bline_points()const { return adj_number_of_bline_points.get_value(); }
+       void set_number_of_bline_points(Real f) { adj_number_of_bline_points.set_value(f); }
+
+       Real get_bline_point_angle_offset()const { return adj_bline_point_angle_offset.get_value(); }
+       void set_bline_point_angle_offset(Real f) { adj_bline_point_angle_offset.set_value(f); }
+
+       bool get_invert()const { return checkbutton_invert.get_active(); }
+       void set_invert(bool i) { checkbutton_invert.set_active(i); }
+
+       bool get_layer_circle_flag()const { return checkbutton_layer_circle.get_active(); }
+       void set_layer_circle_flag(bool x) { return checkbutton_layer_circle.set_active(x); }
+
+       bool get_layer_region_flag()const { return checkbutton_layer_region.get_active(); }
+       void set_layer_region_flag(bool x) { return checkbutton_layer_region.set_active(x); }
+
+       bool get_layer_outline_flag()const { return checkbutton_layer_outline.get_active(); }
+       void set_layer_outline_flag(bool x) { return checkbutton_layer_outline.set_active(x); }
+
+       bool get_layer_curve_gradient_flag()const { return checkbutton_layer_curve_gradient.get_active(); }
+       void set_layer_curve_gradient_flag(bool x) { return checkbutton_layer_curve_gradient.set_active(x); }
+
+       bool get_layer_plant_flag()const { return checkbutton_layer_plant.get_active(); }
+       void set_layer_plant_flag(bool x) { return checkbutton_layer_plant.set_active(x); }
+
+       bool get_layer_link_origins_flag()const { return checkbutton_layer_link_origins.get_active(); }
+       void set_layer_link_origins_flag(bool x) { return checkbutton_layer_link_origins.set_active(x); }
+
+       bool get_layer_origins_at_center_flag()const { return checkbutton_layer_origins_at_center.get_active(); }
+       void set_layer_origins_at_center_flag(bool x) { return checkbutton_layer_origins_at_center.set_active(x); }
+
+       void refresh_tool_options(); //to refresh the toolbox
+
+       //events
+       Smach::event_result event_stop_handler(const Smach::event& x);
+       Smach::event_result event_refresh_handler(const Smach::event& x);
+       Smach::event_result event_mouse_click_handler(const Smach::event& x);
+       Smach::event_result event_refresh_tool_options(const Smach::event& x);
+
+       //constructor destructor
+       StateCircle_Context(CanvasView* canvas_view);
+       ~StateCircle_Context();
+
+       //Canvas interaction
+       const etl::handle<CanvasView>& get_canvas_view()const{return canvas_view_;}
+       etl::handle<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view_->canvas_interface();}
+       synfig::Canvas::Handle get_canvas()const{return canvas_view_->get_canvas();}
+       WorkArea * get_work_area()const{return canvas_view_->get_work_area();}
+
+       //Modifying settings etc.
+       void load_settings();
+       void save_settings();
+       void reset();
+       void increment_id();
+       bool egress_on_selection_change;
+       Smach::event_result event_layer_selection_changed_handler(const Smach::event& /*x*/)
+       {
+               if(egress_on_selection_change)
+                       throw &state_normal; //throw Smach::egress_exception();
+               return Smach::RESULT_OK;
+       }
+
+       void make_circle(const Point& p1, const Point& p2);
+
+};     // END of class StateCircle_Context
+
+/* === M E T H O D S ======================================================= */
+
+StateCircle::StateCircle():
+       Smach::state<StateCircle_Context>("circle")
+{
+       insert(event_def(EVENT_LAYER_SELECTION_CHANGED,&StateCircle_Context::event_layer_selection_changed_handler));
+       insert(event_def(EVENT_STOP,&StateCircle_Context::event_stop_handler));
+       insert(event_def(EVENT_REFRESH,&StateCircle_Context::event_refresh_handler));
+       insert(event_def(EVENT_REFRESH_DUCKS,&StateCircle_Context::event_refresh_handler));
+       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateCircle_Context::event_mouse_click_handler));
+       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DRAG,&StateCircle_Context::event_mouse_click_handler));
+       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_UP,&StateCircle_Context::event_mouse_click_handler));
+       insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateCircle_Context::event_refresh_tool_options));
+}
+
+StateCircle::~StateCircle()
+{
+}
+
+void
+StateCircle_Context::load_settings()
+{
+       String value;
+
+       //parse the arguments yargh!
+       if(settings.get_value("circle.id",value))
+               set_id(value);
+       else
+               set_id("Circle");
+
+       if(settings.get_value("circle.fallofftype",value) && value != "")
+               set_falloff(atoi(value.c_str()));
+       else
+               set_falloff(2);
+
+#ifdef BLEND_METHOD_IN_TOOL_OPTIONS
+       if(settings.get_value("circle.blend",value) && value != "")
+               set_blend(atoi(value.c_str()));
+       else
+               set_blend(0);//(int)Color::BLEND_COMPOSITE); //0 should be blend composites value
+#endif // BLEND_METHOD_IN_TOOL_OPTIONS
+
+       if(settings.get_value("circle.feather",value))
+               set_feather(atof(value.c_str()));
+       else
+               set_feather(0);
+
+       if(settings.get_value("circle.number_of_bline_points",value))
+               set_number_of_bline_points(atof(value.c_str()));
+       else
+               set_number_of_bline_points(4);
+
+       if(settings.get_value("circle.bline_point_angle_offset",value))
+               set_bline_point_angle_offset(atof(value.c_str()));
+       else
+               set_bline_point_angle_offset(0);
+
+       if(settings.get_value("circle.invert",value) && value != "0")
+               set_invert(true);
+       else
+               set_invert(false);
+
+       if(settings.get_value("circle.layer_circle",value) && value=="0")
+               set_layer_circle_flag(false);
+       else
+               set_layer_circle_flag(true);
+
+       if(settings.get_value("circle.layer_region",value) && value=="1")
+               set_layer_region_flag(true);
+       else
+               set_layer_region_flag(false);
+
+       if(settings.get_value("circle.layer_outline",value) && value=="1")
+               set_layer_outline_flag(true);
+       else
+               set_layer_outline_flag(false);
+
+       if(settings.get_value("circle.layer_curve_gradient",value) && value=="1")
+               set_layer_curve_gradient_flag(true);
+       else
+               set_layer_curve_gradient_flag(false);
+
+       if(settings.get_value("circle.layer_plant",value) && value=="1")
+               set_layer_plant_flag(true);
+       else
+               set_layer_plant_flag(false);
+
+       if(settings.get_value("circle.layer_link_origins",value) && value=="0")
+               set_layer_link_origins_flag(false);
+       else
+               set_layer_link_origins_flag(true);
+
+       if(settings.get_value("circle.layer_origins_at_center",value) && value=="0")
+               set_layer_origins_at_center_flag(false);
+       else
+               set_layer_origins_at_center_flag(true);
+}
+
+void
+StateCircle_Context::save_settings()
+{
+       settings.set_value("circle.id",get_id());
+       settings.set_value("circle.fallofftype",strprintf("%d",get_falloff()));
+#ifdef BLEND_METHOD_IN_TOOL_OPTIONS
+       settings.set_value("circle.blend",strprintf("%d",get_blend()));
+#endif // BLEND_METHOD_IN_TOOL_OPTIONS
+       settings.set_value("circle.feather",strprintf("%f",(float)get_feather()));
+       settings.set_value("circle.number_of_bline_points",strprintf("%d",(int)(get_number_of_bline_points() + 0.5)));
+       settings.set_value("circle.bline_point_angle_offset",strprintf("%f",(float)get_bline_point_angle_offset()));
+       settings.set_value("circle.invert",get_invert()?"1":"0");
+       settings.set_value("circle.layer_circle",get_layer_circle_flag()?"1":"0");
+       settings.set_value("circle.layer_outline",get_layer_outline_flag()?"1":"0");
+       settings.set_value("circle.layer_region",get_layer_region_flag()?"1":"0");
+       settings.set_value("circle.layer_curve_gradient",get_layer_curve_gradient_flag()?"1":"0");
+       settings.set_value("circle.layer_plant",get_layer_plant_flag()?"1":"0");
+       settings.set_value("circle.layer_link_origins",get_layer_link_origins_flag()?"1":"0");
+       settings.set_value("circle.layer_origins_at_center",get_layer_origins_at_center_flag()?"1":"0");
+}
+
+void
+StateCircle_Context::reset()
+{
+       refresh_ducks();
+}
+
+void
+StateCircle_Context::increment_id()
+{
+       String id(get_id());
+       int number=1;
+       int digits=0;
+
+       if(id.empty())
+               id="Circle";
+
+       // If there is a number
+       // already at the end of the
+       // id, then remove it.
+       if(id[id.size()-1]<='9' && id[id.size()-1]>='0')
+       {
+               // figure out how many digits it is
+               for (digits = 0;
+                        (int)id.size()-1 >= digits && id[id.size()-1-digits] <= '9' && id[id.size()-1-digits] >= '0';
+                        digits++)
+                       ;
+
+               String str_number;
+               str_number=String(id,id.size()-digits,id.size());
+               id=String(id,0,id.size()-digits);
+
+               number=atoi(str_number.c_str());
+       }
+       else
+       {
+               number=1;
+               digits=3;
+       }
+
+       number++;
+
+       // Add the number back onto the id
+       {
+               const String format(strprintf("%%0%dd",digits));
+               id+=strprintf(format.c_str(),number);
+       }
+
+       // Set the ID
+       set_id(id);
+}
+
+StateCircle_Context::StateCircle_Context(CanvasView* canvas_view):
+       canvas_view_(canvas_view),
+       is_working(*canvas_view),
+       duckmatic_push(get_work_area()),
+       prev_workarea_layer_status_(get_work_area()->get_allow_layer_clicks()),
+       settings(synfigapp::Main::get_selected_input_device()->settings()),
+       entry_id(),                             //   value lower upper  step page
+       adj_feather(                                    0,    0,    1, 0.01, 0.1),
+       adj_number_of_bline_points(             0,    2,  120, 1   , 1  ),
+       adj_bline_point_angle_offset(   0, -360,  360, 0.1 , 1  ),
+       spin_feather(adj_feather,0.1,3),
+       spin_number_of_bline_points(adj_number_of_bline_points,1,0),
+       spin_bline_point_angle_offset(adj_bline_point_angle_offset,1,1),
+       checkbutton_invert(_("Invert")),
+       checkbutton_layer_circle(_("Create Circle Layer")),
+       checkbutton_layer_region(_("Create Region BLine")),
+       checkbutton_layer_outline(_("Create Outline BLine")),
+       checkbutton_layer_curve_gradient(_("Create Curve Gradient BLine")),
+       checkbutton_layer_plant(_("Create Plant BLine")),
+       checkbutton_layer_link_origins(_("Link Origins")),
+       checkbutton_layer_origins_at_center(_("BLine Origins at Center"))
+{
+       egress_on_selection_change=true;
+
+       // Set up the tool options dialog
+       enum_falloff.set_param_desc(ParamDesc("falloff")
+               .set_local_name(_("Falloff"))
+               .set_description(_("Determines the falloff function for the feather"))
+               .set_hint("enum")
+               .add_enum_value(CIRCLE_INTERPOLATION_LINEAR,"linear",_("Linear"))
+               .add_enum_value(CIRCLE_SQUARED,"squared",_("Squared"))
+               .add_enum_value(CIRCLE_SQRT,"sqrt",_("Square Root"))
+               .add_enum_value(CIRCLE_SIGMOND,"sigmond",_("Sigmond"))
+               .add_enum_value(CIRCLE_COSINE,"cosine",_("Cosine")));
+
+#ifdef BLEND_METHOD_IN_TOOL_OPTIONS
+       enum_blend.set_param_desc(ParamDesc(Color::BLEND_COMPOSITE,"blend_method")
+               .set_local_name(_("Blend Method"))
+               .set_description(_("Defines the blend method to be used for circles")));
+#endif // BLEND_METHOD_IN_TOOL_OPTIONS
+
+       load_settings();
+
+       options_table.attach(*manage(new Gtk::Label(_("Circle Tool"))),         0, 2,  0,  1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(entry_id,                                                                          0, 2,  1,  2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+
+       options_table.attach(checkbutton_layer_circle,                                          0, 2,  2,  3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(checkbutton_layer_outline,                                         0, 2,  3,  4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(checkbutton_layer_region,                                          0, 2,  4,  5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(checkbutton_layer_plant,                                           0, 2,  5,  6, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(checkbutton_layer_curve_gradient,                          0, 2,  6,  7, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(checkbutton_layer_link_origins,                            0, 2,  7,  8, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(checkbutton_layer_origins_at_center,                       0, 2,  8,  9, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+
+       //invert flag
+       options_table.attach(checkbutton_invert,                                                0, 2,  9, 10, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+
+       options_table.attach(*manage(new Gtk::Label(_("Falloff:"))),            0, 1, 10, 11, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(enum_falloff,                                      1, 2, 10, 11, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+
+       //feather stuff
+       options_table.attach(*manage(new Gtk::Label(_("Feather:"))),            0, 1, 11, 12, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(spin_feather,                                                              1, 2, 11, 12, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+
+#ifdef BLEND_METHOD_IN_TOOL_OPTIONS
+       options_table.attach(enum_blend,                                        0, 2, 12, 13, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+#endif // BLEND_METHOD_IN_TOOL_OPTIONS
+
+       options_table.attach(*manage(new Gtk::Label(_("BLine Points:"))),       0, 1, 13, 14, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(spin_number_of_bline_points,                                       1, 2, 13, 14, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+
+options_table.attach(*manage(new Gtk::Label(_("Point Angle Offset:"))),        0, 1, 14, 15, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(spin_bline_point_angle_offset,                                     1, 2, 14, 15, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+
+       options_table.show_all();
+
+       refresh_tool_options();
+       App::dialog_tool_options->present();
+
+       // Turn off layer clicking
+       get_work_area()->set_allow_layer_clicks(false);
+
+       // clear out the ducks
+       get_work_area()->clear_ducks();
+
+       // Refresh the work area
+       get_work_area()->queue_draw();
+
+       // Hide the tables if they are showing
+       //prev_table_status=get_canvas_view()->tables_are_visible();
+       //if(prev_table_status)get_canvas_view()->hide_tables();
+
+       // Disable the time bar
+       //get_canvas_view()->set_sensitive_timebar(false);
+
+       // Connect a signal
+       //get_work_area()->signal_user_click().connect(sigc::mem_fun(*this,&studio::StateCircle_Context::on_user_click));
+       get_work_area()->set_cursor(Gdk::CROSSHAIR);
+
+       App::toolbox->refresh();
+}
+
+void
+StateCircle_Context::refresh_tool_options()
+{
+       App::dialog_tool_options->clear();
+       App::dialog_tool_options->set_widget(options_table);
+       App::dialog_tool_options->set_local_name(_("Circle Tool"));
+       App::dialog_tool_options->set_name("circle");
+}
+
+Smach::event_result
+StateCircle_Context::event_refresh_tool_options(const Smach::event& /*x*/)
+{
+       refresh_tool_options();
+       return Smach::RESULT_ACCEPT;
+}
+
+StateCircle_Context::~StateCircle_Context()
+{
+       save_settings();
+
+       // Restore layer clicking
+       get_work_area()->set_allow_layer_clicks(prev_workarea_layer_status_);
+       get_work_area()->reset_cursor();
+
+       App::dialog_tool_options->clear();
+
+       // Enable the time bar
+       //get_canvas_view()->set_sensitive_timebar(true);
+
+       // Bring back the tables if they were out before
+       //if(prev_table_status)get_canvas_view()->show_tables();
+
+       // Refresh the work area
+       get_work_area()->queue_draw();
+
+       get_canvas_view()->queue_rebuild_ducks();
+
+       App::toolbox->refresh();
+}
+
+Smach::event_result
+StateCircle_Context::event_stop_handler(const Smach::event& /*x*/)
+{
+       //throw Smach::egress_exception();
+       throw &state_normal;
+       return Smach::RESULT_OK;
+}
+
+Smach::event_result
+StateCircle_Context::event_refresh_handler(const Smach::event& /*x*/)
+{
+       refresh_ducks();
+       return Smach::RESULT_ACCEPT;
+}
+
+void
+StateCircle_Context::make_circle(const Point& _p1, const Point& _p2)
+{
+       synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("New Circle"));
+       synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
+
+       Layer::Handle layer;
+
+       Canvas::Handle canvas;
+       int depth(0);
+
+       // we are temporarily using the layer to hold something
+       layer=get_canvas_view()->get_selection_manager()->get_selected_layer();
+       if(layer)
+       {
+               depth=layer->get_depth();
+               canvas=layer->get_canvas();
+       }
+
+       synfigapp::SelectionManager::LayerList layer_selection;
+       if (!getenv("SYNFIG_TOOLS_CLEAR_SELECTION"))
+               layer_selection = get_canvas_view()->get_selection_manager()->get_selected_layers();
+
+       const synfig::TransformStack& transform(get_canvas_view()->get_curr_transform_stack());
+       const Point p1(transform.unperform(_p1));
+       const Point p2(transform.unperform(_p2));
+
+       Real radius((p2-p1).mag());
+       int points = get_number_of_bline_points();
+       Angle::deg offset(get_bline_point_angle_offset());
+       Angle::deg angle(360.0/points);
+       Real tangent(4 * ((points == 2)
+                                         ? 1
+                                         : ((2 * Angle::cos(angle/2).get() - Angle::cos(angle).get() - 1) / Angle::sin(angle).get())));
+       Vector origin;
+       Real x, y;
+
+       if (get_layer_origins_at_center_flag())
+       {
+               x = y = 0;
+               origin = p1;
+       }
+       else
+       {
+               x = p1[0];
+               y = p1[1];
+       }
+
+       std::vector<BLinePoint> new_list;
+       for (int i = 0; i < points; i++)
+       {
+               new_list.push_back(*(new BLinePoint));
+               new_list[i].set_width(1);
+               new_list[i].set_vertex(Point(radius*Angle::cos(angle*i + offset).get() + x,
+                                                                        radius*Angle::sin(angle*i + offset).get() + y));
+               new_list[i].set_tangent(Point(-radius*tangent*Angle::sin(angle*i + offset).get(),
+                                                                          radius*tangent*Angle::cos(angle*i + offset).get()));
+       }
+
+       ValueNode_BLine::Handle value_node_bline(ValueNode_BLine::create(new_list));
+       assert(value_node_bline);
+
+       ValueNode_Const::Handle value_node_origin(ValueNode_Const::create(origin));
+       assert(value_node_origin);
+
+       // Set the looping flag
+       value_node_bline->set_loop(true);
+
+       if(!canvas)
+               canvas=get_canvas_view()->get_canvas();
+
+       value_node_bline->set_member_canvas(canvas);
+
+       // count how many layers we're going to be creating
+       int layers_to_create = this->layers_to_create();
+
+       ///////////////////////////////////////////////////////////////////////////
+       //   C I R C L E
+       ///////////////////////////////////////////////////////////////////////////
+
+       if (get_layer_circle_flag() &&
+               get_falloff() >= 0 && get_falloff() < CIRCLE_NUM_FALLOFF)
+       {
+               layer=get_canvas_interface()->add_layer_to("circle",canvas,depth);
+               if (!layer)
+               {
+                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
+                       group.cancel();
+                       return;
+               }
+               layer_selection.push_back(layer);
+
+               layer->set_param("radius",(p2-p1).mag());
+               get_canvas_interface()->signal_layer_param_changed()(layer,"radius");
+
+               layer->set_param("falloff",get_falloff());
+               get_canvas_interface()->signal_layer_param_changed()(layer,"falloff");
+
+               layer->set_param("feather",get_feather());
+               get_canvas_interface()->signal_layer_param_changed()(layer,"feather");
+
+               layer->set_param("invert",get_invert());
+               get_canvas_interface()->signal_layer_param_changed()(layer,"invert");
+
+#ifdef BLEND_METHOD_IN_TOOL_OPTIONS
+               layer->set_param("blend_method",get_blend());
+               get_canvas_interface()->signal_layer_param_changed()(layer,"blend_method");
+#endif // BLEND_METHOD_IN_TOOL_OPTIONS
+
+               layer->set_description(get_id());
+               get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
+
+               // only link the circle's origin parameter if the option is selected, we're putting bline
+               // origins at their centers, and we're creating more than one layer
+               if (get_layer_link_origins_flag() && get_layer_origins_at_center_flag() && layers_to_create > 1)
+               {
+                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
+                       assert(action);
+
+                       action->set_param("canvas",get_canvas());
+                       action->set_param("canvas_interface",get_canvas_interface());
+                       action->set_param("layer",layer);
+                       if(!action->set_param("param",String("origin")))
+                               synfig::error("LayerParamConnect didn't like \"param\"");
+                       if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
+                               synfig::error("LayerParamConnect didn't like \"value_node\"");
+
+                       if(!get_canvas_interface()->get_instance()->perform_action(action))
+                       {
+                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create Circle layer"));
+                               group.cancel();
+                               throw String(_("Unable to create Circle layer"));
+                               return;
+                       }
+               }
+               else
+               {
+                       layer->set_param("origin",p1);
+                       get_canvas_interface()->signal_layer_param_changed()(layer,"origin");
+               }
+       }
+
+       ///////////////////////////////////////////////////////////////////////////
+       //   C U R V E   G R A D I E N T
+       ///////////////////////////////////////////////////////////////////////////
+
+       if(get_layer_curve_gradient_flag())
+       {
+               synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
+
+               Layer::Handle layer(get_canvas_interface()->add_layer_to("curve_gradient",canvas,depth));
+               if (!layer)
+               {
+                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
+                       group.cancel();
+                       return;
+               }
+               layer_selection.push_back(layer);
+               layer->set_description(get_id()+_(" Gradient"));
+               get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
+
+#ifdef BLEND_METHOD_IN_TOOL_OPTIONS
+               layer->set_param("blend_method",get_blend());
+               get_canvas_interface()->signal_layer_param_changed()(layer,"blend_method");
+#endif // BLEND_METHOD_IN_TOOL_OPTIONS
+
+               {
+                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
+                       assert(action);
+
+                       action->set_param("canvas",get_canvas());
+                       action->set_param("canvas_interface",get_canvas_interface());
+                       action->set_param("layer",layer);
+                       if(!action->set_param("param",String("bline")))
+                               synfig::error("LayerParamConnect didn't like \"param\"");
+                       if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
+                               synfig::error("LayerParamConnect didn't like \"value_node\"");
+
+                       if(!get_canvas_interface()->get_instance()->perform_action(action))
+                       {
+                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
+                               group.cancel();
+                               throw String(_("Unable to create Gradient layer"));
+                               return;
+                       }
+               }
+
+               // only link the curve gradient's origin parameter if the option is selected and we're creating more than one layer
+               if (get_layer_link_origins_flag() && layers_to_create > 1)
+               {
+                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
+                       assert(action);
+
+                       action->set_param("canvas",get_canvas());
+                       action->set_param("canvas_interface",get_canvas_interface());
+                       action->set_param("layer",layer);
+                       if(!action->set_param("param",String("origin")))
+                               synfig::error("LayerParamConnect didn't like \"param\"");
+                       if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
+                               synfig::error("LayerParamConnect didn't like \"value_node\"");
+
+                       if(!get_canvas_interface()->get_instance()->perform_action(action))
+                       {
+                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
+                               group.cancel();
+                               throw String(_("Unable to create Gradient layer"));
+                               return;
+                       }
+               }
+               else
+               {
+                       layer->set_param("origin",origin);
+                       get_canvas_interface()->signal_layer_param_changed()(layer,"origin");
+               }
+       }
+
+       ///////////////////////////////////////////////////////////////////////////
+       //   P L A N T
+       ///////////////////////////////////////////////////////////////////////////
+
+       if(get_layer_plant_flag())
+       {
+               synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
+
+               Layer::Handle layer(get_canvas_interface()->add_layer_to("plant",canvas,depth));
+               if (!layer)
+               {
+                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
+                       group.cancel();
+                       return;
+               }
+               layer_selection.push_back(layer);
+               layer->set_description(get_id()+_(" Plant"));
+               get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
+
+#ifdef BLEND_METHOD_IN_TOOL_OPTIONS
+               layer->set_param("blend_method",get_blend());
+               get_canvas_interface()->signal_layer_param_changed()(layer,"blend_method");
+#endif // BLEND_METHOD_IN_TOOL_OPTIONS
+
+               {
+                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
+                       assert(action);
+
+                       action->set_param("canvas",get_canvas());
+                       action->set_param("canvas_interface",get_canvas_interface());
+                       action->set_param("layer",layer);
+                       if(!action->set_param("param",String("bline")))
+                               synfig::error("LayerParamConnect didn't like \"param\"");
+                       if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
+                               synfig::error("LayerParamConnect didn't like \"value_node\"");
+
+                       if(!get_canvas_interface()->get_instance()->perform_action(action))
+                       {
+                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
+                               group.cancel();
+                               throw String(_("Unable to create Plant layer"));
+                               return;
+                       }
+               }
+
+               // only link the plant's origin parameter if the option is selected and we're creating more than one layer
+               if (get_layer_link_origins_flag() && layers_to_create > 1)
+               {
+                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
+                       assert(action);
+
+                       action->set_param("canvas",get_canvas());
+                       action->set_param("canvas_interface",get_canvas_interface());
+                       action->set_param("layer",layer);
+                       if(!action->set_param("param",String("origin")))
+                               synfig::error("LayerParamConnect didn't like \"param\"");
+                       if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
+                               synfig::error("LayerParamConnect didn't like \"value_node\"");
+
+                       if(!get_canvas_interface()->get_instance()->perform_action(action))
+                       {
+                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
+                               group.cancel();
+                               throw String(_("Unable to create Plant layer"));
+                               return;
+                       }
+               }
+               else
+               {
+                       layer->set_param("origin",origin);
+                       get_canvas_interface()->signal_layer_param_changed()(layer,"origin");
+               }
+       }
+
+       ///////////////////////////////////////////////////////////////////////////
+       //   R E G I O N
+       ///////////////////////////////////////////////////////////////////////////
+
+       if(get_layer_region_flag())
+       {
+               synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
+
+               Layer::Handle layer(get_canvas_interface()->add_layer_to("region",canvas,depth));
+               if (!layer)
+               {
+                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
+                       group.cancel();
+                       return;
+               }
+               layer_selection.push_back(layer);
+               layer->set_description(get_id()+_(" Region"));
+               get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
+
+#ifdef BLEND_METHOD_IN_TOOL_OPTIONS
+               layer->set_param("blend_method",get_blend());
+               get_canvas_interface()->signal_layer_param_changed()(layer,"blend_method");
+#endif // BLEND_METHOD_IN_TOOL_OPTIONS
+
+               layer->set_param("feather",get_feather());
+               get_canvas_interface()->signal_layer_param_changed()(layer,"feather");
+
+               layer->set_param("invert",get_invert());
+               get_canvas_interface()->signal_layer_param_changed()(layer,"invert");
+
+               // I don't know if it's safe to reuse the same LayerParamConnect action, so I'm
+               // using 2 separate ones.
+               {
+                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
+                       assert(action);
+
+                       action->set_param("canvas",get_canvas());
+                       action->set_param("canvas_interface",get_canvas_interface());
+                       action->set_param("layer",layer);
+                       if(!action->set_param("param",String("bline")))
+                               synfig::error("LayerParamConnect didn't like \"param\"");
+                       if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
+                               synfig::error("LayerParamConnect didn't like \"value_node\"");
+
+                       if(!get_canvas_interface()->get_instance()->perform_action(action))
+                       {
+                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer"));
+                               group.cancel();
+                               throw String(_("Unable to create Region layer"));
+                               return;
+                       }
+               }
+
+               // only link the region's origin parameter if the option is selected and we're creating more than one layer
+               if (get_layer_link_origins_flag() && layers_to_create > 1)
+               {
+                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
+                       assert(action);
+
+                       action->set_param("canvas",get_canvas());
+                       action->set_param("canvas_interface",get_canvas_interface());
+                       action->set_param("layer",layer);
+                       if(!action->set_param("param",String("origin")))
+                               synfig::error("LayerParamConnect didn't like \"param\"");
+                       if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
+                               synfig::error("LayerParamConnect didn't like \"value_node\"");
+
+                       if(!get_canvas_interface()->get_instance()->perform_action(action))
+                       {
+                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer"));
+                               group.cancel();
+                               throw String(_("Unable to create Region layer"));
+                               return;
+                       }
+               }
+               else
+               {
+                       layer->set_param("origin",origin);
+                       get_canvas_interface()->signal_layer_param_changed()(layer,"origin");
+               }
+       }
+
+       ///////////////////////////////////////////////////////////////////////////
+       //   O U T L I N E
+       ///////////////////////////////////////////////////////////////////////////
+
+       if (get_layer_outline_flag())
+       {
+               Layer::Handle layer(get_canvas_interface()->add_layer_to("outline",canvas,depth));
+               if (!layer)
+               {
+                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
+                       group.cancel();
+                       return;
+               }
+               layer_selection.push_back(layer);
+               layer->set_description(get_id()+_(" Outline"));
+               get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
+
+#ifdef BLEND_METHOD_IN_TOOL_OPTIONS
+               layer->set_param("blend_method",get_blend());
+               get_canvas_interface()->signal_layer_param_changed()(layer,"blend_method");
+#endif // BLEND_METHOD_IN_TOOL_OPTIONS
+
+               layer->set_param("feather",get_feather());
+               get_canvas_interface()->signal_layer_param_changed()(layer,"feather");
+
+               layer->set_param("invert",get_invert());
+               get_canvas_interface()->signal_layer_param_changed()(layer,"invert");
+
+               {
+                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
+                       assert(action);
+
+                       action->set_param("canvas",get_canvas());
+                       action->set_param("canvas_interface",get_canvas_interface());
+                       action->set_param("layer",layer);
+                       if(!action->set_param("param",String("bline")))
+                               synfig::error("LayerParamConnect didn't like \"param\"");
+                       if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
+                               synfig::error("LayerParamConnect didn't like \"value_node\"");
+
+                       if(!get_canvas_interface()->get_instance()->perform_action(action))
+                       {
+                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
+                               group.cancel();
+                               throw String(_("Unable to create Outline layer"));
+                               return;
+                       }
+               }
+
+               // only link the outline's origin parameter if the option is selected and we're creating more than one layer
+               if (get_layer_link_origins_flag() && layers_to_create > 1)
+               {
+                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
+                       assert(action);
+
+                       action->set_param("canvas",get_canvas());
+                       action->set_param("canvas_interface",get_canvas_interface());
+                       action->set_param("layer",layer);
+                       if(!action->set_param("param",String("origin")))
+                               synfig::error("LayerParamConnect didn't like \"param\"");
+                       if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
+                               synfig::error("LayerParamConnect didn't like \"value_node\"");
+
+                       if(!get_canvas_interface()->get_instance()->perform_action(action))
+                       {
+                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
+                               group.cancel();
+                               throw String(_("Unable to create Outline layer"));
+                               return;
+                       }
+               }
+               else
+               {
+                       layer->set_param("origin",origin);
+                       get_canvas_interface()->signal_layer_param_changed()(layer,"origin");
+               }
+       }
+
+       egress_on_selection_change=false;
+       get_canvas_interface()->get_selection_manager()->clear_selected_layers();
+       get_canvas_interface()->get_selection_manager()->set_selected_layers(layer_selection);
+       egress_on_selection_change=true;
+
+       reset();
+       increment_id();
+}
+
+Smach::event_result
+StateCircle_Context::event_mouse_click_handler(const Smach::event& x)
+{
+       const EventMouse& event(*reinterpret_cast<const EventMouse*>(&x));
+
+       if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_DOWN && event.button==BUTTON_LEFT)
+       {
+               point_holder=get_work_area()->snap_point_to_grid(event.pos);
+               etl::handle<Duck> duck=new Duck();
+               duck->set_point(point_holder);
+               duck->set_name("p1");
+               duck->set_type(Duck::TYPE_POSITION);
+               duck->set_editable(false);
+               get_work_area()->add_duck(duck);
+
+               point2_duck=new Duck();
+               point2_duck->set_point(Vector(0,0));
+               point2_duck->set_name("radius");
+               point2_duck->set_origin(duck);
+               point2_duck->set_radius(true);
+               point2_duck->set_scalar(-1);
+               point2_duck->set_type(Duck::TYPE_RADIUS);
+               point2_duck->set_hover(true);
+               get_work_area()->add_duck(point2_duck);
+
+               return Smach::RESULT_ACCEPT;
+       }
+
+       if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_DRAG && event.button==BUTTON_LEFT)
+       {
+               if (!point2_duck) return Smach::RESULT_OK;
+               point2_duck->set_point(point_holder-get_work_area()->snap_point_to_grid(event.pos));
+               get_work_area()->queue_draw();
+               return Smach::RESULT_ACCEPT;
+       }
+
+       if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_UP && event.button==BUTTON_LEFT)
+       {
+               Point point(get_work_area()->snap_point_to_grid(event.pos));
+
+               if (App::restrict_radius_ducks)
+               {
+                       if ((point[0] - point_holder[0]) < 0) point[0] = point_holder[0];
+                       if ((point[1] - point_holder[1]) < 0) point[1] = point_holder[1];
+               }
+
+               make_circle(point_holder, point);
+               get_work_area()->clear_ducks();
+               return Smach::RESULT_ACCEPT;
+       }
+
+       return Smach::RESULT_OK;
+}
+
+
+void
+StateCircle_Context::refresh_ducks()
+{
+       get_work_area()->clear_ducks();
+       get_work_area()->queue_draw();
+}
diff --git a/synfig-studio/src/gui/states/state_circle.h b/synfig-studio/src/gui/states/state_circle.h
new file mode 100644 (file)
index 0000000..b33ccf3
--- /dev/null
@@ -0,0 +1,56 @@
+/* === S Y N F I G ========================================================= */
+/*!    \file state_circle.h
+**     \brief Circle creation state
+**
+**     $Id$
+**
+**     \legal
+**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+**
+**     This package is free software; you can redistribute it and/or
+**     modify it under the terms of the GNU General Public License as
+**     published by the Free Software Foundation; either version 2 of
+**     the License, or (at your option) any later version.
+**
+**     This package is distributed in the hope that it will be useful,
+**     but WITHOUT ANY WARRANTY; without even the implied warranty of
+**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+**     General Public License for more details.
+**     \endlegal
+*/
+/* ========================================================================= */
+
+/* === S T A R T =========================================================== */
+
+#ifndef __SYNFIG_STUDIO_STATE_CIRCLE_H
+#define __SYNFIG_STUDIO_STATE_CIRCLE_H
+
+/* === H E A D E R S ======================================================= */
+
+#include "smach.h"
+
+
+/* === M A C R O S ========================================================= */
+
+/* === T Y P E D E F S ===================================================== */
+
+/* === C L A S S E S & S T R U C T S ======================================= */
+
+namespace studio {
+
+class StateCircle_Context;
+
+class StateCircle : public Smach::state<StateCircle_Context>
+{
+public:
+       StateCircle();
+       ~StateCircle();
+}; // END of class StateCircle
+
+extern StateCircle state_circle;
+
+}; // END of namespace studio
+
+/* === E N D =============================================================== */
+
+#endif
diff --git a/synfig-studio/src/gui/states/state_draw.cpp b/synfig-studio/src/gui/states/state_draw.cpp
new file mode 100644 (file)
index 0000000..4482045
--- /dev/null
@@ -0,0 +1,2036 @@
+/* === S Y N F I G ========================================================= */
+/*!    \file state_draw.cpp
+**     \brief Template File
+**
+**     $Id$
+**
+**     \legal
+**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+**     Copyright (c) 2007 Chris Moore
+**     Copyright (c) 2009 Nikita Kitaev
+**
+**     This package is free software; you can redistribute it and/or
+**     modify it under the terms of the GNU General Public License as
+**     published by the Free Software Foundation; either version 2 of
+**     the License, or (at your option) any later version.
+**
+**     This package is distributed in the hope that it will be useful,
+**     but WITHOUT ANY WARRANTY; without even the implied warranty of
+**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+**     General Public License for more details.
+**     \endlegal
+*/
+/* ========================================================================= */
+
+/* === H E A D E R S ======================================================= */
+
+#ifdef USING_PCH
+#      include "pch.h"
+#else
+#ifdef HAVE_CONFIG_H
+#      include <config.h>
+#endif
+
+#include <gtkmm/dialog.h>
+#include <gtkmm/entry.h>
+
+#include <synfig/valuenode_dynamiclist.h>
+
+#include "state_draw.h"
+#include "state_stroke.h"
+#include "state_normal.h"
+#include "canvasview.h"
+#include "workarea.h"
+#include "app.h"
+#include <synfig/valuenode_bline.h>
+#include <synfig/valuenode_composite.h>
+#include <ETL/hermite>
+#include <ETL/calculus>
+#include <utility>
+#include "event_mouse.h"
+#include "event_layerclick.h"
+#include "toolbox.h"
+
+#include <synfigapp/blineconvert.h>
+#include <synfigapp/main.h>
+
+#include <ETL/gaussian>
+#include "dialog_tooloptions.h"
+
+#include <gtkmm/table.h>
+#include <gtkmm/label.h>
+#include <gtkmm/button.h>
+#include <gtkmm/checkbutton.h>
+#include <gtkmm/scale.h>
+#include <sigc++/connection.h>
+
+#include "general.h"
+
+#endif
+
+/* === U S I N G =========================================================== */
+
+using namespace std;
+using namespace etl;
+using namespace synfig;
+using namespace studio;
+
+/* === M A C R O S ========================================================= */
+
+/* === G L O B A L S ======================================================= */
+
+StateDraw studio::state_draw;
+
+/* === C L A S S E S & S T R U C T S ======================================= */
+
+class studio::StateDraw_Context : public sigc::trackable
+{
+       typedef etl::smart_ptr<std::list<synfig::Point> > StrokeData;
+       typedef etl::smart_ptr<std::list<synfig::Real> > WidthData;
+
+       typedef list< pair<StrokeData,WidthData> > StrokeQueue;
+
+       StrokeQueue stroke_queue;
+
+
+       etl::handle<CanvasView> canvas_view_;
+       CanvasView::IsWorking is_working;
+
+       bool prev_table_status;
+       bool loop_;
+       bool prev_workarea_layer_status_;
+
+       int nested;
+       sigc::connection process_queue_connection;
+
+       ValueNode_BLine::Handle last_stroke;
+       synfig::String last_stroke_id;
+
+       Gtk::Menu menu;
+
+       //Duckmatic::Push duckmatic_push;
+
+       std::list< etl::smart_ptr<std::list<synfig::Point> > > stroke_list;
+
+       void refresh_ducks();
+
+       Duckmatic::Type old_duckmask;
+
+       void fill_last_stroke();
+       Smach::event_result fill_last_stroke_and_unselect_other_layers();
+
+       Smach::event_result new_bline(std::list<synfig::BLinePoint> bline,bool loop_bline_flag,float radius);
+
+       Smach::event_result new_region(std::list<synfig::BLinePoint> bline,synfig::Real radius);
+
+       Smach::event_result extend_bline_from_begin(ValueNode_BLine::Handle value_node,std::list<synfig::BLinePoint> bline,bool complete_loop);
+       Smach::event_result extend_bline_from_end(ValueNode_BLine::Handle value_node,std::list<synfig::BLinePoint> bline,bool complete_loop);
+       void reverse_bline(std::list<synfig::BLinePoint> &bline);
+
+       synfigapp::Settings& settings;
+
+       Gtk::Table options_table;
+       Gtk::Entry entry_id;
+       Gtk::CheckButton checkbutton_pressure_width;
+       Gtk::CheckButton checkbutton_round_ends;
+       Gtk::CheckButton checkbutton_auto_loop;   // whether to loop new strokes which start and end in the same place
+       Gtk::CheckButton checkbutton_auto_extend; // whether to extend existing lines
+       Gtk::CheckButton checkbutton_auto_link;   // whether to link new ducks to existing ducks
+       Gtk::CheckButton checkbutton_region;      // whether to create regions
+       Gtk::CheckButton checkbutton_outline;     // whether to create outlines
+       Gtk::CheckButton checkbutton_auto_export;
+       Gtk::Button button_fill_last_stroke;
+
+       //pressure spinner and such
+       Gtk::Adjustment  adj_min_pressure;
+       Gtk::SpinButton  spin_min_pressure;
+       Gtk::CheckButton check_min_pressure;
+
+       Gtk::Adjustment  adj_feather;
+       Gtk::SpinButton  spin_feather;
+
+       Gtk::Adjustment  adj_globalthres;
+       Gtk::SpinButton  spin_globalthres;
+
+       Gtk::Adjustment  adj_localthres;
+       Gtk::CheckButton check_localerror;
+       void UpdateErrorBox();  //switches the stuff if need be :)
+
+       //Added by Adrian - data drive HOOOOO
+       synfigapp::BLineConverter blineconv;
+
+public:
+       synfig::String get_id()const { return entry_id.get_text(); }
+       void set_id(const synfig::String& x) { return entry_id.set_text(x); }
+
+       bool get_pressure_width_flag()const { return checkbutton_pressure_width.get_active(); }
+       void set_pressure_width_flag(bool x) { return checkbutton_pressure_width.set_active(x); }
+
+       bool get_auto_loop_flag()const { return checkbutton_auto_loop.get_active(); }
+       void set_auto_loop_flag(bool x) { return checkbutton_auto_loop.set_active(x); }
+
+       bool get_auto_extend_flag()const { return checkbutton_auto_extend.get_active(); }
+       void set_auto_extend_flag(bool x) { return checkbutton_auto_extend.set_active(x); }
+
+       bool get_auto_link_flag()const { return checkbutton_auto_link.get_active(); }
+       void set_auto_link_flag(bool x) { return checkbutton_auto_link.set_active(x); }
+
+       bool get_region_flag()const { return checkbutton_region.get_active(); }
+       void set_region_flag(bool x) { return checkbutton_region.set_active(x); }
+
+       bool get_outline_flag()const { return checkbutton_outline.get_active(); }
+       void set_outline_flag(bool x) { return checkbutton_outline.set_active(x); }
+
+       bool get_auto_export_flag()const { return checkbutton_auto_export.get_active(); }
+       void set_auto_export_flag(bool x) { return checkbutton_auto_export.set_active(x); }
+
+       Real get_min_pressure() const { return adj_min_pressure.get_value(); }
+       void set_min_pressure(Real x) { return adj_min_pressure.set_value(x); }
+
+       Real get_feather() const { return adj_feather.get_value(); }
+       void set_feather(Real x) { return adj_feather.set_value(x); }
+
+       Real get_gthres() const { return adj_globalthres.get_value(); }
+       void set_gthres(Real x) { return adj_globalthres.set_value(x); }
+
+       Real get_lthres() const { return adj_localthres.get_value(); }
+       void set_lthres(Real x) { return adj_localthres.set_value(x); }
+
+       bool get_local_error_flag() const { return check_localerror.get_active(); }
+       void set_local_error_flag(bool x) { check_localerror.set_active(x); }
+
+       bool get_min_pressure_flag()const { return check_min_pressure.get_active(); }
+       void set_min_pressure_flag(bool x) { check_min_pressure.set_active(x); }
+
+       void load_settings();
+       void save_settings();
+       void increment_id();
+
+       Smach::event_result event_stop_handler(const Smach::event& x);
+
+       Smach::event_result event_refresh_handler(const Smach::event& x);
+
+       Smach::event_result event_mouse_down_handler(const Smach::event& x);
+
+       Smach::event_result event_stroke(const Smach::event& x);
+       Smach::event_result event_refresh_tool_options(const Smach::event& x);
+       void refresh_tool_options();
+
+       Smach::event_result process_stroke(StrokeData stroke_data, WidthData width_data, bool region_flag=false);
+
+       bool process_queue();
+
+
+       StateDraw_Context(CanvasView* canvas_view);
+
+       ~StateDraw_Context();
+
+       const etl::handle<CanvasView>& get_canvas_view()const{return canvas_view_;}
+       etl::handle<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view_->canvas_interface();}
+       synfig::Time get_time()const { return get_canvas_interface()->get_time(); }
+       synfig::Canvas::Handle get_canvas()const{return canvas_view_->get_canvas();}
+       WorkArea * get_work_area()const{return canvas_view_->get_work_area();}
+
+       //void on_user_click(synfig::Point point);
+
+//     bool run();
+};     // END of class StateDraw_Context
+
+
+/* === M E T H O D S ======================================================= */
+
+StateDraw::StateDraw():
+       Smach::state<StateDraw_Context>("draw")
+{
+       insert(event_def(EVENT_STOP,&StateDraw_Context::event_stop_handler));
+       insert(event_def(EVENT_REFRESH,&StateDraw_Context::event_refresh_handler));
+       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateDraw_Context::event_mouse_down_handler));
+       insert(event_def(EVENT_WORKAREA_STROKE,&StateDraw_Context::event_stroke));
+       insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateDraw_Context::event_refresh_tool_options));
+}
+
+StateDraw::~StateDraw()
+{
+}
+
+
+void
+StateDraw_Context::load_settings()
+{
+       String value;
+
+       if(settings.get_value("draw.id",value))
+               set_id(value);
+       else
+               set_id("NewDrawing");
+
+       if(settings.get_value("draw.pressure_width",value) && value=="0")
+               set_pressure_width_flag(false);
+       else
+               set_pressure_width_flag(true);
+
+       if(settings.get_value("draw.auto_loop",value) && value=="0")
+               set_auto_loop_flag(false);
+       else
+               set_auto_loop_flag(true);
+
+       if(settings.get_value("draw.auto_extend",value) && value=="0")
+               set_auto_extend_flag(false);
+       else
+               set_auto_extend_flag(true);
+
+       if(settings.get_value("draw.auto_link",value) && value=="0")
+               set_auto_link_flag(false);
+       else
+               set_auto_link_flag(true);
+
+       if(settings.get_value("draw.region",value) && value=="0")
+               set_region_flag(false);
+       else
+               set_region_flag(true);
+
+       if(settings.get_value("draw.outline",value) && value=="0")
+               set_outline_flag(false);
+       else
+               set_outline_flag(true);
+
+       if(settings.get_value("draw.auto_export",value) && value=="1")
+               set_auto_export_flag(true);
+       else
+               set_auto_export_flag(false);
+
+       if(settings.get_value("draw.min_pressure_on",value) && value=="0")
+               set_min_pressure_flag(false);
+       else
+               set_min_pressure_flag(true);
+
+       if(settings.get_value("draw.min_pressure",value))
+       {
+               Real n = atof(value.c_str());
+               set_min_pressure(n);
+       }else
+               set_min_pressure(0);
+
+       if(settings.get_value("draw.feather",value))
+       {
+               Real n = atof(value.c_str());
+               set_feather(n);
+       }else
+               set_feather(0);
+
+       if(settings.get_value("draw.gthreshold",value))
+       {
+               Real n = atof(value.c_str());
+               set_gthres(n);
+       }
+
+       if(settings.get_value("draw.lthreshold",value))
+       {
+               Real n = atof(value.c_str());
+               set_lthres(n);
+       }
+
+       if(settings.get_value("draw.localize",value) && value == "1")
+               set_local_error_flag(true);
+       else
+               set_local_error_flag(false);
+}
+
+void
+StateDraw_Context::save_settings()
+{
+       settings.set_value("draw.id",get_id().c_str());
+       settings.set_value("draw.pressure_width",get_pressure_width_flag()?"1":"0");
+       settings.set_value("draw.auto_loop",get_auto_loop_flag()?"1":"0");
+       settings.set_value("draw.auto_extend",get_auto_extend_flag()?"1":"0");
+       settings.set_value("draw.auto_link",get_auto_link_flag()?"1":"0");
+       settings.set_value("draw.region",get_region_flag()?"1":"0");
+       settings.set_value("draw.outline",get_outline_flag()?"1":"0");
+       settings.set_value("draw.auto_export",get_auto_export_flag()?"1":"0");
+       settings.set_value("draw.min_pressure",strprintf("%f",get_min_pressure()));
+       settings.set_value("draw.feather",strprintf("%f",get_feather()));
+       settings.set_value("draw.min_pressure_on",get_min_pressure_flag()?"1":"0");
+       settings.set_value("draw.gthreshold",strprintf("%f",get_gthres()));
+       settings.set_value("draw.lthreshold",strprintf("%f",get_lthres()));
+       settings.set_value("draw.localize",get_local_error_flag()?"1":"0");
+}
+
+void
+StateDraw_Context::increment_id()
+{
+       String id(get_id());
+       int number=1;
+       int digits=0;
+
+       if(id.empty())
+               id="Drawing";
+
+       // If there is a number
+       // already at the end of the
+       // id, then remove it.
+       if(id[id.size()-1]<='9' && id[id.size()-1]>='0')
+       {
+               // figure out how many digits it is
+               for (digits = 0;
+                        (int)id.size()-1 >= digits && id[id.size()-1-digits] <= '9' && id[id.size()-1-digits] >= '0';
+                        digits++)
+                       ;
+
+               String str_number;
+               str_number=String(id,id.size()-digits,id.size());
+               id=String(id,0,id.size()-digits);
+               // synfig::info("---------------- \"%s\"",str_number.c_str());
+
+               number=atoi(str_number.c_str());
+       }
+       else
+       {
+               number=1;
+               digits=3;
+       }
+
+       number++;
+
+       // Add the number back onto the id
+       {
+               const String format(strprintf("%%0%dd",digits));
+               id+=strprintf(format.c_str(),number);
+       }
+
+       // Set the ID
+       set_id(id);
+}
+
+StateDraw_Context::StateDraw_Context(CanvasView* canvas_view):
+       canvas_view_(canvas_view),
+       is_working(*canvas_view),
+       loop_(false),
+       prev_workarea_layer_status_(get_work_area()->get_allow_layer_clicks()),
+       settings(synfigapp::Main::get_selected_input_device()->settings()),
+       entry_id(),
+       checkbutton_pressure_width(_("Pressure Width")),
+       checkbutton_auto_loop(_("Auto Loop")),
+       checkbutton_auto_extend(_("Auto Extend")),
+       checkbutton_auto_link(_("Auto Link")),
+       checkbutton_region(_("Create Region BLine")),
+       checkbutton_outline(_("Create Outline BLine")),
+       checkbutton_auto_export(_("Auto Export")),
+       button_fill_last_stroke(_("Fill Last Stroke")),
+       adj_min_pressure(0,0,1,0.01,0.1),
+       spin_min_pressure(adj_min_pressure,0.1,3),
+       check_min_pressure(_("Min Pressure")),
+       adj_feather(0,0,10000,0.01,0.1),
+       spin_feather(adj_feather,0.01,4),
+       adj_globalthres(.70f,0.01,10000,0.01,0.1),
+       spin_globalthres(adj_globalthres,0.01,3),
+       adj_localthres(20,1,100000,0.1,1),
+       check_localerror(_("LocalError"))
+
+{
+       nested=0;
+       load_settings();
+
+       UpdateErrorBox();
+
+       options_table.attach(*manage(new Gtk::Label(_("Draw Tool"))),   0, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(entry_id,                                                                  0, 2,  1,  2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(checkbutton_outline,                                               0, 2,  2,  3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(checkbutton_region,                                                0, 2,  3,  4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(checkbutton_auto_loop,                                             0, 2,  4,  5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(checkbutton_auto_extend,                                   0, 2,  5,  6, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(checkbutton_auto_link,                                             0, 2,  6,  7, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(checkbutton_auto_export,                                   0, 2,  7,  8, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(checkbutton_pressure_width,                                0, 2,  8,  9, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(check_localerror,                                                  0, 2,  9, 10, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+
+       options_table.attach(check_min_pressure,                                                0, 1, 10, 11, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(spin_min_pressure,                                                 1, 2, 10, 11, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+
+       options_table.attach(*manage(new Gtk::Label(_("Smooth"))),              0, 1, 11, 12, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(spin_globalthres,                                                  1, 2, 11, 12, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+
+       options_table.attach(*manage(new Gtk::Label(_("Feather"))),     0, 1, 12, 13, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(spin_feather,                                                              1, 2, 12, 13, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+
+       //options_table.attach(button_fill_last_stroke, 0, 2, 13, 14, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+
+       button_fill_last_stroke.signal_pressed().connect(sigc::mem_fun(*this,&StateDraw_Context::fill_last_stroke));
+       check_localerror.signal_toggled().connect(sigc::mem_fun(*this,&StateDraw_Context::UpdateErrorBox));
+
+       options_table.show_all();
+       refresh_tool_options();
+       //App::dialog_tool_options->set_widget(options_table);
+       App::dialog_tool_options->present();
+
+
+       old_duckmask=get_work_area()->get_type_mask();
+       get_work_area()->set_type_mask(Duck::TYPE_ALL-Duck::TYPE_TANGENT-Duck::TYPE_WIDTH);
+
+       // Turn off layer clicking
+       get_work_area()->set_allow_layer_clicks(false);
+
+       // Turn off duck clicking
+       get_work_area()->set_allow_duck_clicks(false);
+
+       // clear out the ducks
+       //get_work_area()->clear_ducks();
+
+       // Refresh the work area
+       //get_work_area()->queue_draw();
+
+       // Hide the tables if they are showing
+       prev_table_status=get_canvas_view()->tables_are_visible();
+       //if(prev_table_status)get_canvas_view()->hide_tables();
+
+       // Disable the time bar
+       get_canvas_view()->set_sensitive_timebar(false);
+
+       // Connect a signal
+       //get_work_area()->signal_user_click().connect(sigc::mem_fun(*this,&studio::StateDraw_Context::on_user_click));
+
+       get_work_area()->set_cursor(Gdk::PENCIL);
+
+       App::toolbox->refresh();
+
+       refresh_ducks();
+}
+
+
+void StateDraw_Context::UpdateErrorBox()
+{
+       if(get_local_error_flag())
+       {
+               spin_globalthres.set_adjustment(adj_localthres);
+               spin_globalthres.set_value(adj_localthres.get_value());
+               spin_globalthres.set_increments(0.1,1);
+       }else
+       {
+               spin_globalthres.set_adjustment(adj_globalthres);
+               spin_globalthres.set_value(adj_globalthres.get_value());
+               spin_globalthres.set_increments(0.01,.1);
+       }
+
+       spin_globalthres.update();
+}
+
+void
+StateDraw_Context::refresh_tool_options()
+{
+       App::dialog_tool_options->clear();
+       App::dialog_tool_options->set_widget(options_table);
+       App::dialog_tool_options->set_local_name(_("Draw Tool"));
+       App::dialog_tool_options->set_name("draw");
+
+       App::dialog_tool_options->add_button(
+               Gtk::StockID("synfig-fill"),
+               _("Fill Last Stroke")
+       )->signal_clicked().connect(
+               sigc::mem_fun(
+                       *this,
+                       &StateDraw_Context::fill_last_stroke));
+}
+
+Smach::event_result
+StateDraw_Context::event_refresh_tool_options(const Smach::event& /*x*/)
+{
+       refresh_tool_options();
+       return Smach::RESULT_ACCEPT;
+}
+
+StateDraw_Context::~StateDraw_Context()
+{
+       save_settings();
+
+       App::dialog_tool_options->clear();
+
+       get_work_area()->set_type_mask(old_duckmask);
+
+       get_work_area()->reset_cursor();
+
+       // Restore layer clicking
+       get_work_area()->set_allow_layer_clicks(prev_workarea_layer_status_);
+
+       // Restore duck clicking
+       get_work_area()->set_allow_duck_clicks(true);
+
+       // Enable the time bar
+       get_canvas_view()->set_sensitive_timebar(true);
+
+       // Bring back the tables if they were out before
+       if(prev_table_status)get_canvas_view()->show_tables();
+
+       // Refresh the work area
+       get_work_area()->queue_draw();
+
+       App::toolbox->refresh();
+}
+
+Smach::event_result
+StateDraw_Context::event_stop_handler(const Smach::event& /*x*/)
+{
+       //throw Smach::egress_exception();
+       throw &state_normal;
+       return Smach::RESULT_OK;
+}
+
+Smach::event_result
+StateDraw_Context::event_refresh_handler(const Smach::event& /*x*/)
+{
+       refresh_ducks();
+       return Smach::RESULT_ACCEPT;
+}
+
+Smach::event_result
+StateDraw_Context::event_mouse_down_handler(const Smach::event& x)
+{
+       const EventMouse& event(*reinterpret_cast<const EventMouse*>(&x));
+       switch(event.button)
+       {
+       case BUTTON_LEFT:
+               {
+                       // Enter the stroke state to get the stroke
+                       get_canvas_view()->get_smach().push_state(&state_stroke);
+                       return Smach::RESULT_ACCEPT;
+               }
+
+       default:
+               return Smach::RESULT_OK;
+       }
+}
+
+#define SIMILAR_TANGENT_THRESHOLD      (0.2)
+
+struct debugclass
+{
+       synfig::String x;
+       debugclass(const synfig::String &x):x(x)
+       {
+//             synfig::warning(">>>>>>>>>>>>>>>>>>> "+x);
+       }
+       ~debugclass()
+       {
+//             synfig::warning("<<<<<<<<<<<<<<<<<<< "+x);
+       }
+};
+
+struct DepthCounter
+{
+       int &i;
+       DepthCounter(int &i):i(i) { i++; }
+       ~DepthCounter() { i--; }
+};
+
+Smach::event_result
+StateDraw_Context::event_stroke(const Smach::event& x)
+{
+//     debugclass debugger("StateDraw_Context::event_stroke(const Smach::event& x)");
+
+       const EventStroke& event(*reinterpret_cast<const EventStroke*>(&x));
+
+       assert(event.stroke_data);
+
+       get_work_area()->add_stroke(event.stroke_data,synfigapp::Main::get_outline_color());
+
+       if(nested==0)
+       {
+               DirtyTrap dirty_trap(get_work_area());
+               Smach::event_result result;
+               result=process_stroke(event.stroke_data,event.width_data,event.modifier&Gdk::CONTROL_MASK || event.modifier&Gdk::BUTTON2_MASK);
+               process_queue();
+               return result;
+       }
+
+       stroke_queue.push_back(pair<StrokeData,WidthData>(event.stroke_data,event.width_data));
+
+       return Smach::RESULT_ACCEPT;
+}
+
+bool
+StateDraw_Context::process_queue()
+{
+//     debugclass debugger("StateDraw_Context::process_queue()");
+       if(nested)
+               return true;
+       DepthCounter depth_counter(nested);
+       while(!stroke_queue.empty())
+       {
+               pair<StrokeData,WidthData> front(stroke_queue.front());
+               process_stroke(front.first,front.second);
+               stroke_queue.pop_front();
+       }
+       return false;
+}
+
+Smach::event_result
+StateDraw_Context::process_stroke(StrokeData stroke_data, WidthData width_data, bool region_flag)
+{
+//     debugclass debugger("StateDraw_Context::process_stroke");
+       DepthCounter depth_counter(nested);
+
+       const float radius(synfigapp::Main::get_bline_width().units(get_canvas()->rend_desc())+(abs(get_work_area()->get_pw())+abs(get_work_area()->get_ph()))*5);
+
+
+       // If we aren't using pressure width,
+       // then set all the width to 1
+       if(!get_pressure_width_flag())
+       {
+               std::list<synfig::Real>::iterator iter;
+               for(iter=width_data->begin();iter!=width_data->end();++iter)
+               {
+                       *iter=1.0;
+               }
+       }
+
+       //get_work_area()->add_stroke(event.stroke_data,synfigapp::Main::get_outline_color());
+       //stroke_list.push_back(event.stroke_data);
+       //refresh_ducks();
+
+       std::list<synfig::BLinePoint> bline;
+       bool loop_bline_flag(false);
+
+       //Changed by Adrian - use resident class :)
+       //synfigapp::convert_stroke_to_bline(bline, *event.stroke_data,*event.width_data, synfigapp::Main::get_bline_width());
+       blineconv.width = synfigapp::Main::get_bline_width().units(get_canvas()->rend_desc());
+
+       if(get_local_error_flag())
+       {
+               float pw = get_work_area()->get_pw();
+               float ph = get_work_area()->get_ph();
+
+               blineconv.pixelwidth = sqrt(pw*pw+ph*ph);
+               blineconv.smoothness = get_lthres();
+       }else
+       {
+               blineconv.pixelwidth = 1;
+               blineconv.smoothness = get_gthres();
+       }
+
+       blineconv(bline,*stroke_data,*width_data);
+
+       //Postprocess to require minimum pressure
+       if(get_min_pressure_flag())
+       {
+               synfigapp::BLineConverter::EnforceMinWidth(bline,get_min_pressure());
+       }
+
+       // If the start and end points are similar, then make them the same point
+       if (get_auto_loop_flag() &&
+               bline.size() > 2 &&
+               (bline.front().get_vertex() - bline.back().get_vertex()).mag() <= radius)
+       {
+               loop_bline_flag=true;
+               Vector tangent;
+               Real width(0);
+
+               while (bline.size() > 2 &&
+                          (bline.front().get_vertex() - bline.back().get_vertex()).mag() <= radius)
+               {
+                       tangent=bline.back().get_tangent1();
+                       width=bline.back().get_width();
+                       bline.pop_back();
+               }
+
+               if(abs(bline.front().get_tangent1().norm()*tangent.norm().perp())>SIMILAR_TANGENT_THRESHOLD)
+               {
+                       // If the tangents are not similar, then
+                       // split the tangents
+                       bline.front().set_split_tangent_flag(true);
+                       bline.front().set_tangent1(tangent);
+               }
+               else
+               {
+                       // If the tangents are similar, then set the tangent
+                       // to the average of the two
+                       bline.front().set_tangent((tangent+bline.front().get_tangent1())*0.5f);
+               }
+
+               // Add the widths of the two points
+               {
+                       Real tmp_width(bline.front().get_width()+width);
+                       tmp_width=tmp_width<=1?tmp_width:1;
+                       bline.front().set_width(tmp_width);
+               }
+       }
+
+       // If the bline only has one blinepoint, then there is nothing to do.
+       if(bline.size() < 2)
+       {
+               // hide the 'stroke' line we were drawing, unless the user
+               // explicitly requests that they are kept
+               if (!getenv("SYNFIG_KEEP_ABORTED_DRAW_LINES"))
+                       refresh_ducks();
+
+               return Smach::RESULT_OK;
+       }
+
+       if(region_flag)
+               return new_region(bline,radius);
+
+       return new_bline(bline,loop_bline_flag,radius);
+}
+
+Smach::event_result
+StateDraw_Context::new_bline(std::list<synfig::BLinePoint> bline,bool loop_bline_flag,float radius)
+{
+       synfigapp::SelectionManager::LayerList layer_list = get_canvas_view()->get_selection_manager()->get_selected_layers();
+
+       // Create the action group
+       synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Sketch BLine"));
+
+       bool shift_origin = false;
+       Vector shift_origin_vector;
+       bool join_start_no_extend=false,join_finish_no_extend=false;
+       synfigapp::ValueDesc start_duck_value_desc,finish_duck_value_desc;
+       bool extend_start=false,extend_finish=false,complete_loop=false;
+       bool extend_start_join_same=false,extend_start_join_different=false;
+       bool extend_finish_join_same=false,extend_finish_join_different=false;
+       int start_duck_index = 0,finish_duck_index = 0; // initialized to keep the compiler happy; shouldn't be needed though
+       ValueNode_BLine::Handle start_duck_value_node_bline=NULL,finish_duck_value_node_bline=NULL;
+
+       // Find any ducks at the start or end that we might attach to
+       // (this used to only run if we didn't just draw a loop - ie. !loop_bline_flag
+       // but having loops auto-connect can be useful as well)
+       if(get_auto_extend_flag() || get_auto_link_flag())
+       {
+               etl::handle<Duck> start_duck(get_work_area()->find_duck(bline.front().get_vertex(),radius,Duck::TYPE_VERTEX));
+               etl::handle<Duck> finish_duck(get_work_area()->find_duck(bline.back().get_vertex(),radius,Duck::TYPE_VERTEX));
+
+               // check whether the start of the new line extends an
+               // existing line.  this is only the case if the new
+               // line isn't a self-contained loop, and if the new
+               // line starts at one of the ends of an existing line
+               if(start_duck)do
+               {
+                       if(!(start_duck_value_desc=start_duck->get_value_desc()))break;
+                       if(loop_bline_flag)break; // loops don't extend anything
+                       if(!start_duck_value_desc.parent_is_value_node())break;
+                       start_duck_index=start_duck_value_desc.get_index(); // which point on the line did we start drawing at
+                       start_duck_value_node_bline=ValueNode_BLine::Handle::cast_dynamic(start_duck_value_desc.get_parent_value_node());
+                       if(!get_auto_extend_flag())break;
+
+                       // don't extend looped blines
+                       if(start_duck_value_node_bline&&!start_duck_value_node_bline->get_loop()&&
+                          // did we start drawing at either end of the line?
+                          (start_duck_index==0||start_duck_index==start_duck_value_node_bline->link_count()-1))
+                       {
+                               extend_start=true;
+                               shift_origin=true;
+                               shift_origin_vector=start_duck->get_origin();
+                       }
+               }while(0);
+
+               // check whether the end of the new line extends an
+               // existing line.  this is only the case if the new
+               // line isn't a self-contained loop, and if the new
+               // line ends at one of the ends of an existing line
+               if(finish_duck)do
+               {
+                       if(!(finish_duck_value_desc=finish_duck->get_value_desc()))break;
+                       if(loop_bline_flag)break;
+                       if(!finish_duck_value_desc.parent_is_value_node())break;
+                       finish_duck_index=finish_duck_value_desc.get_index();
+                       finish_duck_value_node_bline=ValueNode_BLine::Handle::cast_dynamic(finish_duck_value_desc.get_parent_value_node());
+                       if(!get_auto_extend_flag())break;
+
+                       // don't extend looped blines
+                       if(finish_duck_value_node_bline&&!finish_duck_value_node_bline->get_loop()&&
+                          (finish_duck_index==0||finish_duck_index==finish_duck_value_node_bline->link_count()-1))
+                       {
+                               if(extend_start)
+                               {
+                                       // we've started and finished drawing at the end of a bline.  we can't
+                                       // extend both blines, so unless we started and finished at the 2 ends
+                                       // of the same bline, only extend the one we started on
+                                       if(start_duck_value_node_bline==finish_duck_value_node_bline)
+                                               complete_loop=extend_finish=true;
+                               }else{
+                                       extend_finish=true;
+                                       shift_origin=true;
+                                       shift_origin_vector=finish_duck->get_origin();
+                               }
+                       }
+               }while(0);
+
+               // if the new line's start didn't extend an existing line,
+               // check whether it needs to be linked to an existing duck
+               if(!extend_start&&get_auto_link_flag()&&start_duck&&start_duck_value_desc)
+                       switch(start_duck_value_desc.get_value_type())
+                       {
+                       case synfig::ValueBase::TYPE_BLINEPOINT:
+                               start_duck_value_desc=synfigapp::ValueDesc(LinkableValueNode::Handle::cast_dynamic(start_duck_value_desc.get_value_node()),0);
+                               // fall through
+                       case synfig::ValueBase::TYPE_VECTOR:
+                               if (shift_origin && shift_origin_vector != start_duck->get_origin())
+                                       break;
+                               shift_origin = true;
+                               shift_origin_vector = start_duck->get_origin();
+                               get_canvas_interface()->auto_export(start_duck_value_desc);
+                               if (extend_finish)
+                                       if(start_duck_value_node_bline&&start_duck_value_node_bline==finish_duck_value_node_bline)
+                                               extend_finish_join_same=true;
+                                       else
+                                               extend_finish_join_different=true;
+                               else
+                                       join_start_no_extend=true;
+                               // fall through
+                       default:break;
+                       }
+
+               // if the new line's end didn't extend an existing line,
+               // check whether it needs to be linked to an existing duck
+               if(!extend_finish&&get_auto_link_flag()&&finish_duck&&finish_duck_value_desc)
+                       switch(finish_duck_value_desc.get_value_type())
+                       {
+                       case synfig::ValueBase::TYPE_BLINEPOINT:
+                               finish_duck_value_desc=synfigapp::ValueDesc(LinkableValueNode::Handle::cast_dynamic(finish_duck_value_desc.get_value_node()),0);
+                               // fall through
+                       case synfig::ValueBase::TYPE_VECTOR:
+                               if (shift_origin && shift_origin_vector != finish_duck->get_origin())
+                                       break;
+                               shift_origin = true;
+                               shift_origin_vector = finish_duck->get_origin();
+                               get_canvas_interface()->auto_export(finish_duck_value_desc);
+                               if(extend_start)
+                                       if(finish_duck_value_node_bline&&start_duck_value_node_bline==finish_duck_value_node_bline)
+                                               extend_start_join_same=true;
+                                       else
+                                               extend_start_join_different=true;
+                               else
+                                       join_finish_no_extend=true;
+                               // fall through
+                       default:break;
+                       }
+       }
+
+       ValueNode_BLine::Handle value_node;
+       std::list<synfig::BLinePoint> trans_bline;
+
+       {
+               std::list<synfig::BLinePoint>::iterator iter;
+               const synfig::TransformStack& transform(get_canvas_view()->get_curr_transform_stack());
+
+               for(iter=bline.begin();iter!=bline.end();++iter)
+               {
+                       BLinePoint bline_point(*iter);
+                       Point new_vertex(transform.unperform(bline_point.get_vertex()));
+
+                       bline_point.set_tangent1(
+                               transform.unperform(
+                                       bline_point.get_tangent1()+bline_point.get_vertex()
+                               ) -new_vertex
+                       );
+
+                       bline_point.set_tangent2(
+                               transform.unperform(
+                                       bline_point.get_tangent2()+bline_point.get_vertex()
+                               ) -new_vertex
+                       );
+
+                       if (shift_origin)
+                               new_vertex=new_vertex-shift_origin_vector;
+
+                       bline_point.set_vertex(new_vertex);
+
+                       trans_bline.push_back(bline_point);
+               }
+               value_node=ValueNode_BLine::create(synfig::ValueBase(trans_bline,loop_bline_flag));
+
+               Canvas::Handle canvas(get_canvas_view()->get_canvas());
+               Layer::Handle layer(get_canvas_view()->get_selection_manager()->get_selected_layer());
+               if (layer) canvas=layer->get_canvas();
+               value_node->set_member_canvas(canvas);
+       }
+
+       Smach::event_result result;
+       synfig::ValueNode_DynamicList::ListEntry source;
+
+       // the new line's start extends an existing line
+       if(extend_start)
+       {
+               int target_offset = 0;
+               if(complete_loop)trans_bline.pop_back();
+               trans_bline.pop_front();
+               if(start_duck_index==0)
+               {       // We need to reverse the BLine first.
+                       reverse_bline(trans_bline);
+                       result=extend_bline_from_begin(start_duck_value_node_bline,trans_bline,complete_loop);
+                       source=start_duck_value_node_bline->list.front();
+                       target_offset=trans_bline.size();
+               }
+               else
+               {
+                       result=extend_bline_from_end(start_duck_value_node_bline,trans_bline,complete_loop);
+                       source=start_duck_value_node_bline->list.back();
+               }
+
+               if(extend_start_join_different)
+                       LinkableValueNode::Handle::cast_dynamic(source.value_node)->
+                               set_link("point",finish_duck_value_desc.get_value_node());
+               else if(extend_start_join_same)
+                       LinkableValueNode::Handle::cast_dynamic(source.value_node)->
+                               set_link("point",synfigapp::ValueDesc(LinkableValueNode::Handle::cast_dynamic(start_duck_value_node_bline->
+                                                                                                       list[target_offset+finish_duck_index].value_node),0).get_value_node());
+               return result;
+       }
+
+       // the new line's end extends an existing line
+       if(extend_finish)
+       {
+               int target_offset = 0;
+               trans_bline.pop_back();
+               if(finish_duck_index==0)
+               {
+                       result=extend_bline_from_begin(finish_duck_value_node_bline,trans_bline,false);
+                       source=finish_duck_value_node_bline->list.front();
+                       target_offset=trans_bline.size();
+               }
+               else
+               {       // We need to reverse the BLine first.
+                       reverse_bline(trans_bline);
+                       result=extend_bline_from_end(finish_duck_value_node_bline,trans_bline,false);
+                       source=finish_duck_value_node_bline->list.back();
+               }
+
+               if(extend_finish_join_different)
+                       LinkableValueNode::Handle::cast_dynamic(source.value_node)->
+                               set_link("point",start_duck_value_desc.get_value_node());
+               else if(extend_finish_join_same)
+                       LinkableValueNode::Handle::cast_dynamic(source.value_node)->
+                               set_link("point",synfigapp::ValueDesc(LinkableValueNode::Handle::cast_dynamic(finish_duck_value_node_bline->
+                                                                                                       list[target_offset+start_duck_index].value_node),0).get_value_node());
+               return result;
+       }
+
+       if (join_start_no_extend)
+               LinkableValueNode::Handle::cast_dynamic(value_node->list.front().value_node)->
+                 set_link("point",start_duck_value_desc.get_value_node());
+
+       if (join_finish_no_extend)
+               LinkableValueNode::Handle::cast_dynamic(value_node->list.back().value_node)->
+                 set_link("point",finish_duck_value_desc.get_value_node());
+
+       if(get_auto_export_flag())
+               if (!get_canvas_interface()->add_value_node(value_node,get_id()))
+               {
+                       /* it's no big deal, is it?  let's keep the shape anyway */
+                       // get_canvas_view()->get_ui_interface()->error(_("Unable to add value node"));
+                       // group.cancel();
+                       // increment_id();
+                       // return Smach::RESULT_ERROR;
+               }
+
+       last_stroke=value_node;
+       last_stroke_id=get_id();
+
+       {
+               // Create the layer(s)
+               Layer::Handle layer;
+               Canvas::Handle canvas(get_canvas_view()->get_canvas());
+               int depth(0);
+
+               // we are temporarily using the layer to hold something
+               layer=get_canvas_view()->get_selection_manager()->get_selected_layer();
+               if(layer)
+               {
+                       depth=layer->get_depth();
+                       canvas=layer->get_canvas();
+               }
+
+               // fill_last_stroke() will take care of clearing the selection if we're calling it
+               if(get_outline_flag() && get_region_flag())
+               {
+                       if (fill_last_stroke_and_unselect_other_layers() == Smach::RESULT_ERROR)
+                       {
+                               get_canvas_view()->get_selection_manager()->set_selected_layers(layer_list);
+                               get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
+                               group.cancel();
+                               return Smach::RESULT_ERROR;
+                       }
+               }
+               else
+                       get_canvas_interface()->get_selection_manager()->clear_selected_layers();
+
+               //int number(synfig::UniqueID().get_uid());
+
+               synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
+
+               // if they're both defined, we'll add the region later
+               if(get_outline_flag())
+               {
+                       layer=get_canvas_interface()->add_layer_to("outline",canvas,depth);
+                       if (!layer)
+                       {
+                               get_canvas_view()->get_selection_manager()->set_selected_layers(layer_list);
+                               get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
+                               group.cancel();
+                               return Smach::RESULT_ERROR;
+                       }
+                       layer->set_description(get_id()+_(" Outline"));
+               }
+               else
+               {
+                       layer=get_canvas_interface()->add_layer_to("region",canvas,depth);
+                       if (!layer)
+                       {
+                               get_canvas_view()->get_selection_manager()->set_selected_layers(layer_list);
+                               get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
+                               group.cancel();
+                               return Smach::RESULT_ERROR;
+                       }
+                       layer->set_description(get_id()+_(" Region"));
+               }
+
+               if(get_feather())
+               {
+                       layer->set_param("feather",get_feather());
+                       get_canvas_interface()->signal_layer_param_changed()(layer,"feather");
+               }
+               assert(layer);
+               //layer->set_description(strprintf("Stroke %d",number));
+               //get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
+
+               if (shift_origin)
+                       get_canvas_interface()->
+                         change_value(synfigapp::ValueDesc(layer,"origin"),shift_origin_vector);
+
+               synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
+
+               assert(action);
+
+               action->set_param("canvas",get_canvas());
+               action->set_param("canvas_interface",get_canvas_interface());
+               action->set_param("layer",layer);
+               if(!action->set_param("param",String("bline")))
+                       synfig::error("LayerParamConnect didn't like \"param\"");
+               if(!action->set_param("value_node",ValueNode::Handle(value_node)))
+                       synfig::error("LayerParamConnect didn't like \"value_node\"");
+
+               if(!get_canvas_interface()->get_instance()->perform_action(action))
+               {
+                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
+                       group.cancel();
+                       increment_id();
+                       //refresh_ducks();
+                       return Smach::RESULT_ERROR;
+               }
+               layer_list.push_back(layer);
+               get_canvas_view()->get_selection_manager()->set_selected_layers(layer_list);
+               //refresh_ducks();
+       }
+
+       increment_id();
+       return Smach::RESULT_ACCEPT;
+}
+
+#ifdef _DEBUG
+static void
+debug_show_vertex_list(int iteration, std::list<synfigapp::ValueDesc>& vertex_list,
+                                          std::string title, int current)
+{
+       std::list<synfigapp::ValueDesc>::iterator i = vertex_list.begin();
+       printf("\n%s\n  ----- iter %d : ", title.c_str(), iteration);
+       int c = 0;
+       synfig::LinkableValueNode::Handle last = 0;
+       int start = -1;
+       int index;
+       int prev;
+       int dir = 0;
+       bool started = false;
+       for(;i!=vertex_list.end();i++,c++)
+       {
+               synfigapp::ValueDesc value_desc(*i);
+
+               if (value_desc.parent_is_value_node()) {
+                       if(value_desc.parent_is_linkable_value_node())
+                       {
+                               index = value_desc.get_index();
+                               // printf("<%d>", index);
+                               if (last == synfig::LinkableValueNode::Handle::cast_reinterpret(value_desc.get_parent_value_node()))
+                               {
+                                       // printf("\n%s:%d\n", __FILE__, __LINE__);
+                                       if (start != -1)
+                                       {
+                                               // printf("\n%s:%d\n", __FILE__, __LINE__);
+                                               if (c == current)
+                                               {
+                                                       // printf("\n%s:%d\n", __FILE__, __LINE__);
+                                                       if (dir)
+                                                       {
+                                                               if (started) printf(", "); else started = true;
+                                                               printf("%d--%d", start, prev);
+                                                       }
+                                                       else
+                                                       {
+                                                               if (started) printf(", "); else started = true;
+                                                               printf("%d", start);
+                                                       }
+                                                       printf(", *%d*", index);
+                                                       start = -1;
+                                               }
+                                               else if (dir == 0)
+                                               {
+                                                       // printf("\n%s:%d\n", __FILE__, __LINE__);
+                                                       if (index == start + 1)
+                                                       {
+                                                               // printf("\n%s:%d\n", __FILE__, __LINE__);
+                                                               dir = 1;
+                                                               prev = index;
+                                                       }
+                                                       else if (index == start - 1)
+                                                       {
+                                                               // printf("\n%s:%d\n", __FILE__, __LINE__);
+                                                               dir = -1;
+                                                               prev = index;
+                                                       }
+                                                       else
+                                                       {
+                                                               if (started) printf(", "); else started = true;
+                                                               printf("%d", start);
+                                                               start = index;
+                                                       }
+                                               }
+                                               else if (index == prev + dir)
+                                               {
+                                                       // printf("\n%s:%d\n", __FILE__, __LINE__);
+                                                       prev = index;
+                                               }
+                                               else
+                                               {
+                                                       // printf("\n%s:%d\n", __FILE__, __LINE__);
+                                                       if (started) printf(", "); else started = true;
+                                                       if (prev != start)
+                                                               printf("%d--%d", start, prev);
+                                                       else
+                                                               printf("%d", start);
+                                                       // printf("\n%s:%d\n", __FILE__, __LINE__);
+                                                       start = index;
+                                                       dir = 0;
+                                               }
+                                       }
+                                       else
+                                       {
+                                               // printf("\n%s:%d\n", __FILE__, __LINE__);
+                                               if (c == current)
+                                               {
+                                                       if (started) printf(", "); else started = true;
+                                                       printf("*%d*", index);
+                                               }
+                                               else
+                                               {
+                                                       // printf("\n%s:%d\n", __FILE__, __LINE__);
+                                                       start = index;
+                                                       dir = 0;
+                                               }
+                                       }
+                               }
+                               else
+                               {
+                                       // printf("\n%s:%d\n", __FILE__, __LINE__);
+                                       if (last)
+                                       {
+                                               // printf("\n%s:%d\n", __FILE__, __LINE__);
+                                               if (start != -1)
+                                               {
+                                                       if (started) printf(", "); else started = true;
+                                                       if (dir != 0)
+                                                               printf("%d--%d", start, prev);
+                                                       else
+                                                               printf("%d", start);
+                                               }
+                                               // printf("\n%s:%d\n", __FILE__, __LINE__);
+                                               printf(") ");
+                                       }
+                                       // printf("\n%s:%d\n", __FILE__, __LINE__);
+                                       last = synfig::LinkableValueNode::Handle::cast_reinterpret(value_desc.get_parent_value_node());
+                                       printf("%d:(", synfig::LinkableValueNode::Handle::cast_reinterpret(value_desc.get_parent_value_node())->link_count());
+                                       started = false;
+                                       // printf("\n%s:%d\n", __FILE__, __LINE__);
+                                       if (c == current)
+                                       {
+                                               start = -1;
+                                               printf("*%d*", index);
+                                       }
+                                       else
+                                       {
+                                               // printf("\n%s:%d\n", __FILE__, __LINE__);
+                                               start = index;
+                                               dir = 0;
+                                       }
+                                       // printf("\n%s:%d\n", __FILE__, __LINE__);
+                               }
+                               // printf("\n%s:%d\n", __FILE__, __LINE__);
+                       }
+                       else if (last)
+                               if (last) printf("?!) ");
+               }
+               else
+               {
+                       last = 0;
+                       printf("? ");
+               }
+       }
+       if (last)
+       {
+               if (started) printf(", "); else started = true;
+               if (start != -1)
+               {
+                       if (dir != 0)
+                               printf("%d--%d", start, prev);
+                       else
+                               printf("%d", start);
+               }
+               printf(")");
+       }
+       printf("\n");
+}
+#else  // _DEBUG
+#define debug_show_vertex_list(a,b,c,d)
+#endif // _DEBUG
+
+Smach::event_result
+StateDraw_Context::new_region(std::list<synfig::BLinePoint> bline, synfig::Real radius)
+{
+       // Create the action group
+       synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Define Region"));
+
+       std::list<synfigapp::ValueDesc> vertex_list;
+
+       printf("new_region with %zd bline points\n", bline.size());
+
+       // First we need to come up with a rough list of
+       // BLinePoints that we are going to be using to
+       // define our region.
+       {
+               std::list<synfig::BLinePoint>::iterator iter;
+               for(iter=bline.begin();iter!=bline.end();++iter)
+               {
+                       etl::handle<Duck> duck(get_work_area()->find_duck(iter->get_vertex(),0,Duck::TYPE_VERTEX));
+
+                       if(!duck)
+                       {
+                               synfig::info(__FILE__":%d: Nothing to enclose!",__LINE__);
+                               return Smach::RESULT_OK;
+                       }
+
+                       assert(duck->get_type()==Duck::TYPE_VERTEX);
+
+                       synfigapp::ValueDesc value_desc(duck->get_value_desc());
+
+                       if(!value_desc)
+                       {
+                               synfig::info(__FILE__":%d: Got a hit, but no ValueDesc on this duck",__LINE__);
+                               continue;
+                       }
+
+                       switch(value_desc.get_value_type())
+                       {
+                       case synfig::ValueBase::TYPE_BLINEPOINT:
+                               //if(vertex_list.empty() || value_desc!=vertex_list.back())
+                               vertex_list.push_back(value_desc);
+                               assert(vertex_list.back().is_valid());
+
+                               break;
+                       default:
+                               break;
+                       }
+               }
+       }
+
+       assert(vertex_list.back().is_valid());
+
+       printf("vertex list with %zd bline points\n", vertex_list.size());
+
+       // Remove any duplicates
+       {
+       }
+
+       ValueNode_BLine::Handle value_node_bline;
+
+       // Now we need to test for the trivial case,
+       // which is where all of the vertices
+       // come from one BLine.
+       if(vertex_list.front().parent_is_linkable_value_node())
+       {
+               bool trivial_case(true);
+               ValueNode::Handle trivial_case_value_node;
+
+               trivial_case_value_node=vertex_list.front().get_parent_value_node();
+
+               std::list<synfigapp::ValueDesc>::iterator iter;
+               for(iter=vertex_list.begin();iter!=vertex_list.end();++iter)
+               {
+                       if(trivial_case_value_node!=iter->get_parent_value_node())
+                       {
+                               trivial_case=false;
+                               break;
+                       }
+               }
+
+               // \todo - re-enable this code
+               if(trivial_case && false)
+               {
+                       synfig::info("all points are on the same bline, so just fill that line");
+                       value_node_bline=ValueNode_BLine::Handle::cast_dynamic(trivial_case_value_node);
+
+                       synfig::info("the line has %d vertices", value_node_bline->link_count());
+
+                       if(value_node_bline->link_count() <= 2)
+                       {
+                               synfig::info(__FILE__":%d: Vertex list too small to make region.",__LINE__);
+                               return Smach::RESULT_OK;
+                       }
+               }
+       }
+
+       if(!value_node_bline)
+               if(vertex_list.size()<=2)
+               {
+                       synfig::info(__FILE__":%d: Vertex list too small to make region.",__LINE__);
+                       return Smach::RESULT_OK;
+               }
+
+       // Now we need to clean the list of vertices up
+       // a bit. This includes inserting missing vertices
+       // and removing extraneous ones.
+       // We can do this in multiple passes.
+       if(!value_node_bline)
+       {
+               debug_show_vertex_list(0, vertex_list, "before shifting stuff", -1);
+               // rearrange the list so that the first and last node are on different blines
+               std::list<synfigapp::ValueDesc>::iterator iter, start;
+               ValueNode::Handle last_value_node = vertex_list.back().get_parent_value_node();
+               for(iter = vertex_list.begin(); iter!=vertex_list.end(); iter++)
+                       if (iter->get_parent_value_node() != last_value_node)
+                       {
+                               vertex_list.insert(vertex_list.end(), vertex_list.begin(), iter);
+                               vertex_list.erase(vertex_list.begin(), iter);
+                               break;
+                       }
+
+               debug_show_vertex_list(0, vertex_list, "before detecting direction and limits", -1);
+               // rearrange the list so that the first and last node are on different blines
+               iter = vertex_list.begin();
+               while (iter!=vertex_list.end())
+               {
+                       // make a note of which bline we're looking at
+                       ValueNode::Handle parent_value_node = iter->get_parent_value_node();
+                       start = iter;
+                       int points_in_line = synfig::LinkableValueNode::Handle::cast_reinterpret(parent_value_node)->link_count();
+                       bool looped = (*parent_value_node)(get_time()).get_loop();
+                       int this_index, last_index = iter->get_index();
+                       int min_index = last_index, max_index = last_index;
+                       bool whole;
+                       int direction = 0;
+
+                       // printf("there are %d points in this line - first is index %d\n", points_in_line, last_index);
+
+                       // while we're looking at the same bline, keep going
+                       iter++;
+                       while (iter != vertex_list.end() && iter->get_parent_value_node() == parent_value_node)
+                       {
+                               this_index = iter->get_index();
+                               // printf("index went from %d to %d\n", last_index, this_index);
+                               if (looped)
+                               {
+                                       if (this_index - last_index > points_in_line/2)
+                                               while (this_index - last_index > points_in_line/2)
+                                                       this_index -= points_in_line;
+                                       else if (last_index - this_index > points_in_line/2)
+                                               while (last_index - this_index > points_in_line/2)
+                                                       this_index += points_in_line;
+                               }
+
+                               if (this_index < min_index) min_index = this_index;
+                               if (this_index > max_index) max_index = this_index;
+
+                               // printf("so let's imagine index went from %d to %d\n", last_index, this_index);
+                               if (this_index > last_index)
+                                       direction++;
+                               else if (this_index < last_index)
+                                       direction--;
+
+                               last_index = this_index;
+                               iter++;
+                       }
+
+                       // printf("min %d and max %d\n", min_index, max_index);
+                       whole = max_index - min_index >= points_in_line;
+                       min_index = (min_index % points_in_line + points_in_line) % points_in_line;
+                       max_index = (max_index % points_in_line + points_in_line) % points_in_line;
+                       // they drew around a shape more than once - what's the start/end point?  does it matter?
+                       if (whole) min_index = max_index = (min_index + max_index) / 2;
+                       // printf("processed min %d max %d whole %d\n", min_index, max_index, whole);
+
+                       if (direction < 0)
+                       {
+                               if (whole)
+                               {
+                                       // printf("whole (down) (%d) ", min_index);
+                                       for (int i = min_index; i >= 0; i--)
+                                       {
+                                               // printf("%d ", i);
+                                               vertex_list.insert(start, synfigapp::ValueDesc(parent_value_node, i));
+                                       }
+                                       for (int i = points_in_line - 1; i >= min_index; i--)
+                                       {
+                                               // printf("%d ", i);
+                                               vertex_list.insert(start, synfigapp::ValueDesc(parent_value_node, i));
+                                       }
+                               }
+                               else
+                               {
+                                       // printf("part (down) (%d -> %d) ", max_index, min_index);
+                                       for (int i = max_index; i != min_index; i--)
+                                       {
+                                               if (i == -1) i = points_in_line - 1;
+                                               // printf("%d ", i);
+                                               vertex_list.insert(start, synfigapp::ValueDesc(parent_value_node, i));
+                                       }
+                                       vertex_list.insert(start, synfigapp::ValueDesc(parent_value_node, min_index));
+                               }
+                       }
+                       else
+                       {
+                               if (whole)
+                               {
+                                       // printf("whole (%d) ", min_index);
+                                       for (int i = min_index; i < points_in_line; i++)
+                                       {
+                                               // printf("%d ", i);
+                                               vertex_list.insert(start, synfigapp::ValueDesc(parent_value_node, i));
+                                       }
+                                       for (int i = 0; i <= min_index; i++)
+                                       {
+                                               // printf("%d ", i);
+                                               vertex_list.insert(start, synfigapp::ValueDesc(parent_value_node, i));
+                                       }
+                               }
+                               else
+                               {
+                                       // printf("part (%d -> %d) ", min_index, max_index);
+                                       for (int i = min_index; i != max_index; i++)
+                                       {
+                                               if (i == points_in_line) i = 0;
+                                               // printf("%d ", i);
+                                               vertex_list.insert(start, synfigapp::ValueDesc(parent_value_node, i));
+                                       }
+                                       vertex_list.insert(start, synfigapp::ValueDesc(parent_value_node, max_index));
+                               }
+                       }
+                       // printf("\n");
+                       // debug_show_vertex_list(0, vertex_list, "after insert", -1);
+                       vertex_list.erase(start, iter);
+                       // debug_show_vertex_list(0, vertex_list, "after delete", -1);
+               }
+
+               debug_show_vertex_list(0, vertex_list, "continuous vertices", -1);
+
+               // \todo reenable or delete this section
+               int i=100;
+               for(bool done=false;!done && i<30;i++)
+               {
+                       debug_show_vertex_list(i, vertex_list, "in big loop", -1);
+
+                       // Set done to "true" for now. If
+                       // any updates are performed, we will
+                       // change it back to false.
+                       done=true;
+
+                       std::list<synfigapp::ValueDesc>::iterator prev,next;
+                       prev=vertex_list.end();prev--;  // Set prev to the last ValueDesc
+                       next=vertex_list.begin();
+                       iter=next++; // Set iter to the first value desc, and next to the second
+
+                       int current = 0;
+                       for(;iter!=vertex_list.end();prev=iter,iter++,next++,current++)
+                       {
+                               // we need to be able to erase(next) and can't do that if next is end()
+                               if (next == vertex_list.end()) next = vertex_list.begin();
+                               debug_show_vertex_list(i, vertex_list, "in loop around vertices", current);
+                               synfigapp::ValueDesc value_prev(*prev);
+                               synfigapp::ValueDesc value_desc(*iter);
+                               synfigapp::ValueDesc value_next(*next);
+
+                               assert(value_desc.is_valid());
+                               assert(value_next.is_valid());
+                               assert(value_prev.is_valid());
+
+                               // synfig::info("-------");
+                               // synfig::info(__FILE__":%d: value_prev 0x%08X:%d",__LINE__,value_prev.get_parent_value_node().get(),value_prev.get_index());
+                               // synfig::info(__FILE__":%d: value_desc 0x%08X:%d",__LINE__,value_desc.get_parent_value_node().get(),value_desc.get_index());
+                               // synfig::info(__FILE__":%d: value_next 0x%08X:%d",__LINE__,value_next.get_parent_value_node().get(),value_next.get_index());
+
+                               /*
+                                 if(value_prev.parent_is_value_node() && value_desc.parent_is_value_node() && value_next.parent_is_value_node())
+                                 {
+                                 // Remove random extraneous vertices
+                                 if(value_prev.get_parent_value_node()==value_next.get_parent_value_node() &&
+                                 value_prev.get_parent_value_node()!=value_desc.get_parent_value_node())
+                                 {
+                                 vertex_list.erase(iter);
+                                 done=false;
+                                 break;
+                                 }
+                                 }
+                               */
+
+                               // // Remove duplicate vertices
+
+                               // // if previous is the same as current or
+                               // //    current is the same as next, remove current
+                               // if(value_prev.get_value_node()==value_desc.get_value_node() ||
+                               //    value_desc.get_value_node()==value_next.get_value_node())
+                               // {
+                               //      vertex_list.erase(iter);
+                               //      done=false;
+                               //      printf("erased node - i = %d\n", i);
+                               //      break;
+                               // }
+
+                               // // if previous is the same as next, remove previous?  or next?
+                               // if(value_prev.get_value_node()==value_next.get_value_node())
+                               // {
+                               //      vertex_list.erase(next);
+                               //      // vertex_list.erase(prev);
+                               //      done=false;
+                               //      printf("erased node - i = %d\n", i);
+                               //      break;
+                               // }
+
+                               // if 'this' and 'next' both have parents
+                               if (value_desc.parent_is_value_node() && value_next.parent_is_value_node())
+                               {
+                                       // if they are both on the same bline - this has been handled by new code above
+                                       if (value_desc.get_parent_value_node() == value_next.get_parent_value_node())
+                                       {
+                                               // // if (next != vertex_list.end())
+                                               // {
+                                               //      printf("parent loop is %d and node loop is ??\n",
+                                               //                 (*(value_desc.get_parent_value_node()))(get_time()).get_loop()
+                                               //                 // value_desc.get_value_node().get_loop(),
+                                               //              );
+                                               //
+                                               //      // Fill in missing vertices
+                                               //      // \todo take loops into account: seeing (15, 2, 3, 4) probably means that (0, 1) is missing, not 14 through 3
+                                               //      if(value_desc.get_index()<value_next.get_index()-1)
+                                               //      {
+                                               //              debug_show_vertex_list(i, vertex_list,
+                                               //                                                         strprintf("same parent, different points this %d < next-1 %d",
+                                               //                                                                               value_desc.get_index(), ((value_next.get_index()-1))),
+                                               //                                                         current);
+                                               //              for (int index = value_desc.get_index()+1; index < value_next.get_index(); index++)
+                                               //              {
+                                               //                      printf("inserting up %d\n", index);
+                                               //                      vertex_list.insert(next, synfigapp::ValueDesc(value_desc.get_parent_value_node(), index));
+                                               //              }
+                                               //              debug_show_vertex_list(i, vertex_list, "new list", current);
+                                               //              done=false;
+                                               //              break;
+                                               //      }
+                                               //      if(value_next.get_index()<value_desc.get_index()-1)
+                                               //      {
+                                               //              debug_show_vertex_list(i, vertex_list,
+                                               //                                                         strprintf("same parent, different points next %d < this-1 %d",
+                                               //                                                                               value_next.get_index(), ((value_desc.get_index()-1))),
+                                               //                                                         current);
+                                               //              for (int index = value_desc.get_index()-1; index > value_next.get_index(); index--)
+                                               //              {
+                                               //                      printf("inserting down %d\n", index);
+                                               //                      vertex_list.insert(next, synfigapp::ValueDesc(value_desc.get_parent_value_node(), index));
+                                               //              }
+                                               //              debug_show_vertex_list(i, vertex_list, "new list", current);
+                                               //              done=false;
+                                               //              break;
+                                               //      }
+                                               // }
+                                       }
+                                       // 'this' and 'next' have different parents
+                                       else
+                                       {
+                                               ValueNode::Handle v1 = value_desc.get_value_node();
+                                               ValueNode::Handle v2 = value_desc.get_parent_value_node();
+                                               if (v1 == v2)
+                                                       printf("same\n");
+                                               else
+                                                       printf("different\n");
+
+                                               if (value_desc.get_value_node() != value_next.get_value_node())
+                                               {
+                                                       // Ensure that connections between blines are properly connected
+                                                       BLinePoint vertex(value_desc.get_value(get_time()).get(BLinePoint()));
+                                                       BLinePoint vertex_next(value_next.get_value(get_time()).get(BLinePoint()));
+
+                                                       //synfig::info("--------");
+                                                       //synfig::info(__FILE__":%d: vertex: [%f, %f]",__LINE__,vertex.get_vertex()[0],vertex.get_vertex()[1]);
+                                                       //synfig::info(__FILE__":%d: vertex_next: [%f, %f]",__LINE__,vertex_next.get_vertex()[0],vertex_next.get_vertex()[1]);
+
+                                                       // if this vertex is close to the next one, replace this vertex with a new one
+                                                       // and erase the next one
+                                                       printf("this point is %5.2f from the next point - compare with %5.2f\n",
+                                                                  (vertex.get_vertex()-vertex_next.get_vertex()).mag_squared(),
+                                                                  radius*radius);
+                                                       if((vertex.get_vertex()-vertex_next.get_vertex()).mag_squared()<radius*radius)
+                                                       {
+                                                               printf("in one - it's close\n");
+                                                               ValueNode_Composite::Handle value_node;
+                                                               ValueNode_Composite::Handle value_node_next;
+                                                               value_node=ValueNode_Composite::Handle::cast_dynamic(value_desc.get_value_node().clone());
+                                                               value_node_next=ValueNode_Composite::Handle::cast_dynamic(value_next.get_value_node().clone());
+                                                               if(!value_node || !value_node_next)
+                                                               {
+                                                                       synfig::info(__FILE__":%d: Unable to properly connect blines.",__LINE__);
+                                                                       continue;
+                                                               }
+                                                               // \todo if next isn't split, don't we want to copy its 'Tangent 1' instead?
+                                                               value_node->set_link("t2",value_node_next->get_link("t2"));
+                                                               value_node->set_link("split",ValueNode_Const::create(true));
+
+                                                               // get_canvas_interface()->auto_export(value_node);
+                                                               printf("exporting\n");
+                                                               get_canvas_interface()->add_value_node(value_node,value_node->get_id() + strprintf("foo %d", rand()));
+
+                                                               assert(value_node->is_exported());
+                                                               // replace 'this' with the new valuenode
+                                                               *iter=synfigapp::ValueDesc(get_canvas(),value_node->get_id());
+                                                               printf("erasing next\n");
+                                                               printf("erasing next point\n");
+                                                               vertex_list.erase(next);
+                                                               done=false;
+                                                               break;
+                                                       } // this vertex isn't close to the next one
+                                                       else if (value_prev.parent_is_value_node())
+                                                       {
+                                                               printf("in two - it's far\n");
+                                                               // \todo this only makes sense if prev is on the same bline
+                                                               printf("this is index %d\n", value_desc.get_index());
+                                                               printf("prev is index %d\n", value_prev.get_index());
+                                                               bool positive_trend(value_desc.get_index()>value_prev.get_index());
+
+                                                               if(positive_trend)
+                                                               {
+                                                                       printf("positive trend\n");
+                                                                       printf("comparing index %d < link_count()-1 = %d-1 = %d\n",
+                                                                                  value_desc.get_index(),
+                                                                                  LinkableValueNode::Handle::cast_static(value_desc.get_parent_value_node())->link_count(),
+                                                                                  LinkableValueNode::Handle::cast_static(value_desc.get_parent_value_node())->link_count()-1);
+                                                                       if (value_desc.get_index()<LinkableValueNode::Handle::cast_static(value_desc.get_parent_value_node())->link_count()-1)
+                                                                       {
+                                                                               printf("in two - b\n");
+                                                                               printf("inserting node with index %d\n", value_desc.get_index()+1);
+                                                                               vertex_list.insert(next,
+                                                                                                                  synfigapp::ValueDesc(value_desc.get_parent_value_node(),
+                                                                                                                                                               value_desc.get_index()+1));
+                                                                               done=false;
+                                                                               break;
+                                                                       }
+                                                               }
+                                                               else // !positive_trend
+                                                               {
+                                                                       printf("negative trend\n");
+                                                                       if(value_desc.get_index()>0)
+                                                                       {
+                                                                               printf("in two - a\n");
+                                                                               printf("inserting node on this line with index %d\n",
+                                                                                          value_desc.get_index()-1);
+                                                                               vertex_list.insert(next,
+                                                                                                                  synfigapp::ValueDesc(value_desc.get_parent_value_node(),
+                                                                                                                                                               value_desc.get_index()-1));
+                                                                               done=false;
+                                                                               break;
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+
+               if(vertex_list.size()<=2)
+               {
+                       synfig::info(__FILE__":%d: Vertex list too small to make region.",__LINE__);
+                       return Smach::RESULT_OK;
+               }
+
+               debug_show_vertex_list(i, vertex_list, "finished tidying list", -1);
+       }
+
+       // If we aren't the trivial case,
+       // then go ahead and create the new
+       // BLine value node
+       if(!value_node_bline)
+       {
+               synfig::info("not all points are on the same bline");
+               value_node_bline=ValueNode_BLine::create();
+
+               std::list<synfigapp::ValueDesc>::iterator iter;
+               for(iter=vertex_list.begin();iter!=vertex_list.end();++iter)
+               {
+                       // Ensure that the vertex is exported.
+                       get_canvas_interface()->auto_export(*iter);
+
+                       value_node_bline->add(iter->get_value_node());
+                       //value_node_bline->add(ValueNode_BLine::ListEntry(iter->get_value_node()));
+               }
+
+               value_node_bline->set_loop(true);
+       }
+
+       get_canvas_interface()->auto_export(value_node_bline);
+
+       // Now we create the region layer
+       // Create the layer
+       {
+               Layer::Handle layer;
+               Canvas::Handle canvas(get_canvas_view()->get_canvas());
+               int depth(0);
+
+               // we are temporarily using the layer to hold something
+               layer=get_canvas_view()->get_selection_manager()->get_selected_layer();
+               if(layer)
+               {
+                       depth=layer->get_depth();
+                       canvas=layer->get_canvas();
+               }
+
+               synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
+
+               layer=get_canvas_interface()->add_layer_to("region",canvas,depth);
+               if (!layer)
+               {
+                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
+                       group.cancel();
+                       return Smach::RESULT_ERROR;
+               }
+
+               if(get_feather())
+               {
+                       layer->set_param("feather",get_feather());
+                       get_canvas_interface()->signal_layer_param_changed()(layer,"feather");
+               }
+               get_canvas_interface()->signal_layer_param_changed()(layer,"color");
+
+               synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
+
+               assert(action);
+
+               action->set_param("canvas",get_canvas());
+               action->set_param("canvas_interface",get_canvas_interface());
+               action->set_param("layer",layer);
+               if(!action->set_param("param",String("bline")))
+                       synfig::error("LayerParamConnect didn't like \"param\"");
+               if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
+                       synfig::error("LayerParamConnect didn't like \"value_node\"");
+
+               if(!get_canvas_interface()->get_instance()->perform_action(action))
+               {
+                       get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer"));
+                       group.cancel();
+                       return Smach::RESULT_ERROR;
+               }
+               get_canvas_view()->get_selection_manager()->set_selected_layer(layer);
+       }
+
+       return Smach::RESULT_ACCEPT;
+}
+
+void
+StateDraw_Context::refresh_ducks()
+{
+       get_canvas_view()->queue_rebuild_ducks();
+/*
+       get_work_area()->clear_ducks();
+
+
+       std::list< etl::smart_ptr<std::list<synfig::Point> > >::iterator iter;
+
+       for(iter=stroke_list.begin();iter!=stroke_list.end();++iter)
+       {
+               get_work_area()->add_stroke(*iter);
+       }
+
+       get_work_area()->queue_draw();
+*/
+}
+
+
+Smach::event_result
+StateDraw_Context::extend_bline_from_begin(ValueNode_BLine::Handle value_node,std::list<synfig::BLinePoint> bline,bool complete_loop)
+{
+       // Create the action group
+       synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Extend BLine"));
+
+       if (complete_loop)
+       {
+               synfigapp::Action::Handle action(synfigapp::Action::create("ValueNodeDynamicListLoop"));
+               assert(action);
+
+               action->set_param("canvas",get_canvas());
+               action->set_param("canvas_interface",get_canvas_interface());
+               action->set_param("value_node",ValueNode::Handle(value_node));
+
+               if(!get_canvas_interface()->get_instance()->perform_action(action))
+               {
+                       get_canvas_view()->get_ui_interface()->error(_("Unable to set loop for bline"));
+                       group.cancel();
+                       return Smach::RESULT_ERROR;
+               }
+       }
+
+       std::list<synfig::BLinePoint>::reverse_iterator iter;
+       for(iter=bline.rbegin();!(iter==bline.rend());++iter)
+       {
+               ValueNode_Composite::Handle composite(ValueNode_Composite::create(*iter));
+
+               synfigapp::Action::Handle action(synfigapp::Action::create("ValueNodeDynamicListInsert"));
+
+               assert(action);
+               synfigapp::ValueDesc value_desc(value_node,0);
+
+               action->set_param("canvas",get_canvas());
+               action->set_param("canvas_interface",get_canvas_interface());
+               action->set_param("value_desc",value_desc);
+               if(!action->set_param("item",ValueNode::Handle(composite)))
+                       synfig::error("ACTION didn't like \"item\"");
+
+               if(!get_canvas_interface()->get_instance()->perform_action(action))
+               {
+                       get_canvas_view()->get_ui_interface()->error(_("Unable to insert item"));
+                       group.cancel();
+                       //refresh_ducks();
+                       return Smach::RESULT_ERROR;
+               }
+       }
+       last_stroke=value_node;
+       return Smach::RESULT_ACCEPT;
+}
+
+Smach::event_result
+StateDraw_Context::extend_bline_from_end(ValueNode_BLine::Handle value_node,std::list<synfig::BLinePoint> bline,bool complete_loop)
+{
+       // Create the action group
+       synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Extend BLine"));
+
+       if (complete_loop)
+       {
+               synfigapp::Action::Handle action(synfigapp::Action::create("ValueNodeDynamicListLoop"));
+               assert(action);
+
+               action->set_param("canvas",get_canvas());
+               action->set_param("canvas_interface",get_canvas_interface());
+               action->set_param("value_node",ValueNode::Handle(value_node));
+
+               if(!get_canvas_interface()->get_instance()->perform_action(action))
+               {
+                       get_canvas_view()->get_ui_interface()->error(_("Unable to set loop for bline"));
+                       group.cancel();
+                       return Smach::RESULT_ERROR;
+               }
+       }
+
+       std::list<synfig::BLinePoint>::iterator iter;
+       for(iter=bline.begin();iter!=bline.end();++iter)
+       {
+               ValueNode_Composite::Handle composite(ValueNode_Composite::create(*iter));
+
+               synfigapp::Action::Handle action(synfigapp::Action::create("ValueNodeDynamicListInsert"));
+
+               assert(action);
+               synfigapp::ValueDesc value_desc(value_node,value_node->link_count());
+
+               action->set_param("canvas",get_canvas());
+               action->set_param("canvas_interface",get_canvas_interface());
+               action->set_param("value_desc",value_desc);
+               if(!action->set_param("item",ValueNode::Handle(composite)))
+                       synfig::error("ACTION didn't like \"item\"");
+
+               if(!get_canvas_interface()->get_instance()->perform_action(action))
+               {
+                       get_canvas_view()->get_ui_interface()->error(_("Unable to insert item"));
+                       group.cancel();
+                       //refresh_ducks();
+                       return Smach::RESULT_ERROR;
+               }
+       }
+       last_stroke=value_node;
+       return Smach::RESULT_ACCEPT;
+}
+
+void
+StateDraw_Context::reverse_bline(std::list<synfig::BLinePoint> &bline)
+{
+       int i;
+
+       std::list<synfig::BLinePoint>::iterator iter,eiter;
+       iter=bline.begin();
+       eiter=bline.end();
+       eiter--;
+       for(i=0;i<(int)bline.size()/2;++iter,--eiter,i++)
+       {
+               iter_swap(iter,eiter);
+               iter->reverse();
+               eiter->reverse();
+       }
+}
+
+Smach::event_result
+StateDraw_Context::fill_last_stroke_and_unselect_other_layers()
+{
+       if(!last_stroke)
+               return Smach::RESULT_OK;
+
+       synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Fill Stroke"));
+
+       Layer::Handle layer;
+
+       get_canvas_interface()->auto_export(last_stroke);
+
+       synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
+
+       Canvas::Handle canvas(get_canvas_view()->get_canvas());
+       int depth(0);
+
+       layer=get_canvas_view()->get_selection_manager()->get_selected_layer();
+       if(layer)
+       {
+               depth=layer->get_depth();
+               canvas=layer->get_canvas();
+       }
+
+       get_canvas_interface()->get_selection_manager()->clear_selected_layers();
+       layer=get_canvas_interface()->add_layer_to("region", canvas, depth);
+       if (!layer) return Smach::RESULT_ERROR;
+       layer->set_description(last_stroke_id + _(" Region"));
+
+       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
+
+       assert(action);
+
+       action->set_param("canvas",get_canvas());
+       action->set_param("canvas_interface",get_canvas_interface());
+       action->set_param("layer",layer);
+       if(!action->set_param("param",String("bline")))
+               synfig::error("LayerParamConnect didn't like \"param\"");
+       if(!action->set_param("value_node",ValueNode::Handle(last_stroke)))
+               synfig::error("LayerParamConnect didn't like \"value_node\"");
+
+       if(!get_canvas_interface()->get_instance()->perform_action(action))
+       {
+               get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer"));
+               group.cancel();
+               return Smach::RESULT_OK;
+       }
+       get_canvas_view()->get_selection_manager()->set_selected_layer(layer);
+       return Smach::RESULT_OK;
+}
+
+void
+StateDraw_Context::fill_last_stroke()
+{
+       if(!last_stroke)
+               return;
+
+       synfigapp::SelectionManager::LayerList layer_list = get_canvas_view()->get_selection_manager()->get_selected_layers();
+       fill_last_stroke_and_unselect_other_layers();
+       get_canvas_view()->get_selection_manager()->set_selected_layers(layer_list);
+}
diff --git a/synfig-studio/src/gui/states/state_draw.h b/synfig-studio/src/gui/states/state_draw.h
new file mode 100644 (file)
index 0000000..2c074a5
--- /dev/null
@@ -0,0 +1,56 @@
+/* === S Y N F I G ========================================================= */
+/*!    \file state_draw.h
+**     \brief Template Header
+**
+**     $Id$
+**
+**     \legal
+**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+**
+**     This package is free software; you can redistribute it and/or
+**     modify it under the terms of the GNU General Public License as
+**     published by the Free Software Foundation; either version 2 of
+**     the License, or (at your option) any later version.
+**
+**     This package is distributed in the hope that it will be useful,
+**     but WITHOUT ANY WARRANTY; without even the implied warranty of
+**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+**     General Public License for more details.
+**     \endlegal
+*/
+/* ========================================================================= */
+
+/* === S T A R T =========================================================== */
+
+#ifndef __SYNFIG_STUDIO_STATE_ROTOSCOPE_H
+#define __SYNFIG_STUDIO_STATE_ROTOSCOPE_H
+
+/* === H E A D E R S ======================================================= */
+
+#include "smach.h"
+
+
+/* === M A C R O S ========================================================= */
+
+/* === T Y P E D E F S ===================================================== */
+
+/* === C L A S S E S & S T R U C T S ======================================= */
+
+namespace studio {
+
+class StateDraw_Context;
+
+class StateDraw : public Smach::state<StateDraw_Context>
+{
+public:
+       StateDraw();
+       ~StateDraw();
+}; // END of class StateDraw
+
+extern StateDraw state_draw;
+
+}; // END of namespace studio
+
+/* === E N D =============================================================== */
+
+#endif
diff --git a/synfig-studio/src/gui/states/state_eyedrop.cpp b/synfig-studio/src/gui/states/state_eyedrop.cpp
new file mode 100644 (file)
index 0000000..e7cf4bb
--- /dev/null
@@ -0,0 +1,146 @@
+/* === S Y N F I G ========================================================= */
+/*!    \file state_eyedrop.cpp
+**     \brief Template File
+**
+**     $Id$
+**
+**     \legal
+**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+**
+**     This package is free software; you can redistribute it and/or
+**     modify it under the terms of the GNU General Public License as
+**     published by the Free Software Foundation; either version 2 of
+**     the License, or (at your option) any later version.
+**
+**     This package is distributed in the hope that it will be useful,
+**     but WITHOUT ANY WARRANTY; without even the implied warranty of
+**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+**     General Public License for more details.
+**     \endlegal
+*/
+/* ========================================================================= */
+
+/* === H E A D E R S ======================================================= */
+
+#ifdef USING_PCH
+#      include "pch.h"
+#else
+#ifdef HAVE_CONFIG_H
+#      include <config.h>
+#endif
+
+#include "state_eyedrop.h"
+#include "state_normal.h"
+#include "workarea.h"
+#include <synfig/context.h>
+#include "app.h"
+#include "dialogs/dialog_color.h"
+#include "event_mouse.h"
+#include "event_layerclick.h"
+#include "toolbox.h"
+#include "canvasview.h"
+#include <synfigapp/main.h>
+
+#include "general.h"
+
+#endif
+
+/* === U S I N G =========================================================== */
+
+using namespace std;
+using namespace etl;
+using namespace synfig;
+using namespace studio;
+
+/* === M A C R O S ========================================================= */
+
+/* === C L A S S E S & S T R U C T S ======================================= */
+
+class studio::StateEyedrop_Context
+{
+       CanvasView *canvas_view;
+       CanvasView::IsWorking is_working;
+
+public:
+       StateEyedrop_Context(CanvasView *canvas_view);
+       ~StateEyedrop_Context();
+
+       Smach::event_result event_stop_handler(const Smach::event& x);
+
+       Smach::event_result event_refresh_handler(const Smach::event& x);
+
+       Smach::event_result event_workarea_mouse_button_down_handler(const Smach::event& x);
+
+}; // END of class StateEyedrop_Context
+
+/* === G L O B A L S ======================================================= */
+
+StateEyedrop studio::state_eyedrop;
+
+/* === P R O C E D U R E S ================================================= */
+
+/* === M E T H O D S ======================================================= */
+
+StateEyedrop::StateEyedrop():
+       Smach::state<StateEyedrop_Context>("eyedrop")
+{
+       insert(event_def(EVENT_LAYER_SELECTION_CHANGED,&StateEyedrop_Context::event_stop_handler));
+       insert(event_def(EVENT_STOP,&StateEyedrop_Context::event_stop_handler));
+       insert(event_def(EVENT_REFRESH,&StateEyedrop_Context::event_refresh_handler));
+       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateEyedrop_Context::event_workarea_mouse_button_down_handler));
+}
+
+StateEyedrop::~StateEyedrop()
+{
+}
+
+StateEyedrop_Context::StateEyedrop_Context(CanvasView *canvas_view):
+       canvas_view(canvas_view),
+       is_working(*canvas_view)
+{
+       synfig::info("Entered Eyedrop State");
+       canvas_view->work_area->set_cursor(Gdk::Cursor(Gdk::CROSSHAIR));
+
+       App::toolbox->refresh();
+}
+
+StateEyedrop_Context::~StateEyedrop_Context()
+{
+       synfig::info("Left Eyedrop State");
+       canvas_view->work_area->reset_cursor();
+       App::toolbox->refresh();
+}
+
+Smach::event_result
+StateEyedrop_Context::event_stop_handler(const Smach::event& /*x*/)
+{
+       //synfig::info("STATE EYEDROP: Received Stop Event");
+       //throw Smach::egress_exception();
+       throw &state_normal;
+       return Smach::RESULT_OK;
+//     canvas_view->get_smach().pop_state();
+//     return Smach::RESULT_ACCEPT;
+}
+
+Smach::event_result
+StateEyedrop_Context::event_refresh_handler(const Smach::event& /*x*/)
+{
+       synfig::info("STATE EYEDROP: Received Refresh Event");
+       canvas_view->work_area->queue_render_preview();
+       return Smach::RESULT_ACCEPT;
+}
+
+Smach::event_result
+StateEyedrop_Context::event_workarea_mouse_button_down_handler(const Smach::event& x)
+{
+       synfig::info("STATE EYEDROP: Received mouse button down Event");
+       const EventMouse& event(*reinterpret_cast<const EventMouse*>(&x));
+       if(event.button==BUTTON_LEFT)
+       {
+               Color color(canvas_view->get_canvas()->get_context().get_color(event.pos));
+               synfigapp::Main::set_outline_color(color);
+               studio::App::dialog_color->set_color(color);
+               return Smach::RESULT_ACCEPT;
+       }
+       return Smach::RESULT_OK;
+}
diff --git a/synfig-studio/src/gui/states/state_eyedrop.h b/synfig-studio/src/gui/states/state_eyedrop.h
new file mode 100644 (file)
index 0000000..4a90021
--- /dev/null
@@ -0,0 +1,56 @@
+/* === S Y N F I G ========================================================= */
+/*!    \file state_eyedrop.h
+**     \brief Template Header
+**
+**     $Id$
+**
+**     \legal
+**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+**
+**     This package is free software; you can redistribute it and/or
+**     modify it under the terms of the GNU General Public License as
+**     published by the Free Software Foundation; either version 2 of
+**     the License, or (at your option) any later version.
+**
+**     This package is distributed in the hope that it will be useful,
+**     but WITHOUT ANY WARRANTY; without even the implied warranty of
+**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+**     General Public License for more details.
+**     \endlegal
+*/
+/* ========================================================================= */
+
+/* === S T A R T =========================================================== */
+
+#ifndef __SYNFIG_STATE_EYEDROP_H
+#define __SYNFIG_STATE_EYEDROP_H
+
+/* === H E A D E R S ======================================================= */
+
+#include "smach.h"
+
+
+/* === M A C R O S ========================================================= */
+
+/* === T Y P E D E F S ===================================================== */
+
+/* === C L A S S E S & S T R U C T S ======================================= */
+
+namespace studio {
+
+class StateEyedrop_Context;
+
+class StateEyedrop : public Smach::state<StateEyedrop_Context>
+{
+public:
+       StateEyedrop();
+       ~StateEyedrop();
+}; // END of class StateEyedrop
+
+extern StateEyedrop state_eyedrop;
+
+}; // END of namespace studio
+
+/* === E N D =============================================================== */
+
+#endif
diff --git a/synfig-studio/src/gui/states/state_fill.cpp b/synfig-studio/src/gui/states/state_fill.cpp
new file mode 100644 (file)
index 0000000..cf6c750
--- /dev/null
@@ -0,0 +1,182 @@
+/* === S Y N F I G ========================================================= */
+/*!    \file state_fill.cpp
+**     \brief Template File
+**
+**     $Id$
+**
+**     \legal
+**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+**
+**     This package is free software; you can redistribute it and/or
+**     modify it under the terms of the GNU General Public License as
+**     published by the Free Software Foundation; either version 2 of
+**     the License, or (at your option) any later version.
+**
+**     This package is distributed in the hope that it will be useful,
+**     but WITHOUT ANY WARRANTY; without even the implied warranty of
+**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+**     General Public License for more details.
+**     \endlegal
+*/
+/* ========================================================================= */
+
+/* === H E A D E R S ======================================================= */
+
+#ifdef USING_PCH
+#      include "pch.h"
+#else
+#ifdef HAVE_CONFIG_H
+#      include <config.h>
+#endif
+
+#include "state_fill.h"
+#include "state_normal.h"
+#include "workarea.h"
+#include <synfig/context.h>
+#include "app.h"
+#include "dialogs/dialog_color.h"
+#include "event_mouse.h"
+#include "event_layerclick.h"
+#include "toolbox.h"
+#include "canvasview.h"
+#include <synfigapp/main.h>
+
+#include "general.h"
+
+#endif
+
+/* === U S I N G =========================================================== */
+
+using namespace std;
+using namespace etl;
+using namespace synfig;
+using namespace studio;
+
+/* === M A C R O S ========================================================= */
+
+/* === C L A S S E S & S T R U C T S ======================================= */
+
+class studio::StateFill_Context
+{
+       CanvasView *canvas_view;
+       CanvasView::IsWorking is_working;
+
+public:
+       StateFill_Context(CanvasView *canvas_view);
+       ~StateFill_Context();
+
+       Smach::event_result event_stop_handler(const Smach::event& x);
+
+       Smach::event_result event_refresh_handler(const Smach::event& x);
+
+       Smach::event_result event_workarea_layer_clicked_handler(const Smach::event& x);
+
+
+       etl::handle<CanvasView> get_canvas_view()const{return canvas_view;}
+       etl::handle<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view->canvas_interface();}
+       synfig::Canvas::Handle get_canvas()const{return canvas_view->get_canvas();}
+       WorkArea * get_work_area()const{return canvas_view->get_work_area();}
+
+
+}; // END of class StateFill_Context
+
+/* === G L O B A L S ======================================================= */
+
+StateFill studio::state_fill;
+
+/* === P R O C E D U R E S ================================================= */
+
+/* === M E T H O D S ======================================================= */
+
+StateFill::StateFill():
+       Smach::state<StateFill_Context>("fill")
+{
+       insert(event_def(EVENT_LAYER_SELECTION_CHANGED,&StateFill_Context::event_stop_handler));
+       insert(event_def(EVENT_STOP,&StateFill_Context::event_stop_handler));
+       insert(event_def(EVENT_REFRESH,&StateFill_Context::event_refresh_handler));
+       insert(event_def(EVENT_WORKAREA_LAYER_CLICKED,&StateFill_Context::event_workarea_layer_clicked_handler));
+}
+
+StateFill::~StateFill()
+{
+}
+
+StateFill_Context::StateFill_Context(CanvasView *canvas_view):
+       canvas_view(canvas_view),
+       is_working(*canvas_view)
+{
+       synfig::info("Entered Fill State");
+       canvas_view->work_area->set_cursor(Gdk::CROSSHAIR);
+
+       App::toolbox->refresh();
+}
+
+StateFill_Context::~StateFill_Context()
+{
+       synfig::info("Left Fill State");
+       canvas_view->work_area->reset_cursor();
+       App::toolbox->refresh();
+}
+
+Smach::event_result
+StateFill_Context::event_stop_handler(const Smach::event& /*x*/)
+{
+       synfig::info("STATE FILL: Received Stop Event");
+       //throw Smach::egress_exception();
+       throw &state_normal;
+       return Smach::RESULT_OK;
+//     canvas_view->get_smach().pop_state();
+//     return Smach::RESULT_ACCEPT;
+}
+
+Smach::event_result
+StateFill_Context::event_refresh_handler(const Smach::event& /*x*/)
+{
+       synfig::info("STATE FILL: Received Refresh Event");
+       canvas_view->work_area->queue_render_preview();
+       return Smach::RESULT_ACCEPT;
+}
+
+Smach::event_result
+StateFill_Context::event_workarea_layer_clicked_handler(const Smach::event& x)
+{
+       synfig::info("STATE FILL: Received layer clicked Event");
+       const EventLayerClick& event(*reinterpret_cast<const EventLayerClick*>(&x));
+
+       if(!event.layer)
+       {
+               get_canvas_view()->get_ui_interface()->warning(_("No layer here"));
+               return Smach::RESULT_ACCEPT;
+       }
+
+
+       //synfigapp::Action::Handle action(synfigapp::Action::create("ValueDescSet"));
+       synfigapp::ValueDesc value_desc(event.layer,"color");
+
+       if(!get_canvas_interface()->change_value(value_desc,ValueBase(synfigapp::Main::get_fill_color())))
+       {
+               get_canvas_view()->get_ui_interface()->warning(_("Unable to set layer color"));
+               return Smach::RESULT_ERROR;
+       }
+       /*
+       assert(action);
+
+       action->set_param("canvas",get_canvas());
+       action->set_param("canvas_interface",get_canvas_interface());
+       action->set_param("value_desc",value_desc);
+       action->set_param("time",get_canvas_interface()->get_time());
+       //action->set_param("layer",event.layer);
+       //if(!action->set_param("param",String("color")))
+       //      synfig::error("LayerParamConnect didn't like \"param\"");
+       if(!action->set_param("new_value",ValueBase(synfigapp::Main::get_fill_color())))
+               synfig::error("LayerParamConnect didn't like \"fill_color\"");
+
+       if(!get_canvas_interface()->get_instance()->perform_action(action))
+       {
+               get_canvas_view()->get_ui_interface()->warning(_("Unable to set layer color"));
+               return Smach::RESULT_ERROR;
+       }
+       get_canvas_view()->get_ui_interface()->task(_("Idle"));
+       */
+       return Smach::RESULT_ACCEPT;
+}
diff --git a/synfig-studio/src/gui/states/state_fill.h b/synfig-studio/src/gui/states/state_fill.h
new file mode 100644 (file)
index 0000000..349a1ce
--- /dev/null
@@ -0,0 +1,56 @@
+/* === S Y N F I G ========================================================= */
+/*!    \file state_fill.h
+**     \brief Template Header
+**
+**     $Id$
+**
+**     \legal
+**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+**
+**     This package is free software; you can redistribute it and/or
+**     modify it under the terms of the GNU General Public License as
+**     published by the Free Software Foundation; either version 2 of
+**     the License, or (at your option) any later version.
+**
+**     This package is distributed in the hope that it will be useful,
+**     but WITHOUT ANY WARRANTY; without even the implied warranty of
+**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+**     General Public License for more details.
+**     \endlegal
+*/
+/* ========================================================================= */
+
+/* === S T A R T =========================================================== */
+
+#ifndef __SYNFIG_STATE_FILL_H
+#define __SYNFIG_STATE_FILL_H
+
+/* === H E A D E R S ======================================================= */
+
+#include "smach.h"
+
+
+/* === M A C R O S ========================================================= */
+
+/* === T Y P E D E F S ===================================================== */
+
+/* === C L A S S E S & S T R U C T S ======================================= */
+
+namespace studio {
+
+class StateFill_Context;
+
+class StateFill : public Smach::state<StateFill_Context>
+{
+public:
+       StateFill();
+       ~StateFill();
+}; // END of class StateFill
+
+extern StateFill state_fill;
+
+}; // END of namespace studio
+
+/* === E N D =============================================================== */
+
+#endif
diff --git a/synfig-studio/src/gui/states/state_gradient.cpp b/synfig-studio/src/gui/states/state_gradient.cpp
new file mode 100644 (file)
index 0000000..68f35c0
--- /dev/null
@@ -0,0 +1,546 @@
+/* === S Y N F I G ========================================================= */
+/*!    \file state_gradient.cpp
+**     \brief Template File
+**
+**     $Id$
+**
+**     \legal
+**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+**  Copyright (c) 2008 Chris Moore
+**
+**     This package is free software; you can redistribute it and/or
+**     modify it under the terms of the GNU General Public License as
+**     published by the Free Software Foundation; either version 2 of
+**     the License, or (at your option) any later version.
+**
+**     This package is distributed in the hope that it will be useful,
+**     but WITHOUT ANY WARRANTY; without even the implied warranty of
+**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+**     General Public License for more details.
+**     \endlegal
+*/
+/* ========================================================================= */
+
+/* === H E A D E R S ======================================================= */
+
+#ifdef USING_PCH
+#      include "pch.h"
+#else
+#ifdef HAVE_CONFIG_H
+#      include <config.h>
+#endif
+
+#include <gtkmm/dialog.h>
+#include <gtkmm/entry.h>
+
+#include <synfig/valuenode_dynamiclist.h>
+#include <synfigapp/action_system.h>
+
+#include "state_gradient.h"
+#include "state_normal.h"
+#include "canvasview.h"
+#include "workarea.h"
+#include "app.h"
+
+#include <synfigapp/action.h>
+#include "event_mouse.h"
+#include "event_layerclick.h"
+#include "toolbox.h"
+#include "dialog_tooloptions.h"
+#include <gtkmm/optionmenu.h>
+#include "duck.h"
+
+#include "widgets/widget_enum.h"
+#include <synfigapp/main.h>
+
+#include "general.h"
+
+#endif
+
+/* === U S I N G =========================================================== */
+
+using namespace std;
+using namespace etl;
+using namespace synfig;
+using namespace studio;
+
+/* === M A C R O S ========================================================= */
+
+enum
+{
+       GRADIENT_INTERPOLATION_LINEAR=0,
+       GRADIENT_RADIAL=1,
+       GRADIENT_CONICAL=2,
+       GRADIENT_SPIRAL=3
+};
+
+/* === G L O B A L S ======================================================= */
+
+StateGradient studio::state_gradient;
+
+/* === C L A S S E S & S T R U C T S ======================================= */
+
+class studio::StateGradient_Context : public sigc::trackable
+{
+       etl::handle<CanvasView> canvas_view_;
+       CanvasView::IsWorking is_working;
+
+       Duckmatic::Push duckmatic_push;
+
+       synfigapp::Settings& settings;
+
+       Point point_holder;
+
+       etl::handle<Duck> point2_duck;
+
+       void refresh_ducks();
+
+       bool prev_workarea_layer_status_;
+
+       Gtk::Table options_table;
+       Gtk::Entry entry_id;
+       Widget_Enum enum_type;
+#ifdef BLEND_METHOD_IN_TOOL_OPTIONS
+       Widget_Enum     enum_blend;
+#endif // BLEND_METHOD_IN_TOOL_OPTIONS
+
+public:
+       synfig::String get_id()const { return entry_id.get_text(); }
+       void set_id(const synfig::String& x) { return entry_id.set_text(x); }
+
+       int get_type()const { return enum_type.get_value(); }
+       void set_type(int x) { return enum_type.set_value(x); }
+
+#ifdef BLEND_METHOD_IN_TOOL_OPTIONS
+       int get_blend()const { return enum_blend.get_value(); }
+       void set_blend(int x) { return enum_blend.set_value(x); }
+#endif // BLEND_METHOD_IN_TOOL_OPTIONS
+
+       Smach::event_result event_stop_handler(const Smach::event& x);
+
+       Smach::event_result event_refresh_handler(const Smach::event& x);
+
+       Smach::event_result event_mouse_click_handler(const Smach::event& x);
+       Smach::event_result event_refresh_tool_options(const Smach::event& x);
+
+       void refresh_tool_options();
+
+       StateGradient_Context(CanvasView* canvas_view);
+
+       ~StateGradient_Context();
+
+       const etl::handle<CanvasView>& get_canvas_view()const{return canvas_view_;}
+       etl::handle<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view_->canvas_interface();}
+       synfig::Canvas::Handle get_canvas()const{return canvas_view_->get_canvas();}
+       WorkArea * get_work_area()const{return canvas_view_->get_work_area();}
+
+       //void on_user_click(synfig::Point point);
+       void load_settings();
+       void save_settings();
+       void reset();
+       void increment_id();
+
+       void make_gradient(const Point& p1, const Point& p2);
+       bool egress_on_selection_change;
+       Smach::event_result event_layer_selection_changed_handler(const Smach::event& /*x*/)
+       {
+               if(egress_on_selection_change)
+                       throw &state_normal; //throw Smach::egress_exception();
+               return Smach::RESULT_OK;
+       }
+
+};     // END of class StateGradient_Context
+
+/* === M E T H O D S ======================================================= */
+
+StateGradient::StateGradient():
+       Smach::state<StateGradient_Context>("gradient")
+{
+       insert(event_def(EVENT_LAYER_SELECTION_CHANGED,&StateGradient_Context::event_layer_selection_changed_handler));
+       insert(event_def(EVENT_STOP,&StateGradient_Context::event_stop_handler));
+       insert(event_def(EVENT_TABLES_SHOW,&StateGradient_Context::event_stop_handler));
+       insert(event_def(EVENT_REFRESH,&StateGradient_Context::event_refresh_handler));
+       insert(event_def(EVENT_REFRESH_DUCKS,&StateGradient_Context::event_refresh_handler));
+       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateGradient_Context::event_mouse_click_handler));
+       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DRAG,&StateGradient_Context::event_mouse_click_handler));
+       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_UP,&StateGradient_Context::event_mouse_click_handler));
+       insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateGradient_Context::event_refresh_tool_options));
+}
+
+StateGradient::~StateGradient()
+{
+}
+
+void
+StateGradient_Context::load_settings()
+{
+       String value;
+
+       if(settings.get_value("gradient.id",value))
+               set_id(value);
+       else
+               set_id("Gradient");
+
+       if(settings.get_value("gradient.type",value))
+               set_type(atoi(value.c_str()));
+       else
+               set_type(GRADIENT_INTERPOLATION_LINEAR);
+
+#ifdef BLEND_METHOD_IN_TOOL_OPTIONS
+       if(settings.get_value("gradient.blend",value))
+               set_blend(atoi(value.c_str()));
+       else
+               set_blend(Color::BLEND_COMPOSITE);
+#endif // BLEND_METHOD_IN_TOOL_OPTIONS
+}
+
+void
+StateGradient_Context::save_settings()
+{
+       settings.set_value("gradient.id",get_id().c_str());
+       settings.set_value("gradient.type",strprintf("%d",get_type()));
+#ifdef BLEND_METHOD_IN_TOOL_OPTIONS
+       settings.set_value("gradient.blend",strprintf("%d",get_blend()));
+#endif // BLEND_METHOD_IN_TOOL_OPTIONS
+}
+
+void
+StateGradient_Context::reset()
+{
+       refresh_ducks();
+}
+
+void
+StateGradient_Context::increment_id()
+{
+       String id(get_id());
+       int number=1;
+       int digits=0;
+
+       if(id.empty())
+               id="Gradient";
+
+       // If there is a number
+       // already at the end of the
+       // id, then remove it.
+       if(id[id.size()-1]<='9' && id[id.size()-1]>='0')
+       {
+               // figure out how many digits it is
+               for (digits = 0;
+                        (int)id.size()-1 >= digits && id[id.size()-1-digits] <= '9' && id[id.size()-1-digits] >= '0';
+                        digits++)
+                       ;
+
+               String str_number;
+               str_number=String(id,id.size()-digits,id.size());
+               id=String(id,0,id.size()-digits);
+
+               number=atoi(str_number.c_str());
+       }
+       else
+       {
+               number=1;
+               digits=3;
+       }
+
+       number++;
+
+       // Add the number back onto the id
+       {
+               const String format(strprintf("%%0%dd",digits));
+               id+=strprintf(format.c_str(),number);
+       }
+
+       // Set the ID
+       set_id(id);
+}
+
+StateGradient_Context::StateGradient_Context(CanvasView* canvas_view):
+       canvas_view_(canvas_view),
+       is_working(*canvas_view),
+       duckmatic_push(get_work_area()),
+       settings(synfigapp::Main::get_selected_input_device()->settings()),
+       prev_workarea_layer_status_(get_work_area()->get_allow_layer_clicks()),
+       entry_id()
+{
+       egress_on_selection_change=true;
+       // Set up the tool options dialog
+       options_table.attach(*manage(new Gtk::Label(_("Gradient Tool"))),       0, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(entry_id,                                                                          0, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+
+       enum_type.set_param_desc(ParamDesc("type")
+               .set_local_name(_("Gradient Type"))
+               .set_description(_("Determines the type of Gradient used"))
+               .set_hint("enum")
+               .add_enum_value(GRADIENT_INTERPOLATION_LINEAR,"linear",_("Linear"))
+               .add_enum_value(GRADIENT_RADIAL,"radial",_("Radial"))
+               .add_enum_value(GRADIENT_CONICAL,"conical",_("Conical"))
+               .add_enum_value(GRADIENT_SPIRAL,"spiral",_("Spiral")));
+
+#ifdef BLEND_METHOD_IN_TOOL_OPTIONS
+       enum_blend.set_param_desc(ParamDesc(Color::BLEND_COMPOSITE,"blend_method")
+               .set_local_name(_("Blend Method"))
+               .set_description(_("The blend method the gradient will use")));
+#endif // BLEND_METHOD_IN_TOOL_OPTIONS
+
+       load_settings();
+
+       options_table.attach(enum_type, 0, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+#ifdef BLEND_METHOD_IN_TOOL_OPTIONS
+       options_table.attach(enum_blend, 0, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+#endif // BLEND_METHOD_IN_TOOL_OPTIONS
+
+       options_table.show_all();
+       refresh_tool_options();
+       App::dialog_tool_options->present();
+
+
+       // Turn off layer clicking
+       get_work_area()->set_allow_layer_clicks(false);
+
+       get_work_area()->set_cursor(Gdk::CROSSHAIR);
+
+       // clear out the ducks
+       get_work_area()->clear_ducks();
+
+       // Refresh the work area
+       get_work_area()->queue_draw();
+
+       get_work_area()->refresh_cursor();
+
+       // Hide the tables if they are showing
+       get_canvas_view()->hide_tables();
+
+       // Disable the time bar
+       //get_canvas_view()->set_sensitive_timebar(false);
+
+       // Connect a signal
+       //get_work_area()->signal_user_click().connect(sigc::mem_fun(*this,&studio::StateGradient_Context::on_user_click));
+
+       App::toolbox->refresh();
+}
+
+void
+StateGradient_Context::refresh_tool_options()
+{
+       App::dialog_tool_options->clear();
+       App::dialog_tool_options->set_widget(options_table);
+       App::dialog_tool_options->set_local_name(_("Gradient Tool"));
+       App::dialog_tool_options->set_name("gradient");
+}
+
+Smach::event_result
+StateGradient_Context::event_refresh_tool_options(const Smach::event& /*x*/)
+{
+       refresh_tool_options();
+       return Smach::RESULT_ACCEPT;
+}
+
+StateGradient_Context::~StateGradient_Context()
+{
+       save_settings();
+
+       // Restore layer clicking
+//     get_work_area()->set_allow_layer_clicks(prev_workarea_layer_status_);
+       get_work_area()->set_allow_layer_clicks(true);
+       get_work_area()->reset_cursor();
+
+       App::dialog_tool_options->clear();
+
+       // Enable the time bar
+       //get_canvas_view()->set_sensitive_timebar(true);
+
+       // Bring back the tables if they were out before
+       //if(prev_table_status)get_canvas_view()->show_tables();
+
+       // Refresh the work area
+       get_work_area()->queue_draw();
+
+       get_canvas_view()->queue_rebuild_ducks();
+
+       //get_canvas_view()->show_tables();
+
+       get_work_area()->refresh_cursor();
+
+       App::toolbox->refresh();
+}
+
+Smach::event_result
+StateGradient_Context::event_stop_handler(const Smach::event& /*x*/)
+{
+       //throw Smach::egress_exception();
+       throw &state_normal;
+       return Smach::RESULT_OK;
+}
+
+Smach::event_result
+StateGradient_Context::event_refresh_handler(const Smach::event& /*x*/)
+{
+       refresh_ducks();
+       return Smach::RESULT_ACCEPT;
+}
+
+void
+StateGradient_Context::make_gradient(const Point& _p1, const Point& _p2)
+{
+       synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("New Gradient"));
+       synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
+
+       Layer::Handle layer;
+
+       Canvas::Handle canvas(get_canvas_view()->get_canvas());
+       int depth(0);
+
+       // we are temporarily using the layer to hold something
+       layer=get_canvas_view()->get_selection_manager()->get_selected_layer();
+       if(layer)
+       {
+               depth=layer->get_depth();
+               canvas=layer->get_canvas();
+       }
+       const synfig::TransformStack& transform(get_canvas_view()->get_curr_transform_stack());
+       const Point p1(transform.unperform(_p1));
+       const Point p2(transform.unperform(_p2));
+
+       switch(get_type())
+       {
+       case GRADIENT_INTERPOLATION_LINEAR:
+
+               layer=get_canvas_interface()->add_layer_to("linear_gradient",canvas,depth);
+               if (!layer)
+               {
+                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
+                       group.cancel();
+                       return;
+               }
+               layer->set_param("p1",p1);
+               get_canvas_interface()->signal_layer_param_changed()(layer,"p1");
+               layer->set_param("p2",p2);
+               get_canvas_interface()->signal_layer_param_changed()(layer,"p2");
+               break;
+       case GRADIENT_RADIAL:
+               layer=get_canvas_interface()->add_layer_to("radial_gradient",canvas,depth);
+               if (!layer)
+               {
+                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
+                       group.cancel();
+                       return;
+               }
+               layer->set_param("center",p1);
+               get_canvas_interface()->signal_layer_param_changed()(layer,"center");
+               layer->set_param("radius",(p2-p1).mag());
+               get_canvas_interface()->signal_layer_param_changed()(layer,"radius");
+               break;
+       case GRADIENT_CONICAL:
+               layer=get_canvas_interface()->add_layer_to("conical_gradient",canvas,depth);
+               if (!layer)
+               {
+                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
+                       group.cancel();
+                       return;
+               }
+               layer->set_param("center",p1);
+               get_canvas_interface()->signal_layer_param_changed()(layer,"center");
+               {
+                       Vector diff(p2-p1);
+                       layer->set_param("angle",Angle::tan(diff[1],diff[0]));
+                       get_canvas_interface()->signal_layer_param_changed()(layer,"angle");
+               }
+               break;
+       case GRADIENT_SPIRAL:
+               layer=get_canvas_interface()->add_layer_to("spiral_gradient",canvas,depth);
+               if (!layer)
+               {
+                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
+                       group.cancel();
+                       return;
+               }
+               layer->set_param("center",p1);
+               get_canvas_interface()->signal_layer_param_changed()(layer,"center");
+               layer->set_param("radius",(p2-p1).mag());
+               get_canvas_interface()->signal_layer_param_changed()(layer,"radius");
+               {
+                       Vector diff(p2-p1);
+                       layer->set_param("angle",Angle::tan(diff[1],diff[0]));
+                       get_canvas_interface()->signal_layer_param_changed()(layer,"angle");
+               }
+               break;
+
+       default:
+               return;
+       }
+
+#ifdef BLEND_METHOD_IN_TOOL_OPTIONS
+       layer->set_param("blend_method",get_blend());
+       get_canvas_interface()->signal_layer_param_changed()(layer,"blend_method");
+#endif // BLEND_METHOD_IN_TOOL_OPTIONS
+
+       layer->set_description(get_id());
+       get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
+
+       egress_on_selection_change=false;
+       synfigapp::SelectionManager::LayerList layer_selection;
+       if (!getenv("SYNFIG_TOOLS_CLEAR_SELECTION"))
+               layer_selection = get_canvas_view()->get_selection_manager()->get_selected_layers();
+       get_canvas_interface()->get_selection_manager()->clear_selected_layers();
+       layer_selection.push_back(layer);
+       get_canvas_interface()->get_selection_manager()->set_selected_layers(layer_selection);
+       egress_on_selection_change=true;
+
+       reset();
+       increment_id();
+}
+
+Smach::event_result
+StateGradient_Context::event_mouse_click_handler(const Smach::event& x)
+{
+       const EventMouse& event(*reinterpret_cast<const EventMouse*>(&x));
+
+       if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_DOWN && event.button==BUTTON_LEFT)
+       {
+               point_holder=get_work_area()->snap_point_to_grid(event.pos);
+               etl::handle<Duck> duck=new Duck();
+               duck->set_point(point_holder);
+               duck->set_name("p1");
+               duck->set_type(Duck::TYPE_POSITION);
+               get_work_area()->add_duck(duck);
+
+               point2_duck=new Duck();
+               point2_duck->set_point(point_holder);
+               point2_duck->set_name("p2");
+               point2_duck->set_type(Duck::TYPE_POSITION);
+               get_work_area()->add_duck(point2_duck);
+
+               handle<Duckmatic::Bezier> bezier(new Duckmatic::Bezier());
+               bezier->p1=bezier->c1=duck;
+               bezier->p2=bezier->c2=point2_duck;
+               get_work_area()->add_bezier(bezier);
+
+               return Smach::RESULT_ACCEPT;
+       }
+
+       if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_DRAG && event.button==BUTTON_LEFT)
+       {
+               if (!point2_duck) return Smach::RESULT_OK;
+               point2_duck->set_point(get_work_area()->snap_point_to_grid(event.pos));
+               get_work_area()->queue_draw();
+               return Smach::RESULT_ACCEPT;
+       }
+
+       if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_UP && event.button==BUTTON_LEFT)
+       {
+               make_gradient(point_holder, get_work_area()->snap_point_to_grid(event.pos));
+               get_work_area()->clear_ducks();
+               return Smach::RESULT_ACCEPT;
+       }
+
+       return Smach::RESULT_OK;
+}
+
+
+void
+StateGradient_Context::refresh_ducks()
+{
+       get_work_area()->clear_ducks();
+       get_work_area()->queue_draw();
+}
diff --git a/synfig-studio/src/gui/states/state_gradient.h b/synfig-studio/src/gui/states/state_gradient.h
new file mode 100644 (file)
index 0000000..308b5ee
--- /dev/null
@@ -0,0 +1,56 @@
+/* === S Y N F I G ========================================================= */
+/*!    \file state_gradient.h
+**     \brief Template Header
+**
+**     $Id$
+**
+**     \legal
+**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+**
+**     This package is free software; you can redistribute it and/or
+**     modify it under the terms of the GNU General Public License as
+**     published by the Free Software Foundation; either version 2 of
+**     the License, or (at your option) any later version.
+**
+**     This package is distributed in the hope that it will be useful,
+**     but WITHOUT ANY WARRANTY; without even the implied warranty of
+**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+**     General Public License for more details.
+**     \endlegal
+*/
+/* ========================================================================= */
+
+/* === S T A R T =========================================================== */
+
+#ifndef __SYNFIG_STUDIO_STATE_GRADIENT_H
+#define __SYNFIG_STUDIO_STATE_GRADIENT_H
+
+/* === H E A D E R S ======================================================= */
+
+#include "smach.h"
+
+
+/* === M A C R O S ========================================================= */
+
+/* === T Y P E D E F S ===================================================== */
+
+/* === C L A S S E S & S T R U C T S ======================================= */
+
+namespace studio {
+
+class StateGradient_Context;
+
+class StateGradient : public Smach::state<StateGradient_Context>
+{
+public:
+       StateGradient();
+       ~StateGradient();
+}; // END of class StateGradient
+
+extern StateGradient state_gradient;
+
+}; // END of namespace studio
+
+/* === E N D =============================================================== */
+
+#endif
diff --git a/synfig-studio/src/gui/states/state_mirror.cpp b/synfig-studio/src/gui/states/state_mirror.cpp
new file mode 100644 (file)
index 0000000..59fc759
--- /dev/null
@@ -0,0 +1,336 @@
+/* === S Y N F I G ========================================================= */
+/*!    \file state_mirror.cpp
+**     \brief Template File
+**
+**     $Id$
+**
+**     \legal
+**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+**     Copyright (c) 2009 Nikita Kitaev
+**
+**     This package is free software; you can redistribute it and/or
+**     modify it under the terms of the GNU General Public License as
+**     published by the Free Software Foundation; either version 2 of
+**     the License, or (at your option) any later version.
+**
+**     This package is distributed in the hope that it will be useful,
+**     but WITHOUT ANY WARRANTY; without even the implied warranty of
+**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+**     General Public License for more details.
+**     \endlegal
+*/
+/* ========================================================================= */
+
+/* === H E A D E R S ======================================================= */
+
+#ifdef USING_PCH
+#      include "pch.h"
+#else
+#ifdef HAVE_CONFIG_H
+#      include <config.h>
+#endif
+
+#include <gtkmm/dialog.h>
+#include <gtkmm/entry.h>
+
+#include <synfig/valuenode_dynamiclist.h>
+#include <synfigapp/action_system.h>
+
+#include "state_mirror.h"
+#include "state_normal.h"
+#include "canvasview.h"
+#include "workarea.h"
+#include "app.h"
+
+#include <synfigapp/action.h>
+#include "event_mouse.h"
+#include "event_layerclick.h"
+#include "toolbox.h"
+#include "dialog_tooloptions.h"
+#include <gtkmm/optionmenu.h>
+#include "duck.h"
+#include <synfigapp/main.h>
+
+#include "general.h"
+
+#endif
+
+/* === U S I N G =========================================================== */
+
+using namespace std;
+using namespace etl;
+using namespace synfig;
+using namespace studio;
+
+/* === M A C R O S ========================================================= */
+
+enum Axis {
+       AXIS_X,
+       AXIS_Y
+} ;
+
+/* === G L O B A L S ======================================================= */
+
+StateMirror studio::state_mirror;
+
+/* === C L A S S E S & S T R U C T S ======================================= */
+
+class DuckDrag_Mirror : public DuckDrag_Base
+{
+       synfig::Vector center;
+
+       std::vector<synfig::Vector> positions;
+
+public:
+       Axis axis;
+
+       DuckDrag_Mirror();
+       void begin_duck_drag(Duckmatic* duckmatic, const synfig::Vector& begin);
+       bool end_duck_drag(Duckmatic* duckmatic);
+       void duck_drag(Duckmatic* duckmatic, const synfig::Vector& vector);
+};
+
+class studio::StateMirror_Context : public sigc::trackable
+{
+       etl::handle<CanvasView> canvas_view_;
+       CanvasView::IsWorking is_working;
+
+       synfigapp::Settings& settings;
+
+       sigc::connection keypress_connect;
+       sigc::connection keyrelease_connect;
+
+       etl::handle<DuckDrag_Mirror> duck_dragger_;
+
+       Gtk::Table options_table;
+
+       Gtk::RadioButton::Group radiobutton_group;
+       Gtk::RadioButton radiobutton_axis_x;
+       Gtk::RadioButton radiobutton_axis_y;
+
+public:
+
+       Axis get_axis()const { return radiobutton_axis_x.get_active()?AXIS_X:AXIS_Y; }
+       void set_axis(Axis a)
+       {
+               if(a==AXIS_X)
+                       radiobutton_axis_x.set_active(true);
+               else
+                       radiobutton_axis_y.set_active(true);
+
+               duck_dragger_->axis=get_axis();
+       }
+
+       void update_axes()
+       {
+               duck_dragger_->axis=get_axis();
+               get_work_area()->set_cursor(get_axis() == AXIS_X?Gdk::SB_H_DOUBLE_ARROW:Gdk::SB_V_DOUBLE_ARROW);
+       }
+
+       Smach::event_result event_stop_handler(const Smach::event& x);
+       Smach::event_result event_refresh_tool_options(const Smach::event& x);
+
+       void refresh_tool_options();
+
+       StateMirror_Context(CanvasView* canvas_view);
+
+       ~StateMirror_Context();
+
+       const etl::handle<CanvasView>& get_canvas_view()const{return canvas_view_;}
+       etl::handle<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view_->canvas_interface();}
+       synfig::Canvas::Handle get_canvas()const{return canvas_view_->get_canvas();}
+       WorkArea * get_work_area()const{return canvas_view_->get_work_area();}
+
+       void load_settings();
+       void save_settings();
+
+       bool key_event(GdkEventKey *event);
+};     // END of class StateMirror_Context
+
+/* === M E T H O D S ======================================================= */
+
+StateMirror::StateMirror():
+       Smach::state<StateMirror_Context>("mirror")
+{
+       insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateMirror_Context::event_refresh_tool_options));
+       insert(event_def(EVENT_STOP,&StateMirror_Context::event_stop_handler));
+}
+
+StateMirror::~StateMirror()
+{
+}
+
+void
+StateMirror_Context::load_settings()
+{
+       String value;
+
+       settings.get_value("mirror.axis",value);
+       set_axis((Axis)atoi(value.c_str()));
+}
+
+void
+StateMirror_Context::save_settings()
+{
+       settings.set_value("mirror.lock_aspect",strprintf("%d",(int)get_axis()));
+}
+
+StateMirror_Context::StateMirror_Context(CanvasView* canvas_view):
+       canvas_view_(canvas_view),
+       is_working(*canvas_view),
+       settings(synfigapp::Main::get_selected_input_device()->settings()),
+       duck_dragger_(new DuckDrag_Mirror()),
+       radiobutton_axis_x(radiobutton_group,_("Horizontal")),
+       radiobutton_axis_y(radiobutton_group,_("Vertical"))
+{
+       // Set up the tool options dialog
+       options_table.attach(*manage(new Gtk::Label(_("Mirror Tool"))), 0, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(radiobutton_axis_x, 0, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(radiobutton_axis_y, 0, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(*manage(new Gtk::Label(_("(Shift key toggles axis)"))), 0, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+
+       radiobutton_axis_x.signal_toggled().connect(sigc::mem_fun(*this,&StateMirror_Context::update_axes));
+       radiobutton_axis_y.signal_toggled().connect(sigc::mem_fun(*this,&StateMirror_Context::update_axes));
+
+       options_table.show_all();
+       refresh_tool_options();
+       App::dialog_tool_options->present();
+
+       get_work_area()->set_allow_layer_clicks(true);
+       get_work_area()->set_duck_dragger(duck_dragger_);
+
+       keypress_connect=get_work_area()->signal_key_press_event().connect(sigc::mem_fun(*this,&StateMirror_Context::key_event),false);
+       keyrelease_connect=get_work_area()->signal_key_release_event().connect(sigc::mem_fun(*this,&StateMirror_Context::key_event),false);
+
+       get_work_area()->set_cursor(Gdk::SB_H_DOUBLE_ARROW);
+//     get_work_area()->reset_cursor();
+
+       App::toolbox->refresh();
+
+       set_axis(AXIS_X);
+       load_settings();
+}
+
+bool
+StateMirror_Context::key_event(GdkEventKey *event)
+{
+       if (event->keyval==GDK_Shift_L || event->keyval==GDK_Shift_R )
+       {
+               set_axis(get_axis()==AXIS_X ? AXIS_Y:AXIS_X);
+               get_work_area()->set_cursor(get_axis() == AXIS_X?Gdk::SB_H_DOUBLE_ARROW:Gdk::SB_V_DOUBLE_ARROW);
+       }
+
+       return false; //Pass on the event to other handlers, just in case
+}
+
+void
+StateMirror_Context::refresh_tool_options()
+{
+       App::dialog_tool_options->clear();
+       App::dialog_tool_options->set_widget(options_table);
+       App::dialog_tool_options->set_local_name(_("Mirror Tool"));
+       App::dialog_tool_options->set_name("mirror");
+}
+
+Smach::event_result
+StateMirror_Context::event_refresh_tool_options(const Smach::event& /*x*/)
+{
+       refresh_tool_options();
+       return Smach::RESULT_ACCEPT;
+}
+
+Smach::event_result
+StateMirror_Context::event_stop_handler(const Smach::event& /*x*/)
+{
+       throw &state_normal;
+       return Smach::RESULT_OK;
+}
+
+StateMirror_Context::~StateMirror_Context()
+{
+       save_settings();
+
+       get_work_area()->clear_duck_dragger();
+       get_work_area()->reset_cursor();
+
+       keypress_connect.disconnect();
+       keyrelease_connect.disconnect();
+
+       App::dialog_tool_options->clear();
+
+       App::toolbox->refresh();
+}
+
+DuckDrag_Mirror::DuckDrag_Mirror():
+       axis(AXIS_X)
+{
+}
+
+#ifndef EPSILON
+#define EPSILON        0.0000001
+#endif
+
+void
+DuckDrag_Mirror::begin_duck_drag(Duckmatic* duckmatic, const synfig::Vector& /*offset*/)
+{
+       const DuckList selected_ducks(duckmatic->get_selected_ducks());
+       DuckList::const_iterator iter;
+
+       positions.clear();
+       int i;
+       for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
+       {
+               Point p((*iter)->get_trans_point());
+               positions.push_back(p);
+       }
+
+}
+
+void
+DuckDrag_Mirror::duck_drag(Duckmatic* duckmatic, const synfig::Vector& vector)
+{
+       center=vector;
+       int i;
+
+       const DuckList selected_ducks(duckmatic->get_selected_ducks());
+       DuckList::const_iterator iter;
+
+       Time time(duckmatic->get_time());
+
+       // do the Vertex and Position ducks first
+       for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
+               if ((*iter)->get_type() == Duck::TYPE_VERTEX ||
+                       (*iter)->get_type() == Duck::TYPE_POSITION)
+               {
+                       Vector p(positions[i]);
+
+                       if              (axis==AXIS_X) p[0] = -(p[0]-center[0]) + center[0];
+                       else if (axis==AXIS_Y) p[1] = -(p[1]-center[1]) + center[1];
+
+                       (*iter)->set_trans_point(p);
+               }
+
+       // then do the other ducks
+       for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
+               if ((*iter)->get_type() != Duck::TYPE_VERTEX &&
+                       (*iter)->get_type() != Duck::TYPE_POSITION)
+               {
+                       // we don't need to mirror radius ducks - they're one-dimensional
+                       if ((*iter)->is_radius())
+                               continue;
+
+                       Vector p(positions[i]);
+
+                       if              (axis==AXIS_X) p[0] = -(p[0]-center[0]) + center[0];
+                       else if (axis==AXIS_Y) p[1] = -(p[1]-center[1]) + center[1];
+
+                       (*iter)->set_trans_point(p);
+               }
+}
+
+bool
+DuckDrag_Mirror::end_duck_drag(Duckmatic* duckmatic)
+{
+       duckmatic->signal_edited_selected_ducks();
+       return true;
+}
diff --git a/synfig-studio/src/gui/states/state_mirror.h b/synfig-studio/src/gui/states/state_mirror.h
new file mode 100644 (file)
index 0000000..4ac878e
--- /dev/null
@@ -0,0 +1,55 @@
+/* === S Y N F I G ========================================================= */
+/*!    \file state_mirror.h
+**     \brief Template Header
+**
+**     $Id$
+**
+**     \legal
+**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+**
+**     This package is free software; you can redistribute it and/or
+**     modify it under the terms of the GNU General Public License as
+**     published by the Free Software Foundation; either version 2 of
+**     the License, or (at your option) any later version.
+**
+**     This package is distributed in the hope that it will be useful,
+**     but WITHOUT ANY WARRANTY; without even the implied warranty of
+**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+**     General Public License for more details.
+**     \endlegal
+*/
+/* ========================================================================= */
+
+/* === S T A R T =========================================================== */
+
+#ifndef __SYNFIG_STUDIO_STATE_MIRROR_H
+#define __SYNFIG_STUDIO_STATE_MIRROR_H
+
+/* === H E A D E R S ======================================================= */
+
+#include "smach.h"
+
+/* === M A C R O S ========================================================= */
+
+/* === T Y P E D E F S ===================================================== */
+
+/* === C L A S S E S & S T R U C T S ======================================= */
+
+namespace studio {
+
+class StateMirror_Context;
+
+class StateMirror : public Smach::state<StateMirror_Context>
+{
+public:
+       StateMirror();
+       ~StateMirror();
+}; // END of class StateMirror
+
+extern StateMirror state_mirror;
+
+}; // END of namespace studio
+
+/* === E N D =============================================================== */
+
+#endif
diff --git a/synfig-studio/src/gui/states/state_normal.cpp b/synfig-studio/src/gui/states/state_normal.cpp
new file mode 100644 (file)
index 0000000..c763022
--- /dev/null
@@ -0,0 +1,824 @@
+/* === S Y N F I G ========================================================= */
+/*!    \file state_normal.cpp
+**     \brief Template File
+**
+**     $Id$
+**
+**     \legal
+**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+**     Copyright (c) 2007, 2008 Chris Moore
+**     Copyright (c) 2009 Nikita Kitaev
+**
+**     This package is free software; you can redistribute it and/or
+**     modify it under the terms of the GNU General Public License as
+**     published by the Free Software Foundation; either version 2 of
+**     the License, or (at your option) any later version.
+**
+**     This package is distributed in the hope that it will be useful,
+**     but WITHOUT ANY WARRANTY; without even the implied warranty of
+**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+**     General Public License for more details.
+**     \endlegal
+*/
+/* ========================================================================= */
+
+/* === H E A D E R S ======================================================= */
+
+#ifdef USING_PCH
+#      include "pch.h"
+#else
+#ifdef HAVE_CONFIG_H
+#      include <config.h>
+#endif
+
+#include <gtkmm/dialog.h>
+#include <gtkmm/entry.h>
+
+#include <synfig/valuenode_animated.h>
+#include <synfig/valuenode_blinecalcvertex.h>
+#include <synfig/valuenode_composite.h>
+#include <synfig/valuenode_const.h>
+#include <synfig/valuenode_dynamiclist.h>
+#include <synfigapp/action_system.h>
+
+#include "state_normal.h"
+#include "canvasview.h"
+#include "workarea.h"
+#include "app.h"
+
+#include <synfigapp/action.h>
+#include "event_mouse.h"
+#include "event_layerclick.h"
+#include "toolbox.h"
+#include "dialog_tooloptions.h"
+#include <gtkmm/optionmenu.h>
+#include "duck.h"
+#include <synfig/angle.h>
+#include <synfigapp/main.h>
+
+#include "general.h"
+#endif
+
+/* === U S I N G =========================================================== */
+
+using namespace std;
+using namespace etl;
+using namespace synfig;
+using namespace studio;
+
+/* === M A C R O S ========================================================= */
+
+#ifndef EPSILON
+#define EPSILON        0.0000001
+#endif
+
+/* === G L O B A L S ======================================================= */
+
+StateNormal studio::state_normal;
+
+/* === C L A S S E S & S T R U C T S ======================================= */
+
+class DuckDrag_Combo : public DuckDrag_Base
+{
+       synfig::Vector last_move;
+       synfig::Vector drag_offset;
+       synfig::Vector center;
+       synfig::Vector snap;
+
+       synfig::Angle original_angle;
+       synfig::Real original_mag;
+
+       std::vector<synfig::Vector> last_;
+       std::vector<synfig::Vector> positions;
+
+
+       bool bad_drag;
+       bool move_only;
+
+public:
+       etl::handle<CanvasView> canvas_view_;
+       bool scale;
+       bool rotate;
+       bool constrain;
+       DuckDrag_Combo();
+       void begin_duck_drag(Duckmatic* duckmatic, const synfig::Vector& begin);
+       bool end_duck_drag(Duckmatic* duckmatic);
+       void duck_drag(Duckmatic* duckmatic, const synfig::Vector& vector);
+
+       etl::handle<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view_->canvas_interface();}
+};
+
+
+class studio::StateNormal_Context : public sigc::trackable
+{
+       etl::handle<CanvasView> canvas_view_;
+
+       synfigapp::Settings& settings;
+
+       sigc::connection keypress_connect;
+       sigc::connection keyrelease_connect;
+
+       etl::handle<DuckDrag_Combo> duck_dragger_;
+
+       Gtk::Table options_table;
+
+       Gtk::CheckButton checkbutton_rotate;
+       Gtk::CheckButton checkbutton_scale;
+       Gtk::CheckButton checkbutton_constrain;
+
+public:
+
+       bool get_rotate_flag()const { return checkbutton_rotate.get_active(); }
+       void set_rotate_flag(bool x) { checkbutton_rotate.set_active(x); refresh_rotate_flag(); }
+       void refresh_rotate_flag() { if(duck_dragger_)duck_dragger_->rotate=get_rotate_flag(); }
+
+       bool get_scale_flag()const { return checkbutton_scale.get_active(); }
+       void set_scale_flag(bool x) { checkbutton_scale.set_active(x); refresh_scale_flag(); }
+       void refresh_scale_flag() { if(duck_dragger_)duck_dragger_->scale=get_scale_flag(); }
+
+       bool get_constrain_flag()const { return checkbutton_constrain.get_active(); }
+       void set_constrain_flag(bool x) { checkbutton_constrain.set_active(x); refresh_constrain_flag(); }
+       void refresh_constrain_flag() { if(duck_dragger_)duck_dragger_->constrain=get_constrain_flag(); }
+
+       StateNormal_Context(CanvasView* canvas_view);
+
+       ~StateNormal_Context();
+
+       const etl::handle<CanvasView>& get_canvas_view()const{return canvas_view_;}
+       etl::handle<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view_->canvas_interface();}
+       synfig::Canvas::Handle get_canvas()const{return canvas_view_->get_canvas();}
+       WorkArea * get_work_area()const{return canvas_view_->get_work_area();}
+
+       void load_settings();
+       void save_settings();
+
+       bool key_pressed(GdkEventKey *event);
+       bool key_released(GdkEventKey *event);
+
+       Smach::event_result event_stop_handler(const Smach::event& x);
+       Smach::event_result event_refresh_handler(const Smach::event& x);
+       Smach::event_result event_refresh_ducks_handler(const Smach::event& x);
+       Smach::event_result event_undo_handler(const Smach::event& x);
+       Smach::event_result event_redo_handler(const Smach::event& x);
+       Smach::event_result event_mouse_button_down_handler(const Smach::event& x);
+       Smach::event_result event_multiple_ducks_clicked_handler(const Smach::event& x);
+       Smach::event_result event_refresh_tool_options(const Smach::event& x);
+       void refresh_tool_options();
+       Smach::event_result event_layer_click(const Smach::event& x);
+
+
+};     // END of class StateNormal_Context
+
+/* === M E T H O D S ======================================================= */
+
+StateNormal::StateNormal():
+       Smach::state<StateNormal_Context>("normal")
+{
+       insert(event_def(EVENT_STOP,&StateNormal_Context::event_stop_handler));
+       insert(event_def(EVENT_REFRESH,&StateNormal_Context::event_refresh_handler));
+       insert(event_def(EVENT_REFRESH_DUCKS,&StateNormal_Context::event_refresh_ducks_handler));
+       insert(event_def(EVENT_UNDO,&StateNormal_Context::event_undo_handler));
+       insert(event_def(EVENT_REDO,&StateNormal_Context::event_redo_handler));
+       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateNormal_Context::event_mouse_button_down_handler));
+       insert(event_def(EVENT_WORKAREA_MULTIPLE_DUCKS_CLICKED,&StateNormal_Context::event_multiple_ducks_clicked_handler));
+       insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateNormal_Context::event_refresh_tool_options));
+       insert(event_def(EVENT_WORKAREA_LAYER_CLICKED,&StateNormal_Context::event_layer_click));
+
+}
+
+StateNormal::~StateNormal()
+{
+}
+
+void
+StateNormal_Context::load_settings()
+{
+       String value;
+
+       if(settings.get_value("normal.rotate",value) && value=="1")
+               set_rotate_flag(true);
+       else
+               set_rotate_flag(false);
+
+       if(settings.get_value("normal.scale",value) && value=="1")
+               set_scale_flag(true);
+       else
+               set_scale_flag(false);
+
+       if(settings.get_value("normal.constrain",value) && value=="1")
+               set_constrain_flag(true);
+       else
+               set_constrain_flag(false);
+
+}
+
+void
+StateNormal_Context::save_settings()
+{
+       settings.set_value("normal.rotate",get_rotate_flag()?"1":"0");
+       settings.set_value("normal.scale",get_scale_flag()?"1":"0");
+       settings.set_value("normal.constrain",get_constrain_flag()?"1":"0");
+}
+
+StateNormal_Context::StateNormal_Context(CanvasView* canvas_view):
+       canvas_view_(canvas_view),
+       settings(synfigapp::Main::get_selected_input_device()->settings()),
+       duck_dragger_(new DuckDrag_Combo()),
+       checkbutton_rotate(_("Rotate (Ctrl)")),
+       checkbutton_scale(_("Scale (Alt)")),
+       checkbutton_constrain(_("Constrain (Shift)"))
+{
+       duck_dragger_->canvas_view_=get_canvas_view();
+
+       // Set up the tool options dialog
+       options_table.attach(*manage(new Gtk::Label(_("Normal Tool"))), 0, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(checkbutton_rotate,                                                        0, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(checkbutton_scale,                                                 0, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(checkbutton_constrain,                                                     0, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+
+       checkbutton_rotate.signal_toggled().connect(sigc::mem_fun(*this,&StateNormal_Context::refresh_rotate_flag));
+       checkbutton_scale.signal_toggled().connect(sigc::mem_fun(*this,&StateNormal_Context::refresh_scale_flag));
+       checkbutton_constrain.signal_toggled().connect(sigc::mem_fun(*this,&StateNormal_Context::refresh_constrain_flag));
+
+
+       options_table.show_all();
+       refresh_tool_options();
+       //App::dialog_tool_options->set_widget(options_table);
+       //App::dialog_tool_options->present();
+
+       get_work_area()->set_allow_layer_clicks(true);
+       get_work_area()->set_duck_dragger(duck_dragger_);
+
+       keypress_connect=get_work_area()->signal_key_press_event().connect(sigc::mem_fun(*this,&StateNormal_Context::key_pressed),false);
+       keyrelease_connect=get_work_area()->signal_key_release_event().connect(sigc::mem_fun(*this,&StateNormal_Context::key_released),false);
+
+       //these will segfault
+//     get_work_area()->set_cursor(Gdk::CROSSHAIR);
+//     get_work_area()->reset_cursor();
+
+       App::toolbox->refresh();
+
+       load_settings();
+       refresh_scale_flag();
+}
+
+bool
+StateNormal_Context::key_pressed(GdkEventKey *event)
+{
+       switch(event->keyval)
+       {
+               case GDK_Control_L:
+               case GDK_Control_R:
+                       set_rotate_flag(true);
+                       break;
+               case GDK_Alt_L:
+               case GDK_Alt_R:
+                       set_scale_flag(true);
+                       break;
+               case GDK_Shift_L:
+               case GDK_Shift_R:
+                       set_constrain_flag(true);
+                       break;
+               default:
+                       break;
+       }
+       return false; //Pass on the event to other handlers, just in case
+}
+
+bool
+StateNormal_Context::key_released(GdkEventKey *event)
+{
+       switch(event->keyval)
+       {
+               case GDK_Control_L:
+               case GDK_Control_R:
+                       set_rotate_flag(false);
+                       break;
+               case GDK_Alt_L:
+               case GDK_Alt_R:
+                       set_scale_flag(false);
+                       break;
+               case GDK_Shift_L:
+               case GDK_Shift_R:
+                       set_constrain_flag(false);
+                       break;
+               default:
+                       break;
+       }
+       return false; //Pass on the event to other handlers
+}
+
+void
+StateNormal_Context::refresh_tool_options()
+{
+       App::dialog_tool_options->clear();
+       App::dialog_tool_options->set_widget(options_table);
+       App::dialog_tool_options->set_local_name(_("Normal Tool"));
+       App::dialog_tool_options->set_name("normal");
+}
+
+
+
+StateNormal_Context::~StateNormal_Context()
+{
+       save_settings();
+
+       get_work_area()->clear_duck_dragger();
+       get_work_area()->reset_cursor();
+
+       keypress_connect.disconnect();
+       keyrelease_connect.disconnect();
+
+       App::dialog_tool_options->clear();
+
+       App::toolbox->refresh();
+}
+
+DuckDrag_Combo::DuckDrag_Combo():
+       scale(false),
+       rotate(false),
+       constrain(false) // Lock aspect for scale; smooth move for translate
+{
+}
+
+void
+DuckDrag_Combo::begin_duck_drag(Duckmatic* duckmatic, const synfig::Vector& offset)
+{
+       last_move=Vector(1,1);
+
+       const DuckList selected_ducks(duckmatic->get_selected_ducks());
+       DuckList::const_iterator iter;
+
+       bad_drag=false;
+
+               drag_offset=duckmatic->find_duck(offset)->get_trans_point();
+
+               //snap=drag_offset-duckmatic->snap_point_to_grid(drag_offset);
+               //snap=offset-drag_offset_;
+               snap=Vector(0,0);
+
+       // Calculate center
+       Point vmin(100000000,100000000);
+       Point vmax(-100000000,-100000000);
+       //std::set<etl::handle<Duck> >::iterator iter;
+       positions.clear();
+       int i;
+       for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
+       {
+               Point p((*iter)->get_trans_point());
+               vmin[0]=min(vmin[0],p[0]);
+               vmin[1]=min(vmin[1],p[1]);
+               vmax[0]=max(vmax[0],p[0]);
+               vmax[1]=max(vmax[1],p[1]);
+               positions.push_back(p);
+       }
+       center=(vmin+vmax)*0.5;
+       if((vmin-vmax).mag()<=EPSILON)
+               move_only=true;
+       else
+               move_only=false;
+
+
+       synfig::Vector vect(offset-center);
+       original_angle=Angle::tan(vect[1],vect[0]);
+       original_mag=vect.mag();
+}
+
+
+void
+DuckDrag_Combo::duck_drag(Duckmatic* duckmatic, const synfig::Vector& vector)
+{
+       if (!duckmatic) return;
+
+       if(bad_drag)
+               return;
+
+       //Override axis lock set in workarea when holding down the shift key
+       if (!move_only && (scale || rotate))
+               duckmatic->set_axis_lock(false);
+
+       synfig::Vector vect;
+       if (move_only || (!scale && !rotate))
+               vect= duckmatic->snap_point_to_grid(vector)-drag_offset+snap;
+       else
+               vect= duckmatic->snap_point_to_grid(vector)-center+snap;
+
+       last_move=vect;
+
+       const DuckList selected_ducks(duckmatic->get_selected_ducks());
+       DuckList::const_iterator iter;
+
+       Time time(duckmatic->get_time());
+
+       int i;
+       if( move_only || (!scale && !rotate) )
+       {
+               for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
+               {
+                       if((*iter)->get_type()==Duck::TYPE_VERTEX || (*iter)->get_type()==Duck::TYPE_POSITION)
+                               (*iter)->set_trans_point(positions[i]+vect, time);
+               }
+               for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
+               {
+                       if((*iter)->get_type()!=Duck::TYPE_VERTEX&&(*iter)->get_type()!=Duck::TYPE_POSITION)
+                               (*iter)->set_trans_point(positions[i]+vect, time);
+               }
+       }
+
+       if (rotate)
+       {
+               Angle::deg angle(Angle::tan(vect[1],vect[0]));
+               angle=original_angle-angle;
+               if (constrain)
+               {
+                       float degrees = angle.get()/15;
+                       angle= Angle::deg (degrees>0?std::floor(degrees)*15:std::ceil(degrees)*15);
+               }
+               Real mag(vect.mag()/original_mag);
+               Real sine(Angle::sin(angle).get());
+               Real cosine(Angle::cos(angle).get());
+
+               for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
+               {
+                       if((*iter)->get_type()!=Duck::TYPE_VERTEX&&(*iter)->get_type()!=Duck::TYPE_POSITION)continue;
+
+                       Vector x(positions[i]-center),p;
+
+                       p[0]=cosine*x[0]+sine*x[1];
+                       p[1]=-sine*x[0]+cosine*x[1];
+                       if(scale)p*=mag;
+                       p+=center;
+                       (*iter)->set_trans_point(p, time);
+               }
+               for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
+               {
+                       if(!((*iter)->get_type()!=Duck::TYPE_VERTEX&&(*iter)->get_type()!=Duck::TYPE_POSITION))continue;
+
+                       Vector x(positions[i]-center),p;
+
+                       p[0]=cosine*x[0]+sine*x[1];
+                       p[1]=-sine*x[0]+cosine*x[1];
+                       if(scale)p*=mag;
+                       p+=center;
+                       (*iter)->set_trans_point(p, time);
+               }
+       } else if (scale)
+       {
+               if(!constrain)
+               {
+                       if(abs(drag_offset[0]-center[0])>EPSILON)
+                               vect[0]/=drag_offset[0]-center[0];
+                       else
+                               vect[0]=1;
+                       if(abs(drag_offset[1]-center[1])>EPSILON)
+                               vect[1]/=drag_offset[1]-center[1];
+                       else
+                               vect[1]=1;
+                       }
+               else
+               {
+                       //vect[0]=vect[1]=vect.mag()*0.707106781;
+                       Real amount(vect.mag()/(drag_offset-center).mag());
+                       vect[0]=vect[1]=amount;
+               }
+
+               if(vect[0]<EPSILON && vect[0]>-EPSILON)
+                       vect[0]=1;
+               if(vect[1]<EPSILON && vect[1]>-EPSILON)
+                       vect[1]=1;
+
+               for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
+               {
+                       if(((*iter)->get_type()!=Duck::TYPE_VERTEX&&(*iter)->get_type()!=Duck::TYPE_POSITION))continue;
+
+                       Vector p(positions[i]-center);
+
+                       p[0]*=vect[0];
+                       p[1]*=vect[1];
+                       p+=center;
+                       (*iter)->set_trans_point(p, time);
+               }
+               for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
+               {
+                       if(!((*iter)->get_type()!=Duck::TYPE_VERTEX&&(*iter)->get_type()!=Duck::TYPE_POSITION))continue;
+
+                       Vector p(positions[i]-center);
+
+                       p[0]*=vect[0];
+                       p[1]*=vect[1];
+                       p+=center;
+                       (*iter)->set_trans_point(p, time);
+               }
+       }
+
+       // then patch up the tangents for the vertices we've moved
+       duckmatic->update_ducks();
+
+       last_move=vect;
+}
+
+bool
+DuckDrag_Combo::end_duck_drag(Duckmatic* duckmatic)
+{
+       if(bad_drag)return false;
+
+       //synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Rotate Ducks"));
+
+       if((last_move-Vector(1,1)).mag()>0.0001)
+       {
+               duckmatic->signal_edited_selected_ducks();
+               return true;
+       }
+       else
+       {
+               duckmatic->signal_user_click_selected_ducks(0);
+               return false;
+       }
+}
+
+Smach::event_result
+StateNormal_Context::event_refresh_tool_options(const Smach::event& /*x*/)
+{
+       refresh_tool_options();
+       return Smach::RESULT_ACCEPT;
+}
+
+Smach::event_result
+StateNormal_Context::event_stop_handler(const Smach::event& /*x*/)
+{
+       // synfig::info("STATE NORMAL: Received Stop Event");
+       canvas_view_->stop();
+       return Smach::RESULT_ACCEPT;
+}
+
+Smach::event_result
+StateNormal_Context::event_refresh_handler(const Smach::event& /*x*/)
+{
+       // synfig::info("STATE NORMAL: Received Refresh Event");
+       canvas_view_->rebuild_tables();
+       canvas_view_->work_area->queue_render_preview();
+       return Smach::RESULT_ACCEPT;
+}
+
+Smach::event_result
+StateNormal_Context::event_refresh_ducks_handler(const Smach::event& /*x*/)
+{
+       // synfig::info("STATE NORMAL: Received Refresh Ducks");
+       canvas_view_->queue_rebuild_ducks();
+       return Smach::RESULT_ACCEPT;
+}
+
+Smach::event_result
+StateNormal_Context::event_undo_handler(const Smach::event& /*x*/)
+{
+       // synfig::info("STATE NORMAL: Received Undo Event");
+       canvas_view_->get_instance()->undo();
+       return Smach::RESULT_ACCEPT;
+}
+
+Smach::event_result
+StateNormal_Context::event_redo_handler(const Smach::event& /*x*/)
+{
+       // synfig::info("STATE NORMAL: Received Redo Event");
+       canvas_view_->get_instance()->redo();
+       return Smach::RESULT_ACCEPT;
+}
+
+Smach::event_result
+StateNormal_Context::event_mouse_button_down_handler(const Smach::event& x)
+{
+       // synfig::info("STATE NORMAL: Received mouse button down Event");
+
+       const EventMouse& event(*reinterpret_cast<const EventMouse*>(&x));
+
+       switch(event.button)
+       {
+       case BUTTON_RIGHT:
+               canvas_view_->popup_main_menu();
+               return Smach::RESULT_ACCEPT;
+       default:
+               return Smach::RESULT_OK;
+       }
+}
+
+Smach::event_result
+StateNormal_Context::event_layer_click(const Smach::event& x)
+{
+       const EventLayerClick& event(*reinterpret_cast<const EventLayerClick*>(&x));
+
+       if(event.layer)
+       {
+               // synfig::info("STATE NORMAL: Received layer click Event, \"%s\"",event.layer->get_name().c_str());
+       }
+       else
+       {
+               // synfig::info("STATE NORMAL: Received layer click Event with an empty layer.");
+       }
+
+       switch(event.button)
+       {
+       case BUTTON_LEFT:
+               if(!(event.modifier&Gdk::CONTROL_MASK))
+                       canvas_view_->get_selection_manager()->clear_selected_layers();
+               if(event.layer)
+               {
+                       std::list<Layer::Handle> layer_list(canvas_view_->get_selection_manager()->get_selected_layers());
+                       std::set<Layer::Handle> layers(layer_list.begin(),layer_list.end());
+                       if(layers.count(event.layer))
+                       {
+                               layers.erase(event.layer);
+                               layer_list=std::list<Layer::Handle>(layers.begin(),layers.end());
+                               canvas_view_->get_selection_manager()->clear_selected_layers();
+                               canvas_view_->get_selection_manager()->set_selected_layers(layer_list);
+                       }
+                       else
+                       {
+                               canvas_view_->get_selection_manager()->set_selected_layer(event.layer);
+                       }
+               }
+               return Smach::RESULT_ACCEPT;
+       case BUTTON_RIGHT:
+               canvas_view_->popup_layer_menu(event.layer);
+               return Smach::RESULT_ACCEPT;
+       default:
+               return Smach::RESULT_OK;
+       }
+}
+
+/*
+void
+StateNormal_Context::edit_several_waypoints(std::list<synfigapp::ValueDesc> value_desc_list)
+{
+       Gtk::Dialog dialog(
+               "Edit Multiple Waypoints",              // Title
+               true,           // Modal
+               true            // use_separator
+       );
+
+       Widget_WaypointModel widget_waypoint_model;
+       widget_waypoint_model.show();
+
+       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();
+
+       if(dialog.run()==0)
+               return;
+       synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Set Waypoints"));
+
+       std::list<synfigapp::ValueDesc>::iterator iter;
+       for(iter=value_desc_list.begin();iter!=value_desc_list.end();++iter)
+       {
+               synfigapp::ValueDesc value_desc(*iter);
+
+               if(!value_desc.is_valid())
+                       continue;
+
+               ValueNode_Animated::Handle value_node;
+
+               // If this value isn't a ValueNode_Animated, but
+               // it is somewhat constant, then go ahead and convert
+               // it to a ValueNode_Animated.
+               if(!value_desc.is_value_node() || ValueNode_Const::Handle::cast_dynamic(value_desc.get_value_node()))
+               {
+                       ValueBase value;
+                       if(value_desc.is_value_node())
+                               value=ValueNode_Const::Handle::cast_dynamic(value_desc.get_value_node())->get_value();
+                       else
+                               value=value_desc.get_value();
+
+                       value_node=ValueNode_Animated::create(value,get_canvas()->get_time());
+
+                       synfigapp::Action::Handle action;
+
+                       if(!value_desc.is_value_node())
+                       {
+                               action=synfigapp::Action::create("ValueDescConnect");
+                               action->set_param("dest",value_desc);
+                               action->set_param("src",ValueNode::Handle(value_node));
+                       }
+                       else
+                       {
+                               action=synfigapp::Action::create("ValueNodeReplace");
+                               action->set_param("dest",value_desc.get_value_node());
+                               action->set_param("src",ValueNode::Handle(value_node));
+                       }
+
+                       action->set_param("canvas",get_canvas());
+                       action->set_param("canvas_interface",get_canvas_interface());
+
+
+                       if(!get_canvas_interface()->get_instance()->perform_action(action))
+                       {
+                               get_canvas_view()->get_ui_interface()->error(_("Unable to convert to animated waypoint"));
+                               group.cancel();
+                               return;
+                       }
+               }
+               else
+               {
+                       if(value_desc.is_value_node())
+                               value_node=ValueNode_Animated::Handle::cast_dynamic(value_desc.get_value_node());
+               }
+
+
+               if(value_node)
+               {
+
+                       synfigapp::Action::Handle action(synfigapp::Action::create("WaypointSetSmart"));
+
+                       if(!action)
+                       {
+                               get_canvas_view()->get_ui_interface()->error(_("Unable to find WaypointSetSmart action"));
+                               group.cancel();
+                               return;
+                       }
+
+
+                       action->set_param("canvas",get_canvas());
+                       action->set_param("canvas_interface",get_canvas_interface());
+                       action->set_param("value_node",ValueNode::Handle(value_node));
+                       action->set_param("time",get_canvas()->get_time());
+                       action->set_param("model",widget_waypoint_model.get_waypoint_model());
+
+                       if(!get_canvas_interface()->get_instance()->perform_action(action))
+                       {
+                               get_canvas_view()->get_ui_interface()->error(_("Unable to set a specific waypoint"));
+                               group.cancel();
+                               return;
+                       }
+               }
+               else
+               {
+                       //get_canvas_view()->get_ui_interface()->error(_("Unable to animate a specific valuedesc"));
+                       //group.cancel();
+                       //return;
+               }
+
+       }
+}
+*/
+
+Smach::event_result
+StateNormal_Context::event_multiple_ducks_clicked_handler(const Smach::event& /*x*/)
+{
+       // synfig::info("STATE NORMAL: Received multiple duck click event");
+
+       //const EventMouse& event(*reinterpret_cast<const EventMouse*>(&x));
+
+       std::list<synfigapp::ValueDesc> value_desc_list;
+
+       // Create a list of value_descs associated with selection
+       const DuckList selected_ducks(get_work_area()->get_selected_ducks());
+       DuckList::const_iterator iter;
+       for(iter=selected_ducks.begin();iter!=selected_ducks.end();++iter)
+       {
+               synfigapp::ValueDesc value_desc((*iter)->get_value_desc());
+
+               if(!value_desc.is_valid())
+                       continue;
+
+               if(value_desc.get_value_type()==ValueBase::TYPE_BLINEPOINT && value_desc.is_value_node() && ValueNode_Composite::Handle::cast_dynamic(value_desc.get_value_node()))
+               {
+                       value_desc_list.push_back(
+                               synfigapp::ValueDesc(
+                                       ValueNode_Composite::Handle::cast_dynamic(value_desc.get_value_node())
+                                       ,ValueNode_Composite::Handle::cast_dynamic(value_desc.get_value_node())
+                                                               ->get_link_index_from_name("point")
+                               )
+                       );
+               }
+               else
+                       value_desc_list.push_back(value_desc);
+       }
+
+       Gtk::Menu *menu=manage(new Gtk::Menu());
+       menu->signal_hide().connect(sigc::bind(sigc::ptr_fun(&delete_widget), menu));
+
+       canvas_view_->get_instance()->make_param_menu(menu,canvas_view_->get_canvas(),value_desc_list);
+
+       /*
+       synfigapp::Action::ParamList param_list;
+       param_list=get_canvas_interface()->generate_param_list(value_desc_list);
+
+       canvas_view_->add_actions_to_menu(menu, param_list,synfigapp::Action::CATEGORY_VALUEDESC|synfigapp::Action::CATEGORY_VALUENODE);
+
+       menu->items().push_back(Gtk::Menu_Helpers::MenuElem(_("Edit Waypoints"),
+               sigc::bind(
+                       sigc::mem_fun(
+                               *this,
+                               &studio::StateNormal_Context::edit_several_waypoints
+                       ),
+                       value_desc_list
+               )
+       ));
+       */
+       menu->popup(3,gtk_get_current_event_time());
+
+       return Smach::RESULT_ACCEPT;
+}
+
+
diff --git a/synfig-studio/src/gui/states/state_normal.h b/synfig-studio/src/gui/states/state_normal.h
new file mode 100644 (file)
index 0000000..01b040b
--- /dev/null
@@ -0,0 +1,57 @@
+/* === S Y N F I G ========================================================= */
+/*!    \file state_normal.h
+**     \brief Template Header
+**
+**     $Id$
+**
+**     \legal
+**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+**     Copyright (c) 2009 Nikita Kitaev
+**
+**     This package is free software; you can redistribute it and/or
+**     modify it under the terms of the GNU General Public License as
+**     published by the Free Software Foundation; either version 2 of
+**     the License, or (at your option) any later version.
+**
+**     This package is distributed in the hope that it will be useful,
+**     but WITHOUT ANY WARRANTY; without even the implied warranty of
+**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+**     General Public License for more details.
+**     \endlegal
+*/
+/* ========================================================================= */
+
+/* === S T A R T =========================================================== */
+
+#ifndef __SYNFIG_STUDIO_STATE_NORMAL_H
+#define __SYNFIG_STUDIO_STATE_NORMAL_H
+
+/* === H E A D E R S ======================================================= */
+
+#include "smach.h"
+
+
+/* === M A C R O S ========================================================= */
+
+/* === T Y P E D E F S ===================================================== */
+
+/* === C L A S S E S & S T R U C T S ======================================= */
+
+namespace studio {
+
+class StateNormal_Context;
+
+class StateNormal : public Smach::state<StateNormal_Context>
+{
+public:
+       StateNormal();
+       ~StateNormal();
+}; // END of class StateNormal
+
+extern StateNormal state_normal;
+
+}; // END of namespace studio
+
+/* === E N D =============================================================== */
+
+#endif
diff --git a/synfig-studio/src/gui/states/state_polygon.cpp b/synfig-studio/src/gui/states/state_polygon.cpp
new file mode 100644 (file)
index 0000000..7c11c05
--- /dev/null
@@ -0,0 +1,945 @@
+/* === S Y N F I G ========================================================= */
+/*!    \file state_polygon.cpp
+**     \brief Template File
+**
+**     $Id$
+**
+**     \legal
+**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+**     Copyright (c) 2007, 2008 Chris Moore
+**
+**     This package is free software; you can redistribute it and/or
+**     modify it under the terms of the GNU General Public License as
+**     published by the Free Software Foundation; either version 2 of
+**     the License, or (at your option) any later version.
+**
+**     This package is distributed in the hope that it will be useful,
+**     but WITHOUT ANY WARRANTY; without even the implied warranty of
+**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+**     General Public License for more details.
+**     \endlegal
+*/
+/* ========================================================================= */
+
+/* === H E A D E R S ======================================================= */
+
+#ifdef USING_PCH
+#      include "pch.h"
+#else
+#ifdef HAVE_CONFIG_H
+#      include <config.h>
+#endif
+
+#include <gtkmm/dialog.h>
+#include <gtkmm/entry.h>
+
+#include <synfig/valuenode_dynamiclist.h>
+#include <synfigapp/action_system.h>
+#include <synfig/valuenode_bline.h>
+
+#include "state_polygon.h"
+#include "state_normal.h"
+#include "canvasview.h"
+#include "workarea.h"
+#include "app.h"
+
+#include <synfigapp/action.h>
+#include "event_mouse.h"
+#include "event_layerclick.h"
+#include "toolbox.h"
+#include "dialog_tooloptions.h"
+#include <synfigapp/main.h>
+
+#include "general.h"
+
+#endif
+
+/* === U S I N G =========================================================== */
+
+using namespace std;
+using namespace etl;
+using namespace synfig;
+using namespace studio;
+
+/* === M A C R O S ========================================================= */
+
+/* === G L O B A L S ======================================================= */
+
+StatePolygon studio::state_polygon;
+
+/* === C L A S S E S & S T R U C T S ======================================= */
+
+class studio::StatePolygon_Context : public sigc::trackable
+{
+       etl::handle<CanvasView> canvas_view_;
+       CanvasView::IsWorking is_working;
+
+       bool prev_table_status;
+       bool prev_workarea_layer_status_;
+
+       Gtk::Menu menu;
+
+       Duckmatic::Push duckmatic_push;
+
+       std::list<synfig::Point> polygon_point_list;
+       synfigapp::Settings& settings;
+
+
+       bool on_polygon_duck_change(const synfig::Point &point, std::list<synfig::Point>::iterator iter);
+
+
+       void popup_handle_menu(synfigapp::ValueDesc value_desc);
+
+
+       void refresh_ducks();
+
+       Gtk::Table options_table;
+       Gtk::Entry entry_id;
+       Gtk::CheckButton checkbutton_invert;
+       Gtk::CheckButton checkbutton_layer_polygon;
+       Gtk::CheckButton checkbutton_layer_region;
+       Gtk::CheckButton checkbutton_layer_outline;
+       Gtk::CheckButton checkbutton_layer_curve_gradient;
+       Gtk::CheckButton checkbutton_layer_plant;
+       Gtk::CheckButton checkbutton_layer_link_origins;
+       Gtk::Button button_make;
+       Gtk::Adjustment  adj_feather;
+       Gtk::SpinButton  spin_feather;
+
+public:
+
+       // this counts the layers we create - they all have origins we can link
+       int layers_to_create()const
+       {
+               return
+                       get_layer_polygon_flag() +
+                       get_layer_region_flag() +
+                       get_layer_outline_flag() +
+                       get_layer_curve_gradient_flag() +
+                       get_layer_plant_flag();
+       }
+
+       synfig::String get_id()const { return entry_id.get_text(); }
+       void set_id(const synfig::String& x) { return entry_id.set_text(x); }
+
+       bool get_invert()const { return checkbutton_invert.get_active(); }
+       void set_invert(bool i) { checkbutton_invert.set_active(i); }
+
+       bool get_layer_polygon_flag()const { return checkbutton_layer_polygon.get_active(); }
+       void set_layer_polygon_flag(bool x) { return checkbutton_layer_polygon.set_active(x); }
+
+       bool get_layer_region_flag()const { return checkbutton_layer_region.get_active(); }
+       void set_layer_region_flag(bool x) { return checkbutton_layer_region.set_active(x); }
+
+       bool get_layer_outline_flag()const { return checkbutton_layer_outline.get_active(); }
+       void set_layer_outline_flag(bool x) { return checkbutton_layer_outline.set_active(x); }
+
+       bool get_layer_curve_gradient_flag()const { return checkbutton_layer_curve_gradient.get_active(); }
+       void set_layer_curve_gradient_flag(bool x) { return checkbutton_layer_curve_gradient.set_active(x); }
+
+       bool get_layer_plant_flag()const { return checkbutton_layer_plant.get_active(); }
+       void set_layer_plant_flag(bool x) { return checkbutton_layer_plant.set_active(x); }
+
+       bool get_layer_link_origins_flag()const { return checkbutton_layer_link_origins.get_active(); }
+       void set_layer_link_origins_flag(bool x) { return checkbutton_layer_link_origins.set_active(x); }
+
+       Real get_feather() const { return adj_feather.get_value(); }
+       void set_feather(Real x) { return adj_feather.set_value(x); }
+
+       Smach::event_result event_stop_handler(const Smach::event& x);
+
+       Smach::event_result event_refresh_handler(const Smach::event& x);
+
+       Smach::event_result event_mouse_click_handler(const Smach::event& x);
+       Smach::event_result event_refresh_tool_options(const Smach::event& x);
+       void refresh_tool_options();
+
+       StatePolygon_Context(CanvasView* canvas_view);
+
+       ~StatePolygon_Context();
+
+       const etl::handle<CanvasView>& get_canvas_view()const{return canvas_view_;}
+       etl::handle<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view_->canvas_interface();}
+       synfig::Canvas::Handle get_canvas()const{return canvas_view_->get_canvas();}
+       WorkArea * get_work_area()const{return canvas_view_->get_work_area();}
+
+       //void on_user_click(synfig::Point point);
+       void load_settings();
+       void save_settings();
+       void reset();
+       void increment_id();
+       bool egress_on_selection_change;
+       Smach::event_result event_layer_selection_changed_handler(const Smach::event& /*x*/)
+       {
+               if(egress_on_selection_change)
+                       throw &state_normal; //throw Smach::egress_exception();
+               return Smach::RESULT_OK;
+       }
+
+       void run();
+};     // END of class StatePolygon_Context
+
+/* === M E T H O D S ======================================================= */
+
+StatePolygon::StatePolygon():
+       Smach::state<StatePolygon_Context>("polygon")
+{
+       insert(event_def(EVENT_LAYER_SELECTION_CHANGED,&StatePolygon_Context::event_layer_selection_changed_handler));
+       insert(event_def(EVENT_STOP,&StatePolygon_Context::event_stop_handler));
+       insert(event_def(EVENT_REFRESH,&StatePolygon_Context::event_refresh_handler));
+       insert(event_def(EVENT_REFRESH_DUCKS,&StatePolygon_Context::event_refresh_handler));
+       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StatePolygon_Context::event_mouse_click_handler));
+       insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StatePolygon_Context::event_refresh_tool_options));
+}
+
+StatePolygon::~StatePolygon()
+{
+}
+
+void
+StatePolygon_Context::load_settings()
+{
+       String value;
+
+       if(settings.get_value("polygon.id",value))
+               set_id(value);
+       else
+               set_id("Polygon");
+
+       if(settings.get_value("polygon.invert",value) && value != "0")
+               set_invert(true);
+       else
+               set_invert(false);
+
+       if(settings.get_value("polygon.layer_polygon",value) && value=="0")
+               set_layer_polygon_flag(false);
+       else
+               set_layer_polygon_flag(true);
+
+       if(settings.get_value("polygon.layer_region",value) && value=="1")
+               set_layer_region_flag(true);
+       else
+               set_layer_region_flag(false);
+
+       if(settings.get_value("polygon.layer_outline",value) && value=="1")
+               set_layer_outline_flag(true);
+       else
+               set_layer_outline_flag(false);
+
+       if(settings.get_value("polygon.layer_curve_gradient",value) && value=="1")
+               set_layer_curve_gradient_flag(true);
+       else
+               set_layer_curve_gradient_flag(false);
+
+       if(settings.get_value("polygon.layer_plant",value) && value=="1")
+               set_layer_plant_flag(true);
+       else
+               set_layer_plant_flag(false);
+
+       if(settings.get_value("polygon.layer_link_origins",value) && value=="0")
+               set_layer_link_origins_flag(false);
+       else
+               set_layer_link_origins_flag(true);
+
+       if(settings.get_value("polygon.feather",value))
+       {
+               Real n = atof(value.c_str());
+               set_feather(n);
+       }
+}
+
+void
+StatePolygon_Context::save_settings()
+{
+       settings.set_value("polygon.id",get_id().c_str());
+       settings.set_value("polygon.invert",get_invert()?"1":"0");
+       settings.set_value("polygon.layer_polygon",get_layer_polygon_flag()?"1":"0");
+       settings.set_value("polygon.layer_outline",get_layer_outline_flag()?"1":"0");
+       settings.set_value("polygon.layer_region",get_layer_region_flag()?"1":"0");
+       settings.set_value("polygon.layer_curve_gradient",get_layer_curve_gradient_flag()?"1":"0");
+       settings.set_value("polygon.layer_plant",get_layer_plant_flag()?"1":"0");
+       settings.set_value("polygon.layer_link_origins",get_layer_link_origins_flag()?"1":"0");
+       settings.set_value("polygon.feather",strprintf("%f",get_feather()));
+}
+
+void
+StatePolygon_Context::reset()
+{
+       polygon_point_list.clear();
+       refresh_ducks();
+}
+
+void
+StatePolygon_Context::increment_id()
+{
+       String id(get_id());
+       int number=1;
+       int digits=0;
+
+       if(id.empty())
+               id="Polygon";
+
+       // If there is a number
+       // already at the end of the
+       // id, then remove it.
+       if(id[id.size()-1]<='9' && id[id.size()-1]>='0')
+       {
+               // figure out how many digits it is
+               for (digits = 0;
+                        (int)id.size()-1 >= digits && id[id.size()-1-digits] <= '9' && id[id.size()-1-digits] >= '0';
+                        digits++)
+                       ;
+
+               String str_number;
+               str_number=String(id,id.size()-digits,id.size());
+               id=String(id,0,id.size()-digits);
+
+               number=atoi(str_number.c_str());
+       }
+       else
+       {
+               number=1;
+               digits=3;
+       }
+
+       number++;
+
+       // Add the number back onto the id
+       {
+               const String format(strprintf("%%0%dd",digits));
+               id+=strprintf(format.c_str(),number);
+       }
+
+       // Set the ID
+       set_id(id);
+}
+
+StatePolygon_Context::StatePolygon_Context(CanvasView* canvas_view):
+       canvas_view_(canvas_view),
+       is_working(*canvas_view),
+       prev_workarea_layer_status_(get_work_area()->get_allow_layer_clicks()),
+       duckmatic_push(get_work_area()),
+       settings(synfigapp::Main::get_selected_input_device()->settings()),
+       entry_id(),
+       checkbutton_invert(_("Invert")),
+       checkbutton_layer_polygon(_("Create Polygon Layer")),
+       checkbutton_layer_region(_("Create Region BLine")),
+       checkbutton_layer_outline(_("Create Outline BLine")),
+       checkbutton_layer_curve_gradient(_("Create Curve Gradient BLine")),
+       checkbutton_layer_plant(_("Create Plant BLine")),
+       checkbutton_layer_link_origins(_("Link Origins")),
+       button_make(_("Make")),
+       adj_feather(0,0,10000,0.01,0.1),
+       spin_feather(adj_feather,0.01,4)
+{
+       egress_on_selection_change=true;
+       load_settings();
+
+       // Set up the tool options dialog
+       options_table.attach(*manage(new Gtk::Label(_("Polygon Tool"))),        0, 2, 0,  1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(entry_id,                                                                          0, 2, 1,  2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+
+       options_table.attach(checkbutton_layer_polygon,                                         0, 2, 2,  3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(checkbutton_layer_outline,                                         0, 2, 3,  4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(checkbutton_layer_region,                                          0, 2, 4,  5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(checkbutton_layer_plant,                                           0, 2, 5,  6, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(checkbutton_layer_curve_gradient,                          0, 2, 6,  7, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(checkbutton_layer_link_origins,                            0, 2, 7,  8, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+
+       //invert flag
+       options_table.attach(checkbutton_invert,                                                        0, 2, 8,  9, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+
+       //feather stuff
+       options_table.attach(*manage(new Gtk::Label(_("Feather"))),             0, 1, 9, 10, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(spin_feather,                                                                      1, 2, 9, 10, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+
+       //options_table.attach(button_make, 0, 2, 4, 5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       button_make.signal_pressed().connect(sigc::mem_fun(*this,&StatePolygon_Context::run));
+       options_table.show_all();
+       refresh_tool_options();
+       App::dialog_tool_options->present();
+
+
+       // Turn off layer clicking
+       get_work_area()->set_allow_layer_clicks(false);
+
+       // clear out the ducks
+       get_work_area()->clear_ducks();
+
+       // Refresh the work area
+       get_work_area()->queue_draw();
+
+       get_work_area()->set_cursor(Gdk::CROSSHAIR);
+
+       // Hide the tables if they are showing
+       prev_table_status=get_canvas_view()->tables_are_visible();
+       if(prev_table_status)get_canvas_view()->hide_tables();
+
+       // Disable the time bar
+       get_canvas_view()->set_sensitive_timebar(false);
+
+       // Connect a signal
+       //get_work_area()->signal_user_click().connect(sigc::mem_fun(*this,&studio::StatePolygon_Context::on_user_click));
+
+       App::toolbox->refresh();
+}
+
+void
+StatePolygon_Context::refresh_tool_options()
+{
+       App::dialog_tool_options->clear();
+       App::dialog_tool_options->set_widget(options_table);
+
+       App::dialog_tool_options->set_local_name(_("Polygon Tool"));
+       App::dialog_tool_options->set_name("polygon");
+
+       App::dialog_tool_options->add_button(
+               Gtk::StockID("gtk-execute"),
+               _("Make Polygon")
+       )->signal_clicked().connect(
+               sigc::mem_fun(
+                       *this,
+                       &StatePolygon_Context::run
+               )
+       );
+
+       App::dialog_tool_options->add_button(
+               Gtk::StockID("gtk-clear"),
+               _("Clear current Polygon")
+       )->signal_clicked().connect(
+               sigc::mem_fun(
+                       *this,
+                       &StatePolygon_Context::reset
+               )
+       );
+}
+
+Smach::event_result
+StatePolygon_Context::event_refresh_tool_options(const Smach::event& /*x*/)
+{
+       refresh_tool_options();
+       return Smach::RESULT_ACCEPT;
+}
+
+StatePolygon_Context::~StatePolygon_Context()
+{
+       run();
+
+       save_settings();
+       // Restore layer clicking
+       get_work_area()->set_allow_layer_clicks(prev_workarea_layer_status_);
+
+       App::dialog_tool_options->clear();
+
+       get_work_area()->reset_cursor();
+
+       // Enable the time bar
+       get_canvas_view()->set_sensitive_timebar(true);
+
+       // Bring back the tables if they were out before
+       if(prev_table_status)get_canvas_view()->show_tables();
+
+       // Refresh the work area
+       get_work_area()->queue_draw();
+
+       App::toolbox->refresh();
+}
+
+Smach::event_result
+StatePolygon_Context::event_stop_handler(const Smach::event& /*x*/)
+{
+       synfig::info("STATE RotoPolygon: Received Stop Event");
+       //throw Smach::egress_exception();
+       reset();
+       return Smach::RESULT_ACCEPT;
+
+}
+
+Smach::event_result
+StatePolygon_Context::event_refresh_handler(const Smach::event& /*x*/)
+{
+       synfig::info("STATE RotoPolygon: Received Refresh Event");
+       refresh_ducks();
+       return Smach::RESULT_ACCEPT;
+}
+
+void
+StatePolygon_Context::run()
+{
+       if(polygon_point_list.empty())
+               return;
+
+       if(polygon_point_list.size()<3)
+       {
+               get_canvas_view()->get_ui_interface()->error("You need at least 3 points to create a polygon");
+               return;
+       }
+
+       synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("New Polygon"));
+
+       Layer::Handle layer;
+
+       Canvas::Handle canvas;
+       int depth(0);
+
+       // we are temporarily using the layer to hold something
+       layer=get_canvas_view()->get_selection_manager()->get_selected_layer();
+       if(layer)
+       {
+               depth=layer->get_depth();
+               canvas=layer->get_canvas();
+       }
+
+       synfigapp::SelectionManager::LayerList layer_selection;
+       if (!getenv("SYNFIG_TOOLS_CLEAR_SELECTION"))
+               layer_selection = get_canvas_view()->get_selection_manager()->get_selected_layers();
+
+       const synfig::TransformStack& transform(get_canvas_view()->get_curr_transform_stack());
+
+       std::vector<BLinePoint> new_list;
+       std::list<synfig::Point>::iterator iter;
+       int i;
+       for(i=0,iter=polygon_point_list.begin();iter!=polygon_point_list.end();++iter,++i)
+       {
+               *iter = transform.unperform(*iter);
+               new_list.push_back(*(new BLinePoint));
+               new_list[i].set_width(1);
+               new_list[i].set_vertex(*iter);
+               new_list[i].set_tangent(Point(0,0));
+       }
+
+       ValueNode_BLine::Handle value_node_bline(ValueNode_BLine::create(new_list));
+       assert(value_node_bline);
+
+       ValueNode_Const::Handle value_node_origin(ValueNode_Const::create(Vector()));
+       assert(value_node_origin);
+
+       // Set the looping flag
+       value_node_bline->set_loop(true);
+
+       if(!canvas)
+               canvas=get_canvas_view()->get_canvas();
+
+       value_node_bline->set_member_canvas(canvas);
+
+       // count how many layers we're going to be creating
+       int layers_to_create = this->layers_to_create();
+
+       ///////////////////////////////////////////////////////////////////////////
+       //   P O L Y G O N
+       ///////////////////////////////////////////////////////////////////////////
+
+       if (get_layer_polygon_flag())
+       {
+               layer=get_canvas_interface()->add_layer_to("polygon",canvas,depth);
+               if (!layer)
+               {
+                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
+                       group.cancel();
+                       return;
+               }
+               layer_selection.push_back(layer);
+
+               layer->set_param("invert",get_invert());
+               get_canvas_interface()->signal_layer_param_changed()(layer,"invert");
+
+               if(get_feather())
+               {
+                       layer->set_param("feather",get_feather());
+                       get_canvas_interface()->signal_layer_param_changed()(layer,"feather");
+               }
+
+               layer->set_description(get_id());
+               get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
+
+               layer->disconnect_dynamic_param("vector_list");
+               if(!layer->set_param("vector_list",polygon_point_list))
+               {
+                       group.cancel();
+                       get_canvas_view()->get_ui_interface()->error("Unable to set layer parameter");
+                       return;
+               }
+
+               {
+                       synfigapp::Action::Handle action(synfigapp::Action::create("ValueDescConvert"));
+                       synfigapp::ValueDesc value_desc(layer,"vector_list");
+                       action->set_param("canvas",get_canvas());
+                       action->set_param("canvas_interface",get_canvas_interface());
+                       action->set_param("value_desc",value_desc);
+                       action->set_param("type","dynamic_list");
+                       action->set_param("time",get_canvas_interface()->get_time());
+                       if(!get_canvas_interface()->get_instance()->perform_action(action))
+                       {
+                               group.cancel();
+                               get_canvas_view()->get_ui_interface()->error("Unable to execute action \"ValueDescConvert\"");
+                               return;
+                       }
+               }
+
+               // only link the polygon's origin parameter if the option is selected and we're creating more than one layer
+               if (get_layer_link_origins_flag() && layers_to_create > 1)
+               {
+                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
+                       assert(action);
+
+                       action->set_param("canvas",get_canvas());
+                       action->set_param("canvas_interface",get_canvas_interface());
+                       action->set_param("layer",layer);
+                       if(!action->set_param("param",String("origin")))
+                               synfig::error("LayerParamConnect didn't like \"param\"");
+                       if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
+                               synfig::error("LayerParamConnect didn't like \"value_node\"");
+
+                       if(!get_canvas_interface()->get_instance()->perform_action(action))
+                       {
+                               get_canvas_view()->get_ui_interface()->error(_("Unable to create Polygon layer"));
+                               group.cancel();
+                               throw String(_("Unable to create Polygon layer"));
+                               return;
+                       }
+               }
+       }
+
+       ///////////////////////////////////////////////////////////////////////////
+       //   C U R V E   G R A D I E N T
+       ///////////////////////////////////////////////////////////////////////////
+
+       if(get_layer_curve_gradient_flag())
+       {
+               synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
+
+               Layer::Handle layer(get_canvas_interface()->add_layer_to("curve_gradient",canvas,depth));
+               if (!layer)
+               {
+                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
+                       group.cancel();
+                       return;
+               }
+               layer_selection.push_back(layer);
+               layer->set_description(get_id()+_(" Gradient"));
+               get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
+
+               {
+                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
+                       assert(action);
+
+                       action->set_param("canvas",get_canvas());
+                       action->set_param("canvas_interface",get_canvas_interface());
+                       action->set_param("layer",layer);
+                       if(!action->set_param("param",String("bline")))
+                               synfig::error("LayerParamConnect didn't like \"param\"");
+                       if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
+                               synfig::error("LayerParamConnect didn't like \"value_node\"");
+
+                       if(!get_canvas_interface()->get_instance()->perform_action(action))
+                       {
+                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
+                               group.cancel();
+                               throw String(_("Unable to create Gradient layer"));
+                               return;
+                       }
+               }
+
+               // only link the curve gradient's origin parameter if the option is selected and we're creating more than one layer
+               if (get_layer_link_origins_flag() && layers_to_create > 1)
+               {
+                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
+                       assert(action);
+
+                       action->set_param("canvas",get_canvas());
+                       action->set_param("canvas_interface",get_canvas_interface());
+                       action->set_param("layer",layer);
+                       if(!action->set_param("param",String("origin")))
+                               synfig::error("LayerParamConnect didn't like \"param\"");
+                       if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
+                               synfig::error("LayerParamConnect didn't like \"value_node\"");
+
+                       if(!get_canvas_interface()->get_instance()->perform_action(action))
+                       {
+                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
+                               group.cancel();
+                               throw String(_("Unable to create Gradient layer"));
+                               return;
+                       }
+               }
+       }
+
+       ///////////////////////////////////////////////////////////////////////////
+       //   P L A N T
+       ///////////////////////////////////////////////////////////////////////////
+
+       if(get_layer_plant_flag())
+       {
+               synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
+
+               Layer::Handle layer(get_canvas_interface()->add_layer_to("plant",canvas,depth));
+               if (!layer)
+               {
+                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
+                       group.cancel();
+                       return;
+               }
+               layer_selection.push_back(layer);
+               layer->set_description(get_id()+_(" Plant"));
+               get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
+
+               {
+                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
+                       assert(action);
+
+                       action->set_param("canvas",get_canvas());
+                       action->set_param("canvas_interface",get_canvas_interface());
+                       action->set_param("layer",layer);
+                       if(!action->set_param("param",String("bline")))
+                               synfig::error("LayerParamConnect didn't like \"param\"");
+                       if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
+                               synfig::error("LayerParamConnect didn't like \"value_node\"");
+
+                       if(!get_canvas_interface()->get_instance()->perform_action(action))
+                       {
+                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
+                               group.cancel();
+                               throw String(_("Unable to create Plant layer"));
+                               return;
+                       }
+               }
+
+               // only link the plant's origin parameter if the option is selected and we're creating more than one layer
+               if (get_layer_link_origins_flag() && layers_to_create > 1)
+               {
+                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
+                       assert(action);
+
+                       action->set_param("canvas",get_canvas());
+                       action->set_param("canvas_interface",get_canvas_interface());
+                       action->set_param("layer",layer);
+                       if(!action->set_param("param",String("origin")))
+                               synfig::error("LayerParamConnect didn't like \"param\"");
+                       if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
+                               synfig::error("LayerParamConnect didn't like \"value_node\"");
+
+                       if(!get_canvas_interface()->get_instance()->perform_action(action))
+                       {
+                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
+                               group.cancel();
+                               throw String(_("Unable to create Plant layer"));
+                               return;
+                       }
+               }
+       }
+
+       ///////////////////////////////////////////////////////////////////////////
+       //   R E G I O N
+       ///////////////////////////////////////////////////////////////////////////
+
+       if(get_layer_region_flag())
+       {
+               synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
+
+               Layer::Handle layer(get_canvas_interface()->add_layer_to("region",canvas,depth));
+               if (!layer)
+               {
+                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
+                       group.cancel();
+                       return;
+               }
+               layer_selection.push_back(layer);
+               layer->set_description(get_id()+_(" Region"));
+               get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
+
+               layer->set_param("feather",get_feather());
+               get_canvas_interface()->signal_layer_param_changed()(layer,"feather");
+
+               layer->set_param("invert",get_invert());
+               get_canvas_interface()->signal_layer_param_changed()(layer,"invert");
+
+               // I don't know if it's safe to reuse the same LayerParamConnect action, so I'm
+               // using 2 separate ones.
+               {
+                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
+                       assert(action);
+
+                       action->set_param("canvas",get_canvas());
+                       action->set_param("canvas_interface",get_canvas_interface());
+                       action->set_param("layer",layer);
+                       if(!action->set_param("param",String("bline")))
+                               synfig::error("LayerParamConnect didn't like \"param\"");
+                       if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
+                               synfig::error("LayerParamConnect didn't like \"value_node\"");
+
+                       if(!get_canvas_interface()->get_instance()->perform_action(action))
+                       {
+                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer"));
+                               group.cancel();
+                               throw String(_("Unable to create Region layer"));
+                               return;
+                       }
+               }
+
+               // only link the region's origin parameter if the option is selected and we're creating more than one layer
+               if (get_layer_link_origins_flag() && layers_to_create > 1)
+               {
+                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
+                       assert(action);
+
+                       action->set_param("canvas",get_canvas());
+                       action->set_param("canvas_interface",get_canvas_interface());
+                       action->set_param("layer",layer);
+                       if(!action->set_param("param",String("origin")))
+                               synfig::error("LayerParamConnect didn't like \"param\"");
+                       if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
+                               synfig::error("LayerParamConnect didn't like \"value_node\"");
+
+                       if(!get_canvas_interface()->get_instance()->perform_action(action))
+                       {
+                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer"));
+                               group.cancel();
+                               throw String(_("Unable to create Region layer"));
+                               return;
+                       }
+               }
+       }
+
+       ///////////////////////////////////////////////////////////////////////////
+       //   O U T L I N E
+       ///////////////////////////////////////////////////////////////////////////
+
+       if (get_layer_outline_flag())
+       {
+               Layer::Handle layer(get_canvas_interface()->add_layer_to("outline",canvas,depth));
+               if (!layer)
+               {
+                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
+                       group.cancel();
+                       return;
+               }
+               layer_selection.push_back(layer);
+               layer->set_description(get_id()+_(" Outline"));
+               get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
+
+               layer->set_param("feather",get_feather());
+               get_canvas_interface()->signal_layer_param_changed()(layer,"feather");
+
+               layer->set_param("invert",get_invert());
+               get_canvas_interface()->signal_layer_param_changed()(layer,"invert");
+
+               {
+                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
+                       assert(action);
+
+                       action->set_param("canvas",get_canvas());
+                       action->set_param("canvas_interface",get_canvas_interface());
+                       action->set_param("layer",layer);
+                       if(!action->set_param("param",String("bline")))
+                               synfig::error("LayerParamConnect didn't like \"param\"");
+                       if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
+                               synfig::error("LayerParamConnect didn't like \"value_node\"");
+
+                       if(!get_canvas_interface()->get_instance()->perform_action(action))
+                       {
+                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
+                               group.cancel();
+                               throw String(_("Unable to create Outline layer"));
+                               return;
+                       }
+               }
+
+               // only link the outline's origin parameter if the option is selected and we're creating more than one layer
+               if (get_layer_link_origins_flag() && layers_to_create > 1)
+               {
+                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
+                       assert(action);
+
+                       action->set_param("canvas",get_canvas());
+                       action->set_param("canvas_interface",get_canvas_interface());
+                       action->set_param("layer",layer);
+                       if(!action->set_param("param",String("origin")))
+                               synfig::error("LayerParamConnect didn't like \"param\"");
+                       if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
+                               synfig::error("LayerParamConnect didn't like \"value_node\"");
+
+                       if(!get_canvas_interface()->get_instance()->perform_action(action))
+                       {
+                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
+                               group.cancel();
+                               throw String(_("Unable to create Outline layer"));
+                               return;
+                       }
+               }
+       }
+
+       egress_on_selection_change=false;
+       get_canvas_interface()->get_selection_manager()->clear_selected_layers();
+       get_canvas_interface()->get_selection_manager()->set_selected_layers(layer_selection);
+       egress_on_selection_change=true;
+
+       //post clean up stuff...
+       reset();
+       increment_id();
+}
+
+Smach::event_result
+StatePolygon_Context::event_mouse_click_handler(const Smach::event& x)
+{
+       synfig::info("STATE ROTOPOLYGON: Received mouse button down Event");
+       const EventMouse& event(*reinterpret_cast<const EventMouse*>(&x));
+       switch(event.button)
+       {
+       case BUTTON_LEFT:
+               polygon_point_list.push_back(get_work_area()->snap_point_to_grid(event.pos));
+               refresh_ducks();
+               return Smach::RESULT_ACCEPT;
+
+       default:
+               return Smach::RESULT_OK;
+       }
+}
+
+
+void
+StatePolygon_Context::refresh_ducks()
+{
+       get_work_area()->clear_ducks();
+       get_work_area()->queue_draw();
+
+       if(polygon_point_list.empty()) return;
+
+       std::list<synfig::Point>::iterator iter=polygon_point_list.begin();
+
+       etl::handle<WorkArea::Duck> duck;
+       duck=new WorkArea::Duck(*iter);
+       duck->set_editable(true);
+       duck->signal_edited().connect(
+               sigc::bind(sigc::mem_fun(*this,&studio::StatePolygon_Context::on_polygon_duck_change),iter)
+       );
+       duck->signal_user_click(0).connect(sigc::mem_fun(*this,&StatePolygon_Context::run));
+
+       get_work_area()->add_duck(duck);
+
+       for(++iter;iter!=polygon_point_list.end();++iter)
+       {
+               etl::handle<WorkArea::Bezier> bezier(new WorkArea::Bezier());
+               bezier->p1=bezier->c1=duck;
+
+               duck=new WorkArea::Duck(*iter);
+               duck->set_editable(true);
+               duck->set_name(strprintf("%x",&*iter));
+               duck->signal_edited().connect(
+                       sigc::bind(sigc::mem_fun(*this,&studio::StatePolygon_Context::on_polygon_duck_change),iter)
+               );
+
+               get_work_area()->add_duck(duck);
+
+               bezier->p2=bezier->c2=duck;
+               get_work_area()->add_bezier(bezier);
+       }
+       get_work_area()->queue_draw();
+}
+
+
+bool
+StatePolygon_Context::on_polygon_duck_change(const synfig::Point &point, std::list<synfig::Point>::iterator iter)
+{
+       *iter=point;
+       return true;
+}
diff --git a/synfig-studio/src/gui/states/state_polygon.h b/synfig-studio/src/gui/states/state_polygon.h
new file mode 100644 (file)
index 0000000..c633c4e
--- /dev/null
@@ -0,0 +1,55 @@
+/* === S Y N F I G ========================================================= */
+/*!    \file state_polygon.h
+**     \brief Template Header
+**
+**     $Id$
+**
+**     \legal
+**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+**
+**     This package is free software; you can redistribute it and/or
+**     modify it under the terms of the GNU General Public License as
+**     published by the Free Software Foundation; either version 2 of
+**     the License, or (at your option) any later version.
+**
+**     This package is distributed in the hope that it will be useful,
+**     but WITHOUT ANY WARRANTY; without even the implied warranty of
+**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+**     General Public License for more details.
+**     \endlegal
+*/
+/* ========================================================================= */
+
+/* === S T A R T =========================================================== */
+
+#ifndef __SYNFIG_STUDIO_ROTOSCOPE_POLYGON_H
+#define __SYNFIG_STUDIO_ROTOSCOPE_POLYGON_H
+
+/* === H E A D E R S ======================================================= */
+
+#include "smach.h"
+
+/* === M A C R O S ========================================================= */
+
+/* === T Y P E D E F S ===================================================== */
+
+/* === C L A S S E S & S T R U C T S ======================================= */
+
+namespace studio {
+
+class StatePolygon_Context;
+
+class StatePolygon : public Smach::state<StatePolygon_Context>
+{
+public:
+       StatePolygon();
+       ~StatePolygon();
+}; // END of class StatePolygon
+
+extern StatePolygon state_polygon;
+
+}; // END of namespace studio
+
+/* === E N D =============================================================== */
+
+#endif
diff --git a/synfig-studio/src/gui/states/state_rectangle.cpp b/synfig-studio/src/gui/states/state_rectangle.cpp
new file mode 100644 (file)
index 0000000..4f3eccb
--- /dev/null
@@ -0,0 +1,875 @@
+/* === S Y N F I G ========================================================= */
+/*!    \file state_rectangle.cpp
+**     \brief Template File
+**
+**     $Id$
+**
+**     \legal
+**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+**  Copyright (c) 2008 Chris Moore
+**
+**     This package is free software; you can redistribute it and/or
+**     modify it under the terms of the GNU General Public License as
+**     published by the Free Software Foundation; either version 2 of
+**     the License, or (at your option) any later version.
+**
+**     This package is distributed in the hope that it will be useful,
+**     but WITHOUT ANY WARRANTY; without even the implied warranty of
+**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+**     General Public License for more details.
+**     \endlegal
+*/
+/* ========================================================================= */
+
+/* === H E A D E R S ======================================================= */
+
+#ifdef USING_PCH
+#      include "pch.h"
+#else
+#ifdef HAVE_CONFIG_H
+#      include <config.h>
+#endif
+
+#include <gtkmm/dialog.h>
+#include <gtkmm/entry.h>
+
+#include <synfig/valuenode_dynamiclist.h>
+#include <synfigapp/action_system.h>
+#include <synfig/valuenode_bline.h>
+
+#include "state_rectangle.h"
+#include "state_normal.h"
+#include "canvasview.h"
+#include "workarea.h"
+#include "app.h"
+
+#include <synfigapp/action.h>
+#include "event_mouse.h"
+#include "event_layerclick.h"
+#include "toolbox.h"
+#include "dialog_tooloptions.h"
+#include <gtkmm/optionmenu.h>
+#include "duck.h"
+#include <synfigapp/main.h>
+
+#include "general.h"
+
+#endif
+
+/* === U S I N G =========================================================== */
+
+using namespace std;
+using namespace etl;
+using namespace synfig;
+using namespace studio;
+
+/* === M A C R O S ========================================================= */
+
+/* === G L O B A L S ======================================================= */
+
+StateRectangle studio::state_rectangle;
+
+/* === C L A S S E S & S T R U C T S ======================================= */
+
+class studio::StateRectangle_Context : public sigc::trackable
+{
+       etl::handle<CanvasView> canvas_view_;
+       CanvasView::IsWorking is_working;
+
+       Duckmatic::Push duckmatic_push;
+
+       Point point_holder;
+
+       etl::handle<Duck> point2_duck;
+
+       void refresh_ducks();
+
+       bool prev_workarea_layer_status_;
+
+       //Toolbox settings
+       synfigapp::Settings& settings;
+
+       //Toolbox display
+       Gtk::Table options_table;
+
+       Gtk::Entry              entry_id; //what to name the layer
+
+       Gtk::Adjustment adj_expand;
+       Gtk::Adjustment adj_feather;
+       Gtk::SpinButton spin_expand;
+       Gtk::SpinButton spin_feather;
+
+       Gtk::CheckButton checkbutton_invert;
+       Gtk::CheckButton checkbutton_layer_rectangle;
+       Gtk::CheckButton checkbutton_layer_region;
+       Gtk::CheckButton checkbutton_layer_outline;
+       Gtk::CheckButton checkbutton_layer_curve_gradient;
+       Gtk::CheckButton checkbutton_layer_plant;
+       Gtk::CheckButton checkbutton_layer_link_origins;
+
+public:
+
+       // this only counts the layers which use blines - they're the only
+       // ones we link the origins for
+       int layers_to_create()const
+       {
+               return
+                       get_layer_region_flag() +
+                       get_layer_outline_flag() +
+                       get_layer_curve_gradient_flag() +
+                       get_layer_plant_flag();
+       }
+
+       synfig::String get_id()const { return entry_id.get_text(); }
+       void set_id(const synfig::String& x) { return entry_id.set_text(x); }
+
+       Real get_expand()const { return adj_expand.get_value(); }
+       void set_expand(Real f) { adj_expand.set_value(f); }
+
+       Real get_feather()const { return adj_feather.get_value(); }
+       void set_feather(Real f) { adj_feather.set_value(f); }
+
+       bool get_invert()const { return checkbutton_invert.get_active(); }
+       void set_invert(bool i) { checkbutton_invert.set_active(i); }
+
+       bool get_layer_rectangle_flag()const { return checkbutton_layer_rectangle.get_active(); }
+       void set_layer_rectangle_flag(bool x) { return checkbutton_layer_rectangle.set_active(x); }
+
+       bool get_layer_region_flag()const { return checkbutton_layer_region.get_active(); }
+       void set_layer_region_flag(bool x) { return checkbutton_layer_region.set_active(x); }
+
+       bool get_layer_outline_flag()const { return checkbutton_layer_outline.get_active(); }
+       void set_layer_outline_flag(bool x) { return checkbutton_layer_outline.set_active(x); }
+
+       bool get_layer_curve_gradient_flag()const { return checkbutton_layer_curve_gradient.get_active(); }
+       void set_layer_curve_gradient_flag(bool x) { return checkbutton_layer_curve_gradient.set_active(x); }
+
+       bool get_layer_plant_flag()const { return checkbutton_layer_plant.get_active(); }
+       void set_layer_plant_flag(bool x) { return checkbutton_layer_plant.set_active(x); }
+
+       bool get_layer_link_origins_flag()const { return checkbutton_layer_link_origins.get_active(); }
+       void set_layer_link_origins_flag(bool x) { return checkbutton_layer_link_origins.set_active(x); }
+
+       void refresh_tool_options(); //to refresh the toolbox
+
+       //events
+       Smach::event_result event_stop_handler(const Smach::event& x);
+       Smach::event_result event_refresh_handler(const Smach::event& x);
+       Smach::event_result event_mouse_click_handler(const Smach::event& x);
+       Smach::event_result event_refresh_tool_options(const Smach::event& x);
+
+       //constructor destructor
+       StateRectangle_Context(CanvasView* canvas_view);
+       ~StateRectangle_Context();
+
+       //Canvas interaction
+       const etl::handle<CanvasView>& get_canvas_view()const{return canvas_view_;}
+       etl::handle<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view_->canvas_interface();}
+       synfig::Canvas::Handle get_canvas()const{return canvas_view_->get_canvas();}
+       WorkArea * get_work_area()const{return canvas_view_->get_work_area();}
+
+       //Modifying settings etc.
+       void load_settings();
+       void save_settings();
+       void reset();
+       void increment_id();
+       bool egress_on_selection_change;
+       Smach::event_result event_layer_selection_changed_handler(const Smach::event& /*x*/)
+       {
+               if(egress_on_selection_change)
+                       throw &state_normal; //throw Smach::egress_exception();
+               return Smach::RESULT_OK;
+       }
+
+       void make_rectangle(const Point& p1, const Point& p2);
+
+};     // END of class StateGradient_Context
+
+/* === M E T H O D S ======================================================= */
+
+StateRectangle::StateRectangle():
+       Smach::state<StateRectangle_Context>("rectangle")
+{
+       insert(event_def(EVENT_STOP,&StateRectangle_Context::event_stop_handler));
+       insert(event_def(EVENT_LAYER_SELECTION_CHANGED,&StateRectangle_Context::event_layer_selection_changed_handler));
+       insert(event_def(EVENT_REFRESH,&StateRectangle_Context::event_refresh_handler));
+       insert(event_def(EVENT_REFRESH_DUCKS,&StateRectangle_Context::event_refresh_handler));
+       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateRectangle_Context::event_mouse_click_handler));
+       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DRAG,&StateRectangle_Context::event_mouse_click_handler));
+       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_UP,&StateRectangle_Context::event_mouse_click_handler));
+       insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateRectangle_Context::event_refresh_tool_options));
+}
+
+StateRectangle::~StateRectangle()
+{
+}
+
+void
+StateRectangle_Context::load_settings()
+{
+       String value;
+
+       //parse the arguments yargh!
+       if(settings.get_value("rectangle.id",value))
+               set_id(value);
+       else
+               set_id("Rectangle");
+
+       if(settings.get_value("rectangle.expand",value))
+               set_expand(atof(value.c_str()));
+       else
+               set_expand(0);
+
+       if(settings.get_value("rectangle.feather",value))
+               set_feather(atof(value.c_str()));
+       else
+               set_feather(0);
+
+       if(settings.get_value("rectangle.invert",value) && value != "0")
+               set_invert(true);
+       else
+               set_invert(false);
+
+       if(settings.get_value("rectangle.layer_rectangle",value) && value=="0")
+               set_layer_rectangle_flag(false);
+       else
+               set_layer_rectangle_flag(true);
+
+       if(settings.get_value("rectangle.layer_region",value) && value=="1")
+               set_layer_region_flag(true);
+       else
+               set_layer_region_flag(false);
+
+       if(settings.get_value("rectangle.layer_outline",value) && value=="1")
+               set_layer_outline_flag(true);
+       else
+               set_layer_outline_flag(false);
+
+       if(settings.get_value("rectangle.layer_curve_gradient",value) && value=="1")
+               set_layer_curve_gradient_flag(true);
+       else
+               set_layer_curve_gradient_flag(false);
+
+       if(settings.get_value("rectangle.layer_plant",value) && value=="1")
+               set_layer_plant_flag(true);
+       else
+               set_layer_plant_flag(false);
+
+       if(settings.get_value("rectangle.layer_link_origins",value) && value=="0")
+               set_layer_link_origins_flag(false);
+       else
+               set_layer_link_origins_flag(true);
+}
+
+void
+StateRectangle_Context::save_settings()
+{
+       settings.set_value("rectangle.id",get_id().c_str());
+       settings.set_value("rectangle.expand",strprintf("%f",get_expand()));
+       settings.set_value("rectangle.feather",strprintf("%f",(float)get_feather()));
+       settings.set_value("rectangle.invert",get_invert()?"1":"0");
+       settings.set_value("rectangle.layer_rectangle",get_layer_rectangle_flag()?"1":"0");
+       settings.set_value("rectangle.layer_outline",get_layer_outline_flag()?"1":"0");
+       settings.set_value("rectangle.layer_region",get_layer_region_flag()?"1":"0");
+       settings.set_value("rectangle.layer_curve_gradient",get_layer_curve_gradient_flag()?"1":"0");
+       settings.set_value("rectangle.layer_plant",get_layer_plant_flag()?"1":"0");
+       settings.set_value("rectangle.layer_link_origins",get_layer_link_origins_flag()?"1":"0");
+}
+
+void
+StateRectangle_Context::reset()
+{
+       refresh_ducks();
+}
+
+void
+StateRectangle_Context::increment_id()
+{
+       String id(get_id());
+       int number=1;
+       int digits=0;
+
+       if(id.empty())
+               id="Rectangle";
+
+       // If there is a number
+       // already at the end of the
+       // id, then remove it.
+       if(id[id.size()-1]<='9' && id[id.size()-1]>='0')
+       {
+               // figure out how many digits it is
+               for (digits = 0;
+                        (int)id.size()-1 >= digits && id[id.size()-1-digits] <= '9' && id[id.size()-1-digits] >= '0';
+                        digits++)
+                       ;
+
+               String str_number;
+               str_number=String(id,id.size()-digits,id.size());
+               id=String(id,0,id.size()-digits);
+
+               number=atoi(str_number.c_str());
+       }
+       else
+       {
+               number=1;
+               digits=3;
+       }
+
+       number++;
+
+       // Add the number back onto the id
+       {
+               const String format(strprintf("%%0%dd",digits));
+               id+=strprintf(format.c_str(),number);
+       }
+
+       // Set the ID
+       set_id(id);
+}
+
+StateRectangle_Context::StateRectangle_Context(CanvasView* canvas_view):
+       canvas_view_(canvas_view),
+       is_working(*canvas_view),
+       duckmatic_push(get_work_area()),
+       prev_workarea_layer_status_(get_work_area()->get_allow_layer_clicks()),
+       settings(synfigapp::Main::get_selected_input_device()->settings()),
+       entry_id(),
+       adj_expand(0,0,1,0.01,0.1),
+       adj_feather(0,0,1,0.01,0.1),
+       spin_expand(adj_expand,0.1,3),
+       spin_feather(adj_feather,0.1,3),
+       checkbutton_invert(_("Invert")),
+       checkbutton_layer_rectangle(_("Create Rectangle Layer")),
+       checkbutton_layer_region(_("Create Region BLine")),
+       checkbutton_layer_outline(_("Create Outline BLine")),
+       checkbutton_layer_curve_gradient(_("Create Curve Gradient BLine")),
+       checkbutton_layer_plant(_("Create Plant BLine")),
+       checkbutton_layer_link_origins(_("Link BLine Origins"))
+{
+       egress_on_selection_change=true;
+       load_settings();
+
+       // Set up the tool options dialog
+       options_table.attach(*manage(new Gtk::Label(_("Rectangle Tool"))),      0, 2,  0,  1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(entry_id,                                                                          0, 2,  1,  2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+
+       options_table.attach(checkbutton_layer_rectangle,                                       0, 2,  2,  3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(checkbutton_layer_outline,                                         0, 2,  3,  4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(checkbutton_layer_region,                                          0, 2,  4,  5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(checkbutton_layer_plant,                                           0, 2,  5,  6, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(checkbutton_layer_curve_gradient,                          0, 2,  6,  7, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(checkbutton_layer_link_origins,                            0, 2,  7,  8, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+
+       //invert flag
+       options_table.attach(checkbutton_invert,                                                        0, 2,  8,  9, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+
+       //expand stuff
+       options_table.attach(*manage(new Gtk::Label(_("Expansion:"))),          0, 1,  9, 10, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(spin_expand,                                                                       1, 2,  9, 10, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+
+       //feather stuff
+       options_table.attach(*manage(new Gtk::Label(_("Feather:"))),            0, 1, 10, 11, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(spin_feather,                                                                      1, 2, 10, 11, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+
+       options_table.show_all();
+
+       //App::dialog_tool_options->set_widget(options_table);
+       refresh_tool_options();
+       App::dialog_tool_options->present();
+
+       // Turn off layer clicking
+       get_work_area()->set_allow_layer_clicks(false);
+
+       // clear out the ducks
+       get_work_area()->clear_ducks();
+
+       // Refresh the work area
+       get_work_area()->queue_draw();
+
+       get_work_area()->set_cursor(Gdk::DOTBOX);
+
+       // Hide the tables if they are showing
+       //prev_table_status=get_canvas_view()->tables_are_visible();
+       //if(prev_table_status)get_canvas_view()->hide_tables();
+
+       // Disable the time bar
+       //get_canvas_view()->set_sensitive_timebar(false);
+
+       // Connect a signal
+       //get_work_area()->signal_user_click().connect(sigc::mem_fun(*this,&studio::StateRectangle_Context::on_user_click));
+
+       App::toolbox->refresh();
+}
+
+void
+StateRectangle_Context::refresh_tool_options()
+{
+       App::dialog_tool_options->clear();
+       App::dialog_tool_options->set_widget(options_table);
+       App::dialog_tool_options->set_local_name(_("Rectangle Tool"));
+       App::dialog_tool_options->set_name("rectangle");
+}
+
+Smach::event_result
+StateRectangle_Context::event_refresh_tool_options(const Smach::event& /*x*/)
+{
+       refresh_tool_options();
+       return Smach::RESULT_ACCEPT;
+}
+
+StateRectangle_Context::~StateRectangle_Context()
+{
+       save_settings();
+
+       // Restore layer clicking
+       get_work_area()->set_allow_layer_clicks(prev_workarea_layer_status_);
+
+       get_work_area()->reset_cursor();
+
+       App::dialog_tool_options->clear();
+
+       // Enable the time bar
+       //get_canvas_view()->set_sensitive_timebar(true);
+
+       // Bring back the tables if they were out before
+       //if(prev_table_status)get_canvas_view()->show_tables();
+
+       // Refresh the work area
+       get_work_area()->queue_draw();
+
+       get_canvas_view()->queue_rebuild_ducks();
+
+       App::toolbox->refresh();
+}
+
+Smach::event_result
+StateRectangle_Context::event_stop_handler(const Smach::event& /*x*/)
+{
+       //throw Smach::egress_exception();
+       throw &state_normal;
+       return Smach::RESULT_OK;
+}
+
+Smach::event_result
+StateRectangle_Context::event_refresh_handler(const Smach::event& /*x*/)
+{
+       refresh_ducks();
+       return Smach::RESULT_ACCEPT;
+}
+
+void
+StateRectangle_Context::make_rectangle(const Point& _p1, const Point& _p2)
+{
+       synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("New Rectangle"));
+       synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
+
+       Layer::Handle layer;
+
+       Canvas::Handle canvas;
+       int depth(0);
+
+       // we are temporarily using the layer to hold something
+       layer=get_canvas_view()->get_selection_manager()->get_selected_layer();
+       if(layer)
+       {
+               depth=layer->get_depth();
+               canvas=layer->get_canvas();
+       }
+
+       synfigapp::SelectionManager::LayerList layer_selection;
+       if (!getenv("SYNFIG_TOOLS_CLEAR_SELECTION"))
+               layer_selection = get_canvas_view()->get_selection_manager()->get_selected_layers();
+
+       const synfig::TransformStack& transform(get_canvas_view()->get_curr_transform_stack());
+       const Point p1(transform.unperform(_p1));
+       const Point p2(transform.unperform(_p2));
+       Real x_min, x_max, y_min, y_max;
+       if (p1[0] < p2[0]) { x_min = p1[0]; x_max = p2[0]; } else { x_min = p2[0]; x_max = p1[0]; }
+       if (p1[1] < p2[1]) { y_min = p1[1]; y_max = p2[1]; } else { y_min = p2[1]; y_max = p1[1]; }
+       x_min -= get_expand(); x_max += get_expand(); y_min -= get_expand(); y_max += get_expand();
+
+       std::vector<BLinePoint> new_list;
+       for (int i = 0; i < 4; i++)
+       {
+               new_list.push_back(*(new BLinePoint));
+               new_list[i].set_width(1);
+               new_list[i].set_vertex(Point((i==0||i==3)?x_min:x_max,
+                                                                        (i==0||i==1)?y_min:y_max));
+               new_list[i].set_tangent(Point(0,0));
+       }
+
+       ValueNode_BLine::Handle value_node_bline(ValueNode_BLine::create(new_list));
+       assert(value_node_bline);
+
+       ValueNode_Const::Handle value_node_origin(ValueNode_Const::create(Vector()));
+       assert(value_node_origin);
+
+       // Set the looping flag
+       value_node_bline->set_loop(true);
+
+       if(!canvas)
+               canvas=get_canvas_view()->get_canvas();
+
+       value_node_bline->set_member_canvas(canvas);
+
+       // count how many layers we're going to be creating
+       int layers_to_create = this->layers_to_create();
+
+       ///////////////////////////////////////////////////////////////////////////
+       //   R E C T A N G L E
+       ///////////////////////////////////////////////////////////////////////////
+
+       if (get_layer_rectangle_flag())
+       {
+               layer=get_canvas_interface()->add_layer_to("rectangle",canvas,depth);
+               if (!layer)
+               {
+                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
+                       group.cancel();
+                       return;
+               }
+               layer_selection.push_back(layer);
+
+               layer->set_param("point1",p1);
+               get_canvas_interface()->signal_layer_param_changed()(layer,"point1");
+
+               layer->set_param("point2",p2);
+               get_canvas_interface()->signal_layer_param_changed()(layer,"point2");
+
+               layer->set_param("expand",get_expand());
+               get_canvas_interface()->signal_layer_param_changed()(layer,"expand");
+
+               layer->set_param("invert",get_invert());
+               get_canvas_interface()->signal_layer_param_changed()(layer,"invert");
+
+               layer->set_description(get_id());
+               get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
+       }
+
+       ///////////////////////////////////////////////////////////////////////////
+       //   C U R V E   G R A D I E N T
+       ///////////////////////////////////////////////////////////////////////////
+
+       if(get_layer_curve_gradient_flag())
+       {
+               synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
+
+               Layer::Handle layer(get_canvas_interface()->add_layer_to("curve_gradient",canvas,depth));
+               if (!layer)
+               {
+                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
+                       group.cancel();
+                       return;
+               }
+               layer_selection.push_back(layer);
+               layer->set_description(get_id()+_(" Gradient"));
+               get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
+
+               {
+                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
+                       assert(action);
+
+                       action->set_param("canvas",get_canvas());
+                       action->set_param("canvas_interface",get_canvas_interface());
+                       action->set_param("layer",layer);
+                       if(!action->set_param("param",String("bline")))
+                               synfig::error("LayerParamConnect didn't like \"param\"");
+                       if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
+                               synfig::error("LayerParamConnect didn't like \"value_node\"");
+
+                       if(!get_canvas_interface()->get_instance()->perform_action(action))
+                       {
+                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
+                               group.cancel();
+                               throw String(_("Unable to create Gradient layer"));
+                               return;
+                       }
+               }
+
+               // only link the curve gradient's origin parameter if the option is selected and we're creating more than one layer
+               if (get_layer_link_origins_flag() && layers_to_create > 1)
+               {
+                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
+                       assert(action);
+
+                       action->set_param("canvas",get_canvas());
+                       action->set_param("canvas_interface",get_canvas_interface());
+                       action->set_param("layer",layer);
+                       if(!action->set_param("param",String("origin")))
+                               synfig::error("LayerParamConnect didn't like \"param\"");
+                       if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
+                               synfig::error("LayerParamConnect didn't like \"value_node\"");
+
+                       if(!get_canvas_interface()->get_instance()->perform_action(action))
+                       {
+                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
+                               group.cancel();
+                               throw String(_("Unable to create Gradient layer"));
+                               return;
+                       }
+               }
+       }
+
+       ///////////////////////////////////////////////////////////////////////////
+       //   P L A N T
+       ///////////////////////////////////////////////////////////////////////////
+
+       if(get_layer_plant_flag())
+       {
+               synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
+
+               Layer::Handle layer(get_canvas_interface()->add_layer_to("plant",canvas,depth));
+               if (!layer)
+               {
+                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
+                       group.cancel();
+                       return;
+               }
+               layer_selection.push_back(layer);
+               layer->set_description(get_id()+_(" Plant"));
+               get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
+
+               {
+                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
+                       assert(action);
+
+                       action->set_param("canvas",get_canvas());
+                       action->set_param("canvas_interface",get_canvas_interface());
+                       action->set_param("layer",layer);
+                       if(!action->set_param("param",String("bline")))
+                               synfig::error("LayerParamConnect didn't like \"param\"");
+                       if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
+                               synfig::error("LayerParamConnect didn't like \"value_node\"");
+
+                       if(!get_canvas_interface()->get_instance()->perform_action(action))
+                       {
+                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
+                               group.cancel();
+                               throw String(_("Unable to create Plant layer"));
+                               return;
+                       }
+               }
+
+               // only link the plant's origin parameter if the option is selected and we're creating more than one layer
+               if (get_layer_link_origins_flag() && layers_to_create > 1)
+               {
+                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
+                       assert(action);
+
+                       action->set_param("canvas",get_canvas());
+                       action->set_param("canvas_interface",get_canvas_interface());
+                       action->set_param("layer",layer);
+                       if(!action->set_param("param",String("origin")))
+                               synfig::error("LayerParamConnect didn't like \"param\"");
+                       if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
+                               synfig::error("LayerParamConnect didn't like \"value_node\"");
+
+                       if(!get_canvas_interface()->get_instance()->perform_action(action))
+                       {
+                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
+                               group.cancel();
+                               throw String(_("Unable to create Plant layer"));
+                               return;
+                       }
+               }
+       }
+
+       ///////////////////////////////////////////////////////////////////////////
+       //   R E G I O N
+       ///////////////////////////////////////////////////////////////////////////
+
+       if(get_layer_region_flag())
+       {
+               synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
+
+               Layer::Handle layer(get_canvas_interface()->add_layer_to("region",canvas,depth));
+               if (!layer)
+               {
+                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
+                       group.cancel();
+                       return;
+               }
+               layer_selection.push_back(layer);
+               layer->set_description(get_id()+_(" Region"));
+               get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
+
+               layer->set_param("feather",get_feather());
+               get_canvas_interface()->signal_layer_param_changed()(layer,"feather");
+
+               layer->set_param("invert",get_invert());
+               get_canvas_interface()->signal_layer_param_changed()(layer,"invert");
+
+               // I don't know if it's safe to reuse the same LayerParamConnect action, so I'm
+               // using 2 separate ones.
+               {
+                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
+                       assert(action);
+
+                       action->set_param("canvas",get_canvas());
+                       action->set_param("canvas_interface",get_canvas_interface());
+                       action->set_param("layer",layer);
+                       if(!action->set_param("param",String("bline")))
+                               synfig::error("LayerParamConnect didn't like \"param\"");
+                       if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
+                               synfig::error("LayerParamConnect didn't like \"value_node\"");
+
+                       if(!get_canvas_interface()->get_instance()->perform_action(action))
+                       {
+                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer"));
+                               group.cancel();
+                               throw String(_("Unable to create Region layer"));
+                               return;
+                       }
+               }
+
+               // only link the region's origin parameter if the option is selected and we're creating more than one layer
+               if (get_layer_link_origins_flag() && layers_to_create > 1)
+               {
+                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
+                       assert(action);
+
+                       action->set_param("canvas",get_canvas());
+                       action->set_param("canvas_interface",get_canvas_interface());
+                       action->set_param("layer",layer);
+                       if(!action->set_param("param",String("origin")))
+                               synfig::error("LayerParamConnect didn't like \"param\"");
+                       if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
+                               synfig::error("LayerParamConnect didn't like \"value_node\"");
+
+                       if(!get_canvas_interface()->get_instance()->perform_action(action))
+                       {
+                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer"));
+                               group.cancel();
+                               throw String(_("Unable to create Region layer"));
+                               return;
+                       }
+               }
+       }
+
+       ///////////////////////////////////////////////////////////////////////////
+       //   O U T L I N E
+       ///////////////////////////////////////////////////////////////////////////
+
+       if (get_layer_outline_flag())
+       {
+               Layer::Handle layer(get_canvas_interface()->add_layer_to("outline",canvas,depth));
+               if (!layer)
+               {
+                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
+                       group.cancel();
+                       return;
+               }
+               layer_selection.push_back(layer);
+               layer->set_description(get_id()+_(" Outline"));
+               get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
+
+               layer->set_param("feather",get_feather());
+               get_canvas_interface()->signal_layer_param_changed()(layer,"feather");
+
+               layer->set_param("invert",get_invert());
+               get_canvas_interface()->signal_layer_param_changed()(layer,"invert");
+
+               {
+                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
+                       assert(action);
+
+                       action->set_param("canvas",get_canvas());
+                       action->set_param("canvas_interface",get_canvas_interface());
+                       action->set_param("layer",layer);
+                       if(!action->set_param("param",String("bline")))
+                               synfig::error("LayerParamConnect didn't like \"param\"");
+                       if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
+                               synfig::error("LayerParamConnect didn't like \"value_node\"");
+
+                       if(!get_canvas_interface()->get_instance()->perform_action(action))
+                       {
+                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
+                               group.cancel();
+                               throw String(_("Unable to create Outline layer"));
+                               return;
+                       }
+               }
+
+               // only link the outline's origin parameter if the option is selected and we're creating more than one layer
+               if (get_layer_link_origins_flag() && layers_to_create > 1)
+               {
+                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
+                       assert(action);
+
+                       action->set_param("canvas",get_canvas());
+                       action->set_param("canvas_interface",get_canvas_interface());
+                       action->set_param("layer",layer);
+                       if(!action->set_param("param",String("origin")))
+                               synfig::error("LayerParamConnect didn't like \"param\"");
+                       if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
+                               synfig::error("LayerParamConnect didn't like \"value_node\"");
+
+                       if(!get_canvas_interface()->get_instance()->perform_action(action))
+                       {
+                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
+                               group.cancel();
+                               throw String(_("Unable to create Outline layer"));
+                               return;
+                       }
+               }
+       }
+
+       egress_on_selection_change=false;
+       get_canvas_interface()->get_selection_manager()->clear_selected_layers();
+       get_canvas_interface()->get_selection_manager()->set_selected_layers(layer_selection);
+       egress_on_selection_change=true;
+
+       //post clean up stuff...
+       reset();
+       increment_id();
+}
+
+Smach::event_result
+StateRectangle_Context::event_mouse_click_handler(const Smach::event& x)
+{
+       const EventMouse& event(*reinterpret_cast<const EventMouse*>(&x));
+
+       if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_DOWN && event.button==BUTTON_LEFT)
+       {
+               point_holder=get_work_area()->snap_point_to_grid(event.pos);
+               etl::handle<Duck> duck=new Duck();
+               duck->set_point(point_holder);
+               duck->set_name("p1");
+               duck->set_type(Duck::TYPE_POSITION);
+               get_work_area()->add_duck(duck);
+
+               point2_duck=new Duck();
+               point2_duck->set_point(point_holder);
+               point2_duck->set_name("p2");
+               point2_duck->set_type(Duck::TYPE_POSITION);
+               point2_duck->set_box_duck(duck);
+               get_work_area()->add_duck(point2_duck);
+
+               return Smach::RESULT_ACCEPT;
+       }
+
+       if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_DRAG && event.button==BUTTON_LEFT)
+       {
+               if (!point2_duck) return Smach::RESULT_OK;
+               point2_duck->set_point(get_work_area()->snap_point_to_grid(event.pos));
+               get_work_area()->queue_draw();
+               return Smach::RESULT_ACCEPT;
+       }
+
+       if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_UP && event.button==BUTTON_LEFT)
+       {
+               make_rectangle(point_holder, get_work_area()->snap_point_to_grid(event.pos));
+               get_work_area()->clear_ducks();
+               return Smach::RESULT_ACCEPT;
+       }
+
+       return Smach::RESULT_OK;
+}
+
+
+void
+StateRectangle_Context::refresh_ducks()
+{
+       get_work_area()->clear_ducks();
+       get_work_area()->queue_draw();
+}
diff --git a/synfig-studio/src/gui/states/state_rectangle.h b/synfig-studio/src/gui/states/state_rectangle.h
new file mode 100644 (file)
index 0000000..131dd40
--- /dev/null
@@ -0,0 +1,56 @@
+/* === S Y N F I G ========================================================= */
+/*!    \file state_rectangle.h
+**     \brief Rectangle creation state
+**
+**     $Id$
+**
+**     \legal
+**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+**
+**     This package is free software; you can redistribute it and/or
+**     modify it under the terms of the GNU General Public License as
+**     published by the Free Software Foundation; either version 2 of
+**     the License, or (at your option) any later version.
+**
+**     This package is distributed in the hope that it will be useful,
+**     but WITHOUT ANY WARRANTY; without even the implied warranty of
+**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+**     General Public License for more details.
+**     \endlegal
+*/
+/* ========================================================================= */
+
+/* === S T A R T =========================================================== */
+
+#ifndef __SYNFIG_STUDIO_STATE_RECTANGLE_H
+#define __SYNFIG_STUDIO_STATE_RECTANGLE_H
+
+/* === H E A D E R S ======================================================= */
+
+#include "smach.h"
+
+
+/* === M A C R O S ========================================================= */
+
+/* === T Y P E D E F S ===================================================== */
+
+/* === C L A S S E S & S T R U C T S ======================================= */
+
+namespace studio {
+
+class StateRectangle_Context;
+
+class StateRectangle : public Smach::state<StateRectangle_Context>
+{
+public:
+       StateRectangle();
+       ~StateRectangle();
+}; // END of class StateRectangle
+
+extern StateRectangle state_rectangle;
+
+}; // END of namespace studio
+
+/* === E N D =============================================================== */
+
+#endif
diff --git a/synfig-studio/src/gui/states/state_rotate.cpp b/synfig-studio/src/gui/states/state_rotate.cpp
new file mode 100644 (file)
index 0000000..5463a41
--- /dev/null
@@ -0,0 +1,398 @@
+/* === S Y N F I G ========================================================= */
+/*!    \file state_rotate.cpp
+**     \brief Template File
+**
+**     $Id$
+**
+**     \legal
+**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+**  Copyright (c) 2008 Chris Moore
+**
+**     This package is free software; you can redistribute it and/or
+**     modify it under the terms of the GNU General Public License as
+**     published by the Free Software Foundation; either version 2 of
+**     the License, or (at your option) any later version.
+**
+**     This package is distributed in the hope that it will be useful,
+**     but WITHOUT ANY WARRANTY; without even the implied warranty of
+**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+**     General Public License for more details.
+**     \endlegal
+*/
+/* ========================================================================= */
+
+/* === H E A D E R S ======================================================= */
+
+#ifdef USING_PCH
+#      include "pch.h"
+#else
+#ifdef HAVE_CONFIG_H
+#      include <config.h>
+#endif
+
+#include <gtkmm/dialog.h>
+#include <gtkmm/entry.h>
+
+#include <synfig/valuenode_dynamiclist.h>
+#include <synfigapp/action_system.h>
+
+#include "state_rotate.h"
+#include "state_normal.h"
+#include "canvasview.h"
+#include "workarea.h"
+#include "app.h"
+
+#include <synfigapp/action.h>
+#include "event_mouse.h"
+#include "event_layerclick.h"
+#include "toolbox.h"
+#include "dialog_tooloptions.h"
+#include <gtkmm/optionmenu.h>
+#include "duck.h"
+#include <synfig/angle.h>
+#include <synfigapp/main.h>
+
+#include "general.h"
+
+#endif
+
+/* === U S I N G =========================================================== */
+
+using namespace std;
+using namespace etl;
+using namespace synfig;
+using namespace studio;
+
+/* === M A C R O S ========================================================= */
+
+#ifndef EPSILON
+#define EPSILON        0.0000001
+#endif
+
+/* === G L O B A L S ======================================================= */
+
+StateRotate studio::state_rotate;
+
+/* === C L A S S E S & S T R U C T S ======================================= */
+
+class DuckDrag_Rotate : public DuckDrag_Base
+{
+
+       synfig::Vector last_rotate;
+       synfig::Vector drag_offset;
+       synfig::Vector center;
+       synfig::Vector snap;
+
+       Angle original_angle;
+       Real original_mag;
+
+       std::vector<synfig::Vector> positions;
+
+
+       bool bad_drag;
+       bool move_only;
+
+public:
+       etl::handle<CanvasView> canvas_view_;
+       bool use_magnitude;
+       DuckDrag_Rotate();
+       void begin_duck_drag(Duckmatic* duckmatic, const synfig::Vector& begin);
+       bool end_duck_drag(Duckmatic* duckmatic);
+       void duck_drag(Duckmatic* duckmatic, const synfig::Vector& vector);
+
+       etl::handle<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view_->canvas_interface();}
+};
+
+
+class studio::StateRotate_Context : public sigc::trackable
+{
+       etl::handle<CanvasView> canvas_view_;
+       CanvasView::IsWorking is_working;
+
+       synfigapp::Settings& settings;
+
+       etl::handle<DuckDrag_Rotate> duck_dragger_;
+
+       Gtk::Table options_table;
+
+       Gtk::CheckButton checkbutton_scale;
+
+public:
+
+       bool get_scale_flag()const { return checkbutton_scale.get_active(); }
+       void set_scale_flag(bool x) { return checkbutton_scale.set_active(x); refresh_scale_flag(); }
+
+       Smach::event_result event_stop_handler(const Smach::event& x);
+       Smach::event_result event_refresh_tool_options(const Smach::event& x);
+
+       void refresh_tool_options();
+
+       void refresh_scale_flag() { if(duck_dragger_)duck_dragger_->use_magnitude=get_scale_flag(); }
+
+       StateRotate_Context(CanvasView* canvas_view);
+
+       ~StateRotate_Context();
+
+       const etl::handle<CanvasView>& get_canvas_view()const{return canvas_view_;}
+       etl::handle<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view_->canvas_interface();}
+       synfig::Canvas::Handle get_canvas()const{return canvas_view_->get_canvas();}
+       WorkArea * get_work_area()const{return canvas_view_->get_work_area();}
+
+       void load_settings();
+       void save_settings();
+};     // END of class StateRotate_Context
+
+/* === M E T H O D S ======================================================= */
+
+StateRotate::StateRotate():
+       Smach::state<StateRotate_Context>("rotate")
+{
+       insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateRotate_Context::event_refresh_tool_options));
+       insert(event_def(EVENT_STOP,&StateRotate_Context::event_stop_handler));
+}
+
+StateRotate::~StateRotate()
+{
+}
+
+void
+StateRotate_Context::load_settings()
+{
+       String value;
+
+       if(settings.get_value("rotate.scale",value) && value=="0")
+               set_scale_flag(false);
+       else
+               set_scale_flag(true);
+}
+
+void
+StateRotate_Context::save_settings()
+{
+       settings.set_value("rotate.scale",get_scale_flag()?"1":"0");
+}
+
+StateRotate_Context::StateRotate_Context(CanvasView* canvas_view):
+       canvas_view_(canvas_view),
+       is_working(*canvas_view),
+       settings(synfigapp::Main::get_selected_input_device()->settings()),
+       duck_dragger_(new DuckDrag_Rotate()),
+       checkbutton_scale(_("Allow Scale"))
+{
+       duck_dragger_->canvas_view_=get_canvas_view();
+
+       // Set up the tool options dialog
+       options_table.attach(*manage(new Gtk::Label(_("Rotate Tool"))), 0, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(checkbutton_scale,                                                 0, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+
+       checkbutton_scale.signal_toggled().connect(sigc::mem_fun(*this,&StateRotate_Context::refresh_scale_flag));
+
+       options_table.show_all();
+       refresh_tool_options();
+       //App::dialog_tool_options->set_widget(options_table);
+       App::dialog_tool_options->present();
+
+       get_work_area()->set_allow_layer_clicks(true);
+       get_work_area()->set_duck_dragger(duck_dragger_);
+
+       get_work_area()->set_cursor(Gdk::EXCHANGE);
+//     get_work_area()->reset_cursor();
+
+       App::toolbox->refresh();
+
+       load_settings();
+       refresh_scale_flag();
+}
+
+void
+StateRotate_Context::refresh_tool_options()
+{
+       App::dialog_tool_options->clear();
+       App::dialog_tool_options->set_widget(options_table);
+       App::dialog_tool_options->set_local_name(_("Rotate Tool"));
+       App::dialog_tool_options->set_name("rotate");
+}
+
+Smach::event_result
+StateRotate_Context::event_refresh_tool_options(const Smach::event& /*x*/)
+{
+       refresh_tool_options();
+       return Smach::RESULT_ACCEPT;
+}
+
+Smach::event_result
+StateRotate_Context::event_stop_handler(const Smach::event& /*x*/)
+{
+       throw &state_normal;
+       return Smach::RESULT_OK;
+}
+
+StateRotate_Context::~StateRotate_Context()
+{
+       save_settings();
+
+       get_work_area()->clear_duck_dragger();
+       get_work_area()->reset_cursor();
+
+       App::dialog_tool_options->clear();
+
+       App::toolbox->refresh();
+}
+
+
+
+
+DuckDrag_Rotate::DuckDrag_Rotate()
+{
+       use_magnitude=true;
+}
+
+void
+DuckDrag_Rotate::begin_duck_drag(Duckmatic* duckmatic, const synfig::Vector& offset)
+{
+       last_rotate=Vector(1,1);
+
+       const DuckList selected_ducks(duckmatic->get_selected_ducks());
+       DuckList::const_iterator iter;
+
+/*
+       if(duckmatic->get_selected_ducks().size()<2)
+       {
+               bad_drag=true;
+               return;
+       }
+*/
+       bad_drag=false;
+
+               drag_offset=duckmatic->find_duck(offset)->get_trans_point();
+
+               //snap=drag_offset-duckmatic->snap_point_to_grid(drag_offset);
+               //snap=offset-drag_offset;
+               snap=Vector(0,0);
+
+       // Calculate center
+       Point vmin(100000000,100000000);
+       Point vmax(-100000000,-100000000);
+       //std::set<etl::handle<Duck> >::iterator iter;
+       positions.clear();
+       int i;
+       for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
+       {
+               Point p((*iter)->get_trans_point());
+               vmin[0]=min(vmin[0],p[0]);
+               vmin[1]=min(vmin[1],p[1]);
+               vmax[0]=max(vmax[0],p[0]);
+               vmax[1]=max(vmax[1],p[1]);
+               positions.push_back(p);
+       }
+       center=(vmin+vmax)*0.5;
+       if((vmin-vmax).mag()<=EPSILON)
+               move_only=true;
+       else
+               move_only=false;
+
+
+       synfig::Vector vect(offset-center);
+       original_angle=Angle::tan(vect[1],vect[0]);
+       original_mag=vect.mag();
+}
+
+
+void
+DuckDrag_Rotate::duck_drag(Duckmatic* duckmatic, const synfig::Vector& vector)
+{
+       if(bad_drag)
+               return;
+
+       //std::set<etl::handle<Duck> >::iterator iter;
+       synfig::Vector vect(duckmatic->snap_point_to_grid(vector)-center+snap);
+
+       const DuckList selected_ducks(duckmatic->get_selected_ducks());
+       DuckList::const_iterator iter;
+
+       if(move_only)
+       {
+               int i;
+               for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
+               {
+                       if((*iter)->get_type()!=Duck::TYPE_VERTEX&&(*iter)->get_type()!=Duck::TYPE_POSITION)continue;
+
+                       Vector p(positions[i]);
+
+                       p[0]+=vect[0];
+                       p[1]+=vect[1];
+                       (*iter)->set_trans_point(p);
+               }
+               for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
+               {
+                       if(!((*iter)->get_type()!=Duck::TYPE_VERTEX&&(*iter)->get_type()!=Duck::TYPE_POSITION))continue;
+
+                       Vector p(positions[i]);
+
+                       p[0]+=vect[0];
+                       p[1]+=vect[1];
+                       (*iter)->set_trans_point(p);
+               }
+               return;
+       }
+
+       Angle::tan angle(vect[1],vect[0]);
+       angle=original_angle-angle;
+       Real mag(vect.mag()/original_mag);
+       Real sine(Angle::sin(angle).get());
+       Real cosine(Angle::cos(angle).get());
+
+       int i;
+       for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
+       {
+               if((*iter)->get_type()!=Duck::TYPE_VERTEX&&(*iter)->get_type()!=Duck::TYPE_POSITION)continue;
+
+               Vector x(positions[i]-center),p;
+
+               p[0]=cosine*x[0]+sine*x[1];
+               p[1]=-sine*x[0]+cosine*x[1];
+               if(use_magnitude)p*=mag;
+               p+=center;
+               (*iter)->set_trans_point(p);
+       }
+       for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
+       {
+               if(!((*iter)->get_type()!=Duck::TYPE_VERTEX&&(*iter)->get_type()!=Duck::TYPE_POSITION))continue;
+
+               Vector x(positions[i]-center),p;
+
+               p[0]=cosine*x[0]+sine*x[1];
+               p[1]=-sine*x[0]+cosine*x[1];
+               if(use_magnitude)p*=mag;
+               p+=center;
+               (*iter)->set_trans_point(p);
+       }
+
+       last_rotate=vect;
+       //snap=Vector(0,0);
+}
+
+bool
+DuckDrag_Rotate::end_duck_drag(Duckmatic* duckmatic)
+{
+       if(bad_drag)return false;
+       if(move_only)
+       {
+               synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Move Duck"));
+               duckmatic->signal_edited_selected_ducks();
+               return true;
+       }
+
+       synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Rotate Ducks"));
+
+       if((last_rotate-Vector(1,1)).mag()>0.0001)
+       {
+               duckmatic->signal_edited_selected_ducks();
+               return true;
+       }
+       else
+       {
+               duckmatic->signal_user_click_selected_ducks(0);
+               return false;
+       }
+}
diff --git a/synfig-studio/src/gui/states/state_rotate.h b/synfig-studio/src/gui/states/state_rotate.h
new file mode 100644 (file)
index 0000000..e2caafe
--- /dev/null
@@ -0,0 +1,56 @@
+/* === S Y N F I G ========================================================= */
+/*!    \file state_rotate.h
+**     \brief Template Header
+**
+**     $Id$
+**
+**     \legal
+**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+**
+**     This package is free software; you can redistribute it and/or
+**     modify it under the terms of the GNU General Public License as
+**     published by the Free Software Foundation; either version 2 of
+**     the License, or (at your option) any later version.
+**
+**     This package is distributed in the hope that it will be useful,
+**     but WITHOUT ANY WARRANTY; without even the implied warranty of
+**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+**     General Public License for more details.
+**     \endlegal
+*/
+/* ========================================================================= */
+
+/* === S T A R T =========================================================== */
+
+#ifndef __SYNFIG_STUDIO_STATE_ROTATE_H
+#define __SYNFIG_STUDIO_STATE_ROTATE_H
+
+/* === H E A D E R S ======================================================= */
+
+#include "smach.h"
+
+
+/* === M A C R O S ========================================================= */
+
+/* === T Y P E D E F S ===================================================== */
+
+/* === C L A S S E S & S T R U C T S ======================================= */
+
+namespace studio {
+
+class StateRotate_Context;
+
+class StateRotate : public Smach::state<StateRotate_Context>
+{
+public:
+       StateRotate();
+       ~StateRotate();
+}; // END of class StateRotate
+
+extern StateRotate state_rotate;
+
+}; // END of namespace studio
+
+/* === E N D =============================================================== */
+
+#endif
diff --git a/synfig-studio/src/gui/states/state_scale.cpp b/synfig-studio/src/gui/states/state_scale.cpp
new file mode 100644 (file)
index 0000000..edfb89b
--- /dev/null
@@ -0,0 +1,389 @@
+/* === S Y N F I G ========================================================= */
+/*!    \file state_scale.cpp
+**     \brief Template File
+**
+**     $Id$
+**
+**     \legal
+**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+**  Copyright (c) 2008 Chris Moore
+**
+**     This package is free software; you can redistribute it and/or
+**     modify it under the terms of the GNU General Public License as
+**     published by the Free Software Foundation; either version 2 of
+**     the License, or (at your option) any later version.
+**
+**     This package is distributed in the hope that it will be useful,
+**     but WITHOUT ANY WARRANTY; without even the implied warranty of
+**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+**     General Public License for more details.
+**     \endlegal
+*/
+/* ========================================================================= */
+
+/* === H E A D E R S ======================================================= */
+
+#ifdef USING_PCH
+#      include "pch.h"
+#else
+#ifdef HAVE_CONFIG_H
+#      include <config.h>
+#endif
+
+#include <gtkmm/dialog.h>
+#include <gtkmm/entry.h>
+
+#include <synfig/valuenode_dynamiclist.h>
+#include <synfigapp/action_system.h>
+
+#include "state_scale.h"
+#include "state_normal.h"
+#include "canvasview.h"
+#include "workarea.h"
+#include "app.h"
+
+#include <synfigapp/action.h>
+#include "event_mouse.h"
+#include "event_layerclick.h"
+#include "toolbox.h"
+#include "dialog_tooloptions.h"
+#include <gtkmm/optionmenu.h>
+#include "duck.h"
+#include <synfigapp/main.h>
+
+#include "general.h"
+
+#endif
+
+/* === U S I N G =========================================================== */
+
+using namespace std;
+using namespace etl;
+using namespace synfig;
+using namespace studio;
+
+/* === M A C R O S ========================================================= */
+
+/* === G L O B A L S ======================================================= */
+
+StateScale studio::state_scale;
+
+/* === C L A S S E S & S T R U C T S ======================================= */
+
+class DuckDrag_Scale : public DuckDrag_Base
+{
+
+       synfig::Vector last_scale;
+       synfig::Vector drag_offset;
+       synfig::Vector center;
+       synfig::Vector snap;
+
+       std::vector<synfig::Vector> positions;
+
+       bool move_only;
+
+       bool bad_drag;
+public:
+       bool lock_aspect;
+       DuckDrag_Scale();
+       void begin_duck_drag(Duckmatic* duckmatic, const synfig::Vector& begin);
+       bool end_duck_drag(Duckmatic* duckmatic);
+       void duck_drag(Duckmatic* duckmatic, const synfig::Vector& vector);
+};
+
+
+class studio::StateScale_Context : public sigc::trackable
+{
+       etl::handle<CanvasView> canvas_view_;
+       CanvasView::IsWorking is_working;
+
+       synfigapp::Settings& settings;
+
+       etl::handle<DuckDrag_Scale> duck_dragger_;
+
+       Gtk::Table options_table;
+
+
+       Gtk::CheckButton checkbutton_aspect_lock;
+
+public:
+
+       bool get_aspect_lock_flag()const { return checkbutton_aspect_lock.get_active(); }
+       void set_aspect_lock_flag(bool x) { return checkbutton_aspect_lock.set_active(x); refresh_aspect_lock_flag(); }
+
+       void refresh_aspect_lock_flag() { if(duck_dragger_)duck_dragger_->lock_aspect=get_aspect_lock_flag(); }
+
+       Smach::event_result event_stop_handler(const Smach::event& x);
+       Smach::event_result event_refresh_tool_options(const Smach::event& x);
+
+       void refresh_tool_options();
+
+       StateScale_Context(CanvasView* canvas_view);
+
+       ~StateScale_Context();
+
+       const etl::handle<CanvasView>& get_canvas_view()const{return canvas_view_;}
+       etl::handle<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view_->canvas_interface();}
+       synfig::Canvas::Handle get_canvas()const{return canvas_view_->get_canvas();}
+       WorkArea * get_work_area()const{return canvas_view_->get_work_area();}
+
+       void load_settings();
+       void save_settings();
+};     // END of class StateScale_Context
+
+/* === M E T H O D S ======================================================= */
+
+StateScale::StateScale():
+       Smach::state<StateScale_Context>("scale")
+{
+       insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateScale_Context::event_refresh_tool_options));
+       insert(event_def(EVENT_STOP,&StateScale_Context::event_stop_handler));
+}
+
+StateScale::~StateScale()
+{
+}
+
+void
+StateScale_Context::load_settings()
+{
+       String value;
+
+       if(settings.get_value("scale.lock_aspect",value) && value=="0")
+               set_aspect_lock_flag(false);
+       else
+               set_aspect_lock_flag(true);
+}
+
+void
+StateScale_Context::save_settings()
+{
+       settings.set_value("scale.lock_aspect",get_aspect_lock_flag()?"1":"0");
+}
+
+StateScale_Context::StateScale_Context(CanvasView* canvas_view):
+       canvas_view_(canvas_view),
+       is_working(*canvas_view),
+       settings(synfigapp::Main::get_selected_input_device()->settings()),
+       duck_dragger_(new DuckDrag_Scale()),
+       checkbutton_aspect_lock(_("Lock Aspect Ratio"))
+{
+       // Set up the tool options dialog
+       options_table.attach(*manage(new Gtk::Label(_("Scale Tool"))),  0, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(checkbutton_aspect_lock,                                   0, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+
+       checkbutton_aspect_lock.signal_toggled().connect(sigc::mem_fun(*this,&StateScale_Context::refresh_aspect_lock_flag));
+
+       options_table.show_all();
+       refresh_tool_options();
+       App::dialog_tool_options->present();
+
+       get_work_area()->set_allow_layer_clicks(true);
+       get_work_area()->set_duck_dragger(duck_dragger_);
+
+       get_work_area()->set_cursor(Gdk::SIZING);
+//     get_work_area()->reset_cursor();
+
+       App::toolbox->refresh();
+
+       set_aspect_lock_flag(true);
+       load_settings();
+}
+
+void
+StateScale_Context::refresh_tool_options()
+{
+       App::dialog_tool_options->clear();
+       App::dialog_tool_options->set_widget(options_table);
+       App::dialog_tool_options->set_local_name(_("Scale Tool"));
+       App::dialog_tool_options->set_name("scale");
+}
+
+Smach::event_result
+StateScale_Context::event_refresh_tool_options(const Smach::event& /*x*/)
+{
+       refresh_tool_options();
+       return Smach::RESULT_ACCEPT;
+}
+
+Smach::event_result
+StateScale_Context::event_stop_handler(const Smach::event& /*x*/)
+{
+       throw &state_normal;
+       return Smach::RESULT_OK;
+}
+
+StateScale_Context::~StateScale_Context()
+{
+       save_settings();
+
+       get_work_area()->clear_duck_dragger();
+       get_work_area()->reset_cursor();
+
+       App::dialog_tool_options->clear();
+
+       App::toolbox->refresh();
+}
+
+
+
+
+DuckDrag_Scale::DuckDrag_Scale():
+       lock_aspect(true)
+{
+}
+
+#ifndef EPSILON
+#define EPSILON        0.0000001
+#endif
+
+void
+DuckDrag_Scale::begin_duck_drag(Duckmatic* duckmatic, const synfig::Vector& offset)
+{
+       last_scale=Vector(1,1);
+       const DuckList selected_ducks(duckmatic->get_selected_ducks());
+       DuckList::const_iterator iter;
+
+       //if(duckmatic->get_selected_ducks().size()<2)
+       //{
+       //      bad_drag=true;
+//             return;
+//     }
+       bad_drag=false;
+
+               drag_offset=duckmatic->find_duck(offset)->get_trans_point();
+
+               //snap=drag_offset-duckmatic->snap_point_to_grid(drag_offset);
+               //snap=offset-drag_offset;
+               snap=Vector(0,0);
+
+       // Calculate center
+       Point vmin(100000000,100000000);
+       Point vmax(-100000000,-100000000);
+       //std::set<etl::handle<Duck> >::iterator iter;
+       positions.clear();
+       int i;
+       for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
+       {
+               Point p((*iter)->get_trans_point());
+               vmin[0]=min(vmin[0],p[0]);
+               vmin[1]=min(vmin[1],p[1]);
+               vmax[0]=max(vmax[0],p[0]);
+               vmax[1]=max(vmax[1],p[1]);
+               positions.push_back(p);
+       }
+       if((vmin-vmax).mag()<=EPSILON)
+               move_only=true;
+       else
+               move_only=false;
+
+       center=(vmin+vmax)*0.5;
+}
+
+
+void
+DuckDrag_Scale::duck_drag(Duckmatic* duckmatic, const synfig::Vector& vector)
+{
+       const DuckList selected_ducks(duckmatic->get_selected_ducks());
+       DuckList::const_iterator iter;
+
+       if(bad_drag)
+               return;
+
+       //std::set<etl::handle<Duck> >::iterator iter;
+       synfig::Vector vect(duckmatic->snap_point_to_grid(vector)-center);
+       last_scale=vect;
+
+       if(move_only)
+       {
+               int i;
+               for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
+               {
+                       if(((*iter)->get_type()!=Duck::TYPE_VERTEX&&(*iter)->get_type()!=Duck::TYPE_POSITION))continue;
+
+                       Vector p(positions[i]);
+
+                       p[0]+=vect[0];
+                       p[1]+=vect[1];
+                       (*iter)->set_trans_point(p);
+               }
+               for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
+               {
+                       if(!((*iter)->get_type()!=Duck::TYPE_VERTEX&&(*iter)->get_type()!=Duck::TYPE_POSITION))continue;
+
+                       Vector p(positions[i]);
+
+                       p[0]+=vect[0];
+                       p[1]+=vect[1];
+                       (*iter)->set_trans_point(p);
+               }
+               return;
+       }
+
+       if(!lock_aspect)
+       {
+               if(abs(drag_offset[0]-center[0])>EPSILON)
+                       vect[0]/=drag_offset[0]-center[0];
+               else
+                       vect[0]=1;
+               if(abs(drag_offset[1]-center[1])>EPSILON)
+                       vect[1]/=drag_offset[1]-center[1];
+               else
+                       vect[1]=1;
+               }
+       else
+       {
+               //vect[0]=vect[1]=vect.mag()*0.707106781;
+               Real amount(vect.mag()/(drag_offset-center).mag());
+               vect[0]=vect[1]=amount;
+       }
+
+       if(vect[0]<EPSILON && vect[0]>-EPSILON)
+               vect[0]=1;
+       if(vect[1]<EPSILON && vect[1]>-EPSILON)
+               vect[1]=1;
+
+       int i;
+       for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
+       {
+               if(((*iter)->get_type()!=Duck::TYPE_VERTEX&&(*iter)->get_type()!=Duck::TYPE_POSITION))continue;
+
+               Vector p(positions[i]-center);
+
+               p[0]*=vect[0];
+               p[1]*=vect[1];
+               p+=center;
+               (*iter)->set_trans_point(p);
+       }
+       for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
+       {
+               if(!((*iter)->get_type()!=Duck::TYPE_VERTEX&&(*iter)->get_type()!=Duck::TYPE_POSITION))continue;
+
+               Vector p(positions[i]-center);
+
+               p[0]*=vect[0];
+               p[1]*=vect[1];
+               p+=center;
+               (*iter)->set_trans_point(p);
+       }
+
+       last_scale=vect;
+       //snap=Vector(0,0);
+}
+
+bool
+DuckDrag_Scale::end_duck_drag(Duckmatic* duckmatic)
+{
+       if(bad_drag)return false;
+
+       if((last_scale-Vector(1,1)).mag()>0.0001)
+       {
+               duckmatic->signal_edited_selected_ducks();
+               return true;
+       }
+       else
+       {
+               duckmatic->signal_user_click_selected_ducks(0);
+               return false;
+       }
+}
diff --git a/synfig-studio/src/gui/states/state_scale.h b/synfig-studio/src/gui/states/state_scale.h
new file mode 100644 (file)
index 0000000..f351c12
--- /dev/null
@@ -0,0 +1,55 @@
+/* === S Y N F I G ========================================================= */
+/*!    \file state_scale.h
+**     \brief Template Header
+**
+**     $Id$
+**
+**     \legal
+**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+**
+**     This package is free software; you can redistribute it and/or
+**     modify it under the terms of the GNU General Public License as
+**     published by the Free Software Foundation; either version 2 of
+**     the License, or (at your option) any later version.
+**
+**     This package is distributed in the hope that it will be useful,
+**     but WITHOUT ANY WARRANTY; without even the implied warranty of
+**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+**     General Public License for more details.
+**     \endlegal
+*/
+/* ========================================================================= */
+
+/* === S T A R T =========================================================== */
+
+#ifndef __SYNFIG_STUDIO_STATE_SCALE_H
+#define __SYNFIG_STUDIO_STATE_SCALE_H
+
+/* === H E A D E R S ======================================================= */
+
+#include "smach.h"
+
+/* === M A C R O S ========================================================= */
+
+/* === T Y P E D E F S ===================================================== */
+
+/* === C L A S S E S & S T R U C T S ======================================= */
+
+namespace studio {
+
+class StateScale_Context;
+
+class StateScale : public Smach::state<StateScale_Context>
+{
+public:
+       StateScale();
+       ~StateScale();
+}; // END of class StateScale
+
+extern StateScale state_scale;
+
+}; // END of namespace studio
+
+/* === E N D =============================================================== */
+
+#endif
diff --git a/synfig-studio/src/gui/states/state_sketch.cpp b/synfig-studio/src/gui/states/state_sketch.cpp
new file mode 100644 (file)
index 0000000..f8b77a3
--- /dev/null
@@ -0,0 +1,508 @@
+/* === S Y N F I G ========================================================= */
+/*!    \file state_sketch.cpp
+**     \brief Template File
+**
+**     $Id$
+**
+**     \legal
+**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+**     Copyright (c) 2007, 2008 Chris Moore
+**
+**     This package is free software; you can redistribute it and/or
+**     modify it under the terms of the GNU General Public License as
+**     published by the Free Software Foundation; either version 2 of
+**     the License, or (at your option) any later version.
+**
+**     This package is distributed in the hope that it will be useful,
+**     but WITHOUT ANY WARRANTY; without even the implied warranty of
+**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+**     General Public License for more details.
+**     \endlegal
+*/
+/* ========================================================================= */
+
+/* === H E A D E R S ======================================================= */
+
+#ifdef USING_PCH
+#      include "pch.h"
+#else
+#ifdef HAVE_CONFIG_H
+#      include <config.h>
+#endif
+
+#include <gtkmm/dialog.h>
+#include <gtkmm/entry.h>
+
+#include <synfig/valuenode_dynamiclist.h>
+
+#include "state_sketch.h"
+#include "state_normal.h"
+#include "state_stroke.h"
+#include "canvasview.h"
+#include "workarea.h"
+#include "app.h"
+#include <synfig/valuenode_bline.h>
+#include <ETL/hermite>
+#include <ETL/calculus>
+#include <utility>
+#include "event_mouse.h"
+#include "event_layerclick.h"
+#include "toolbox.h"
+
+#include <synfigapp/blineconvert.h>
+#include <synfigapp/main.h>
+
+#include <ETL/gaussian>
+
+#include "dialog_tooloptions.h"
+
+#include <gtkmm/table.h>
+#include <gtkmm/label.h>
+#include <gtkmm/button.h>
+#include <gtkmm/checkbutton.h>
+#include <gtkmm/actiongroup.h>
+
+#include "general.h"
+
+#endif
+
+/* === U S I N G =========================================================== */
+
+using namespace std;
+using namespace etl;
+using namespace synfig;
+using namespace studio;
+
+/* === M A C R O S ========================================================= */
+
+/* === G L O B A L S ======================================================= */
+
+StateSketch studio::state_sketch;
+
+/* === C L A S S E S & S T R U C T S ======================================= */
+
+class studio::StateSketch_Context : public sigc::trackable
+{
+       Glib::RefPtr<Gtk::ActionGroup> action_group;
+
+       etl::handle<CanvasView> canvas_view_;
+       CanvasView::IsWorking is_working;
+
+       bool prev_table_status;
+       bool prev_workarea_layer_status_;
+
+       Gtk::Table options_table;
+       Gtk::Button button_clear_sketch;
+       Gtk::Button button_undo_stroke;
+       Gtk::Button button_save_sketch;
+       Gtk::Button button_load_sketch;
+       Gtk::CheckButton checkbutton_show_sketch;
+
+       void clear_sketch();
+       void save_sketch();
+       void load_sketch();
+       void undo_stroke();
+       void toggle_show_sketch();
+
+public:
+
+       Smach::event_result event_stop_handler(const Smach::event& x);
+
+       Smach::event_result event_refresh_handler(const Smach::event& x);
+
+       Smach::event_result event_mouse_down_handler(const Smach::event& x);
+
+       Smach::event_result event_stroke(const Smach::event& x);
+
+       Smach::event_result event_refresh_tool_options(const Smach::event& x);
+       Smach::event_result event_yield_tool_options(const Smach::event& x);
+
+       void refresh_tool_options();
+       void yield_tool_options();
+
+       StateSketch_Context(CanvasView* canvas_view);
+
+       ~StateSketch_Context();
+
+       const etl::handle<CanvasView>& get_canvas_view()const{return canvas_view_;}
+       etl::handle<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view_->canvas_interface();}
+       synfig::Time get_time()const { return get_canvas_interface()->get_time(); }
+       synfig::Canvas::Handle get_canvas()const{return canvas_view_->get_canvas();}
+       WorkArea * get_work_area()const{return canvas_view_->get_work_area();}
+
+};     // END of class StateSketch_Context
+
+
+/* === M E T H O D S ======================================================= */
+
+StateSketch::StateSketch():
+       Smach::state<StateSketch_Context>("sketch")
+{
+       insert(event_def(EVENT_STOP,&StateSketch_Context::event_stop_handler));
+       //insert(event_def(EVENT_REFRESH,&StateSketch_Context::event_refresh_handler));
+       insert(event_def(EVENT_REFRESH_DUCKS,&StateSketch_Context::event_refresh_handler));
+       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateSketch_Context::event_mouse_down_handler));
+       insert(event_def(EVENT_WORKAREA_STROKE,&StateSketch_Context::event_stroke));
+       insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateSketch_Context::event_refresh_tool_options));
+       insert(event_def(EVENT_YIELD_TOOL_OPTIONS,&StateSketch_Context::event_yield_tool_options));
+}
+
+StateSketch::~StateSketch()
+{
+}
+
+void
+StateSketch_Context::save_sketch()
+{
+       synfig::String filename(basename(get_canvas()->get_file_name())+".sketch");
+
+       while(App::dialog_save_file(_("Save Sketch"), filename, SKETCH_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())
+                       continue;
+
+               if(get_work_area()->save_sketch(filename))
+                       break;
+
+               get_canvas_view()->get_ui_interface()->error(_("Unable to save sketch"));
+       }
+}
+
+void
+StateSketch_Context::load_sketch()
+{
+       synfig::String filename(basename(get_canvas()->get_file_name())+".sketch");
+
+       while(App::dialog_open_file(_("Load Sketch"), filename, SKETCH_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())
+                       continue;
+
+               if(get_work_area()->load_sketch(filename))
+                       break;
+
+               get_canvas_view()->get_ui_interface()->error(_("Unable to load sketch"));
+       }
+       get_work_area()->queue_draw();
+}
+
+void
+StateSketch_Context::clear_sketch()
+{
+       get_work_area()->clear_persistent_strokes();
+
+       // if the sketch is currently shown, make sure it is updated
+       //! \todo is there a better way than this of getting Duckmatic to update its stroke_list_?
+       if (checkbutton_show_sketch.get_active())
+       {
+               get_work_area()->set_show_persistent_strokes(false);
+               get_work_area()->set_show_persistent_strokes(true);
+               get_canvas_view()->get_smach().process_event(EVENT_REFRESH);
+       }
+}
+
+void
+StateSketch_Context::undo_stroke()
+{
+       if(!get_work_area()->persistent_stroke_list().empty())
+       {
+               get_work_area()->persistent_stroke_list().pop_back();
+
+               // if the sketch is currently shown, make sure it is updated
+               //! \todo is there a better way than this of getting Duckmatic to update its stroke_list_?
+               if (checkbutton_show_sketch.get_active())
+               {
+                       get_work_area()->set_show_persistent_strokes(false);
+                       get_work_area()->set_show_persistent_strokes(true);
+                       get_canvas_view()->get_smach().process_event(EVENT_REFRESH);
+               }
+       }
+}
+
+void
+StateSketch_Context::toggle_show_sketch()
+{
+       get_work_area()->set_show_persistent_strokes(checkbutton_show_sketch.get_active());
+       get_work_area()->queue_draw();
+}
+
+StateSketch_Context::StateSketch_Context(CanvasView* canvas_view):
+       action_group(Gtk::ActionGroup::create("action_group_state_sketch")),
+       canvas_view_(canvas_view),
+       is_working(*canvas_view),
+       prev_workarea_layer_status_(get_work_area()->get_allow_layer_clicks()),
+       button_clear_sketch(_("Clear Sketch")),
+       button_undo_stroke(_("Undo Stroke")),
+       button_save_sketch(_("Save Sketch")),
+       button_load_sketch(_("Load Sketch")),
+       checkbutton_show_sketch(_("Show Sketch"))
+{
+    Glib::ustring ui_info =
+       "<ui>"
+       "       <toolbar action='toolbar-sketch'>"
+       "       <toolitem action='sketch-undo' />"
+       "       <toolitem action='sketch-clear' />"
+       "       <toolitem action='sketch-save-as' />"
+       "       <toolitem action='sketch-open' />"
+       "       </toolbar>"
+       "</ui>";
+
+       action_group->add(Gtk::Action::create(
+               "sketch-undo",
+               Gtk::StockID("gtk-undo"),
+               _("Undo Last Stroke"),
+               _("Undo Last Stroke")
+       ),
+               sigc::mem_fun(
+                       *this,
+                       &studio::StateSketch_Context::undo_stroke
+               )
+       );
+
+       action_group->add(Gtk::Action::create(
+               "sketch-clear",
+               Gtk::StockID("gtk-clear"),
+               _("Clear Sketch"),
+               _("Clear Sketch")
+       ),
+               sigc::mem_fun(
+                       *this,
+                       &studio::StateSketch_Context::clear_sketch
+               )
+       );
+
+       action_group->add(Gtk::Action::create(
+               "sketch-save-as",
+               Gtk::StockID("gtk-save-as"),
+               _("Save Sketch As..."),
+               _("Save Sketch As...")
+       ),
+               sigc::mem_fun(
+                       *this,
+                       &studio::StateSketch_Context::save_sketch
+               )
+       );
+
+       action_group->add(Gtk::Action::create(
+               "sketch-save-as",
+               Gtk::StockID("gtk-save-as"),
+               _("Save Sketch As..."),
+               _("Save Sketch As...")
+       ),
+               sigc::mem_fun(
+                       *this,
+                       &studio::StateSketch_Context::save_sketch
+               )
+       );
+
+       action_group->add(Gtk::Action::create(
+               "sketch-open",
+               Gtk::StockID("gtk-open"),
+               _("Open a Sketch"),
+               _("Open a Sketch")
+       ),
+               sigc::mem_fun(
+                       *this,
+                       &studio::StateSketch_Context::load_sketch
+               )
+       );
+
+       action_group->add( Gtk::Action::create("toolbar-sketch", "Sketch Toolbar") );
+
+       App::ui_manager()->add_ui_from_string(ui_info);
+
+       checkbutton_show_sketch.set_active(get_work_area()->get_show_persistent_strokes());
+
+       button_clear_sketch.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::clear_sketch));
+       button_undo_stroke.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::undo_stroke));
+       button_save_sketch.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::save_sketch));
+       button_load_sketch.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::load_sketch));
+       checkbutton_show_sketch.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::toggle_show_sketch));
+
+       options_table.attach(*manage(new Gtk::Label(_("Sketch Tool"))), 0, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(checkbutton_show_sketch,                                   0, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       //options_table.attach(button_undo_stroke, 0, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       //options_table.attach(button_clear_sketch, 0, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       //options_table.attach(button_save_sketch, 0, 1, 4, 5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       //options_table.attach(button_load_sketch, 1, 2, 4, 5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+
+       options_table.show_all();
+       refresh_tool_options();
+       App::dialog_tool_options->present();
+
+       // Turn off layer clicking
+       get_work_area()->set_allow_layer_clicks(false);
+
+       get_work_area()->set_cursor(Gdk::PENCIL);
+
+       // Turn off duck clicking
+       get_work_area()->set_allow_duck_clicks(false);
+
+       // clear out the ducks
+       //get_work_area()->clear_ducks();
+
+       // Refresh the work area
+       //get_work_area()->queue_draw();
+
+       // Hide the tables if they are showing
+       prev_table_status=get_canvas_view()->tables_are_visible();
+       //if(prev_table_status)get_canvas_view()->hide_tables();
+
+       // Disable the time bar
+       //get_canvas_view()->set_sensitive_timebar(false);
+
+       // Connect a signal
+       //get_work_area()->signal_user_click().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::on_user_click));
+
+       App::toolbox->refresh();
+}
+
+StateSketch_Context::~StateSketch_Context()
+{
+       get_work_area()->reset_cursor();
+
+       App::dialog_tool_options->clear();
+
+       // Restore layer clicking
+       get_work_area()->set_allow_layer_clicks(prev_workarea_layer_status_);
+
+       // Restore duck clicking
+       get_work_area()->set_allow_duck_clicks(true);
+
+       // Enable the time bar
+       //get_canvas_view()->set_sensitive_timebar(true);
+
+       // Bring back the tables if they were out before
+       if(prev_table_status)get_canvas_view()->show_tables();
+
+       // Refresh the work area
+       //get_work_area()->queue_draw();
+
+       App::toolbox->refresh();
+}
+
+void
+StateSketch_Context::yield_tool_options()
+{
+       App::dialog_tool_options->clear();
+       App::ui_manager()->remove_action_group(action_group);
+}
+
+void
+StateSketch_Context::refresh_tool_options()
+{
+       App::dialog_tool_options->clear();
+       App::dialog_tool_options->set_widget(options_table);
+       App::dialog_tool_options->set_local_name(_("Sketch Tool"));
+       App::dialog_tool_options->set_name("sketch");
+
+       App::ui_manager()->insert_action_group(action_group);
+       App::dialog_tool_options->set_toolbar(*dynamic_cast<Gtk::Toolbar*>(App::ui_manager()->get_widget("/toolbar-sketch")));
+
+       /*
+       App::dialog_tool_options->add_button(
+               Gtk::StockID("gtk-undo"),
+               _("Undo Last Stroke")
+       )->signal_clicked().connect(
+               sigc::mem_fun(
+                       *this,
+                       &studio::StateSketch_Context::undo_stroke
+               )
+       );
+       App::dialog_tool_options->add_button(
+               Gtk::StockID("gtk-clear"),
+               _("Clear Sketch")
+       )->signal_clicked().connect(
+               sigc::mem_fun(
+                       *this,
+                       &studio::StateSketch_Context::clear_sketch
+               )
+       );
+       App::dialog_tool_options->add_button(
+               Gtk::StockID("gtk-save"),
+               _("Save Sketch to a File")
+       )->signal_clicked().connect(
+               sigc::mem_fun(
+                       *this,
+                       &studio::StateSketch_Context::save_sketch
+               )
+       );
+
+       App::dialog_tool_options->add_button(
+               Gtk::StockID("gtk-open"),
+               _("Open a Sketch")
+       )->signal_clicked().connect(
+               sigc::mem_fun(
+                       *this,
+                       &studio::StateSketch_Context::load_sketch
+               )
+       );
+       */
+       //button_clear_sketch.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::clear_sketch));
+       //button_undo_stroke.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::undo_stroke));
+       //button_save_sketch.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::save_sketch));
+       //button_load_sketch.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::load_sketch));
+       //checkbutton_show_sketch.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::toggle_show_sketch));
+}
+
+Smach::event_result
+StateSketch_Context::event_refresh_tool_options(const Smach::event& /*x*/)
+{
+       refresh_tool_options();
+       return Smach::RESULT_ACCEPT;
+}
+
+Smach::event_result
+StateSketch_Context::event_yield_tool_options(const Smach::event& /*x*/)
+{
+       yield_tool_options();
+       return Smach::RESULT_ACCEPT;
+}
+
+Smach::event_result
+StateSketch_Context::event_stop_handler(const Smach::event& /*x*/)
+{
+       //throw Smach::egress_exception();
+       throw &state_normal;
+       return Smach::RESULT_OK;
+}
+
+Smach::event_result
+StateSketch_Context::event_refresh_handler(const Smach::event& /*x*/)
+{
+       return Smach::RESULT_ACCEPT;
+}
+
+Smach::event_result
+StateSketch_Context::event_mouse_down_handler(const Smach::event& x)
+{
+       const EventMouse& event(*reinterpret_cast<const EventMouse*>(&x));
+       switch(event.button)
+       {
+       case BUTTON_LEFT:
+               {
+                       // Enter the stroke state to get the stroke
+                       get_canvas_view()->get_smach().push_state(&state_stroke);
+                       return Smach::RESULT_ACCEPT;
+               }
+
+       default:
+               return Smach::RESULT_OK;
+       }
+}
+
+Smach::event_result
+StateSketch_Context::event_stroke(const Smach::event& x)
+{
+       const EventStroke& event(*reinterpret_cast<const EventStroke*>(&x));
+
+       assert(event.stroke_data);
+
+       get_work_area()->add_persistent_stroke(event.stroke_data,synfigapp::Main::get_outline_color());
+
+       return Smach::RESULT_ACCEPT;
+}
diff --git a/synfig-studio/src/gui/states/state_sketch.h b/synfig-studio/src/gui/states/state_sketch.h
new file mode 100644 (file)
index 0000000..301c81d
--- /dev/null
@@ -0,0 +1,55 @@
+/* === S Y N F I G ========================================================= */
+/*!    \file state_sketch.h
+**     \brief Template Header
+**
+**     $Id$
+**
+**     \legal
+**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+**
+**     This package is free software; you can redistribute it and/or
+**     modify it under the terms of the GNU General Public License as
+**     published by the Free Software Foundation; either version 2 of
+**     the License, or (at your option) any later version.
+**
+**     This package is distributed in the hope that it will be useful,
+**     but WITHOUT ANY WARRANTY; without even the implied warranty of
+**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+**     General Public License for more details.
+**     \endlegal
+*/
+/* ========================================================================= */
+
+/* === S T A R T =========================================================== */
+
+#ifndef __SYNFIG_STUDIO_STATE_SKETCH_H
+#define __SYNFIG_STUDIO_STATE_SKETCH_H
+
+/* === H E A D E R S ======================================================= */
+
+#include "smach.h"
+
+/* === M A C R O S ========================================================= */
+
+/* === T Y P E D E F S ===================================================== */
+
+/* === C L A S S E S & S T R U C T S ======================================= */
+
+namespace studio {
+
+class StateSketch_Context;
+
+class StateSketch : public Smach::state<StateSketch_Context>
+{
+public:
+       StateSketch();
+       ~StateSketch();
+}; // END of class StateSketch
+
+extern StateSketch state_sketch;
+
+}; // END of namespace studio
+
+/* === E N D =============================================================== */
+
+#endif
diff --git a/synfig-studio/src/gui/states/state_smoothmove.cpp b/synfig-studio/src/gui/states/state_smoothmove.cpp
new file mode 100644 (file)
index 0000000..f42df35
--- /dev/null
@@ -0,0 +1,388 @@
+/* === S Y N F I G ========================================================= */
+/*!    \file state_smoothmove.cpp
+**     \brief Template File
+**
+**     $Id$
+**
+**     \legal
+**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+**  Copyright (c) 2008 Chris Moore
+**     Copyright (c) 2009 Nikita Kitaev
+**
+**     This package is free software; you can redistribute it and/or
+**     modify it under the terms of the GNU General Public License as
+**     published by the Free Software Foundation; either version 2 of
+**     the License, or (at your option) any later version.
+**
+**     This package is distributed in the hope that it will be useful,
+**     but WITHOUT ANY WARRANTY; without even the implied warranty of
+**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+**     General Public License for more details.
+**     \endlegal
+*/
+/* ========================================================================= */
+
+/* === H E A D E R S ======================================================= */
+
+#ifdef USING_PCH
+#      include "pch.h"
+#else
+#ifdef HAVE_CONFIG_H
+#      include <config.h>
+#endif
+
+#include <gtkmm/dialog.h>
+#include <gtkmm/entry.h>
+
+#include <synfig/valuenode_blinecalcvertex.h>
+#include <synfig/valuenode_composite.h>
+#include <synfig/valuenode_dynamiclist.h>
+#include <synfigapp/action_system.h>
+
+#include "state_smoothmove.h"
+#include "state_normal.h"
+#include "canvasview.h"
+#include "workarea.h"
+#include "app.h"
+
+#include <synfigapp/action.h>
+#include "event_mouse.h"
+#include "event_layerclick.h"
+#include "toolbox.h"
+#include "dialog_tooloptions.h"
+#include <gtkmm/optionmenu.h>
+#include "duck.h"
+#include "onemoment.h"
+#include <synfigapp/main.h>
+
+#include "general.h"
+
+#endif
+
+/* === U S I N G =========================================================== */
+
+using namespace std;
+using namespace etl;
+using namespace synfig;
+using namespace studio;
+
+/* === M A C R O S ========================================================= */
+
+/* === G L O B A L S ======================================================= */
+
+StateSmoothMove studio::state_smooth_move;
+
+/* === C L A S S E S & S T R U C T S ======================================= */
+
+class DuckDrag_SmoothMove : public DuckDrag_Base
+{
+       float radius;
+
+       synfig::Vector last_translate_;
+       synfig::Vector drag_offset_;
+       synfig::Vector snap;
+
+       std::vector<synfig::Vector> last_;
+       std::vector<synfig::Vector> positions;
+
+public:
+       DuckDrag_SmoothMove();
+       void begin_duck_drag(Duckmatic* duckmatic, const synfig::Vector& begin);
+       bool end_duck_drag(Duckmatic* duckmatic);
+       void duck_drag(Duckmatic* duckmatic, const synfig::Vector& vector);
+
+       void set_radius(float x) { radius=x; }
+       float get_radius()const { return radius; }
+};
+
+
+class studio::StateSmoothMove_Context : public sigc::trackable
+{
+       etl::handle<CanvasView> canvas_view_;
+       CanvasView::IsWorking is_working;
+
+       //Duckmatic::Push duckmatic_push;
+
+       synfigapp::Settings& settings;
+
+       etl::handle<DuckDrag_SmoothMove> duck_dragger_;
+
+       Gtk::Table options_table;
+
+       Gtk::Adjustment  adj_radius;
+       Gtk::SpinButton  spin_radius;
+
+       float pressure;
+
+public:
+       float get_radius()const { return adj_radius.get_value(); }
+       void set_radius(float x) { return adj_radius.set_value(x); }
+
+       void refresh_radius() { duck_dragger_->set_radius(get_radius()*pressure); }
+
+       Smach::event_result event_stop_handler(const Smach::event& x);
+
+       Smach::event_result event_refresh_tool_options(const Smach::event& x);
+
+       void refresh_tool_options();
+
+       StateSmoothMove_Context(CanvasView* canvas_view);
+
+       ~StateSmoothMove_Context();
+
+       const etl::handle<CanvasView>& get_canvas_view()const{return canvas_view_;}
+       etl::handle<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view_->canvas_interface();}
+       synfig::Canvas::Handle get_canvas()const{return canvas_view_->get_canvas();}
+       WorkArea * get_work_area()const{return canvas_view_->get_work_area();}
+
+       void load_settings();
+       void save_settings();
+};     // END of class StateSmoothMove_Context
+
+/* === M E T H O D S ======================================================= */
+
+StateSmoothMove::StateSmoothMove():
+       Smach::state<StateSmoothMove_Context>("smooth_move")
+{
+       insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateSmoothMove_Context::event_refresh_tool_options));
+       insert(event_def(EVENT_STOP,&StateSmoothMove_Context::event_stop_handler));
+}
+
+StateSmoothMove::~StateSmoothMove()
+{
+}
+
+void
+StateSmoothMove_Context::load_settings()
+{
+       String value;
+
+       if(settings.get_value("smooth_move.radius",value))
+               set_radius(atof(value.c_str()));
+       else
+               set_radius(1.0f);
+}
+
+void
+StateSmoothMove_Context::save_settings()
+{
+       settings.set_value("smooth_move.radius",strprintf("%f",get_radius()));
+}
+
+StateSmoothMove_Context::StateSmoothMove_Context(CanvasView* canvas_view):
+       canvas_view_(canvas_view),
+       is_working(*canvas_view),
+//     duckmatic_push(get_work_area()),
+       settings(synfigapp::Main::get_selected_input_device()->settings()),
+       duck_dragger_(new DuckDrag_SmoothMove()),
+       adj_radius(1,0,100000,0.01,0.1),
+       spin_radius(adj_radius,0.1,3)
+{
+       pressure=1.0f;
+
+       // Set up the tool options dialog
+       options_table.attach(*manage(new Gtk::Label(_("SmoothMove Tool"))),     0, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(*manage(new Gtk::Label(_("Radius"))),                      0, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(spin_radius,                                                                       0, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+
+       spin_radius.signal_value_changed().connect(sigc::mem_fun(*this,&StateSmoothMove_Context::refresh_radius));
+
+       options_table.show_all();
+       refresh_tool_options();
+       //App::dialog_tool_options->set_widget(options_table);
+       App::dialog_tool_options->present();
+
+       get_work_area()->set_allow_layer_clicks(true);
+       get_work_area()->set_duck_dragger(duck_dragger_);
+
+       App::toolbox->refresh();
+
+       get_work_area()->set_cursor(Gdk::FLEUR);
+       //get_work_area()->reset_cursor();
+
+       load_settings();
+}
+
+void
+StateSmoothMove_Context::refresh_tool_options()
+{
+       App::dialog_tool_options->clear();
+       App::dialog_tool_options->set_widget(options_table);
+       App::dialog_tool_options->set_local_name(_("Smooth Move"));
+       App::dialog_tool_options->set_name("smooth_move");
+}
+
+Smach::event_result
+StateSmoothMove_Context::event_refresh_tool_options(const Smach::event& /*x*/)
+{
+       refresh_tool_options();
+       return Smach::RESULT_ACCEPT;
+}
+
+Smach::event_result
+StateSmoothMove_Context::event_stop_handler(const Smach::event& /*x*/)
+{
+       throw &state_normal;
+       return Smach::RESULT_OK;
+}
+
+StateSmoothMove_Context::~StateSmoothMove_Context()
+{
+       save_settings();
+
+       get_work_area()->clear_duck_dragger();
+       get_work_area()->reset_cursor();
+
+       App::dialog_tool_options->clear();
+
+       App::toolbox->refresh();
+}
+
+
+
+
+DuckDrag_SmoothMove::DuckDrag_SmoothMove():radius(1.0f)
+{
+}
+
+void
+DuckDrag_SmoothMove::begin_duck_drag(Duckmatic* duckmatic, const synfig::Vector& offset)
+{
+       last_translate_=Vector(0,0);
+               drag_offset_=duckmatic->find_duck(offset)->get_trans_point();
+
+               //snap=drag_offset-duckmatic->snap_point_to_grid(drag_offset);
+               //snap=offset-drag_offset_;
+               snap=Vector(0,0);
+
+       last_.clear();
+       positions.clear();
+       const DuckList selected_ducks(duckmatic->get_selected_ducks());
+       DuckList::const_iterator iter;
+       int i;
+       for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
+       {
+               last_.push_back(Vector(0,0));
+               positions.push_back((*iter)->get_trans_point());
+       }
+}
+
+void
+DuckDrag_SmoothMove::duck_drag(Duckmatic* duckmatic, const synfig::Vector& vector)
+{
+       const DuckList selected_ducks(duckmatic->get_selected_ducks());
+       DuckList::const_iterator iter;
+       synfig::Vector vect(duckmatic->snap_point_to_grid(vector)-drag_offset_+snap);
+
+       int i;
+
+       Time time(duckmatic->get_time());
+
+       // process vertex and position ducks first
+       for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
+       {
+               // skip this duck if it is NOT a vertex or a position
+               if (((*iter)->get_type() != Duck::TYPE_VERTEX &&
+                        (*iter)->get_type() != Duck::TYPE_POSITION))
+                       continue;
+               Point p(positions[i]);
+
+               float dist(1.0f-(p-drag_offset_).mag()/get_radius());
+               if(dist<0)
+                       dist=0;
+
+               last_[i]=vect*dist;
+               (*iter)->set_trans_point(p+last_[i], time);
+       }
+
+       // then process non vertex and non position ducks
+       for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
+       {
+               // skip this duck if it IS a vertex or a position
+               if (!((*iter)->get_type() != Duck::TYPE_VERTEX &&
+                        (*iter)->get_type() != Duck::TYPE_POSITION))
+                       continue;
+               Point p(positions[i]);
+
+               float dist(1.0f-(p-drag_offset_).mag()/get_radius());
+               if(dist<0)
+                       dist=0;
+
+               last_[i]=vect*dist;
+               (*iter)->set_trans_point(p+last_[i], time);
+       }
+
+       // then patch up the tangents for the vertices we've moved
+       duckmatic->update_ducks();
+
+       last_translate_=vect;
+       //snap=Vector(0,0);
+}
+
+bool
+DuckDrag_SmoothMove::end_duck_drag(Duckmatic* duckmatic)
+{
+       //synfig::info("end_duck_drag(): Diff= %f",last_translate_.mag());
+       if(last_translate_.mag()>0.0001)
+       {
+               const DuckList selected_ducks(duckmatic->get_selected_ducks());
+               DuckList::const_iterator iter;
+
+               int i;
+
+               smart_ptr<OneMoment> wait;if(selected_ducks.size()>20)wait.spawn();
+
+               for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
+               {
+                       if(last_[i].mag()>0.0001)
+                               {
+                               if ((*iter)->get_type() == Duck::TYPE_ANGLE)
+                                       {
+                                               if(!(*iter)->signal_edited_angle()((*iter)->get_rotations()))
+                                               {
+                                                       throw String("Bad edit");
+                                               }
+                                       }
+                                       else if (App::restrict_radius_ducks &&
+                                                        (*iter)->is_radius())
+                                       {
+                                               Point point((*iter)->get_point());
+                                               bool changed = false;
+
+                                               if (point[0] < 0)
+                                               {
+                                                       point[0] = 0;
+                                                       changed = true;
+                                               }
+                                               if (point[1] < 0)
+                                               {
+                                                       point[1] = 0;
+                                                       changed = true;
+                                               }
+
+                                               if (changed) (*iter)->set_point(point);
+
+                                               if(!(*iter)->signal_edited()(point))
+                                               {
+                                                       throw String("Bad edit");
+                                               }
+                                       }
+                                       else
+                                       {
+                                               if(!(*iter)->signal_edited()((*iter)->get_point()))
+                                               {
+                                                       throw String("Bad edit");
+                                               }
+                                       }
+                               }
+               }
+               //duckmatic->get_selected_ducks()=new_set;
+               //duckmatic->refresh_selected_ducks();
+               return true;
+       }
+       else
+       {
+               duckmatic->signal_user_click_selected_ducks(0);
+               return false;
+       }
+}
diff --git a/synfig-studio/src/gui/states/state_smoothmove.h b/synfig-studio/src/gui/states/state_smoothmove.h
new file mode 100644 (file)
index 0000000..07442af
--- /dev/null
@@ -0,0 +1,56 @@
+/* === S Y N F I G ========================================================= */
+/*!    \file state_smoothmove.h
+**     \brief Template Header
+**
+**     $Id$
+**
+**     \legal
+**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+**
+**     This package is free software; you can redistribute it and/or
+**     modify it under the terms of the GNU General Public License as
+**     published by the Free Software Foundation; either version 2 of
+**     the License, or (at your option) any later version.
+**
+**     This package is distributed in the hope that it will be useful,
+**     but WITHOUT ANY WARRANTY; without even the implied warranty of
+**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+**     General Public License for more details.
+**     \endlegal
+*/
+/* ========================================================================= */
+
+/* === S T A R T =========================================================== */
+
+#ifndef __SYNFIG_STUDIO_STATE_SMOOTHMOVE_H
+#define __SYNFIG_STUDIO_STATE_SMOOTHMOVE_H
+
+/* === H E A D E R S ======================================================= */
+
+#include "smach.h"
+
+
+/* === M A C R O S ========================================================= */
+
+/* === T Y P E D E F S ===================================================== */
+
+/* === C L A S S E S & S T R U C T S ======================================= */
+
+namespace studio {
+
+class StateSmoothMove_Context;
+
+class StateSmoothMove : public Smach::state<StateSmoothMove_Context>
+{
+public:
+       StateSmoothMove();
+       ~StateSmoothMove();
+}; // END of class StateSmoothMove
+
+extern StateSmoothMove state_smooth_move;
+
+}; // END of namespace studio
+
+/* === E N D =============================================================== */
+
+#endif
diff --git a/synfig-studio/src/gui/states/state_star.cpp b/synfig-studio/src/gui/states/state_star.cpp
new file mode 100644 (file)
index 0000000..3be4b53
--- /dev/null
@@ -0,0 +1,1091 @@
+/* === S Y N F I G ========================================================= */
+/*!    \file state_star.cpp
+**     \brief Template File
+**
+**     $Id$
+**
+**     \legal
+**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+**     Copyright (c) 2008 Chris Moore
+**
+**     This package is free software; you can redistribute it and/or
+**     modify it under the terms of the GNU General Public License as
+**     published by the Free Software Foundation; either version 2 of
+**     the License, or (at your option) any later version.
+**
+**     This package is distributed in the hope that it will be useful,
+**     but WITHOUT ANY WARRANTY; without even the implied warranty of
+**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+**     General Public License for more details.
+**     \endlegal
+*/
+/* ========================================================================= */
+
+/* === H E A D E R S ======================================================= */
+
+#ifdef USING_PCH
+#      include "pch.h"
+#else
+#ifdef HAVE_CONFIG_H
+#      include <config.h>
+#endif
+
+#include <gtkmm/dialog.h>
+#include <gtkmm/entry.h>
+
+#include <synfig/valuenode_dynamiclist.h>
+#include <synfigapp/action_system.h>
+#include <synfig/valuenode_bline.h>
+
+#include "state_star.h"
+#include "state_normal.h"
+#include "canvasview.h"
+#include "workarea.h"
+#include "app.h"
+
+#include <synfigapp/action.h>
+#include "event_mouse.h"
+#include "event_layerclick.h"
+#include "toolbox.h"
+#include "dialog_tooloptions.h"
+#include <gtkmm/optionmenu.h>
+#include "duck.h"
+#include "widgets/widget_enum.h"
+#include <synfigapp/main.h>
+
+#include "general.h"
+
+#endif
+
+/* === U S I N G =========================================================== */
+
+using namespace std;
+using namespace etl;
+using namespace synfig;
+using namespace studio;
+
+/* === M A C R O S ========================================================= */
+
+/* === G L O B A L S ======================================================= */
+
+StateStar studio::state_star;
+
+/* === C L A S S E S & S T R U C T S ======================================= */
+
+class studio::StateStar_Context : public sigc::trackable
+{
+       etl::handle<CanvasView> canvas_view_;
+       CanvasView::IsWorking is_working;
+
+       Duckmatic::Push duckmatic_push;
+
+       Point point_holder;
+
+       etl::handle<Duck> point2_duck;
+
+       void refresh_ducks();
+
+       bool prev_workarea_layer_status_;
+
+       //Toolbox settings
+       synfigapp::Settings& settings;
+
+       //Toolbox display
+       Gtk::Table options_table;
+
+       Gtk::Entry              entry_id; //what to name the layer
+
+       Gtk::Adjustment adj_feather;
+       Gtk::Adjustment adj_number_of_points;
+       Gtk::Adjustment adj_inner_tangent;
+       Gtk::Adjustment adj_outer_tangent;
+       Gtk::Adjustment adj_inner_width;
+       Gtk::Adjustment adj_outer_width;
+       Gtk::Adjustment adj_radius_ratio;
+       Gtk::Adjustment adj_angle_offset;
+       Gtk::SpinButton spin_feather;
+       Gtk::SpinButton spin_number_of_points;
+       Gtk::SpinButton spin_inner_tangent;
+       Gtk::SpinButton spin_outer_tangent;
+       Gtk::SpinButton spin_inner_width;
+       Gtk::SpinButton spin_outer_width;
+       Gtk::SpinButton spin_radius_ratio;
+       Gtk::SpinButton spin_angle_offset;
+
+       Gtk::CheckButton checkbutton_invert;
+       Gtk::CheckButton checkbutton_regular_polygon;
+       Gtk::CheckButton checkbutton_layer_star;
+       Gtk::CheckButton checkbutton_layer_region;
+       Gtk::CheckButton checkbutton_layer_outline;
+       Gtk::CheckButton checkbutton_layer_curve_gradient;
+       Gtk::CheckButton checkbutton_layer_plant;
+       Gtk::CheckButton checkbutton_layer_link_origins;
+       Gtk::CheckButton checkbutton_layer_origins_at_center;
+
+public:
+
+       // this only counts the layers which will have their origins linked
+       int layers_to_create()const
+       {
+               return
+                       (get_layer_star_flag() && get_layer_origins_at_center_flag()) +
+                       get_layer_region_flag() +
+                       get_layer_outline_flag() +
+                       get_layer_curve_gradient_flag() +
+                       get_layer_plant_flag();
+       }
+
+       synfig::String get_id()const { return entry_id.get_text(); }
+       void set_id(const synfig::String& x) { return entry_id.set_text(x); }
+
+       Real get_feather()const { return adj_feather.get_value(); }
+       void set_feather(Real f) { adj_feather.set_value(f); }
+
+       Real get_number_of_points()const { return adj_number_of_points.get_value(); }
+       void set_number_of_points(Real f) { adj_number_of_points.set_value(f); }
+
+       Real get_inner_tangent()const { return adj_inner_tangent.get_value(); }
+       void set_inner_tangent(Real f) { adj_inner_tangent.set_value(f); }
+
+       Real get_outer_tangent()const { return adj_outer_tangent.get_value(); }
+       void set_outer_tangent(Real f) { adj_outer_tangent.set_value(f); }
+
+       Real get_inner_width()const { return adj_inner_width.get_value(); }
+       void set_inner_width(Real f) { adj_inner_width.set_value(f); }
+
+       Real get_outer_width()const { return adj_outer_width.get_value(); }
+       void set_outer_width(Real f) { adj_outer_width.set_value(f); }
+
+       Real get_radius_ratio()const { return adj_radius_ratio.get_value(); }
+       void set_radius_ratio(Real f) { adj_radius_ratio.set_value(f); }
+
+       Real get_angle_offset()const { return adj_angle_offset.get_value(); }
+       void set_angle_offset(Real f) { adj_angle_offset.set_value(f); }
+
+       bool get_invert()const { return checkbutton_invert.get_active(); }
+       void set_invert(bool i) { checkbutton_invert.set_active(i); }
+
+       bool get_regular_polygon()const { return checkbutton_regular_polygon.get_active(); }
+       void set_regular_polygon(bool i) { checkbutton_regular_polygon.set_active(i); }
+
+       bool get_layer_star_flag()const { return checkbutton_layer_star.get_active(); }
+       void set_layer_star_flag(bool x) { return checkbutton_layer_star.set_active(x); }
+
+       bool get_layer_region_flag()const { return checkbutton_layer_region.get_active(); }
+       void set_layer_region_flag(bool x) { return checkbutton_layer_region.set_active(x); }
+
+       bool get_layer_outline_flag()const { return checkbutton_layer_outline.get_active(); }
+       void set_layer_outline_flag(bool x) { return checkbutton_layer_outline.set_active(x); }
+
+       bool get_layer_curve_gradient_flag()const { return checkbutton_layer_curve_gradient.get_active(); }
+       void set_layer_curve_gradient_flag(bool x) { return checkbutton_layer_curve_gradient.set_active(x); }
+
+       bool get_layer_plant_flag()const { return checkbutton_layer_plant.get_active(); }
+       void set_layer_plant_flag(bool x) { return checkbutton_layer_plant.set_active(x); }
+
+       bool get_layer_link_origins_flag()const { return checkbutton_layer_link_origins.get_active(); }
+       void set_layer_link_origins_flag(bool x) { return checkbutton_layer_link_origins.set_active(x); }
+
+       bool get_layer_origins_at_center_flag()const { return checkbutton_layer_origins_at_center.get_active(); }
+       void set_layer_origins_at_center_flag(bool x) { return checkbutton_layer_origins_at_center.set_active(x); }
+
+       void refresh_tool_options(); //to refresh the toolbox
+
+       //events
+       Smach::event_result event_stop_handler(const Smach::event& x);
+       Smach::event_result event_refresh_handler(const Smach::event& x);
+       Smach::event_result event_mouse_click_handler(const Smach::event& x);
+       Smach::event_result event_refresh_tool_options(const Smach::event& x);
+
+       //constructor destructor
+       StateStar_Context(CanvasView* canvas_view);
+       ~StateStar_Context();
+
+       //Canvas interaction
+       const etl::handle<CanvasView>& get_canvas_view()const{return canvas_view_;}
+       etl::handle<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view_->canvas_interface();}
+       synfig::Canvas::Handle get_canvas()const{return canvas_view_->get_canvas();}
+       WorkArea * get_work_area()const{return canvas_view_->get_work_area();}
+
+       //Modifying settings etc.
+       void load_settings();
+       void save_settings();
+       void reset();
+       void increment_id();
+       bool egress_on_selection_change;
+       Smach::event_result event_layer_selection_changed_handler(const Smach::event& /*x*/)
+       {
+               if(egress_on_selection_change)
+                       throw &state_normal; //throw Smach::egress_exception();
+               return Smach::RESULT_OK;
+       }
+
+       void make_star(const Point& p1, const Point& p2);
+
+};     // END of class StateStar_Context
+
+/* === M E T H O D S ======================================================= */
+
+StateStar::StateStar():
+       Smach::state<StateStar_Context>("star")
+{
+       insert(event_def(EVENT_LAYER_SELECTION_CHANGED,&StateStar_Context::event_layer_selection_changed_handler));
+       insert(event_def(EVENT_STOP,&StateStar_Context::event_stop_handler));
+       insert(event_def(EVENT_REFRESH,&StateStar_Context::event_refresh_handler));
+       insert(event_def(EVENT_REFRESH_DUCKS,&StateStar_Context::event_refresh_handler));
+       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateStar_Context::event_mouse_click_handler));
+       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DRAG,&StateStar_Context::event_mouse_click_handler));
+       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_UP,&StateStar_Context::event_mouse_click_handler));
+       insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateStar_Context::event_refresh_tool_options));
+}
+
+StateStar::~StateStar()
+{
+}
+
+void
+StateStar_Context::load_settings()
+{
+       String value;
+
+       //parse the arguments yargh!
+       if(settings.get_value("star.id",value))
+               set_id(value);
+       else
+               set_id("Star");
+
+       if(settings.get_value("star.feather",value))
+               set_feather(atof(value.c_str()));
+       else
+               set_feather(0);
+
+       if(settings.get_value("star.number_of_points",value))
+               set_number_of_points(atof(value.c_str()));
+       else
+               set_number_of_points(5);
+
+       if(settings.get_value("star.inner_tangent",value))
+               set_inner_tangent(atof(value.c_str()));
+       else
+               set_inner_tangent(0);
+
+       if(settings.get_value("star.outer_tangent",value))
+               set_outer_tangent(atof(value.c_str()));
+       else
+               set_outer_tangent(0);
+
+       if(settings.get_value("star.inner_width",value))
+               set_inner_width(atof(value.c_str()));
+       else
+               set_inner_width(1);
+
+       if(settings.get_value("star.outer_width",value))
+               set_outer_width(atof(value.c_str()));
+       else
+               set_outer_width(1);
+
+       if(settings.get_value("star.radius_ratio",value))
+               set_radius_ratio(atof(value.c_str()));
+       else
+               set_radius_ratio(0.5);
+
+       if(settings.get_value("star.angle_offset",value))
+               set_angle_offset(atof(value.c_str()));
+       else
+               set_angle_offset(0);
+
+       if(settings.get_value("star.invert",value) && value != "0")
+               set_invert(true);
+       else
+               set_invert(false);
+
+       if(settings.get_value("star.regular_polygon",value) && value != "0")
+               set_regular_polygon(true);
+       else
+               set_regular_polygon(false);
+
+       if(settings.get_value("star.layer_star",value) && value=="0")
+               set_layer_star_flag(false);
+       else
+               set_layer_star_flag(true);
+
+       if(settings.get_value("star.layer_region",value) && value=="1")
+               set_layer_region_flag(true);
+       else
+               set_layer_region_flag(false);
+
+       if(settings.get_value("star.layer_outline",value) && value=="1")
+               set_layer_outline_flag(true);
+       else
+               set_layer_outline_flag(false);
+
+       if(settings.get_value("star.layer_curve_gradient",value) && value=="1")
+               set_layer_curve_gradient_flag(true);
+       else
+               set_layer_curve_gradient_flag(false);
+
+       if(settings.get_value("star.layer_plant",value) && value=="1")
+               set_layer_plant_flag(true);
+       else
+               set_layer_plant_flag(false);
+
+       if(settings.get_value("star.layer_link_origins",value) && value=="0")
+               set_layer_link_origins_flag(false);
+       else
+               set_layer_link_origins_flag(true);
+
+       if(settings.get_value("star.layer_origins_at_center",value) && value=="0")
+               set_layer_origins_at_center_flag(false);
+       else
+               set_layer_origins_at_center_flag(true);
+}
+
+void
+StateStar_Context::save_settings()
+{
+       settings.set_value("star.id",get_id());
+       settings.set_value("star.feather",strprintf("%f",(float)get_feather()));
+       settings.set_value("star.number_of_points",strprintf("%d",(int)(get_number_of_points() + 0.5)));
+       settings.set_value("star.inner_tangent",strprintf("%f",(float)get_inner_tangent()));
+       settings.set_value("star.outer_tangent",strprintf("%f",(float)get_outer_tangent()));
+       settings.set_value("star.inner_width",strprintf("%f",(float)get_inner_width()));
+       settings.set_value("star.outer_width",strprintf("%f",(float)get_outer_width()));
+       settings.set_value("star.radius_ratio",strprintf("%f",(float)get_radius_ratio()));
+       settings.set_value("star.angle_offset",strprintf("%f",(float)get_angle_offset()));
+       settings.set_value("star.invert",get_invert()?"1":"0");
+       settings.set_value("star.regular_polygon",get_regular_polygon()?"1":"0");
+       settings.set_value("star.layer_star",get_layer_star_flag()?"1":"0");
+       settings.set_value("star.layer_outline",get_layer_outline_flag()?"1":"0");
+       settings.set_value("star.layer_region",get_layer_region_flag()?"1":"0");
+       settings.set_value("star.layer_curve_gradient",get_layer_curve_gradient_flag()?"1":"0");
+       settings.set_value("star.layer_plant",get_layer_plant_flag()?"1":"0");
+       settings.set_value("star.layer_link_origins",get_layer_link_origins_flag()?"1":"0");
+       settings.set_value("star.layer_origins_at_center",get_layer_origins_at_center_flag()?"1":"0");
+}
+
+void
+StateStar_Context::reset()
+{
+       refresh_ducks();
+}
+
+void
+StateStar_Context::increment_id()
+{
+       String id(get_id());
+       int number=1;
+       int digits=0;
+
+       if(id.empty())
+               id="Star";
+
+       // If there is a number
+       // already at the end of the
+       // id, then remove it.
+       if(id[id.size()-1]<='9' && id[id.size()-1]>='0')
+       {
+               // figure out how many digits it is
+               for (digits = 0;
+                        (int)id.size()-1 >= digits && id[id.size()-1-digits] <= '9' && id[id.size()-1-digits] >= '0';
+                        digits++)
+                       ;
+
+               String str_number;
+               str_number=String(id,id.size()-digits,id.size());
+               id=String(id,0,id.size()-digits);
+
+               number=atoi(str_number.c_str());
+       }
+       else
+       {
+               number=1;
+               digits=3;
+       }
+
+       number++;
+
+       // Add the number back onto the id
+       {
+               const String format(strprintf("%%0%dd",digits));
+               id+=strprintf(format.c_str(),number);
+       }
+
+       // Set the ID
+       set_id(id);
+}
+
+StateStar_Context::StateStar_Context(CanvasView* canvas_view):
+       canvas_view_(canvas_view),
+       is_working(*canvas_view),
+       duckmatic_push(get_work_area()),
+       prev_workarea_layer_status_(get_work_area()->get_allow_layer_clicks()),
+       settings(synfigapp::Main::get_selected_input_device()->settings()),
+       entry_id(),             //   value lower upper  step page
+       adj_feather(                    0,    0,    1, 0.01, 0.1),
+       adj_number_of_points(   0,    2,  120, 1   , 1  ),
+       adj_inner_tangent(              0,  -10,   10, 0.01, 0.1),
+       adj_outer_tangent(              0,  -10,   10, 0.01, 0.1),
+       adj_inner_width(                0,  -10,   10, 0.01, 0.1),
+       adj_outer_width(                0,  -10,   10, 0.01, 0.1),
+       adj_radius_ratio(               0,  -10,   10, 0.01, 0.1),
+       adj_angle_offset(               0, -360,  360, 0.1 , 1  ),
+       spin_feather(adj_feather,0.1,3),
+       spin_number_of_points(adj_number_of_points,1,0),
+       spin_inner_tangent(adj_inner_tangent,1,2),
+       spin_outer_tangent(adj_outer_tangent,1,2),
+       spin_inner_width(adj_inner_width,1,2),
+       spin_outer_width(adj_outer_width,1,2),
+       spin_radius_ratio(adj_radius_ratio,1,2),
+       spin_angle_offset(adj_angle_offset,1,1),
+       checkbutton_invert(_("Invert")),
+       checkbutton_regular_polygon(_("Regular Polygon")),
+       checkbutton_layer_star(_("Create Star Layer")),
+       checkbutton_layer_region(_("Create Region BLine")),
+       checkbutton_layer_outline(_("Create Outline BLine")),
+       checkbutton_layer_curve_gradient(_("Create Curve Gradient BLine")),
+       checkbutton_layer_plant(_("Create Plant BLine")),
+       checkbutton_layer_link_origins(_("Link Origins")),
+       checkbutton_layer_origins_at_center(_("BLine Origins at Center"))
+{
+       egress_on_selection_change=true;
+
+       load_settings();
+
+       // Set up the tool options dialog
+       options_table.attach(*manage(new Gtk::Label(_("Star Tool"))),                   0, 2,  0,  1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(entry_id,                                                                                  0, 2,  1,  2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(checkbutton_layer_star,                                                    0, 2,  2,  3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(checkbutton_layer_outline,                                                 0, 2,  3,  4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(checkbutton_layer_region,                                                  0, 2,  4,  5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(checkbutton_layer_plant,                                                   0, 2,  5,  6, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(checkbutton_layer_curve_gradient,                                  0, 2,  6,  7, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(checkbutton_layer_link_origins,                                    0, 2,  7,  8, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(checkbutton_layer_origins_at_center,                               0, 2,  8,  9, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(checkbutton_invert,                                                                0, 2,  9, 10, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(checkbutton_regular_polygon,                                               0, 2, 10, 11, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+
+       options_table.attach(*manage(new Gtk::Label(_("Feather:"))),                    0, 1, 11, 12, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(spin_feather,                                                                              1, 2, 11, 12, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+
+       options_table.attach(*manage(new Gtk::Label(_("Number of Points:"))),   0, 1, 12, 13, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(spin_number_of_points,                                                             1, 2, 12, 13, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+
+       options_table.attach(*manage(new Gtk::Label(_("Inner Tangent:"))),              0, 1, 13, 14, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(spin_inner_tangent,                                                                1, 2, 13, 14, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+
+       options_table.attach(*manage(new Gtk::Label(_("Outer Tangent:"))),              0, 1, 14, 15, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(spin_outer_tangent,                                                                1, 2, 14, 15, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+
+       options_table.attach(*manage(new Gtk::Label(_("Inner Width:"))),                0, 1, 15, 16, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(spin_inner_width,                                                                  1, 2, 15, 16, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+
+       options_table.attach(*manage(new Gtk::Label(_("Outer Width:"))),                0, 1, 16, 17, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(spin_outer_width,                                                                  1, 2, 16, 17, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+
+       options_table.attach(*manage(new Gtk::Label(_("Radius Ratio:"))),               0, 1, 17, 18, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(spin_radius_ratio,                                                                 1, 2, 17, 18, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+
+       options_table.attach(*manage(new Gtk::Label(_("Angle Offset:"))),               0, 1, 18, 19, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(spin_angle_offset,                                                                 1, 2, 18, 19, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+
+       options_table.show_all();
+
+       refresh_tool_options();
+       App::dialog_tool_options->present();
+
+       // Turn off layer clicking
+       get_work_area()->set_allow_layer_clicks(false);
+
+       // clear out the ducks
+       get_work_area()->clear_ducks();
+
+       // Refresh the work area
+       get_work_area()->queue_draw();
+
+       // Hide the tables if they are showing
+       //prev_table_status=get_canvas_view()->tables_are_visible();
+       //if(prev_table_status)get_canvas_view()->hide_tables();
+
+       // Disable the time bar
+       //get_canvas_view()->set_sensitive_timebar(false);
+
+       // Connect a signal
+       //get_work_area()->signal_user_click().connect(sigc::mem_fun(*this,&studio::StateStar_Context::on_user_click));
+       get_work_area()->set_cursor(Gdk::STAR);
+
+       App::toolbox->refresh();
+}
+
+void
+StateStar_Context::refresh_tool_options()
+{
+       App::dialog_tool_options->clear();
+       App::dialog_tool_options->set_widget(options_table);
+       App::dialog_tool_options->set_local_name(_("Star Tool"));
+       App::dialog_tool_options->set_name("star");
+}
+
+Smach::event_result
+StateStar_Context::event_refresh_tool_options(const Smach::event& /*x*/)
+{
+       refresh_tool_options();
+       return Smach::RESULT_ACCEPT;
+}
+
+StateStar_Context::~StateStar_Context()
+{
+       save_settings();
+
+       // Restore layer clicking
+       get_work_area()->set_allow_layer_clicks(prev_workarea_layer_status_);
+       get_work_area()->reset_cursor();
+
+       App::dialog_tool_options->clear();
+
+       // Enable the time bar
+       //get_canvas_view()->set_sensitive_timebar(true);
+
+       // Bring back the tables if they were out before
+       //if(prev_table_status)get_canvas_view()->show_tables();
+
+       // Refresh the work area
+       get_work_area()->queue_draw();
+
+       get_canvas_view()->queue_rebuild_ducks();
+
+       App::toolbox->refresh();
+}
+
+Smach::event_result
+StateStar_Context::event_stop_handler(const Smach::event& /*x*/)
+{
+       //throw Smach::egress_exception();
+       throw &state_normal;
+       return Smach::RESULT_OK;
+}
+
+Smach::event_result
+StateStar_Context::event_refresh_handler(const Smach::event& /*x*/)
+{
+       refresh_ducks();
+       return Smach::RESULT_ACCEPT;
+}
+
+void
+StateStar_Context::make_star(const Point& _p1, const Point& _p2)
+{
+       synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("New Star"));
+       synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
+
+       Layer::Handle layer;
+
+       Canvas::Handle canvas;
+       int depth(0);
+
+       // we are temporarily using the layer to hold something
+       layer=get_canvas_view()->get_selection_manager()->get_selected_layer();
+       if(layer)
+       {
+               depth=layer->get_depth();
+               canvas=layer->get_canvas();
+       }
+
+       synfigapp::SelectionManager::LayerList layer_selection;
+       if (!getenv("SYNFIG_TOOLS_CLEAR_SELECTION"))
+               layer_selection = get_canvas_view()->get_selection_manager()->get_selected_layers();
+
+       const synfig::TransformStack& transform(get_canvas_view()->get_curr_transform_stack());
+       const Point p1(transform.unperform(_p1));
+       const Point p2(transform.unperform(_p2));
+
+       Real radius_ratio(get_radius_ratio());
+       Real radius1((p2-p1).mag());
+       Real radius2(radius1 * radius_ratio);
+       int points = get_number_of_points();
+       Real inner_tangent = get_inner_tangent() * radius1;
+       Real outer_tangent = get_outer_tangent() * radius2;
+       Real inner_width = get_inner_width();
+       Real outer_width = get_outer_width();
+       Angle::deg offset(get_angle_offset());
+       bool regular(get_regular_polygon());
+       Angle::deg angle(360.0/points);
+       Vector origin;
+       Real x, y;
+
+       if (get_layer_origins_at_center_flag())
+       {
+               x = y = 0;
+               origin = p1;
+       }
+       else
+       {
+               x = p1[0];
+               y = p1[1];
+       }
+
+       std::vector<BLinePoint> new_list;
+       int point(0);
+       for (int i = 0; i < points; i++)
+       {
+               new_list.push_back(*(new BLinePoint));
+               new_list[point].set_width(outer_width);
+               new_list[point].set_vertex(Point(radius1*Angle::cos(angle*i + offset).get() + x,
+                                                                                radius1*Angle::sin(angle*i + offset).get() + y));
+               new_list[point++].set_tangent(Point(-Angle::sin(angle*i + offset).get(),
+                                                                                        Angle::cos(angle*i + offset).get()) * outer_tangent);
+
+               if (!regular)
+               {
+                       new_list.push_back(*(new BLinePoint));
+                       new_list[point].set_width(inner_width);
+                       new_list[point].set_vertex(Point(radius2*Angle::cos(angle*i + angle/2 + offset).get() + x,
+                                                                                        radius2*Angle::sin(angle*i + angle/2 + offset).get() + y));
+                       new_list[point++].set_tangent(Point(-Angle::sin(angle*i + angle/2 + offset).get(),
+                                                                                                Angle::cos(angle*i + angle/2 + offset).get()) * inner_tangent);
+               }
+       }
+
+       ValueNode_BLine::Handle value_node_bline(ValueNode_BLine::create(new_list));
+       assert(value_node_bline);
+
+       ValueNode_Const::Handle value_node_origin(ValueNode_Const::create(origin));
+       assert(value_node_origin);
+
+       // Set the looping flag
+       value_node_bline->set_loop(true);
+
+       if(!canvas)
+               canvas=get_canvas_view()->get_canvas();
+
+       value_node_bline->set_member_canvas(canvas);
+
+       // count how many layers we're going to be creating
+       int layers_to_create = this->layers_to_create();
+
+       ///////////////////////////////////////////////////////////////////////////
+       //   S T A R
+       ///////////////////////////////////////////////////////////////////////////
+
+       if (get_layer_star_flag())
+       {
+               layer=get_canvas_interface()->add_layer_to("star",canvas,depth);
+               if (!layer)
+               {
+                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
+                       group.cancel();
+                       return;
+               }
+               layer_selection.push_back(layer);
+
+               layer->set_param("radius1",radius1);
+               get_canvas_interface()->signal_layer_param_changed()(layer,"radius1");
+
+               layer->set_param("radius2",radius2);
+               get_canvas_interface()->signal_layer_param_changed()(layer,"radius2");
+
+               layer->set_param("angle",offset);
+               get_canvas_interface()->signal_layer_param_changed()(layer,"angle");
+
+               layer->set_param("points",points);
+               get_canvas_interface()->signal_layer_param_changed()(layer,"points");
+
+               layer->set_param("regular_polygon",regular);
+               get_canvas_interface()->signal_layer_param_changed()(layer,"regular_polygon");
+
+               layer->set_param("feather",get_feather());
+               get_canvas_interface()->signal_layer_param_changed()(layer,"feather");
+
+               layer->set_param("invert",get_invert());
+               get_canvas_interface()->signal_layer_param_changed()(layer,"invert");
+
+               layer->set_description(get_id());
+               get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
+
+               // only link the star's origin parameter if the option is selected, we're putting bline
+               // origins at their centers, and we're creating more than one layer
+               if (get_layer_link_origins_flag() && get_layer_origins_at_center_flag() && layers_to_create > 1)
+               {
+                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
+                       assert(action);
+
+                       action->set_param("canvas",get_canvas());
+                       action->set_param("canvas_interface",get_canvas_interface());
+                       action->set_param("layer",layer);
+                       if(!action->set_param("param",String("origin")))
+                               synfig::error("LayerParamConnect didn't like \"param\"");
+                       if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
+                               synfig::error("LayerParamConnect didn't like \"value_node\"");
+
+                       if(!get_canvas_interface()->get_instance()->perform_action(action))
+                       {
+                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create Star layer"));
+                               group.cancel();
+                               throw String(_("Unable to create Star layer"));
+                               return;
+                       }
+               }
+               else
+               {
+                       layer->set_param("origin",p1);
+                       get_canvas_interface()->signal_layer_param_changed()(layer,"origin");
+               }
+       }
+
+       ///////////////////////////////////////////////////////////////////////////
+       //   C U R V E   G R A D I E N T
+       ///////////////////////////////////////////////////////////////////////////
+
+       if(get_layer_curve_gradient_flag())
+       {
+               synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
+
+               Layer::Handle layer(get_canvas_interface()->add_layer_to("curve_gradient",canvas,depth));
+               if (!layer)
+               {
+                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
+                       group.cancel();
+                       return;
+               }
+               layer_selection.push_back(layer);
+               layer->set_description(get_id()+_(" Gradient"));
+               get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
+
+               {
+                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
+                       assert(action);
+
+                       action->set_param("canvas",get_canvas());
+                       action->set_param("canvas_interface",get_canvas_interface());
+                       action->set_param("layer",layer);
+                       if(!action->set_param("param",String("bline")))
+                               synfig::error("LayerParamConnect didn't like \"param\"");
+                       if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
+                               synfig::error("LayerParamConnect didn't like \"value_node\"");
+
+                       if(!get_canvas_interface()->get_instance()->perform_action(action))
+                       {
+                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
+                               group.cancel();
+                               throw String(_("Unable to create Gradient layer"));
+                               return;
+                       }
+               }
+
+               // only link the curve gradient's origin parameter if the option is selected and we're creating more than one layer
+               if (get_layer_link_origins_flag() && layers_to_create > 1)
+               {
+                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
+                       assert(action);
+
+                       action->set_param("canvas",get_canvas());
+                       action->set_param("canvas_interface",get_canvas_interface());
+                       action->set_param("layer",layer);
+                       if(!action->set_param("param",String("origin")))
+                               synfig::error("LayerParamConnect didn't like \"param\"");
+                       if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
+                               synfig::error("LayerParamConnect didn't like \"value_node\"");
+
+                       if(!get_canvas_interface()->get_instance()->perform_action(action))
+                       {
+                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
+                               group.cancel();
+                               throw String(_("Unable to create Gradient layer"));
+                               return;
+                       }
+               }
+               else
+               {
+                       layer->set_param("origin",origin);
+                       get_canvas_interface()->signal_layer_param_changed()(layer,"origin");
+               }
+       }
+
+       ///////////////////////////////////////////////////////////////////////////
+       //   P L A N T
+       ///////////////////////////////////////////////////////////////////////////
+
+       if(get_layer_plant_flag())
+       {
+               synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
+
+               Layer::Handle layer(get_canvas_interface()->add_layer_to("plant",canvas,depth));
+               if (!layer)
+               {
+                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
+                       group.cancel();
+                       return;
+               }
+               layer_selection.push_back(layer);
+               layer->set_description(get_id()+_(" Plant"));
+               get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
+
+               {
+                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
+                       assert(action);
+
+                       action->set_param("canvas",get_canvas());
+                       action->set_param("canvas_interface",get_canvas_interface());
+                       action->set_param("layer",layer);
+                       if(!action->set_param("param",String("bline")))
+                               synfig::error("LayerParamConnect didn't like \"param\"");
+                       if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
+                               synfig::error("LayerParamConnect didn't like \"value_node\"");
+
+                       if(!get_canvas_interface()->get_instance()->perform_action(action))
+                       {
+                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
+                               group.cancel();
+                               throw String(_("Unable to create Plant layer"));
+                               return;
+                       }
+               }
+
+               // only link the plant's origin parameter if the option is selected and we're creating more than one layer
+               if (get_layer_link_origins_flag() && layers_to_create > 1)
+               {
+                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
+                       assert(action);
+
+                       action->set_param("canvas",get_canvas());
+                       action->set_param("canvas_interface",get_canvas_interface());
+                       action->set_param("layer",layer);
+                       if(!action->set_param("param",String("origin")))
+                               synfig::error("LayerParamConnect didn't like \"param\"");
+                       if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
+                               synfig::error("LayerParamConnect didn't like \"value_node\"");
+
+                       if(!get_canvas_interface()->get_instance()->perform_action(action))
+                       {
+                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
+                               group.cancel();
+                               throw String(_("Unable to create Plant layer"));
+                               return;
+                       }
+               }
+               else
+               {
+                       layer->set_param("origin",origin);
+                       get_canvas_interface()->signal_layer_param_changed()(layer,"origin");
+               }
+       }
+
+       ///////////////////////////////////////////////////////////////////////////
+       //   R E G I O N
+       ///////////////////////////////////////////////////////////////////////////
+
+       if(get_layer_region_flag())
+       {
+               synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
+
+               Layer::Handle layer(get_canvas_interface()->add_layer_to("region",canvas,depth));
+               if (!layer)
+               {
+                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
+                       group.cancel();
+                       return;
+               }
+               layer_selection.push_back(layer);
+               layer->set_description(get_id()+_(" Region"));
+               get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
+
+               layer->set_param("feather",get_feather());
+               get_canvas_interface()->signal_layer_param_changed()(layer,"feather");
+
+               layer->set_param("invert",get_invert());
+               get_canvas_interface()->signal_layer_param_changed()(layer,"invert");
+
+               // I don't know if it's safe to reuse the same LayerParamConnect action, so I'm
+               // using 2 separate ones.
+               {
+                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
+                       assert(action);
+
+                       action->set_param("canvas",get_canvas());
+                       action->set_param("canvas_interface",get_canvas_interface());
+                       action->set_param("layer",layer);
+                       if(!action->set_param("param",String("bline")))
+                               synfig::error("LayerParamConnect didn't like \"param\"");
+                       if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
+                               synfig::error("LayerParamConnect didn't like \"value_node\"");
+
+                       if(!get_canvas_interface()->get_instance()->perform_action(action))
+                       {
+                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer"));
+                               group.cancel();
+                               throw String(_("Unable to create Region layer"));
+                               return;
+                       }
+               }
+
+               // only link the region's origin parameter if the option is selected and we're creating more than one layer
+               if (get_layer_link_origins_flag() && layers_to_create > 1)
+               {
+                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
+                       assert(action);
+
+                       action->set_param("canvas",get_canvas());
+                       action->set_param("canvas_interface",get_canvas_interface());
+                       action->set_param("layer",layer);
+                       if(!action->set_param("param",String("origin")))
+                               synfig::error("LayerParamConnect didn't like \"param\"");
+                       if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
+                               synfig::error("LayerParamConnect didn't like \"value_node\"");
+
+                       if(!get_canvas_interface()->get_instance()->perform_action(action))
+                       {
+                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer"));
+                               group.cancel();
+                               throw String(_("Unable to create Region layer"));
+                               return;
+                       }
+               }
+               else
+               {
+                       layer->set_param("origin",origin);
+                       get_canvas_interface()->signal_layer_param_changed()(layer,"origin");
+               }
+       }
+
+       ///////////////////////////////////////////////////////////////////////////
+       //   O U T L I N E
+       ///////////////////////////////////////////////////////////////////////////
+
+       if (get_layer_outline_flag())
+       {
+               Layer::Handle layer(get_canvas_interface()->add_layer_to("outline",canvas,depth));
+               if (!layer)
+               {
+                       get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
+                       group.cancel();
+                       return;
+               }
+               layer_selection.push_back(layer);
+               layer->set_description(get_id()+_(" Outline"));
+               get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
+
+               layer->set_param("feather",get_feather());
+               get_canvas_interface()->signal_layer_param_changed()(layer,"feather");
+
+               layer->set_param("invert",get_invert());
+               get_canvas_interface()->signal_layer_param_changed()(layer,"invert");
+
+               {
+                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
+                       assert(action);
+
+                       action->set_param("canvas",get_canvas());
+                       action->set_param("canvas_interface",get_canvas_interface());
+                       action->set_param("layer",layer);
+                       if(!action->set_param("param",String("bline")))
+                               synfig::error("LayerParamConnect didn't like \"param\"");
+                       if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
+                               synfig::error("LayerParamConnect didn't like \"value_node\"");
+
+                       if(!get_canvas_interface()->get_instance()->perform_action(action))
+                       {
+                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
+                               group.cancel();
+                               throw String(_("Unable to create Outline layer"));
+                               return;
+                       }
+               }
+
+               // only link the outline's origin parameter if the option is selected and we're creating more than one layer
+               if (get_layer_link_origins_flag() && layers_to_create > 1)
+               {
+                       synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
+                       assert(action);
+
+                       action->set_param("canvas",get_canvas());
+                       action->set_param("canvas_interface",get_canvas_interface());
+                       action->set_param("layer",layer);
+                       if(!action->set_param("param",String("origin")))
+                               synfig::error("LayerParamConnect didn't like \"param\"");
+                       if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
+                               synfig::error("LayerParamConnect didn't like \"value_node\"");
+
+                       if(!get_canvas_interface()->get_instance()->perform_action(action))
+                       {
+                               //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
+                               group.cancel();
+                               throw String(_("Unable to create Outline layer"));
+                               return;
+                       }
+               }
+               else
+               {
+                       layer->set_param("origin",origin);
+                       get_canvas_interface()->signal_layer_param_changed()(layer,"origin");
+               }
+       }
+
+       egress_on_selection_change=false;
+       get_canvas_interface()->get_selection_manager()->clear_selected_layers();
+       get_canvas_interface()->get_selection_manager()->set_selected_layers(layer_selection);
+       egress_on_selection_change=true;
+
+       reset();
+       increment_id();
+}
+
+Smach::event_result
+StateStar_Context::event_mouse_click_handler(const Smach::event& x)
+{
+       const EventMouse& event(*reinterpret_cast<const EventMouse*>(&x));
+
+       if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_DOWN && event.button==BUTTON_LEFT)
+       {
+               point_holder=get_work_area()->snap_point_to_grid(event.pos);
+               etl::handle<Duck> duck=new Duck();
+               duck->set_point(point_holder);
+               duck->set_name("p1");
+               duck->set_type(Duck::TYPE_POSITION);
+               duck->set_editable(false);
+               get_work_area()->add_duck(duck);
+
+               point2_duck=new Duck();
+               point2_duck->set_point(Vector(0,0));
+               point2_duck->set_name("radius");
+               point2_duck->set_origin(duck);
+               point2_duck->set_radius(true);
+               point2_duck->set_scalar(-1);
+               point2_duck->set_type(Duck::TYPE_RADIUS);
+               point2_duck->set_hover(true);
+               get_work_area()->add_duck(point2_duck);
+
+               return Smach::RESULT_ACCEPT;
+       }
+
+       if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_DRAG && event.button==BUTTON_LEFT)
+       {
+               if (!point2_duck) return Smach::RESULT_OK;
+               point2_duck->set_point(point_holder-get_work_area()->snap_point_to_grid(event.pos));
+               get_work_area()->queue_draw();
+               return Smach::RESULT_ACCEPT;
+       }
+
+       if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_UP && event.button==BUTTON_LEFT)
+       {
+               Point point(get_work_area()->snap_point_to_grid(event.pos));
+
+               if (App::restrict_radius_ducks)
+               {
+                       if ((point[0] - point_holder[0]) < 0) point[0] = point_holder[0];
+                       if ((point[1] - point_holder[1]) < 0) point[1] = point_holder[1];
+               }
+
+               make_star(point_holder, point);
+               get_work_area()->clear_ducks();
+               return Smach::RESULT_ACCEPT;
+       }
+
+       return Smach::RESULT_OK;
+}
+
+
+void
+StateStar_Context::refresh_ducks()
+{
+       get_work_area()->clear_ducks();
+       get_work_area()->queue_draw();
+}
diff --git a/synfig-studio/src/gui/states/state_star.h b/synfig-studio/src/gui/states/state_star.h
new file mode 100644 (file)
index 0000000..606f77d
--- /dev/null
@@ -0,0 +1,57 @@
+/* === S Y N F I G ========================================================= */
+/*!    \file state_star.h
+**     \brief Star creation state
+**
+**     $Id$
+**
+**     \legal
+**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+**  Copyright (c) 2008 Chris Moore
+**
+**     This package is free software; you can redistribute it and/or
+**     modify it under the terms of the GNU General Public License as
+**     published by the Free Software Foundation; either version 2 of
+**     the License, or (at your option) any later version.
+**
+**     This package is distributed in the hope that it will be useful,
+**     but WITHOUT ANY WARRANTY; without even the implied warranty of
+**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+**     General Public License for more details.
+**     \endlegal
+*/
+/* ========================================================================= */
+
+/* === S T A R T =========================================================== */
+
+#ifndef __SYNFIG_STUDIO_STATE_STAR_H
+#define __SYNFIG_STUDIO_STATE_STAR_H
+
+/* === H E A D E R S ======================================================= */
+
+#include "smach.h"
+
+
+/* === M A C R O S ========================================================= */
+
+/* === T Y P E D E F S ===================================================== */
+
+/* === C L A S S E S & S T R U C T S ======================================= */
+
+namespace studio {
+
+class StateStar_Context;
+
+class StateStar : public Smach::state<StateStar_Context>
+{
+public:
+       StateStar();
+       ~StateStar();
+}; // END of class StateStar
+
+extern StateStar state_star;
+
+}; // END of namespace studio
+
+/* === E N D =============================================================== */
+
+#endif
diff --git a/synfig-studio/src/gui/states/state_stroke.cpp b/synfig-studio/src/gui/states/state_stroke.cpp
new file mode 100644 (file)
index 0000000..a0f7eca
--- /dev/null
@@ -0,0 +1,198 @@
+/* === S Y N F I G ========================================================= */
+/*!    \file state_stroke.cpp
+**     \brief Template File
+**
+**     $Id$
+**
+**     \legal
+**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+**     Copyright (c) 2007 Chris Moore
+**
+**     This package is free software; you can redistribute it and/or
+**     modify it under the terms of the GNU General Public License as
+**     published by the Free Software Foundation; either version 2 of
+**     the License, or (at your option) any later version.
+**
+**     This package is distributed in the hope that it will be useful,
+**     but WITHOUT ANY WARRANTY; without even the implied warranty of
+**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+**     General Public License for more details.
+**     \endlegal
+*/
+/* ========================================================================= */
+
+/* === H E A D E R S ======================================================= */
+
+#ifdef USING_PCH
+#      include "pch.h"
+#else
+#ifdef HAVE_CONFIG_H
+#      include <config.h>
+#endif
+
+#include <gtkmm/dialog.h>
+#include <gtkmm/entry.h>
+
+#include <synfig/valuenode_dynamiclist.h>
+
+#include "state_stroke.h"
+#include "canvasview.h"
+#include "workarea.h"
+#include "app.h"
+#include <synfig/valuenode_bline.h>
+#include <ETL/hermite>
+#include <ETL/calculus>
+#include <utility>
+#include "event_mouse.h"
+#include "event_layerclick.h"
+#include "toolbox.h"
+#include <synfigapp/main.h>
+
+#include "general.h"
+
+#endif
+
+/* === U S I N G =========================================================== */
+
+using namespace std;
+using namespace etl;
+using namespace synfig;
+using namespace studio;
+
+/* === M A C R O S ========================================================= */
+
+/* === G L O B A L S ======================================================= */
+
+StateStroke studio::state_stroke;
+
+/* === C L A S S E S & S T R U C T S ======================================= */
+
+class studio::StateStroke_Context : public sigc::trackable
+{
+       etl::handle<CanvasView> canvas_view_;
+       CanvasView::IsWorking is_working;
+
+       Duckmatic::Push duckmatic_push;
+
+       etl::smart_ptr<std::list<synfig::Point> > stroke_data;
+
+       etl::smart_ptr<std::list<synfig::Real> > width_data;
+
+       Gdk::ModifierType modifier;
+
+public:
+
+       Smach::event_result event_stop_handler(const Smach::event& x);
+
+       Smach::event_result event_refresh_handler(const Smach::event& x);
+
+       Smach::event_result event_mouse_up_handler(const Smach::event& x);
+
+       Smach::event_result event_mouse_draw_handler(const Smach::event& x);
+       Smach::event_result event_refresh_tool_options(const Smach::event& x);
+
+       StateStroke_Context(CanvasView* canvas_view);
+
+       ~StateStroke_Context();
+
+       const etl::handle<CanvasView>& get_canvas_view()const{return canvas_view_;}
+       etl::handle<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view_->canvas_interface();}
+       synfig::Canvas::Handle get_canvas()const{return canvas_view_->get_canvas();}
+       WorkArea * get_work_area()const{return canvas_view_->get_work_area();}
+
+};     // END of class StateStroke_Context
+
+
+/* === M E T H O D S ======================================================= */
+
+StateStroke::StateStroke():
+       Smach::state<StateStroke_Context>("stroke")
+{
+       insert(event_def(EVENT_STOP,&StateStroke_Context::event_stop_handler));
+       insert(event_def(EVENT_REFRESH,&StateStroke_Context::event_refresh_handler));
+//     insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateStroke_Context::event_mouse_down_handler));
+       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_UP,&StateStroke_Context::event_mouse_up_handler));
+       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DRAG,&StateStroke_Context::event_mouse_draw_handler));
+       insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateStroke_Context::event_refresh_tool_options));
+}
+
+StateStroke::~StateStroke()
+{
+}
+
+
+StateStroke_Context::StateStroke_Context(CanvasView* canvas_view):
+       canvas_view_(canvas_view),
+       is_working(*canvas_view),
+       duckmatic_push(get_work_area())
+{
+       width_data.spawn();
+       stroke_data.spawn();
+
+       get_work_area()->add_stroke(stroke_data, synfigapp::Main::get_outline_color());
+}
+
+StateStroke_Context::~StateStroke_Context()
+{
+       duckmatic_push.restore();
+
+       App::toolbox->refresh();
+
+       // Send the stroke data to whatever previously called this state.
+       if(stroke_data->size()>=2)
+               get_canvas_view()->get_smach().process_event(EventStroke(stroke_data,width_data,modifier));
+}
+
+Smach::event_result
+StateStroke_Context::event_refresh_tool_options(const Smach::event& /*x*/)
+{
+       return Smach::RESULT_ACCEPT;
+}
+
+Smach::event_result
+StateStroke_Context::event_stop_handler(const Smach::event& /*x*/)
+{
+       throw Smach::pop_exception();
+}
+
+Smach::event_result
+StateStroke_Context::event_refresh_handler(const Smach::event& /*x*/)
+{
+       return Smach::RESULT_ACCEPT;
+}
+
+Smach::event_result
+StateStroke_Context::event_mouse_up_handler(const Smach::event& x)
+{
+       const EventMouse& event(*reinterpret_cast<const EventMouse*>(&x));
+       switch(event.button)
+       {
+       case BUTTON_LEFT:
+               {
+                       modifier=event.modifier;
+                       throw Smach::pop_exception();
+               }
+
+       default:
+               return Smach::RESULT_OK;
+       }
+}
+
+Smach::event_result
+StateStroke_Context::event_mouse_draw_handler(const Smach::event& x)
+{
+       const EventMouse& event(*reinterpret_cast<const EventMouse*>(&x));
+       switch(event.button)
+       {
+       case BUTTON_LEFT:
+               {
+                       stroke_data->push_back(event.pos);
+                       width_data->push_back(event.pressure);
+                       get_work_area()->queue_draw();
+                       return Smach::RESULT_ACCEPT;
+               }
+
+       default:
+               return Smach::RESULT_OK;
+       }
+}
diff --git a/synfig-studio/src/gui/states/state_stroke.h b/synfig-studio/src/gui/states/state_stroke.h
new file mode 100644 (file)
index 0000000..0beade5
--- /dev/null
@@ -0,0 +1,80 @@
+/* === S Y N F I G ========================================================= */
+/*!    \file state_stroke.h
+**     \brief Template Header
+**
+**     $Id$
+**
+**     \legal
+**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+**
+**     This package is free software; you can redistribute it and/or
+**     modify it under the terms of the GNU General Public License as
+**     published by the Free Software Foundation; either version 2 of
+**     the License, or (at your option) any later version.
+**
+**     This package is distributed in the hope that it will be useful,
+**     but WITHOUT ANY WARRANTY; without even the implied warranty of
+**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+**     General Public License for more details.
+**     \endlegal
+*/
+/* ========================================================================= */
+
+/* === S T A R T =========================================================== */
+
+#ifndef __SYNFIG_STUDIO_STATE_STROKE_H
+#define __SYNFIG_STUDIO_STATE_STROKE_H
+
+/* === H E A D E R S ======================================================= */
+
+#include "canvasview.h"
+#include "workarea.h"
+#include <sigc++/object.h>
+#include "duckmatic.h"
+#include <synfig/blinepoint.h>
+#include <list>
+#include <ETL/smart_ptr>
+#include "eventkey.h"
+#include <gdkmm/types.h>
+
+/* === M A C R O S ========================================================= */
+
+/* === T Y P E D E F S ===================================================== */
+
+/* === C L A S S E S & S T R U C T S ======================================= */
+
+namespace studio {
+
+class StateStroke_Context;
+
+class StateStroke : public Smach::state<StateStroke_Context>
+{
+public:
+       StateStroke();
+       ~StateStroke();
+}; // END of class StateStroke
+
+extern StateStroke state_stroke;
+
+struct EventStroke : public Smach::event
+{
+       etl::smart_ptr<std::list<synfig::Point> > stroke_data;
+       etl::smart_ptr<std::list<synfig::Real> > width_data;
+       Gdk::ModifierType modifier;
+
+       EventStroke(etl::smart_ptr<std::list<synfig::Point> > stroke_data,
+                       etl::smart_ptr<std::list<synfig::Real> > width_data,
+                       Gdk::ModifierType modifier=Gdk::ModifierType(0)
+       ):
+               Smach::event(EVENT_WORKAREA_STROKE),
+               stroke_data(stroke_data),
+               width_data(width_data),
+               modifier(modifier)
+       { }
+}; // END of EventStroke
+
+}; // END of namespace studio
+
+/* === E N D =============================================================== */
+
+#endif
diff --git a/synfig-studio/src/gui/states/state_text.cpp b/synfig-studio/src/gui/states/state_text.cpp
new file mode 100644 (file)
index 0000000..733f907
--- /dev/null
@@ -0,0 +1,460 @@
+/* === S Y N F I G ========================================================= */
+/*!    \file state_text.cpp
+**     \brief Template File
+**
+**     $Id$
+**
+**     \legal
+**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+**  Copyright (c) 2008 Chris Moore
+**
+**     This package is free software; you can redistribute it and/or
+**     modify it under the terms of the GNU General Public License as
+**     published by the Free Software Foundation; either version 2 of
+**     the License, or (at your option) any later version.
+**
+**     This package is distributed in the hope that it will be useful,
+**     but WITHOUT ANY WARRANTY; without even the implied warranty of
+**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+**     General Public License for more details.
+**     \endlegal
+*/
+/* ========================================================================= */
+
+/* === H E A D E R S ======================================================= */
+
+#ifdef USING_PCH
+#      include "pch.h"
+#else
+#ifdef HAVE_CONFIG_H
+#      include <config.h>
+#endif
+
+#include <gtkmm/dialog.h>
+#include <gtkmm/entry.h>
+
+#include "state_text.h"
+#include "state_normal.h"
+#include "canvasview.h"
+#include "workarea.h"
+#include "app.h"
+
+#include <synfigapp/action.h>
+#include "event_mouse.h"
+#include "event_layerclick.h"
+#include "toolbox.h"
+#include "dialog_tooloptions.h"
+#include <gtkmm/optionmenu.h>
+#include "duck.h"
+#include "widgets/widget_enum.h"
+#include <synfigapp/main.h>
+
+#include "general.h"
+
+#endif
+
+/* === U S I N G =========================================================== */
+
+using namespace std;
+using namespace etl;
+using namespace synfig;
+using namespace studio;
+
+/* === M A C R O S ========================================================= */
+
+/* === G L O B A L S ======================================================= */
+
+StateText studio::state_text;
+
+/* === C L A S S E S & S T R U C T S ======================================= */
+
+class studio::StateText_Context
+{
+       etl::handle<CanvasView> canvas_view;
+       CanvasView::IsWorking is_working;
+
+       Duckmatic::Push duckmatic_push;
+
+       void refresh_ducks();
+
+       bool prev_workarea_layer_status_;
+
+       //Toolbox settings
+       synfigapp::Settings& settings;
+
+       //Toolbox display
+       Gtk::Table options_table;
+
+       Gtk::Entry              entry_id; //what to name the layer
+       Gtk::Entry              entry_family;
+       Widget_Vector   widget_size;
+       Widget_Vector   widget_orientation;
+       Gtk::CheckButton checkbutton_paragraph;
+
+public:
+       synfig::String get_id()const { return entry_id.get_text(); }
+       void set_id(const synfig::String& x) { return entry_id.set_text(x); }
+
+       bool get_paragraph_flag()const { return checkbutton_paragraph.get_active(); }
+       void set_paragraph_flag(bool x) { return checkbutton_paragraph.set_active(x); }
+
+       Vector get_size() { return widget_size.get_value(); }
+       void set_size(Vector s) { return widget_size.set_value(s); }
+
+       Vector get_orientation() { return widget_orientation.get_value(); }
+       void set_orientation(Vector s) { return widget_orientation.set_value(s); }
+
+       String get_family()const { return entry_family.get_text(); }
+       void set_family(String s) { return entry_family.set_text(s); }
+
+       void refresh_tool_options(); //to refresh the toolbox
+
+       //events
+       Smach::event_result event_stop_handler(const Smach::event& x);
+       Smach::event_result event_refresh_handler(const Smach::event& x);
+       Smach::event_result event_mouse_click_handler(const Smach::event& x);
+       Smach::event_result event_refresh_tool_options(const Smach::event& x);
+       Smach::event_result event_workarea_mouse_button_down_handler(const Smach::event& x);
+
+       //constructor destructor
+       StateText_Context(CanvasView *canvas_view);
+       ~StateText_Context();
+
+       const etl::handle<CanvasView>& get_canvas_view()const{return canvas_view;}
+       etl::handle<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view->canvas_interface();}
+       WorkArea * get_work_area()const{return canvas_view->get_work_area();}
+
+       //Modifying settings etc.
+       void load_settings();
+       void save_settings();
+       void reset();
+       void increment_id();
+       bool egress_on_selection_change;
+       Smach::event_result event_layer_selection_changed_handler(const Smach::event& /*x*/)
+       {
+               if(egress_on_selection_change)
+                       throw &state_normal; //throw Smach::egress_exception();
+               return Smach::RESULT_OK;
+       }
+
+       void make_text(const Point& point);
+
+}; // END of class StateText_Context
+
+/* === P R O C E D U R E S ================================================= */
+
+/* === M E T H O D S ======================================================= */
+
+StateText::StateText():
+       Smach::state<StateText_Context>("text")
+{
+       insert(event_def(EVENT_LAYER_SELECTION_CHANGED,&StateText_Context::event_layer_selection_changed_handler));
+       insert(event_def(EVENT_STOP,&StateText_Context::event_stop_handler));
+       insert(event_def(EVENT_REFRESH,&StateText_Context::event_refresh_handler));
+       insert(event_def(EVENT_REFRESH_DUCKS,&StateText_Context::event_refresh_handler));
+       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateText_Context::event_workarea_mouse_button_down_handler));
+       insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateText_Context::event_refresh_tool_options));
+}
+
+StateText::~StateText()
+{
+}
+
+void
+StateText_Context::load_settings()
+{
+       String value;
+       Vector v;
+
+       //parse the arguments yargh!
+       if(settings.get_value("text.id",value))
+               set_id(value);
+       else
+               set_id("Text");
+
+       if(settings.get_value("text.paragraph",value) && value=="1")
+               set_paragraph_flag(true);
+       else
+               set_paragraph_flag(false);
+
+       if(settings.get_value("text.size_x",value))
+               v[0] = atof(value.c_str());
+       else
+               v[0] = 0.25;
+       if(settings.get_value("text.size_y",value))
+               v[1] = atof(value.c_str());
+       else
+               v[1] = 0.25;
+       set_size(v);
+
+       if(settings.get_value("text.orient_x",value))
+               v[0] = atof(value.c_str());
+       else
+               v[0] = 0.5;
+       if(settings.get_value("text.orient_y",value))
+               v[1] = atof(value.c_str());
+       else
+               v[1] = 0.5;
+       set_orientation(v);
+
+       if(settings.get_value("text.family",value))
+               set_family(value);
+       else
+               set_family("Sans Serif");
+}
+
+void
+StateText_Context::save_settings()
+{
+       settings.set_value("text.id",get_id());
+       settings.set_value("text.paragraph",get_paragraph_flag()?"1":"0");
+       settings.set_value("text.size_x",strprintf("%f",(float)get_size()[0]));
+       settings.set_value("text.size_y",strprintf("%f",(float)get_size()[1]));
+       settings.set_value("text.orient_x",strprintf("%f",(float)get_orientation()[0]));
+       settings.set_value("text.orient_y",strprintf("%f",(float)get_orientation()[1]));
+       settings.set_value("text.family",get_family());
+}
+
+void
+StateText_Context::reset()
+{
+       refresh_ducks();
+}
+
+void
+StateText_Context::increment_id()
+{
+       String id(get_id());
+       int number=1;
+       int digits=0;
+
+       if(id.empty())
+               id="Text";
+
+       // If there is a number
+       // already at the end of the
+       // id, then remove it.
+       if(id[id.size()-1]<='9' && id[id.size()-1]>='0')
+       {
+               // figure out how many digits it is
+               for (digits = 0;
+                        (int)id.size()-1 >= digits && id[id.size()-1-digits] <= '9' && id[id.size()-1-digits] >= '0';
+                        digits++)
+                       ;
+
+               String str_number;
+               str_number=String(id,id.size()-digits,id.size());
+               id=String(id,0,id.size()-digits);
+
+               number=atoi(str_number.c_str());
+       }
+       else
+       {
+               number=1;
+               digits=3;
+       }
+
+       number++;
+
+       // Add the number back onto the id
+       {
+               const String format(strprintf("%%0%dd",digits));
+               id+=strprintf(format.c_str(),number);
+       }
+
+       // Set the ID
+       set_id(id);
+}
+
+StateText_Context::StateText_Context(CanvasView *canvas_view):
+       canvas_view(canvas_view),
+       is_working(*canvas_view),
+       duckmatic_push(get_work_area()),
+       prev_workarea_layer_status_(get_work_area()->get_allow_layer_clicks()),
+       settings(synfigapp::Main::get_selected_input_device()->settings()),
+       entry_id(),
+       checkbutton_paragraph(_("Multiline Editor"))
+{
+       egress_on_selection_change=true;
+
+       widget_size.set_digits(2);
+       widget_size.set_canvas(canvas_view->get_canvas());
+
+       widget_orientation.set_digits(2);
+
+       options_table.attach(*manage(new Gtk::Label(_("Text Tool"))),           0, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(entry_id,                                                                          0, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(checkbutton_paragraph,                                                     0, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(*manage(new Gtk::Label(_("Size:"))),                       0, 1, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(widget_size,                                                                       1, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(*manage(new Gtk::Label(_("Orientation:"))),        0, 1, 4, 5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(widget_orientation,                                                        1, 2, 4, 5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(*manage(new Gtk::Label(_("Family:"))),                     0, 1, 5, 6, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(entry_family,                                                                      1, 2, 5, 6, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+
+       load_settings();
+
+       options_table.show_all();
+
+       refresh_tool_options();
+       App::dialog_tool_options->present();
+
+       // Turn off layer clicking
+       get_work_area()->set_allow_layer_clicks(false);
+
+       // clear out the ducks
+       get_work_area()->clear_ducks();
+
+       // Refresh the work area
+       get_work_area()->queue_draw();
+
+       // Hide the tables if they are showing
+       //prev_table_status=get_canvas_view()->tables_are_visible();
+       //if(prev_table_status)get_canvas_view()->hide_tables();
+
+       // Disable the time bar
+       //get_canvas_view()->set_sensitive_timebar(false);
+
+       // Connect a signal
+       //get_work_area()->signal_user_click().connect(sigc::mem_fun(*this,&studio::StateText_Context::on_user_click));
+       get_work_area()->set_cursor(Gdk::XTERM);
+
+       App::toolbox->refresh();
+}
+
+void
+StateText_Context::refresh_tool_options()
+{
+       App::dialog_tool_options->clear();
+       App::dialog_tool_options->set_widget(options_table);
+       App::dialog_tool_options->set_local_name(_("Text Tool"));
+       App::dialog_tool_options->set_name("text");
+}
+
+Smach::event_result
+StateText_Context::event_refresh_tool_options(const Smach::event& /*x*/)
+{
+       refresh_tool_options();
+       return Smach::RESULT_ACCEPT;
+}
+
+StateText_Context::~StateText_Context()
+{
+       save_settings();
+
+       // Restore layer clicking
+       get_work_area()->set_allow_layer_clicks(prev_workarea_layer_status_);
+       get_work_area()->reset_cursor();
+
+       App::dialog_tool_options->clear();
+
+       get_work_area()->queue_draw();
+
+       get_canvas_view()->queue_rebuild_ducks();
+
+       App::toolbox->refresh();
+}
+
+Smach::event_result
+StateText_Context::event_stop_handler(const Smach::event& /*x*/)
+{
+       //throw Smach::egress_exception();
+       throw &state_normal;
+       return Smach::RESULT_OK;
+}
+
+Smach::event_result
+StateText_Context::event_refresh_handler(const Smach::event& /*x*/)
+{
+       refresh_ducks();
+       return Smach::RESULT_ACCEPT;
+}
+
+void
+StateText_Context::make_text(const Point& _point)
+{
+       synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("New Text"));
+       synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
+
+       Layer::Handle layer;
+
+       Canvas::Handle canvas(get_canvas_view()->get_canvas());
+       int depth(0);
+
+       // we are temporarily using the layer to hold something
+       layer=get_canvas_view()->get_selection_manager()->get_selected_layer();
+       if(layer)
+       {
+               depth=layer->get_depth();
+               canvas=layer->get_canvas();
+       }
+
+       synfigapp::SelectionManager::LayerList layer_selection;
+       if (!getenv("SYNFIG_TOOLS_CLEAR_SELECTION"))
+               layer_selection = get_canvas_view()->get_selection_manager()->get_selected_layers();
+
+       const synfig::TransformStack& transform(get_canvas_view()->get_curr_transform_stack());
+       const Point point(transform.unperform(_point));
+
+       String text;
+       if (get_paragraph_flag())
+               App::dialog_paragraph(_("Text Paragraph"), _("Enter text here:"), text);
+       else
+               App::dialog_entry(_("Text Entry"), _("Enter text here:"), text);
+
+       layer=get_canvas_interface()->add_layer_to("text",canvas,depth);
+       if (!layer)
+       {
+               get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
+               group.cancel();
+               return;
+       }
+       layer_selection.push_back(layer);
+
+       layer->set_param("origin",point);
+       get_canvas_interface()->signal_layer_param_changed()(layer,"origin");
+
+       layer->set_param("text",text);
+       get_canvas_interface()->signal_layer_param_changed()(layer,"text");
+
+       layer->set_param("size",get_size());
+       get_canvas_interface()->signal_layer_param_changed()(layer,"size");
+
+       layer->set_param("orient",get_orientation());
+       get_canvas_interface()->signal_layer_param_changed()(layer,"orient");
+
+       layer->set_param("family",get_family());
+       get_canvas_interface()->signal_layer_param_changed()(layer,"family");
+
+       layer->set_description(get_id());
+       get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
+
+       egress_on_selection_change=false;
+       get_canvas_interface()->get_selection_manager()->clear_selected_layers();
+       get_canvas_interface()->get_selection_manager()->set_selected_layers(layer_selection);
+       egress_on_selection_change=true;
+
+       reset();
+       increment_id();
+}
+
+Smach::event_result
+StateText_Context::event_workarea_mouse_button_down_handler(const Smach::event& x)
+{
+       const EventMouse& event(*reinterpret_cast<const EventMouse*>(&x));
+       if(event.button==BUTTON_LEFT)
+       {
+               make_text(get_work_area()->snap_point_to_grid(event.pos));
+
+               get_work_area()->clear_ducks();
+               return Smach::RESULT_ACCEPT;
+       }
+       return Smach::RESULT_OK;
+}
+
+void
+StateText_Context::refresh_ducks()
+{
+       get_work_area()->clear_ducks();
+       get_work_area()->queue_draw();
+}
diff --git a/synfig-studio/src/gui/states/state_text.h b/synfig-studio/src/gui/states/state_text.h
new file mode 100644 (file)
index 0000000..4b05db5
--- /dev/null
@@ -0,0 +1,57 @@
+/* === S Y N F I G ========================================================= */
+/*!    \file state_text.h
+**     \brief Template Header
+**
+**     $Id$
+**
+**     \legal
+**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+**  Copyright (c) 2008 Chris Moore
+**
+**     This package is free software; you can redistribute it and/or
+**     modify it under the terms of the GNU General Public License as
+**     published by the Free Software Foundation; either version 2 of
+**     the License, or (at your option) any later version.
+**
+**     This package is distributed in the hope that it will be useful,
+**     but WITHOUT ANY WARRANTY; without even the implied warranty of
+**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+**     General Public License for more details.
+**     \endlegal
+*/
+/* ========================================================================= */
+
+/* === S T A R T =========================================================== */
+
+#ifndef __SYNFIG_STATE_TEXT_H
+#define __SYNFIG_STATE_TEXT_H
+
+/* === H E A D E R S ======================================================= */
+
+#include "smach.h"
+
+
+/* === M A C R O S ========================================================= */
+
+/* === T Y P E D E F S ===================================================== */
+
+/* === C L A S S E S & S T R U C T S ======================================= */
+
+namespace studio {
+
+class StateText_Context;
+
+class StateText : public Smach::state<StateText_Context>
+{
+public:
+       StateText();
+       ~StateText();
+}; // END of class StateText
+
+extern StateText state_text;
+
+}; // END of namespace studio
+
+/* === E N D =============================================================== */
+
+#endif
diff --git a/synfig-studio/src/gui/states/state_width.cpp b/synfig-studio/src/gui/states/state_width.cpp
new file mode 100644 (file)
index 0000000..8c74daa
--- /dev/null
@@ -0,0 +1,606 @@
+/* === S Y N F I G ========================================================= */
+/*!    \file state_width.cpp
+**     \brief Template File
+**
+**     $Id$
+**
+**     \legal
+**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+**  Copyright (c) 2008 Chris Moore
+**
+**     This package is free software; you can redistribute it and/or
+**     modify it under the terms of the GNU General Public License as
+**     published by the Free Software Foundation; either version 2 of
+**     the License, or (at your option) any later version.
+**
+**     This package is distributed in the hope that it will be useful,
+**     but WITHOUT ANY WARRANTY; without even the implied warranty of
+**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+**     General Public License for more details.
+**     \endlegal
+*/
+/* ========================================================================= */
+
+/* === H E A D E R S ======================================================= */
+
+#ifdef USING_PCH
+#      include "pch.h"
+#else
+#ifdef HAVE_CONFIG_H
+#      include <config.h>
+#endif
+
+#include <gtkmm/dialog.h>
+#include <gtkmm/entry.h>
+
+#include <ETL/bezier>
+
+#include <synfig/valuenode_dynamiclist.h>
+#include <synfigapp/action_system.h>
+
+#include "state_width.h"
+#include "state_normal.h"
+#include "canvasview.h"
+#include "workarea.h"
+#include "app.h"
+
+#include <synfigapp/action.h>
+#include "event_mouse.h"
+#include "event_layerclick.h"
+#include "toolbox.h"
+#include "dialog_tooloptions.h"
+#include <gtkmm/optionmenu.h>
+#include "duck.h"
+
+//#include <synfigapp/value_desc.h>
+#include <synfigapp/main.h>
+
+#include <ETL/clock>
+
+#include "general.h"
+
+#endif
+
+/* === U S I N G =========================================================== */
+
+using namespace std;
+using namespace etl;
+using namespace synfig;
+using namespace synfigapp;
+using namespace studio;
+
+/* === M A C R O S ========================================================= */
+
+/* === G L O B A L S ======================================================= */
+
+StateWidth studio::state_width;
+
+/* === C L A S S E S & S T R U C T S ======================================= */
+
+class studio::StateWidth_Context : public sigc::trackable
+{
+       etl::handle<CanvasView> canvas_view_;
+       CanvasView::IsWorking is_working;
+
+       //Point mouse_pos;
+
+       handle<Duck> center;
+       handle<Duck> radius;
+       handle<Duck> closestpoint;
+
+       map<handle<Duck>,Real>  changetable;
+
+       etl::clock      clocktime;
+       Real            lastt;
+
+       bool added;
+
+       void refresh_ducks();
+
+       bool prev_workarea_layer_clicking;
+       bool prev_workarea_duck_clicking;
+       Duckmatic::Type old_duckmask;
+
+       //Toolbox settings
+       synfigapp::Settings& settings;
+
+       //Toolbox display
+       Gtk::Table options_table;
+
+       Gtk::Adjustment adj_delta;
+       Gtk::SpinButton spin_delta;
+
+       Gtk::Adjustment adj_radius;
+       Gtk::SpinButton spin_radius;
+
+       Gtk::CheckButton check_relative;
+
+       void AdjustWidth(handle<Duckmatic::Bezier> c, float t, Real mult, bool invert);
+
+public:
+
+       Real get_delta()const { return adj_delta.get_value(); }
+       void set_delta(Real f) { adj_delta.set_value(f); }
+
+       Real get_radius()const { return adj_radius.get_value(); }
+       void set_radius(Real f) { adj_radius.set_value(f); }
+
+       bool get_relative() const { return check_relative.get_active(); }
+       void set_relative(bool r) { check_relative.set_active(r); }
+
+       void refresh_tool_options(); //to refresh the toolbox
+
+       //events
+       Smach::event_result event_stop_handler(const Smach::event& x);
+       Smach::event_result event_refresh_handler(const Smach::event& x);
+       Smach::event_result event_mouse_handler(const Smach::event& x);
+       Smach::event_result event_refresh_tool_options(const Smach::event& x);
+
+       //constructor destructor
+       StateWidth_Context(CanvasView* canvas_view);
+       ~StateWidth_Context();
+
+       //Canvas interaction
+       const etl::handle<CanvasView>& get_canvas_view()const{return canvas_view_;}
+       etl::handle<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view_->canvas_interface();}
+       synfig::Canvas::Handle get_canvas()const{return canvas_view_->get_canvas();}
+       WorkArea * get_work_area()const{return canvas_view_->get_work_area();}
+
+       //Modifying settings etc.
+       void load_settings();
+       void save_settings();
+       void reset();
+
+};     // END of class StateWidth_Context
+
+/* === M E T H O D S ======================================================= */
+
+StateWidth::StateWidth():
+       Smach::state<StateWidth_Context>("width")
+{
+       insert(event_def(EVENT_STOP,&StateWidth_Context::event_stop_handler));
+       insert(event_def(EVENT_REFRESH,&StateWidth_Context::event_refresh_handler));
+       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateWidth_Context::event_mouse_handler));
+       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DRAG,&StateWidth_Context::event_mouse_handler));
+       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_UP,&StateWidth_Context::event_mouse_handler));
+       insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateWidth_Context::event_refresh_tool_options));
+}
+
+StateWidth::~StateWidth()
+{
+}
+
+void
+StateWidth_Context::load_settings()
+{
+       String value;
+
+       //parse the arguments yargh!
+       if(settings.get_value("width.delta",value))
+               set_delta(atof(value.c_str()));
+       else
+               set_delta(6);
+
+       if(settings.get_value("width.radius",value))
+               set_radius(atof(value.c_str()));
+       else
+               set_radius(15);
+
+       //defaults to false
+       if(settings.get_value("width.relative",value) && value == "1")
+               set_relative(true);
+       else
+               set_relative(false);
+}
+
+void
+StateWidth_Context::save_settings()
+{
+       settings.set_value("width.delta",strprintf("%f",get_delta()));
+       settings.set_value("width.radius",strprintf("%f",get_radius()));
+       settings.set_value("width.relative",get_relative()?"1":"0");
+}
+
+void
+StateWidth_Context::reset()
+{
+       refresh_ducks();
+}
+
+StateWidth_Context::StateWidth_Context(CanvasView* canvas_view):
+       canvas_view_(canvas_view),
+       is_working(*canvas_view),
+       prev_workarea_layer_clicking(get_work_area()->get_allow_layer_clicks()),
+       prev_workarea_duck_clicking(get_work_area()->get_allow_duck_clicks()),
+       old_duckmask(get_work_area()->get_type_mask()),
+
+       settings(synfigapp::Main::get_selected_input_device()->settings()),
+
+       adj_delta(6,0,20,0.01,0.1),
+       spin_delta(adj_delta,0.01,3),
+
+       adj_radius(200,0,1e50,1,10),
+       spin_radius(adj_radius,1,1),
+
+       check_relative(_("Relative Growth"))
+{
+       load_settings();
+
+       // Set up the tool options dialog
+       options_table.attach(*manage(new Gtk::Label(_("Width Tool"))),  0, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+
+       //expand stuff
+       options_table.attach(*manage(new Gtk::Label(_("Growth:"))),             0, 1, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(spin_delta,                                                                1, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+
+       options_table.attach(*manage(new Gtk::Label(_("Radius:"))),             0, 1, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+       options_table.attach(spin_radius,                                                               1, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+
+       options_table.attach(check_relative,                                                    0, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
+
+       options_table.show_all();
+
+       refresh_tool_options();
+       App::dialog_tool_options->present();
+
+       // Turn off layer clicking
+       get_work_area()->set_allow_layer_clicks(false);
+
+       // clear out the ducks
+       //get_work_area()->clear_ducks();
+
+       // Refresh the work area
+       get_work_area()->queue_draw();
+
+       //Create the new ducks
+       added = false;
+
+       if(!center)
+       {
+               center = new Duck();
+               center->set_name("p1");
+               center->set_type(Duck::TYPE_POSITION);
+       }
+
+       if(!radius)
+       {
+               radius = new Duck();
+               radius->set_origin(center);
+               radius->set_radius(true);
+               radius->set_type(Duck::TYPE_RADIUS);
+               radius->set_name("radius");
+       }
+
+       if(!closestpoint)
+       {
+               closestpoint = new Duck();
+               closestpoint->set_name("closest");
+               closestpoint->set_type(Duck::TYPE_POSITION);
+       }
+
+       //Disable duck clicking for the maximum coolness :)
+       get_work_area()->set_allow_duck_clicks(false);
+       get_work_area()->set_type_mask((Duck::Type)((int)Duck::TYPE_WIDTH + (int)Duck::TYPE_RADIUS));
+
+       // Turn the mouse pointer to crosshairs
+       get_work_area()->set_cursor(Gdk::CROSSHAIR);
+
+       // Hide the tables if they are showing
+       //prev_table_status=get_canvas_view()->tables_are_visible();
+       //if(prev_table_status)get_canvas_view()->hide_tables();
+
+       // Disable the time bar
+       //get_canvas_view()->set_sensitive_timebar(false);
+
+       // Connect a signal
+       //get_work_area()->signal_user_click().connect(sigc::mem_fun(*this,&studio::StateWidth_Context::on_user_click));
+
+       App::toolbox->refresh();
+}
+
+void
+StateWidth_Context::refresh_tool_options()
+{
+       App::dialog_tool_options->clear();
+       App::dialog_tool_options->set_widget(options_table);
+       App::dialog_tool_options->set_local_name(_("Width Tool"));
+       App::dialog_tool_options->set_name("width");
+}
+
+Smach::event_result
+StateWidth_Context::event_refresh_tool_options(const Smach::event& /*x*/)
+{
+       refresh_tool_options();
+       return Smach::RESULT_ACCEPT;
+}
+
+StateWidth_Context::~StateWidth_Context()
+{
+       save_settings();
+
+       //remove ducks if need be
+       if(added)
+       {
+               get_work_area()->erase_duck(center);
+               get_work_area()->erase_duck(radius);
+               get_work_area()->erase_duck(closestpoint);
+               added = false;
+       }
+
+       // Restore Duck clicking
+       get_work_area()->set_allow_duck_clicks(prev_workarea_duck_clicking);
+
+       // Restore layer clicking
+       get_work_area()->set_allow_layer_clicks(prev_workarea_layer_clicking);
+
+       // Restore the mouse pointer
+       get_work_area()->reset_cursor();
+
+       // Restore duck masking
+       get_work_area()->set_type_mask(old_duckmask);
+
+       // Tool options be rid of ye!!
+       App::dialog_tool_options->clear();
+
+       // Enable the time bar
+       //get_canvas_view()->set_sensitive_timebar(true);
+
+       // Bring back the tables if they were out before
+       //if(prev_table_status)get_canvas_view()->show_tables();
+
+       // Refresh the work area
+       get_work_area()->queue_draw();
+
+       App::toolbox->refresh();
+}
+
+Smach::event_result
+StateWidth_Context::event_stop_handler(const Smach::event& /*x*/)
+{
+       //throw Smach::egress_exception();
+       throw &state_normal;
+       return Smach::RESULT_OK;
+}
+
+Smach::event_result
+StateWidth_Context::event_refresh_handler(const Smach::event& /*x*/)
+{
+       refresh_ducks();
+       return Smach::RESULT_ACCEPT;
+}
+
+void
+StateWidth_Context::AdjustWidth(handle<Duckmatic::Bezier> c, float t, Real mult, bool invert)
+{
+       //Leave the function if there is no curve
+       if(!c)return;
+
+       Real amount1=0,amount2=0;
+
+       //decide how much to change each width
+       /*
+       t \in [0,1]
+
+       both pressure and multiply amount are in mult
+               (may want to change this to allow different types of falloff)
+
+       rsq is the squared distance from the point on the curve (also part of the falloff)
+
+
+       */
+       //may want to provide a different falloff function...
+       if(t <= 0.2)
+               amount1 = mult;
+       else if(t >= 0.8)
+               amount2 = mult;
+       else
+       {
+               t = (t-0.2)/0.6;
+               amount1 = (1-t)*mult;
+               amount2 = t*mult;
+       }
+
+       if(invert)
+       {
+               amount1 *= -1;
+               amount2 *= -1;
+       }
+
+       handle<Duck>    p1 = c->p1;
+       handle<Duck>    p2 = c->p2;
+
+       handle<Duck>    w1,w2;
+
+       //find w1,w2
+       {
+               const DuckList dl = get_work_area()->get_duck_list();
+
+               DuckList::const_iterator i = dl.begin();
+
+               for(;i != dl.end(); ++i)
+               {
+                       if((*i)->get_type() == Duck::TYPE_WIDTH)
+                       {
+                               if((*i)->get_origin_duck() == p1)
+                               {
+                                       w1 = *i;
+                               }
+
+                               if((*i)->get_origin_duck() == p2)
+                               {
+                                       w2 = *i;
+                               }
+                       }
+               }
+       }
+
+       if(amount1 != 0 && w1)
+       {
+               Real width = w1->get_point().mag();
+
+               width += amount1;
+               w1->set_point(Vector(width,0));
+
+               //log in the list of changes...
+               //to truly be changed after everything is said and done
+               changetable[w1] = width;
+       }
+
+       if(amount2 != 0 && w2)
+       {
+               Real width = w2->get_point().mag();
+
+               width += amount2;
+               w2->set_point(Vector(width,0));
+
+               //log in the list of changes...
+               //to truly be changed after everything is said and done
+               changetable[w2] = width;
+       }
+}
+
+Smach::event_result
+StateWidth_Context::event_mouse_handler(const Smach::event& x)
+{
+       const EventMouse& event(*reinterpret_cast<const EventMouse*>(&x));
+
+       //handle the click
+       if( (event.key == EVENT_WORKAREA_MOUSE_BUTTON_DOWN || event.key == EVENT_WORKAREA_MOUSE_BUTTON_DRAG)
+                       && event.button == BUTTON_LEFT )
+       {
+               const Real pw = get_work_area()->get_pw();
+               const Real ph = get_work_area()->get_ph();
+               const Real scale = sqrt(pw*pw+ph*ph);
+               const Real rad = get_relative() ? scale * get_radius() : get_radius();
+
+               bool invert = (event.modifier&Gdk::CONTROL_MASK);
+
+               const Real threshold = 0.08;
+
+               float t = 0;
+               Real rsq = 0;
+
+               Real dtime = 1/60.0;
+
+               //if we're dragging get the difference in time between now and then
+               if(event.key == EVENT_WORKAREA_MOUSE_BUTTON_DRAG)
+               {
+                       dtime = min(1/15.0,clocktime());
+               }
+               clocktime.reset();
+
+               //make way for new ducks
+               //get_work_area()->clear_ducks();
+
+               //update positions
+               //mouse_pos = event.pos;
+
+               center->set_point(event.pos);
+               if(!added)get_work_area()->add_duck(center);
+
+               radius->set_scalar(rad);
+               if(!added)get_work_area()->add_duck(radius);
+
+               //the other duck is at the current duck
+               closestpoint->set_point(event.pos);
+               if(!added)get_work_area()->add_duck(closestpoint);
+
+               //get the closest curve...
+               handle<Duckmatic::Bezier>       c;
+               if(event.pressure >= threshold)
+                       c = get_work_area()->find_bezier(event.pos,scale*8,rad,&t);
+
+               //run algorithm on event.pos to get 2nd placement
+               if(!c.empty())
+               {
+                       bezier<Point> curve;
+                       Point p;
+
+                       curve[0] = c->p1->get_trans_point();
+                       curve[1] = c->c1->get_trans_point();
+                       curve[2] = c->c2->get_trans_point();
+                       curve[3] = c->p2->get_trans_point();
+
+                       p = curve(t);
+                       rsq = (p-event.pos).mag_squared();
+
+                       const Real r = rad*rad;
+
+                       if(rsq < r)
+                       {
+                               closestpoint->set_point(curve(t));
+
+                               //adjust the width...
+                               //squared falloff for radius... [0,1]
+
+                               Real ri = (r - rsq)/r;
+                               AdjustWidth(c,t,ri*event.pressure*get_delta()*dtime,invert);
+                       }
+               }
+
+               //the points have been added
+               added = true;
+
+               //draw where it is yo!
+               get_work_area()->queue_draw();
+
+               return Smach::RESULT_ACCEPT;
+       }
+
+       if(event.key == EVENT_WORKAREA_MOUSE_BUTTON_UP && event.button == BUTTON_LEFT)
+       {
+               if(added)
+               {
+                       get_work_area()->erase_duck(center);
+                       get_work_area()->erase_duck(radius);
+                       get_work_area()->erase_duck(closestpoint);
+                       added = false;
+               }
+
+               //Affect the width changes here...
+               map<handle<Duck>,Real>::iterator i = changetable.begin();
+
+               synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Sketch Width"));
+               for(; i != changetable.end(); ++i)
+               {
+                       //for each duck modify IT!!!
+                       ValueDesc desc = i->first->get_value_desc();
+
+                       if(     desc.get_value_type() == ValueBase::TYPE_REAL )
+                       {
+                               Action::Handle action(Action::create("ValueDescSet"));
+                               assert(action);
+
+                               action->set_param("canvas",get_canvas());
+                               action->set_param("canvas_interface",get_canvas_interface());
+
+                               action->set_param("value_desc",desc);
+                               action->set_param("new_value",ValueBase(i->second));
+                               action->set_param("time",get_canvas_view()->get_time());
+
+                               if(!action->is_ready() || !get_canvas_view()->get_instance()->perform_action(action))
+                               {
+                                       group.cancel();
+                                       synfig::warning("Changing the width action has failed");
+                                       return Smach::RESULT_ERROR;
+                               }
+                       }
+               }
+
+               changetable.clear();
+
+               get_work_area()->queue_draw();
+
+               return Smach::RESULT_ACCEPT;
+       }
+
+       return Smach::RESULT_OK;
+}
+
+
+void
+StateWidth_Context::refresh_ducks()
+{
+       get_work_area()->clear_ducks();
+       get_work_area()->queue_draw();
+}
diff --git a/synfig-studio/src/gui/states/state_width.h b/synfig-studio/src/gui/states/state_width.h
new file mode 100644 (file)
index 0000000..f649140
--- /dev/null
@@ -0,0 +1,56 @@
+/* === S Y N F I G ========================================================= */
+/*!    \file state_width.h
+**     \brief Width creation state
+**
+**     $Id$
+**
+**     \legal
+**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+**
+**     This package is free software; you can redistribute it and/or
+**     modify it under the terms of the GNU General Public License as
+**     published by the Free Software Foundation; either version 2 of
+**     the License, or (at your option) any later version.
+**
+**     This package is distributed in the hope that it will be useful,
+**     but WITHOUT ANY WARRANTY; without even the implied warranty of
+**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+**     General Public License for more details.
+**     \endlegal
+*/
+/* ========================================================================= */
+
+/* === S T A R T =========================================================== */
+
+#ifndef __SYNFIG_STUDIO_STATE_WIDTH_H
+#define __SYNFIG_STUDIO_STATE_WIDTH_H
+
+/* === H E A D E R S ======================================================= */
+
+#include "smach.h"
+
+
+/* === M A C R O S ========================================================= */
+
+/* === T Y P E D E F S ===================================================== */
+
+/* === C L A S S E S & S T R U C T S ======================================= */
+
+namespace studio {
+
+class StateWidth_Context;
+
+class StateWidth : public Smach::state<StateWidth_Context>
+{
+public:
+       StateWidth();
+       ~StateWidth();
+}; // END of class StateWidth
+
+extern StateWidth state_width;
+
+}; // END of namespace studio
+
+/* === E N D =============================================================== */
+
+#endif
diff --git a/synfig-studio/src/gui/states/state_zoom.cpp b/synfig-studio/src/gui/states/state_zoom.cpp
new file mode 100644 (file)
index 0000000..56363e6
--- /dev/null
@@ -0,0 +1,263 @@
+/* === S Y N F I G ========================================================= */
+/*!    \file state_zoom.cpp
+**     \brief Zoom Tool Implementation File
+**
+**     $Id$
+**
+**     \legal
+**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+**  Copyright (c) 2008 Chris Moore
+**
+**     This package is free software; you can redistribute it and/or
+**     modify it under the terms of the GNU General Public License as
+**     published by the Free Software Foundation; either version 2 of
+**     the License, or (at your option) any later version.
+**
+**     This package is distributed in the hope that it will be useful,
+**     but WITHOUT ANY WARRANTY; without even the implied warranty of
+**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+**     General Public License for more details.
+**     \endlegal
+*/
+/* ========================================================================= */
+
+/* === H E A D E R S ======================================================= */
+
+#ifdef USING_PCH
+#      include "pch.h"
+#else
+#ifdef HAVE_CONFIG_H
+#      include <config.h>
+#endif
+
+#include <sigc++/signal.h>
+#include <sigc++/object.h>
+
+#include <ETL/handle>
+#include <synfig/vector.h>
+
+
+#include "state_zoom.h"
+#include "state_normal.h"
+#include "event_mouse.h"
+#include "canvasview.h"
+#include "workarea.h"
+#include "app.h"
+#include "toolbox.h"
+#include <synfigapp/main.h>
+
+#include "general.h"
+
+#endif
+
+/* === U S I N G =========================================================== */
+
+using namespace std;
+using namespace etl;
+using namespace synfig;
+using namespace studio;
+
+/* === M A C R O S ========================================================= */
+
+/* === G L O B A L S ======================================================= */
+StateZoom studio::state_zoom;
+
+const float ZOOMFACTOR = 1.25f;
+
+/* === C L A S S E S & S T R U C T S ======================================= */
+
+class studio::StateZoom_Context : public sigc::trackable
+{
+       etl::handle<CanvasView> canvas_view_;
+       CanvasView::IsWorking is_working;
+
+       Point p1,p2;
+
+       bool prev_workarea_layer_status_;
+
+public:
+
+       //events
+       Smach::event_result event_stop_handler(const Smach::event& x);
+       Smach::event_result event_refresh_handler(const Smach::event& x);
+       Smach::event_result event_mouse_click_handler(const Smach::event& x);
+
+       //constructor destructor
+       StateZoom_Context(CanvasView* canvas_view);
+       ~StateZoom_Context();
+
+       //Canvas interaction
+       const etl::handle<CanvasView>& get_canvas_view()const{return canvas_view_;}
+       etl::handle<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view_->canvas_interface();}
+       synfig::Canvas::Handle get_canvas()const{return canvas_view_->get_canvas();}
+       WorkArea * get_work_area()const{return canvas_view_->get_work_area();}
+
+       //void zoom(const Point& p1, const Point& p2);
+
+};     // END of class StateZoom_Context
+
+/* === M E T H O D S ======================================================= */
+
+StateZoom::StateZoom():
+       Smach::state<StateZoom_Context>("zoom")
+{
+       insert(event_def(EVENT_STOP,&StateZoom_Context::event_stop_handler));
+       insert(event_def(EVENT_REFRESH,&StateZoom_Context::event_refresh_handler));
+       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateZoom_Context::event_mouse_click_handler));
+       //insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DRAG,&StateZoom_Context::event_mouse_click_handler));
+       insert(event_def(EVENT_WORKAREA_BOX,&StateZoom_Context::event_mouse_click_handler));
+       //insert(event_def(EVENT_WORKAREA_BUTTON_CLICK,&StateZoom_Context::event_mouse_click_handler));
+       insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_UP,&StateZoom_Context::event_mouse_click_handler));
+}
+
+StateZoom::~StateZoom()
+{
+}
+
+StateZoom_Context::StateZoom_Context(CanvasView* canvas_view):
+       canvas_view_(canvas_view),
+       is_working(*canvas_view),
+       prev_workarea_layer_status_(get_work_area()->get_allow_layer_clicks())
+{
+       // Turn off layer clicking
+       get_work_area()->set_allow_layer_clicks(false);
+
+       // clear out the ducks
+       get_work_area()->clear_ducks(); //???
+
+       // Refresh the work area
+       get_work_area()->queue_draw();
+
+       // Hide the tables if they are showing
+       //prev_table_status=get_canvas_view()->tables_are_visible();
+       //if(prev_table_status)get_canvas_view()->hide_tables();
+
+       // Disable the time bar
+       //get_canvas_view()->set_sensitive_timebar(false);
+
+       // Connect a signal
+       //get_work_area()->signal_user_click().connect(sigc::mem_fun(*this,&studio::StateZoom_Context::on_user_click));
+       get_work_area()->set_cursor(Gdk::CROSSHAIR);
+
+       App::toolbox->refresh();
+}
+
+StateZoom_Context::~StateZoom_Context()
+{
+       // Restore layer clicking
+       get_work_area()->set_allow_layer_clicks(prev_workarea_layer_status_);
+       get_work_area()->reset_cursor();
+
+       // Enable the time bar
+       //get_canvas_view()->set_sensitive_timebar(true);
+
+       // Bring back the tables if they were out before
+       //if(prev_table_status)get_canvas_view()->show_tables();
+
+       // Refresh the work area
+       get_work_area()->queue_draw();
+
+       App::toolbox->refresh();
+
+       get_canvas_view()->get_smach().process_event(EVENT_REFRESH_DUCKS);
+}
+
+Smach::event_result
+StateZoom_Context::event_stop_handler(const Smach::event& /*x*/)
+{
+       //throw Smach::egress_exception();
+       throw &state_normal;
+       return Smach::RESULT_OK;
+}
+
+Smach::event_result
+StateZoom_Context::event_refresh_handler(const Smach::event& /*x*/)
+{
+       return Smach::RESULT_ACCEPT;
+}
+
+Smach::event_result
+StateZoom_Context::event_mouse_click_handler(const Smach::event& x)
+{
+       if(x.key==EVENT_WORKAREA_BOX)
+       {
+               const EventBox& event(*reinterpret_cast<const EventBox*>(&x));
+
+               if(event.button==BUTTON_LEFT)
+               {
+                       Point tl = get_work_area()->get_window_tl();
+                       Point br = get_work_area()->get_window_br();
+                       Vector  window_span = br - tl, window_middle = (br+tl)/2;
+                       Vector  box_span = event.p2 - event.p1, box_middle = (event.p1+event.p2)/2;
+                       Point newpos;
+                       float zoom;
+
+                       if(event.modifier & Gdk::CONTROL_MASK) //zoom out...
+                       {
+                               if (window_span[0] == 0 || window_span[1] == 0) zoom = 1;
+                               else zoom = max(abs(box_span[0]/window_span[0]), abs(box_span[1]/window_span[1]));
+
+                               // focus_point is -1 times the real position for some reason...
+                               // center the window so the old contents fill the drawn box
+                               newpos = -((window_middle - box_middle)/zoom + window_middle);
+                       }
+                       else                            // zoom in
+                       {
+                               if (box_span[0] == 0 || box_span[1] == 0) zoom = 1;
+                               else zoom = min(abs(window_span[0]/box_span[0]), abs(window_span[1]/box_span[1]));
+
+                               // center the window at the center of the box
+                               newpos = -(-get_work_area()->get_focus_point() + (box_middle - window_middle));
+                       }
+
+                       get_work_area()->set_focus_point(newpos);
+                       get_work_area()->set_zoom(get_work_area()->get_zoom()*zoom);
+
+                       return Smach::RESULT_ACCEPT;
+               }
+       }
+
+       if(x.key==EVENT_WORKAREA_MOUSE_BUTTON_UP)
+       {
+               const EventMouse& event(*reinterpret_cast<const EventMouse*>(&x));
+
+               if(event.button==BUTTON_LEFT)
+               {
+                       Point evpos;
+
+                       //make the event pos be in the same space...
+                       //   The weird ass inverted center normalized space...
+                       {
+                               const Point realcenter = (get_work_area()->get_window_tl() + get_work_area()->get_window_br())/2;
+                               evpos = -(event.pos - realcenter) + get_work_area()->get_focus_point();
+                       }
+
+                       /*      Zooming:
+                               focus point must zoom about the point evpos...
+
+                               trans about an origin not 0:
+                               p' = A(p - o) + o
+                       */
+
+                       Vector v = get_work_area()->get_focus_point() - evpos;
+
+                       if(event.modifier & Gdk::CONTROL_MASK) //zoom out...
+                       {
+                               v*=ZOOMFACTOR;
+                               //get_work_area()->zoom_out();
+                               get_work_area()->set_focus_point(evpos + v);
+                               get_work_area()->set_zoom(get_work_area()->get_zoom()/ZOOMFACTOR);
+                       }else //zoom in
+                       {
+                               v/=ZOOMFACTOR;
+                               //get_work_area()->zoom_in();
+                               get_work_area()->set_focus_point(evpos + v);
+                               get_work_area()->set_zoom(get_work_area()->get_zoom()*ZOOMFACTOR);
+                       }
+
+                       return Smach::RESULT_ACCEPT;
+               }
+       }
+
+       return Smach::RESULT_OK;
+}
diff --git a/synfig-studio/src/gui/states/state_zoom.h b/synfig-studio/src/gui/states/state_zoom.h
new file mode 100644 (file)
index 0000000..e5e7260
--- /dev/null
@@ -0,0 +1,55 @@
+/* === S Y N F I G ========================================================= */
+/*!    \file state_zoom.h
+**     \brief Zoom tool Header
+**
+**     $Id$
+**
+**     \legal
+**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+**
+**     This package is free software; you can redistribute it and/or
+**     modify it under the terms of the GNU General Public License as
+**     published by the Free Software Foundation; either version 2 of
+**     the License, or (at your option) any later version.
+**
+**     This package is distributed in the hope that it will be useful,
+**     but WITHOUT ANY WARRANTY; without even the implied warranty of
+**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+**     General Public License for more details.
+**     \endlegal
+*/
+/* ========================================================================= */
+
+/* === S T A R T =========================================================== */
+
+#ifndef __SYNFIG_STATE_ZOOM_H
+#define __SYNFIG_STATE_ZOOM_H
+
+/* === H E A D E R S ======================================================= */
+#include "smach.h"
+
+
+/* === M A C R O S ========================================================= */
+
+/* === T Y P E D E F S ===================================================== */
+
+/* === C L A S S E S & S T R U C T S ======================================= */
+
+namespace studio {
+
+class StateZoom_Context;
+
+class StateZoom : public Smach::state<StateZoom_Context>
+{
+public:
+       StateZoom();
+       ~StateZoom();
+}; // END of class StateZoom
+
+extern StateZoom state_zoom;
+
+}; // END of namespace studio
+
+/* === E N D =============================================================== */
+
+#endif