Changed the "tagrelease" and "tagstable" make targets to use subversion. Also increme...
[synfig.git] / synfig-studio / tags / stable / src / gtkmm / state_sketch.cpp
1 /* === S I N F G =========================================================== */
2 /*!     \file state_sketch.cpp
3 **      \brief Template File
4 **
5 **      $Id: state_sketch.cpp,v 1.1.1.1 2005/01/07 03:34:37 darco Exp $
6 **
7 **      \legal
8 **      Copyright (c) 2002 Robert B. Quattlebaum Jr.
9 **
10 **      This software and associated documentation
11 **      are CONFIDENTIAL and PROPRIETARY property of
12 **      the above-mentioned copyright holder.
13 **
14 **      You may not copy, print, publish, or in any
15 **      other way distribute this software without
16 **      a prior written agreement with
17 **      the copyright holder.
18 **      \endlegal
19 */
20 /* ========================================================================= */
21
22 /* === H E A D E R S ======================================================= */
23
24 #ifdef USING_PCH
25 #       include "pch.h"
26 #else
27 #ifdef HAVE_CONFIG_H
28 #       include <config.h>
29 #endif
30
31 #include <gtkmm/dialog.h>
32 #include <gtkmm/entry.h>
33
34 #include <sinfg/valuenode_dynamiclist.h>
35
36 #include "state_sketch.h"
37 #include "state_stroke.h"
38 #include "canvasview.h"
39 #include "workarea.h"
40 #include "app.h"
41 #include <sinfg/valuenode_bline.h>
42 #include <ETL/hermite>
43 #include <ETL/calculus>
44 #include <utility>
45 #include "event_mouse.h"
46 #include "event_layerclick.h"
47 #include "toolbox.h"
48
49 #include <sinfgapp/blineconvert.h>
50 #include <sinfgapp/main.h>
51
52 #include <ETL/gaussian>
53
54 #include "dialog_tooloptions.h"
55
56 #include <gtkmm/table.h>
57 #include <gtkmm/label.h>
58 #include <gtkmm/button.h>
59 #include <gtkmm/checkbutton.h>
60 #include <gtkmm/actiongroup.h>
61
62 #endif
63
64 /* === U S I N G =========================================================== */
65
66 using namespace std;
67 using namespace etl;
68 using namespace sinfg;
69 using namespace studio;
70
71 /* === M A C R O S ========================================================= */
72
73 /* === G L O B A L S ======================================================= */
74
75 StateSketch studio::state_sketch;
76
77 /* === C L A S S E S & S T R U C T S ======================================= */
78
79 class studio::StateSketch_Context : public sigc::trackable
80 {
81         Glib::RefPtr<Gtk::ActionGroup> action_group;
82
83         etl::handle<CanvasView> canvas_view_;
84         CanvasView::IsWorking is_working;
85
86         bool prev_table_status;
87         bool prev_workarea_layer_status_;
88         
89         Gtk::Table options_table;
90         Gtk::Button button_clear_sketch;
91         Gtk::Button button_undo_stroke;
92         Gtk::Button button_save_sketch;
93         Gtk::Button button_load_sketch;
94         Gtk::CheckButton checkbutton_show_sketch;
95
96         void clear_sketch();
97         void save_sketch();
98         void load_sketch();
99         void undo_stroke();
100         void toggle_show_sketch();
101         
102 public:
103
104         Smach::event_result event_stop_handler(const Smach::event& x);
105
106         Smach::event_result event_refresh_handler(const Smach::event& x);
107
108         Smach::event_result event_mouse_down_handler(const Smach::event& x);
109
110         Smach::event_result event_stroke(const Smach::event& x);
111
112         Smach::event_result event_refresh_tool_options(const Smach::event& x);
113         Smach::event_result event_yield_tool_options(const Smach::event& x);
114
115         void refresh_tool_options();
116         void yield_tool_options();
117
118         StateSketch_Context(CanvasView* canvas_view);
119
120         ~StateSketch_Context();
121
122         const etl::handle<CanvasView>& get_canvas_view()const{return canvas_view_;}
123         etl::handle<sinfgapp::CanvasInterface> get_canvas_interface()const{return canvas_view_->canvas_interface();}
124         sinfg::Time get_time()const { return get_canvas_interface()->get_time(); }
125         sinfg::Canvas::Handle get_canvas()const{return canvas_view_->get_canvas();}
126         WorkArea * get_work_area()const{return canvas_view_->get_work_area();}
127         
128 };      // END of class StateSketch_Context
129
130
131 /* === M E T H O D S ======================================================= */
132
133 StateSketch::StateSketch():
134         Smach::state<StateSketch_Context>("sketch")
135 {
136         insert(event_def(EVENT_STOP,&StateSketch_Context::event_stop_handler));
137         //insert(event_def(EVENT_REFRESH,&StateSketch_Context::event_refresh_handler));
138         insert(event_def(EVENT_REFRESH_DUCKS,&StateSketch_Context::event_refresh_handler));
139         insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateSketch_Context::event_mouse_down_handler));
140         insert(event_def(EVENT_WORKAREA_STROKE,&StateSketch_Context::event_stroke));
141         insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateSketch_Context::event_refresh_tool_options)); 
142         insert(event_def(EVENT_YIELD_TOOL_OPTIONS,&StateSketch_Context::event_yield_tool_options));     
143 }       
144
145 StateSketch::~StateSketch()
146 {
147 }
148
149 void
150 StateSketch_Context::save_sketch()
151 {
152         sinfg::String filename(basename(get_canvas()->get_file_name())+".sketch");
153         
154         while(App::dialog_save_file(_("Save Sketch"), filename))
155         {
156                 // If the filename still has wildcards, then we should
157                 // continue looking for the file we want
158                 if(find(filename.begin(),filename.end(),'*')!=filename.end())
159                         continue;
160
161                 if(get_work_area()->save_sketch(filename))
162                         break;
163
164                 get_canvas_view()->get_ui_interface()->error(_("Unable to save sketch"));
165         }
166 }
167
168 void
169 StateSketch_Context::load_sketch()
170 {
171         sinfg::String filename(basename(get_canvas()->get_file_name())+".sketch");
172         
173         while(App::dialog_open_file(_("Load Sketch"), filename))
174         {
175                 // If the filename still has wildcards, then we should
176                 // continue looking for the file we want
177                 if(find(filename.begin(),filename.end(),'*')!=filename.end())
178                         continue;
179
180                 if(get_work_area()->load_sketch(filename))
181                         break;
182
183                 get_canvas_view()->get_ui_interface()->error(_("Unable to load sketch"));
184         }
185         get_work_area()->queue_draw();
186 }
187
188 void
189 StateSketch_Context::clear_sketch()
190 {
191         get_work_area()->clear_persistant_strokes();
192         get_canvas_view()->get_smach().process_event(EVENT_REFRESH);
193 }
194
195 void
196 StateSketch_Context::undo_stroke()
197 {
198         if(!get_work_area()->persistant_stroke_list().empty())
199         {
200                 get_work_area()->persistant_stroke_list().pop_back();
201                 get_canvas_view()->get_smach().process_event(EVENT_REFRESH);
202         }
203 }
204
205 void
206 StateSketch_Context::toggle_show_sketch()
207 {
208         get_work_area()->set_show_persistant_strokes(checkbutton_show_sketch.get_active());
209         get_work_area()->queue_draw();
210 }
211
212 StateSketch_Context::StateSketch_Context(CanvasView* canvas_view):
213         action_group(Gtk::ActionGroup::create()),
214         canvas_view_(canvas_view),
215         is_working(*canvas_view),
216         prev_workarea_layer_status_(get_work_area()->allow_layer_clicks),
217         button_clear_sketch(_("Clear Sketch")),
218         button_undo_stroke(_("Undo Stroke")),
219         button_save_sketch(_("Save Sketch")),
220         button_load_sketch(_("Load Sketch")),
221         checkbutton_show_sketch(_("Show Sketch"))
222 {
223     Glib::ustring ui_info =
224         "<ui>"
225         "       <toolbar action='toolbar-sketch'>"
226         "       <toolitem action='sketch-undo' />"
227         "       <toolitem action='sketch-clear' />"
228         "       <toolitem action='sketch-save-as' />"
229         "       <toolitem action='sketch-open' />"
230         "       </toolbar>"
231         "</ui>";
232
233         action_group->add(Gtk::Action::create(
234                 "sketch-undo",
235                 Gtk::StockID("gtk-undo"),
236                 _("Undo Last Stroke"),
237                 _("Undo Last Stroke")
238         ),
239                 sigc::mem_fun(
240                         *this,
241                         &studio::StateSketch_Context::undo_stroke
242                 )
243         );
244
245         action_group->add(Gtk::Action::create(
246                 "sketch-clear",
247                 Gtk::StockID("gtk-clear"),
248                 _("Clear Sketch"),
249                 _("Clear Sketch")
250         ),
251                 sigc::mem_fun(
252                         *this,
253                         &studio::StateSketch_Context::clear_sketch
254                 )
255         );
256
257         action_group->add(Gtk::Action::create(
258                 "sketch-save-as",
259                 Gtk::StockID("gtk-save-as"),
260                 _("Save Sketch As..."),
261                 _("Save Sketch As...")
262         ),
263                 sigc::mem_fun(
264                         *this,
265                         &studio::StateSketch_Context::save_sketch
266                 )
267         );
268
269         action_group->add(Gtk::Action::create(
270                 "sketch-save-as",
271                 Gtk::StockID("gtk-save-as"),
272                 _("Save Sketch As..."),
273                 _("Save Sketch As...")
274         ),
275                 sigc::mem_fun(
276                         *this,
277                         &studio::StateSketch_Context::save_sketch
278                 )
279         );
280
281         action_group->add(Gtk::Action::create(
282                 "sketch-open",
283                 Gtk::StockID("gtk-open"),
284                 _("Open a Sketch"),
285                 _("Open a Sketch")
286         ),
287                 sigc::mem_fun(
288                         *this,
289                         &studio::StateSketch_Context::load_sketch
290                 )
291         );
292
293         action_group->add( Gtk::Action::create("toolbar-sketch", "Sketch Toolbar") );
294
295
296         App::ui_manager()->add_ui_from_string(ui_info);
297
298         
299         checkbutton_show_sketch.set_active(get_work_area()->get_show_persistant_strokes());
300         
301         button_clear_sketch.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::clear_sketch));
302         button_undo_stroke.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::undo_stroke));
303         button_save_sketch.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::save_sketch));
304         button_load_sketch.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::load_sketch));
305         checkbutton_show_sketch.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::toggle_show_sketch));
306         //options_table.attach(*manage(new Gtk::Label(_("Sketch Tool"))), 0, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);      
307         options_table.attach(checkbutton_show_sketch, 0, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);  
308         //options_table.attach(button_undo_stroke, 0, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);     
309         //options_table.attach(button_clear_sketch, 0, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);    
310         //options_table.attach(button_save_sketch, 0, 1, 4, 5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);     
311         //options_table.attach(button_load_sketch, 1, 2, 4, 5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);     
312
313         
314         options_table.show_all();
315         refresh_tool_options();
316         App::dialog_tool_options->present();
317         
318         // Turn off layer clicking
319         get_work_area()->allow_layer_clicks=false;
320
321         get_canvas_view()->work_area->set_cursor(Gdk::PENCIL);
322
323         // Turn off duck clicking
324         get_work_area()->allow_duck_clicks=false;
325         
326         // clear out the ducks
327         //get_work_area()->clear_ducks();
328         
329         // Refresh the work area
330         //get_work_area()->queue_draw();
331         
332         // Hide the tables if they are showing
333         prev_table_status=get_canvas_view()->tables_are_visible();
334         //if(prev_table_status)get_canvas_view()->hide_tables();
335                 
336         // Hide the time bar
337         //get_canvas_view()->hide_timebar();
338         
339         // Connect a signal
340         //get_work_area()->signal_user_click().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::on_user_click));
341
342         App::toolbox->refresh();
343 }
344
345 StateSketch_Context::~StateSketch_Context()
346 {
347         get_canvas_view()->work_area->reset_cursor();
348
349         App::dialog_tool_options->clear();
350         
351         // Restore layer clicking
352         get_work_area()->allow_layer_clicks=prev_workarea_layer_status_;
353
354         // Restore duck clicking
355         get_work_area()->allow_duck_clicks=true;
356
357         // Show the time bar
358         if(get_canvas_view()->get_canvas()->rend_desc().get_time_start()!=get_canvas_view()->get_canvas()->rend_desc().get_time_end())
359                 get_canvas_view()->show_timebar();
360
361         // Bring back the tables if they were out before
362         if(prev_table_status)get_canvas_view()->show_tables();
363                         
364         // Refresh the work area
365         //get_work_area()->queue_draw();
366
367         App::toolbox->refresh();
368 }
369
370 void
371 StateSketch_Context::yield_tool_options()
372 {
373         App::dialog_tool_options->clear();
374         App::ui_manager()->remove_action_group(action_group);
375 }
376
377 void
378 StateSketch_Context::refresh_tool_options()
379 {
380         App::dialog_tool_options->clear();
381         App::dialog_tool_options->set_widget(options_table);
382         App::dialog_tool_options->set_local_name(_("Sketch Tool"));
383         App::dialog_tool_options->set_name("sketch");
384
385         App::ui_manager()->insert_action_group(action_group);
386         App::dialog_tool_options->set_toolbar(*dynamic_cast<Gtk::Toolbar*>(App::ui_manager()->get_widget("/toolbar-sketch")));  
387
388         /*
389         App::dialog_tool_options->add_button(
390                 Gtk::StockID("gtk-undo"),
391                 _("Undo Last Stroke")
392         )->signal_clicked().connect(
393                 sigc::mem_fun(
394                         *this,
395                         &studio::StateSketch_Context::undo_stroke
396                 )
397         );
398         App::dialog_tool_options->add_button(
399                 Gtk::StockID("gtk-clear"),
400                 _("Clear Sketch")
401         )->signal_clicked().connect(
402                 sigc::mem_fun(
403                         *this,
404                         &studio::StateSketch_Context::clear_sketch
405                 )
406         );
407         App::dialog_tool_options->add_button(
408                 Gtk::StockID("gtk-save"),
409                 _("Save Sketch to a File")
410         )->signal_clicked().connect(
411                 sigc::mem_fun(
412                         *this,
413                         &studio::StateSketch_Context::save_sketch
414                 )
415         );
416
417         App::dialog_tool_options->add_button(
418                 Gtk::StockID("gtk-open"),
419                 _("Open a Sketch")
420         )->signal_clicked().connect(
421                 sigc::mem_fun(
422                         *this,
423                         &studio::StateSketch_Context::load_sketch
424                 )
425         );
426         */
427         //button_clear_sketch.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::clear_sketch));
428         //button_undo_stroke.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::undo_stroke));
429         //button_save_sketch.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::save_sketch));
430         //button_load_sketch.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::load_sketch));
431         //checkbutton_show_sketch.signal_clicked().connect(sigc::mem_fun(*this,&studio::StateSketch_Context::toggle_show_sketch));
432 }
433
434 Smach::event_result
435 StateSketch_Context::event_refresh_tool_options(const Smach::event& x)
436 {
437         refresh_tool_options();
438         return Smach::RESULT_ACCEPT;
439 }
440
441 Smach::event_result
442 StateSketch_Context::event_yield_tool_options(const Smach::event& x)
443 {
444         yield_tool_options();
445         return Smach::RESULT_ACCEPT;
446 }
447
448 Smach::event_result
449 StateSketch_Context::event_stop_handler(const Smach::event& x)
450 {
451         throw Smach::egress_exception();
452 }
453
454 Smach::event_result
455 StateSketch_Context::event_refresh_handler(const Smach::event& x)
456 {
457         return Smach::RESULT_ACCEPT;
458 }
459
460 Smach::event_result
461 StateSketch_Context::event_mouse_down_handler(const Smach::event& x)
462 {
463         const EventMouse& event(*reinterpret_cast<const EventMouse*>(&x));
464         switch(event.button)
465         {
466         case BUTTON_LEFT:
467                 {
468                         // Enter the stroke state to get the stroke
469                         get_canvas_view()->get_smach().push_state(&state_stroke);
470                         return Smach::RESULT_ACCEPT;
471                 }
472         
473         case BUTTON_RIGHT: // Intercept the right-button click to short-circut the pop-up menu
474                 return Smach::RESULT_ACCEPT;
475         
476         default:        
477                 return Smach::RESULT_OK;
478         }
479 }
480
481 Smach::event_result
482 StateSketch_Context::event_stroke(const Smach::event& x)
483 {
484         const EventStroke& event(*reinterpret_cast<const EventStroke*>(&x));
485
486         assert(event.stroke_data);
487                 
488         get_work_area()->add_persistant_stroke(event.stroke_data,sinfgapp::Main::get_foreground_color());
489
490         return Smach::RESULT_ACCEPT;
491 }