3 * Copyright(c) 2006-2011 Sencha Inc.
5 * http://www.sencha.com/license
9 * @class Ext.ux.desktop.Desktop
10 * @extends Ext.panel.Panel
11 * <p>This class manages the wallpaper, shortcuts and taskbar.</p>
13 Ext.define('Ext.ux.desktop.Desktop', {
14 extend: 'Ext.panel.Panel',
16 alias: 'widget.desktop',
19 'Ext.util.MixedCollection',
21 'Ext.view.View', // dataview
24 'Ext.ux.desktop.TaskBar',
25 'Ext.ux.desktop.Wallpaper',
26 'Ext.ux.desktop.FitAllLayout'
29 activeWindowCls: 'ux-desktop-active-win',
30 inactiveWindowCls: 'ux-desktop-inactive-win',
31 lastActiveWindow: null,
43 * @cfg {Array|Store} shortcuts
44 * The items to add to the DataView. This can be a {@link Ext.data.Store Store} or a
45 * simple array. Items should minimally provide the fields in the
46 * {@link Ext.ux.desktop.ShorcutModel ShortcutModel}.
51 * @cfg {String} shortcutItemSelector
52 * This property is passed to the DataView for the desktop to select shortcut items.
53 * If the {@link #shortcutTpl} is modified, this will probably need to be modified as
56 shortcutItemSelector: 'div.ux-desktop-shortcut',
59 * @cfg {String} shortcutTpl
60 * This XTemplate is used to render items in the DataView. If this is changed, the
61 * {@link shortcutItemSelect} will probably also need to changed.
65 '<div class="ux-desktop-shortcut" id="{name}-shortcut">',
66 '<div class="ux-desktop-shortcut-icon {iconCls}">',
67 '<img src="',Ext.BLANK_IMAGE_URL,'" title="{name}">',
69 '<span class="ux-desktop-shortcut-text">{name}</span>',
72 '<div class="x-clear"></div>'
76 * @cfg {Object} taskbarConfig
77 * The config object for the TaskBar.
83 initComponent: function () {
86 me.windowMenu = new Ext.menu.Menu(me.createWindowMenu());
88 me.bbar = me.taskbar = new Ext.ux.desktop.TaskBar(me.taskbarConfig);
89 me.taskbar.windowMenu = me.windowMenu;
91 me.windows = new Ext.util.MixedCollection();
93 me.contextMenu = new Ext.menu.Menu(me.createDesktopMenu());
96 { xtype: 'wallpaper', id: me.id+'_wallpaper' },
102 me.shortcutsView = me.items.getAt(1);
103 me.shortcutsView.on('itemclick', me.onShortcutItemClick, me);
105 var wallpaper = me.wallpaper;
106 me.wallpaper = me.items.getAt(0);
108 me.setWallpaper(wallpaper, me.wallpaperStretch);
112 afterRender: function () {
115 me.el.on('contextmenu', me.onDesktopMenu, me);
118 //------------------------------------------------------
119 // Overrideable configuration creation methods
121 createDataView: function () {
125 overItemCls: 'x-view-over',
127 itemSelector: me.shortcutItemSelector,
129 tpl: new Ext.XTemplate(me.shortcutTpl)
133 createDesktopMenu: function () {
134 var me = this, ret = {
135 items: me.contextMenuItems || []
138 if (ret.items.length) {
143 { text: 'Tile', handler: me.tileWindows, scope: me, minWindows: 1 },
144 { text: 'Cascade', handler: me.cascadeWindows, scope: me, minWindows: 1 })
149 createWindowMenu: function () {
152 defaultAlign: 'br-tr',
154 { text: 'Restore', handler: me.onWindowMenuRestore, scope: me },
155 { text: 'Minimize', handler: me.onWindowMenuMinimize, scope: me },
156 { text: 'Maximize', handler: me.onWindowMenuMaximize, scope: me },
158 { text: 'Close', handler: me.onWindowMenuClose, scope: me }
161 beforeshow: me.onWindowMenuBeforeShow,
162 hide: me.onWindowMenuHide,
168 //------------------------------------------------------
169 // Event handler methods
171 onDesktopMenu: function (e) {
172 var me = this, menu = me.contextMenu;
174 if (!menu.rendered) {
175 menu.on('beforeshow', me.onDesktopMenuBeforeShow, me);
177 menu.showAt(e.getXY());
181 onDesktopMenuBeforeShow: function (menu) {
182 var me = this, count = me.windows.getCount();
184 menu.items.each(function (item) {
185 var min = item.minWindows || 0;
186 item.setDisabled(count < min);
190 onShortcutItemClick: function (dataView, record) {
191 var me = this, module = me.app.getModule(record.data.module),
192 win = module && module.createWindow();
195 me.restoreWindow(win);
199 onWindowClose: function(win) {
201 me.windows.remove(win);
202 me.taskbar.removeTaskButton(win.taskButton);
203 me.updateActiveWindow();
206 //------------------------------------------------------
207 // Window context menu handlers
209 onWindowMenuBeforeShow: function (menu) {
210 var items = menu.items.items, win = menu.theWin;
211 items[0].setDisabled(win.maximized !== true && win.hidden !== true); // Restore
212 items[1].setDisabled(win.minimized === true); // Minimize
213 items[2].setDisabled(win.maximized === true || win.hidden === true); // Maximize
216 onWindowMenuClose: function () {
217 var me = this, win = me.windowMenu.theWin;
222 onWindowMenuHide: function (menu) {
226 onWindowMenuMaximize: function () {
227 var me = this, win = me.windowMenu.theWin;
232 onWindowMenuMinimize: function () {
233 var me = this, win = me.windowMenu.theWin;
238 onWindowMenuRestore: function () {
239 var me = this, win = me.windowMenu.theWin;
241 me.restoreWindow(win);
244 //------------------------------------------------------
245 // Dynamic (re)configuration methods
247 getWallpaper: function () {
248 return this.wallpaper.wallpaper;
251 setTickSize: function(xTickSize, yTickSize) {
253 xt = me.xTickSize = xTickSize,
254 yt = me.yTickSize = (arguments.length > 1) ? yTickSize : xt;
256 me.windows.each(function(win) {
257 var dd = win.dd, resizer = win.resizer;
260 resizer.widthIncrement = xt;
261 resizer.heightIncrement = yt;
265 setWallpaper: function (wallpaper, stretch) {
266 this.wallpaper.setWallpaper(wallpaper, stretch);
270 //------------------------------------------------------
271 // Window management methods
273 cascadeWindows: function() {
275 zmgr = this.getDesktopZIndexManager();
277 zmgr.eachBottomUp(function(win) {
278 if (win.isWindow && win.isVisible() && !win.maximized) {
279 win.setPosition(x, y);
286 createWindow: function(config, cls) {
287 var me = this, win, cfg = Ext.applyIf(config || {}, {
290 constrainHeader: true,
295 cls = cls || Ext.window.Window;
296 win = me.add(new cls(cfg));
300 win.taskButton = me.taskbar.addTaskButton(win);
301 win.animateTarget = win.taskButton.el;
304 activate: me.updateActiveWindow,
305 beforeshow: me.updateActiveWindow,
306 deactivate: me.updateActiveWindow,
307 minimize: me.minimizeWindow,
308 destroy: me.onWindowClose,
313 afterrender: function () {
314 win.dd.xTickSize = me.xTickSize;
315 win.dd.yTickSize = me.yTickSize;
318 win.resizer.widthIncrement = me.xTickSize;
319 win.resizer.heightIncrement = me.yTickSize;
325 // replace normal window close w/fadeOut animation:
326 win.doClose = function () {
327 win.el.disableShadow();
330 afteranimate: function () {
340 getActiveWindow: function () {
342 zmgr = this.getDesktopZIndexManager();
345 // We cannot rely on activate/deactive because that fires against non-Window
346 // components in the stack.
348 zmgr.eachTopDown(function (comp) {
349 if (comp.isWindow && !comp.hidden) {
360 getDesktopZIndexManager: function () {
361 var windows = this.windows;
362 // TODO - there has to be a better way to get this...
363 return (windows.getCount() && windows.getAt(0).zIndexManager) || null;
366 getWindow: function(id) {
367 return this.windows.get(id);
370 minimizeWindow: function(win) {
371 win.minimized = true;
375 restoreWindow: function (win) {
376 if (win.isVisible()) {
385 tileWindows: function() {
386 var me = this, availWidth = me.body.getWidth(true);
387 var x = me.xTickSize, y = me.yTickSize, nextY = y;
389 me.windows.each(function(win) {
390 if (win.isVisible() && !win.maximized) {
391 var w = win.el.getWidth();
393 // Wrap to next row if we are not at the line start and this Window will
395 if (x > me.xTickSize && x + w > availWidth) {
400 win.setPosition(x, y);
401 x += w + me.xTickSize;
402 nextY = Math.max(nextY, y + win.el.getHeight() + me.yTickSize);
407 updateActiveWindow: function () {
408 var me = this, activeWindow = me.getActiveWindow(), last = me.lastActiveWindow;
409 if (activeWindow === last) {
415 last.addCls(me.inactiveWindowCls);
416 last.removeCls(me.activeWindowCls);
421 me.lastActiveWindow = activeWindow;
424 activeWindow.addCls(me.activeWindowCls);
425 activeWindow.removeCls(me.inactiveWindowCls);
426 activeWindow.minimized = false;
427 activeWindow.active = true;
430 me.taskbar.setActiveButton(activeWindow && activeWindow.taskButton);