Dillo v3.1.1-98-g318d1f14
Loading...
Searching...
No Matches
ooffloatsmgr.cc
Go to the documentation of this file.
1/*
2 * Dillo Widget
3 *
4 * Copyright 2013-2014 Sebastian Geerken <sgeerken@dillo.org>
5 * Copyright 2024 Rodrigo Arias Mallo <rodarima@gmail.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#include "ooffloatsmgr.hh"
22#include "oofawarewidget.hh"
23#include "../lout/debug.hh"
24
25#include <limits.h>
26
27using namespace lout::object;
28using namespace lout::container::typed;
29using namespace lout::misc;
30using namespace dw::core;
31using namespace dw::core::style;
32
33namespace dw {
34
35namespace oof {
36
38{
39 this->oofm = oofm;
40 this->widget = widget;
41}
42
43// ----------------------------------------------------------------------
44
46 OOFAwareWidget *generatingBlock, int externalIndex)
47 : WidgetInfo (oofm, widget)
48{
49 this->generator = generatingBlock;
50 this->externalIndex = externalIndex;
51
53 dirty = true;
54 index = -1;
55
56 // Sometimes a float with widget = NULL is created as a key; this
57 // is not interesting for RTFL.
58 if (widget) {
59 DBG_OBJ_SET_PTR_O (widget, "<Float>.generatingBlock", generatingBlock);
60 DBG_OBJ_SET_NUM_O (widget, "<Float>.externalIndex", externalIndex);
61 DBG_OBJ_SET_NUM_O (widget, "<Float>.yReq", yReq);
62 DBG_OBJ_SET_NUM_O (widget, "<Float>.yReal", yReal);
63 DBG_OBJ_SET_NUM_O (widget, "<Float>.size.width", size.width);
64 DBG_OBJ_SET_NUM_O (widget, "<Float>.size.ascent", size.ascent);
65 DBG_OBJ_SET_NUM_O (widget, "<Float>.size.descent", size.descent);
66 DBG_OBJ_SET_BOOL_O (widget, "<Float>.dirty", dirty);
67 }
68}
69
71{
72 sb->append ("{ widget = ");
73 sb->appendPointer (getWidget ());
74
75 if (getWidget ()) {
76 sb->append (" (");
77 sb->append (getWidget()->getClassName ());
78 sb->append (")");
79 }
80
81 sb->append (", index = ");
82 sb->appendInt (index);
83 sb->append (", sideSpanningIndex = ");
84 sb->appendInt (sideSpanningIndex);
85 sb->append (", generator = ");
86 sb->appendPointer (generator);
87 sb->append (", yReq = ");
88 sb->appendInt (yReq);
89 sb->append (", yReal = ");
90 sb->appendInt (yReal);
91 sb->append (", size = { ");
92 sb->appendInt (size.width);
93 sb->append (" * ");
94 sb->appendInt (size.ascent);
95 sb->append (" + ");
96 sb->appendInt (size.descent);
97 sb->append (" }, dirty = ");
98 sb->appendBool (dirty);
99 sb->append (", sizeChangedSinceLastAllocation = ");
100 sb->append (" }");
101}
102
107{
108 DBG_OBJ_ENTER_O ("border", 0, getOOFFloatsMgr (), "covers",
109 "%d, %d [vloat: %p]", y, h, getWidget ());
110
111 getOOFFloatsMgr()->ensureFloatSize (this);
112 bool b = yReal + size.ascent + size.descent > y && yReal < y + h;
113
114 DBG_OBJ_LEAVE_VAL_O (getOOFFloatsMgr (), "%s", b ? "true" : "false");
115 return b;
116}
117
119{
120 return ((Float*)o1)->yReal - ((Float*)o2)->yReal;
121}
122
124 Object *o2)
125{
126 return ((Float*)o1)->sideSpanningIndex - ((Float*)o2)->sideSpanningIndex;
127}
128
130{
131 Float *f1 = (Float*)o1, *f2 = (Float*)o2;
132 int r = -123; // Compiler happiness: GCC 4.7 does not handle this?;
133
134 DBG_OBJ_ENTER_O ("border", 1, oofm, "CompareGBAndExtIndex::compare",
135 "#%d -> %p/%d, #%d -> %p/#%d",
136 f1->index, f1->generator, f1->externalIndex,
137 f2->index, f2->generator, f2->externalIndex);
138
139 if (f1->generator == f2->generator) {
140 r = f1->externalIndex - f2->externalIndex;
141 DBG_OBJ_MSGF_O ("border", 2, oofm,
142 "(a) generating blocks equal => %d - %d = %d",
143 f1->externalIndex, f2->externalIndex, r);
144 } else {
145 TBInfo *t1 = oofm->getOOFAwareWidget (f1->generator),
146 *t2 = oofm->getOOFAwareWidget (f2->generator);
147 bool rdef = false;
148
149 for (TBInfo *t = t1; t != NULL; t = t->parent)
150 if (t->parent == t2) {
151 rdef = true;
152 r = t->parentExtIndex - f2->externalIndex;
153 DBG_OBJ_MSGF_O ("border", 2, oofm,
154 "(b) %p is an achestor of %p; direct child is "
155 "%p (%d) => %d - %d = %d\n",
156 t2->getOOFAwareWidget (), t1->getOOFAwareWidget (),
157 t->getOOFAwareWidget (), t->parentExtIndex,
158 t->parentExtIndex, f2->externalIndex, r);
159 }
160
161 for (TBInfo *t = t2; !rdef && t != NULL; t = t->parent)
162 if (t->parent == t1) {
163 r = f1->externalIndex - t->parentExtIndex;
164 rdef = true;
165 DBG_OBJ_MSGF_O ("border", 2, oofm,
166 "(c) %p is an achestor of %p; direct child is %p "
167 "(%d) => %d - %d = %d\n",
168 t1->getOOFAwareWidget (), t2->getOOFAwareWidget (),
169 t->getOOFAwareWidget (), t->parentExtIndex,
170 f1->externalIndex, t->parentExtIndex, r);
171 }
172
173 if (!rdef) {
174 r = t1->index - t2->index;
175 DBG_OBJ_MSGF_O ("border", 2, oofm, "(d) other => %d - %d = %d",
176 t1->index, t2->index, r);
177 }
178 }
179
180 DBG_OBJ_LEAVE_VAL_O (oofm, "%d", r);
181 return r;
182}
183
185 int lastExtIndex)
186{
187 DBG_OBJ_ENTER_O ("border", 0, oofm, "findFloatIndex", "%p, %d",
188 lastGB, lastExtIndex);
189
190 Float key (oofm, NULL, lastGB, lastExtIndex);
191 key.index = -1; // for debugging
192 Float::CompareGBAndExtIndex comparator (oofm);
193 int i = bsearch (&key, false, &comparator);
194
195 // At position i is the next larger element, so element i should
196 // not included, but i - 1 returned; except if the exact element is
197 // found: then include it and so return i.
198 int r;
199 if (i == size())
200 r = i - 1;
201 else {
202 Float *f = get (i);
203 if (comparator.compare (f, &key) == 0)
204 r = i;
205 else
206 r = i - 1;
207 }
208
209 //printf ("[%p] findFloatIndex (%p, %d) => i = %d, r = %d (size = %d); "
210 // "in %s list %p on the %s side\n",
211 // oofm->container, lastGB, lastExtIndex, i, r, size (),
212 // type == GB ? "GB" : "CB", this, side == LEFT ? "left" : "right");
213
214 //for (int i = 0; i < size (); i++) {
215 // Float *f = get(i);
216 // TBInfo *t = oofm->getOOFAwareWidget(f->generatingBlock);
217 // printf (" %d: (%p [%d, %p], %d)\n", i, f->generatingBlock,
218 // t->index, t->parent ? t->parent->textblock : NULL,
219 // get(i)->externalIndex);
220 //}
221
222 DBG_OBJ_LEAVE_VAL_O (oofm, "%d", r);
223 return r;
224}
225
229int OOFFloatsMgr::SortedFloatsVector::find (int y, int start, int end)
230{
231 DBG_OBJ_ENTER_O ("border", 0, oofm, "find", "%d, %d, %d", y, start, end);
232
233 Float key (oofm, NULL, NULL, 0);
234 key.yReal = y;
235 Float::ComparePosition comparator;
236 int result = bsearch (&key, false, start, end, &comparator);
237
238 DBG_OBJ_LEAVE_VAL_O (oofm, "%d", result);
239 return result;
240}
241
243 OOFAwareWidget *lastGB,
244 int lastExtIndex,
245 int *lastReturn)
246{
247 DBG_OBJ_ENTER_O ("border", 0, oofm, "findFirst", "%d, %d, %p, %d",
248 y, h, lastGB, lastExtIndex);
249
250 int last = findFloatIndex (lastGB, lastExtIndex);
251 DBG_OBJ_MSGF_O ("border", 1, oofm, "last = %d", last);
252 assert (last < size());
253
254 // If the caller wants to reuse this value:
255 if (lastReturn)
256 *lastReturn = last;
257
258 int i = find (y, 0, last), result;
259 DBG_OBJ_MSGF_O ("border", 1, oofm, "i = %d", i);
260
261 // Note: The smallest value of "i" is 0, which means that "y" is before or
262 // equal to the first float. The largest value is "last + 1", which means
263 // that "y" is after the last float. In both cases, the first or last,
264 // respectively, float is a candidate. Generally, both floats, before and
265 // at the search position, are candidates.
266
267 if (i > 0 && get(i - 1)->covers (y, h))
268 result = i - 1;
269 else if (i <= last && get(i)->covers (y, h))
270 result = i;
271 else
272 result = -1;
273
274 DBG_OBJ_LEAVE_VAL_O (oofm, "%d", result);
275 return result;
276}
277
279 (int sideSpanningIndex)
280{
282 Float key (NULL, NULL, NULL, 0);
283 key.sideSpanningIndex = sideSpanningIndex;
284 return bsearch (&key, false, &comparator) - 1;
285}
286
288{
290 vloat->index = size() - 1;
291}
292
294{
295 TBInfo *tbInfo1 = (TBInfo*)o1, *tbInfo2 = (TBInfo*)o2;
296 int y1 = tbInfo1->getOOFAwareWidget () == NULL ? tbInfo1->y :
298 int y2 = tbInfo2->getOOFAwareWidget () == NULL ? tbInfo2->y :
299 tbInfo2->getOOFAwareWidget()->getGeneratorY (oofmIndex);
300 return y1 - y2;
301}
302
304 TBInfo *parent, int parentExtIndex) :
305 WidgetInfo (oofm, textblock)
306{
307 this->parent = parent;
308 this->parentExtIndex = parentExtIndex;
309
310 leftFloats = new Vector<Float> (1, false);
311 rightFloats = new Vector<Float> (1, false);
312}
313
315{
316 delete leftFloats;
317 delete rightFloats;
318}
319
321{
322 DBG_OBJ_CREATE ("dw::oof::OOFFloatsMgr");
323
324 this->container = container;
325 this->oofmIndex = oofmIndex;
326
327 leftFloats = new SortedFloatsVector (this, LEFT, true);
328 rightFloats = new SortedFloatsVector (this, RIGHT, true);
329
330 DBG_OBJ_SET_NUM ("leftFloats.size", leftFloats->size());
331 DBG_OBJ_SET_NUM ("rightFloats.size", rightFloats->size());
332
333 floatsByWidget = new HashTable <TypedPointer <Widget>, Float> (true, false);
334
335 tbInfos = new Vector<TBInfo> (1, false);
337 new HashTable <TypedPointer <OOFAwareWidget>, TBInfo> (true, true);
338
341
342 SizeChanged = true;
343 DBG_OBJ_SET_BOOL ("SizeChanged", SizeChanged);
344
346
347 addWidgetInFlow (this->container, NULL, 0);
348}
349
351{
352 // Order is important: tbInfosByOOFAwareWidget is owner of the instances
353 // of TBInfo.tbInfosByOOFAwareWidget. Also, leftFloats and rightFloats are
354 // owners of the floats.
355 delete tbInfos;
357
358 delete floatsByWidget;
359
360 delete leftFloats;
361 delete rightFloats;
362
364}
365
367 Allocation *allocation)
368{
369 DBG_OBJ_ENTER ("resize.oofm", 0, "sizeAllocateStart",
370 "%p, (%d, %d, %d * (%d + %d))",
371 caller, allocation->x, allocation->y, allocation->width,
372 allocation->ascent, allocation->descent);
373
374 if (caller == container)
375 containerAllocation = *allocation;
376
377 DBG_OBJ_LEAVE ();
378}
379
381{
382 DBG_OBJ_ENTER ("resize.oofm", 0, "sizeAllocateEnd", "%p", caller);
383
384 if (caller == container) {
387 }
388
389 DBG_OBJ_LEAVE ();
390}
391
393{
394 DBG_OBJ_ENTER0 ("resize", 0, "containerSizeChangedForChildren");
395
396 for (int i = 0; i < leftFloats->size (); i++)
398 for (int i = 0; i < rightFloats->size (); i++)
400
401 DBG_OBJ_LEAVE ();
402}
403
405{
406 SortedFloatsVector *list = side == LEFT ? leftFloats : rightFloats;
407
408 DBG_OBJ_ENTER ("resize.oofm", 0, "sizeAllocateFloats", "%s",
409 side == LEFT ? "LEFT" : "RIGHT");
410
411 for (int i = 0; i < list->size (); i++) {
412 Float *vloat = list->get(i);
413 ensureFloatSize (vloat);
414
415 Allocation childAllocation;
416 childAllocation.x = containerAllocation.x + calcFloatX (vloat);
417 childAllocation.y = containerAllocation.y + vloat->yReal;
418 childAllocation.width = vloat->size.width;
419 childAllocation.ascent = vloat->size.ascent;
420 childAllocation.descent = vloat->size.descent;
421
422 vloat->getWidget()->sizeAllocate (&childAllocation);
423 }
424
425 DBG_OBJ_LEAVE ();
426}
427
432{
433 DBG_OBJ_ENTER ("resize.common", 0, "calcFloatX", "%p", vloat->getWidget ());
434 int x, effGeneratorWidth;
435 OOFAwareWidget *generator = vloat->generator;
436
437 ensureFloatSize (vloat);
438
439 switch (vloat->getWidget()->getStyle()->vloat) {
440 case FLOAT_LEFT:
441 // Left floats are always aligned on the left side of the generator
442 // (content, not allocation) ...
443 x = generator->getGeneratorX (oofmIndex)
444 + generator->getStyle()->boxOffsetX();
445
446 // ... but when the float exceeds the line break width of the container,
447 // it is corrected (but not left of the container). This way, we save
448 // space and, especially within tables, avoid some problems.
449 if (x + vloat->size.width > container->getMaxGeneratorWidth ())
450 x = max (0, container->getMaxGeneratorWidth () - vloat->size.width);
451 break;
452
453 case FLOAT_RIGHT:
454 // Similar for right floats, but in this case, floats are shifted to the
455 // right when they are too big (instead of shifting the generator to the
456 // right).
457
458 // (The following code for calculating effGeneratorWidth, is quite
459 // specific for textblocks; this also applies for the comments. Both may
460 // be generalized, but actually, only textblocks play a role here.)
461
462 if (vloat->generator->usesMaxGeneratorWidth ())
463 // For most textblocks, the line break width is used for calculating
464 // the x position. (This changed for GROWS, where the width of a
465 // textblock is often smaller that the line break.)
466 effGeneratorWidth = vloat->generator->getMaxGeneratorWidth ();
467 else
468 // For some textblocks, like inline blocks, the line break width would
469 // be too large for right floats in some cases.
470 //
471 // (i) Consider a small inline block with only a few words in one
472 // line, narrower that line break width minus float width. In this
473 // case, the sum should be used.
474 //
475 // (ii) If there is more than one line, the line break will already be
476 // exceeded, and so be smaller that GB width + float width.
477 effGeneratorWidth =
478 min (vloat->generator->getGeneratorWidth () + vloat->size.width,
480
481 x = max (generator->getGeneratorX (oofmIndex) + effGeneratorWidth
482 - vloat->size.width - generator->getStyle()->boxRestWidth(),
483 // Do not exceed container allocation:
484 0);
485 break;
486
487 default:
489 x = 0;
490 break;
491 }
492
493 DBG_OBJ_LEAVE_VAL ("%d", x);
494 return x;
495}
496
497void OOFFloatsMgr::draw (View *view, Rectangle *area, DrawingContext *context)
498{
499 DBG_OBJ_ENTER ("draw", 0, "draw", "%d, %d, %d * %d",
500 area->x, area->y, area->width, area->height);
501
502 drawFloats (leftFloats, view, area, context);
503 drawFloats (rightFloats, view, area, context);
504
505 DBG_OBJ_LEAVE ();
506}
507
509 Rectangle *area, DrawingContext *context)
510{
511 // This could be improved, since the list is sorted: search the
512 // first float fitting into the area, and iterate until one is
513 // found below the area.
514
515 for (int i = 0; i < list->size(); i++) {
516 Float *vloat = list->get(i);
517 Widget *childWidget = vloat->getWidget ();
518
519 Rectangle childArea;
520 if (!context->hasWidgetBeenProcessedAsInterruption (childWidget) &&
522 childWidget->intersects (container, area, &childArea))
523 childWidget->draw (view, &childArea, context);
524 }
525}
526
528 OOFAwareWidget *parentBlock,
529 int externalIndex)
530{
531 //printf ("[%p] addWidgetInFlow (%p, %p, %d)\n",
532 // container, textblock, parentBlock, externalIndex);
533
534 TBInfo *tbInfo =
535 new TBInfo (this, textblock,
536 parentBlock ? getOOFAwareWidget (parentBlock) : NULL,
537 externalIndex);
538 tbInfo->index = tbInfos->size();
539
540 tbInfos->put (tbInfo);
542 tbInfo);
543}
544
545int OOFFloatsMgr::addWidgetOOF (Widget *widget, OOFAwareWidget *generatingBlock,
546 int externalIndex)
547{
548 DBG_OBJ_ENTER ("construct.oofm", 0, "addWidgetOOF", "%p, %p, %d",
549 widget, generatingBlock, externalIndex);
550
551 int subRef = 0;
552
553 TBInfo *tbInfo = getOOFAwareWidget (generatingBlock);
554 Float *vloat = new Float (this, widget, generatingBlock, externalIndex);
555
556 // Note: Putting the float first in the GB list, and then, possibly
557 // into the CB list (in that order) will trigger setting
558 // Float::inCBList to the right value.
559
560 switch (widget->getStyle()->vloat) {
561 case FLOAT_LEFT:
562 leftFloats->put (vloat);
563 DBG_OBJ_SET_NUM ("leftFloats.size", leftFloats->size());
564 DBG_OBJ_ARRATTRSET_PTR ("leftFloats", leftFloats->size() - 1,
565 "widget", vloat->getWidget ());
566 tbInfo->leftFloats->put (vloat);
567
568 subRef = createSubRefLeftFloat (leftFloats->size() - 1);
569
570 break;
571
572 case FLOAT_RIGHT:
573 rightFloats->put (vloat);
574 DBG_OBJ_SET_NUM ("rightFloats.size", rightFloats->size());
575 DBG_OBJ_ARRATTRSET_PTR ("rightFloats", rightFloats->size() - 1,
576 "widget", vloat->getWidget ());
577 tbInfo->rightFloats->put (vloat);
578
579 subRef = createSubRefRightFloat (rightFloats->size() - 1);
580 break;
581
582 default:
584 }
585
586 // "sideSpanningIndex" is only compared, so this simple assignment
587 // is sufficient; differenciation between GB and CB lists is not
588 // neccessary.
589 vloat->sideSpanningIndex =
590 leftFloats->size() + rightFloats->size() - 1;
591
592 floatsByWidget->put (new TypedPointer<Widget> (widget), vloat);
593
594 DBG_OBJ_LEAVE_VAL ("%d", subRef);
595 return subRef;
596}
597
599{
600 size->width = size->ascent = size->descent = 0;
601}
602
604 int oldStartIndex, int diff)
605{
606 TBInfo *tbInfo = getOOFAwareWidget (generatingBlock);
607 moveExternalIndices (tbInfo->leftFloats, oldStartIndex, diff);
608 moveExternalIndices (tbInfo->rightFloats, oldStartIndex, diff);
609}
610
612 int diff)
613{
614 // Could be faster with binary search, but the number of floats per generator
615 // should be rather small.
616 for (int i = 0; i < list->size (); i++) {
617 Float *vloat = list->get (i);
618 if (vloat->externalIndex >= oldStartIndex) {
619 vloat->externalIndex += diff;
620 DBG_OBJ_SET_NUM_O (vloat->getWidget (), "<Float>.externalIndex",
621 vloat->externalIndex);
622 }
623 }
624}
625
627{
628 TypedPointer <Widget> key (widget);
629 Float *vloat = floatsByWidget->get (&key);
630 assert (vloat != NULL);
631 return vloat;
632}
633
634/*
635 * Currently this is a compound recursion for textblocks:
636 * markSizeChange -> updateReference -> queueResize -> markSizeChange
637 * One way to see it is as a widget tree coverage problem. i.e. to cover all
638 * the nodes that need a resize when a float changes its size.
639 * The coverage logic of it is shared between resize code and mark code (here).
640 *
641 * This implementation works for all the test cases so far. It relies on the
642 * fact that Widget::queueResize should be called whenever a widget changes its
643 * size. When "SizeChanged" is true, we notify the parent, when not, just the
644 * following textblocks.
645 */
647{
648 DBG_OBJ_ENTER ("resize.oofm", 0, "markSizeChange", "%d", ref);
649
650 // When "SizeChanged" is true, we know this float changed its size.
651 // This helps to prune redundant passes.
652 // "SizeChanged" is set by getSize(), which is called by sizeRequest().
653
654 SortedFloatsVector *list;
656 Float *vloat = list->get (getFloatIndexFromSubRef (ref));
657
658 vloat->dirty = true;
659 DBG_OBJ_SET_BOOL_O (vloat->getWidget (), "<Float>.dirty", vloat->dirty);
660
661 updateGenerators (vloat);
662
663 DBG_OBJ_LEAVE ();
664}
665
670{
671 DBG_OBJ_ENTER ("resize.oofm", 0, "updateGenerators", "#%d [%p]",
672 vloat->index, vloat->getWidget ());
673
674 assert (vloat->getWidget()->getWidgetReference() != NULL);
675
676 int first = getOOFAwareWidget(vloat->generator)->index;
677 DBG_OBJ_MSGF ("resize.oofm", 1, "updating from %d", first);
678
679 //printf("IN markSizeChange %p ref %d SzCh=%d\n", this, ref,
680 // (int)SizeChanged);
681
682 if (SizeChanged)
683 tbInfos->get(first)->getOOFAwareWidget()
684 ->updateReference (vloat->getWidget()->getWidgetReference()
685 ->parentRef);
686
687 for (int i = first + 1; i < tbInfos->size(); i++)
688 tbInfos->get(i)->getOOFAwareWidget()->updateReference(0);
689
690 SizeChanged = false; // Done.
691
692 DBG_OBJ_LEAVE ();
693}
694
699{
700 DBG_OBJ_ENTER ("findTBInfo", 0, "findTBInfo", "%d", y);
701
702 TBInfo key (this, NULL, NULL, 0);
703 key.y = y;
705 int index = tbInfos->bsearch (&key, false, &comparator);
706
707 // "bsearch" returns next greater, but we are interrested in the last which
708 // is less or equal.
709 int result = index > 0 ? index - 1 : index;
710
711 DBG_OBJ_LEAVE_VAL ("%d", result);
712 return result;
713}
714
715
717{
718 // Nothing to do here.
719}
720
723{
724 Widget *widgetAtPoint = NULL;
725
726 widgetAtPoint = getFloatWidgetAtPoint (rightFloats, x, y, context);
727 if (widgetAtPoint == NULL)
728 widgetAtPoint = getFloatWidgetAtPoint (leftFloats, x, y, context);
729
730 return widgetAtPoint;
731}
732
734 int y,
736 *context)
737{
738 // Could use binary search to be faster (similar to drawing).
739 Widget *widgetAtPoint = NULL;
740
741 for (int i = list->size() - 1; widgetAtPoint == NULL && i >= 0; i--) {
742 Widget *childWidget = list->get(i)->getWidget ();
743 if (!context->hasWidgetBeenProcessedAsInterruption (childWidget) &&
745 widgetAtPoint = childWidget->getWidgetAtPoint (x, y, context);
746 }
747
748 return widgetAtPoint;
749}
750
751void OOFFloatsMgr::tellPosition1 (Widget *widget, int x, int y)
752{
753 DBG_OBJ_ENTER ("resize.oofm", 0, "tellPosition1", "%p, %d, %d",
754 widget, x, y);
755
756 assert (y >= 0);
757
758 Float *vloat = findFloatByWidget(widget);
759
760 SortedFloatsVector *listSame, *listOpp;
761 Side side;
762 getFloatsListsAndSide (vloat, &listSame, &listOpp, &side);
763 ensureFloatSize (vloat);
764
765 int oldYReal = vloat->yReal;
766
767 // "yReal" may change due to collisions (see below).
768 vloat->yReq = vloat->yReal = y;
769
770 DBG_OBJ_SET_NUM_O (vloat->getWidget (), "<Float>.yReq", vloat->yReq);
771 DBG_OBJ_SET_NUM_O (vloat->getWidget (), "<Float>.yReal", vloat->yReal);
772
773 // Test collisions (on this side). Although there are (rare) cases
774 // where it could make sense, the horizontal dimensions are not
775 // tested; especially since searching and border calculation would
776 // be confused. For this reaspn, only the previous float is
777 // relevant. (Cf. below, collisions on the other side.)
778 int yRealNew;
779 if (vloat->index >= 1 &&
780 collidesV (vloat, listSame->get (vloat->index - 1), &yRealNew)) {
781 vloat->yReal = yRealNew;
782 DBG_OBJ_SET_NUM_O (vloat->getWidget (), "<Float>.yReal", vloat->yReal);
783 }
784
785 // Test collisions (on the opposite side). There are cases when
786 // more than one float has to be tested. Consider the following
787 // HTML snippet ("id" attribute only used for simple reference
788 // below, as #f1, #f2, and #f3):
789 //
790 // <div style="float:left" id="f1">
791 // Left left left left left left left left left left.
792 // </div>
793 // <div style="float:left" id="f2">Also left.</div>
794 // <div style="float:right" id="f3">Right.</div>
795 //
796 // When displayed with a suitable window width (only slightly wider
797 // than the text within #f1), this should look like this:
798 //
799 // ---------------------------------------------------------
800 // | Left left left left left left left left left left. |
801 // | Also left. Right. |
802 // ---------------------------------------------------------
803 //
804 // Consider float #f3: a collision test with #f2, considering
805 // vertical dimensions, is positive, but not the test with
806 // horizontal dimensions (because #f2 and #f3 are too
807 // narrow). However, a collision has to be tested with #f1;
808 // otherwise #f3 and #f1 would overlap.
809
810 int oppFloatIndex =
812 // Generally, the rules are simple: loop as long as the vertical
813 // dimensions test is positive (and, of course, there are floats),
814 // ...
815 for (bool foundColl = false;
816 !foundColl && oppFloatIndex >= 0 &&
817 collidesV (vloat, listOpp->get (oppFloatIndex), &yRealNew);
818 oppFloatIndex--) {
819 // ... but stop the loop as soon as the horizontal dimensions
820 // test is positive.
821 if (collidesH (vloat, listOpp->get (oppFloatIndex))) {
822 vloat->yReal = yRealNew;
823 DBG_OBJ_SET_NUM_O (vloat->getWidget (), "<Float>.yReal", vloat->yReal);
824 foundColl = true;
825 }
826 }
827
828 DBG_OBJ_MSGF ("resize.oofm", 1, "vloat->yReq = %d, vloat->yReal = %d",
829 vloat->yReq, vloat->yReal);
830
831 // In some cases, an explicit update is neccessary, as in this example:
832 //
833 // <body>
834 // <div id="a">
835 // <div id="b" style="float:left">main</div>
836 // </div>
837 // <div id="c" style="clear:both">x</div>
838 // <div id="d">footer</div>
839 // </body>
840 //
841 // Without an explicit update, #c would keep an old value for extraSpace.top,
842 // based on the old value of vloat->yReal.
843 //
844 // Notice that #c would be updated otherwise, if it had at least one word
845 // content.
846
847 if (vloat->yReal != oldYReal)
848 updateGenerators (vloat);
849
850 DBG_OBJ_LEAVE ();
851}
852
853void OOFFloatsMgr::tellPosition2 (Widget *widget, int x, int y)
854{
855 // Nothing to do.
856}
857
859 int x, int y)
860{
861 notImplemented ("OOFFloatsMgr::tellIncompletePosition1");
862}
863
865 int x, int y)
866{
867 notImplemented ("OOFFloatsMgr::tellIncompletePosition2");
868}
869
870bool OOFFloatsMgr::collidesV (Float *vloat, Float *other, int *yReal)
871{
872 DBG_OBJ_ENTER ("resize.oofm", 0, "collidesV", "#%d [%p], #%d [%p], ...",
873 vloat->index, vloat->getWidget (), other->index,
874 other->getWidget ());
875
876 bool result;
877
878 DBG_OBJ_MSGF ("resize.oofm", 1, "initial yReal = %d", vloat->yReal);
879
880 ensureFloatSize (other);
881 int otherBottomGB = other->yReal + other->size.ascent + other->size.descent;
882
883 DBG_OBJ_MSGF ("resize.oofm", 1, "otherBottomGB = %d + (%d + %d) = %d",
884 other->yReal, other->size.ascent, other->size.descent,
885 otherBottomGB);
886
887 if (vloat->yReal < otherBottomGB) {
888 *yReal = otherBottomGB;
889 result = true;
890 } else
891 result = false;
892
893 if (result)
894 DBG_OBJ_LEAVE_VAL ("%s, %d", "true", *yReal);
895 else
896 DBG_OBJ_LEAVE_VAL ("%s", "false");
897
898 return result;
899}
900
901
903{
904 // Only checks horizontal collision. For a complete test, use collidesV (...)
905 // && collidesH (...).
906 bool collidesH;
907
908 int vloatX = calcFloatX (vloat), otherX = calcFloatX (other);
909
910 // Generally: right border of the left float > left border of the right float
911 // (all in canvas coordinates).
912 if (vloat->getWidget()->getStyle()->vloat == FLOAT_LEFT) {
913 // "vloat" is left, "other" is right
914 ensureFloatSize (vloat);
915 collidesH = vloatX + vloat->size.width > otherX;
916 } else {
917 // "other" is left, "vloat" is right
918 ensureFloatSize (other);
919 collidesH = otherX + other->size.width > vloatX;
920 }
921
922 return collidesH;
923}
924
926 SortedFloatsVector **listSame,
927 SortedFloatsVector **listOpp,
928 Side *side)
929{
930 switch (vloat->getWidget()->getStyle()->vloat) {
931 case FLOAT_LEFT:
932 if (listSame) *listSame = leftFloats;
933 if (listOpp) *listOpp = rightFloats;
934 if (side) *side = LEFT;
935 break;
936
937 case FLOAT_RIGHT:
938 if (listSame) *listSame = rightFloats;
939 if (listOpp) *listOpp = leftFloats;
940 if (side) *side = RIGHT;
941 break;
942
943 default:
945 }
946}
947
948void OOFFloatsMgr::getSize (Requisition *cbReq, int *oofWidth, int *oofHeight)
949{
950 DBG_OBJ_ENTER0 ("resize.oofm", 0, "getSize");
951
952 int oofWidthtLeft, oofWidthRight, oofHeightLeft, oofHeightRight;
953 getFloatsSize (cbReq, LEFT, &oofWidthtLeft, &oofHeightLeft);
954 getFloatsSize (cbReq, RIGHT, &oofWidthRight, &oofHeightRight);
955
956 // Floats must be within the *content* area of the containing
957 // block, not its *margin* area (which is equivalent to the
958 // requisition / allocation). For this reason, boxRestWidth() and
959 // boxRestHeight() are added here.
960
961 *oofWidth =
962 max (oofWidthtLeft, oofWidthRight) + container->boxRestWidth ();
963 *oofHeight =
964 max (oofHeightLeft, oofHeightRight) + container->boxRestHeight ();
965
966 SizeChanged = true;
967
968 DBG_OBJ_MSGF ("resize.oofm", 1,
969 "=> (l: %d, r: %d => %d) * (l: %d, r: %d => %d)",
970 oofWidthtLeft, oofWidthRight, *oofWidth, oofHeightLeft,
971 oofHeightRight, *oofHeight);
972 DBG_OBJ_LEAVE ();
973}
974
975void OOFFloatsMgr::getFloatsSize (Requisition *cbReq, Side side, int *width,
976 int *height)
977{
978 DBG_OBJ_ENTER ("resize.oofm", 0, "getFloatsSize", "(%d * (%d + %d), %s, ...",
979 cbReq->width, cbReq->ascent, cbReq->descent,
980 side == LEFT ? "LEFT" : "RIGHT");
981
982 SortedFloatsVector *list = side == LEFT ? leftFloats : rightFloats;
983
984 *width = *height = 0;
985
986 DBG_OBJ_MSGF ("resize.oofm", 1, "%d floats on this side", list->size());
987
988 for (int i = 0; i < list->size(); i++) {
989 Float *vloat = list->get(i);
990
991 DBG_OBJ_MSGF ("resize.oofm", 1,
992 "float %p has generator %p (container is %p)",
993 vloat->getWidget (), vloat->generator, container);
994
995 ensureFloatSize (vloat);
996
997 *width = max (*width, calcFloatX (vloat) + vloat->size.width);
998 *height = max (*height,
999 vloat->yReal + vloat->size.ascent + vloat->size.descent);
1000 }
1001
1002 DBG_OBJ_LEAVE ();
1003}
1004
1006{
1007 return false;
1008}
1009
1010void OOFFloatsMgr::getExtremes (Extremes *cbExtr, int *oofMinWidth,
1011 int *oofMaxWidth)
1012{
1013 DBG_OBJ_ENTER ("resize.oofm", 0, "getExtremes", "(%d / %d), ...",
1014 cbExtr->minWidth, cbExtr->maxWidth);
1015
1016 int oofMinWidthtLeft, oofMinWidthRight, oofMaxWidthLeft, oofMaxWidthRight;
1017 getFloatsExtremes (cbExtr, LEFT, &oofMinWidthtLeft, &oofMaxWidthLeft);
1018 getFloatsExtremes (cbExtr, RIGHT, &oofMinWidthRight, &oofMaxWidthRight);
1019
1020 *oofMinWidth = max (oofMinWidthtLeft, oofMinWidthRight);
1021 *oofMaxWidth = max (oofMaxWidthLeft, oofMaxWidthRight);
1022
1023 DBG_OBJ_MSGF ("resize.oofm", 1,
1024 "=> (l: %d, r: %d => %d) / (l: %d, r: %d => %d)",
1025 oofMinWidthtLeft, oofMinWidthRight, *oofMinWidth,
1026 oofMaxWidthLeft, oofMaxWidthRight, *oofMaxWidth);
1027 DBG_OBJ_LEAVE ();
1028}
1029
1031 int *minWidth, int *maxWidth)
1032{
1033 DBG_OBJ_ENTER ("resize.oofm", 0, "getFloatsExtremes", "(%d / %d), %s, ...",
1034 cbExtr->minWidth, cbExtr->maxWidth,
1035 side == LEFT ? "LEFT" : "RIGHT");
1036
1037 *minWidth = *maxWidth = 0;
1038
1039 SortedFloatsVector *list = side == LEFT ? leftFloats : rightFloats;
1040 DBG_OBJ_MSGF ("resize.oofm", 1, "%d floats to be examined", list->size());
1041
1042 for (int i = 0; i < list->size(); i++) {
1043 Float *vloat = list->get(i);
1044
1045 DBG_OBJ_MSGF ("resize.oofm", 1,
1046 "float %p has generator %p (container is %p)",
1047 vloat->getWidget (), vloat->generator,
1048 container);
1049
1050 Extremes extr;
1051 vloat->getWidget()->getExtremes (&extr);
1052
1053 // The calculation of extremes must be kept consistent with
1054 // getFloatsSize(). Especially this means for the *minimal* width:
1055 //
1056 // - The right border (difference between float and container) does not
1057 // have to be considered (see getFloatsSize()).
1058 //
1059 // - This is also the case for the left border, as seen in calcFloatX()
1060 // ("... but when the float exceeds the line break width" ...).
1061
1062 *minWidth = max (*minWidth, extr.minWidth);
1063
1064 // For the maximal width, borders must be considered.
1065 *maxWidth = max (*maxWidth,
1066 extr.maxWidth
1067 + vloat->generator->getStyle()->boxDiffWidth(),
1069 - vloat->generator->getGeneratorWidth (),
1070 0));
1071
1072 DBG_OBJ_MSGF ("resize.oofm", 1, "%d / %d => %d / %d",
1073 extr.minWidth, extr.maxWidth, *minWidth, *maxWidth);
1074 }
1075
1076 DBG_OBJ_LEAVE ();
1077}
1078
1080 (OOFAwareWidget *widget)
1081{
1082 DBG_OBJ_ENTER ("oofm.common", 0, "getOOFAwareWidgetWhenRegistered", "%p",
1083 widget);
1084 TypedPointer<OOFAwareWidget> key (widget);
1085 TBInfo *tbInfo = tbInfosByOOFAwareWidget->get (&key);
1086 DBG_OBJ_MSGF ("oofm.common", 1, "found? %s", tbInfo ? "yes" : "no");
1087 DBG_OBJ_LEAVE ();
1088 return tbInfo;
1089}
1090
1092{
1093 DBG_OBJ_ENTER ("oofm.common", 0, "getOOFAwareWidget", "%p", widget);
1094 TBInfo *tbInfo = getOOFAwareWidgetWhenRegistered (widget);
1095 assert (tbInfo);
1096 DBG_OBJ_LEAVE ();
1097 return tbInfo;
1098}
1099
1101 int lastExtIndex)
1102{
1103 int b = getBorder (LEFT, y, h, lastGB, lastExtIndex);
1104 DBG_OBJ_MSGF ("border", 0, "left border (%d, %d, %p, %d) => %d",
1105 y, h, lastGB, lastExtIndex, b);
1106 return b;
1107}
1108
1110 int lastExtIndex)
1111{
1112 int b = getBorder (RIGHT, y, h, lastGB, lastExtIndex);
1113 DBG_OBJ_MSGF ("border", 0, "right border (%d, %d, %p, %d) => %d",
1114 y, h, lastGB, lastExtIndex, b);
1115 return b;
1116}
1117
1118int OOFFloatsMgr::getBorder (Side side, int y, int h, OOFAwareWidget *lastGB,
1119 int lastExtIndex)
1120{
1121 DBG_OBJ_ENTER ("border", 0, "getBorder", "%s, %d, %d, %p, %d",
1122 side == LEFT ? "LEFT" : "RIGHT", y, h, lastGB, lastExtIndex);
1123
1124 SortedFloatsVector *list = side == LEFT ? leftFloats : rightFloats;
1125 int last;
1126 int first = list->findFirst (y, h, lastGB, lastExtIndex, &last);
1127 int border = 0;
1128
1129 DBG_OBJ_MSGF ("border", 1, "first = %d", first);
1130
1131 if (first != -1) {
1132 // It is not sufficient to find the first float, since a line
1133 // (with height h) may cover the region of multiple float, of
1134 // which the widest has to be choosen.
1135 bool covers = true;
1136
1137 // We are not searching until the end of the list, but until the
1138 // float defined by lastGB and lastExtIndex.
1139 for (int i = first; covers && i <= last; i++) {
1140 Float *vloat = list->get(i);
1141 covers = vloat->covers (y, h);
1142 DBG_OBJ_MSGF ("border", 1, "float %d (%p) covers? %s.",
1143 i, vloat->getWidget(), covers ? "<b>yes</b>" : "no");
1144
1145 if (covers) {
1146 int d;
1147 switch (side) {
1148 case LEFT:
1149 d = vloat->generator->getGeneratorX (oofmIndex)
1150 + vloat->generator->getStyle()->boxOffsetX ();
1151 break;
1152
1153 case RIGHT:
1154 // There is no simple possibility to get the difference between
1155 // container and generator at the right border (as it is at the
1156 // left border, see above). We have to calculate the difference
1157 // between the maximal widths.
1159 - (vloat->generator->getGeneratorX (oofmIndex)
1160 + vloat->generator->getMaxGeneratorWidth ())
1161 + vloat->generator->getStyle()->boxRestWidth ();
1162 break;
1163
1164 default:
1166 d = 0;
1167 break;
1168 }
1169
1170 int thisBorder = vloat->size.width + d;
1171 DBG_OBJ_MSGF ("border", 1, "thisBorder = %d + %d = %d",
1172 vloat->size.width, d, thisBorder);
1173
1174 border = max (border, thisBorder);
1175 }
1176 }
1177 }
1178
1179 DBG_OBJ_LEAVE_VAL ("%d", border);
1180 return border;
1181}
1182
1183bool OOFFloatsMgr::hasFloatLeft (int y, int h, OOFAwareWidget *lastGB,
1184 int lastExtIndex)
1185{
1186 bool b = hasFloat (LEFT, y, h, lastGB, lastExtIndex);
1187 DBG_OBJ_MSGF ("border", 0, "has float left (%d, %d, %p, %d) => %s",
1188 y, h, lastGB, lastExtIndex, b ? "true" : "false");
1189 return b;
1190}
1191
1193 int lastExtIndex)
1194{
1195 bool b = hasFloat (RIGHT, y, h, lastGB, lastExtIndex);
1196 DBG_OBJ_MSGF ("border", 0, "has float right (%d, %d, %p, %d) => %s",
1197 y, h, lastGB, lastExtIndex, b ? "true" : "false");
1198 return b;
1199}
1200
1201bool OOFFloatsMgr::hasFloat (Side side, int y, int h, OOFAwareWidget *lastGB,
1202 int lastExtIndex)
1203{
1204 DBG_OBJ_ENTER ("border", 0, "hasFloat", "%s, %d, %d, %p, %d",
1205 side == LEFT ? "LEFT" : "RIGHT", y, h, lastGB, lastExtIndex);
1206
1207 SortedFloatsVector *list = side == LEFT ? leftFloats : rightFloats;
1208 int first = list->findFirst (y, h, lastGB, lastExtIndex, NULL);
1209
1210 DBG_OBJ_MSGF ("border", 1, "first = %d", first);
1211 DBG_OBJ_LEAVE ();
1212 return first != -1;
1213}
1214
1216 int lastExtIndex)
1217{
1218 return getFloatHeight (LEFT, y, h, lastGB, lastExtIndex);
1219}
1220
1222 int lastExtIndex)
1223{
1224 return getFloatHeight (RIGHT, y, h, lastGB, lastExtIndex);
1225}
1226
1227int OOFFloatsMgr::getFloatHeight (Side side, int y, int h,
1228 OOFAwareWidget *lastGB, int lastExtIndex)
1229{
1230 DBG_OBJ_ENTER ("border", 0, "getFloatHeight", "%s, %d, %d, %p, %d",
1231 side == LEFT ? "LEFT" : "RIGHT", y, h, lastGB, lastExtIndex);
1232
1233 SortedFloatsVector *list = side == LEFT ? leftFloats : rightFloats;
1234 int first = list->findFirst (y, h, lastGB, lastExtIndex, NULL);
1235 assert (first != -1); /* This method must not be called when there is no
1236 float on the respective side. */
1237
1238 Float *vloat = list->get (first);
1239 int yRelToFloat = y - vloat->yReal;
1240 DBG_OBJ_MSGF ("border", 1, "caller is CB: yRelToFloat = %d - %d = %d",
1241 y, vloat->yReal, yRelToFloat);
1242
1243 ensureFloatSize (vloat);
1244 int height = vloat->size.ascent + vloat->size.descent - yRelToFloat;
1245
1246 DBG_OBJ_MSGF ("border", 1, "=> (%d + %d) - %d = %d",
1247 vloat->size.ascent, vloat->size.descent, yRelToFloat, height);
1248 DBG_OBJ_LEAVE ();
1249 return height;
1250}
1251
1253{
1254 DBG_OBJ_ENTER ("resize.oofm", 0, "getClearPosition", "%p", widget);
1255
1256 int pos;
1257
1258 if (widget->getStyle()) {
1259 bool left = false, right = false;
1260 switch (widget->getStyle()->clear) {
1261 case CLEAR_NONE: break;
1262 case CLEAR_LEFT: left = true; break;
1263 case CLEAR_RIGHT: right = true; break;
1264 case CLEAR_BOTH: left = right = true; break;
1265 default: assertNotReached ();
1266 }
1267
1268 pos = max (left ? getClearPosition (widget, LEFT) : 0,
1269 right ? getClearPosition (widget, RIGHT) : 0);
1270 } else
1271 pos = 0;
1272
1273 DBG_OBJ_LEAVE_VAL ("%d", pos);
1274 return pos;
1275}
1276
1278{
1279 return widget->getStyle()->vloat == core::style::FLOAT_LEFT;
1280}
1281
1283{
1284 return widget->getStyle()->vloat == core::style::FLOAT_RIGHT;
1285};
1286
1288{
1289 return true;
1290}
1291
1293{
1294 DBG_OBJ_ENTER ("resize.oofm", 0, "getClearPosition", "%p, %s",
1295 widget, side == LEFT ? "LEFT" : "RIGHT");
1296
1297 int pos;
1298 SortedFloatsVector *list = side == LEFT ? leftFloats : rightFloats;
1299
1300 // Search the last float before (therfore -1) this widget.
1301 int i = list->findFloatIndex (widget, -1);
1302 if (i < 0)
1303 pos = 0;
1304 else {
1305 Float *vloat = list->get(i);
1306 assert (vloat->generator != widget);
1307 ensureFloatSize (vloat);
1308 int yRel = widget->getGeneratorY (oofmIndex);
1309 pos = max (vloat->yReal + vloat->size.ascent + vloat->size.descent - yRel,
1310 0);
1311 DBG_OBJ_MSGF ("resize.oofm", 1, "pos = max (%d + %d + %d - %d, 0)",
1312 vloat->yReal, vloat->size.ascent, vloat->size.descent,
1313 yRel);
1314 }
1315
1316 DBG_OBJ_LEAVE_VAL ("%d", pos);
1317
1318 return pos;
1319}
1320
1322{
1323 // Historical note: relative sizes (e. g. percentages) are already
1324 // handled by (at this time) Layout::containerSizeChanged, so
1325 // Float::dirty will be set.
1326
1327 DBG_OBJ_ENTER ("resize.oofm", 0, "ensureFloatSize", "%p",
1328 vloat->getWidget ());
1329
1330 if (vloat->dirty) {
1331 DBG_OBJ_MSG ("resize.oofm", 1, "dirty: recalculation");
1332
1333 vloat->getWidget()->sizeRequest (&vloat->size);
1334 vloat->dirty = false;
1335 DBG_OBJ_SET_BOOL_O (vloat->getWidget (), "<Float>.dirty", vloat->dirty);
1336
1337 DBG_OBJ_MSGF ("resize.oofm", 1, "size: %d * (%d + %d)",
1338 vloat->size.width, vloat->size.ascent, vloat->size.descent);
1339
1340 DBG_OBJ_SET_NUM_O (vloat->getWidget(), "<Float>.size.width",
1341 vloat->size.width);
1342 DBG_OBJ_SET_NUM_O (vloat->getWidget(), "<Float>.size.ascent",
1343 vloat->size.ascent);
1344 DBG_OBJ_SET_NUM_O (vloat->getWidget(), "<Float>.size.descent",
1345 vloat->size.descent);
1346
1347 // "sizeChangedSinceLastAllocation" is reset in sizeAllocateEnd()
1348 }
1349
1350 DBG_OBJ_LEAVE ();
1351}
1352
1354{
1355 return false;
1356}
1357
1358int OOFFloatsMgr::getAvailWidthOfChild (Widget *child, bool forceValue)
1359{
1360 notImplemented ("OOFFloatsMgr::getAvailWidthOfChild");
1361 return 0;
1362}
1363
1364int OOFFloatsMgr::getAvailHeightOfChild (Widget *child, bool forceValue)
1365{
1366 notImplemented ("OOFFloatsMgr::getAvailHeightOfChild");
1367 return 0;
1368}
1369
1371{
1372 return leftFloats->size() + rightFloats->size();
1373}
1374
1376{
1377 if (i < leftFloats->size())
1378 return leftFloats->get(i)->getWidget ();
1379 else
1380 return rightFloats->get(i - leftFloats->size())->getWidget ();
1381}
1382
1383} // namespace oof
1384
1385} // namespace dw
Set at the top when drawing.
Definition types.hh:295
Set at the top when getting the widget at the point.
Definition types.hh:313
dw::core::Shape implemtation for simple rectangles.
Definition types.hh:70
static bool handledByStackingContextMgr(Widget *widget)
bool hasWidgetBeenProcessedAsInterruption(Widget *widget)
Definition types.hh:277
An interface to encapsulate platform dependent drawing.
Definition view.hh:17
The base class of all dillo widgets.
Definition widget.hh:44
Allocation * getAllocation()
Definition widget.hh:484
void sizeAllocate(Allocation *allocation)
Wrapper for Widget::sizeAllocateImpl, calls the latter only when needed.
Definition widget.cc:1209
bool intersects(Widget *refWidget, Rectangle *area, Rectangle *intersection)
Calculates the intersection of the visible allocation (i.
Definition widget.cc:151
virtual void draw(View *view, Rectangle *area, DrawingContext *context)=0
Area is given in widget coordinates.
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
style::Style * getStyle()
Definition widget.hh:482
WidgetReference * getWidgetReference()
Definition widget.hh:594
Widget * generator
The generating widget, NULL for top-level widgets, or if not set; in the latter case,...
Definition widget.hh:139
int boxRestWidth()
Definition widget.hh:493
int boxRestHeight()
Definition widget.hh:498
virtual Widget * getWidgetAtPoint(int x, int y, GettingWidgetAtPointContext *context)
Definition widget.cc:223
void containerSizeChanged()
Definition widget.cc:420
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.
virtual int getMaxGeneratorWidth()
virtual int getGeneratorX(int oofmIndex)
Return position relative to container, not regarding margin/border/padding, Called by OOFFloatsMgr to...
virtual int getGeneratorWidth()
Return width including margin/border/padding Called by OOFFloatsMgr to position floats.
virtual bool usesMaxGeneratorWidth()
virtual int getGeneratorY(int oofmIndex)
Return position relative to container, not regarding margin/border/padding, Called by OOFFloatsMgr to...
int compare(Object *o1, Object *o2)
Compare two objects o1 and o2.
int compare(Object *o1, Object *o2)
Compare two objects o1 and o2.
int compare(Object *o1, Object *o2)
Compare two objects o1 and o2.
void intoStringBuffer(lout::misc::StringBuffer *sb)
Store a textual representation of the object in a misc::StringBuffer.
Float(OOFFloatsMgr *oofm, core::Widget *widget, OOFAwareWidget *generatingBlock, int externalIndex)
bool covers(int y, int h)
y is given relative to the container.
int findFloatIndex(OOFAwareWidget *lastGB, int lastExtIndex)
int findLastBeforeSideSpanningIndex(int sideSpanningIndex)
int find(int y, int start, int end)
y is given relative to the container.
int findFirst(int y, int h, OOFAwareWidget *lastGB, int lastExtIndex, int *lastReturn)
int compare(Object *o1, Object *o2)
Compare two objects o1 and o2.
TBInfo(OOFFloatsMgr *oofm, OOFAwareWidget *textblock, TBInfo *parent, int parentExtIndex)
lout::container::typed::Vector< Float > * rightFloats
OOFAwareWidget * getOOFAwareWidget()
lout::container::typed::Vector< Float > * leftFloats
WidgetInfo(OOFFloatsMgr *oofm, core::Widget *widget)
OutOfFlowMgr implementation dealing with floats.
void getFloatsListsAndSide(Float *vloat, SortedFloatsVector **listSame, SortedFloatsVector **listOpp, Side *side)
core::Widget * getWidgetAtPoint(int x, int y, core::GettingWidgetAtPointContext *context)
bool hasFloat(Side side, int y, int h, OOFAwareWidget *lastGB, int lastExtIndex)
void moveExternalIndices(lout::container::typed::Vector< Float > *list, int oldStartIndex, int diff)
bool dealingWithSizeOfChild(core::Widget *child)
bool collidesV(Float *vloat, Float *other, int *yReal)
int getAvailHeightOfChild(core::Widget *child, bool forceValue)
static int getFloatIndexFromSubRef(int ref)
void getFloatsSize(core::Requisition *cbReq, Side side, int *width, int *height)
int getAvailWidthOfChild(core::Widget *child, bool forceValue)
int findTBInfo(int y)
y is given relative to the container.
core::Widget * getFloatWidgetAtPoint(SortedFloatsVector *list, int x, int y, core::GettingWidgetAtPointContext *context)
void tellIncompletePosition2(core::Widget *generator, core::Widget *widget, int x, int y)
int getRightFloatHeight(int y, int h, OOFAwareWidget *lastGB, int lastExtIndex)
Assuming there is a float on the right side, return the rest height of it.
void ensureFloatSize(Float *vloat)
void updateGenerators(Float *vloat)
Update all generators which are affected by a given float.
OOFFloatsMgr(OOFAwareWidget *container, int oofmIndex)
int getLeftBorder(int y, int h, OOFAwareWidget *lastGB, int lastExtIndex)
Get the left border for the vertical position of y, for a height of h", based on floats; relative to ...
bool collidesH(Float *vloat, Float *other)
void containerSizeChangedForChildren()
int getBorder(Side side, int y, int h, OOFAwareWidget *lastGB, int lastExtIndex)
core::Allocation containerAllocation
TBInfo * getOOFAwareWidget(OOFAwareWidget *widget)
lout::container::typed::Vector< TBInfo > * tbInfos
void tellPosition1(core::Widget *widget, int x, int y)
Called before tellPosition2, see there for more.
core::Widget * getWidget(int i)
bool hasFloatRight(int y, int h, OOFAwareWidget *lastGB, int lastExtIndex)
Return whether there is a float on the right side.
void getExtremes(core::Extremes *cbExtr, int *oofMinWidth, int *oofMaxWidth)
bool affectsLeftBorder(core::Widget *widget)
static int createSubRefLeftFloat(int index)
void getFloatsExtremes(core::Extremes *cbExtr, Side side, int *minWidth, int *maxWidth)
void sizeAllocateEnd(OOFAwareWidget *caller)
void addWidgetInFlow(OOFAwareWidget *textblock, OOFAwareWidget *parentBlock, int externalIndex)
void calcWidgetRefSize(core::Widget *widget, core::Requisition *size)
static bool isSubRefLeftFloat(int ref)
void tellPosition2(core::Widget *widget, int x, int y)
Called after tellPosition1.
void draw(core::View *view, core::Rectangle *area, core::DrawingContext *context)
OOFAwareWidget * container
static int createSubRefRightFloat(int index)
lout::container::typed::HashTable< lout::object::TypedPointer< OOFAwareWidget >, TBInfo > * tbInfosByOOFAwareWidget
bool affectsRightBorder(core::Widget *widget)
void markSizeChange(int ref)
int calcFloatX(Float *vloat)
Return position of a float relative to the container.
int getRightBorder(int y, int h, OOFAwareWidget *lastGB, int lastExtIndex)
Get the right border for the vertical position of y, for a height of h, based on floats; relative to ...
void sizeAllocateFloats(Side side)
int getLeftFloatHeight(int y, int h, OOFAwareWidget *lastGB, int lastExtIndex)
Assuming there is a float on the left side, return the rest height of it.
Float * findFloatByWidget(core::Widget *widget)
int getClearPosition(OOFAwareWidget *widget, Side side)
lout::container::typed::HashTable< lout::object::TypedPointer< dw::core::Widget >, Float > * floatsByWidget
TBInfo * getOOFAwareWidgetWhenRegistered(OOFAwareWidget *widget)
bool hasFloatLeft(int y, int h, OOFAwareWidget *lastGB, int lastExtIndex)
Return whether there is a float on the left side.
void markExtremesChange(int ref)
void getSize(core::Requisition *cbReq, int *oofWidth, int *oofHeight)
int getFloatHeight(Side side, int y, int h, OOFAwareWidget *lastGB, int lastExtIndex)
void tellIncompletePosition1(core::Widget *generator, core::Widget *widget, int x, int y)
int addWidgetOOF(core::Widget *widget, OOFAwareWidget *generatingBlock, int externalIndex)
void drawFloats(SortedFloatsVector *list, core::View *view, core::Rectangle *area, core::DrawingContext *context)
void sizeAllocateStart(OOFAwareWidget *caller, core::Allocation *allocation)
SortedFloatsVector * rightFloats
SortedFloatsVector * leftFloats
Typed version of container::untyped::Vector.
Definition container.hh:447
void put(T *newElement, int newPos=-1)
Definition container.hh:452
A class for fast concatenation of a large number of strings.
Definition misc.hh:570
void appendBool(bool b)
Definition misc.hh:598
void appendPointer(void *p)
Definition misc.hh:596
void appendInt(int n)
Definition misc.hh:594
void append(const char *str)
Append a NUL-terminated string to the buffer, with copying.
Definition misc.hh:593
This is the base class for many other classes, which defines very common virtual methods.
Definition object.hh:25
A typed version of object::Pointer.
Definition object.hh:116
#define DBG_OBJ_ENTER0(aspect, prio, funname)
#define DBG_OBJ_SET_BOOL_O(obj, var, val)
#define DBG_OBJ_DELETE()
#define DBG_OBJ_CREATE(klass)
#define DBG_OBJ_SET_BOOL(var, val)
#define DBG_OBJ_MSGF(aspect, prio, fmt,...)
#define DBG_OBJ_SET_NUM(var, val)
#define DBG_OBJ_MSG(aspect, prio, msg)
#define DBG_OBJ_LEAVE_VAL_O(obj, fmt,...)
#define DBG_OBJ_MSGF_O(aspect, prio, obj, fmt,...)
#define DBG_OBJ_ENTER(aspect, prio, funname, fmt,...)
#define DBG_OBJ_LEAVE()
#define DBG_OBJ_SET_NUM_O(obj, var, val)
#define DBG_OBJ_LEAVE_VAL(fmt,...)
#define DBG_OBJ_SET_PTR_O(obj, var, val)
#define DBG_OBJ_ENTER_O(aspect, prio, obj, funname, fmt,...)
#define DBG_OBJ_ARRATTRSET_PTR(var, ind, attr, val)
Anything related to Dillo Widget styles is defined here.
Definition style.cc:34
The core of Dw is defined in this namespace.
Definition core.hh:23
Dw is in this namespace, or sub namespaces of this one.
This namespace provides thin wrappers, implemented as C++ templates, to gain type-safety.
Definition container.hh:387
Miscellaneous stuff, which does not fit anywhere else.
Definition misc.cc:31
T min(T a, T b)
Definition misc.hh:40
void notImplemented(const char *name)
Definition misc.hh:76
T max(T a, T b)
Definition misc.hh:41
void assertNotReached()
Definition misc.hh:56
Here, some common classes (or interfaces) are defined, to standardize the access to other classes.
Definition object.cc:30
Represents the allocation, i.e.
Definition types.hh:164