Dillo v3.1.1-119-g140d9ebd
Loading...
Searching...
No Matches
widget.cc
Go to the documentation of this file.
1/*
2 * Dillo Widget
3 *
4 * Copyright 2005-2007 Sebastian Geerken <sgeerken@dillo.org>
5 * Copyright 2023-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//#define DEBUG_LEVEL 1
22#include "core.hh"
23
24#include "../lout/msg.h"
25#include "../lout/debug.hh"
26
27using namespace lout;
28using namespace lout::object;
29using namespace lout::misc;
30
31namespace dw {
32namespace core {
33
34/* Used to determine which action to take when correcting the aspect ratio of a
35 * requisition in Widget::correctReqAspectRatio(). */
36enum {
39 PASS_KEEP = 2
40};
41
42
43// ----------------------------------------------------------------------
44
49
50void Widget::WidgetImgRenderer::getBgArea (int *x, int *y, int *width,
51 int *height)
52{
53 widget->getPaddingArea (x, y, width, height);
54}
55
56void Widget::WidgetImgRenderer::getRefArea (int *xRef, int *yRef, int *widthRef,
57 int *heightRef)
58{
59 widget->getPaddingArea (xRef, yRef, widthRef, heightRef);
60}
61
63{
64 return widget->getStyle ();
65}
66
67void Widget::WidgetImgRenderer::draw (int x, int y, int width, int height)
68{
69 widget->queueDrawArea (x - widget->allocation.x, y - widget->allocation.y,
70 width, height);
71}
72
73// ----------------------------------------------------------------------
74
75bool Widget::adjustMinWidth = true;
76int Widget::CLASS_ID = -1;
77
79{
80 DBG_OBJ_CREATE ("dw::core::Widget");
81 registerName ("dw::core::Widget", &CLASS_ID);
82
85
88 setWidgetReference (NULL);
89 DBG_OBJ_SET_PTR ("container", container);
90
91 layout = NULL;
92
93 allocation.x = -1;
94 allocation.y = -1;
95 allocation.width = 1;
98
100
101 style = NULL;
102 bgColor = NULL;
103 buttonSensitive = true;
104 buttonSensitiveSet = false;
105
106 deleteCallbackData = NULL;
107 deleteCallbackFunc = NULL;
108
109 widgetImgRenderer = NULL;
110
111 stackingContextMgr = NULL;
112
113 ratio = 0.0;
114}
115
117{
120
121 if (widgetImgRenderer) {
124 delete widgetImgRenderer;
125 }
126
128 delete stackingContextMgr;
129
130 if (style)
131 style->unref ();
132
133 if (parent)
134 parent->removeChild (this);
135 else if (layout)
137
139}
140
141
151bool Widget::intersects (Widget *refWidget, Rectangle *area,
152 Rectangle *intersection)
153{
154 DBG_OBJ_ENTER ("draw", 0, "intersects", "%p, [%d, %d, %d * %d]",
155 refWidget, area->x, area->y, area->width, area->height);
156 bool r;
157
158 if (wasAllocated ()) {
159 *intersection = *area;
160 intersection->x += refWidget->allocation.x;
161 intersection->y += refWidget->allocation.y;
162
163 r = true;
164 // "RefWidget" is excluded; it is assumed that "area" its already within
165 // its allocation.
166 for (Widget *widget = this; r && widget != refWidget;
167 widget = widget->parent) {
168 assert (widget != NULL); // refWidget must be ancestor.
169
170 Rectangle widgetArea, newIntersection;
171 widgetArea.x = widget->allocation.x;
172 widgetArea.y = widget->allocation.y;
173 widgetArea.width = widget->allocation.width;
174 widgetArea.height = widget->getHeight ();
175
176 if (intersection->intersectsWith (&widgetArea, &newIntersection)) {
177 DBG_OBJ_MSGF ("draw", 1, "new intersection: %d, %d, %d * %d",
178 newIntersection.x, newIntersection.y,
179 newIntersection.width, newIntersection.height);
180 *intersection = newIntersection;
181 } else {
182 DBG_OBJ_MSG ("draw", 1, "no new intersection");
183 r = false;
184 }
185 }
186
187 if (r) {
188 intersection->x -= allocation.x;
189 intersection->y -= allocation.y;
190
191 DBG_OBJ_MSGF ("draw", 1, "final intersection: %d, %d, %d * %d",
192 intersection->x, intersection->y,
193 intersection->width, intersection->height);
194 }
195 } else {
196 r = false;
197 DBG_OBJ_MSG ("draw", 1, "not allocated");
198 }
199
200 if (r)
201 DBG_OBJ_LEAVE_VAL ("true: %d, %d, %d * %d",
202 intersection->x, intersection->y,
203 intersection->width, intersection->height);
204 else
205 DBG_OBJ_LEAVE_VAL0 ("false");
206
207 return r;
208}
209
214 DrawingContext *context)
215{
216 Rectangle thisArea;
217 if (intersects (layout->topLevel, context->getToplevelArea (), &thisArea))
218 draw (view, &thisArea, context);
219
220 context->addWidgetProcessedAsInterruption (this);
221}
222
225{
226 // Suitable for simple widgets, without children.
227
228 if (inAllocation (x, y))
229 return this;
230 else
231 return NULL;
232}
233
236 *context)
237{
238 Widget *widgetAtPoint = getWidgetAtPoint (x, y, context);
239 context->addWidgetProcessedAsInterruption (this);
240 return widgetAtPoint;
241}
242
244{
245 DBG_OBJ_ENTER ("construct", 0, "setParent", "%p", parent);
246
247 this->parent = parent;
249
252
254 //printf ("The %s %p becomes a child of the %s %p\n",
255 // getClassName(), this, parent->getClassName(), parent);
256
257 // Determine the container. Currently rather simple; will become
258 // more complicated when absolute and fixed positions are
259 // supported.
260 container = NULL;
261 for (Widget *widget = getParent (); widget != NULL && container == NULL;
262 widget = widget->getParent())
263 if (widget->isPossibleContainer ())
264 container = widget;
265 // If there is no possible container widget, there is
266 // (surprisingly!) also no container (i. e. the viewport is
267 // used). Does not occur in dillo, where the toplevel widget is a
268 // Textblock.
269 DBG_OBJ_SET_PTR ("container", container);
270
271 // If at all, stackingContextMgr should have set *before*, see also
272 // Widget::setStyle() and Layout::addWidget().
273 if (stackingContextMgr) {
275 while (stackingContextWidget &&
278 assert (stackingContextWidget);
280 } else
282
284
285 DBG_OBJ_LEAVE ();
286}
287
289{
290 this->quasiParent = quasiParent;
291
292 // More to do? Compare with setParent().
293
294 DBG_OBJ_SET_PTR ("quasiParent", quasiParent);
295}
296
297void Widget::queueDrawArea (int x, int y, int width, int height)
298{
301 DBG_OBJ_ENTER ("draw", 0, "queueDrawArea", "%d, %d, %d, %d",
302 x, y, width, height);
303
304 _MSG("Widget::queueDrawArea alloc(%d %d %d %d) wid(%d %d %d %d)\n",
307 x, y, width, height);
308 if (layout)
309 layout->queueDraw (x + allocation.x, y + allocation.y, width, height);
310
311 DBG_OBJ_LEAVE ();
312}
313
321void Widget::queueResize (int ref, bool extremesChanged, bool fast)
322{
323 DBG_OBJ_ENTER ("resize", 0, "queueResize", "%d, %s, %s",
324 ref, extremesChanged ? "true" : "false",
325 fast ? "true" : "false");
326
328
329 Widget *widget2, *child;
330
331 Flags resizeFlag, extremesFlag, totalFlags;
332
333 if (layout) {
334 // If RESIZE_QUEUED is set, this widget is already in the list.
335 if (!resizeQueued ())
336 layout->queueResizeList->put (this);
337
338 resizeFlag = RESIZE_QUEUED;
339 extremesFlag = EXTREMES_QUEUED;
340 } else {
341 resizeFlag = NEEDS_RESIZE;
342 extremesFlag = EXTREMES_CHANGED;
343 }
344
345 setFlags (resizeFlag);
347 markSizeChange (ref);
348
349 totalFlags = resizeFlag;
350
351 if (extremesChanged) {
352 totalFlags = (Flags)(totalFlags | extremesFlag);
353
354 setFlags (extremesFlag);
355 markExtremesChange (ref);
356 }
357
358 if (fast) {
359 if (parent) {
360 // In this case, queueResize is called from top (may be a
361 // random entry point) to bottom, so markSizeChange and
362 // markExtremesChange have to be called explicitly for the
363 // parent. The tests (needsResize etc.) are uses to check
364 // whether queueResize has been called for the parent, or
365 // whether this widget is the entry point.
366 if (parent->needsResize () || parent->resizeQueued ())
370 }
371 } else {
372 for (widget2 = parent, child = this; widget2;
373 child = widget2, widget2 = widget2->parent) {
374 if (layout && !widget2->resizeQueued ())
375 layout->queueResizeList->put (widget2);
376
377 DBG_OBJ_MSGF ("resize", 2, "setting %s and ALLOCATE_QUEUED for %p",
378 resizeFlag == RESIZE_QUEUED ?
379 "RESIZE_QUEUED" : "NEEDS_RESIZE",
380 widget2);
381
382 widget2->setFlags (resizeFlag);
383 widget2->markSizeChange (child->parentRef);
384 widget2->setFlags (ALLOCATE_QUEUED);
385
386 if (extremesChanged) {
387 widget2->setFlags (extremesFlag);
388 widget2->markExtremesChange (child->parentRef);
389 }
390
392 if (widget2->parent)
393 DBG_OBJ_MSGF ("resize", 2,
394 "checking parent %p: (%d & %d) [= %d] == %d?",
395 widget2->parent, widget2->parent->flags,
396 totalFlags, widget2->parent->flags & totalFlags,
397 totalFlags);
398 }
399
400 if (widget2->parent &&
401 (widget2->parent->flags & totalFlags) == totalFlags) {
402 widget2->parent->markSizeChange (widget2->parentRef);
403 if (extremesChanged) {
404 widget2->parent->markExtremesChange (widget2->parentRef);
405 }
406
407 break;
408 }
409 }
410
411 if (layout)
413 }
414
416
417 DBG_OBJ_LEAVE ();
418}
419
421{
422 DBG_OBJ_ENTER0 ("resize", 0, "containerSizeChanged");
423
424 // If there is a container widget (not the viewport), which has not
425 // changed its size (which can be determined by the respective
426 // flags: this method is called recursively), this widget will
427 // neither change its size. Also, the recursive iteration can be
428 // stopped, since the children of this widget will
429 if (container == NULL ||
432 // Viewport (container == NULL) or container widget has changed
433 // its size.
435 queueResizeFast (0, true);
436
437 // Even if *this* widget is not affected, children may be, so
438 // iterate over children.
440 }
441
442 DBG_OBJ_LEAVE ();
443}
444
446{
447 DBG_OBJ_ENTER0 ("resize", 0, "affectedByContainerSizeChange");
448
449 bool ret;
450
451 // This standard implementation is suitable for all widgets which
452 // call correctRequisition() and correctExtremes(), even in the way
453 // how Textblock and Image do (see comments there). Has to be kept
454 // in sync.
455
456 if (container == NULL) {
457 if (style::isAbsLength (getStyle()->width) &&
458 style::isAbsLength (getStyle()->height))
459 // Both absolute, i. e. fixed: no dependency.
460 ret = false;
461 else if (style::isPerLength (getStyle()->width) ||
462 style::isPerLength (getStyle()->height)) {
463 // Any percentage: certainly dependenant.
464 ret = true;
465 } else
466 // One or both is "auto": depends ...
467 ret =
469 usesAvailWidth () : false) ||
471 usesAvailHeight () : false);
472 } else
474
475 DBG_OBJ_LEAVE_VAL ("%s", boolToStr(ret));
476 return ret;
477}
478
480{
481 DBG_OBJ_ENTER ("resize", 0, "affectsSizeChangeContainerChild", "%p", child);
482
483 bool ret;
484
485 // From the point of view of the container. This standard
486 // implementation should be suitable for most (if not all)
487 // containers.
488
489 if (style::isAbsLength (child->getStyle()->width) &&
491 // Both absolute, i. e. fixed: no dependency.
492 ret = false;
493 else if (style::isPerLength (child->getStyle()->width) ||
494 style::isPerLength (child->getStyle()->height)) {
495 // Any percentage: certainly dependenant.
496 ret = true;
497 } else
498 // One or both is "auto": depends ...
499 ret =
500 (child->getStyle()->width == style::LENGTH_AUTO ?
501 child->usesAvailWidth () : false) ||
502 (child->getStyle()->height == style::LENGTH_AUTO ?
503 child->usesAvailHeight () : false);
504
505 DBG_OBJ_LEAVE_VAL ("%s", boolToStr(ret));
506 return ret;
507}
508
510{
511 DBG_OBJ_ENTER0 ("resize", 0, "containerSizeChangedForChildren");
512
513 // Working, but inefficient standard implementation.
516 false);
517 while (it->next ())
519 it->unref ();
520
521 DBG_OBJ_LEAVE ();
522}
523
529{
530 return false;
531}
532
538{
539 return false;
540}
541
551 Widget **references, int *x, int *y)
552{
553 assert (!queueResizeEntered ());
554
555 DBG_OBJ_ENTER ("resize", 0, "sizeRequest", "%d, ...", numPos);
556
559 for(int i = 0; i < numPos; i++)
560 DBG_OBJ_MSGF ("resize", 1, "ref #%d: %p, %d, %d",
561 i, references[i], x[i], y[i]);
563 }
564
566
567 if (resizeQueued ()) {
568 // This method is called outside of Layout::resizeIdle.
571 // The widget is not taken out of Layout::queueResizeList, since
572 // other *_QUEUED flags may still be set and processed in
573 // Layout::resizeIdle.
574 }
575
576 SizeParams newRequisitionParams (numPos, references, x, y);
577 DBG_OBJ_ASSOC_CHILD (&newRequisitionParams);
578
579 bool callImpl;
580 if (needsResize ())
581 callImpl = true;
582 else {
583 // Even if RESIZE_QUEUED / NEEDS_RESIZE is not set, calling
584 // sizeRequestImpl is necessary when the relavive positions passed here
585 // have changed.
586 callImpl = !newRequisitionParams.isEquivalent (&requisitionParams);
587 }
588
589 DBG_OBJ_MSGF ("resize", 1, "callImpl = %s", boolToStr (callImpl));
590
591 requisitionParams = newRequisitionParams;
592
593 if (callImpl) {
594 calcExtraSpace (numPos, references, x, y);
596 sizeRequestImpl (requisition, numPos, references, x, y);
597 this->requisition = *requisition;
599
600 DBG_OBJ_SET_NUM ("requisition.width", requisition->width);
601 DBG_OBJ_SET_NUM ("requisition.ascent", requisition->ascent);
602 DBG_OBJ_SET_NUM ("requisition.descent", requisition->descent);
603 } else
604 *requisition = this->requisition;
605
607
608 DBG_OBJ_LEAVE ();
609}
610
620int Widget::getMinWidth (Extremes *extremes, bool forceValue)
621{
623 if (extremes)
624 DBG_OBJ_ENTER ("resize", 0, "getMinWidth", "[%d (%d) / %d (%d)], %s",
627 forceValue ? "true" : "false");
628 else
629 DBG_OBJ_ENTER ("resize", 0, "getMinWidth", "(nil), %s",
630 forceValue ? "true" : "false");
631 }
632
633 int minWidth;
634
635 if (getAdjustMinWidth ()) {
636 Extremes extremes2;
637 if (extremes == NULL) {
638 if (forceValue) {
639 getExtremes (&extremes2);
640 extremes = &extremes2;
641 }
642 }
643
644 // TODO Not completely clear whether this is feasable: Within
645 // the context of getAvailWidth(false) etc., getExtremes may not
646 // be called. We ignore the minimal width then.
647 if (extremes)
648 minWidth = extremes->adjustmentWidth;
649 else
650 minWidth = 0;
651 } else
652 minWidth = 0;
653
654 DBG_OBJ_LEAVE_VAL ("%d", minWidth);
655 return minWidth;
656}
657
665int Widget::getAvailWidth (bool forceValue)
666{
667 DBG_OBJ_ENTER ("resize", 0, "getAvailWidth", "%s",
668 forceValue ? "true" : "false");
669
670 int width;
671
672 if (parent == NULL && quasiParent == NULL) {
673 DBG_OBJ_MSG ("resize", 1, "no parent, regarding viewport");
675
676 // TODO Consider nested layouts (e. g. <button>).
677
678 int viewportWidth =
681 width = viewportWidth;
682 calcFinalWidth (getStyle (), viewportWidth, NULL, 0, forceValue, &width);
683 assert(width != -1);
685 } else if (parent) {
686 DBG_OBJ_MSG ("resize", 1, "delegated to parent");
688 width = parent->getAvailWidthOfChild (this, forceValue);
690 } else /* if (quasiParent) */ {
691 DBG_OBJ_MSG ("resize", 1, "delegated to quasiParent");
693 width = quasiParent->getAvailWidthOfChild (this, forceValue);
695 }
696
697 DBG_OBJ_LEAVE_VAL ("%d", width);
698 return width;
699}
700
705int Widget::getAvailHeight (bool forceValue)
706{
707 // TODO Correct by ... not extremes, but ...? (Height extremes?)
708
709 // TODO Consider 'min-height' and 'max-height'. (Minor priority, as long as
710 // "getAvailHeight (true)" is not used.
711
712 DBG_OBJ_ENTER ("resize", 0, "getAvailHeight", "%s",
713 forceValue ? "true" : "false");
714
715 int height;
716
717 if (parent == NULL && quasiParent == NULL) {
718 DBG_OBJ_MSG ("resize", 1, "no parent, regarding viewport");
720
721 // TODO Consider nested layouts (e. g. <button>).
722 if (style::isAbsLength (getStyle()->height)) {
723 DBG_OBJ_MSGF ("resize", 1, "absolute height: %dpx",
724 style::absLengthVal (getStyle()->height));
725 height = style::absLengthVal (getStyle()->height) + boxDiffHeight ();
726 } else if (style::isPerLength (getStyle()->height)) {
727 DBG_OBJ_MSGF ("resize", 1, "percentage height: %g%%",
729 (getStyle()->height));
730 // Notice that here -- unlike getAvailWidth() --
731 // layout->hScrollbarThickness is not considered here;
732 // something like canvasWidthGreater (analogue to
733 // canvasHeightGreater) would be complicated and lead to
734 // possibly contradictory self-references.
735 height = applyPerHeight (layout->viewportHeight, getStyle()->height);
736 } else {
737 DBG_OBJ_MSG ("resize", 1, "no specification");
738 if (forceValue)
739 height = layout->viewportHeight;
740 else
741 height = -1;
742 }
743
745 } else if (parent) {
746 DBG_OBJ_MSG ("resize", 1, "delegated to parent");
748 height = parent->getAvailHeightOfChild (this, forceValue);
750 } else /* if (quasiParent) */ {
751 DBG_OBJ_MSG ("resize", 1, "delegated to quasiParent");
753 height = quasiParent->getAvailHeightOfChild (this, forceValue);
755 }
756
757 DBG_OBJ_LEAVE_VAL ("%d", height);
758 return height;
759}
760
769 void (*splitHeightFun) (int, int *, int *),
770 bool allowDecreaseWidth,
771 bool allowDecreaseHeight)
772{
773 int limitMinWidth = getMinWidth (NULL, true);
774 if (!allowDecreaseWidth && limitMinWidth < requisition->width)
775 limitMinWidth = requisition->width;
776
777 int viewportWidth =
780 calcFinalWidth (getStyle (), viewportWidth, NULL, limitMinWidth, false,
782
783 // For layout->viewportHeight, see comment in getAvailHeight().
784 int height = calcHeight (getStyle()->height, false,
785 layout->viewportHeight, NULL, false);
786 adjustHeight (&height, allowDecreaseHeight, requisition->ascent,
788
789 int minHeight = calcHeight (getStyle()->minHeight, false,
790 layout->viewportHeight, NULL, false);
791
792 int maxHeight = calcHeight (getStyle()->maxHeight, false,
793 layout->viewportHeight, NULL, false);
794
795 if (minHeight != -1 && maxHeight != -1) {
796 /* Prefer the maximum size for pathological cases (min > max) */
797 if (maxHeight < minHeight)
798 maxHeight = minHeight;
799 }
800
801 adjustHeight (&minHeight, allowDecreaseHeight, requisition->ascent,
803
804 adjustHeight (&maxHeight, allowDecreaseHeight, requisition->ascent,
806
807 // TODO Perhaps split first, then add box ascent and descent.
808 if (height != -1)
809 splitHeightFun (height, &requisition->ascent, &requisition->descent);
810 if (minHeight != -1 &&
811 requisition->ascent + requisition->descent < minHeight)
812 splitHeightFun (minHeight, &requisition->ascent,
814 if (maxHeight != -1 &&
815 requisition->ascent + requisition->descent > maxHeight)
816 splitHeightFun (maxHeight, &requisition->ascent,
818}
819
821 void (*splitHeightFun) (int, int *, int *),
822 bool allowDecreaseWidth,
823 bool allowDecreaseHeight)
824{
825 // TODO Correct height by ... not extremes, but ...? (Height extremes?)
826
827 DBG_OBJ_ENTER ("resize", 0, "correctRequisition",
828 "%d * (%d + %d), ..., %s, %s",
830 requisition->descent, misc::boolToStr (allowDecreaseWidth),
831 misc::boolToStr (allowDecreaseHeight));
832
833 if (parent == NULL && quasiParent == NULL) {
834 DBG_OBJ_MSG ("resize", 1, "no parent, regarding viewport");
836
837 for (int pass = 0; pass < 3; pass++) {
839 allowDecreaseWidth, allowDecreaseHeight);
840 bool changed = correctReqAspectRatio (pass, this, requisition,
841 allowDecreaseWidth, allowDecreaseHeight, splitHeightFun);
842
843 /* No need to repeat more passes */
844 if (!changed)
845 break;
846 }
847
849 } else if (parent) {
850 DBG_OBJ_MSG ("resize", 1, "delegated to parent");
852 parent->correctRequisitionOfChild (this, requisition, splitHeightFun,
853 allowDecreaseWidth,
854 allowDecreaseHeight);
856 } else /* if (quasiParent) */ {
857 DBG_OBJ_MSG ("resize", 1, "delegated to quasiParent");
860 splitHeightFun,
861 allowDecreaseWidth,
862 allowDecreaseHeight);
864 }
865
868}
869
870void Widget::correctExtremes (Extremes *extremes, bool useAdjustmentWidth)
871{
872 DBG_OBJ_ENTER ("resize", 0, "correctExtremes", "%d (%d) / %d (%d)",
875
876 if (container == NULL && quasiParent == NULL) {
877 DBG_OBJ_MSG ("resize", 1, "no parent, regarding viewport");
879
880 int limitMinWidth =
881 useAdjustmentWidth ? getMinWidth (extremes, false) : 0;
882 int viewportWidth =
885
886 int width = calcWidth (getStyle()->width, viewportWidth, NULL,
887 limitMinWidth, false);
888 int minWidth = calcWidth (getStyle()->minWidth, viewportWidth, NULL,
889 limitMinWidth, false);
890 int maxWidth = calcWidth (getStyle()->maxWidth, viewportWidth, NULL,
891 limitMinWidth, false);
892
893 DBG_OBJ_MSGF ("resize", 1, "width = %d, minWidth = %d, maxWidth = %d",
894 width, minWidth, maxWidth);
895
896 if (width != -1)
898 if (minWidth != -1)
899 extremes->minWidth = minWidth;
900 if (maxWidth != -1)
901 extremes->maxWidth = maxWidth;
902
904 } else if (parent) {
905 DBG_OBJ_MSG ("resize", 1, "delegated to parent");
907 parent->correctExtremesOfChild (this, extremes, useAdjustmentWidth);
909 } else /* if (quasiParent) */ {
910 DBG_OBJ_MSG ("resize", 1, "delegated to quasiParent");
912 quasiParent->correctExtremesOfChild (this, extremes, useAdjustmentWidth);
914 }
915
918
920}
921
932int Widget::calcWidth (style::Length cssValue, int refWidth, Widget *refWidget,
933 int limitMinWidth, bool forceValue)
934{
935 DBG_OBJ_ENTER ("resize", 0, "calcWidth", "0x%x, %d, %p, %d",
936 cssValue, refWidth, refWidget, limitMinWidth);
937
938 assert (refWidth != -1 || refWidget != NULL);
939
940 int width;
941
942 if (style::isAbsLength (cssValue)) {
943 DBG_OBJ_MSGF ("resize", 1, "absolute width: %dpx",
944 style::absLengthVal (cssValue));
945 width = misc::max (style::absLengthVal (cssValue) + boxDiffWidth (),
946 limitMinWidth);
947 } else if (style::isPerLength (cssValue)) {
948 DBG_OBJ_MSGF ("resize", 1, "percentage width: %g%%",
950 (cssValue));
951 if (refWidth != -1)
952 width = misc::max (applyPerWidth (refWidth, cssValue), limitMinWidth);
953 else {
954 int availWidth = refWidget->getAvailWidth (forceValue);
955 if (availWidth != -1) {
956 int containerWidth = availWidth - refWidget->boxDiffWidth ();
957 width = misc::max (applyPerWidth (containerWidth, cssValue),
958 limitMinWidth);
959 } else
960 width = -1;
961 }
962 } else {
963 DBG_OBJ_MSG ("resize", 1, "not specified");
964 width = -1;
965 }
966
967 DBG_OBJ_LEAVE_VAL ("%d", width);
968 return width;
969}
970
992 Widget *refWidget, int limitMinWidth,
993 bool forceValue, int *finalWidth)
994{
995 DBG_OBJ_ENTER ("resize", 0, "calcFinalWidth", "..., %d, %p, %d, [%d]",
996 refWidth, refWidget, limitMinWidth, *finalWidth);
997
998 int w = *finalWidth;
999 int width = calcWidth (style->width, refWidth, refWidget, limitMinWidth,
1000 forceValue);
1001 DBG_OBJ_MSGF ("resize", 1, "w = %d, width = %d", w, width);
1002
1003 if (width != -1)
1004 w = width;
1005
1006 /* Only correct w if not set to auto (-1) */
1007 if (w != -1) {
1008 int minWidth = calcWidth (style->minWidth, refWidth, refWidget,
1009 limitMinWidth, forceValue);
1010 int maxWidth = calcWidth (style->maxWidth, refWidth, refWidget,
1011 limitMinWidth, forceValue);
1012
1013 DBG_OBJ_MSGF ("resize", 1, "minWidth = %d, maxWidth = %d",
1014 minWidth, maxWidth);
1015
1016 if (minWidth != -1 && maxWidth != -1) {
1017 /* Prefer the maximum size for pathological cases (min > max) */
1018 if (maxWidth < minWidth)
1019 maxWidth = minWidth;
1020 }
1021
1022 if (minWidth != -1 && w < minWidth)
1023 w = minWidth;
1024
1025 if (maxWidth != -1 && w > maxWidth)
1026 w = maxWidth;
1027 }
1028
1029 /* Check postcondition: *finalWidth != -1 (implies) w != -1 */
1030 assert(!(*finalWidth != -1 && w == -1));
1031
1032 *finalWidth = w;
1033
1034 DBG_OBJ_LEAVE_VAL ("%d", *finalWidth);
1035}
1036
1037int Widget::calcHeight (style::Length cssValue, bool usePercentage,
1038 int refHeight, Widget *refWidget, bool forceValue)
1039{
1040 // TODO Search for usage of this method and check the value of
1041 // "usePercentage"; this has to be clarified.
1042
1043 DBG_OBJ_ENTER ("resize", 0, "calcHeight", "0x%x, %s, %d, %p",
1044 cssValue, usePercentage ? "true" : "false", refHeight,
1045 refWidget);
1046
1047 assert (refHeight != -1 || refWidget != NULL);
1048
1049 int height;
1050
1051 if (style::isAbsLength (cssValue)) {
1052 DBG_OBJ_MSGF ("resize", 1, "absolute height: %dpx",
1053 style::absLengthVal (cssValue));
1054 height =
1055 misc::max (style::absLengthVal (cssValue) + boxDiffHeight (), 0);
1056 } else if (style::isPerLength (cssValue)) {
1057 DBG_OBJ_MSGF ("resize", 1, "percentage height: %g%%",
1058 100 *
1060 if (usePercentage) {
1061 if (refHeight != -1)
1062 height = misc::max (applyPerHeight (refHeight, cssValue), 0);
1063 else {
1064 int availHeight = refWidget->getAvailHeight (forceValue);
1065 if (availHeight != -1) {
1066 int containerHeight = availHeight - refWidget->boxDiffHeight ();
1067 height =
1068 misc::max (applyPerHeight (containerHeight, cssValue), 0);
1069 } else
1070 height = -1;
1071 }
1072 } else
1073 height = -1;
1074 } else {
1075 DBG_OBJ_MSG ("resize", 1, "not specified");
1076 height = -1;
1077 }
1078
1079 DBG_OBJ_LEAVE_VAL ("%d", height);
1080 return height;
1081}
1082
1083void Widget::adjustHeight (int *height, bool allowDecreaseHeight, int ascent,
1084 int descent)
1085{
1086 if (!allowDecreaseHeight && *height != -1 && *height < ascent + descent)
1087 *height = ascent + descent;
1088}
1089
1093void Widget::getExtremes (Extremes *extremes, int numPos, Widget **references,
1094 int *x, int *y)
1095{
1096 assert (!queueResizeEntered ());
1097
1098 DBG_OBJ_ENTER ("resize", 0, "getExtremes", "%d, ...", numPos);
1099
1101
1102 if (extremesQueued ()) {
1103 // This method is called outside of Layout::resizeIdle.
1106 // The widget is not taken out of Layout::queueResizeList, since
1107 // other *_QUEUED flags may still be set and processed in
1108 // Layout::resizeIdle.
1109 }
1110
1111 bool callImpl;
1112 if (extremesChanged ())
1113 callImpl = true;
1114 else {
1115 // Even if EXTREMES_QUEUED / EXTREMES_CHANGED is not set, calling
1116 // getExtremesImpl is necessary when the relavive positions passed here
1117 // have changed.
1118 SizeParams newParams (numPos, references, x, y);
1119 DBG_OBJ_ASSOC_CHILD (&newParams);
1120 if (newParams.isEquivalent (&extremesParams))
1121 callImpl = false;
1122 else {
1123 callImpl = true;
1124 extremesParams = newParams;
1125 }
1126 }
1127
1128 if (callImpl) {
1129 // For backward compatibility (part 1/2):
1131
1132 getExtremesImpl (extremes, numPos, references, x, y);
1133
1134 // For backward compatibility (part 2/2):
1135 if (extremes->minWidthIntrinsic == -1)
1137 if (extremes->maxWidthIntrinsic == -1)
1139
1140 this->extremes = *extremes;
1142
1143 DBG_OBJ_SET_NUM ("extremes.minWidth", extremes->minWidth);
1144 DBG_OBJ_SET_NUM ("extremes.minWidthIntrinsic",
1146 DBG_OBJ_SET_NUM ("extremes.maxWidth", extremes->maxWidth);
1147 DBG_OBJ_SET_NUM ("extremes.maxWidthIntrinsic",
1149 DBG_OBJ_SET_NUM ("extremes.adjustmentWidth", extremes->adjustmentWidth);
1150 } else
1151 *extremes = this->extremes;
1152
1154
1155 DBG_OBJ_LEAVE ();
1156}
1157
1164void Widget::calcExtraSpace (int numPos, Widget **references, int *x, int *y)
1165{
1166 DBG_OBJ_ENTER0 ("resize", 0, "calcExtraSpace");
1167
1169 calcExtraSpaceImpl (numPos, references, x, y);
1170
1171 DBG_OBJ_SET_NUM ("extraSpace.top", extraSpace.top);
1172 DBG_OBJ_SET_NUM ("extraSpace.bottom", extraSpace.bottom);
1173 DBG_OBJ_SET_NUM ("extraSpace.left", extraSpace.left);
1174 DBG_OBJ_SET_NUM ("extraSpace.right", extraSpace.right);
1175
1176 DBG_OBJ_LEAVE ();
1177}
1178
1180{
1181 return 0;
1182}
1183
1185{
1186 misc::notImplemented ("Widget::sizeRequestReference");
1187 return NULL;
1188}
1189
1191{
1192 return 0;
1193}
1194
1196{
1197 misc::notImplemented ("Widget::getExtremesReference");
1198 return NULL;
1199}
1200
1210{
1211 assert (!queueResizeEntered ());
1212 assert (!sizeRequestEntered ());
1213 assert (!getExtremesEntered ());
1214 assert (resizeIdleEntered ());
1215
1216 DBG_OBJ_ENTER ("resize", 0, "sizeAllocate", "%d, %d; %d * (%d + %d)",
1219
1220 DBG_OBJ_MSGF ("resize", 1,
1221 "old allocation (%d, %d; %d * (%d + %d)); needsAllocate: %s",
1222 this->allocation.x, this->allocation.y, this->allocation.width,
1223 this->allocation.ascent, this->allocation.descent,
1224 needsAllocate () ? "true" : "false");
1225
1227
1228 /*printf ("The %stop-level %s %p is allocated:\n",
1229 parent ? "non-" : "", getClassName(), this);
1230 printf (" old = (%d, %d, %d + (%d + %d))\n",
1231 this->allocation.x, this->allocation.y, this->allocation.width,
1232 this->allocation.ascent, this->allocation.descent);
1233 printf (" new = (%d, %d, %d + (%d + %d))\n",
1234 allocation->x, allocation->y, allocation->width, allocation->ascent,
1235 allocation->descent);
1236 printf (" NEEDS_ALLOCATE = %s\n", needsAllocate () ? "true" : "false");*/
1237
1238 if (needsAllocate () ||
1239 allocation->x != this->allocation.x ||
1240 allocation->y != this->allocation.y ||
1241 allocation->width != this->allocation.width ||
1242 allocation->ascent != this->allocation.ascent ||
1243 allocation->descent != this->allocation.descent) {
1244
1245 if (wasAllocated ()) {
1247 this->allocation.x,
1248 this->allocation.y,
1249 this->allocation.width,
1250 this->allocation.ascent + this->allocation.descent,
1251 allocation->x,
1252 allocation->y,
1255 }
1256
1258
1259 //DEBUG_MSG (DEBUG_ALLOC, "... to %d, %d, %d x %d x %d\n",
1260 // widget->allocation.x, widget->allocation.y,
1261 // widget->allocation.width, widget->allocation.ascent,
1262 // widget->allocation.descent);
1263
1264 this->allocation = *allocation;
1267
1268 resizeDrawImpl ();
1269
1270 DBG_OBJ_SET_NUM ("allocation.x", this->allocation.x);
1271 DBG_OBJ_SET_NUM ("allocation.y", this->allocation.y);
1272 DBG_OBJ_SET_NUM ("allocation.width", this->allocation.width);
1273 DBG_OBJ_SET_NUM ("allocation.ascent", this->allocation.ascent);
1274 DBG_OBJ_SET_NUM ("allocation.descent", this->allocation.descent);
1275 }
1276
1277 /*unsetFlags (NEEDS_RESIZE);*/
1278
1280
1281 DBG_OBJ_LEAVE ();
1282}
1283
1285{
1286 return buttonPressImpl (event);
1287}
1288
1290{
1291 return buttonReleaseImpl (event);
1292}
1293
1295{
1296 return motionNotifyImpl (event);
1297}
1298
1300{
1301 enterNotifyImpl (event);
1302}
1303
1305{
1306 leaveNotifyImpl (event);
1307}
1308
1317{
1318 bool sizeChanged;
1319
1320 if (widgetImgRenderer && this->style && this->style->backgroundImage)
1323
1324 style->ref ();
1325
1326 if (this->style) {
1327 sizeChanged = this->style->sizeDiffs (style);
1328 this->style->unref ();
1329 } else
1330 sizeChanged = true;
1331
1332 this->style = style;
1333
1335
1336 if (style && style->backgroundImage) {
1337 // Create instance of WidgetImgRenderer when needed. Until this
1338 // widget is deleted, "widgetImgRenderer" will be kept, since it
1339 // is not specific to the style, but only to this widget.
1340 if (widgetImgRenderer == NULL)
1343 }
1344
1345 if (layout != NULL) {
1346 layout->updateCursor ();
1347 }
1348
1349 // After Layout::addWidget() (as toplevel widget) or Widget::setParent()
1350 // (which also sets layout), changes of the style cannot be considered
1351 // anymore. (Should print a warning?)
1352 if (layout == NULL &&
1356 stackingContextWidget = this;
1357 }
1358
1359 if (sizeChanged)
1360 queueResize (0, true);
1361 else
1362 queueDraw ();
1363
1364 // These should better be attributed to the style itself, and a
1365 // script processing RTFL messages could transfer it to something
1366 // equivalent:
1367
1368 DBG_OBJ_SET_NUM ("style.margin.top", style->margin.top);
1369 DBG_OBJ_SET_NUM ("style.margin.bottom", style->margin.bottom);
1370 DBG_OBJ_SET_NUM ("style.margin.left", style->margin.left);
1371 DBG_OBJ_SET_NUM ("style.margin.right", style->margin.right);
1372
1373 DBG_OBJ_SET_NUM ("style.border-width.top", style->borderWidth.top);
1374 DBG_OBJ_SET_NUM ("style.border-width.bottom", style->borderWidth.bottom);
1375 DBG_OBJ_SET_NUM ("style.border-width.left", style->borderWidth.left);
1376 DBG_OBJ_SET_NUM ("style.border-width.right", style->borderWidth.right);
1377
1378 DBG_OBJ_SET_NUM ("style.padding.top", style->padding.top);
1379 DBG_OBJ_SET_NUM ("style.padding.bottom", style->padding.bottom);
1380 DBG_OBJ_SET_NUM ("style.padding.left", style->padding.left);
1381 DBG_OBJ_SET_NUM ("style.padding.right", style->padding.right);
1382
1383 DBG_OBJ_SET_NUM ("style.border-spacing (h)", style->hBorderSpacing);
1384 DBG_OBJ_SET_NUM ("style.border-spacing (v)", style->vBorderSpacing);
1385
1386 DBG_OBJ_SET_SYM ("style.display",
1387 style->display == style::DISPLAY_BLOCK ? "block" :
1388 style->display == style::DISPLAY_INLINE ? "inline" :
1390 "inline-block" :
1391 style->display == style::DISPLAY_LIST_ITEM ? "list-item" :
1392 style->display == style::DISPLAY_NONE ? "none" :
1393 style->display == style::DISPLAY_TABLE ? "table" :
1395 "table-row-group" :
1397 "table-header-group" :
1399 "table-footer-group" :
1400 style->display == style::DISPLAY_TABLE_ROW ? "table-row" :
1401 style->display == style::DISPLAY_TABLE_CELL ? "table-cell" :
1402 "???");
1403
1404 DBG_OBJ_SET_NUM ("style.width (raw)", style->width);
1405 DBG_OBJ_SET_NUM ("style.min-width (raw)", style->minWidth);
1406 DBG_OBJ_SET_NUM ("style.max-width (raw)", style->maxWidth);
1407 DBG_OBJ_SET_NUM ("style.height (raw)", style->height);
1408 DBG_OBJ_SET_NUM ("style.min-height (raw)", style->minHeight);
1409 DBG_OBJ_SET_NUM ("style.max-height (raw)", style->maxHeight);
1410
1412 DBG_OBJ_SET_COL ("style.background-color",
1414 else
1415 DBG_OBJ_SET_SYM ("style.background-color", "transparent");
1416}
1417
1424{
1425 this->bgColor = bgColor;
1426}
1427
1432{
1433 Widget *widget = this;
1434
1435 while (widget != NULL) {
1436 if (widget->style->backgroundColor)
1437 return widget->style->backgroundColor;
1438 if (widget->bgColor)
1439 return widget->bgColor;
1440
1441 widget = widget->parent;
1442 }
1443
1444 return layout->getBgColor ();
1445}
1446
1451{
1452 Widget *widget = this;
1453
1454 while (widget != NULL) {
1455 if (widget->style->color)
1456 return widget->style->color;
1457
1458 widget = widget->parent;
1459 }
1460
1461 return NULL;
1462}
1463
1464
1472 int x, int y, int width, int height, bool inverse)
1473{
1474 Rectangle canvasArea;
1475 canvasArea.x = area->x + allocation.x;
1476 canvasArea.y = area->y + allocation.y;
1477 canvasArea.width = area->width;
1478 canvasArea.height = area->height;
1479
1480 style::drawBorder (view, layout, &canvasArea,
1481 allocation.x + x, allocation.y + y,
1482 width, height, style, inverse);
1483
1484 // This method is used for inline elements, where the CSS 2 specification
1485 // does not define what here is called "reference area". To make it look
1486 // smoothly, the widget padding box is used.
1487
1488 // TODO Handle inverse drawing the same way as in drawWidgetBox?
1489 // Maybe this method (drawBox) is anyway obsolete when extraSpace
1490 // is fully supported (as here, in the "dillo_grows" repository).
1491
1492 int xPad, yPad, widthPad, heightPad;
1493 getPaddingArea (&xPad, &yPad, &widthPad, &heightPad);
1495 (view, layout, &canvasArea,
1500 height - style->margin.top - style->borderWidth.top
1502 xPad, yPad, widthPad, heightPad, style, style->backgroundColor,
1503 inverse, false);
1504}
1505
1512void Widget::drawWidgetBox (View *view, Rectangle *area, bool inverse)
1513{
1514 Rectangle canvasArea;
1515 canvasArea.x = area->x + allocation.x;
1516 canvasArea.y = area->y + allocation.y;
1517 canvasArea.width = area->width;
1518 canvasArea.height = area->height;
1519
1520 int xMar, yMar, widthMar, heightMar;
1521 getMarginArea (&xMar, &yMar, &widthMar, &heightMar);
1522 style::drawBorder (view, layout, &canvasArea, xMar, yMar, widthMar,
1523 heightMar, style, inverse);
1524
1525 int xPad, yPad, widthPad, heightPad;
1526 getPaddingArea (&xPad, &yPad, &widthPad, &heightPad);
1527
1529 if (inverse && style->backgroundColor == NULL) {
1530 // See style::drawBackground: for inverse drawing, we need a
1531 // defined background color. Search through ancestors.
1532 Widget *w = this;
1533 while (w != NULL && w->style->backgroundColor == NULL)
1534 w = w->parent;
1535
1536 if (w != NULL && w->style->backgroundColor != NULL)
1538 else
1540 } else
1542
1543 style::drawBackground (view, layout, &canvasArea,
1544 xPad, yPad, widthPad, heightPad,
1545 xPad, yPad, widthPad, heightPad,
1546 style, bgColor, inverse, parent == NULL);
1547}
1548
1549/*
1550 * This function is used by some widgets, when they are selected (as a whole).
1551 *
1552 * \todo This could be accelerated by using clipping bitmaps. Two important
1553 * issues:
1554 *
1555 * (i) There should always been a pixel in the upper-left corner of the
1556 * *widget*, so probably two different clipping bitmaps have to be
1557 * used (10/01 and 01/10).
1558 *
1559 * (ii) Should a new GC always be created?
1560 *
1561 * \bug Not implemented.
1562 */
1564{
1565}
1566
1567
1569{
1570 this->buttonSensitive = buttonSensitive;
1571 buttonSensitiveSet = true;
1572}
1573
1574
1579{
1580 Widget *widget = this;
1581
1582 while (widget->parent)
1583 widget = widget->parent;
1584
1585 return widget;
1586}
1587
1594{
1595 Widget *widget = this;
1596 int level = 0;
1597
1598 while (widget->parent) {
1599 level++;
1600 widget = widget->parent;
1601 }
1602
1603 return level;
1604}
1605
1613{
1614 Widget *widget = this;
1615 int level = 0;
1616
1617 while (widget->getGenerator ()) {
1618 level++;
1619 widget = widget->getGenerator ();
1620 }
1621
1622 return level;
1623}
1624
1630{
1631 Widget *widget1 = this, *widget2 = otherWidget;
1632 int level1 = widget1->getLevel (), level2 = widget2->getLevel();
1633
1634 /* Get both widgets onto the same level.*/
1635 while (level1 > level2) {
1636 widget1 = widget1->parent;
1637 level1--;
1638 }
1639
1640 while (level2 > level1) {
1641 widget2 = widget2->parent;
1642 level2--;
1643 }
1644
1645 /* Search upwards. */
1646 while (widget1 != widget2) {
1647 if (widget1->parent == NULL) {
1648 MSG_WARN("widgets in different trees\n");
1649 return NULL;
1650 }
1651
1652 widget1 = widget1->parent;
1653 widget2 = widget2->parent;
1654 }
1655
1656 return widget1;
1657}
1658
1660 int x, int y, int width, int height)
1661{
1662 layout->scrollTo (hpos, vpos,
1663 x + allocation.x, y + allocation.y, width, height);
1664}
1665
1666void Widget::getMarginArea (int *xMar, int *yMar, int *widthMar, int *heightMar)
1667{
1668 *xMar = allocation.x + extraSpace.left;
1669 *yMar = allocation.y + extraSpace.top;
1670 *widthMar = allocation.width - (extraSpace.left + extraSpace.right);
1671 *heightMar = getHeight () - (extraSpace.top + extraSpace.bottom);
1672}
1673
1674void Widget::getBorderArea (int *xBor, int *yBor, int *widthBor, int *heightBor)
1675{
1676 getMarginArea (xBor, yBor, widthBor, heightBor);
1677
1678 *xBor += style->margin.left;
1679 *yBor += style->margin.top;
1680 *widthBor -= style->margin.left + style->margin.right;
1681 *heightBor -= style->margin.top + style->margin.bottom;
1682}
1683
1690void Widget::getPaddingArea (int *xPad, int *yPad, int *widthPad,
1691 int *heightPad)
1692{
1693 getBorderArea (xPad, yPad, widthPad, heightPad);
1694
1695 *xPad += style->borderWidth.left;
1696 *yPad += style->borderWidth.top;
1697 *widthPad -= style->borderWidth.left + style->borderWidth.right;
1698 *heightPad -= style->borderWidth.top + style->borderWidth.bottom;
1699}
1700
1702 Widget **references, int *x, int *y)
1703{
1704 // Use the simple variant.
1705 DBG_OBJ_ENTER0 ("resize", 0, "Widget::sizeRequestImpl");
1707 DBG_OBJ_LEAVE ();
1708}
1709
1711{
1712 // Either variant should be implemented.
1713 misc::notImplemented ("Widget::sizeRequestSimpl");
1714}
1715
1717 Widget **references, int *x, int *y)
1718{
1719 // Use the simple variant.
1720 DBG_OBJ_ENTER0 ("resize", 0, "Widget::getExtremesImpl");
1722 DBG_OBJ_LEAVE ();
1723}
1724
1726{
1727 // Either variant should be implemented.
1728 misc::notImplemented ("Widget::getExtremesSimpl");
1729}
1730
1734
1744void Widget::calcExtraSpaceImpl (int numPos, Widget **references, int *x,
1745 int *y)
1746{
1747}
1748
1750{
1751}
1752
1754{
1755}
1756
1757int Widget::applyPerWidth (int containerWidth, style::Length perWidth)
1758{
1759 return style::multiplyWithPerLength (containerWidth, perWidth)
1760 + boxDiffWidth ();
1761}
1762
1763int Widget::applyPerHeight (int containerHeight, style::Length perHeight)
1764{
1765 return style::multiplyWithPerLength (containerHeight, perHeight)
1766 + boxDiffHeight ();
1767}
1768
1779int Widget::getAvailWidthOfChild (Widget *child, bool forceValue)
1780{
1781 // This is a halfway suitable implementation for all
1782 // containers. For simplification, this will be used during the
1783 // development; then, a differentiation could be possible.
1784
1785 DBG_OBJ_ENTER ("resize", 0, "getAvailWidthOfChild", "%p, %s",
1786 child, forceValue ? "true" : "false");
1787
1788 int width;
1789
1790 if (child->getStyle()->width == style::LENGTH_AUTO) {
1791 DBG_OBJ_MSG ("resize", 1, "no specification");
1792
1793 /* We only compute when forceValue is true */
1794 if (forceValue) {
1795 width = misc::max (getAvailWidth (true) - boxDiffWidth (), 0);
1796
1797 if (width != -1) {
1798 /* Clamp to min-width and max-width if given */
1799 int maxWidth = child->calcWidth (child->getStyle()->maxWidth,
1800 -1, this, -1, false);
1801 if (maxWidth != -1 && width > maxWidth)
1802 width = maxWidth;
1803
1804 int minWidth = child->calcWidth (child->getStyle()->minWidth,
1805 -1, this, -1, false);
1806 if (minWidth != -1 && width < minWidth)
1807 width = minWidth;
1808 }
1809
1810 } else {
1811 width = -1;
1812 }
1813 } else {
1814 // In most cases, the toplevel widget should be a container, so
1815 // the container is non-NULL when the parent is non-NULL. Just
1816 // in case, regard also parent. And quasiParent.
1817 Widget *effContainer = child->quasiParent ? child->quasiParent :
1818 (child->container ? child->container : child->parent);
1819
1820 if (effContainer == this) {
1821 width = -1;
1822 child->calcFinalWidth (child->getStyle(), -1, this, 0, forceValue,
1823 &width);
1824 } else {
1825 DBG_OBJ_MSG ("resize", 1, "delegated to (effective) container");
1827 width = effContainer->getAvailWidthOfChild (child, forceValue);
1828 DBG_OBJ_MSG_END ();
1829 }
1830 }
1831
1832 DBG_OBJ_LEAVE_VAL ("%d", width);
1833 return width;
1834}
1835
1836int Widget::getAvailHeightOfChild (Widget *child, bool forceValue)
1837{
1838 // Again, a suitable implementation for all widgets (perhaps).
1839
1840 // TODO Consider 'min-height' and 'max-height'. (Minor priority, as long as
1841 // "getAvailHeight (true)" is not used.
1842
1843 DBG_OBJ_ENTER ("resize", 0, "getAvailHeightOfChild", "%p, %s",
1844 child, forceValue ? "true" : "false");
1845
1846 int height;
1847
1848 if (child->getStyle()->height == style::LENGTH_AUTO) {
1849 DBG_OBJ_MSG ("resize", 1, "no specification");
1850 if (forceValue)
1851 height = misc::max (getAvailHeight (true) - boxDiffHeight (), 0);
1852 else
1853 height = -1;
1854 } else {
1855 // See comment in Widget::getAvailWidthOfChild.
1856 Widget *effContainer = child->quasiParent ? child->quasiParent :
1857 (child->container ? child->container : child->parent);
1858
1859 if (effContainer == this) {
1860 if (style::isAbsLength (child->getStyle()->height)) {
1861 DBG_OBJ_MSGF ("resize", 1, "absolute height: %dpx",
1862 style::absLengthVal (child->getStyle()->height));
1863 height = misc::max (style::absLengthVal (child->getStyle()->height)
1864 + child->boxDiffHeight (), 0);
1865 } else {
1866 assert (style::isPerLength (child->getStyle()->height));
1867 DBG_OBJ_MSGF ("resize", 1, "percentage height: %g%%",
1869 (child->getStyle()->height));
1870
1871 int availHeight = getAvailHeight (forceValue);
1872 if (availHeight == -1)
1873 height = -1;
1874 else
1875 height =
1876 misc::max (child->applyPerHeight (availHeight -
1877 boxDiffHeight (),
1878 child->getStyle()->height),
1879 0);
1880 }
1881 } else {
1882 DBG_OBJ_MSG ("resize", 1, "delegated to (effective) container");
1884 height = effContainer->getAvailHeightOfChild (child, forceValue);
1885 DBG_OBJ_MSG_END ();
1886 }
1887 }
1888
1889 DBG_OBJ_LEAVE_VAL ("%d", height);
1890 return height;
1891}
1892
1894 void (*splitHeightFun) (int, int*,
1895 int*),
1896 bool allowDecreaseWidth,
1897 bool allowDecreaseHeight)
1898{
1899 // Again, a suitable implementation for all widgets (perhaps).
1900
1901 DBG_OBJ_ENTER ("resize", 0, "correctRequisitionOfChild",
1902 "%p, %d * (%d + %d), ..., %s, %s", child, requisition->width,
1904 misc::boolToStr (allowDecreaseWidth),
1905 misc::boolToStr (allowDecreaseHeight));
1906
1907 // See comment in Widget::getAvailWidthOfChild.
1908 Widget *effContainer = child->quasiParent ? child->quasiParent :
1909 (child->container ? child->container : child->parent);
1910
1911 if (effContainer == this) {
1912 /* Try several passes before giving up */
1913 for (int pass = 0; pass < 3; pass++) {
1914 correctReqWidthOfChild (child, requisition, allowDecreaseWidth);
1915 correctReqHeightOfChild (child, requisition, splitHeightFun,
1916 allowDecreaseHeight);
1917 bool changed = correctReqAspectRatio (pass, child, requisition,
1918 allowDecreaseWidth, allowDecreaseHeight, splitHeightFun);
1919
1920 /* No need to repeat more passes */
1921 if (!changed)
1922 break;
1923 }
1924 } else {
1925 DBG_OBJ_MSG ("resize", 1, "delegated to (effective) container");
1927 effContainer->correctRequisitionOfChild (child, requisition,
1928 splitHeightFun,
1929 allowDecreaseWidth,
1930 allowDecreaseHeight);
1931 DBG_OBJ_MSG_END ();
1932 }
1933
1936}
1937
1959 bool allowDecreaseWidth, bool allowDecreaseHeight,
1960 void (*splitHeightFun) (int, int*, int*))
1961{
1962 /* Only correct the requisition if both dimensions are set, otherwise is left
1963 * to the child how to proceed. */
1964 int wReq = requisition->width;
1965 int hReq = requisition->ascent + requisition->descent;
1966
1967 /* Prevent division by 0 */
1968 bool sizeSet = wReq > 0 && hReq > 0;
1969
1970 float ratio = child->ratio;
1971 bool changed = false;
1972
1973 DEBUG_MSG(1, "Widget::correctReqAspectRatio() -- wReq=%d, hReq=%d, pass=%d\n",
1974 wReq, hReq, pass);
1975
1976 DEBUG_MSG(1, "Widget::correctReqAspectRatio() -- border: w=%d, h=%d\n",
1977 child->boxDiffWidth(), child->boxDiffHeight());
1978
1979 wReq -= child->boxDiffWidth();
1980 hReq -= child->boxDiffHeight();
1981 DEBUG_MSG(1, "Widget::correctReqAspectRatio() -- with border: wReq=%d, hReq=%d\n",
1982 wReq, hReq);
1983 DEBUG_MSG(1, "child=%s, preferred ratio=%f\n", child->getClassName(), ratio);
1984
1985 if (pass != PASS_KEEP && ratio > 0.0 && sizeSet) {
1986 /* Compute the current ratio from the content box. */
1987 float curRatio = (float) wReq / (float) hReq;
1988 DEBUG_MSG(1, "curRatio=%f, preferred ratio=%f\n", curRatio, ratio);
1989
1990 if (curRatio < ratio) {
1991 /* W is too small compared to H. Try to increase W or decrease H. */
1992 if (pass == PASS_INCREASE) {
1993 /* Increase w */
1994 int w = (float) hReq * ratio;
1995 DEBUG_MSG(1, "increase w: %d -> %d\n", wReq, w);
1996 w += child->boxDiffWidth();
1997 DEBUG_MSG(1, "increase w (with border): %d -> %d\n", wReq, w);
1998 requisition->width = w;
1999 changed = true;
2000 } else if (pass == PASS_DECREASE) {
2001 /* Decrease h */
2002 if (allowDecreaseHeight) {
2003 /* FIXME: This may lose cases where allowDecreaseHeight is false, and
2004 * the requisition has increased the height first, but we could still
2005 * reduce the corrected hight above the original height, without
2006 * making the requisition height smaller. */
2007 int h = (float) wReq / ratio;
2008 DEBUG_MSG(1, "decrease h: %d -> %d\n", hReq, h);
2009 h += child->boxDiffHeight();
2010 DEBUG_MSG(1, "decrease h (with border): %d -> %d\n", hReq, h);
2011 splitHeightFun (h, &requisition->ascent, &requisition->descent);
2012 changed = true;
2013 }
2014 }
2015 } else if (curRatio > ratio) {
2016 /* W is too big compared to H. Try to decrease W or increase H. */
2017 if (pass == PASS_INCREASE) {
2018 /* Increase h */
2019 int h = (float) wReq / ratio;
2020 DEBUG_MSG(1, "increase h: %d -> %d\n", hReq, h);
2021 h += child->boxDiffHeight();
2022 DEBUG_MSG(1, "increase h (width border): %d -> %d\n", hReq, h);
2023 splitHeightFun (h, &requisition->ascent, &requisition->descent);
2024 changed = true;
2025 } else if (pass == PASS_DECREASE) {
2026 /* Decrease w */
2027 if (allowDecreaseWidth) {
2028 /* FIXME: This may lose cases where allowDecreaseWidth is false, and
2029 * the requisition has increased the width first, but we could still
2030 * reduce the corrected width above the original width, without
2031 * making the requisition width smaller. */
2032 int w = (float) hReq * ratio;
2033 DEBUG_MSG(1, "decrease w: %d -> %d\n", wReq, w);
2034 w += child->boxDiffWidth();
2035 DEBUG_MSG(1, "decrease w (width border): %d -> %d\n", wReq, w);
2036 requisition->width = w;
2037 changed = true;
2038 }
2039 }
2040 } else {
2041 /* Current ratio is the preferred one. */
2042 }
2043 }
2044
2045 DEBUG_MSG(1, "Widget::correctReqAspectRatio() -- output: wReq=%d, hReq=%d, changed=%d\n",
2047
2048 return changed;
2049}
2050
2057 bool allowDecreaseWidth)
2058{
2059 DBG_OBJ_ENTER ("resize", 0, "correctReqWidthOfChild",
2060 "%p, %d * (%d + %d), %s",
2062 requisition->descent, misc::boolToStr (allowDecreaseWidth));
2063
2064 assert (this == child->quasiParent || this == child->container);
2065
2066 int limitMinWidth = child->getMinWidth (NULL, true);
2067 if (!allowDecreaseWidth && limitMinWidth < requisition->width)
2068 limitMinWidth = requisition->width;
2069
2070 child->calcFinalWidth (child->getStyle(), -1, this, limitMinWidth, true,
2071 &requisition->width);
2072
2075}
2076
2078 void (*splitHeightFun) (int, int*, int*),
2079 bool allowDecreaseHeight)
2080{
2081 // TODO Correct height by extremes? (Height extemes?)
2082
2083 assert (this == child->quasiParent || this == child->container);
2084
2085 DBG_OBJ_ENTER ("resize", 0, "correctReqHeightOfChild",
2086 "%p, %d * (%d + %d), ..., %s", child, requisition->width,
2088 misc::boolToStr (allowDecreaseHeight));
2089
2090 int height = child->calcHeight (child->getStyle()->height, true, -1, this,
2091 false);
2092 adjustHeight (&height, allowDecreaseHeight, requisition->ascent,
2094
2095 int minHeight = child->calcHeight (child->getStyle()->minHeight, true, -1,
2096 this, false);
2097 int maxHeight = child->calcHeight (child->getStyle()->maxHeight, true, -1,
2098 this, false);
2099
2100 if (minHeight != -1 && maxHeight != -1) {
2101 /* Prefer the maximum size for pathological cases (min > max) */
2102 if (maxHeight < minHeight)
2103 maxHeight = minHeight;
2104 }
2105
2106 adjustHeight (&minHeight, allowDecreaseHeight, requisition->ascent,
2108
2109 adjustHeight (&maxHeight, allowDecreaseHeight, requisition->ascent,
2111
2112 // TODO Perhaps split first, then add box ascent and descent.
2113 if (height != -1)
2114 splitHeightFun (height, &requisition->ascent, &requisition->descent);
2115 if (minHeight != -1 &&
2116 requisition->ascent + requisition->descent < minHeight)
2117 splitHeightFun (minHeight, &requisition->ascent,
2119 if (maxHeight != -1 &&
2120 requisition->ascent + requisition->descent > maxHeight)
2121 splitHeightFun (maxHeight, &requisition->ascent,
2123
2126}
2127
2129 bool useAdjustmentWidth)
2130{
2131 // See comment in correctRequisitionOfChild.
2132
2133 DBG_OBJ_ENTER ("resize", 0, "correctExtremesOfChild",
2134 "%p, %d (%d) / %d (%d)",
2137
2138 // See comment in Widget::getAvailWidthOfChild.
2139 Widget *effContainer = child->quasiParent ? child->quasiParent :
2140 (child->container ? child->container : child->parent);
2141
2142 if (effContainer == this) {
2143 int limitMinWidth =
2144 useAdjustmentWidth ? child->getMinWidth (extremes, false) : 0;
2145 int width = child->calcWidth (child->getStyle()->width, -1, this,
2146 limitMinWidth, false);
2147 int minWidth = child->calcWidth (child->getStyle()->minWidth, -1, this,
2148 limitMinWidth, false);
2149 int maxWidth = child->calcWidth (child->getStyle()->maxWidth, -1, this,
2150 limitMinWidth, false);
2151
2152 DBG_OBJ_MSGF ("resize", 1, "width = %d, minWidth = %d, maxWidth = %d",
2153 width, minWidth, maxWidth);
2154
2155 if (width != -1)
2156 extremes->minWidth = extremes->maxWidth = width;
2157 if (minWidth != -1)
2158 extremes->minWidth = minWidth;
2159 if (maxWidth != -1)
2160 extremes->maxWidth = maxWidth;
2161 } else {
2162 DBG_OBJ_MSG ("resize", 1, "delegated to (effective) container");
2164 effContainer->correctExtremesOfChild (child, extremes,
2165 useAdjustmentWidth);
2166 DBG_OBJ_MSG_END ();
2167 }
2168
2169
2171}
2172
2182
2189{
2190}
2191
2193{
2194 // Most widgets are not block-level.
2195 return false;
2196}
2197
2199{
2200 // In most (all?) cases identical to:
2201 return isBlockLevel ();
2202}
2203
2205{
2206 return false;
2207}
2208
2210{
2211 return false;
2212}
2213
2215{
2216 return false;
2217}
2218
2220{
2221 style::Tooltip *tooltip = getStyle()->x_tooltip;
2222
2223 if (tooltip)
2224 tooltip->onEnter();
2225}
2226
2228{
2229 style::Tooltip *tooltip = getStyle()->x_tooltip;
2230
2231 if (tooltip)
2232 tooltip->onLeave();
2233}
2234
2235
2237{
2238 // Should be implemented.
2239 misc::notImplemented ("Widget::removeChild");
2240}
2241
2242// ----------------------------------------------------------------------
2243
2244void splitHeightPreserveAscent (int height, int *ascent, int *descent)
2245{
2246 DBG_OBJ_ENTER_S ("resize", 1, "splitHeightPreserveAscent", "%d, %d, %d",
2247 height, *ascent, *descent);
2248
2249 *descent = height - *ascent;
2250 if (*descent < 0) {
2251 *descent = 0;
2252 *ascent = height;
2253 }
2254
2255 DBG_OBJ_LEAVE_VAL_S ("%d, %d", *ascent, *descent);
2256}
2257
2258void splitHeightPreserveDescent (int height, int *ascent, int *descent)
2259{
2260 DBG_OBJ_ENTER_S ("resize", 1, "splitHeightPreserveDescent", "%d, %d, %d",
2261 height, *ascent, *descent);
2262
2263 *ascent = height - *descent;
2264 if (*ascent < 0) {
2265 *ascent = 0;
2266 *descent = height;
2267 }
2268
2269 DBG_OBJ_LEAVE_VAL_S ("%d, %d", *ascent, *descent);
2270}
2271
2272} // namespace core
2273} // namespace dw
#define _MSG(...)
Definition bookmarks.c:45
Set at the top when drawing.
Definition types.hh:295
Rectangle * getToplevelArea()
Definition types.hh:304
Represents a button press or release event.
Definition events.hh:58
Represents a enter or leave notify event.
Definition events.hh:75
Represents a mouse motion event.
Definition events.hh:68
Set at the top when getting the widget at the point.
Definition types.hh:313
Iterators are used to iterate through the contents of a widget.
Definition iterator.hh:20
virtual void unref()
Delete the iterator.
Definition iterator.cc:82
virtual bool next()=0
Move iterator forward and store content it.
Content * getContent()
Definition iterator.hh:37
void queueDraw(int x, int y, int width, int height)
Definition layout.cc:991
style::Color * getBgColor()
Definition layout.hh:443
void queueDrawExcept(int x, int y, int width, int height, int ex, int ey, int ewidth, int eheight)
Definition layout.cc:1004
lout::container::typed::Vector< Widget > * queueResizeList
Definition layout.hh:158
int vScrollbarThickness
Definition layout.hh:173
void updateCursor()
Definition layout.cc:818
void removeWidget()
Definition layout.cc:406
Widget * topLevel
Definition layout.hh:157
void scrollTo(HPosition hpos, VPosition vpos, int x, int y, int width, int height)
Scrolls all viewports, so that the region [x, y, width, height] is seen, according to hpos and vpos.
Definition layout.cc:539
bool canvasHeightGreater
Definition layout.hh:172
void queueResize(bool extremesChanged)
Definition layout.cc:1027
dw::core::Shape implemtation for simple rectangles.
Definition types.hh:70
bool intersectsWith(Rectangle *otherRect, Rectangle *dest)
Return whether this rectangle and otherRect intersect.
Definition types.cc:53
Hold arguments passed to dw::core::Widget::sizeRequest and dw::core::Widget::getExtremes,...
Definition tools.hh:19
bool isEquivalent(SizeParams *other)
Compares two instances, but considers a change in the order of the reference widgets as equivalent.
Definition tools.cc:164
See Handling stacking contexts.
static bool isEstablishingStackingContext(Widget *widget)
void addChildSCWidget(Widget *widget)
void addWidgetProcessedAsInterruption(Widget *widget)
Definition types.hh:282
An interface to encapsulate platform dependent drawing.
Definition view.hh:17
Implementation which represents the whole widget.
Definition widget.hh:105
bool readyToDraw()
If this method returns false, nothing is done at all.
Definition widget.cc:45
style::Style * getStyle()
Return the style this background image is part of.
Definition widget.cc:62
void getBgArea(int *x, int *y, int *width, int *height)
Return the area covered by the background image.
Definition widget.cc:50
void getRefArea(int *xRef, int *yRef, int *widthRef, int *heightRef)
Return the "reference area".
Definition widget.cc:56
void draw(int x, int y, int width, int height)
Draw (or queue for drawing) an area, which is given in canvas coordinates.
Definition widget.cc:67
The base class of all dillo widgets.
Definition widget.hh:44
virtual void notifySetParent()
This method is called after a widget has been added to a parent.
Definition widget.cc:2188
virtual void setStyle(style::Style *style)
Change the style of a widget.
Definition widget.cc:1316
void leaveSizeRequest()
Definition widget.hh:452
WidgetImgRenderer * widgetImgRenderer
Definition widget.hh:119
virtual void leaveNotifyImpl(EventCrossing *event)
Definition widget.cc:2227
void sizeAllocate(Allocation *allocation)
Wrapper for Widget::sizeAllocateImpl, calls the latter only when needed.
Definition widget.cc:1209
bool queueResizeEntered()
Definition widget.hh:445
bool motionNotify(EventMotion *event)
Definition widget.cc:1294
void setWidgetReference(WidgetReference *widgetReference)
Definition widget.hh:595
Extremes extremes
Analogue to dw::core::Widget::requisition.
Definition widget.hh:166
Layout * layout
Definition widget.hh:216
Widget * container
The containing widget, equivalent to the "containing block" defined by CSS.
Definition widget.hh:146
void enterQueueResize()
Definition widget.hh:443
SizeParams requisitionParams
Definition widget.hh:161
virtual bool usesAvailWidth()
Must be implemengted by a method returning true, when getAvailWidth() is called.
Definition widget.cc:528
bool intersects(Widget *refWidget, Rectangle *area, Rectangle *intersection)
Calculates the intersection of the visible allocation (i.
Definition widget.cc:151
void setQuasiParent(Widget *quasiParent)
Definition widget.cc:288
Allocation allocation
The current allocation: size and position, always relative to the canvas.
Definition widget.hh:204
static void adjustHeight(int *height, bool allowDecreaseHeight, int ascent, int descent)
Definition widget.cc:1083
virtual bool affectedByContainerSizeChange()
Definition widget.cc:445
virtual Iterator * iterator(Content::Type mask, bool atEnd)=0
Return an iterator for this widget.
style::Color * getFgColor()
Get the actual foreground color of a widget.
Definition widget.cc:1450
void leaveGetExtremes()
Definition widget.hh:456
virtual void draw(View *view, Rectangle *area, DrawingContext *context)=0
Area is given in widget coordinates.
void setButtonSensitive(bool buttonSensitive)
Definition widget.cc:1568
virtual void markExtremesChange(int ref)
See Sizes of Dillo Widgets.
Definition widget.cc:1753
@ NEEDS_ALLOCATE
Only used internally, set to enforce size allocation.
Definition widget.hh:76
@ WAS_ALLOCATED
Set, when a widget was already once allocated,.
Definition widget.hh:96
@ EXTREMES_CHANGED
Set, when dw::core::Widget::extremes is not up to date anymore.
Definition widget.hh:89
@ NEEDS_RESIZE
Set, when dw::core::Widget::requisition is not up to date anymore.
Definition widget.hh:65
virtual int getAvailWidthOfChild(Widget *child, bool forceValue)
Computes the content width available of a child widget.
Definition widget.cc:1779
virtual bool affectsSizeChangeContainerChild(Widget *child)
Definition widget.cc:479
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
Widget * getParent()
Definition widget.hh:587
int boxDiffWidth()
Definition widget.hh:495
int parentRef
This value is defined by the parent widget, and used for incremential resizing.
Definition widget.hh:195
int getAvailWidth(bool forceValue)
Return available width including margin/border/padding (extraSpace?), not only the content width.
Definition widget.cc:665
bool sizeRequestEntered()
Definition widget.hh:453
void enterNotify(EventCrossing *event)
Definition widget.cc:1299
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
void drawWidgetBox(View *view, Rectangle *area, bool inverse)
Draw borders and background of a widget.
Definition widget.cc:1512
bool needsAllocate()
Definition widget.hh:472
void correctRequisition(Requisition *requisition, void(*splitHeightFun)(int, int *, int *), bool allowDecreaseWidth, bool allowDecreaseHeight)
Definition widget.cc:820
void drawSelected(View *view, Rectangle *area)
Definition widget.cc:1563
void calcExtraSpace(int numPos, Widget **references, int *x, int *y)
Calculates dw::core::Widget::extraSpace.
Definition widget.cc:1164
virtual bool getAdjustMinWidth()
Definition widget.hh:532
style::Style * getStyle()
Definition widget.hh:482
int getLevel()
Get the level of the widget within the tree.
Definition widget.cc:1593
bool resizeQueued()
Definition widget.hh:469
virtual void removeChild(Widget *child)
Definition widget.cc:2236
virtual bool motionNotifyImpl(EventMotion *event)
Definition widget.cc:2214
bool buttonRelease(EventButton *event)
Definition widget.cc:1289
Widget * stackingContextWidget
The bottom-most ancestor (or this) for which stackingContextMgr is set.
Definition widget.hh:238
virtual void notifySetAsTopLevel()
This method is called after a widget has been set as the top of a widget tree.
Definition widget.cc:2179
style::Color * bgColor
See dw::core::Widget::setBgColor().
Definition widget.hh:172
StackingContextMgr * stackingContextMgr
Set iff this widget constitutes a stacking context, as defined by CSS.
Definition widget.hh:232
Requisition requisition
Size_request() stores the result of the last call of size_request_impl().
Definition widget.hh:160
Widget * getGenerator()
Definition widget.hh:600
Widget * getWidgetAtPointInterrupted(int x, int y, GettingWidgetAtPointContext *context)
Definition widget.cc:234
virtual void enterNotifyImpl(EventCrossing *event)
Definition widget.cc:2219
style::Box extraSpace
Space around the margin box.
Definition widget.hh:226
int calcWidth(style::Length cssValue, int refWidth, Widget *refWidget, int limitMinWidth, bool forceValue)
Computes a width value in pixels from cssValue.
Definition widget.cc:932
virtual void getExtremesSimpl(Extremes *extremes)
Simple variant, to be implemented by widgets with extremes not depending on positions.
Definition widget.cc:1725
void queueDrawArea(int x, int y, int width, int height)
Definition widget.cc:297
virtual int getAvailHeightOfChild(Widget *child, bool forceValue)
Definition widget.cc:1836
bool resizeIdleEntered()
Definition widget.hh:441
bool inAllocation(int x, int y)
Definition widget.hh:485
virtual void correctRequisitionOfChild(Widget *child, Requisition *requisition, void(*splitHeightFun)(int, int *, int *), bool allowDecreaseWidth, bool allowDecreaseHeight)
Definition widget.cc:1893
Widget * getNearestCommonAncestor(Widget *otherWidget)
Get the widget with the highest level, which is a direct ancestor of widget1 and widget2.
Definition widget.cc:1629
virtual void sizeAllocateImpl(Allocation *allocation)
See Sizes of Dillo Widgets.
Definition widget.cc:1731
bool extremesQueued()
Definition widget.hh:470
bool extremesChanged()
Definition widget.hh:474
virtual void correctExtremesOfChild(Widget *child, Extremes *extremes, bool useAdjustmentWidth)
Definition widget.cc:2128
bool getExtremesEntered()
Definition widget.hh:457
Widget * generator
The generating widget, NULL for top-level widgets, or if not set; in the latter case,...
Definition widget.hh:139
virtual void sizeRequestSimpl(Requisition *requisition)
Simple variant, to be implemented by widgets with sizes not depending on positions.
Definition widget.cc:1710
void * deleteCallbackData
Definition widget.hh:433
int getMinWidth(Extremes *extremes, bool forceValue)
Used to evaluate Widget::adjustMinWidth.
Definition widget.cc:620
virtual void calcExtraSpaceImpl(int numPos, Widget **references, int *x, int *y)
The actual implementation for calculating dw::core::Widget::extraSpace.
Definition widget.cc:1744
virtual void resizeDrawImpl()
Called after sizeAllocateImpl() to redraw necessary areas.
Definition widget.hh:346
virtual bool buttonPressImpl(EventButton *event)
Definition widget.cc:2204
void setParent(Widget *parent)
Definition widget.cc:243
virtual bool isPossibleContainer()
Definition widget.cc:2198
DW_Callback_t deleteCallbackFunc
Definition widget.hh:434
virtual void getExtremesImpl(Extremes *extremes, int numPos, Widget **references, int *x, int *y)
See Sizes of Dillo Widgets.
Definition widget.cc:1716
void queueResizeFast(int ref, bool extremesChanged)
Definition widget.hh:185
bool needsResize()
Definition widget.hh:471
virtual void containerSizeChangedForChildren()
Definition widget.cc:509
void scrollTo(HPosition hpos, VPosition vpos, int x, int y, int width, int height)
Definition widget.cc:1659
void enterSizeAllocate()
Definition widget.hh:447
int calcHeight(style::Length cssValue, bool usePercentage, int refHeight, Widget *refWidget, bool forceValue)
Definition widget.cc:1037
virtual Widget * getWidgetAtPoint(int x, int y, GettingWidgetAtPointContext *context)
Definition widget.cc:223
virtual int applyPerHeight(int containerHeight, style::Length perHeight)
Definition widget.cc:1763
void leaveNotify(EventCrossing *event)
Definition widget.cc:1304
void drawInterruption(View *view, Rectangle *area, DrawingContext *context)
See Interrupted drawing for details.
Definition widget.cc:213
bool correctReqAspectRatio(int pass, Widget *child, Requisition *requisition, bool allowDecreaseWidth, bool allowDecreaseHeight, void(*splitHeightFun)(int, int *, int *))
Correct a child requisition aspect ratio if needed.
Definition widget.cc:1958
virtual int numGetExtremesReferences()
See Sizes of Dillo Widgets (or Size requisitions depending on positions).
Definition widget.cc:1190
virtual Widget * sizeRequestReference(int index)
See Sizes of Dillo Widgets (or Size requisitions depending on positions).
Definition widget.cc:1184
Widget * parent
The parent widget, NULL for top-level widgets.
Definition widget.hh:127
int getAvailHeight(bool forceValue)
Return available height including margin/border/padding (extraSpace?), not only the content height.
Definition widget.cc:705
void leaveQueueResize()
Definition widget.hh:444
style::Style * style
Definition widget.hh:150
static bool adjustMinWidth
Definition widget.hh:122
void containerSizeChanged()
Definition widget.cc:420
int getGeneratorLevel()
Get the level of the widget within the tree, regarting the generators, not the parents.
Definition widget.cc:1612
void leaveSizeAllocate()
Definition widget.hh:448
void unsetFlags(Flags f)
Definition widget.hh:301
void queueResize(int ref, bool extremesChanged, bool fast)
This method should be called, when a widget changes its size.
Definition widget.cc:321
virtual void sizeRequestImpl(Requisition *requisition, int numPos, Widget **references, int *x, int *y)
See Sizes of Dillo Widgets.
Definition widget.cc:1701
bool buttonPress(EventButton *event)
Definition widget.cc:1284
void correctReqHeightOfChild(Widget *child, Requisition *requisition, void(*splitHeightFun)(int, int *, int *), bool allowDecreaseHeight)
Definition widget.cc:2077
virtual bool usesAvailHeight()
Must be implemengted by a method returning true, when getAvailHeight() is called.
Definition widget.cc:537
virtual void markSizeChange(int ref)
See Sizes of Dillo Widgets.
Definition widget.cc:1749
Widget * getTopLevel()
Get the widget at the root of the tree, this widget is part from.
Definition widget.cc:1578
style::Color * getBgColor()
Get the actual background of a widget.
Definition widget.cc:1431
bool wasAllocated()
Definition widget.hh:475
virtual int numSizeRequestReferences()
See Sizes of Dillo Widgets (or Size requisitions depending on positions).
Definition widget.cc:1179
virtual Widget * getExtremesReference(int index)
See Sizes of Dillo Widgets (or Size requisitions depending on positions).
Definition widget.cc:1195
void getBorderArea(int *xBor, int *yBor, int *widthBor, int *heightBor)
Definition widget.cc:1674
int boxDiffHeight()
Definition widget.hh:500
void setBgColor(style::Color *bgColor)
Set the background "behind" the widget, if it is not the background of the parent widget,...
Definition widget.cc:1423
void queueDraw()
Definition widget.hh:304
virtual int applyPerWidth(int containerWidth, style::Length perWidth)
Definition widget.cc:1757
void correctExtremes(Extremes *extremes, bool useAdjustmentWidth)
Definition widget.cc:870
void getMarginArea(int *xMar, int *yMar, int *widthMar, int *heightMar)
Definition widget.cc:1666
void getPaddingArea(int *xPad, int *yPad, int *widthPad, int *heightPad)
Return the padding area (content plus padding).
Definition widget.cc:1690
virtual bool buttonReleaseImpl(EventButton *event)
Definition widget.cc:2209
SizeParams extremesParams
Definition widget.hh:167
float ratio
Preferred aspect ratio of the widget.
Definition widget.hh:214
void setFlags(Flags f)
Definition widget.hh:299
void correctReqWidthOfChild(Widget *child, Requisition *requisition, bool allowDecreaseWidth)
Correct a child requisition to fit the parent.
Definition widget.cc:2056
bool buttonSensitiveSet
See dw::core::Widget::setButtonSensitive().
Definition widget.hh:182
void getExtremes(Extremes *extremes, int numPos=0, Widget **references=NULL, int *x=NULL, int *y=NULL)
Wrapper for Widget::getExtremesImpl().
Definition widget.cc:1093
void enterGetExtremes()
Definition widget.hh:455
void drawBox(View *view, style::Style *style, Rectangle *area, int x, int y, int width, int height, bool inverse)
Draw borders and background of a widget part, which allocation is given by (x, y, width,...
Definition widget.cc:1471
Widget * quasiParent
...
Definition widget.hh:132
static int CLASS_ID
Definition widget.hh:461
bool buttonSensitive
See dw::core::Widget::setButtonSensitive().
Definition widget.hh:177
void enterSizeRequest()
Definition widget.hh:451
virtual bool isBlockLevel()
Definition widget.cc:2192
void correctRequisitionViewport(Requisition *requisition, void(*splitHeightFun)(int, int *, int *), bool allowDecreaseWidth, bool allowDecreaseHeight)
Corrects a requisition to fit in the viewport.
Definition widget.cc:768
StyleImage * backgroundImage
Definition style.hh:537
bool sizeDiffs(StyleAttrs *otherStyleAttrs)
This method returns whether something may change its size, when its style changes from this style to ...
Definition style.cc:150
void putExternalImgRenderer(ImgRenderer *ir)
Add an additional ImgRenderer, especially used for drawing.
Definition style.hh:892
void removeExternalImgRenderer(ImgRenderer *ir)
Remove a previously added additional ImgRenderer.
Definition style.hh:898
virtual void onLeave()
Definition style.hh:673
virtual void onEnter()
Definition style.hh:672
const char * getClassName()
Return the name, under which the class of this object was registered.
Definition identity.hh:140
void registerName(const char *className, int *classId)
This method must be called in the constructor for the sub class.
Definition identity.cc:83
#define DBG_IF_RTFL
Definition debug.hh:73
#define DEBUG_MSG(level,...)
Definition debug.hh:29
#define DBG_OBJ_LEAVE_VAL_S(fmt,...)
Definition debug.hh:80
#define DBG_OBJ_ENTER_S(aspect, prio, funname, fmt,...)
Definition debug.hh:78
#define DBG_OBJ_ENTER0(aspect, prio, funname)
#define DBG_OBJ_DELETE()
#define DBG_OBJ_CREATE(klass)
#define DBG_OBJ_SET_COL(var, val)
#define DBG_OBJ_SET_SYM(var, val)
#define DBG_OBJ_MSG_END()
#define DBG_OBJ_MSGF(aspect, prio, fmt,...)
#define DBG_OBJ_SET_NUM(var, val)
#define DBG_OBJ_MSG(aspect, prio, msg)
#define DBG_OBJ_ENTER(aspect, prio, funname, fmt,...)
#define DBG_OBJ_LEAVE()
#define DBG_OBJ_MSG_START()
#define DBG_OBJ_ASSOC_PARENT(parent)
#define DBG_OBJ_ASSOC_CHILD(child)
#define DBG_OBJ_SET_PTR(var, val)
#define DBG_OBJ_LEAVE_VAL0(val)
#define DBG_OBJ_LEAVE_VAL(fmt,...)
#define MSG_WARN(...)
Definition msg.h:26
int multiplyWithPerLength(int x, Length l)
Multiply an int with a percentage length, returning int.
Definition style.hh:474
void drawBackground(View *view, Layout *layout, Rectangle *area, int x, int y, int width, int height, int xRef, int yRef, int widthRef, int heightRef, Style *style, Color *bgColor, bool inverse, bool atTop)
Draw the background (content plus padding) of a region in window, according to style.
Definition style.cc:1233
@ DISPLAY_TABLE_HEADER_GROUP
Definition style.hh:286
@ DISPLAY_TABLE_ROW_GROUP
Definition style.hh:285
@ DISPLAY_INLINE_BLOCK
Definition style.hh:281
@ DISPLAY_TABLE_FOOTER_GROUP
Definition style.hh:287
int Length
Type for representing all lengths within dw::core::style.
Definition style.hh:429
double perLengthVal_useThisOnlyForDebugging(Length l)
Returns the value of a percentage, relative to 1, as a double.
Definition style.hh:459
void drawBorder(View *view, Layout *layout, Rectangle *area, int x, int y, int width, int height, Style *style, bool inverse)
Draw the border of a region in window, according to style.
Definition style.cc:1168
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
void splitHeightPreserveDescent(int height, int *ascent, int *descent)
Definition widget.cc:2258
@ PASS_DECREASE
Definition widget.cc:38
@ PASS_KEEP
Definition widget.cc:39
@ PASS_INCREASE
Definition widget.cc:37
VPosition
Definition types.hh:26
void splitHeightPreserveAscent(int height, int *ascent, int *descent)
Definition widget.cc:2244
HPosition
Definition types.hh:16
Dw is in this namespace, or sub namespaces of this one.
Miscellaneous stuff, which does not fit anywhere else.
Definition misc.cc:31
void notImplemented(const char *name)
Definition misc.hh:76
T max(T a, T b)
Definition misc.hh:41
const char * boolToStr(bool b)
Definition misc.hh:108
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
@ WIDGET_IN_FLOW
widget in normal flow, so that this widget (containing this content) is both container (parent) and g...
Definition types.hh:207
@ WIDGET_OOF_CONT
widget out of flow (OOF); this widget (containing this content) is only the container (parent),...
Definition types.hh:212
Widget * widget
Definition types.hh:237