1 /* === S Y N F I G ========================================================= */
2 /*! \file state_zoom.cpp
3 ** \brief Zoom Tool Implementation File
8 ** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 ** Copyright (c) 2008 Chris Moore
11 ** This package is free software; you can redistribute it and/or
12 ** modify it under the terms of the GNU General Public License as
13 ** published by the Free Software Foundation; either version 2 of
14 ** the License, or (at your option) any later version.
16 ** This package is distributed in the hope that it will be useful,
17 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 ** General Public License for more details.
22 /* ========================================================================= */
24 /* === H E A D E R S ======================================================= */
33 #include <sigc++/signal.h>
34 #include <sigc++/object.h>
37 #include <synfig/vector.h>
40 #include "state_zoom.h"
41 #include "event_mouse.h"
42 #include "canvasview.h"
46 #include <synfigapp/main.h>
52 /* === U S I N G =========================================================== */
56 using namespace synfig
;
57 using namespace studio
;
59 /* === M A C R O S ========================================================= */
61 /* === G L O B A L S ======================================================= */
62 StateZoom
studio::state_zoom
;
64 const float ZOOMFACTOR
= 1.25f
;
66 /* === C L A S S E S & S T R U C T S ======================================= */
68 class studio::StateZoom_Context
: public sigc::trackable
70 etl::handle
<CanvasView
> canvas_view_
;
71 CanvasView::IsWorking is_working
;
75 bool prev_workarea_layer_status_
;
80 Smach::event_result
event_stop_handler(const Smach::event
& x
);
81 Smach::event_result
event_refresh_handler(const Smach::event
& x
);
82 Smach::event_result
event_mouse_click_handler(const Smach::event
& x
);
84 //constructor destructor
85 StateZoom_Context(CanvasView
* canvas_view
);
89 const etl::handle
<CanvasView
>& get_canvas_view()const{return canvas_view_
;}
90 etl::handle
<synfigapp::CanvasInterface
> get_canvas_interface()const{return canvas_view_
->canvas_interface();}
91 synfig::Canvas::Handle
get_canvas()const{return canvas_view_
->get_canvas();}
92 WorkArea
* get_work_area()const{return canvas_view_
->get_work_area();}
94 //void zoom(const Point& p1, const Point& p2);
96 }; // END of class StateZoom_Context
98 /* === M E T H O D S ======================================================= */
100 StateZoom::StateZoom():
101 Smach::state
<StateZoom_Context
>("zoom")
103 insert(event_def(EVENT_STOP
,&StateZoom_Context::event_stop_handler
));
104 insert(event_def(EVENT_REFRESH
,&StateZoom_Context::event_refresh_handler
));
105 insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN
,&StateZoom_Context::event_mouse_click_handler
));
106 //insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DRAG,&StateZoom_Context::event_mouse_click_handler));
107 insert(event_def(EVENT_WORKAREA_BOX
,&StateZoom_Context::event_mouse_click_handler
));
108 //insert(event_def(EVENT_WORKAREA_BUTTON_CLICK,&StateZoom_Context::event_mouse_click_handler));
109 insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_UP
,&StateZoom_Context::event_mouse_click_handler
));
112 StateZoom::~StateZoom()
116 StateZoom_Context::StateZoom_Context(CanvasView
* canvas_view
):
117 canvas_view_(canvas_view
),
118 is_working(*canvas_view
),
119 prev_workarea_layer_status_(get_work_area()->get_allow_layer_clicks())
121 // Turn off layer clicking
122 get_work_area()->set_allow_layer_clicks(false);
124 // clear out the ducks
125 get_work_area()->clear_ducks(); //???
127 // Refresh the work area
128 get_work_area()->queue_draw();
130 // Hide the tables if they are showing
131 //prev_table_status=get_canvas_view()->tables_are_visible();
132 //if(prev_table_status)get_canvas_view()->hide_tables();
134 // Disable the time bar
135 //get_canvas_view()->set_sensitive_timebar(false);
138 //get_work_area()->signal_user_click().connect(sigc::mem_fun(*this,&studio::StateZoom_Context::on_user_click));
139 get_canvas_view()->work_area
->set_cursor(Gdk::CROSSHAIR
);
141 App::toolbox
->refresh();
144 StateZoom_Context::~StateZoom_Context()
146 // Restore layer clicking
147 get_work_area()->set_allow_layer_clicks(prev_workarea_layer_status_
);
148 get_canvas_view()->work_area
->reset_cursor();
150 // Enable the time bar
151 //get_canvas_view()->set_sensitive_timebar(true);
153 // Bring back the tables if they were out before
154 //if(prev_table_status)get_canvas_view()->show_tables();
156 // Refresh the work area
157 get_work_area()->queue_draw();
159 App::toolbox
->refresh();
161 get_canvas_view()->get_smach().process_event(EVENT_REFRESH_DUCKS
);
165 StateZoom_Context::event_stop_handler(const Smach::event
& /*x*/)
167 throw Smach::egress_exception();
171 StateZoom_Context::event_refresh_handler(const Smach::event
& /*x*/)
173 return Smach::RESULT_ACCEPT
;
177 StateZoom_Context::event_mouse_click_handler(const Smach::event
& x
)
179 if(x
.key
==EVENT_WORKAREA_BOX
)
181 const EventBox
& event(*reinterpret_cast<const EventBox
*>(&x
));
183 if(event
.button
==BUTTON_LEFT
)
185 //respond to event box...
188 //Center the new position at the center of the box
190 //OH MY GOD HACK - the space is -1* and offset (by the value of the center of the canvas)...
193 const Point evcenter
= (event
.p1
+event
.p2
)/2;
194 const Point realcenter
= (get_work_area()->get_window_tl() + get_work_area()->get_window_br())/2;
195 newpos
= -(evcenter
- realcenter
) + get_work_area()->get_focus_point();
198 //The zoom will be whatever the required factor to convert current box size to desired box size
199 Point tl
= get_work_area()->get_window_tl();
200 Point br
= get_work_area()->get_window_br();
202 Vector span
= br
- tl
;
203 Vector v
= event
.p2
- event
.p1
;
205 //get the minimum zoom as long as it's greater than 1...
206 v
[0] = abs(v
[0])/abs(span
[0]);
207 v
[1] = abs(v
[1])/abs(span
[1]);
209 float zdiv
= max(v
[0],v
[1]);
210 if(zdiv
> 0) //must be zoomable
212 get_work_area()->set_focus_point(newpos
);
213 get_work_area()->set_zoom(get_work_area()->get_zoom()/zdiv
);
216 return Smach::RESULT_ACCEPT
;
220 if(x
.key
==EVENT_WORKAREA_MOUSE_BUTTON_UP
)
222 const EventMouse
& event(*reinterpret_cast<const EventMouse
*>(&x
));
224 if(event
.button
==BUTTON_LEFT
)
228 //make the event pos be in the same space...
229 // The weird ass inverted center normalized space...
231 const Point realcenter
= (get_work_area()->get_window_tl() + get_work_area()->get_window_br())/2;
232 evpos
= -(event
.pos
- realcenter
) + get_work_area()->get_focus_point();
236 focus point must zoom about the point evpos...
238 trans about an origin not 0:
242 Vector v
= get_work_area()->get_focus_point() - evpos
;
244 if(event
.modifier
& Gdk::CONTROL_MASK
) //zoom out...
247 //get_work_area()->zoom_out();
248 get_work_area()->set_focus_point(evpos
+ v
);
249 get_work_area()->set_zoom(get_work_area()->get_zoom()/ZOOMFACTOR
);
253 //get_work_area()->zoom_in();
254 get_work_area()->set_focus_point(evpos
+ v
);
255 get_work_area()->set_zoom(get_work_area()->get_zoom()*ZOOMFACTOR
);
258 return Smach::RESULT_ACCEPT
;
262 return Smach::RESULT_OK
;