GtkTreeView Refactoring Considerations [was Re: Private types inside GTK+]



Please excuse the double-posting here, I neglected to create a new
thread and I really needed this to stand out as a separate subject line.

Sorry.

On Tue, 2010-09-14 at 15:00 +0200, Kristian Rietveld wrote:
[...]
> As I also noted in the bug, I would not make GtkTreeViewColumn a stand-alone class, rather, I would work on getting the algorithms that do the cell and column layouting in separate classes and then have GtkTreeView, GtkTreeViewColumn and GtkComboBoxMenu re-use this.  Note that even though cell layouting is done in GtkTreeViewColumn, the column layouting is done in GtkTreeView.
> 
> I think that these layouting algorithms in separate classes might actually be useful public API, to reflect on the comment I made at the start of this e-mail.
> 
> There might be more "components" of GtkTreeView that could be useful to refactor into new separate classes, for example the rendering loop, selection handling, input event handling etc.  My goal would be to refactor GtkTreeView in such a way so that it (the original functionality) can be composed from these separate classes.  And also so that GtkIconView (and new kinds of such views, Windows-style columnary perhaps?) could also be re-written by a composition of these classes.  This will reduce the amount of code that is duplicated between GtkTreeView and GtkIconView, and in this case you can also add GtkComboBox and GtkCellView to that list.  Furthermore, the road for creating variations of these "view" widgets with more flexible and special layouting has then been opened.
> 

    Ok I've been giving this some real thought, considering
the long list of requirements and scribbling things down on
white papers. Before jumping straight into writing code I'd 
like to share these ideas with you and the list and see what
I may have missed and what we can do to improve the plan.

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.

Here's the big abstract picture I've come up with so far to address
the above issues and come up with a more dynamic and reusable code
base for cell rendering. I'll just go ahead and enumerate the classes
and what they are intended for:
------------------------------------------------------------------


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.

GtkCellAreaBox
--------------
   A CellAreaBox would be the first concrete class implementation of 
the GtkCellArea, it would be orientable and when oriented horizontally 
it would pretty much act like how a GtkTreeViewColumn acts today.


GtkCellAlignment
----------------
   A GtkCellAlignment would be a very simple object class that is 
responsible for taking a collection of sizes into account. A
GtkCellAlignment would be used as a GtkCellAreaBox delegate to 
achieve the horizontal alignment of cells across rows that the
GtkTreeViewColumn does today.

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
(for instance, I would like to append an icon at the end of a text
renderer and not have the annoying alignment/gap between the dynamic
text length and the icon).

For possible future tabular GtkCellArea classes (GtkCellAreaTable
anyone ?) ; two GtkCellAlignments could be optionally used to aid 
in the alignment its child cells vertically and horizontally).


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)

  - Add a callback to be defined by the user when the GtkCellAreaManager
    wants to update the cache for a given row.

  - Provide a way to invalidate the cache on a per-cache and 
    per-row basis

  - 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.

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.

The GtkIconView could most certainly reuse the GtkCellAreaBox
object and orient it vertically or horizontally (text below
or beside icon).

The GtkComboBoxMenu solution for bug 629133, could simply
use the GtkCellAreaBox oriented horizontally to draw the
menu-items; the menu-items themselves would simply contain
a single GtkDrawingArea and then call the GtkCellArea->render()
method when the drawing area's expose themselves.



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.

However the nature of code is that it doesn't all fit in a single
brain at once, time runs thin and we have to start writing code
soon ;-)

So please, any thoughts, considerations, things I've missed will
be great to share here.

Thanks !

     -Tristan




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]