27 #ifndef EMP_WEB_TABLE_H 28 #define EMP_WEB_TABLE_H 30 #include "../base/vector.h" 62 bool OK(std::stringstream & ss,
bool verbose=
false,
const std::string & prefix=
"") {
64 if (verbose) ss << prefix <<
"Scanning: emp::TableDataInfo" <<
std::endl;
65 if (masked) { ss <<
"Warning: Masked cell may have contents!" <<
std::endl; ok =
false; }
76 template <
typename SETTING_TYPE>
83 template <
typename SETTING_TYPE>
85 data[col_id].extras.style.Set(setting, value);
90 bool OK(std::stringstream & ss,
bool verbose=
false,
const std::string & prefix=
"") {
92 if (verbose) { ss << prefix <<
"Scanning: emp::TableRowInfo" <<
std::endl; }
93 for (
auto & cell : data) ok = ok && cell.OK(ss, verbose, prefix+
" ");
122 : internal::
WidgetInfo(in_id), row_count(0), col_count(0), append_row(0), append_col(0) { ; }
127 std::string
TypeName()
const override {
return "TableInfo"; }
130 void Resize(
size_t new_rows,
size_t new_cols) {
132 if (new_cols != col_count) {
133 for (
size_t r = 0; r < rows.
size() && r < new_rows; r++) {
134 rows[r].data.
resize(new_cols);
135 for (
size_t c = col_count; c < new_cols; c++) { AddChild(r, c,
Text(
"")); }
137 col_count = new_cols;
141 if (col_groups.
size()) col_groups.
resize(new_cols);
145 if (new_rows != row_count) {
147 for (
size_t r = row_count; r < new_rows; r++) {
148 rows[r].data.
resize(col_count);
149 for (
size_t c = 0; c < col_count; c++) { AddChild(r, c,
Text(
"")); }
151 row_count = new_rows;
154 if (row_groups.
size()) row_groups.
resize(new_rows);
161 for (
size_t r = 0; r < row_count; r++) {
162 for (
size_t c = 0; c < col_count; c++) {
163 for (
auto & child : rows[r].
data[c].
children) child->DoActivate(
false);
174 auto & cell_children = rows[r].data[c].children;
176 if (cell_children.size() == 0
177 || cell_children.back().IsText() ==
false 178 || cell_children.back().AppendOK() ==
false) {
181 return (
Text &) cell_children.back();
186 if (append_row >= row_count) append_row = 0;
187 if (append_col >= col_count) append_col = 0;
189 return GetTextWidget(append_row, append_col);
194 Widget Append(
const std::string & text)
override {
return GetTextWidget() << text; }
196 return GetTextWidget() << in_fun;
201 emp_assert(in->
parent ==
nullptr &&
"Cannot insert widget if already has parent!", in->
id);
214 parent_id = Pointer_stringify($0);
215 child_id = Pointer_stringify($1);
216 $(
'#' + parent_id).append(
'<span id="' + child_id +
'"></span>');
217 }, cell_id.c_str(), in.
GetID().c_str());
227 if (append_row >= row_count) append_row = 0;
228 if (append_col >= col_count) append_col = 0;
230 AddChild(append_row, append_col, in);
237 for (
size_t r = 0; r < row_count; r++) {
238 for (
size_t c = 0; c < col_count; c++) {
245 for (
size_t r = 0; r < row_count; r++) {
246 for (
size_t c = 0; c < col_count; c++) {
252 virtual void GetHTML(std::stringstream & HTML)
override {
257 HTML <<
"<table id=\"" <<
id <<
"\">";
260 const bool use_colg = col_groups.
size();
261 const bool use_cols = cols.
size();
262 const bool use_rowg = row_groups.
size();
264 if (use_colg || use_cols) {
265 for (
size_t c = 0; c < col_count; ++c) {
266 if (use_colg && col_groups[c].
masked ==
false) {
268 if (col_groups[c].
extras) HTML <<
" id=" <<
id <<
"_cg" << c;
272 if (use_cols && cols[c].
extras) HTML <<
" id=" <<
id <<
"_c" << c;
278 for (
size_t r = 0; r < rows.
size(); r++) {
279 if (use_rowg && row_groups[r].
masked ==
false) {
281 if (row_groups[r].
extras) HTML <<
" id=" <<
id <<
"_rg" << r;
285 auto & row = rows[r];
287 if (row.extras) HTML <<
" id=" <<
id <<
'_' << r;
291 for (
size_t c = 0; c < row.data.size(); c++) {
292 auto & datum = row.data[c];
293 if (datum.masked)
continue;
296 HTML << (datum.header ?
"<th" :
"<td");
299 if (datum.extras) HTML <<
" id=" <<
id <<
'_' << r <<
'_' << c;
302 if (datum.colspan > 1) HTML <<
" colspan=\"" << datum.colspan <<
"\"";
303 if (datum.rowspan > 1) HTML <<
" rowspan=\"" << datum.rowspan <<
"\"";
308 for (
Widget & w : datum.children) {
309 HTML <<
"<span id=\'" << w.
GetID() <<
"'></span>";
313 HTML << (datum.header ?
"</th>" :
"</td>");
324 auto & datum = rows[row_id].data[col_id];
325 if (parent)
for (
Widget & child : datum.children) parent->Unregister(child);
329 for (
size_t col_id = 0; col_id < col_count; col_id++) ClearCellChildren(row_id, col_id);
332 for (
size_t row_id = 0; row_id < row_count; row_id++) ClearCellChildren(row_id, col_id);
335 for (
size_t offset=0; offset < row_groups[row_id].span; offset++) {
336 ClearRowChildren(row_id+offset);
340 for (
size_t offset=0; offset < col_groups[col_id].span; offset++) {
341 ClearColChildren(col_id+offset);
345 for (
size_t col_id = 0; col_id < col_count; col_id++) {
346 for (
size_t row_id = 0; row_id < row_count; row_id++) {
347 ClearCellChildren(row_id, col_id);
353 auto & datum = rows[row_id].data[col_id];
356 datum.header =
false;
357 datum.masked =
false;
358 datum.extras.Clear();
360 ClearCellChildren(row_id, col_id);
363 for (
size_t col_id = 0; col_id < col_count; col_id++) ClearCell(row_id, col_id);
366 for (
size_t row_id = 0; row_id < row_count; row_id++) ClearCell(row_id, col_id);
369 rows[row_id].extras.Clear();
370 ClearRowCells(row_id);
373 cols[col_id].extras.Clear();
374 ClearColCells(col_id);
377 row_groups[row_id].extras.Clear();
378 for (
size_t offset=0; offset < row_groups[row_id].span; offset++) ClearRow(row_id+offset);
381 col_groups[col_id].extras.Clear();
382 for (
size_t offset=0; offset < col_groups[col_id].span; offset++) ClearCol(col_id+offset);
389 bool OK(std::stringstream & ss,
bool verbose=
false,
const std::string & prefix=
"") {
394 ss << prefix <<
"Scanning: emp::TableInfo (rows=" << row_count
395 <<
", cols=" << col_count <<
")." <<
std::endl;
399 if (row_count != rows.
size()) {
400 ss << prefix <<
"Error: row_count = " << row_count
401 <<
", but rows has " << rows.
size() <<
" elements." <<
std::endl;
405 if (cols.
size() && col_count != cols.
size()) {
406 ss << prefix <<
"Error: col_count = " << col_count
407 <<
", but cols has " << cols.
size() <<
" elements." <<
std::endl;
412 ss << prefix <<
"Error: Cannot have " << row_count
418 ss << prefix <<
"Error: Cannot have " << col_count
424 if (col_groups.
size() && col_count != col_groups.
size()) {
425 ss << prefix <<
"Error: col_count = " << col_count
426 <<
", but col_groups has " << col_groups.
size() <<
" elements." <<
std::endl;
430 if (row_groups.
size() && row_count != row_groups.
size()) {
431 ss << prefix <<
"Error: row_count = " << row_count
432 <<
", but row_groups has " << row_groups.
size() <<
" elements." <<
std::endl;
437 for (
size_t r = 0; r < row_count; r++) {
438 ok = ok && rows[r].OK(ss, verbose, prefix+
" ");
439 if (col_count != rows[r].
data.
size()) {
440 ss << prefix <<
" Error: col_count = " << col_count
441 <<
", but row has " << rows[r].data.
size() <<
" elements." <<
std::endl;
444 for (
size_t c = 0; c < col_count; c++) {
445 auto & cell = rows[r].data[c];
446 if (c + cell.colspan > col_count) {
447 ss << prefix <<
" Error: Cell at row " << r <<
", col " << c
448 <<
" extends past right side of table." <<
std::endl;
451 if (r + cell.rowspan > row_count) {
452 ss << prefix <<
" Error: Cell at row " << r <<
", col " << c
453 <<
" extends past bottom of table." <<
std::endl;
471 for (
size_t r = 0; r < row_count; r++) {
473 for (
size_t c = 0; c < col_count; c++) {
474 auto & datum = rows[r].data[c];
475 if (datum.masked)
continue;
480 for (
auto & child : datum.children) child->ReplaceHTML();
487 for (
size_t c = 0; c < col_count; c++) {
488 if (!cols[c].
extras)
continue;
492 if (col_groups.
size()) {
493 for (
size_t c = 0; c < col_count; c++) {
494 if (col_groups[c].
masked || !col_groups[c].
extras)
continue;
498 if (row_groups.
size()) {
499 for (
size_t c = 0; c < col_count; c++) {
500 if (row_groups[c].
masked || !row_groups[c].
extras)
continue;
507 virtual std::string
GetType()
override {
return "web::TableInfo"; }
526 : WidgetFacet(in_info), cur_row(_row), cur_col(_col) { ; }
529 void DoCSS(
const std::string & setting,
const std::string & value)
override {
530 parent_t::DoCSS(setting, value);
534 void DoAttr(
const std::string & setting,
const std::string & value)
override {
535 parent_t::DoAttr(setting, value);
539 void DoListen(
const std::string & event_name,
size_t fun_id)
override {
540 parent_t::DoListen(event_name, fun_id);
545 : WidgetFacet(in_id), cur_row(0), cur_col(0)
549 Info()->Resize(r, c);
552 : WidgetFacet(in), cur_row(in.cur_row), cur_col(in.cur_col) { ; }
567 Info()->append_row = cur_row;
568 Info()->append_col = cur_col;
598 Widget AddText(
size_t r,
size_t c,
const std::string & text);
601 Widget AddHeader(
size_t r,
size_t c,
const std::string & text);
603 using parent_t::SetCSS;
606 std::string
GetCSS(
const std::string & setting)
override {
607 return Info()->extras.GetStyle(setting);
611 virtual bool OK(std::stringstream & ss,
bool verbose=
false,
const std::string & prefix=
"") {
616 ss << prefix <<
"Scanning: emp::Table (rows=" <<
Info()->row_count
621 if (cur_row >=
Info()->row_count) {
622 ss << prefix <<
"Error: cur_row = " << cur_row <<
"." <<
std::endl;
626 if (cur_col >=
Info()->col_count) {
627 ss << prefix <<
"Error: cur_col = " << cur_col <<
"." <<
std::endl;
632 ok = ok &&
Info()->OK(ss, verbose, prefix+
" ");
656 Info()->Resize(r,
Info()->col_count);
657 if (cur_row >= r) cur_row = 0;
663 Info()->Resize(
Info()->row_count, c);
664 if (cur_col >= c) cur_col = 0;
670 Info()->Resize(r, c);
671 if (cur_row >= r) cur_row = 0;
672 if (cur_col >= c) cur_col = 0;
678 emp_assert((cur_col + new_span <= GetNumCols()) &&
"Col span too wide for table!",
679 cur_col, new_span, GetNumCols(), GetID());
682 if (
Info()->col_groups.size() == 0)
Info()->col_groups.resize(GetNumCols());
684 const size_t old_span =
Info()->col_groups[cur_col].span;
685 Info()->col_groups[cur_col].span = new_span;
687 if (old_span != new_span) {
688 for (
size_t i=old_span; i<new_span; i++) {
Info()->col_groups[cur_col+i].masked =
true; }
689 for (
size_t i=new_span; i<old_span; i++) {
Info()->col_groups[cur_col+i].masked =
false; }
693 if (IsActive())
Info()->ReplaceHTML();
699 template <
typename SETTING_TYPE>
700 Table &
RowCSS(
size_t row_id,
const std::string & setting, SETTING_TYPE && value) {
702 Info()->rows[row_id].extras.style.Set(setting, value);
703 if (IsActive())
Info()->ReplaceHTML();
708 template <
typename SETTING_TYPE>
709 Table &
CellCSS(
size_t row_id,
size_t col_id,
const std::string & setting, SETTING_TYPE && value) {
712 Info()->rows[row_id].extras.style.Set(setting, value);
713 if (IsActive())
Info()->ReplaceHTML();
718 template <
typename SETTING_TYPE>
721 if (IsActive())
Info()->ReplaceHTML();
726 template <
typename SETTING_TYPE>
729 if (IsActive())
Info()->ReplaceHTML();
750 r, c,
Info()->row_count,
Info()->col_count, GetID());
779 GetCell(r,c) << text;
Table & SetColSpan(size_t new_span)
Setup the number of columns the current column group.
Definition: Table.h:677
void UnregisterChildren(internal::DivInfo *regestrar) override
Definition: Table.h:244
WidgetExtras extras
Extra annotations (attributes, style, listeners)
Definition: Table.h:73
void ClearColCells(size_t col_id)
Definition: Table.h:365
WidgetExtras extras
Is the current group masked because of a previous span?
Definition: Table.h:104
A Text widget handles putting text on a web page that can be controlled and modified.
Definition: Text.h:27
size_t append_row
Detail object for each row group (if needed)
Definition: Table.h:118
Table & Resize(size_t r, size_t c)
Fully resize the table (both rows and columns)
Definition: Table.h:669
TableRowInfo & CellCSS(size_t col_id, const std::string &setting, SETTING_TYPE &&value)
Apply CSS to specific cell in row.
Definition: Table.h:84
Table(const TableWidget &in)
Definition: Table.h:641
Widget Append(Widget in) override
Definition: Table.h:193
The TableCol widget, which behaves like the Table widget, but focuses on a single column...
The TableRowGoup widget, which behaves like the Table widget, but focuses on a group of rows...
void ClearRow(size_t row_id)
Definition: Table.h:368
void ClearTableChildren()
Definition: Table.h:344
std::string to_string(ALL_TYPES &&...all_values)
Definition: string_utils.h:511
Table & ClearStyle()
Definition: Table.h:648
void Unregister(Widget &old_widget) override
Definition: Div.h:110
Table & CellsCSS(const std::string &setting, SETTING_TYPE &&value)
Apply CSS to all cells.
Definition: Table.h:727
void AddChild(Widget in)
Definition: Table.h:225
Table & ClearExtras()
Definition: Table.h:651
bool header
Is this TableData a header (vs )?
Definition: Table.h:55
void ClearTable()
Definition: Table.h:387
void ClearRowChildren(size_t row_id)
Definition: Table.h:328
size_t row_count
Definition: Table.h:111
Table(internal::TableInfo *in_info, size_t _row, size_t _col)
Definition: Table.h:643
The TableColGoup widget, which behaves like the Table widget, but focuses on a group of columns...
Include information (name, keyword, description) for each instance.
void ClearColGroupChildren(size_t col_id)
Definition: Table.h:339
Style & Set(const std::string &s, SET_TYPE v)
Record that setting "s" is set to value "v" (converted to string) and return this object...
Definition: Style.h:50
virtual bool IsTableInfo() const override
Definition: Table.h:128
void ClearRowGroup(size_t row_id)
Definition: Table.h:376
An object that focuses on a group of columns in a specified table.
Definition: _TableColGroup.h:19
size_t colspan
How many columns wide is this TableData?
Definition: Table.h:53
void AddChild(size_t r, size_t c, Widget in)
Definition: Table.h:200
virtual ~TableInfo()
Definition: Table.h:125
TableInfo(const std::string &in_id="")
Which col is triggering an append?
Definition: Table.h:121
virtual std::string GetType() override
Definition: Table.h:507
An object that focuses on a single cell in a specified table.
Definition: _TableCell.h:19
data
A set of modifiers are available do describe DataNode.
Definition: DataNode.h:38
Table & ClearAttr()
Definition: Table.h:649
size_t size() const
Definition: vector.h:151
WidgetExtras extras
Extra annotations (attributes, style, listeners)
Definition: Table.h:57
void emplace_back(ARGS &&...args)
Definition: vector.h:219
void RegisterChildren(internal::DivInfo *regestrar) override
Definition: Table.h:236
Table & ClearChildren()
Definition: Table.h:652
emp::vector< Widget > children
Widgets contained in this cell.
Definition: Table.h:59
WidgetExtras extras
Definition: Table.h:98
An object that focuses on a single column in a specified table.
Definition: _TableRow.h:19
bool OK(std::stringstream &ss, bool verbose=false, const std::string &prefix="")
Debug function to determine if this datum is structually consistent.
Definition: Table.h:62
Table & CellCSS(size_t row_id, size_t col_id, const std::string &setting, SETTING_TYPE &&value)
Apply CSS to target cell.
Definition: Table.h:709
size_t rowspan
How many rows deep is this TableData?
Definition: Table.h:54
emp::vector< TableRowInfo > rows
Definition: Table.h:113
emp::vector< TableGroupInfo > col_groups
Detail object for each column (if needed)
Definition: Table.h:115
Table & RowCSS(size_t row_id, const std::string &setting, SETTING_TYPE &&value)
Apply CSS to target row.
Definition: Table.h:700
static const PrintStr endl("<br>")
Pre-define emp::endl to insert a "<br>" and thus acting like a newline.
The TableCell widget, which behaves like the Table widget, but focuses on a single cell...
Widget Append(const std::string &text) override
Definition: Table.h:194
Div Widgets maintain an ordered collection of other widgets in an HTML div.
bool OK(std::stringstream &ss, bool verbose=false, const std::string &prefix="")
Definition: Table.h:389
TableCell & SetHeader(bool _h=true)
Definition: _TableCell.h:58
web::Text & GetTextWidget()
Definition: Table.h:184
virtual void GetHTML(std::stringstream &HTML) override
Definition: Table.h:252
void resize(size_t new_size)
Definition: vector.h:161
The TableRow widget, which behaves like the Table widget, but focuses on a single row...
Table()
Definition: Table.h:645
An object that focuses on a group of rows in a specified table.
Definition: _TableRowGroup.h:19
Widget Append(const std::function< std::string()> &in_fun) override
Definition: Table.h:195
Table & Rows(size_t r)
Resize the number of rows in the table.
Definition: Table.h:655
void Resize(size_t new_rows, size_t new_cols)
Definition: Table.h:130
std::string TypeName() const override
Debugging helpers...
Definition: Table.h:127
TableRowInfo & CellsCSS(const std::string &setting, SETTING_TYPE &&value)
Apply CSS to all cells in row.
Definition: Table.h:77
If we are in emscripten, make sure to include the header.
Definition: array.h:37
void ClearCol(size_t col_id)
Definition: Table.h:372
Table(size_t r, size_t c, const std::string &in_id="")
Definition: Table.h:640
Build a debug wrapper emp::vector around std::vector.
Definition: vector.h:42
bool OK(std::stringstream &ss, bool verbose=false, const std::string &prefix="")
Debug function to determine if this row is structually consistent.
Definition: Table.h:90
Table & Cols(size_t c)
Resize the number of columns in the table.
Definition: Table.h:662
An object that focuses on a single column in a specified table.
Definition: _TableCol.h:19
#define emp_assert(...)
Definition: assert.h:199
emp::vector< TableColInfo > cols
Detail object for each row.
Definition: Table.h:114
emp::vector< TableGroupInfo > row_groups
Detail object for each column group (if needed)
Definition: Table.h:116
void Register(Widget &new_widget) override
Definition: Div.h:95
Table & RowsCSS(const std::string &setting, SETTING_TYPE &&value)
Apply CSS to all rows. (: Should we use fancier jquery here?)
Definition: Table.h:719
emp::vector< TableDataInfo > data
detail object for each cell in this row.
Definition: Table.h:72
void ClearColChildren(size_t col_id)
Definition: Table.h:331
Table & Clear()
Definition: Table.h:647
bool masked
Is this cell masked by another cell?
Definition: Table.h:56
void ClearCell(size_t row_id, size_t col_id)
Definition: Table.h:352
void ClearCellChildren(size_t row_id, size_t col_id)
Definition: Table.h:322
void ClearRowGroupChildren(size_t row_id)
Definition: Table.h:334
void ClearTableCells()
Definition: Table.h:385
size_t col_count
How big is this table?
Definition: Table.h:112
size_t append_col
Which row is triggering an append?
Definition: Table.h:119
void ReplaceHTML() override
Definition: Table.h:462
void ClearColGroup(size_t col_id)
Definition: Table.h:380
void ClearTableRows()
Definition: Table.h:386
void DoActivate(bool top_level=true) override
Definition: Table.h:159
Table(const Widget &in)
Definition: Table.h:642
Table & ClearListen()
Definition: Table.h:650
web::Text & GetTextWidget(size_t r, size_t c)
Definition: Table.h:173
void ClearRowCells(size_t row_id)
Definition: Table.h:362