source: synfigstudio/trunk/fuentes/src/gui/states/state_normal.cpp @ 481

Last change on this file since 481 was 481, checked in by jrpelegrina, 4 years ago

First release to xenial

File size: 22.8 KB
Line 
1/* === S Y N F I G ========================================================= */
2/*!     \file state_normal.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) 2009 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/* === 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 <gtkmm/dialog.h>
35#include <gtkmm/entry.h>
36#include <gdk/gdkkeysyms.h>
37
38#include <synfig/valuenodes/valuenode_animated.h>
39#include <synfig/valuenodes/valuenode_blinecalcvertex.h>
40#include <synfig/valuenodes/valuenode_composite.h>
41#include <synfig/valuenodes/valuenode_const.h>
42#include <synfig/valuenodes/valuenode_dynamiclist.h>
43#include <synfigapp/action_system.h>
44
45#include "state_normal.h"
46#include "canvasview.h"
47#include "workarea.h"
48#include "app.h"
49
50#include <synfigapp/action.h>
51#include "event_mouse.h"
52#include "event_layerclick.h"
53#include "event_keyboard.h"
54#include "docks/dock_toolbox.h"
55#include "docks/dialog_tooloptions.h"
56#include "duck.h"
57#include <synfig/angle.h>
58#include <synfigapp/main.h>
59
60#include "general.h"
61#endif
62
63/* === U S I N G =========================================================== */
64
65using namespace std;
66using namespace etl;
67using namespace synfig;
68using namespace studio;
69
70/* === M A C R O S ========================================================= */
71
72#ifndef EPSILON
73#define EPSILON 0.0000001
74#endif
75
76#if !GTK_CHECK_VERSION(2, 21, 0)
77#define GDK_KEY_Control_L GDK_Control_L
78#define GDK_KEY_Control_R GDK_Control_R
79#define GDK_KEY_Shift_L GDK_Shift_L
80#define GDK_KEY_Shift_R GDK_Shift_R
81#define GDK_KEY_Alt_L GDK_Alt_L
82#define GDK_KEY_Alt_R GDK_Alt_R
83#define GDK_KEY_Meta_L GDK_Meta_L
84#define GDK_KEY_Meta_R GDK_Meta_R
85#define GDK_KEY_space GDK_space
86#endif
87
88/* === G L O B A L S ======================================================= */
89
90StateNormal studio::state_normal;
91
92/* === C L A S S E S & S T R U C T S ======================================= */
93
94class DuckDrag_Combo : public DuckDrag_Base
95{
96        synfig::Vector last_move;
97        synfig::Vector drag_offset;
98        synfig::Vector center;
99        synfig::Vector snap;
100
101        synfig::Angle original_angle;
102        synfig::Real original_mag;
103
104        std::vector<synfig::Vector> last_;
105        std::vector<synfig::Vector> positions;
106
107
108        bool bad_drag;
109        bool move_only;
110
111        bool is_moving;
112
113public:
114        CanvasView* canvas_view_;
115        bool scale;
116        bool rotate;
117        bool constrain;
118        DuckDrag_Combo();
119        void begin_duck_drag(Duckmatic* duckmatic, const synfig::Vector& begin);
120        bool end_duck_drag(Duckmatic* duckmatic);
121        void duck_drag(Duckmatic* duckmatic, const synfig::Vector& vector);
122
123        etl::handle<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view_->canvas_interface();}
124};
125
126
127class studio::StateNormal_Context : public sigc::trackable
128{
129        CanvasView* canvas_view_;
130
131        etl::handle<DuckDrag_Combo> duck_dragger_;
132
133        Gtk::Table options_table;
134
135        bool ctrl_pressed;
136        bool alt_pressed;
137        bool shift_pressed;
138        bool space_pressed;
139
140        void set_ctrl_pressed(bool value);
141        void set_alt_pressed(bool value);
142        void set_shift_pressed(bool value);
143        void set_space_pressed(bool value);
144
145public:
146
147        void refresh_cursor();
148
149        bool get_rotate_flag()const { if(duck_dragger_) return duck_dragger_->rotate; else return false; }
150        void set_rotate_flag(bool x) { if(duck_dragger_ && x!=duck_dragger_->rotate)
151                                               {duck_dragger_->rotate=x; refresh_cursor();} }
152
153        bool get_scale_flag()const { if(duck_dragger_) return duck_dragger_->scale; else return false; }
154        void set_scale_flag(bool x) { if(duck_dragger_ && x!=duck_dragger_->scale)
155                                              {duck_dragger_->scale=x; refresh_cursor();} }
156
157        bool get_constrain_flag()const { if(duck_dragger_) return duck_dragger_->constrain; else return false; }
158        void set_constrain_flag(bool x) { if(duck_dragger_ && x!=duck_dragger_->constrain)
159                                                  {duck_dragger_->constrain=x; refresh_cursor();} }
160
161        bool get_alternative_flag()const
162        {
163                return get_canvas_view()
164                        && get_canvas_view()->get_work_area()
165                        && get_canvas_view()->get_work_area()->get_alternative_mode();
166        }
167        void set_alternative_flag(bool x)
168        {
169                if ( get_canvas_view()
170                  && get_canvas_view()->get_work_area()
171                  && get_canvas_view()->get_work_area()->get_alternative_mode() != x )
172                {
173                        get_canvas_view()->get_work_area()->set_alternative_mode(x);
174                        get_canvas_view()->get_work_area()->queue_draw();
175                        refresh_cursor();
176                }
177        }
178
179        bool get_lock_animation_flag()const
180        {
181                return get_canvas_view()
182                        && get_canvas_view()->get_work_area()
183                        && get_canvas_view()->get_work_area()->get_lock_animation_mode();
184        }
185        void set_lock_animation_flag(bool x)
186        {
187                if ( get_canvas_view()
188                  && get_canvas_view()->get_work_area()
189                  && get_canvas_view()->get_work_area()->get_lock_animation_mode() != x )
190                {
191                        get_canvas_view()->get_work_area()->set_lock_animation_mode(x);
192                        get_canvas_view()->get_work_area()->queue_draw();
193                        refresh_cursor();
194                }
195        }
196
197        StateNormal_Context(CanvasView* canvas_view);
198
199        ~StateNormal_Context();
200
201        CanvasView* get_canvas_view()const{return canvas_view_;}
202        etl::handle<synfigapp::CanvasInterface> get_canvas_interface()const{return canvas_view_->canvas_interface();}
203        synfig::Canvas::Handle get_canvas()const{return canvas_view_->get_canvas();}
204        WorkArea * get_work_area()const{return canvas_view_->get_work_area();}
205
206        Smach::event_result event_stop_handler(const Smach::event& x);
207        Smach::event_result event_refresh_handler(const Smach::event& x);
208        Smach::event_result event_refresh_ducks_handler(const Smach::event& x);
209        Smach::event_result event_undo_handler(const Smach::event& x);
210        Smach::event_result event_redo_handler(const Smach::event& x);
211        Smach::event_result event_mouse_button_down_handler(const Smach::event& x);
212        Smach::event_result event_multiple_ducks_clicked_handler(const Smach::event& x);
213        Smach::event_result event_mouse_motion_handler(const Smach::event& x);
214        Smach::event_result event_key_down_handler(const Smach::event& x);
215        Smach::event_result event_key_up_handler(const Smach::event& x);
216        Smach::event_result event_refresh_tool_options(const Smach::event& x);
217        void refresh_tool_options();
218        Smach::event_result event_layer_click(const Smach::event& x);
219
220
221};      // END of class StateNormal_Context
222
223/* === M E T H O D S ======================================================= */
224
225StateNormal::StateNormal():
226        Smach::state<StateNormal_Context>("normal")
227{
228        insert(event_def(EVENT_STOP,&StateNormal_Context::event_stop_handler));
229        insert(event_def(EVENT_REFRESH,&StateNormal_Context::event_refresh_handler));
230        insert(event_def(EVENT_REFRESH_DUCKS,&StateNormal_Context::event_refresh_ducks_handler));
231        insert(event_def(EVENT_UNDO,&StateNormal_Context::event_undo_handler));
232        insert(event_def(EVENT_REDO,&StateNormal_Context::event_redo_handler));
233        insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateNormal_Context::event_mouse_button_down_handler));
234        insert(event_def(EVENT_WORKAREA_MULTIPLE_DUCKS_CLICKED,&StateNormal_Context::event_multiple_ducks_clicked_handler));
235        insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateNormal_Context::event_refresh_tool_options));
236        insert(event_def(EVENT_WORKAREA_MOUSE_MOTION,           &StateNormal_Context::event_mouse_motion_handler));
237        insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DRAG,      &StateNormal_Context::event_mouse_motion_handler));
238        insert(event_def(EVENT_WORKAREA_KEY_DOWN,&StateNormal_Context::event_key_down_handler));
239        insert(event_def(EVENT_WORKAREA_KEY_UP,&StateNormal_Context::event_key_up_handler));
240        insert(event_def(EVENT_WORKAREA_LAYER_CLICKED,&StateNormal_Context::event_layer_click));
241
242}
243
244StateNormal::~StateNormal()
245{
246}
247
248void StateNormal_Context::refresh_cursor()
249{
250        // Check the current state and return when applicable
251        synfig::String sname;
252        sname=get_canvas_view()->get_smach().get_state_name();
253        if (sname!="normal")
254                        return;
255
256        // Change the cursor based on key flags
257        if(get_rotate_flag() && !get_scale_flag())
258        {
259            //!TODO Do not change the cursor in WorkArea::DragMode mode, but actually not stable enough to catch
260            //! real DRAGBOX mode (go to DRAGNONE too quick)
261                get_work_area()->set_cursor(Gdk::EXCHANGE);
262                return;
263        }
264        if(!get_rotate_flag() && get_scale_flag())
265        {
266                get_work_area()->set_cursor(Gdk::SIZING);
267                return;
268        }
269        if(get_rotate_flag() && get_scale_flag())
270        {
271                get_work_area()->set_cursor(Gdk::CROSSHAIR);
272                return;
273        }
274        if(get_lock_animation_flag())
275        {
276                get_work_area()->set_cursor(Gdk::DRAFT_LARGE);
277                return;
278        }
279
280        // Default cursor for Transform tool
281        get_work_area()->set_cursor(Gdk::ARROW);
282
283}
284
285StateNormal_Context::StateNormal_Context(CanvasView* canvas_view):
286        canvas_view_(canvas_view),
287        duck_dragger_(new DuckDrag_Combo()),
288        ctrl_pressed(),
289        alt_pressed(),
290        shift_pressed()
291{
292        duck_dragger_->canvas_view_=get_canvas_view();
293
294        // Set up the tool options dialog
295        options_table.attach(*manage(new Gtk::Label(_("Transform Tool"))),      0, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
296        options_table.attach(*manage(new Gtk::Label(_("Ctrl to rotate"), Gtk::ALIGN_START)),    0, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
297        options_table.attach(*manage(new Gtk::Label(_("Alt to scale"), Gtk::ALIGN_START)),      0, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
298        options_table.attach(*manage(new Gtk::Label(_("Shift to constrain"), Gtk::ALIGN_START)),        0, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
299
300        options_table.show_all();
301        refresh_tool_options();
302        //App::dialog_tool_options->set_widget(options_table);
303        //App::dialog_tool_options->present();
304
305        get_work_area()->set_allow_layer_clicks(true);
306        get_work_area()->set_duck_dragger(duck_dragger_);
307
308        //these will segfault
309//      get_work_area()->set_cursor(Gdk::CROSSHAIR);
310//      get_work_area()->reset_cursor();
311
312        App::dock_toolbox->refresh();
313}
314
315void
316StateNormal_Context::refresh_tool_options()
317{
318        App::dialog_tool_options->clear();
319        App::dialog_tool_options->set_widget(options_table);
320        App::dialog_tool_options->set_local_name(_("Transform Tool"));
321        App::dialog_tool_options->set_name("normal");
322}
323
324
325
326StateNormal_Context::~StateNormal_Context()
327{
328        get_work_area()->clear_duck_dragger();
329        get_work_area()->reset_cursor();
330
331        App::dialog_tool_options->clear();
332
333        App::dock_toolbox->refresh();
334}
335
336DuckDrag_Combo::DuckDrag_Combo():
337        original_mag(),
338        bad_drag(),
339        move_only(),
340        is_moving(false),
341        canvas_view_(NULL),
342        scale(false),
343        rotate(false),
344        constrain(false) // Lock aspect for scale
345{ }
346
347void
348DuckDrag_Combo::begin_duck_drag(Duckmatic* duckmatic, const synfig::Vector& offset)
349{
350        is_moving = false;
351        last_move=Vector(1,1);
352
353        const DuckList selected_ducks(duckmatic->get_selected_ducks());
354        DuckList::const_iterator iter;
355
356        bad_drag=false;
357
358                drag_offset=duckmatic->find_duck(offset)->get_trans_point();
359
360                //snap=drag_offset-duckmatic->snap_point_to_grid(drag_offset);
361                //snap=offset-drag_offset_;
362                snap=Vector(0,0);
363
364        // Calculate center
365        Point vmin(100000000,100000000);
366        Point vmax(-100000000,-100000000);
367        //std::set<etl::handle<Duck> >::iterator iter;
368        positions.clear();
369        int i;
370        for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
371        {
372                Point p((*iter)->get_trans_point());
373                vmin[0]=min(vmin[0],p[0]);
374                vmin[1]=min(vmin[1],p[1]);
375                vmax[0]=max(vmax[0],p[0]);
376                vmax[1]=max(vmax[1],p[1]);
377                positions.push_back(p);
378        }
379        center=(vmin+vmax)*0.5;
380        if((vmin-vmax).mag()<=EPSILON)
381                move_only=true;
382        else
383                move_only=false;
384
385
386        synfig::Vector vect(offset-center);
387        original_angle=Angle::tan(vect[1],vect[0]);
388        original_mag=vect.mag();
389}
390
391
392void
393DuckDrag_Combo::duck_drag(Duckmatic* duckmatic, const synfig::Vector& vector)
394{
395        if (!duckmatic) return;
396
397        if(bad_drag)
398                return;
399
400        //Override axis lock set in workarea when holding down the shift key
401        if (!move_only && (scale || rotate))
402                duckmatic->set_axis_lock(false);
403
404        synfig::Vector vect;
405        if (move_only || (!scale && !rotate))
406                vect= duckmatic->snap_point_to_grid(vector)-drag_offset+snap;
407        else
408                vect= duckmatic->snap_point_to_grid(vector)-center+snap;
409
410        last_move=vect;
411
412        const DuckList selected_ducks(duckmatic->get_selected_ducks());
413        DuckList::const_iterator iter;
414
415        Time time(duckmatic->get_time());
416
417        int i;
418        if( move_only || (!scale && !rotate) )
419        {
420                for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
421                {
422                        if((*iter)->get_type()==Duck::TYPE_VERTEX || (*iter)->get_type()==Duck::TYPE_POSITION)
423                                (*iter)->set_trans_point(positions[i]+vect, time);
424                }
425                for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
426                {
427                        if((*iter)->get_type()!=Duck::TYPE_VERTEX&&(*iter)->get_type()!=Duck::TYPE_POSITION)
428                                (*iter)->set_trans_point(positions[i]+vect, time);
429                }
430        }
431
432        if (rotate)
433        {
434                Angle::deg angle(Angle::tan(vect[1],vect[0]));
435                angle=original_angle-angle;
436                if (constrain)
437                {
438                        float degrees = angle.get()/15;
439                        angle= Angle::deg (degrees>0?std::floor(degrees)*15:std::ceil(degrees)*15);
440                }
441                Real mag(vect.mag()/original_mag);
442                Real sine(Angle::sin(angle).get());
443                Real cosine(Angle::cos(angle).get());
444
445                for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
446                {
447                        if((*iter)->get_type()!=Duck::TYPE_VERTEX&&(*iter)->get_type()!=Duck::TYPE_POSITION)continue;
448
449                        Vector x(positions[i]-center),p;
450
451                        p[0]=cosine*x[0]+sine*x[1];
452                        p[1]=-sine*x[0]+cosine*x[1];
453                        if(scale)p*=mag;
454                        p+=center;
455                        (*iter)->set_trans_point(p, time);
456                }
457                for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
458                {
459                        if(!((*iter)->get_type()!=Duck::TYPE_VERTEX&&(*iter)->get_type()!=Duck::TYPE_POSITION))continue;
460
461                        Vector x(positions[i]-center),p;
462
463                        p[0]=cosine*x[0]+sine*x[1];
464                        p[1]=-sine*x[0]+cosine*x[1];
465                        if(scale)p*=mag;
466                        p+=center;
467                        (*iter)->set_trans_point(p, time);
468                }
469        } else if (scale)
470        {
471                if(!constrain)
472                {
473                        if(abs(drag_offset[0]-center[0])>EPSILON)
474                                vect[0]/=drag_offset[0]-center[0];
475                        else
476                                vect[0]=1;
477                        if(abs(drag_offset[1]-center[1])>EPSILON)
478                                vect[1]/=drag_offset[1]-center[1];
479                        else
480                                vect[1]=1;
481                        }
482                else
483                {
484                        Real amount;
485                        if((drag_offset-center).mag() < EPSILON)
486                                amount = 1;
487                        else
488                                amount = vect.mag()/(drag_offset-center).mag();
489
490                        vect[0]=vect[1]=amount;
491                }
492
493                if(vect[0]<EPSILON && vect[0]>-EPSILON)
494                        vect[0]=1;
495                if(vect[1]<EPSILON && vect[1]>-EPSILON)
496                        vect[1]=1;
497
498                for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
499                {
500                        if(((*iter)->get_type()!=Duck::TYPE_VERTEX&&(*iter)->get_type()!=Duck::TYPE_POSITION))continue;
501
502                        Vector p(positions[i]-center);
503
504                        p[0]*=vect[0];
505                        p[1]*=vect[1];
506                        p+=center;
507                        (*iter)->set_trans_point(p, time);
508                }
509                for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++)
510                {
511                        if(!((*iter)->get_type()!=Duck::TYPE_VERTEX&&(*iter)->get_type()!=Duck::TYPE_POSITION))continue;
512
513                        Vector p(positions[i]-center);
514
515                        p[0]*=vect[0];
516                        p[1]*=vect[1];
517                        p+=center;
518                        (*iter)->set_trans_point(p, time);
519                }
520
521        }
522
523        last_move=vect;
524
525        if((last_move-Vector(1,1)).mag()>0.0001)
526                is_moving = true;
527
528        if (is_moving)
529                duckmatic->signal_edited_selected_ducks(true);
530
531        // then patch up the tangents for the vertices we've moved
532        duckmatic->update_ducks();
533}
534
535bool
536DuckDrag_Combo::end_duck_drag(Duckmatic* duckmatic)
537{
538        if(bad_drag)return false;
539
540        //synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Rotate Ducks"));
541
542        if(is_moving)
543        {
544                duckmatic->signal_edited_selected_ducks();
545                return true;
546        }
547        else
548        {
549                duckmatic->signal_user_click_selected_ducks(0);
550                return false;
551        }
552}
553
554Smach::event_result
555StateNormal_Context::event_refresh_tool_options(const Smach::event& /*x*/)
556{
557        refresh_tool_options();
558        return Smach::RESULT_ACCEPT;
559}
560
561Smach::event_result
562StateNormal_Context::event_stop_handler(const Smach::event& /*x*/)
563{
564        // synfig::info("STATE NORMAL: Received Stop Event");
565        canvas_view_->stop();
566        return Smach::RESULT_ACCEPT;
567}
568
569Smach::event_result
570StateNormal_Context::event_refresh_handler(const Smach::event& /*x*/)
571{
572        // synfig::info("STATE NORMAL: Received Refresh Event");
573        canvas_view_->rebuild_tables();
574        canvas_view_->work_area->queue_render_preview();
575        return Smach::RESULT_ACCEPT;
576}
577
578Smach::event_result
579StateNormal_Context::event_refresh_ducks_handler(const Smach::event& /*x*/)
580{
581        // synfig::info("STATE NORMAL: Received Refresh Ducks");
582        canvas_view_->queue_rebuild_ducks();
583        return Smach::RESULT_ACCEPT;
584}
585
586Smach::event_result
587StateNormal_Context::event_undo_handler(const Smach::event& /*x*/)
588{
589        // synfig::info("STATE NORMAL: Received Undo Event");
590        canvas_view_->get_instance()->undo();
591        return Smach::RESULT_ACCEPT;
592}
593
594Smach::event_result
595StateNormal_Context::event_redo_handler(const Smach::event& /*x*/)
596{
597        // synfig::info("STATE NORMAL: Received Redo Event");
598        canvas_view_->get_instance()->redo();
599        return Smach::RESULT_ACCEPT;
600}
601
602Smach::event_result
603StateNormal_Context::event_mouse_button_down_handler(const Smach::event& x)
604{
605        // synfig::info("STATE NORMAL: Received mouse button down Event");
606
607        const EventMouse& event(*reinterpret_cast<const EventMouse*>(&x));
608
609        switch(event.button)
610        {
611        case BUTTON_RIGHT:
612                canvas_view_->popup_main_menu();
613                return Smach::RESULT_ACCEPT;
614        default:
615                return Smach::RESULT_OK;
616        }
617}
618
619Smach::event_result
620StateNormal_Context::event_mouse_motion_handler(const Smach::event& x)
621{
622        // synfig::info("STATE NORMAL: Received mouse button down Event");
623
624        const EventMouse& event(*reinterpret_cast<const EventMouse*>(&x));
625
626        set_ctrl_pressed(event.modifier&GDK_CONTROL_MASK);
627        set_alt_pressed(event.modifier&GDK_MOD1_MASK);
628        set_shift_pressed(event.modifier&GDK_SHIFT_MASK);
629
630        return Smach::RESULT_OK;
631}
632
633void
634StateNormal_Context::set_ctrl_pressed(bool value)
635{
636        if (ctrl_pressed == value) return;
637        ctrl_pressed = value;
638
639        if (ctrl_pressed)
640        {
641                if (get_canvas_view()->get_work_area()->get_selected_ducks().size() <= 1
642                 /* && get_canvas_view()->get_work_area()->get_selected_duck()->get_value_desc().get_value_type() == synfig::type_transformation */ )
643                {
644                        set_rotate_flag(false);
645                        set_alternative_flag(true);
646                }
647                else
648                {
649                        set_rotate_flag(true);
650                        set_alternative_flag(false);
651                }
652        }
653        else
654        {
655                set_alternative_flag(false);
656                set_rotate_flag(false);
657        }
658}
659
660void
661StateNormal_Context::set_alt_pressed(bool value)
662{
663        if (alt_pressed == value) return;
664        alt_pressed = value;
665        set_scale_flag(alt_pressed);
666}
667
668void
669StateNormal_Context::set_shift_pressed(bool value)
670{
671        if (shift_pressed == value) return;
672        shift_pressed = value;
673        set_constrain_flag(shift_pressed);
674}
675
676void
677StateNormal_Context::set_space_pressed(bool value)
678{
679        if (space_pressed == value) return;
680        space_pressed = value;
681        set_lock_animation_flag(space_pressed);
682}
683
684Smach::event_result
685StateNormal_Context::event_key_down_handler(const Smach::event& x)
686{
687        // event.modifier yet not set when ctrl (or alt or shift)
688        // key pressed event handled. So we need to check this keys manually.
689        // We may encountred some cosmetic problems with mouse-cursor image
690        // if user will redefine modifier keys.
691        // Anyway processing of keys Ctrl+Right, Ctrl+Left etc will works fine.
692        // see 'xmodmap' command
693        const EventKeyboard& event(*reinterpret_cast<const EventKeyboard*>(&x));
694        switch(event.keyval)
695        {
696        case GDK_KEY_Control_L:
697        case GDK_KEY_Control_R:
698                set_ctrl_pressed(true);
699                break;
700        case GDK_KEY_Alt_L:
701        case GDK_KEY_Alt_R:
702        case GDK_KEY_Meta_L:
703                set_alt_pressed(true);
704                break;
705        case GDK_KEY_Shift_L:
706        case GDK_KEY_Shift_R:
707                set_shift_pressed(true);
708                break;
709        case GDK_KEY_space:
710                set_space_pressed(true);
711                break;
712        default:
713                set_ctrl_pressed(event.modifier&GDK_CONTROL_MASK);
714                set_alt_pressed(event.modifier&GDK_MOD1_MASK);
715                set_shift_pressed(event.modifier&GDK_SHIFT_MASK);
716                break;
717        }
718        return Smach::RESULT_REJECT;
719}
720
721Smach::event_result
722StateNormal_Context::event_key_up_handler(const Smach::event& x)
723{
724        // see event_key_down_handler for possible problems
725        const EventKeyboard& event(*reinterpret_cast<const EventKeyboard*>(&x));
726        switch(event.keyval)
727        {
728        case GDK_KEY_Control_L:
729        case GDK_KEY_Control_R:
730                set_ctrl_pressed(false);
731                break;
732        case GDK_KEY_Alt_L:
733        case GDK_KEY_Alt_R:
734        case GDK_KEY_Meta_L:
735                set_alt_pressed(false);
736                break;
737        case GDK_KEY_Shift_L:
738        case GDK_KEY_Shift_R:
739                set_shift_pressed(false);
740                break;
741        case GDK_KEY_space:
742                set_space_pressed(false);
743                break;
744        default:
745                break;
746        }
747        return Smach::RESULT_REJECT;
748}
749
750Smach::event_result
751StateNormal_Context::event_layer_click(const Smach::event& x)
752{
753        const EventLayerClick& event(*reinterpret_cast<const EventLayerClick*>(&x));
754
755        if(event.layer)
756        {
757                // synfig::info("STATE NORMAL: Received layer click Event, \"%s\"",event.layer->get_name().c_str());
758        }
759        else
760        {
761                // synfig::info("STATE NORMAL: Received layer click Event with an empty layer.");
762        }
763
764        switch(event.button)
765        {
766        case BUTTON_LEFT:
767                if(!(event.modifier&Gdk::CONTROL_MASK))
768                        canvas_view_->get_selection_manager()->clear_selected_layers();
769                if(event.layer)
770                {
771                        std::list<Layer::Handle> layer_list(canvas_view_->get_selection_manager()->get_selected_layers());
772                        std::set<Layer::Handle> layers(layer_list.begin(),layer_list.end());
773                        if(layers.count(event.layer))
774                        {
775                                layers.erase(event.layer);
776                                layer_list=std::list<Layer::Handle>(layers.begin(),layers.end());
777                                canvas_view_->get_selection_manager()->clear_selected_layers();
778                                canvas_view_->get_selection_manager()->set_selected_layers(layer_list);
779                        }
780                        else
781                        {
782                                canvas_view_->get_selection_manager()->set_selected_layer(event.layer);
783                        }
784                }
785                return Smach::RESULT_ACCEPT;
786        case BUTTON_RIGHT:
787                canvas_view_->popup_layer_menu(event.layer);
788                return Smach::RESULT_ACCEPT;
789        default:
790                return Smach::RESULT_OK;
791        }
792}
793
794Smach::event_result
795StateNormal_Context::event_multiple_ducks_clicked_handler(const Smach::event& x)
796{
797        // synfig::info("STATE NORMAL: Received multiple duck click event");
798
799        //const EventMouse& event(*reinterpret_cast<const EventMouse*>(&x));
800
801        std::list<synfigapp::ValueDesc> value_desc_list;
802
803        // Create a list of value_descs associated with selection
804        const DuckList selected_ducks(get_work_area()->get_selected_ducks());
805        DuckList::const_iterator iter;
806        for(iter=selected_ducks.begin();iter!=selected_ducks.end();++iter)
807        {
808                synfigapp::ValueDesc value_desc((*iter)->get_value_desc());
809
810                if(!value_desc.is_valid())
811                        continue;
812                value_desc_list.push_back(value_desc);
813        }
814
815        Gtk::Menu *menu=manage(new Gtk::Menu());
816        menu->signal_hide().connect(sigc::bind(sigc::ptr_fun(&delete_widget), menu));
817
818        const EventMouse& event(*reinterpret_cast<const EventMouse*>(&x));
819        canvas_view_->get_instance()->make_param_menu(
820                        menu,
821                        canvas_view_->get_canvas(),
822                        value_desc_list,
823                        event.duck ? event.duck->get_value_desc() : synfigapp::ValueDesc()
824                );
825
826        menu->popup(3,gtk_get_current_event_time());
827
828        return Smach::RESULT_ACCEPT;
829}
830
831
Note: See TracBrowser for help on using the repository browser.