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 >
