aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.hgignore1
-rw-r--r--ChangeLog11
-rw-r--r--Doxyfile3
-rw-r--r--dillorc3
-rw-r--r--doc/dw-grows.doc130
-rw-r--r--doc/dw-widget-sizes.doc24
-rw-r--r--dw/Makefile.am7
-rw-r--r--dw/alignedtablecell.cc (renamed from dw/tablecell.cc)35
-rw-r--r--dw/alignedtablecell.hh34
-rw-r--r--dw/bullet.cc19
-rw-r--r--dw/bullet.hh3
-rw-r--r--dw/fltkui.cc38
-rw-r--r--dw/image.cc88
-rw-r--r--dw/image.hh2
-rw-r--r--dw/layout.cc91
-rw-r--r--dw/layout.hh8
-rw-r--r--dw/listitem.cc2
-rw-r--r--dw/outofflowmgr.cc652
-rw-r--r--dw/outofflowmgr.hh12
-rw-r--r--dw/ruler.cc33
-rw-r--r--dw/ruler.hh9
-rw-r--r--dw/simpletablecell.cc58
-rw-r--r--dw/simpletablecell.hh24
-rw-r--r--dw/style.hh25
-rw-r--r--dw/table.cc1291
-rw-r--r--dw/table.hh75
-rw-r--r--dw/table_iterator.cc134
-rw-r--r--dw/tablecell.hh29
-rw-r--r--dw/textblock.cc507
-rw-r--r--dw/textblock.hh44
-rw-r--r--dw/textblock_iterator.cc2
-rw-r--r--dw/textblock_linebreaking.cc345
-rw-r--r--dw/types.hh2
-rw-r--r--dw/ui.cc195
-rw-r--r--dw/ui.hh53
-rw-r--r--dw/widget.cc875
-rw-r--r--dw/widget.hh146
-rw-r--r--lout/debug.hh122
-rw-r--r--lout/misc.hh15
-rw-r--r--src/dillo.cc2
-rw-r--r--src/prefs.c1
-rw-r--r--src/prefs.h1
-rw-r--r--src/prefsparser.cc1
-rw-r--r--src/table.cc5
-rw-r--r--test/Makefile.am12
-rw-r--r--test/dw_simple_container.cc241
-rw-r--r--test/dw_simple_container.hh56
-rw-r--r--test/dw_simple_container_test.cc114
-rw-r--r--test/dw_table.cc1
-rw-r--r--test/dw_table_aligned.cc6
50 files changed, 3569 insertions, 2018 deletions
diff --git a/.hgignore b/.hgignore
index 759077b4..f3e9fd41 100644
--- a/.hgignore
+++ b/.hgignore
@@ -37,6 +37,7 @@
^test/dw-links2$
^test/dw-lists$
^test/dw-resource-test$
+^test/dw-simple-container-test$
^test/dw-table$
^test/dw-table-aligned$
^test/dw-ui-test$
diff --git a/ChangeLog b/ChangeLog
index 18f062e7..285ad801 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -7,6 +7,17 @@ user. For a history of changes in full detail, see our Mercurial repository
at http://hg.dillo.org/dillo
+dillo_grows [to be integrated after merge]
+
++- Redesign of widget sizes ("GROWS").
+ - Applied CSS attribute 'width' to all elements, 'height' is now also
+ supported.
+ - Image aspect ratio is preserved when one dimension is specified by a
+ percentage value.
+ - New dillorc option 'adjust_min_width'.
+ Patches: Sebastian Geerken
+
+
dillo-3.1 [not released yet]
+- Floating elements.
diff --git a/Doxyfile b/Doxyfile
index 971cf7be..ee527bab 100644
--- a/Doxyfile
+++ b/Doxyfile
@@ -599,8 +599,7 @@ EXCLUDE = dlib \
dpi \
dpid \
dpip \
- src \
- test
+ src
# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
# directories that are symbolic links (a Unix filesystem feature) are excluded
diff --git a/dillorc b/dillorc
index e0195961..1260c28a 100644
--- a/dillorc
+++ b/dillorc
@@ -79,6 +79,9 @@
# Set this to YES to limit the word wrap width to the viewport width
#limit_text_width=NO
+# If this is set to YES, all CSS size specifications are adjusted so that
+# all contents can be displayed.
+#adjust_min_width=NO
#-------------------------------------------------------------------------
# PENALTIES
diff --git a/doc/dw-grows.doc b/doc/dw-grows.doc
index 32800c19..79262fab 100644
--- a/doc/dw-grows.doc
+++ b/doc/dw-grows.doc
@@ -14,6 +14,132 @@ calculating widget sizes. Goals are:
- *display: inline-block*;
- <button>.
-(...)
-*/ \ No newline at end of file
+A short sketch
+==============
+
+**dw::core::Widget::sizeRequest and dw::core::Widget::getExtremes will
+return final results.** The caller does not have to correct the size,
+e.&nbsp;g. when percentages are defined. As an example,
+dw::Textblock::calcWidgetSize has already become much simpler.
+
+**A new hierarchy, *container*:** Aside from dw::core::Widget::parent
+and dw::core::Widget::generator, there is a third hierarchy
+dw::core::Widget::container, which is (unlike *generator*) always a
+direct ancestor, and represents what in CSS is called *containing
+block*. Containers are important to define the "context size", which
+is (not solely) used for percentage sizes.
+
+(There is another "containing block", dw::Textblock::containingBlock;
+these may be consolidated some day.)
+
+**The process of size calculation is split between the widget itself
+and its container:**
+
+- The container provides some abstract methods:
+ dw::core::Widget::getAvailWidthOfChild,
+ dw::core::Widget::getAvailHeightOfChild,
+ dw::core::Widget::correctRequisitionOfChild, and
+ dw::core::Widget::correctExtremesOfChild, which can be used in the
+ actual implementation of dw::core::Widget::sizeRequestImpl;
+ different containers with different ways how to arrange their
+ children will implement these methods in a different way. (Simple
+ example: the *available width* for children within a textblock is
+ the *available width* for the textblock itself, minus
+ margin/border/padding; on the other hand, it is completely different
+ for children of tables, for which a complex column width calculation
+ is used.)
+
+- The actual size calculation is, however, controlled by the widget
+ itself, which only *uses* these methods above.
+
+<div style="border: 2px solid #ffff00; margin-top: 0.5em;
+ margin-bottom: 0.5em; padding: 0.5em 1em; background-color: #ffffe0">
+ <b>Update:</b> This is not fully correct; the parents are also involved
+ for calculating available widths and heights, at least when CSS 'width'
+ and 'height' are not set.</div>
+
+**Size hints are removed.** Instead, the container methods in the
+previous paragraph are used. Changes of container sizes (especially
+viewport the size) are handled in a different way.
+
+**Extremes are extended by intrinsic values.** In some cases (see
+dw::Table::forceCalcCellSizes, case *minWidth* > *totalWidth*, for an
+example) it is useful to know about minimal and maximal width of a
+widget independent of CSS attributes. For this, dw::core::Extremes is
+extended by:
+
+- dw::core::Extremes::minWidthIntrinsic and
+- dw::core::Extremes::maxWidthIntrinsic.
+
+The rules for the calculation:
+
+1. If a widget has no children, it calculates *minWidthIntrinsic* and
+ *maxWidthIntrinsic* as those values not affected by CSS hints.
+ (dw::core::Widget::correctExtremes will not change these values.)
+2. A widget must calculate *minWidthIntrinsic* and *maxWidthIntrinsic*
+ from *minWidthIntrinsic* and *maxWidthIntrinsic* of its children,
+ and *minWidth* and *maxWidth* from *minWidth* and *maxWidth* of its
+ children.
+3. At the end, *minWidth* and *maxWidth* of a widget are corrected by
+ CSS attributes. (dw::core::Widget::correctExtremes will do this.)
+
+<div style="border: 2px solid #ffff00; margin-top: 0.5em;
+ margin-bottom: 0.5em; padding: 0.5em 1em; background-color: #ffffe0">
+ <b>Notice:</b> Currently, dw::core::Widget::getExtremesImpl must
+ set all four members in dw::core::Extremes; this may change.</div>
+
+Open issues
+===========
+
+**Do CSS size dimensions override intrinsic sizes in all cases?** If a
+textblock needs at least, say, 100 pixels width so that the text can
+be read, but has a specification "width: 50px", should half of the
+text be invisible? Or should the width be corrected again to 100
+pixels?
+
+Currently, in the CSS size specification is honoured in all cases,
+with one exception: see dw::Textblock::sizeRequestImpl and see
+dw::Textblock::getExtremesImpl (the time when
+dw::core::Widget::correctRequisition and
+dw::core::Widget::correctExtremes, respectively, is called).
+
+*Not* honouring the CSS size specification in all cases could improve
+readability in some cases, so this could depend on a user preference.
+
+**Update:** There is now a dillorc option <tt>adjust_min_width</tt>,
+which is implemented for widths, but not heights (since it is based on
+width extremes, but there are currently no height extremes).
+
+Another problem is that in most cases, there is no clippping, so that
+contents may exceed the allocation of the widget, but redrawing is not
+necessarily triggered.
+
+**Percentage values for margins and paddings, as well as negative
+margins** are interesting applications, but have not been considered
+yet. For negative margins, a new attribute
+dw::core::Widget::extraSpace could solve the problem of widgets
+sticking out of the allocation of parent.
+
+**Clarify percentage heights.** Search in widget.cc, and compare
+section 10.5 ('height') of the CSS 2.1 specification to section 10.2
+('width').
+
+**Fast queue resize does not work fully.** Example: run
+*test/dw-simple-container-test* (dw_simple_container_test.cc), resize
+(best maximize) the window and follow (e.&nbsp;g. by using RTFL) what
+happens in consequence of dw::core::Layout::viewportSizeChanged. The
+dw::SimpleContainer in the middle is not affected, so only the two
+dw::Textblock's (at the top and at the bottom) call queueResize with
+*fast = true*, and so get *NEEDS_RESIZE* set; but since it is not set
+for the dw::SimpleContainer, *sizeRequest* is never called for the
+bottom dw::Textblock.
+
+There does not seem to be a real case for this problem in dillo, since
+all widgets which may contain other widgets (except
+dw::SimpleContainer, which is not used outside tests) use the
+available width and height (dw::core::Widget::usesAvailWidth and
+dw::core::Widget::usesAvailHeight), and so are always affected by
+viewport size changes.
+
+*/
diff --git a/doc/dw-widget-sizes.doc b/doc/dw-widget-sizes.doc
index a9b6b00c..a82d3b99 100644
--- a/doc/dw-widget-sizes.doc
+++ b/doc/dw-widget-sizes.doc
@@ -1,5 +1,9 @@
/** \page dw-widget-sizes Sizes of Dillo Widgets
+<div style="border: 2px solid #ff4040; margin-bottom: 0.5em;
+padding: 0.5em 1em; background-color: #fff0f0"><b>Info:</b>
+Not up to date, see \ref dw-grows.</div>
+
Allocation
==========
@@ -87,23 +91,9 @@ the image buffer when allocated at another size.)
Size Hints
==========
-Some widgets do not have an inherent size, but depend on the context,
-e.g. the viewport size. These widgets should adhere to <i>size hints</i>,
-i.e. implement the methods dw::core::Widget::setWidth,
-dw::core::Widget::setAscent and dw::core::Widget::setDescent. The values
-passed to the callees are
-
-- the viewport size (ascent is the heigt here, while descent is 0) for
- the toplevel widget, and
-- determined by the parent for its child widgets.
-
-Generally, the values should define the available space for the
-widget.
-
-A widget, which depends on size hints, should call
-dw::core::Widget::queueResize, when apropriate.
-
-\todo There should be a definition of "available space".
+<div style="border: 2px solid #ff4040; margin-bottom: 0.5em;
+padding: 0.5em 1em; background-color: #fff0f0"><b>Info:</b>
+Size hints have been removed, see \ref dw-grows.</div>
Width Extremes
diff --git a/dw/Makefile.am b/dw/Makefile.am
index 5306c5a5..25d8bbce 100644
--- a/dw/Makefile.am
+++ b/dw/Makefile.am
@@ -57,6 +57,8 @@ libDw_fltk_a_SOURCES = \
libDw_fltk_a_CXXFLAGS = @LIBFLTK_CXXFLAGS@
libDw_widgets_a_SOURCES = \
+ alignedtablecell.cc \
+ alignedtablecell.hh \
alignedtextblock.cc \
alignedtextblock.hh \
bullet.cc \
@@ -71,10 +73,11 @@ libDw_widgets_a_SOURCES = \
outofflowmgr.hh \
ruler.cc \
ruler.hh \
+ simpletablecell.cc \
+ simpletablecell.hh \
table.cc \
+ table_iterator.cc \
table.hh \
- tablecell.cc \
- tablecell.hh \
textblock.cc \
textblock_iterator.cc \
textblock_linebreaking.cc \
diff --git a/dw/tablecell.cc b/dw/alignedtablecell.cc
index cbd5e0bf..a9f091f3 100644
--- a/dw/tablecell.cc
+++ b/dw/alignedtablecell.cc
@@ -19,19 +19,19 @@
-#include "tablecell.hh"
+#include "alignedtablecell.hh"
#include "../lout/debug.hh"
#include <stdio.h>
namespace dw {
-int TableCell::CLASS_ID = -1;
+int AlignedTableCell::CLASS_ID = -1;
-TableCell::TableCell (TableCell *ref, bool limitTextWidth):
+AlignedTableCell::AlignedTableCell (AlignedTableCell *ref, bool limitTextWidth):
AlignedTextblock (limitTextWidth)
{
- DBG_OBJ_CREATE ("dw::TableCell");
- registerName ("dw::TableCell", &CLASS_ID);
+ DBG_OBJ_CREATE ("dw::AlignedTableCell");
+ registerName ("dw::AlignedTableCell", &CLASS_ID);
/** \bug ignoreLine1OffsetSometimes does not work? */
//ignoreLine1OffsetSometimes = true;
@@ -40,12 +40,29 @@ TableCell::TableCell (TableCell *ref, bool limitTextWidth):
setButtonSensitive(true);
}
-TableCell::~TableCell()
+AlignedTableCell::~AlignedTableCell()
{
DBG_OBJ_DELETE ();
}
-int TableCell::wordWrap(int wordIndex, bool wrapAll)
+bool AlignedTableCell::isBlockLevel ()
+{
+ return false;
+}
+
+int AlignedTableCell::applyPerWidth (int containerWidth,
+ core::style::Length perWidth)
+{
+ return core::style::multiplyWithPerLength (containerWidth, perWidth);
+}
+
+int AlignedTableCell::applyPerHeight (int containerHeight,
+ core::style::Length perHeight)
+{
+ return core::style::multiplyWithPerLength (containerHeight, perHeight);
+}
+
+int AlignedTableCell::wordWrap(int wordIndex, bool wrapAll)
{
Textblock::Word *word;
const char *p;
@@ -73,7 +90,7 @@ int TableCell::wordWrap(int wordIndex, bool wrapAll)
return ret;
}
-int TableCell::getValue ()
+int AlignedTableCell::getValue ()
{
Textblock::Word *word;
int i, wordIndex;
@@ -104,7 +121,7 @@ int TableCell::getValue ()
return w;
}
-void TableCell::setMaxValue (int maxValue, int value)
+void AlignedTableCell::setMaxValue (int maxValue, int value)
{
line1Offset = maxValue - value;
queueResize (OutOfFlowMgr::createRefNormalFlow (0), true);
diff --git a/dw/alignedtablecell.hh b/dw/alignedtablecell.hh
new file mode 100644
index 00000000..caf59307
--- /dev/null
+++ b/dw/alignedtablecell.hh
@@ -0,0 +1,34 @@
+#ifndef __DW_ALIGNEDTABLECELL_HH__
+#define __DW_ALIGNEDTABLECELL_HH__
+
+#include "core.hh"
+#include "alignedtextblock.hh"
+
+namespace dw {
+
+class AlignedTableCell: public AlignedTextblock
+{
+private:
+ int charWordIndex, charWordPos;
+
+protected:
+ int wordWrap (int wordIndex, bool wrapAll);
+
+ int getValue ();
+ void setMaxValue (int maxValue, int value);
+
+public:
+ static int CLASS_ID;
+
+ AlignedTableCell(AlignedTableCell *ref, bool limitTextWidth);
+ ~AlignedTableCell();
+
+ int applyPerWidth (int containerWidth, core::style::Length perWidth);
+ int applyPerHeight (int containerHeight, core::style::Length perHeight);
+
+ bool isBlockLevel ();
+};
+
+} // namespace dw
+
+#endif // __DW_ALIGNEDTABLECELL_HH__
diff --git a/dw/bullet.cc b/dw/bullet.cc
index af7f5451..0ae8ccb7 100644
--- a/dw/bullet.cc
+++ b/dw/bullet.cc
@@ -27,6 +27,12 @@ namespace dw {
Bullet::Bullet ()
{
+ DBG_OBJ_CREATE ("dw::Bullet");
+}
+
+Bullet::~Bullet ()
+{
+ DBG_OBJ_DELETE ();
}
void Bullet::sizeRequestImpl (core::Requisition *requisition)
@@ -36,6 +42,19 @@ void Bullet::sizeRequestImpl (core::Requisition *requisition)
requisition->descent = 0;
}
+void Bullet::getExtremesImpl (core::Extremes *extremes)
+{
+ extremes->minWidth = extremes->maxWidth =
+ lout::misc::max (getStyle()->font->xHeight * 4 / 5, 1);
+}
+
+void Bullet::containerSizeChangedForChildren ()
+{
+ DBG_OBJ_ENTER0 ("resize", 0, "containerSizeChangedForChildren");
+ // Nothing to do.
+ DBG_OBJ_LEAVE ();
+}
+
void Bullet::draw (core::View *view, core::Rectangle *area)
{
int x, y, l;
diff --git a/dw/bullet.hh b/dw/bullet.hh
index 98854abb..004187cd 100644
--- a/dw/bullet.hh
+++ b/dw/bullet.hh
@@ -15,11 +15,14 @@ class Bullet: public core::Widget
{
protected:
void sizeRequestImpl (core::Requisition *requisition);
+ void getExtremesImpl (core::Extremes *extremes);
+ void containerSizeChangedForChildren ();
void draw (core::View *view, core::Rectangle *area);
core::Iterator *iterator (core::Content::Type mask, bool atEnd);
public:
Bullet ();
+ ~Bullet ();
};
} // namespace dw
diff --git a/dw/fltkui.cc b/dw/fltkui.cc
index bfc07528..29008055 100644
--- a/dw/fltkui.cc
+++ b/dw/fltkui.cc
@@ -213,12 +213,14 @@ void FltkResource::detachView (FltkView *view)
void FltkResource::sizeAllocate (core::Allocation *allocation)
{
- DBG_OBJ_MSGF ("resize", 0, "<b>sizeAllocate</b> (%d, %d; %d * (%d + %d))",
- allocation->x, allocation->y, allocation->width,
- allocation->ascent, allocation->descent);
+ DBG_OBJ_ENTER ("resize", 0, "sizeAllocate", "%d, %d; %d * (%d + %d)",
+ allocation->x, allocation->y, allocation->width,
+ allocation->ascent, allocation->descent);
this->allocation = *allocation;
view->allocateFltkWidget (widget, allocation);
+
+ DBG_OBJ_LEAVE ();
}
void FltkResource::draw (core::View *view, core::Rectangle *area)
@@ -389,8 +391,7 @@ Fl_Widget *FltkLabelButtonResource::createNewWidget (core::Allocation
void FltkLabelButtonResource::sizeRequest (core::Requisition *requisition)
{
- DBG_OBJ_MSG ("resize", 0, "<b>sizeRequest</b>");
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER0 ("resize", 0, "sizeRequest");
if (style) {
FltkFont *font = (FltkFont*)style->font;
@@ -408,7 +409,7 @@ void FltkLabelButtonResource::sizeRequest (core::Requisition *requisition)
DBG_OBJ_MSGF ("resize", 1, "result: %d * (%d + %d)",
requisition->width, requisition->ascent, requisition->descent);
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
/*
@@ -674,8 +675,7 @@ void FltkEntryResource::setDisplayed(bool displayed)
void FltkEntryResource::sizeRequest (core::Requisition *requisition)
{
- DBG_OBJ_MSG ("resize", 0, "<b>sizeRequest</b>");
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER0 ("resize", 0, "sizeRequest");
if (displayed() && style) {
FltkFont *font = (FltkFont*)style->font;
@@ -696,7 +696,7 @@ void FltkEntryResource::sizeRequest (core::Requisition *requisition)
DBG_OBJ_MSGF ("resize", 1, "result: %d * (%d + %d)",
requisition->width, requisition->ascent, requisition->descent);
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
void FltkEntryResource::sizeAllocate (core::Allocation *allocation)
@@ -831,8 +831,7 @@ void FltkMultiLineTextResource::setWidgetStyle (Fl_Widget *widget,
void FltkMultiLineTextResource::sizeRequest (core::Requisition *requisition)
{
- DBG_OBJ_MSG ("resize", 0, "<b>sizeRequest</b>");
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER0 ("resize", 0, "sizeRequest");
if (style) {
FltkFont *font = (FltkFont*)style->font;
@@ -855,7 +854,7 @@ void FltkMultiLineTextResource::sizeRequest (core::Requisition *requisition)
DBG_OBJ_MSGF ("resize", 1, "result: %d * (%d + %d)",
requisition->width, requisition->ascent, requisition->descent);
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
const char *FltkMultiLineTextResource::getText ()
@@ -923,8 +922,7 @@ void FltkToggleButtonResource<I>::setWidgetStyle (Fl_Widget *widget,
template <class I>
void FltkToggleButtonResource<I>::sizeRequest (core::Requisition *requisition)
{
- DBG_OBJ_MSG ("resize", 0, "<b>sizeRequest</b>");
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER0 ("resize", 0, "sizeRequest");
FltkFont *font = (FltkFont *)
(this->FltkResource::style ? this->FltkResource::style->font : NULL);
@@ -942,7 +940,7 @@ void FltkToggleButtonResource<I>::sizeRequest (core::Requisition *requisition)
DBG_OBJ_MSGF ("resize", 1, "result: %d * (%d + %d)",
requisition->width, requisition->ascent, requisition->descent);
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
@@ -1182,8 +1180,7 @@ int FltkOptionMenuResource::getMaxItemWidth()
void FltkOptionMenuResource::sizeRequest (core::Requisition *requisition)
{
- DBG_OBJ_MSG ("resize", 0, "<b>sizeRequest</b>");
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER0 ("resize", 0, "sizeRequest");
if (style) {
FltkFont *font = (FltkFont*)style->font;
@@ -1202,7 +1199,7 @@ void FltkOptionMenuResource::sizeRequest (core::Requisition *requisition)
DBG_OBJ_MSGF ("resize", 1, "result: %d * (%d + %d)",
requisition->width, requisition->ascent, requisition->descent);
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
void FltkOptionMenuResource::enlargeMenu ()
@@ -1478,8 +1475,7 @@ int FltkListResource::getMaxItemWidth()
void FltkListResource::sizeRequest (core::Requisition *requisition)
{
- DBG_OBJ_MSG ("resize", 0, "<b>sizeRequest</b>");
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER0 ("resize", 0, "sizeRequest");
if (style) {
CustBrowser *b = (CustBrowser *) widget;
@@ -1504,7 +1500,7 @@ void FltkListResource::sizeRequest (core::Requisition *requisition)
DBG_OBJ_MSGF ("resize", 1, "result: %d * (%d + %d)",
requisition->width, requisition->ascent, requisition->descent);
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
int FltkListResource::getNumberOfItems()
diff --git a/dw/image.cc b/dw/image.cc
index e71c8f2f..9dc6d6ee 100644
--- a/dw/image.cc
+++ b/dw/image.cc
@@ -170,45 +170,56 @@ Image::~Image()
void Image::sizeRequestImpl (core::Requisition *requisition)
{
+ DBG_OBJ_ENTER0 ("resize", 0, "sizeRequestImpl");
+
if (buffer) {
- if (getStyle ()->height == core::style::LENGTH_AUTO &&
- core::style::isAbsLength (getStyle ()->width) &&
- buffer->getRootWidth () > 0) {
- // preserve aspect ratio when only width is given
- requisition->width = core::style::absLengthVal (getStyle ()->width);
- requisition->ascent = buffer->getRootHeight () *
- requisition->width / buffer->getRootWidth ();
- } else if (getStyle ()->width == core::style::LENGTH_AUTO &&
- core::style::isAbsLength (getStyle ()->height) &&
- buffer->getRootHeight () > 0) {
- // preserve aspect ratio when only height is given
- requisition->ascent = core::style::absLengthVal (getStyle ()->height);
- requisition->width = buffer->getRootWidth () *
- requisition->ascent / buffer->getRootHeight ();
- } else {
- requisition->width = buffer->getRootWidth ();
- requisition->ascent = buffer->getRootHeight ();
- }
- requisition->descent = 0;
- } else {
- if (altText && altText[0]) {
- if (altTextWidth == -1)
- altTextWidth =
- layout->textWidth (getStyle()->font, altText, strlen (altText));
+ requisition->width = buffer->getRootWidth ();
+ requisition->ascent = buffer->getRootHeight ();
+ } else
+ requisition->width = requisition->ascent = 0;
+
+ requisition->width += boxDiffWidth ();
+ requisition->ascent += boxOffsetY ();
+
+ requisition->descent = boxRestHeight ();
- requisition->width = altTextWidth;
- requisition->ascent = getStyle()->font->ascent;
- requisition->descent = getStyle()->font->descent;
- } else {
- requisition->width = 0;
- requisition->ascent = 0;
- requisition->descent = 0;
+ correctRequisition (requisition, core::splitHeightPreserveDescent);
+
+ if (buffer) {
+ // If one dimension is set, preserve the aspect ratio (without
+ // extraSpace/margin/border/padding). Notice that
+ // requisition->descent could have been changed in
+ // core::splitHeightPreserveDescent, so we do not make any
+ // assumtions here about it (and requisition->ascent).
+
+ // TODO Check again possible overflows. (Aren't buffer
+ // dimensions limited to 2^15?)
+
+ if (getStyle()->width == core::style::LENGTH_AUTO &&
+ getStyle()->height != core::style::LENGTH_AUTO) {
+ requisition->width =
+ (requisition->ascent + requisition->descent - boxDiffHeight ())
+ * buffer->getRootWidth () / buffer->getRootHeight ()
+ + boxDiffWidth ();
+ } else if (getStyle()->width != core::style::LENGTH_AUTO &&
+ getStyle()->height == core::style::LENGTH_AUTO) {
+ requisition->ascent = (requisition->width + boxDiffWidth ())
+ * buffer->getRootHeight () / buffer->getRootWidth ()
+ + boxOffsetY ();
+ requisition->descent = boxRestHeight ();
}
- }
+ }
- requisition->width += getStyle()->boxDiffWidth ();
- requisition->ascent += getStyle()->boxOffsetY ();
- requisition->descent += getStyle()->boxRestHeight ();
+ DBG_OBJ_MSGF ("resize", 1, "=> %d * (%d + %d)",
+ requisition->width, requisition->ascent, requisition->descent);
+ DBG_OBJ_LEAVE ();
+}
+
+void Image::getExtremesImpl (core::Extremes *extremes)
+{
+ extremes->minWidth = extremes->maxWidth =
+ (buffer ? buffer->getRootWidth () : 0) + boxDiffWidth ();
+ correctExtremes (extremes);
}
void Image::sizeAllocateImpl (core::Allocation *allocation)
@@ -247,6 +258,13 @@ void Image::sizeAllocateImpl (core::Allocation *allocation)
}
}
+void Image::containerSizeChangedForChildren ()
+{
+ DBG_OBJ_ENTER0 ("resize", 0, "containerSizeChangedForChildren");
+ // Nothing to do.
+ DBG_OBJ_LEAVE ();
+}
+
void Image::enterNotifyImpl (core::EventCrossing *event)
{
// BUG: this is wrong for image maps, but the cursor position is unknown.
diff --git a/dw/image.hh b/dw/image.hh
index a712936e..71ed85b9 100644
--- a/dw/image.hh
+++ b/dw/image.hh
@@ -130,7 +130,9 @@ private:
protected:
void sizeRequestImpl (core::Requisition *requisition);
+ void getExtremesImpl (core::Extremes *extremes);
void sizeAllocateImpl (core::Allocation *allocation);
+ void containerSizeChangedForChildren ();
void draw (core::View *view, core::Rectangle *area);
diff --git a/dw/layout.cc b/dw/layout.cc
index 1609dae0..82a21f57 100644
--- a/dw/layout.cc
+++ b/dw/layout.cc
@@ -277,6 +277,11 @@ Layout::Layout (Platform *platform)
viewportWidth = viewportHeight = 0;
hScrollbarThickness = vScrollbarThickness = 0;
+ DBG_OBJ_SET_NUM ("viewportWidth", viewportWidth);
+ DBG_OBJ_SET_NUM ("viewportHeight", viewportHeight);
+ DBG_OBJ_SET_NUM ("hScrollbarThickness", hScrollbarThickness);
+ DBG_OBJ_SET_NUM ("vScrollbarThickness", vScrollbarThickness);
+
requestedAnchor = NULL;
scrollIdleId = -1;
scrollIdleNotInterrupted = false;
@@ -371,13 +376,17 @@ void Layout::addWidget (Widget *widget)
topLevel = widget;
widget->layout = this;
+ widget->container = NULL;
+ DBG_OBJ_SET_PTR_O (widget, "container", widget->container);
+
queueResizeList->clear ();
- widget->notifySetAsTopLevel();
+ widget->notifySetAsTopLevel ();
findtextState.setWidget (widget);
canvasHeightGreater = false;
- setSizeHints ();
+ DBG_OBJ_SET_SYM ("canvasHeightGreater",
+ canvasHeightGreater ? "true" : "false");
// Do not directly call Layout::queueResize(), but
// Widget::queueResize(), so that all flags are set properly,
@@ -471,6 +480,11 @@ void Layout::attachView (View *view)
hScrollbarThickness = view->getHScrollbarThickness ();
vScrollbarThickness = view->getVScrollbarThickness ();
}
+
+ DBG_OBJ_SET_NUM ("viewportWidth", viewportWidth);
+ DBG_OBJ_SET_NUM ("viewportHeight", viewportHeight);
+ DBG_OBJ_SET_NUM ("hScrollbarThickness", hScrollbarThickness);
+ DBG_OBJ_SET_NUM ("vScrollbarThickness", vScrollbarThickness);
}
/*
@@ -834,8 +848,7 @@ void Layout::setBgImage (style::StyleImage *bgImage,
void Layout::resizeIdle ()
{
- DBG_OBJ_MSG ("resize", 0, "<b>resizeIdle</b>");
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER0 ("resize", 0, "resizeIdle");
enterResizeIdle ();
@@ -873,7 +886,10 @@ void Layout::resizeIdle ()
// called again.
resizeIdleId = -1;
- if (topLevel) {
+ // If this method is triggered by a viewport change, we can save
+ // time when the toplevel widget is not affected (as for a toplevel
+ // image resource).
+ if (topLevel && (topLevel->needsResize () || topLevel->needsAllocate ())) {
Requisition requisition;
Allocation allocation;
@@ -882,9 +898,11 @@ void Layout::resizeIdle ()
requisition.width, requisition.ascent, requisition.descent);
// This method is triggered by Widget::queueResize, which will,
- // in any case, set NEEDS_ALLOCATE (indirectly, as
- // ALLOCATE_QUEUED). This assertion helps to find
- // inconsistences.
+ // in any case, set NEEDS_ALLOCATE (indirectly, as ALLOCATE_QUEUED).
+ // This assertion helps to find inconsistences. (Cases where
+ // this method is triggered by a viewport change, but the
+ // toplevel widget is not affected, are filtered out some lines
+ // above: "if (topLevel && topLevel->needsResize ())".)
assert (topLevel->needsAllocate ());
allocation.x = allocation.y = 0;
@@ -908,12 +926,12 @@ void Layout::resizeIdle ()
int currVThickness = currVScrollbarThickness();
if (!canvasHeightGreater &&
- canvasAscent + canvasDescent
- > viewportHeight - currHThickness) {
+ canvasAscent + canvasDescent > viewportHeight - currHThickness) {
canvasHeightGreater = true;
- setSizeHints ();
- /* May queue a new resize. */
- }
+ DBG_OBJ_SET_SYM ("canvasHeightGreater",
+ canvasHeightGreater ? "true" : "false");
+ containerSizeChanged ();
+ }
// Set viewport sizes.
view->setViewportSize (viewportWidth, viewportHeight,
@@ -927,21 +945,11 @@ void Layout::resizeIdle ()
DBG_OBJ_MSGF ("resize", 1,
"after resizeIdle: resizeIdleId = %d", resizeIdleId);
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
leaveResizeIdle ();
}
-void Layout::setSizeHints ()
-{
- if (topLevel) {
- topLevel->setWidth (viewportWidth
- - (canvasHeightGreater ? vScrollbarThickness : 0));
- topLevel->setAscent (viewportHeight - hScrollbarThickness);
- topLevel->setDescent (0);
- }
-}
-
void Layout::queueDraw (int x, int y, int width, int height)
{
Rectangle area;
@@ -980,9 +988,8 @@ void Layout::queueDrawExcept (int x, int y, int width, int height,
void Layout::queueResize (bool extremesChanged)
{
- DBG_OBJ_MSGF ("resize", 0, "<b>queueResize</b> (%s)",
- extremesChanged ? "true" : "false");
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("resize", 0, "queueResize", "%s",
+ extremesChanged ? "true" : "false");
if (resizeIdleId == -1) {
view->cancelQueueDraw ();
@@ -993,7 +1000,7 @@ void Layout::queueResize (bool extremesChanged)
emitter.emitResizeQueued (extremesChanged);
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
@@ -1264,13 +1271,16 @@ void Layout::scrollPosChanged (View *view, int x, int y)
*/
void Layout::viewportSizeChanged (View *view, int width, int height)
{
- _MSG("Layout::viewportSizeChanged w=%d h=%d new_w=%d new_h=%d\n",
- viewportWidth, viewportHeight, width, height);
+ DBG_OBJ_ENTER ("resize", 0, "viewportSizeChanged", "%p, %d, %d",
+ view, width, height);
/* If the width has become higher, we test again, whether the vertical
* scrollbar (so to speak) can be hidden again. */
- if (usesViewport && width > viewportWidth)
+ if (usesViewport && width > viewportWidth) {
canvasHeightGreater = false;
+ DBG_OBJ_SET_SYM ("canvasHeightGreater",
+ canvasHeightGreater ? "true" : "false");
+ }
/* if size changes, redraw this view.
* TODO: this is a resize call (redraw/resize code needs a review). */
@@ -1285,7 +1295,24 @@ void Layout::viewportSizeChanged (View *view, int width, int height)
viewportWidth = width;
viewportHeight = height;
- setSizeHints ();
+ DBG_OBJ_SET_NUM ("viewportWidth", viewportWidth);
+ DBG_OBJ_SET_NUM ("viewportHeight", viewportHeight);
+
+ containerSizeChanged ();
+
+ DBG_OBJ_LEAVE ();
+}
+
+void Layout::containerSizeChanged ()
+{
+ DBG_OBJ_ENTER0 ("resize", 0, "containerSizeChanged");
+
+ if (topLevel) {
+ topLevel->containerSizeChanged ();
+ queueResize (true);
+ }
+
+ DBG_OBJ_LEAVE ();
}
} // namespace core
diff --git a/dw/layout.hh b/dw/layout.hh
index 2120d877..88532187 100644
--- a/dw/layout.hh
+++ b/dw/layout.hh
@@ -157,13 +157,15 @@ private:
public:
Widget *widget;
int ref;
- bool extremesChanged;
+ bool extremesChanged, fast;
- inline QueueResizeItem (Widget *widget, int ref, bool extremesChanged)
+ inline QueueResizeItem (Widget *widget, int ref, bool extremesChanged,
+ bool fast)
{
this->widget = widget;
this->ref = ref;
this->extremesChanged = extremesChanged;
+ this->fast = fast;
}
};
@@ -328,6 +330,8 @@ public:
return buttonEvent (BUTTON_PRESS, view, numPressed, x, y, state, button);
}
+ void containerSizeChanged ();
+
/**
* \brief This function is called by a view, to delegate a button press
* event.
diff --git a/dw/listitem.cc b/dw/listitem.cc
index 05344d79..65293d8d 100644
--- a/dw/listitem.cc
+++ b/dw/listitem.cc
@@ -69,7 +69,7 @@ int ListItem::getValue ()
void ListItem::setMaxValue (int maxValue, int value)
{
- innerPadding = maxValue;
+ leftInnerPadding = maxValue;
line1Offset = - value;
redrawY = 0;
queueResize (0, true);
diff --git a/dw/outofflowmgr.cc b/dw/outofflowmgr.cc
index eb5bf3e8..62386b15 100644
--- a/dw/outofflowmgr.cc
+++ b/dw/outofflowmgr.cc
@@ -41,9 +41,8 @@ OutOfFlowMgr::WidgetInfo::WidgetInfo (OutOfFlowMgr *oofm, Widget *widget)
void OutOfFlowMgr::WidgetInfo::update (bool wasAllocated, int xCB, int yCB,
int width, int height)
{
- DBG_OBJ_MSGF_O ("resize.oofm", 0, widget,
- "<b>update</b> (%s, %d, %d, %d, %d)",
- wasAllocated ? "true" : "false", xCB, yCB, width, height);
+ DBG_OBJ_ENTER_O ("resize.oofm", 0, widget, "update", "%s, %d, %d, %d, %d",
+ wasAllocated ? "true" : "false", xCB, yCB, width, height);
this->wasAllocated = wasAllocated;
this->xCB = xCB;
@@ -55,6 +54,8 @@ void OutOfFlowMgr::WidgetInfo::update (bool wasAllocated, int xCB, int yCB,
DBG_OBJ_SET_NUM_O (widget, "<WidgetInfo>.yCB", yCB);
DBG_OBJ_SET_NUM_O (widget, "<WidgetInfo>.width", width);
DBG_OBJ_SET_NUM_O (widget, "<WidgetInfo>.height", height);
+
+ DBG_OBJ_LEAVE_O (widget);
}
// ----------------------------------------------------------------------
@@ -80,18 +81,20 @@ OutOfFlowMgr::Float::Float (OutOfFlowMgr *oofm, Widget *widget,
DBG_OBJ_SET_NUM_O (widget, "<Float>.size.width", size.width);
DBG_OBJ_SET_NUM_O (widget, "<Float>.size.ascent", size.ascent);
DBG_OBJ_SET_NUM_O (widget, "<Float>.size.descent", size.descent);
+ DBG_OBJ_SET_BOOL_O (widget, "<Float>.dirty", dirty);
+ DBG_OBJ_SET_BOOL_O (widget, "<Float>.sizeChangedSinceLastAllocation",
+ sizeChangedSinceLastAllocation);
}
}
void OutOfFlowMgr::Float::updateAllocation ()
{
- DBG_OBJ_MSG_O ("resize.oofm", 0, getWidget (), "<b>updateAllocation</b> ()");
- DBG_OBJ_MSG_START_O (getWidget ());
+ DBG_OBJ_ENTER0_O ("resize.oofm", 0, getWidget (), "updateAllocation");
update (isNowAllocated (), getNewXCB (), getNewYCB (), getNewWidth (),
getNewHeight ());
- DBG_OBJ_MSG_END_O (getWidget ());
+ DBG_OBJ_LEAVE_O (getWidget ());
}
void OutOfFlowMgr::Float::intoStringBuffer(StringBuffer *sb)
@@ -132,10 +135,9 @@ void OutOfFlowMgr::Float::intoStringBuffer(StringBuffer *sb)
bool OutOfFlowMgr::Float::covers (Textblock *textblock, int y, int h)
{
- DBG_OBJ_MSGF_O ("border", 0, getOutOfFlowMgr (),
- "<b>covers</b> (%p, %d, %d) [vloat: %p]",
- textblock, y, h, getWidget ());
- DBG_OBJ_MSG_START_O (getOutOfFlowMgr ());
+ DBG_OBJ_ENTER_O ("border", 0, getOutOfFlowMgr (), "covers",
+ "%p, %d, %d [vloat: %p]",
+ textblock, y, h, getWidget ());
bool b;
@@ -176,7 +178,7 @@ bool OutOfFlowMgr::Float::covers (Textblock *textblock, int y, int h)
}
}
- DBG_OBJ_MSG_END_O (getOutOfFlowMgr ());
+ DBG_OBJ_LEAVE_O (getOutOfFlowMgr ());
return b;
}
@@ -186,10 +188,9 @@ int OutOfFlowMgr::Float::ComparePosition::compare (Object *o1, Object *o2)
Float *fl1 = (Float*)o1, *fl2 = (Float*)o2;
int r;
- DBG_OBJ_MSGF_O ("border", 1, oofm,
- "<b>ComparePosition::compare</b> (#%d, #%d) [refTB = %p]",
- fl1->getIndex (type), fl2->getIndex (type), refTB);
- DBG_OBJ_MSG_START_O (oofm);
+ DBG_OBJ_ENTER_O ("border", 1, oofm,
+ "ComparePosition/compare", "(#%d, #%d) [refTB = %p]",
+ fl1->getIndex (type), fl2->getIndex (type), refTB);
if (refTB == fl1->generatingBlock && refTB == fl2->generatingBlock) {
DBG_OBJ_MSG_O ("border", 2, oofm, "refTB is generating both floats");
@@ -237,7 +238,7 @@ int OutOfFlowMgr::Float::ComparePosition::compare (Object *o1, Object *o2)
}
DBG_OBJ_MSGF_O ("border", 1, oofm, "result: %d", r);
- DBG_OBJ_MSG_END_O (oofm);
+ DBG_OBJ_LEAVE_O (oofm);
return r;
}
@@ -252,12 +253,11 @@ int OutOfFlowMgr::Float::CompareGBAndExtIndex::compare (Object *o1, Object *o2)
Float *f1 = (Float*)o1, *f2 = (Float*)o2;
int r = -123; // Compiler happiness: GCC 4.7 does not handle this?;
- DBG_OBJ_MSGF_O ("border", 1, oofm,
- "<b>CompareGBAndExtIndex::compare</b> (#%d -> %p/%d, "
- "#%d -> %p/#%d)",
- f1->getIndex (type), f1->generatingBlock, f1->externalIndex,
- f2->getIndex (type), f2->generatingBlock, f2->externalIndex);
- DBG_OBJ_MSG_START_O (oofm);
+ DBG_OBJ_ENTER_O ("border", 1, oofm, "CompareGBAndExtIndex/compare",
+ "#%d -> %p/%d, #%d -> %p/#%d",
+ f1->getIndex (type), f1->generatingBlock, f1->externalIndex,
+ f2->getIndex (type), f2->generatingBlock,
+ f2->externalIndex);
if (f1->generatingBlock == f2->generatingBlock) {
r = f1->externalIndex - f2->externalIndex;
@@ -301,16 +301,15 @@ int OutOfFlowMgr::Float::CompareGBAndExtIndex::compare (Object *o1, Object *o2)
}
DBG_OBJ_MSGF_O ("border", 2, oofm, "result: %d", r);
- DBG_OBJ_MSG_END_O (oofm);
+ DBG_OBJ_LEAVE_O (oofm);
return r;
}
int OutOfFlowMgr::SortedFloatsVector::findFloatIndex (Textblock *lastGB,
int lastExtIndex)
{
- DBG_OBJ_MSGF_O ("border", 0, oofm, "<b>findFloatIndex</b> (%p, %d)",
- lastGB, lastExtIndex);
- DBG_OBJ_MSG_START_O (oofm);
+ DBG_OBJ_ENTER_O ("border", 0, oofm, "findFloatIndex", "%p, %d",
+ lastGB, lastExtIndex);
Float key (oofm, NULL, lastGB, lastExtIndex);
key.setIndex (type, -1); // for debugging
@@ -345,16 +344,15 @@ int OutOfFlowMgr::SortedFloatsVector::findFloatIndex (Textblock *lastGB,
//}
DBG_OBJ_MSGF_O ("border", 1, oofm, "=> r = %d", r);
- DBG_OBJ_MSG_END_O (oofm);
+ DBG_OBJ_LEAVE_O (oofm);
return r;
}
int OutOfFlowMgr::SortedFloatsVector::find (Textblock *textblock, int y,
int start, int end)
{
- DBG_OBJ_MSGF_O ("border", 0, oofm, "<b>find</b> (%p, %d, %d, %d)",
- textblock, y, start, end);
- DBG_OBJ_MSG_START_O (oofm);
+ DBG_OBJ_ENTER_O ("border", 0, oofm, "find", "%p, %d, %d, %d",
+ textblock, y, start, end);
Float key (oofm, NULL, NULL, 0);
key.generatingBlock = textblock;
@@ -364,7 +362,7 @@ int OutOfFlowMgr::SortedFloatsVector::find (Textblock *textblock, int y,
int result = bsearch (&key, false, start, end, &comparator);
DBG_OBJ_MSGF_O ("border", 1, oofm, "=> result = %d", result);
- DBG_OBJ_MSG_END_O (oofm);
+ DBG_OBJ_LEAVE_O (oofm);
return result;
}
@@ -373,9 +371,8 @@ int OutOfFlowMgr::SortedFloatsVector::findFirst (Textblock *textblock,
Textblock *lastGB,
int lastExtIndex)
{
- DBG_OBJ_MSGF_O ("border", 0, oofm, "<b>findFirst</b> (%p, %d, %d, %p, %d)",
- textblock, y, h, lastGB, lastExtIndex);
- DBG_OBJ_MSG_START_O (oofm);
+ DBG_OBJ_ENTER_O ("border", 0, oofm, "findFirst", "%p, %d, %d, %p, %d",
+ textblock, y, h, lastGB, lastExtIndex);
DBG_IF_RTFL {
DBG_OBJ_MSG_O ("border", 2, oofm, "searching in list:");
@@ -420,7 +417,7 @@ int OutOfFlowMgr::SortedFloatsVector::findFirst (Textblock *textblock,
result = -1;
DBG_OBJ_MSGF_O ("border", 1, oofm, "=> result = %d", result);
- DBG_OBJ_MSG_END_O (oofm);
+ DBG_OBJ_LEAVE_O (oofm);
return result;
}
@@ -461,13 +458,12 @@ OutOfFlowMgr::TBInfo::~TBInfo ()
void OutOfFlowMgr::TBInfo::updateAllocation ()
{
- DBG_OBJ_MSG_O ("resize.oofm", 0, getWidget (), "<b>updateAllocation</b> ()");
- DBG_OBJ_MSG_START_O (getWidget ());
+ DBG_OBJ_ENTER0_O ("resize.oofm", 0, getWidget (), "updateAllocation");
update (isNowAllocated (), getNewXCB (), getNewYCB (), getNewWidth (),
getNewHeight ());
- DBG_OBJ_MSG_END_O (getWidget ());
+ DBG_OBJ_LEAVE_O (getWidget ());
}
OutOfFlowMgr::AbsolutelyPositioned::AbsolutelyPositioned (OutOfFlowMgr *oofm,
@@ -489,6 +485,9 @@ OutOfFlowMgr::OutOfFlowMgr (Textblock *containingBlock)
leftFloatsCB = new SortedFloatsVector (this, LEFT, CB);
rightFloatsCB = new SortedFloatsVector (this, RIGHT, CB);
+ DBG_OBJ_SET_NUM ("leftFloatsCB.size", leftFloatsCB->size());
+ DBG_OBJ_SET_NUM ("rightFloatsCB.size", rightFloatsCB->size());
+
leftFloatsAll = new Vector<Float> (1, true);
rightFloatsAll = new Vector<Float> (1, true);
@@ -539,11 +538,10 @@ OutOfFlowMgr::~OutOfFlowMgr ()
void OutOfFlowMgr::sizeAllocateStart (Textblock *caller, Allocation *allocation)
{
- DBG_OBJ_MSGF ("resize.oofm", 0,
- "<b>sizeAllocateStart</b> (%p, (%d, %d, %d * (%d + %d)))",
- caller, allocation->x, allocation->y, allocation->width,
- allocation->ascent, allocation->descent);
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("resize.oofm", 0, "sizeAllocateStart",
+ "%p, (%d, %d, %d * (%d + %d))",
+ caller, allocation->x, allocation->y, allocation->width,
+ allocation->ascent, allocation->descent);
getTextblock(caller)->allocation = *allocation;
getTextblock(caller)->wasAllocated = true;
@@ -566,13 +564,12 @@ void OutOfFlowMgr::sizeAllocateStart (Textblock *caller, Allocation *allocation)
lastAllocatedLeftFloat = lastAllocatedRightFloat = -1;
}
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
void OutOfFlowMgr::sizeAllocateEnd (Textblock *caller)
{
- DBG_OBJ_MSGF ("resize.oofm", 0, "<b>sizeAllocateEnd</b> (%p)", caller);
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("resize.oofm", 0, "sizeAllocateEnd", "%p", caller);
// (Later, absolutely positioned blocks have to be allocated.)
@@ -616,7 +613,7 @@ void OutOfFlowMgr::sizeAllocateEnd (Textblock *caller)
Textblock *tb = key->getTypedValue();
tbInfo->updateAllocation ();
- tbInfo->availWidth = tb->getAvailWidth ();
+ tbInfo->lineBreakWidth = tb->getLineBreakWidth ();
}
// There are cases where some allocated floats (TODO: later also
@@ -638,16 +635,33 @@ void OutOfFlowMgr::sizeAllocateEnd (Textblock *caller)
containingBlock->oofSizeChanged (extremesChanged);
}
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
+}
+
+void OutOfFlowMgr::containerSizeChangedForChildren ()
+{
+ DBG_OBJ_ENTER0 ("resize", 0, "containerSizeChangedForChildren");
+
+ DBG_OBJ_MSGF ("resize", 0,
+ "%d left floats, %d right floats %d abspos",
+ leftFloatsAll->size (), rightFloatsAll->size (),
+ absolutelyPositioned->size());
+
+ for (int i = 0; i < leftFloatsAll->size (); i++)
+ leftFloatsAll->get(i)->getWidget()->containerSizeChanged ();
+ for (int i = 0; i < rightFloatsAll->size (); i++)
+ rightFloatsAll->get(i)->getWidget()->containerSizeChanged ();
+ for (int i = 0; i < absolutelyPositioned->size(); i++)
+ absolutelyPositioned->get(i)->widget->containerSizeChanged ();
+
+ DBG_OBJ_LEAVE ();
}
bool OutOfFlowMgr::hasRelationChanged (TBInfo *tbInfo, int *minFloatPos,
Widget **minFloat)
{
- DBG_OBJ_MSGF ("resize.oofm", 0,
- "<b>hasRelationChanged</b> (<i>widget:</i> %p, ...)",
- tbInfo->getWidget ());
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("resize.oofm", 0, "hasRelationChanged",
+ "<i>widget:</i> %p, ...", tbInfo->getWidget ());
int leftMinPos, rightMinPos;
Widget *leftMinFloat, *rightMinFloat;
@@ -680,17 +694,16 @@ bool OutOfFlowMgr::hasRelationChanged (TBInfo *tbInfo, int *minFloatPos,
else
DBG_OBJ_MSG ("resize.oofm", 1, "has not changed");
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
return c1 || c2;
}
bool OutOfFlowMgr::hasRelationChanged (TBInfo *tbInfo, Side side,
int *minFloatPos, Widget **minFloat)
{
- DBG_OBJ_MSGF ("resize.oofm", 0,
- "<b>hasRelationChanged</b> (<i>widget:</i> %p, %s, ...)",
- tbInfo->getWidget (), side == LEFT ? "LEFT" : "RIGHT");
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("resize.oofm", 0, "hasRelationChanged",
+ "<i>widget:</i> %p, %s, ...",
+ tbInfo->getWidget (), side == LEFT ? "LEFT" : "RIGHT");
SortedFloatsVector *list = side == LEFT ? leftFloatsCB : rightFloatsCB;
bool changed = false;
@@ -709,8 +722,8 @@ bool OutOfFlowMgr::hasRelationChanged (TBInfo *tbInfo, Side side,
int newFlx =
calcFloatX (vloat, side,
- gba->x - containingBlockAllocation.x,
- gba->width, vloat->generatingBlock->getAvailWidth ());
+ gba->x - containingBlockAllocation.x, gba->width,
+ vloat->generatingBlock->getLineBreakWidth ());
int newFly = vloat->generatingBlock->getAllocation()->y
- containingBlockAllocation.y + vloat->yReal;
@@ -758,7 +771,7 @@ bool OutOfFlowMgr::hasRelationChanged (TBInfo *tbInfo, Side side,
else
DBG_OBJ_MSG ("resize.oofm", 1, "has not changed");
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
return changed;
}
@@ -778,10 +791,8 @@ bool OutOfFlowMgr::hasRelationChanged (bool oldTBAlloc,
int newFlw, int newFlh,
Side side, int *floatPos)
{
- DBG_OBJ_MSGF ("resize.oofm", 0,
- "<b>hasRelationChanged</b> (<i>see below</i>, %s, ...)",
- side == LEFT ? "LEFT" : "RIGHT");
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("resize.oofm", 0, "hasRelationChanged",
+ "<i>see below</i>, %s, ...", side == LEFT ? "LEFT" : "RIGHT");
if (oldTBAlloc)
DBG_OBJ_MSGF ("resize.oofm", 1, "old TB: %d, %d; %d * %d",
@@ -884,16 +895,23 @@ bool OutOfFlowMgr::hasRelationChanged (bool oldTBAlloc,
else
DBG_OBJ_MSG ("resize.oofm", 1, "has not changed");
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
return result;
}
bool OutOfFlowMgr::doFloatsExceedCB (Side side)
{
- DBG_OBJ_MSGF ("resize.oofm", 0, "<b>doFloatsExceedCB</b> (%s)",
- side == LEFT ? "LEFT" : "RIGHT");
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("resize.oofm", 0, "doFloatsExceedCB", "%s",
+ side == LEFT ? "LEFT" : "RIGHT");
+
+ // This method is called to determine whether the *requisition* of
+ // the CB must be recalculated. So, we check the float allocations
+ // against the *requisition* of the CB, which may (e. g. within
+ // tables) differ from the new allocation. (Generally, a widget may
+ // allocated at a different size.)
+ core::Requisition cbReq;
+ containingBlock->sizeRequest (&cbReq);
SortedFloatsVector *list = side == LEFT ? leftFloatsCB : rightFloatsCB;
bool exceeds = false;
@@ -909,14 +927,10 @@ bool OutOfFlowMgr::doFloatsExceedCB (Side side)
"(%d, %d, %d * %d)?",
fla->x, fla->y, fla->width, fla->ascent + fla->descent,
containingBlockAllocation.x, containingBlockAllocation.y,
- containingBlockAllocation.width,
- containingBlockAllocation.ascent
- + containingBlockAllocation.descent);
- if (fla->x + fla->width >
- containingBlockAllocation.x + containingBlockAllocation.width ||
- fla->y + fla->ascent + fla->descent >
- containingBlockAllocation.y + containingBlockAllocation.ascent
- + containingBlockAllocation.descent) {
+ cbReq.width, cbReq.ascent + cbReq.descent);
+ if (fla->x + fla->width > containingBlockAllocation.x + cbReq.width ||
+ fla->y + fla->ascent + fla->descent
+ > containingBlockAllocation.y + cbReq.ascent + cbReq.descent) {
exceeds = true;
DBG_OBJ_MSG ("resize.oofm", 2, "Yes.");
} else
@@ -927,16 +941,15 @@ bool OutOfFlowMgr::doFloatsExceedCB (Side side)
DBG_OBJ_MSG_END ();
DBG_OBJ_MSGF ("resize.oofm", 1, "=> %s", exceeds ? "true" : "false");
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
return exceeds;
}
bool OutOfFlowMgr::haveExtremesChanged (Side side)
{
- DBG_OBJ_MSGF ("resize.oofm", 0, "<b>haveExtremesChanged</b> (%s)",
- side == LEFT ? "LEFT" : "RIGHT");
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("resize.oofm", 0, "haveExtremesChanged", "%s",
+ side == LEFT ? "LEFT" : "RIGHT");
// This is quite different from doFloatsExceedCB, since there is no
// counterpart to getExtremes, as sizeAllocate is a counterpart to
@@ -986,13 +999,16 @@ bool OutOfFlowMgr::haveExtremesChanged (Side side)
}
DBG_OBJ_MSGF ("resize.oofm", 1, "=> %s", changed ? "true" : "false");
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
return changed;
}
void OutOfFlowMgr::moveFromGBToCB (Side side)
{
+ DBG_OBJ_ENTER ("oofm.resize", 0, "moveFromGBToCB", "%s",
+ side == LEFT ? "LEFT" : "RIGHT");
+
SortedFloatsVector *dest = side == LEFT ? leftFloatsCB : rightFloatsCB;
int *floatsMark = side == LEFT ? &leftFloatsMark : &rightFloatsMark;
@@ -1007,20 +1023,24 @@ void OutOfFlowMgr::moveFromGBToCB (Side side)
// "vloat->indexCBList == -1": prevent copying the vloat twice.
if (vloat->indexCBList == -1 && vloat->mark == mark) {
dest->put (vloat);
- //printf("[%p] moving %s float %p (%s %p, mark %d) to CB list\n",
- // containingBlock, side == LEFT ? "left" : "right",
- // vloat, vloat->widget->getClassName(), vloat->widget,
- // vloat->mark);
+ DBG_OBJ_MSGF ("oofm.resize", 1,
+ "moving float %p (mark %d) to CB list\n",
+ vloat->getWidget (), vloat->mark);
+ DBG_OBJ_SET_NUM (side == LEFT ?
+ "leftFloatsCB.size" : "rightFloatsCB.size",
+ dest->size());
+ DBG_OBJ_ARRATTRSET_PTR (side == LEFT ?
+ "leftFloatsCB" : "rightFloatsCB",
+ dest->size() - 1, "widget",
+ vloat->getWidget ());
+
}
}
}
*floatsMark = 0;
- //printf ("[%p] new %s list:\n",
- // containingBlock, side == LEFT ? "left" : "right");
- //for (int i = 0; i < dest->size(); i++)
- // printf (" %d: %s\n", i, dest->get(i)->toString());
+ DBG_OBJ_LEAVE ();
}
void OutOfFlowMgr::sizeAllocateFloats (Side side, int newLastAllocatedFloat)
@@ -1029,11 +1049,10 @@ void OutOfFlowMgr::sizeAllocateFloats (Side side, int newLastAllocatedFloat)
int *lastAllocatedFloat =
side == LEFT ? &lastAllocatedLeftFloat : &lastAllocatedRightFloat;
- DBG_OBJ_MSGF ("resize.oofm", 0,
- "<b>sizeAllocateFloats</b> (%s, [%d ->] %d [size = %d])",
- side == LEFT ? "LEFT" : "RIGHT", *lastAllocatedFloat,
- newLastAllocatedFloat, list->size ());
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("resize.oofm", 0, "sizeAllocateFloats",
+ "%s, [%d ->] %d [size = %d]",
+ side == LEFT ? "LEFT" : "RIGHT", *lastAllocatedFloat,
+ newLastAllocatedFloat, list->size ());
Allocation *cba = &containingBlockAllocation;
@@ -1042,11 +1061,11 @@ void OutOfFlowMgr::sizeAllocateFloats (Side side, int newLastAllocatedFloat)
ensureFloatSize (vloat);
Allocation *gba = getAllocation (vloat->generatingBlock);
- int availWidth = vloat->generatingBlock->getAvailWidth();
+ int lineBreakWidth = vloat->generatingBlock->getLineBreakWidth();
Allocation childAllocation;
childAllocation.x = cba->x +
- calcFloatX (vloat, side, gba->x - cba->x, gba->width, availWidth);
+ calcFloatX (vloat, side, gba->x - cba->x, gba->width, lineBreakWidth);
childAllocation.y = gba->y + vloat->yReal;
childAllocation.width = vloat->size.width;
childAllocation.ascent = vloat->size.ascent;
@@ -1057,7 +1076,7 @@ void OutOfFlowMgr::sizeAllocateFloats (Side side, int newLastAllocatedFloat)
*lastAllocatedFloat = newLastAllocatedFloat;
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
@@ -1067,41 +1086,49 @@ void OutOfFlowMgr::sizeAllocateFloats (Side side, int newLastAllocatedFloat)
* gbX is given relative to the CB, as is the return value.
*/
int OutOfFlowMgr::calcFloatX (Float *vloat, Side side, int gbX, int gbWidth,
- int gbAvailWidth)
+ int gbLineBreakWidth)
{
- DBG_OBJ_MSGF ("resize.oofm", 0, "<b>calcFloatX</b> (%p, %s, %d, %d, %d)",
- vloat->getWidget (), side == LEFT ? "LEFT" : "RIGHT", gbX,
- gbWidth, gbAvailWidth);
- DBG_OBJ_MSG_START ();
-
- int gbActualWidth, x;
+ DBG_OBJ_ENTER ("resize.common", 0, "calcFloatX", "%p, %s, %d, %d, %d",
+ vloat->getWidget (), side == LEFT ? "LEFT" : "RIGHT", gbX,
+ gbWidth, gbLineBreakWidth);
+ int x;
switch (side) {
case LEFT:
// Left floats are always aligned on the left side of the
- // generator (content, not allocation).
+ // generator (content, not allocation) ...
x = gbX + vloat->generatingBlock->getStyle()->boxOffsetX();
DBG_OBJ_MSGF ("resize.oofm", 1, "left: x = %d + %d = %d",
gbX, vloat->generatingBlock->getStyle()->boxOffsetX(), x);
+ // ... but when the float exceeds the line break width of the
+ // container, it is corrected (but not left of the container).
+ // This way, we save space and, especially within tables, avoid
+ // some problems.
+ if (wasAllocated (containingBlock) &&
+ x + vloat->size.width > containingBlock->getLineBreakWidth ()) {
+ x = max (0, containingBlock->getLineBreakWidth () - vloat->size.width);
+ DBG_OBJ_MSGF ("resize.common", 1,
+ "corrected to: max (0, %d - %d) = %d",
+ containingBlock->getLineBreakWidth (), vloat->size.width,
+ x);
+ }
break;
case RIGHT:
- // In some cases, the actual (allocated) width is too large; we
- // use the "available" width here.
- gbActualWidth = min (gbWidth, gbAvailWidth);
- DBG_OBJ_MSGF ("resize.oofm", 1,
- "right: gbActualWidth = min (%d, %d) = %d",
- gbWidth, gbAvailWidth, gbActualWidth);
-
// Similar for right floats, but in this case, floats are
// shifted to the right when they are too big (instead of
// shifting the generator to the right).
- x = max (gbX + gbActualWidth - vloat->size.width
+
+ // Notice that not the actual width, but the line break width is
+ // used. (This changed for GROWS, where the width of a textblock
+ // is often smaller that the line break.)
+
+ x = max (gbX + gbLineBreakWidth - vloat->size.width
- vloat->generatingBlock->getStyle()->boxRestWidth(),
// Do not exceed CB allocation:
0);
- DBG_OBJ_MSGF ("resize.oofm", 1, "x = max (%d + %d - %d - %d, 0) = %d",
- gbX, gbActualWidth, vloat->size.width,
+ DBG_OBJ_MSGF ("resize.common", 1, "x = max (%d + %d - %d - %d, 0) = %d",
+ gbX, gbLineBreakWidth, vloat->size.width,
vloat->generatingBlock->getStyle()->boxRestWidth(), x);
break;
@@ -1111,7 +1138,7 @@ int OutOfFlowMgr::calcFloatX (Float *vloat, Side side, int gbX, int gbWidth,
break;
}
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
return x;
}
@@ -1190,8 +1217,8 @@ void OutOfFlowMgr::addWidgetInFlow (Textblock *textblock,
void OutOfFlowMgr::addWidgetOOF (Widget *widget, Textblock *generatingBlock,
int externalIndex)
{
- DBG_OBJ_MSGF ("construct.oofm", 0, "<b>addWidgetOOF</b> (%p, %p, %d)",
- widget, generatingBlock, externalIndex);
+ DBG_OBJ_ENTER ("construct.oofm", 0, "addWidgetOOF", "%p, %p, %d",
+ widget, generatingBlock, externalIndex);
if (isWidgetFloat (widget)) {
TBInfo *tbInfo = getTextblock (generatingBlock);
@@ -1206,13 +1233,17 @@ void OutOfFlowMgr::addWidgetOOF (Widget *widget, Textblock *generatingBlock,
case FLOAT_LEFT:
leftFloatsAll->put (vloat);
DBG_OBJ_SET_NUM ("leftFloatsAll.size", leftFloatsAll->size());
+ DBG_OBJ_ARRATTRSET_PTR ("leftFloatsAll", leftFloatsAll->size() - 1,
+ "widget", vloat->getWidget ());
+
widget->parentRef = createRefLeftFloat (leftFloatsAll->size() - 1);
tbInfo->leftFloatsGB->put (vloat);
if (wasAllocated (generatingBlock)) {
leftFloatsCB->put (vloat);
- //printf ("[%p] adding left float %p (%s %p) to CB list\n",
- // containingBlock, vloat, widget->getClassName(), widget);
+ DBG_OBJ_SET_NUM ("leftFloatsCB.size", leftFloatsCB->size());
+ DBG_OBJ_ARRATTRSET_PTR ("leftFloatsCB", leftFloatsCB->size() - 1,
+ "widget", vloat->getWidget ());
} else {
if (tbInfo->index < lastLeftTBIndex)
leftFloatsMark++;
@@ -1230,13 +1261,17 @@ void OutOfFlowMgr::addWidgetOOF (Widget *widget, Textblock *generatingBlock,
case FLOAT_RIGHT:
rightFloatsAll->put (vloat);
DBG_OBJ_SET_NUM ("rightFloatsAll.size", rightFloatsAll->size());
+ DBG_OBJ_ARRATTRSET_PTR ("rightFloatsAll", rightFloatsAll->size() - 1,
+ "widget", vloat->getWidget ());
+
widget->parentRef = createRefRightFloat (rightFloatsAll->size() - 1);
tbInfo->rightFloatsGB->put (vloat);
if (wasAllocated (generatingBlock)) {
rightFloatsCB->put (vloat);
- //printf ("[%p] adding right float %p (%s %p) to CB list\n",
- // containingBlock, vloat, widget->getClassName(), widget);
+ DBG_OBJ_SET_NUM ("rightFloatsCB.size", rightFloatsCB->size());
+ DBG_OBJ_ARRATTRSET_PTR ("rightFloatsCB", rightFloatsCB->size() - 1,
+ "widget", vloat->getWidget ());
} else {
if (tbInfo->index < lastRightTBIndex)
rightFloatsMark++;
@@ -1275,6 +1310,8 @@ void OutOfFlowMgr::addWidgetOOF (Widget *widget, Textblock *generatingBlock,
} else
// May be extended.
assertNotReached();
+
+ DBG_OBJ_LEAVE ();
}
void OutOfFlowMgr::moveExternalIndices (Textblock *generatingBlock,
@@ -1310,8 +1347,7 @@ OutOfFlowMgr::Float *OutOfFlowMgr::findFloatByWidget (Widget *widget)
void OutOfFlowMgr::markSizeChange (int ref)
{
- DBG_OBJ_MSGF ("resize.oofm", 0, "<b>markSizeChange</b> (%d)", ref);
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("resize.oofm", 0, "markSizeChange", "%d", ref);
if (isRefFloat (ref)) {
Float *vloat;
@@ -1331,6 +1367,11 @@ void OutOfFlowMgr::markSizeChange (int ref)
vloat->dirty = vloat->sizeChangedSinceLastAllocation = true;
+ DBG_OBJ_SET_BOOL_O (vloat->getWidget (), "<Float>.dirty", vloat->dirty);
+ DBG_OBJ_SET_BOOL_O (vloat->getWidget (),
+ "<Float>.sizeChangedSinceLastAllocation",
+ vloat->sizeChangedSinceLastAllocation);
+
// The generating block is told directly about this. (Others later, in
// sizeAllocateEnd.) Could be faster (cf. hasRelationChanged, which
// differentiates many special cases), but the size is not known yet,
@@ -1341,7 +1382,7 @@ void OutOfFlowMgr::markSizeChange (int ref)
} else
assertNotReached();
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
@@ -1404,9 +1445,8 @@ void OutOfFlowMgr::tellPosition (Widget *widget, int yReq)
void OutOfFlowMgr::tellFloatPosition (Widget *widget, int yReq)
{
- DBG_OBJ_MSGF ("resize.oofm", 0, "<b>tellFloatPosition</b> (%p, %d)",
- widget, yReq);
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("resize.oofm", 0, "tellFloatPosition", "%p, %d",
+ widget, yReq);
assert (yReq >= 0);
@@ -1483,7 +1523,7 @@ void OutOfFlowMgr::tellFloatPosition (Widget *widget, int yReq)
DBG_OBJ_MSGF ("resize.oofm", 1, "vloat->yReq = %d, vloat->yReal = %d",
vloat->yReq, vloat->yReal);
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
bool OutOfFlowMgr::collidesV (Float *vloat, Float *other, SFVType type,
@@ -1493,11 +1533,9 @@ bool OutOfFlowMgr::collidesV (Float *vloat, Float *other, SFVType type,
// vloat->yReal; never to vloat->allocation->y, even when the GBs are
// different. Used only in tellPosition.
- DBG_OBJ_MSGF ("resize.oofm", 0,
- "<b>collides</b> (#%d [%p], #%d [%p], ...)",
- vloat->getIndex (type), vloat->getWidget (),
- other->getIndex (type), other->getWidget ());
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("resize.oofm", 0, "collides", "#%d [%p], #%d [%p], ...",
+ vloat->getIndex (type), vloat->getWidget (),
+ other->getIndex (type), other->getWidget ());
bool result;
@@ -1551,7 +1589,7 @@ bool OutOfFlowMgr::collidesV (Float *vloat, Float *other, SFVType type,
else
DBG_OBJ_MSG ("resize.oofm", 1, "does not collide");
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
return result;
}
@@ -1565,7 +1603,7 @@ bool OutOfFlowMgr::collidesH (Float *vloat, Float *other, SFVType type)
if (vloat->generatingBlock == other->generatingBlock)
collidesH = vloat->size.width + other->size.width
+ vloat->generatingBlock->getStyle()->boxDiffWidth()
- > vloat->generatingBlock->getAvailWidth();
+ > vloat->generatingBlock->getLineBreakWidth();
else {
assert (wasAllocated (vloat->generatingBlock));
assert (wasAllocated (other->generatingBlock));
@@ -1582,7 +1620,7 @@ bool OutOfFlowMgr::collidesH (Float *vloat, Float *other, SFVType type)
vloat->getWidget()->getStyle()->vloat == FLOAT_LEFT ?
LEFT : RIGHT,
gba->x, gba->width,
- vloat->generatingBlock->getAvailWidth ());
+ vloat->generatingBlock->getLineBreakWidth ());
// Generally: right border of the left float > left border of
// the right float (all in canvas coordinates).
@@ -1638,8 +1676,7 @@ void OutOfFlowMgr::getFloatsListsAndSide (Float *vloat,
void OutOfFlowMgr::getSize (Requisition *cbReq, int *oofWidth, int *oofHeight)
{
- DBG_OBJ_MSG ("resize.oofm", 0, "<b>getSize</b> ()");
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER0 ("resize.oofm", 0, "getSize");
int oofWidthAbsPos, oofHeightAbsPos;
getAbsolutelyPositionedSize (cbReq, &oofWidthAbsPos, &oofHeightAbsPos);
@@ -1655,22 +1692,22 @@ void OutOfFlowMgr::getSize (Requisition *cbReq, int *oofWidth, int *oofHeight)
"=> (a: %d, l: %d, r: %d => %d) * (a: %d, l: %d, r: %d => %d)",
oofWidthAbsPos, oofWidthtLeft, oofWidthRight, *oofWidth,
oofHeightAbsPos, oofHeightLeft, oofHeightRight, *oofHeight);
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
void OutOfFlowMgr::getFloatsSize (Requisition *cbReq, Side side, int *width,
int *height)
{
- DBG_OBJ_MSGF ("resize.oofm", 0,
- "<b>getFloatsSize</b> ((%d * (%d + %d), %s, ...)",
- cbReq->width, cbReq->ascent, cbReq->descent,
- side == LEFT ? "LEFT" : "RIGHT");
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("resize.oofm", 0, "getFloatsSize", "(%d * (%d + %d), %s, ...",
+ cbReq->width, cbReq->ascent, cbReq->descent,
+ side == LEFT ? "LEFT" : "RIGHT");
SortedFloatsVector *list = getFloatsListForTextblock (containingBlock, side);
*width = *height = 0;
+ DBG_OBJ_MSGF ("resize.oofm", 1, "%d floats on this side", list->size());
+
for (int i = 0; i < list->size(); i++) {
Float *vloat = list->get(i);
@@ -1681,13 +1718,13 @@ void OutOfFlowMgr::getFloatsSize (Requisition *cbReq, Side side, int *width,
if (vloat->generatingBlock == containingBlock) {
x = calcFloatX (vloat, side, 0, cbReq->width,
- vloat->generatingBlock->getAvailWidth ());
+ vloat->generatingBlock->getLineBreakWidth ());
y = vloat->yReal;
} else {
Allocation *gba = getAllocation(vloat->generatingBlock);
x = calcFloatX (vloat, side,
gba->x - containingBlockAllocation.x, gba->width,
- vloat->generatingBlock->getAvailWidth ());
+ vloat->generatingBlock->getLineBreakWidth ());
y = gba->y - containingBlockAllocation.y + vloat->yReal;
}
@@ -1707,15 +1744,14 @@ void OutOfFlowMgr::getFloatsSize (Requisition *cbReq, Side side, int *width,
vloat->getWidget (), vloat->generatingBlock);
}
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
void OutOfFlowMgr::getExtremes (Extremes *cbExtr, int *oofMinWidth,
int *oofMaxWidth)
{
- DBG_OBJ_MSGF ("resize.oofm", 0, "<b>getExtremes</b> ((%d / %d), ...)",
- cbExtr->minWidth, cbExtr->maxWidth);
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("resize.oofm", 0, "getExtremes", "(%d / %d), ...",
+ cbExtr->minWidth, cbExtr->maxWidth);
int oofMinWidthAbsPos, oofMaxWidthAbsPos;
getAbsolutelyPositionedExtremes (cbExtr, &oofMinWidthAbsPos,
@@ -1733,17 +1769,15 @@ void OutOfFlowMgr::getExtremes (Extremes *cbExtr, int *oofMinWidth,
oofMinWidthAbsPos, oofMinWidthtLeft, oofMinWidthRight,
*oofMinWidth, oofMaxWidthAbsPos, oofMaxWidthLeft,
oofMaxWidthRight, *oofMaxWidth);
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
void OutOfFlowMgr::getFloatsExtremes (Extremes *cbExtr, Side side,
int *minWidth, int *maxWidth)
{
- DBG_OBJ_MSGF ("resize.oofm", 0,
- "<b>getFloatsExtremes</b> ((%d / %d), %s, ...)",
- cbExtr->minWidth, cbExtr->maxWidth,
- side == LEFT ? "LEFT" : "RIGHT");
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("resize.oofm", 0, "getFloatsExtremes", "(%d / %d), %s, ...",
+ cbExtr->minWidth, cbExtr->maxWidth,
+ side == LEFT ? "LEFT" : "RIGHT");
*minWidth = *maxWidth = 0;
@@ -1763,19 +1797,6 @@ void OutOfFlowMgr::getFloatsExtremes (Extremes *cbExtr, Side side,
vloat->getWidget (), vloat->generatingBlock,
extr.minWidth, extr.maxWidth);
- if (isAbsLength (vloat->getWidget()->getStyle()->width)) {
- int width = absLengthVal (vloat->getWidget()->getStyle()->width);
- if (extr.minWidth < width)
- extr.minWidth = width;
- if (extr.maxWidth > width)
- // maxWidth not smaller than minWidth
- extr.maxWidth = max (width, extr.minWidth);
-
- DBG_OBJ_MSGF ("resize.oofm", 1,
- "corrected by absolute width %d: %d / %d",
- width, extr.minWidth, extr.maxWidth);
- }
-
// TODO: Or zero (instead of rightDiff) for right floats?
*minWidth =
max (*minWidth,
@@ -1789,7 +1810,7 @@ void OutOfFlowMgr::getFloatsExtremes (Extremes *cbExtr, Side side,
vloat->getWidget (), vloat->generatingBlock);
}
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
// Returns "false" when borders cannot yet determined; *leftDiff and
@@ -1797,10 +1818,9 @@ void OutOfFlowMgr::getFloatsExtremes (Extremes *cbExtr, Side side,
bool OutOfFlowMgr::getFloatDiffToCB (Float *vloat, int *leftDiff,
int *rightDiff)
{
- DBG_OBJ_MSGF ("resize.oofm", 0,
- "<b>getDiffToCB</b> (float %p [generated by %p], ...)",
- vloat->getWidget (), vloat->generatingBlock);
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("resize.oofm", 0, "getDiffToCB",
+ "float %p [generated by %p], ...",
+ vloat->getWidget (), vloat->generatingBlock);
bool result;
@@ -1834,7 +1854,7 @@ bool OutOfFlowMgr::getFloatDiffToCB (Float *vloat, int *leftDiff,
result = false;
}
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
return result;
}
@@ -1882,10 +1902,9 @@ int OutOfFlowMgr::getRightBorder (Textblock *textblock, int y, int h,
int OutOfFlowMgr::getBorder (Textblock *textblock, Side side, int y, int h,
Textblock *lastGB, int lastExtIndex)
{
- DBG_OBJ_MSGF ("border", 0, "<b>getBorder</b> (%p, %s, %d, %d, %p, %d)",
- textblock, side == LEFT ? "LEFT" : "RIGHT", y, h,
- lastGB, lastExtIndex);
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("border", 0, "getBorder", "%p, %s, %d, %d, %p, %d",
+ textblock, side == LEFT ? "LEFT" : "RIGHT", y, h,
+ lastGB, lastExtIndex);
SortedFloatsVector *list = getFloatsListForTextblock (textblock, side);
int first = list->findFirst (textblock, y, h, lastGB, lastExtIndex);
@@ -1894,7 +1913,7 @@ int OutOfFlowMgr::getBorder (Textblock *textblock, Side side, int y, int h,
if (first == -1) {
// No float.
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
return 0;
} else {
// It is not sufficient to find the first float, since a line
@@ -1931,12 +1950,12 @@ int OutOfFlowMgr::getBorder (Textblock *textblock, Side side, int y, int h,
fla->x, fla->width, tba->x, thisBorder);
} else {
// See also calcFloatX.
- int tbAvWidth = textblock->getAvailWidth ();
- thisBorder = tba->x + min (tba->width, tbAvWidth) - fla->x;
+ thisBorder =
+ tba->x + textblock->getLineBreakWidth () - fla->x;
DBG_OBJ_MSGF ("border", 1,
- "not GB: thisBorder = %d + min (%d, %d) - %d "
+ "not GB: thisBorder = %d + %d - %d "
"= %d",
- tba->x, tba->width, tbAvWidth, fla->x,
+ tba->x, textblock->getLineBreakWidth (), fla->x,
thisBorder);
}
}
@@ -1946,7 +1965,7 @@ int OutOfFlowMgr::getBorder (Textblock *textblock, Side side, int y, int h,
}
}
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
return border;
}
}
@@ -1955,12 +1974,22 @@ int OutOfFlowMgr::getBorder (Textblock *textblock, Side side, int y, int h,
OutOfFlowMgr::SortedFloatsVector *OutOfFlowMgr::getFloatsListForTextblock
(Textblock *textblock, Side side)
{
- if (wasAllocated (textblock))
- return side == LEFT ? leftFloatsCB : rightFloatsCB;
- else {
+ DBG_OBJ_ENTER ("oofm.common", 1, "getFloatsListForTextblock", "%p, %s",
+ textblock, side == LEFT ? "LEFT" : "RIGHT");
+
+ OutOfFlowMgr::SortedFloatsVector *list;
+
+ if (wasAllocated (textblock)) {
+ DBG_OBJ_MSG ("oofm.common", 2, "returning <b>CB</b> list");
+ list = side == LEFT ? leftFloatsCB : rightFloatsCB;
+ } else {
+ DBG_OBJ_MSG ("oofm.common", 2, "returning <b>GB</b> list");
TBInfo *tbInfo = getTextblock (textblock);
- return side == LEFT ? tbInfo->leftFloatsGB : tbInfo->rightFloatsGB;
+ list = side == LEFT ? tbInfo->leftFloatsGB : tbInfo->rightFloatsGB;
}
+
+ DBG_OBJ_LEAVE ();
+ return list;
}
@@ -1985,16 +2014,15 @@ bool OutOfFlowMgr::hasFloatRight (Textblock *textblock, int y, int h,
bool OutOfFlowMgr::hasFloat (Textblock *textblock, Side side, int y, int h,
Textblock *lastGB, int lastExtIndex)
{
- DBG_OBJ_MSGF ("border", 0, "<b>hasFloat</b> (%p, %s, %d, %d, %p, %d)",
- textblock, side == LEFT ? "LEFT" : "RIGHT", y, h,
- lastGB, lastExtIndex);
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("border", 0, "hasFloat", "%p, %s, %d, %d, %p, %d",
+ textblock, side == LEFT ? "LEFT" : "RIGHT", y, h,
+ lastGB, lastExtIndex);
SortedFloatsVector *list = getFloatsListForTextblock (textblock, side);
int first = list->findFirst (textblock, y, h, lastGB, lastExtIndex);
DBG_OBJ_MSGF ("border", 1, "first = %d", first);
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
return first != -1;
}
@@ -2003,8 +2031,7 @@ bool OutOfFlowMgr::hasFloat (Textblock *textblock, Side side, int y, int h,
*/
int OutOfFlowMgr::getClearPosition (Textblock *tb)
{
- DBG_OBJ_MSGF ("resize.oofm", 0, "<b>getClearPosition</b> (%p)", tb);
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("resize.oofm", 0, "getClearPosition", "%p", tb);
int pos;
@@ -2024,16 +2051,15 @@ int OutOfFlowMgr::getClearPosition (Textblock *tb)
pos = 0;
DBG_OBJ_MSGF ("resize.oofm", 1, "=> %d", pos);
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
return pos;
}
int OutOfFlowMgr::getClearPosition (Textblock *tb, Side side)
{
- DBG_OBJ_MSGF ("resize.oofm", 0, "<b>getClearPosition</b> (%p, %s)",
- tb, side == LEFT ? "LEFT" : "RIGHT");
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("resize.oofm", 0, "getClearPosition", "%p, %s",
+ tb, side == LEFT ? "LEFT" : "RIGHT");
int pos;
@@ -2063,127 +2089,29 @@ int OutOfFlowMgr::getClearPosition (Textblock *tb, Side side)
}
DBG_OBJ_MSGF ("resize.oofm", 1, "=> %d", pos);
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
return pos;
}
void OutOfFlowMgr::ensureFloatSize (Float *vloat)
{
- if (vloat->dirty ||
- (vloat->cbAvailWidth != containingBlock->getAvailWidth () &&
- (// If the size of the containing block has changed (represented
- // currently by the available width), a recalculation of a relative
- // float width may also be necessary.
- isPerLength (vloat->getWidget()->getStyle()->width) ||
- // Similar for "auto" widths of textblocks etc.
- (vloat->getWidget()->usesHints () &&
- vloat->getWidget()->getStyle()->width == LENGTH_AUTO)))) {
- DBG_OBJ_MSGF ("resize.oofm", 0,
- "<b>ensureFloatSize</b> (%p): recalculation",
- vloat->getWidget ());
- DBG_OBJ_MSG_START ();
+ // Historical note: relative sizes (e. g. percentages) are already
+ // handled by (at this time) Layout::containerSizeChanged, so
+ // Float::dirty will be set.
- Extremes extremes;
- vloat->getWidget()->getExtremes (&extremes);
- DBG_OBJ_MSGF ("resize.oofm", 1, "getExtremes => %d / %d",
- extremes.minWidth, extremes.maxWidth);
-
- // TODO Ugly. Soon to be replaced by cleaner code? See also
- // comment in Textblock::calcWidgetSize.
-
- if (vloat->getWidget()->usesHints ()) {
- // For widths defined by CSS, similar adjustments (extremes
- // etc.) like below are necessary, to prevent CPU hogging.
-
- Length cssWidth = vloat->getWidget()->getStyle()->width;
- if (isAbsLength (cssWidth)) {
- int width = absLengthVal (cssWidth);
- DBG_OBJ_MSGF ("resize.oofm", 1, "about to set absolute width: %d",
- width);
- width = adjustFloatWidth (width, &extremes);
- vloat->getWidget()->setWidth (width);
- } else if (cssWidth == LENGTH_AUTO || isPerLength (cssWidth)) {
- // It is important that the width of the *CB* is not
- // larger than its minimal width, when the latter is set
- // as size hint; otherwise we have an endless queueResize
- // cycle (resulting in CPU hogging) when the CB is part of
- // a narrow table column. To prevent this, the width of
- // the *float* has to be limited (cf. also getExtremes).
-
- int availWidth, leftDiff, rightDiff;
- if (getFloatDiffToCB (vloat, &leftDiff, &rightDiff))
- availWidth = containingBlock->getAvailWidth()
- - (vloat->getWidget()->getStyle()->vloat == FLOAT_LEFT ?
- leftDiff : rightDiff);
- else
- // Not allocated: next allocation will take care.
- availWidth = containingBlock->getAvailWidth();
-
- int width;
-
- if (cssWidth == LENGTH_AUTO) {
- width = availWidth;
- DBG_OBJ_MSGF ("resize.oofm", 1, "setting width 'auto': %d",
- width);
- } else {
- width = multiplyWithPerLength (availWidth, cssWidth);
-
- // Some more corrections (nonsense percentage values):
- if (width < 1)
- width = 1;
- if (width > availWidth)
- width = availWidth;
-
- DBG_OBJ_MSGF ("resize.oofm", 1,
- "about to set percentage width: %d * %g -> %d",
- availWidth, perLengthVal (cssWidth), width);
- width = adjustFloatWidth (width, &extremes);
- }
+ DBG_OBJ_ENTER ("resize.oofm", 0, "ensureFloatSize", "%p",
+ vloat->getWidget ());
- vloat->getWidget()->setWidth (width);
- } else
- DBG_OBJ_MSG ("resize.oofm", 1,
- "setting width: <b>relative length? may be a bug</b>");
- } else
- DBG_OBJ_MSG ("resize.oofm", 1, "setting no width: uses no hints");
-
- // This is a bit hackish: We first request the size, then set
- // the available width (also considering the one of the
- // containing block, and the extremes of the float), then
- // request the size again, which may of course have a different
- // result. This is a fix for the bug:
- //
- // Text in floats, which are wider because of an image, are
- // broken at a too narrow width. Reproduce:
- // test/floats2.html. After the image has been loaded, the
- // text "Some text in a float." should not be broken
- // anymore.
- //
- // If the call of setWidth not is neccessary, the second call
- // will read the size from the cache, so no redundant
- // calculation is necessary.
- //
- // Furthermore, extremes are considered; especially, floats are too
- // wide, sometimes.
-
- vloat->getWidget()->sizeRequest (&vloat->size);
- DBG_OBJ_MSGF ("resize.oofm", 1, "sizeRequest (1) => %d * (%d + %d)",
- vloat->size.width, vloat->size.ascent, vloat->size.descent);
+ if (vloat->dirty) {
+ DBG_OBJ_MSG ("resize.oofm", 1, "dirty: recalculation");
- // Set width ...
- int width = vloat->size.width;
- DBG_OBJ_MSGF ("resize.oofm", 1, "new width: %d", width);
- width = adjustFloatWidth (width, &extremes);
- vloat->getWidget()->setWidth (width);
vloat->getWidget()->sizeRequest (&vloat->size);
- DBG_OBJ_MSGF ("resize.oofm", 1, "sizeRequest (2) => %d * (%d + %d)",
- vloat->size.width, vloat->size.ascent, vloat->size.descent);
-
- vloat->cbAvailWidth = containingBlock->getAvailWidth ();
+ vloat->cbLineBreakWidth = containingBlock->getLineBreakWidth ();
vloat->dirty = false;
+ DBG_OBJ_SET_BOOL_O (vloat->getWidget (), "<Float>.dirty", vloat->dirty);
- DBG_OBJ_MSGF ("resize.oofm", 1, "final size: %d * (%d + %d)",
+ DBG_OBJ_MSGF ("resize.oofm", 1, "size: %d * (%d + %d)",
vloat->size.width, vloat->size.ascent, vloat->size.descent);
DBG_OBJ_SET_NUM_O (vloat->getWidget(), "<Float>.size.width",
@@ -2194,42 +2122,9 @@ void OutOfFlowMgr::ensureFloatSize (Float *vloat)
vloat->size.descent);
// "sizeChangedSinceLastAllocation" is reset in sizeAllocateEnd()
-
- DBG_OBJ_MSG_END ();
}
-}
-
-int OutOfFlowMgr::adjustFloatWidth (int width, Extremes *extremes)
-{
- DBG_OBJ_MSGF ("resize.oofm", 0,
- "<b>adjustFloatWidth</b> (%d, (%d, %d)) [CB->availWidth = %d]",
- width, extremes->minWidth, extremes->maxWidth,
- containingBlock->getAvailWidth());
- DBG_OBJ_MSG_START ();
-
- // Consider extremes (as described above).
- if (width < extremes->minWidth) {
- width = extremes->minWidth;
- DBG_OBJ_MSGF ("resize.oofm", 1, "adjusted to minWidth: %d", width);
- }
- if (width > extremes->maxWidth) {
- width = extremes->maxWidth;
- DBG_OBJ_MSGF ("resize.oofm", 1, "adjusted to maxWidth: %d", width);
- }
- // Finally, consider the available width of the containing
- // block. Order is important: to prevent problems, the available
- // width of the float must never be larger than the one of the
- // containing block. (Somewhat hackish, will be solved cleaner with
- // GROWS.)
- if (width > containingBlock->getAvailWidth()) {
- width = containingBlock->getAvailWidth();
- DBG_OBJ_MSGF ("resize.oofm", 1, "adjusted to CB::availWidth: %d", width);
- }
-
- DBG_OBJ_MSGF ("resize.oofm", 1, "=> %d", width);
- DBG_OBJ_MSG_END ();
-
- return width;
+
+ DBG_OBJ_LEAVE ();
}
void OutOfFlowMgr::getAbsolutelyPositionedSize (Requisition *cbReq, int *width,
@@ -2250,69 +2145,8 @@ void OutOfFlowMgr::getAbsolutelyPositionedExtremes (Extremes *cbExtr,
void OutOfFlowMgr::ensureAbsolutelyPositionedSizeAndPosition
(AbsolutelyPositioned *abspos)
{
- // No work is done anymore on this, since widget sizes will be
- // redesigned before absolute positions are finished.
-
- if (abspos->dirty) {
- Style *style = abspos->widget->getStyle();
- int availWidth = containingBlock->getAvailWidth();
- int availHeight =
- containingBlock->getAvailAscent() + containingBlock->getAvailDescent();
-
- if (style->left == LENGTH_AUTO)
- abspos->xCB = 0;
- else
- abspos->xCB =
- calcValueForAbsolutelyPositioned (abspos, style->left, availWidth);
-
- if (style->top == LENGTH_AUTO)
- abspos->yCB = 0;
- else
- abspos->yCB =
- calcValueForAbsolutelyPositioned (abspos, style->top, availHeight);
-
- abspos->width = -1; // undefined
- if (style->width != LENGTH_AUTO)
- abspos->width = calcValueForAbsolutelyPositioned (abspos, style->width,
- availWidth);
- else if (style->right != LENGTH_AUTO) {
- int right = calcValueForAbsolutelyPositioned (abspos, style->right,
- availWidth);
- abspos->width = max (0, availWidth - (abspos->xCB + right));
- }
-
- abspos->height = -1; // undefined
- if (style->height != LENGTH_AUTO)
- abspos->height = calcValueForAbsolutelyPositioned (abspos,
- style->height,
- availHeight);
- else if (style->bottom != LENGTH_AUTO) {
- int bottom = calcValueForAbsolutelyPositioned (abspos, style->bottom,
- availHeight);
- abspos->height = max (0, availHeight - (abspos->yCB + bottom));
- }
-
- if (abspos->width != -1)
- abspos->widget->setWidth (abspos->width);
-
- if (abspos->height != -1) {
- abspos->widget->setAscent (abspos->height);
- abspos->widget->setDescent (0); // TODO
- }
-
- if (abspos->width == -1 || abspos->height == -1) {
- Requisition req;
- abspos->widget->sizeRequest (&req);
-
- if (abspos->width == -1)
- abspos->width = req.width;
-
- if (abspos->height == -1)
- abspos->height = req.ascent + req.descent;
- }
-
- abspos->dirty = false;
- }
+ // TODO
+ assertNotReached ();
}
int OutOfFlowMgr::calcValueForAbsolutelyPositioned
@@ -2332,7 +2166,7 @@ int OutOfFlowMgr::calcValueForAbsolutelyPositioned
void OutOfFlowMgr::sizeAllocateAbsolutelyPositioned ()
{
for (int i = 0; i < absolutelyPositioned->size(); i++) {
- Allocation *cbAllocation = getAllocation(containingBlock);
+ Allocation *cbAllocation = getAllocation (containingBlock);
AbsolutelyPositioned *abspos = absolutelyPositioned->get (i);
ensureAbsolutelyPositionedSizeAndPosition (abspos);
diff --git a/dw/outofflowmgr.hh b/dw/outofflowmgr.hh
index 429482fd..19205717 100644
--- a/dw/outofflowmgr.hh
+++ b/dw/outofflowmgr.hh
@@ -97,9 +97,9 @@ private:
respectively. -1 initially. */
int sideSpanningIndex, mark;
core::Requisition size;
- int cbAvailWidth; /* On which the calculation of relative sizes
- is based. Height not yet used, and probably
- not added before size redesign. */
+ int cbLineBreakWidth; /* On which the calculation of relative sizes
+ is based. Height not yet used, and probably
+ not added before size redesign. */
bool dirty, sizeChangedSinceLastAllocation;
Float (OutOfFlowMgr *oofm, core::Widget *widget,
@@ -172,7 +172,7 @@ private:
class TBInfo: public WidgetInfo
{
public:
- int availWidth;
+ int lineBreakWidth;
int index; // position within "tbInfos"
TBInfo *parent;
@@ -272,7 +272,7 @@ private:
void moveFromGBToCB (Side side);
void sizeAllocateFloats (Side side, int newLastAllocatedFloat);
int calcFloatX (Float *vloat, Side side, int gbX, int gbWidth,
- int gbAvailWidth);
+ int gbLineBreakWidth);
bool hasRelationChanged (TBInfo *tbInfo,int *minFloatPos,
core::Widget **minFloat);
@@ -319,7 +319,6 @@ private:
int getClearPosition (Textblock *tb, Side side);
void ensureFloatSize (Float *vloat);
- int adjustFloatWidth (int width, core::Extremes *extremes);
void tellFloatPosition (core::Widget *widget, int yReq);
@@ -395,6 +394,7 @@ public:
void sizeAllocateStart (Textblock *caller, core::Allocation *allocation);
void sizeAllocateEnd (Textblock *caller);
+ void containerSizeChangedForChildren ();
void draw (core::View *view, core::Rectangle *area);
void markSizeChange (int ref);
diff --git a/dw/ruler.cc b/dw/ruler.cc
index 2b5288c2..3fdbfb6d 100644
--- a/dw/ruler.cc
+++ b/dw/ruler.cc
@@ -28,26 +28,39 @@ namespace dw {
Ruler::Ruler ()
{
- setFlags (USES_HINTS);
- setFlags (BLOCK_LEVEL);
- unsetFlags (HAS_CONTENTS);
- availWidth = 0;
}
void Ruler::sizeRequestImpl (core::Requisition *requisition)
{
requisition->width =
- lout::misc::max (availWidth, getStyle()->boxDiffWidth ());
+ lout::misc::max (getAvailWidth (true), getStyle()->boxDiffWidth ());
requisition->ascent = getStyle()->boxOffsetY ();
requisition->descent = getStyle()->boxRestHeight ();
}
-void Ruler::setWidth (int width)
+void Ruler::getExtremesImpl (core::Extremes *extremes)
{
- if (availWidth != width) {
- availWidth = width;
- queueResize (0, false);
- }
+ extremes->minWidth = extremes->maxWidth = getStyle()->boxDiffWidth ();
+ extremes->minWidthIntrinsic = extremes->minWidth;
+ extremes->maxWidthIntrinsic = extremes->maxWidth;
+ correctExtremes (extremes);
+}
+
+bool Ruler::isBlockLevel ()
+{
+ return true;
+}
+
+void Ruler::containerSizeChangedForChildren ()
+{
+ DBG_OBJ_ENTER0 ("resize", 0, "containerSizeChangedForChildren");
+ // Nothing to do.
+ DBG_OBJ_LEAVE ();
+}
+
+bool Ruler::usesAvailWidth ()
+{
+ return true;
}
void Ruler::draw (core::View *view, core::Rectangle *area)
diff --git a/dw/ruler.hh b/dw/ruler.hh
index 863792dd..1f3491bc 100644
--- a/dw/ruler.hh
+++ b/dw/ruler.hh
@@ -15,17 +15,18 @@ namespace dw {
*/
class Ruler: public core::Widget
{
-private:
- int availWidth;
-
protected:
void sizeRequestImpl (core::Requisition *requisition);
- void setWidth (int width);
+ void getExtremesImpl (core::Extremes *extremes);
+ void containerSizeChangedForChildren ();
+ bool usesAvailWidth ();
void draw (core::View *view, core::Rectangle *area);
public:
Ruler ();
+ bool isBlockLevel ();
+
core::Iterator *iterator (core::Content::Type mask, bool atEnd);
};
diff --git a/dw/simpletablecell.cc b/dw/simpletablecell.cc
new file mode 100644
index 00000000..083deaed
--- /dev/null
+++ b/dw/simpletablecell.cc
@@ -0,0 +1,58 @@
+/*
+ * Dillo Widget
+ *
+ * Copyright 2014 Sebastian Geerken <sgeerken@dillo.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+
+#include "simpletablecell.hh"
+#include "../lout/debug.hh"
+
+namespace dw {
+
+int SimpleTableCell::CLASS_ID = -1;
+
+SimpleTableCell::SimpleTableCell (bool limitTextWidth):
+ Textblock (limitTextWidth)
+{
+ DBG_OBJ_CREATE ("dw::SimpleTableCell");
+ registerName ("dw::SimpleTableCell", &CLASS_ID);
+}
+
+SimpleTableCell::~SimpleTableCell()
+{
+ DBG_OBJ_DELETE ();
+}
+
+bool SimpleTableCell::isBlockLevel ()
+{
+ return false;
+}
+
+int SimpleTableCell::applyPerWidth (int containerWidth,
+ core::style::Length perWidth)
+{
+ return core::style::multiplyWithPerLength (containerWidth, perWidth);
+}
+
+int SimpleTableCell::applyPerHeight (int containerHeight,
+ core::style::Length perHeight)
+{
+ return core::style::multiplyWithPerLength (containerHeight, perHeight);
+}
+
+} // namespace dw
diff --git a/dw/simpletablecell.hh b/dw/simpletablecell.hh
new file mode 100644
index 00000000..a452add9
--- /dev/null
+++ b/dw/simpletablecell.hh
@@ -0,0 +1,24 @@
+#ifndef __DW_SIMPLETABLECELL_HH__
+#define __DW_SIMPLETABLECELL_HH__
+
+#include "textblock.hh"
+
+namespace dw {
+
+class SimpleTableCell: public Textblock
+{
+public:
+ static int CLASS_ID;
+
+ SimpleTableCell (bool limitTextWidth);
+ ~SimpleTableCell ();
+
+ int applyPerWidth (int containerWidth, core::style::Length perWidth);
+ int applyPerHeight (int containerHeight, core::style::Length perHeight);
+
+ bool isBlockLevel ();
+};
+
+} // namespace dw
+
+#endif // __DW_SIMPLETABLECELL_HH__
diff --git a/dw/style.hh b/dw/style.hh
index 2cc258bf..578e65c0 100644
--- a/dw/style.hh
+++ b/dw/style.hh
@@ -435,7 +435,8 @@ inline int absLengthVal(Length l) { return l >> 2; }
* When possible, do not use this function directly; it may be removed
* soon. Instead, use multiplyWithPerLength or multiplyWithPerLengthRounded.
*/
-inline double perLengthVal(Length l) { return (double)(l & ~3) / (1 << 18); }
+inline double perLengthVal_useThisOnlyForDebugging(Length l)
+{ return (double)(l & ~3) / (1 << 18); }
/** \brief Returns the value of a relative length, as a float.
*
@@ -450,7 +451,7 @@ inline double relLengthVal(Length l) { return (double)(l & ~3) / (1 << 18); }
* Use this instead of perLengthVal, when possible.
*/
inline int multiplyWithPerLength(int x, Length l) {
- return x * perLengthVal(l);
+ return x * perLengthVal_useThisOnlyForDebugging (l);
}
/**
@@ -459,8 +460,8 @@ inline int multiplyWithPerLength(int x, Length l) {
*
* (This function exists for backward compatibility.)
*/
-inline int multiplyWithPerLengthRounded (int x, Length l) {
- return lout::misc::roundInt (x * perLengthVal(l));
+inline int multiplyWithPerLengthRounded(int x, Length l) {
+ return lout::misc::roundInt (x * perLengthVal_useThisOnlyForDebugging (l));
}
inline int multiplyWithRelLength(int x, Length l) {
@@ -564,22 +565,14 @@ public:
= borderStyle.left = val; }
inline int boxOffsetX ()
- {
- return margin.left + borderWidth.left + padding.left;
- }
+ { return margin.left + borderWidth.left + padding.left; }
inline int boxRestWidth ()
- {
- return margin.right + borderWidth.right + padding.right;
- }
+ { return margin.right + borderWidth.right + padding.right; }
inline int boxDiffWidth () { return boxOffsetX () + boxRestWidth (); }
inline int boxOffsetY ()
- {
- return margin.top + borderWidth.top + padding.top;
- }
+ { return margin.top + borderWidth.top + padding.top; }
inline int boxRestHeight ()
- {
- return margin.bottom + borderWidth.bottom + padding.bottom;
- }
+ { return margin.bottom + borderWidth.bottom + padding.bottom; }
inline int boxDiffHeight () { return boxOffsetY () + boxRestHeight (); }
inline bool hasBackground ()
diff --git a/dw/table.cc b/dw/table.cc
index 565dfc9e..f8efa9da 100644
--- a/dw/table.cc
+++ b/dw/table.cc
@@ -1,7 +1,7 @@
/*
* Dillo Widget
*
- * Copyright 2005-2007 Sebastian Geerken <sgeerken@dillo.org>
+ * Copyright 2005-2007, 2014 Sebastian Geerken <sgeerken@dillo.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -34,41 +34,36 @@ Table::Table(bool limitTextWidth)
{
DBG_OBJ_CREATE ("dw::Table");
registerName ("dw::Table", &CLASS_ID);
- setFlags (BLOCK_LEVEL);
- setFlags (USES_HINTS);
setButtonSensitive(false);
this->limitTextWidth = limitTextWidth;
rowClosed = false;
- // random values
- availWidth = 100;
- availAscent = 100;
- availDescent = 0;
-
numRows = 0;
numCols = 0;
curRow = -1;
curCol = 0;
+ DBG_OBJ_SET_NUM ("numCols", numCols);
+ DBG_OBJ_SET_NUM ("numRows", numCols);
+
children = new misc::SimpleVector <Child*> (16);
colExtremes = new misc::SimpleVector<core::Extremes> (8);
colWidths = new misc::SimpleVector <int> (8);
cumHeight = new misc::SimpleVector <int> (8);
rowSpanCells = new misc::SimpleVector <int> (8);
- colSpanCells = new misc::SimpleVector <int> (8);
baseline = new misc::SimpleVector <int> (8);
rowStyle = new misc::SimpleVector <core::style::Style*> (8);
- hasColPercent = 0;
- colPercents = new misc::SimpleVector <core::style::Length> (8);
+ colWidthsUpToDateWidthColExtremes = true;
+ DBG_OBJ_SET_BOOL ("colWidthsUpToDateWidthColExtremes",
+ colWidthsUpToDateWidthColExtremes);
redrawX = 0;
redrawY = 0;
}
-
Table::~Table()
{
for (int i = 0; i < children->size (); i++) {
@@ -94,17 +89,17 @@ Table::~Table()
delete colWidths;
delete cumHeight;
delete rowSpanCells;
- delete colSpanCells;
delete baseline;
delete rowStyle;
- delete colPercents;
DBG_OBJ_DELETE ();
}
void Table::sizeRequestImpl (core::Requisition *requisition)
{
- forceCalcCellSizes ();
+ DBG_OBJ_ENTER0 ("resize", 0, "sizeRequestImpl");
+
+ forceCalcCellSizes (true);
/**
* \bug Baselines are not regarded here.
@@ -119,40 +114,44 @@ void Table::sizeRequestImpl (core::Requisition *requisition)
+ getStyle()->vBorderSpacing;
requisition->descent = 0;
+ correctRequisition (requisition, core::splitHeightPreserveDescent);
+
+ DBG_OBJ_LEAVE ();
}
void Table::getExtremesImpl (core::Extremes *extremes)
{
- if (numCols == 0) {
- extremes->minWidth = extremes->maxWidth = 0;
- return;
- }
-
- forceCalcColumnExtremes ();
+ DBG_OBJ_ENTER0 ("resize", 0, "getExtremesImpl");
- extremes->minWidth = extremes->maxWidth =
- (numCols + 1) * getStyle()->hBorderSpacing
- + getStyle()->boxDiffWidth ();
- for (int col = 0; col < numCols; col++) {
- extremes->minWidth += colExtremes->getRef(col)->minWidth;
- extremes->maxWidth += colExtremes->getRef(col)->maxWidth;
- }
- if (core::style::isAbsLength (getStyle()->width)) {
- extremes->minWidth =
- misc::max (extremes->minWidth,
- core::style::absLengthVal(getStyle()->width));
- extremes->maxWidth =
- misc::max (extremes->maxWidth,
- core::style::absLengthVal(getStyle()->width));
+ if (numCols == 0)
+ extremes->minWidth = extremes->minWidthIntrinsic = extremes->maxWidth =
+ extremes->maxWidthIntrinsic = boxDiffWidth ();
+ else {
+ forceCalcColumnExtremes ();
+
+ extremes->minWidth = extremes->minWidthIntrinsic = extremes->maxWidth =
+ extremes->maxWidthIntrinsic =
+ (numCols + 1) * getStyle()->hBorderSpacing + boxDiffWidth ();
+ for (int col = 0; col < numCols; col++) {
+ extremes->minWidth += colExtremes->getRef(col)->minWidth;
+ extremes->minWidthIntrinsic +=
+ colExtremes->getRef(col)->minWidthIntrinsic;
+ extremes->maxWidth += colExtremes->getRef(col)->maxWidth;
+ extremes->maxWidthIntrinsic +=
+ colExtremes->getRef(col)->maxWidthIntrinsic;
+ }
}
- _MSG(" Table::getExtremesImpl, {%d, %d} numCols=%d\n",
- extremes->minWidth, extremes->maxWidth, numCols);
+ correctExtremes (extremes);
+
+ DBG_OBJ_LEAVE ();
}
void Table::sizeAllocateImpl (core::Allocation *allocation)
{
- calcCellSizes ();
+ DBG_OBJ_ENTER0 ("resize", 0, "sizeAllocateImpl");
+
+ calcCellSizes (true);
/**
* \bug Baselines are not regarded here.
@@ -167,8 +166,7 @@ void Table::sizeAllocateImpl (core::Allocation *allocation)
for (int row = 0; row < numRows; row++) {
int n = row * numCols + col;
if (childDefined (n)) {
- int width =
- (children->get(n)->cell.colspanEff - 1)
+ int width = (children->get(n)->cell.colspanEff - 1)
* getStyle()->hBorderSpacing;
for (int i = 0; i < children->get(n)->cell.colspanEff; i++)
width += colWidths->get (col + i);
@@ -192,6 +190,8 @@ void Table::sizeAllocateImpl (core::Allocation *allocation)
x += colWidths->get (col) + getStyle()->hBorderSpacing;
}
+
+ DBG_OBJ_LEAVE ();
}
void Table::resizeDrawImpl ()
@@ -202,30 +202,147 @@ void Table::resizeDrawImpl ()
redrawY = getHeight ();
}
-void Table::setWidth (int width)
+int Table::getAvailWidthOfChild (Widget *child, bool forceValue)
{
- // If limitTextWidth is set, a queueResize may also be necessary.
- if (availWidth != width || limitTextWidth) {
- _MSG(" Table::setWidth %d\n", width);
- availWidth = width;
- queueResize (0, false);
+ DBG_OBJ_ENTER ("resize", 0, "getAvailWidthOfChild", "%p, %s",
+ child, forceValue ? "true" : "false");
+
+ int width;
+
+ // Unlike other containers, the table widget sometimes narrows
+ // columns to a width less than specified by CSS (see
+ // forceCalcCellSizes). For this reason, the column widths have to
+ // be calculated in all cases.
+ if (forceValue) {
+ calcCellSizes (false);
+ width = calcAvailWidthForDescendant (child);
+ } else
+ width = -1;
+
+ DBG_OBJ_MSGF ("resize", 1, "=> %d", width);
+ DBG_OBJ_LEAVE ();
+ return width;
+}
+
+void Table::correctRequisitionOfChild (core::Widget *child,
+ core::Requisition *requisition,
+ void (*splitHeightFun) (int, int*, int*))
+{
+ // TODO Same comments as in Widget::correctRequisitionOfChild may
+ // apply here.
+
+ DBG_OBJ_ENTER ("resize", 0, "correctRequisitionOfChild",
+ "%p, %d * (%d + %d), ...)",
+ child, requisition->width, requisition->ascent,
+ requisition->descent);
+
+ if (child->getStyle()->width != core::style::LENGTH_AUTO) {
+ calcCellSizes (false);
+ // The requisition is always the width of the column; the table
+ // widget is special in inforcing this, based on extremes, which
+ // may again be corrected again by CSS attributes.
+ requisition->width = calcAvailWidthForDescendant (child);
}
+
+ correctReqHeightOfChild (child, requisition, splitHeightFun);
+
+ DBG_OBJ_MSGF ("resize", 1, "=> %d * (%d + %d)",
+ requisition->width, requisition->ascent,
+ requisition->descent);
+ DBG_OBJ_LEAVE ();
}
-void Table::setAscent (int ascent)
+int Table::calcAvailWidthForDescendant (Widget *child)
{
- if (availAscent != ascent) {
- availAscent = ascent;
- queueResize (0, false);
+ DBG_OBJ_ENTER ("resize", 0, "calcAvailWidthForDescendant", "%p", child);
+
+ // "child" is not a direct child, but a direct descendant. Search
+ // for the actual childs.
+ Widget *actualChild = child;
+ while (actualChild != NULL && actualChild->getParent () != this)
+ actualChild = actualChild->getParent ();
+
+ assert (actualChild != NULL);
+
+ // TODO This is inefficient. (Use parentRef?)
+ int width = -1;
+ for (int row = numRows - 1; width == -1 && row >= 0; row--) {
+ for (int col = 0; width == -1 && col < numCols; col++) {
+ int n = row * numCols + col;
+ if (childDefined (n) &&
+ children->get(n)->cell.widget == actualChild) {
+ DBG_OBJ_MSGF ("resize", 1, "calculated from column %d", col);
+ width = (children->get(n)->cell.colspanEff - 1)
+ * getStyle()->hBorderSpacing;
+ for (int i = 0; i < children->get(n)->cell.colspanEff; i++)
+ width += colWidths->get (col + i);
+ width = misc::max (width, 0);
+ }
+ }
}
+
+ assert (width != -1);
+
+ DBG_OBJ_MSGF ("resize", 1, "=> %d", width);
+ DBG_OBJ_LEAVE ();
+ return width;
+}
+
+int Table::applyPerWidth (int containerWidth, core::style::Length perWidth)
+{
+ return core::style::multiplyWithPerLength (containerWidth, perWidth);
}
-void Table::setDescent (int descent)
+int Table::applyPerHeight (int containerHeight, core::style::Length perHeight)
{
- if (availDescent != descent) {
- availDescent = descent;
- queueResize (0, false);
+ return core::style::multiplyWithPerLength (containerHeight, perHeight);
+}
+
+void Table::containerSizeChangedForChildren ()
+{
+ DBG_OBJ_ENTER0 ("resize", 0, "containerSizeChangedForChildren");
+
+ for (int col = 0; col < numCols; col++) {
+ for (int row = 0; row < numRows; row++) {
+ int n = row * numCols + col;
+ if (childDefined (n))
+ children->get(n)->cell.widget->containerSizeChanged ();
+ }
}
+
+ DBG_OBJ_LEAVE ();
+}
+
+bool Table::affectsSizeChangeContainerChild (core::Widget *child)
+{
+ DBG_OBJ_ENTER ("resize", 0, "affectsSizeChangeContainerChild", "%p", child);
+
+ bool ret;
+
+ // This is a bit more complicated, as compared to the standard
+ // implementation (Widget::affectsSizeChangeContainerChild).
+ // Height would handled the same way, but width is more
+ // complicated: we would have to track numerous values here. Always
+ // returning true is correct in all cases, but generally
+ // inefficient.
+
+ // TODO Better solution?
+
+ ret = true;
+
+ DBG_OBJ_MSGF ("resize", 1, "=> %s", ret ? "true" : "false");
+ DBG_OBJ_LEAVE ();
+ return ret;
+}
+
+bool Table::usesAvailWidth ()
+{
+ return true;
+}
+
+bool Table::isBlockLevel ()
+{
+ return true;
}
void Table::draw (core::View *view, core::Rectangle *area)
@@ -272,6 +389,9 @@ core::Iterator *Table::iterator (core::Content::Type mask, bool atEnd)
void Table::addCell (Widget *widget, int colspan, int rowspan)
{
+ DBG_OBJ_ENTER ("resize", 0, "addCell", "%p, %d, %d",
+ widget, colspan, rowspan);
+
const int maxspan = 100;
Child *child;
int colspanEff;
@@ -373,6 +493,8 @@ void Table::addCell (Widget *widget, int colspan, int rowspan)
}
MSG("\n");
#endif
+
+ DBG_OBJ_LEAVE ();
}
void Table::addRow (core::style::Style *style)
@@ -393,7 +515,7 @@ void Table::addRow (core::style::Style *style)
rowClosed = false;
}
-TableCell *Table::getCellRef ()
+AlignedTableCell *Table::getCellRef ()
{
core::Widget *child;
@@ -401,14 +523,93 @@ TableCell *Table::getCellRef ()
int n = curCol + row * numCols;
if (childDefined (n)) {
child = children->get(n)->cell.widget;
- if (child->instanceOf (TableCell::CLASS_ID))
- return (TableCell*)child;
+ if (child->instanceOf (AlignedTableCell::CLASS_ID))
+ return (AlignedTableCell*)child;
}
}
return NULL;
}
+const char *Table::getExtrModName (ExtrMod mod)
+{
+ switch (mod) {
+ case MIN:
+ return "MIN";
+
+ case MIN_INTR:
+ return "MIN_INTR";
+
+ case MIN_MIN:
+ return "MIN_MIN";
+
+ case MAX_MIN:
+ return "MAX_MIN";
+
+ case MAX:
+ return "MAX";
+
+ case MAX_INTR:
+ return "MAX_INTR";
+
+ default:
+ misc::assertNotReached ();
+ return NULL;
+ }
+}
+
+int Table::getExtreme (core::Extremes *extremes, ExtrMod mod)
+{
+ switch (mod) {
+ case MIN:
+ return extremes->minWidth;
+
+ case MIN_INTR:
+ return extremes->minWidthIntrinsic;
+
+ case MIN_MIN:
+ return misc::min (extremes->minWidth, extremes->minWidthIntrinsic);
+
+ case MAX_MIN:
+ return misc::max (extremes->minWidth, extremes->minWidthIntrinsic);
+
+ case MAX:
+ return extremes->maxWidth;
+
+ case MAX_INTR:
+ return extremes->maxWidthIntrinsic;
+
+ default:
+ misc::assertNotReached (); return 0;
+ }
+}
+
+void Table::setExtreme (core::Extremes *extremes, ExtrMod mod, int value)
+{
+ switch (mod) {
+ case MIN:
+ extremes->minWidth = value;
+ break;
+
+ case MIN_INTR:
+ extremes->minWidthIntrinsic = value;
+ break;
+
+ // MIN_MIN and MAX_MIN not supported here.
+
+ case MAX:
+ extremes->maxWidth = value;
+ break;
+
+ case MAX_INTR:
+ extremes->maxWidthIntrinsic = value;
+ break;
+
+ default:
+ misc::assertNotReached ();
+ }
+}
+
void Table::reallocChildren (int newNumCols, int newNumRows)
{
assert (newNumCols >= numCols);
@@ -476,107 +677,171 @@ void Table::reallocChildren (int newNumCols, int newNumRows)
numCols = newNumCols;
numRows = newNumRows;
+
+ DBG_OBJ_SET_NUM ("numCols", numCols);
+ DBG_OBJ_SET_NUM ("numRows", numCols);
}
// ----------------------------------------------------------------------
-void Table::calcCellSizes ()
+void Table::calcCellSizes (bool calcHeights)
{
- if (needsResize () || resizeQueued ())
- forceCalcCellSizes ();
+ DBG_OBJ_ENTER ("resize", 0, "calcCellSizes", "%s",
+ calcHeights ? "true" : "false");
+
+ bool sizeChanged = needsResize () || resizeQueued ();
+ bool extremesChanges = extremesChanged () || extremesQueued ();
+
+ if (calcHeights ? (extremesChanges || sizeChanged) :
+ (extremesChanges || !colWidthsUpToDateWidthColExtremes))
+ forceCalcCellSizes (calcHeights);
+
+ DBG_OBJ_LEAVE ();
}
-void Table::forceCalcCellSizes ()
+void Table::forceCalcCellSizes (bool calcHeights)
{
- int totalWidth = 0, childHeight, forceTotalWidth = 1;
+ DBG_OBJ_ENTER0 ("resize", 0, "forceCalcCellSizes");
+
+ int childHeight;
core::Extremes extremes;
// Will also call calcColumnExtremes(), when needed.
getExtremes (&extremes);
- if (core::style::isAbsLength (getStyle()->width)) {
- totalWidth = core::style::absLengthVal (getStyle()->width);
- } else if (core::style::isPerLength (getStyle()->width)) {
- /*
- * If the width is > 100%, we use 100%, this prevents ugly
- * results. (May be changed in future, when a more powerful
- * rendering is implemented, to handle fixed positions etc.,
- * as defined by CSS2.)
- */
- totalWidth =
- misc::min (core::style::multiplyWithPerLength (availWidth,
- getStyle()->width),
- availWidth);
- } else if (getStyle()->width == core::style::LENGTH_AUTO) {
- totalWidth = availWidth;
- forceTotalWidth = 0;
- }
-
- _MSG(" availWidth = %d\n", availWidth);
- _MSG(" totalWidth1 = %d\n", totalWidth);
-
- if (totalWidth < extremes.minWidth)
- totalWidth = extremes.minWidth;
- totalWidth = totalWidth
- - (numCols + 1) * getStyle()->hBorderSpacing
- - getStyle()->boxDiffWidth ();
-
- _MSG(" totalWidth2 = %d curCol=%d\n", totalWidth,curCol);
+ int availWidth = getAvailWidth (true);
+ int totalWidth = availWidth -
+ ((numCols + 1) * getStyle()->hBorderSpacing + boxDiffWidth ());
+ DBG_OBJ_MSGF ("resize", 1,
+ "totalWidth = %d - ((%d - 1) * %d + %d) = <b>%d</b>",
+ availWidth, numCols, getStyle()->hBorderSpacing,
+ boxDiffWidth (), totalWidth);
colWidths->setSize (numCols, 0);
cumHeight->setSize (numRows + 1, 0);
rowSpanCells->setSize (0);
baseline->setSize (numRows);
- _MSG(" extremes = %d,%d\n", extremes.minWidth, extremes.maxWidth);
- _MSG(" getStyle()->boxDiffWidth() = %d\n", getStyle()->boxDiffWidth());
- _MSG(" getStyle()->hBorderSpacing = %d\n", getStyle()->hBorderSpacing);
+ misc::SimpleVector<int> *oldColWidths = colWidths;
+ colWidths = new misc::SimpleVector <int> (8);
+ int minWidth = 0;
+ for (int col = 0; col < colExtremes->size(); col++)
+ minWidth += getColExtreme (col, MIN);
+
+ DBG_OBJ_MSGF ("resize", 1, "minWidth (= %d) > totalWidth (= %d)?",
+ minWidth, totalWidth);
+
+ if (minWidth > totalWidth)
+ // The sum of all column minima is larger than the available
+ // width, so we narrow the columns (see also CSS2 spec,
+ // section 17.5, #6). We use a similar apportioning, but not
+ // bases on minimal and maximal widths, but on intrinsic minimal
+ // widths and corrected minimal widths. This way, intrinsic
+ // extremes are preferred (so avoiding columns too narrow for
+ // the actual contents), at the expenses of corrected ones
+ // (which means that sometimes CSS values are handled
+ // incorrectly).
+
+ apportion2 (totalWidth, 0, colExtremes->size() - 1, MIN_MIN, MAX_MIN,
+ colWidths, 0);
+ else {
+ // Normal apportioning.
+ int width;
+ if (getStyle()->width == core::style::LENGTH_AUTO) {
+ // Do not force width, when maximal width is smaller.
+ int maxWidth = 0;
+ for (int col = 0; col < colExtremes->size(); col++)
+ maxWidth += getColExtreme (col, MAX);
+ width = misc::min (totalWidth, maxWidth);
+ DBG_OBJ_MSGF ("resize", 1, "width = min (%d, %d) = %d",
+ totalWidth, maxWidth, width);
+ } else
+ // CSS 'width' defined: force this width.
+ width = totalWidth;
- apportion_percentages2 (totalWidth, forceTotalWidth);
- if (!hasColPercent)
- apportion2 (totalWidth, forceTotalWidth);
+ apportion2 (width, 0, colExtremes->size() - 1, MIN, MAX, colWidths, 0);
+ }
- setCumHeight (0, 0);
- for (int row = 0; row < numRows; row++) {
- /**
- * \bug dw::Table::baseline is not filled.
- */
- int rowHeight = 0;
+ // TODO: Adapted from old inline function "setColWidth". But (i) is
+ // this anyway correct (col width is is not x)? And does the
+ // performance gain actually play a role?
+ for (int col = 0; col < colExtremes->size(); col++) {
+ if (colWidths->get (col) != oldColWidths->get (col))
+ redrawX = lout::misc::min (redrawX, colWidths->get (col));
+ }
+
+ DBG_IF_RTFL {
+ DBG_OBJ_SET_NUM ("colWidths.size", colWidths->size ());
+ for (int i = 0; i < colWidths->size (); i++)
+ DBG_OBJ_ARRSET_NUM ("colWidths", i, colWidths->get (i));
+ }
- for (int col = 0; col < numCols; col++) {
- int n = row * numCols + col;
- if (childDefined (n)) {
- int width = (children->get(n)->cell.colspanEff - 1)
- * getStyle()->hBorderSpacing;
- for (int i = 0; i < children->get(n)->cell.colspanEff; i++)
- width += colWidths->get (col + i);
+ colWidthsUpToDateWidthColExtremes = true;
+ DBG_OBJ_SET_BOOL ("colWidthsUpToDateWidthColExtremes",
+ colWidthsUpToDateWidthColExtremes);
- core::Requisition childRequisition;
- children->get(n)->cell.widget->setWidth (width);
- children->get(n)->cell.widget->sizeRequest (&childRequisition);
- childHeight = childRequisition.ascent + childRequisition.descent;
- if (children->get(n)->cell.rowspan == 1) {
- rowHeight = misc::max (rowHeight, childHeight);
- } else {
- rowSpanCells->increase();
- rowSpanCells->set(rowSpanCells->size()-1, n);
- }
+ for (int col = 0; col < numCols; col++) {
+ if (col >= oldColWidths->size () || col >= colWidths->size () ||
+ oldColWidths->get (col) != colWidths->get (col)) {
+ // Column width has changed, tell children about this.
+ for (int row = 0; row < numRows; row++) {
+ int n = row * numCols + col;
+ // TODO: Columns spanning several rows are only regarded
+ // when the first column is affected.
+ if (childDefined (n))
+ children->get(n)->cell.widget->containerSizeChanged ();
}
- }/*for col*/
+ }
+ }
+
+ delete oldColWidths;
- setCumHeight (row + 1,
- cumHeight->get (row) + rowHeight + getStyle()->vBorderSpacing);
+ if (calcHeights) {
+ setCumHeight (0, 0);
+ for (int row = 0; row < numRows; row++) {
+ /**
+ * \bug dw::Table::baseline is not filled.
+ */
+ int rowHeight = 0;
+
+ for (int col = 0; col < numCols; col++) {
+ int n = row * numCols + col;
+ if (childDefined (n)) {
+ int width = (children->get(n)->cell.colspanEff - 1)
+ * getStyle()->hBorderSpacing;
+ for (int i = 0; i < children->get(n)->cell.colspanEff; i++)
+ width += colWidths->get (col + i);
+
+ core::Requisition childRequisition;
+ //children->get(n)->cell.widget->setWidth (width);
+ children->get(n)->cell.widget->sizeRequest (&childRequisition);
+ childHeight = childRequisition.ascent + childRequisition.descent;
+ if (children->get(n)->cell.rowspan == 1) {
+ rowHeight = misc::max (rowHeight, childHeight);
+ } else {
+ rowSpanCells->increase();
+ rowSpanCells->set(rowSpanCells->size()-1, n);
+ }
+ }
+ } // for col
+
+ setCumHeight (row + 1,
+ cumHeight->get (row) + rowHeight + getStyle()->vBorderSpacing);
+ } // for row
- }/*for row*/
+ apportionRowSpan ();
+ }
- apportionRowSpan ();
+ DBG_OBJ_LEAVE ();
}
void Table::apportionRowSpan ()
{
+ DBG_OBJ_ENTER0 ("resize", 0, "apportionRowSpan");
+
int *rowHeight = NULL;
for (int c = 0; c < rowSpanCells->size(); ++c) {
@@ -630,6 +895,8 @@ void Table::apportionRowSpan ()
setCumHeight (i+1, cumHeight->get(i) + rowHeight[i]);
}
delete[] rowHeight;
+
+ DBG_OBJ_LEAVE ();
}
@@ -640,8 +907,12 @@ void Table::apportionRowSpan ()
*/
void Table::calcColumnExtremes ()
{
+ DBG_OBJ_ENTER0 ("resize", 0, "calcColumnExtremes");
+
if (extremesChanged () || extremesQueued ())
forceCalcColumnExtremes ();
+
+ DBG_OBJ_LEAVE ();
}
@@ -650,570 +921,282 @@ void Table::calcColumnExtremes ()
*/
void Table::forceCalcColumnExtremes ()
{
- _MSG(" Table::forceCalcColumnExtremes numCols=%d\n", numCols);
-
- if (numCols == 0)
- return;
+ DBG_OBJ_ENTER0 ("resize", 0, "forceCalcColumnExtremes");
- colExtremes->setSize (numCols);
- colPercents->setSize (numCols);
- colSpanCells->setSize (0);
- /* 1. cells with colspan = 1 */
- for (int col = 0; col < numCols; col++) {
- colExtremes->getRef(col)->minWidth = 0;
- colExtremes->getRef(col)->maxWidth = 0;
- colPercents->set(col, core::style::LENGTH_AUTO);
+ if (numCols > 0) {
+ lout::misc::SimpleVector<int> colSpanCells (8);
+ colExtremes->setSize (numCols);
- for (int row = 0; row < numRows; row++) {
- int n = row * numCols + col;
- if (!childDefined (n))
- continue;
- if (children->get(n)->cell.colspanEff == 1) {
- core::Extremes cellExtremes;
- int cellMinW, cellMaxW, pbm;
- core::style::Length width =
- children->get(n)->cell.widget->getStyle()->width;
- pbm = (numCols + 1) * getStyle()->hBorderSpacing
- + children->get(n)->cell.widget->getStyle()->boxDiffWidth ();
- children->get(n)->cell.widget->getExtremes (&cellExtremes);
- if (core::style::isAbsLength (width)) {
- // Fixed lengths include table padding, border and margin.
- cellMinW = cellExtremes.minWidth;
- cellMaxW = misc::max (cellMinW,
- core::style::absLengthVal(width) - pbm);
- } else {
- cellMinW = cellExtremes.minWidth;
- cellMaxW = cellExtremes.maxWidth;
+ // 1. cells with colspan = 1
+ for (int col = 0; col < numCols; col++) {
+ DBG_OBJ_MSGF ("resize", 1, "column %d", col);
+ DBG_OBJ_MSG_START ();
+
+ colExtremes->getRef(col)->minWidth = 0;
+ colExtremes->getRef(col)->minWidthIntrinsic = 0;
+ colExtremes->getRef(col)->maxWidth = 0;
+ colExtremes->getRef(col)->maxWidthIntrinsic = 0;
+
+ for (int row = 0; row < numRows; row++) {
+ DBG_OBJ_MSGF ("resize", 1, "row %d", row);
+ DBG_OBJ_MSG_START ();
+
+ int n = row * numCols + col;
+
+ if (childDefined (n)) {
+ if (children->get(n)->cell.colspanEff == 1) {
+ core::Extremes cellExtremes;
+ children->get(n)->cell.widget->getExtremes (&cellExtremes);
+
+ DBG_OBJ_MSGF ("resize", 1, "child: %d / %d",
+ cellExtremes.minWidth, cellExtremes.maxWidth);
+
+ colExtremes->getRef(col)->minWidthIntrinsic =
+ misc::max (colExtremes->getRef(col)->minWidthIntrinsic,
+ cellExtremes.minWidthIntrinsic);
+ colExtremes->getRef(col)->maxWidthIntrinsic =
+ misc::max (colExtremes->getRef(col)->minWidthIntrinsic,
+ colExtremes->getRef(col)->maxWidthIntrinsic,
+ cellExtremes.maxWidthIntrinsic);
+
+ colExtremes->getRef(col)->minWidth =
+ misc::max (colExtremes->getRef(col)->minWidth,
+ cellExtremes.minWidth);
+ colExtremes->getRef(col)->maxWidth =
+ misc::max (colExtremes->getRef(col)->minWidth,
+ colExtremes->getRef(col)->maxWidth,
+ cellExtremes.maxWidth);
+
+ DBG_OBJ_MSGF ("resize", 1, "column: %d / %d (%d / %d)",
+ colExtremes->getRef(col)->minWidth,
+ colExtremes->getRef(col)->maxWidth,
+ colExtremes->getRef(col)->minWidthIntrinsic,
+ colExtremes->getRef(col)->maxWidthIntrinsic);
+ } else {
+ colSpanCells.increase ();
+ colSpanCells.setLast (n);
+ }
}
- _MSG("FCCE, col%d colMin,colMax,cellMin,cellMax = %d,%d,%d,%d\n",
- col,
- colExtremes->getRef(col)->minWidth,
- colExtremes->getRef(col)->maxWidth,
- cellMinW, cellMaxW);
-
- colExtremes->getRef(col)->minWidth =
- misc::max (colExtremes->getRef(col)->minWidth, cellMinW);
- colExtremes->getRef(col)->maxWidth =
- misc::max (colExtremes->getRef(col)->minWidth, misc::max (
- colExtremes->getRef(col)->maxWidth,
- cellMaxW));
-
- // Also fill the colPercents array in this pass
- if (core::style::isPerLength (width)) {
- hasColPercent = 1;
- if (colPercents->get(col) == core::style::LENGTH_AUTO)
- colPercents->set(col, width);
- } else if (core::style::isAbsLength (width)) {
- // We treat LEN_ABS as a special case of LEN_AUTO.
- /*
- * if (colPercents->get(col) == LEN_AUTO)
- * colPercents->set(col, LEN_ABS);
- *
- * (Hint: that's old code!)
- */
- }
- } else {
- colSpanCells->increase();
- colSpanCells->set(colSpanCells->size()-1, n);
+ DBG_OBJ_MSG_END ();
}
- }
- }
- /* 2. cells with colspan > 1 */
- /* If needed, here we set proportionally apportioned col maximums */
- for (int c = 0; c < colSpanCells->size(); ++c) {
- core::Extremes cellExtremes;
- int cellMinW, cellMaxW, pbm;
- int n = colSpanCells->get(c);
- int col = n % numCols;
- int cs = children->get(n)->cell.colspanEff;
- core::style::Length width =
- children->get(n)->cell.widget->getStyle()->width;
- pbm = (numCols + 1) * getStyle()->hBorderSpacing
- + children->get(n)->cell.widget->getStyle()->boxDiffWidth ();
- children->get(n)->cell.widget->getExtremes (&cellExtremes);
- if (core::style::isAbsLength (width)) {
- // Fixed lengths include table padding, border and margin.
- cellMinW = cellExtremes.minWidth;
- cellMaxW =
- misc::max (cellMinW, core::style::absLengthVal(width) - pbm);
- } else {
- cellMinW = cellExtremes.minWidth;
- cellMaxW = cellExtremes.maxWidth;
+ DBG_OBJ_MSG_END ();
}
- int minSumCols = 0, maxSumCols = 0;
- for (int i = 0; i < cs; ++i) {
- minSumCols += colExtremes->getRef(col+i)->minWidth;
- maxSumCols += colExtremes->getRef(col+i)->maxWidth;
- }
-
- _MSG("cs=%d spanWidth=%d,%d sumCols=%d,%d\n",
- cs,cellMinW,cellMaxW,minSumCols,maxSumCols);
- if (minSumCols >= cellMinW && maxSumCols >= cellMaxW)
- continue;
+ // 2. cells with colspan > 1
- // Cell size is too small; apportion {min,max} for this colspan.
- int spanMinW = misc::max (misc::max (cs, minSumCols),
- cellMinW - (cs-1) * getStyle()->hBorderSpacing),
- spanMaxW = misc::max (misc::max (cs, maxSumCols),
- cellMaxW - (cs-1) * getStyle()->hBorderSpacing);
-
- if (minSumCols == 0) {
- // No single cells defined for this span => pre-apportion equally
- minSumCols = spanMinW; maxSumCols = spanMaxW;
- int minW = spanMinW, maxW = spanMaxW;
- for (int i = 0; i < cs; ++i) {
- colExtremes->getRef(col+i)->minWidth = minW / (cs - i);
- colExtremes->getRef(col+i)->maxWidth = maxW / (cs - i);
- minW -= colExtremes->getRef(col+i)->minWidth;
- maxW -= colExtremes->getRef(col+i)->maxWidth;
- }
- }
-
- // These values will help if the span has percents.
- int spanHasColPercent = 0;
- int availSpanMinW = spanMinW;
- float cumSpanPercent = 0.0f;
- for (int i = col; i < col + cs; ++i) {
- if (core::style::isPerLength (colPercents->get(i))) {
- cumSpanPercent += core::style::perLengthVal (colPercents->get(i));
- ++spanHasColPercent;
- } else
- availSpanMinW -= colExtremes->getRef(i)->minWidth;
- }
-
- // Calculate weighted-apportion columns for this span.
- int wMin = 0, wMax;
- int cumMaxWnew = 0, cumMaxWold = 0, goalMaxW = spanMaxW;
- int curAppW = maxSumCols;
- int curExtraW = spanMinW - minSumCols;
- for (int i = col; i < col + cs; ++i) {
-
- if (!spanHasColPercent) {
- int d_a = colExtremes->getRef(i)->maxWidth;
- int d_w = curAppW > 0 ? (int)((float)curExtraW * d_a/curAppW) : 0;
- if (d_a < 0||d_w < 0) {
- MSG("d_a=%d d_w=%d\n",d_a,d_w);
- exit(1);
- }
- wMin = colExtremes->getRef(i)->minWidth + d_w;
- colExtremes->getRef(i)->minWidth = wMin;
- curExtraW -= d_w;
- curAppW -= d_a;
- } else {
- if (core::style::isPerLength (colPercents->get(i))) {
- // multiplyWithPerLength would cause rounding errors,
- // therefore the deprecated way, using perLengthVal:
- wMin = misc::max (colExtremes->getRef(i)->minWidth,
- (int)(availSpanMinW *
- core::style::perLengthVal
- (colPercents->get (i))
- / cumSpanPercent));
- colExtremes->getRef(i)->minWidth = wMin;
- }
- }
+ // TODO: Is this old comment still relevant? "If needed, here we
+ // set proportionally apportioned col maximums."
- wMax = (goalMaxW-cumMaxWnew <= 0) ? 0 :
- (int)((float)(goalMaxW-cumMaxWnew)
- * colExtremes->getRef(i)->maxWidth
- / (maxSumCols-cumMaxWold));
- wMax = misc::max (wMin, wMax);
- cumMaxWnew += wMax;
- cumMaxWold += colExtremes->getRef(i)->maxWidth;
- colExtremes->getRef(i)->maxWidth = wMax;
+ for (int i = 0; i < colSpanCells.size(); i++) {
+ int n = colSpanCells.get (i);
+ int col = n % numCols;
+ int cs = children->get(n)->cell.colspanEff;
- _MSG("i=%d, wMin=%d wMax=%d cumMaxWold=%d\n",
- i,wMin,wMax,cumMaxWold);
+ core::Extremes cellExtremes;
+ children->get(n)->cell.widget->getExtremes (&cellExtremes);
+ calcExtremesSpanMulteCols (col, cs, &cellExtremes, MIN, MAX);
+ calcExtremesSpanMulteCols (col, cs, &cellExtremes, MIN_INTR, MAX_INTR);
}
-#ifdef DBG
- MSG("col min,max: [");
- for (int i = 0; i < numCols; i++)
- MSG("%d,%d ",
- colExtremes->getRef(i)->minWidth,
- colExtremes->getRef(i)->maxWidth);
- MSG("]\n");
- MSG("getStyle()->hBorderSpacing = %d\n", getStyle()->hBorderSpacing);
-#endif
}
-}
-/**
- * \brief Apportionment function for AUTO-length columns.
- * 'extremes' comes filled, 'result' comes defined for percentage columns.
- */
-void Table::apportion2 (int totalWidth, int forceTotalWidth)
-{
- if (colExtremes->size() == 0)
- return;
-#ifdef DBG
- MSG("app2, availWidth=%d, totalWidth=%d, forceTotalWidth=%d\n",
- availWidth, totalWidth, forceTotalWidth);
- MSG("app2, extremes: ( ");
- for (int i = 0; i < colExtremes->size (); i++)
- MSG("%d,%d ",
- colExtremes->get(i).minWidth, colExtremes->get(i).maxWidth);
- MSG(")\n");
-#endif
- int minAutoWidth = 0, maxAutoWidth = 0, availAutoWidth = totalWidth;
- for (int col = 0; col < numCols; col++) {
- if (core::style::isAbsLength (colPercents->get(col))) {
- // set absolute lengths
- setColWidth (col, colExtremes->get(col).minWidth);
+ DBG_IF_RTFL {
+ DBG_OBJ_SET_NUM ("colExtremes.size", colExtremes->size ());
+ for (int i = 0; i < colExtremes->size (); i++) {
+ DBG_OBJ_ARRATTRSET_NUM ("colExtremes", i, "minWidth",
+ colExtremes->get(i).minWidth);
+ DBG_OBJ_ARRATTRSET_NUM ("colExtremes", i, "minWidthIntrinsic",
+ colExtremes->get(i).minWidthIntrinsic);
+ DBG_OBJ_ARRATTRSET_NUM ("colExtremes", i, "maxWidth",
+ colExtremes->get(i).maxWidth);
+ DBG_OBJ_ARRATTRSET_NUM ("colExtremes", i, "maxWidthIntrinsic",
+ colExtremes->get(i).maxWidthIntrinsic);
}
- if (colPercents->get(col) == core::style::LENGTH_AUTO) {
- maxAutoWidth += colExtremes->get(col).maxWidth;
- minAutoWidth += colExtremes->get(col).minWidth;
- } else
- availAutoWidth -= colWidths->get(col);
- }
-
- if (!maxAutoWidth) // no core::style::LENGTH_AUTO cols!
- return;
-
- colWidths->setSize (colExtremes->size (), 0);
-
- if (!forceTotalWidth && maxAutoWidth < availAutoWidth) {
- // Enough space for the maximum table, don't widen past max.
- availAutoWidth = maxAutoWidth;
}
- // General case.
- int curTargetWidth = misc::max (availAutoWidth, minAutoWidth);
- int curExtraWidth = curTargetWidth - minAutoWidth;
- int curMaxWidth = maxAutoWidth;
- int curNewWidth = minAutoWidth;
- for (int col = 0; col < numCols; col++) {
- _MSG("app2, col %d, minWidth=%d maxWidth=%d\n",
- col, colExtremes->getRef(col)->minWidth,
- colExtremes->get(col).maxWidth);
-
- if (colPercents->get(col) != core::style::LENGTH_AUTO)
- continue;
-
- int colMinWidth = colExtremes->getRef(col)->minWidth;
- int colMaxWidth = colExtremes->getRef(col)->maxWidth;
- int w = (curMaxWidth <= 0) ? 0 :
- (int)((float)curTargetWidth * colMaxWidth/curMaxWidth);
-
- _MSG("app2, curTargetWidth=%d colMaxWidth=%d curMaxWidth=%d "
- "curNewWidth=%d ",
- curTargetWidth, colMaxWidth,curMaxWidth,curNewWidth);
- _MSG("w = %d, ", w);
-
- if (w <= colMinWidth)
- w = colMinWidth;
- else if (curNewWidth - colMinWidth + w > curTargetWidth)
- w = colMinWidth + curExtraWidth;
-
- _MSG("w = %d\n", w);
+ colWidthsUpToDateWidthColExtremes = false;
+ DBG_OBJ_SET_BOOL ("colWidthsUpToDateWidthColExtremes",
+ colWidthsUpToDateWidthColExtremes);
- curNewWidth -= colMinWidth;
- curMaxWidth -= colMaxWidth;
- curExtraWidth -= (w - colMinWidth);
- curTargetWidth -= w;
- setColWidth (col, w);
- }
-#ifdef DBG
- MSG("app2, result: ( ");
- for (int i = 0; i < colWidths->size (); i++)
- MSG("%d ", colWidths->get (i));
- MSG(")\n");
-#endif
+ DBG_OBJ_LEAVE ();
}
-void Table::apportion_percentages2(int totalWidth, int forceTotalWidth)
+void Table::calcExtremesSpanMulteCols (int col, int cs,
+ core::Extremes *cellExtremes,
+ ExtrMod minExtrMod, ExtrMod maxExtrMod)
{
- int hasTablePercent = core::style::isPerLength (getStyle()->width) ? 1 : 0;
-
- if (colExtremes->size() == 0 || (!hasTablePercent && !hasColPercent))
- return;
-
- // If there's a table-wide percentage, totalWidth comes already scaled.
- _MSG("APP_P, availWidth=%d, totalWidth=%d, forceTotalWidth=%d\n",
- availWidth, totalWidth, forceTotalWidth);
+ DBG_OBJ_ENTER ("resize", 0, "calcExtremesSpanMulteCols",
+ "%d, %d, ..., %s, %s",
+ col, cs, getExtrModName (minExtrMod),
+ getExtrModName (maxExtrMod));
+
+ int cellMin = getExtreme (cellExtremes, minExtrMod);
+ int cellMax = getExtreme (cellExtremes, maxExtrMod);
+
+ int minSumCols = 0, maxSumCols = 0;
+
+ for (int j = 0; j < cs; j++) {
+ minSumCols += getColExtreme (col + j, minExtrMod);
+ maxSumCols += getColExtreme (col + j, maxExtrMod);
+ }
- if (!hasColPercent) {
-#ifdef DBG
- MSG("APP_P, only a table-wide percentage\n");
- MSG("APP_P, extremes = { ");
- for (int col = 0; col < numCols; col++)
- MSG("%d,%d ", colExtremes->getRef(col)->minWidth,
- colExtremes->getRef(col)->maxWidth);
- MSG("}\n");
-#endif
- // It has only a table-wide percentage. Apportion non-absolute widths.
- int sumMaxWidth = 0, perAvailWidth = totalWidth;
- for (int col = 0; col < numCols; col++) {
- if (core::style::isAbsLength (colPercents->get(col)))
- perAvailWidth -= colExtremes->getRef(col)->maxWidth;
- else
- sumMaxWidth += colExtremes->getRef(col)->maxWidth;
+ DBG_OBJ_MSGF ("resize", 1, "cs = %d, cell: %d / %d, sum: %d / %d\n",
+ cs, cellMin, cellMax, minSumCols, maxSumCols);
+
+ bool changeMin = cellMin > minSumCols;
+ bool changeMax = cellMax > maxSumCols;
+ if (changeMin || changeMax) {
+ // TODO This differs from the documentation? Should work, anyway.
+ misc::SimpleVector<int> newMin, newMax;
+ if (changeMin)
+ apportion2 (cellMin, col, col + cs - 1, MIN, MAX, &newMin, 0);
+ if (changeMax)
+ apportion2 (cellMax, col, col + cs - 1, MIN, MAX, &newMax, 0);
+
+ for (int j = 0; j < cs; j++) {
+ if (changeMin)
+ setColExtreme (col + j, minExtrMod, newMin.get (j));
+ if (changeMax)
+ setColExtreme (col + j, maxExtrMod, newMax.get (j));
+
+ // For cases where min and max are somewhat confused:
+ setColExtreme (col + j, maxExtrMod,
+ misc::max (getColExtreme (col + j, minExtrMod),
+ getColExtreme (col + j, maxExtrMod)));
}
+ }
- _MSG("APP_P, perAvailWidth=%d, sumMaxWidth=%d\n",
- perAvailWidth, sumMaxWidth);
-
- for (int col = 0; col < numCols; col++) {
- int max_wi = colExtremes->getRef(col)->maxWidth, new_wi;
- if (!core::style::isAbsLength (colPercents->get(col))) {
- new_wi =
- misc::max (colExtremes->getRef(col)->minWidth,
- (int)((float)max_wi * perAvailWidth/sumMaxWidth));
- setColWidth (col, new_wi);
- perAvailWidth -= new_wi;
- sumMaxWidth -= max_wi;
- }
- }
-#ifdef DBG
- MSG("APP_P, result = { ");
- for (int col = 0; col < numCols; col++)
- MSG("%d ", colWidths->get(col));
- MSG("}\n");
-#endif
+ DBG_OBJ_LEAVE ();
+}
- } else {
- // we'll have to apportion...
- _MSG("APP_P, we'll have to apportion...\n");
+/**
+ * \brief Actual apportionment function.
+ */
+void Table::apportion2 (int totalWidth, int firstCol, int lastCol,
+ ExtrMod minExtrMod, ExtrMod maxExtrMod,
+ misc::SimpleVector<int> *dest, int destOffset)
+{
+ DBG_OBJ_ENTER ("resize", 0, "apportion2", "%d, %d, %d, %s, %s, ..., %d",
+ totalWidth, firstCol, lastCol, getExtrModName (minExtrMod),
+ getExtrModName (maxExtrMod), destOffset);
- // Calculate cumPercent and available space
- float cumPercent = 0.0f;
- int hasAutoCol = 0;
- int sumMinWidth = 0, sumMaxWidth = 0, sumMinNonPer = 0, sumMaxNonPer = 0;
- for (int col = 0; col < numCols; col++) {
- if (core::style::isPerLength (colPercents->get(col))) {
- cumPercent += core::style::perLengthVal (colPercents->get(col));
- } else {
- sumMinNonPer += colExtremes->getRef(col)->minWidth;
- sumMaxNonPer += colExtremes->getRef(col)->maxWidth;
- if (colPercents->get(col) == core::style::LENGTH_AUTO)
- hasAutoCol++;
- }
- sumMinWidth += colExtremes->getRef(col)->minWidth;
- sumMaxWidth += colExtremes->getRef(col)->maxWidth;
+ if (lastCol >= firstCol) {
+ dest->setSize (destOffset + lastCol - firstCol + 1, 0);
- _MSG("APP_P, col %d minWidth=%d maxWidth=%d\n", col,
- colExtremes->getRef(col)->minWidth,
- colExtremes->getRef(col)->maxWidth);
+ int totalMin = 0, totalMax = 0;
+ for (int col = firstCol; col <= lastCol; col++) {
+ totalMin += getColExtreme (col, minExtrMod);
+ totalMax += getColExtreme (col, maxExtrMod);
}
- int oldTotalWidth = totalWidth;
- if (!forceTotalWidth) {
- if (sumMaxNonPer == 0 || cumPercent < 0.99f) {
- // only percentage columns, or cumPercent < 100% => restrict width
- int totW = (int)(sumMaxNonPer / (1.0f - cumPercent));
- for (int col = 0; col < numCols; col++) {
- totW = misc::max
- (totW,
- (int)(colExtremes->getRef(col)->maxWidth
- / core::style::perLengthVal (colPercents->get(col))));
- }
- totalWidth = misc::min (totW, totalWidth);
+
+ DBG_OBJ_MSGF ("resize", 1,
+ "totalWidth = %d, totalMin = %d, totalMax = %d",
+ totalWidth, totalMin, totalMax);
+
+ // The actual calculation is rather simple, the ith value is:
+ //
+ //
+ // (max[i] - min[i]) * (totalMax - totalMin)
+ // width[i] = min[i] + -----------------------------------------
+ // (totalWidth - totalMin)
+ //
+ // (Regard "total" as "sum".) With the following general
+ // definitions (for both the list and sums):
+ //
+ // diffExtr = max - min
+ // diffWidth = width - min
+ //
+ // it is simplified to:
+ //
+ // diffExtr[i] * totalDiffWidth
+ // diffWidth[i] = ----------------------------
+ // totalDiffExtr
+ //
+ // Of course, if totalDiffExtr is 0, this is not defined;
+ // instead, we apportion according to the minima:
+ //
+ // min[i] * totalWidth
+ // width[i] = -------------------
+ // totalMin
+ //
+ // Since min[i] <= max[i] for all i, totalMin == totalMax
+ // implies that min[i] == max[i] for all i.
+ //
+ // Third, it totalMin == 0 (which also implies min[i] = max[i] = 0),
+ // the result is
+ //
+ // width[i] = totalWidth / n
+
+ int totalDiffExtr = totalMax - totalMin;
+ if (totalDiffExtr != 0) {
+ // Normal case. The algorithm described in
+ // "rounding-errors.doc" is used, with:
+ //
+ // x[i] = diffExtr[i]
+ // y[i] = diffWidth[i]
+ // a = totalDiffWidth
+ // b = totalDiffExtr
+
+ DBG_OBJ_MSG ("resize", 1, "normal case");
+
+ int totalDiffWidth = totalWidth - totalMin;
+ int cumDiffExtr = 0, cumDiffWidth = 0;
+
+ for (int col = firstCol; col <= lastCol; col++) {
+ int min = getColExtreme (col, minExtrMod);
+ int max = getColExtreme (col, maxExtrMod);
+ int diffExtr = max - min;
+
+ cumDiffExtr += diffExtr;
+ int diffWidth =
+ (cumDiffExtr * totalDiffWidth) / totalDiffExtr - cumDiffWidth;
+ cumDiffWidth += diffWidth;
+
+ dest->set (destOffset - firstCol + col, diffWidth + min);
}
- }
-
- // make sure there's enough space
- totalWidth = misc::max (totalWidth, sumMinWidth);
- // extraWidth is always >= 0
- int extraWidth = totalWidth - sumMinWidth;
- int sumMinWidthPer = sumMinWidth - sumMinNonPer;
- int curPerWidth = sumMinWidthPer;
- // percentages refer to workingWidth
- int workingWidth = totalWidth - sumMinNonPer;
- if (cumPercent < 0.99f) {
- // In this case, use the whole table width
- workingWidth = totalWidth;
- curPerWidth = sumMinWidth;
- }
-
- _MSG("APP_P, oldTotalWidth=%d totalWidth=%d"
- " workingWidth=%d extraWidth=%d sumMinNonPer=%d\n",
- oldTotalWidth,totalWidth,workingWidth,extraWidth,sumMinNonPer);
-
- for (int col = 0; col < numCols; col++) {
- int colMinWidth = colExtremes->getRef(col)->minWidth;
- if (core::style::isPerLength (colPercents->get(col))) {
- int w = core::style::multiplyWithPerLength (workingWidth,
- colPercents->get(col));
- if (w < colMinWidth)
- w = colMinWidth;
- else if (curPerWidth - colMinWidth + w > workingWidth)
- w = colMinWidth + extraWidth;
- extraWidth -= (w - colMinWidth);
- curPerWidth += (w - colMinWidth);
- setColWidth (col, w);
- } else {
- setColWidth (col, colMinWidth);
+ } else if (totalMin != 0) {
+ // Special case. Again, same algorithm, with
+ //
+ // x[i] = min[i]
+ // y[i] = width[i]
+ // a = totalWidth
+ // b = totalMin
+
+ DBG_OBJ_MSG ("resize", 1, "special case 1");
+
+ int cumMin = 0, cumWidth = 0;
+ for (int col = firstCol; col <= lastCol; col++) {
+ int min = getColExtreme (col, minExtrMod);
+ cumMin += min;
+ int width = (cumMin * totalWidth) / totalMin - cumWidth;
+ cumWidth += width;
+
+ dest->set (destOffset - firstCol + col, width);
}
- }
-
- if (cumPercent < 0.99f) {
- // Will have to apportion the other columns
-#ifdef DBG
- MSG("APP_P, extremes: ( ");
- for (int i = 0; i < colExtremes->size (); i++)
- MSG("%d,%d ",
- colExtremes->get(i).minWidth, colExtremes->get(i).maxWidth);
- MSG(")\n");
-#endif
- curPerWidth -= sumMinNonPer;
- int perWidth = (int)(curPerWidth/cumPercent);
- totalWidth = misc::max (totalWidth, perWidth);
- totalWidth = misc::min (totalWidth, oldTotalWidth);
-
- _MSG("APP_P, curPerWidth=%d perWidth=%d, totalWidth=%d\n",
- curPerWidth, perWidth, totalWidth);
-
- if (hasAutoCol == 0) {
- // Special case, cumPercent < 100% and no other columns to expand.
- // We'll honor totalWidth by expanding the percentage cols.
- int extraWidth = totalWidth - curPerWidth - sumMinNonPer;
- for (int col = 0; col < numCols; col++) {
- if (core::style::isPerLength (colPercents->get(col))) {
- // This could cause rounding errors:
- //
- // int d =
- // core::dw::multiplyWithPerLength (extraWidth,
- // colPercents->get(col))
- // / cumPercent;
- //
- // Thus the "old" way:
- int d =
- (int)(extraWidth *
- core::style::perLengthVal (colPercents->get(col))
- / cumPercent);
- setColWidth (col, colWidths->get(col) + d);
- }
- }
+ } else { // if (totalMin == 0)
+ // Last special case. Ssame algorithm, with
+ //
+ // x[i] = 1 (so cumX = i = col - firstCol + 1)
+ // y[i] = width[i]
+ // a = totalWidth
+ // b = n = lastCol - firstCol + 1
+
+ DBG_OBJ_MSG ("resize", 1, "special case 2");
+
+ int cumWidth = 0, n = (lastCol - firstCol + 1);
+ for (int col = firstCol; col <= lastCol; col++) {
+ int i = (col - firstCol + 1);
+ int width = (i * totalWidth) / n - cumWidth;
+ cumWidth += width;
+
+ dest->set (destOffset - firstCol + col, width);
}
}
-#ifdef DBG
- MSG("APP_P, result ={ ");
- for (int col = 0; col < numCols; col++)
- MSG("%d ", colWidths->get(col));
- MSG("}\n");
-#endif
- apportion2 (totalWidth, 2);
-
-#ifdef DBG
- MSG("APP_P, percent={");
- for (int col = 0; col < numCols; col++)
- MSG("%f ", core::dw::perLengthVal (colPercents->get(col)));
- MSG("}\n");
- MSG("APP_P, result ={ ");
- for (int col = 0; col < numCols; col++)
- MSG("%d ", colWidths->get(col));
- MSG("}\n");
-#endif
- }
-}
-
-// ----------------------------------------------------------------------
-
-Table::TableIterator::TableIterator (Table *table,
- core::Content::Type mask, bool atEnd):
- core::Iterator (table, mask, atEnd)
-{
- index = atEnd ? table->children->size () : -1;
- content.type = atEnd ? core::Content::END : core::Content::START;
-}
-
-Table::TableIterator::TableIterator (Table *table,
- core::Content::Type mask, int index):
- core::Iterator (table, mask, false)
-{
- this->index = index;
-
- if (index < 0)
- content.type = core::Content::START;
- else if (index >= table->children->size ())
- content.type = core::Content::END;
- else {
- content.type = core::Content::WIDGET_IN_FLOW;
- content.widget = table->children->get(index)->cell.widget;
- }
-}
-
-object::Object *Table::TableIterator::clone()
-{
- return new TableIterator ((Table*)getWidget(), getMask(), index);
-}
-
-int Table::TableIterator::compareTo(object::Comparable *other)
-{
- return index - ((TableIterator*)other)->index;
-}
-
-bool Table::TableIterator::next ()
-{
- Table *table = (Table*)getWidget();
-
- if (content.type == core::Content::END)
- return false;
-
- // tables only contain widgets (in flow):
- if ((getMask() & core::Content::WIDGET_IN_FLOW) == 0) {
- content.type = core::Content::END;
- return false;
- }
-
- do {
- index++;
- if (index >= table->children->size ()) {
- content.type = core::Content::END;
- return false;
- }
- } while (table->children->get(index) == NULL ||
- table->children->get(index)->type != Child::CELL);
-
- content.type = core::Content::WIDGET_IN_FLOW;
- content.widget = table->children->get(index)->cell.widget;
- return true;
-}
-
-bool Table::TableIterator::prev ()
-{
- Table *table = (Table*)getWidget();
-
- if (content.type == core::Content::START)
- return false;
-
- // tables only contain widgets (in flow):
- if ((getMask() & core::Content::WIDGET_IN_FLOW) == 0) {
- content.type = core::Content::START;
- return false;
}
-
- do {
- index--;
- if (index < 0) {
- content.type = core::Content::START;
- return false;
- }
- } while (table->children->get(index) == NULL ||
- table->children->get(index)->type != Child::CELL);
-
- content.type = core::Content::WIDGET_IN_FLOW;
- content.widget = table->children->get(index)->cell.widget;
- return true;
-}
-
-void Table::TableIterator::highlight (int start, int end,
- core::HighlightLayer layer)
-{
- /** todo Needs this an implementation? */
-}
-
-void Table::TableIterator::unhighlight (int direction,
- core::HighlightLayer layer)
-{
-}
-
-void Table::TableIterator::getAllocation (int start, int end,
- core::Allocation *allocation)
-{
- /** \bug Not implemented. */
+
+ DBG_OBJ_LEAVE ();
}
} // namespace dw
diff --git a/dw/table.hh b/dw/table.hh
index 6966a163..b9dae75d 100644
--- a/dw/table.hh
+++ b/dw/table.hh
@@ -2,7 +2,7 @@
#define __DW_TABLE_HH__
#include "core.hh"
-#include "tablecell.hh"
+#include "alignedtablecell.hh"
#include "../lout/misc.hh"
namespace dw {
@@ -10,6 +10,11 @@ namespace dw {
/**
* \brief A Widget for rendering tables.
*
+ * <div style="border: 2px solid #ff0000; margin-top: 0.5em;
+ * margin-bottom: 0.5em; padding: 0.5em 1em;
+ * background-color: #ffefe0"><b>Warning:</b> Some parts of this
+ * description are outdated since \ref dw-grows.</div>
+ *
* <h3>Introduction</h3>
*
* The dw::Table widget is used to render HTML tables.
@@ -191,8 +196,9 @@ namespace dw {
*
* <ul>
* <li> the specified absolute width of the table, when given, or
- * <li> the available width (set by dw::Table::setWidth) times the specified
- * percentage width of t(at max 100%), if the latter is given, or
+ * <li> the available width (set by dw::Table::setWidth [TODO outdated]) times
+ * the specified percentage width of t(at max 100%), if the latter is
+ * given, or
* <li> otherwise the available width.
* </ul>
*
@@ -356,7 +362,6 @@ private:
friend class TableIterator;
bool limitTextWidth, rowClosed;
- int availWidth, availAscent, availDescent; // set by set...
int numRows, numCols, curRow, curCol;
lout::misc::SimpleVector<Child*> *children;
@@ -383,19 +388,22 @@ private:
* If a Cell has rowspan > 1, it goes into this array
*/
lout::misc::SimpleVector<int> *rowSpanCells;
- /**
- * If a Cell has colspan > 1, it goes into this array
- */
- lout::misc::SimpleVector<int> *colSpanCells;
lout::misc::SimpleVector<int> *baseline;
lout::misc::SimpleVector<core::style::Style*> *rowStyle;
- /**
- * hasColPercent becomes true when any cell specifies a percentage width.
- */
- int hasColPercent;
- lout::misc::SimpleVector<core::style::Length> *colPercents;
+ bool colWidthsUpToDateWidthColExtremes;
+
+ enum ExtrMod { MIN, MIN_INTR, MIN_MIN, MAX_MIN, MAX, MAX_INTR };
+
+ const char *getExtrModName (ExtrMod mod);
+ int getExtreme (core::Extremes *extremes, ExtrMod mod);
+ void setExtreme (core::Extremes *extremes, ExtrMod mod, int value);
+
+ inline int getColExtreme (int col, ExtrMod mod) {
+ return getExtreme (colExtremes->getRef(col), mod); }
+ inline void setColExtreme (int col, ExtrMod mod, int value) {
+ setExtreme (colExtremes->getRef(col), mod, value); }
inline bool childDefined(int n)
{
@@ -403,17 +411,23 @@ private:
children->get(n)->type != Child::SPAN_SPACE;
}
+ int calcAvailWidthForDescendant (Widget *child);
+
void reallocChildren (int newNumCols, int newNumRows);
- void calcCellSizes ();
- void forceCalcCellSizes ();
+ void calcCellSizes (bool calcHeights);
+ void forceCalcCellSizes (bool calcHeights);
void apportionRowSpan ();
void calcColumnExtremes ();
void forceCalcColumnExtremes ();
+ void calcExtremesSpanMulteCols (int col, int cs,
+ core::Extremes *cellExtremes,
+ ExtrMod minExtrMod, ExtrMod maxExtrMod);
- void apportion2 (int totalWidth, int forceTotalWidth);
- void apportion_percentages2 (int totalWidth, int forceTotalWidth);
+ void apportion2 (int totalWidth, int firstCol, int lastCol,
+ ExtrMod minExtrMod, ExtrMod maxExtrMod,
+ lout::misc::SimpleVector<int> *dest, int destOffset);
void setCumHeight (int row, int value)
{
@@ -423,23 +437,23 @@ private:
}
}
- inline void setColWidth (int col, int value)
- {
- if (value != colWidths->get (col)) {
- redrawX = lout::misc::min (redrawX, value);
- colWidths->set (col, value);
- }
- }
-
protected:
void sizeRequestImpl (core::Requisition *requisition);
void getExtremesImpl (core::Extremes *extremes);
void sizeAllocateImpl (core::Allocation *allocation);
void resizeDrawImpl ();
- void setWidth (int width);
- void setAscent (int ascent);
- void setDescent (int descent);
+ int getAvailWidthOfChild (Widget *child, bool forceValue);
+ void correctRequisitionOfChild (core::Widget *child,
+ core::Requisition *requisition,
+ void (*splitHeightFun) (int, int*, int*));
+
+ void containerSizeChangedForChildren ();
+ bool affectsSizeChangeContainerChild (Widget *child);
+ bool usesAvailWidth ();
+
+ bool isBlockLevel ();
+
void draw (core::View *view, core::Rectangle *area);
//bool buttonPressImpl (core::EventButton *event);
@@ -454,11 +468,14 @@ public:
Table(bool limitTextWidth);
~Table();
+ int applyPerWidth (int containerWidth, core::style::Length perWidth);
+ int applyPerHeight (int containerHeight, core::style::Length perHeight);
+
core::Iterator *iterator (core::Content::Type mask, bool atEnd);
void addCell (Widget *widget, int colspan, int rowspan);
void addRow (core::style::Style *style);
- TableCell *getCellRef ();
+ AlignedTableCell *getCellRef ();
};
} // namespace dw
diff --git a/dw/table_iterator.cc b/dw/table_iterator.cc
new file mode 100644
index 00000000..4da0ef4f
--- /dev/null
+++ b/dw/table_iterator.cc
@@ -0,0 +1,134 @@
+/*
+ * Dillo Widget
+ *
+ * Copyright 2005-2007, 2014 Sebastian Geerken <sgeerken@dillo.org>
+ *
+ * (This file was originally part of textblock.cc.)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "table.hh"
+
+using namespace lout;
+
+namespace dw {
+
+Table::TableIterator::TableIterator (Table *table,
+ core::Content::Type mask, bool atEnd):
+ core::Iterator (table, mask, atEnd)
+{
+ index = atEnd ? table->children->size () : -1;
+ content.type = atEnd ? core::Content::END : core::Content::START;
+}
+
+Table::TableIterator::TableIterator (Table *table,
+ core::Content::Type mask, int index):
+ core::Iterator (table, mask, false)
+{
+ this->index = index;
+
+ if (index < 0)
+ content.type = core::Content::START;
+ else if (index >= table->children->size ())
+ content.type = core::Content::END;
+ else {
+ content.type = core::Content::WIDGET_IN_FLOW;
+ content.widget = table->children->get(index)->cell.widget;
+ }
+}
+
+object::Object *Table::TableIterator::clone()
+{
+ return new TableIterator ((Table*)getWidget(), getMask(), index);
+}
+
+int Table::TableIterator::compareTo(object::Comparable *other)
+{
+ return index - ((TableIterator*)other)->index;
+}
+
+bool Table::TableIterator::next ()
+{
+ Table *table = (Table*)getWidget();
+
+ if (content.type == core::Content::END)
+ return false;
+
+ // tables only contain widgets (in flow):
+ if ((getMask() & core::Content::WIDGET_IN_FLOW) == 0) {
+ content.type = core::Content::END;
+ return false;
+ }
+
+ do {
+ index++;
+ if (index >= table->children->size ()) {
+ content.type = core::Content::END;
+ return false;
+ }
+ } while (table->children->get(index) == NULL ||
+ table->children->get(index)->type != Child::CELL);
+
+ content.type = core::Content::WIDGET_IN_FLOW;
+ content.widget = table->children->get(index)->cell.widget;
+ return true;
+}
+
+bool Table::TableIterator::prev ()
+{
+ Table *table = (Table*)getWidget();
+
+ if (content.type == core::Content::START)
+ return false;
+
+ // tables only contain widgets (in flow):
+ if ((getMask() & core::Content::WIDGET_IN_FLOW) == 0) {
+ content.type = core::Content::START;
+ return false;
+ }
+
+ do {
+ index--;
+ if (index < 0) {
+ content.type = core::Content::START;
+ return false;
+ }
+ } while (table->children->get(index) == NULL ||
+ table->children->get(index)->type != Child::CELL);
+
+ content.type = core::Content::WIDGET_IN_FLOW;
+ content.widget = table->children->get(index)->cell.widget;
+ return true;
+}
+
+void Table::TableIterator::highlight (int start, int end,
+ core::HighlightLayer layer)
+{
+ /** todo Needs this an implementation? */
+}
+
+void Table::TableIterator::unhighlight (int direction,
+ core::HighlightLayer layer)
+{
+}
+
+void Table::TableIterator::getAllocation (int start, int end,
+ core::Allocation *allocation)
+{
+ /** \bug Not implemented. */
+}
+
+} // namespace dw
diff --git a/dw/tablecell.hh b/dw/tablecell.hh
deleted file mode 100644
index 1e13abf9..00000000
--- a/dw/tablecell.hh
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef __DW_TABLECELL_HH__
-#define __DW_TABLECELL_HH__
-
-#include "core.hh"
-#include "alignedtextblock.hh"
-
-namespace dw {
-
-class TableCell: public AlignedTextblock
-{
-private:
- int charWordIndex, charWordPos;
-
-protected:
- int wordWrap (int wordIndex, bool wrapAll);
-
- int getValue ();
- void setMaxValue (int maxValue, int value);
-
-public:
- static int CLASS_ID;
-
- TableCell(TableCell *ref, bool limitTextWidth);
- ~TableCell();
-};
-
-} // namespace dw
-
-#endif // __DW_TABLECELL_HH__
diff --git a/dw/textblock.cc b/dw/textblock.cc
index 123b5b40..11bfdc0c 100644
--- a/dw/textblock.cc
+++ b/dw/textblock.cc
@@ -225,13 +225,11 @@ Textblock::Textblock (bool limitTextWidth)
{
DBG_OBJ_CREATE ("dw::Textblock");
registerName ("dw::Textblock", &CLASS_ID);
- setFlags (BLOCK_LEVEL);
- setFlags (USES_HINTS);
setButtonSensitive(true);
containingBlock = NULL;
hasListitemValue = false;
- innerPadding = 0;
+ leftInnerPadding = 0;
line1Offset = 0;
ignoreLine1OffsetSometimes = false;
mustQueueResize = false;
@@ -265,14 +263,9 @@ Textblock::Textblock (bool limitTextWidth)
hoverLink = -1;
- // random values
- availWidth = 100;
- availAscent = 100;
- availDescent = 0;
-
- DBG_OBJ_SET_NUM ("availWidth", availWidth);
- DBG_OBJ_SET_NUM ("availAscent", availAscent);
- DBG_OBJ_SET_NUM ("availDescent", availDescent);
+ // -1 means undefined.
+ lineBreakWidth = -1;
+ DBG_OBJ_SET_NUM ("lineBreakWidth", lineBreakWidth);
verticalOffset = 0;
DBG_OBJ_SET_NUM ("verticalOffset", verticalOffset);
@@ -335,9 +328,16 @@ Textblock::~Textblock ()
*/
void Textblock::sizeRequestImpl (core::Requisition *requisition)
{
- DBG_OBJ_MSG ("resize", 0, "<b>sizeRequestImpl</b> ()");
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER0 ("resize", 0, "sizeRequestImpl");
+ int newLineBreakWidth = getAvailWidth (true);
+ if (newLineBreakWidth != lineBreakWidth) {
+ lineBreakWidth = newLineBreakWidth;
+ wrapRefLines = 0;
+ DBG_OBJ_SET_NUM ("lineBreakWidth", lineBreakWidth);
+ DBG_OBJ_SET_NUM ("wrapRefLines", wrapRefLines);
+ }
+
rewrap ();
showMissingLines ();
@@ -369,18 +369,33 @@ void Textblock::sizeRequestImpl (core::Requisition *requisition)
requisition->descent = 0;
}
- DBG_OBJ_MSGF ("resize", 1, "inner padding = %d, boxDiffWidth = %d",
- innerPadding, getStyle()->boxDiffWidth ());
+ DBG_OBJ_MSGF ("resize", 1, "left inner padding = %d, boxDiffWidth = %d",
+ leftInnerPadding, getStyle()->boxDiffWidth ());
- requisition->width += innerPadding + getStyle()->boxDiffWidth ();
+ requisition->width += leftInnerPadding + getStyle()->boxDiffWidth ();
requisition->ascent += verticalOffset + getStyle()->boxOffsetY ();
requisition->descent += getStyle()->boxRestHeight ();
+ DBG_OBJ_MSGF ("resize", 1, "before correction: %d * (%d + %d)",
+ requisition->width, requisition->ascent, requisition->descent);
+
+ correctRequisition (requisition, core::splitHeightPreserveAscent);
+
// Dealing with parts out of flow, which may overlap the borders of
// the text block. Base lines are ignored here: they do not play a
// role (currently) and caring about them (for the future) would
// cause too much problems.
+ // Notice that the order is not typical: correctRequisition should
+ // be the last call. However, calling correctRequisition after
+ // outOfFlowMgr->getSize may result again in a size which is too
+ // small for floats, so triggering again (and again) the resize
+ // idle function resulting in CPU hogging. See also
+ // getExtremesImpl.
+ //
+ // Is this really what we want? An alternative could be that
+ // OutOfFlowMgr::getSize honours CSS attributes an corrected sizes.
+
DBG_OBJ_MSGF ("resize", 1, "before considering OOF widgets: %d * (%d + %d)",
requisition->width, requisition->ascent, requisition->descent);
@@ -392,21 +407,9 @@ void Textblock::sizeRequestImpl (core::Requisition *requisition)
requisition->descent = oofHeight - requisition->ascent;
}
- DBG_OBJ_MSGF ("resize", 1,
- "before considering availWidth (= %d): %d * (%d + %d)",
- availWidth, requisition->width, requisition->ascent,
- requisition->descent);
-
- if (requisition->width < availWidth) {
- requisition->width = availWidth;
- DBG_OBJ_MSGF ("resize", 1, "adjusting to availWidth => %d",
- requisition->width);
- }
-
- DBG_OBJ_MSGF ("resize", 1, "=> %d * (%d + %d)",
+ DBG_OBJ_MSGF ("resize", 1, "final: %d * (%d + %d)",
requisition->width, requisition->ascent, requisition->descent);
-
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
/**
@@ -414,88 +417,95 @@ void Textblock::sizeRequestImpl (core::Requisition *requisition)
*/
void Textblock::getWordExtremes (Word *word, core::Extremes *extremes)
{
- if (word->content.type == core::Content::WIDGET_IN_FLOW) {
- if (word->content.widget->usesHints ()) {
- word->content.widget->getExtremes (extremes);
-
- if (core::style::isAbsLength (word->content.widget
- ->getStyle()->width)) {
- int width =
- core::style::absLengthVal (word->content.widget
- ->getStyle()->width);
- if (extremes->minWidth < width)
- extremes->minWidth = width;
- if (extremes->maxWidth > width)
- // maxWidth not smaller than minWidth
- extremes->maxWidth = misc::max (width, extremes->minWidth);
- }
- } else {
- if (core::style::isPerLength
- (word->content.widget->getStyle()->width)) {
- extremes->minWidth = 0;
- if (word->content.widget->hasContents ())
- extremes->maxWidth = 1000000;
- else
- extremes->maxWidth = 0;
- } else if (core::style::isAbsLength
- (word->content.widget->getStyle()->width)) {
- /* Fixed lengths are only applied to the content, so we have to
- * add padding, border and margin. */
- extremes->minWidth = extremes->maxWidth =
- core::style::absLengthVal (word->content.widget->getStyle()
- ->width)
- + word->style->boxDiffWidth ();
- } else
- word->content.widget->getExtremes (extremes);
- }
- } else {
- extremes->minWidth = word->size.width;
- extremes->maxWidth = word->size.width;
- }
+ if (word->content.type == core::Content::WIDGET_IN_FLOW)
+ word->content.widget->getExtremes (extremes);
+ else
+ extremes->minWidth = extremes->minWidthIntrinsic = extremes->maxWidth =
+ extremes->maxWidthIntrinsic = word->size.width;
}
void Textblock::getExtremesImpl (core::Extremes *extremes)
{
- DBG_OBJ_MSG ("resize", 0, "<b>getExtremesImpl</b>");
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER0 ("resize", 0, "getExtremesImpl");
+
+ // TODO Can extremes depend on the available width? Should not; if
+ // they do, the following code must be reactivated, but it causes
+ // an endless recursion.
+#if 0
+ int newLineBreakWidth = getAvailWidth (true);
+ if (newLineBreakWidth != lineBreakWidth) {
+ lineBreakWidth = newLineBreakWidth;
+ wrapRefParagraphs = 0;
+ DBG_OBJ_SET_NUM ("lineBreakWidth", lineBreakWidth);
+ DBG_OBJ_SET_NUM ("wrapRefParagraphs", wrapRefLines);
+ }
+#endif
fillParagraphs ();
if (paragraphs->size () == 0) {
/* empty page */
extremes->minWidth = 0;
+ extremes->minWidthIntrinsic = 0;
extremes->maxWidth = 0;
+ extremes->maxWidthIntrinsic = 0;
} else {
Paragraph *lastPar = paragraphs->getLastRef ();
extremes->minWidth = lastPar->maxParMin;
+ extremes->minWidthIntrinsic = lastPar->maxParMinIntrinsic;
extremes->maxWidth = lastPar->maxParMax;
+ extremes->maxWidthIntrinsic = lastPar->maxParMaxIntrinsic;
- DBG_OBJ_MSGF ("resize", 1, "paragraphs[%d]->maxParMin = %d",
- paragraphs->size () - 1, lastPar->maxParMin);
- DBG_OBJ_MSGF ("resize", 1, "paragraphs[%d]->maxParMax = %d",
- paragraphs->size () - 1, lastPar->maxParMax);
+ DBG_OBJ_MSGF ("resize", 1, "paragraphs[%d]->maxParMin = %d (%d)",
+ paragraphs->size () - 1, lastPar->maxParMin,
+ lastPar->maxParMinIntrinsic);
+ DBG_OBJ_MSGF ("resize", 1, "paragraphs[%d]->maxParMax = %d (%d)",
+ paragraphs->size () - 1, lastPar->maxParMax,
+ lastPar->maxParMaxIntrinsic);
}
- int diff = innerPadding + getStyle()->boxDiffWidth ();
+ DBG_OBJ_MSGF ("resize", 0, "after considering paragraphs: %d (%d) / %d (%d)",
+ extremes->minWidth, extremes->minWidthIntrinsic,
+ extremes->maxWidth, extremes->maxWidthIntrinsic);
+
+ int diff = leftInnerPadding + getStyle()->boxDiffWidth ();
extremes->minWidth += diff;
+ extremes->minWidthIntrinsic += diff;
extremes->maxWidth += diff;
+ extremes->maxWidthIntrinsic += diff;
+
+ DBG_OBJ_MSGF ("resize", 0, "after adding diff: %d (%d) / %d (%d)",
+ extremes->minWidth, extremes->minWidthIntrinsic,
+ extremes->maxWidth, extremes->maxWidthIntrinsic);
+
+ // For the order, see similar reasoning in sizeRequestImpl.
+
+ correctExtremes (extremes);
+
+ DBG_OBJ_MSGF ("resize", 0, "after correction: %d (%d) / %d (%d)",
+ extremes->minWidth, extremes->minWidthIntrinsic,
+ extremes->maxWidth, extremes->maxWidthIntrinsic);
if (outOfFlowMgr) {
int oofMinWidth, oofMaxWidth;
outOfFlowMgr->getExtremes (extremes, &oofMinWidth, &oofMaxWidth);
- DBG_OBJ_MSGF ("resize", 1, "extremes: %d / %d, corrected: %d / %d",
- extremes->minWidth, extremes->maxWidth,
+ DBG_OBJ_MSGF ("resize", 1, "OOFM correction: %d / %d",
oofMinWidth, oofMaxWidth);
extremes->minWidth = misc::max (extremes->minWidth, oofMinWidth);
+ extremes->minWidthIntrinsic =
+ misc::max (extremes->minWidthIntrinsic, oofMinWidth);
extremes->maxWidth = misc::max (extremes->maxWidth, oofMaxWidth);
+ extremes->maxWidthIntrinsic =
+ misc::max (extremes->maxWidthIntrinsic, oofMinWidth);
}
- DBG_OBJ_MSGF ("resize", 1, "=> %d / %d",
- extremes->minWidth, extremes->maxWidth);
-
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_MSGF ("resize", 0,
+ "finally, after considering OOFM: %d (%d) / %d (%d)",
+ extremes->minWidth, extremes->minWidthIntrinsic,
+ extremes->maxWidth, extremes->maxWidthIntrinsic);
+ DBG_OBJ_LEAVE ();
}
@@ -523,8 +533,13 @@ void Textblock::sizeAllocateImpl (core::Allocation *allocation)
}
for (lineIndex = 0; lineIndex < lines->size (); lineIndex++) {
+ // Especially for floats, allocation->width may be different
+ // from the line break width, so that for centered and right
+ // text, the offsets have to be recalculated again.
+ calcTextOffset (lineIndex, allocation->width);
+
line = lines->getRef (lineIndex);
- xCursor = line->offsetCompleteWidget;
+ xCursor = line->textOffset;
for (wordIndex = line->firstWord; wordIndex <= line->lastWord;
wordIndex++) {
@@ -632,10 +647,30 @@ void Textblock::sizeAllocateImpl (core::Allocation *allocation)
}
}
+void Textblock::containerSizeChangedForChildren ()
+{
+ DBG_OBJ_ENTER0 ("resize", 0, "containerSizeChangedForChildren");
+
+ for (int i = 0; i < words->size (); i++) {
+ Word *word = words->getRef (i);
+ if (word->content.type == core::Content::WIDGET_IN_FLOW)
+ word->content.widget->containerSizeChanged ();
+ }
+
+ if (outOfFlowMgr)
+ outOfFlowMgr->containerSizeChangedForChildren ();
+
+ DBG_OBJ_LEAVE ();
+}
+
+bool Textblock::usesAvailWidth ()
+{
+ return true;
+}
+
void Textblock::resizeDrawImpl ()
{
- DBG_OBJ_MSG ("draw", 0, "<b>resizeDrawImpl</b> ()");
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER0 ("draw", 0, "resizeDrawImpl");
queueDrawArea (0, redrawY, allocation.width, getHeight () - redrawY);
if (lines->size () > 0) {
@@ -650,13 +685,12 @@ void Textblock::resizeDrawImpl ()
redrawY = getHeight ();
DBG_OBJ_SET_NUM ("redrawY", redrawY);
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
void Textblock::markSizeChange (int ref)
{
- DBG_OBJ_MSGF ("resize", 0, "<b>markSizeChange</b> (%d)", ref);
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("resize", 0, "markSizeChange", "%d", ref);
if (OutOfFlowMgr::isRefOutOfFlow (ref)) {
assert (outOfFlowMgr != NULL);
@@ -688,13 +722,12 @@ void Textblock::markSizeChange (int ref)
markExtremesChange (ref);
}
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
void Textblock::markExtremesChange (int ref)
{
- DBG_OBJ_MSGF ("resize", 1, "<b>markExtremesChange</b> (%d)", ref);
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("resize", 1, "markExtremesChange", "%d", ref);
if (OutOfFlowMgr::isRefOutOfFlow (ref)) {
assert (outOfFlowMgr != NULL);
@@ -720,7 +753,7 @@ void Textblock::markExtremesChange (int ref)
DBG_OBJ_SET_NUM ("wrapRefParagraphs", wrapRefParagraphs);
}
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
void Textblock::notifySetAsTopLevel()
@@ -773,53 +806,9 @@ void Textblock::notifySetParent ()
assert (containingBlock != NULL);
}
-void Textblock::setWidth (int width)
+bool Textblock::isBlockLevel ()
{
- /* If limitTextWidth is set to YES, a queueResize() may also be
- * necessary. */
- if (availWidth != width || limitTextWidth) {
- DBG_OBJ_MSGF ("resize", 0, "<b>setWidth</b> (%d)", width);
- DBG_OBJ_MSG_START ();
-
- availWidth = width;
- DBG_OBJ_SET_NUM ("availWidth", availWidth);
- queueResize (OutOfFlowMgr::createRefNormalFlow (0), false);
- mustQueueResize = false;
- redrawY = 0;
- DBG_OBJ_SET_NUM ("redrawY", redrawY);
-
- DBG_OBJ_MSG_END ();
- }
-}
-
-void Textblock::setAscent (int ascent)
-{
- if (availAscent != ascent) {
- DBG_OBJ_MSGF ("resize", 0, "<b>setAscent</b> (%d)", ascent);
- DBG_OBJ_MSG_START ();
-
- availAscent = ascent;
- DBG_OBJ_SET_NUM ("availAscent", availAscent);
- queueResize (OutOfFlowMgr::createRefNormalFlow (0), false);
- mustQueueResize = false;
-
- DBG_OBJ_MSG_END ();
- }
-}
-
-void Textblock::setDescent (int descent)
-{
- if (availDescent != descent) {
- DBG_OBJ_MSGF ("resize", 0, "<b>setDescent</b> (%d)", descent);
- DBG_OBJ_MSG_START ();
-
- availDescent = descent;
- DBG_OBJ_SET_NUM ("availDescent", availDescent);
- queueResize (OutOfFlowMgr::createRefNormalFlow (0), false);
- mustQueueResize = false;
-
- DBG_OBJ_MSG_END ();
- }
+ return true;
}
bool Textblock::buttonPressImpl (core::EventButton *event)
@@ -935,11 +924,11 @@ bool Textblock::sendSelectionEvent (core::SelectionState::EventType eventType,
// Choose this break.
wordIndex = line->lastWord;
charPos = core::SelectionState::END_OF_WORD;
- } else if (event->xWidget < line->offsetCompleteWidget) {
+ } else if (event->xWidget < line->textOffset) {
// Left of the first word in the line.
wordIndex = line->firstWord;
} else {
- int nextWordStartX = line->offsetCompleteWidget;
+ int nextWordStartX = line->textOffset;
for (wordIndex = line->firstWord;
wordIndex <= line->lastWord;
@@ -1052,93 +1041,24 @@ core::Iterator *Textblock::iterator (core::Content::Type mask, bool atEnd)
return new TextblockIterator (this, mask, atEnd);
}
-
/**
* Calculate the size of a widget within the page.
- * (Subject of change in the near future!)
*/
void Textblock::calcWidgetSize (core::Widget *widget, core::Requisition *size)
{
- DBG_OBJ_MSGF ("resize", 0, "<b>calcWidgetSize</b> (%p, ...)", widget);
-
- core::Requisition requisition;
- int availWidth, availAscent, availDescent;
- core::style::Style *wstyle = widget->getStyle();
+ DBG_OBJ_ENTER ("resize", 0, "calcWidgetSize", "%p, ...", widget);
- /* We ignore line1_offset[_eff]. */
- availWidth = this->availWidth - getStyle()->boxDiffWidth () - innerPadding;
- availAscent = this->availAscent - getStyle()->boxDiffHeight ();
- availDescent = this->availDescent;
-
- if (widget->usesHints ()) {
- // This is a simplified version of calcAvailWidth (see there for
- // more details). Until recently, the *attribute* availWidth was
- // used, widthout any corrections. To limit the damage, only
- // includde left and right border (by floats), until the Great
- // Redesign Of Widget Sizes (GROWS).
- int corrAvailWidth;
- // Textblocks keep track of borders themselves, so they get the
- // total available width. (Should once replaced by something
- // like OOFAware.)
- if (widget->instanceOf (Textblock::CLASS_ID))
- corrAvailWidth = availWidth;
- else
- corrAvailWidth =
- misc::max (availWidth - (newLineLeftBorder + newLineRightBorder),
- 0);
-
- DBG_OBJ_MSGF ("resize", 1, "setting hints: %d, %d, %d",
- corrAvailWidth, availAscent, availDescent);
- widget->setWidth (corrAvailWidth);
- widget->setAscent (availAscent);
- widget->setDescent (availDescent);
- widget->sizeRequest (size);
- DBG_OBJ_MSGF ("resize", 1, "sizeRequest => %d * (%d + %d)",
- size->width, size->ascent, size->descent);
- } else {
- if (wstyle->width == core::style::LENGTH_AUTO ||
- wstyle->height == core::style::LENGTH_AUTO) {
- widget->sizeRequest (&requisition);
- DBG_OBJ_MSGF ("resize", 1, "AUTO; sizeRequest => %d * (%d + %d)",
- requisition.width, requisition.ascent,
- requisition.descent);
- }
+ widget->sizeRequest (size);
- if (wstyle->width == core::style::LENGTH_AUTO)
- size->width = requisition.width;
- else if (core::style::isAbsLength (wstyle->width))
- /* Fixed lengths are only applied to the content, so we have to
- * add padding, border and margin. */
- size->width = core::style::absLengthVal (wstyle->width)
- + wstyle->boxDiffWidth ();
- else
- size->width =
- core::style::multiplyWithPerLength (availWidth, wstyle->width);
-
- if (wstyle->height == core::style::LENGTH_AUTO) {
- size->ascent = requisition.ascent;
- size->descent = requisition.descent;
- } else if (core::style::isAbsLength (wstyle->height)) {
- /* Fixed lengths are only applied to the content, so we have to
- * add padding, border and margin. */
- size->ascent = core::style::absLengthVal (wstyle->height)
- + wstyle->boxDiffHeight ();
- size->descent = 0;
- } else {
- size->ascent =
- core::style::multiplyWithPerLength (wstyle->height, availAscent);
- size->descent =
- core::style::multiplyWithPerLength (wstyle->height, availDescent);
- }
- }
-
- /* ascent and descent in words do not contain margins. */
+ // Ascent and descent in words do not contain margins.
+ // TODO: Re-evaluate (GROWS)!
+ core::style::Style *wstyle = widget->getStyle();
size->ascent -= wstyle->margin.top;
size->descent -= wstyle->margin.bottom;
DBG_OBJ_MSGF ("resize", 1, "result: %d * (%d + %d)",
size->width, size->ascent, size->descent);
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
/*
@@ -1450,11 +1370,10 @@ void Textblock::drawSpace(int wordIndex, core::View *view,
*/
void Textblock::drawLine (Line *line, core::View *view, core::Rectangle *area)
{
- DBG_OBJ_MSGF ("draw", 0, "<b>drawLine</b> (..., %d, %d, %d * %d)",
- area->x, area->y, area->width, area->height);
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("draw", 0, "drawLine", "..., %d, %d, %d * %d",
+ area->x, area->y, area->width, area->height);
- int xWidget = line->offsetCompleteWidget;
+ int xWidget = line->textOffset;
int yWidgetBase = lineYOffsetWidget (line) + line->boxAscent;
DBG_OBJ_MSGF ("draw", 1, "line from %d to %d (%d words), at (%d, %d)",
@@ -1516,7 +1435,7 @@ void Textblock::drawLine (Line *line, core::View *view, core::Rectangle *area)
xWidget += wordSize + word->effSpace;
}
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
/**
@@ -1647,7 +1566,7 @@ Textblock::Word *Textblock::findWord (int x, int y, bool *inSpace)
if (yWidgetBase + line->boxDescent <= y)
return NULL;
- xCursor = line->offsetCompleteWidget;
+ xCursor = line->textOffset;
for (wordIndex = line->firstWord; wordIndex <= line->lastWord;wordIndex++) {
word = words->getRef (wordIndex);
lastXCursor = xCursor;
@@ -1676,9 +1595,8 @@ Textblock::Word *Textblock::findWord (int x, int y, bool *inSpace)
void Textblock::draw (core::View *view, core::Rectangle *area)
{
- DBG_OBJ_MSGF ("draw", 0, "<b>draw</b> (%d, %d, %d * %d)",
- area->x, area->y, area->width, area->height);
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("draw", 0, "draw", "%d, %d, %d * %d",
+ area->x, area->y, area->width, area->height);
int lineIndex;
Line *line;
@@ -1707,7 +1625,7 @@ void Textblock::draw (core::View *view, core::Rectangle *area)
if(outOfFlowMgr)
outOfFlowMgr->draw(view, area);
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
/**
@@ -1716,9 +1634,13 @@ void Textblock::draw (core::View *view, core::Rectangle *area)
Textblock::Word *Textblock::addWord (int width, int ascent, int descent,
short flags, core::style::Style *style)
{
- DBG_OBJ_MSGF ("construct.word", 0, "<b>addWord</b> (%d * (%d + %d), %d, %p)",
- width, ascent, descent, flags, style);
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("construct.word", 0, "addWord", "%d * (%d + %d), %d, %p",
+ width, ascent, descent, flags, style);
+
+ if (lineBreakWidth == -1) {
+ lineBreakWidth = getAvailWidth (true);
+ DBG_OBJ_SET_NUM ("lineBreakWidth", lineBreakWidth);
+ }
words->increase ();
DBG_OBJ_SET_NUM ("words.size", words->size ());
@@ -1726,7 +1648,7 @@ Textblock::Word *Textblock::addWord (int width, int ascent, int descent,
initWord (wordNo);
fillWord (wordNo, width, ascent, descent, flags, style);
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
return words->getRef (wordNo);
}
@@ -1957,9 +1879,8 @@ void Textblock::calcTextSize (const char *text, size_t len,
void Textblock::addText (const char *text, size_t len,
core::style::Style *style)
{
- DBG_OBJ_MSGF ("construct.word", 0, "<b>addText</b> (..., %d, %p)",
- (int)len, style);
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("construct.word", 0, "addText", "..., %d, %p",
+ (int)len, style);
// Count dividing characters.
int numParts = 1;
@@ -2166,7 +2087,7 @@ void Textblock::addText (const char *text, size_t len,
}
}
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
void Textblock::calcTextSizes (const char *text, size_t textLen,
@@ -2209,20 +2130,18 @@ void Textblock::calcTextSizes (const char *text, size_t textLen,
void Textblock::addText0 (const char *text, size_t len, short flags,
core::style::Style *style, core::Requisition *size)
{
- DBG_OBJ_MSGF ("construct.word", 0,
- "<b>addText0</b> (..., %d, %s:%s:%s:%s:%s:%s:%s, %p, "
- "%d * (%d + %d)",
- (int)len,
- // Ugly copy&paste from printWordFlags:
- (flags & Word::CAN_BE_HYPHENATED) ? "h?" : "--",
- (flags & Word::DIV_CHAR_AT_EOL) ? "de" : "--",
- (flags & Word::PERM_DIV_CHAR) ? "dp" : "--",
- (flags & Word::DRAW_AS_ONE_TEXT) ? "t1" : "--",
- (flags & Word::UNBREAKABLE_FOR_MIN_WIDTH) ? "um" : "--",
- (flags & Word::WORD_START) ? "st" : "--",
- (flags & Word::WORD_END) ? "en" : "--",
- style, size->width, size->ascent, size->descent);
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("construct.word", 0, "addText0",
+ "..., %d, %s:%s:%s:%s:%s:%s:%s, %p, %d * (%d + %d)",
+ (int)len,
+ // Ugly copy&paste from printWordFlags:
+ (flags & Word::CAN_BE_HYPHENATED) ? "h?" : "--",
+ (flags & Word::DIV_CHAR_AT_EOL) ? "de" : "--",
+ (flags & Word::PERM_DIV_CHAR) ? "dp" : "--",
+ (flags & Word::DRAW_AS_ONE_TEXT) ? "t1" : "--",
+ (flags & Word::UNBREAKABLE_FOR_MIN_WIDTH) ? "um" : "--",
+ (flags & Word::WORD_START) ? "st" : "--",
+ (flags & Word::WORD_END) ? "en" : "--",
+ style, size->width, size->ascent, size->descent);
//printf("[%p] addText0 ('", this);
//for (size_t i = 0; i < len; i++)
@@ -2247,7 +2166,7 @@ void Textblock::addText0 (const char *text, size_t len, short flags,
processWord (words->size () - 1);
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
/**
@@ -2255,9 +2174,7 @@ void Textblock::addText0 (const char *text, size_t len, short flags,
*/
void Textblock::addWidget (core::Widget *widget, core::style::Style *style)
{
- DBG_OBJ_MSGF ("construct.word", 0, "<b>addWidget</b> (%p, %p)",
- widget, style);
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("construct.word", 0, "addWidget", "%p, %p", widget, style);
/* We first assign -1 as parent_ref, since the call of widget->size_request
* will otherwise let this Textblock be rewrapped from the beginning.
@@ -2317,7 +2234,7 @@ void Textblock::addWidget (core::Widget *widget, core::style::Style *style)
// "in page with %d word(s)\n",
// lines->size () - 1, words->size() - 1, words->size());
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
/**
@@ -2329,9 +2246,7 @@ void Textblock::addWidget (core::Widget *widget, core::style::Style *style)
*/
bool Textblock::addAnchor (const char *name, core::style::Style *style)
{
- DBG_OBJ_MSGF ("construct.word", 0, "<b>addAnchor</b> (\"%s\", %p)",
- name, style);
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("construct.word", 0, "addAnchor", "\"%s\", %p", name, style);
char *copy;
int y;
@@ -2365,7 +2280,7 @@ bool Textblock::addAnchor (const char *name, core::style::Style *style)
}
DBG_OBJ_MSGF ("construct.word", 0, "=> %s", result ? "true" : "false");
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
return result;
}
@@ -2375,8 +2290,7 @@ bool Textblock::addAnchor (const char *name, core::style::Style *style)
*/
void Textblock::addSpace (core::style::Style *style)
{
- DBG_OBJ_MSGF ("construct.word", 0, "<b>addSpace</b> (%p)", style);
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("construct.word", 0, "addSpace", "%p", style);
int wordIndex = words->size () - 1;
if (wordIndex >= 0) {
@@ -2386,7 +2300,7 @@ void Textblock::addSpace (core::style::Style *style)
correctLastWordExtremes ();
}
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
/**
@@ -2397,9 +2311,8 @@ void Textblock::addSpace (core::style::Style *style)
*/
void Textblock::addBreakOption (core::style::Style *style, bool forceBreak)
{
- DBG_OBJ_MSGF ("construct.word", 0, "<b>addBreakOption</b> (%p, %s)",
- style, forceBreak ? "true" : "false");
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("construct.word", 0, "addBreakOption", "%p, %s",
+ style, forceBreak ? "true" : "false");
int wordIndex = words->size () - 1;
if (wordIndex >= 0) {
@@ -2409,13 +2322,12 @@ void Textblock::addBreakOption (core::style::Style *style, bool forceBreak)
correctLastWordExtremes ();
}
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
void Textblock::fillSpace (int wordNo, core::style::Style *style)
{
- DBG_OBJ_MSGF ("construct.word", 0, "<b>fillSpace</b> (%d, ...)", wordNo);
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("construct.word", 0, "fillSpace", "%d, ...", wordNo);
DBG_OBJ_MSGF ("construct.word", 1, "style.white-space = %s",
style->whiteSpace == core::style::WHITE_SPACE_NORMAL ? "normal"
@@ -2464,7 +2376,7 @@ void Textblock::fillSpace (int wordNo, core::style::Style *style)
setSpaceImgRenderer (wordNo);
}
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
/**
@@ -2476,9 +2388,8 @@ void Textblock::setBreakOption (Word *word, core::style::Style *style,
int breakPenalty1, int breakPenalty2,
bool forceBreak)
{
- DBG_OBJ_MSGF ("construct.word", 0, "<b>setBreakOption</b> (..., %d, %d, %s)",
- breakPenalty1, breakPenalty2, forceBreak ? "true" : "false");
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("construct.word", 0, "setBreakOption", "..., %d, %d, %s",
+ breakPenalty1, breakPenalty2, forceBreak ? "true" : "false");
// TODO: lineMustBeBroken should be independent of the penalty
// index? Otherwise, examine the last line.
@@ -2489,7 +2400,7 @@ void Textblock::setBreakOption (Word *word, core::style::Style *style,
word->badnessAndPenalty.setPenalty (PENALTY_PROHIBIT_BREAK);
}
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
bool Textblock::isBreakAllowed (core::style::Style *style)
@@ -2517,9 +2428,11 @@ bool Textblock::isBreakAllowed (core::style::Style *style)
*/
void Textblock::addParbreak (int space, core::style::Style *style)
{
- DBG_OBJ_MSGF ("construct.word", 0, "<b>addParbreak</b> (%d, %p)",
- space, style);
- DBG_OBJ_MSG ("construct.word", 0, "<i>no nesting!</i>");
+ DBG_OBJ_ENTER ("construct.word", 0, "addParbreak", "%d, %p",
+ space, style);
+ DBG_OBJ_MSG ("construct.word", 0,
+ "<i>No nesting! Strack trace may be incomplete.</i>");
+ DBG_OBJ_LEAVE ();
Word *word;
@@ -2604,8 +2517,7 @@ void Textblock::addParbreak (int space, core::style::Style *style)
*/
void Textblock::addLinebreak (core::style::Style *style)
{
- DBG_OBJ_MSGF ("construct.word", 0, "<b>addLinebreak</b> (%p)", style);
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("construct.word", 0, "addLinebreak", "%p", style);
Word *word;
@@ -2630,7 +2542,7 @@ void Textblock::addLinebreak (core::style::Style *style)
breakAdded ();
processWord (words->size () - 1);
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
/**
@@ -2743,15 +2655,16 @@ void Textblock::handOverBreak (core::style::Style *style)
*/
void Textblock::flush ()
{
+ DBG_OBJ_ENTER0 ("resize", 0, "flush");
+
if (mustQueueResize) {
- DBG_OBJ_MSG ("resize", 0, "<b>flush</b> (mustQueueResize set)");
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_MSG ("resize", 0, "mustQueueResize set");
queueResize (-1, true);
mustQueueResize = false;
-
- DBG_OBJ_MSG_END ();
}
+
+ DBG_OBJ_LEAVE ();
}
@@ -2840,8 +2753,7 @@ void Textblock::queueDrawRange (int index1, int index2)
void Textblock::setVerticalOffset (int verticalOffset)
{
- DBG_OBJ_MSGF ("resize", 0, "<b>setVerticalOffset</b> (%d)", verticalOffset);
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("resize", 0, "setVerticalOffset", "%d", verticalOffset);
if (this->verticalOffset != verticalOffset) {
this->verticalOffset = verticalOffset;
@@ -2850,7 +2762,7 @@ void Textblock::setVerticalOffset (int verticalOffset)
queueDraw (); // Could perhaps be optimized.
}
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
/**
@@ -2863,8 +2775,7 @@ void Textblock::setVerticalOffset (int verticalOffset)
*/
void Textblock::borderChanged (int y, Widget *vloat)
{
- DBG_OBJ_MSGF ("resize", 0, "<b>borderChanged</b> (%d, %p)", y, vloat);
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("resize", 0, "borderChanged", "%d, %p", y, vloat);
int lineIndex = findLineIndex (y);
DBG_OBJ_MSGF ("resize", 1, "Line index: %d (of %d).",
@@ -2883,7 +2794,7 @@ void Textblock::borderChanged (int y, Widget *vloat)
DBG_OBJ_MSGF ("resize", 1, "Rewrapping from line %d (of %d).",
wrapLineIndex, lines->size ());
- if (vloat->getGenerator() == this) {
+ if (vloat->getGenerator() == this && lines->size () > 0) {
bool found = false;
// Sometimes, the respective word is not yet part of a
// line. Nothing to do, but because of the assertion below
@@ -2943,6 +2854,14 @@ void Textblock::borderChanged (int y, Widget *vloat)
exceeds = exceedsBeginning = lineIndex2 < 0;
}
+ DBG_OBJ_MSGF ("resize", 2,
+ "lineIndex2 = %d (of %d), exceeds = %s, "
+ "exceedsBeginning = %s, exceedsEnd = %s",
+ lineIndex2, lines->size (),
+ exceeds ? "true" : "false",
+ exceedsBeginning ? "true" : "false",
+ exceedsEnd ? "true" : "false");
+
if (exceedsBeginning && exceedsEnd)
break;
@@ -2983,7 +2902,7 @@ void Textblock::borderChanged (int y, Widget *vloat)
//DBG_OBJ_SET_NUM ("redrawY", redrawY);
}
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
void Textblock::printBorderChangedErrorAndAbort (int y, Widget *vloat,
@@ -3086,10 +3005,8 @@ Textblock *Textblock::getTextblockForLine (int firstWord, int lastWord)
*/
int Textblock::yOffsetOfPossiblyMissingLine (int lineNo)
{
- DBG_OBJ_MSGF ("line.yoffset", 0,
- "<b>yOffsetOfPossiblyMissingLine</b> (%d <i>of %d</i>)",
- lineNo, lines->size());
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("line.yoffset", 0, "yOffsetOfPossiblyMissingLine",
+ "%d <i>of %d</i>", lineNo, lines->size());
int result;
@@ -3109,17 +3026,15 @@ int Textblock::yOffsetOfPossiblyMissingLine (int lineNo)
prevLine->breakSpace, result);
}
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
return result;
}
int Textblock::heightOfPossiblyMissingLine (int lineNo)
{
- DBG_OBJ_MSGF ("line.height", 0,
- "<b>heightOfPossiblyMissingLine</b> (%d <i>of %d</i>)",
- lineNo, lines->size());
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("line.height", 0, "heightOfPossiblyMissingLine",
+ "%d <i>of %d</i>", lineNo, lines->size());
int result;
@@ -3156,7 +3071,7 @@ int Textblock::heightOfPossiblyMissingLine (int lineNo)
result = 1;
DBG_OBJ_MSGF ("line.height", 0, "result = %d", result);
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
return result;
}
diff --git a/dw/textblock.hh b/dw/textblock.hh
index 3254b843..5676f718 100644
--- a/dw/textblock.hh
+++ b/dw/textblock.hh
@@ -130,7 +130,7 @@ namespace dw {
* widget:
*
* <ul>
- * <li> The available size of the widget has changed, e.g., because the
+ * <li> The line break size of the widget has changed, e.g., because the
* user has changed the size of the browser window. In this case,
* it is necessary to rewrap all the lines.
*
@@ -306,14 +306,18 @@ protected:
int parMin; /* The sum of all word minima (plus spaces,
hyphen width etc.) since the last possible
break within this paragraph. */
+ int parMinIntrinsic;
int parMax; /* The sum of all word maxima in this
paragraph (plus spaces, hyphen width
etc.). */
+ int parMaxIntrinsic;
int maxParMin; /* Maximum of all paragraph minima (value of
"parMin"), including this paragraph. */
+ int maxParMinIntrinsic;
int maxParMax; /* Maximum of all paragraph maxima (value of
"parMax""), including this paragraph. */
+ int maxParMaxIntrinsic;
};
struct Line
@@ -334,8 +338,7 @@ protected:
int contentAscent; /* ??? */
int contentDescent; /* ??? */
int breakSpace; /* Space between this line and the next one. */
- int leftOffset; /* ??? */
- int offsetCompleteWidget; /* ??? */
+ int textOffset; /* ??? */
/* This is similar to descent, but includes the bottom margins of the
* widgets within this line. */
@@ -361,6 +364,9 @@ protected:
* even a following line, when positioned before (this is the
* reason this attribute exists); see \ref dw-out-of-flow. */
int lastOofRefPositionedBeforeThisLine;
+
+ int leftOffset, rightOffset;
+ enum { LEFT, RIGHT, CENTER } alignment;
};
struct Word
@@ -472,7 +478,7 @@ protected:
/* These fields provide some ad-hoc-functionality, used by sub-classes. */
bool hasListitemValue; /* If true, the first word of the page is treated
specially (search in source). */
- int innerPadding; /* This is an additional padding on the left side
+ int leftInnerPadding; /* This is an additional padding on the left side
(used by ListItem). */
int line1Offset; /* This is an additional offset of the first line.
May be negative (shift to left) or positive
@@ -489,7 +495,7 @@ protected:
* (which is used by DwTable!), and
* (ii) line1_offset is ignored (line1_offset_eff is set to 0),
* when line1_offset plus the width of the first word is
- * greater than the the available witdh.
+ * greater than the the line break witdh.
*
* \todo Eliminate all these ad-hoc features by a new, simpler and
* more elegant design. ;-)
@@ -516,8 +522,8 @@ protected:
int redrawY;
int lastWordDrawn;
- /* These values are set by set_... */
- int availWidth, availAscent, availDescent;
+ /* This value is (currently) set by setAscent(). */
+ int lineBreakWidth;
// Additional vertical offset, used for the "clear" attribute.
int verticalOffset;
@@ -702,8 +708,6 @@ protected:
bool sendSelectionEvent (core::SelectionState::EventType eventType,
core::MousePositionEvent *event);
- void accumulateWordExtremes (int firstWord, int lastWord,
- int *maxOfMinWidth, int *sumOfMaxWidth);
void processWord (int wordIndex);
virtual int wordWrap (int wordIndex, bool wrapAll);
int wrapWordInFlow (int wordIndex, bool wrapAll);
@@ -737,22 +741,26 @@ protected:
void moveWordIndices (int wordIndex, int num, int *addIndex1 = NULL);
void accumulateWordForLine (int lineIndex, int wordIndex);
void accumulateWordData (int wordIndex);
- int calcAvailWidth (int lineIndex);
+ int calcLineBreakWidth (int lineIndex);
void initLine1Offset (int wordIndex);
void alignLine (int lineIndex);
+ void calcTextOffset (int lineIndex, int totalWidth);
void sizeRequestImpl (core::Requisition *requisition);
void getExtremesImpl (core::Extremes *extremes);
void sizeAllocateImpl (core::Allocation *allocation);
+ void containerSizeChangedForChildren ();
+ bool usesAvailWidth ();
void resizeDrawImpl ();
void markSizeChange (int ref);
void markExtremesChange (int ref);
+
void notifySetAsTopLevel();
void notifySetParent();
- void setWidth (int width);
- void setAscent (int ascent);
- void setDescent (int descent);
+
+ bool isBlockLevel ();
+
void draw (core::View *view, core::Rectangle *area);
bool buttonPressImpl (core::EventButton *event);
@@ -808,15 +816,13 @@ public:
void borderChanged (int y, core::Widget *vloat);
inline void oofSizeChanged (bool extremesChanged) {
- DBG_OBJ_MSGF ("resize", 0, "<b>oofSizeChanged</b> (%s)",
- extremesChanged ? "true" : "false");
+ DBG_OBJ_ENTER ("resize", 0, "oofSizeChanged", "%s",
+ extremesChanged ? "true" : "false");
DBG_OBJ_MSG_START ();
queueResize (-1, extremesChanged);
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
- inline int getAvailWidth () { return availWidth; }
- inline int getAvailAscent () { return availAscent; }
- inline int getAvailDescent () { return availDescent; }
+ inline int getLineBreakWidth () { return lineBreakWidth; }
};
#define DBG_SET_WORD_PENALTY(n, i, is) \
diff --git a/dw/textblock_iterator.cc b/dw/textblock_iterator.cc
index c26b7f6e..56ad6e15 100644
--- a/dw/textblock_iterator.cc
+++ b/dw/textblock_iterator.cc
@@ -289,7 +289,7 @@ void Textblock::TextblockIterator::getAllocation (int start, int end,
Word *word = textblock->words->getRef (index);
allocation->x =
- textblock->allocation.x + line->offsetCompleteWidget;
+ textblock->allocation.x + line->textOffset;
for (int i = line->firstWord; i < index; i++) {
Word *w = textblock->words->getRef(i);
diff --git a/dw/textblock_linebreaking.cc b/dw/textblock_linebreaking.cc
index a773f24c..792f7d8a 100644
--- a/dw/textblock_linebreaking.cc
+++ b/dw/textblock_linebreaking.cc
@@ -92,7 +92,7 @@ void Textblock::BadnessAndPenalty::calcBadness (int totalWidth, int idealWidth,
badness = ratio * ratio * ratio;
}
}
- } else { // if (totalWidth > availWidth)
+ } else { // if (totalWidth > idealWidth)
if (totalShrinkability == 0)
badnessState = TOO_TIGHT;
else {
@@ -290,8 +290,7 @@ void Textblock::printWord (Word *word)
*/
void Textblock::justifyLine (Line *line, int diff)
{
- DBG_OBJ_MSGF ("construct.line", 0, "<b>justifyLine</b> (..., %d)", diff);
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("construct.line", 0, "justifyLine", "..., %d", diff);
// To avoid rounding errors, the calculation is based on accumulated
// values. See doc/rounding-errors.doc.
@@ -342,16 +341,16 @@ void Textblock::justifyLine (Line *line, int diff)
}
}
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
Textblock::Line *Textblock::addLine (int firstWord, int lastWord,
int newLastOofPos, bool temporary)
{
- DBG_OBJ_MSGF ("construct.line", 0, "<b>addLine</b> (%d, %d) => %d",
- firstWord, lastWord, lines->size ());
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("construct.line", 0, "addLine", "%d, %d",
+ firstWord, lastWord);
+ DBG_OBJ_MSGF ("construct.line", 0, "=> %d", lines->size ());
int lineWidth;
if (lastWord >= firstWord) {
@@ -378,10 +377,6 @@ Textblock::Line *Textblock::addLine (int firstWord, int lastWord,
lineWidth);
}
- int maxOfMinWidth, sumOfMaxWidth;
- accumulateWordExtremes (firstWord, lastWord, &maxOfMinWidth,
- &sumOfMaxWidth);
-
lines->increase ();
DBG_OBJ_SET_NUM ("lines.size", lines->size ());
@@ -403,10 +398,17 @@ Textblock::Line *Textblock::addLine (int firstWord, int lastWord,
line->boxDescent = line->contentDescent = 0;
line->marginDescent = 0;
line->breakSpace = 0;
- line->leftOffset = 0;
line->finished = false;
+
+ bool regardBorder = mustBorderBeRegarded (line);
+ line->leftOffset = misc::max (regardBorder ? newLineLeftBorder : 0,
+ boxOffsetX () + leftInnerPadding
+ + (lineIndex == 0 ? line1OffsetEff : 0));
+ line->rightOffset = misc::max (regardBorder ? newLineRightBorder : 0,
+ boxRestWidth ());
alignLine (lineIndex);
+ calcTextOffset (lineIndex, lineBreakWidth);
for (int i = line->firstWord; i < line->lastWord; i++) {
Word *word = words->getRef (i);
@@ -438,14 +440,6 @@ Textblock::Line *Textblock::addLine (int firstWord, int lastWord,
// the height should be positive.
line->boxAscent = misc::max (line->boxAscent, 1);
- // Calculate offsetCompleteWidget, which includes also floats.
- int leftBorder = mustBorderBeRegarded (line) ? newLineLeftBorder : 0;
- line->offsetCompleteWidget =
- misc::max (leftBorder,
- getStyle()->boxOffsetX() + innerPadding
- + (lineIndex == 0 ? line1OffsetEff : 0))
- + line->leftOffset;
-
DBG_OBJ_MSGF ("construct.line", 1, "top = %d\n", line->top);
DBG_OBJ_MSGF ("construct.line", 1, "boxAscent = %d\n", line->boxAscent);
DBG_OBJ_MSGF ("construct.line", 1, "boxDescent = %d\n", line->boxDescent);
@@ -455,8 +449,7 @@ Textblock::Line *Textblock::addLine (int firstWord, int lastWord,
line->contentDescent);
DBG_OBJ_MSGF ("construct.line", 1, "maxLineWidth = %d (lineWidth = %d)\n",
line->maxLineWidth, lineWidth);
- DBG_OBJ_MSGF ("construct.line", 1, "offsetCompleteWidget = %d\n",
- line->offsetCompleteWidget);
+ DBG_OBJ_MSGF ("construct.line", 1, "textOffset = %d\n", line->textOffset);
mustQueueResize = true;
@@ -467,7 +460,7 @@ Textblock::Line *Textblock::addLine (int firstWord, int lastWord,
//words->getRef(line->lastWord)->badnessAndPenalty.print ();
//printf ("\n");
- int xWidget = line->offsetCompleteWidget;
+ int xWidget = line->textOffset;
for (int i = firstWord; i <= lastWord; i++) {
Word *word = words->getRef (i);
if (word->wordImgRenderer)
@@ -485,52 +478,13 @@ Textblock::Line *Textblock::addLine (int firstWord, int lastWord,
initNewLine ();
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
return line;
}
-void Textblock::accumulateWordExtremes (int firstWord, int lastWord,
- int *maxOfMinWidth, int *sumOfMaxWidth)
-{
- int parMin = 0;
- *maxOfMinWidth = *sumOfMaxWidth = 0;
-
- for (int i = firstWord; i <= lastWord; i++) {
- Word *word = words->getRef (i);
- bool atLastWord = i == lastWord;
-
- core::Extremes extremes;
- getWordExtremes (word, &extremes);
-
- // Minimum: between two *possible* breaks (or at the end).
- // TODO This is redundant to getExtremesImpl().
- // TODO: Again, index 1 is used for lineCanBeBroken(). See getExtremes().
- if (word->badnessAndPenalty.lineCanBeBroken (1) || atLastWord) {
- parMin += extremes.minWidth + word->hyphenWidth;
- *maxOfMinWidth = misc::max (*maxOfMinWidth, parMin);
- parMin = 0;
- } else
- // Shrinkability could be considered, but really does not play a
- // role.
- parMin += extremes.minWidth + word->origSpace;
-
- //printf ("[%p] after word: ", this);
- //printWord (word);
- //printf ("\n");
-
- //printf ("[%p] (%d / %d) => parMin = %d, maxOfMinWidth = %d\n",
- // this, extremes.minWidth, extremes.maxWidth, parMin,
- // *maxOfMinWidth);
-
- *sumOfMaxWidth += (extremes.maxWidth + word->origSpace);
- // Notice that the last space is added. See also: Line::parMax.
- }
-}
-
void Textblock::processWord (int wordIndex)
{
- DBG_OBJ_MSGF ("construct.all", 0, "<b>processWord</b> (%d)", wordIndex);
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("construct.all", 0, "processWord", "%d", wordIndex);
DBG_MSG_WORD ("construct.all", 1, "<i>processed word:</i>", wordIndex, "");
int diffWords = wordWrap (wordIndex, false);
@@ -576,7 +530,7 @@ void Textblock::processWord (int wordIndex)
DBG_OBJ_MSG_END ();
}
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
/*
@@ -589,10 +543,8 @@ void Textblock::processWord (int wordIndex)
*/
int Textblock::wordWrap (int wordIndex, bool wrapAll)
{
- DBG_OBJ_MSGF ("construct.word", 0, "<b>wordWrap</b> (%d, %s)",
+ DBG_OBJ_ENTER ("construct.word", 0, "wordWrap", "%d, %s",
wordIndex, wrapAll ? "true" : "false");
- DBG_OBJ_MSG_START ();
-
DBG_MSG_WORD ("construct.word", 1, "<i>wrapped word:</i> ", wordIndex, "");
if (!wrapAll)
@@ -612,16 +564,15 @@ int Textblock::wordWrap (int wordIndex, bool wrapAll)
n = wrapWordInFlow (wordIndex, wrapAll);
DBG_OBJ_MSGF ("construct.word", 1, "=> %d", n);
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
return n;
}
int Textblock::wrapWordInFlow (int wordIndex, bool wrapAll)
{
- DBG_OBJ_MSGF ("construct.word", 0, "<b>wrapWordInFlow</b> (%d, %s)",
+ DBG_OBJ_ENTER ("construct.word", 0, "wrapWordInFlow", "%d, %s",
wordIndex, wrapAll ? "true" : "false");
- DBG_OBJ_MSG_START ();
Word *word = words->getRef (wordIndex);
int diffWords = 0;
@@ -637,7 +588,7 @@ int Textblock::wrapWordInFlow (int wordIndex, bool wrapAll)
// be left empty.
// (In other cases, lines are never left empty, even if this means
- // that the contents is wider than the available witdh. Leaving
+ // that the contents is wider than the line break width. Leaving
// lines empty does not make sense without floats, since there will
// be no possibility with more space anymore.)
@@ -846,7 +797,7 @@ int Textblock::wrapWordInFlow (int wordIndex, bool wrapAll)
}
}
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
return diffWords;
}
@@ -863,15 +814,13 @@ void Textblock::balanceBreakPosAndHeight (int wordIndex, int firstIndex,
bool regardBorder, int *height,
int *breakPos)
{
- DBG_OBJ_MSGF ("construct.word", 0,
- "<b>balanceBreakPosAndHeight</b> (%d, %d. %d, %s, %d, %s, "
- "..., %s, ..., %d, %s, %d, ...)",
- wordIndex, firstIndex, *searchUntil,
- tempNewLine ? "true" : "false", penaltyIndex,
- borderIsCalculated ? "true" : "false",
- wrapAll ? "true" : "false", *lastFloatPos,
- regardBorder ? "true" : "false", *height);
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("construct.word", 0, "balanceBreakPosAndHeight",
+ "%d, %d. %d, %s, %d, %s, ..., %s, ..., %d, %s, %d, ...",
+ wordIndex, firstIndex, *searchUntil,
+ tempNewLine ? "true" : "false", penaltyIndex,
+ borderIsCalculated ? "true" : "false",
+ wrapAll ? "true" : "false", *lastFloatPos,
+ regardBorder ? "true" : "false", *height);
// The height of this part of the line (until the new break
// position) may change with the break position, but the break
@@ -947,7 +896,7 @@ void Textblock::balanceBreakPosAndHeight (int wordIndex, int firstIndex,
runNo++;
}
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
// *wordIndexEnd must be initialized (initially to wordIndex)
@@ -957,13 +906,12 @@ int Textblock::searchBreakPos (int wordIndex, int firstIndex, int *searchUntil,
int *diffWords, int *wordIndexEnd,
int *addIndex1)
{
- DBG_OBJ_MSGF ("construct.word", 0,
- "<b>searchBreakPos</b> (%d, %d. %d, %s, %d, %s, %s, ...)",
- wordIndex, firstIndex, *searchUntil,
- tempNewLine ? "true" : "false", penaltyIndex,
- thereWillBeMoreSpace ? "true" : "false",
- wrapAll ? "true" : "false");
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("construct.word", 0, "searchBreakPos",
+ "%d, %d. %d, %s, %d, %s, %s, ...",
+ wordIndex, firstIndex, *searchUntil,
+ tempNewLine ? "true" : "false", penaltyIndex,
+ thereWillBeMoreSpace ? "true" : "false",
+ wrapAll ? "true" : "false");
DBG_MSG_WORD ("construct.word", 0, "<i>first word:</i> ", firstIndex, "");
int result;
@@ -1053,7 +1001,7 @@ int Textblock::searchBreakPos (int wordIndex, int firstIndex, int *searchUntil,
} while(!lineAdded);
DBG_OBJ_MSGF ("construct.word", 1, "=> %d", result);
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
return result;
}
@@ -1061,12 +1009,10 @@ int Textblock::searchBreakPos (int wordIndex, int firstIndex, int *searchUntil,
int Textblock::searchMinBap (int firstWord, int lastWord, int penaltyIndex,
bool thereWillBeMoreSpace, bool correctAtEnd)
{
- DBG_OBJ_MSGF ("construct.word", 0,
- "<b>searchMinBap</b> (%d, %d, %d, %s, %s)",
- firstWord, lastWord, penaltyIndex,
- thereWillBeMoreSpace ? "true" : "false",
- correctAtEnd ? "true" : "false");
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("construct.word", 0, "searchMinBap", "%d, %d, %d, %s, %s",
+ firstWord, lastWord, penaltyIndex,
+ thereWillBeMoreSpace ? "true" : "false",
+ correctAtEnd ? "true" : "false");
int pos = -1;
@@ -1123,7 +1069,7 @@ int Textblock::searchMinBap (int firstWord, int lastWord, int penaltyIndex,
}
}
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
return pos;
}
@@ -1197,9 +1143,8 @@ void Textblock::handleWordExtremes (int wordIndex)
{
// TODO Overall, clarify penalty index.
- DBG_OBJ_MSGF ("construct.paragraph", 0,
- "<b>handleWordExtremes</b> (%d)", wordIndex);
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("construct.paragraph", 0, "handleWordExtremes", "%d",
+ wordIndex);
initLine1Offset (wordIndex);
@@ -1209,12 +1154,15 @@ void Textblock::handleWordExtremes (int wordIndex)
core::Extremes wordExtremes;
getWordExtremes (word, &wordExtremes);
- DBG_OBJ_MSGF ("construct.paragraph", 1, "extremes: %d / %d",
- wordExtremes.minWidth, wordExtremes.maxWidth);
+ DBG_OBJ_MSGF ("construct.paragraph", 1, "extremes: %d (%d) / %d (%d)",
+ wordExtremes.minWidth, wordExtremes.minWidthIntrinsic,
+ wordExtremes.maxWidth, wordExtremes.maxWidthIntrinsic);
if (wordIndex == 0) {
wordExtremes.minWidth += line1OffsetEff;
+ wordExtremes.minWidthIntrinsic += line1OffsetEff;
wordExtremes.maxWidth += line1OffsetEff;
+ wordExtremes.maxWidthIntrinsic += line1OffsetEff;
}
if (paragraphs->size() == 0 ||
@@ -1227,13 +1175,17 @@ void Textblock::handleWordExtremes (int wordIndex)
Paragraph *par = paragraphs->getLastRef();
par->firstWord = par->lastWord = wordIndex;
- par->parMin = par->parMax = 0;
+ par->parMin = par->parMinIntrinsic = par->parMax = par->parMaxIntrinsic
+ = 0;
if (prevPar) {
par->maxParMin = prevPar->maxParMin;
+ par->maxParMinIntrinsic = prevPar->maxParMinIntrinsic;
par->maxParMax = prevPar->maxParMax;
+ par->maxParMaxIntrinsic = prevPar->maxParMaxIntrinsic;
} else
- par->maxParMin = par->maxParMax = 0;
+ par->maxParMin = par->maxParMinIntrinsic = par->maxParMax =
+ par->maxParMaxIntrinsic = 0;
DBG_OBJ_MSGF ("construct.paragraph", 1, "new par: %d",
paragraphs->size() - 1);
@@ -1261,25 +1213,44 @@ void Textblock::handleWordExtremes (int wordIndex)
lastPar->firstWord, lastPar->lastWord, corrDiffMin,
corrDiffMax);
+ DBG_OBJ_MSGF ("construct.paragraph", 1,
+ "before: parMin = %d (%d) (max = %d (%d)), "
+ "parMax = %d (%d) (max = %d (%d))",
+ lastPar->parMin, lastPar->parMinIntrinsic,
+ lastPar->maxParMin, lastPar->maxParMinIntrinsic,
+ lastPar->parMax, lastPar->parMaxIntrinsic,
+ lastPar->maxParMax, lastPar->maxParMaxIntrinsic);
+
// Minimum: between two *possible* breaks.
// Shrinkability could be considered, but really does not play a role.
lastPar->parMin += wordExtremes.minWidth + word->hyphenWidth + corrDiffMin;
+ lastPar->parMinIntrinsic +=
+ wordExtremes.minWidthIntrinsic + word->hyphenWidth + corrDiffMin;
lastPar->maxParMin = misc::max (lastPar->maxParMin, lastPar->parMin);
+ lastPar->maxParMinIntrinsic =
+ misc::max (lastPar->maxParMinIntrinsic, lastPar->parMinIntrinsic);
if (word->badnessAndPenalty.lineCanBeBroken (1) &&
(word->flags & Word::UNBREAKABLE_FOR_MIN_WIDTH) == 0)
- lastPar->parMin = 0;
+ lastPar->parMin = lastPar->parMinIntrinsic = 0;
// Maximum: between two *necessary* breaks.
lastPar->parMax += wordExtremes.maxWidth + word->hyphenWidth + corrDiffMax;
+ lastPar->parMaxIntrinsic +=
+ wordExtremes.maxWidthIntrinsic + word->hyphenWidth + corrDiffMax;
lastPar->maxParMax = misc::max (lastPar->maxParMax, lastPar->parMax);
+ lastPar->maxParMaxIntrinsic =
+ misc::max (lastPar->maxParMaxIntrinsic, lastPar->parMaxIntrinsic);
DBG_OBJ_MSGF ("construct.paragraph", 1,
- "=> parMin = %d (max = %d), parMax = %d (max = %d)",
- lastPar->parMin, lastPar->maxParMin, lastPar->parMax,
- lastPar->maxParMax);
+ "after: parMin = %d (%d) (max = %d (%d)), "
+ "parMax = %d (%d) (max = %d (%d))",
+ lastPar->parMin, lastPar->parMinIntrinsic,
+ lastPar->maxParMin, lastPar->maxParMinIntrinsic,
+ lastPar->parMax, lastPar->parMaxIntrinsic,
+ lastPar->maxParMax, lastPar->maxParMaxIntrinsic);
lastPar->lastWord = wordIndex;
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
/**
@@ -1291,7 +1262,8 @@ void Textblock::correctLastWordExtremes ()
Word *word = words->getLastRef ();
if (word->badnessAndPenalty.lineCanBeBroken (1) &&
(word->flags & Word::UNBREAKABLE_FOR_MIN_WIDTH) == 0) {
- paragraphs->getLastRef()->parMin = 0;
+ paragraphs->getLastRef()->parMin =
+ paragraphs->getLastRef()->parMinIntrinsic = 0;
PRINTF (" => corrected; parMin = %d\n",
paragraphs->getLastRef()->parMin);
}
@@ -1408,9 +1380,8 @@ int Textblock::hyphenateWord (int wordIndex, int *addIndex1)
void Textblock::moveWordIndices (int wordIndex, int num, int *addIndex1)
{
- DBG_OBJ_MSGF ("construct.word", 0, "<b>moveWordIndices</b> (%d, %d)",
+ DBG_OBJ_ENTER ("construct.word", 0, "moveWordIndices", "%d, %d",
wordIndex, num);
- DBG_OBJ_MSG_START ();
if (containingBlock->outOfFlowMgr)
containingBlock->outOfFlowMgr->moveExternalIndices (this, wordIndex, num);
@@ -1437,7 +1408,7 @@ void Textblock::moveWordIndices (int wordIndex, int num, int *addIndex1)
if (addIndex1 && *addIndex1 >= wordIndex)
*addIndex1 += num;
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
void Textblock::accumulateWordForLine (int lineIndex, int wordIndex)
@@ -1474,7 +1445,7 @@ void Textblock::accumulateWordForLine (int lineIndex, int wordIndex)
word->content.widget->getStyle()->margin.bottom);
if (lines->size () == 1 &&
- word->content.widget->blockLevel () &&
+ word->content.widget->isBlockLevel () &&
getStyle ()->borderWidth.top == 0 &&
getStyle ()->padding.top == 0) {
// collapse top margins of parent element and its first child
@@ -1505,9 +1476,8 @@ void Textblock::accumulateWordForLine (int lineIndex, int wordIndex)
void Textblock::accumulateWordData (int wordIndex)
{
- DBG_OBJ_MSGF ("construct.word.accum", 1, "<b>accumulateWordData</b> (%d)",
+ DBG_OBJ_ENTER ("construct.word.accum", 1, "accumulateWordData", "%d",
wordIndex);
- DBG_OBJ_MSG_START ();
DBG_MSG_WORD ("construct.word.accum", 1, "<i>word:</i> ", wordIndex, "");
// Typically, the word in question is in the last line; in any case
@@ -1526,12 +1496,13 @@ void Textblock::accumulateWordData (int wordIndex)
Word *word = words->getRef (wordIndex);
DBG_OBJ_MSGF ("construct.word.accum", 2, "lineIndex = %d", lineIndex);
- int availWidth = calcAvailWidth (lineIndex);
+ int lineBreakWidth = calcLineBreakWidth (lineIndex);
DBG_OBJ_MSGF ("construct.word.accum", 2,
- "(%s existing line %d starts with word %d; availWidth = %d)",
+ "(%s existing line %d starts with word %d; "
+ "lineBreakWidth = %d)",
lineIndex < lines->size () ? "already" : "not yet",
- lineIndex, firstWordOfLine, availWidth);
+ lineIndex, firstWordOfLine, lineBreakWidth);
if (wordIndex == firstWordOfLine) {
// first word of the (not neccessarily yet existing) line
@@ -1582,7 +1553,7 @@ void Textblock::accumulateWordData (int wordIndex)
"totalShrinkability = %d + ... = %d",
word->totalSpaceShrinkability, totalShrinkability);
- word->badnessAndPenalty.calcBadness (word->totalWidth, availWidth,
+ word->badnessAndPenalty.calcBadness (word->totalWidth, lineBreakWidth,
totalStretchability,
totalShrinkability);
@@ -1592,25 +1563,23 @@ void Textblock::accumulateWordData (int wordIndex)
DBG_OBJ_MSGF ("construct.word.accum", 1, "b+p: %s", sb.getChars ());
}
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
-int Textblock::calcAvailWidth (int lineIndex)
+int Textblock::calcLineBreakWidth (int lineIndex)
{
- DBG_OBJ_MSGF ("construct.word.width", 1,
- "<b>calcAvailWidth</b> (%d <i>of %d</i>)",
- lineIndex, lines->size());
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("construct.word.width", 1, "calcLineBreakWidth",
+ "%d <i>of %d</i>", lineIndex, lines->size());
- int availWidth = this->availWidth - innerPadding;
+ int lineBreakWidth = this->lineBreakWidth - leftInnerPadding;
if (limitTextWidth &&
layout->getUsesViewport () &&
// margin/border/padding will be subtracted later, via OOFM.
- availWidth - getStyle()->boxDiffWidth()
+ lineBreakWidth - getStyle()->boxDiffWidth()
> layout->getWidthViewport () - 10)
- availWidth = layout->getWidthViewport () - 10;
+ lineBreakWidth = layout->getWidthViewport () - 10;
if (lineIndex == 0)
- availWidth -= line1OffsetEff;
+ lineBreakWidth -= line1OffsetEff;
int leftBorder, rightBorder;
if (mustBorderBeRegarded (lineIndex)) {
@@ -1622,14 +1591,14 @@ int Textblock::calcAvailWidth (int lineIndex)
leftBorder = misc::max (leftBorder, getStyle()->boxOffsetX());
rightBorder = misc::max (rightBorder, getStyle()->boxRestWidth());
- availWidth -= (leftBorder + rightBorder);
+ lineBreakWidth -= (leftBorder + rightBorder);
DBG_OBJ_MSGF ("construct.word.width", 2, "=> %d - %d - (%d + %d) = %d\n",
- this->availWidth, innerPadding, leftBorder, rightBorder,
- availWidth);
+ this->lineBreakWidth, leftInnerPadding, leftBorder,
+ rightBorder, lineBreakWidth);
- DBG_OBJ_MSG_END ();
- return availWidth;
+ DBG_OBJ_LEAVE ();
+ return lineBreakWidth;
}
void Textblock::initLine1Offset (int wordIndex)
@@ -1639,18 +1608,18 @@ void Textblock::initLine1Offset (int wordIndex)
/* Test whether line1Offset can be used. */
if (wordIndex == 0) {
if (ignoreLine1OffsetSometimes &&
- line1Offset + word->size.width > availWidth) {
+ line1Offset + word->size.width > lineBreakWidth) {
line1OffsetEff = 0;
} else {
int indent = 0;
if (word->content.type == core::Content::WIDGET_IN_FLOW &&
- word->content.widget->blockLevel() == true) {
+ word->content.widget->isBlockLevel()) {
/* don't use text-indent when nesting blocks */
} else {
if (core::style::isPerLength(getStyle()->textIndent)) {
indent = core::style::multiplyWithPerLengthRounded
- (this->availWidth, getStyle()->textIndent);
+ (lineBreakWidth, getStyle()->textIndent);
} else {
indent = core::style::absLengthVal (getStyle()->textIndent);
}
@@ -1667,14 +1636,15 @@ void Textblock::initLine1Offset (int wordIndex)
*/
void Textblock::alignLine (int lineIndex)
{
- DBG_OBJ_MSGF ("construct.line", 0, "<b>alignLine</b> (%d)", lineIndex);
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("construct.line", 0, "alignLine", "%d", lineIndex);
Line *line = lines->getRef (lineIndex);
- int availWidth = calcAvailWidth (lineIndex);
+
if (line->firstWord <= line->lastWord) {
Word *firstWord = words->getRef (line->firstWord);
Word *lastWord = words->getRef (line->lastWord);
+ int lineBreakWidth =
+ this->lineBreakWidth - (line->leftOffset + line->rightOffset);
for (int i = line->firstWord; i < line->lastWord; i++)
words->getRef(i)->origSpace = words->getRef(i)->effSpace;
@@ -1684,18 +1654,18 @@ void Textblock::alignLine (int lineIndex)
case core::style::TEXT_ALIGN_LEFT:
DBG_OBJ_MSG ("construct.line", 1,
"first word has 'text-align: left'");
- line->leftOffset = 0;
+ line->alignment = Line::LEFT;
break;
case core::style::TEXT_ALIGN_STRING: /* handled elsewhere (in the
* future)? */
DBG_OBJ_MSG ("construct.line", 1,
"first word has 'text-align: string'");
- line->leftOffset = 0;
+ line->alignment = Line::LEFT;
break;
case core::style::TEXT_ALIGN_JUSTIFY: /* see some lines above */
- line->leftOffset = 0;
DBG_OBJ_MSG ("construct.line", 1,
"first word has 'text-align: justify'");
+ line->alignment = Line::LEFT;
// Do not justify the last line of a paragraph (which ends on a
// BREAK or with the last word of the page).
if(!(lastWord->content.type == core::Content::BREAK ||
@@ -1704,33 +1674,62 @@ void Textblock::alignLine (int lineIndex)
// when the line would be shrunken otherwise. (This solution is
// far from perfect, but a better solution would make changes in
// the line breaking algorithm necessary.)
- availWidth < lastWord->totalWidth)
- justifyLine (line, availWidth - lastWord->totalWidth);
+ lineBreakWidth < lastWord->totalWidth)
+ justifyLine (line, lineBreakWidth - lastWord->totalWidth);
break;
case core::style::TEXT_ALIGN_RIGHT:
DBG_OBJ_MSG ("construct.line", 1,
"first word has 'text-align: right'");
- line->leftOffset = availWidth - lastWord->totalWidth;
+ line->alignment = Line::RIGHT;
break;
case core::style::TEXT_ALIGN_CENTER:
DBG_OBJ_MSG ("construct.line", 1,
"first word has 'text-align: center'");
- line->leftOffset = (availWidth - lastWord->totalWidth) / 2;
+ line->alignment = Line::CENTER;
break;
default:
- /* compiler happiness */
- line->leftOffset = 0;
+ // compiler happiness
+ line->alignment = Line::LEFT;
}
- /* For large lines (images etc), which do not fit into the viewport: */
- if (line->leftOffset < 0)
- line->leftOffset = 0;
- }
+ } else
+ // empty line (only line break);
+ line->alignment = Line::LEFT;
} else
// empty line
- line->leftOffset = 0;
+ line->alignment = Line::LEFT;
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
+}
+
+void Textblock::calcTextOffset (int lineIndex, int totalWidth)
+{
+ Line *line = lines->getRef (lineIndex);
+ int lineWidth = line->firstWord <= line->lastWord ?
+ words->getRef(line->lastWord)->totalWidth : 0;
+
+ switch (line->alignment) {
+ case Line::LEFT:
+ line->textOffset = line->leftOffset;
+ break;
+
+ case Line::RIGHT:
+ line->textOffset = totalWidth - line->rightOffset - lineWidth;
+ break;
+
+ case Line::CENTER:
+ line->textOffset =
+ (line->leftOffset + totalWidth - line->rightOffset - lineWidth) / 2;
+ break;
+
+ default:
+ misc::assertNotReached ();
+ break;
+ }
+
+ // For large lines (images etc), which do not fit into the viewport:
+ if (line->textOffset < line->leftOffset)
+ line->textOffset = line->leftOffset;
}
/**
@@ -1741,8 +1740,7 @@ void Textblock::alignLine (int lineIndex)
*/
void Textblock::rewrap ()
{
- DBG_OBJ_MSG ("construct.line", 0, "<b>rewrap</b> ()");
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER0 ("construct.line", 0, "rewrap");
if (wrapRefLines == -1)
DBG_OBJ_MSG ("construct.line", 0, "does not have to be rewrapped");
@@ -1790,7 +1788,7 @@ void Textblock::rewrap ()
DBG_OBJ_SET_NUM ("wrapRefLines", wrapRefLines);
}
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
/**
@@ -1798,8 +1796,7 @@ void Textblock::rewrap ()
*/
void Textblock::fillParagraphs ()
{
- DBG_OBJ_MSG ("resize", 0, "<b>fillParagraphs</b>");
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER0 ("resize", 0, "fillParagraphs");
DBG_OBJ_MSGF ("resize", 1, "wrapRefParagraphs = %d", wrapRefParagraphs);
@@ -1850,13 +1847,12 @@ void Textblock::fillParagraphs ()
DBG_OBJ_SET_NUM ("wrapRefParagraphs", wrapRefParagraphs);
}
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
void Textblock::initNewLine ()
{
- DBG_OBJ_MSG ("construct.line", 0, "<b>initNewLine</b> ()");
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER0 ("construct.line", 0, "initNewLine");
// At the very beginning, in Textblock::Textblock, where this
// method is called, containingBlock is not yet defined.
@@ -1878,14 +1874,13 @@ void Textblock::initNewLine ()
DBG_OBJ_SET_NUM ("newLineAscent", newLineAscent);
DBG_OBJ_SET_NUM ("newLineDescent", newLineDescent);
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
void Textblock::calcBorders (int lastOofRef, int height)
{
- DBG_OBJ_MSGF ("construct.line", 0, "<b>calcBorders</b> (%d, %d)",
+ DBG_OBJ_ENTER ("construct.line", 0, "calcBorders", "%d, %d",
lastOofRef, height);
- DBG_OBJ_MSG_START ();
if (containingBlock && containingBlock->outOfFlowMgr) {
// Consider the example:
@@ -1953,13 +1948,12 @@ void Textblock::calcBorders (int lastOofRef, int height)
DBG_OBJ_MSG ("construct.line", 0, "<i>no CB of OOFM</i>");
}
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
void Textblock::showMissingLines ()
{
- DBG_OBJ_MSG ("construct.line", 0, "<b>showMissingLines</b> ()");
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER0 ("construct.line", 0, "showMissingLines");
// "Temporary word": when the last word is an OOF reference, it is
// not processed, and not part of any line. For this reason, we
@@ -2010,7 +2004,7 @@ void Textblock::showMissingLines ()
addLine (firstWordNotInLine, words->size () - 1, -1, true);
*/
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
@@ -2045,9 +2039,8 @@ int Textblock::getLineShrinkability(int lastWordIndex)
int Textblock::getLineStretchability(int lastWordIndex)
{
- DBG_OBJ_MSGF ("construct.word.accum", 0,
- "<b>getLineStretchability</b> (%d)", lastWordIndex);
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("construct.word.accum", 0, "getLineStretchability", "%d",
+ lastWordIndex);
DBG_MSG_WORD ("construct.word.accum", 1, "<i>last word:</i> ",
lastWordIndex, "");
@@ -2066,7 +2059,7 @@ int Textblock::getLineStretchability(int lastWordIndex)
lastWord->maxDescent, str);
}
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
return str;
// Alternative: return 0;
diff --git a/dw/types.hh b/dw/types.hh
index e910d296..36d6caa1 100644
--- a/dw/types.hh
+++ b/dw/types.hh
@@ -180,6 +180,8 @@ struct Extremes
{
int minWidth;
int maxWidth;
+ int minWidthIntrinsic;
+ int maxWidthIntrinsic;
};
struct Content
diff --git a/dw/ui.cc b/dw/ui.cc
index 8fb34c96..d58164c9 100644
--- a/dw/ui.cc
+++ b/dw/ui.cc
@@ -56,6 +56,7 @@ void Embed::sizeRequestImpl (Requisition *requisition)
void Embed::getExtremesImpl (Extremes *extremes)
{
resource->getExtremes (extremes);
+ correctExtremes (extremes);
}
void Embed::sizeAllocateImpl (Allocation *allocation)
@@ -63,6 +64,35 @@ void Embed::sizeAllocateImpl (Allocation *allocation)
resource->sizeAllocate (allocation);
}
+int Embed::getAvailWidthOfChild (Widget *child, bool forceValue)
+{
+ return resource->getAvailWidthOfChild (child, forceValue);
+}
+
+int Embed::getAvailHeightOfChild (Widget *child, bool forceValue)
+{
+ return resource->getAvailHeightOfChild (child, forceValue);
+}
+
+void Embed::correctRequisitionOfChild (Widget *child,
+ Requisition *requisition,
+ void (*splitHeightFun) (int, int*, int*))
+{
+ resource->correctRequisitionOfChild (child, requisition, splitHeightFun);
+}
+
+void Embed::correctExtremesOfChild (Widget *child, Extremes *extremes)
+{
+ resource->correctExtremesOfChild (child, extremes);
+}
+
+void Embed::containerSizeChangedForChildren ()
+{
+ DBG_OBJ_ENTER0 ("resize", 0, "containerSizeChangedForChildren");
+ resource->containerSizeChangedForChildren ();
+ DBG_OBJ_LEAVE ();
+}
+
void Embed::enterNotifyImpl (core::EventCrossing *event)
{
resource->emitEnter();
@@ -88,36 +118,6 @@ bool Embed::buttonPressImpl (core::EventButton *event)
return handled;
}
-void Embed::setWidth (int width)
-{
- DBG_OBJ_MSGF ("resize", 0, "<b>setWidth</b> (%d)", width);
- DBG_OBJ_MSG_START ();
-
- resource->setWidth (width);
-
- DBG_OBJ_MSG_END ();
-}
-
-void Embed::setAscent (int ascent)
-{
- DBG_OBJ_MSGF ("resize", 0, "<b>setAscent</b> (%d)", ascent);
- DBG_OBJ_MSG_START ();
-
- resource->setAscent (ascent);
-
- DBG_OBJ_MSG_END ();
-}
-
-void Embed::setDescent (int descent)
-{
- DBG_OBJ_MSGF ("resize", 0, "<b>setDescent</b> (%d)", descent);
- DBG_OBJ_MSG_START ();
-
- resource->setDescent (descent);
-
- DBG_OBJ_MSG_END ();
-}
-
void Embed::setDisplayed (bool displayed)
{
resource->setDisplayed (displayed);
@@ -206,8 +206,7 @@ void Resource::setEmbed (Embed *embed)
void Resource::getExtremes (Extremes *extremes)
{
- DBG_OBJ_MSG ("resize", 0, "<b>getExtremes</b>");
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER0 ("resize", 0, "getExtremes");
/* Simply return the requisition width */
Requisition requisition;
@@ -216,23 +215,45 @@ void Resource::getExtremes (Extremes *extremes)
DBG_OBJ_MSGF ("resize", 1, "result: %d / %d",
extremes->minWidth, extremes->maxWidth);
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
void Resource::sizeAllocate (Allocation *allocation)
{
}
-void Resource::setWidth (int width)
+int Resource::getAvailWidthOfChild (Widget *child, bool forceValue)
+{
+ // Only used when the resource contains other dillo widgets.
+ misc::assertNotReached ();
+ return 0;
+}
+
+int Resource::getAvailHeightOfChild (Widget *child, bool forceValue)
+{
+ // Only used when the resource contains other dillo widgets.
+ misc::assertNotReached ();
+ return 0;
+}
+
+void Resource::correctRequisitionOfChild (Widget *child,
+ Requisition *requisition,
+ void (*splitHeightFun) (int, int*,
+ int*))
{
+ // Only used when the resource contains other dillo widgets.
+ misc::assertNotReached ();
}
-void Resource::setAscent (int ascent)
+void Resource::correctExtremesOfChild (Widget *child, Extremes *extremes)
{
+ // Only used when the resource contains other dillo widgets.
+ misc::assertNotReached ();
}
-void Resource::setDescent (int descent)
+void Resource::containerSizeChangedForChildren ()
{
+ // No children by default.
}
void Resource::setDisplayed (bool displayed)
@@ -290,14 +311,10 @@ Iterator *LabelButtonResource::iterator (Content::Type mask, bool atEnd)
void ComplexButtonResource::LayoutReceiver::resizeQueued (bool extremesChanged)
{
- DBG_OBJ_MSGF_O ("resize", 0, resource,
- "LayoutReceiver::<b>resizeQueued</b> (%s)",
+ DBG_OBJ_ENTER ("resize", 0, "LayoutReceiver/resizeQueued", "%s",
extremesChanged ? "true" : "false");
- DBG_OBJ_MSG_START_O (resource);
-
resource->queueResize (extremesChanged);
-
- DBG_OBJ_MSG_END_O (resource);
+ DBG_OBJ_LEAVE ();
}
ComplexButtonResource::ComplexButtonResource ()
@@ -310,21 +327,24 @@ ComplexButtonResource::ComplexButtonResource ()
void ComplexButtonResource::init (Widget *widget)
{
- this->childWidget = widget;
+ childWidget = widget;
layout = new Layout (createPlatform ());
setLayout (layout);
DBG_OBJ_ASSOC_CHILD (layout);
layout->setWidget (widget);
layout->connect (&layoutReceiver);
+
+ if (getEmbed ())
+ childWidget->setQuasiParent (getEmbed ());
}
void ComplexButtonResource::setEmbed (Embed *embed)
{
ButtonResource::setEmbed (embed);
- if (childWidget->usesHints ())
- embed->setUsesHints ();
+ if (childWidget)
+ childWidget->setQuasiParent (getEmbed ());
}
ComplexButtonResource::~ComplexButtonResource ()
@@ -335,8 +355,7 @@ ComplexButtonResource::~ComplexButtonResource ()
void ComplexButtonResource::sizeRequest (Requisition *requisition)
{
- DBG_OBJ_MSG ("resize", 0, "<b>sizeRequest</b>");
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER0 ("resize", 0, "sizeRequest");
Requisition widgetRequisition;
childWidget->sizeRequest (&widgetRequisition);
@@ -346,13 +365,12 @@ void ComplexButtonResource::sizeRequest (Requisition *requisition)
DBG_OBJ_MSGF ("resize", 1, "result: %d * (%d + %d)",
requisition->width, requisition->ascent, requisition->descent);
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
void ComplexButtonResource::getExtremes (Extremes *extremes)
{
- DBG_OBJ_MSG ("resize", 0, "<b>getExtremes</b>");
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER0 ("resize", 0, "getExtremes");
Extremes widgetExtremes;
childWidget->getExtremes (&widgetExtremes);
@@ -361,41 +379,82 @@ void ComplexButtonResource::getExtremes (Extremes *extremes)
DBG_OBJ_MSGF ("resize", 1, "result: %d / %d",
extremes->minWidth, extremes->maxWidth);
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
void ComplexButtonResource::sizeAllocate (Allocation *allocation)
{
}
-void ComplexButtonResource::setWidth (int width)
+int ComplexButtonResource::getAvailWidthOfChild (Widget *child, bool forceValue)
{
- DBG_OBJ_MSGF ("resize", 0, "<b>setWidth</b> (%d)", width);
- DBG_OBJ_MSG_START ();
-
- childWidget->setWidth (width - 2 * reliefXThickness ());
+ int embedWidth = getEmbed()->getAvailWidth (forceValue);
+ if (embedWidth == -1)
+ return -1;
+ else
+ return misc::max (embedWidth - 2 * reliefXThickness (), 0);
+}
- DBG_OBJ_MSG_END ();
+int ComplexButtonResource::getAvailHeightOfChild (Widget *child,
+ bool forceValue)
+{
+ int embedHeight = getEmbed()->getAvailHeight (forceValue);
+ if (embedHeight == -1)
+ return -1;
+ else
+ return misc::max (embedHeight - 2 * reliefYThickness (), 0);
}
-void ComplexButtonResource::setAscent (int ascent)
+void ComplexButtonResource::correctRequisitionOfChild (Widget *child,
+ Requisition *requisition,
+ void (*splitHeightFun)
+ (int, int*, int*))
{
- DBG_OBJ_MSGF ("resize", 0, "<b>setAscent</b> (%d)", ascent);
- DBG_OBJ_MSG_START ();
+ // Similar to Widget::correctRequisitionOfChild, but for percentage
+ // the relief has to be considered.
+
+ if (style::isPerLength (child->getStyle()->width)) {
+ int availWidth = getEmbed()->getAvailHeight (false);
+ if (availWidth != -1) {
+ int baseWidth = misc::max (availWidth
+ - getEmbed()->boxDiffWidth ()
+ - 2 * reliefXThickness (),
+ 0);
+ requisition->width =
+ child->applyPerWidth (baseWidth, child->getStyle()->width);
+ }
+ } else
+ getEmbed()->correctReqWidthOfChildNoRec (child, requisition);
- childWidget->setAscent (ascent - reliefYThickness ());
+ // TODO Percentage heights are ignored again.
+ getEmbed()->correctReqHeightOfChildNoRec (child, requisition,
+ splitHeightFun);
- DBG_OBJ_MSG_END ();
}
-void ComplexButtonResource::setDescent (int descent)
+void ComplexButtonResource::correctExtremesOfChild (Widget *child,
+ Extremes *extremes)
{
- DBG_OBJ_MSGF ("resize", 0, "<b>setDescent</b> (%d)", descent);
- DBG_OBJ_MSG_START ();
-
- childWidget->setDescent (descent - reliefYThickness ());
+ // Similar to Widget::correctExtremesOfChild, but for percentage
+ // the relief has to be considered.
+
+ if (style::isPerLength (child->getStyle()->width)) {
+ int availWidth = getEmbed()->getAvailHeight (false);
+ if (availWidth != -1) {
+ int baseWidth = misc::max (availWidth
+ - getEmbed()->boxDiffWidth ()
+ - 2 * reliefXThickness (),
+ 0);
+ extremes->minWidth = extremes->maxWidth =
+ child->applyPerWidth (baseWidth, child->getStyle()->width);
+ }
+ } else
+ getEmbed()->correctExtremesOfChildNoRec (child, extremes);
+}
- DBG_OBJ_MSG_END ();
+void ComplexButtonResource::containerSizeChangedForChildren ()
+{
+ layout->containerSizeChanged ();
}
Iterator *ComplexButtonResource::iterator (Content::Type mask, bool atEnd)
diff --git a/dw/ui.hh b/dw/ui.hh
index cab67e17..6703ccca 100644
--- a/dw/ui.hh
+++ b/dw/ui.hh
@@ -231,6 +231,16 @@ protected:
void sizeRequestImpl (Requisition *requisition);
void getExtremesImpl (Extremes *extremes);
void sizeAllocateImpl (Allocation *allocation);
+
+ int getAvailWidthOfChild (Widget *child, bool forceValue);
+ int getAvailHeightOfChild (Widget *child, bool forceValue);
+ void correctRequisitionOfChild (Widget *child,
+ Requisition *requisition,
+ void (*splitHeightFun) (int, int*, int*));
+ void correctExtremesOfChild (Widget *child, Extremes *extremes);
+
+ void containerSizeChangedForChildren ();
+
void enterNotifyImpl (core::EventCrossing *event);
void leaveNotifyImpl (core::EventCrossing *event);
bool buttonPressImpl (core::EventButton *event);
@@ -241,18 +251,26 @@ public:
Embed(Resource *resource);
~Embed();
- void setWidth (int width);
- void setAscent (int ascent);
- void setDescent (int descent);
void setDisplayed (bool displayed);
void setEnabled (bool enabled);
void draw (View *view, Rectangle *area);
Iterator *iterator (Content::Type mask, bool atEnd);
void setStyle (style::Style *style);
- inline void setUsesHints () { setFlags (USES_HINTS); }
-
inline Resource *getResource () { return resource; }
+
+ inline void correctReqWidthOfChildNoRec (Widget *child,
+ Requisition *requisition)
+ { Widget::correctReqWidthOfChild (child, requisition); }
+
+ inline void correctReqHeightOfChildNoRec (Widget *child,
+ Requisition *requisition,
+ void (*splitHeightFun) (int, int*,
+ int*))
+ { Widget::correctReqHeightOfChild (child, requisition, splitHeightFun); }
+
+ virtual void correctExtremesOfChildNoRec (Widget *child, Extremes *extremes)
+ { Widget::correctExtremesOfChild (child, extremes); }
};
/**
@@ -337,9 +355,16 @@ public:
virtual void sizeRequest (Requisition *requisition) = 0;
virtual void getExtremes (Extremes *extremes);
virtual void sizeAllocate (Allocation *allocation);
- virtual void setWidth (int width);
- virtual void setAscent (int ascent);
- virtual void setDescent (int descent);
+
+ virtual int getAvailWidthOfChild (Widget *child, bool forceValue);
+ virtual int getAvailHeightOfChild (Widget *child, bool forceValue);
+ virtual void correctRequisitionOfChild (Widget *child,
+ Requisition *requisition,
+ void (*splitHeightFun) (int, int*,
+ int*));
+ virtual void correctExtremesOfChild (Widget *child, Extremes *extremes);
+ virtual void containerSizeChangedForChildren ();
+
virtual void setDisplayed (bool displayed);
virtual void draw (View *view, Rectangle *area);
virtual Iterator *iterator (Content::Type mask, bool atEnd) = 0;
@@ -407,9 +432,15 @@ public:
void sizeRequest (Requisition *requisition);
void getExtremes (Extremes *extremes);
void sizeAllocate (Allocation *allocation);
- void setWidth (int width);
- void setAscent (int ascent);
- void setDescent (int descent);
+
+ int getAvailWidthOfChild (Widget *child, bool forceValue);
+ int getAvailHeightOfChild (Widget *child, bool forceValue);
+ void correctRequisitionOfChild (Widget *child,
+ Requisition *requisition,
+ void (*splitHeightFun) (int, int*, int*));
+ void correctExtremesOfChild (Widget *child, Extremes *extremes);
+ void containerSizeChangedForChildren ();
+
Iterator *iterator (Content::Type mask, bool atEnd);
int getClickX () {return click_x;};
int getClickY () {return click_y;};
diff --git a/dw/widget.cc b/dw/widget.cc
index a3d85d0a..628aa2b4 100644
--- a/dw/widget.cc
+++ b/dw/widget.cc
@@ -62,6 +62,7 @@ void Widget::WidgetImgRenderer::draw (int x, int y, int width, int height)
// ----------------------------------------------------------------------
+bool Widget::adjustMinWidth = false;
int Widget::CLASS_ID = -1;
Widget::Widget ()
@@ -69,8 +70,10 @@ Widget::Widget ()
DBG_OBJ_CREATE ("dw::core::Widget");
registerName ("dw::core::Widget", &CLASS_ID);
- flags = (Flags)(NEEDS_RESIZE | EXTREMES_CHANGED | HAS_CONTENTS);
- parent = generator = NULL;
+ flags = (Flags)(NEEDS_RESIZE | EXTREMES_CHANGED);
+ parent = quasiParent = generator = container = NULL;
+ DBG_OBJ_SET_PTR ("container", container);
+
layout = NULL;
allocation.x = -1;
@@ -79,6 +82,8 @@ Widget::Widget ()
allocation.ascent = 1;
allocation.descent = 0;
+ extraSpace.top = extraSpace.right = extraSpace.bottom = extraSpace.left = 0;
+
style = NULL;
bgColor = NULL;
buttonSensitive = true;
@@ -153,16 +158,38 @@ void Widget::setParent (Widget *parent)
//printf ("The %s %p becomes a child of the %s %p\n",
// getClassName(), this, parent->getClassName(), parent);
+ // Determine the container. Currently rather simple; will become
+ // more complicated when absolute and fixed positions are
+ // supported.
+ container = NULL;
+ for (Widget *widget = getParent (); widget != NULL && container == NULL;
+ widget = widget->getParent())
+ if (widget->isPossibleContainer ())
+ container = widget;
+ // If there is no possible container widget, there is
+ // (surprisingly!) also no container (i. e. the viewport is
+ // used). Does not occur in dillo, where the toplevel widget is a
+ // Textblock.
+ DBG_OBJ_SET_PTR ("container", container);
+
notifySetParent();
}
+void Widget::setQuasiParent (Widget *quasiParent)
+{
+ this->quasiParent = quasiParent;
+
+ // More to do? Compare with setParent().
+
+ DBG_OBJ_SET_PTR ("quasiParent", quasiParent);
+}
+
void Widget::queueDrawArea (int x, int y, int width, int height)
{
/** \todo Maybe only the intersection? */
- DBG_OBJ_MSGF ("draw", 0, "<b>queueDrawArea</b> (%d, %d, %d, %d)",
- x, y, width, height);
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("draw", 0, "queueDrawArea", "%d, %d, %d, %d",
+ x, y, width, height);
_MSG("Widget::queueDrawArea alloc(%d %d %d %d) wid(%d %d %d %d)\n",
allocation.x, allocation.y,
@@ -171,17 +198,21 @@ void Widget::queueDrawArea (int x, int y, int width, int height)
if (layout)
layout->queueDraw (x + allocation.x, y + allocation.y, width, height);
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
/**
* \brief This method should be called, when a widget changes its size.
+ *
+ * A "fast" queueResize will ignore the anchestors, and furthermore
+ * not trigger the idle function. Used only within
+ * viewportSizeChanged, and not available outside Layout and Widget.
*/
-void Widget::queueResize (int ref, bool extremesChanged)
+void Widget::queueResize (int ref, bool extremesChanged, bool fast)
{
- DBG_OBJ_MSGF ("resize", 0, "<b>queueResize</b> (%d, %s)",
- ref, extremesChanged ? "true" : "false");
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("resize", 0, "queueResize", "%d, %s, %s",
+ ref, extremesChanged ? "true" : "false",
+ fast ? "true" : "false");
// queueResize() can be called recursively; calls are queued, so
// that actualQueueResize() is clean.
@@ -189,38 +220,60 @@ void Widget::queueResize (int ref, bool extremesChanged)
if (queueResizeEntered ()) {
DBG_OBJ_MSG ("resize", 1, "put into queue");
layout->queueQueueResizeList->put (new Layout::QueueResizeItem
- (this, ref, extremesChanged));
+ (this, ref, extremesChanged, fast));
} else {
- actualQueueResize (ref, extremesChanged);
-
+ actualQueueResize (ref, extremesChanged, fast);
+
+ DBG_IF_RTFL {
+ if (layout == NULL)
+ DBG_OBJ_MSG ("resize", 1, "layout is not set");
+ else if (layout->queueQueueResizeList->size () == 0)
+ DBG_OBJ_MSG ("resize", 1, "queue item list is empty");
+ }
+
while (layout != NULL && layout->queueQueueResizeList->size () > 0) {
+ DBG_IF_RTFL {
+ DBG_OBJ_MSGF ("resize", 1, "queue item list has %d elements:",
+ layout->queueQueueResizeList->size ());
+ DBG_OBJ_MSG_START ();
+ for (int i = 0; i < layout->queueQueueResizeList->size (); i++) {
+ DBG_OBJ_MSGF
+ ("resize", 1,
+ "#%d: widget = %p, ref = %d, extremesChanged = %s, "
+ "fast = %s",
+ i, layout->queueQueueResizeList->get(i)->widget,
+ layout->queueQueueResizeList->get(i)->ref,
+ layout->queueQueueResizeList->get(i)->extremesChanged ?
+ "true" : "false",
+ layout->queueQueueResizeList->get(i)->fast ?
+ "true" : "false");
+ }
+ DBG_OBJ_MSG_END ();
+ DBG_OBJ_MSG ("resize", 1, "taking #0 out of list");
+ }
+
Layout::QueueResizeItem *item = layout->queueQueueResizeList->get (0);
- DBG_OBJ_MSGF ("resize", 1, "taken out of queue queue (size = %d)",
- layout->queueQueueResizeList->size ());
- item->widget->actualQueueResize (item->ref, item->extremesChanged);
+ item->widget->actualQueueResize (item->ref, item->extremesChanged,
+ item->fast);
layout->queueQueueResizeList->remove (0); // hopefully not too large
}
}
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
-void Widget::actualQueueResize (int ref, bool extremesChanged)
+void Widget::actualQueueResize (int ref, bool extremesChanged, bool fast)
{
assert (!queueResizeEntered ());
- DBG_OBJ_MSGF ("resize", 0, "<b>actualQueueResize</b> (%d, %s)",
- ref, extremesChanged ? "true" : "false");
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("resize", 0, "actualQueueResize", "%d, %s, %s",
+ ref, extremesChanged ? "true" : "false",
+ fast ? "true" : "false");
enterQueueResize ();
Widget *widget2, *child;
- //printf("The %stop-level %s %p with parentRef = %d has changed its size. "
- // "Layout = %p.\n",
- // parent ? "non-" : "", getClassName(), this, parentRef, layout);
-
Flags resizeFlag, extremesFlag;
if (layout) {
@@ -243,36 +296,173 @@ void Widget::actualQueueResize (int ref, bool extremesChanged)
setFlags (extremesFlag);
markExtremesChange (ref);
}
-
- for (widget2 = parent, child = this; widget2;
- child = widget2, widget2 = widget2->parent) {
- //printf (" Setting %s and ALLOCATE_QUEUED for the "
- // "%stop-level %s %p with parentRef = %d\n",
- // resizeFlag == RESIZE_QUEUED ? "RESIZE_QUEUED" : "NEEDS_RESIZE",
- // widget2->parent ? "non-" : "", widget2->getClassName(), widget2,
- // widget2->parentRef);
-
- if (layout && !widget2->resizeQueued ())
- layout->queueResizeList->put (widget2);
-
- widget2->setFlags (resizeFlag);
- widget2->markSizeChange (child->parentRef);
- widget2->setFlags (ALLOCATE_QUEUED);
-
- if (extremesChanged) {
- widget2->setFlags (extremesFlag);
- widget2->markExtremesChange (child->parentRef);
+
+ if (fast) {
+ if (parent) {
+ // In this case, queueResize is called from top (may be a
+ // random entry point) to bottom, so markSizeChange and
+ // markExtremesChange have to be called explicitly for the
+ // parent. The tests (needsResize etc.) are uses to check
+ // whether queueResize has been called for the parent, or
+ // whether this widget is the enty point.
+ if (parent->needsResize () || parent->resizeQueued ())
+ parent->markSizeChange (parentRef);
+ if (parent->extremesChanged () || parent->extremesQueued ())
+ parent->markExtremesChange (parentRef);
+ }
+ } else {
+ for (widget2 = parent, child = this; widget2;
+ child = widget2, widget2 = widget2->parent) {
+ if (layout && !widget2->resizeQueued ())
+ layout->queueResizeList->put (widget2);
+
+ DBG_OBJ_MSGF ("resize", 2, "setting %s and ALLOCATE_QUEUED for %p",
+ resizeFlag == RESIZE_QUEUED ?
+ "RESIZE_QUEUED" : "NEEDS_RESIZE",
+ widget2);
+
+ widget2->setFlags (resizeFlag);
+ widget2->markSizeChange (child->parentRef);
+ widget2->setFlags (ALLOCATE_QUEUED);
+
+ if (extremesChanged) {
+ widget2->setFlags (extremesFlag);
+ widget2->markExtremesChange (child->parentRef);
+ }
}
- }
- if (layout)
- layout->queueResize (extremesChanged);
+ if (layout)
+ layout->queueResize (extremesChanged);
+ }
leaveQueueResize ();
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
+}
+
+void Widget::containerSizeChanged ()
+{
+ DBG_OBJ_ENTER0 ("resize", 0, "containerSizeChanged");
+
+ // If there is a container widget (not the viewport), which has not
+ // changed its size (which can be determined by the respective
+ // flags: this method is called recursively), this widget will
+ // neither change its size. Also, the recursive iteration can be
+ // stopped, since the children of this widget will
+ if (container == NULL ||
+ container->needsResize () || container->resizeQueued () ||
+ container->extremesChanged () || container->extremesQueued ()) {
+ // Viewport (container == NULL) or container widget has changed
+ // its size.
+ if (affectedByContainerSizeChange ())
+ queueResizeFast (0, true);
+
+ // Even if *this* widget is not affected, children may be, so
+ // iterate over children.
+ containerSizeChangedForChildren ();
+ }
+
+ DBG_OBJ_LEAVE ();
+}
+
+bool Widget::affectedByContainerSizeChange ()
+{
+ DBG_OBJ_ENTER0 ("resize", 0, "affectedByContainerSizeChange");
+
+ bool ret;
+
+ // This standard implementation is suitable for all widgets which
+ // call correctRequisition() and correctExtremes(), even in the way
+ // how Textblock and Image do (see comments there). Has to be kept
+ // in sync.
+
+ if (container == NULL) {
+ if (style::isAbsLength (getStyle()->width) &&
+ style::isAbsLength (getStyle()->height))
+ // Both absolute, i. e. fixed: no dependency.
+ ret = false;
+ else if (style::isPerLength (getStyle()->width) ||
+ style::isPerLength (getStyle()->height)) {
+ // Any percentage: certainly dependenant.
+ ret = true;
+ } else
+ // One or both is "auto": depends ...
+ ret =
+ (getStyle()->width == style::LENGTH_AUTO ?
+ usesAvailWidth () : false) ||
+ (getStyle()->height == style::LENGTH_AUTO ?
+ usesAvailHeight () : false);
+ } else
+ ret = container->affectsSizeChangeContainerChild (this);
+
+ DBG_OBJ_MSGF ("resize", 1, "=> %s", ret ? "true" : "false");
+ DBG_OBJ_LEAVE ();
+ return ret;
+}
+
+bool Widget::affectsSizeChangeContainerChild (Widget *child)
+{
+ DBG_OBJ_ENTER ("resize", 0, "affectsSizeChangeContainerChild", "%p", child);
+
+ bool ret;
+
+ // From the point of view of the container. This standard
+ // implementation should be suitable for most (if not all)
+ // containers.
+
+ if (style::isAbsLength (child->getStyle()->width) &&
+ style::isAbsLength (child->getStyle()->height))
+ // Both absolute, i. e. fixed: no dependency.
+ ret = false;
+ else if (style::isPerLength (child->getStyle()->width) ||
+ style::isPerLength (child->getStyle()->height)) {
+ // Any percentage: certainly dependenant.
+ ret = true;
+ } else
+ // One or both is "auto": depends ...
+ ret =
+ (child->getStyle()->width == style::LENGTH_AUTO ?
+ child->usesAvailWidth () : false) ||
+ (child->getStyle()->height == style::LENGTH_AUTO ?
+ child->usesAvailHeight () : false);
+
+ DBG_OBJ_MSGF ("resize", 1, "=> %s", ret ? "true" : "false");
+ DBG_OBJ_LEAVE ();
+ return ret;
+}
+
+void Widget::containerSizeChangedForChildren ()
+{
+ DBG_OBJ_ENTER0 ("resize", 0, "containerSizeChangedForChildren");
+
+ // Working, but inefficient standard implementation.
+ Iterator *it = iterator ((Content::Type)(Content::WIDGET_IN_FLOW |
+ Content::WIDGET_OOF_CONT),
+ false);
+ while (it->next ())
+ it->getContent()->widget->containerSizeChanged ();
+ it->unref ();
+
+ DBG_OBJ_LEAVE ();
+}
+
+/**
+ * \brief Must be implemengted by a method returning true, when
+ * getAvailWidth() is called.
+ */
+bool Widget::usesAvailWidth ()
+{
+ return false;
}
+/**
+ * \brief Must be implemengted by a method returning true, when
+ * getAvailHeight() is called.
+ */
+bool Widget::usesAvailHeight ()
+{
+ return false;
+}
/**
* \brief This method is a wrapper for Widget::sizeRequestImpl(); it calls
@@ -282,8 +472,7 @@ void Widget::sizeRequest (Requisition *requisition)
{
assert (!queueResizeEntered ());
- DBG_OBJ_MSG ("resize", 0, "<b>sizeRequest</b>");
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER0 ("resize", 0, "sizeRequest");
enterSizeRequest ();
@@ -319,7 +508,240 @@ void Widget::sizeRequest (Requisition *requisition)
leaveSizeRequest ();
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
+}
+
+/**
+ * \brief Used to evaluate Widget::adjustMinWidth.
+ *
+ * If extremes == NULL, getExtremes is called.
+ */
+int Widget::getMinWidth (Extremes *extremes)
+{
+ DBG_OBJ_ENTER0 ("resize", 0, "getMinWidth");
+ int minWidth;
+
+ if (adjustMinWidth) {
+ Extremes extremes2;
+ if (extremes == NULL) {
+ getExtremes (&extremes2);
+ extremes = &extremes2;
+ }
+
+ minWidth = extremes->minWidthIntrinsic;
+ } else
+ minWidth = 0;
+
+ DBG_OBJ_MSGF ("resize", 1, "=> %d", minWidth);
+ DBG_OBJ_LEAVE ();
+
+ return minWidth;
+}
+
+/**
+ * Return available width including margin/border/padding
+ * (extraSpace?), not only the content width.
+ */
+int Widget::getAvailWidth (bool forceValue)
+{
+ DBG_OBJ_ENTER ("resize", 0, "getAvailWidth", "%s",
+ forceValue ? "true" : "false");
+
+ int width;
+
+ if (parent == NULL && quasiParent == NULL) {
+ DBG_OBJ_MSG ("resize", 1, "no parent, regarding viewport");
+ DBG_OBJ_MSG_START ();
+
+ // TODO Consider nested layouts (e. g. <button>).
+ if (style::isAbsLength (getStyle()->width)) {
+ DBG_OBJ_MSGF ("resize", 1, "absolute width: %dpx",
+ style::absLengthVal (getStyle()->width));
+ width = style::absLengthVal (getStyle()->width) + boxDiffWidth ();
+ } else {
+ int viewportWidth =
+ layout->viewportWidth - (layout->canvasHeightGreater ?
+ layout->vScrollbarThickness : 0);
+ if (style::isPerLength (getStyle()->width)) {
+ DBG_OBJ_MSGF ("resize", 1, "percentage width: %g%%",
+ 100 * style::perLengthVal_useThisOnlyForDebugging
+ (getStyle()->width));
+ width = applyPerWidth (viewportWidth, getStyle()->width);
+ } else {
+ DBG_OBJ_MSG ("resize", 1, "no specification");
+ width = viewportWidth;
+ }
+ }
+ DBG_OBJ_MSG_END ();
+ } else if (parent) {
+ DBG_OBJ_MSG ("resize", 1, "delegated to parent");
+ DBG_OBJ_MSG_START ();
+ width = parent->getAvailWidthOfChild (this, forceValue);
+ DBG_OBJ_MSG_END ();
+ } else /* if (quasiParent) */ {
+ DBG_OBJ_MSG ("resize", 1, "delegated to quasiParent");
+ DBG_OBJ_MSG_START ();
+ width = quasiParent->getAvailWidthOfChild (this, forceValue);
+ DBG_OBJ_MSG_END ();
+ }
+
+ if (width != -1)
+ width = misc::max (width, getMinWidth (NULL));
+
+ DBG_OBJ_MSGF ("resize", 1, "=> %d", width);
+ DBG_OBJ_LEAVE ();
+
+ return width;
+}
+
+/**
+ * Return available height including margin/border/padding
+ * (extraSpace?), not only the content height.
+ */
+int Widget::getAvailHeight (bool forceValue)
+{
+ // TODO Correct by ... not extremes, but ...? (Height extremes?)
+
+ DBG_OBJ_ENTER ("resize", 0, "getAvailHeight", "%s",
+ forceValue ? "true" : "false");
+
+ int height;
+
+ if (parent == NULL && quasiParent == NULL) {
+ DBG_OBJ_MSG ("resize", 1, "no parent, regarding viewport");
+ DBG_OBJ_MSG_START ();
+
+ // TODO Consider nested layouts (e. g. <button>).
+ if (style::isAbsLength (getStyle()->height)) {
+ DBG_OBJ_MSGF ("resize", 1, "absolute height: %dpx",
+ style::absLengthVal (getStyle()->height));
+ height = style::absLengthVal (getStyle()->height) + boxDiffHeight ();
+ } else if (style::isPerLength (getStyle()->height)) {
+ DBG_OBJ_MSGF ("resize", 1, "percentage height: %g%%",
+ 100 * style::perLengthVal_useThisOnlyForDebugging
+ (getStyle()->height));
+ // Notice that here -- unlike getAvailWidth() --
+ // layout->hScrollbarThickness is not considered here;
+ // something like canvasWidthGreater (analogue to
+ // canvasHeightGreater) would be complicated and lead to
+ // possibly contradictory self-references.
+ height = applyPerHeight (layout->viewportHeight, getStyle()->height);
+ } else {
+ DBG_OBJ_MSG ("resize", 1, "no specification");
+ height = layout->viewportHeight;
+ }
+
+ DBG_OBJ_MSG_END ();
+ } else if (parent) {
+ DBG_OBJ_MSG ("resize", 1, "delegated to parent");
+ DBG_OBJ_MSG_START ();
+ height = quasiParent->getAvailHeightOfChild (this, forceValue);
+ DBG_OBJ_MSG_END ();
+ } else /* if (quasiParent) */ {
+ DBG_OBJ_MSG ("resize", 1, "delegated to quasiParent");
+ DBG_OBJ_MSG_START ();
+ height = quasiParent->getAvailHeightOfChild (this, forceValue);
+ DBG_OBJ_MSG_END ();
+ }
+
+ DBG_OBJ_MSGF ("resize", 1, "=> %d", height);
+ DBG_OBJ_LEAVE ();
+
+ return height;
+}
+
+void Widget::correctRequisition (Requisition *requisition,
+ void (*splitHeightFun) (int, int *, int *))
+{
+ // TODO Correct height by ... not extremes, but ...? (Height extremes?)
+
+ DBG_OBJ_ENTER ("resize", 0, "correctRequisition", "%d * (%d + %d), ...",
+ requisition->width, requisition->ascent,
+ requisition->descent);
+
+ if (container == NULL && quasiParent == NULL) {
+ if (style::isAbsLength (getStyle()->width)) {
+ DBG_OBJ_MSGF ("resize", 1, "absolute width: %dpx",
+ style::absLengthVal (getStyle()->width));
+ requisition->width =
+ misc::max (style::absLengthVal (getStyle()->width)
+ + boxDiffWidth (),
+ getMinWidth (NULL));
+ } else if (style::isPerLength (getStyle()->width)) {
+ DBG_OBJ_MSGF ("resize", 1, "percentage width: %g%%",
+ 100 * style::perLengthVal_useThisOnlyForDebugging
+ (getStyle()->width));
+ int viewportWidth =
+ layout->viewportWidth - (layout->canvasHeightGreater ?
+ layout->vScrollbarThickness : 0);
+ requisition->width =
+ misc::max (applyPerWidth (viewportWidth, getStyle()->width),
+ getMinWidth (NULL));
+ }
+
+ // TODO Perhaps split first, then add box ascent and descent.
+ if (style::isAbsLength (getStyle()->height)) {
+ DBG_OBJ_MSGF ("resize", 1, "absolute height: %dpx",
+ style::absLengthVal (getStyle()->height));
+ splitHeightFun (style::absLengthVal (getStyle()->height)
+ + boxDiffHeight (),
+ &requisition->ascent, &requisition->descent);
+ } else if (style::isPerLength (getStyle()->height)) {
+ DBG_OBJ_MSGF ("resize", 1, "percentage height: %g%%",
+ 100 * style::perLengthVal_useThisOnlyForDebugging
+ (getStyle()->height));
+#if 0
+ // TODO Percentage heights are somewhat more complicated. Has
+ // to be clarified.
+
+ // For layout->viewportHeight, see comment in getAvailHeight().
+ splitHeightFun (applyPerHeight (layout->viewportHeight,
+ getStyle()->height),
+ &requisition->ascent, &requisition->descent);
+#endif
+ }
+ } else if (container)
+ container->correctRequisitionOfChild (this, requisition, splitHeightFun);
+ else // if (quasiParent)
+ // Here, quasiParent plays the same role as the container.
+ quasiParent->correctRequisitionOfChild (this, requisition,
+ splitHeightFun);
+
+ DBG_OBJ_MSGF ("resize", 1, "=> %d * (%d + %d)",
+ requisition->width, requisition->ascent,
+ requisition->descent);
+ DBG_OBJ_LEAVE ();
+}
+
+void Widget::correctExtremes (Extremes *extremes)
+{
+ DBG_OBJ_ENTER ("resize", 0, "correctExtremes", "%d (%d) / %d (%d)",
+ extremes->minWidth, extremes->minWidthIntrinsic,
+ extremes->maxWidth, extremes->maxWidthIntrinsic);
+
+ if (container == NULL && quasiParent == NULL) {
+ if (style::isAbsLength (getStyle()->width))
+ extremes->minWidth = extremes->maxWidth =
+ misc::max (style::absLengthVal (getStyle()->width)
+ + boxDiffWidth (),
+ getMinWidth (extremes));
+ else if (style::isPerLength (getStyle()->width)) {
+ int viewportWidth =
+ layout->viewportWidth - (layout->canvasHeightGreater ?
+ layout->vScrollbarThickness : 0);
+ extremes->minWidth = extremes->maxWidth =
+ misc::max (applyPerWidth (viewportWidth, getStyle()->width),
+ getMinWidth (extremes));
+ }
+ } else if (container)
+ container->correctExtremesOfChild (this, extremes);
+ else // if (quasiParent)
+ // Here, quasiParent plays the same role as the container.
+ quasiParent->correctExtremesOfChild (this, extremes);
+
+ DBG_OBJ_MSGF ("resize", 1, "=> %d / %d",
+ extremes->minWidth, extremes->maxWidth);
+ DBG_OBJ_LEAVE ();
}
/**
@@ -329,7 +751,7 @@ void Widget::getExtremes (Extremes *extremes)
{
assert (!queueResizeEntered ());
- DBG_OBJ_MSG ("resize", 0, "<b>getExtremes</b>");
+ DBG_OBJ_ENTER0 ("resize", 0, "getExtremes");
DBG_OBJ_MSG_START ();
enterGetExtremes ();
@@ -344,18 +766,32 @@ void Widget::getExtremes (Extremes *extremes)
}
if (extremesChanged ()) {
+ // For backward compatibility (part 1/2):
+ extremes->minWidthIntrinsic = extremes->maxWidthIntrinsic = -1;
+
getExtremesImpl (extremes);
+
+ // For backward compatibility (part 2/2):
+ if (extremes->minWidthIntrinsic == -1)
+ extremes->minWidthIntrinsic = extremes->minWidth;
+ if (extremes->maxWidthIntrinsic == -1)
+ extremes->maxWidthIntrinsic = extremes->maxWidth;
+
this->extremes = *extremes;
unsetFlags (EXTREMES_CHANGED);
DBG_OBJ_SET_NUM ("extremes.minWidth", extremes->minWidth);
+ DBG_OBJ_SET_NUM ("extremes.minWidthIntrinsic",
+ extremes->minWidthIntrinsic);
DBG_OBJ_SET_NUM ("extremes.maxWidth", extremes->maxWidth);
+ DBG_OBJ_SET_NUM ("extremes.maxWidthIntrinsic",
+ extremes->maxWidthIntrinsic);
} else
*extremes = this->extremes;
leaveGetExtremes ();
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
/**
@@ -369,10 +805,9 @@ void Widget::sizeAllocate (Allocation *allocation)
assert (!getExtremesEntered ());
assert (resizeIdleEntered ());
- DBG_OBJ_MSGF ("resize", 0, "<b>sizeAllocate</b> (%d, %d; %d * (%d + %d))",
- allocation->x, allocation->y, allocation->width,
- allocation->ascent, allocation->descent);
- DBG_OBJ_MSG_START ();
+ DBG_OBJ_ENTER ("resize", 0, "sizeAllocate", "%d, %d; %d * (%d + %d)",
+ allocation->x, allocation->y, allocation->width,
+ allocation->ascent, allocation->descent);
DBG_OBJ_MSGF ("resize", 1,
"old allocation (%d, %d; %d * (%d + %d)); needsAllocate: %s",
@@ -435,7 +870,7 @@ void Widget::sizeAllocate (Allocation *allocation)
leaveSizeAllocate ();
- DBG_OBJ_MSG_END ();
+ DBG_OBJ_LEAVE ();
}
bool Widget::buttonPress (EventButton *event)
@@ -507,6 +942,28 @@ void Widget::setStyle (style::Style *style)
queueResize (0, true);
else
queueDraw ();
+
+ // These should better be attributed to the style itself, and a
+ // script processing RTFL messages could transfer it to something
+ // equivalent:
+
+ DBG_OBJ_SET_NUM ("style.margin.top", style->margin.top);
+ DBG_OBJ_SET_NUM ("style.margin.bottom", style->margin.bottom);
+ DBG_OBJ_SET_NUM ("style.margin.left", style->margin.left);
+ DBG_OBJ_SET_NUM ("style.margin.right", style->margin.right);
+
+ DBG_OBJ_SET_NUM ("style.border-width.top", style->borderWidth.top);
+ DBG_OBJ_SET_NUM ("style.border-width.bottom", style->borderWidth.bottom);
+ DBG_OBJ_SET_NUM ("style.border-width.left", style->borderWidth.left);
+ DBG_OBJ_SET_NUM ("style.border-width.right", style->borderWidth.right);
+
+ DBG_OBJ_SET_NUM ("style.padding.top", style->padding.top);
+ DBG_OBJ_SET_NUM ("style.padding.bottom", style->padding.bottom);
+ DBG_OBJ_SET_NUM ("style.padding.left", style->padding.left);
+ DBG_OBJ_SET_NUM ("style.padding.right", style->padding.right);
+
+ DBG_OBJ_SET_NUM ("style.border-spacing (h)", style->hBorderSpacing);
+ DBG_OBJ_SET_NUM ("style.border-spacing (v)", style->vBorderSpacing);
}
/**
@@ -781,14 +1238,6 @@ void Widget::getPaddingArea (int *xPad, int *yPad, int *widthPad,
- style->margin.bottom - style->borderWidth.bottom;
}
-void Widget::getExtremesImpl (Extremes *extremes)
-{
- /* Simply return the requisition width */
- Requisition requisition;
- sizeRequest (&requisition);
- extremes->minWidth = extremes->maxWidth = requisition.width;
-}
-
void Widget::sizeAllocateImpl (Allocation *allocation)
{
}
@@ -801,6 +1250,264 @@ void Widget::markExtremesChange (int ref)
{
}
+int Widget::applyPerWidth (int containerWidth, style::Length perWidth)
+{
+ return style::multiplyWithPerLength (containerWidth, perWidth)
+ + boxDiffWidth ();
+}
+
+int Widget::applyPerHeight (int containerHeight, style::Length perHeight)
+{
+ return style::multiplyWithPerLength (containerHeight, perHeight)
+ + boxDiffHeight ();
+}
+
+int Widget::getAvailWidthOfChild (Widget *child, bool forceValue)
+{
+ // This is a halfway suitable implementation for all
+ // containers. For simplification, this will be used during the
+ // development; then, a differentiation could be possible.
+
+ // TODO Correct by extremes?
+
+ DBG_OBJ_ENTER ("resize", 0, "getAvailWidthOfChild", "%p, %s",
+ child, forceValue ? "true" : "false");
+
+ int width;
+
+ if (child->getStyle()->width == style::LENGTH_AUTO) {
+ DBG_OBJ_MSG ("resize", 1, "no specification");
+ int availWidth = getAvailWidth (forceValue);
+ if (availWidth == -1)
+ width = -1;
+ else
+ width = misc::max (availWidth - boxDiffWidth (), 0);
+ } else {
+ // In most cases, the toplevel widget should be a container, so
+ // the container is non-NULL when the parent is non-NULL. Just
+ // in case ...:
+ Widget *effContainer =
+ child->container ? child->container : child->parent;
+
+ if (effContainer == this) {
+ if (style::isAbsLength (child->getStyle()->width)) {
+ DBG_OBJ_MSGF ("resize", 1, "absolute width: %dpx",
+ style::absLengthVal (child->getStyle()->width));
+ width = misc::max (style::absLengthVal (child->getStyle()->width)
+ + child->boxDiffWidth (), 0);
+ } else {
+ assert (style::isPerLength (child->getStyle()->width));
+ DBG_OBJ_MSGF ("resize", 1, "percentage width: %g%%",
+ 100 * style::perLengthVal_useThisOnlyForDebugging
+ (child->getStyle()->width));
+
+ int availWidth = getAvailWidth (forceValue);
+ if (availWidth == -1)
+ width = -1;
+ else
+ width =
+ misc::max (child->applyPerWidth (availWidth - boxDiffWidth (),
+ child->getStyle()->width),
+ 0);
+ }
+ } else {
+ DBG_OBJ_MSG ("resize", 1, "delegated to (effective) container");
+ DBG_OBJ_MSG_START ();
+ width = effContainer->getAvailWidthOfChild (child, forceValue);
+ DBG_OBJ_MSG_END ();
+ }
+ }
+
+ if (width != -1)
+ width = misc::max (width, child->getMinWidth (NULL));
+
+ DBG_OBJ_MSGF ("resize", 1, "=> %d", width);
+ DBG_OBJ_LEAVE ();
+
+ return width;
+}
+
+int Widget::getAvailHeightOfChild (Widget *child, bool forceValue)
+{
+ // Again, a suitable implementation for all widgets (perhaps).
+
+ // TODO Correct by extremes? (Height extemes?)
+
+ DBG_OBJ_ENTER ("resize", 0, "getAvailHeightOfChild", "%p, %s",
+ child, forceValue ? "true" : "false");
+
+ int height;
+
+ if (child->getStyle()->height == style::LENGTH_AUTO) {
+ DBG_OBJ_MSG ("resize", 1, "no specification");
+ int availHeight = getAvailHeight (forceValue);
+ if (availHeight == -1)
+ height = -1;
+ else
+ height = misc::max (availHeight - boxDiffHeight (), 0);
+ } else {
+ // In most cases, the toplevel widget should be a container, so
+ // the container is non-NULL when the parent is non-NULL. Just
+ // in case ...:
+ Widget *effContainer =
+ child->container ? child->container : child->parent;
+
+ if (effContainer == this) {
+ if (style::isAbsLength (child->getStyle()->height)) {
+ DBG_OBJ_MSGF ("resize", 1, "absolute height: %dpx",
+ style::absLengthVal (child->getStyle()->height));
+ height = misc::max (style::absLengthVal (child->getStyle()->height)
+ + child->boxDiffHeight (), 0);
+ } else {
+ assert (style::isPerLength (child->getStyle()->height));
+ DBG_OBJ_MSGF ("resize", 1, "percentage height: %g%%",
+ 100 * style::perLengthVal_useThisOnlyForDebugging
+ (child->getStyle()->height));
+
+ int availHeight = getAvailHeight (forceValue);
+ if (availHeight == -1)
+ height = -1;
+ else
+ height =
+ misc::max (child->applyPerHeight (availHeight -
+ boxDiffHeight (),
+ child->getStyle()->height),
+ 0);
+ }
+ } else {
+ DBG_OBJ_MSG ("resize", 1, "delegated to (effective) container");
+ DBG_OBJ_MSG_START ();
+ height = effContainer->getAvailHeightOfChild (child, forceValue);
+ DBG_OBJ_MSG_END ();
+ }
+ }
+
+ DBG_OBJ_MSGF ("resize", 1, "=> %d", height);
+ DBG_OBJ_LEAVE ();
+
+ return height;
+}
+
+void Widget::correctRequisitionOfChild (Widget *child, Requisition *requisition,
+ void (*splitHeightFun) (int, int*,
+ int*))
+{
+ // Again, a suitable implementation for all widgets (perhaps).
+
+ DBG_OBJ_ENTER ("resize", 0, "correctRequisitionOfChild",
+ "%p, %d * (%d + %d), ...", child, requisition->width,
+ requisition->ascent, requisition->descent);
+
+ correctReqWidthOfChild (child, requisition);
+ correctReqHeightOfChild (child, requisition, splitHeightFun);
+
+ DBG_OBJ_MSGF ("resize", 1, "=> %d * (%d + %d)",
+ requisition->width, requisition->ascent,
+ requisition->descent);
+ DBG_OBJ_LEAVE ();
+}
+
+void Widget::correctReqWidthOfChild (Widget *child, Requisition *requisition)
+{
+ DBG_OBJ_ENTER ("resize", 0, "correctReqWidthOfChild", "%p, %d * (%d + %d)",
+ child, requisition->width, requisition->ascent,
+ requisition->descent);
+
+ if (style::isAbsLength (child->getStyle()->width))
+ requisition->width =
+ misc::max (style::absLengthVal (child->getStyle()->width)
+ + child->boxDiffWidth (),
+ child->getMinWidth (NULL));
+ else if (style::isPerLength (child->getStyle()->width)) {
+ int availWidth = getAvailWidth (false);
+ if (availWidth != -1) {
+ int containerWidth = availWidth - boxDiffWidth ();
+ requisition->width =
+ misc::max (child->applyPerWidth (containerWidth,
+ child->getStyle()->width),
+ child->getMinWidth (NULL));
+ }
+ }
+
+ DBG_OBJ_MSGF ("resize", 1, "=> %d * (%d + %d)",
+ requisition->width, requisition->ascent,
+ requisition->descent);
+ DBG_OBJ_LEAVE ();
+}
+
+void Widget::correctReqHeightOfChild (Widget *child, Requisition *requisition,
+ void (*splitHeightFun) (int, int*, int*))
+{
+ // TODO Correct height by extremes? (Height extemes?)
+
+ DBG_OBJ_ENTER ("resize", 0, "correctReqHeightOfChild",
+ "%p, %d * (%d + %d), ...", child, requisition->width,
+ requisition->ascent, requisition->descent);
+
+ // TODO Perhaps split first, then add box ascent and descent.
+ if (style::isAbsLength (child->getStyle()->height))
+ splitHeightFun (style::absLengthVal (child->getStyle()->height)
+ + child->boxDiffHeight (),
+ &requisition->ascent, &requisition->descent);
+ else if (style::isPerLength (child->getStyle()->height)) {
+#if 0
+ // TODO Percentage heights are somewhat more complicated. Has to
+ // be clarified. See also Widget::correctRequisition.
+
+ int availHeight = getAvailHeight (false);
+ if (availHeight != -1) {
+ int containerHeight = availHeight - boxDiffHeight ();
+ splitHeightFun (child->applyPerHeight (containerHeight,
+ child->getStyle()->height),
+ &requisition->ascent, &requisition->descent);
+ }
+#endif
+ }
+
+ DBG_OBJ_MSGF ("resize", 1, "=> %d * (%d + %d)",
+ requisition->width, requisition->ascent,
+ requisition->descent);
+ DBG_OBJ_LEAVE ();
+}
+
+void Widget::correctExtremesOfChild (Widget *child, Extremes *extremes)
+{
+ // See comment in correctRequisitionOfChild.
+
+ DBG_OBJ_ENTER ("resize", 0, "correctExtremesOfChild",
+ "%p, %d (%d) / %d (%d)",
+ child, extremes->minWidth, extremes->minWidthIntrinsic,
+ extremes->maxWidth, extremes->maxWidthIntrinsic);
+
+ if (style::isAbsLength (child->getStyle()->width)) {
+ DBG_OBJ_MSGF ("resize", 1, "absolute width: %dpx",
+ style::absLengthVal (child->getStyle()->width));
+ extremes->minWidth = extremes->maxWidth =
+ misc::max (style::absLengthVal (child->getStyle()->width)
+ + child->boxDiffWidth (),
+ child->getMinWidth (extremes));
+ } else if (style::isPerLength (child->getStyle()->width)) {
+ DBG_OBJ_MSGF ("resize", 1, "percentage width: %g%%",
+ 100 * style::perLengthVal_useThisOnlyForDebugging
+ (child->getStyle()->width));
+ int availWidth = getAvailWidth (false);
+ if (availWidth != -1) {
+ int containerWidth = availWidth - boxDiffWidth ();
+ DBG_OBJ_MSGF ("resize", 1, "containerWidth = %d - %d = %d",
+ availWidth, boxDiffWidth (), containerWidth);
+ extremes->minWidth = extremes->maxWidth =
+ misc::max (child->applyPerWidth (containerWidth,
+ child->getStyle()->width),
+ child->getMinWidth (extremes));
+ }
+ } else
+ DBG_OBJ_MSG ("resize", 1, "no specification");
+
+ DBG_OBJ_MSGF ("resize", 1, "=> %d / %d",
+ extremes->minWidth, extremes->maxWidth);
+ DBG_OBJ_LEAVE ();
+}
+
/**
* \brief This method is called after a widget has been set as the top of a
* widget tree.
@@ -820,16 +1527,16 @@ void Widget::notifySetParent()
{
}
-void Widget::setWidth (int width)
-{
-}
-
-void Widget::setAscent (int ascent)
+bool Widget::isBlockLevel ()
{
+ // Most widgets are not block-level.
+ return false;
}
-void Widget::setDescent (int descent)
+bool Widget::isPossibleContainer ()
{
+ // In most (all?) cases identical to:
+ return isBlockLevel ();
}
bool Widget::buttonPressImpl (EventButton *event)
@@ -849,7 +1556,7 @@ bool Widget::motionNotifyImpl (EventMotion *event)
void Widget::enterNotifyImpl (EventCrossing *)
{
- core::style::Tooltip *tooltip = getStyle()->x_tooltip;
+ style::Tooltip *tooltip = getStyle()->x_tooltip;
if (tooltip)
tooltip->onEnter();
@@ -857,7 +1564,7 @@ void Widget::enterNotifyImpl (EventCrossing *)
void Widget::leaveNotifyImpl (EventCrossing *)
{
- core::style::Tooltip *tooltip = getStyle()->x_tooltip;
+ style::Tooltip *tooltip = getStyle()->x_tooltip;
if (tooltip)
tooltip->onLeave();
@@ -869,5 +1576,25 @@ void Widget::removeChild (Widget *child)
misc::assertNotReached ();
}
+// ----------------------------------------------------------------------
+
+void splitHeightPreserveAscent (int height, int *ascent, int *descent)
+{
+ *descent = height - *ascent;
+ if (*descent < 0) {
+ *descent = 0;
+ *ascent = height;
+ }
+}
+
+void splitHeightPreserveDescent (int height, int *ascent, int *descent)
+{
+ *ascent = height - *descent;
+ if (*ascent < 0) {
+ *ascent = 0;
+ *descent = height;
+ }
+}
+
} // namespace core
} // namespace dw
diff --git a/dw/widget.hh b/dw/widget.hh
index e3d9cbe1..23d91a55 100644
--- a/dw/widget.hh
+++ b/dw/widget.hh
@@ -69,32 +69,11 @@ protected:
EXTREMES_CHANGED = 1 << 5,
/**
- * \brief Set by the widget itself (in the constructor), when set...
- * methods are implemented.
- *
- * Will hopefully be removed, after redesigning the size model.
- */
- USES_HINTS = 1 << 6,
-
- /**
- * \brief Set by the widget itself (in the constructor), when it contains
- * some contents, e.g. an image, as opposed to a horizontal ruler.
- *
- * Will hopefully be removed, after redesigning the size model.
- */
- HAS_CONTENTS = 1 << 7,
-
- /**
* \brief Set, when a widget was already once allocated,
*
* The dw::Image widget uses this flag, see dw::Image::setBuffer.
*/
- WAS_ALLOCATED = 1 << 8,
-
- /**
- * \brief Set for block-level widgets (as opposed to inline widgets)
- */
- BLOCK_LEVEL = 1 << 9,
+ WAS_ALLOCATED = 1 << 6,
};
/**
@@ -120,18 +99,32 @@ protected:
WidgetImgRenderer *widgetImgRenderer;
private:
+ static bool adjustMinWidth;
+
/**
* \brief The parent widget, NULL for top-level widgets.
*/
Widget *parent;
/**
+ * \brief ...
+ */
+ Widget *quasiParent;
+
+ /**
* \brief The generating widget, NULL for top-level widgets, or if
- * not set; in the latter case, the effective generator (see
- * getGenerator) is the parent.
+ * not set; in the latter case, the effective generator (see
+ * getGenerator) is the parent.
*/
Widget *generator;
+ /**
+ * \brief The containing widget, equivalent to the "containing
+ * block" defined by CSS. May be NULL, in this case the viewport
+ * is used.
+ */
+ Widget *container;
+
style::Style *style;
Flags flags;
@@ -164,7 +157,10 @@ private:
*/
bool buttonSensitiveSet;
- void actualQueueResize (int ref, bool extremesChanged);
+ void queueResize (int ref, bool extremesChanged, bool fast);
+ inline void queueResizeFast (int ref, bool extremesChanged)
+ { queueResize (ref, extremesChanged, true); }
+ void actualQueueResize (int ref, bool extremesChanged, bool fast);
public:
/**
@@ -191,20 +187,23 @@ protected:
Layout *layout;
+ /**
+ * \brief Space around the margin box. Allocation is extraSpace +
+ * margin + border + padding + contents;
+ */
+ style::Box extraSpace;
+
/*inline void printFlags () {
DBG_IF_RTFL {
char buf[10 * 3 - 1 + 1];
- snprintf (buf, sizeof (buf), "%s:%s:%s:%s:%s:%s:%s:%s:%s:%s",
+ snprintf (buf, sizeof (buf), "%s:%s:%s:%s:%s:%s:%s",
(flags & RESIZE_QUEUED) ? "Rq" : "--",
(flags & EXTREMES_QUEUED) ? "Eq" : "--",
(flags & NEEDS_RESIZE) ? "nR" : "--",
(flags & NEEDS_ALLOCATE) ? "nA" : "--",
(flags & ALLOCATE_QUEUED) ? "Aq" : "--",
(flags & EXTREMES_CHANGED) ? "Ec" : "--",
- (flags & USES_HINTS) ? "uh" : "--",
- (flags & HAS_CONTENTS) ? "hc" : "--",
- (flags & WAS_ALLOCATED) ? "wA" : "--",
- (flags & BLOCK_LEVEL) ? "bl" : "--");
+ (flags & WAS_ALLOCATED) ? "wA" : "--");
DBG_OBJ_SET_SYM ("flags", buf);
}
}*/
@@ -241,26 +240,11 @@ protected:
DBG_OBJ_SET_SYM ("flags.EXTREMES_CHANGED",
(flags & EXTREMES_CHANGED) ? "true" : "false");
break;
-
- case USES_HINTS:
- DBG_OBJ_SET_SYM ("flags.USES_HINTS",
- (flags & USES_HINTS) ? "true" : "false");
- break;
-
- case HAS_CONTENTS:
- DBG_OBJ_SET_SYM ("flags.HAS_CONTENTS",
- (flags & HAS_CONTENTS) ? "true" : "false");
- break;
-
+
case WAS_ALLOCATED:
DBG_OBJ_SET_SYM ("flags.WAS_ALLOCATED",
(flags & WAS_ALLOCATED) ? "true" : "false");
- break;
-
- case BLOCK_LEVEL:
- DBG_OBJ_SET_SYM ("flags.BLOCK_LEVEL",
- (flags & BLOCK_LEVEL) ? "true" : "false");
- break;
+ break;
}
}
}
@@ -272,11 +256,10 @@ protected:
inline void queueDraw ()
- {
- queueDrawArea (0, 0, allocation.width, getHeight());
- }
+ { queueDrawArea (0, 0, allocation.width, getHeight()); }
void queueDrawArea (int x, int y, int width, int height);
- void queueResize (int ref, bool extremesChanged);
+ inline void queueResize (int ref, bool extremesChanged)
+ { queueResize (ref, extremesChanged, false); }
/**
* \brief See \ref dw-widget-sizes.
@@ -286,7 +269,7 @@ protected:
/**
* \brief See \ref dw-widget-sizes.
*/
- virtual void getExtremesImpl (Extremes *extremes);
+ virtual void getExtremesImpl (Extremes *extremes) = 0;
/**
* \brief See \ref dw-widget-sizes.
@@ -309,6 +292,26 @@ protected:
*/
virtual void markExtremesChange (int ref);
+ int getMinWidth (Extremes *extremes);
+
+ virtual int getAvailWidthOfChild (Widget *child, bool forceValue);
+ virtual int getAvailHeightOfChild (Widget *child, bool forceValue);
+ virtual void correctRequisitionOfChild (Widget *child,
+ Requisition *requisition,
+ void (*splitHeightFun) (int, int*,
+ int*));
+ void correctReqWidthOfChild (Widget *child, Requisition *requisition);
+ void correctReqHeightOfChild (Widget *child, Requisition *requisition,
+ void (*splitHeightFun) (int, int*, int*));
+ virtual void correctExtremesOfChild (Widget *child, Extremes *extremes);
+
+ virtual void containerSizeChangedForChildren ();
+
+ virtual bool affectedByContainerSizeChange ();
+ virtual bool affectsSizeChangeContainerChild (Widget *child);
+ virtual bool usesAvailWidth ();
+ virtual bool usesAvailHeight ();
+
virtual void notifySetAsTopLevel();
virtual void notifySetParent();
@@ -384,6 +387,10 @@ private:
public:
static int CLASS_ID;
+ inline static void setAdjustMinWidth (bool adjustMinWidth)
+ { Widget::adjustMinWidth = adjustMinWidth; }
+ inline static bool getAdjustMinWidth () { return Widget::adjustMinWidth; }
+
Widget ();
~Widget ();
@@ -394,11 +401,9 @@ public:
inline bool allocateQueued () { return flags & ALLOCATE_QUEUED; }
inline bool extremesChanged () { return flags & EXTREMES_CHANGED; }
inline bool wasAllocated () { return flags & WAS_ALLOCATED; }
- inline bool usesHints () { return flags & USES_HINTS; }
- inline bool hasContents () { return flags & HAS_CONTENTS; }
- inline bool blockLevel () { return flags & BLOCK_LEVEL; }
void setParent (Widget *parent);
+ void setQuasiParent (Widget *quasiParent);
void setGenerator (Widget *generator) { this->generator = generator; }
@@ -406,12 +411,34 @@ public:
/** \todo I do not like this. */
inline Allocation *getAllocation () { return &allocation; }
+ inline int boxOffsetX ()
+ { return extraSpace.left + getStyle()->boxOffsetX (); }
+ inline int boxRestWidth ()
+ { return extraSpace.right + getStyle()->boxRestWidth (); }
+ inline int boxDiffWidth () { return boxOffsetX () + boxRestWidth (); }
+ inline int boxOffsetY ()
+ { return extraSpace.top + getStyle()->boxOffsetY (); }
+ inline int boxRestHeight ()
+ { return extraSpace.bottom + getStyle()->boxRestHeight (); }
+ inline int boxDiffHeight () { return boxOffsetY () + boxRestHeight (); }
+
void sizeRequest (Requisition *requisition);
void getExtremes (Extremes *extremes);
void sizeAllocate (Allocation *allocation);
- virtual void setWidth (int width);
- virtual void setAscent (int ascent);
- virtual void setDescent (int descent);
+
+ int getAvailWidth (bool forceValue);
+ int getAvailHeight (bool forceValue);
+ void correctRequisition (Requisition *requisition,
+ void (*splitHeightFun) (int, int*, int*));
+ void correctExtremes (Extremes *extremes);
+
+ virtual int applyPerWidth (int containerWidth, style::Length perWidth);
+ virtual int applyPerHeight (int containerHeight, style::Length perHeight);
+
+ virtual bool isBlockLevel ();
+ virtual bool isPossibleContainer ();
+
+ void containerSizeChanged ();
bool intersects (Rectangle *area, Rectangle *intersection);
@@ -470,6 +497,9 @@ public:
virtual void removeChild (Widget *child);
};
+void splitHeightPreserveAscent (int height, int *ascent, int *descent);
+void splitHeightPreserveDescent (int height, int *ascent, int *descent);
+
} // namespace core
} // namespace dw
diff --git a/lout/debug.hh b/lout/debug.hh
index b823f171..d4e545a2 100644
--- a/lout/debug.hh
+++ b/lout/debug.hh
@@ -108,6 +108,48 @@
fflush (stdout); \
} D_STMT_END
+#define DBG_OBJ_ENTER0(aspect, prio, funname) \
+ D_STMT_START { \
+ printf (RTFL_PREFIX_FMT "obj-enter:%p:%s:%d:%s:\n", \
+ RTFL_PREFIX_ARGS, this, aspect, prio, funname); \
+ fflush (stdout); \
+ } D_STMT_END
+
+#define DBG_OBJ_ENTER0_O(aspect, prio, obj, funname) \
+ D_STMT_START { \
+ printf (RTFL_PREFIX_FMT "obj-enter:%p:%s:%d:%s:\n", \
+ RTFL_PREFIX_ARGS, obj, aspect, prio, funname); \
+ fflush (stdout); \
+ } D_STMT_END
+
+#define DBG_OBJ_ENTER(aspect, prio, funname, fmt, ...) \
+ D_STMT_START { \
+ fflush (stdout); \
+ printf (RTFL_PREFIX_FMT "obj-enter:%p:%s:%d:%s:" fmt "\n", \
+ RTFL_PREFIX_ARGS, this, aspect, prio, funname, __VA_ARGS__); \
+ } D_STMT_END
+
+#define DBG_OBJ_ENTER_O(aspect, prio, obj, funname, fmt, ...) \
+ D_STMT_START { \
+ fflush (stdout); \
+ printf (RTFL_PREFIX_FMT "obj-enter:%p:%s:%d:%s:" fmt "\n", \
+ RTFL_PREFIX_ARGS, obj, aspect, prio, funname, __VA_ARGS__); \
+ } D_STMT_END
+
+#define DBG_OBJ_LEAVE() \
+ D_STMT_START { \
+ printf (RTFL_PREFIX_FMT "obj-leave:%p\n", \
+ RTFL_PREFIX_ARGS, this); \
+ fflush (stdout); \
+ } D_STMT_END
+
+#define DBG_OBJ_LEAVE_O(obj) \
+ D_STMT_START { \
+ printf (RTFL_PREFIX_FMT "obj-leave:%p\n", \
+ RTFL_PREFIX_ARGS, obj); \
+ fflush (stdout); \
+ } D_STMT_END
+
#define DBG_OBJ_CREATE(klass) \
D_STMT_START { \
printf (RTFL_PREFIX_FMT "obj-create:%p:%s\n", \
@@ -196,6 +238,20 @@
fflush (stdout); \
} D_STMT_END
+#define DBG_OBJ_SET_BOOL(var, val) \
+ D_STMT_START { \
+ printf (RTFL_PREFIX_FMT "obj-set:%p:%s:%s\n", \
+ RTFL_PREFIX_ARGS, this, var, val ? "true" : "false"); \
+ fflush (stdout); \
+ } D_STMT_END
+
+#define DBG_OBJ_SET_BOOL_O(obj, var, val) \
+ D_STMT_START { \
+ printf (RTFL_PREFIX_FMT "obj-set:%p:%s:%s\n", \
+ RTFL_PREFIX_ARGS, obj, var, val ? "true" : "false"); \
+ fflush (stdout); \
+ } D_STMT_END
+
#define DBG_OBJ_ARRSET_NUM(var, ind, val) \
D_STMT_START { \
printf (RTFL_PREFIX_FMT "obj-set:%p:%s.%d:%d\n", \
@@ -263,35 +319,43 @@
#define DBG_IF_RTFL if(0)
-#define DBG_OBJ_MSG(aspect, prio, msg) D_STMT_NOP
-#define DBG_OBJ_MSG_O(aspect, prio, obj, msg) D_STMT_NOP
-#define DBG_OBJ_MSGF(aspect, prio, fmt, ...) D_STMT_NOP
-#define DBG_OBJ_MSGF_O(aspect, prio, obj, fmt, ...) D_STMT_NOP
-#define DBG_OBJ_MSG_START() D_STMT_NOP
-#define DBG_OBJ_MSG_START_O(obj) D_STMT_NOP
-#define DBG_OBJ_MSG_END() D_STMT_NOP
-#define DBG_OBJ_MSG_END_O(obj) D_STMT_NOP
-#define DBG_OBJ_CREATE(klass) D_STMT_NOP
-#define DBG_OBJ_DELETE() D_STMT_NOP
-#define DBG_OBJ_BASECLASS(klass) D_STMT_NOP
-#define DBG_OBJ_ASSOC_PARENT(parent) D_STMT_NOP
-#define DBG_OBJ_ASSOC_CHILD(child) D_STMT_NOP
-#define DBG_OBJ_ASSOC(parent, child) D_STMT_NOP
-#define DBG_OBJ_SET_NUM(var, val) D_STMT_NOP
-#define DBG_OBJ_SET_NUM_O(obj, var, val) D_STMT_NOP
-#define DBG_OBJ_SET_SYM(var, val) D_STMT_NOP
-#define DBG_OBJ_SET_STR(var, val) D_STMT_NOP
-#define DBG_OBJ_SET_PTR(var, val) D_STMT_NOP
-#define DBG_OBJ_SET_PTR_O(obj, var, val) D_STMT_NOP
-#define DBG_OBJ_ARRSET_NUM(var, ind, val) D_STMT_NOP
-#define DBG_OBJ_ARRSET_SYM(var, ind, val) D_STMT_NOP
-#define DBG_OBJ_ARRSET_STR(var, ind, val) D_STMT_NOP
-#define DBG_OBJ_ARRSET_PTR(var, ind, val) D_STMT_NOP
-#define DBG_OBJ_ARRATTRSET_NUM(var, ind, attr, val) D_STMT_NOP
-#define DBG_OBJ_ARRATTRSET_SYM(var, ind, attr, val) D_STMT_NOP
-#define DBG_OBJ_ARRATTRSET_STR(var, ind, attr, val) D_STMT_NOP
-#define DBG_OBJ_ARRATTRSET_PTR(var, ind, attr, val) D_STMT_NOP
-#define DBG_OBJ_COLOR(klass, color) D_STMT_NOP
+#define DBG_OBJ_MSG(aspect, prio, msg) D_STMT_NOP
+#define DBG_OBJ_MSG_O(aspect, prio, obj, msg) D_STMT_NOP
+#define DBG_OBJ_MSGF(aspect, prio, fmt, ...) D_STMT_NOP
+#define DBG_OBJ_MSGF_O(aspect, prio, obj, fmt, ...) D_STMT_NOP
+#define DBG_OBJ_MSG_START() D_STMT_NOP
+#define DBG_OBJ_MSG_START_O(obj) D_STMT_NOP
+#define DBG_OBJ_MSG_END() D_STMT_NOP
+#define DBG_OBJ_MSG_END_O(obj) D_STMT_NOP
+#define DBG_OBJ_ENTER0(aspect, prio, funname) D_STMT_NOP
+#define DBG_OBJ_ENTER0_O(aspect, prio, obj, funname) D_STMT_NOP
+#define DBG_OBJ_ENTER(aspect, prio, funname, fmt, ...) D_STMT_NOP
+#define DBG_OBJ_ENTER_O(aspect, prio, obj, funname, fmt, ...) D_STMT_NOP
+#define DBG_OBJ_LEAVE() D_STMT_NOP
+#define DBG_OBJ_LEAVE_O(obj) D_STMT_NOP
+#define DBG_OBJ_CREATE(klass) D_STMT_NOP
+#define DBG_OBJ_DELETE() D_STMT_NOP
+#define DBG_OBJ_BASECLASS(klass) D_STMT_NOP
+#define DBG_OBJ_ASSOC_PARENT(parent) D_STMT_NOP
+#define DBG_OBJ_ASSOC_CHILD(child) D_STMT_NOP
+#define DBG_OBJ_ASSOC(parent, child) D_STMT_NOP
+#define DBG_OBJ_SET_NUM(var, val) D_STMT_NOP
+#define DBG_OBJ_SET_NUM_O(obj, var, val) D_STMT_NOP
+#define DBG_OBJ_SET_SYM(var, val) D_STMT_NOP
+#define DBG_OBJ_SET_STR(var, val) D_STMT_NOP
+#define DBG_OBJ_SET_PTR(var, val) D_STMT_NOP
+#define DBG_OBJ_SET_PTR_O(obj, var, val) D_STMT_NOP
+#define DBG_OBJ_SET_BOOL(var, val) D_STMT_NOP
+#define DBG_OBJ_SET_BOOL_O(obj, var, val) D_STMT_NOP
+#define DBG_OBJ_ARRSET_NUM(var, ind, val) D_STMT_NOP
+#define DBG_OBJ_ARRSET_SYM(var, ind, val) D_STMT_NOP
+#define DBG_OBJ_ARRSET_STR(var, ind, val) D_STMT_NOP
+#define DBG_OBJ_ARRSET_PTR(var, ind, val) D_STMT_NOP
+#define DBG_OBJ_ARRATTRSET_NUM(var, ind, attr, val) D_STMT_NOP
+#define DBG_OBJ_ARRATTRSET_SYM(var, ind, attr, val) D_STMT_NOP
+#define DBG_OBJ_ARRATTRSET_STR(var, ind, attr, val) D_STMT_NOP
+#define DBG_OBJ_ARRATTRSET_PTR(var, ind, attr, val) D_STMT_NOP
+#define DBG_OBJ_COLOR(klass, color) D_STMT_NOP
#endif /* DBG_RTFL */
diff --git a/lout/misc.hh b/lout/misc.hh
index 5aafd018..cac3da77 100644
--- a/lout/misc.hh
+++ b/lout/misc.hh
@@ -223,6 +223,14 @@ public:
assert (i >= 0 && this->num - i > 0);
this->array[i] = t;
}
+
+ /**
+ * \brief Store an object at the end of the vector.
+ */
+ inline void setLast (T t) {
+ assert (this->num > 0);
+ this->array[this->num - 1] = t;
+ }
};
/**
@@ -500,6 +508,13 @@ public:
inline void set (int i, T t) {
*(this->getRef(i)) = t;
}
+
+ /**
+ * \brief Store an object at the end of the vector.
+ */
+ inline void setLast (T t) {
+ *(this->getLastRef()) = t;
+ }
};
/**
diff --git a/src/dillo.cc b/src/dillo.cc
index 4d96988f..d67ba3af 100644
--- a/src/dillo.cc
+++ b/src/dillo.cc
@@ -56,6 +56,7 @@
#include "lout/debug.hh"
#include "dw/fltkcore.hh"
+#include "dw/widget.hh"
#include "dw/textblock.hh"
/*
@@ -483,6 +484,7 @@ int main(int argc, char **argv)
a_UIcmd_init();
StyleEngine::init();
+ dw::core::Widget::setAdjustMinWidth (prefs.adjust_min_width);
dw::Textblock::setPenaltyHyphen (prefs.penalty_hyphen);
dw::Textblock::setPenaltyHyphen2 (prefs.penalty_hyphen_2);
dw::Textblock::setPenaltyEmDashLeft (prefs.penalty_em_dash_left);
diff --git a/src/prefs.c b/src/prefs.c
index 56e02006..b0213fcc 100644
--- a/src/prefs.c
+++ b/src/prefs.c
@@ -68,6 +68,7 @@ void a_Prefs_init(void)
prefs.http_referer = dStrdup(PREFS_HTTP_REFERER);
prefs.http_user_agent = dStrdup(PREFS_HTTP_USER_AGENT);
prefs.limit_text_width = FALSE;
+ prefs.adjust_min_width = FALSE;
prefs.load_images=TRUE;
prefs.load_background_images=FALSE;
prefs.load_stylesheets=TRUE;
diff --git a/src/prefs.h b/src/prefs.h
index 0e54e0fc..b742e6e7 100644
--- a/src/prefs.h
+++ b/src/prefs.h
@@ -66,6 +66,7 @@ typedef struct {
int panel_size;
bool_t small_icons;
bool_t limit_text_width;
+ bool_t adjust_min_width;
bool_t w3c_plus_heuristics;
bool_t focus_new_tab;
double font_factor;
diff --git a/src/prefsparser.cc b/src/prefsparser.cc
index ce420eac..33f6cf51 100644
--- a/src/prefsparser.cc
+++ b/src/prefsparser.cc
@@ -79,6 +79,7 @@ int PrefsParser::parseOption(char *name, char *value)
{ "http_referer", &prefs.http_referer, PREFS_STRING },
{ "http_user_agent", &prefs.http_user_agent, PREFS_STRING },
{ "limit_text_width", &prefs.limit_text_width, PREFS_BOOL },
+ { "adjust_min_width", &prefs.adjust_min_width, PREFS_BOOL },
{ "load_images", &prefs.load_images, PREFS_BOOL },
{ "load_background_images", &prefs.load_background_images, PREFS_BOOL },
{ "load_stylesheets", &prefs.load_stylesheets, PREFS_BOOL },
diff --git a/src/table.cc b/src/table.cc
index a3002ebf..29b5fbc9 100644
--- a/src/table.cc
+++ b/src/table.cc
@@ -15,6 +15,7 @@
#include "dw/style.hh"
#include "dw/textblock.hh"
#include "dw/table.hh"
+#include "dw/simpletablecell.hh"
#include "prefs.h"
#include "msg.h"
@@ -445,11 +446,11 @@ static void Html_tag_content_table_cell(DilloHtml *html,
rowspan = MAX(1, strtol (attrbuf, NULL, 10));
if (html->style ()->textAlign
== TEXT_ALIGN_STRING)
- col_tb = new dw::TableCell (
+ col_tb = new AlignedTableCell (
((dw::Table*)S_TOP(html)->table)->getCellRef (),
prefs.limit_text_width);
else
- col_tb = new Textblock (prefs.limit_text_width);
+ col_tb = new SimpleTableCell (prefs.limit_text_width);
if (html->style()->borderCollapse == BORDER_MODEL_COLLAPSE){
Html_set_collapsing_border_model(html, col_tb);
diff --git a/test/Makefile.am b/test/Makefile.am
index f0ac2b0a..3b474466 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -17,6 +17,7 @@ noinst_PROGRAMS = \
dw-images-scaled \
dw-images-scaled2 \
dw-lists \
+ dw-simple-container-test \
dw-table-aligned \
dw-table \
dw-border-test \
@@ -119,6 +120,17 @@ dw_lists_LDADD = \
$(top_builddir)/lout/liblout.a \
@LIBFLTK_LIBS@ @LIBX11_LIBS@
+dw_simple_container_test_SOURCES = \
+ dw_simple_container.hh \
+ dw_simple_container.cc \
+ dw_simple_container_test.cc
+dw_simple_container_test_LDADD = \
+ $(top_builddir)/dw/libDw-widgets.a \
+ $(top_builddir)/dw/libDw-fltk.a \
+ $(top_builddir)/dw/libDw-core.a \
+ $(top_builddir)/lout/liblout.a \
+ @LIBFLTK_LIBS@
+
dw_table_aligned_SOURCES = dw_table_aligned.cc
dw_table_aligned_LDADD = \
$(top_builddir)/dw/libDw-widgets.a \
diff --git a/test/dw_simple_container.cc b/test/dw_simple_container.cc
new file mode 100644
index 00000000..c4a1aa2a
--- /dev/null
+++ b/test/dw_simple_container.cc
@@ -0,0 +1,241 @@
+/*
+ * Dillo Widget
+ *
+ * Copyright 2014 Sebastian Geerken <sgeerken@dillo.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <math.h>
+
+#include "dw_simple_container.hh"
+
+using namespace dw::core;
+using namespace dw::core::style;
+using namespace lout::misc;
+
+namespace dw {
+
+int SimpleContainer::CLASS_ID = -1;
+
+// ----------------------------------------------------------------------
+
+SimpleContainer::SimpleContainerIterator::SimpleContainerIterator
+ (SimpleContainer *simpleContainer, Content::Type mask, bool atEnd) :
+ Iterator (simpleContainer, mask, atEnd)
+{
+ content.type = atEnd ? Content::END : Content::START;
+}
+
+lout::object::Object *SimpleContainer::SimpleContainerIterator::clone ()
+{
+ SimpleContainerIterator *sci =
+ new SimpleContainerIterator ((SimpleContainer*)getWidget(),
+ getMask(), false);
+ sci->content = content;
+ return sci;
+}
+
+int SimpleContainer::SimpleContainerIterator::index ()
+{
+ switch (content.type) {
+ case Content::START:
+ return 0;
+ case Content::WIDGET_IN_FLOW:
+ return 1;
+ case Content::END:
+ return 2;
+ default:
+ assertNotReached ();
+ return 0;
+ }
+}
+
+int SimpleContainer::SimpleContainerIterator::compareTo
+ (lout::object::Comparable *other)
+{
+ return index () - ((SimpleContainerIterator*)other)->index ();
+}
+
+bool SimpleContainer::SimpleContainerIterator::next ()
+{
+ SimpleContainer *simpleContainer = (SimpleContainer*)getWidget();
+
+ if (content.type == Content::END)
+ return false;
+
+ // simple containers only contain widgets:
+ if ((getMask() & Content::WIDGET_IN_FLOW) == 0) {
+ content.type = Content::END;
+ return false;
+ }
+
+ if (content.type == Content::START) {
+ if (simpleContainer->child != NULL) {
+ content.type = Content::WIDGET_IN_FLOW;
+ content.widget = simpleContainer->child;
+ return true;
+ } else {
+ content.type = Content::END;
+ return false;
+ }
+ } else /* if (content.type == Content::WIDGET) */ {
+ content.type = Content::END;
+ return false;
+ }
+}
+
+bool SimpleContainer::SimpleContainerIterator::prev ()
+{
+ SimpleContainer *simpleContainer = (SimpleContainer*)getWidget();
+
+ if (content.type == Content::START)
+ return false;
+
+ // simple containers only contain widgets:
+ if ((getMask() & Content::WIDGET_IN_FLOW) == 0) {
+ content.type = Content::START;
+ return false;
+ }
+
+ if (content.type == Content::END) {
+ if (simpleContainer->child != NULL) {
+ content.type = Content::WIDGET_IN_FLOW;
+ content.widget = simpleContainer->child;
+ return true;
+ } else {
+ content.type = Content::START;
+ return false;
+ }
+ } else /* if (content.type == Content::WIDGET) */ {
+ content.type = Content::START;
+ return false;
+ }
+}
+
+void SimpleContainer::SimpleContainerIterator::highlight (int start,
+ int end,
+ HighlightLayer layer)
+{
+ /** todo Needs this an implementation? */
+}
+
+void SimpleContainer::SimpleContainerIterator::unhighlight (int direction,
+ HighlightLayer
+ layer)
+{
+ /** todo Needs this an implementation? */
+}
+
+void SimpleContainer::SimpleContainerIterator::getAllocation (int start,
+ int end,
+ Allocation
+ *allocation)
+{
+ /** \bug Not implemented. */
+}
+
+// ----------------------------------------------------------------------
+
+SimpleContainer::SimpleContainer ()
+{
+ registerName ("dw::SimpleContainer", &CLASS_ID);
+ child = NULL;
+}
+
+SimpleContainer::~SimpleContainer ()
+{
+ if (child)
+ delete child;
+}
+
+void SimpleContainer::sizeRequestImpl (Requisition *requisition)
+{
+ Requisition childReq;
+ if (child)
+ child->sizeRequest (&childReq);
+ else
+ childReq.width = childReq.ascent = childReq.descent = 0;
+
+ requisition->width = childReq.width + boxDiffWidth ();
+ requisition->ascent = childReq.ascent + boxOffsetY ();
+ requisition->descent = childReq.descent + boxRestHeight ();
+
+ correctRequisition (requisition, splitHeightPreserveAscent);
+}
+
+
+void SimpleContainer::getExtremesImpl (Extremes *extremes)
+{
+ Extremes childExtr;
+ if (child)
+ child->getExtremes (&childExtr);
+ else
+ childExtr.minWidth = childExtr.maxWidth = 0;
+
+ extremes->minWidth = childExtr.minWidth + boxDiffWidth ();
+ extremes->maxWidth = childExtr.maxWidth + boxDiffWidth ();
+
+ correctExtremes (extremes);
+}
+
+
+void SimpleContainer::sizeAllocateImpl (Allocation *allocation)
+{
+ Allocation childAlloc;
+
+ if (child) {
+ childAlloc.x = allocation->x + boxOffsetX ();
+ childAlloc.y = allocation->y + boxOffsetY ();
+ childAlloc.width = allocation->width - boxDiffWidth ();
+ childAlloc.ascent = allocation->ascent - boxOffsetY ();
+ childAlloc.descent = allocation->descent - boxRestHeight ();
+ child->sizeAllocate (&childAlloc);
+ }
+}
+
+void SimpleContainer::draw (View *view, Rectangle *area)
+{
+ drawWidgetBox (view, area, false);
+ Rectangle childArea;
+ if (child && child->intersects (area, &childArea))
+ child->draw (view, &childArea);
+}
+
+Iterator *SimpleContainer::iterator (Content::Type mask, bool atEnd)
+{
+ return new SimpleContainerIterator (this, mask, atEnd);
+}
+
+void SimpleContainer::removeChild (Widget *child)
+{
+ assert (child == this->child);
+ this->child = NULL;
+
+ queueResize (0, true);
+}
+
+void SimpleContainer::setChild (Widget *child)
+{
+ if (this->child)
+ delete this->child;
+
+ this->child = child;
+ if (this->child)
+ this->child->setParent (this);
+
+ queueResize (0, true);
+}
+
+} // namespace dw
diff --git a/test/dw_simple_container.hh b/test/dw_simple_container.hh
new file mode 100644
index 00000000..c8a629db
--- /dev/null
+++ b/test/dw_simple_container.hh
@@ -0,0 +1,56 @@
+#ifndef __DW_SIMPLE_CONTAINER_HH__
+#define __DWR_SIMPLE_CONTAINER_HH__
+
+#include "dw/core.hh"
+
+namespace dw {
+
+/**
+ * Simple widget used for testing concepts.
+ */
+class SimpleContainer: public core::Widget
+{
+private:
+ class SimpleContainerIterator: public core::Iterator
+ {
+ private:
+ int index ();
+
+ public:
+ SimpleContainerIterator (SimpleContainer *simpleContainer,
+ core::Content::Type mask,
+ bool atEnd);
+
+ lout::object::Object *clone ();
+ int compareTo (lout::object::Comparable *other);
+
+ bool next ();
+ bool prev ();
+ void highlight (int start, int end, core::HighlightLayer layer);
+ void unhighlight (int direction, core::HighlightLayer layer);
+ void getAllocation (int start, int end, core::Allocation *allocation);
+ };
+
+ Widget *child;
+
+protected:
+ void sizeRequestImpl (core::Requisition *requisition);
+ void getExtremesImpl (core::Extremes *extremes);
+ void sizeAllocateImpl (core::Allocation *allocation);
+
+public:
+ static int CLASS_ID;
+
+ SimpleContainer ();
+ ~SimpleContainer ();
+
+ void draw (core::View *view, core::Rectangle *area);
+ core::Iterator *iterator (core::Content::Type mask, bool atEnd);
+ void removeChild (Widget *child);
+
+ void setChild (core::Widget *child);
+};
+
+} // namespace dw
+
+#endif // __DW_SIMPLE_CONTAINER_HH__
diff --git a/test/dw_simple_container_test.cc b/test/dw_simple_container_test.cc
new file mode 100644
index 00000000..20697dd6
--- /dev/null
+++ b/test/dw_simple_container_test.cc
@@ -0,0 +1,114 @@
+/*
+ * Dillo Widget
+ *
+ * Copyright 2014 Sebastian Geerken <sgeerken@dillo.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+
+#include <FL/Fl_Window.H>
+#include <FL/Fl.H>
+
+#include "../dw/core.hh"
+#include "../dw/fltkcore.hh"
+#include "../dw/fltkviewport.hh"
+#include "dw_simple_container.hh"
+#include "../dw/textblock.hh"
+
+using namespace dw;
+using namespace dw::core;
+using namespace dw::core::style;
+using namespace dw::fltk;
+
+int main(int argc, char **argv)
+{
+ FltkPlatform *platform = new FltkPlatform ();
+ Layout *layout = new Layout (platform);
+
+ Fl_Window *window = new Fl_Window(200, 300, "Dw Example");
+ window->box(FL_NO_BOX);
+ window->begin();
+
+ FltkViewport *viewport = new FltkViewport (0, 0, 200, 300);
+ layout->attachView (viewport);
+
+ StyleAttrs styleAttrs;
+ styleAttrs.initValues ();
+ styleAttrs.margin.setVal (5);
+
+ FontAttrs fontAttrs;
+ fontAttrs.name = "Bitstream Charter";
+ fontAttrs.size = 14;
+ fontAttrs.weight = 400;
+ fontAttrs.style = FONT_STYLE_NORMAL;
+ fontAttrs.letterSpacing = 0;
+ fontAttrs.fontVariant = FONT_VARIANT_NORMAL;
+ styleAttrs.font = style::Font::create (layout, &fontAttrs);
+
+ styleAttrs.color = Color::create (layout, 0x000000);
+ styleAttrs.backgroundColor = Color::create (layout, 0xffffff);
+
+ Style *textblockStyle1 = Style::create (&styleAttrs);
+
+ styleAttrs.backgroundColor = NULL;
+ styleAttrs.margin.setVal (0);
+
+ Style *textblockStyle2 = Style::create (&styleAttrs);
+ Style *wordStyle = Style::create (&styleAttrs);
+
+ styleAttrs.borderWidth.setVal (5);
+ styleAttrs.setBorderColor (Color::create (layout, 0x800080));
+ styleAttrs.setBorderStyle (BORDER_DASHED);
+ styleAttrs.padding.setVal (5);
+
+ Style *containerStyle = Style::create (&styleAttrs);
+
+ Textblock *textblock1 = new Textblock (false);
+ textblock1->setStyle (textblockStyle1);
+ layout->setWidget (textblock1);
+
+ SimpleContainer *simpleContainer = new SimpleContainer ();
+ simpleContainer->setStyle (containerStyle);
+ textblock1->addWidget (simpleContainer, containerStyle);
+
+ Textblock *textblock2 = new Textblock (false);
+ textblock2->setStyle (textblockStyle2);
+ simpleContainer->setChild (textblock2);
+
+ const char *words[] = { "This", "is", "only", "a", "short", "paragraph.",
+ NULL };
+
+ for(int j = 0; words[j]; j++) {
+ textblock2->addText(words[j], wordStyle);
+ textblock2->addSpace(wordStyle);
+ }
+
+ textblockStyle1->unref();
+ textblockStyle2->unref();
+ containerStyle->unref();
+ wordStyle->unref();
+
+ textblock1->flush ();
+ textblock2->flush ();
+
+ window->resizable(viewport);
+ window->show();
+ int errorCode = Fl::run();
+
+ delete layout;
+
+ return errorCode;
+}
diff --git a/test/dw_table.cc b/test/dw_table.cc
index 5416d05b..9bec1a09 100644
--- a/test/dw_table.cc
+++ b/test/dw_table.cc
@@ -26,7 +26,6 @@
#include "../dw/fltkcore.hh"
#include "../dw/fltkviewport.hh"
#include "../dw/table.hh"
-#include "../dw/tablecell.hh"
using namespace dw;
using namespace dw::core;
diff --git a/test/dw_table_aligned.cc b/test/dw_table_aligned.cc
index 96cb0602..bef3d521 100644
--- a/test/dw_table_aligned.cc
+++ b/test/dw_table_aligned.cc
@@ -26,7 +26,7 @@
#include "../dw/fltkcore.hh"
#include "../dw/fltkviewport.hh"
#include "../dw/table.hh"
-#include "../dw/tablecell.hh"
+#include "../dw/alignedtablecell.hh"
using namespace dw;
using namespace dw::core;
@@ -87,10 +87,10 @@ int main(int argc, char **argv)
Style *wordStyle = Style::create (&styleAttrs);
- TableCell *ref = NULL;
+ AlignedTableCell *ref = NULL;
for(int i = 0; i < 10; i++) {
//for(int i = 0; i < 1; i++) {
- TableCell *cell = new TableCell (ref, false);
+ AlignedTableCell *cell = new AlignedTableCell (ref, false);
cell->setStyle (cellStyle);
ref = cell;
table->addRow (wordStyle);