grid widget (was Re: possible removal of GtkWrapBox)



Hi,

I did a little exercise a while ago of screenshotting some apps that
seemed to be doing moderately complex layout and trying to write down
what would be intuitive / no-redundant-typing sequences of commands to
pack the layouts.

Don't know if this will make sense to anyone else but I do think it's
useful to take some real-world layouts and see how much typing they'd
require and how clear the resulting code is. I didn't really finish
the exercise so there's probably some mistakes in here.

Some preliminary theories from the exercise:

* it's right to have certain layouts require recursive (child) grids
or size groups. it's easy to go down the road of trying to have too
many features in order to do complex layouts all in one container.
* just naming methods/props with "left and right" might be clearest,
even though in RTL mode these might flip and if GtkOrientable they
might become top and bottom
* it seems to work well when packing by hand in code to have a
"cursor" (current row/column/sibling - and possibly properties to
apply to child)
* per-row/column homogeneous flag doesn't seem necessary because you
can just nest another table. make these table-wide?

The primitives I came up with that seemed natural were:

* add_row(child): adds child spanning an entire row, move cursor to next row
* next_row(): move cursor to next row
* add_left(), add_right(): add child on left or on right end of current row
  note add_right() appends on right, rather than appending on "inside"
like pack_end,
  which is clearer for reading code
* push_props() pushes align or expand or margin props to apply to all
newly-added widgets
* table-wide h-homogeneous and v-homogeneous flags

The model I was messing with here would involve saving each row in a
list, and then to layout you would go over the lists to find the max
number of cells, then size the table automatically and assign widgets
to cells.

I guess I didn't really figure out the "span" question (children
spanning columns). I made add_row() span all the columns and
add_left/right span only one, and for these layouts I was looking at I
guess never used any other setting. Also I never came up with how
columns would work I guess. (can you add_column() or add_top() /
add_bottom() ? maybe too complex)

Things that may be true, I didn't think through:
* can you always use a size group or nested grid rather than an
arbitrary column span?
* can you always use a nested grid rather than allowing arbitrary row span?

If those are true then you could say each child is a whole row OR a
single cell, and each child is always only one row high. That'd
simplify both implementation and API quite a bit. Then you have
essentially a stack of boxes where the items in the boxes are aligned
on columns. To do anything more complex you use nested grids or size
groups. However, at least in the sample layouts I was looking at,
basically you just want hboxes but you want to line up the stuff in
the hboxes instead of having each hbox all by itself. So ended up
optimizing for that 90% case.

One useful API might be an add_spacer(size) which would just fill a
cell with a fixed spacer, so you could have some rows indented for
example.

Anyway from this exercise, a grid is more "stack of boxes" than it is GtkTable.

Havoc

On Wed, Oct 6, 2010 at 11:58 PM, Matthias Clasen
<matthias clasen gmail com> wrote:
> On Wed, Oct 6, 2010 at 11:36 PM, Tristan Van Berkom
> <tristanvb openismus com> wrote:
>
>> Any takers ? thoughts ?
>>
>
> One thing that I would like to save from this whole experiment is your
> experience in wfh containers... I've started writing a grid widget
> like Havoc was describing a while ago. I have put what I have on the
> 'grid-widget' branch. Currently, it just uses the GtkTable size
> allocation. Getting it to do hfw is the last thing needed to ensure
> that has a full superset of GtkBox and GtkTable functionality.
About gedit
===

push_props(h-align=center)
add_row(logo)
add_row(name)
add_row(description)
add_row(copyright)
add_row(url)
pop_props()

add_left(credits_button)
add_right(close_button)

Calculator
===

add_row(entry)

add_left(degrees)
add_left(gradians)
add_left(radians)
add_right(eng)
add_right(fix)
add_right(sci)

add_row(inv_hyp_grid)
inv_hyp_grid.add(inv)
inv_hyp_grid.add(hyp)

add_row(keypad_grid)

keypad_grid.h-homogeneous=true
keypad_grid.v-homogeneous=true

push_props(h-expand=true,v-expand=true)
keypad_grid.add_left(ln)
keypad_grid.add_left(log)
keypad_grid.add_left(log2)
keypad_grid.add_left(xy)
keypad_grid.add_left(x!)
keypad_grid.add_right(acc)
keypad_grid.next_row()
keypad_grid.add_left(con)
// ... etc.
pop_props()

Monitor Preferences
===

add_left(left_grid)
add_right(right_grid)
add_row(buttons_grid)

buttons_grid.h-align=end
buttons_grid.add(apply)
buttons_grid.add(close)

left_grid.add_row(monitors_picture)
left_grid.next_row()
left_grid.add_left(same_image_check)
left_grid.add_right(detect_monitors)
left_grid.add_row(panel_icon_frame)

right_grid.add_row(laptop_label)
right_grid.add_row(radio_grid)

radio_grid.add(on)
radio_grid.add(off)

right_grid.next_row()
right_grid.add_left(resolution)
right_grid.add_right(resolution_menu)
right_grid.next_row()
right_grid.add_left(refresh)
right_grid.add_right(refresh_menu)
right_grid.next_row()
right_grid.add_left(rotation)
right_grid.add_right(rotation_menu)



Attachment: About gedit.png
Description: PNG image

Attachment: Calculator.png
Description: PNG image

Attachment: Monitor Preferences.png
Description: PNG image



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