Upgrade to ExtJS 4.0.2 - Released 06/09/2011
[extjs.git] / examples / desktop / js / TaskBar.js
index ce6c5ab..0837014 100644 (file)
-/*!
- * Ext JS Library 3.2.0
- * Copyright(c) 2006-2010 Ext JS, Inc.
- * licensing@extjs.com
- * http://www.extjs.com/license
- */
-/**
- * @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;
+This file is part of Ext JS 4
 
-        var sbBox = new Ext.BoxComponent({
-            el: 'ux-taskbar-start',
-            id: 'TaskBarStart',
-            minWidth: width,
-            region:'west',
-            split: true,
-            width: width
-        });
+Copyright (c) 2011 Sencha Inc
 
-        this.tbPanel = new Ext.ux.TaskButtonsPanel({
-            el: 'ux-taskbuttons-panel',
-            id: 'TaskBarButtons',
-            region:'center'
-        });
+Contact:  http://www.sencha.com/contact
 
-        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);
-    }
-});
+GNU General Public License Usage
+This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file.  Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
 
+If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
 
+*/
+/*!
+ * Ext JS Library 4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
 
 /**
- * @class Ext.ux.TaskBarContainer
- * @extends Ext.Container
+ * @class Ext.ux.desktop.TaskBar
+ * @extends Ext.toolbar.Toolbar
  */
-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;
+Ext.define('Ext.ux.desktop.TaskBar', {
+    extend: 'Ext.toolbar.Toolbar', // TODO - make this a basic hbox panel...
+
+    requires: [
+        'Ext.button.Button',
+        'Ext.resizer.Splitter',
+        'Ext.menu.Menu',
+
+        'Ext.ux.desktop.StartMenu'
+    ],
+
+    alias: 'widget.taskbar',
+
+    cls: 'ux-taskbar',
+
+    /**
+     * @cfg {String} startBtnText
+     * The text for the Start Button.
+     */
+    startBtnText: 'Start',
+
+    initComponent: function () {
+        var me = this;
+
+        me.startMenu = new Ext.ux.desktop.StartMenu(me.startConfig);
+
+        me.quickStart = new Ext.toolbar.Toolbar(me.getQuickStart());
+
+        me.windowBar = new Ext.toolbar.Toolbar(me.getWindowBarConfig());
+
+        me.tray = new Ext.toolbar.Toolbar(me.getTrayConfig());
+
+        me.items = [
+            {
+                xtype: 'button',
+                cls: 'ux-start-button',
+                iconCls: 'ux-start-button-icon',
+                menu: me.startMenu,
+                menuAlign: 'bl-tl',
+                text: me.startBtnText
+            },
+            me.quickStart,
+            {
+                xtype: 'splitter', html: '&#160;',
+                height: 14, width: 2, // TODO - there should be a CSS way here
+                cls: 'x-toolbar-separator x-toolbar-separator-horizontal'
+            },
+            //'-',
+            me.windowBar,
+            '-',
+            me.tray
+        ];
+
+        me.callParent();
     },
 
-    fireResize : function(w, h){
-        this.onResize(w, h, w, h);
-        this.fireEvent('resize', this, w, h, w, h);
-    }
-});
-
+    afterLayout: function () {
+        var me = this;
+        me.callParent();
+        me.windowBar.el.on('contextmenu', me.onButtonContextMenu, me);
+    },
 
+    /**
+     * This method returns the configuration object for the Quick Start toolbar. A derived
+     * class can override this method, call the base version to build the config and
+     * then modify the returned object before returning it.
+     */
+    getQuickStart: function () {
+        var me = this, ret = {
+            minWidth: 20,
+            width: 60,
+            items: [],
+            enableOverflow: true
+        };
 
-/**
- * @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'
+        Ext.each(this.quickStart, function (item) {
+            ret.items.push({
+                tooltip: { text: item.name, align: 'bl-tl' },
+                //tooltip: item.name,
+                overflowText: item.name,
+                iconCls: item.iconCls,
+                module: item.module,
+                handler: me.onQuickStartClick,
+                scope: me
+            });
         });
-        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'
-        });
+        return ret;
     },
 
-    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;
+    /**
+     * This method returns the configuration object for the Tray toolbar. A derived
+     * class can override this method, call the base version to build the config and
+     * then modify the returned object before returning it.
+     */
+    getTrayConfig: function () {
+        var ret = {
+            width: 80,
+            items: this.trayItems
+        };
+        delete this.trayItems;
+        return ret;
     },
 
-    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();
+    getWindowBarConfig: function () {
+        return {
+            flex: 1,
+            cls: 'ux-desktop-windowbar',
+            items: [ '&#160;' ],
+            layout: { overflowHandler: 'Scroller' }
+        };
     },
 
-    setActiveButton : function(btn){
-        this.activeButton = btn;
-        this.delegateUpdates();
+    getWindowBtnFromEl: function (el) {
+        var c = this.windowBar.getChildByElement(el);
+        return c || null;
     },
 
-    delegateUpdates : function(){
-        /*if(this.suspendUpdates){
-            return;
-        }*/
-        if(this.resizeButtons && this.rendered){
-            this.autoSize();
-        }
-        if(this.enableScroll && this.rendered){
-            this.autoScroll();
+    onQuickStartClick: function (btn) {
+        var module = this.app.getModule(btn.module);
+        if (module) {
+            module.createWindow();
         }
     },
-
-    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;
+    
+    onButtonContextMenu: function (e) {
+        var me = this, t = e.getTarget(), btn = me.getWindowBtnFromEl(t);
+        if (btn) {
+            e.stopEvent();
+            me.windowMenu.theWin = btn.win;
+            me.windowMenu.showBy(t);
         }
+    },
 
-        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;
+    onWindowBtnClick: function (btn) {
+        var win = btn.win;
 
-            btn.style.width = (each - (tw-iw)) + 'px';
+        if (win.minimized || win.hidden) {
+            win.show();
+        } else if (win.active) {
+            win.minimize();
+        } else {
+            win.toFront();
         }
     },
 
-    autoScroll : function(){
-        var count = this.items.length;
-        var ow = this.el.dom.offsetWidth;
-        var tw = this.el.dom.clientWidth;
+    addTaskButton: function(win) {
+        var config = {
+            iconCls: win.iconCls,
+            enableToggle: true,
+            toggleGroup: 'all',
+            width: 140,
+            text: Ext.util.Format.ellipsis(win.title, 20),
+            listeners: {
+                click: this.onWindowBtnClick,
+                scope: this
+            },
+            win: win
+        };
 
-        var wrap = this.stripWrap;
-        var cw = wrap.dom.offsetWidth;
-        var pos = this.getScrollPos();
-        var l = this.edge.getOffsetsTo(this.stripWrap)[0] + pos;
+        var cmp = this.windowBar.add(config);
+        cmp.toggle(true);
+        return cmp;
+    },
 
-        if(!this.enableScroll || count < 1 || cw < 20){ // 20 to prevent display:none issues
-            return;
+    removeTaskButton: function (btn) {
+        var found, me = this;
+        me.windowBar.items.each(function (item) {
+            if (item === btn) {
+                found = item;
+            }
+            return !found;
+        });
+        if (found) {
+            me.windowBar.remove(found);
         }
+        return found;
+    },
 
-        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();
+    setActiveButton: function(btn) {
+        if (btn) {
+            btn.toggle(true);
+        } else {
+            this.windowBar.items.each(function (item) {
+                if (item.isButton) {
+                    item.toggle(false);
                 }
-            }
-            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;
+/**
+ * @class Ext.ux.desktop.TrayClock
+ * @extends Ext.toolbar.TextItem
+ * This class displays a clock on the toolbar.
+ */
+Ext.define('Ext.ux.desktop.TrayClock', {
+    extend: 'Ext.toolbar.TextItem',
 
-        // 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;
+    alias: 'widget.trayclock',
 
-        // 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;
-    },
+    cls: 'ux-desktop-trayclock',
 
-    getScrollWidth : function(){
-        return this.edge.getOffsetsTo(this.stripWrap)[0] + this.getScrollPos();
-    },
+    html: '&#160;',
 
-    getScrollPos : function(){
-        return parseInt(this.stripWrap.dom.scrollLeft, 10) || 0;
-    },
+    timeFormat: 'g:i A',
 
-    getScrollArea : function(){
-        return parseInt(this.stripWrap.dom.clientWidth, 10) || 0;
-    },
+    tpl: '{time}',
 
-    getScrollAnim : function(){
-        return {
-            duration: this.scrollDuration,
-            callback: this.updateScrollButtons,
-            scope: this
-        };
-    },
+    initComponent: function () {
+        var me = this;
 
-    getScrollIncrement : function(){
-        return (this.scrollIncrement || this.lastButtonWidth+2);
-    },
+        me.callParent();
 
-    /* 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);
+        if (typeof(me.tpl) == 'string') {
+            me.tpl = new Ext.XTemplate(me.tpl);
         }
     },
 
-    scrollTo : function(pos, animate){
-        this.stripWrap.scrollTo('left', pos, animate ? this.getScrollAnim() : false);
-        if(!animate){
-            this.updateScrollButtons();
-        }
+    afterRender: function () {
+        var me = this;
+        Ext.Function.defer(me.updateTime, 100, me);
+        me.callParent();
     },
 
-    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);
-        }
-    },
+    onDestroy: function () {
+        var me = this;
 
-    onScrollLeft : function(){
-        var pos = this.getScrollPos();
-        var s = Math.max(0, pos - this.getScrollIncrement());
-        if(s != pos){
-            this.scrollTo(s, this.animScroll);
+        if (me.timer) {
+            window.clearTimeout(me.timer);
+            me.timer = null;
         }
-    },
-
-    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);
+        me.callParent();
     },
 
-    closeWin : function(cMenu, e, win){
-        if(!win.isVisible()){
-            win.show();
-        }else{
-            win.restore();
+    updateTime: function () {
+        var me = this, time = Ext.Date.format(new Date(), me.timeFormat),
+            text = me.tpl.apply({ time: time });
+        if (me.lastText != text) {
+            me.setText(text);
+            me.lastText = text;
         }
-        win.close();
+        me.timer = Ext.Function.defer(me.updateTime, 10000, me);
     }
-});
\ No newline at end of file
+});
+