1 /* === S Y N F I G ========================================================= */
2 /*!	\file workarea.h
3 **	\brief Template Header
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) 2011 Nikita Kitaev
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 /* === S T A R T =========================================================== */
26 
27 #ifndef __SYNFIG_GTKMM_WORKAREA_H
28 #define __SYNFIG_GTKMM_WORKAREA_H
29 
30 /* === H E A D E R S ======================================================= */
31 
32 #include <list>
33 #include <map>
34 #include <set>
35 
36 #include <ETL/smart_ptr>
37 #include <ETL/handle>
38 
39 #include <gtkmm/drawingarea.h>
40 #include <gtkmm/table.h>
41 #include <gtkmm/adjustment.h>
42 #include <gtkmm/image.h>
43 #include <gdkmm/pixbuf.h>
44 #include <gdkmm/cursor.h>
45 #include <gdkmm/device.h>
46 
47 #include <synfig/time.h>
48 #include <synfig/vector.h>
49 #include <synfig/renddesc.h>
50 #include <synfig/canvas.h>
51 
52 #include "dials/zoomdial.h"
53 #include "widgets/widget_ruler.h"
54 #include "duckmatic.h"
55 #include "instance.h"
56 #include "app.h"
57 
58 /* === M A C R O S ========================================================= */
59 
60 /* === T Y P E D E F S ===================================================== */
61 
62 /* === C L A S S E S & S T R U C T S ======================================= */
63 
64 /*
65 namespace etl {
66 
67 template <typename T_, typename C_=std::less<T_,T_> >
68 class dereferenced_compare
69 {
70 public:
71 	typedef etl::loose_handle<T_> first_argument_type;
72 	typedef etl::loose_handle<T_> second_argument_type;
73 	typedef bool result_type;
74 
75 }
76 };
77 */
78 
79 namespace synfigapp { class CanvasInterface; };
80 
81 namespace synfig { class Layer; };
82 namespace Gtk { class Frame; };
83 
84 namespace studio
85 {
86 class WorkAreaTarget;
87 class WorkAreaTarget_Full;
88 class WorkAreaTarget_GL;
89 
90 class Instance;
91 class CanvasView;
92 class WorkArea;
93 class WorkAreaRenderer;
94 class AsyncRenderer;
95 
96 class DirtyTrap
97 {
98 	friend class WorkArea;
99 	WorkArea *work_area;
100 public:
101 	DirtyTrap(WorkArea *work_area);
102 	~DirtyTrap();
103 };
104 
105 class WorkAreaTile
106 {
107 public:
108 	typedef std::list<WorkAreaTile> List;
109 
110 	int refresh_id;
111 	synfig::RectInt rect;
112 	Glib::RefPtr<Gdk::Pixbuf> pixbuf;
113 	cairo_surface_t* surface;
114 
WorkAreaTile()115 	WorkAreaTile(): refresh_id(), surface()
116 		{ }
WorkAreaTile(int refresh_id,int left,int top,const Glib::RefPtr<Gdk::Pixbuf> & pixbuf)117 	WorkAreaTile(int refresh_id, int left, int top, const Glib::RefPtr<Gdk::Pixbuf> &pixbuf):
118 		refresh_id(refresh_id),
119 		rect( left,
120 			  top,
121 			  left + (pixbuf ? pixbuf->get_width() : 0),
122 			  top + (pixbuf ? pixbuf->get_height() : 0) ),
123 		pixbuf(pixbuf),
124 		surface() { }
WorkAreaTile(int refresh_id,int left,int top,cairo_surface_t * surface)125 	WorkAreaTile(int refresh_id, int left, int top, cairo_surface_t *surface):
126 		refresh_id(refresh_id),
127 		rect( left,
128 			  top,
129 			  left + (surface ? cairo_image_surface_get_width(surface) : 0),
130 			  top + (surface ? cairo_image_surface_get_height(surface) : 0) ),
131 		surface() { }
132 
133 	bool operator< (const WorkAreaTile &other) const { return refresh_id < other.refresh_id; }
134 };
135 
136 class WorkAreaTileBook
137 {
138 private:
139 	WorkAreaTile::List tiles;
140 
141 public:
get_tiles()142 	const WorkAreaTile::List& get_tiles() const { return tiles; }
143 
144 	WorkAreaTile* find_tile(int refresh_id, const synfig::RectInt &rect);
145 
clear()146 	void clear() { tiles.clear(); }
147 
148 	void sort();
149 
150 	void add(const WorkAreaTile &tile);
151 
add(int refresh_id,int left,int top,const Glib::RefPtr<Gdk::Pixbuf> & pixbuf)152 	void add(int refresh_id, int left, int top, const Glib::RefPtr<Gdk::Pixbuf> &pixbuf)
153 		{ add(WorkAreaTile(refresh_id, left, top, pixbuf)); }
add(int refresh_id,int left,int top,cairo_surface_t * surface)154 	void add(int refresh_id, int left, int top, cairo_surface_t *surface)
155 		{ add(WorkAreaTile(refresh_id, left, top, surface)); }
156 
157 	void get_dirty_rects(
158 		std::vector<synfig::RectInt> &out_rects,
159 		int refresh_id,
160 		const synfig::RectInt &bounds,
161 		const synfig::VectorInt &max_size = synfig::VectorInt(INT_MAX, INT_MAX) ) const;
162 };
163 
164 
165 class WorkArea : public Gtk::Table, public Duckmatic
166 {
167 	friend class WorkAreaTarget;
168 	friend class WorkAreaTarget_Full;
169 	friend class WorkAreaTarget_Cairo;
170 	friend class WorkAreaTarget_Cairo_Tile;
171 	friend class WorkAreaTarget_GL;
172 	friend class DirtyTrap;
173 	friend class WorkAreaRenderer;
174 	friend class WorkAreaProgress;
175 
176 	/*
177  -- ** -- P U B L I C   T Y P E S ---------------------------------------------
178 	*/
179 
180 public:
181 
182 	class PushState;
183 	friend class PushState;
184 
185 	void insert_renderer(const etl::handle<WorkAreaRenderer> &x);
186 	void insert_renderer(const etl::handle<WorkAreaRenderer> &x,int priority);
187 	void erase_renderer(const etl::handle<WorkAreaRenderer> &x);
188 	void resort_render_set();
189 
190 	enum DragMode
191 	{
192 		DRAG_NONE=0,
193 		DRAG_WINDOW,
194 		DRAG_DUCK,
195 		DRAG_GUIDE,
196 		DRAG_BOX,
197 		DRAG_BEZIER,
198 		DRAG_ZOOM_WINDOW,
199 		DRAG_ROTATE_WINDOW
200 	};
201 	// Class used to store the cairo surface
202 	class SurfaceElement
203 	{
204 	public:
205 		cairo_surface_t* surface;
206 		int refreshes;
SurfaceElement()207 		SurfaceElement()
208 		{
209 			surface=NULL;
210 			refreshes=0;
211 		}
212 		//Copy constructor
SurfaceElement(const SurfaceElement & other)213 		SurfaceElement(const SurfaceElement& other): surface(cairo_surface_reference(other.surface)), refreshes(other.refreshes)
214 		{
215 		}
~SurfaceElement()216 		~SurfaceElement()
217 		{
218 			if(surface)
219 				cairo_surface_destroy(surface);
220 		}
221 	};
222 
223 	typedef std::vector<SurfaceElement>	 SurfaceBook;
224 
225 	/*
226  -- ** -- P R I V A T E   D A T A ---------------------------------------------
227 	*/
228 
229 private:
230 
231 	std::set<etl::handle<WorkAreaRenderer> > renderer_set_;
232 
233 	etl::handle<studio::AsyncRenderer> async_renderer;
234 
235 
236 	etl::loose_handle<synfigapp::CanvasInterface> canvas_interface;
237 	etl::handle<synfig::Canvas> canvas;
238 	etl::loose_handle<studio::Instance> instance;
239 	etl::loose_handle<studio::CanvasView> canvas_view;
240 
241 	// Widgets
242 	Gtk::DrawingArea *drawing_area;
243 	Glib::RefPtr<Gtk::Adjustment> scrollx_adjustment;
244 	Glib::RefPtr<Gtk::Adjustment> scrolly_adjustment;
245 	Widget_Ruler *vruler;
246 	Widget_Ruler *hruler;
247 	Gtk::Frame *drawing_frame;
248 	ZoomDial *zoomdial;
249 
250 	GdkDevice* curr_input_device;
251 
252 	// Bleh!
253 	int	w;						//!< Width of the image (in pixels)
254 	int	h;						//!< Height of the image (in pixels)
255 	synfig::Real	canvaswidth;	//!< Width of the canvas
256 	synfig::Real	canvasheight;	//!< Height of the canvas
257 	synfig::Real	pw;				//!< The width of a pixel
258 	synfig::Real	ph;				//!< The height of a pixel
259 	// float zoom and prev_zoom are declared in Duckmatic
260 	synfig::Point window_tl;		//!< The (theoretical) top-left corner of the view window
261 	synfig::Point window_br;		//!< The (theoretical) bottom-right corner of the view window
262 
263 	guint32 last_event_time;
264 
265 	int bpp;
266 	//unsigned char *buffer;
267 
268 	//! ???
269 	synfig::ProgressCallback *progresscallback;
270 
271 	//! ???
272 	synfig::RendDesc desc;
273 
274 	//! This flag is set if the user is dragging the video window
275 	/*! \see drag_point */
276 	DragMode dragging;
277 
278 	etl::handle<Duckmatic::Duck> clicked_duck;
279 	etl::handle<Duckmatic::Duck> hover_duck;
280 
281 	//! When dragging the viewport, this is set to the origin of the drag
282 	synfig::Point drag_point;
283 
284 	synfig::Point curr_point;
285 
286 	//! ???
287 	synfig::Point previous_focus;
288 
289 	//! This flag is set if the grid should be drawn
290 	bool show_grid;
291 
292 	//! This flag is set if the guides should be drawn
293 	bool show_guides;
294 
295 	//! Checker background size
296 	synfig::Vector background_size;
297 	//! Checker background first color
298 	synfig::Color background_first_color;
299 	//! Checker background second color
300 	synfig::Color background_second_color;
301 
302 	synfig::Time jack_offset;
303 
304 	bool low_resolution;
305 
306 	bool meta_data_lock;
307 
308 	//! This flag is set if the entire frame is rendered rather than using tiles
309 	bool full_frame;
310 
311 	//Glib::RefPtr<Gdk::Pixbuf> pix_buf;
312 
313 	//! This vector holds all of the tiles for this frame
314 	WorkAreaTileBook tile_book;
315 
316 	//! This integer describes the total times that the work area has been refreshed
317 	int refreshes;
318 
319 	//! This list holds the queue of tiles that need to be rendered
320 	//std::list<int> tile_queue;
321 
322 	int tile_w, tile_h;
323 
324 	gint render_idle_func_id;
325 
326 	//! The coordinates of the focus the last time a part of the screen was refreshed
327 	synfig::Point last_focus_point;
328 
329 	bool canceled_;
330 
331 	int quality;
332 	int low_res_pixel_size;
333 
334 	bool dirty_trap_enabled;
335 
336 	int dirty_trap_queued;
337 
338 	// This flag is set if onion skin is visible
339 	bool onion_skin;
340 	//! stores the future [1] and past [0] onion skins based on keyframes
341 	int onion_skins[2];
342 
343 	etl::loose_handle<synfig::ValueNode> selected_value_node_;
344 
345 	bool allow_duck_clicks;
346 	bool allow_bezier_clicks;
347 	bool allow_layer_clicks;
348 	bool cancel;
349 	bool curr_guide_is_x;
350 	bool dirty;
351 	bool queued;
352 	bool rendering;
353 
354 #ifdef SINGLE_THREADED
355 	/* resize bug workaround */
356 	int old_window_width;
357 	int old_window_height;
358 #endif
359 
360 	/*
361  -- ** -- P U B L I C   D A T A -----------------------------------------------
362 	*/
363 
364 public:
365 
get_selected_value_node()366 	const etl::loose_handle<synfig::ValueNode>& get_selected_value_node() { return  selected_value_node_; }
get_drag_point()367 	const synfig::Point& get_drag_point()const { return drag_point; }
get_tile_book()368 	const WorkAreaTileBook& get_tile_book() const { return tile_book; }
get_tile_book()369 	WorkAreaTileBook& get_tile_book() { return tile_book; }
get_refreshes()370 	int get_refreshes()const { return refreshes; }
get_canceled()371 	bool get_canceled()const { return canceled_; }
get_queued()372 	bool get_queued()const { return queued; }
get_rendering()373 	bool get_rendering()const { return rendering; }
374 #ifdef SINGLE_THREADED
375 	bool get_updating()const;
376 	void stop_updating(bool cancel = false);
377 #endif
get_full_frame()378 	bool get_full_frame()const { return full_frame; }
379 	//int get_w()const { return w; }
380 	//int get_h()const { return h; }
381 
382 	synfig::VectorInt get_windows_offset() const;
383 	synfig::RectInt get_window_rect(int stepx = 1, int stepy = 1) const;
get_tile_w()384 	int get_tile_w()const { return tile_w; }
get_tile_h()385 	int get_tile_h()const { return tile_h; }
386 
get_allow_layer_clicks()387 	bool get_allow_layer_clicks() { return allow_layer_clicks; }
set_allow_layer_clicks(bool value)388 	void set_allow_layer_clicks(bool value) { allow_layer_clicks=value; }
389 
get_allow_duck_clicks()390 	bool get_allow_duck_clicks() { return allow_duck_clicks; }
set_allow_duck_clicks(bool value)391 	void set_allow_duck_clicks(bool value) { allow_duck_clicks=value; }
392 
get_allow_bezier_clicks()393 	bool get_allow_bezier_clicks() { return allow_bezier_clicks; }
set_allow_bezier_clicks(bool value)394 	void set_allow_bezier_clicks(bool value) { allow_bezier_clicks=value; }
395 
396 	// used in renderer_ducks.cpp
397 	bool solid_lines;
398 
399 	// used in renderer_guides.cpp
400 	GuideList::iterator curr_guide;
401 
402 	// used in renderer_timecode.cpp
403 	int timecode_width, timecode_height;
404 
405 	// used in renderer_bonesetup.cpp
406 	int bonesetup_width, bonesetup_height;
407 
408 	/*
409  -- ** -- P R I V A T E   M E T H O D S ---------------------------------------
410 	*/
411 
412 private:
413 
414 	//unsigned char *get_buffer() { return buffer; }
415 	bool set_wh(int w, int h,int chan=3);
416 
417 	/*
418  -- ** -- S I G N A L S -------------------------------------------------------
419 	*/
420 
421 private:
422 
423 	sigc::signal<void,GdkDevice* > signal_input_device_changed_;
424 
425 	//! One signal per button
426 	sigc::signal<void,synfig::Point> signal_user_click_[5];
427 
428 	sigc::signal<void> signal_popup_menu_;
429 
430 	sigc::signal<void> signal_cursor_moved_;
431 	sigc::signal<void> signal_rendering_;
432 
433 	//! Signal for when the user clicks on a layer
434 	sigc::signal<void, etl::handle<synfig::Layer> > signal_layer_selected_;
435 
436 	sigc::signal<void> signal_view_window_changed_;
437 
438 	sigc::signal<void> signal_meta_data_changed_;
439 
440 public:
441 
signal_rendering()442 	sigc::signal<void>& signal_rendering() { return signal_rendering_; }
443 
signal_cursor_moved()444 	sigc::signal<void>& signal_cursor_moved() { return signal_cursor_moved_; }
445 
signal_view_window_changed()446 	sigc::signal<void>& signal_view_window_changed() { return signal_view_window_changed_; }
447 
signal_meta_data_changed()448 	sigc::signal<void>& signal_meta_data_changed() { return signal_meta_data_changed_; }
449 
view_window_changed()450 	void view_window_changed() { signal_view_window_changed()(); }
451 
signal_input_device_changed()452 	sigc::signal<void,GdkDevice* >& signal_input_device_changed() { return signal_input_device_changed_; }
453 
signal_popup_menu()454 	sigc::signal<void> &signal_popup_menu() { return signal_popup_menu_; }
455 
456 	//! One signal per button (5 buttons)
457 	sigc::signal<void,synfig::Point> &signal_user_click(int button=0){ return signal_user_click_[button]; }
458 
signal_layer_selected()459 	sigc::signal<void, etl::handle<synfig::Layer> >& signal_layer_selected() { return signal_layer_selected_; }
460 
461 	/*
462  -- ** -- P U B L I C   M E T H O D S -----------------------------------------
463 	*/
464 
465 public:
466 	void set_onion_skin(bool x);
467 	bool get_onion_skin()const;
toggle_onion_skin()468 	void toggle_onion_skin() { set_onion_skin(!get_onion_skin()); }
469 	void set_onion_skins(int *onions);
470 	int const * get_onion_skins()const;
471 
472 	void set_selected_value_node(etl::loose_handle<synfig::ValueNode> x);
473 
is_dragging()474 	bool is_dragging() { return dragging!=DRAG_NONE; }
475 
get_dragging_mode()476 	DragMode get_dragging_mode() { return dragging; }
477 
478 	WorkArea(etl::loose_handle<synfigapp::CanvasInterface> canvas_interface);
479 	virtual ~WorkArea();
480 
481 	void set_cursor(const Glib::RefPtr<Gdk::Cursor> &x);
482 	void set_cursor(Gdk::CursorType x);
483 
get_cursor_pos()484 	const synfig::Point& get_cursor_pos()const { return curr_point; }
485 
get_scrollx_adjustment()486 	Glib::RefPtr<Gtk::Adjustment> get_scrollx_adjustment() { return scrollx_adjustment; }
get_scrolly_adjustment()487 	Glib::RefPtr<Gtk::Adjustment> get_scrolly_adjustment() { return scrolly_adjustment; }
get_scrollx_adjustment()488 	Glib::RefPtr<const Gtk::Adjustment> get_scrollx_adjustment() const { return scrollx_adjustment; }
get_scrolly_adjustment()489 	Glib::RefPtr<const Gtk::Adjustment> get_scrolly_adjustment() const { return scrolly_adjustment; }
490 
set_instance(etl::loose_handle<studio::Instance> x)491 	void set_instance(etl::loose_handle<studio::Instance> x) { instance=x; }
set_canvas(etl::handle<synfig::Canvas> x)492 	void set_canvas(etl::handle<synfig::Canvas> x) { canvas=x; }
set_canvas_view(etl::loose_handle<studio::CanvasView> x)493 	void set_canvas_view(etl::loose_handle<studio::CanvasView> x) { canvas_view=x; }
get_canvas()494 	etl::handle<synfig::Canvas> get_canvas()const { return canvas; }
get_instance()495 	etl::handle<studio::Instance> get_instance()const { return instance; }
get_canvas_view()496 	etl::loose_handle<studio::CanvasView> get_canvas_view()const { return canvas_view; }
497 
498 	void refresh_dimension_info();
499 
500 	//! Enables showing of the grid
501 	void enable_grid();
502 	//! Disables showing of the grid
503 	void disable_grid();
504 	//! Toggles the showing of the grid
505 	void toggle_grid();
506 	//! Returns the state of the show_grid flag
grid_status()507 	bool grid_status()const { return show_grid; }
508 	//! Toggles the snap of the grid
509 	void toggle_grid_snap();
510 	//! Sets the size of the grid
511 	void set_grid_size(const synfig::Vector &s);
512 	//! Sets the color of the grid
513 	void set_grid_color(const synfig::Color &c);
514 	//! Returns the color of the grid
get_grid_color()515 	const synfig::Color &get_grid_color()const { return Duckmatic::get_grid_color();}
516 
517 	//! Returns the state of the show_guides flag
get_show_guides()518 	bool get_show_guides()const { return show_guides; }
519 	//! Sets the showing of the grid
520 	void set_show_guides(bool x);
521 	//! Toggles the showing of the guides
toggle_show_guides()522 	void toggle_show_guides() { set_show_guides(!get_show_guides()); }
523 	//! Toggles the snap of the guides
524 	void toggle_guide_snap();
525 	//! Sets the color of the guides
526 	void set_guides_color(const synfig::Color &c);
527 	//! Returns the color of the guides
get_guides_color()528 	const synfig::Color &get_guides_color()const { return Duckmatic::get_guides_color();}
529 
get_jack_offset()530 	synfig::Time get_jack_offset()const { return jack_offset; }
531 	void set_jack_offset(const synfig::Time &x);
532 
533 	//! Sets the size of the checker background
534 	void set_background_size(const synfig::Vector &s);
535 	//! Sets the first color of the checker background
536 	void set_background_first_color(const synfig::Color &c);
537 	//! Sets the second color of the checker background
538 	void set_background_second_color(const synfig::Color &c);
539 	//! Sets the size of the checker background
get_background_size()540 	const synfig::Vector &get_background_size()const { return background_size;}
541 	//! Returns the first color of the checker background
get_background_first_color()542 	const synfig::Color &get_background_first_color()const { return background_first_color;}
543 	//! Returns the second color of the checker background
get_background_second_color()544 	const synfig::Color &get_background_second_color()const { return background_second_color;}
545 
get_low_resolution_flag()546 	bool get_low_resolution_flag()const { return low_resolution; }
547 	void set_low_resolution_flag(bool x);
548 	void toggle_low_resolution_flag();
549 
550 	//! ???
551 	void queue_scroll();
552 
553 	//! ??
554 	void popup_menu();
555 
get_quality()556 	int get_quality()const { return quality; }
get_low_res_pixel_size()557 	int get_low_res_pixel_size()const { return low_res_pixel_size; }
558 	synfig::String get_renderer() const;
559 
560 	void set_quality(int x);
561 	void set_low_res_pixel_size(int x);
562 
563 
get_w()564 	int get_w()const { return w; }
get_h()565 	int get_h()const { return h; }
get_bpp()566 	int get_bpp()const { return bpp; }
567 
568 	//! ??
get_rend_desc()569 	const synfig::RendDesc &get_rend_desc()const { return desc; }
570 
571 	//! ??
set_rend_desc(const synfig::RendDesc & x)572 	void set_rend_desc(const synfig::RendDesc &x) { desc=x; }
573 
574 	//! Converts screen coords (ie: pixels) to composition coordinates
575 	synfig::Point screen_to_comp_coords(synfig::Point pos)const;
576 
577 	//! Converts composition coordinates to screen coords (ie: pixels)
578 	synfig::Point comp_to_screen_coords(synfig::Point pos)const;
579 
get_pw()580 	float get_pw()const { return pw; }
get_ph()581 	float get_ph()const { return ph; }
582 
get_window_tl()583 	const synfig::Point &get_window_tl()const { return window_tl; }
get_window_br()584 	const synfig::Point &get_window_br()const { return window_br; }
585 
586 
587 	bool async_update_preview();
588 	void async_update_finished();
589 	void async_render_preview(synfig::Time time);
590 	void async_render_preview();
591 
592 	bool sync_update_preview();
593 	bool sync_render_preview(synfig::Time time);
594 	bool sync_render_preview();
595 	void sync_render_preview_hook();
596 
597 	void queue_render_preview();
598 
599 
600 	void queue_draw_preview();
601 
602 	void zoom_in();
603 	void zoom_out();
604 	void zoom_fit();
605 	void zoom_norm();
606 	void zoom_edit();
get_zoom()607 	float get_zoom()const { return zoom; } // zoom is declared in Duckmatic
608 
609 	void set_zoom(float z);
610 
611 
set_progress_callback(synfig::ProgressCallback * x)612 	void set_progress_callback(synfig::ProgressCallback *x)	{ progresscallback=x; }
get_progress_callback()613 	synfig::ProgressCallback *get_progress_callback() { return progresscallback; }
614 
615 	void set_focus_point(const synfig::Point &x);
616 
617 	synfig::Point get_focus_point()const;
618 
619 	void done_rendering();
620 
621 #ifdef SINGLE_THREADED
622 	/* resize bug workaround */
623 	void refresh_second_check();
624 #endif
625 	bool refresh(const Cairo::RefPtr<Cairo::Context> &cr);
626 
627 	void reset_cursor();
628 	void refresh_cursor();
629 
630 	void save_meta_data();
631 	void load_meta_data();
632 	//! Test initial meta data values
633 	bool have_meta_data();
634 
635 	/*
636  -- ** -- S I G N A L   T E R M I N A L S -------------------------------------
637 	*/
638 
639 private:
640 	bool on_key_press_event(GdkEventKey* event);
641 	bool on_key_release_event(GdkEventKey* event);
642 	bool on_drawing_area_event(GdkEvent* event);
643 	bool on_hruler_event(GdkEvent* event);
644 	bool on_vruler_event(GdkEvent* event);
645 	void on_duck_selection_single(const etl::handle<Duck>& duck_guid);
646 
647 	/*
648  -- ** -- S T A T I C   P U B L I C   M E T H O D S ---------------------------
649 	*/
650 
651 public:
652 
653 	/*
654  -- ** -- S T A T I C   P R I V A T E   M E T H O D S -------------------------
655 	*/
656 
657 private:
658 
659 	static gboolean __render_preview(gpointer data);
660 #ifdef SINGLE_THREADED
661 	/* resize bug workaround */
662 	static gboolean __refresh_second_check(gpointer data);
663 #endif
664 
665 }; // END of class WorkArea
666 
667 /*! \class WorkArea::PushState
668 **	Saves the current duck view and editing options
669 **  Should be used by tools that hide ducks or change clickability settings */
670 class WorkArea::PushState
671 {
672 	WorkArea *workarea_;
673 	Type type_mask;
674 	bool allow_duck_clicks;
675 	bool allow_bezier_clicks;
676 	bool allow_layer_clicks;
677 
678 	bool needs_restore;
679 
680 public:
681 	PushState(WorkArea *workarea_);
682 	~PushState();
683 	void restore();
684 }; // END of class WorkArea::PushState
685 
686 }; // END of namespace studio
687 
688 /* === E N D =============================================================== */
689 
690 #endif
691