stever
7 Oct 2007, 7:58 PM
I broke apart the desktop example to separate out the idea of applications/modules and the desktop window manager. As part of that, I removed the launcher, etc. Anyhow, here is the desktop window manager as a panel.
I have successfully put a portal in the desktop which sits behind the windows. Alternatively, I've put a desktop inside a portlet and dragged it around. I've done both at the same time, while also having a window up with a desktop in that, etc., etc. :D
I can't figure out one bug though -- every time I close a window there is an error (it is trying to stop listening on the window after it is already destroyed). Jack, can you provide any insight?
Ext.ux.Desktop = function(config)
{
config = Ext.apply(config || {},{
cls:'x-desktop',
bbar:[]
});
Ext.applyIf(config,{
layout:'fit'
});
Ext.ux.Desktop.superclass.constructor.call(this,config);
}
Ext.extend(Ext.ux.Desktop, Ext.Panel, {
initComponent : function(){
Ext.ux.Desktop.superclass.initComponent.call(this);
this.windows = new Ext.WindowGroup();
this.on('render',function(){
this.taskbar=this.getBottomToolbar();
this.taskbar.el.addClass('x-taskbar')
},this,{defer:50,single:true});
},
activeWindow:null,
minimizeWin: function(win){
win.minimized = true;
win.hide();
},
markActive: function(win){
if(this.activeWindow && this.activeWindow != win){
this.markInactive(this.activeWindow);
}
this.activeWindow = win;
Ext.fly(win.taskItem.el).addClass('active-win');
win.minimized = false;
},
markInactive: function(win){
if(win == this.activeWindow){
this.activeWindow = null;
Ext.fly(win.taskItem.el).removeClass('active-win');
}
},
removeWin: function(win){
win.taskItem.destroy();
},
createWindow: function(config, cls)
{
var win = new (cls||Ext.Window)(
Ext.applyIf(config||{}, {
manager: this.windows,
minimizable: true,
maximizable: true
})
);
win.render(this.body.dom);
win.taskItem = new Ext.ux.DesktopTaskBarItem(win);
this.taskbar.add(win.taskItem);
win.animateTarget = win.taskItem.el;
win.on('activate', this.markActive);
win.on('beforeshow', this.markActive);
win.on('deactivate', this.markInactive);
win.on('minimize', this.minimizeWin);
win.on('close', this.removeWin);
return win;
},
getManager: function(){
return this.windows;
},
getWindow: function(id){
return this.windows.get(id);
}
});
Ext.reg('desktop', Ext.ux.Desktop);
Ext.ux.DesktopTaskBarItem = function(win){
this.win = win;
Ext.ux.DesktopTaskBarItem.superclass.constructor.call(this, {
iconCls: win.iconCls,
text: win.title,
handler : function(){
if(win.minimized || win.hidden){
win.show();
}else if(win == win.manager.getActive()){
win.minimize();
}else{
win.toFront();
}
},
scope:this
});
};
Ext.extend(Ext.ux.DesktopTaskBarItem, Ext.Toolbar.Button, {
onRender : function(){
Ext.ux.DesktopTaskBarItem.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.win.close,
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);
}
});
.x-desktop {
width: 100%;
height: 100%;
border: 0 none;
position: relative;
overflow:hidden;
zoom: 1;
}
.x-taskbar .x-btn {
float: left;
margin: 2px 0 0 2px;
position:relative;
}
.x-taskbar button {
width: 150px;
overflow: hidden;
text-align: left;
color: #15428b;
}
.x-taskbar {
background: url(images/winbar-bg.gif ) #b9cbe1 repeat-x;
padding-top: 2px;
height:25px;
z-index:12001;
}
.x-taskbar .x-btn-left{
background:url(images/winbar-btn.gif) no-repeat 0 -189px;
}
.x-taskbar .x-btn-right{
background:url(images/winbar-btn.gif) no-repeat 0 -210px;
}
.x-taskbar .x-btn-center{
background:url(images/winbar-btn.gif) repeat-x 0 -231px;
}
.x-taskbar .x-btn-over .x-btn-left{
background:url(images/winbar-btn.gif) no-repeat 0 0;
}
.x-taskbar .x-btn-over .x-btn-right{
background:url(images/winbar-btn.gif) no-repeat 0 -21px;
}
.x-taskbar .x-btn-over .x-btn-center{
background:url(images/winbar-btn.gif) repeat-x 0 -42px;
}
.x-taskbar .x-btn-click .x-btn-left{
background:url(images/winbar-btn.gif) no-repeat 0 -63px;
}
.x-taskbar .x-btn-click .x-btn-right{
background:url(images/winbar-btn.gif) no-repeat 0 -84px;
}
.x-taskbar .x-btn-click .x-btn-center{
background:url(images/winbar-btn.gif) repeat-x 0 -105px;
}
.x-taskbar .active-win .x-btn-left{
background:url(images/winbar-btn.gif) no-repeat 0 -126px;
}
.x-taskbar .active-win .x-btn-right{
background:url(images/winbar-btn.gif) no-repeat 0 -147px;
}
.x-taskbar .active-win .x-btn-center{
background:url(images/winbar-btn.gif) repeat-x 0 -168px;
}
.x-taskbar .active-win .x-btn-center button {
color:#fff;
}
I have successfully put a portal in the desktop which sits behind the windows. Alternatively, I've put a desktop inside a portlet and dragged it around. I've done both at the same time, while also having a window up with a desktop in that, etc., etc. :D
I can't figure out one bug though -- every time I close a window there is an error (it is trying to stop listening on the window after it is already destroyed). Jack, can you provide any insight?
Ext.ux.Desktop = function(config)
{
config = Ext.apply(config || {},{
cls:'x-desktop',
bbar:[]
});
Ext.applyIf(config,{
layout:'fit'
});
Ext.ux.Desktop.superclass.constructor.call(this,config);
}
Ext.extend(Ext.ux.Desktop, Ext.Panel, {
initComponent : function(){
Ext.ux.Desktop.superclass.initComponent.call(this);
this.windows = new Ext.WindowGroup();
this.on('render',function(){
this.taskbar=this.getBottomToolbar();
this.taskbar.el.addClass('x-taskbar')
},this,{defer:50,single:true});
},
activeWindow:null,
minimizeWin: function(win){
win.minimized = true;
win.hide();
},
markActive: function(win){
if(this.activeWindow && this.activeWindow != win){
this.markInactive(this.activeWindow);
}
this.activeWindow = win;
Ext.fly(win.taskItem.el).addClass('active-win');
win.minimized = false;
},
markInactive: function(win){
if(win == this.activeWindow){
this.activeWindow = null;
Ext.fly(win.taskItem.el).removeClass('active-win');
}
},
removeWin: function(win){
win.taskItem.destroy();
},
createWindow: function(config, cls)
{
var win = new (cls||Ext.Window)(
Ext.applyIf(config||{}, {
manager: this.windows,
minimizable: true,
maximizable: true
})
);
win.render(this.body.dom);
win.taskItem = new Ext.ux.DesktopTaskBarItem(win);
this.taskbar.add(win.taskItem);
win.animateTarget = win.taskItem.el;
win.on('activate', this.markActive);
win.on('beforeshow', this.markActive);
win.on('deactivate', this.markInactive);
win.on('minimize', this.minimizeWin);
win.on('close', this.removeWin);
return win;
},
getManager: function(){
return this.windows;
},
getWindow: function(id){
return this.windows.get(id);
}
});
Ext.reg('desktop', Ext.ux.Desktop);
Ext.ux.DesktopTaskBarItem = function(win){
this.win = win;
Ext.ux.DesktopTaskBarItem.superclass.constructor.call(this, {
iconCls: win.iconCls,
text: win.title,
handler : function(){
if(win.minimized || win.hidden){
win.show();
}else if(win == win.manager.getActive()){
win.minimize();
}else{
win.toFront();
}
},
scope:this
});
};
Ext.extend(Ext.ux.DesktopTaskBarItem, Ext.Toolbar.Button, {
onRender : function(){
Ext.ux.DesktopTaskBarItem.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.win.close,
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);
}
});
.x-desktop {
width: 100%;
height: 100%;
border: 0 none;
position: relative;
overflow:hidden;
zoom: 1;
}
.x-taskbar .x-btn {
float: left;
margin: 2px 0 0 2px;
position:relative;
}
.x-taskbar button {
width: 150px;
overflow: hidden;
text-align: left;
color: #15428b;
}
.x-taskbar {
background: url(images/winbar-bg.gif ) #b9cbe1 repeat-x;
padding-top: 2px;
height:25px;
z-index:12001;
}
.x-taskbar .x-btn-left{
background:url(images/winbar-btn.gif) no-repeat 0 -189px;
}
.x-taskbar .x-btn-right{
background:url(images/winbar-btn.gif) no-repeat 0 -210px;
}
.x-taskbar .x-btn-center{
background:url(images/winbar-btn.gif) repeat-x 0 -231px;
}
.x-taskbar .x-btn-over .x-btn-left{
background:url(images/winbar-btn.gif) no-repeat 0 0;
}
.x-taskbar .x-btn-over .x-btn-right{
background:url(images/winbar-btn.gif) no-repeat 0 -21px;
}
.x-taskbar .x-btn-over .x-btn-center{
background:url(images/winbar-btn.gif) repeat-x 0 -42px;
}
.x-taskbar .x-btn-click .x-btn-left{
background:url(images/winbar-btn.gif) no-repeat 0 -63px;
}
.x-taskbar .x-btn-click .x-btn-right{
background:url(images/winbar-btn.gif) no-repeat 0 -84px;
}
.x-taskbar .x-btn-click .x-btn-center{
background:url(images/winbar-btn.gif) repeat-x 0 -105px;
}
.x-taskbar .active-win .x-btn-left{
background:url(images/winbar-btn.gif) no-repeat 0 -126px;
}
.x-taskbar .active-win .x-btn-right{
background:url(images/winbar-btn.gif) no-repeat 0 -147px;
}
.x-taskbar .active-win .x-btn-center{
background:url(images/winbar-btn.gif) repeat-x 0 -168px;
}
.x-taskbar .active-win .x-btn-center button {
color:#fff;
}