all lists on 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal