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 Point tl
= get_work_area()->get_window_tl();
186 Point br
= get_work_area()->get_window_br();
187 Vector window_span
= br
- tl
, window_middle
= (br
+tl
)/2;
188 Vector box_span
= event
.p2
- event
.p1
, box_middle
= (event
.p1
+event
.p2
)/2;
192 if(event
.modifier
& Gdk::CONTROL_MASK
) //zoom out...
194 if (window_span
[0] == 0 || window_span
[1] == 0) zoom
= 1;
195 else zoom
= max(abs(box_span
[0]/window_span
[0]), abs(box_span
[1]/window_span
[1]));
197 // focus_point is -1 times the real position for some reason...
198 // center the window so the old contents fill the drawn box
199 newpos
= -((window_middle
- box_middle
)/zoom
+ window_middle
);
203 if (box_span
[0] == 0 || box_span
[1] == 0) zoom
= 1;
204 else zoom
= min(abs(window_span
[0]/box_span
[0]), abs(window_span
[1]/box_span
[1]));
206 // center the window at the center of the box
207 newpos
= -(-get_work_area()->get_focus_point() + (box_middle
- window_middle
));
210 get_work_area()->set_focus_point(newpos
);
211 get_work_area()->set_zoom(get_work_area()->get_zoom()*zoom
);
213 return Smach::RESULT_ACCEPT
;
217 if(x
.key
==EVENT_WORKAREA_MOUSE_BUTTON_UP
)
219 const EventMouse
& event(*reinterpret_cast<const EventMouse
*>(&x
));
221 if(event
.button
==BUTTON_LEFT
)
225 //make the event pos be in the same space...
226 // The weird ass inverted center normalized space...
228 const Point realcenter
= (get_work_area()->get_window_tl() + get_work_area()->get_window_br())/2;
229 evpos
= -(event
.pos
- realcenter
) + get_work_area()->get_focus_point();
233 focus point must zoom about the point evpos...
235 trans about an origin not 0:
239 Vector v
= get_work_area()->get_focus_point() - evpos
;
241 if(event
.modifier
& Gdk::CONTROL_MASK
) //zoom out...
244 //get_work_area()->zoom_out();
245 get_work_area()->set_focus_point(evpos
+ v
);
246 get_work_area()->set_zoom(get_work_area()->get_zoom()/ZOOMFACTOR
);
250 //get_work_area()->zoom_in();
251 get_work_area()->set_focus_point(evpos
+ v
);
252 get_work_area()->set_zoom(get_work_area()->get_zoom()*ZOOMFACTOR
);
255 return Smach::RESULT_ACCEPT
;
259 return Smach::RESULT_OK
;