PDA

View Full Version : ViewPort>Panel>TabPanel>TreePanel Not Resizing on node Expand



wwarby
1 Jul 2008, 6:14 AM
I have the following hierarchy of components on a page:

Viewport

|--Component (region: left)


|--Panel



|--No content


|--Panel



|--TabPanel




|--Tab





|--No content




|--Tab





|--TreePanel






|--TreeLoader

|--Component (region: center)


|--Component



|--No content

The page initially loads correctly - the root node gets the child nodes from the server and the panel shown in bold above expands to accommodate the new tree nodes. After this point, resizing of the panel appears unpredictable. Most of the time, the nodes load but the panel height remains constant, so the nodes are overflowing and thus invisible. One time (without changing any code, just refreshing the page), the panel expanded to accommodate the new nodes when I clicked on a node below the root, but when I collapsed that node, the panel didn't shrink again. On another occasion, the panel refused to change size when I clicked on the other tab that had no content.

I've tried calling syncSize() on every component in the hierarchy after expanding a node below the root using Ext.ComponentMgr.get(id).syncSize() and this made no difference. Any help would be greatly appreciated.

Also (since I'm asking for help anyway), if I use the exact same code shown below but change the line activeTab: 'location-browser-tab' to start on the tab that doesn't contain the TreePanel, the tree panel isn't rendered at start up or when I click on the tab that contains it. After a whole day of trying various combinations of listener functions and different methods of initializing the components I am utterly unable to render the tree unless it is in a panel that is visible from the outset. Full source code below...


Ext.onReady(function(){

Ext.state.Manager.setProvider(new Ext.state.CookieProvider());

var viewport = new Ext.Viewport({
layout: 'border',
items: [{
id: 'left',
region: 'west',
split: true,
width: 250,
minWidth: 150,
maxWidth: 350,
border: false,
autoScroll: true,
items: [new Ext.Panel({
id: 'login-panel',
title: 'Login',
frame: true,
collapsible: true,
titleCollapse: true
}), new Ext.Panel({
id: 'location-finder-panel',
title: 'Location Finder',
frame: true,
collapsible: true,
titleCollapse: true,
items: new Ext.TabPanel({
id: 'location-finder-tabs',
border: false,
tabPosition: 'top',
activeTab: 'location-browser-tab',
items: [{
id: 'location-search-tab',
title: 'Search'
},{
id: 'location-browser-tab',
title: 'Browse',
items: new Ext.tree.TreePanel({
id: 'location-browser-tree',
border: false,
loader: new Ext.tree.TreeLoader({
dataUrl: 'core/location-browser-tree.php',
listeners: {
beforeload: function(treeLoader, node) {
this.baseParams.recordtype = node.attributes.recordtype;
this.baseParams.recordid = node.attributes.recordid;
}
}
}),
root: new Ext.tree.AsyncTreeNode({
id: 'gazetteer-root-node',
recordtype: 'root',
recordid: 1,
text: GAZETTEER_ROOT,
expanded: true
})
})
}]
})
})]
},{
id: 'content',
region: 'center'
}]
});
});

wwarby
1 Jul 2008, 6:18 AM
Grrr. The indentation I so carefully put into my ASCII tree representation is gone. Hopefully my source code will be pretty easy to follow as regards to hierarchy.

Animal
1 Jul 2008, 7:00 AM
You are overnesting.

To put a TreePanel into a TabPanel just put the TreePanel in as a child item. Give it title: 'Browse', and just use it as a direct child item of the TabPanel.

It is a Panel's layout which sizes its child items. If you do not specify a layout, it will use the default ContainerLayout which does no sizing, just dumbly renders

wwarby
1 Jul 2008, 8:56 AM
Animal,

Thank you very much for the speedy and helpful reply. I have done as you suggested regarding the overnesting of the TreePanel inside a panel that acted as a tab (I didn't realise the TreePanel itself could become the tab). Unfortunately, the result was slightly worse than what I had before. Where previously the page loaded with the root node and child nodes of the tree visible, now only the root node starts visible. Using Firebug's DOM inspector I can see that the second level nodes are there, it's just that the container (now the TabPanel component) isn't resizing to accommodate changes in the tree nodes.

As per your advice regarding the container's layout controlling the sizes of it's children, I've tried every available option for the layout config option, both on the TabPanel and on the ViewPort region that contains the TabPanel. None had any effect on the problem. I can only think this is because the child object (the TreePanel) actually is being sized correctly, but it's the container which is not being sized to accommodate it's children, presumably because the container isn't aware of the new nodes coming in from the TreeLoader. Or I could be totally wrong. I'm confused!

Very grateful if you (or anyone else) could spare another minute to nudge me in the right direction.


Ext.onReady(function(){

Ext.state.Manager.setProvider(new Ext.state.CookieProvider());

var viewport = new Ext.Viewport({
layout: 'border',
items: [{
id: 'left',
region: 'west',
split: true,
width: 250,
minWidth: 150,
maxWidth: 350,
border: false,
autoScroll: true,
items: [new Ext.Panel({
id: 'login-panel',
title: 'Login',
frame: true,
collapsible: true,
titleCollapse: true
}), new Ext.Panel({
id: 'location-finder-panel',
title: 'Location Finder',
frame: true,
collapsible: true,
titleCollapse: true,
items: new Ext.TabPanel({
id: 'location-finder-tabs',
border: false,
tabPosition: 'top',
activeTab: 'location-browser-tree',
items: [{
id: 'location-search-tab',
title: 'Search'
},new Ext.tree.TreePanel({
id: 'location-browser-tree',
title: 'Browse',
border: false,
loader: new Ext.tree.TreeLoader({
dataUrl: 'core/location-browser-tree.php',
listeners: {
beforeload: function(treeLoader, node) {
this.baseParams.recordtype = node.attributes.recordtype;
this.baseParams.recordid = node.attributes.recordid;
}
}
}),
root: new Ext.tree.AsyncTreeNode({
id: 'gazetteer-root-node',
recordtype: 'root',
recordid: 1,
text: GAZETTEER_ROOT,
expanded: true
})
})]
})
})]
},{
id: 'content',
region: 'center'
}]
});
});

devnull
1 Jul 2008, 9:13 AM
I dont see a single layout config anywhere, except the viewport! you almost always want to have a layout other than the default container layout when a panel has child items. usually 'fit' layout is the best option for panels with one child panel. the best layout for multiple children depends on the desired look of the ui.

wwarby
1 Jul 2008, 9:48 AM
I dont see a single layout config anywhere, except the viewport! you almost always want to have a layout other than the default container layout when a panel has child items. usually 'fit' layout is the best option for panels with one child panel. the best layout for multiple children depends on the desired look of the ui.

I've taken all the layout configs out because none of them made the slightest difference, but trust me when I say that I've tried at least 50 combinations of putting one or more of them in the code. If I put one in the TabPanel object I get an error, presumably because TabPanels must implement the 'card' layout. 'fit' on the Viewport region forces the first of the two viewport panels (the "Login") one to the full size of the window, and 'fit' on the TreePanel has no effect.

The interface I'm trying to achieve is a left-docked task pane with several collapsible panels, each of which expands to accommodate it's contents, and one of which contains a tabbed dialog with a tree panel on one of the tabs. The tree is loaded lazily which is (I suspect) causing the problem. I'm looking at a way of forcing a resize by listening for the expandnode and collapsenode events and forcing the container resize using the setHeight() method. I think I'll be able to make this work, but I'm sure it isn't the right way of doing it...

Cheers for the advice - any more ideas?

devnull
1 Jul 2008, 10:48 AM
your left panel probably needs an accordian layout then, 'fit' is only for when there is one child item. take another look at the available layouts and decide based on their descriptions which one will be the best choice for each part of your ui. you are correct that tabPanel uses a default of 'card' and that is fine.

Animal
2 Jul 2008, 12:00 AM
Of course layout configs make a difference.

It's the layout manager that renders child items.

Some layout managers perform sizing of child items depending on the kind of layout they implement.

Using no layout manager means no sizing behaviour at all

You need to consider the layout of every Container in your structure.

And "{" ... "}" is a Container. Depending upon the settings of its Container, it probably equates to an Ext.Panel. So you need to consider what layout you require to to have.

Animal
2 Jul 2008, 12:02 AM
For example, how big should your TabPanel 'location-finder-tabs' be?

wwarby
2 Jul 2008, 1:12 AM
Animal, devnull,

Thank you very much for taking the time to offer your advice. Perhaps I was just applying layout in the wrong places, but it seemed that wherever I applied the layout the result was exactly the same. I'm inclined to think that the layout I wanted was actually very difficult to achieve - in any event, I'm working to a deadline and after two days of experimenting I decided to settle for a different user interface approach. I've switched to an accordion for the left region of the viewport and replaced my "search" and "browse" tabs with top level panels in the viewport region, and now at least it's working as expected.

Animal: I wanted the TabPanel 'location-finder-tabs' to adjust it's height automatically to accommodate it's contents rather than have any fixed height. The height of the contents would depend on the number of expanded nodes in the browse tab, or the contents of the search tab depending on which was selected.

Anyway, thanks again for the help, it's great to know that there's a community of experts ready to lend a hand when needed ;)

Animal
2 Jul 2008, 2:02 AM
A TabPanel sizes it's child items to fit whatever size it is set to.

That's because it uses CardLayout (look it up) which extends FitLayout (also look that up)

So those things you put in a TabPanel will depend on the sizing of thae TabPanel.

The TabPanel is in a no-layout Container which is in a no-layout Container.

You have to plan your layouts fully.