On Sep 23, 2010, at 10:56 AM, Tristan Van Berkom wrote:
> So to help stay on track without straying too too much, these
> are (my perceived) reasons for the said refactoring work:
> 
>  - Code sharing: A good refactoring of cell layouting logic 
>    into some classes that can be (more) easily reused by the 
>    major candidates GtkTreeView, GtkIconView and GtkComboBox[Menu]. 
> 
>  - Adaptation for height-for-width support (currently only
>    the GtkComboBox uses hfw'ness of cell renderers, big patch
>    pending on treeviews could be better written based on the
>    refactored code).
> 
>  - Alignment of GtkComboBox menu renderers currently cant be
>    done as described in bug 629133.
> 
>  - While we're on the topic of refactoring the cell layouting
>    code, I'd personally like to open up new avenues for rendering
>    cell layouts in more dynamic ways (as I'll describe in more 
>    detail below); Rationale for this is if we're going to give this
>    a go at all, we better be ambitious and awesome about it.

Layouting cells in more dynamic ways is one reason; for me another big reason 
is to also make column/row layouting (thus the layouting of cell layouts ;) 
more flexible.  Think of:

 - Making it easier to create widgets such as icon view, Windows-style 
columnary list view, etc.  Basically, you only want to write the algorithm 
laying out the rows and re-use the algorithms that layout cells.

 - For list and tree views, make row and column spanning possible.

 - Proper implementations of separator rows, group headings or other custom 
content.  (More on that below).

 - Possibly embedding non-cell content in list/tree views, such as custom 
widgets.  Most notably, for example a button (see mobile platforms).


> GtkCellArea
> -----------
>   A GtkCellArea would be an abstract class which implements 
> GtkCellLayout and acts as a collection of cells which are rendered 
> in a completely undefined way, GtkCellArea classes would be responsible 
> for handling all geometric tasks in the laying out of cells:
> 
>  - Allocation of cell positions inside the area 
> 
>  - Returning overall bounderies that the cells take up inside an
>    area as well as returning the bountries of a single cell inside
>    the area.
> 
>    This is important for widgets like TreeView and IconView
>    who want to draw focus around a cell, a column or an entire row.
> 
>  - Returning the cell at a specified coordinate inside the area for
>    a given treemodel row.
> 
>    This is needed for the sake of handling mouse-clicks so that the 
>    owner of the CellArea can go on to start editing a given cell, or
>    activate an icon in a given cell.
> 
>  - Responding to height-for-width/width-for-height apis for a 
>    collection of cells for a given treemodel row.
> 
>  - Actually render the GtkCellArea for a given row into a given 
>    space/GdkRectangle.
> 
> Conceptually, the GtkCellArea is for a cell renderer what a 
> GtkContainer is for a GtkWidget. The main bonus of keeping the 
> GtkCellArea as an abstract class and responding to some generalized 
> apis is it opens up avenues for more complex implementations such as 
> a tabular CellArea, or a cell-wrapping CellArea which could be more 
> easily implemented in the future.

At first, I thought this would be an entity for rendering one "row", so one set 
of cells (basically, what cell view does currently).  But I think you mean to 
have GtkCellArea manage multiple rows?  I leave whether or not GtkCellArea 
should manage one or more rows in the middle below.

An "object" that handles cell layout for a single row is what I kind of ended 
up with in a previous refactoring.  This was not really an object, as it was a 
set of internal functions.  What I did was refactoring the cell layouting code 
in gtktreeviewcolumn.c into a manageable set of functions that implemented an 
iteratable interface over a list of cells.  Turning something like this into a 
stand-alone class (and enable subclassing) sounds like a good idea to me.

One of my original ideas was to introduce the concept of a "row renderer".  
This would be an abstract class with several subclasses.  One row renderer 
subclass for rendering a row consisting out of cell renderers, re-using the 
original cell layouting code.  Other "row renderers" for embedding widgets, 
separators, group headings, etc.  Layouting row renderers would then give you 
your full-featured tree view, icon view, etc.  (Though combining an icon view 
and a group heading row renderer would mean combining tabular and "list" layout 
-- another puzzle to solve but an interesting feature).

To go back to the proposed GtkCellArea:

 - I am not yet sure if this should be tied to GtkTreeModel.  The main 
consideration is if you want to use GtkCellArea without a GtkTreeModel.  Though 
it seems cumbersome to provide some other means to populate the properties of 
the cell renderers in this case ...

  Another consideration is whether GtkCellArea will manage one or multiple 
rows.  If only one, then you might want to have another object set the data on 
the cell renderers (the data is "pushed" by another object).  If multiple, then 
directly accessing the model seems a better fit (GtkCellArea "pulls" the data 
by itself).

 - GtkCellArea (or a subclass) might also have to implement the custom 
"event-handling" and focus drawing code that is currently in GtkTreeViewColumn.

> The CellAlignment helps in general to optimize the overall size requests
> of treeview rows, however where performance is not an issue; the use of
> CellAlignment by the GtkCellAreaBox can be optional, in this way 
> allowing cell renderers to "flow naturally" across a GtkTreeView column

Yes, such natural flowing of cell renderers in a column should definitely be 
supported.

> GtkCellAreaManager
> ------------------
>   This would essentially be a cleaned up API and refactored version of
> the current GtkRBTree. The rbtree currently caches information about how
> a GtkTreeView is currently rendering a given model, it caches things
> such as which rows are expanded; the indentation level used by the
> treeview and most notably the variable height of rows.
> 
> Some things that would change in the GtkCellAreaManager would be:
> 
>  - Rip out GtkTreeView specific information such as expanded rows
>    and indentation.
> 
>  - Add a client data pointer to be defined by the user which describes
>    what kind of data is cached in a row (all the treeview specific
>    row cached stuff comes back here)

I assume that such a pointer will be placed in GtkRBNode.  You mention the 
expanded rows and indentation as tree view specific stuff above.  Note that 
this data is not stored in the GtkRBNode fields.  Expanded rows are deduced 
from the RBTree structure, simply because collapsed rows are not present in the 
RBTree.  Indentation is calculated based on row depth (which is in turn taken 
from the RBTree structure again).  What is stored in the GtkRBNode, is the 
state of the expand/collapse animation (the expander animation).

What has been requested as feature in the past is to save the selection and 
expansion state of rows that are being collapsed.  For example, if you collapse 
a row and then expand it again, the selection will appear as it was before you 
collapsed the row.  The same for expansion state of child rows.  If we were to 
provide such a feature, RBTree would need to see changes.

>  - Provide a configurable iterative process for updating the cache,
>    this would be performed synchronously for all the visible rows and
>    then fall off into the background only updating a configurable
>    ~1000 rows at at time and then marking them "validated" for access.

This would basically be moving out as much of GtkTreeView's validation code as 
possible into this class.

> How does this all map to current GtkCellLayout implementations ?
> 
> Most of the above text referrs to GtkTreeView, being the most
> complex configuration making use of these classes.

Whereas the RBTree works very well for lists and trees, are we sure that this 
will work nicely and performant for tabular layouts as well?  Or would a 
different data structure be a better choice?

If it is useful to re-use RBTree in several widgets, then we should likely do 
it in a similar way as you proposed with GtkCellAreaManager.  However, more 
study might be required as RBTree is quite a central element of the tree view.  
Because it is so central, we should likely also take performance into account.

Have you given any thought to selection handling?  GtkTreeSelection is now only 
used by GtkTreeView, you would also want to generalize that.  Currently, 
selection state is stored in GtkRBTree, so GtkTreeSelection and GtkRBTree are 
again intertwined with each other.  Perhaps GtkCellAreaManager is also a good 
choice for placing the selection handling code, possibly made 
extensible/adaptable through a delegate object?

> Conclusion: There is a plethora of requirements relating to
> GtkTreeView in general, some of which I'm sure to have missed,
> some of which will surely present themselves as road-blocks
> while implementing the said refactoring.

It's a huge task, which I think is (unfortunately) impossible to get done 
before 3.0.  If we do something like this, I think  we also have to decide on 
some kind of compatibility with current GtkTreeView. Getting there throughout 
the 3.x releases would be cool though.

I will try to look for my notes on tree view refactoring which I wrote a long 
time ago and see if there were more ideas that could fit in nicely with what 
has been proposed so far.  While pencil and paper is great for brainstorming, 
paper has a tendency to get lost :)


regards,

-kris.

_______________________________________________
gtk-devel-list mailing list
gtk-devel-list@gnome.org
http://mail.gnome.org/mailman/listinfo/gtk-devel-list

Reply via email to