2012-09-29 18 views
6

Mam panel z dwoma toolbars. Jak mogę zaimplementować niestandardową klasę do używania jako overflowHandler, która przeniesie komponenty do drugiego paska narzędzi na przepełnieniu pierwszego paska narzędzi?Implementacja niestandardowego przepełnienia pamięci w ExtJS 4

Próbowałem użyć kodu Ext.layout.container.boxOverflow.Menu, ale mój drugi pasek narzędzi po prostu się ukrywa.

Oto mój kod, który został wymieszany z toolbar overflow przykładem z dystrybucji ExtJS 4.

Ext.require(['Ext.window.Window', 'Ext.toolbar.Toolbar', 'Ext.menu.ColorPicker', 'Ext.form.field.Date']); 
Ext.onReady(function(){ 

    /** 
    * Override for implementing tbar2 
    */ 
    Ext.override(Ext.panel.Panel, { 
     bridgeToolbars : function() { 
      var toolbar; 
      this.callParent(arguments); 
      if (this.tbar2) { 
       if (Ext.isArray(this.tbar2)) { 
        toolbar = { 
         xtype : 'toolbar', 
         items : this.tbar2 
        }; 
       } 
       else if (!toolbar.xtype) { 
        toolbar.xtype = 'toolbar'; 
       } 
       toolbar.dock = 'top'; 
       toolbar.isTbar2 = true; 
       this.dockedItems = this.dockedItems.concat(toolbar); 
       this.tbar2 = null; 
      } 
     }, 
     onRender  : function() { 
      this.callParent(arguments); 
      var topBars = this.getDockedItems('toolbar[dock="top"]'), 
       i, 
       len; 
      for (i = 0, len = topBars.length; i < len; i++) { 
       if (topBars[i].isTbar2) { 
        this.tbar2 = topBars[i]; 
        break; 
       } 
      } 
     }, 
     /** 
     * Lazy creates new toolbar and returns it 
     * @param {Ext.panel.Panel} panel 
     * @param {String} position 
     * @return {Ext.toolbar.Toolbar} 
     */ 
     getDynamicTBar : function (position) { 
      var panel = this, 
       params, 
       tb; 
      position = position || 'top'; 
      if (position === 'tbar2') { 
       tb = panel.tbar2; 
       params = {dock : 'top', isTbar2 : true}; 
      } 
      else { 
       tb = panel.getDockedItems('toolbar[dock="' + position + '"]'); 
       params = {dock : position}; 
       if (tb.length > 0) { 
        tb = tb[0]; 
       } 
      } 
      if (!tb) { 
       console.log('created tb at ' + position); 
       tb = Ext.create('Ext.toolbar.Toolbar', params); 
       panel.addDocked(tb); 
      } 
      return tb; 
     } 
    }); 

    Ext.define('Ext.layout.container.boxOverflow.TBar2', { 
     extend : 'Ext.layout.container.boxOverflow.None', 

     constructor : function() { 
      this.tbar2Items = []; 
      return this.callParent(arguments); 
     }, 

     beginLayout : function (ownerContext) { 
      this.callParent(arguments); 
      this.clearOverflow(ownerContext); 
     }, 

     beginLayoutCycle : function (ownerContext, firstCycle) { 
      this.callParent(arguments); 
      if (!firstCycle) { 
       this.clearOverflow(ownerContext); 
       this.layout.cacheChildItems(ownerContext); 
      } 
     }, 

     getOverflowCls : function() { 
      return Ext.baseCSSPrefix + this.layout.direction + '-box-overflow-body'; 
     }, 

     _asLayoutRoot : { isRoot : true }, 

     clearOverflow : function() { 
      if (this.tbar2) { 
       this.tbar2.suspendLayouts(); 
       this.tbar2.hide(); 
       this.tbar2.resumeLayouts(this._asLayoutRoot); 
      } 
      this.tbar2Items.length = 0; 
     }, 

     handleOverflow : function (ownerContext) { 

      var me = this, 
       layout = me.layout, 
       owner = layout.owner, 
       names = layout.getNames(), 
       startProp = names.x, 
       sizeProp = names.width, 
       plan = ownerContext.state.boxPlan, 
       available = plan.targetSize[sizeProp], 
       childItems = ownerContext.childItems, 
       len = childItems.length, 
       childContext, 
       comp, i, props, 
       tbarOwner = owner.ownerCt; 
      owner.suspendLayouts(); 
      // Hide all items which are off the end, and store them to allow them to be restored 
      // before each layout operation. 
      me.tbar2Items.length = 0; 
      for (i = 0; i < len; i++) { 
       childContext = childItems[i]; 
       props = childContext.props; 
       if (props[startProp] + props[sizeProp] > available) { 
        comp = childContext.target; 
        me.tbar2Items.push(comp); 
        owner.remove(comp, false); 
       } 
      } 
      owner.resumeLayouts(); 
      if (!me.tbar2 && (tbarOwner instanceof Ext.panel.Panel)) { 
       me.tbar2 = tbarOwner.getDynamicTBar('tbar2'); 
      } 
      me.tbar2.suspendLayouts(); 
      me.tbar2.show(); 

      Ext.each(me.tbar2Items, function(item, index) { 
       me.tbar2.add(item); 
      }); 
      me.tbar2.resumeLayouts(me._asLayoutRoot); 
     } 

    }); 


    var handleAction = function(action){ 
     Ext.example.msg('<b>Action</b>', 'You clicked "' + action + '"'); 
    }; 

    var colorMenu = Ext.create('Ext.menu.ColorPicker', { 
     handler: function(cm, color){ 
      Ext.example.msg('Color Selected', '<span style="color:#' + color + ';">You choose {0}.</span>', color); 
     } 
    }); 

    var showDate = function(d, value) { 
     Ext.example.msg('<b>Action date</b>', 'You picked ' + Ext.Date.format(value, d.format)); 
    }; 

    var fromPicker = false; 

    Ext.create('Ext.window.Window', { 
     title: 'Standard', 
     closable: false, 
     height:250, 
     width: 500, 
     bodyStyle: 'padding:10px', 
     contentEl: 'content', 
     autoScroll: true, 
     tbar: Ext.create('Ext.toolbar.Toolbar', { 
      layout: { 
       overflowHandler: 'TBar2' 
      }, 
      items: [{ 
       xtype:'splitbutton', 
       text: 'Menu Button', 
       iconCls: 'add16', 
       handler: Ext.Function.pass(handleAction, 'Menu Button'), 
       menu: [{text: 'Menu Item 1', handler: Ext.Function.pass(handleAction, 'Menu Item 1')}] 
      },'-',{ 
       xtype:'splitbutton', 
       text: 'Cut', 
       iconCls: 'add16', 
       handler: Ext.Function.pass(handleAction, 'Cut'), 
       menu: [{text: 'Cut menu', handler: Ext.Function.pass(handleAction, 'Cut menu')}] 
      },{ 
       text: 'Copy', 
       iconCls: 'add16', 
       handler: Ext.Function.pass(handleAction, 'Copy') 
      },{ 
       text: 'Paste', 
       iconCls: 'add16', 
       menu: [{text: 'Paste menu', handler: Ext.Function.pass(handleAction, 'Paste menu')}] 
      },'-',{ 
       text: 'Format', 
       iconCls: 'add16', 
       handler: Ext.Function.pass(handleAction, 'Format') 
      },'->', { 
       fieldLabel: 'Action', 
       labelWidth: 70, 
       width: 180, 
       xtype: 'datefield', 
       labelSeparator: '', 
       enableKeyEvents: true, 
       listeners: { 
        expand: function(){ 
         fromPicker = true; 
        }, 
        collapse: function(){ 
         fromPicker = false; 
        }, 
        change: function(d, newVal, oldVal) { 
         if (fromPicker || !d.isVisible()) { 
          showDate(d, newVal); 
         } 
        }, 
        keypress: { 
         buffer: 500, 
         fn: function(field){ 
          var value = field.getValue(); 
          if (value !== null && field.isValid()) { 
           showDate(field, value); 
          } 
         } 
        } 
       } 
      }, { 
       text: 'Sell', 
       iconCls: 'money-down', 
       enableToggle: true, 
       toggleHandler: function(button, pressed) { 
        Ext.example.msg('<b>Action</b>', 'Right ToggleButton ' + (pressed ? 'Buy' : 'Sell')); 
        button.setText(pressed ? 'Buy' : 'Sell') 
        button.setIconCls(pressed ? 'money-up' : 'money-down') 
       } 
      }, { 
       text: 'Choose a Color', 
       menu: colorMenu // <-- submenu by reference 
      }] 
     }) 
    }).show(); 
}); 
+0

co dokładna wersja R u użyciu? – dbrin

+0

Moja wersja ExtJS to 4.1.2 –

Odpowiedz

3

Musimy wdrożyć overflowHandler do paska narzędzi układu, który będzie dodać drugi pasek i owija komponenty z pierwszego paska do sekundy kiedy im nie mogą być wyświetlane, ponieważ nie ma wystarczająco dużo szerokość pojemnika paska narzędzi. Po pierwsze, musimy nadpisać Ext.panel.Panel:

Ext4.override(Ext4.panel.Panel, { 
    bridgeToolbars: function() { 
     var toolbar; 
     this.callParent(arguments); 
     if (this.tbar2) { 
      if (Ext4.isArray(this.tbar2)) { 
       toolbar = { 
        xtype: 'toolbar', 
        items: this.tbar2 
       }; 
      } else if (!toolbar.xtype) { 
       toolbar.xtype = 'toolbar'; 
      } 
      toolbar.dock = 'top'; 
      toolbar.isTbar2 = true; 
      this.dockedItems = this.dockedItems.concat(toolbar); 
      this.tbar2 = null; 
     } 
    }, 
    onRender: function() { 
     this.callParent(arguments); 
     var topBars = this.getDockedItems('toolbar[dock="top"]'), 
      i, 
      len; 
     for (i = 0, len = topBars.length; i < len; i++) { 
      if (topBars[i].isTbar2) { 
       this.tbar2 = topBars[i]; 
       break; 
      } 
     } 
    }, 
    /** 
    * Creates, if not exists, and returns toolbar at passed position 
    * @param {Ext.panel.Panel} panel 
    * @param {String} position 
    * @return {Ext.toolbar.Toolbar} 
    */ 
    getDynamicTBar: function (position) { 
     var panel = this, 
      params, 
      tb; 
     position = position || 'top'; 
     if (position === 'tbar2') { 
      tb = panel.tbar2; 
      params = { 
       dock: 'top', 
       isTbar2: true, 
       layout: { 
        overflowHandler: 'Scroller' 
       } 
      }; 
     } else { 
      tb = panel.getDockedItems('toolbar[dock="' + position + '"]'); 
      params = { 
       dock: position 
      }; 
      if (tb.length > 0) { 
       tb = tb[0]; 
      } 
     } 
     if (!tb) { 
      tb = Ext4.create('Ext4.toolbar.Toolbar', params); 
      panel.addDocked(tb); 
      if (position === 'tbar2') { 
       panel.tbar2 = tb; 
      } 
     } 
     return tb; 
    } 
}); 

Następnie musimy stworzyć klasę Ext4.layout.container.boxOverflow.TBar2 (ma tak długą nazwę, ponieważ ExtJS przeszukuje handleOverflow (który jest instancją ciągu znaków) w zakodowanej na stałe przestrzeni nazw Ext4.layout.container.boxOverflow).

/** 
* @class Ext4.layout.container.boxOverflow.TBar2 
* Class for using as overflowHandler 
* @extends Ext.layout.container.boxOverflow.None 
*/ 
Ext4.define('Ext4.layout.container.boxOverflow.TBar2', { 
    extend: 'Ext4.layout.container.boxOverflow.None', 

    /** 
    * @private 
    * @property {Boolean} initialized 
    */ 
    initialized: false, 

    constructor: function() { 
     /** 
     * @private 
     * @property {Array} tbar2Items 
     * List of moved components 
     */ 
     this.tbar2Items = []; 
     return this.callParent(arguments); 
    }, 

    beginLayout: function (ownerContext) { 
     if (!this.initialized) { 
      this.layout.owner.ownerCt.on('afterlayout', this.createTBar2, this); 
      this.initialized = true; 
     } 
     this.callParent(arguments); 
     this.clearOverflow(ownerContext); 
    }, 

    beginLayoutCycle: function (ownerContext, firstCycle) { 
     this.callParent(arguments); 
     if (!firstCycle) { 
      this.clearOverflow(ownerContext); 
      this.layout.cacheChildItems(ownerContext); 
     } 
    }, 

    getOverflowCls: function() { 
     return Ext4.baseCSSPrefix + this.layout.direction + '-box-overflow-body'; 
    }, 

    /** 
    * @private 
    * @property {Object} _asLayoutRoot 
    */ 
    _asLayoutRoot: { 
     isRoot: true 
    }, 

    clearOverflow: function() { 
     // If afterlayout is not processing and tbar2 already created, 
     // we can to move components from tbar2 to first toolbar, because now 
     // there isn't any overflow 
     if (!this.processing && this.tbar2) { 
      this.tbar2.items.each(function (item) { 
       this.tbar1.add(item); 
       // change ui from saved property, or CSS will be incorrect 
       item.ui = item.origUI; 
      }, this); 
      this.tbar2.removeAll(false); 
      this.tbar2.hide(); 
     } 
     this.tbar2Items.length = 0; 
    }, 

    /** 
    * @private 
    * Creates tbar2 and does other routines 
    */ 
    createTBar2: function() { 
     // if afterlayout event is still processing, 
     // or we don't need to handle toolbar overflow, just return from function 
     if (this.processing || !this.doTbar2) { 
      return; 
     } 
     this.processing = true; 
     this.doTbar2 = false; 
     var me = this, 
      ownerContext = this.mOwnerContext, 
      layout = me.layout, 
      owner = layout.owner, 
      names = layout.getNames(), 
      startProp = names.x, 
      sizeProp = names.width, 
      plan = ownerContext.state.boxPlan, 
      available = plan.targetSize[sizeProp], 
      childItems = ownerContext.childItems, 
      len = childItems.length, 
      childContext, 
      comp, i, props, 
      tbarOwner = owner.ownerCt; 

     me.tbar1 = owner; 
     // save components which will be moved 
     owner.suspendLayouts(); 
     me.tbar2Items.length = 0; 
     for (i = 0; i < len; i++) { 
      childContext = childItems[i]; 
      props = childContext.props; 
      if (props[startProp] + props[sizeProp] > available) { 
       comp = childContext.target; 
       me.tbar2Items.push(comp); 
       // save original ui property 
       comp.origUI = comp.ui; 
       owner.remove(comp, false); 
      } 
     } 
     owner.resumeLayouts(); 

     // add tbar2 to the layout cycle (you can see very similar code in clearOverflow 
     // method of Ext.layout.container.boxOverflow.Menu) 
     tbarOwner.suspendLayouts(); 
     me.tbar2 = tbarOwner.getDynamicTBar('tbar2'); 
     me.tbar2.show(); 
     // moving components 
     Ext4.each(me.tbar2Items, function (item, index) { 
      me.tbar2.insert(index, item); 
      item.ui = item.origUI; 
     }); 
     tbarOwner.resumeLayouts(this._asLayoutRoot); 
     this.processing = false; 
    }, 

    handleOverflow: function (ownerContext) { 
     // set flag and store context for later using 
     this.doTbar2 = true; 
     this.mOwnerContext = ownerContext; 
    } 

}); 

Uwaga używam ExtJS 4 ładowania (bo w mojej aplikacji internetowej jest ExtJD 2.3 też), więc w kodzie trzeba chyba użyć Ext. zamiast Ext4.

Powiązane problemy