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