Upgrade to ExtJS 4.0.0 - Released 04/26/2011
[extjs.git] / examples / desktop / js / Desktop.js
old mode 100644 (file)
new mode 100755 (executable)
index 43a855e..614c68f
 /*!
- * Ext JS Library 3.1.1
- * Copyright(c) 2006-2010 Ext JS, LLC
- * licensing@extjs.com
- * http://www.extjs.com/license
+ * Ext JS Library 4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
  */
-Ext.Desktop = function(app){\r
-       this.taskbar = new Ext.ux.TaskBar(app);\r
-       var taskbar = this.taskbar;\r
-       \r
-       var desktopEl = Ext.get('x-desktop');\r
-    var taskbarEl = Ext.get('ux-taskbar');\r
-    var shortcuts = Ext.get('x-shortcuts');\r
-\r
-    var windows = new Ext.WindowGroup();\r
-    var activeWindow;\r
-               \r
-    function minimizeWin(win){\r
-        win.minimized = true;\r
-        win.hide();\r
-    }\r
-\r
-    function markActive(win){\r
-        if(activeWindow && activeWindow != win){\r
-            markInactive(activeWindow);\r
-        }\r
-        taskbar.setActiveButton(win.taskButton);\r
-        activeWindow = win;\r
-        Ext.fly(win.taskButton.el).addClass('active-win');\r
-        win.minimized = false;\r
-    }\r
-\r
-    function markInactive(win){\r
-        if(win == activeWindow){\r
-            activeWindow = null;\r
-            Ext.fly(win.taskButton.el).removeClass('active-win');\r
-        }\r
-    }\r
-\r
-    function removeWin(win){\r
-       taskbar.removeTaskButton(win.taskButton);\r
-        layout();\r
-    }\r
-\r
-    function layout(){\r
-        desktopEl.setHeight(Ext.lib.Dom.getViewHeight()-taskbarEl.getHeight());\r
-    }\r
-    Ext.EventManager.onWindowResize(layout);\r
-\r
-    this.layout = layout;\r
-\r
-    this.createWindow = function(config, cls){\r
-       var win = new (cls||Ext.Window)(\r
-            Ext.applyIf(config||{}, {\r
-                manager: windows,\r
-                minimizable: true,\r
-                maximizable: true\r
-            })\r
-        );\r
-        win.render(desktopEl);\r
-        win.taskButton = taskbar.addTaskButton(win);\r
-\r
-        win.cmenu = new Ext.menu.Menu({\r
-            items: [\r
-\r
-            ]\r
-        });\r
-\r
-        win.animateTarget = win.taskButton.el;\r
-        \r
-        win.on({\r
-               'activate': {\r
-                       fn: markActive\r
-               },\r
-               'beforeshow': {\r
-                       fn: markActive\r
-               },\r
-               'deactivate': {\r
-                       fn: markInactive\r
-               },\r
-               'minimize': {\r
-                       fn: minimizeWin\r
-               },\r
-               'close': {\r
-                       fn: removeWin\r
-               }\r
-        });\r
-        \r
-        layout();\r
-        return win;\r
-    };\r
-\r
-    this.getManager = function(){\r
-        return windows;\r
-    };\r
-\r
-    this.getWindow = function(id){\r
-        return windows.get(id);\r
-    }\r
-    \r
-    this.getWinWidth = function(){\r
-               var width = Ext.lib.Dom.getViewWidth();\r
-               return width < 200 ? 200 : width;\r
-       }\r
-               \r
-       this.getWinHeight = function(){\r
-               var height = (Ext.lib.Dom.getViewHeight()-taskbarEl.getHeight());\r
-               return height < 100 ? 100 : height;\r
-       }\r
-               \r
-       this.getWinX = function(width){\r
-               return (Ext.lib.Dom.getViewWidth() - width) / 2\r
-       }\r
-               \r
-       this.getWinY = function(height){\r
-               return (Ext.lib.Dom.getViewHeight()-taskbarEl.getHeight() - height) / 2;\r
-       }\r
-\r
-    layout();\r
-\r
-    if(shortcuts){\r
-        shortcuts.on('click', function(e, t){\r
-            if(t = e.getTarget('dt', shortcuts)){\r
-                e.stopEvent();\r
-                var module = app.getModule(t.id.replace('-shortcut', ''));\r
-                if(module){\r
-                    module.createWindow();\r
-                }\r
-            }\r
-        });\r
-    }\r
-};\r
+
+/**
+ * @class Ext.ux.desktop.Desktop
+ * @extends Ext.panel.Panel
+ * <p>This class manages the wallpaper, shortcuts and taskbar.</p>
+ */
+Ext.define('Ext.ux.desktop.Desktop', {
+    extend: 'Ext.panel.Panel',
+
+    alias: 'widget.desktop',
+
+    uses: [
+        'Ext.util.MixedCollection',
+        'Ext.menu.Menu',
+        'Ext.view.View', // dataview
+        'Ext.window.Window',
+
+        'Ext.ux.desktop.TaskBar',
+        'Ext.ux.desktop.Wallpaper',
+        'Ext.ux.desktop.FitAllLayout'
+    ],
+
+    activeWindowCls: 'ux-desktop-active-win',
+    inactiveWindowCls: 'ux-desktop-inactive-win',
+    lastActiveWindow: null,
+
+    border: false,
+    html: '&#160;',
+    layout: 'fitall',
+
+    xTickSize: 1,
+    yTickSize: 1,
+
+    app: null,
+
+    /**
+     * @cfg {Array|Store} shortcuts
+     * The items to add to the DataView. This can be a {@link Ext.data.Store Store} or a
+     * simple array. Items should minimally provide the fields in the
+     * {@link Ext.ux.desktop.ShorcutModel ShortcutModel}.
+     */
+    shortcuts: null,
+
+    /**
+     * @cfg {String} shortcutItemSelector
+     * This property is passed to the DataView for the desktop to select shortcut items.
+     * If the {@link #shortcutTpl} is modified, this will probably need to be modified as
+     * well.
+     */
+    shortcutItemSelector: 'div.ux-desktop-shortcut',
+
+    /**
+     * @cfg {String} shortcutTpl
+     * This XTemplate is used to render items in the DataView. If this is changed, the
+     * {@link shortcutItemSelect} will probably also need to changed.
+     */
+    shortcutTpl: [
+        '<tpl for=".">',
+            '<div class="ux-desktop-shortcut" id="{name}-shortcut">',
+                '<div class="ux-desktop-shortcut-icon {iconCls}">',
+                    '<img src="',Ext.BLANK_IMAGE_URL,'" title="{name}">',
+                '</div>',
+                '<span class="ux-desktop-shortcut-text">{name}</span>',
+            '</div>',
+        '</tpl>',
+        '<div class="x-clear"></div>'
+    ],
+
+    /**
+     * @cfg {Object} taskbarConfig
+     * The config object for the TaskBar.
+     */
+    taskbarConfig: null,
+
+    windowMenu: null,
+
+    initComponent: function () {
+        var me = this;
+
+        me.windowMenu = new Ext.menu.Menu(me.createWindowMenu());
+
+        me.bbar = me.taskbar = new Ext.ux.desktop.TaskBar(me.taskbarConfig);
+        me.taskbar.windowMenu = me.windowMenu;
+
+        me.windows = new Ext.util.MixedCollection();
+
+        me.contextMenu = new Ext.menu.Menu(me.createDesktopMenu());
+
+        me.items = [
+            { xtype: 'wallpaper', id: me.id+'_wallpaper' },
+            me.createDataView()
+        ];
+
+        me.callParent();
+
+        me.shortcutsView = me.items.getAt(1);
+        me.shortcutsView.on('itemclick', me.onShortcutItemClick, me);
+
+        var wallpaper = me.wallpaper;
+        me.wallpaper = me.items.getAt(0);
+        if (wallpaper) {
+            me.setWallpaper(wallpaper, me.wallpaperStretch);
+        }
+    },
+
+    afterRender: function () {
+        var me = this;
+        me.callParent();
+        me.el.on('contextmenu', me.onDesktopMenu, me);
+    },
+
+    //------------------------------------------------------
+    // Overrideable configuration creation methods
+
+    createDataView: function () {
+        var me = this;
+        return {
+            xtype: 'dataview',
+            overItemCls: 'x-view-over',
+            trackOver: true,
+            itemSelector: me.shortcutItemSelector,
+            store: me.shortcuts,
+            tpl: new Ext.XTemplate(me.shortcutTpl)
+        };
+    },
+
+    createDesktopMenu: function () {
+        var me = this, ret = {
+            items: me.contextMenuItems || []
+        };
+
+        if (ret.items.length) {
+            ret.items.push('-');
+        }
+
+        ret.items.push(
+                { text: 'Tile', handler: me.tileWindows, scope: me, minWindows: 1 },
+                { text: 'Cascade', handler: me.cascadeWindows, scope: me, minWindows: 1 })
+
+        return ret;
+    },
+
+    createWindowMenu: function () {
+        var me = this;
+        return {
+            defaultAlign: 'br-tr',
+            items: [
+                { text: 'Restore', handler: me.onWindowMenuRestore, scope: me },
+                { text: 'Minimize', handler: me.onWindowMenuMinimize, scope: me },
+                { text: 'Maximize', handler: me.onWindowMenuMaximize, scope: me },
+                '-',
+                { text: 'Close', handler: me.onWindowMenuClose, scope: me }
+            ],
+            listeners: {
+                beforeshow: me.onWindowMenuBeforeShow,
+                hide: me.onWindowMenuHide,
+                scope: me
+            }
+        };
+    },
+
+    //------------------------------------------------------
+    // Event handler methods
+
+    onDesktopMenu: function (e) {
+        var me = this, menu = me.contextMenu;
+        e.stopEvent();
+        if (!menu.rendered) {
+            menu.on('beforeshow', me.onDesktopMenuBeforeShow, me);
+        }
+        menu.showAt(e.getXY());
+        menu.doConstrain();
+    },
+
+    onDesktopMenuBeforeShow: function (menu) {
+        var me = this, count = me.windows.getCount();
+
+        menu.items.each(function (item) {
+            var min = item.minWindows || 0;
+            item.setDisabled(count < min);
+        });
+    },
+
+    onShortcutItemClick: function (dataView, record) {
+        var me = this, module = me.app.getModule(record.data.module),
+            win = module && module.createWindow();
+
+        if (win) {
+            me.restoreWindow(win);
+        }
+    },
+
+    onWindowClose: function(win) {
+        var me = this;
+        me.windows.remove(win);
+        me.taskbar.removeTaskButton(win.taskButton);
+        me.updateActiveWindow();
+    },
+
+    //------------------------------------------------------
+    // Window context menu handlers
+
+    onWindowMenuBeforeShow: function (menu) {
+        var items = menu.items.items, win = menu.theWin;
+        items[0].setDisabled(win.maximized !== true && win.hidden !== true); // Restore
+        items[1].setDisabled(win.minimized === true); // Minimize
+        items[2].setDisabled(win.maximized === true || win.hidden === true); // Maximize
+    },
+
+    onWindowMenuClose: function () {
+        var me = this, win = me.windowMenu.theWin;
+
+        win.close();
+    },
+
+    onWindowMenuHide: function (menu) {
+        menu.theWin = null;
+    },
+
+    onWindowMenuMaximize: function () {
+        var me = this, win = me.windowMenu.theWin;
+
+        win.maximize();
+    },
+
+    onWindowMenuMinimize: function () {
+        var me = this, win = me.windowMenu.theWin;
+
+        win.minimize();
+    },
+
+    onWindowMenuRestore: function () {
+        var me = this, win = me.windowMenu.theWin;
+
+        me.restoreWindow(win);
+    },
+
+    //------------------------------------------------------
+    // Dynamic (re)configuration methods
+
+    getWallpaper: function () {
+        return this.wallpaper.wallpaper;
+    },
+
+    setTickSize: function(xTickSize, yTickSize) {
+        var me = this,
+            xt = me.xTickSize = xTickSize,
+            yt = me.yTickSize = (arguments.length > 1) ? yTickSize : xt;
+
+        me.windows.each(function(win) {
+            var dd = win.dd, resizer = win.resizer;
+            dd.xTickSize = xt;
+            dd.yTickSize = yt;
+            resizer.widthIncrement = xt;
+            resizer.heightIncrement = yt;
+        });
+    },
+
+    setWallpaper: function (wallpaper, stretch) {
+        this.wallpaper.setWallpaper(wallpaper, stretch);
+        return this;
+    },
+
+    //------------------------------------------------------
+    // Window management methods
+
+    cascadeWindows: function() {
+        var x = 0, y = 0,
+            zmgr = this.getDesktopZIndexManager();
+
+        zmgr.eachBottomUp(function(win) {
+            if (win.isWindow && win.isVisible() && !win.maximized) {
+                win.setPosition(x, y);
+                x += 20;
+                y += 20;
+            }
+        });
+    },
+
+    createWindow: function(config, cls) {
+        var me = this, win, cfg = Ext.applyIf(config || {}, {
+                stateful: false,
+                isWindow: true,
+                constrainHeader: true,
+                minimizable: true,
+                maximizable: true
+            });
+
+        cls = cls || Ext.window.Window;
+        win = me.add(new cls(cfg));
+
+        me.windows.add(win);
+
+        win.taskButton = me.taskbar.addTaskButton(win);
+        win.animateTarget = win.taskButton.el;
+
+        win.on({
+            activate: me.updateActiveWindow,
+            beforeshow: me.updateActiveWindow,
+            deactivate: me.updateActiveWindow,
+            minimize: me.minimizeWindow,
+            destroy: me.onWindowClose,
+            scope: me
+        });
+
+        win.on({
+            afterrender: function () {
+                win.dd.xTickSize = me.xTickSize;
+                win.dd.yTickSize = me.yTickSize;
+
+                if (win.resizer) {
+                    win.resizer.widthIncrement = me.xTickSize;
+                    win.resizer.heightIncrement = me.yTickSize;
+                }
+            },
+            single: true
+        });
+
+        // replace normal window close w/fadeOut animation:
+        win.doClose = function ()  {
+            win.el.disableShadow();
+            win.el.fadeOut({
+                listeners: {
+                    afteranimate: function () {
+                        win.destroy();
+                    }
+                }
+            });
+        };
+
+        return win;
+    },
+
+    getActiveWindow: function () {
+        var win = null,
+            zmgr = this.getDesktopZIndexManager();
+
+        if (zmgr) {
+            // We cannot rely on activate/deactive because that fires against non-Window
+            // components in the stack.
+
+            zmgr.eachTopDown(function (comp) {
+                if (comp.isWindow && !comp.hidden) {
+                    win = comp;
+                    return false;
+                }
+                return true;
+            });
+        }
+
+        return win;
+    },
+
+    getDesktopZIndexManager: function () {
+        var windows = this.windows;
+        // TODO - there has to be a better way to get this...
+        return (windows.getCount() && windows.getAt(0).zIndexManager) || null;
+    },
+
+    getWindow: function(id) {
+        return this.windows.get(id);
+    },
+
+    minimizeWindow: function(win) {
+        win.minimized = true;
+        win.hide();
+    },
+
+    restoreWindow: function (win) {
+        if (win.isVisible()) {
+            win.restore();
+            win.toFront();
+        } else {
+            win.show();
+        }
+        return win;
+    },
+
+    tileWindows: function() {
+        var me = this, availWidth = me.body.getWidth(true);
+        var x = me.xTickSize, y = me.yTickSize, nextY = y;
+
+        me.windows.each(function(win) {
+            if (win.isVisible() && !win.maximized) {
+                var w = win.el.getWidth();
+
+                // Wrap to next row if we are not at the line start and this Window will
+                // go off the end
+                if (x > me.xTickSize && x + w > availWidth) {
+                    x = me.xTickSize;
+                    y = nextY;
+                }
+
+                win.setPosition(x, y);
+                x += w + me.xTickSize;
+                nextY = Math.max(nextY, y + win.el.getHeight() + me.yTickSize);
+            }
+        });
+    },
+
+    updateActiveWindow: function () {
+        var me = this, activeWindow = me.getActiveWindow(), last = me.lastActiveWindow;
+        if (activeWindow === last) {
+            return;
+        }
+
+        if (last) {
+            if (last.el.dom) {
+                last.addCls(me.inactiveWindowCls);
+                last.removeCls(me.activeWindowCls);
+            }
+            last.active = false;
+        }
+
+        me.lastActiveWindow = activeWindow;
+
+        if (activeWindow) {
+            activeWindow.addCls(me.activeWindowCls);
+            activeWindow.removeCls(me.inactiveWindowCls);
+            activeWindow.minimized = false;
+            activeWindow.active = true;
+        }
+
+        me.taskbar.setActiveButton(activeWindow && activeWindow.taskButton);
+    }
+});