Hi Edgar,
That's a very good question about a common source of confusion. Let me
attempt to answer in such a way so as to explain not only TablePane, but
many other containers... This topic should probably be covered in the
"knowledge base", were we to have one :)
Container fundamentally provides us with the component *hierarchy*. Without
it, we'd simply have a bunch sibling components, which would be... messy :)
As part of providing this hierarchy, it is responsible for things such as
propagating mouse events, focus traversal, translating coordinate spaces
during paints, etc. A Container knows of its child components via
implementing Sequence<Component>. If *and only if* a child component is in
this sequence, it will receive propagated mouse events and paint() calls
from the container.
Now enter the concept of layout. Layout is the process by which components
are organized within their parent. It is the responsibility of the parent
itself (technically, the parent's skin) to lay out its children (Panel
non-withstanding). Each Container subclass defines a different layout
policy. That policy may require it to differentiate its children and treat
each one differently. Take TablePane, for instance; it needs to know the
cell in which to place each child component. If all it had were a sequence
of components, it wouldn't know which one went at 0,0, which one at 1,0,
etc. These types of containers define other data structures or members to
denote these characteristics. TablePane defines getRows() [RowSequence
implements Sequence<Component>]. When you add a component to a table pane
row, you're also implicitly adding it to the Container's component sequence
(that happens behind the scenes), but moreover, you're telling the table
pane how to lay out the child component. This design applies to a bunch of
containers; Rollup (setHeading(), setContent()), TabPane (setCorner(),
getTabs()), Accordion (getPanels()), Window (setContent()), and Border
(setContent()) are a few of them.
So what would happen if you added a component to a table pane using
tablePane.add(component) instead of adding it to a row? You would have
successfully added a child component to the table pane, but the table pane's
skin wouldn't know how to lay the child out, so the child's size and
location would remain untouched. As a test of this, try the following:
<Window maximized="true" xmlns:wtkx="http://pivot.apache.org/wtkx"
xmlns="org.apache.pivot.wtk" styles="{backgroundColor:'#777777'}">
<content>
<TablePane>
<columns>
<TablePane.Column width="1*" />
<TablePane.Column width="1*" />
</columns>
<rows>
<TablePane.Row height="1*">
<Panel styles="{backgroundColor:'#000000'}" />
<Panel styles="{backgroundColor:'#ffffff'}" />
</TablePane.Row>
<TablePane.Row height="1*">
<Panel styles="{backgroundColor:'#ff0000'}" />
<Panel styles="{backgroundColor:'#00ff00'}" />
</TablePane.Row>
</rows>
<Panel styles="{backgroundColor:'#0000ff'}" x="25" y="25"
width="50" height="50" />
</TablePane>
</content>
</Window>
In this example, the table pane skin will lay out the black, white, red, and
green panels in the four cells, but it won't touch the blue one -- the blue
one will remain at 25,25+50x50. If you resize the table pane, the panels in
the cells will get resized too, but again, the blue one will remain
untouched.
So one question you might have is "Why this design? Why not use attributes?"
Some other toolkits attach attributes to child components to provide such
metadata. In fact, Pivot itself uses attributes that it attaches to child
components to provide metadata such as a tab's label within a TabPane.
However, Pivot does *not* use attributes to specify layout metadata; mainly
to promote code cleanliness. In the case of TablePane, if each child
component had a ROW and COLUMN attribute attached to it, then what would
happen when you dynamically inserted (or removed) a row or a column from the
table pane? You'd have to update your book-keeping of all the attributes to
increment or decrement the associated row or column attribute. The same
goes for the tab pane tabs, accordion panels, etc. We believe that the
"special designation children" design yields a cleaner distinction than you
would achieve via attributes.
I hope that helps. It was a little long winded, but it was a deep question
:).
Greg knows this stuff better than I do, so he probably has a good
perspective and can add a lot here as well.
Cheers,
-T
On Wed, Sep 23, 2009 at 7:46 PM, Edgar Merino <[email protected]> wrote:
Hello, long time I haven't write to this list. I'm currently developing a
"text engine" for php, most of the component hierarchy model I'm using is
based on pivot (conceptually). For laying out components I've chose to use
Containers too, by looking at TablePane's source code I see it extends
Container, but somehow I don't see it using the "components" ArrayList
Container has, instead it's defining it's own Sequences (RowSequence and
ColumnSequence) and using them, ignoring it's parent's components. So the
question is, what is the reason behind TablePane extending Container? adding
a component to a TablePane using TablePane#add() doesn't make sense to me,
but maybe I'm missing something.
P.S. I still have some code I'd like to contribute, but work's on me right
now :).
Thanks in advance,
Edgar Merino