slint icon indicating copy to clipboard operation
slint copied to clipboard

Some thoughts on implementing a table view

Open cppdev123 opened this issue 2 years ago • 1 comments

Currently slint does not have a table view but only a list view however a list view is a table view which only has one column so I have the following ideas for implementing table view:

  • the table has a model which notifies it for each insertion, deletion and changing of an item
  • the table has a delegate which is responsible for painting the items and determining their size hint (just like in qt)
  • the table have a state for each column which contains : min and max height and width, total height and width and average height and width
  • for each insert and data change notification the table receives it gets the item(s) size from the delegate and update the state of affected columns
  • when painting the table will provide the delegate the min, max or average width and height depending on the user choosing or a fixed width or height if the user chooses so
  • the table can then scroll very easily and determine which items to paint and which to not since items are assigned equal heights and widths
  • a list is a simplified table with one column with a simplified model

Why not draw rows for list view instead of cells for a table (the current approach) ? the current approach lacks a main benefit of tables : rows and columns should have consistent width and height. Currently the user must right code to ensure that items in the rows have equal width which is not always an easy to do especially when text is involved since

Another improvement for models: There should be some sort of decoration role, font role, display role, etc. Cause it is very common to use and will save the time to code them manually each time for each table and list

cppdev123 avatar Jun 04 '22 13:06 cppdev123

Thanks for the comments. There are already some discussion about tableview in #759 and #574

  • the table has a model which notifies it for each insertion, deletion and changing of an item

Right, the current Model used by the repeater and the ListView currently already do that.

  • the table has a delegate which is responsible for painting the items and determining their size hint (just like in qt)

Yes, the ListView also has that, in the for

  • the table have a state for each column which contains : min and max height and width, total height and width and average height and width

Right, a TableView need that. This could be supported by a runtime layouting function, like there is one for the ListView, it also need to compute the size of each column.

The problem is that we probably do not want to instentiate every elements in the model. But without instentiating it can be hard or impossible to know the size. unless we make something special that'd allow us to query the size without instentiating the component.

  • when painting the table will provide the delegate the min, max or average width and height depending on the user choosing or a fixed width or height if the user chooses so

The row of the table would just be Component, but these Component must have different column in it and would be able to query the size of each column from the TableView

  • a list is a simplified table with one column with a simplified model

Kind of, yes. Another way to say it is that a Table is a generalized List

Why not draw rows for list view instead of cells for a table (the current approach) ? the current approach lacks a main benefit of tables : rows and columns should have consistent width and height.

Yes, that's the missing part.

There should be some sort of decoration role, font role, display role, etc. Cause it is very common to use and will save the time to code them manually each time for each table and list

This is what the StandardListViewItem is meant to be, but it currently only has "display" right now.


Now, the question is how would the model be. What's the type in sline. For example, a ListView uses [StandardListViewItem] then a TableView would use a [[StandardListViewItem]] ? (a model of model)

Or would we have something better where the delegate can basically take any value from the model struct.

So this could be looking like:

property <[{foo: string, bar: string}]> model;
tb := TableView {
   for data in model: HorizontalLayout {
      t1 := Text { width: tb.col-width(0); text: data.foo; }  // column1
      t2 := Text { width: tb.col-width(1); text: data.bar; }  // column2
   }
}

But this doesn't allow to compute the size of the column easily from the content. Another alternative:

property <[{foo: string, bar: string}]> model;
tb := TableView {
   for data in model: TableRow {
      Text { text: data.foo; }  // column1
      Text { text: data.bar; }  // column2
   }
}

or

StandardTableView := StandardView {
   property <[[StandardListViewItem]]> model;
   for data in model: TableRow {
      for data2 in data : Xxx { ... }
   }
}

ogoffart avatar Jun 27 '22 16:06 ogoffart

Here is an example of a table view built on top of a ListView: https://slint-ui.com/docs/rust/slint/docs/recipes/index.html#table-view

ogoffart avatar Nov 29 '22 12:11 ogoffart

Florian implemented and merged an initial version of StandardTableView in https://github.com/slint-ui/slint/pull/2032 . I suppose the acceptance criteria for closing this issue though is a more generic mechanism?

tronical avatar Jan 13 '23 10:01 tronical

Table View is in 0.3.4. Further features are tracked in https://github.com/slint-ui/slint/issues/2033

ogoffart avatar Feb 06 '23 10:02 ogoffart