diff options
author | corvid, Sebastian Geerken <devnull@localhost> | 2014-07-20 02:27:02 +0200 |
---|---|---|
committer | corvid, Sebastian Geerken <devnull@localhost> | 2014-07-20 02:27:02 +0200 |
commit | bad27299f5473125ffb39363632246f7dae50bf6 (patch) | |
tree | fa1565e2907438d842103d1fe65261739b7ff5f2 | |
parent | 1cf4023330a2b101973d9186342e57eb0c8b9099 (diff) |
Another change in table column apportion scheme: specified widths.
-rw-r--r-- | dw/table.cc | 180 | ||||
-rw-r--r-- | dw/table.hh | 25 | ||||
-rw-r--r-- | lout/debug.hh | 16 |
3 files changed, 187 insertions, 34 deletions
diff --git a/dw/table.cc b/dw/table.cc index b4366e51..35a40bbc 100644 --- a/dw/table.cc +++ b/dw/table.cc @@ -50,6 +50,7 @@ Table::Table(bool limitTextWidth) children = new misc::SimpleVector <Child*> (16); colExtremes = new misc::SimpleVector<core::Extremes> (8); + colWidthSpecified = new misc::SimpleVector<bool> (8); colWidths = new misc::SimpleVector <int> (8); cumHeight = new misc::SimpleVector <int> (8); rowSpanCells = new misc::SimpleVector <int> (8); @@ -60,6 +61,7 @@ Table::Table(bool limitTextWidth) DBG_OBJ_SET_BOOL ("colWidthsUpToDateWidthColExtremes", colWidthsUpToDateWidthColExtremes); + numColWidthSpecified = 0; redrawX = 0; redrawY = 0; } @@ -86,6 +88,7 @@ Table::~Table() delete children; delete colExtremes; + delete colWidthSpecified; delete colWidths; delete cumHeight; delete rowSpanCells; @@ -552,6 +555,9 @@ const char *Table::getExtrModName (ExtrMod mod) case MAX_INTR: return "MAX_INTR"; + case DATA: + return "DATA"; + default: misc::assertNotReached (); return NULL; @@ -580,7 +586,8 @@ int Table::getExtreme (core::Extremes *extremes, ExtrMod mod) return extremes->maxWidthIntrinsic; default: - misc::assertNotReached (); return 0; + misc::assertNotReached (); + return 0; } } @@ -610,6 +617,28 @@ void Table::setExtreme (core::Extremes *extremes, ExtrMod mod, int value) } } +int Table::getColExtreme (int col, ExtrMod mod, void *data) +{ + switch (mod) { + case DATA: + return ((misc::SimpleVector<int>*)data)->get (col); + + default: + return getExtreme (colExtremes->getRef(col), mod); + } +} + +void Table::setColExtreme (int col, ExtrMod mod, void *data, int value) +{ + switch (mod) { + case DATA: + ((misc::SimpleVector<int>*)data)->set (col, value); + + default: + setExtreme (colExtremes->getRef(col), mod, value); + } +} + void Table::reallocChildren (int newNumCols, int newNumRows) { assert (newNumCols >= numCols); @@ -729,8 +758,8 @@ void Table::forceCalcCellSizes (bool calcHeights) int minWidth = 0, maxWidth = 0; for (int col = 0; col < colExtremes->size(); col++) { - minWidth += getColExtreme (col, MIN); - maxWidth += getColExtreme (col, MAX); + minWidth += getColExtreme (col, MIN, NULL); + maxWidth += getColExtreme (col, MAX, NULL); } // CSS 'width' defined? @@ -755,7 +784,7 @@ void Table::forceCalcCellSizes (bool calcHeights) // incorrectly). apportion2 (totalWidth, 0, colExtremes->size() - 1, MIN_MIN, MAX_MIN, - colWidths, 0); + NULL, colWidths, 0); } else if (totalWidthSpecified && totalWidth > maxWidth) { DBG_OBJ_MSG ("resize", 1, "case 2: totalWidthSpecified && totalWidth < maxWidth"); @@ -767,14 +796,84 @@ void Table::forceCalcCellSizes (bool calcHeights) // maxima. This is done by simply passing MAX twice to the // apportioning function. - apportion2 (totalWidth, 0, colExtremes->size() - 1, MAX, MAX, colWidths, - 0); + // When column widths are specified (numColWidthSpecified > 0, + // as calculated in forceCalcColumnExtremes()), they are treated + // specially and excluded from the apportioning, so that the + // specified column widths are enforced. + + if (numColWidthSpecified == 0) { + DBG_OBJ_MSG ("resize", 1, + "subcase 2a: no columns with specified width"); + apportion2 (totalWidth, 0, colExtremes->size() - 1, MAX, MAX, NULL, + colWidths, 0); + } else { + DBG_OBJ_MSGF ("resize", 1, + "subcase 2b: %d columns with specified width", + numColWidthSpecified); + + // Seperate columns with specified and unspecified width, and + // apply apportion2() only to the latter. + + int numNotSpecified = colExtremes->size() - numColWidthSpecified; + + misc::SimpleVector<int> widthsNotSpecified (numNotSpecified); + widthsNotSpecified.setSize (numNotSpecified); + misc::SimpleVector<int> apportionDest (numNotSpecified); + + int totalWidthNotSpecified = totalWidth, indexNotSpecified = 0; + for (int col = 0; col < colExtremes->size(); col++) + if (colWidthSpecified->get (col)) + totalWidthNotSpecified -= getColExtreme (col, MAX, NULL); + else { + widthsNotSpecified.set (indexNotSpecified, + getColExtreme (col, MAX, NULL)); + indexNotSpecified++; + } + + DBG_IF_RTFL { + DBG_OBJ_MSGF ("resize", 1, "totalWidthNotSpecified = %d", + totalWidthNotSpecified); + + DBG_OBJ_MSG ("resize", 1, "widthsNotSpecified:"); + DBG_OBJ_MSG_START (); + + for (int i = 0; i < widthsNotSpecified.size (); i++) + DBG_OBJ_MSGF ("resize", 1, "#%d: %d", + i, widthsNotSpecified.get (i)); + + DBG_OBJ_MSG_END (); + } + + apportion2 (totalWidthNotSpecified, 0, numNotSpecified - 1, DATA, DATA, + (void*)&widthsNotSpecified, &apportionDest, 0); + + DBG_IF_RTFL { + DBG_OBJ_MSG ("resize", 1, "apportionDest:"); + DBG_OBJ_MSG_START (); + + for (int i = 0; i < apportionDest.size (); i++) + DBG_OBJ_MSGF ("resize", 1, "#%d: %d", i, apportionDest.get (i)); + + DBG_OBJ_MSG_END (); + } + + colWidths->setSize (colExtremes->size()); + indexNotSpecified = 0; + for (int col = 0; col < colExtremes->size(); col++) + if (colWidthSpecified->get (col)) + colWidths->set (col, getColExtreme (col, MAX, NULL)); + else { + colWidths->set (col, apportionDest.get (indexNotSpecified)); + indexNotSpecified++; + } + } } else { // Normal apportioning. int width = totalWidthSpecified ? totalWidth : misc::min (totalWidth, maxWidth); DBG_OBJ_MSGF ("resize", 1, "case 3: else; width = %d", width); - apportion2 (width, 0, colExtremes->size() - 1, MIN, MAX, colWidths, 0); + apportion2 (width, 0, colExtremes->size() - 1, MIN, MAX, NULL, colWidths, + 0); } // TODO: Adapted from old inline function "setColWidth". But (i) is @@ -938,12 +1037,15 @@ void Table::forceCalcColumnExtremes () if (numCols > 0) { lout::misc::SimpleVector<int> colSpanCells (8); colExtremes->setSize (numCols); + colWidthSpecified->setSize (numCols); // 1. cells with colspan = 1 for (int col = 0; col < numCols; col++) { DBG_OBJ_MSGF ("resize", 1, "column %d", col); DBG_OBJ_MSG_START (); + colWidthSpecified->set (col, false); + colExtremes->getRef(col)->minWidth = 0; colExtremes->getRef(col)->minWidthIntrinsic = 0; colExtremes->getRef(col)->maxWidth = 0; @@ -979,6 +1081,10 @@ void Table::forceCalcColumnExtremes () colExtremes->getRef(col)->maxWidth, cellExtremes.maxWidth); + if (children->get(n)->cell.widget->getStyle()->width + != core::style::LENGTH_AUTO) + colWidthSpecified->set (col, true); + DBG_OBJ_MSGF ("resize", 1, "column: %d / %d (%d / %d)", colExtremes->getRef(col)->minWidth, colExtremes->getRef(col)->maxWidth, @@ -1009,13 +1115,26 @@ void Table::forceCalcColumnExtremes () core::Extremes cellExtremes; children->get(n)->cell.widget->getExtremes (&cellExtremes); - calcExtremesSpanMulteCols (col, cs, &cellExtremes, MIN, MAX); - calcExtremesSpanMulteCols (col, cs, &cellExtremes, MIN_INTR, MAX_INTR); + calcExtremesSpanMulteCols (col, cs, &cellExtremes, MIN, MAX, NULL); + calcExtremesSpanMulteCols (col, cs, &cellExtremes, MIN_INTR, MAX_INTR, + NULL); + + if (children->get(n)->cell.widget->getStyle()->width + != core::style::LENGTH_AUTO) + for (int j = 0; j < cs; j++) + colWidthSpecified->set (col + j, true); } } + numColWidthSpecified = 0; + for (int i = 0; i < colExtremes->size (); i++) + if (colWidthSpecified->get (i)) + numColWidthSpecified++; + DBG_IF_RTFL { DBG_OBJ_SET_NUM ("colExtremes.size", colExtremes->size ()); + DBG_OBJ_SET_NUM ("colWidthSpecified.size", colWidthSpecified->size ()); + for (int i = 0; i < colExtremes->size (); i++) { DBG_OBJ_ARRATTRSET_NUM ("colExtremes", i, "minWidth", colExtremes->get(i).minWidth); @@ -1026,6 +1145,12 @@ void Table::forceCalcColumnExtremes () DBG_OBJ_ARRATTRSET_NUM ("colExtremes", i, "maxWidthIntrinsic", colExtremes->get(i).maxWidthIntrinsic); } + + for (int i = 0; i < colWidthSpecified->size (); i++) + DBG_OBJ_ARRSET_BOOL ("colWidthSpecified", i, + colWidthSpecified->get(i)); + + DBG_OBJ_SET_NUM ("numColWidthSpecified", numColWidthSpecified); } colWidthsUpToDateWidthColExtremes = false; @@ -1037,10 +1162,11 @@ void Table::forceCalcColumnExtremes () void Table::calcExtremesSpanMulteCols (int col, int cs, core::Extremes *cellExtremes, - ExtrMod minExtrMod, ExtrMod maxExtrMod) + ExtrMod minExtrMod, ExtrMod maxExtrMod, + void *extrData) { DBG_OBJ_ENTER ("resize", 0, "calcExtremesSpanMulteCols", - "%d, %d, ..., %s, %s", + "%d, %d, ..., %s, %s, ...", col, cs, getExtrModName (minExtrMod), getExtrModName (maxExtrMod)); @@ -1050,8 +1176,8 @@ void Table::calcExtremesSpanMulteCols (int col, int cs, int minSumCols = 0, maxSumCols = 0; for (int j = 0; j < cs; j++) { - minSumCols += getColExtreme (col + j, minExtrMod); - maxSumCols += getColExtreme (col + j, maxExtrMod); + minSumCols += getColExtreme (col + j, minExtrMod, extrData); + maxSumCols += getColExtreme (col + j, maxExtrMod, extrData); } DBG_OBJ_MSGF ("resize", 1, "cs = %d, cell: %d / %d, sum: %d / %d\n", @@ -1063,20 +1189,22 @@ void Table::calcExtremesSpanMulteCols (int col, int cs, // 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); + apportion2 (cellMin, col, col + cs - 1, MIN, MAX, NULL, &newMin, 0); if (changeMax) - apportion2 (cellMax, col, col + cs - 1, MIN, MAX, &newMax, 0); + apportion2 (cellMax, col, col + cs - 1, MIN, MAX, NULL, &newMax, 0); for (int j = 0; j < cs; j++) { if (changeMin) - setColExtreme (col + j, minExtrMod, newMin.get (j)); + setColExtreme (col + j, minExtrMod, extrData, newMin.get (j)); if (changeMax) - setColExtreme (col + j, maxExtrMod, newMax.get (j)); + setColExtreme (col + j, maxExtrMod, extrData, 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))); + setColExtreme (col + j, maxExtrMod, extrData, + misc::max (getColExtreme (col + j, minExtrMod, + extrData), + getColExtreme (col + j, maxExtrMod, + extrData))); } } @@ -1087,7 +1215,7 @@ void Table::calcExtremesSpanMulteCols (int col, int cs, * \brief Actual apportionment function. */ void Table::apportion2 (int totalWidth, int firstCol, int lastCol, - ExtrMod minExtrMod, ExtrMod maxExtrMod, + ExtrMod minExtrMod, ExtrMod maxExtrMod, void *extrData, misc::SimpleVector<int> *dest, int destOffset) { DBG_OBJ_ENTER ("resize", 0, "apportion2", "%d, %d, %d, %s, %s, ..., %d", @@ -1099,8 +1227,8 @@ void Table::apportion2 (int totalWidth, int firstCol, int lastCol, int totalMin = 0, totalMax = 0; for (int col = firstCol; col <= lastCol; col++) { - totalMin += getColExtreme (col, minExtrMod); - totalMax += getColExtreme (col, maxExtrMod); + totalMin += getColExtreme (col, minExtrMod, extrData); + totalMax += getColExtreme (col, maxExtrMod, extrData); } DBG_OBJ_MSGF ("resize", 1, @@ -1157,8 +1285,8 @@ void Table::apportion2 (int totalWidth, int firstCol, int lastCol, int cumDiffExtr = 0, cumDiffWidth = 0; for (int col = firstCol; col <= lastCol; col++) { - int min = getColExtreme (col, minExtrMod); - int max = getColExtreme (col, maxExtrMod); + int min = getColExtreme (col, minExtrMod, extrData); + int max = getColExtreme (col, maxExtrMod, extrData); int diffExtr = max - min; cumDiffExtr += diffExtr; @@ -1180,7 +1308,7 @@ void Table::apportion2 (int totalWidth, int firstCol, int lastCol, int cumMin = 0, cumWidth = 0; for (int col = firstCol; col <= lastCol; col++) { - int min = getColExtreme (col, minExtrMod); + int min = getColExtreme (col, minExtrMod, extrData); cumMin += min; int width = (cumMin * totalWidth) / totalMin - cumWidth; cumWidth += width; diff --git a/dw/table.hh b/dw/table.hh index b9dae75d..903b73d1 100644 --- a/dw/table.hh +++ b/dw/table.hh @@ -374,6 +374,17 @@ private: lout::misc::SimpleVector<core::Extremes> *colExtremes; /** + * \brief Wether the column itself (in the future?) or at least one + * cell in this column or spanning over this column has CSS + * 'width' specified. + * + * Filled by forceCalcColumnExtremes(), since it is needed to + * calculate the column widths. + */ + lout::misc::SimpleVector<bool> *colWidthSpecified; + int numColWidthSpecified; + + /** * \brief The widths of all columns. */ lout::misc::SimpleVector<int> *colWidths; @@ -394,16 +405,13 @@ private: bool colWidthsUpToDateWidthColExtremes; - enum ExtrMod { MIN, MIN_INTR, MIN_MIN, MAX_MIN, MAX, MAX_INTR }; + enum ExtrMod { MIN, MIN_INTR, MIN_MIN, MAX_MIN, MAX, MAX_INTR, DATA }; 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); } + int getColExtreme (int col, ExtrMod mod, void *data); + inline void setColExtreme (int col, ExtrMod mod, void *data, int value); inline bool childDefined(int n) { @@ -423,10 +431,11 @@ private: void forceCalcColumnExtremes (); void calcExtremesSpanMulteCols (int col, int cs, core::Extremes *cellExtremes, - ExtrMod minExtrMod, ExtrMod maxExtrMod); + ExtrMod minExtrMod, ExtrMod maxExtrMod, + void *extrData); void apportion2 (int totalWidth, int firstCol, int lastCol, - ExtrMod minExtrMod, ExtrMod maxExtrMod, + ExtrMod minExtrMod, ExtrMod maxExtrMod, void *extrData, lout::misc::SimpleVector<int> *dest, int destOffset); void setCumHeight (int row, int value) diff --git a/lout/debug.hh b/lout/debug.hh index d4e545a2..432707db 100644 --- a/lout/debug.hh +++ b/lout/debug.hh @@ -266,6 +266,13 @@ fflush (stdout); \ } D_STMT_END +#define DBG_OBJ_ARRSET_BOOL(var, ind, val) \ + D_STMT_START { \ + printf (RTFL_PREFIX_FMT "obj-set:%p:%s.%d:%s\n", \ + RTFL_PREFIX_ARGS, this, var, ind, val ? "true" : "false"); \ + fflush (stdout); \ + } D_STMT_END + #define DBG_OBJ_ARRSET_STR(var, ind, val) \ D_STMT_START { \ printf (RTFL_PREFIX_FMT "obj-set:%p:%s.%d:\"%s\"\n", \ @@ -294,6 +301,13 @@ fflush (stdout); \ } D_STMT_END +#define DBG_OBJ_ARRATTRSET_BOOL(var, ind, attr, val) \ + D_STMT_START { \ + printf (RTFL_PREFIX_FMT "obj-set:%p:%s.%d.%s:%s\n", \ + RTFL_PREFIX_ARGS, this, var, ind, attr, val ? "true" : "false"); \ + fflush (stdout); \ + } D_STMT_END + #define DBG_OBJ_ARRATTRSET_STR(var, ind, attr, val) \ D_STMT_START { \ printf (RTFL_PREFIX_FMT "obj-set:%p:%s.%d.%s:\"%s\"\n", \ @@ -351,10 +365,12 @@ #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_ARRSET_BOOL(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_ARRATTRSET_BOOL(var, ind, attr, val) D_STMT_NOP #define DBG_OBJ_COLOR(klass, color) D_STMT_NOP #endif /* DBG_RTFL */ |