Re: GtkTreeView Refactoring Considerations [was Re: Private types inside GTK+]
- From: Tristan Van Berkom <tristanvb openismus com>
- To: Kristian Rietveld <kris gtk org>
- Cc: gtk-devel-list gnome org
- Subject: Re: GtkTreeView Refactoring Considerations [was Re: Private types inside GTK+]
- Date: Sun, 31 Oct 2010 15:21:28 +0900
On Wed, 2010-10-27 at 08:59 +0200, Kristian Rietveld wrote:
> On Tue, Oct 26, 2010 at 6:34 PM, Tristan Van Berkom
> <tristanvb openismus com> wrote:
> > Depending on the GtkSizeRequestMode in use by the parenting
> > layout widget (hfw of wfh), generally only allocate_width()
> > or allocate_height() will be called. However there will be
> > cases where we get to further reduce computing of sizes at
> > ->event()/->render() time by having both width and height
> > allocated on a GtkCellArea (i.e. GtkTreeView's fixed-height-mode
> > will allow us to just always know the complete allocated
> > size and position of each renderer before rendering or handling
> > events).
> >
> > After implementing the allocation methods, I'll move on
> > to write/implement the actual ->render() and ->event() methods
> > (which is more or less just copying what GtkTreeViewColumn
> > does already).
>
> As soon as you have implemented the allocation methods, I can also
> take over and do the GtkTreeViewColumn migration, together with
> merging in the refactorings I was talking about earlier.
>
> > And finally what is still missing is a ->get_bounds() method
> > to return a GdkRectangle of the actual space used by cell
> > renderers inside the space allocated to a GtkCellArea (i.e.
> > to allow parent layout widgets to smartly do their focus
> > painting).
>
> So I take it we will not be doing focus drawing in GtkCellArea, but
> rather in the parent layout widget, right? The focus drawing code for
> GtkTreeView is currently at several places, so I will also look into
> properly migrating that.
>
> Another thing what get_bounds() will be useful for is to make it
> possible to start rubber banding when clicking on an area that is not
> covered by cell contents (and is thus "background"). See bug 350618.
>
> > And then will come the grimy situation of pushing this all
> > into GtkTreeView/GtkTreeViewColumn, looking in depth at
> > validate_row again etc. (I'm sure I'll have some more
> > questions and be happy to get any help in that area).
>
> As soon as you have the allocate methods in place that you described
> above, tell me and I can quickly do a tree view migration during the
> evenings and see how far we can come with the current API.
>
Ok so I'm pretty much finished the request/allocation code... I've got
as far as having a list of renderers with allocated positions and sizes
come time for ->render()/->event() etc.
If I understand correctly about cell_area vs background_area, the
difference is basically only the focus line width... the reason for
this is that we want cells to be allowed to fill the whole background
area with a possible background color before we go ahead and pain a
dotted focus line over the possibly modified background area.
so currently the api on the GtkCellArea only takes a single cell_area
when rendering, I think thats going to be fine in general and make for
a clearer API (let me know if I missed something).
So for this I'd like to add a "focus-line-width" property to the
base class GtkCellArea, and just make the cell area implementations
always request space for focus-line-width around cells ... then
come time to render we just create a background/cell_area based
on the focus-line-width and pass both areas to
gtk_cell_renderer_render()... I'll do that part presently.
So as an overview of what I have in the branch, heres some
outlines on how the API is expected to be used particularly
in the case of treeview in the form of some pseudo code:
------------------------------------------------------------
/* First cells are configured and setup with these brand
* of apis
*/
GtkCellArea *gtk_cell_area_box_new (void);
/* Note the 'align' argument here denotes whether the position
* of the added cell is to be aligned with adjacent rows
* using the same iter.
*/
void gtk_cell_area_box_pack_start (GtkCellAreaBox *box,
GtkCellRenderer *renderer,
gboolean expand,
gboolean align);
gint gtk_cell_area_box_set_spacing (GtkCellAreaBox *box);
(gint spacing);
/* By default the box is horizontal anyway */
gtk_orientable_set_orientation (GTK_ORIENTABLE (box));
/* Then at least one GtkCellAreaIter is aquired, its possible
* to use several iters if one wants to group rendering by
* row data (for instance by treeview depth, or GtkComboBox
* will probably want to use one per submenu).
*/
GtkCellAreaIter *
gtk_cell_area_create_iter (GtkCellArea *area);
At this point we have an unrequested/unallocated 'iter' so
we should only be performing requests... for treeview it should
generally look like this:
while (looping over some rows) {
/* Apply the row data for every consecutive call */
void gtk_cell_area_apply_attributes(GtkCellArea *area,
GtkTreeModel *tree_model,
GtkTreeIter *iter);
/* Run the get_preferred_width, we ignore returned results
* for each row as that is stored in the iter
*/
void gtk_cell_area_get_preferred_width (GtkCellArea *area,
GtkCellAreaIter *iter,
GtkWidget *widget,
gint *minimum_size,
gint *natural_size)
}
/* Now we've saved some processing to sum up the alignments of every
* row, so its important to go ahead and call:
*/
void gtk_cell_area_iter_sum_preferred_width (GtkCellAreaIter *iter);
/* Now that we have some alignments of cells stored, we can access our
* proposed widths
*/
void gtk_cell_area_iter_get_preferred_width (GtkCellAreaIter *iter,
gint *minimum_width,
gint *natural_width);
/* ... And then we can get the heights of each row for that width
*/
while (looping over some rows) {
/* Apply the row data for every consecutive call */
void gtk_cell_area_apply_attributes(GtkCellArea *area,
GtkTreeModel *tree_model,
GtkTreeIter *iter);
/* Run the get_preferred_height_width() on a series of rows
* We can gather the collective heights here for variable
* row heights... or...
*/
void gtk_cell_area_get_preferred_width (GtkCellArea *area,
GtkCellAreaIter *iter,
GtkWidget *widget,
gint width,
gint *minimum_height,
gint *natural_height);
}
/* ... Or for fixed row heights we can at this point sum up the
* heights for that with using:
*/
void
gtk_cell_area_iter_sum_preferred_height_for_width
(GtkCellAreaIter *iter,
gint for_width);
/* And then access it at any time using: */
void
gtk_cell_area_iter_get_preferred_height_for_width
(GtkCellAreaIter *iter,
gint for_width,
gint *minimum_height,
gint *natural_height);
/* Now, before we can operate on the GtkCellArea we need to allocate
* the iter in at least the orientation of the GtkCellAreaBox (this
* is a requirement of the GtkCellAreaBox itself but might not be
* a requirement for others, still I think generally its optimal to
* have areas orientable and demand an allocation in their orientation).
*/
void gtk_cell_area_iter_allocate_width (GtkCellAreaIter *iter,
gint width);
/* Now we can go ahead and render cells, the previous call to
* allocate the iter has performed the natural allocation
* among any cells that are to be aligned across rows,
* when rendering cells, any unaligned cells leading up to
* an aligned cell will be done on demand for every row:
*/
while (looping over some rows) {
/* Apply the row data for every consecutive call */
void gtk_cell_area_apply_attributes(GtkCellArea *area,
GtkTreeModel *tree_model,
GtkTreeIter *iter);
/* Render the GtkCellArea */
void gtk_cell_area_render (GtkCellArea *area,
GtkCellAreaIter *iter,
GtkWidget *widget,
cairo_t *cr,
const GdkRectangle *cell_area);
}
/* When an allocated width for a height for width treeview changes,
* its important to flush out the previous results (or when we
* allow the width of the treeview to shrink in consequence of
* data updates and we may want to re-request the whole thing),
* for this we have:
*/
void gtk_cell_area_iter_flush (GtkCellAreaIter *iter);
void gtk_cell_area_iter_flush_preferred_width (GtkCellAreaIter *iter);
void gtk_cell_area_iter_flush_preferred_height_for_width
(GtkCellAreaIter *iter,
gint for_width);
void gtk_cell_area_iter_flush_preferred_height (GtkCellAreaIter *iter);
void gtk_cell_area_iter_flush_preferred_width_for_height
(GtkCellAreaIter *iter,
gint for_height);
/* The contextual height-for-width flushing can be useful if the
* implementing layout widget wants to synchronously respond to
* gtk_widget_height_for_width() calls, it would perform the request
* for a said width, accumulate the results and flush the cache...
* however for large treeviews this might not be interesting.
*/
/* Another thing that may or may not be advantageous, the
* GtkCellAreaIter provides some notifications so one can
* watch the base preferred widths/heights as properties
* as well as trap some signals which tell of heights which
* change for a given width... this may be interesting for
* some layouts who want to request things in the background
* and just find out when the overall sum of the required
* width has grown.
*/
------------------------------------------------------------
So it's not so vague anymore, probably a little rough around the
edges but taking shape.
There remains only to implement the actual render/event methods,
add the focus area introspecting... and then we should be ready
to try this out.
Cheers,
-Tristan
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]