I’m trying to create a table-like widget, where I have 3 columns of data (each row will have a button as well) and x number of rows inside of a list
widget (on the feature/list-widget-reloaded
branch). And I have a somewhat working example, where it shows 1 of my 3 pieces of data
I am just a bit confused on the proper set up for this idea. My initial hope was to have a very abstracted interface for app, where I have a struct Data
, and my app holds a iced::widget::list::Content<Data>
, and creates the widget based on that.
After some messing around, I cannot seem to get much further than placing widgets and things in the top right corner of each row. Introducing row![]
appears to be the wrong approach just based on the trait errors I was getting. Not sure if I’m approaching this wrong and I should have like 3 ‘cell’ widgets inside of one ‘row’ widget, but since my app will make no difference between the 3 cells (something something performance?) I decided to do the ‘single row’ approach
It would also be nice if there was super long text in a ‘cell’, it wouldn’t just push the other cells away, like some sort of cut-off.
Code: (trying to only include important parts cause it is pretty long)
// row.rs
pub struct RowData {
pub title: String,
pub author: String,
pub row_num: usize
}
pub struct RowWidget<'a, Message, Theme, Renderer>
where
Renderer: iced::advanced::Renderer + iced::advanced::text::Renderer,
Theme: Catalog + iced::widget::text::Catalog + iced::widget::button::Catalog,
{
// like should rowdata be something else?
rowdata: Element<'a, Message, Theme, Renderer>,
on_left_click: Option<Message>,
on_right_click: Option<Message>,
row_num: usize,
}
impl<'a, Message, Theme, Renderer> RowWidget<'a, Message, Theme, Renderer>
where
Renderer:
'a + iced::advanced::Renderer + iced::advanced::text::Renderer,
Theme: 'a + Catalog + iced::widget::text::Catalog + iced::widget::button::Catalog,
Message: 'a + Clone,
{
pub fn new(
rowdata: RowData,
on_left_click: Option<Message>,
on_right_click: Option<Message>,
row_num: usize,
) -> Self {
let main_part = row![text(rowdata.title.clone()), text(rowdata.author.clone())];
RowWidget {
rowdata: main_part.into(),
on_left_click,
on_right_click,
row_num,
}
}
}
// this is inside of the impl for `Widget`, where I was trying to 'place' my text and whatnot
fn draw(
&self,
tree: &iced::advanced::widget::Tree,
renderer: &mut Renderer,
theme: &Theme,
style: &renderer::Style,
layout: layout::Layout<'_>,
cursor: iced::advanced::mouse::Cursor,
viewport: &iced::Rectangle,
) {
// varying cell colors
let cell_color = if self.row_num % 2 == 0 {
Color {
r: 0.3,
g: 0.3,
b: 0.3,
a: 1.0
}
}
else {
Color {
r: 0.5,
g: 0.5,
b: 0.5,
a: 1.0
}
};
// create the cell color
renderer.fill_quad(renderer::Quad {
bounds: layout.bounds(),
border: Border::default(),
..renderer::Quad::default()
}, cell_color);
self.rowdata.as_widget().draw(
&tree.children[0],
renderer,
theme,
&renderer::Style {
text_color: Color::WHITE
},
layout,
cursor,
&viewport
);
// is this the right idea to place a button? All it did was change the color of my cell (and take up all of it)
// <iced::widget::Button<'_, Message, Theme, Renderer> as Widget<Message, Theme, Renderer>>::draw(&button(text("yello!!")), &tree.children[0], renderer, theme, &renderer::Style { text_color: Color::WHITE}, layout, cursor, &viewport);
impl<'a, Message, Theme, Renderer> RowWidget<'a, Message, Theme, Renderer>
where
Renderer:
'a + iced::advanced::Renderer + iced::advanced::text::Renderer,
Theme: 'a + Catalog + iced::widget::text::Catalog + iced::widget::button::Catalog,
Message: 'a + Clone,
{
pub fn new(
rowdata: RowData,
on_left_click: Option<Message>,
on_right_click: Option<Message>,
row_num: usize,
) -> Self {
let main_part = row![text(rowdata.title.clone()), text(rowdata.author.clone())];
RowWidget {
rowdata: main_part.into(),
on_left_click,
on_right_click,
row_num,
}
}
}
}
// main.rs
// (inside `view`)
scrollable(list(&self.content, |index, item| {
row::RowWidget::new(
row::RowData {
title: format!("testing: {} ", index),
author: format!("author: {}", index),
row_num: index,
},
None,
None,
index,
)
.into()
}))
TLDR: How do I ‘spread’ buttons & text out inside of a custom widget?
(Yes I am aware I am doing a very similar widget to Tarkah/iced_table, I wanted some extra functionality, remove some of their features and also practice making widgets)