-
12 Jun 2012 6:22 AM #1
Questions on absolute layout
Questions on absolute layout
Hi,
i try to make an absolute layout. But i have a lot of problems with that. First i can not resize the browser the inner panels disappear.
This is my complete layout:
It is an viewport with fit layout which contains a form with absolute layout. I need this because i need a bbar and its not possible to place a bbar in a viewport. After creation the absolute panel conatins 3 inner panels and looks like this:Code:var viewport = Ext.create('Ext.container.Viewport', { title: 'Absolute Layout', layout: 'fit', listeners:{ resize: { fn: function(el) { // pwidth=el.getWidth()/5; // pheight=el.getHeight(); // Ext.getCmp('east').setPosition(0,0); // Ext.getCmp('east').setWidth(pwidth); // Ext.getCmp('east').setHeight(pheight); // Ext.getCmp('center').setPosition(pwidth,0); // Ext.getCmp('center').setWidth(pwidth); // Ext.getCmp('center').setHeight(pheight); // Ext.getCmp('west').setPosition(pwidth*2,0); // Ext.getCmp('west').setWidth(pwidth); // Ext.getCmp('west').setHeight(pheight); console.info("viewport width = " + pwidth); } } }, items : [ // need this for bbar mainForm = Ext.create('Ext.panel.Panel',{ xtype: 'panel', layout: 'absolute', //bbar: statusBar, items: [ east = Ext.create('Ext.panel.Panel',{ title: 'East Region', id: 'east', xtype: 'panel', layout: { type: 'vbox', align: 'stretch' }, anchor: '20% 100%', listeners:{ resize: { fn: function(el) { pwidth=el.up('viewport').getWidth(); pheight=el.up('viewport').getHeight(); //this.setHeight(pheight); //this.setPosition(0,0); this.setWidth(pwidth/5); console.info("east "+pwidth/5); } } }, collapsible: true, // make collapsible hideCollapseTool: true, collapseDirection : 'left', itemId: 'dummy-region-container' }), west = Ext.create('Ext.panel.Panel',{ title: 'West Region', id: 'west', xtype: 'panel', layout: { type: 'vbox', align: 'stretch' }, anchor: '20% 100%', listeners:{ resize: { fn: function(el) { pwidth=el.up('viewport').getWidth(); pheight=el.up('viewport').getHeight(); //this.setHeight(pheight); this.setPosition((pwidth/5)*2,0); this.setWidth(pwidth/5); console.info("west "+(pwidth/5)*2); } } }, collapsible: true, // make collapsible hideCollapseTool: true, collapseDirection : 'left', itemId: 'west-region-container' }), center = Ext.create('Ext.panel.Panel',{ title: 'Center Region', xtype: 'panel', id: 'center', anchor: '20% 100%', layout: { type: 'vbox', align: 'stretch' }, hideCollapseTool: true, collapseDirection : 'left', collapsible: true, // make collapsible listeners:{ resize: { fn: function(el) { pwidth=el.up('viewport').getWidth(); pheight=el.up('viewport').getHeight(); //this.setHeight(pheight); this.setPosition(pwidth/5,0); this.setWidth(pwidth/5); console.info("center "+pwidth/5); } } } })] })], renderTo: Ext.getBody() });
absolute.jpg
If i now resize the browser window center and west region disappear?!
I played with anchor and flex and the resize handler, but this is the best result i can produce.
Second problem is adding new panels. There is a lot of space on the right edge in this viewport. I need a way to add a panel dynamically on user request to the already existing mainForm.
What is necessary to add a panel to the mainForm?
If i add the panel in this way the layout gets corrupt and just one panel is visible.Code:var addPanel = Ext.create('Ext.panel.Panel', { title: 'add - One Region', hideCollapseTool: true, collapseDirection : 'right', collapsible: true, // make collapsible layout: { type: 'vbox', align: 'stretch' }, anchor: '20% 100%', flex: 1, html: 'new panel inside dummy' }); addPanel.setPosition(west.x+west.getWidth(),0); mainForm.insert(3, addPanel);
I need the absolute layout to animate/slide the inner panels. I played with the build in layouts from Sencha but the animations for collapse/expand/move are looking bad. So i think i have to do the positioning on my own. This is in 4.1.
Can anybody give me some help on this. Thanks!
-
13 Jun 2012 1:33 PM #2
I am not sure I understand your requirement .. I created small example based on your post, but it may be way off. Please make changes and reply accordingly.
Regards,Code:Ext.define('MyApp.view.MyViewport', { extend: 'Ext.container.Viewport', layout: { align: 'stretch', type: 'vbox' }, initComponent: function() { var me = this; Ext.applyIf(me, { items: [ { xtype: 'toolbar', items: [ { xtype: 'button', text: 'MyButton' } ] }, { xtype: 'container', layout: { align: 'stretch', type: 'hbox' }, flex: 1, items: [ { xtype: 'panel', title: 'My Panel', flex: 1 }, { xtype: 'panel', collapsible: true, title: 'My Panel', html: 'Collapsible Panel ??', flex: 1 }, { xtype: 'panel', title: 'My Panel', flex: 1 } ] } ] }); me.callParent(arguments); } }); Ext.create('MyApp.view.MyViewport', {});
Scott.
-
21 Jun 2012 5:59 AM #3
Hi Scott,
sorry for delay but this costs time. So please have a look at my code. This thing does nearly what i want. But i have a few questions on this.
As you see sliding looks nice. Maybe setDisable is not an optical beauty. Is there an nicer way to do this?Code:var collapseSize = 12;//26; Ext.onReady(function() { Ext.define('SliderToolbar', { extend: 'Ext.toolbar.Toolbar', alias: 'widget.slidertoolbar', anchor: 'bottom', region: 'south', height: 27, items: [ { //iconCls: 'pagenext', text: 'Press me!', handler: function() { } } ], constructor: function(config) { SliderToolbar.superclass.constructor.call(this, config); this.initConfig(config); return this; } }); var eastPanel = Ext.create('Ext.panel.Panel', { title: '4 four', hideCollapseTool: true, collapseDirection : 'right', collapsible: true, // make collapsible //flex: 1, style: 'z-index: 3', bbar: Ext.create('widget.slidertoolbar'), html: 'new added panel inside' }); var addPanel = Ext.create('Ext.panel.Panel', { title: '5 five', hideCollapseTool: true, collapseDirection : 'right', collapsible: true, // make collapsible //flex: 1, style: 'z-index: 4', bbar: Ext.create('widget.slidertoolbar'), html: 'new added panel no 5' }); var addPanel2 = Ext.create('Ext.panel.Panel', { title: '6 six', hideCollapseTool: true, collapseDirection : 'right', collapsible: true, // make collapsible style: 'z-index: 5', bbar: Ext.create('widget.slidertoolbar'), html: 'new added panel no 6' }); Ext.define('MyApp.view.MyViewport', { extend: 'Ext.container.Viewport', layout: { align: 'stretch', type: 'vbox' }, initComponent: function() { var me = this; Ext.applyIf(me, { items: [ { xtype: 'toolbar', anchor: 'bottom', region: 'south', items: [ { xtype: 'button', text: 'MyButton' } ] }, { id: 'oneContainer', xtype: 'container', layout: { align: 'stretch', type: 'hbox' }, flex: 1, listeners:{ resize: { fn: function(el, width, height, oldWidth, oldHeight, eOpts ) { var num = this.items.length; var cWidth = getCurrentWidth(); var currPos = 0; for(i=0;i<num;i++) { var itm = this.items.items[i]; itm.currentPos = currPos; if(itm.isDisabled()){ currPos = currPos + collapseSize; } else { currPos = currPos + cWidth; } if(itm.currentPos){ itm.setPosition(itm.currentPos,0); } itm.setWidth(cWidth); } // dont know why a anim is necessary?! for(i=0;i<num;i++){ Ext.create('Ext.fx.Anim', { target: this.items.items[i], duration: 0, from: { }, to: { left: this.items.items[i].currentPos?this.items.items[i].currentPos:0 } }); } console.info("resize panel"); } }, add: { fn: function(container, component, index, eOpts ){ if(this.rendered){ var num = this.items.length; if(num>2){ var pos = this.getWidth(); for(i=num;i>2;i--){ pos = pos - collapseSize; this.items.items[i-1].currentPos = pos; this.items.items[i-1].setDisabled(true); } pos = this.getWidth()-((num-2)*collapseSize); this.items.items[1].currentPos = pos/2; } var cWidth = getCurrentWidth(); for(i=0;i<=index;i++) { var itm = this.items.items[i]; if(itm.currentPos){ itm.setPosition(itm.currentPos,0); } itm.setWidth(cWidth); } // no idea why anim is necessary for(i=0;i<num;i++){ Ext.create('Ext.fx.Anim', { target: this.items.items[i], duration: 100, from: { }, to: { left: this.items.items[i].currentPos } }); } console.info("add panel " + index); } } } }, items: [ { id: 'oneOne', xtype: 'panel', title: '1 one', style: 'z-index: 0', collapsible: true, // make collapsible hideCollapseTool: true, collapseDirection : 'left' }, { id: 'oneTwo', xtype: 'panel', style: 'z-index: 1', collapsible: true, // make collapsible bbar: Ext.create('widget.slidertoolbar'), hideCollapseTool: true, collapseDirection : 'left', title: '2 two', html: 'i am 2' }, { id: 'twoOne', xtype: 'panel', title: '3 three', style: 'z-index: 2', collapsible: true, // make collapsible bbar: Ext.create('widget.slidertoolbar'), hideCollapseTool: true, collapseDirection : 'left' } ] } ] }); me.callParent(arguments); } }); function getCurrentWidth(){ var cmp = Ext.getCmp('oneContainer'); var num = cmp.items.length; return (cmp.getWidth()-((num-2)*collapseSize))/2; } var sliderfct = function(currIdx) { var container = Ext.getCmp('oneContainer'); var east = container.items.items[currIdx-1]; var center = container.items.items[currIdx]; var west = container.items.items[currIdx+1]; var num = container.items.length; var cWidth = getCurrentWidth(); if(center.x<=east.x+collapseSize) { east.setDisabled(false); center.currentPos = east.x+cWidth; if(west) { west.currentPos = east.x+2*cWidth; west.setDisabled(true); } for(i=1;i<num;i++){ Ext.create('Ext.fx.Anim', { target: container.items.items[i], duration: 500, from: { }, to: { left: container.items.items[i].currentPos } }); } } else { east.setDisabled(true); center.currentPos = east.x+collapseSize; if(west) { west.currentPos = east.x+collapseSize+cWidth; west.setDisabled(false); } for(i=1;i<num;i++){ Ext.create('Ext.fx.Anim', { target: container.items.items[i], duration: 500, from: { }, to: { left: container.items.items[i].currentPos } }); } } } Ext.create('MyApp.view.MyViewport', {}); var scenter = Ext.getCmp('oneTwo').down('toolbar').down('button'); if(scenter) { scenter.on('click', function(){sliderfct(1)} ); } scenter = Ext.getCmp('twoOne').down('toolbar').down('button'); if(scenter) { scenter.on('click', function(){sliderfct(2)} ); } Ext.getCmp('oneContainer').add(eastPanel); scenter = eastPanel.down('toolbar').down('button'); if(scenter) { scenter.on('click', function(){sliderfct(3)} ); } Ext.getCmp('oneContainer').add(addPanel); scenter = addPanel.down('toolbar').down('button'); if(scenter) { scenter.on('click', function(){sliderfct(4)} ); } Ext.getCmp('oneContainer').add(addPanel2); scenter = addPanel2.down('toolbar').down('button'); if(scenter) { scenter.on('click', function(){sliderfct(5)} ); } });
Adding new panels during runtime is possible.
There are two listeners. Resize and add but i think there is something missing?
I am using animations in these listeners to set the position. This is ugly, is there another way to do this?
Now i integrated this new sliding in my prototype. Ready for some entertainment?
http://screencast.com/t/Eo1gVc1IM
The problem is the thing i called navigationbar. Did you see that thing with blue text just above the panels. It is a toolbar with text items in the form with the sliding panels. It gets an update with each selectionchange in the grids. If the panels are in starting position everthing is fine. But if you are somewhere in the middle and update one of these text items with setText the layout gets corrupt. Looks like it takes the calculated layout not mine.
I debugged but i couldn't find a listener in flush dom. I tested with suspendLayout : true but i couldn't get a good result.
Are there one or two more listeners necessary?
I have no more idea. Can you give me some help!
Regards
-
22 Jun 2012 4:45 AM #4
Hi,
i added this navigationbar to my example. As you see sliding stopps at panel #3. Maybe this makes it easier to reproduce this issue.
and css:Code:var collapseSize = 12;//26; Ext.onReady(function() { Ext.define('LinkLabel', { extend: 'Ext.form.Label', alias: 'widget.linklabel', config: { cls: 'link-label', overCls: 'link-label-over', clickListener: null }, constructor: function(config) { LinkLabel.superclass.constructor.call(this, config); this.initConfig(config); return this; }, listeners:{ scope: this, 'render': function(c) { c.getEl().on('click', function() { //logInfo("click"); if(this.clickListener) { this.clickListener(this); } }, c); } } }); Ext.define('SliderToolbar', { extend: 'Ext.toolbar.Toolbar', alias: 'widget.slidertoolbar', anchor: 'bottom', region: 'south', height: 27, items: [ { //iconCls: 'pagenext', text: 'Press me!', handler: function() { } } ], constructor: function(config) { SliderToolbar.superclass.constructor.call(this, config); this.initConfig(config); return this; } }); var eastPanel = Ext.create('Ext.panel.Panel', { title: '4 four', hideCollapseTool: true, collapseDirection : 'right', collapsible: true, // make collapsible //flex: 1, style: 'z-index: 3', bbar: Ext.create('widget.slidertoolbar'), html: 'new added panel inside' }); var addPanel = Ext.create('Ext.panel.Panel', { title: '5 five', hideCollapseTool: true, collapseDirection : 'right', collapsible: true, // make collapsible //flex: 1, style: 'z-index: 4', bbar: Ext.create('widget.slidertoolbar'), html: 'new added panel no 5' }); var addPanel2 = Ext.create('Ext.panel.Panel', { title: '6 six', hideCollapseTool: true, collapseDirection : 'right', collapsible: true, // make collapsible style: 'z-index: 5', bbar: Ext.create('widget.slidertoolbar'), html: 'new added panel no 6' }); Ext.define('MyApp.view.MyViewport', { extend: 'Ext.container.Viewport', layout: { align: 'stretch', type: 'vbox' }, initComponent: function() { var me = this; Ext.applyIf(me, { items: [ { id: 'oneContainer', xtype: 'panel',//container', layout: { align: 'stretch', type: 'hbox' }, flex: 1, listeners:{ resize: { fn: function(el, width, height, oldWidth, oldHeight, eOpts ) { var num = this.items.length; var cWidth = getCurrentWidth(); var currPos = 0; for(i=0;i<num;i++) { var itm = this.items.items[i]; itm.currentPos = currPos; if(itm.isDisabled()){ currPos = currPos + collapseSize; } else { currPos = currPos + cWidth; } if(itm.currentPos){ itm.setPosition(itm.currentPos,0); } itm.setWidth(cWidth); } // dont know why a anim is necessary?! for(i=0;i<num;i++){ Ext.create('Ext.fx.Anim', { target: this.items.items[i], duration: 0, from: { }, to: { left: this.items.items[i].currentPos?this.items.items[i].currentPos:0 } }); } console.info("resize panel"); } }, add: { fn: function(container, component, index, eOpts ){ if(this.rendered){ var num = this.items.length; if(num>2){ var pos = this.getWidth(); for(i=num;i>2;i--){ pos = pos - collapseSize; this.items.items[i-1].currentPos = pos; this.items.items[i-1].setDisabled(true); } pos = this.getWidth()-((num-2)*collapseSize); this.items.items[1].currentPos = pos/2; } var cWidth = getCurrentWidth(); for(i=0;i<=index;i++) { var itm = this.items.items[i]; if(itm.currentPos){ itm.setPosition(itm.currentPos,0); } itm.setWidth(cWidth); } // no idea why anim is necessary for(i=0;i<num;i++){ Ext.create('Ext.fx.Anim', { target: this.items.items[i], duration: 100, from: { }, to: { left: this.items.items[i].currentPos } }); } console.info("add panel " + index); } } } }, tbar: { xtype: 'toolbar', anchor: 'bottom', region: 'south', items: [ { xtype: 'tbspacer', width: 10 }, {itemId: '0', xtype: 'linklabel', text:"✪"}, { xtype: 'tbspacer', width: 10 }, {itemId: '1', xtype: 'linklabel', text:"✪"}, { xtype: 'tbspacer', width: 10 }, {itemId: '2', xtype: 'linklabel', text:"✪"}, { xtype: 'tbspacer', width: 10 }, {itemId: '3', xtype: 'linklabel', text:"✪"}, { xtype: 'tbspacer', width: 10 }, {itemId: '4', xtype: 'linklabel', text:"✪"}, { xtype: 'tbspacer', width: 10 }, {itemId: '5', xtype: 'linklabel', text:"✪"}, ] }, items: [ { id: 'oneOne', xtype: 'panel', title: '1 one', style: 'z-index: 0', collapsible: true, // make collapsible hideCollapseTool: true, collapseDirection : 'left' }, { id: 'oneTwo', xtype: 'panel', style: 'z-index: 1', collapsible: true, // make collapsible bbar: Ext.create('widget.slidertoolbar'), hideCollapseTool: true, collapseDirection : 'left', title: '2 two', html: 'i am 2' }, { id: 'twoOne', xtype: 'panel', title: '3 three', style: 'z-index: 2', collapsible: true, // make collapsible bbar: Ext.create('widget.slidertoolbar'), hideCollapseTool: true, collapseDirection : 'left' } ] } ] }); me.callParent(arguments); } }); function getCurrentWidth(){ var cmp = Ext.getCmp('oneContainer'); var num = cmp.items.length; return (cmp.getWidth()-((num-2)*collapseSize))/2; } var sliderfct = function(currIdx) { var container = Ext.getCmp('oneContainer'); var east = container.items.items[currIdx-1]; var center = container.items.items[currIdx]; var west = container.items.items[currIdx+1]; var num = container.items.length; var cWidth = getCurrentWidth(); container.down('toolbar').down('#' + (currIdx-1).toString()).setText('✪'); container.down('toolbar').down('#' + (currIdx).toString()).setText('⇓'); container.down('toolbar').down('#' + (currIdx+1).toString()).setText('✪'); if(center.x<=east.x+collapseSize) { east.setDisabled(false); center.currentPos = east.x+cWidth; if(west) { west.currentPos = east.x+2*cWidth; west.setDisabled(true); } for(i=1;i<num;i++){ Ext.create('Ext.fx.Anim', { target: container.items.items[i], duration: 500, from: { }, to: { left: container.items.items[i].currentPos } }); } } else { east.setDisabled(true); center.currentPos = east.x+collapseSize; if(west) { west.currentPos = east.x+collapseSize+cWidth; west.setDisabled(false); } for(i=1;i<num;i++){ Ext.create('Ext.fx.Anim', { target: container.items.items[i], duration: 500, from: { }, to: { left: container.items.items[i].currentPos } }); } } } Ext.create('MyApp.view.MyViewport', {}); var scenter = Ext.getCmp('oneTwo').down('toolbar').down('button'); if(scenter) { scenter.on('click', function(){sliderfct(1)} ); } scenter = Ext.getCmp('twoOne').down('toolbar').down('button'); if(scenter) { scenter.on('click', function(){sliderfct(2)} ); } Ext.getCmp('oneContainer').add(eastPanel); scenter = eastPanel.down('toolbar').down('button'); if(scenter) { scenter.on('click', function(){sliderfct(3)} ); } Ext.getCmp('oneContainer').add(addPanel); scenter = addPanel.down('toolbar').down('button'); if(scenter) { scenter.on('click', function(){sliderfct(4)} ); } Ext.getCmp('oneContainer').add(addPanel2); scenter = addPanel2.down('toolbar').down('button'); if(scenter) { scenter.on('click', function(){sliderfct(5)} ); } });
Is there a tool available to see what events are fired during runtime? I just know page-analyzer. But no success with that.Code:<style type="text/css"> .link-label { color: blue; text-decoration: underline; } .link-label-over { color: lightblue; cursor: pointer; } </style>
I try a few listeners like afterlayout/afterrender but this results in endless loops. Is there a better description available what to do and what not to do in these listeners?

-
27 Jun 2012 6:09 AM #5
Hi,
no solution for this? Or is it too complicated? Hello you techs from Sencha!
If i am sending an event with each setText and doing all the stuff same as the resize listener with positioning and size of the panels it becomes super slow. It helps a little to update these positions just when its necessary. But it looks bad because the panels first take the wrong position and than move back. I think the best would be not to take the 'wrong' positions at all!
Is there no way to avoid this? Is there an option to hbox + stretch layout?
-
27 Jun 2012 6:55 AM #6
The issue here is that it will take some time for someone to perform a "code review" of your custom functions in your application ... as I would say this simply needs to be tweaked.
I do not see the slowness you are speaking of in the working example you provided. Panels move freely back and forth.
Scott.


Reply With Quote