Upgrade to ExtJS 3.2.0 - Released 03/30/2010
[extjs.git] / examples / desktop / js / TaskBar.js
index bfbb787..ce6c5ab 100644 (file)
 /*!
- * Ext JS Library 3.1.1
- * Copyright(c) 2006-2010 Ext JS, LLC
+ * Ext JS Library 3.2.0
+ * Copyright(c) 2006-2010 Ext JS, Inc.
  * licensing@extjs.com
  * http://www.extjs.com/license
  */
-/**\r
- * @class Ext.ux.TaskBar\r
- * @extends Ext.util.Observable\r
- */\r
-Ext.ux.TaskBar = function(app){\r
-    this.app = app;\r
-    this.init();\r
-}\r
-\r
-Ext.extend(Ext.ux.TaskBar, Ext.util.Observable, {\r
-    init : function(){\r
-        this.startMenu = new Ext.ux.StartMenu(Ext.apply({\r
-            iconCls: 'user',\r
-            height: 300,\r
-            shadow: true,\r
-            title: 'Jack Slocum',\r
-            width: 300\r
-        }, this.app.startConfig));\r
-\r
-        this.startBtn = new Ext.Button({\r
-            text: 'Start',\r
-            id: 'ux-startbutton',\r
-            iconCls:'start',\r
-            menu: this.startMenu,\r
-            menuAlign: 'bl-tl',\r
-            renderTo: 'ux-taskbar-start',\r
-            clickEvent: 'mousedown',\r
-            template: new Ext.Template(\r
-                '<table cellspacing="0" class="x-btn {3}"><tbody><tr>',\r
-                '<td class="ux-startbutton-left"><i>&#160;</i></td>',\r
-                '<td class="ux-startbutton-center"><em class="{5} unselectable="on">',\r
-                    '<button class="x-btn-text {2}" type="{1}" style="height:30px;">{0}</button>',\r
-                '</em></td>',\r
-                '<td class="ux-startbutton-right"><i>&#160;</i></td>',\r
-                "</tr></tbody></table>")\r
-        });\r
-\r
-        var width = this.startBtn.getEl().getWidth()+10;\r
-\r
-        var sbBox = new Ext.BoxComponent({\r
-            el: 'ux-taskbar-start',\r
-            id: 'TaskBarStart',\r
-            minWidth: width,\r
-            region:'west',\r
-            split: true,\r
-            width: width\r
-        });\r
-\r
-        this.tbPanel = new Ext.ux.TaskButtonsPanel({\r
-            el: 'ux-taskbuttons-panel',\r
-            id: 'TaskBarButtons',\r
-            region:'center'\r
-        });\r
-\r
-        var container = new Ext.ux.TaskBarContainer({\r
-            el: 'ux-taskbar',\r
-            layout: 'border',\r
-            items: [sbBox,this.tbPanel]\r
-        });\r
-\r
-        return this;\r
-    },\r
-\r
-    addTaskButton : function(win){\r
-        return this.tbPanel.addButton(win, 'ux-taskbuttons-panel');\r
-    },\r
-\r
-    removeTaskButton : function(btn){\r
-        this.tbPanel.removeButton(btn);\r
-    },\r
-\r
-    setActiveButton : function(btn){\r
-        this.tbPanel.setActiveButton(btn);\r
-    }\r
-});\r
-\r
-\r
-\r
-/**\r
- * @class Ext.ux.TaskBarContainer\r
- * @extends Ext.Container\r
- */\r
-Ext.ux.TaskBarContainer = Ext.extend(Ext.Container, {\r
-    initComponent : function() {\r
-        Ext.ux.TaskBarContainer.superclass.initComponent.call(this);\r
-\r
-        this.el = Ext.get(this.el) || Ext.getBody();\r
-        this.el.setHeight = Ext.emptyFn;\r
-        this.el.setWidth = Ext.emptyFn;\r
-        this.el.setSize = Ext.emptyFn;\r
-        this.el.setStyle({\r
-            overflow:'hidden',\r
-            margin:'0',\r
-            border:'0 none'\r
-        });\r
-        this.el.dom.scroll = 'no';\r
-        this.allowDomMove = false;\r
-        this.autoWidth = true;\r
-        this.autoHeight = true;\r
-        Ext.EventManager.onWindowResize(this.fireResize, this);\r
-        this.renderTo = this.el;\r
-    },\r
-\r
-    fireResize : function(w, h){\r
-        this.onResize(w, h, w, h);\r
-    }\r
-});\r
-\r
-\r
-\r
-/**\r
- * @class Ext.ux.TaskButtonsPanel\r
- * @extends Ext.BoxComponent\r
- */\r
-Ext.ux.TaskButtonsPanel = Ext.extend(Ext.BoxComponent, {\r
-    activeButton: null,\r
-    enableScroll: true,\r
-    scrollIncrement: 0,\r
-    scrollRepeatInterval: 400,\r
-    scrollDuration: .35,\r
-    animScroll: true,\r
-    resizeButtons: true,\r
-    buttonWidth: 168,\r
-    minButtonWidth: 118,\r
-    buttonMargin: 2,\r
-    buttonWidthSet: false,\r
-\r
-    initComponent : function() {\r
-        Ext.ux.TaskButtonsPanel.superclass.initComponent.call(this);\r
-        this.on('resize', this.delegateUpdates);\r
-        this.items = [];\r
-\r
-        this.stripWrap = Ext.get(this.el).createChild({\r
-            cls: 'ux-taskbuttons-strip-wrap',\r
-            cn: {\r
-                tag:'ul', cls:'ux-taskbuttons-strip'\r
-            }\r
-        });\r
-        this.stripSpacer = Ext.get(this.el).createChild({\r
-            cls:'ux-taskbuttons-strip-spacer'\r
-        });\r
-        this.strip = new Ext.Element(this.stripWrap.dom.firstChild);\r
-\r
-        this.edge = this.strip.createChild({\r
-            tag:'li',\r
-            cls:'ux-taskbuttons-edge'\r
-        });\r
-        this.strip.createChild({\r
-            cls:'x-clear'\r
-        });\r
-    },\r
-\r
-    addButton : function(win){\r
-        var li = this.strip.createChild({tag:'li'}, this.edge); // insert before the edge\r
-        var btn = new Ext.ux.TaskBar.TaskButton(win, li);\r
-\r
-        this.items.push(btn);\r
-\r
-        if(!this.buttonWidthSet){\r
-            this.lastButtonWidth = btn.container.getWidth();\r
-        }\r
-\r
-        this.setActiveButton(btn);\r
-        return btn;\r
-    },\r
-\r
-    removeButton : function(btn){\r
-        var li = document.getElementById(btn.container.id);\r
-        btn.destroy();\r
-        li.parentNode.removeChild(li);\r
-\r
-        var s = [];\r
-        for(var i = 0, len = this.items.length; i < len; i++) {\r
-            if(this.items[i] != btn){\r
-                s.push(this.items[i]);\r
-            }\r
-        }\r
-        this.items = s;\r
-\r
-        this.delegateUpdates();\r
-    },\r
-\r
-    setActiveButton : function(btn){\r
-        this.activeButton = btn;\r
-        this.delegateUpdates();\r
-    },\r
-\r
-    delegateUpdates : function(){\r
-        /*if(this.suspendUpdates){\r
-            return;\r
-        }*/\r
-        if(this.resizeButtons && this.rendered){\r
-            this.autoSize();\r
-        }\r
-        if(this.enableScroll && this.rendered){\r
-            this.autoScroll();\r
-        }\r
-    },\r
-\r
-    autoSize : function(){\r
-        var count = this.items.length;\r
-        var ow = this.el.dom.offsetWidth;\r
-        var aw = this.el.dom.clientWidth;\r
-\r
-        if(!this.resizeButtons || count < 1 || !aw){ // !aw for display:none\r
-            return;\r
-        }\r
-\r
-        var each = Math.max(Math.min(Math.floor((aw-4) / count) - this.buttonMargin, this.buttonWidth), this.minButtonWidth); // -4 for float errors in IE\r
-        var btns = this.stripWrap.dom.getElementsByTagName('button');\r
-\r
-        this.lastButtonWidth = Ext.get(btns[0].id).findParent('li').offsetWidth;\r
-\r
-        for(var i = 0, len = btns.length; i < len; i++) {\r
-            var btn = btns[i];\r
-\r
-            var tw = Ext.get(btns[i].id).findParent('li').offsetWidth;\r
-            var iw = btn.offsetWidth;\r
-\r
-            btn.style.width = (each - (tw-iw)) + 'px';\r
-        }\r
-    },\r
-\r
-    autoScroll : function(){\r
-        var count = this.items.length;\r
-        var ow = this.el.dom.offsetWidth;\r
-        var tw = this.el.dom.clientWidth;\r
-\r
-        var wrap = this.stripWrap;\r
-        var cw = wrap.dom.offsetWidth;\r
-        var pos = this.getScrollPos();\r
-        var l = this.edge.getOffsetsTo(this.stripWrap)[0] + pos;\r
-\r
-        if(!this.enableScroll || count < 1 || cw < 20){ // 20 to prevent display:none issues\r
-            return;\r
-        }\r
-\r
-        wrap.setWidth(tw); // moved to here because of problem in Safari\r
-\r
-        if(l <= tw){\r
-            wrap.dom.scrollLeft = 0;\r
-            //wrap.setWidth(tw); moved from here because of problem in Safari\r
-            if(this.scrolling){\r
-                this.scrolling = false;\r
-                this.el.removeClass('x-taskbuttons-scrolling');\r
-                this.scrollLeft.hide();\r
-                this.scrollRight.hide();\r
-            }\r
-        }else{\r
-            if(!this.scrolling){\r
-                this.el.addClass('x-taskbuttons-scrolling');\r
-            }\r
-            tw -= wrap.getMargins('lr');\r
-            wrap.setWidth(tw > 20 ? tw : 20);\r
-            if(!this.scrolling){\r
-                if(!this.scrollLeft){\r
-                    this.createScrollers();\r
-                }else{\r
-                    this.scrollLeft.show();\r
-                    this.scrollRight.show();\r
-                }\r
-            }\r
-            this.scrolling = true;\r
-            if(pos > (l-tw)){ // ensure it stays within bounds\r
-                wrap.dom.scrollLeft = l-tw;\r
-            }else{ // otherwise, make sure the active button is still visible\r
-                this.scrollToButton(this.activeButton, true); // true to animate\r
-            }\r
-            this.updateScrollButtons();\r
-        }\r
-    },\r
-\r
-    createScrollers : function(){\r
-        var h = this.el.dom.offsetHeight; //var h = this.stripWrap.dom.offsetHeight;\r
-\r
-        // left\r
-        var sl = this.el.insertFirst({\r
-            cls:'ux-taskbuttons-scroller-left'\r
-        });\r
-        sl.setHeight(h);\r
-        sl.addClassOnOver('ux-taskbuttons-scroller-left-over');\r
-        this.leftRepeater = new Ext.util.ClickRepeater(sl, {\r
-            interval : this.scrollRepeatInterval,\r
-            handler: this.onScrollLeft,\r
-            scope: this\r
-        });\r
-        this.scrollLeft = sl;\r
-\r
-        // right\r
-        var sr = this.el.insertFirst({\r
-            cls:'ux-taskbuttons-scroller-right'\r
-        });\r
-        sr.setHeight(h);\r
-        sr.addClassOnOver('ux-taskbuttons-scroller-right-over');\r
-        this.rightRepeater = new Ext.util.ClickRepeater(sr, {\r
-            interval : this.scrollRepeatInterval,\r
-            handler: this.onScrollRight,\r
-            scope: this\r
-        });\r
-        this.scrollRight = sr;\r
-    },\r
-\r
-    getScrollWidth : function(){\r
-        return this.edge.getOffsetsTo(this.stripWrap)[0] + this.getScrollPos();\r
-    },\r
-\r
-    getScrollPos : function(){\r
-        return parseInt(this.stripWrap.dom.scrollLeft, 10) || 0;\r
-    },\r
-\r
-    getScrollArea : function(){\r
-        return parseInt(this.stripWrap.dom.clientWidth, 10) || 0;\r
-    },\r
-\r
-    getScrollAnim : function(){\r
-        return {\r
-            duration: this.scrollDuration,\r
-            callback: this.updateScrollButtons,\r
-            scope: this\r
-        };\r
-    },\r
-\r
-    getScrollIncrement : function(){\r
-        return (this.scrollIncrement || this.lastButtonWidth+2);\r
-    },\r
-\r
-    /* getBtnEl : function(item){\r
-        return document.getElementById(item.id);\r
-    }, */\r
-\r
-    scrollToButton : function(item, animate){\r
-        item = item.el.dom.parentNode; // li\r
-        if(!item){ return; }\r
-        var el = item; //this.getBtnEl(item);\r
-        var pos = this.getScrollPos(), area = this.getScrollArea();\r
-        var left = Ext.fly(el).getOffsetsTo(this.stripWrap)[0] + pos;\r
-        var right = left + el.offsetWidth;\r
-        if(left < pos){\r
-            this.scrollTo(left, animate);\r
-        }else if(right > (pos + area)){\r
-            this.scrollTo(right - area, animate);\r
-        }\r
-    },\r
-\r
-    scrollTo : function(pos, animate){\r
-        this.stripWrap.scrollTo('left', pos, animate ? this.getScrollAnim() : false);\r
-        if(!animate){\r
-            this.updateScrollButtons();\r
-        }\r
-    },\r
-\r
-    onScrollRight : function(){\r
-        var sw = this.getScrollWidth()-this.getScrollArea();\r
-        var pos = this.getScrollPos();\r
-        var s = Math.min(sw, pos + this.getScrollIncrement());\r
-        if(s != pos){\r
-            this.scrollTo(s, this.animScroll);\r
-        }\r
-    },\r
-\r
-    onScrollLeft : function(){\r
-        var pos = this.getScrollPos();\r
-        var s = Math.max(0, pos - this.getScrollIncrement());\r
-        if(s != pos){\r
-            this.scrollTo(s, this.animScroll);\r
-        }\r
-    },\r
-\r
-    updateScrollButtons : function(){\r
-        var pos = this.getScrollPos();\r
-        this.scrollLeft[pos == 0 ? 'addClass' : 'removeClass']('ux-taskbuttons-scroller-left-disabled');\r
-        this.scrollRight[pos >= (this.getScrollWidth()-this.getScrollArea()) ? 'addClass' : 'removeClass']('ux-taskbuttons-scroller-right-disabled');\r
-    }\r
-});\r
-\r
-\r
-\r
-/**\r
- * @class Ext.ux.TaskBar.TaskButton\r
- * @extends Ext.Button\r
- */\r
-Ext.ux.TaskBar.TaskButton = function(win, el){\r
-    this.win = win;\r
-    Ext.ux.TaskBar.TaskButton.superclass.constructor.call(this, {\r
-        iconCls: win.iconCls,\r
-        text: Ext.util.Format.ellipsis(win.title, 12),\r
-        renderTo: el,\r
-        handler : function(){\r
-            if(win.minimized || win.hidden){\r
-                win.show();\r
-            }else if(win == win.manager.getActive()){\r
-                win.minimize();\r
-            }else{\r
-                win.toFront();\r
-            }\r
-        },\r
-        clickEvent:'mousedown',\r
-        template: new Ext.Template(\r
-            '<table cellspacing="0" class="x-btn {3}"><tbody><tr>',\r
-            '<td class="ux-taskbutton-left"><i>&#160;</i></td>',\r
-            '<td class="ux-taskbutton-center"><em class="{5} unselectable="on">',\r
-                '<button class="x-btn-text {2}" type="{1}" style="height:28px;">{0}</button>',\r
-            '</em></td>',\r
-            '<td class="ux-taskbutton-right"><i>&#160;</i></td>',\r
-            "</tr></tbody></table>")\r
-    });\r
-};\r
-\r
-Ext.extend(Ext.ux.TaskBar.TaskButton, Ext.Button, {\r
-    onRender : function(){\r
-        Ext.ux.TaskBar.TaskButton.superclass.onRender.apply(this, arguments);\r
-\r
-        this.cmenu = new Ext.menu.Menu({\r
-            items: [{\r
-                text: 'Restore',\r
-                handler: function(){\r
-                    if(!this.win.isVisible()){\r
-                        this.win.show();\r
-                    }else{\r
-                        this.win.restore();\r
-                    }\r
-                },\r
-                scope: this\r
-            },{\r
-                text: 'Minimize',\r
-                handler: this.win.minimize,\r
-                scope: this.win\r
-            },{\r
-                text: 'Maximize',\r
-                handler: this.win.maximize,\r
-                scope: this.win\r
-            }, '-', {\r
-                text: 'Close',\r
-                handler: this.closeWin.createDelegate(this, this.win, true),\r
-                scope: this.win\r
-            }]\r
-        });\r
-\r
-        this.cmenu.on('beforeshow', function(){\r
-            var items = this.cmenu.items.items;\r
-            var w = this.win;\r
-            items[0].setDisabled(w.maximized !== true && w.hidden !== true);\r
-            items[1].setDisabled(w.minimized === true);\r
-            items[2].setDisabled(w.maximized === true || w.hidden === true);\r
-        }, this);\r
-\r
-        this.el.on('contextmenu', function(e){\r
-            e.stopEvent();\r
-            if(!this.cmenu.el){\r
-                this.cmenu.render();\r
-            }\r
-            var xy = e.getXY();\r
-            xy[1] -= this.cmenu.el.getHeight();\r
-            this.cmenu.showAt(xy);\r
-        }, this);\r
-    },\r
-\r
-    closeWin : function(cMenu, e, win){\r
-        if(!win.isVisible()){\r
-            win.show();\r
-        }else{\r
-            win.restore();\r
-        }\r
-        win.close();\r
-    }\r
+/**
+ * @class Ext.ux.TaskBar
+ * @extends Ext.util.Observable
+ */
+Ext.ux.TaskBar = function(app){
+    this.app = app;
+    this.init();
+}
+
+Ext.extend(Ext.ux.TaskBar, Ext.util.Observable, {
+    init : function(){
+        this.startMenu = new Ext.ux.StartMenu(Ext.apply({
+            iconCls: 'user',
+            height: 300,
+            shadow: true,
+            title: 'Jack Slocum',
+            width: 300
+        }, this.app.startConfig));
+
+        this.startBtn = new Ext.Button({
+            text: 'Start',
+            id: 'ux-startbutton',
+            iconCls:'start',
+            menu: this.startMenu,
+            menuAlign: 'bl-tl',
+            renderTo: 'ux-taskbar-start',
+            clickEvent: 'mousedown',
+            template: new Ext.Template(
+                '<table cellspacing="0" class="x-btn"><tbody class="{1}"><tr>',
+                '<td class="ux-startbutton-left"><i>&#160;</i></td>',
+                '<td class="ux-startbutton-center"><em class="{2} unselectable="on">',
+                    '<button class="x-btn-text" type="{0}" style="height:30px;"></button>',
+                '</em></td>',
+                '<td class="ux-startbutton-right"><i>&#160;</i></td>',
+                '</tr></tbody></table>')
+        });
+
+        var width = this.startBtn.getEl().getWidth()+10;
+
+        var sbBox = new Ext.BoxComponent({
+            el: 'ux-taskbar-start',
+            id: 'TaskBarStart',
+            minWidth: width,
+            region:'west',
+            split: true,
+            width: width
+        });
+
+        this.tbPanel = new Ext.ux.TaskButtonsPanel({
+            el: 'ux-taskbuttons-panel',
+            id: 'TaskBarButtons',
+            region:'center'
+        });
+
+        var container = new Ext.ux.TaskBarContainer({
+            el: 'ux-taskbar',
+            layout: 'border',
+            items: [sbBox,this.tbPanel]
+        });
+
+        return this;
+    },
+
+    addTaskButton : function(win){
+        return this.tbPanel.addButton(win, 'ux-taskbuttons-panel');
+    },
+
+    removeTaskButton : function(btn){
+        this.tbPanel.removeButton(btn);
+    },
+
+    setActiveButton : function(btn){
+        this.tbPanel.setActiveButton(btn);
+    }
+});
+
+
+
+/**
+ * @class Ext.ux.TaskBarContainer
+ * @extends Ext.Container
+ */
+Ext.ux.TaskBarContainer = Ext.extend(Ext.Container, {
+    initComponent : function() {
+        Ext.ux.TaskBarContainer.superclass.initComponent.call(this);
+
+        this.el = Ext.get(this.el) || Ext.getBody();
+        this.el.setHeight = Ext.emptyFn;
+        this.el.setWidth = Ext.emptyFn;
+        this.el.setSize = Ext.emptyFn;
+        this.el.setStyle({
+            overflow:'hidden',
+            margin:'0',
+            border:'0 none'
+        });
+        this.el.dom.scroll = 'no';
+        this.allowDomMove = false;
+        this.autoWidth = true;
+        this.autoHeight = true;
+        Ext.EventManager.onWindowResize(this.fireResize, this);
+        this.renderTo = this.el;
+    },
+
+    fireResize : function(w, h){
+        this.onResize(w, h, w, h);
+        this.fireEvent('resize', this, w, h, w, h);
+    }
+});
+
+
+
+/**
+ * @class Ext.ux.TaskButtonsPanel
+ * @extends Ext.BoxComponent
+ */
+Ext.ux.TaskButtonsPanel = Ext.extend(Ext.BoxComponent, {
+    activeButton: null,
+    enableScroll: true,
+    scrollIncrement: 0,
+    scrollRepeatInterval: 400,
+    scrollDuration: .35,
+    animScroll: true,
+    resizeButtons: true,
+    buttonWidth: 168,
+    minButtonWidth: 118,
+    buttonMargin: 2,
+    buttonWidthSet: false,
+
+    initComponent : function() {
+        Ext.ux.TaskButtonsPanel.superclass.initComponent.call(this);
+        this.on('resize', this.delegateUpdates);
+        this.items = [];
+
+        this.stripWrap = Ext.get(this.el).createChild({
+            cls: 'ux-taskbuttons-strip-wrap',
+            cn: {
+                tag:'ul', cls:'ux-taskbuttons-strip'
+            }
+        });
+        this.stripSpacer = Ext.get(this.el).createChild({
+            cls:'ux-taskbuttons-strip-spacer'
+        });
+        this.strip = new Ext.Element(this.stripWrap.dom.firstChild);
+
+        this.edge = this.strip.createChild({
+            tag:'li',
+            cls:'ux-taskbuttons-edge'
+        });
+        this.strip.createChild({
+            cls:'x-clear'
+        });
+    },
+
+    addButton : function(win){
+        var li = this.strip.createChild({tag:'li'}, this.edge); // insert before the edge
+        var btn = new Ext.ux.TaskBar.TaskButton(win, li);
+
+        this.items.push(btn);
+
+        if(!this.buttonWidthSet){
+            this.lastButtonWidth = btn.container.getWidth();
+        }
+
+        this.setActiveButton(btn);
+        return btn;
+    },
+
+    removeButton : function(btn){
+        var li = document.getElementById(btn.container.id);
+        btn.destroy();
+        li.parentNode.removeChild(li);
+
+        var s = [];
+        for(var i = 0, len = this.items.length; i < len; i++) {
+            if(this.items[i] != btn){
+                s.push(this.items[i]);
+            }
+        }
+        this.items = s;
+
+        this.delegateUpdates();
+    },
+
+    setActiveButton : function(btn){
+        this.activeButton = btn;
+        this.delegateUpdates();
+    },
+
+    delegateUpdates : function(){
+        /*if(this.suspendUpdates){
+            return;
+        }*/
+        if(this.resizeButtons && this.rendered){
+            this.autoSize();
+        }
+        if(this.enableScroll && this.rendered){
+            this.autoScroll();
+        }
+    },
+
+    autoSize : function(){
+        var count = this.items.length;
+        var ow = this.el.dom.offsetWidth;
+        var aw = this.el.dom.clientWidth;
+
+        if(!this.resizeButtons || count < 1 || !aw){ // !aw for display:none
+            return;
+        }
+
+        var each = Math.max(Math.min(Math.floor((aw-4) / count) - this.buttonMargin, this.buttonWidth), this.minButtonWidth); // -4 for float errors in IE
+        var btns = this.stripWrap.dom.getElementsByTagName('button');
+
+        this.lastButtonWidth = Ext.get(btns[0].id).findParent('li').offsetWidth;
+
+        for(var i = 0, len = btns.length; i < len; i++) {
+            var btn = btns[i];
+
+            var tw = Ext.get(btns[i].id).findParent('li').offsetWidth;
+            var iw = btn.offsetWidth;
+
+            btn.style.width = (each - (tw-iw)) + 'px';
+        }
+    },
+
+    autoScroll : function(){
+        var count = this.items.length;
+        var ow = this.el.dom.offsetWidth;
+        var tw = this.el.dom.clientWidth;
+
+        var wrap = this.stripWrap;
+        var cw = wrap.dom.offsetWidth;
+        var pos = this.getScrollPos();
+        var l = this.edge.getOffsetsTo(this.stripWrap)[0] + pos;
+
+        if(!this.enableScroll || count < 1 || cw < 20){ // 20 to prevent display:none issues
+            return;
+        }
+
+        wrap.setWidth(tw); // moved to here because of problem in Safari
+
+        if(l <= tw){
+            wrap.dom.scrollLeft = 0;
+            //wrap.setWidth(tw); moved from here because of problem in Safari
+            if(this.scrolling){
+                this.scrolling = false;
+                this.el.removeClass('x-taskbuttons-scrolling');
+                this.scrollLeft.hide();
+                this.scrollRight.hide();
+            }
+        }else{
+            if(!this.scrolling){
+                this.el.addClass('x-taskbuttons-scrolling');
+            }
+            tw -= wrap.getMargins('lr');
+            wrap.setWidth(tw > 20 ? tw : 20);
+            if(!this.scrolling){
+                if(!this.scrollLeft){
+                    this.createScrollers();
+                }else{
+                    this.scrollLeft.show();
+                    this.scrollRight.show();
+                }
+            }
+            this.scrolling = true;
+            if(pos > (l-tw)){ // ensure it stays within bounds
+                wrap.dom.scrollLeft = l-tw;
+            }else{ // otherwise, make sure the active button is still visible
+                this.scrollToButton(this.activeButton, true); // true to animate
+            }
+            this.updateScrollButtons();
+        }
+    },
+
+    createScrollers : function(){
+        var h = this.el.dom.offsetHeight; //var h = this.stripWrap.dom.offsetHeight;
+
+        // left
+        var sl = this.el.insertFirst({
+            cls:'ux-taskbuttons-scroller-left'
+        });
+        sl.setHeight(h);
+        sl.addClassOnOver('ux-taskbuttons-scroller-left-over');
+        this.leftRepeater = new Ext.util.ClickRepeater(sl, {
+            interval : this.scrollRepeatInterval,
+            handler: this.onScrollLeft,
+            scope: this
+        });
+        this.scrollLeft = sl;
+
+        // right
+        var sr = this.el.insertFirst({
+            cls:'ux-taskbuttons-scroller-right'
+        });
+        sr.setHeight(h);
+        sr.addClassOnOver('ux-taskbuttons-scroller-right-over');
+        this.rightRepeater = new Ext.util.ClickRepeater(sr, {
+            interval : this.scrollRepeatInterval,
+            handler: this.onScrollRight,
+            scope: this
+        });
+        this.scrollRight = sr;
+    },
+
+    getScrollWidth : function(){
+        return this.edge.getOffsetsTo(this.stripWrap)[0] + this.getScrollPos();
+    },
+
+    getScrollPos : function(){
+        return parseInt(this.stripWrap.dom.scrollLeft, 10) || 0;
+    },
+
+    getScrollArea : function(){
+        return parseInt(this.stripWrap.dom.clientWidth, 10) || 0;
+    },
+
+    getScrollAnim : function(){
+        return {
+            duration: this.scrollDuration,
+            callback: this.updateScrollButtons,
+            scope: this
+        };
+    },
+
+    getScrollIncrement : function(){
+        return (this.scrollIncrement || this.lastButtonWidth+2);
+    },
+
+    /* getBtnEl : function(item){
+        return document.getElementById(item.id);
+    }, */
+
+    scrollToButton : function(item, animate){
+        item = item.el.dom.parentNode; // li
+        if(!item){ return; }
+        var el = item; //this.getBtnEl(item);
+        var pos = this.getScrollPos(), area = this.getScrollArea();
+        var left = Ext.fly(el).getOffsetsTo(this.stripWrap)[0] + pos;
+        var right = left + el.offsetWidth;
+        if(left < pos){
+            this.scrollTo(left, animate);
+        }else if(right > (pos + area)){
+            this.scrollTo(right - area, animate);
+        }
+    },
+
+    scrollTo : function(pos, animate){
+        this.stripWrap.scrollTo('left', pos, animate ? this.getScrollAnim() : false);
+        if(!animate){
+            this.updateScrollButtons();
+        }
+    },
+
+    onScrollRight : function(){
+        var sw = this.getScrollWidth()-this.getScrollArea();
+        var pos = this.getScrollPos();
+        var s = Math.min(sw, pos + this.getScrollIncrement());
+        if(s != pos){
+            this.scrollTo(s, this.animScroll);
+        }
+    },
+
+    onScrollLeft : function(){
+        var pos = this.getScrollPos();
+        var s = Math.max(0, pos - this.getScrollIncrement());
+        if(s != pos){
+            this.scrollTo(s, this.animScroll);
+        }
+    },
+
+    updateScrollButtons : function(){
+        var pos = this.getScrollPos();
+        this.scrollLeft[pos == 0 ? 'addClass' : 'removeClass']('ux-taskbuttons-scroller-left-disabled');
+        this.scrollRight[pos >= (this.getScrollWidth()-this.getScrollArea()) ? 'addClass' : 'removeClass']('ux-taskbuttons-scroller-right-disabled');
+    }
+});
+
+
+
+/**
+ * @class Ext.ux.TaskBar.TaskButton
+ * @extends Ext.Button
+ */
+Ext.ux.TaskBar.TaskButton = function(win, el){
+    this.win = win;
+    Ext.ux.TaskBar.TaskButton.superclass.constructor.call(this, {
+        iconCls: win.iconCls,
+        text: Ext.util.Format.ellipsis(win.title, 12),
+        renderTo: el,
+        handler : function(){
+            if(win.minimized || win.hidden){
+                win.show();
+            }else if(win == win.manager.getActive()){
+                win.minimize();
+            }else{
+                win.toFront();
+            }
+        },
+        clickEvent:'mousedown',
+        template: new Ext.Template(
+            '<table cellspacing="0" class="x-btn {3}"><tbody><tr>',
+            '<td class="ux-taskbutton-left"><i>&#160;</i></td>',
+            '<td class="ux-taskbutton-center"><em class="{5} unselectable="on">',
+                '<button class="x-btn-text {2}" type="{1}" style="height:28px;">{0}</button>',
+            '</em></td>',
+            '<td class="ux-taskbutton-right"><i>&#160;</i></td>',
+            "</tr></tbody></table>")
+    });
+};
+
+Ext.extend(Ext.ux.TaskBar.TaskButton, Ext.Button, {
+    onRender : function(){
+        Ext.ux.TaskBar.TaskButton.superclass.onRender.apply(this, arguments);
+
+        this.cmenu = new Ext.menu.Menu({
+            items: [{
+                text: 'Restore',
+                handler: function(){
+                    if(!this.win.isVisible()){
+                        this.win.show();
+                    }else{
+                        this.win.restore();
+                    }
+                },
+                scope: this
+            },{
+                text: 'Minimize',
+                handler: this.win.minimize,
+                scope: this.win
+            },{
+                text: 'Maximize',
+                handler: this.win.maximize,
+                scope: this.win
+            }, '-', {
+                text: 'Close',
+                handler: this.closeWin.createDelegate(this, this.win, true),
+                scope: this.win
+            }]
+        });
+
+        this.cmenu.on('beforeshow', function(){
+            var items = this.cmenu.items.items;
+            var w = this.win;
+            items[0].setDisabled(w.maximized !== true && w.hidden !== true);
+            items[1].setDisabled(w.minimized === true);
+            items[2].setDisabled(w.maximized === true || w.hidden === true);
+        }, this);
+
+        this.el.on('contextmenu', function(e){
+            e.stopEvent();
+            if(!this.cmenu.el){
+                this.cmenu.render();
+            }
+            var xy = e.getXY();
+            xy[1] -= this.cmenu.el.getHeight();
+            this.cmenu.showAt(xy);
+        }, this);
+    },
+
+    closeWin : function(cMenu, e, win){
+        if(!win.isVisible()){
+            win.show();
+        }else{
+            win.restore();
+        }
+        win.close();
+    }
 });
\ No newline at end of file