Changes between Version 2 and Version 3 of Ticket #11030


Ignore:
Timestamp:
May 28, 2010, 10:06:04 AM (12 years ago)
Author:
bill
Comment:

Here are some notes I made after the discussion mentioned above:

Chris implemented a version of BorderContainer that could handle 7 children, and in doing so eliminated the branching on design=headline or design.sidebar. The seven panes were:

+-----------------------+
|         header        |
+------+---------+------+
|      |   top   |      |
| left |  center | right|
|      |  bottom |      |
+------+---------+------+
|        footer         |
+-----------------------+

However, I think (and Chris agreed) that BorderContainer could follow a generic algorithm like the current dijit.layout.LayoutContainer does... or from another angle, the current LayoutContainer class could be enhanced to support draggable splitters and collapsible panes. The goal would be to reduce the code size, and allow for more complicated layouts, like having 2 headers (for example: a menubar and a toolbar).

The current dijit.layout.LayoutContainer's algorithm is implemented here: http://bugs.dojotoolkit.org/browser/dijit/trunk/layout/_LayoutWidget.js#L219. Basically, it lays panes down from the outside in, according to a specified order of panes, so the free space in the center keeps getting smaller and smaller.

If a user wanted to achieve a 7 pane layout using the current dijit.layout.LayoutContainer, they would simply specify 7 children in the following precendence order:

  1. header (layoutAlign=top)
  2. footer (layoutAlign=bottom)
  3. left (layoutAlign=left)
  4. right (layoutAlign=right)
  5. top (layoutAlign=top)
  6. bottom (layoutAlign=bottom)
  7. client (layoutAlign=client)

The order is what determines which pane takes "precedence"... in the above example "header" comes before "left" so the LayoutContainer's upper-left corner is filled by "header" rather than "left"... and so on recursively.

Alternately the splitters could also be treated as children:

  1. header (layoutAlign=top)
  2. header splitter (layoutAlign=top)
  3. footer (layoutAlign=bottom)
  4. footer (layoutAlign=bottom)
  5. left (layoutAlign=left)
  6. left splitter (layoutAlign=left)
  7. right (layoutAlign=right)
  8. right splitter (layoutAlign=right)
  9. top (layoutAlign=top)
  10. top splitter (layoutAlign=top)
  11. bottom (layoutAlign=bottom)
  12. bottom splitter (layoutAlign=bottom)
  13. client (layoutAlign=client)

I see two issues with using that technique for a new BorderContainer, but I think they are fairly easy to overcome:

  1. calculating the maximum amount that the user can drag a splitter

When dragging the splitter on (for example) the header of the 7 pane example above, the max size the header pane can become is:

LayoutContainerHeight - (footerHeight + topHeight + bottomHeight)

To calculate that generically I think it's just a question of adding up the heights of all the elements with layoutAlign==top or layoutAlign=bottom:

LayoutContainerHeight - (sum of heights of other horizontal panes)

And similarly to calculate the max size that a vertical pane can be expanded to

LayoutContainerWidth - (sum of widths of other vertical panes)
  1. avoiding calling resize() on panes that haven't moved

The efficiency issue is both with unnecessary marginBox() (as a getter) calls, and more importantly, unnecessary resize() calls on complicated child widgets like Grid.

So the goals for efficiency should be:

  • don't call resize() on a pane if it's the same size as before
  • don't call marginBox() (as a getter) unnecessarily. apart from initial setup (when we query the height of horizontal panes and the width of vertical panes), we never need to query the width of the vertical panes, and we only need to query the height of the horizontal panes if the width has changed. (the latter case might be true when a width change causes the toolbar's icons overflow to two rows).

What if LayoutContainer remembered the size of each pane, and then whenever there was a resize() it would go through each pane, getting ready to resize it, but if it turned out the same size as before it would skip it? Plus, it would only call marginBox() when it needed to, as listed above.

For example, in a 7-pane layout say that the user increased the height of the header pane. The code would process the panes like this (in this order):

  1. header pane. it used to be 500x200, and now I'm told that it's size has been changed to 500x250. It's size has changed, so call resize() on it, to reflect that change.
  2. footer pane. It used to be 500x200, and neither it's height nor width has changed, so we don't call resize() on it.
  3. left pane. It used to be 100x500, but now it's 100x450, so call resize(). (the height changed but the width didn't, and we don't need to do a marginBox() to get the width since we already know it from last time.)
  4. right pane: same
  5. top pane: It used to be 300x100, and it still is, no resizing
  6. bottom pane: same 7 center pane: resize

Resizing a vertical pane is a bit different:

  1. header pane: no size change, skip
  2. footer pane: no size change, skip
  3. left pane: resized from 100x500 --> 150x500, resize
  4. right pane: no change
  5. top pane: width decreased by 50px, so maybe the height has changed? change width, then query height (same as current dijit.layout.LayoutContainer does)
  6. bottom pane: basically same as top pane
  7. center pane: resize

Legend:

Unmodified
Added
Removed
Modified
  • Ticket #11030 – Description

    v2 v3  
    1 !SplitContainer has been deprecated, but there is no way to get N vertical/horizontal containers in a region with BorderContainer like there is with !SplitContainer.   
     1!SplitContainer has been deprecated, but there is no way to get N vertical/horizontal containers in a region with !BorderContainer like there is with !SplitContainer.   
    22
    3 Suggestion was made to nest !BorderContainers, but thats not acceptable.   Border and split handlers do not show as they would with a !SplitContainer. 
     3Suggestion was made to nest !BorderContainers, but that's not acceptable.   Border and split handlers do not show as they would with a !SplitContainer.