/** * A TabPanel with grouping support. */Ext.define('Ext.ux.GroupTabPanel', { extend: 'Ext.container.Container', alias: 'widget.grouptabpanel', requires:[ 'Ext.tree.Panel', 'Ext.ux.GroupTabRenderer' ], baseCls : Ext.baseCSSPrefix + 'grouptabpanel', /** * @event beforetabchange * Fires before a tab change (activated by {@link #setActiveTab}). Return false in any listener to cancel * the tabchange * @param {Ext.ux.GroupTabPanel} grouptabPanel The GroupTabPanel * @param {Ext.Component} newCard The card that is about to be activated * @param {Ext.Component} oldCard The card that is currently active */ /** * @event tabchange * Fires when a new tab has been activated (activated by {@link #setActiveTab}). * @param {Ext.ux.GroupTabPanel} grouptabPanel The GroupTabPanel * @param {Ext.Component} newCard The newly activated item * @param {Ext.Component} oldCard The previously active item */ /** * @event beforegroupchange * Fires before a group change (activated by {@link #setActiveGroup}). Return false in any listener to cancel * the groupchange * @param {Ext.ux.GroupTabPanel} grouptabPanel The GroupTabPanel * @param {Ext.Component} newGroup The root group card that is about to be activated * @param {Ext.Component} oldGroup The root group card that is currently active */ /** * @event groupchange * Fires when a new group has been activated (activated by {@link #setActiveGroup}). * @param {Ext.ux.GroupTabPanel} grouptabPanel The GroupTabPanel * @param {Ext.Component} newGroup The newly activated root group item * @param {Ext.Component} oldGroup The previously active root group item */ initComponent: function(config) { var me = this; Ext.apply(me, config); // Processes items to create the TreeStore and also set up // "this.cards" containing the actual card items. me.store = me.createTreeStore(); me.layout = { type: 'hbox', align: 'stretch' }; me.defaults = { border: false }; me.items = [{ xtype: 'treepanel', cls: 'x-tree-panel x-grouptabbar', width: 150, rootVisible: false, store: me.store, hideHeaders: true, animate: false, processEvent: Ext.emptyFn, border: false, plugins: [{ ptype: 'grouptabrenderer' }], viewConfig: { overItemCls: '', getRowClass: me.getRowClass }, columns: [{ xtype: 'treecolumn', sortable: false, dataIndex: 'text', flex: 1, renderer: function (value, cell, node, idx1, idx2, store, tree) { var cls = ''; if (node.parentNode && node.parentNode.parentNode === null) { cls += ' x-grouptab-first'; if (node.previousSibling) { cls += ' x-grouptab-prev'; } if (!node.get('expanded') || node.firstChild == null) { cls += ' x-grouptab-last'; } } else if (node.nextSibling === null) { cls += ' x-grouptab-last'; } else { cls += ' x-grouptab-center'; } if (node.data.activeTab) { cls += ' x-active-tab'; } cell.tdCls= 'x-grouptab'+ cls; return value; } }] }, { xtype: 'container', flex: 1, layout: 'card', activeItem: me.mainItem, baseCls: Ext.baseCSSPrefix + 'grouptabcontainer', items: me.cards }]; me.callParent(arguments); me.setActiveTab(me.activeTab); me.setActiveGroup(me.activeGroup); me.mon(me.down('treepanel').getSelectionModel(), 'select', me.onNodeSelect, me); }, getRowClass: function(node, rowIndex, rowParams, store) { var cls = ''; if (node.data.activeGroup) { cls += ' x-active-group'; } return cls; }, /** * @private * Node selection listener. */ onNodeSelect: function (selModel, node) { var me = this, currentNode = me.store.getRootNode(), parent; if (node.parentNode && node.parentNode.parentNode === null) { parent = node; } else { parent = node.parentNode; } if (me.setActiveGroup(parent.get('id')) === false || me.setActiveTab(node.get('id')) === false) { return false; } while (currentNode) { currentNode.set('activeTab', false); currentNode.set('activeGroup', false); currentNode = currentNode.firstChild || currentNode.nextSibling || currentNode.parentNode.nextSibling; } parent.set('activeGroup', true); parent.eachChild(function(child) { child.set('activeGroup', true); }); node.set('activeTab', true); selModel.view.refresh(); }, /** * Makes the given component active (makes it the visible card in the GroupTabPanel's CardLayout) * @param {Ext.Component} cmp The component to make active */ setActiveTab: function(cmp) { var me = this, newTab = cmp, oldTab; if(Ext.isString(cmp)) { newTab = Ext.getCmp(newTab); } if (newTab === me.activeTab) { return false; } oldTab = me.activeTab; if (me.fireEvent('beforetabchange', me, newTab, oldTab) !== false) { me.activeTab = newTab; if (me.rendered) { me.down('container[baseCls=' + Ext.baseCSSPrefix + 'grouptabcontainer' + ']').getLayout().setActiveItem(newTab); } me.fireEvent('tabchange', me, newTab, oldTab); } return true; }, /** * Makes the given group active * @param {Ext.Component} cmp The root component to make active. */ setActiveGroup: function(cmp) { var me = this, newGroup = cmp, oldGroup; if(Ext.isString(cmp)) { newGroup = Ext.getCmp(newGroup); } if (newGroup === me.activeGroup) { return true; } oldGroup = me.activeGroup; if (me.fireEvent('beforegroupchange', me, newGroup, oldGroup) !== false) { me.activeGroup = newGroup; me.fireEvent('groupchange', me, newGroup, oldGroup); } else { return false; } return true; }, /** * @private * Creates the TreeStore used by the GroupTabBar. */ createTreeStore: function() { var me = this, groups = me.prepareItems(me.items), data = { text: '.', children: [] }, cards = me.cards = []; me.activeGroup = me.activeGroup || 0; Ext.each(groups, function(groupItem, idx) { var leafItems = groupItem.items.items, rootItem = (leafItems[groupItem.mainItem] || leafItems[0]), groupRoot = { children: [] }; // Create the root node of the group groupRoot.id = rootItem.id; groupRoot.text = rootItem.title; groupRoot.iconCls = rootItem.iconCls; groupRoot.expanded = true; groupRoot.activeGroup = (me.activeGroup === idx); groupRoot.activeTab = groupRoot.activeGroup ? true : false; if (groupRoot.activeTab) { me.activeTab = groupRoot.id; } if (groupRoot.activeGroup) { me.mainItem = groupItem.mainItem || 0; me.activeGroup = groupRoot.id; } Ext.each(leafItems, function(leafItem) { // First node has been done if (leafItem.id !== groupRoot.id) { var child = { id: leafItem.id, leaf: true, text: leafItem.title, iconCls: leafItem.iconCls, activeGroup: groupRoot.activeGroup, activeTab: false }; groupRoot.children.push(child); } // Ensure the items do not get headers delete leafItem.title; delete leafItem.iconCls; cards.push(leafItem); }); data.children.push(groupRoot); }); return Ext.create('Ext.data.TreeStore', { fields: ['id', 'text', 'activeGroup', 'activeTab'], root: { expanded: true }, proxy: { type: 'memory', data: data } }); }, /** * Returns the item that is currently active inside this GroupTabPanel. * @return {Ext.Component/Number} The currently active item */ getActiveTab: function() { return this.activeTab; }, /** * Returns the root group item that is currently active inside this GroupTabPanel. * @return {Ext.Component/Number} The currently active root group item */ getActiveGroup: function() { return this.activeGroup; }});