public inbox for yew-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: Dominik Csapak <d.csapak@proxmox.com>
To: yew-devel@lists.proxmox.com
Subject: [PATCH yew-widget-toolkit v4 1/2] widget: data table: factor out cell rendering logic
Date: Thu, 15 Oct 2026 14:38:27 +0200	[thread overview]
Message-ID: <20261015124047.3536357-2-d.csapak@proxmox.com> (raw)
In-Reply-To: <20261015124047.3536357-1-d.csapak@proxmox.com>

Move the loop that renders the visible cells of a row, including the
colspan handling, into a separate function, so that it can be reused for
rendering invisible sample rows to size the columns.

No functional change intended.

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
 src/widget/data_table/mod.rs           |  3 ++
 src/widget/data_table/rendered_cell.rs | 59 +++++++++++++++++++++++
 src/widget/data_table/row.rs           | 66 +++++++++-----------------
 3 files changed, 84 insertions(+), 44 deletions(-)
 create mode 100644 src/widget/data_table/rendered_cell.rs

diff --git a/src/widget/data_table/mod.rs b/src/widget/data_table/mod.rs
index 2ab03b6..ba0d0ff 100644
--- a/src/widget/data_table/mod.rs
+++ b/src/widget/data_table/mod.rs
@@ -29,6 +29,9 @@ pub use cell_configuration::CellConfiguration;
 mod cell_render_callback;
 pub use cell_render_callback::{DataTableCellRenderArgs, DataTableCellRenderer};
 
+mod rendered_cell;
+pub(crate) use rendered_cell::render_row_cells;
+
 mod header_render_callback;
 pub use header_render_callback::{
     DataTableHeaderRenderArgs, DataTableHeaderRenderer, DataTableHeaderTableLink,
diff --git a/src/widget/data_table/rendered_cell.rs b/src/widget/data_table/rendered_cell.rs
new file mode 100644
index 0000000..42ab8e6
--- /dev/null
+++ b/src/widget/data_table/rendered_cell.rs
@@ -0,0 +1,59 @@
+use yew::Html;
+
+use crate::widget::data_table::{CellConfiguration, DataTableCellRenderArgs, DataTableColumn};
+
+/// Contains the rendered cell contents plus meta info to properly show it in the data table
+pub(crate) struct RenderedCell<'a, T: 'static> {
+    pub column_num: usize,
+    pub config: CellConfiguration,
+    pub content: Html,
+    pub column: &'a DataTableColumn<T>,
+}
+
+/// Calculates the necessary index and colspan properties and renders the cell for a row.
+pub(crate) fn render_row_cells<'a, T>(
+    columns: &'a [DataTableColumn<T>],
+    columns_hidden: &[bool],
+    mut make_args: impl FnMut(usize) -> DataTableCellRenderArgs<'a, T>,
+) -> Vec<RenderedCell<'a, T>> {
+    let mut res = Vec::with_capacity(columns.len());
+
+    let mut col_index = 0;
+    let mut column_num = 0;
+
+    while let Some(column) = columns.get(column_num) {
+        if let Some(true) = columns_hidden.get(column_num) {
+            column_num += 1;
+            continue;
+        }
+
+        let mut args = make_args(col_index);
+
+        let content = column.apply_render(&mut args);
+
+        let mut colspan = 1;
+
+        for (attr_name, attr_value) in args.config.attributes.iter() {
+            if attr_name != "colspan" {
+                continue;
+            }
+
+            match attr_value.parse::<usize>() {
+                Ok(n) if n > 0 => colspan = n,
+                _ => {}
+            }
+        }
+
+        res.push(RenderedCell {
+            column_num,
+            config: args.config,
+            content,
+            column,
+        });
+
+        col_index += colspan;
+        column_num += colspan;
+    }
+
+    res
+}
diff --git a/src/widget/data_table/row.rs b/src/widget/data_table/row.rs
index 34bbbdf..9ce1f4d 100644
--- a/src/widget/data_table/row.rs
+++ b/src/widget/data_table/row.rs
@@ -13,7 +13,7 @@ use crate::widget::Container;
 
 use super::{
     CellConfiguration, DataTableCellRenderArgs, DataTableColumn, DataTableRowRenderArgs,
-    DataTableRowRenderCallback,
+    DataTableRowRenderCallback, render_row_cells,
 };
 
 /// DataTable row properties.
@@ -119,15 +119,23 @@ impl<T: Clone + PartialEq + 'static> Component for PwtDataTableRow<T> {
         let minheight_cell_style =
             AttrValue::Rc(format!("vertical-align:top;height: {}px;", props.min_row_height).into());
 
-        let mut col_index = 0;
-        let mut column_num = 0;
-
-        while let Some(column) = props.columns.get(column_num) {
-            if let Some(true) = props.column_hidden.get(column_num) {
-                column_num += 1;
-                continue;
+        let rendered_cells = render_row_cells(&props.columns, &props.column_hidden, |col_index| {
+            DataTableCellRenderArgs {
+                selection: props.selection.clone(),
+                record: &props.record,
+                record_key: &props.record_key,
+                row_index: props.row_num,
+                column_index: col_index,
+                selected: props.selected,
+                config: (*props.cell_config).clone(),
+                is_expanded: props.is_expanded,
+                is_leaf: props.is_leaf,
+                level: props.level,
             }
+        });
 
+        for cell in rendered_cells {
+            let column = cell.column;
             let vertical_align = props
                 .vertical_align
                 .to_owned()
@@ -136,52 +144,22 @@ impl<T: Clone + PartialEq + 'static> Component for PwtDataTableRow<T> {
             let text_align = column.justify.to_owned();
 
             let cell_active = match props.active_cell {
-                Some(active_cell) => active_cell == column_num,
+                Some(active_cell) => active_cell == cell.column_num,
                 None => false,
             };
 
-            let mut args = DataTableCellRenderArgs {
-                selection: props.selection.clone(),
-                record: &props.record,
-                record_key: &props.record_key,
-                row_index: props.row_num,
-                column_index: col_index,
-                selected: props.selected,
-                config: (*props.cell_config).clone(),
-                is_expanded: props.is_expanded,
-                is_leaf: props.is_leaf,
-                level: props.level,
-            };
-
-            let cell = column.apply_render(&mut args);
-
             let mut td = Container::from_tag("td")
-                .class(args.config.class)
+                .class(cell.config.class)
                 .class((cell_active && props.has_focus).then_some("cell-cursor"))
-                .styles(args.config.style)
+                .styles(cell.config.style)
                 .style("vertical-align", vertical_align)
                 .style("text-align", text_align)
                 .attribute("role", "gridcell")
-                .attribute("data-column-num", column_num.to_string())
+                .attribute("data-column-num", cell.column_num.to_string())
                 .attribute("tabindex", if cell_active { "0" } else { "-1" })
-                .with_child(html! {<div role="none">{cell}</div>});
-
-            let mut colspan = 1;
-
-            for (attr_name, attr_value) in args.config.attributes.iter() {
-                if attr_name == "colspan" {
-                    if let Ok(n) = attr_value.parse::<usize>() {
-                        if n > 0 {
-                            colspan = n
-                        }
-                    }
-                }
-            }
-
-            td.as_std_props_mut().add_attributes(args.config.attributes);
+                .with_child(html! {<div role="none">{cell.content}</div>});
 
-            col_index += colspan;
-            column_num += colspan;
+            td.as_std_props_mut().add_attributes(cell.config.attributes);
 
             row.add_child(td);
         }
-- 
2.47.3





  reply	other threads:[~2026-10-15 12:40 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-15 12:38 [PATCH yew-widget-toolkit v4 0/2] data table: auto width Dominik Csapak
2026-10-15 12:38 ` Dominik Csapak [this message]
2026-10-15 12:38 ` [PATCH yew-widget-toolkit v4 2/2] widget: data table: implement auto column sizing based on sample records Dominik Csapak
2026-10-16  7:42 ` [PATCH yew-widget-toolkit v4 0/2] data table: auto width Dietmar Maurer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261015124047.3536357-2-d.csapak@proxmox.com \
    --to=d.csapak@proxmox.com \
    --cc=yew-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal