/*!
- * Ext JS Library 3.3.0
- * Copyright(c) 2006-2010 Ext JS, Inc.
- * 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) {
- this.taskbar = new Ext.ux.TaskBar(app);
- this.xTickSize = this.yTickSize = 1;
- var taskbar = this.taskbar;
- var desktopEl = Ext.get('x-desktop');
- var taskbarEl = Ext.get('ux-taskbar');
- var shortcuts = Ext.get('x-shortcuts');
+/**
+ * @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',
- var windows = new Ext.WindowGroup();
- var activeWindow;
+ alias: 'widget.desktop',
- function minimizeWin(win) {
- win.minimized = true;
- win.hide();
- }
+ uses: [
+ 'Ext.util.MixedCollection',
+ 'Ext.menu.Menu',
+ 'Ext.view.View', // dataview
+ 'Ext.window.Window',
- function markActive(win) {
- if (activeWindow && activeWindow != win) {
- markInactive(activeWindow);
- }
- taskbar.setActiveButton(win.taskButton);
- activeWindow = win;
- Ext.fly(win.taskButton.el).addClass('active-win');
- win.minimized = false;
- }
+ '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: ' ',
+ 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,
- function markInactive(win) {
- if (win == activeWindow) {
- activeWindow = null;
- Ext.fly(win.taskButton.el).removeClass('active-win');
+ 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);
}
- }
+ },
- function removeWin(win) {
- taskbar.removeTaskButton(win.taskButton);
- layout();
- }
+ afterRender: function () {
+ var me = this;
+ me.callParent();
+ me.el.on('contextmenu', me.onDesktopMenu, me);
+ },
- function layout() {
- desktopEl.setHeight(Ext.lib.Dom.getViewHeight() - taskbarEl.getHeight());
- }
- Ext.EventManager.onWindowResize(layout);
-
- this.layout = layout;
-
- this.createWindow = function(config, cls) {
- var win = new(cls || Ext.Window)(
- Ext.applyIf(config || {},
- {
- renderTo: desktopEl,
- manager: windows,
- minimizable: true,
- maximizable: true
- })
- );
- win.dd.xTickSize = this.xTickSize;
- win.dd.yTickSize = this.yTickSize;
- if (win.resizer) {
- win.resizer.widthIncrement = this.xTickSize;
- win.resizer.heightIncrement = this.yTickSize;
+ //------------------------------------------------------
+ // 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('-');
}
- win.render(desktopEl);
- win.taskButton = taskbar.addTaskButton(win);
- win.cmenu = new Ext.menu.Menu({
+ 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': {
- fn: markActive
- },
- 'beforeshow': {
- fn: markActive
- },
- 'deactivate': {
- fn: markInactive
- },
- 'minimize': {
- fn: minimizeWin
+ 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;
+ }
},
- 'close': {
- fn: removeWin
- }
+ single: true
});
- layout();
+ // replace normal window close w/fadeOut animation:
+ win.doClose = function () {
+ win.el.disableShadow();
+ win.el.fadeOut({
+ listeners: {
+ afteranimate: function () {
+ win.destroy();
+ }
+ }
+ });
+ };
+
return win;
- };
-
- this.getManager = function() {
- return windows;
- };
-
- this.getWindow = function(id) {
- return windows.get(id);
- };
-
- this.getWinWidth = function() {
- var width = Ext.lib.Dom.getViewWidth();
- return width < 200 ? 200: width;
- };
-
- this.getWinHeight = function() {
- var height = (Ext.lib.Dom.getViewHeight() - taskbarEl.getHeight());
- return height < 100 ? 100: height;
- };
-
- this.getWinX = function(width) {
- return (Ext.lib.Dom.getViewWidth() - width) / 2;
- };
-
- this.getWinY = function(height) {
- return (Ext.lib.Dom.getViewHeight() - taskbarEl.getHeight() - height) / 2;
- };
-
- this.setTickSize = function(xTickSize, yTickSize) {
- this.xTickSize = xTickSize;
- if (arguments.length == 1) {
- this.yTickSize = xTickSize;
+ },
+
+ 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 {
- this.yTickSize = yTickSize;
+ win.show();
}
- windows.each(function(win) {
- win.dd.xTickSize = this.xTickSize;
- win.dd.yTickSize = this.yTickSize;
- win.resizer.widthIncrement = this.xTickSize;
- win.resizer.heightIncrement = this.yTickSize;
- },
- this);
- };
-
- this.cascade = function() {
- var x = 0,
- y = 0;
- windows.each(function(win) {
- if (win.isVisible() && !win.maximized) {
- win.setPosition(x, y);
- x += 20;
- y += 20;
- }
- },
- this);
- };
-
- this.tile = function() {
- var availWidth = desktopEl.getWidth(true);
- var x = this.xTickSize;
- var y = this.yTickSize;
- var nextY = y;
- windows.each(function(win) {
+ 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 > this.xTickSize) && (x + w > availWidth)) {
- x = this.xTickSize;
+ // 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 + this.xTickSize;
- nextY = Math.max(nextY, y + win.el.getHeight() + this.yTickSize);
- }
- },
- this);
- };
-
- this.contextMenu = new Ext.menu.Menu({
- items: [{
- text: 'Tile',
- handler: this.tile,
- scope: this
- },
- {
- text: 'Cascade',
- handler: this.cascade,
- scope: this
- }]
- });
- desktopEl.on('contextmenu',
- function(e) {
- e.stopEvent();
- this.contextMenu.showAt(e.getXY());
- },
- this);
-
- layout();
-
- if (shortcuts) {
- shortcuts.on('click',
- function(e, t) {
- t = e.getTarget('dt', shortcuts);
- if (t) {
- e.stopEvent();
- var module = app.getModule(t.id.replace('-shortcut', ''));
- if (module) {
- module.createWindow();
- }
+ 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);
}
-};
+});