TaskBar.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. /*!
  2. * Ext JS Library 3.3.1
  3. * Copyright(c) 2006-2010 Sencha Inc.
  4. * licensing@sencha.com
  5. * http://www.sencha.com/license
  6. */
  7. /**
  8. * @class Ext.ux.TaskBar
  9. * @extends Ext.util.Observable
  10. */
  11. Ext.ux.TaskBar = function(app){
  12. this.app = app;
  13. this.init();
  14. }
  15. Ext.extend(Ext.ux.TaskBar, Ext.util.Observable, {
  16. init : function(){
  17. this.startMenu = new Ext.ux.StartMenu(Ext.apply({
  18. iconCls: 'user',
  19. height: 300,
  20. shadow: true,
  21. title: 'Tommy Maintz',
  22. width: 300
  23. }, this.app.startConfig));
  24. this.startBtn = new Ext.Button({
  25. text: 'Start',
  26. id: 'ux-startbutton',
  27. iconCls:'start',
  28. menu: this.startMenu,
  29. menuAlign: 'bl-tl',
  30. renderTo: 'ux-taskbar-start',
  31. clickEvent: 'mousedown',
  32. template: new Ext.Template(
  33. '<table cellspacing="0" class="x-btn"><tbody class="{1}"><tr>',
  34. '<td class="ux-startbutton-left"><i>&#160;</i></td>',
  35. '<td class="ux-startbutton-center"><em class="{2} unselectable="on">',
  36. '<button class="x-btn-text" type="{0}" style="height:30px;"></button>',
  37. '</em></td>',
  38. '<td class="ux-startbutton-right"><i>&#160;</i></td>',
  39. '</tr></tbody></table>')
  40. });
  41. var width = this.startBtn.getEl().getWidth()+10;
  42. var sbBox = new Ext.BoxComponent({
  43. el: 'ux-taskbar-start',
  44. id: 'TaskBarStart',
  45. minWidth: width,
  46. region:'west',
  47. split: true,
  48. width: width
  49. });
  50. this.tbPanel = new Ext.ux.TaskButtonsPanel({
  51. el: 'ux-taskbuttons-panel',
  52. id: 'TaskBarButtons',
  53. region:'center'
  54. });
  55. var container = new Ext.ux.TaskBarContainer({
  56. el: 'ux-taskbar',
  57. layout: 'border',
  58. items: [sbBox,this.tbPanel]
  59. });
  60. return this;
  61. },
  62. addTaskButton : function(win){
  63. return this.tbPanel.addButton(win, 'ux-taskbuttons-panel');
  64. },
  65. removeTaskButton : function(btn){
  66. this.tbPanel.removeButton(btn);
  67. },
  68. setActiveButton : function(btn){
  69. this.tbPanel.setActiveButton(btn);
  70. }
  71. });
  72. /**
  73. * @class Ext.ux.TaskBarContainer
  74. * @extends Ext.Container
  75. */
  76. Ext.ux.TaskBarContainer = Ext.extend(Ext.Container, {
  77. initComponent : function() {
  78. Ext.ux.TaskBarContainer.superclass.initComponent.call(this);
  79. this.el = Ext.get(this.el) || Ext.getBody();
  80. this.el.setHeight = Ext.emptyFn;
  81. this.el.setWidth = Ext.emptyFn;
  82. this.el.setSize = Ext.emptyFn;
  83. this.el.setStyle({
  84. overflow:'hidden',
  85. margin:'0',
  86. border:'0 none'
  87. });
  88. this.el.dom.scroll = 'no';
  89. this.allowDomMove = false;
  90. this.autoWidth = true;
  91. this.autoHeight = true;
  92. Ext.EventManager.onWindowResize(this.fireResize, this);
  93. this.renderTo = this.el;
  94. },
  95. fireResize : function(w, h){
  96. this.onResize(w, h, w, h);
  97. this.fireEvent('resize', this, w, h, w, h);
  98. }
  99. });
  100. /**
  101. * @class Ext.ux.TaskButtonsPanel
  102. * @extends Ext.BoxComponent
  103. */
  104. Ext.ux.TaskButtonsPanel = Ext.extend(Ext.BoxComponent, {
  105. activeButton: null,
  106. enableScroll: true,
  107. scrollIncrement: 0,
  108. scrollRepeatInterval: 400,
  109. scrollDuration: .35,
  110. animScroll: true,
  111. resizeButtons: true,
  112. buttonWidth: 168,
  113. minButtonWidth: 118,
  114. buttonMargin: 2,
  115. buttonWidthSet: false,
  116. initComponent : function() {
  117. Ext.ux.TaskButtonsPanel.superclass.initComponent.call(this);
  118. this.on('resize', this.delegateUpdates);
  119. this.items = [];
  120. this.stripWrap = Ext.get(this.el).createChild({
  121. cls: 'ux-taskbuttons-strip-wrap',
  122. cn: {
  123. tag:'ul', cls:'ux-taskbuttons-strip'
  124. }
  125. });
  126. this.stripSpacer = Ext.get(this.el).createChild({
  127. cls:'ux-taskbuttons-strip-spacer'
  128. });
  129. this.strip = new Ext.Element(this.stripWrap.dom.firstChild);
  130. this.edge = this.strip.createChild({
  131. tag:'li',
  132. cls:'ux-taskbuttons-edge'
  133. });
  134. this.strip.createChild({
  135. cls:'x-clear'
  136. });
  137. },
  138. addButton : function(win){
  139. var li = this.strip.createChild({tag:'li'}, this.edge); // insert before the edge
  140. var btn = new Ext.ux.TaskBar.TaskButton(win, li);
  141. this.items.push(btn);
  142. if(!this.buttonWidthSet){
  143. this.lastButtonWidth = btn.container.getWidth();
  144. }
  145. this.setActiveButton(btn);
  146. return btn;
  147. },
  148. removeButton : function(btn){
  149. var li = document.getElementById(btn.container.id);
  150. btn.destroy();
  151. li.parentNode.removeChild(li);
  152. var s = [];
  153. for(var i = 0, len = this.items.length; i < len; i++) {
  154. if(this.items[i] != btn){
  155. s.push(this.items[i]);
  156. }
  157. }
  158. this.items = s;
  159. this.delegateUpdates();
  160. },
  161. setActiveButton : function(btn){
  162. this.activeButton = btn;
  163. this.delegateUpdates();
  164. },
  165. delegateUpdates : function(){
  166. /*if(this.suspendUpdates){
  167. return;
  168. }*/
  169. if(this.resizeButtons && this.rendered){
  170. this.autoSize();
  171. }
  172. if(this.enableScroll && this.rendered){
  173. this.autoScroll();
  174. }
  175. },
  176. autoSize : function(){
  177. var count = this.items.length;
  178. var ow = this.el.dom.offsetWidth;
  179. var aw = this.el.dom.clientWidth;
  180. if(!this.resizeButtons || count < 1 || !aw){ // !aw for display:none
  181. return;
  182. }
  183. var each = Math.max(Math.min(Math.floor((aw-4) / count) - this.buttonMargin, this.buttonWidth), this.minButtonWidth); // -4 for float errors in IE
  184. var btns = this.stripWrap.dom.getElementsByTagName('button');
  185. this.lastButtonWidth = Ext.get(btns[0].id).findParent('li').offsetWidth;
  186. for(var i = 0, len = btns.length; i < len; i++) {
  187. var btn = btns[i];
  188. var tw = Ext.get(btns[i].id).findParent('li').offsetWidth;
  189. var iw = btn.offsetWidth;
  190. btn.style.width = (each - (tw-iw)) + 'px';
  191. }
  192. },
  193. autoScroll : function(){
  194. var count = this.items.length;
  195. var ow = this.el.dom.offsetWidth;
  196. var tw = this.el.dom.clientWidth;
  197. var wrap = this.stripWrap;
  198. var cw = wrap.dom.offsetWidth;
  199. var pos = this.getScrollPos();
  200. var l = this.edge.getOffsetsTo(this.stripWrap)[0] + pos;
  201. if(!this.enableScroll || count < 1 || cw < 20){ // 20 to prevent display:none issues
  202. return;
  203. }
  204. wrap.setWidth(tw); // moved to here because of problem in Safari
  205. if(l <= tw){
  206. wrap.dom.scrollLeft = 0;
  207. //wrap.setWidth(tw); moved from here because of problem in Safari
  208. if(this.scrolling){
  209. this.scrolling = false;
  210. this.el.removeClass('x-taskbuttons-scrolling');
  211. this.scrollLeft.hide();
  212. this.scrollRight.hide();
  213. }
  214. }else{
  215. if(!this.scrolling){
  216. this.el.addClass('x-taskbuttons-scrolling');
  217. }
  218. tw -= wrap.getMargins('lr');
  219. wrap.setWidth(tw > 20 ? tw : 20);
  220. if(!this.scrolling){
  221. if(!this.scrollLeft){
  222. this.createScrollers();
  223. }else{
  224. this.scrollLeft.show();
  225. this.scrollRight.show();
  226. }
  227. }
  228. this.scrolling = true;
  229. if(pos > (l-tw)){ // ensure it stays within bounds
  230. wrap.dom.scrollLeft = l-tw;
  231. }else{ // otherwise, make sure the active button is still visible
  232. this.scrollToButton(this.activeButton, true); // true to animate
  233. }
  234. this.updateScrollButtons();
  235. }
  236. },
  237. createScrollers : function(){
  238. var h = this.el.dom.offsetHeight; //var h = this.stripWrap.dom.offsetHeight;
  239. // left
  240. var sl = this.el.insertFirst({
  241. cls:'ux-taskbuttons-scroller-left'
  242. });
  243. sl.setHeight(h);
  244. sl.addClassOnOver('ux-taskbuttons-scroller-left-over');
  245. this.leftRepeater = new Ext.util.ClickRepeater(sl, {
  246. interval : this.scrollRepeatInterval,
  247. handler: this.onScrollLeft,
  248. scope: this
  249. });
  250. this.scrollLeft = sl;
  251. // right
  252. var sr = this.el.insertFirst({
  253. cls:'ux-taskbuttons-scroller-right'
  254. });
  255. sr.setHeight(h);
  256. sr.addClassOnOver('ux-taskbuttons-scroller-right-over');
  257. this.rightRepeater = new Ext.util.ClickRepeater(sr, {
  258. interval : this.scrollRepeatInterval,
  259. handler: this.onScrollRight,
  260. scope: this
  261. });
  262. this.scrollRight = sr;
  263. },
  264. getScrollWidth : function(){
  265. return this.edge.getOffsetsTo(this.stripWrap)[0] + this.getScrollPos();
  266. },
  267. getScrollPos : function(){
  268. return parseInt(this.stripWrap.dom.scrollLeft, 10) || 0;
  269. },
  270. getScrollArea : function(){
  271. return parseInt(this.stripWrap.dom.clientWidth, 10) || 0;
  272. },
  273. getScrollAnim : function(){
  274. return {
  275. duration: this.scrollDuration,
  276. callback: this.updateScrollButtons,
  277. scope: this
  278. };
  279. },
  280. getScrollIncrement : function(){
  281. return (this.scrollIncrement || this.lastButtonWidth+2);
  282. },
  283. /* getBtnEl : function(item){
  284. return document.getElementById(item.id);
  285. }, */
  286. scrollToButton : function(item, animate){
  287. item = item.el.dom.parentNode; // li
  288. if(!item){ return; }
  289. var el = item; //this.getBtnEl(item);
  290. var pos = this.getScrollPos(), area = this.getScrollArea();
  291. var left = Ext.fly(el).getOffsetsTo(this.stripWrap)[0] + pos;
  292. var right = left + el.offsetWidth;
  293. if(left < pos){
  294. this.scrollTo(left, animate);
  295. }else if(right > (pos + area)){
  296. this.scrollTo(right - area, animate);
  297. }
  298. },
  299. scrollTo : function(pos, animate){
  300. this.stripWrap.scrollTo('left', pos, animate ? this.getScrollAnim() : false);
  301. if(!animate){
  302. this.updateScrollButtons();
  303. }
  304. },
  305. onScrollRight : function(){
  306. var sw = this.getScrollWidth()-this.getScrollArea();
  307. var pos = this.getScrollPos();
  308. var s = Math.min(sw, pos + this.getScrollIncrement());
  309. if(s != pos){
  310. this.scrollTo(s, this.animScroll);
  311. }
  312. },
  313. onScrollLeft : function(){
  314. var pos = this.getScrollPos();
  315. var s = Math.max(0, pos - this.getScrollIncrement());
  316. if(s != pos){
  317. this.scrollTo(s, this.animScroll);
  318. }
  319. },
  320. updateScrollButtons : function(){
  321. var pos = this.getScrollPos();
  322. this.scrollLeft[pos == 0 ? 'addClass' : 'removeClass']('ux-taskbuttons-scroller-left-disabled');
  323. this.scrollRight[pos >= (this.getScrollWidth()-this.getScrollArea()) ? 'addClass' : 'removeClass']('ux-taskbuttons-scroller-right-disabled');
  324. }
  325. });
  326. /**
  327. * @class Ext.ux.TaskBar.TaskButton
  328. * @extends Ext.Button
  329. */
  330. Ext.ux.TaskBar.TaskButton = function(win, el){
  331. this.win = win;
  332. Ext.ux.TaskBar.TaskButton.superclass.constructor.call(this, {
  333. iconCls: win.iconCls,
  334. text: Ext.util.Format.ellipsis(win.title, 12),
  335. renderTo: el,
  336. handler : function(){
  337. if(win.minimized || win.hidden){
  338. win.show();
  339. }else if(win == win.manager.getActive()){
  340. win.minimize();
  341. }else{
  342. win.toFront();
  343. }
  344. },
  345. clickEvent:'mousedown',
  346. template: new Ext.Template(
  347. '<table cellspacing="0" class="x-btn {3}"><tbody><tr>',
  348. '<td class="ux-taskbutton-left"><i>&#160;</i></td>',
  349. '<td class="ux-taskbutton-center"><em class="{5} unselectable="on">',
  350. '<button class="x-btn-text {2}" type="{1}" style="height:28px;">{0}</button>',
  351. '</em></td>',
  352. '<td class="ux-taskbutton-right"><i>&#160;</i></td>',
  353. "</tr></tbody></table>")
  354. });
  355. };
  356. Ext.extend(Ext.ux.TaskBar.TaskButton, Ext.Button, {
  357. onRender : function(){
  358. Ext.ux.TaskBar.TaskButton.superclass.onRender.apply(this, arguments);
  359. this.cmenu = new Ext.menu.Menu({
  360. items: [{
  361. text: 'Restore',
  362. handler: function(){
  363. if(!this.win.isVisible()){
  364. this.win.show();
  365. }else{
  366. this.win.restore();
  367. }
  368. },
  369. scope: this
  370. },{
  371. text: 'Minimize',
  372. handler: this.win.minimize,
  373. scope: this.win
  374. },{
  375. text: 'Maximize',
  376. handler: this.win.maximize,
  377. scope: this.win
  378. }, '-', {
  379. text: 'Close',
  380. handler: this.closeWin.createDelegate(this, this.win, true),
  381. scope: this.win
  382. }]
  383. });
  384. this.cmenu.on('beforeshow', function(){
  385. var items = this.cmenu.items.items;
  386. var w = this.win;
  387. items[0].setDisabled(w.maximized !== true && w.hidden !== true);
  388. items[1].setDisabled(w.minimized === true);
  389. items[2].setDisabled(w.maximized === true || w.hidden === true);
  390. }, this);
  391. this.el.on('contextmenu', function(e){
  392. e.stopEvent();
  393. if(!this.cmenu.el){
  394. this.cmenu.render();
  395. }
  396. var xy = e.getXY();
  397. xy[1] -= this.cmenu.el.getHeight();
  398. this.cmenu.showAt(xy);
  399. }, this);
  400. },
  401. closeWin : function(cMenu, e, win){
  402. if(!win.isVisible()){
  403. win.show();
  404. }else{
  405. win.restore();
  406. }
  407. win.close();
  408. }
  409. });