1 /* === S Y N F I G ========================================================= */
2 /*!	\file state_polygon.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) 2007, 2008 Chris Moore
10 **  Copyright (c) 2010 Carlos López
11 **
12 **	This package is free software; you can redistribute it and/or
13 **	modify it under the terms of the GNU General Public License as
14 **	published by the Free Software Foundation; either version 2 of
15 **	the License, or (at your option) any later version.
16 **
17 **	This package is distributed in the hope that it will be useful,
18 **	but WITHOUT ANY WARRANTY; without even the implied warranty of
19 **	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 **	General Public License for more details.
21 **	\endlegal
22 */
23 /* ========================================================================= */
24 
25 /* === H E A D E R S ======================================================= */
26 
27 #ifdef USING_PCH
28 #	include "pch.h"
29 #else
30 #ifdef HAVE_CONFIG_H
31 #	include <config.h>
32 #endif
33 
34 #include <synfig/general.h>
35 
36 #include <synfig/valuenodes/valuenode_dynamiclist.h>
37 #include <synfigapp/action_system.h>
38 #include <synfig/valuenodes/valuenode_bline.h>
39 
40 #include "state_polygon.h"
41 #include "state_normal.h"
42 #include "canvasview.h"
43 #include "workarea.h"
44 #include "app.h"
45 
46 #include <synfigapp/action.h>
47 #include "event_mouse.h"
48 #include "event_layerclick.h"
49 #include "docks/dock_toolbox.h"
50 #include "docks/dialog_tooloptions.h"
51 #include "widgets/widget_enum.h"
52 #include "widgets/widget_distance.h"
53 #include <synfigapp/main.h>
54 
55 #include <gui/localization.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 #ifndef LAYER_CREATION
69 #define LAYER_CREATION(button, stockid, tooltip)	\
70 	{ \
71 		Gtk::Image *icon = manage(new Gtk::Image(Gtk::StockID(stockid), \
72 			Gtk::ICON_SIZE_SMALL_TOOLBAR)); \
73 		button.add(*icon); \
74 	} \
75 	button.set_relief(Gtk::RELIEF_NONE); \
76 	button.set_tooltip_text(tooltip) ;\
77 	button.signal_toggled().connect(sigc::mem_fun(*this, \
78 		&studio::StatePolygon_Context::toggle_layer_creation))
79 #endif
80 
81 // indentation for options layout
82 #ifndef SPACING
83 #define SPACING(name, px) \
84 	Gtk::Alignment *name = Gtk::manage(new Gtk::Alignment()); \
85 	name->set_size_request(px)
86 #endif
87 
88 #define GAP	(3)
89 #define INDENTATION (6)
90 
91 /* === G L O B A L S ======================================================= */
92 
93 StatePolygon studio::state_polygon;
94 
95 /* === C L A S S E S & S T R U C T S ======================================= */
96 
97 class studio::StatePolygon_Context : public sigc::trackable
98 {
99 	etl::handle<CanvasView> canvas_view_;
100 	CanvasView::IsWorking is_working;
101 
102 	bool prev_table_status;
103 	bool prev_workarea_layer_status_;
104 
105 	Duckmatic::Push duckmatic_push;
106 
107 	std::list<synfig::Point> polygon_point_list;
108 
109 	bool on_polygon_duck_change(const studio::Duck &duck, std::list<synfig::Point>::iterator iter);
110 	void popup_handle_menu(synfigapp::ValueDesc value_desc);
111 	void refresh_ducks();
112 
113 	//Toolbox settings
114 	synfigapp::Settings& settings;
115 
116 	// holder of options
117 	Gtk::Table options_table;
118 
119 	// title
120 	Gtk::Label title_label;
121 
122 	// layer name:
123 	Gtk::Label id_label;
124 	Gtk::HBox id_box;
125 	Gtk::Entry id_entry;
126 
127 	// layer types to create:
128 	Gtk::Label layer_types_label;
129 	Gtk::ToggleButton layer_polygon_togglebutton;
130 	Gtk::ToggleButton layer_region_togglebutton;
131 	Gtk::ToggleButton layer_outline_togglebutton;
132 	Gtk::ToggleButton layer_advanced_outline_togglebutton;
133 	Gtk::ToggleButton layer_curve_gradient_togglebutton;
134 	Gtk::ToggleButton layer_plant_togglebutton;
135 	Gtk::HBox layer_types_box;
136 
137 	// blend method
138 	Gtk::Label blend_label;
139 	Gtk::HBox blend_box;
140 	Widget_Enum blend_enum;
141 
142 	// opacity
143 	Gtk::Label opacity_label;
144 	Gtk::HScale opacity_hscl;
145 
146 	// brush size
147 	Gtk::Label bline_width_label;
148 	Widget_Distance bline_width_dist;
149 
150 	// invert
151 	Gtk::Label invert_label;
152 	Gtk::CheckButton invert_checkbutton;
153 	Gtk::HBox invert_box;
154 
155 	// feather size
156 	Gtk::Label feather_label;
157 	Widget_Distance feather_dist;
158 
159 	// link origins
160 	Gtk::Label link_origins_label;
161 	Gtk::CheckButton layer_link_origins_checkbutton;
162 	Gtk::HBox link_origins_box;
163 
164 	// spline origins at center
165 	Gtk::Label origins_at_center_label;
166 	Gtk::CheckButton layer_origins_at_center_checkbutton;
167 	Gtk::HBox origins_at_center_box;
168 
169 	// toolbar buttons
170 	Gtk::Button button_make;
171 
172 public:
173 
174 	// this counts the layers we create - they all have origins we can link
layers_to_create() const175 	int layers_to_create()const
176 	{
177 		return
178 			get_layer_polygon_flag() +
179 			get_layer_region_flag() +
180 			get_layer_outline_flag() +
181 			get_layer_advanced_outline_flag() +
182 			get_layer_curve_gradient_flag() +
183 			get_layer_plant_flag();
184 	}
185 
get_id() const186 	synfig::String get_id()const { return id_entry.get_text(); }
set_id(const synfig::String & x)187 	void set_id(const synfig::String& x) { return id_entry.set_text(x); }
188 
get_blend() const189 	int get_blend()const { return blend_enum.get_value(); }
set_blend(int x)190 	void set_blend(int x) { return blend_enum.set_value(x); }
191 
get_opacity() const192 	Real get_opacity()const { return opacity_hscl.get_value(); }
set_opacity(Real x)193 	void set_opacity(Real x) { opacity_hscl.set_value(x); }
194 
get_bline_width() const195 	Real get_bline_width() const {
196 		return bline_width_dist.get_value().get(
197 			Distance::SYSTEM_UNITS,
198 			get_canvas_view()->get_canvas()->rend_desc()
199 		);
200 	}
set_bline_width(Distance x)201 	void set_bline_width(Distance x) { return bline_width_dist.set_value(x);}
202 
get_feather_size() const203 	Real get_feather_size() const {
204 		return feather_dist.get_value().get(
205 			Distance::SYSTEM_UNITS,
206 			get_canvas_view()->get_canvas()->rend_desc()
207 		);
208 	}
set_feather_size(Distance x)209 	void set_feather_size(Distance x) { return feather_dist.set_value(x);}
210 
get_invert() const211 	bool get_invert()const { return invert_checkbutton.get_active(); }
set_invert(bool i)212 	void set_invert(bool i) { invert_checkbutton.set_active(i); }
213 
get_layer_polygon_flag() const214 	bool get_layer_polygon_flag()const { return layer_polygon_togglebutton.get_active(); }
set_layer_polygon_flag(bool x)215 	void set_layer_polygon_flag(bool x) { return layer_polygon_togglebutton.set_active(x); }
216 
get_layer_region_flag() const217 	bool get_layer_region_flag()const { return layer_region_togglebutton.get_active(); }
set_layer_region_flag(bool x)218 	void set_layer_region_flag(bool x) { return layer_region_togglebutton.set_active(x); }
219 
get_layer_outline_flag() const220 	bool get_layer_outline_flag()const { return layer_outline_togglebutton.get_active(); }
set_layer_outline_flag(bool x)221 	void set_layer_outline_flag(bool x) { return layer_outline_togglebutton.set_active(x); }
222 
get_layer_advanced_outline_flag() const223 	bool get_layer_advanced_outline_flag()const { return layer_advanced_outline_togglebutton.get_active(); }
set_layer_advanced_outline_flag(bool x)224 	void set_layer_advanced_outline_flag(bool x) { return layer_advanced_outline_togglebutton.set_active(x); }
225 
get_layer_curve_gradient_flag() const226 	bool get_layer_curve_gradient_flag()const { return layer_curve_gradient_togglebutton.get_active(); }
set_layer_curve_gradient_flag(bool x)227 	void set_layer_curve_gradient_flag(bool x) { return layer_curve_gradient_togglebutton.set_active(x); }
228 
get_layer_plant_flag() const229 	bool get_layer_plant_flag()const { return layer_plant_togglebutton.get_active(); }
set_layer_plant_flag(bool x)230 	void set_layer_plant_flag(bool x) { return layer_plant_togglebutton.set_active(x); }
231 
get_layer_link_origins_flag() const232 	bool get_layer_link_origins_flag()const { return layer_link_origins_checkbutton.get_active(); }
set_layer_link_origins_flag(bool x)233 	void set_layer_link_origins_flag(bool x) { return layer_link_origins_checkbutton.set_active(x); }
234 
235   bool layer_polygon_flag;
236   bool layer_region_flag;
237   bool layer_outline_flag;
238   bool layer_advanced_outline_flag;
239   bool layer_curve_gradient_flag;
240   bool layer_plant_flag;
241 
242 	Smach::event_result event_stop_handler(const Smach::event& x);
243 
244 	Smach::event_result event_refresh_handler(const Smach::event& x);
245 
246 	Smach::event_result event_mouse_click_handler(const Smach::event& x);
247 	Smach::event_result event_refresh_tool_options(const Smach::event& x);
248 	void refresh_tool_options();
249 
250 	StatePolygon_Context(CanvasView* canvas_view);
251 
252 	~StatePolygon_Context();
253 
get_canvas_view() const254 	const etl::handle<CanvasView>& get_canvas_view()const{return canvas_view_;}
get_canvas_interface() const255 	etl::handle<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view_->canvas_interface();}
get_canvas() const256 	synfig::Canvas::Handle get_canvas()const{return canvas_view_->get_canvas();}
get_work_area() const257 	WorkArea * get_work_area()const{return canvas_view_->get_work_area();}
258 
259 	//void on_user_click(synfig::Point point);
260 	void load_settings();
261 	void save_settings();
262 	void reset();
263 	void increment_id();
264 	bool egress_on_selection_change;
event_layer_selection_changed_handler(const Smach::event &)265 	Smach::event_result event_layer_selection_changed_handler(const Smach::event& /*x*/)
266 	{
267 		if(egress_on_selection_change)
268 			throw &state_normal;
269 		return Smach::RESULT_OK;
270 	}
271 
272 	void run();
273 	void toggle_layer_creation();
274 
275 };	// END of class StatePolygon_Context
276 
277 /* === M E T H O D S ======================================================= */
278 
StatePolygon()279 StatePolygon::StatePolygon():
280 	Smach::state<StatePolygon_Context>("polygon")
281 {
282 	insert(event_def(EVENT_LAYER_SELECTION_CHANGED,&StatePolygon_Context::event_layer_selection_changed_handler));
283 	insert(event_def(EVENT_STOP,&StatePolygon_Context::event_stop_handler));
284 	insert(event_def(EVENT_REFRESH,&StatePolygon_Context::event_refresh_handler));
285 	insert(event_def(EVENT_REFRESH_DUCKS,&StatePolygon_Context::event_refresh_handler));
286 	insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StatePolygon_Context::event_mouse_click_handler));
287 	insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StatePolygon_Context::event_refresh_tool_options));
288 }
289 
~StatePolygon()290 StatePolygon::~StatePolygon()
291 {
292 }
293 
294 void
load_settings()295 StatePolygon_Context::load_settings()
296 {
297 	try
298 	{
299 		synfig::ChangeLocale change_locale(LC_NUMERIC, "C");
300 		String value;
301 
302 		if(settings.get_value("polygon.id",value))
303 			set_id(value);
304 		else
305 			set_id("Polygon");
306 
307 		if(settings.get_value("polygon.blend",value) && value != "")
308 			set_blend(atoi(value.c_str()));
309 		else
310 			set_blend(0);//(int)Color::BLEND_COMPOSITE); //0 should be blend composites value
311 
312 		if(settings.get_value("polygon.opacity",value))
313 			set_opacity(atof(value.c_str()));
314 		else
315 			set_opacity(1);
316 
317 		if(settings.get_value("polygon.bline_width",value) && value != "")
318 			set_bline_width(Distance(atof(value.c_str()), App::distance_system));
319 		else
320 			set_bline_width(Distance(1, App::distance_system)); // default width
321 
322 		if(settings.get_value("polygon.feather",value))
323 			set_feather_size(Distance(atof(value.c_str()), App::distance_system));
324 		else
325 			set_feather_size(Distance(0, App::distance_system)); // default feather
326 
327 		if(settings.get_value("polygon.invert",value) && value != "0")
328 			set_invert(true);
329 		else
330 			set_invert(false);
331 
332 		if(settings.get_value("polygon.layer_polygon",value) && value=="0")
333 			set_layer_polygon_flag(false);
334 		else
335 			set_layer_polygon_flag(true);
336 
337 		if(settings.get_value("polygon.layer_region",value) && value=="1")
338 			set_layer_region_flag(true);
339 		else
340 			set_layer_region_flag(false);
341 
342 		if(settings.get_value("polygon.layer_outline",value) && value=="1")
343 			set_layer_outline_flag(true);
344 		else
345 			set_layer_outline_flag(false);
346 
347 		if(settings.get_value("polygon.layer_advanced_outline",value) && value=="1")
348 			set_layer_advanced_outline_flag(true);
349 		else
350 			set_layer_advanced_outline_flag(false);
351 
352 		if(settings.get_value("polygon.layer_curve_gradient",value) && value=="1")
353 			set_layer_curve_gradient_flag(true);
354 		else
355 			set_layer_curve_gradient_flag(false);
356 
357 		if(settings.get_value("polygon.layer_plant",value) && value=="1")
358 			set_layer_plant_flag(true);
359 		else
360 			set_layer_plant_flag(false);
361 
362 		if(settings.get_value("polygon.layer_link_origins",value) && value=="0")
363 			set_layer_link_origins_flag(false);
364 		else
365 			set_layer_link_origins_flag(true);
366 
367 	  // determine layer flags
368 		layer_polygon_flag = get_layer_polygon_flag();
369 	  layer_region_flag = get_layer_region_flag();
370 	  layer_outline_flag = get_layer_outline_flag();
371 	  layer_advanced_outline_flag = get_layer_outline_flag();
372 	  layer_curve_gradient_flag = get_layer_curve_gradient_flag();
373 	  layer_plant_flag = get_layer_plant_flag();
374 	}
375 	catch(...)
376 	{
377 		synfig::warning("State Polygon: Caught exception when attempting to load settings.");
378 	}
379 }
380 
381 void
save_settings()382 StatePolygon_Context::save_settings()
383 {
384 	try
385 	{
386 		synfig::ChangeLocale change_locale(LC_NUMERIC, "C");
387 		settings.set_value("polygon.id",get_id().c_str());
388 		settings.set_value("polygon.blend",strprintf("%d",get_blend()));
389 		settings.set_value("polygon.opacity",strprintf("%f",(float)get_opacity()));
390 		settings.set_value("polygon.bline_width", bline_width_dist.get_value().get_string());
391 		settings.set_value("polygon.feather", feather_dist.get_value().get_string());
392 		settings.set_value("polygon.invert",get_invert()?"1":"0");
393 		settings.set_value("polygon.layer_polygon",get_layer_polygon_flag()?"1":"0");
394 		settings.set_value("polygon.layer_outline",get_layer_outline_flag()?"1":"0");
395 		settings.set_value("polygon.layer_advanced_outline",get_layer_advanced_outline_flag()?"1":"0");
396 		settings.set_value("polygon.layer_region",get_layer_region_flag()?"1":"0");
397 		settings.set_value("polygon.layer_curve_gradient",get_layer_curve_gradient_flag()?"1":"0");
398 		settings.set_value("polygon.layer_plant",get_layer_plant_flag()?"1":"0");
399 		settings.set_value("polygon.layer_link_origins",get_layer_link_origins_flag()?"1":"0");
400 	}
401 	catch(...)
402 	{
403 		synfig::warning("State Polygon: Caught exception when attempting to save settings.");
404 	}
405 }
406 
407 void
reset()408 StatePolygon_Context::reset()
409 {
410 	polygon_point_list.clear();
411 	refresh_ducks();
412 }
413 
414 void
increment_id()415 StatePolygon_Context::increment_id()
416 {
417 	String id(get_id());
418 	int number=1;
419 	int digits=0;
420 
421 	if(id.empty())
422 		id="Polygon";
423 
424 	// If there is a number
425 	// already at the end of the
426 	// id, then remove it.
427 	if(id[id.size()-1]<='9' && id[id.size()-1]>='0')
428 	{
429 		// figure out how many digits it is
430 		for (digits = 0;
431 			 (int)id.size()-1 >= digits && id[id.size()-1-digits] <= '9' && id[id.size()-1-digits] >= '0';
432 			 digits++)
433 			;
434 
435 		String str_number;
436 		str_number=String(id,id.size()-digits,id.size());
437 		id=String(id,0,id.size()-digits);
438 
439 		number=atoi(str_number.c_str());
440 	}
441 	else
442 	{
443 		number=1;
444 		digits=3;
445 	}
446 
447 	number++;
448 
449 	// Add the number back onto the id
450 	{
451 		const String format(strprintf("%%0%dd",digits));
452 		id+=strprintf(format.c_str(),number);
453 	}
454 
455 	// Set the ID
456 	set_id(id);
457 }
458 
StatePolygon_Context(CanvasView * canvas_view)459 StatePolygon_Context::StatePolygon_Context(CanvasView* canvas_view):
460 	canvas_view_(canvas_view),
461 	is_working(*canvas_view),
462 	prev_workarea_layer_status_(get_work_area()->get_allow_layer_clicks()),
463 	duckmatic_push(get_work_area()),
464 	settings(synfigapp::Main::get_selected_input_device()->settings()),
465 	opacity_hscl(0.0f, 1.0125f, 0.0125f),
466 	button_make(_("Make"))
467 {
468 	egress_on_selection_change=true;
469 
470 
471 	/* Set up the tool options dialog */
472 
473 	// 0, title
474 	title_label.set_label(_("Polygon Creation"));
475 	Pango::AttrList list;
476 	Pango::AttrInt attr = Pango::Attribute::create_attr_weight(Pango::WEIGHT_BOLD);
477 	list.insert(attr);
478 	title_label.set_attributes(list);
479 	title_label.set_alignment(Gtk::ALIGN_START, Gtk::ALIGN_CENTER);
480 
481 	// 1, layer name label and entry
482 	id_label.set_label(_("Name:"));
483 	id_label.set_alignment(Gtk::ALIGN_START, Gtk::ALIGN_CENTER);
484 	SPACING(id_gap, GAP);
485 	id_box.pack_start(id_label, Gtk::PACK_SHRINK);
486 	id_box.pack_start(*id_gap, Gtk::PACK_SHRINK);
487 
488 	id_box.pack_start(id_entry);
489 
490 	// 2, layer types creation
491 	layer_types_label.set_label(_("Layer Type:"));
492 	layer_types_label.set_alignment(Gtk::ALIGN_START, Gtk::ALIGN_CENTER);
493 
494 	LAYER_CREATION(layer_polygon_togglebutton,
495 		("synfig-layer_geometry_polygon"), _("Create a polygon layer"));
496 
497 	LAYER_CREATION(layer_region_togglebutton,
498 		("synfig-layer_geometry_region"), _("Create a region layer"));
499 
500 	LAYER_CREATION(layer_outline_togglebutton,
501 		("synfig-layer_geometry_outline"), _("Create a outline layer"));
502 
503 	LAYER_CREATION(layer_advanced_outline_togglebutton,
504 		("synfig-layer_geometry_advanced_outline"), _("Create a advanced outline layer"));
505 
506 	LAYER_CREATION(layer_plant_togglebutton,
507 		("synfig-layer_other_plant"), _("Create a plant layer"));
508 
509 	LAYER_CREATION(layer_curve_gradient_togglebutton,
510 		("synfig-layer_gradient_curve"), _("Create a gradient layer"));
511 
512 	SPACING(layer_types_indent, INDENTATION);
513 
514 	layer_types_box.pack_start(*layer_types_indent, Gtk::PACK_SHRINK);
515 	layer_types_box.pack_start(layer_polygon_togglebutton, Gtk::PACK_SHRINK);
516 	layer_types_box.pack_start(layer_region_togglebutton, Gtk::PACK_SHRINK);
517 	layer_types_box.pack_start(layer_outline_togglebutton, Gtk::PACK_SHRINK);
518 	layer_types_box.pack_start(layer_advanced_outline_togglebutton, Gtk::PACK_SHRINK);
519 	layer_types_box.pack_start(layer_plant_togglebutton, Gtk::PACK_SHRINK);
520 	layer_types_box.pack_start(layer_curve_gradient_togglebutton, Gtk::PACK_SHRINK);
521 
522 	// 3, blend method label and dropdown list
523 	blend_label.set_label(_("Blend Method:"));
524 	blend_label.set_alignment(Gtk::ALIGN_START, Gtk::ALIGN_CENTER);
525 	SPACING(blend_gap, GAP);
526 	blend_box.pack_start(blend_label, Gtk::PACK_SHRINK);
527 	blend_box.pack_start(*blend_gap, Gtk::PACK_SHRINK);
528 
529 	blend_enum.set_param_desc(ParamDesc(Color::BLEND_COMPOSITE,"blend_method")
530 		.set_local_name(_("Blend Method"))
531 		.set_description(_("Defines the blend method to be used for polygons")));
532 
533 	// 4, opacity label and slider
534 	opacity_label.set_label(_("Opacity:"));
535 	opacity_label.set_alignment(Gtk::ALIGN_START, Gtk::ALIGN_CENTER);
536 
537 	opacity_hscl.set_digits(2);
538 	opacity_hscl.set_value_pos(Gtk::POS_LEFT);
539 	opacity_hscl.set_tooltip_text(_("Opacity"));
540 
541 	// 5, brush size
542 	bline_width_label.set_label(_("Brush Size:"));
543 	bline_width_label.set_alignment(Gtk::ALIGN_START, Gtk::ALIGN_CENTER);
544 	bline_width_label.set_sensitive(false);
545 
546 	bline_width_dist.set_digits(2);
547 	bline_width_dist.set_range(0,10000000);
548 	bline_width_dist.set_sensitive(false);
549 
550 	// 6, invert
551 	invert_label.set_label(_("Invert"));
552 	invert_label.set_alignment(Gtk::ALIGN_START, Gtk::ALIGN_CENTER);
553 
554 	invert_box.pack_start(invert_label);
555 	invert_box.pack_end(invert_checkbutton, Gtk::PACK_SHRINK);
556 	invert_box.set_sensitive(false);
557 
558 	// 7, feather
559 	feather_label.set_label(_("Feather:"));
560 	feather_label.set_alignment(Gtk::ALIGN_START, Gtk::ALIGN_CENTER);
561 	feather_label.set_sensitive(false);
562 
563 	feather_dist.set_digits(2);
564 	feather_dist.set_range(0,10000000);
565 	feather_dist.set_sensitive(false);
566 
567 	// 8, link origins
568 	link_origins_label.set_label(_("Link Origins"));
569 	link_origins_label.set_alignment(Gtk::ALIGN_START, Gtk::ALIGN_CENTER);
570 
571 	link_origins_box.pack_start(link_origins_label);
572 	link_origins_box.pack_end(layer_link_origins_checkbutton, Gtk::PACK_SHRINK);
573 	link_origins_box.set_sensitive(false);
574 
575 	load_settings();
576 
577 	// pack all options to the options_table
578 
579 	// 0, title
580 	options_table.attach(title_label,
581 		0, 2, 0, 1, Gtk::FILL, Gtk::FILL, 0, 0
582 		);
583 	// 1, name
584 	options_table.attach(id_box,
585 		0, 2, 1, 2, Gtk::FILL, Gtk::FILL, 0, 0
586 		);
587 	// 2, layer types creation
588 	options_table.attach(layer_types_label,
589 		0, 2, 2, 3, Gtk::FILL, Gtk::FILL, 0, 0
590 		);
591 	options_table.attach(layer_types_box,
592 		0, 2, 3, 4, Gtk::FILL, Gtk::FILL, 0, 0
593 		);
594 	// 3, blend method
595 	options_table.attach(blend_box,
596 		0, 1, 4, 5, Gtk::EXPAND|Gtk::FILL, Gtk::FILL, 0, 0
597 		);
598 	options_table.attach(blend_enum,
599 		1, 2, 4, 5, Gtk::EXPAND|Gtk::FILL, Gtk::FILL, 0, 0
600 		);
601 	// 4, opacity
602 	options_table.attach(opacity_label,
603 		0, 1, 5, 6, Gtk::EXPAND|Gtk::FILL, Gtk::FILL, 0, 0
604 		);
605 	options_table.attach(opacity_hscl,
606 		1, 2, 5, 6, Gtk::EXPAND|Gtk::FILL, Gtk::FILL, 0, 0
607 		);
608 	// 5, brush size
609 	options_table.attach(bline_width_label,
610 		0, 1, 6, 7, Gtk::EXPAND|Gtk::FILL, Gtk::FILL, 0, 0
611 		);
612 	options_table.attach(bline_width_dist,
613 		1, 2, 6, 7, Gtk::EXPAND|Gtk::FILL, Gtk::FILL, 0, 0
614 		);
615 	// 6, invert
616 	options_table.attach(invert_box,
617 		0, 2, 7, 8, Gtk::EXPAND|Gtk::FILL, Gtk::FILL, 0, 0
618 		);
619 	// 7, feather
620 	options_table.attach(feather_label,
621 		0, 1, 8, 9, Gtk::EXPAND|Gtk::FILL, Gtk::FILL, 0, 0
622 		);
623 	options_table.attach(feather_dist,
624 		1, 2, 8, 9, Gtk::EXPAND|Gtk::FILL, Gtk::FILL, 0, 0
625 		);
626 	// 8, link origins
627 	options_table.attach(link_origins_box,
628 		0, 2, 9, 10, Gtk::FILL, Gtk::FILL, 0, 0
629 		);
630 
631 	// fine-tune options layout
632 	options_table.set_border_width(GAP*2); // border width
633 	options_table.set_row_spacings(GAP); // row gap
634 	options_table.set_row_spacing(0, GAP*2); // the gap between first and second row.
635 	options_table.set_row_spacing(2, 1); // row gap between label and icon of layer type
636 	//options_table.set_row_spacing(9, 0); // the final row using border width of table
637 	options_table.set_margin_bottom(0);
638 
639 	options_table.show_all();
640 
641 	button_make.signal_pressed().connect(sigc::mem_fun(*this,&StatePolygon_Context::run));
642 	refresh_tool_options();
643 	App::dialog_tool_options->present();
644 
645 
646 	// Turn off layer clicking
647 	get_work_area()->set_allow_layer_clicks(false);
648 
649 	// clear out the ducks
650 	get_work_area()->clear_ducks();
651 
652 	// Refresh the work area
653 	get_work_area()->queue_draw();
654 
655 	get_work_area()->set_cursor(Gdk::CROSSHAIR);
656 
657 	// Hide the tables if they are showing
658 	prev_table_status=get_canvas_view()->tables_are_visible();
659 	if(prev_table_status)get_canvas_view()->hide_tables();
660 
661 	// Disable the time bar
662 	get_canvas_view()->set_sensitive_timebar(false);
663 
664 	App::dock_toolbox->refresh();
665 }
666 
667 void
refresh_tool_options()668 StatePolygon_Context::refresh_tool_options()
669 {
670 	App::dialog_tool_options->clear();
671 	App::dialog_tool_options->set_widget(options_table);
672 
673 	App::dialog_tool_options->set_local_name(_("Polygon Tool"));
674 	App::dialog_tool_options->set_name("polygon");
675 
676 	App::dialog_tool_options->add_button(
677 		Gtk::StockID("gtk-execute"),
678 		_("Make Polygon")
679 	)->signal_clicked().connect(
680 		sigc::mem_fun(
681 			*this,
682 			&StatePolygon_Context::run
683 		)
684 	);
685 
686 	App::dialog_tool_options->add_button(
687 		Gtk::StockID("gtk-clear"),
688 		_("Clear current Polygon")
689 	)->signal_clicked().connect(
690 		sigc::mem_fun(
691 			*this,
692 			&StatePolygon_Context::reset
693 		)
694 	);
695 }
696 
697 Smach::event_result
event_refresh_tool_options(const Smach::event &)698 StatePolygon_Context::event_refresh_tool_options(const Smach::event& /*x*/)
699 {
700 	refresh_tool_options();
701 	return Smach::RESULT_ACCEPT;
702 }
703 
~StatePolygon_Context()704 StatePolygon_Context::~StatePolygon_Context()
705 {
706 	run();
707 
708 	save_settings();
709 	// Restore layer clicking
710 	get_work_area()->set_allow_layer_clicks(prev_workarea_layer_status_);
711 
712 	App::dialog_tool_options->clear();
713 
714 	get_work_area()->reset_cursor();
715 
716 	// Enable the time bar
717 	get_canvas_view()->set_sensitive_timebar(true);
718 
719 	// Bring back the tables if they were out before
720 	if(prev_table_status)get_canvas_view()->show_tables();
721 
722 	// Refresh the work area
723 	get_work_area()->queue_draw();
724 
725 	App::dock_toolbox->refresh();
726 }
727 
728 Smach::event_result
event_stop_handler(const Smach::event &)729 StatePolygon_Context::event_stop_handler(const Smach::event& /*x*/)
730 {
731 	reset();
732 	return Smach::RESULT_ACCEPT;
733 
734 }
735 
736 Smach::event_result
event_refresh_handler(const Smach::event &)737 StatePolygon_Context::event_refresh_handler(const Smach::event& /*x*/)
738 {
739 	refresh_ducks();
740 	return Smach::RESULT_ACCEPT;
741 }
742 
743 void
run()744 StatePolygon_Context::run()
745 {
746 	if(polygon_point_list.empty())
747 		return;
748 
749 	if(polygon_point_list.size()<3)
750 	{
751 		get_canvas_view()->get_ui_interface()->error("You need at least 3 points to create a polygon");
752 		return;
753 	}
754 
755 	synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("New Polygon"));
756 
757 	Layer::Handle layer;
758 
759 	Canvas::Handle canvas;
760 	int depth(0);
761 
762 	// we are temporarily using the layer to hold something
763 	layer=get_canvas_view()->get_selection_manager()->get_selected_layer();
764 	if(layer)
765 	{
766 		depth=layer->get_depth();
767 		canvas=layer->get_canvas();
768 	}
769 
770 	synfigapp::SelectionManager::LayerList layer_selection;
771 	if (!getenv("SYNFIG_TOOLS_CLEAR_SELECTION"))
772 		layer_selection = get_canvas_view()->get_selection_manager()->get_selected_layers();
773 
774 	const synfig::TransformStack& transform(get_work_area()->get_curr_transform_stack());
775 
776 	std::vector<BLinePoint> new_list;
777 	std::list<synfig::Point>::iterator iter;
778 	int i;
779 	for(i=0,iter=polygon_point_list.begin();iter!=polygon_point_list.end();++iter,++i)
780 	{
781 		*iter = transform.unperform(*iter);
782 		new_list.push_back(*(new BLinePoint));
783 		new_list[i].set_width(1);
784 		new_list[i].set_vertex(*iter);
785 		new_list[i].set_tangent(Point(0,0));
786 	}
787 
788 	ValueNode_BLine::Handle value_node_bline(ValueNode_BLine::create(new_list));
789 	assert(value_node_bline);
790 
791 	ValueNode::Handle value_node_origin(ValueNode_Const::create(Vector()));
792 	assert(value_node_origin);
793 
794 	// Set the looping flag
795 	value_node_bline->set_loop(true);
796 
797 	if(!canvas)
798 		canvas=get_canvas_view()->get_canvas();
799 
800 	value_node_bline->set_member_canvas(canvas);
801 
802 	// count how many layers we're going to be creating
803 	int layers_to_create = this->layers_to_create();
804 
805 	///////////////////////////////////////////////////////////////////////////
806 	//   P O L Y G O N
807 	///////////////////////////////////////////////////////////////////////////
808 
809 	if (get_layer_polygon_flag())
810 	{
811 		egress_on_selection_change=false;
812 		layer=get_canvas_interface()->add_layer_to("polygon",canvas,depth);
813 		egress_on_selection_change=true;
814 		if (!layer)
815 		{
816 			get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
817 			group.cancel();
818 			return;
819 		}
820 		layer_selection.push_back(layer);
821 
822 		layer->set_param("invert",get_invert());
823 		get_canvas_interface()->signal_layer_param_changed()(layer,"invert");
824 
825 		if(get_feather_size())
826 		{
827 			layer->set_param("feather",get_feather_size());
828 			get_canvas_interface()->signal_layer_param_changed()(layer,"feather");
829 		}
830 
831 		layer->set_description(get_id());
832 		get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
833 
834 		layer->disconnect_dynamic_param("vector_list");
835 		if(!layer->set_param("vector_list",ValueBase::List(polygon_point_list.begin(), polygon_point_list.end())))
836 		{
837 			group.cancel();
838 			get_canvas_view()->get_ui_interface()->error("Unable to set layer parameter");
839 			return;
840 		}
841 
842 		{
843 			synfigapp::Action::Handle action(synfigapp::Action::create("ValueDescConvert"));
844 			synfigapp::ValueDesc value_desc(layer,"vector_list");
845 			action->set_param("canvas",get_canvas());
846 			action->set_param("canvas_interface",get_canvas_interface());
847 			action->set_param("value_desc",value_desc);
848 			action->set_param("type","dynamic_list");
849 			action->set_param("time",get_canvas_interface()->get_time());
850 			if(!get_canvas_interface()->get_instance()->perform_action(action))
851 			{
852 				group.cancel();
853 				get_canvas_view()->get_ui_interface()->error("Unable to execute action \"ValueDescConvert\"");
854 				return;
855 			}
856 		}
857 
858 		// only link the polygon's origin parameter if the option is selected and we're creating more than one layer
859 		if (get_layer_link_origins_flag() && layers_to_create > 1)
860 		{
861 			synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
862 			assert(action);
863 
864 			action->set_param("canvas",get_canvas());
865 			action->set_param("canvas_interface",get_canvas_interface());
866 			action->set_param("layer",layer);
867 			if(!action->set_param("param",String("origin")))
868 				synfig::error("LayerParamConnect didn't like \"param\"");
869 			if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
870 				synfig::error("LayerParamConnect didn't like \"value_node\"");
871 
872 			if(!get_canvas_interface()->get_instance()->perform_action(action))
873 			{
874 				get_canvas_view()->get_ui_interface()->error(_("Unable to create Polygon layer"));
875 				group.cancel();
876 				throw String(_("Unable to create Polygon layer"));
877 				return;
878 			}
879 		}
880 	}
881 
882 	///////////////////////////////////////////////////////////////////////////
883 	//   C U R V E   G R A D I E N T
884 	///////////////////////////////////////////////////////////////////////////
885 
886 	if(get_layer_curve_gradient_flag())
887 	{
888 		synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
889 
890 		egress_on_selection_change=false;
891 		Layer::Handle layer(get_canvas_interface()->add_layer_to("curve_gradient",canvas,depth));
892 		egress_on_selection_change=true;
893 		if (!layer)
894 		{
895 			get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
896 			group.cancel();
897 			return;
898 		}
899 		layer_selection.push_back(layer);
900 		layer->set_description(get_id()+_(" Gradient"));
901 		get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
902 
903 		layer->set_param("blend_method",get_blend());
904 		get_canvas_interface()->signal_layer_param_changed()(layer,"blend_method");
905 
906 		layer->set_param("amount",get_opacity());
907 		get_canvas_interface()->signal_layer_param_changed()(layer,"amount");
908 
909 		layer->set_param("width",get_bline_width());
910 		get_canvas_interface()->signal_layer_param_changed()(layer,"width");
911 
912 		{
913 			synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
914 			assert(action);
915 
916 			action->set_param("canvas",get_canvas());
917 			action->set_param("canvas_interface",get_canvas_interface());
918 			action->set_param("layer",layer);
919 			if(!action->set_param("param",String("bline")))
920 				synfig::error("LayerParamConnect didn't like \"param\"");
921 			if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
922 				synfig::error("LayerParamConnect didn't like \"value_node\"");
923 
924 			if(!get_canvas_interface()->get_instance()->perform_action(action))
925 			{
926 				group.cancel();
927 				throw String(_("Unable to create Gradient layer"));
928 				return;
929 			}
930 		}
931 
932 		// only link the curve gradient's origin parameter if the option is selected and we're creating more than one layer
933 		if (get_layer_link_origins_flag() && layers_to_create > 1)
934 		{
935 			synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
936 			assert(action);
937 
938 			action->set_param("canvas",get_canvas());
939 			action->set_param("canvas_interface",get_canvas_interface());
940 			action->set_param("layer",layer);
941 			if(!action->set_param("param",String("origin")))
942 				synfig::error("LayerParamConnect didn't like \"param\"");
943 			if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
944 				synfig::error("LayerParamConnect didn't like \"value_node\"");
945 
946 			if(!get_canvas_interface()->get_instance()->perform_action(action))
947 			{
948 				group.cancel();
949 				throw String(_("Unable to create Gradient layer"));
950 				return;
951 			}
952 		}
953 	}
954 
955 	///////////////////////////////////////////////////////////////////////////
956 	//   P L A N T
957 	///////////////////////////////////////////////////////////////////////////
958 
959 	if(get_layer_plant_flag())
960 	{
961 		synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
962 
963 		egress_on_selection_change=false;
964 		Layer::Handle layer(get_canvas_interface()->add_layer_to("plant",canvas,depth));
965 		egress_on_selection_change=true;
966 		if (!layer)
967 		{
968 			get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
969 			group.cancel();
970 			return;
971 		}
972 		layer_selection.push_back(layer);
973 		layer->set_description(get_id()+_(" Plant"));
974 		get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
975 
976 		layer->set_param("blend_method",get_blend());
977 		get_canvas_interface()->signal_layer_param_changed()(layer,"blend_method");
978 
979 		layer->set_param("amount",get_opacity());
980 		get_canvas_interface()->signal_layer_param_changed()(layer,"amount");
981 
982 		{
983 			synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
984 			assert(action);
985 
986 			action->set_param("canvas",get_canvas());
987 			action->set_param("canvas_interface",get_canvas_interface());
988 			action->set_param("layer",layer);
989 			if(!action->set_param("param",String("bline")))
990 				synfig::error("LayerParamConnect didn't like \"param\"");
991 			if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
992 				synfig::error("LayerParamConnect didn't like \"value_node\"");
993 
994 			if(!get_canvas_interface()->get_instance()->perform_action(action))
995 			{
996 				group.cancel();
997 				throw String(_("Unable to create Plant layer"));
998 				return;
999 			}
1000 		}
1001 
1002 		// only link the plant's origin parameter if the option is selected and we're creating more than one layer
1003 		if (get_layer_link_origins_flag() && layers_to_create > 1)
1004 		{
1005 			synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
1006 			assert(action);
1007 
1008 			action->set_param("canvas",get_canvas());
1009 			action->set_param("canvas_interface",get_canvas_interface());
1010 			action->set_param("layer",layer);
1011 			if(!action->set_param("param",String("origin")))
1012 				synfig::error("LayerParamConnect didn't like \"param\"");
1013 			if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
1014 				synfig::error("LayerParamConnect didn't like \"value_node\"");
1015 
1016 			if(!get_canvas_interface()->get_instance()->perform_action(action))
1017 			{
1018 				group.cancel();
1019 				throw String(_("Unable to create Plant layer"));
1020 				return;
1021 			}
1022 		}
1023 	}
1024 
1025 	///////////////////////////////////////////////////////////////////////////
1026 	//   R E G I O N
1027 	///////////////////////////////////////////////////////////////////////////
1028 
1029 	if(get_layer_region_flag())
1030 	{
1031 		synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
1032 
1033 		egress_on_selection_change=false;
1034 		Layer::Handle layer(get_canvas_interface()->add_layer_to("region",canvas,depth));
1035 		egress_on_selection_change=true;
1036 		if (!layer)
1037 		{
1038 			get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
1039 			group.cancel();
1040 			return;
1041 		}
1042 		layer_selection.push_back(layer);
1043 		layer->set_description(get_id()+_(" Region"));
1044 		get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
1045 
1046 		layer->set_param("blend_method",get_blend());
1047 		get_canvas_interface()->signal_layer_param_changed()(layer,"blend_method");
1048 
1049 		layer->set_param("amount",get_opacity());
1050 		get_canvas_interface()->signal_layer_param_changed()(layer,"amount");
1051 
1052 		layer->set_param("feather",get_feather_size());
1053 		get_canvas_interface()->signal_layer_param_changed()(layer,"feather");
1054 
1055 		layer->set_param("invert",get_invert());
1056 		get_canvas_interface()->signal_layer_param_changed()(layer,"invert");
1057 
1058 		// I don't know if it's safe to reuse the same LayerParamConnect action, so I'm
1059 		// using 2 separate ones.
1060 		{
1061 			synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
1062 			assert(action);
1063 
1064 			action->set_param("canvas",get_canvas());
1065 			action->set_param("canvas_interface",get_canvas_interface());
1066 			action->set_param("layer",layer);
1067 			if(!action->set_param("param",String("bline")))
1068 				synfig::error("LayerParamConnect didn't like \"param\"");
1069 			if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
1070 				synfig::error("LayerParamConnect didn't like \"value_node\"");
1071 
1072 			if(!get_canvas_interface()->get_instance()->perform_action(action))
1073 			{
1074 				group.cancel();
1075 				throw String(_("Unable to create Region layer"));
1076 				return;
1077 			}
1078 		}
1079 
1080 		// only link the region's origin parameter if the option is selected and we're creating more than one layer
1081 		if (get_layer_link_origins_flag() && layers_to_create > 1)
1082 		{
1083 			synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
1084 			assert(action);
1085 
1086 			action->set_param("canvas",get_canvas());
1087 			action->set_param("canvas_interface",get_canvas_interface());
1088 			action->set_param("layer",layer);
1089 			if(!action->set_param("param",String("origin")))
1090 				synfig::error("LayerParamConnect didn't like \"param\"");
1091 			if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
1092 				synfig::error("LayerParamConnect didn't like \"value_node\"");
1093 
1094 			if(!get_canvas_interface()->get_instance()->perform_action(action))
1095 			{
1096 				group.cancel();
1097 				throw String(_("Unable to create Region layer"));
1098 				return;
1099 			}
1100 		}
1101 	}
1102 
1103 	///////////////////////////////////////////////////////////////////////////
1104 	//   O U T L I N E
1105 	///////////////////////////////////////////////////////////////////////////
1106 
1107 	if (get_layer_outline_flag())
1108 	{
1109 		synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
1110 
1111 		egress_on_selection_change=false;
1112 		Layer::Handle layer(get_canvas_interface()->add_layer_to("outline",canvas,depth));
1113 		egress_on_selection_change=true;
1114 		if (!layer)
1115 		{
1116 			get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
1117 			group.cancel();
1118 			return;
1119 		}
1120 		layer_selection.push_back(layer);
1121 		layer->set_description(get_id()+_(" Outline"));
1122 		get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
1123 
1124 		layer->set_param("blend_method",get_blend());
1125 		get_canvas_interface()->signal_layer_param_changed()(layer,"blend_method");
1126 
1127 		layer->set_param("amount",get_opacity());
1128 		get_canvas_interface()->signal_layer_param_changed()(layer,"amount");
1129 
1130 		layer->set_param("width",get_bline_width());
1131 		get_canvas_interface()->signal_layer_param_changed()(layer,"width");
1132 
1133 		layer->set_param("feather",get_feather_size());
1134 		get_canvas_interface()->signal_layer_param_changed()(layer,"feather");
1135 
1136 		layer->set_param("invert",get_invert());
1137 		get_canvas_interface()->signal_layer_param_changed()(layer,"invert");
1138 
1139 		{
1140 			synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
1141 			assert(action);
1142 
1143 			action->set_param("canvas",get_canvas());
1144 			action->set_param("canvas_interface",get_canvas_interface());
1145 			action->set_param("layer",layer);
1146 			if(!action->set_param("param",String("bline")))
1147 				synfig::error("LayerParamConnect didn't like \"param\"");
1148 			if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
1149 				synfig::error("LayerParamConnect didn't like \"value_node\"");
1150 
1151 			if(!get_canvas_interface()->get_instance()->perform_action(action))
1152 			{
1153 				group.cancel();
1154 				throw String(_("Unable to create Outline layer"));
1155 				return;
1156 			}
1157 		}
1158 
1159 		// only link the outline's origin parameter if the option is selected and we're creating more than one layer
1160 		if (get_layer_link_origins_flag() && layers_to_create > 1)
1161 		{
1162 			synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
1163 			assert(action);
1164 
1165 			action->set_param("canvas",get_canvas());
1166 			action->set_param("canvas_interface",get_canvas_interface());
1167 			action->set_param("layer",layer);
1168 			if(!action->set_param("param",String("origin")))
1169 				synfig::error("LayerParamConnect didn't like \"param\"");
1170 			if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
1171 				synfig::error("LayerParamConnect didn't like \"value_node\"");
1172 
1173 			if(!get_canvas_interface()->get_instance()->perform_action(action))
1174 			{
1175 				group.cancel();
1176 				throw String(_("Unable to create Outline layer"));
1177 				return;
1178 			}
1179 		}
1180 	}
1181 
1182 	///////////////////////////////////////////////////////////////////////////
1183 	//   A D V A N C E D   O U T L I N E
1184 	///////////////////////////////////////////////////////////////////////////
1185 
1186 	if (get_layer_advanced_outline_flag())
1187 	{
1188 		synfigapp::PushMode push_mode(get_canvas_interface(),synfigapp::MODE_NORMAL);
1189 
1190 		egress_on_selection_change=false;
1191 		Layer::Handle layer(get_canvas_interface()->add_layer_to("advanced_outline",canvas,depth));
1192 		egress_on_selection_change=true;
1193 		if (!layer)
1194 		{
1195 			get_canvas_view()->get_ui_interface()->error(_("Unable to create layer"));
1196 			group.cancel();
1197 			return;
1198 		}
1199 		layer_selection.push_back(layer);
1200 		layer->set_description(get_id()+_(" Advanced Outline"));
1201 		get_canvas_interface()->signal_layer_new_description()(layer,layer->get_description());
1202 
1203 		layer->set_param("blend_method",get_blend());
1204 		get_canvas_interface()->signal_layer_param_changed()(layer,"blend_method");
1205 
1206 		layer->set_param("amount",get_opacity());
1207 		get_canvas_interface()->signal_layer_param_changed()(layer,"amount");
1208 
1209 		layer->set_param("width",get_bline_width());
1210 		get_canvas_interface()->signal_layer_param_changed()(layer,"width");
1211 
1212 		layer->set_param("feather",get_feather_size());
1213 		get_canvas_interface()->signal_layer_param_changed()(layer,"feather");
1214 
1215 		layer->set_param("invert",get_invert());
1216 		get_canvas_interface()->signal_layer_param_changed()(layer,"invert");
1217 
1218 		{
1219 			synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
1220 			assert(action);
1221 
1222 			action->set_param("canvas",get_canvas());
1223 			action->set_param("canvas_interface",get_canvas_interface());
1224 			action->set_param("layer",layer);
1225 			if(!action->set_param("param",String("bline")))
1226 				synfig::error("LayerParamConnect didn't like \"param\"");
1227 			if(!action->set_param("value_node",ValueNode::Handle(value_node_bline)))
1228 				synfig::error("LayerParamConnect didn't like \"value_node\"");
1229 
1230 			if(!get_canvas_interface()->get_instance()->perform_action(action))
1231 			{
1232 				group.cancel();
1233 				throw String(_("Unable to create Advanced Outline layer"));
1234 				return;
1235 			}
1236 		}
1237 
1238 		// only link the advanced outline's origin parameter if the option is selected and we're creating more than one layer
1239 		if (get_layer_link_origins_flag() && layers_to_create > 1)
1240 		{
1241 			synfigapp::Action::Handle action(synfigapp::Action::create("LayerParamConnect"));
1242 			assert(action);
1243 
1244 			action->set_param("canvas",get_canvas());
1245 			action->set_param("canvas_interface",get_canvas_interface());
1246 			action->set_param("layer",layer);
1247 			if(!action->set_param("param",String("origin")))
1248 				synfig::error("LayerParamConnect didn't like \"param\"");
1249 			if(!action->set_param("value_node",ValueNode::Handle(value_node_origin)))
1250 				synfig::error("LayerParamConnect didn't like \"value_node\"");
1251 
1252 			if(!get_canvas_interface()->get_instance()->perform_action(action))
1253 			{
1254 				group.cancel();
1255 				throw String(_("Unable to create Advanced Outline layer"));
1256 				return;
1257 			}
1258 		}
1259 	}
1260 
1261 	egress_on_selection_change=false;
1262 	get_canvas_interface()->get_selection_manager()->clear_selected_layers();
1263 	get_canvas_interface()->get_selection_manager()->set_selected_layers(layer_selection);
1264 	egress_on_selection_change=true;
1265 
1266 	//post clean up stuff...
1267 	reset();
1268 	increment_id();
1269 }
1270 
1271 Smach::event_result
event_mouse_click_handler(const Smach::event & x)1272 StatePolygon_Context::event_mouse_click_handler(const Smach::event& x)
1273 {
1274 	const EventMouse& event(*reinterpret_cast<const EventMouse*>(&x));
1275 	switch(event.button)
1276 	{
1277 	case BUTTON_LEFT:
1278 		polygon_point_list.push_back(get_work_area()->snap_point_to_grid(event.pos));
1279 		refresh_ducks();
1280 		return Smach::RESULT_ACCEPT;
1281 
1282 	default:
1283 		return Smach::RESULT_OK;
1284 	}
1285 }
1286 
1287 
1288 void
refresh_ducks()1289 StatePolygon_Context::refresh_ducks()
1290 {
1291 	get_work_area()->clear_ducks();
1292 	get_work_area()->queue_draw();
1293 
1294 	if(polygon_point_list.empty()) return;
1295 
1296 	std::list<synfig::Point>::iterator iter=polygon_point_list.begin();
1297 
1298 	etl::handle<WorkArea::Duck> duck;
1299 	duck=new WorkArea::Duck(*iter);
1300 	duck->set_editable(true);
1301 	duck->signal_edited().connect(
1302 		sigc::bind(sigc::mem_fun(*this,&studio::StatePolygon_Context::on_polygon_duck_change),iter)
1303 	);
1304 	duck->signal_user_click(0).connect(sigc::mem_fun(*this,&StatePolygon_Context::run));
1305 
1306 	get_work_area()->add_duck(duck);
1307 
1308 	for(++iter;iter!=polygon_point_list.end();++iter)
1309 	{
1310 		etl::handle<WorkArea::Bezier> bezier(new WorkArea::Bezier());
1311 		bezier->p1=bezier->c1=duck;
1312 
1313 		duck=new WorkArea::Duck(*iter);
1314 		duck->set_editable(true);
1315 		duck->set_name(strprintf("%x",&*iter));
1316 		duck->signal_edited().connect(
1317 			sigc::bind(sigc::mem_fun(*this,&studio::StatePolygon_Context::on_polygon_duck_change),iter)
1318 		);
1319 
1320 		get_work_area()->add_duck(duck);
1321 
1322 		bezier->p2=bezier->c2=duck;
1323 		get_work_area()->add_bezier(bezier);
1324 	}
1325 	get_work_area()->queue_draw();
1326 }
1327 
1328 
1329 bool
on_polygon_duck_change(const studio::Duck & duck,std::list<synfig::Point>::iterator iter)1330 StatePolygon_Context::on_polygon_duck_change(const studio::Duck &duck, std::list<synfig::Point>::iterator iter)
1331 {
1332 	*iter=duck.get_point();
1333 	return true;
1334 }
1335 
1336 
1337 void
toggle_layer_creation()1338 StatePolygon_Context::toggle_layer_creation()
1339 {
1340   // don't allow none layer creation
1341   if (get_layer_polygon_flag() +
1342      get_layer_region_flag() +
1343      get_layer_outline_flag() +
1344      get_layer_advanced_outline_flag() +
1345      get_layer_curve_gradient_flag() +
1346      get_layer_plant_flag() == 0)
1347   {
1348     if(layer_polygon_flag) set_layer_polygon_flag(true);
1349     else if(layer_region_flag) set_layer_region_flag(true);
1350     else if(layer_outline_flag) set_layer_outline_flag(true);
1351     else if(layer_advanced_outline_flag) set_layer_advanced_outline_flag(true);
1352     else if(layer_curve_gradient_flag) set_layer_curve_gradient_flag(true);
1353     else if(layer_plant_flag) set_layer_plant_flag(true);
1354   }
1355 
1356 	// brush size
1357 	if (get_layer_outline_flag() ||
1358 		get_layer_advanced_outline_flag() ||
1359 		get_layer_curve_gradient_flag())
1360 	{
1361 		bline_width_label.set_sensitive(true);
1362 		bline_width_dist.set_sensitive(true);
1363 	}
1364 	else
1365 	{
1366 		bline_width_label.set_sensitive(false);
1367 		bline_width_dist.set_sensitive(false);
1368 	}
1369 
1370 	// invert
1371 	if (get_layer_polygon_flag() ||
1372 		get_layer_region_flag() ||
1373 		get_layer_outline_flag() ||
1374 		get_layer_advanced_outline_flag())
1375 	{
1376 		invert_box.set_sensitive(true);
1377 	}
1378 	else
1379 		invert_box.set_sensitive(false);
1380 
1381 	// feather size
1382 	if (get_layer_polygon_flag() ||
1383 		get_layer_polygon_flag() ||
1384 		get_layer_region_flag() ||
1385 		get_layer_outline_flag() ||
1386 		get_layer_advanced_outline_flag())
1387 	{
1388 		feather_label.set_sensitive(true);
1389 		feather_dist.set_sensitive(true);
1390 	}
1391 	else
1392 	{
1393 		feather_label.set_sensitive(false);
1394 		feather_dist.set_sensitive(false);
1395 	}
1396 
1397 	// link origins
1398 	if (get_layer_region_flag() +
1399 		get_layer_outline_flag() +
1400 		get_layer_advanced_outline_flag() +
1401 		get_layer_plant_flag() +
1402 		get_layer_curve_gradient_flag() +
1403 		get_layer_polygon_flag() >= 2)
1404 		{
1405 			link_origins_box.set_sensitive(true);
1406 		}
1407 	else link_origins_box.set_sensitive(false);
1408 
1409   // update layer flags
1410   layer_polygon_flag = get_layer_polygon_flag();
1411   layer_region_flag = get_layer_region_flag();
1412   layer_outline_flag = get_layer_outline_flag();
1413   layer_advanced_outline_flag = get_layer_advanced_outline_flag();
1414   layer_curve_gradient_flag = get_layer_curve_gradient_flag();
1415   layer_plant_flag = get_layer_plant_flag();
1416 }
1417