1 /***********************************************************************
2     created:    Tue May 31 2005
3     author:     Paul D Turner <paul@cegui.org.uk>
4 *************************************************************************/
5 /***************************************************************************
6  *   Copyright (C) 2004 - 2006 Paul D Turner & The CEGUI Development Team
7  *
8  *   Permission is hereby granted, free of charge, to any person obtaining
9  *   a copy of this software and associated documentation files (the
10  *   "Software"), to deal in the Software without restriction, including
11  *   without limitation the rights to use, copy, modify, merge, publish,
12  *   distribute, sublicense, and/or sell copies of the Software, and to
13  *   permit persons to whom the Software is furnished to do so, subject to
14  *   the following conditions:
15  *
16  *   The above copyright notice and this permission notice shall be
17  *   included in all copies or substantial portions of the Software.
18  *
19  *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20  *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21  *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22  *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23  *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24  *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25  *   OTHER DEALINGS IN THE SOFTWARE.
26  ***************************************************************************/
27 #ifndef _CEGUIUDim_h_
28 #define _CEGUIUDim_h_
29 
30 #include "CEGUI/Base.h"
31 #include <ostream>
32 
33 #if defined(_MSC_VER)
34 #	pragma warning(push)
35 #	pragma warning(disable : 4251)
36 #endif
37 
38 // some macros to aid in the creation of UDims
39 #define cegui_absdim(x)     CEGUI::UDim(0,(x))
40 #define cegui_reldim(x)     CEGUI::UDim((x),0)
41 
42 
43 // Start of CEGUI namespace section
44 namespace CEGUI
45 {
46 /*!
47 \brief
48     Dimension that has both a relative 'scale' portion and and absolute 'offset' portion
49 
50 \par
51     The meaning of this class depends on where you use it, it is just a
52     float tuple. We will only describe the usual usecase for CEGUI::Window
53     position and size. CEGUI::Window gets that behavior from CEGUI::Element.
54 
55     UDims are used for both positioning and sizing (hence the name dimension).
56 
57     The scale component describes the amount of dimension we take from the
58     parent CEGUI::Element. The offset component describes the amount of pixels
59     and is not dependent on any element in the tree.
60 
61 \par Example: 50% of parent's width
62     \code{.cpp}
63     UDim(0.5f, 0);
64     \endcode
65 
66 \par Example: 100px
67     \code{.cpp}
68     UDim(0, 100.0f);
69     \endcode
70 
71 \par Negative components
72     You can use negative components in UDim and they are in fact very useful!
73     \code{.cpp}
74     UDim(1.0f, -100.0f); // 100px to the left from the right edge of parent widget
75     \endcode
76 
77 \par Floating point
78     Both components are floats, that means that expressing fractions of pixels
79     is allowed even though such construct goes against the definition of pixel.
80     \code{.cpp}
81     UDim(0.0f, 1.123456f); // perfectly valid UDim
82     \endcode
83 
84     Keep in mind that if you use such dimensions they will likely get pixel
85     aligned before rendering. You can disable such behavior via
86     Element::setPixelAligned.
87 
88 \see CEGUI::UVector2
89 \see CEGUI::USize
90 \see CEGUI::URect
91 */
92 class CEGUIEXPORT UDim :
93     public AllocatedObject<UDim>
94 {
95 public:
UDim()96     inline UDim()
97     {}
98 
UDim(float scale,float offset)99     inline UDim(float scale, float offset):
100         d_scale(scale),
101         d_offset(offset)
102     {}
103 
UDim(const UDim & v)104     inline UDim(const UDim& v):
105         d_scale(v.d_scale),
106         d_offset(v.d_offset)
107     {}
108 
109     inline UDim operator+(const UDim& other) const
110     {
111         return UDim(d_scale + other.d_scale, d_offset + other.d_offset);
112     }
113 
114     inline UDim operator-(const UDim& other) const
115     {
116         return UDim(d_scale - other.d_scale, d_offset - other.d_offset);
117     }
118 
119     inline UDim operator*(const float val) const
120     {
121         return UDim(d_scale * val, d_offset * val);
122     }
123 
124     inline friend UDim operator*(const float val, const UDim& u)
125     {
126         return UDim(val * u.d_scale, val * u.d_offset);
127     }
128 
129     inline UDim operator*(const UDim& other) const
130     {
131         return UDim(d_scale * other.d_scale, d_offset * other.d_offset);
132     }
133 
134     inline UDim operator/(const UDim& other) const
135     {
136         // division by zero sets component to zero.  Not technically correct
137         // but probably better than exceptions and/or NaN values.
138         return UDim(other.d_scale == 0.0f ? 0.0f : d_scale / other.d_scale,
139                     other.d_offset == 0.0f ? 0.0f : d_offset / other.d_offset);
140     }
141 
142     inline const UDim& operator+=(const UDim& other)
143     {
144         d_scale += other.d_scale;
145         d_offset += other.d_offset;
146         return *this;
147     }
148 
149     inline const UDim& operator-=(const UDim& other)
150     {
151         d_scale -= other.d_scale;
152         d_offset -= other.d_offset;
153         return *this;
154     }
155 
156     inline const UDim& operator*=(const UDim& other)
157     {
158         d_scale *= other.d_scale;
159         d_offset *= other.d_offset;
160         return *this;
161     }
162 
163     inline const UDim& operator/=(const UDim& other)
164     {
165         // division by zero sets component to zero.  Not technically correct
166         // but probably better than exceptions and/or NaN values.
167         d_scale = (other.d_scale == 0.0f ? 0.0f : d_scale / other.d_scale);
168         d_offset = (other.d_offset == 0.0f ? 0.0f : d_offset / other.d_offset);
169         return *this;
170     }
171 
172     inline bool operator==(const UDim& other) const
173     {
174         return d_scale == other.d_scale && d_offset == other.d_offset;
175     }
176 
177     inline bool operator!=(const UDim& other) const
178     {
179         return !operator==(other);
180     }
181 
182     /*!
183     \brief allows writing the udim to std ostream
184     */
185     inline friend std::ostream& operator << (std::ostream& s, const UDim& v)
186     {
187         s << "CEGUI::UDim(" << v.d_scale << ", " << v.d_offset << ")";
188         return s;
189     }
190 
191     /*!
192     \brief finger saving convenience method returning UDim(0, 0)
193     */
zero()194     inline static UDim zero()
195     {
196         return UDim(0.0f, 0.0f);
197     }
198 
199     /*!
200     \brief finger saving convenience method returning UDim(1, 0)
201 
202     \note
203         Allows quite neat 0.5 * UDim::relative() self documenting syntax
204     */
relative()205     inline static UDim relative()
206     {
207         return UDim(1.0f, 0.0f);
208     }
209 
210     /*!
211     \brief finger saving convenience method returning UDim(0.01, 0)
212 
213     \note
214         Allows quite neat 50 * UDim::percent() self documenting syntax
215     */
percent()216     inline static UDim percent()
217     {
218         return UDim(0.01f, 0.0f);
219     }
220 
221     /*!
222     \brief finger saving convenience method returning UDim(0, 1)
223 
224     \note
225         Allows quite neat 100 * UDim::px() self documenting syntax,
226         you can combine it with UDim::relative() as well (using operator+)
227     */
px()228     inline static UDim px()
229     {
230         return UDim(0.0f, 1.0f);
231     }
232 
233     float d_scale;
234     float d_offset;
235 };
236 
237 /*!
238 \brief
239     Class encapsulating the 'Unified Box' - this is usually used for margin
240 
241 \par
242     top, left, right and bottom represent offsets on each edge
243 
244 \note
245     Name taken from W3 'box model'
246 */
247 class CEGUIEXPORT UBox :
248     public AllocatedObject<UBox>
249 {
250 public:
UBox()251     UBox():
252             d_top(),
253             d_left(),
254             d_bottom(),
255             d_right()
256     {}
257 
UBox(const UDim & margin)258     UBox(const UDim& margin):
259             d_top(margin),
260             d_left(margin),
261             d_bottom(margin),
262             d_right(margin)
263     {}
264 
UBox(const UDim & top,const UDim & left,const UDim & bottom,const UDim & right)265     UBox(const UDim& top, const UDim& left, const UDim& bottom, const UDim& right):
266             d_top(top),
267             d_left(left),
268             d_bottom(bottom),
269             d_right(right)
270     {}
271 
UBox(const UBox & b)272     UBox(const UBox& b):
273             d_top(b.d_top),
274             d_left(b.d_left),
275             d_bottom(b.d_bottom),
276             d_right(b.d_right)
277     {}
278 
279     /*************************************************************************
280         Operators
281     *************************************************************************/
282     bool operator==(const UBox& rhs) const
283     {
284         return ((d_top == rhs.d_top) &&
285                 (d_left == rhs.d_left) &&
286                 (d_bottom == rhs.d_bottom) &&
287                 (d_right == rhs.d_right));
288     }
289 
290     bool operator!=(const UBox& rhs) const
291     {
292         return !operator==(rhs);
293     }
294 
295     UBox& operator=(const UBox& rhs)
296     {
297         d_top = rhs.d_top;
298         d_left = rhs.d_left;
299         d_bottom = rhs.d_bottom;
300         d_right = rhs.d_right;
301 
302         return *this;
303     }
304 
305     UBox operator*(const float val) const
306     {
307         return UBox(
308                    d_top * val, d_left * val,
309                    d_bottom * val, d_right * val);
310     }
311 
312     UBox operator*(const UDim& dim) const
313     {
314         return UBox(
315                    d_top * dim, d_left * dim,
316                    d_bottom * dim, d_right * dim);
317     }
318 
319     UBox operator+(const UBox& b) const
320     {
321         return UBox(
322                    d_top + b.d_top, d_left + b.d_left,
323                    d_bottom + b.d_bottom, d_right + b.d_right);
324     }
325 
326     /*************************************************************************
327         Data Fields
328     *************************************************************************/
329     UDim d_top;
330     UDim d_left;
331     UDim d_bottom;
332     UDim d_right;
333 };
334 
335 /*!
336 * \brief allows you to get UDim(0, 0) if you pass UDim or just 0 if you pass anything else
337 *
338 * \todo Is this the right place where to put this?
339 */
340 template<typename T>
TypeSensitiveZero()341 inline T TypeSensitiveZero()
342 {
343     return T(0);
344 }
345 
346 template<>
347 inline UDim TypeSensitiveZero<UDim>()
348 {
349     return UDim(0, 0);
350 }
351 
352 /*!
353 * \brief allows you to get UDim::relative() if you pass UDim or just 1 if you pass anything else
354 *
355 * \todo Is this the right place where to put this?
356 */
357 template<typename T>
TypeSensitiveOne()358 inline T TypeSensitiveOne()
359 {
360     return T(1);
361 }
362 
363 template<>
364 inline UDim TypeSensitiveOne<UDim>()
365 {
366     return UDim::relative();
367 }
368 
369 } // End of  CEGUI namespace section
370 
371 
372 #if defined(_MSC_VER)
373 #	pragma warning(pop)
374 #endif
375 
376 #endif  // end of guard _CEGUIUDim_h_
377 
378