r25048: From the archives (patch found in one of my old working trees):
[jelmer/samba4-debian.git] / webapps / qooxdoo-0.6.5-sdk / frontend / framework / source / class / qx / ui / window / Window.js
1 /* ************************************************************************
2
3    qooxdoo - the new era of web development
4
5    http://qooxdoo.org
6
7    Copyright:
8      2004-2007 1&1 Internet AG, Germany, http://www.1and1.org
9
10    License:
11      LGPL: http://www.gnu.org/licenses/lgpl.html
12      EPL: http://www.eclipse.org/org/documents/epl-v10.php
13      See the LICENSE file in the project's top-level directory for details.
14
15    Authors:
16      * Sebastian Werner (wpbasti)
17      * Andreas Ecker (ecker)
18
19 ************************************************************************ */
20
21 /* ************************************************************************
22
23 #module(ui_window)
24 #embed(qx.widgettheme/window/*)
25
26 ************************************************************************ */
27
28 qx.OO.defineClass("qx.ui.window.Window", qx.ui.popup.Popup,
29 function(vCaption, vIcon, vWindowManager)
30 {
31   qx.ui.popup.Popup.call(this);
32
33   // ************************************************************************
34   //   FUNCTIONAL STYLE
35   // ************************************************************************
36
37   this.setMinWidth("auto");
38   this.setMinHeight("auto");
39   this.setAutoHide(false);
40
41
42
43   // ************************************************************************
44   //   MANAGER
45   // ************************************************************************
46
47   // Init Window Manager
48   this.setWindowManager(vWindowManager || qx.ui.window.Window.getDefaultWindowManager());
49
50
51
52   // ************************************************************************
53   //   RESIZE AND MOVE FRAME
54   // ************************************************************************
55
56   var f = this._frame = new qx.ui.basic.Terminator;
57   f.setAppearance("window-resize-frame");
58
59
60   // ************************************************************************
61   //   LAYOUT
62   // ************************************************************************
63
64   var l = this._layout = new qx.ui.layout.VerticalBoxLayout;
65   l.setEdge(0);
66   this.add(l);
67
68
69   // ************************************************************************
70   //   CAPTIONBAR
71   // ************************************************************************
72
73   var cb = this._captionBar = new qx.ui.layout.HorizontalBoxLayout;
74   cb.setAppearance("window-captionbar");
75   l.add(cb);
76
77
78   // ************************************************************************
79   //   CAPTIONICON
80   // ************************************************************************
81
82   if (vIcon != null)
83   {
84     var ci = this._captionIcon = new qx.ui.basic.Image(vIcon);
85     ci.setAppearance("window-captionbar-icon");
86     cb.add(ci);
87   }
88
89
90   // ************************************************************************
91   //   CAPTIONTITLE
92   // ************************************************************************
93
94   var ct = this._captionTitle = new qx.ui.basic.Label(vCaption);
95   ct.setAppearance("window-captionbar-title");
96   ct.setSelectable(false);
97   cb.add(ct);
98
99
100   // ************************************************************************
101   //   CAPTIONFLEX
102   // ************************************************************************
103
104   var cf = this._captionFlex = new qx.ui.basic.HorizontalSpacer;
105   cb.add(cf);
106
107
108   // ************************************************************************
109   //   CAPTIONBUTTONS: MINIMIZE
110   // ************************************************************************
111
112   var bm = this._minimizeButton = new qx.ui.form.Button(null, "widget/window/minimize.gif");
113
114   bm.setAppearance("window-captionbar-minimize-button");
115   bm.setTabIndex(-1);
116
117   bm.addEventListener("execute", this._onminimizebuttonclick, this);
118   bm.addEventListener("mousedown", this._onbuttonmousedown, this);
119
120   cb.add(bm);
121
122
123   // ************************************************************************
124   //   CAPTIONBUTTONS: RESTORE
125   // ************************************************************************
126
127   var br = this._restoreButton = new qx.ui.form.Button(null, "widget/window/restore.gif");
128
129   br.setAppearance("window-captionbar-restore-button");
130   br.setTabIndex(-1);
131
132   br.addEventListener("execute", this._onrestorebuttonclick, this);
133   br.addEventListener("mousedown", this._onbuttonmousedown, this);
134
135   // don't add initially
136   // cb.add(br);
137
138
139   // ************************************************************************
140   //   CAPTIONBUTTONS: MAXIMIZE
141   // ************************************************************************
142
143   var bx = this._maximizeButton = new qx.ui.form.Button(null, "widget/window/maximize.gif");
144
145   bx.setAppearance("window-captionbar-maximize-button");
146   bx.setTabIndex(-1);
147
148   bx.addEventListener("execute", this._onmaximizebuttonclick, this);
149   bx.addEventListener("mousedown", this._onbuttonmousedown, this);
150
151   cb.add(bx);
152
153
154   // ************************************************************************
155   //   CAPTIONBUTTONS: CLOSE
156   // ************************************************************************
157
158   var bc = this._closeButton = new qx.ui.form.Button(null, "widget/window/close.gif");
159
160   bc.setAppearance("window-captionbar-close-button");
161   bc.setTabIndex(-1);
162
163   bc.addEventListener("execute", this._onclosebuttonclick, this);
164   bc.addEventListener("mousedown", this._onbuttonmousedown, this);
165
166   cb.add(bc);
167
168
169   // ************************************************************************
170   //   PANE
171   // ************************************************************************
172
173   var p = this._pane = new qx.ui.layout.CanvasLayout;
174   p.setHeight("1*");
175   p.setOverflow("hidden");
176   l.add(p);
177
178
179   // ************************************************************************
180   //   STATUSBAR
181   // ************************************************************************
182
183   var sb = this._statusBar = new qx.ui.layout.HorizontalBoxLayout;
184   sb.setAppearance("window-statusbar");
185
186
187   // ************************************************************************
188   //   STATUSTEXT
189   // ************************************************************************
190
191   var st = this._statusText = new qx.ui.basic.Label("Ready");
192   st.setAppearance("window-statusbar-text");
193   st.setSelectable(false);
194   sb.add(st);
195
196
197   // ************************************************************************
198   //   INIT
199   // ************************************************************************
200
201   this.setCaption(vCaption);
202   this.setIcon(vIcon);
203
204
205   // ************************************************************************
206   //   EVENTS: WINDOW
207   // ************************************************************************
208
209   this.addEventListener("mousedown", this._onwindowmousedown, this);
210   this.addEventListener("mouseup", this._onwindowmouseup, this);
211   this.addEventListener("mousemove", this._onwindowmousemove, this);
212   this.addEventListener("click", this._onwindowclick, this);
213
214
215   // ************************************************************************
216   //   EVENTS: CAPTIONBAR
217   // ************************************************************************
218
219   cb.addEventListener("mousedown", this._oncaptionmousedown, this);
220   cb.addEventListener("mouseup", this._oncaptionmouseup, this);
221   cb.addEventListener("mousemove", this._oncaptionmousemove, this);
222   cb.addEventListener("dblclick", this._oncaptiondblblick, this);
223
224
225   // ************************************************************************
226   //   REMAPPING
227   // ************************************************************************
228   this.remapChildrenHandlingTo(this._pane);
229 });
230
231
232
233
234
235 /*
236 ---------------------------------------------------------------------------
237   PROPERTIES
238 ---------------------------------------------------------------------------
239 */
240
241 /*!
242   Appearance of the widget
243 */
244 qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "window" });
245
246 /*!
247   The windowManager to use for.
248 */
249 qx.OO.addProperty({ name : "windowManager", type : "object" });
250
251 /*!
252   If the window is active, only one window in a single qx.manager.object.WindowManager could
253   have set this to true at the same time.
254 */
255 qx.OO.addProperty({ name : "active", type : "boolean", defaultValue : false });
256
257 /*!
258   Should be window be modal (this disable minimize and maximize buttons)
259 */
260 qx.OO.addProperty({ name : "modal", type : "boolean", defaultValue : false });
261
262 /*!
263   Should be window be modal (this disable minimize and maximize buttons)
264 */
265 qx.OO.addProperty({ name : "mode", type : "string", defaultValue : null, possibleValues : [ "minimized", "maximized" ], allowNull : true });
266
267 /*!
268   The opener (button) of the window
269 */
270 qx.OO.addProperty({ name : "opener", type : "object" });
271
272 /*!
273   The text of the caption
274 */
275 qx.OO.addProperty({ name : "caption" });
276
277 /*!
278   The icon of the caption
279 */
280 qx.OO.addProperty({ name : "icon", type : "string" });
281
282 /*!
283   The text of the statusbar
284 */
285 qx.OO.addProperty({ name : "status", type : "string", defaultValue : "Ready" });
286
287 /*!
288   Should the close button be shown
289 */
290 qx.OO.addProperty({ name : "showClose", type : "boolean", defaultValue : true });
291
292 /*!
293   Should the maximize button be shown
294 */
295 qx.OO.addProperty({ name : "showMaximize", type : "boolean", defaultValue : true });
296
297 /*!
298   Should the minimize button be shown
299 */
300 qx.OO.addProperty({ name : "showMinimize", type : "boolean", defaultValue : true });
301
302 /*!
303   Should the statusbar be shown
304 */
305 qx.OO.addProperty({ name : "showStatusbar", type : "boolean", defaultValue : false });
306
307 /*!
308   Should the user have the ability to close the window
309 */
310 qx.OO.addProperty({ name : "allowClose", type : "boolean", defaultValue : true });
311
312 /*!
313   Should the user have the ability to maximize the window
314 */
315 qx.OO.addProperty({ name : "allowMaximize", type : "boolean", defaultValue : true });
316
317 /*!
318   Should the user have the ability to minimize the window
319 */
320 qx.OO.addProperty({ name : "allowMinimize", type : "boolean", defaultValue : true });
321
322 /*!
323   If the text (in the captionbar) should be visible
324 */
325 qx.OO.addProperty({ name : "showCaption", type : "boolean", defaultValue : true });
326
327 /*!
328   If the icon (in the captionbar) should be visible
329 */
330 qx.OO.addProperty({ name : "showIcon", type : "boolean", defaultValue : true });
331
332 /*!
333   If the window is resizeable
334 */
335 qx.OO.addProperty({ name : "resizeable", type : "boolean", defaultValue : true });
336
337 /*!
338   If the window is moveable
339 */
340 qx.OO.addProperty({ name : "moveable", type : "boolean", defaultValue : true });
341
342 /*!
343   The resize method to use
344 */
345 qx.OO.addProperty({ name : "resizeMethod", type : "string", defaultValue : "frame", possibleValues : [ "opaque", "lazyopaque", "frame", "translucent" ] });
346
347 /*!
348   The move method to use
349 */
350 qx.OO.addProperty({ name : "moveMethod", type : "string", defaultValue : "opaque", possibleValues : [ "opaque", "frame", "translucent" ] });
351
352
353
354
355 /*
356 ---------------------------------------------------------------------------
357   MANAGER HANDLING
358 ---------------------------------------------------------------------------
359 */
360
361 qx.ui.window.Window.getDefaultWindowManager = function()
362 {
363   if (!qx.ui.window.Window._defaultWindowManager) {
364     qx.ui.window.Window._defaultWindowManager = new qx.manager.object.WindowManager;
365   }
366
367   return qx.ui.window.Window._defaultWindowManager;
368 }
369
370
371
372
373
374 /*
375 ---------------------------------------------------------------------------
376   UTILITIES
377 ---------------------------------------------------------------------------
378 */
379
380 qx.Proto.getPane = function() {
381   return this._pane;
382 }
383
384 qx.Proto.getCaptionBar = function() {
385   return this._captionBar;
386 }
387
388 qx.Proto.getStatusBar = function() {
389   return this._statusBar;
390 }
391
392 qx.Proto.close = function() {
393   this.hide();
394 }
395
396 qx.Proto.open = function(vOpener)
397 {
398   if (vOpener != null) {
399     this.setOpener(vOpener);
400   }
401
402   if (this.getCentered()) {
403     this.centerToBrowser();
404   }
405
406   this.show();
407 }
408
409 qx.Proto.focus = function() {
410   this.setActive(true);
411 }
412
413 qx.Proto.blur = function() {
414   this.setActive(false);
415 }
416
417 qx.Proto.maximize = function() {
418   this.setMode("maximized");
419 }
420
421 qx.Proto.minimize = function() {
422   this.setMode("minimized");
423 }
424
425 qx.Proto.restore = function() {
426   this.setMode(null);
427 }
428
429
430
431
432
433
434
435
436 /*
437 ---------------------------------------------------------------------------
438   APPEAR/DISAPPEAR
439 ---------------------------------------------------------------------------
440 */
441
442 qx.Proto._beforeAppear = function()
443 {
444   // Intentionally bypass superclass and call super.super._beforeAppear
445   qx.ui.layout.CanvasLayout.prototype._beforeAppear.call(this);
446
447   // Hide popups
448   qx.manager.object.PopupManager.getInstance().update();
449
450   // Configure the focus root to be the current opened window
451   qx.event.handler.EventHandler.getInstance().setFocusRoot(this);
452
453   this.getWindowManager().add(this);
454   this._makeActive();
455 }
456
457 qx.Proto._beforeDisappear = function()
458 {
459   // Intentionally bypass superclass and call super.super._beforeDisappear
460   qx.ui.layout.CanvasLayout.prototype._beforeDisappear.call(this);
461
462   // Reset focus root
463   var vFocusRoot = qx.event.handler.EventHandler.getInstance().getFocusRoot();
464   if (vFocusRoot == this || this.contains(vFocusRoot)) {
465     qx.event.handler.EventHandler.getInstance().setFocusRoot(null);
466   }
467
468   // Be sure to disable any capturing inside invisible parts
469   // Is this to much overhead?
470   // Are there any other working solutions?
471   var vWidget = qx.event.handler.EventHandler.getInstance().getCaptureWidget();
472   if (vWidget && this.contains(vWidget)) {
473     vWidget.setCapture(false);
474   }
475
476   this.getWindowManager().remove(this);
477   this._makeInactive();
478 }
479
480
481
482
483
484 /*
485 ---------------------------------------------------------------------------
486   ZIndex Positioning
487 ---------------------------------------------------------------------------
488 */
489
490 qx.Proto._minZIndex = 1e5;
491
492 qx.Proto._sendTo = function()
493 {
494   var vAll = qx.lang.Object.getValues(this.getWindowManager().getAll()).sort(qx.util.Compare.byZIndex);
495   var vLength = vAll.length;
496   var vIndex = this._minZIndex;
497
498   for (var i=0; i<vLength; i++) {
499     vAll[i].setZIndex(vIndex++);
500   }
501 }
502
503
504
505
506
507
508 /*
509 ---------------------------------------------------------------------------
510   MODIFIERS
511 ---------------------------------------------------------------------------
512 */
513
514 qx.Proto._modifyActive = function(propValue, propOldValue, propData)
515 {
516   if (propOldValue)
517   {
518     if (this.getFocused()) {
519       this.setFocused(false);
520     }
521
522     if (this.getWindowManager().getActiveWindow() == this) {
523       this.getWindowManager().setActiveWindow(null);
524     }
525
526     this.removeState("active");
527     this._captionBar.removeState("active");
528   }
529   else
530   {
531     // Switch focus
532     // Also do this if gets inactive as this moved the focus outline
533     // away from any focused child.
534     if (!this.getFocusedChild()) {
535       this.setFocused(true);
536     }
537
538     this.getWindowManager().setActiveWindow(this);
539     this.bringToFront();
540
541     this.addState("active");
542     this._captionBar.addState("active");
543   }
544
545   return true;
546 }
547
548 qx.Proto._modifyModal = function(propValue, propOldValue, propData)
549 {
550   // Inform blocker
551   if (this._initialLayoutDone && this.getVisibility() && this.getDisplay())
552   {
553     var vTop = this.getTopLevelWidget();
554     propValue ? vTop.block(this) : vTop.release(this);
555   }
556
557   return true;
558 }
559
560 qx.Proto._modifyAllowClose = function(propValue, propOldValue, propData) {
561   return this._closeButtonManager();
562 }
563
564 qx.Proto._modifyAllowMaximize = function(propValue, propOldValue, propData) {
565   return this._maximizeButtonManager();
566 }
567
568 qx.Proto._modifyAllowMinimize = function(propValue, propOldValue, propData) {
569   return this._minimizeButtonManager();
570 }
571
572 qx.Proto._modifyMode = function(propValue, propOldValue, propData)
573 {
574   switch(propValue)
575   {
576     case "minimized":
577       this._minimize();
578       break;
579
580     case "maximized":
581       this._maximize();
582       break;
583
584     default:
585       switch(propOldValue)
586       {
587         case "maximized":
588           this._restoreFromMaximized();
589           break;
590
591         case "minimized":
592           this._restoreFromMinimized();
593           break;
594       }
595   }
596
597   return true;
598 }
599
600 qx.Proto._modifyShowCaption = function(propValue, propOldValue, propData)
601 {
602   if (propValue)
603   {
604     this._captionBar.addAt(this._captionTitle, this.getShowIcon() ? 1 : 0);
605   }
606   else
607   {
608     this._captionBar.remove(this._captionTitle);
609   }
610
611   return true;
612 }
613
614 qx.Proto._modifyShowIcon = function(propValue, propOldValue, propData)
615 {
616   if (propValue)
617   {
618     this._captionBar.addAtBegin(this._captionIcon);
619   }
620   else
621   {
622     this._captionBar.remove(this._captionIcon);
623   }
624
625   return true;
626 }
627
628 qx.Proto._modifyShowStatusbar = function(propValue, propOldValue, propData)
629 {
630   if (propValue)
631   {
632     this._layout.addAtEnd(this._statusBar);
633   }
634   else
635   {
636     this._layout.remove(this._statusBar);
637   }
638
639   return true;
640 }
641
642 qx.Proto._modifyShowClose = function(propValue, propOldValue, propData)
643 {
644   if (propValue)
645   {
646     this._captionBar.addAtEnd(this._closeButton);
647   }
648   else
649   {
650     this._captionBar.remove(this._closeButton);
651   }
652
653   return true;
654 }
655
656 qx.Proto._modifyShowMaximize = function(propValue, propOldValue, propData)
657 {
658   if (propValue)
659   {
660     var t = this.getMode() == "maximized" ? this._restoreButton : this._maximizeButton;
661
662     if (this.getShowMinimize())
663     {
664       this._captionBar.addAfter(t, this._minimizeButton);
665     }
666     else
667     {
668       this._captionBar.addAfter(t, this._captionFlex);
669     }
670   }
671   else
672   {
673     this._captionBar.remove(this._maximizeButton);
674     this._captionBar.remove(this._restoreButton);
675   }
676
677   return true;
678 }
679
680 qx.Proto._modifyShowMinimize = function(propValue, propOldValue, propData)
681 {
682   if (propValue)
683   {
684     this._captionBar.addAfter(this._minimizeButton, this._captionFlex);
685   }
686   else
687   {
688     this._captionBar.remove(this._minimizeButton);
689   }
690
691   return true;
692 }
693
694 qx.Proto._minimizeButtonManager = function()
695 {
696   this._minimizeButton.setEnabled(this.getAllowMinimize());
697
698   return true;
699 }
700
701 qx.Proto._closeButtonManager = function()
702 {
703   this._closeButton.setEnabled(this.getAllowClose());
704
705   return true;
706 }
707
708 qx.Proto._maximizeButtonManager = function()
709 {
710   var b = this.getAllowMaximize() && this.getResizeable() && this._computedMaxWidthTypeNull && this._computedMaxHeightTypeNull;
711
712   this._maximizeButton.setEnabled(b);
713   this._restoreButton.setEnabled(b);
714
715   return true;
716 }
717
718 qx.Proto._modifyStatus = function(propValue, propOldValue, propData)
719 {
720   this._statusText.setHtml(propValue);
721
722   return true;
723 }
724
725 qx.Proto._modifyMaxWidth = function(propValue, propOldValue, propData) {
726   return this._maximizeButtonManager();
727 }
728
729 qx.Proto._modifyMaxHeight = function(propValue, propOldValue, propData) {
730   return this._maximizeButtonManager();
731 }
732
733 qx.Proto._modifyResizeable = function(propValue, propOldValue, propData) {
734   return this._maximizeButtonManager();
735 }
736
737 qx.Proto._modifyCaption = function(propValue, propOldValue, propData)
738 {
739   this._captionTitle.setHtml(propValue);
740   return true;
741 }
742
743
744
745
746
747 /*
748 ---------------------------------------------------------------------------
749   STATE LAYOUT IMPLEMENTATION
750 ---------------------------------------------------------------------------
751 */
752
753 qx.Proto._minimize = function()
754 {
755   this.blur();
756   this.hide();
757 }
758
759 qx.Proto._restoreFromMaximized = function()
760 {
761   // restore previous dimension and location
762   this.setLeft(this._previousLeft ? this._previousLeft : null);
763   this.setWidth(this._previousWidth ? this._previousWidth : null);
764   this.setRight(this._previousRight ? this._previousRight : null);
765
766   this.setTop(this._previousTop ? this._previousTop : null);
767   this.setHeight(this._previousHeight ? this._previousHeight : null);
768   this.setBottom(this._previousBottom ? this._previousBottom : null);
769
770   // update state
771   this.removeState("maximized");
772
773   // toggle button
774   if (this.getShowMaximize())
775   {
776     var cb = this._captionBar;
777     var v = cb.indexOf(this._restoreButton);
778
779     cb.remove(this._restoreButton);
780     cb.addAt(this._maximizeButton, v);
781   }
782
783   // finally focus the window
784   this.focus();
785 }
786
787 qx.Proto._restoreFromMinimized = function()
788 {
789   if (this.hasState("maximized"))
790   {
791     this.setMode("maximized");
792   }
793
794   this.show();
795   this.focus();
796 }
797
798 qx.Proto._maximize = function()
799 {
800   if (this.hasState("maximized"))
801   {
802     return;
803   }
804
805   // store current dimension and location
806   this._previousLeft = this.getLeft();
807   this._previousWidth = this.getWidth();
808   this._previousRight = this.getRight();
809   this._previousTop = this.getTop();
810   this._previousHeight = this.getHeight();
811   this._previousBottom = this.getBottom();
812
813   // setup new dimension and location
814   this.setWidth(null);
815   this.setLeft(0);
816   this.setRight(0);
817   this.setHeight(null);
818   this.setTop(0);
819   this.setBottom(0);
820
821   // update state
822   this.addState("maximized");
823
824   // toggle button
825   if (this.getShowMaximize())
826   {
827     var cb = this._captionBar;
828     var v = cb.indexOf(this._maximizeButton);
829
830     cb.remove(this._maximizeButton);
831     cb.addAt(this._restoreButton, v);
832   }
833
834   // finally focus the window
835   this.focus();
836 }
837
838
839
840
841
842
843
844 /*
845 ---------------------------------------------------------------------------
846   EVENTS: WINDOW
847 ---------------------------------------------------------------------------
848 */
849
850 qx.Proto._onwindowmousedown = function(e)
851 {
852   this.focus();
853
854   if (this._resizeNorth || this._resizeSouth || this._resizeWest || this._resizeEast)
855   {
856     // enable capturing
857     this.setCapture(true);
858
859     // activate global cursor
860     this.getTopLevelWidget().setGlobalCursor(this.getCursor());
861
862     // caching element
863     var el = this.getElement();
864
865     // measuring and caching of values for resize session
866     var pa = this.getParent();
867     var pl = pa.getElement();
868
869     var l = qx.html.Location.getPageAreaLeft(pl);
870     var t = qx.html.Location.getPageAreaTop(pl);
871     var r = qx.html.Location.getPageAreaRight(pl);
872     var b = qx.html.Location.getPageAreaBottom(pl);
873
874     // handle frame and translucently
875     switch(this.getResizeMethod())
876     {
877       case "translucent":
878         this.setOpacity(0.5);
879         break;
880
881       case "frame":
882         var f = this._frame;
883
884         if (f.getParent() != this.getParent())
885         {
886           f.setParent(this.getParent());
887           qx.ui.core.Widget.flushGlobalQueues();
888         }
889
890         f._applyRuntimeLeft(qx.html.Location.getPageBoxLeft(el) - l);
891         f._applyRuntimeTop(qx.html.Location.getPageBoxTop(el) - t);
892
893         f._applyRuntimeWidth(qx.html.Dimension.getBoxWidth(el));
894         f._applyRuntimeHeight(qx.html.Dimension.getBoxHeight(el));
895
896         f.setZIndex(this.getZIndex() + 1);
897
898         break;
899     }
900
901     // create resize session
902     var s = this._resizeSession = {};
903
904     if (this._resizeWest)
905     {
906       s.boxWidth = qx.html.Dimension.getBoxWidth(el);
907       s.boxRight = qx.html.Location.getPageBoxRight(el);
908     }
909
910     if (this._resizeWest || this._resizeEast)
911     {
912       s.boxLeft = qx.html.Location.getPageBoxLeft(el);
913
914       s.parentAreaOffsetLeft = l;
915       s.parentAreaOffsetRight = r;
916
917       s.minWidth = this.getMinWidthValue();
918       s.maxWidth = this.getMaxWidthValue();
919     }
920
921     if (this._resizeNorth)
922     {
923       s.boxHeight = qx.html.Dimension.getBoxHeight(el);
924       s.boxBottom = qx.html.Location.getPageBoxBottom(el);
925     }
926
927     if (this._resizeNorth || this._resizeSouth)
928     {
929       s.boxTop = qx.html.Location.getPageBoxTop(el);
930
931       s.parentAreaOffsetTop = t;
932       s.parentAreaOffsetBottom = b;
933
934       s.minHeight = this.getMinHeightValue();
935       s.maxHeight = this.getMaxHeightValue();
936     }
937   }
938   else
939   {
940     // cleanup resize session
941     delete this._resizeSession;
942   }
943
944   // stop event
945   e.stopPropagation();
946 }
947
948 qx.Proto._onwindowmouseup = function(e)
949 {
950   var s = this._resizeSession;
951
952   if (s)
953   {
954     // disable capturing
955     this.setCapture(false);
956
957     // deactivate global cursor
958     this.getTopLevelWidget().setGlobalCursor(null);
959
960     // sync sizes to frame
961     switch(this.getResizeMethod())
962     {
963       case "frame":
964         var o = this._frame;
965         if (!(o && o.getParent())) {
966           break;
967         }
968         // no break here
969
970       case "lazyopaque":
971         if (s.lastLeft != null) {
972           this.setLeft(s.lastLeft);
973         }
974
975         if (s.lastTop != null) {
976           this.setTop(s.lastTop);
977         }
978
979         if (s.lastWidth != null) {
980           this.setWidth(s.lastWidth);
981         }
982
983         if (s.lastHeight != null) {
984           this.setHeight(s.lastHeight);
985         }
986
987         if (this.getResizeMethod() == "frame") {
988           this._frame.setParent(null);
989         }
990         break;
991
992       case "translucent":
993         this.setOpacity(null);
994         break;
995     }
996
997     // cleanup session
998     delete this._resizeNorth;
999     delete this._resizeEast;
1000     delete this._resizeSouth;
1001     delete this._resizeWest;
1002
1003     delete this._resizeSession;
1004   }
1005
1006   // stop event
1007   e.stopPropagation();
1008 }
1009
1010 qx.Proto._near = function(p, e) {
1011   return e > (p - 5) && e < (p + 5);
1012 }
1013
1014 qx.Proto._onwindowmousemove = function(e)
1015 {
1016   if (!this.getResizeable() || this.getMode() != null) {
1017     return;
1018   }
1019
1020   var s = this._resizeSession;
1021
1022   if (s)
1023   {
1024     if (this._resizeWest)
1025     {
1026       s.lastWidth = qx.lang.Number.limit(s.boxWidth + s.boxLeft - Math.max(e.getPageX(), s.parentAreaOffsetLeft), s.minWidth, s.maxWidth);
1027       s.lastLeft = s.boxRight - s.lastWidth - s.parentAreaOffsetLeft;
1028     }
1029     else if (this._resizeEast)
1030     {
1031       s.lastWidth = qx.lang.Number.limit(Math.min(e.getPageX(), s.parentAreaOffsetRight) - s.boxLeft, s.minWidth, s.maxWidth);
1032     }
1033
1034     if (this._resizeNorth)
1035     {
1036       s.lastHeight = qx.lang.Number.limit(s.boxHeight + s.boxTop - Math.max(e.getPageY(), s.parentAreaOffsetTop), s.minHeight, s.maxHeight);
1037       s.lastTop = s.boxBottom - s.lastHeight - s.parentAreaOffsetTop;
1038     }
1039     else if (this._resizeSouth)
1040     {
1041       s.lastHeight = qx.lang.Number.limit(Math.min(e.getPageY(), s.parentAreaOffsetBottom) - s.boxTop, s.minHeight, s.maxHeight);
1042     }
1043
1044     switch(this.getResizeMethod())
1045     {
1046       case "opaque":
1047       case "translucent":
1048         if (this._resizeWest || this._resizeEast)
1049         {
1050           this.setWidth(s.lastWidth);
1051
1052           if (this._resizeWest) {
1053             this.setLeft(s.lastLeft);
1054           }
1055         }
1056
1057         if (this._resizeNorth || this._resizeSouth)
1058         {
1059           this.setHeight(s.lastHeight);
1060
1061           if (this._resizeNorth) {
1062             this.setTop(s.lastTop);
1063           }
1064         }
1065
1066         break;
1067
1068       default:
1069         var o = this.getResizeMethod() == "frame" ? this._frame : this;
1070
1071         if (this._resizeWest || this._resizeEast)
1072         {
1073           o._applyRuntimeWidth(s.lastWidth);
1074
1075           if (this._resizeWest) {
1076             o._applyRuntimeLeft(s.lastLeft);
1077           }
1078         }
1079
1080         if (this._resizeNorth || this._resizeSouth)
1081         {
1082           o._applyRuntimeHeight(s.lastHeight);
1083
1084           if (this._resizeNorth) {
1085             o._applyRuntimeTop(s.lastTop);
1086           }
1087         }
1088     }
1089   }
1090   else
1091   {
1092     var resizeMode = "";
1093     var el = this.getElement();
1094
1095     this._resizeNorth = this._resizeSouth = this._resizeWest = this._resizeEast = false;
1096
1097     if (this._near(qx.html.Location.getPageBoxTop(el), e.getPageY()))
1098     {
1099       resizeMode = "n";
1100       this._resizeNorth = true;
1101     }
1102     else if (this._near(qx.html.Location.getPageBoxBottom(el), e.getPageY()))
1103     {
1104       resizeMode = "s";
1105       this._resizeSouth = true;
1106     }
1107
1108     if (this._near(qx.html.Location.getPageBoxLeft(el), e.getPageX()))
1109     {
1110       resizeMode += "w";
1111       this._resizeWest = true;
1112     }
1113     else if (this._near(qx.html.Location.getPageBoxRight(el), e.getPageX()))
1114     {
1115       resizeMode += "e";
1116       this._resizeEast = true;
1117     }
1118
1119     if (this._resizeNorth || this._resizeSouth || this._resizeWest || this._resizeEast)
1120     {
1121       this.setCursor(resizeMode + "-resize");
1122     }
1123     else
1124     {
1125       this.setCursor(null);
1126     }
1127   }
1128
1129   // stop event
1130   e.stopPropagation();
1131 }
1132
1133 qx.Proto._onwindowclick = function(e)
1134 {
1135   // stop event
1136   e.stopPropagation();
1137 };
1138
1139
1140
1141
1142
1143 /*
1144 ---------------------------------------------------------------------------
1145   EVENTS: BUTTONS
1146 ---------------------------------------------------------------------------
1147 */
1148
1149 qx.Proto._onbuttonmousedown = function(e) {
1150   e.stopPropagation();
1151 }
1152
1153 qx.Proto._onminimizebuttonclick = function(e)
1154 {
1155   this.minimize();
1156
1157   // we need to be sure that the button gets the right states after clicking
1158   // because the button will move and does not get the mouseup event anymore
1159   this._minimizeButton.removeState("pressed");
1160   this._minimizeButton.removeState("abandoned");
1161   this._minimizeButton.removeState("over");
1162
1163   e.stopPropagation();
1164 }
1165
1166 qx.Proto._onrestorebuttonclick = function(e)
1167 {
1168   this.restore();
1169
1170   // we need to be sure that the button gets the right states after clicking
1171   // because the button will move and does not get the mouseup event anymore
1172   this._restoreButton.removeState("pressed");
1173   this._restoreButton.removeState("abandoned");
1174   this._restoreButton.removeState("over");
1175
1176   e.stopPropagation();
1177 }
1178
1179 qx.Proto._onmaximizebuttonclick = function(e)
1180 {
1181   this.maximize();
1182
1183   // we need to be sure that the button gets the right states after clicking
1184   // because the button will move and does not get the mouseup event anymore
1185   this._maximizeButton.removeState("pressed");
1186   this._maximizeButton.removeState("abandoned");
1187   this._maximizeButton.removeState("over");
1188
1189   e.stopPropagation();
1190 }
1191
1192 qx.Proto._onclosebuttonclick = function(e)
1193 {
1194   this.close();
1195
1196   // we need to be sure that the button gets the right states after clicking
1197   // because the button will move and does not get the mouseup event anymore
1198   this._closeButton.removeState("pressed");
1199   this._closeButton.removeState("abandoned");
1200   this._closeButton.removeState("over");
1201
1202   e.stopPropagation();
1203 }
1204
1205
1206
1207
1208
1209
1210
1211 /*
1212 ---------------------------------------------------------------------------
1213   EVENTS: CAPTIONBAR
1214 ---------------------------------------------------------------------------
1215 */
1216
1217 qx.Proto._oncaptionmousedown = function(e)
1218 {
1219   if (!e.isLeftButtonPressed() || !this.getMoveable() || this.getMode() != null) {
1220     return;
1221   }
1222
1223   // enable capturing
1224   this._captionBar.setCapture(true);
1225
1226   // element cache
1227   var el = this.getElement();
1228
1229   // measuring and caching of values for drag session
1230   var pa = this.getParent();
1231   var pl = pa.getElement();
1232
1233   var l = qx.html.Location.getPageAreaLeft(pl);
1234   var t = qx.html.Location.getPageAreaTop(pl);
1235   var r = qx.html.Location.getPageAreaRight(pl);
1236   var b = qx.html.Location.getPageAreaBottom(pl);
1237
1238   this._dragSession =
1239   {
1240     offsetX : e.getPageX() - qx.html.Location.getPageBoxLeft(el) + l,
1241     offsetY : e.getPageY() - qx.html.Location.getPageBoxTop(el) + t,
1242
1243     parentAvailableAreaLeft : l + 5,
1244     parentAvailableAreaTop : t + 5,
1245     parentAvailableAreaRight : r - 5,
1246     parentAvailableAreaBottom : b - 5
1247   }
1248
1249   // handle frame and translucently
1250   switch(this.getMoveMethod())
1251   {
1252     case "translucent":
1253       this.setOpacity(0.5);
1254       break;
1255
1256     case "frame":
1257       var f = this._frame;
1258
1259       if (f.getParent() != this.getParent())
1260       {
1261         f.setParent(this.getParent());
1262         qx.ui.core.Widget.flushGlobalQueues();
1263       }
1264
1265       f._applyRuntimeLeft(qx.html.Location.getPageBoxLeft(el) - l);
1266       f._applyRuntimeTop(qx.html.Location.getPageBoxTop(el) - t);
1267
1268       f._applyRuntimeWidth(qx.html.Dimension.getBoxWidth(el));
1269       f._applyRuntimeHeight(qx.html.Dimension.getBoxHeight(el));
1270
1271       f.setZIndex(this.getZIndex() + 1);
1272
1273       break;
1274   }
1275 }
1276
1277 qx.Proto._oncaptionmouseup = function(e)
1278 {
1279   var s = this._dragSession;
1280
1281   if (!s) {
1282     return;
1283   }
1284
1285   // disable capturing
1286   this._captionBar.setCapture(false);
1287
1288   // move window to last position
1289   if (s.lastX != null) {
1290     this.setLeft(s.lastX);
1291   }
1292
1293   if (s.lastY != null) {
1294     this.setTop(s.lastY);
1295   }
1296
1297   // handle frame and translucently
1298   switch(this.getMoveMethod())
1299   {
1300     case "translucent":
1301       this.setOpacity(null);
1302       break;
1303
1304     case "frame":
1305       this._frame.setParent(null);
1306       break;
1307   }
1308
1309   // cleanup session
1310   delete this._dragSession;
1311 }
1312
1313 qx.Proto._oncaptionmousemove = function(e)
1314 {
1315   var s = this._dragSession;
1316
1317   // pre check for active session and capturing
1318   if (!s || !this._captionBar.getCapture()) {
1319     return;
1320   }
1321
1322   // pre check if we go out of the available area
1323   if (!qx.lang.Number.isBetweenRange(e.getPageX(), s.parentAvailableAreaLeft, s.parentAvailableAreaRight) || !qx.lang.Number.isBetweenRange(e.getPageY(), s.parentAvailableAreaTop, s.parentAvailableAreaBottom)) {
1324     return;
1325   }
1326
1327   // use the fast and direct dom methods
1328   var o = this.getMoveMethod() == "frame" ? this._frame : this;
1329
1330   o._applyRuntimeLeft(s.lastX = e.getPageX() - s.offsetX);
1331   o._applyRuntimeTop(s.lastY = e.getPageY() - s.offsetY);
1332 }
1333
1334 qx.Proto._oncaptiondblblick = function()
1335 {
1336   if (!this._maximizeButton.getEnabled()) {
1337     return;
1338   }
1339
1340   return this.getMode() == "maximized" ? this.restore() : this.maximize();
1341 }
1342
1343
1344
1345
1346
1347
1348
1349
1350 /*
1351 ---------------------------------------------------------------------------
1352   DISPOSER
1353 ---------------------------------------------------------------------------
1354 */
1355
1356 qx.Proto.dispose = function()
1357 {
1358   if (this.getDisposed()) {
1359     return true;
1360   }
1361
1362   if (this._layout)
1363   {
1364     this._layout.dispose();
1365     this._layout = null;
1366   }
1367
1368   if (this._frame)
1369   {
1370     this._frame.dispose();
1371     this._frame = null;
1372   }
1373
1374   if (this._captionBar)
1375   {
1376     this._captionBar.dispose();
1377     this._captionBar = null;
1378   }
1379
1380   if (this._captionIcon)
1381   {
1382     this._captionIcon.dispose();
1383     this._captionIcon = null;
1384   }
1385
1386   if (this._captionTitle)
1387   {
1388     this._captionTitle.dispose();
1389     this._captionTitle = null;
1390   }
1391
1392   if (this._captionFlex)
1393   {
1394     this._captionFlex.dispose();
1395     this._captionFlex = null;
1396   }
1397
1398   if (this._closeButton)
1399   {
1400     this._closeButton.dispose();
1401     this._closeButton = null;
1402   }
1403
1404   if (this._minimizeButton)
1405   {
1406     this._minimizeButton.dispose();
1407     this._minimizeButton = null;
1408   }
1409
1410   if (this._maximizeButton)
1411   {
1412     this._maximizeButton.dispose();
1413     this._maximizeButton = null;
1414   }
1415
1416   if (this._restoreButton)
1417   {
1418     this._restoreButton.dispose();
1419     this._restoreButton = null;
1420   }
1421
1422   if (this._pane)
1423   {
1424     this._pane.dispose();
1425     this._pane = null;
1426   }
1427
1428   if (this._statusBar)
1429   {
1430     this._statusBar.dispose();
1431     this._statusBar = null;
1432   }
1433
1434   if (this._statusText)
1435   {
1436     this._statusText.dispose();
1437     this._statusText = null;
1438   }
1439
1440   return qx.ui.popup.Popup.prototype.dispose.call(this);
1441 }