Dillo v3.1.1-98-g318d1f14
Loading...
Searching...
No Matches
oofposabslikemgr.cc
Go to the documentation of this file.
1/*
2 * Dillo Widget
3 *
4 * Copyright 2015 Sebastian Geerken <sgeerken@dillo.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include "oofposabslikemgr.hh"
21
22using namespace dw::core;
23using namespace lout::misc;
24
25namespace dw {
26
27namespace oof {
28
30 OOFPositionedMgr (container)
31{
32 DBG_OBJ_CREATE ("dw::oof::OOFPosAbsLikeMgr");
33}
34
39
41{
42 size->width = size->ascent = size->descent = 0;
43}
44
46{
47 DBG_OBJ_ENTER0 ("resize.oofm", 0, "sizeAllocateChildren");
48
49 int refWidth = container->getAvailWidth (true) - containerBoxDiffWidth ();
50 int refHeight = container->getAvailHeight (true) - containerBoxDiffHeight ();
51
52 for (int i = 0; i < children->size(); i++) {
53 Child *child = children->get (i);
54
55 int x, y, width, ascent, descent;
56 calcPosAndSizeChildOfChild (child, refWidth, refHeight, &x, &y, &width,
57 &ascent, &descent);
58
59 Allocation childAllocation;
60 childAllocation.x = containerAllocation.x + x + containerBoxOffsetX ();
61 childAllocation.y = containerAllocation.y + y + containerBoxOffsetY ();
62 childAllocation.width = width;
63 childAllocation.ascent = ascent;
64 childAllocation.descent = descent;
65
66 child->widget->sizeAllocate (&childAllocation);
67 }
68
70}
71
72void OOFPosAbsLikeMgr::getSize (Requisition *containerReq, int *oofWidth,
73 int *oofHeight)
74{
75 DBG_OBJ_ENTER ("resize.oofm", 0, "getSize", "%d * (%d + %d)",
76 containerReq->width, containerReq->ascent,
77 containerReq->descent);
78
79 *oofWidth = *oofHeight = 0;
80
81 int refWidth = container->getAvailWidth (true);
82 int refHeight = container->getAvailHeight (true);
83
84 for (int i = 0; i < children->size(); i++) {
85 Child *child = children->get(i);
86
87 // Children whose position cannot be determined will be
88 // considered later in sizeAllocateEnd.
89 if (posXDefined (child) && posYDefined (child)) {
90 int x, y, width, ascent, descent;
91 calcPosAndSizeChildOfChild (child, refWidth, refHeight, &x, &y, &width,
92 &ascent, &descent);
93 *oofWidth = max (*oofWidth, x + width) + containerBoxDiffWidth ();
94 *oofHeight =
95 max (*oofHeight, y + ascent + descent) + containerBoxDiffHeight ();
96
97 child->consideredForSize = true;
98 } else
99 child->consideredForSize = false;
100 }
101
102 DBG_OBJ_LEAVE_VAL ("%d * %d", *oofWidth, *oofHeight);
103}
104
105void OOFPosAbsLikeMgr::getExtremes (Extremes *containerExtr, int *oofMinWidth,
106 int *oofMaxWidth)
107{
108 DBG_OBJ_ENTER ("resize.oofm", 0, "getExtremes", "(%d / %d), ...",
109 containerExtr->minWidth, containerExtr->maxWidth);
110
111 *oofMinWidth = *oofMaxWidth = 0;
112
113 for (int i = 0; i < children->size(); i++) {
114 Child *child = children->get(i);
115
116 // Children whose position cannot be determined will be
117 // considered later in sizeAllocateEnd.
118 if (posXDefined (child)) {
119 int x, width;
120 Extremes childExtr;
121 child->widget->getExtremes (&childExtr);
122
123 // Here, we put the extremes of the container in relation to
124 // the extremes of the child, as sizes are put in relation
125 // for calculating the size. In one case, the allocation is
126 // used: when neither "left" nor "right" is set, and so the
127 // position told by the generator is used.
128 //
129 // If you look at the Textblock widget, you'll find that this
130 // is always boxOffsetX(), and the horizontal position of a
131 // textblock within its parent is also constant; so this is
132 // not a problem.
133 //
134 // (TODO What about a table cell within a table?)
135
136 calcHPosAndSizeChildOfChild (child, containerExtr->minWidth,
137 childExtr.minWidth, &x, &width);
138 *oofMinWidth = max (*oofMinWidth, x + width);
139
140 calcHPosAndSizeChildOfChild (child, containerExtr->maxWidth,
141 childExtr.maxWidth, &x, &width);
142 *oofMaxWidth = max (*oofMaxWidth, x + width);
143
144 child->consideredForExtremes = true;
145 } else
146 child->consideredForExtremes = false;
147 }
148
149 *oofMinWidth += containerBoxDiffWidth ();
150 *oofMaxWidth += containerBoxDiffWidth ();
151
152 DBG_OBJ_MSGF ("resize.oofm", 0, "=> %d / %d", *oofMinWidth, *oofMaxWidth);
153 DBG_OBJ_LEAVE ();
154}
155
157{
158 DBG_OBJ_ENTER ("resize.oofm", 0,
159 "OOFPositionedMgr/getAvailWidthOfChild", "%p, %s",
160 child, forceValue ? "true" : "false");
161
162 int width;
163
164 if (child->getStyle()->width == style::LENGTH_AUTO &&
165 child->getStyle()->minWidth == style::LENGTH_AUTO &&
166 child->getStyle()->maxWidth == style::LENGTH_AUTO) {
167 // TODO This should (perhaps?) only used when 'width' is undefined.
168 // TODO Is "boxDiffWidth()" correct here?
169 DBG_OBJ_MSG ("resize.oofm", 1, "no specification");
170 if (forceValue) {
171 int availWidth = container->getAvailWidth (true), left, right;
172
173 // Regard undefined values as 0:
174 if (!getPosLeft (child, availWidth, &left)) left = 0;
175 if (!getPosRight (child, availWidth, &right)) right = 0;
176
177 width = max (availWidth - containerBoxDiffWidth () - left - right, 0);
178 } else
179 width = -1;
180 } else {
181 if (forceValue) {
182 int availWidth = container->getAvailWidth (true);
183 child->calcFinalWidth (child->getStyle(),
184 availWidth - containerBoxDiffWidth (), NULL,
185 0, true, &width);
186 } else
187 width = -1;
188 }
189
190 if (width != -1)
191 width = max (width, child->getMinWidth (NULL, forceValue));
192
193 DBG_OBJ_MSGF ("resize.oofm", 1, "=> %d", width);
194 DBG_OBJ_LEAVE ();
195
196 return width;
197}
198
200{
201 DBG_OBJ_ENTER ("resize.oofm", 0,
202 "OOFPositionedMgr/getAvailHeightOfChild", "%p, %s",
203 child, forceValue ? "true" : "false");
204
205 int height;
206
207 if (child->getStyle()->height == style::LENGTH_AUTO &&
210 // TODO This should (perhaps?) only used when 'height' is undefined.
211 // TODO Is "boxDiffHeight()" correct here?
212 DBG_OBJ_MSG ("resize.oofm", 1, "no specification");
213 if (forceValue) {
214 int availHeight = container->getAvailHeight (true), top, bottom;
215
216 // Regard undefined values as 0:
217 if (!getPosTop (child, availHeight, &top)) top = 0;
218 if (!getPosBottom (child, availHeight, &bottom)) bottom = 0;
219
220 height =
221 max (availHeight - containerBoxDiffHeight () - top - bottom, 0);
222 } else
223 height = -1;
224 } else {
225 if (forceValue) {
226 int availHeight = container->getAvailHeight (true);
227 height = child->calcHeight (child->getStyle()->height, true,
228 availHeight - containerBoxDiffHeight (),
229 NULL, true);
230 } else
231 height = -1;
232 }
233
234 DBG_OBJ_MSGF ("resize.oofm", 1, "=> %d", height);
235 DBG_OBJ_LEAVE ();
236
237 return height;
238}
239
241{
242 DBG_OBJ_ENTER ("resize.oofm", 0, "posXAbsolute", "[%p]", child->widget);
243 bool b =
244 (style::isAbsLength (child->widget->getStyle()->left) ||
245 style::isPerLength (child->widget->getStyle()->left)) &&
246 (style::isAbsLength (child->widget->getStyle()->right) ||
248 DBG_OBJ_LEAVE_VAL ("%s", boolToStr (b));
249 return b;
250}
251
253{
254 DBG_OBJ_ENTER ("resize.oofm", 0, "posYAbsolute", "[%p]", child->widget);
255 bool b =
256 (style::isAbsLength (child->widget->getStyle()->top) ||
257 style::isPerLength (child->widget->getStyle()->top)) &&
260 DBG_OBJ_LEAVE_VAL ("%s", boolToStr (b));
261 return b;
262}
263
265 int refHeight, int *xPtr,
266 int *yPtr, int *widthPtr,
267 int *ascentPtr,
268 int *descentPtr)
269{
270 // *xPtr and *yPtr refer to reference area; caller must adjust them.
271
272 DBG_OBJ_ENTER ("resize.oofm", 0, "calcPosAndSizeChildOfChild",
273 "[%p], %d, %d, ...", child->widget, refWidth, refHeight);
274
275 // TODO (i) Consider {min|max}-{width|heigt}. (ii) Height is always
276 // apportioned to descent (ascent is preserved), which makes sense
277 // when the children are textblocks. (iii) Consider minimal width
278 // (getMinWidth)?
279
280 Requisition childRequisition;
281 child->widget->sizeRequest (&childRequisition);
282
283 calcHPosAndSizeChildOfChild (child, refWidth, childRequisition.width,
284 xPtr, widthPtr);
285 calcVPosAndSizeChildOfChild (child, refHeight, childRequisition.ascent,
286 childRequisition.descent, yPtr, ascentPtr,
287 descentPtr);
288
289 DBG_OBJ_LEAVE ();
290}
291
293 int origChildWidth,
294 int *xPtr, int *widthPtr)
295{
296 assert (refWidth != -1 || (xPtr == NULL && widthPtr == NULL));
297
298 int width;
299 bool widthDefined;
300 if (style::isAbsLength (child->widget->getStyle()->width)) {
301 DBG_OBJ_MSGF ("resize.oofm", 1, "absolute width: %dpx",
303 width = style::absLengthVal (child->widget->getStyle()->width)
304 + child->widget->boxDiffWidth ();
305 widthDefined = true;
306 } else if (style::isPerLength (child->widget->getStyle()->width)) {
307 DBG_OBJ_MSGF ("resize.oofm", 1, "percentage width: %g%%",
309 (child->widget->getStyle()->width));
310 width = style::multiplyWithPerLength (refWidth,
311 child->widget->getStyle()->width)
312 + child->widget->boxDiffWidth ();
313 widthDefined = true;
314 } else {
315 DBG_OBJ_MSG ("resize.oofm", 1, "width not specified");
316 width = origChildWidth;
317 widthDefined = false;
318 }
319
320 int left, right;
321 bool leftDefined = getPosLeft (child->widget, refWidth, &left),
322 rightDefined = getPosRight (child->widget, refWidth, &right);
323 DBG_OBJ_MSGF ("resize.oofm", 1,
324 "=> left = %d, right = %d, width = %d (defined: %s)",
325 left, right, width, widthDefined ? "true" : "false");
326
327 if (xPtr) {
328 if (!leftDefined && !rightDefined)
329 *xPtr = generatorPosX (child) + child->x;
330 else {
331 if (!leftDefined && rightDefined)
332 *xPtr = refWidth - width - right - containerBoxRestWidth ();
333 else if (leftDefined && !rightDefined)
334 *xPtr = left + containerBoxOffsetX ();
335 else {
336 *xPtr = left;
337 if (!widthDefined) {
338 width = refWidth - (left + right + containerBoxDiffWidth ());
339 DBG_OBJ_MSGF ("resize.oofm", 0, "=> width (corrected) = %d",
340 width);
341 }
342 }
343 }
344
345 DBG_OBJ_MSGF ("resize.oofm", 0, "=> x = %d", *xPtr);
346 }
347
348 if (widthPtr)
349 *widthPtr = width;
350}
351
353 int origChildAscent,
354 int origChildDescent,
355 int *yPtr, int *ascentPtr,
356 int *descentPtr)
357{
358 assert (refHeight != -1 ||
359 (yPtr == NULL && ascentPtr == NULL && descentPtr == NULL));
360
361 int ascent = origChildAscent, descent = origChildDescent;
362 bool heightDefined;
363
364 if (style::isAbsLength (child->widget->getStyle()->height)) {
365 DBG_OBJ_MSGF ("resize.oofm", 1, "absolute height: %dpx",
367 int height = style::absLengthVal (child->widget->getStyle()->height)
368 + child->widget->boxDiffHeight ();
369 splitHeightPreserveAscent (height, &ascent, &descent);
370 heightDefined = true;
371 } else if (style::isPerLength (child->widget->getStyle()->height)) {
372 DBG_OBJ_MSGF ("resize.oofm", 1, "percentage height: %g%%",
374 (child->widget->getStyle()->height));
375 int height =
377 child->widget->getStyle()->height)
378 + child->widget->boxDiffHeight ();
379 splitHeightPreserveAscent (height, &ascent, &descent);
380 heightDefined = true;
381 } else {
382 DBG_OBJ_MSG ("resize.oofm", 1, "height not specified");
383 heightDefined = false;
384 }
385
386 int top, bottom;
387 bool topDefined = getPosTop (child->widget, refHeight, &top),
388 bottomDefined = getPosBottom (child->widget, refHeight, &bottom);
389 DBG_OBJ_MSGF ("resize.oofm", 1,
390 "=> top = %d, bottom = %d, height = %d + %d (defined: %s)",
391 top, bottom, ascent, descent,
392 heightDefined ? "true" : "false");
393
394 if (yPtr) {
395 if (!topDefined && !bottomDefined)
396 *yPtr = generatorPosY (child) + child->y;
397 else {
398 if (!topDefined && bottomDefined)
399 *yPtr = refHeight - (ascent + descent) - bottom
401 else if (topDefined && !bottomDefined)
402 *yPtr = top + containerBoxOffsetY ();
403 else {
404 *yPtr = top;
405 if (!heightDefined) {
406 int height =
407 refHeight - (top + bottom + containerBoxDiffHeight ());
408 splitHeightPreserveAscent (height, &ascent, &descent);
409 DBG_OBJ_MSGF ("resize.oofm", 0,
410 "=> ascent + descent (corrected) = %d + %d",
411 ascent, descent);
412 }
413 }
414 }
415
416 DBG_OBJ_MSGF ("resize.oofm", 0, "=> y = %d", *yPtr);
417 }
418
419 if (ascentPtr)
420 *ascentPtr = ascent;
421 if (descentPtr)
422 *descentPtr = descent;
423}
424
425} // namespace oof
426
427} // namespace dw
The base class of all dillo widgets.
Definition widget.hh:44
void sizeAllocate(Allocation *allocation)
Wrapper for Widget::sizeAllocateImpl, calls the latter only when needed.
Definition widget.cc:1209
void sizeRequest(Requisition *requisition, int numPos=0, Widget **references=NULL, int *x=NULL, int *y=NULL)
This method is a wrapper for Widget::sizeRequestImpl(); it calls the latter only when needed.
Definition widget.cc:550
int boxDiffWidth()
Definition widget.hh:495
int getAvailWidth(bool forceValue)
Return available width including margin/border/padding (extraSpace?), not only the content width.
Definition widget.cc:665
void calcFinalWidth(style::Style *style, int refWidth, Widget *refWidget, int limitMinWidth, bool forceValue, int *finalWidth)
Computes the final width if posible and constraints it by min-width and max-width.
Definition widget.cc:991
style::Style * getStyle()
Definition widget.hh:482
int getMinWidth(Extremes *extremes, bool forceValue)
Used to evaluate Widget::adjustMinWidth.
Definition widget.cc:620
int calcHeight(style::Length cssValue, bool usePercentage, int refHeight, Widget *refWidget, bool forceValue)
Definition widget.cc:1037
int getAvailHeight(bool forceValue)
Return available height including margin/border/padding (extraSpace?), not only the content height.
Definition widget.cc:705
int boxDiffHeight()
Definition widget.hh:500
void getExtremes(Extremes *extremes, int numPos=0, Widget **references=NULL, int *x=NULL, int *y=NULL)
Wrapper for Widget::getExtremesImpl().
Definition widget.cc:1093
Base class for widgets which can act as container and generator for widgets out of flow.
void calcVPosAndSizeChildOfChild(Child *child, int refHeight, int origChildAscent, int origChildDescent, int *yPtr, int *ascentPtr, int *descentPtr)
void getSize(core::Requisition *containerReq, int *oofWidth, int *oofHeight)
int getAvailHeightOfChild(core::Widget *child, bool forceValue)
virtual int containerBoxOffsetY()=0
void calcPosAndSizeChildOfChild(Child *child, int refWidth, int refHeight, int *xPtr, int *yPtr, int *widthPtr, int *ascentPtr, int *descentPtr)
void getExtremes(core::Extremes *containerExtr, int *oofMinWidth, int *oofMaxWidth)
bool posXAbsolute(Child *child)
void calcWidgetRefSize(core::Widget *widget, core::Requisition *size)
virtual int containerBoxRestWidth()=0
void calcHPosAndSizeChildOfChild(Child *child, int refWidth, int origChildWidth, int *xPtr, int *widthPtr)
int getAvailWidthOfChild(core::Widget *child, bool forceValue)
virtual int containerBoxOffsetX()=0
bool posYAbsolute(Child *child)
OOFPosAbsLikeMgr(OOFAwareWidget *container)
bool posXDefined(Child *child)
bool posYDefined(Child *child)
lout::container::typed::Vector< Child > * children
bool getPosLeft(core::Widget *child, int availWidth, int *result)
int generatorPosX(Child *child)
int generatorPosY(Child *child)
bool getPosRight(core::Widget *child, int availWidth, int *result)
core::Allocation containerAllocation
bool getPosTop(core::Widget *child, int availHeight, int *result)
bool getPosBottom(core::Widget *child, int availHeight, int *result)
#define DBG_OBJ_ENTER0(aspect, prio, funname)
#define DBG_OBJ_DELETE()
#define DBG_OBJ_CREATE(klass)
#define DBG_OBJ_MSGF(aspect, prio, fmt,...)
#define DBG_OBJ_MSG(aspect, prio, msg)
#define DBG_OBJ_ENTER(aspect, prio, funname, fmt,...)
#define DBG_OBJ_LEAVE()
#define DBG_OBJ_LEAVE_VAL(fmt,...)
int multiplyWithPerLength(int x, Length l)
Multiply an int with a percentage length, returning int.
Definition style.hh:474
double perLengthVal_useThisOnlyForDebugging(Length l)
Returns the value of a percentage, relative to 1, as a double.
Definition style.hh:459
bool isPerLength(Length l)
Returns true if l is a percentage.
Definition style.hh:446
bool isAbsLength(Length l)
Returns true if l is an absolute length.
Definition style.hh:443
int absLengthVal(Length l)
Returns the value of a length in pixels, as an integer.
Definition style.hh:452
@ LENGTH_AUTO
Represents "auto" lengths.
Definition style.hh:495
The core of Dw is defined in this namespace.
Definition core.hh:23
void splitHeightPreserveAscent(int height, int *ascent, int *descent)
Definition widget.cc:2244
Dw is in this namespace, or sub namespaces of this one.
Miscellaneous stuff, which does not fit anywhere else.
Definition misc.cc:31
T max(T a, T b)
Definition misc.hh:41
const char * boolToStr(bool b)
Definition misc.hh:108
Represents the allocation, i.e.
Definition types.hh:164