private void encodeTableBody()

in tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SheetRenderer.java [438:691]


  private void encodeTableBody(
      final FacesContext facesContext, final AbstractUISheet sheet,
      final TobagoResponseWriter writer, final String sheetId, final Selectable selectable,
      final List<Integer> columnWidths, final List<Integer> selectedRows, final List<AbstractUIColumnBase> columns,
      final boolean autoLayout, final List<Integer> expandedValue) throws IOException {

    final boolean showHeader = sheet.isShowHeader();
    final Markup sheetMarkup = sheet.getMarkup() != null ? sheet.getMarkup() : Markup.NULL;

    boolean nonLazyUpdate = !sheet.isLazyUpdate(facesContext);
    if (nonLazyUpdate) {
      final UIComponent before = sheet.getFacet(Facets.BEFORE);
      if (before != null) {
        before.encodeAll(facesContext);
      }

      if (showHeader && !autoLayout) {
        // if no autoLayout, we render the header in a separate table.
        writer.startElement(HtmlElements.HEADER);
        writer.startElement(HtmlElements.TABLE);
        writer.writeAttribute(HtmlAttributes.CELLSPACING, "0", false);
        writer.writeAttribute(HtmlAttributes.CELLPADDING, "0", false);
        writer.writeAttribute(HtmlAttributes.SUMMARY, "", false);
        writer.writeClassAttribute(
            BootstrapClass.TABLE,
            sheetMarkup.contains(Markup.DARK) ? BootstrapClass.TABLE_DARK : null,
            sheetMarkup.contains(Markup.BORDERED) ? BootstrapClass.TABLE_BORDERED : null,
            sheetMarkup.contains(Markup.SMALL) ? BootstrapClass.TABLE_SM : null,
            TobagoClass.TABLE_LAYOUT__FIXED);

        writeColgroup(facesContext, sheet, writer, columnWidths, columns, true);
        writer.startElement(HtmlElements.THEAD);
        encodeHeaderRows(facesContext, sheet, writer, columns);
        writer.endElement(HtmlElements.THEAD);
        writer.endElement(HtmlElements.TABLE);

        writer.startElement(HtmlElements.DIV);
        writer.writeClassAttribute(TobagoClass.SCROLLBAR__FILLER,
            BootstrapClass.TABLE,
            sheetMarkup.contains(Markup.DARK) ? BootstrapClass.TABLE_DARK : null,
            sheetMarkup.contains(Markup.BORDERED) ? BootstrapClass.TABLE_BORDERED : null);
        writer.endElement(HtmlElements.DIV);
        writer.endElement(HtmlElements.HEADER);
      }
    }
    writer.startElement(HtmlElements.DIV);
    writer.writeClassAttribute(TobagoClass.BODY);

    writer.startElement(HtmlElements.TABLE);
    writer.writeAttribute(HtmlAttributes.CELLSPACING, "0", false);
    writer.writeAttribute(HtmlAttributes.CELLPADDING, "0", false);
    writer.writeAttribute(HtmlAttributes.SUMMARY, "", false);
    writer.writeClassAttribute(
        BootstrapClass.TABLE,
        sheetMarkup.contains(Markup.DARK) ? BootstrapClass.TABLE_DARK : null,
        sheetMarkup.contains(Markup.STRIPED) ? BootstrapClass.TABLE_STRIPED : null,
        sheetMarkup.contains(Markup.BORDERED) ? BootstrapClass.TABLE_BORDERED : null,
        sheetMarkup.contains(Markup.HOVER) ? BootstrapClass.TABLE_HOVER : null,
        sheetMarkup.contains(Markup.SMALL) ? BootstrapClass.TABLE_SM : null,
        !autoLayout ? TobagoClass.TABLE_LAYOUT__FIXED : null);

    if (nonLazyUpdate) {
      if (showHeader && autoLayout) {
        writer.startElement(HtmlElements.THEAD);
        encodeHeaderRows(facesContext, sheet, writer, columns);
        writer.endElement(HtmlElements.THEAD);
      }
      if (!autoLayout) {
        writeColgroup(facesContext, sheet, writer, columnWidths, columns, false);
      }
    }
    // Print the Content
    if (LOG.isDebugEnabled()) {
      LOG.debug("first = " + sheet.getFirst() + "   rows = " + sheet.getRows());
    }
    writer.startElement(HtmlElements.TBODY);

    final String var = sheet.getVar();

    boolean emptySheet = true;
    // rows = 0 means: show all
    final int first = sheet.isLazy() ? sheet.getLazyFirstRow() : sheet.getFirst();
    final int last = sheet.isLazy() ? sheet.getLazyFirstRow() + sheet.getLazyRows()
        : sheet.isRowsUnlimited() ? Integer.MAX_VALUE : sheet.getFirst() + sheet.getRows();

    AbstractUIRow row = null;
    boolean[] columnRendered = new boolean[columns.size()];
    for (int i = 0; i < columns.size(); i++) {
      UIColumn column = columns.get(i);
      if (column.isRendered()) {
        columnRendered[i] = true;
        if (column instanceof AbstractUIRow) {
          row = (AbstractUIRow) column;
          // todo: Markup.CLICKABLE ???
        }
      }
    }

    for (int rowIndex = first; rowIndex < last; rowIndex++) {
      sheet.setRowIndex(rowIndex);
      if (!sheet.isRowAvailable()) {
        break;
      }

      final Object rowRendered = sheet.getAttributes().get("rowRendered");
      if (rowRendered instanceof Boolean && !((Boolean) rowRendered)) {
        continue;
      }

      emptySheet = false;

      if (LOG.isDebugEnabled()) {
        LOG.debug("var       " + var);
        LOG.debug("list      " + sheet.getValue());
      }

      if (sheet.isTreeModel() && sheet.isFolder() && sheet.getExpandedState().isExpanded(sheet.getPath())) {
        expandedValue.add(rowIndex);
      }

      writer.startElement(HtmlElements.TR);
      writer.writeAttribute(CustomAttributes.ROW_INDEX, rowIndex);
      final boolean selected = selectedRows.contains(rowIndex);
      final String parentId = sheet.getRowParentClientId();
      if (parentId != null) {
        // TODO: replace with writer.writeIdAttribute(parentId + SUB_SEPARATOR + AbstractUITree.SUFFIX_PARENT);
        // todo like in TreeListboxRenderer
        writer.writeAttribute(DataAttributes.TREE_PARENT, parentId, false);
      }
      // the row client id depends on the existence of an UIRow component! TBD: is this good?
      writer.writeIdAttribute(row != null ? row.getClientId(facesContext) : sheet.getRowClientId());
      writer.writeClassAttribute(
          selected ? TobagoClass.SELECTED : null,
          selected ? BootstrapClass.TABLE_INFO : null,
          row != null ? row.getCustomClass() : null,
          sheet.isRowVisible() ? null : BootstrapClass.D_NONE);

      int colSpan = 0;
      AbstractUIColumnPanel panel = null;

      for (int i = 0; i < columns.size(); i++) {
        AbstractUIColumnBase column = columns.get(i);
        if (columnRendered[i]) {
          if (column instanceof AbstractUIColumn || column instanceof AbstractUIColumnSelector
              || column instanceof AbstractUIColumnNode) {
            colSpan++;
            writer.startElement(HtmlElements.TD);
            Markup markup = column.getMarkup();
            if (markup == null) {
              markup = Markup.NULL;
            }
            writer.writeClassAttribute(
                BootstrapClass.textAlign(
                    column instanceof AbstractUIColumn ? ((AbstractUIColumn) column).getAlign() : null),
                BootstrapClass.verticalAlign(
                    column instanceof AbstractUIColumn ? ((AbstractUIColumn) column).getVerticalAlign() : null),
                column.getCustomClass());

            if (column instanceof AbstractUIColumnSelector selector) {
              writer.startElement(HtmlElements.INPUT);
              writer.writeNameAttribute(sheetId + "_data_row_selector_" + rowIndex);
              Selectable currentSelectable = getSelectionMode(selectable, selector);
              if (currentSelectable.isSingle()) {
                writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.RADIO);
              } else {
                writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.CHECKBOX);
              }
              writer.writeAttribute(HtmlAttributes.TITLE,
                  ResourceUtils.getString(facesContext, "sheet.selectRow"), true);
              writer.writeAttribute(Arias.LABEL,
                  ResourceUtils.getString(facesContext, "sheet.selectRow"), true);
              writer.writeAttribute(HtmlAttributes.CHECKED, selected);
              writer.writeAttribute(HtmlAttributes.DISABLED, selector.isDisabled());
              writer.writeClassAttribute(
                  BootstrapClass.FORM_CHECK_INLINE,
                  TobagoClass.SELECTED);
              writer.endElement(HtmlElements.INPUT);
            } else if (column instanceof AbstractUIColumnNode) {
              column.encodeAll(facesContext);
            } else {
              final int childCount = column.getChildCount();
              if (childCount > 0) {
                final List<UIComponent> children = column.getChildren();
                for (int k = 0; k < childCount; k++) {
                  children.get(k).encodeAll(facesContext);
                }
              }
            }
            writer.endElement(HtmlElements.TD);
          } else if (column instanceof AbstractUIColumnPanel) {
            panel = (AbstractUIColumnPanel) column;
          }
        }
      }

      if (!autoLayout) {
        writer.startElement(HtmlElements.TD);
        writer.writeClassAttribute(TobagoClass.ROW__FILLER);
        writer.endElement(HtmlElements.TD);
        colSpan++;
      }

      writer.startElement(HtmlElements.TD);
      writer.writeClassAttribute(TobagoClass.BEHAVIOR__CONTAINER);
      encodeBehavior(writer, facesContext, row);
      writer.endElement(HtmlElements.TD);
      writer.endElement(HtmlElements.TR);

      if (panel != null) {
        writer.startElement(HtmlElements.TR);
        writer.writeNameAttribute(String.valueOf(rowIndex));
        writer.writeClassAttribute(TobagoClass.COLUMN__PANEL, panel.getCustomClass());
        writer.startElement(HtmlElements.TD);
        writer.writeAttribute(HtmlAttributes.COLSPAN, colSpan);
        panel.encodeAll(facesContext);
        writer.endElement(HtmlElements.TD);
        writer.endElement(HtmlElements.TR);
      }
    }
    sheet.setRowIndex(-1);

    if (emptySheet && showHeader) {
      writer.startElement(HtmlElements.TR);
      int countColumns = 0;
      for (final UIColumn column : columns) {
        if (!(column instanceof AbstractUIRow)) {
          countColumns++;
        }
      }
      writer.startElement(HtmlElements.TD);
      writer.writeAttribute(HtmlAttributes.COLSPAN, countColumns);
      final UIComponent emptyFacet = ComponentUtils.getFacet(sheet, Facets.empty);
      if (emptyFacet != null) {
        emptyFacet.encodeAll(facesContext);
      } else {
        writer.startElement(HtmlElements.DIV);
        writer.writeClassAttribute(BootstrapClass.TEXT_CENTER);
        writer.writeText(ResourceUtils.getString(facesContext, "sheet.empty"));
        writer.endElement(HtmlElements.DIV);
      }
      writer.endElement(HtmlElements.TD);
      if (!autoLayout) {
        writer.startElement(HtmlElements.TD);
        writer.startElement(HtmlElements.DIV);
        writer.endElement(HtmlElements.DIV);
        writer.endElement(HtmlElements.TD);
      }
      writer.endElement(HtmlElements.TR);
    }

    writer.endElement(HtmlElements.TBODY);
    writer.endElement(HtmlElements.TABLE);
    writer.endElement(HtmlElements.DIV);
  }