Build rectanglular blines in the same handedness as all the other shapes.
[synfig.git] / synfig-studio / trunk / src / gtkmm / state_star.cpp
1 /* === S Y N F I G ========================================================= */
2 /*!     \file state_star.cpp
3 **      \brief Template File
4 **
5 **      $Id$
6 **
7 **      \legal
8 **      Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 **      Copyright (c) 2008 Chris Moore
10 **
11 **      This package is free software; you can redistribute it and/or
12 **      modify it under the terms of the GNU General Public License as
13 **      published by the Free Software Foundation; either version 2 of
14 **      the License, or (at your option) any later version.
15 **
16 **      This package is distributed in the hope that it will be useful,
17 **      but WITHOUT ANY WARRANTY; without even the implied warranty of
18 **      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 **      General Public License for more details.
20 **      \endlegal
21 */
22 /* ========================================================================= */
23
24 /* === H E A D E R S ======================================================= */
25
26 #ifdef USING_PCH
27 #       include "pch.h"
28 #else
29 #ifdef HAVE_CONFIG_H
30 #       include <config.h>
31 #endif
32
33 #include <gtkmm/dialog.h>
34 #include <gtkmm/entry.h>
35
36 #include <synfig/valuenode_dynamiclist.h>
37 #include <synfigapp/action_system.h>
38 #include <synfig/valuenode_bline.h>
39
40 #include "state_star.h"
41 #include "canvasview.h"
42 #include "workarea.h"
43 #include "app.h"
44
45 #include <synfigapp/action.h>
46 #include "event_mouse.h"
47 #include "event_layerclick.h"
48 #include "toolbox.h"
49 #include "dialog_tooloptions.h"
50 #include <gtkmm/optionmenu.h>
51 #include "duck.h"
52 #include "widget_enum.h"
53 #include <synfigapp/main.h>
54
55 #include "general.h"
56
57 #endif
58
59 /* === U S I N G =========================================================== */
60
61 using namespace std;
62 using namespace etl;
63 using namespace synfig;
64 using namespace studio;
65
66 /* === M A C R O S ========================================================= */
67
68 /* === G L O B A L S ======================================================= */
69
70 StateStar studio::state_star;
71
72 /* === C L A S S E S & S T R U C T S ======================================= */
73
74 class studio::StateStar_Context : public sigc::trackable
75 {
76         etl::handle<CanvasView> canvas_view_;
77         CanvasView::IsWorking is_working;
78
79         Duckmatic::Push duckmatic_push;
80
81         Point point_holder;
82
83         etl::handle<Duck> point2_duck;
84
85         void refresh_ducks();
86
87         bool prev_workarea_layer_status_;
88
89         //Toolbox settings
90         synfigapp::Settings& settings;
91
92         //Toolbox display
93         Gtk::Table options_table;
94
95         Gtk::Entry              entry_id; //what to name the layer
96
97         Gtk::Adjustment adj_feather;
98         Gtk::Adjustment adj_number_of_points;
99         Gtk::Adjustment adj_inner_tangent;
100         Gtk::Adjustment adj_outer_tangent;
101         Gtk::Adjustment adj_inner_width;
102         Gtk::Adjustment adj_outer_width;
103         Gtk::Adjustment adj_radius_ratio;
104         Gtk::Adjustment adj_angle_offset;
105         Gtk::SpinButton spin_feather;
106         Gtk::SpinButton spin_number_of_points;
107         Gtk::SpinButton spin_inner_tangent;
108         Gtk::SpinButton spin_outer_tangent;
109         Gtk::SpinButton spin_inner_width;
110         Gtk::SpinButton spin_outer_width;
111         Gtk::SpinButton spin_radius_ratio;
112         Gtk::SpinButton spin_angle_offset;
113
114         Gtk::CheckButton checkbutton_invert;
115         Gtk::CheckButton checkbutton_regular_polygon;
116         Gtk::CheckButton checkbutton_layer_star;
117         Gtk::CheckButton checkbutton_layer_region;
118         Gtk::CheckButton checkbutton_layer_outline;
119         Gtk::CheckButton checkbutton_layer_curve_gradient;
120         Gtk::CheckButton checkbutton_layer_plant;
121         Gtk::CheckButton checkbutton_layer_link_origins;
122
123 public:
124
125         // this only counts the layers which use blines - they're the only
126         // ones we link the origins for
127         int layers_to_create()const
128         {
129                 return
130                         get_layer_region_flag() +
131                         get_layer_outline_flag() +
132                         get_layer_curve_gradient_flag() +
133                         get_layer_plant_flag();
134         }
135
136         synfig::String get_id()const { return entry_id.get_text(); }
137         void set_id(const synfig::String& x) { return entry_id.set_text(x); }
138
139         Real get_feather()const { return adj_feather.get_value(); }
140         void set_feather(Real f) { adj_feather.set_value(f); }
141
142         Real get_number_of_points()const { return adj_number_of_points.get_value(); }
143         void set_number_of_points(Real f) { adj_number_of_points.set_value(f); }
144
145         Real get_inner_tangent()const { return adj_inner_tangent.get_value(); }
146         void set_inner_tangent(Real f) { adj_inner_tangent.set_value(f); }
147
148         Real get_outer_tangent()const { return adj_outer_tangent.get_value(); }
149         void set_outer_tangent(Real f) { adj_outer_tangent.set_value(f); }
150
151         Real get_inner_width()const { return adj_inner_width.get_value(); }
152         void set_inner_width(Real f) { adj_inner_width.set_value(f); }
153
154         Real get_outer_width()const { return adj_outer_width.get_value(); }
155         void set_outer_width(Real f) { adj_outer_width.set_value(f); }
156
157         Real get_radius_ratio()const { return adj_radius_ratio.get_value(); }
158         void set_radius_ratio(Real f) { adj_radius_ratio.set_value(f); }
159
160         Real get_angle_offset()const { return adj_angle_offset.get_value(); }
161         void set_angle_offset(Real f) { adj_angle_offset.set_value(f); }
162
163         bool get_invert()const { return checkbutton_invert.get_active(); }
164         void set_invert(bool i) { checkbutton_invert.set_active(i); }
165
166         bool get_regular_polygon()const { return checkbutton_regular_polygon.get_active(); }
167         void set_regular_polygon(bool i) { checkbutton_regular_polygon.set_active(i); }
168
169         bool get_layer_star_flag()const { return checkbutton_layer_star.get_active(); }
170         void set_layer_star_flag(bool x) { return checkbutton_layer_star.set_active(x); }
171
172         bool get_layer_region_flag()const { return checkbutton_layer_region.get_active(); }
173         void set_layer_region_flag(bool x) { return checkbutton_layer_region.set_active(x); }
174
175         bool get_layer_outline_flag()const { return checkbutton_layer_outline.get_active(); }
176         void set_layer_outline_flag(bool x) { return checkbutton_layer_outline.set_active(x); }
177
178         bool get_layer_curve_gradient_flag()const { return checkbutton_layer_curve_gradient.get_active(); }
179         void set_layer_curve_gradient_flag(bool x) { return checkbutton_layer_curve_gradient.set_active(x); }
180
181         bool get_layer_plant_flag()const { return checkbutton_layer_plant.get_active(); }
182         void set_layer_plant_flag(bool x) { return checkbutton_layer_plant.set_active(x); }
183
184         bool get_layer_link_origins_flag()const { return checkbutton_layer_link_origins.get_active(); }
185         void set_layer_link_origins_flag(bool x) { return checkbutton_layer_link_origins.set_active(x); }
186
187         void refresh_tool_options(); //to refresh the toolbox
188
189         //events
190         Smach::event_result event_stop_handler(const Smach::event& x);
191         Smach::event_result event_refresh_handler(const Smach::event& x);
192         Smach::event_result event_mouse_click_handler(const Smach::event& x);
193         Smach::event_result event_refresh_tool_options(const Smach::event& x);
194
195         //constructor destructor
196         StateStar_Context(CanvasView* canvas_view);
197         ~StateStar_Context();
198
199         //Canvas interaction
200         const etl::handle<CanvasView>& get_canvas_view()const{return canvas_view_;}
201         etl::handle<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view_->canvas_interface();}
202         synfig::Canvas::Handle get_canvas()const{return canvas_view_->get_canvas();}
203         WorkArea * get_work_area()const{return canvas_view_->get_work_area();}
204
205         //Modifying settings etc.
206         void load_settings();
207         void save_settings();
208         void reset();
209         void increment_id();
210         bool egress_on_selection_change;
211         Smach::event_result event_layer_selection_changed_handler(const Smach::event& /*x*/)
212         {
213                 if(egress_on_selection_change)
214                         throw Smach::egress_exception();
215                 return Smach::RESULT_OK;
216         }
217
218         void make_star(const Point& p1, const Point& p2);
219
220 };      // END of class StateStar_Context
221
222 /* === M E T H O D S ======================================================= */
223
224 StateStar::StateStar():
225         Smach::state<StateStar_Context>("star")
226 {
227         insert(event_def(EVENT_LAYER_SELECTION_CHANGED,&StateStar_Context::event_layer_selection_changed_handler));
228         insert(event_def(EVENT_STOP,&StateStar_Context::event_stop_handler));
229         insert(event_def(EVENT_REFRESH,&StateStar_Context::event_refresh_handler));
230         insert(event_def(EVENT_REFRESH_DUCKS,&StateStar_Context::event_refresh_handler));
231         insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateStar_Context::event_mouse_click_handler));
232         insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DRAG,&StateStar_Context::event_mouse_click_handler));
233         insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_UP,&StateStar_Context::event_mouse_click_handler));
234         insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateStar_Context::event_refresh_tool_options));
235 }
236
237 StateStar::~StateStar()
238 {
239 }
240
241 void
242 StateStar_Context::load_settings()
243 {
244         String value;
245
246         //parse the arguments yargh!
247         if(settings.get_value("star.id",value))
248                 set_id(value);
249         else
250                 set_id("Star");
251
252         if(settings.get_value("star.feather",value))
253                 set_feather(atof(value.c_str()));
254         else
255                 set_feather(0);
256
257         if(settings.get_value("star.number_of_points",value))
258                 set_number_of_points(atof(value.c_str()));
259         else
260                 set_number_of_points(5);
261
262         if(settings.get_value("star.inner_tangent",value))
263                 set_inner_tangent(atof(value.c_str()));
264         else
265                 set_inner_tangent(0);
266
267         if(settings.get_value("star.outer_tangent",value))
268                 set_outer_tangent(atof(value.c_str()));
269         else
270                 set_outer_tangent(0);
271
272         if(settings.get_value("star.inner_width",value))
273                 set_inner_width(atof(value.c_str()));
274         else
275                 set_inner_width(1);
276
277         if(settings.get_value("star.outer_width",value))
278                 set_outer_width(atof(value.c_str()));
279         else
280                 set_outer_width(1);
281
282         if(settings.get_value("star.radius_ratio",value))
283                 set_radius_ratio(atof(value.c_str()));
284         else
285                 set_radius_ratio(0.5);
286
287         if(settings.get_value("star.angle_offset",value))
288                 set_angle_offset(atof(value.c_str()));
289         else
290                 set_angle_offset(0);
291
292         if(settings.get_value("star.invert",value) && value != "0")
293                 set_invert(true);
294         else
295                 set_invert(false);
296
297         if(settings.get_value("star.regular_polygon",value) && value != "0")
298                 set_regular_polygon(true);
299         else
300                 set_regular_polygon(false);
301
302         if(settings.get_value("star.layer_star",value) && value=="0")
303                 set_layer_star_flag(false);
304         else
305                 set_layer_star_flag(true);
306
307         if(settings.get_value("star.layer_region",value) && value=="1")
308                 set_layer_region_flag(true);
309         else
310                 set_layer_region_flag(false);
311
312         if(settings.get_value("star.layer_outline",value) && value=="1")
313                 set_layer_outline_flag(true);
314         else
315                 set_layer_outline_flag(false);
316
317         if(settings.get_value("star.layer_curve_gradient",value) && value=="1")
318                 set_layer_curve_gradient_flag(true);
319         else
320                 set_layer_curve_gradient_flag(false);
321
322         if(settings.get_value("star.layer_plant",value) && value=="1")
323                 set_layer_plant_flag(true);
324         else
325                 set_layer_plant_flag(false);
326
327         if(settings.get_value("star.layer_link_origins",value) && value=="0")
328                 set_layer_link_origins_flag(false);
329         else
330                 set_layer_link_origins_flag(true);
331 }
332
333 void
334 StateStar_Context::save_settings()
335 {
336         settings.set_value("star.id",get_id());
337         settings.set_value("star.feather",strprintf("%f",(float)get_feather()));
338         settings.set_value("star.number_of_points",strprintf("%d",(int)(get_number_of_points() + 0.5)));
339         settings.set_value("star.inner_tangent",strprintf("%f",(float)get_inner_tangent()));
340         settings.set_value("star.outer_tangent",strprintf("%f",(float)get_outer_tangent()));
341         settings.set_value("star.inner_width",strprintf("%f",(float)get_inner_width()));
342         settings.set_value("star.outer_width",strprintf("%f",(float)get_outer_width()));
343         settings.set_value("star.radius_ratio",strprintf("%f",(float)get_radius_ratio()));
344         settings.set_value("star.angle_offset",strprintf("%f",(float)get_angle_offset()));
345         settings.set_value("star.invert",get_invert()?"1":"0");
346         settings.set_value("star.regular_polygon",get_regular_polygon()?"1":"0");
347         settings.set_value("star.layer_star",get_layer_star_flag()?"1":"0");
348         settings.set_value("star.layer_outline",get_layer_outline_flag()?"1":"0");
349         settings.set_value("star.layer_region",get_layer_region_flag()?"1":"0");
350         settings.set_value("star.layer_curve_gradient",get_layer_curve_gradient_flag()?"1":"0");
351         settings.set_value("star.layer_plant",get_layer_plant_flag()?"1":"0");
352         settings.set_value("star.layer_link_origins",get_layer_link_origins_flag()?"1":"0");
353 }
354
355 void
356 StateStar_Context::reset()
357 {
358         refresh_ducks();
359 }
360
361 void
362 StateStar_Context::increment_id()
363 {
364         String id(get_id());
365         int number=1;
366         int digits=0;
367
368         if(id.empty())
369                 id="Star";
370
371         // If there is a number
372         // already at the end of the
373         // id, then remove it.
374         if(id[id.size()-1]<='9' && id[id.size()-1]>='0')
375         {
376                 // figure out how many digits it is
377                 for (digits = 0;
378                          (int)id.size()-1 >= digits && id[id.size()-1-digits] <= '9' && id[id.size()-1-digits] >= '0';
379                          digits++)
380                         ;
381
382                 String str_number;
383                 str_number=String(id,id.size()-digits,id.size());
384                 id=String(id,0,id.size()-digits);
385
386                 number=atoi(str_number.c_str());
387         }
388         else
389         {
390                 number=1;
391                 digits=3;
392         }
393
394         number++;
395
396         // Add the number back onto the id
397         {
398                 const String format(strprintf("%%0%dd",digits));
399                 id+=strprintf(format.c_str(),number);
400         }
401
402         // Set the ID
403         set_id(id);
404 }
405
406 StateStar_Context::StateStar_Context(CanvasView* canvas_view):
407         canvas_view_(canvas_view),
408         is_working(*canvas_view),
409         duckmatic_push(get_work_area()),
410         prev_workarea_layer_status_(get_work_area()->get_allow_layer_clicks()),
411         settings(synfigapp::Main::get_selected_input_device()->settings()),
412         entry_id(),             //   value lower upper  step page
413         adj_feather(                    0,    0,    1, 0.01, 0.1),
414         adj_number_of_points(   0,    2,  120, 1   , 1  ),
415         adj_inner_tangent(              0,  -10,   10, 0.01, 0.1),
416         adj_outer_tangent(              0,  -10,   10, 0.01, 0.1),
417         adj_inner_width(                0,  -10,   10, 0.01, 0.1),
418         adj_outer_width(                0,  -10,   10, 0.01, 0.1),
419         adj_radius_ratio(               0,  -10,   10, 0.01, 0.1),
420         adj_angle_offset(               0, -360,  360, 0.1 , 1  ),
421         spin_feather(adj_feather,0.1,3),
422         spin_number_of_points(adj_number_of_points,1,0),
423         spin_inner_tangent(adj_inner_tangent,1,2),
424         spin_outer_tangent(adj_outer_tangent,1,2),
425         spin_inner_width(adj_inner_width,1,2),
426         spin_outer_width(adj_outer_width,1,2),
427         spin_radius_ratio(adj_radius_ratio,1,2),
428         spin_angle_offset(adj_angle_offset,1,1),
429         checkbutton_invert(_("Invert")),
430         checkbutton_regular_polygon(_("Regular Polygon")),
431         checkbutton_layer_star(_("Create Star Layer")),
432         checkbutton_layer_region(_("Create Region BLine")),
433         checkbutton_layer_outline(_("Create Outline BLine")),
434         checkbutton_layer_curve_gradient(_("Create Curve Gradient BLine")),
435         checkbutton_layer_plant(_("Create Plant BLine")),
436         checkbutton_layer_link_origins(_("Link BLine Origins"))
437 {
438         egress_on_selection_change=true;
439
440         load_settings();
441
442         // Set up the tool options dialog
443         options_table.attach(*manage(new Gtk::Label(_("Star Tool"))),                   0, 2,  0,  1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
444         options_table.attach(entry_id,                                                                                  0, 2,  1,  2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
445         options_table.attach(*manage(new Gtk::Label(_("Feather:"))),                    0, 1,  2,  3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
446         options_table.attach(spin_feather,                                                                              1, 2,  2,  3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
447         options_table.attach(checkbutton_invert,                                                                0, 2,  5,  6, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
448         options_table.attach(checkbutton_regular_polygon,                                               0, 2,  6,  7, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
449         options_table.attach(checkbutton_layer_star,                                                    0, 2,  7,  8, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
450         options_table.attach(checkbutton_layer_outline,                                                 0, 2,  8,  9, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
451         options_table.attach(checkbutton_layer_region,                                                  0, 2,  9, 10, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
452         options_table.attach(checkbutton_layer_plant,                                                   0, 2, 10, 11, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
453         options_table.attach(checkbutton_layer_curve_gradient,                                  0, 2, 11, 12, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
454         options_table.attach(checkbutton_layer_link_origins,                                    0, 2, 12, 13, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
455         options_table.attach(*manage(new Gtk::Label(_("Number of Points:"))),   0, 1, 13, 14, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
456         options_table.attach(spin_number_of_points,                                                             1, 2, 13, 14, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
457         options_table.attach(*manage(new Gtk::Label(_("Inner Tangent:"))),              0, 1, 14, 15, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
458         options_table.attach(spin_inner_tangent,                                                                1, 2, 14, 15, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
459         options_table.attach(*manage(new Gtk::Label(_("Outer Tangent:"))),              0, 1, 15, 16, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
460         options_table.attach(spin_outer_tangent,                                                                1, 2, 15, 16, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
461         options_table.attach(*manage(new Gtk::Label(_("Inner Width:"))),                0, 1, 16, 17, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
462         options_table.attach(spin_inner_width,                                                                  1, 2, 16, 17, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
463         options_table.attach(*manage(new Gtk::Label(_("Outer Width:"))),                0, 1, 17, 18, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
464         options_table.attach(spin_outer_width,                                                                  1, 2, 17, 18, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
465         options_table.attach(*manage(new Gtk::Label(_("Radius Ratio:"))),               0, 1, 18, 19, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
466         options_table.attach(spin_radius_ratio,                                                                 1, 2, 18, 19, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
467         options_table.attach(*manage(new Gtk::Label(_("Angle Offset:"))),               0, 1, 19, 20, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
468         options_table.attach(spin_angle_offset,                                                                 1, 2, 19, 20, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
469
470         options_table.show_all();
471
472         refresh_tool_options();
473         App::dialog_tool_options->present();
474
475         // Turn off layer clicking
476         get_work_area()->set_allow_layer_clicks(false);
477
478         // clear out the ducks
479         get_work_area()->clear_ducks();
480
481         // Refresh the work area
482         get_work_area()->queue_draw();
483
484         // Hide the tables if they are showing
485         //prev_table_status=get_canvas_view()->tables_are_visible();
486         //if(prev_table_status)get_canvas_view()->hide_tables();
487
488         // Disable the time bar
489         //get_canvas_view()->set_sensitive_timebar(false);
490
491         // Connect a signal
492         //get_work_area()->signal_user_click().connect(sigc::mem_fun(*this,&studio::StateStar_Context::on_user_click));
493         get_canvas_view()->work_area->set_cursor(Gdk::CROSSHAIR);
494
495         App::toolbox->refresh();
496 }
497
498 void
499 StateStar_Context::refresh_tool_options()
500 {
501         App::dialog_tool_options->clear();
502         App::dialog_tool_options->set_widget(options_table);
503         App::dialog_tool_options->set_local_name(_("Star Tool"));
504         App::dialog_tool_options->set_name("star");
505 }
506
507 Smach::event_result
508 StateStar_Context::event_refresh_tool_options(const Smach::event& /*x*/)
509 {
510         refresh_tool_options();
511         return Smach::RESULT_ACCEPT;
512 }
513
514 StateStar_Context::~StateStar_Context()
515 {
516         save_settings();
517
518         // Restore layer clicking
519         get_work_area()->set_allow_layer_clicks(prev_workarea_layer_status_);
520         get_canvas_view()->work_area->reset_cursor();
521
522         App::dialog_tool_options->clear();
523
524         // Enable the time bar
525         //get_canvas_view()->set_sensitive_timebar(true);
526
527         // Bring back the tables if they were out before
528         //if(prev_table_status)get_canvas_view()->show_tables();
529
530         // Refresh the work area
531         get_work_area()->queue_draw();
532
533         get_canvas_view()->queue_rebuild_ducks();
534
535         App::toolbox->refresh();
536 }
537
538 Smach::event_result
539 StateStar_Context::event_stop_handler(const Smach::event& /*x*/)
540 {
541         throw Smach::egress_exception();
542 }
543
544 Smach::event_result
545 StateStar_Context::event_refresh_handler(const Smach::event& /*x*/)
546 {
547         refresh_ducks();
548         return Smach::RESULT_ACCEPT;
549 }
550
551 void
552 StateStar_Context::make_star(const Point& _p1, const Point& _p2)
553 {
554         synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("New Star"));
555         synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
556
557         Layer::Handle layer;
558
559         Canvas::Handle canvas;
560         int depth(0);
561
562         // we are temporarily using the layer to hold something
563         layer=get_canvas_view()->get_selection_manager()->get_selected_layer();
564         if(layer)
565         {
566                 depth=layer->get_depth();
567                 canvas=layer->get_canvas();
568         }
569
570         synfigapp::SelectionManager::LayerList layer_selection;
571         if (!getenv("SYNFIG_TOOLS_CLEAR_SELECTION"))
572                 layer_selection = get_canvas_view()->get_selection_manager()->get_selected_layers();
573
574         const synfig::TransformStack& transform(get_canvas_view()->get_curr_transform_stack());
575         const Point p1(transform.unperform(_p1));
576         const Point p2(transform.unperform(_p2));
577
578         Real radius_ratio(get_radius_ratio());
579         Real radius1((p2-p1).mag());
580         Real radius2(radius1 * radius_ratio);
581         int points = get_number_of_points();
582         Real inner_tangent = get_inner_tangent() * radius1;
583         Real outer_tangent = get_outer_tangent() * radius2;
584         Real inner_width = get_inner_width();
585         Real outer_width = get_outer_width();
586         Angle::deg offset(get_angle_offset());
587         bool regular(get_regular_polygon());
588         Angle::deg angle(360.0/points);
589         Real x(p1[0]), y(p1[1]);
590
591         std::vector<BLinePoint> new_list;
592         int point(0);
593         for (int i = 0; i < points; i++)
594         {
595                 new_list.push_back(*(new BLinePoint));
596                 new_list[point].set_width(outer_width);
597                 new_list[point].set_vertex(Point(radius1*Angle::cos(angle*i + offset).get() + x,
598                                                                          radius1*Angle::sin(angle*i + offset).get() + y));
599                 new_list[point++].set_tangent(Point(-Angle::sin(angle*i + offset).get(),
600                                                                                          Angle::cos(angle*i + offset).get()) * outer_tangent);
601
602                 if (!regular)
603                 {
604                         new_list.push_back(*(new BLinePoint));
605                         new_list[point].set_width(inner_width);
606                         new_list[point].set_vertex(Point(radius2*Angle::cos(angle*i + angle/2 + offset).get() + x,
607                                                                                          radius2*Angle::sin(angle*i + angle/2 + offset).get() + y));
608                         new_list[point++].set_tangent(Point(-Angle::sin(angle*i + angle/2 + offset).get(),
609                                                                                                  Angle::cos(angle*i + angle/2 + offset).get()) * inner_tangent);
610                 }
611         }
612
613         ValueNode_BLine::Handle value_node_bline(ValueNode_BLine::create(new_list));
614         assert(value_node_bline);
615
616         ValueNode_Const::Handle value_node_origin(ValueNode_Const::create(Vector()));
617         assert(value_node_origin);
618
619         // Set the looping flag
620         value_node_bline->set_loop(true);
621
622         if(!canvas)
623                 canvas=get_canvas_view()->get_canvas();
624
625         value_node_bline->set_member_canvas(canvas);
626
627         // count how many layers we're going to be creating
628         int layers_to_create = this->layers_to_create();
629
630         ///////////////////////////////////////////////////////////////////////////
631         //   S T A R
632         ///////////////////////////////////////////////////////////////////////////
633
634         if (get_layer_star_flag())
635         {
636                 layer=get_canvas_interface()->add_layer_to("star",canvas,depth);
637                 layer_selection.push_back(layer);
638
639                 layer->set_param("origin",p1);
640                 get_canvas_interface()->signal_layer_param_changed()(layer,"origin");
641
642                 layer->set_param("radius1",(p2-p1).mag());
643                 get_canvas_interface()->signal_layer_param_changed()(layer,"radius1");
644
645                 layer->set_param("radius2",(p2-p1).mag()/2);
646                 get_canvas_interface()->signal_layer_param_changed()(layer,"radius2");
647
648                 layer->set_param("angle",offset);
649                 get_canvas_interface()->signal_layer_param_changed()(layer,"angle");
650
651                 layer->set_param("points",points);
652                 get_canvas_interface()->signal_layer_param_changed()(layer,"points");
653
654                 layer->set_param("regular_polygon",regular);
655                 get_canvas_interface()->signal_layer_param_changed()(layer,"regular_polygon");
656
657                 layer->set_param("feather",get_feather());
658                 get_canvas_interface()->signal_layer_param_changed()(layer,"feather");
659
660                 layer->set_param("invert",get_invert());
661                 get_canvas_interface()->signal_layer_param_changed()(layer,"invert");
662
663                 layer->set_description(get_id());
664                 get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
665
666                 if(get_layer_outline_flag())
667                 {
668                         layer->set_param("color",synfigapp::Main::get_background_color());
669                         get_canvas_interface()->signal_layer_param_changed()(layer,"color");
670                 }
671         }
672
673         ///////////////////////////////////////////////////////////////////////////
674         //   C U R V E   G R A D I E N T
675         ///////////////////////////////////////////////////////////////////////////
676
677         if(get_layer_curve_gradient_flag())
678         {
679                 synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
680
681                 Layer::Handle layer(get_canvas_interface()->add_layer_to("curve_gradient",canvas,depth));
682                 assert(layer);
683                 layer_selection.push_back(layer);
684                 layer->set_description(get_id()+_(" Gradient"));
685                 get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
686
687                 {
688                         synfigapp::Action::Handle action(synfigapp::Action::create("layer_param_connect"));
689                         assert(action);
690
691                         action->set_param("canvas",get_canvas());
692                         action->set_param("canvas_interface",get_canvas_interface());
693                         action->set_param("layer",layer);
694                         if(!action->set_param("param",String("bline")))
695                                 synfig::error("LayerParamConnect didn't like \"param\"");
696                         if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
697                                 synfig::error("LayerParamConnect didn't like \"value_node\"");
698
699                         if(!get_canvas_interface()->get_instance()->perform_action(action))
700                         {
701                                 //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
702                                 group.cancel();
703                                 throw String(_("Unable to create Gradient layer"));
704                                 return;
705                         }
706                 }
707
708                 // only link the curve gradient's origin parameter if the option is selected and we're creating more than one layer
709                 if (get_layer_link_origins_flag() && layers_to_create > 1)
710                 {
711                         synfigapp::Action::Handle action(synfigapp::Action::create("layer_param_connect"));
712                         assert(action);
713
714                         action->set_param("canvas",get_canvas());
715                         action->set_param("canvas_interface",get_canvas_interface());
716                         action->set_param("layer",layer);
717                         if(!action->set_param("param",String("origin")))
718                                 synfig::error("LayerParamConnect didn't like \"param\"");
719                         if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
720                                 synfig::error("LayerParamConnect didn't like \"value_node\"");
721
722                         if(!get_canvas_interface()->get_instance()->perform_action(action))
723                         {
724                                 //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
725                                 group.cancel();
726                                 throw String(_("Unable to create Gradient layer"));
727                                 return;
728                         }
729                 }
730         }
731
732         ///////////////////////////////////////////////////////////////////////////
733         //   P L A N T
734         ///////////////////////////////////////////////////////////////////////////
735
736         if(get_layer_plant_flag())
737         {
738                 synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
739
740                 Layer::Handle layer(get_canvas_interface()->add_layer_to("plant",canvas,depth));
741                 assert(layer);
742                 layer_selection.push_back(layer);
743                 layer->set_description(get_id()+_(" Plant"));
744                 get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
745
746                 {
747                         synfigapp::Action::Handle action(synfigapp::Action::create("layer_param_connect"));
748                         assert(action);
749
750                         action->set_param("canvas",get_canvas());
751                         action->set_param("canvas_interface",get_canvas_interface());
752                         action->set_param("layer",layer);
753                         if(!action->set_param("param",String("bline")))
754                                 synfig::error("LayerParamConnect didn't like \"param\"");
755                         if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
756                                 synfig::error("LayerParamConnect didn't like \"value_node\"");
757
758                         if(!get_canvas_interface()->get_instance()->perform_action(action))
759                         {
760                                 //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
761                                 group.cancel();
762                                 throw String(_("Unable to create Plant layer"));
763                                 return;
764                         }
765                 }
766
767                 // only link the plant's origin parameter if the option is selected and we're creating more than one layer
768                 if (get_layer_link_origins_flag() && layers_to_create > 1)
769                 {
770                         synfigapp::Action::Handle action(synfigapp::Action::create("layer_param_connect"));
771                         assert(action);
772
773                         action->set_param("canvas",get_canvas());
774                         action->set_param("canvas_interface",get_canvas_interface());
775                         action->set_param("layer",layer);
776                         if(!action->set_param("param",String("origin")))
777                                 synfig::error("LayerParamConnect didn't like \"param\"");
778                         if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
779                                 synfig::error("LayerParamConnect didn't like \"value_node\"");
780
781                         if(!get_canvas_interface()->get_instance()->perform_action(action))
782                         {
783                                 //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
784                                 group.cancel();
785                                 throw String(_("Unable to create Plant layer"));
786                                 return;
787                         }
788                 }
789         }
790
791         ///////////////////////////////////////////////////////////////////////////
792         //   R E G I O N
793         ///////////////////////////////////////////////////////////////////////////
794
795         if(get_layer_region_flag())
796         {
797                 synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
798
799                 Layer::Handle layer(get_canvas_interface()->add_layer_to("region",canvas,depth));
800                 assert(layer);
801                 layer_selection.push_back(layer);
802                 layer->set_description(get_id()+_(" Region"));
803                 get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
804
805                 layer->set_param("feather",get_feather());
806                 get_canvas_interface()->signal_layer_param_changed()(layer,"feather");
807
808                 layer->set_param("invert",get_invert());
809                 get_canvas_interface()->signal_layer_param_changed()(layer,"invert");
810
811                 if(get_layer_outline_flag())
812                         layer->set_param("color",synfigapp::Main::get_background_color());
813
814                 // I don't know if it's safe to reuse the same layer_param_connect action, so I'm
815                 // using 2 separate ones.
816                 {
817                         synfigapp::Action::Handle action(synfigapp::Action::create("layer_param_connect"));
818                         assert(action);
819
820                         action->set_param("canvas",get_canvas());
821                         action->set_param("canvas_interface",get_canvas_interface());
822                         action->set_param("layer",layer);
823                         if(!action->set_param("param",String("bline")))
824                                 synfig::error("LayerParamConnect didn't like \"param\"");
825                         if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
826                                 synfig::error("LayerParamConnect didn't like \"value_node\"");
827
828                         if(!get_canvas_interface()->get_instance()->perform_action(action))
829                         {
830                                 //get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer"));
831                                 group.cancel();
832                                 throw String(_("Unable to create Region layer"));
833                                 return;
834                         }
835                 }
836
837                 // only link the region's origin parameter if the option is selected and we're creating more than one layer
838                 if (get_layer_link_origins_flag() && layers_to_create > 1)
839                 {
840                         synfigapp::Action::Handle action(synfigapp::Action::create("layer_param_connect"));
841                         assert(action);
842
843                         action->set_param("canvas",get_canvas());
844                         action->set_param("canvas_interface",get_canvas_interface());
845                         action->set_param("layer",layer);
846                         if(!action->set_param("param",String("origin")))
847                                 synfig::error("LayerParamConnect didn't like \"param\"");
848                         if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
849                                 synfig::error("LayerParamConnect didn't like \"value_node\"");
850
851                         if(!get_canvas_interface()->get_instance()->perform_action(action))
852                         {
853                                 //get_canvas_view()->get_ui_interface()->error(_("Unable to create Region layer"));
854                                 group.cancel();
855                                 throw String(_("Unable to create Region layer"));
856                                 return;
857                         }
858                 }
859         }
860
861         ///////////////////////////////////////////////////////////////////////////
862         //   O U T L I N E
863         ///////////////////////////////////////////////////////////////////////////
864
865         if (get_layer_outline_flag())
866         {
867                 Layer::Handle layer(get_canvas_interface()->add_layer_to("outline",canvas,depth));
868                 assert(layer);
869                 layer_selection.push_back(layer);
870                 layer->set_description(get_id()+_(" Outline"));
871                 get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
872
873                 layer->set_param("feather",get_feather());
874                 get_canvas_interface()->signal_layer_param_changed()(layer,"feather");
875
876                 layer->set_param("invert",get_invert());
877                 get_canvas_interface()->signal_layer_param_changed()(layer,"invert");
878
879                 {
880                         synfigapp::Action::Handle action(synfigapp::Action::create("layer_param_connect"));
881                         assert(action);
882
883                         action->set_param("canvas",get_canvas());
884                         action->set_param("canvas_interface",get_canvas_interface());
885                         action->set_param("layer",layer);
886                         if(!action->set_param("param",String("bline")))
887                                 synfig::error("LayerParamConnect didn't like \"param\"");
888                         if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
889                                 synfig::error("LayerParamConnect didn't like \"value_node\"");
890
891                         if(!get_canvas_interface()->get_instance()->perform_action(action))
892                         {
893                                 //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
894                                 group.cancel();
895                                 throw String(_("Unable to create Outline layer"));
896                                 return;
897                         }
898                 }
899
900                 // only link the outline's origin parameter if the option is selected and we're creating more than one layer
901                 if (get_layer_link_origins_flag() && layers_to_create > 1)
902                 {
903                         synfigapp::Action::Handle action(synfigapp::Action::create("layer_param_connect"));
904                         assert(action);
905
906                         action->set_param("canvas",get_canvas());
907                         action->set_param("canvas_interface",get_canvas_interface());
908                         action->set_param("layer",layer);
909                         if(!action->set_param("param",String("origin")))
910                                 synfig::error("LayerParamConnect didn't like \"param\"");
911                         if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
912                                 synfig::error("LayerParamConnect didn't like \"value_node\"");
913
914                         if(!get_canvas_interface()->get_instance()->perform_action(action))
915                         {
916                                 //get_canvas_view()->get_ui_interface()->error(_("Unable to create BLine layer"));
917                                 group.cancel();
918                                 throw String(_("Unable to create Outline layer"));
919                                 return;
920                         }
921                 }
922         }
923
924         egress_on_selection_change=false;
925         get_canvas_interface()->get_selection_manager()->clear_selected_layers();
926         get_canvas_interface()->get_selection_manager()->set_selected_layers(layer_selection);
927         egress_on_selection_change=true;
928
929         reset();
930         increment_id();
931 }
932
933 Smach::event_result
934 StateStar_Context::event_mouse_click_handler(const Smach::event& x)
935 {
936         const EventMouse& event(*reinterpret_cast<const EventMouse*>(&x));
937
938         if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_DOWN && event.button==BUTTON_LEFT)
939         {
940                 point_holder=get_work_area()->snap_point_to_grid(event.pos);
941                 etl::handle<Duck> duck=new Duck();
942                 duck->set_point(point_holder);
943                 duck->set_name("p1");
944                 duck->set_type(Duck::TYPE_POSITION);
945                 duck->set_editable(false);
946                 get_work_area()->add_duck(duck);
947
948                 point2_duck=new Duck();
949                 point2_duck->set_point(Vector(0,0));
950                 point2_duck->set_name("radius");
951                 point2_duck->set_origin(duck);
952                 point2_duck->set_radius(true);
953                 point2_duck->set_scalar(-1);
954                 point2_duck->set_type(Duck::TYPE_RADIUS);
955                 point2_duck->set_hover(true);
956                 get_work_area()->add_duck(point2_duck);
957
958                 return Smach::RESULT_ACCEPT;
959         }
960
961         if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_DRAG && event.button==BUTTON_LEFT)
962         {
963                 if (!point2_duck) return Smach::RESULT_OK;
964                 point2_duck->set_point(point_holder-get_work_area()->snap_point_to_grid(event.pos));
965                 get_work_area()->queue_draw();
966                 return Smach::RESULT_ACCEPT;
967         }
968
969         if(event.key==EVENT_WORKAREA_MOUSE_BUTTON_UP && event.button==BUTTON_LEFT)
970         {
971                 Point point(get_work_area()->snap_point_to_grid(event.pos));
972
973                 if (App::restrict_radius_ducks)
974                 {
975                         if ((point[0] - point_holder[0]) < 0) point[0] = point_holder[0];
976                         if ((point[1] - point_holder[1]) < 0) point[1] = point_holder[1];
977                 }
978
979                 make_star(point_holder, point);
980                 get_work_area()->clear_ducks();
981                 return Smach::RESULT_ACCEPT;
982         }
983
984         return Smach::RESULT_OK;
985 }
986
987
988 void
989 StateStar_Context::refresh_ducks()
990 {
991         get_work_area()->clear_ducks();
992         get_work_area()->queue_draw();
993 }