X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=synfig-studio%2Ftrunk%2Fsrc%2Fgtkmm%2Fstate_scale.cpp;fp=synfig-studio%2Ftrunk%2Fsrc%2Fgtkmm%2Fstate_scale.cpp;h=94525b34cd22d95a89599af8409a1369c6f2fd3a;hb=3a3c4bca3a17137bec5d7960560934b91ef4146e;hp=0000000000000000000000000000000000000000;hpb=41257b650db1defb40ac20072ffeef70d5985f5e;p=synfig.git diff --git a/synfig-studio/trunk/src/gtkmm/state_scale.cpp b/synfig-studio/trunk/src/gtkmm/state_scale.cpp new file mode 100644 index 0000000..94525b3 --- /dev/null +++ b/synfig-studio/trunk/src/gtkmm/state_scale.cpp @@ -0,0 +1,373 @@ +/* === S I N F G =========================================================== */ +/*! \file state_scale.cpp +** \brief Template File +** +** $Id: state_scale.cpp,v 1.1.1.1 2005/01/07 03:34:37 darco Exp $ +** +** \legal +** Copyright (c) 2002 Robert B. Quattlebaum Jr. +** +** This software and associated documentation +** are CONFIDENTIAL and PROPRIETARY property of +** the above-mentioned copyright holder. +** +** You may not copy, print, publish, or in any +** other way distribute this software without +** a prior written agreement with +** the copyright holder. +** \endlegal +*/ +/* ========================================================================= */ + +/* === H E A D E R S ======================================================= */ + +#ifdef USING_PCH +# include "pch.h" +#else +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#include +#include + +#include "state_scale.h" +#include "canvasview.h" +#include "workarea.h" +#include "app.h" + +#include +#include "event_mouse.h" +#include "event_layerclick.h" +#include "toolbox.h" +#include "dialog_tooloptions.h" +#include +#include "duck.h" +#include + +#endif + +/* === U S I N G =========================================================== */ + +using namespace std; +using namespace etl; +using namespace sinfg; +using namespace studio; + +/* === M A C R O S ========================================================= */ + +/* === G L O B A L S ======================================================= */ + +StateScale studio::state_scale; + +/* === C L A S S E S & S T R U C T S ======================================= */ + +class DuckDrag_Scale : public DuckDrag_Base +{ + + sinfg::Vector last_scale; + sinfg::Vector drag_offset; + sinfg::Vector center; + sinfg::Vector snap; + + std::vector positions; + + bool move_only; + + bool bad_drag; +public: + bool lock_aspect; + DuckDrag_Scale(); + void begin_duck_drag(Duckmatic* duckmatic, const sinfg::Vector& begin); + bool end_duck_drag(Duckmatic* duckmatic); + void duck_drag(Duckmatic* duckmatic, const sinfg::Vector& vector); +}; + + +class studio::StateScale_Context : public sigc::trackable +{ + etl::handle canvas_view_; + + sinfgapp::Settings& settings; + + etl::handle duck_dragger_; + + Gtk::Table options_table; + + + Gtk::CheckButton checkbutton_aspect_lock; + +public: + + bool get_aspect_lock_flag()const { return checkbutton_aspect_lock.get_active(); } + void set_aspect_lock_flag(bool x) { return checkbutton_aspect_lock.set_active(x); refresh_aspect_lock_flag(); } + + void refresh_aspect_lock_flag() { if(duck_dragger_)duck_dragger_->lock_aspect=get_aspect_lock_flag(); } + + Smach::event_result event_refresh_tool_options(const Smach::event& x); + + void refresh_tool_options(); + + StateScale_Context(CanvasView* canvas_view); + + ~StateScale_Context(); + + const etl::handle& get_canvas_view()const{return canvas_view_;} + etl::handle get_canvas_interface()const{return canvas_view_->canvas_interface();} + sinfg::Canvas::Handle get_canvas()const{return canvas_view_->get_canvas();} + WorkArea * get_work_area()const{return canvas_view_->get_work_area();} + + void load_settings(); + void save_settings(); +}; // END of class StateScale_Context + +/* === M E T H O D S ======================================================= */ + +StateScale::StateScale(): + Smach::state("scale") +{ + insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateScale_Context::event_refresh_tool_options)); +} + +StateScale::~StateScale() +{ +} + +void +StateScale_Context::load_settings() +{ + String value; + + if(settings.get_value("scale.lock_aspect",value) && value=="0") + set_aspect_lock_flag(false); + else + set_aspect_lock_flag(true); +} + +void +StateScale_Context::save_settings() +{ + settings.set_value("scale.lock_aspect",get_aspect_lock_flag()?"1":"0"); +} + +StateScale_Context::StateScale_Context(CanvasView* canvas_view): + canvas_view_(canvas_view), + settings(sinfgapp::Main::get_selected_input_device()->settings()), + duck_dragger_(new DuckDrag_Scale()), + checkbutton_aspect_lock(_("Lock Aspect Ratio")) +{ + // Set up the tool options dialog + //options_table.attach(*manage(new Gtk::Label(_("Scale Tool"))), 0, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(checkbutton_aspect_lock, 0, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + + checkbutton_aspect_lock.signal_toggled().connect(sigc::mem_fun(*this,&StateScale_Context::refresh_aspect_lock_flag)); + + options_table.show_all(); + refresh_tool_options(); + App::dialog_tool_options->present(); + + get_work_area()->allow_layer_clicks=true; + get_work_area()->set_duck_dragger(duck_dragger_); + +// get_canvas_view()->work_area->set_cursor(Gdk::CROSSHAIR); + get_canvas_view()->work_area->reset_cursor(); + + App::toolbox->refresh(); + + set_aspect_lock_flag(true); + load_settings(); +} + +void +StateScale_Context::refresh_tool_options() +{ + App::dialog_tool_options->clear(); + App::dialog_tool_options->set_widget(options_table); + App::dialog_tool_options->set_local_name(_("Scale Tool")); + App::dialog_tool_options->set_name("scale"); +} + +Smach::event_result +StateScale_Context::event_refresh_tool_options(const Smach::event& x) +{ + refresh_tool_options(); + return Smach::RESULT_ACCEPT; +} + +StateScale_Context::~StateScale_Context() +{ + save_settings(); + + get_work_area()->clear_duck_dragger(); + get_canvas_view()->work_area->reset_cursor(); + + App::dialog_tool_options->clear(); + + App::toolbox->refresh(); +} + + + + +DuckDrag_Scale::DuckDrag_Scale(): + lock_aspect(true) +{ +} + +#ifndef EPSILON +#define EPSILON 0.0000001 +#endif + +void +DuckDrag_Scale::begin_duck_drag(Duckmatic* duckmatic, const sinfg::Vector& offset) +{ + last_scale=Vector(1,1); + const DuckList selected_ducks(duckmatic->get_selected_ducks()); + DuckList::const_iterator iter; + + //if(duckmatic->get_selected_ducks().size()<2) + //{ + // bad_drag=true; +// return; +// } + bad_drag=false; + + drag_offset=duckmatic->find_duck(offset)->get_trans_point(); + + //snap=drag_offset-duckmatic->snap_point_to_grid(drag_offset); + //snap=offset-drag_offset; + snap=Vector(0,0); + + // Calculate center + Point vmin(100000000,100000000); + Point vmax(-100000000,-100000000); + //std::set >::iterator iter; + positions.clear(); + int i; + for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++) + { + Point p((*iter)->get_trans_point()); + vmin[0]=min(vmin[0],p[0]); + vmin[1]=min(vmin[1],p[1]); + vmax[0]=max(vmax[0],p[0]); + vmax[1]=max(vmax[1],p[1]); + positions.push_back(p); + } + if((vmin-vmax).mag()<=EPSILON) + move_only=true; + else + move_only=false; + + center=(vmin+vmax)*0.5; +} + + +void +DuckDrag_Scale::duck_drag(Duckmatic* duckmatic, const sinfg::Vector& vector) +{ + const DuckList selected_ducks(duckmatic->get_selected_ducks()); + DuckList::const_iterator iter; + + if(bad_drag) + return; + + //std::set >::iterator iter; + sinfg::Vector vect(duckmatic->snap_point_to_grid(vector)-center); + last_scale=vect; + + if(move_only) + { + int i; + for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++) + { + if(((*iter)->get_type()!=Duck::TYPE_VERTEX&&(*iter)->get_type()!=Duck::TYPE_POSITION))continue; + + Vector p(positions[i]); + + p[0]+=vect[0]; + p[1]+=vect[1]; + (*iter)->set_trans_point(p); + } + for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++) + { + if(!((*iter)->get_type()!=Duck::TYPE_VERTEX&&(*iter)->get_type()!=Duck::TYPE_POSITION))continue; + + Vector p(positions[i]); + + p[0]+=vect[0]; + p[1]+=vect[1]; + (*iter)->set_trans_point(p); + } + return; + } + + if(!lock_aspect) + { + if(abs(drag_offset[0]-center[0])>EPSILON) + vect[0]/=drag_offset[0]-center[0]; + else + vect[0]=1; + if(abs(drag_offset[1]-center[1])>EPSILON) + vect[1]/=drag_offset[1]-center[1]; + else + vect[1]=1; + } + else + { + //vect[0]=vect[1]=vect.mag()*0.707106781; + Real amount(vect.mag()/(drag_offset-center).mag()); + vect[0]=vect[1]=amount; + } + + if(vect[0]-EPSILON) + vect[0]=1; + if(vect[1]-EPSILON) + vect[1]=1; + + int i; + for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++) + { + if(((*iter)->get_type()!=Duck::TYPE_VERTEX&&(*iter)->get_type()!=Duck::TYPE_POSITION))continue; + + Vector p(positions[i]-center); + + p[0]*=vect[0]; + p[1]*=vect[1]; + p+=center; + (*iter)->set_trans_point(p); + } + for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++) + { + if(!((*iter)->get_type()!=Duck::TYPE_VERTEX&&(*iter)->get_type()!=Duck::TYPE_POSITION))continue; + + Vector p(positions[i]-center); + + p[0]*=vect[0]; + p[1]*=vect[1]; + p+=center; + (*iter)->set_trans_point(p); + } + + last_scale=vect; + //snap=Vector(0,0); +} + +bool +DuckDrag_Scale::end_duck_drag(Duckmatic* duckmatic) +{ + if(bad_drag)return false; + + if((last_scale-Vector(1,1)).mag()>0.0001) + { + duckmatic->signal_edited_selected_ducks(); + return true; + } + else + { + duckmatic->signal_user_click_selected_ducks(0); + return false; + } +}