487 lines
No EOL
14 KiB
JavaScript
487 lines
No EOL
14 KiB
JavaScript
/*
|
|
This file is part of Ext JS 3.4
|
|
|
|
Copyright (c) 2011-2013 Sencha Inc
|
|
|
|
Contact: http://www.sencha.com/contact
|
|
|
|
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.
|
|
|
|
Build date: 2013-04-03 15:07:25
|
|
*/
|
|
/**
|
|
* @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> </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> </i></td>',
|
|
'</tr></tbody></table>')
|
|
});
|
|
|
|
var width = this.startBtn.getEl().getWidth()+10;
|
|
|
|
var sbBox = new Ext.BoxComponent({
|
|
el: 'ux-taskbar-start',
|
|
id: 'TaskBarStart',
|
|
minWidth: width,
|
|
region:'west',
|
|
split: true,
|
|
width: width
|
|
});
|
|
|
|
this.tbPanel = new Ext.ux.TaskButtonsPanel({
|
|
el: 'ux-taskbuttons-panel',
|
|
id: 'TaskBarButtons',
|
|
region:'center'
|
|
});
|
|
|
|
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);
|
|
}
|
|
});
|
|
|
|
|
|
|
|
/**
|
|
* @class Ext.ux.TaskBarContainer
|
|
* @extends Ext.Container
|
|
*/
|
|
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;
|
|
},
|
|
|
|
fireResize : function(w, h){
|
|
this.onResize(w, h, w, h);
|
|
this.fireEvent('resize', this, w, h, w, h);
|
|
}
|
|
});
|
|
|
|
|
|
|
|
/**
|
|
* @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'
|
|
});
|
|
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'
|
|
});
|
|
},
|
|
|
|
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;
|
|
},
|
|
|
|
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();
|
|
},
|
|
|
|
setActiveButton : function(btn){
|
|
this.activeButton = btn;
|
|
this.delegateUpdates();
|
|
},
|
|
|
|
delegateUpdates : function(){
|
|
/*if(this.suspendUpdates){
|
|
return;
|
|
}*/
|
|
if(this.resizeButtons && this.rendered){
|
|
this.autoSize();
|
|
}
|
|
if(this.enableScroll && this.rendered){
|
|
this.autoScroll();
|
|
}
|
|
},
|
|
|
|
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;
|
|
}
|
|
|
|
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;
|
|
|
|
btn.style.width = (each - (tw-iw)) + 'px';
|
|
}
|
|
},
|
|
|
|
autoScroll : function(){
|
|
var count = this.items.length;
|
|
var ow = this.el.dom.offsetWidth;
|
|
var tw = this.el.dom.clientWidth;
|
|
|
|
var wrap = this.stripWrap;
|
|
var cw = wrap.dom.offsetWidth;
|
|
var pos = this.getScrollPos();
|
|
var l = this.edge.getOffsetsTo(this.stripWrap)[0] + pos;
|
|
|
|
if(!this.enableScroll || count < 1 || cw < 20){ // 20 to prevent display:none issues
|
|
return;
|
|
}
|
|
|
|
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();
|
|
}
|
|
}
|
|
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;
|
|
|
|
// 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;
|
|
|
|
// 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;
|
|
},
|
|
|
|
getScrollWidth : function(){
|
|
return this.edge.getOffsetsTo(this.stripWrap)[0] + this.getScrollPos();
|
|
},
|
|
|
|
getScrollPos : function(){
|
|
return parseInt(this.stripWrap.dom.scrollLeft, 10) || 0;
|
|
},
|
|
|
|
getScrollArea : function(){
|
|
return parseInt(this.stripWrap.dom.clientWidth, 10) || 0;
|
|
},
|
|
|
|
getScrollAnim : function(){
|
|
return {
|
|
duration: this.scrollDuration,
|
|
callback: this.updateScrollButtons,
|
|
scope: this
|
|
};
|
|
},
|
|
|
|
getScrollIncrement : function(){
|
|
return (this.scrollIncrement || this.lastButtonWidth+2);
|
|
},
|
|
|
|
/* 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);
|
|
}
|
|
},
|
|
|
|
scrollTo : function(pos, animate){
|
|
this.stripWrap.scrollTo('left', pos, animate ? this.getScrollAnim() : false);
|
|
if(!animate){
|
|
this.updateScrollButtons();
|
|
}
|
|
},
|
|
|
|
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);
|
|
}
|
|
},
|
|
|
|
onScrollLeft : function(){
|
|
var pos = this.getScrollPos();
|
|
var s = Math.max(0, pos - this.getScrollIncrement());
|
|
if(s != pos){
|
|
this.scrollTo(s, this.animScroll);
|
|
}
|
|
},
|
|
|
|
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> </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> </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);
|
|
},
|
|
|
|
closeWin : function(cMenu, e, win){
|
|
if(!win.isVisible()){
|
|
win.show();
|
|
}else{
|
|
win.restore();
|
|
}
|
|
win.close();
|
|
}
|
|
}); |