Show the size of circles as they are drawn using the draw tool.
[synfig.git] / synfig-studio / trunk / src / gtkmm / duck.cpp
1 /* === S Y N F I G ========================================================= */
2 /*!     \file duck.cpp
3 **      \brief Template File
4 **
5 **      $Id$
6 **
7 **      \legal
8 **      Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 **
10 **      This package is free software; you can redistribute it and/or
11 **      modify it under the terms of the GNU General Public License as
12 **      published by the Free Software Foundation; either version 2 of
13 **      the License, or (at your option) any later version.
14 **
15 **      This package is distributed in the hope that it will be useful,
16 **      but WITHOUT ANY WARRANTY; without even the implied warranty of
17 **      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 **      General Public License for more details.
19 **      \endlegal
20 */
21 /* ========================================================================= */
22
23 /* === H E A D E R S ======================================================= */
24
25 #ifdef USING_PCH
26 #       include "pch.h"
27 #else
28 #ifdef HAVE_CONFIG_H
29 #       include <config.h>
30 #endif
31
32 #include "duck.h"
33 #include <ETL/misc>
34
35 #include "general.h"
36
37 #endif
38
39 /* === U S I N G =========================================================== */
40
41 using namespace std;
42 using namespace etl;
43 using namespace synfig;
44 using namespace studio;
45
46 /* === M A C R O S ========================================================= */
47
48 /* === G L O B A L S ======================================================= */
49
50 int studio::Duck::duck_count(0);
51
52 struct _DuckCounter
53 {
54         static int counter;
55         ~_DuckCounter()
56         {
57                 if(counter)
58                         synfig::error("%d ducks not yet deleted!",counter);
59         }
60 } _duck_counter;
61
62 int _DuckCounter::counter(0);
63
64
65 /* === P R O C E D U R E S ================================================= */
66
67 /* === M E T H O D S ======================================================= */
68
69 Duck::Duck():
70         rotations(synfig::Angle::deg(0)),
71         origin(0,0),
72         scalar(1),
73         editable(false),
74         radius_(false),
75         tangent_(false),
76         hover_(false)
77 { duck_count++; _DuckCounter::counter++; }
78
79 Duck::Duck(const synfig::Point &point):
80         type_(TYPE_NONE),
81         point(point),
82         rotations(synfig::Angle::deg(0)),
83         origin(0,0),
84         scalar(1),
85         guid_(0),
86         editable(false),
87         radius_(false),
88         tangent_(false)
89 { duck_count++; _DuckCounter::counter++;}
90
91 Duck::Duck(const synfig::Point &point,const synfig::Point &origin):
92         point(point),
93         rotations(synfig::Angle::deg(0)),
94         origin(origin),
95         scalar(1),
96         guid_(0),
97         editable(false),
98         radius_(true),
99         tangent_(false)
100 { duck_count++; _DuckCounter::counter++;}
101
102 Duck::~Duck() { duck_count--; _DuckCounter::counter--;}
103
104 synfig::GUID
105 Duck::get_data_guid()const
106 {
107         if(value_desc_.is_value_node())
108                 return value_desc_.get_value_node()->get_guid();
109         return GUID::hasher(get_name());
110 }
111
112 void
113 Duck::set_name(const synfig::String &x)
114 {
115         name=x;
116         if(guid_==GUID::zero())
117         {
118                 guid_=GUID::hasher(name);
119         }
120 }
121
122
123 bool
124 Duck::operator==(const Duck &rhs)const
125 {
126         if(this==&rhs)
127                 return true;
128         return
129                 name==rhs.name &&
130                 scalar==rhs.scalar &&
131                 type_==rhs.type_ &&
132                 transform_stack_.size()==rhs.transform_stack_.size();
133                 //true;
134                 //(origin_duck?*origin_duck==*rhs.origin_duck:origin==rhs.origin) &&
135                 //(shared_point?*shared_point==*rhs.shared_point:point==rhs.point) ;
136 }
137
138 synfig::Point
139 Duck::get_trans_point()const
140 {
141         return transform_stack_.perform(get_sub_trans_point());
142 }
143
144 void
145 Duck::set_trans_point(const synfig::Point &x)
146 {
147         set_sub_trans_point(transform_stack_.unperform(x));
148 }
149
150 //! Sets the origin point.
151 void
152 Duck::set_origin(const synfig::Point &x)
153 {
154         origin=x; origin_duck=0;
155 }
156
157 //! Sets the origin point as another duck
158 void
159 Duck::set_origin(const etl::handle<Duck> &x)
160 {
161         origin_duck=x;
162 }
163
164 //! Retrieves the origin location
165 synfig::Point
166 Duck::get_origin()const
167 {
168         return origin_duck?origin_duck->get_point():origin;
169 }
170
171 //! Retrieves the origin duck
172 const etl::handle<Duck> &
173 Duck::get_origin_duck() const
174 {
175         return origin_duck;
176 }
177
178 //! Retrieves the origin location
179 synfig::Point
180 Duck::get_trans_origin()const
181 {
182         return transform_stack_.perform(get_sub_trans_origin());
183 }
184
185 synfig::Point
186 Duck::get_sub_trans_point()const
187 {
188         return get_point()*get_scalar()+get_sub_trans_origin();
189 }
190
191 void
192 Duck::set_sub_trans_point(const synfig::Point &x)
193 {
194         if (get_type() == Duck::TYPE_TANGENT ||
195                 get_type() == Duck::TYPE_ANGLE)
196         {
197                 Angle old_angle = get_point().angle();
198                 set_point((x-get_sub_trans_origin())/get_scalar());
199                 Angle change = get_point().angle() - old_angle;
200                 while (change < Angle::deg(-180)) change += Angle::deg(360);
201                 while (change > Angle::deg(180)) change -= Angle::deg(360);
202                 int old_quarters = round_to_int(Angle::deg(rotations).get()/90);
203                 rotations += change;
204                 int new_quarters = round_to_int(Angle::deg(rotations).get()/90);
205                 if (old_quarters != new_quarters)
206                         synfig::info("rotation: %.2f turns", new_quarters/4.0);
207         }
208         else
209                 set_point((x-get_sub_trans_origin())/get_scalar());
210 }
211
212 synfig::Point
213 Duck::get_sub_trans_origin()const
214 {
215         return origin_duck?origin_duck->get_sub_trans_point():origin;
216 }