/* ************************************************************************ qooxdoo - the new era of web development http://qooxdoo.org Copyright: 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org License: LGPL 2.1: http://www.gnu.org/licenses/lgpl.html Authors: * Sebastian Werner (wpbasti) * Andreas Ecker (ecker) ************************************************************************ */ /* ************************************************************************ #module(ui_core) #require(qx.renderer.color.ColorCache) #require(qx.renderer.border.BorderCache) #require(qx.manager.object.AppearanceManager) #after(qx.component.init.InterfaceInitComponent) #optional(qx.ui.core.Parent) #optional(qx.ui.form.Button) #optional(qx.client.Timer) #optional(qx.client.Command) #optional(qx.ui.popup.ToolTip) #optional(qx.ui.menu.Menu) #optional(qx.ui.basic.Inline) ************************************************************************ */ /** * This is the main widget, all visible objects in the application extend this. * * @event beforeAppear {qx.event.type.Event} * @event appear {qx.event.type.Event} * @event beforeDisappear {qx.event.type.Event} * @event disappear {qx.event.type.Event} * @event beforeInsertDom {qx.event.type.Event} * @event insertDom {qx.event.type.Event} * @event beforeRemoveDom {qx.event.type.Event} * @event removeDom {qx.event.type.Event} * @event create {qx.event.type.Event} * @event execute {qx.event.type.Event} * @event FADE_FINISHED {qx.event.type.DataEvent} * @event mouseover {qx.event.type.MouseEvent} (Fired by {@link qx.event.handler.EventHandler}) * @event mousemove {qx.event.type.MouseEvent} (Fired by {@link qx.event.handler.EventHandler}) * @event mouseout {qx.event.type.MouseEvent} (Fired by {@link qx.event.handler.EventHandler}) * @event mousedown {qx.event.type.MouseEvent} (Fired by {@link qx.event.handler.EventHandler}) * @event mouseup {qx.event.type.MouseEvent} (Fired by {@link qx.event.handler.EventHandler}) * @event mousewheel {qx.event.type.MouseEvent} (Fired by {@link qx.event.handler.EventHandler}) * @event click {qx.event.type.MouseEvent} (Fired by {@link qx.event.handler.EventHandler}) * @event dblclick {qx.event.type.MouseEvent} (Fired by {@link qx.event.handler.EventHandler}) * @event contextmenu {qx.event.type.MouseEvent} (Fired by {@link qx.event.handler.EventHandler}) * @event keydown {qx.event.type.KeyEvent} (Fired by {@link qx.event.handler.EventHandler}) * @event keypress {qx.event.type.KeyEvent} (Fired by {@link qx.event.handler.EventHandler}) * @event keyinput {qx.event.type.KeyEvent} (Fired by {@link qx.event.handler.EventHandler}) * @event keyup {qx.event.type.KeyEvent} (Fired by {@link qx.event.handler.EventHandler}) * @event focusout {qx.event.type.FocusEvent} (Fired by {@link qx.ui.core.Parent}) * @event focusin {qx.event.type.FocusEvent} (Fired by {@link qx.ui.core.Parent}) * @event blur {qx.event.type.FocusEvent} (Fired by {@link qx.ui.core.Parent}) * @event focus {qx.event.type.FocusEvent} (Fired by {@link qx.ui.core.Parent}) */ qx.OO.defineClass("qx.ui.core.Widget", qx.core.Target, function() { if (this.classname == qx.ui.core.Widget.ABSTRACT_CLASS) { throw new Error("Please omit the usage of qx.ui.core.Widget directly. Choose between qx.ui.core.Parent and qx.ui.basic.Terminator instead!"); } qx.core.Target.call(this, true); // ************************************************************************ // HTML MAPPING DATA STRUCTURES // ************************************************************************ // Allows the user to setup styles and attributes without a // need to have the target element created already. /* this._htmlProperties = { className : this.classname } this._htmlAttributes = { qxhashcode : this._hashCode } */ this._styleProperties = { position : "absolute" } // ************************************************************************ // LAYOUT CHANGES // ************************************************************************ this._layoutChanges = {}; // ************************************************************************ // APPEARANCE // ************************************************************************ this._states = {}; this._applyInitialAppearance(); }); qx.Class.ABSTRACT_CLASS = "qx.ui.core.Widget"; // Will be calculated later (TODO: Move to qx.Dom?) qx.Class.SCROLLBAR_SIZE = 16; /* --------------------------------------------------------------------------- DEFAULT SETTINGS --------------------------------------------------------------------------- */ qx.Settings.setDefault("enableQueueDebug", false); /* --------------------------------------------------------------------------- BASIC PROPERTIES --------------------------------------------------------------------------- */ /*! The parent widget (the real object, no ID or something) */ qx.OO.addProperty({ name : "parent", type : "object", instance : "qx.ui.core.Parent", defaultValue : null }); /*! The element node (if the widget is created, otherwise null) */ qx.OO.addProperty({ name : "element" }); /*! Simple and fast switch of the visibility of a widget. */ qx.OO.addProperty({ name : "visibility", type : "boolean", defaultValue : true }); /*! If the widget should be displayed. Use this property instead of visibility if the change in visibility should have effects on the parent widget. */ qx.OO.addProperty({ name : "display", type : "boolean", defaultValue : true }); /*! If you switch this to true, the widget doesn't handle events directly. It will redirect them to the parent widget. */ qx.OO.addProperty({ name : "anonymous", type : "boolean", defaultValue : false, getAlias : "isAnonymous" }); /*! The tagname of the element which should automatically be created */ qx.OO.addProperty({ name : "tagName", type : "string", defaultValue : "div" }); /*! This is used by many layout managers to control the individual horizontal alignment of this widget inside this parent. This should be used with caution since in some cases this might give unrespected results. */ qx.OO.addProperty({ name : "horizontalAlign", type : "string" }); /*! This is used by many layout managers to control the individual vertical alignment of this widget inside this parent. This should be used with caution since in some cases this might give unrespected results. */ qx.OO.addProperty({ name : "verticalAlign", type : "string" }); /*! Should this widget be stretched on the x-axis if the layout handler will do this? Used by some layout handlers (qx.ui.layout.BoxLayout, ...). */ qx.OO.addProperty({ name : "allowStretchX", type : "boolean", defaultValue : true }); /*! Should this widget be stretched on the y-axis if the layout handler will do this? Used by some layout handlers (qx.ui.layout.BoxLayout, ...). */ qx.OO.addProperty({ name : "allowStretchY", type : "boolean", defaultValue : true }); /* --------------------------------------------------------------------------- STYLE PROPERTIES --------------------------------------------------------------------------- */ /*! Mapping to native style property z-index. This should be used with caution since in some cases this might give unrespected results. */ qx.OO.addProperty({ name : "zIndex", type : "number" }); /*! The backgroundColor style property of the rendered widget. As input are allowed any instance of qx.renderer.color.Color or a string which defines the color itself. */ qx.OO.addProperty({ name : "backgroundColor", type : "object", instance : "qx.renderer.color.Color", convert : qx.renderer.color.ColorCache, allowMultipleArguments : true }); /*! The color style property of the rendered widget. As input are allowed any instance of qx.renderer.color.Color or a string which defines the color itself. */ qx.OO.addProperty({ name : "color", type : "object", instance : "qx.renderer.color.Color", convert : qx.renderer.color.ColorCache, allowMultipleArguments : true }); /*! The border property describes how to paint the border on the widget. This should be used with caution since in some cases (mostly complex widgets) this might give unrespected results. */ qx.OO.addProperty({ name : "border", type : "object", instance : "qx.renderer.border.Border", convert : qx.renderer.border.BorderCache, allowMultipleArguments : true }); /*! Mapping to native style property opacity. The uniform opacity setting to be applied across an entire object. Behaves like the new CSS-3 Property. Any values outside the range 0.0 (fully transparent) to 1.0 (fully opaque) will be clamped to this range. */ qx.OO.addProperty({ name : "opacity", type : "number" }); /*! Mapping to native style property cursor. The name of the cursor to show when the mouse pointer is over the widget. This is any valid CSS2 cursor name defined by W3C. The following values are possible: */ qx.OO.addProperty({ name : "cursor", type : "string" }); /*! Mapping to native style property background-image. The URI of the image file to use as background image. */ qx.OO.addProperty({ name : "backgroundImage", type : "string" }); /** * Describes how to handle content that is too large to fit inside the widget. * * Overflow modes: * * hidden: The content is clipped * * auto: Scroll bars are shown as needed * * scroll: Scroll bars are always shown. Even if there is enough room for the content inside the widget. * * scrollX: Scroll bars for the X-Axis are always shown. Even if there is enough room for the content inside the widget. * * scrollY: Scroll bars for the Y-Axis are always shown. Even if there is enough room for the content inside the widget. */ qx.OO.addProperty({ name : "overflow", type : "string", addToQueue : true }); /*! Clipping of the widget (left) */ qx.OO.addProperty({ name : "clipLeft", type : "number", impl : "clip" }); /*! Clipping of the widget (top) */ qx.OO.addProperty({ name : "clipTop", type : "number", impl : "clip" }); /*! Clipping of the widget (width) */ qx.OO.addProperty({ name : "clipWidth", type : "number", impl : "clip" }); /*! Clipping of the widget (height) */ qx.OO.addProperty({ name : "clipHeight", type : "number", impl : "clip" }); /* --------------------------------------------------------------------------- MANAGMENT PROPERTIES --------------------------------------------------------------------------- */ /*! Set this to a positive value makes the widget able to get the focus. It even is reachable through the usage of the tab-key. Widgets with the same tabIndex are handled through there position in the document. */ qx.OO.addProperty({ name : "tabIndex", type : "number", defaultValue : -1 }); /*! If the focus outline should be hidden. */ qx.OO.addProperty({ name : "hideFocus", type : "boolean", defaultValue : false }); /*! Use DOM focussing (focus() and blur() methods of DOM nodes) */ qx.OO.addProperty({ name : "enableElementFocus", type : "boolean", defaultValue : true }); /*! Handle focus state of this widget. someWidget.setFocused(true) set the current focus to this widget. someWidget.setFocused(false) remove the current focus and leave it blank. Normally you didn't need to set this directly. */ qx.OO.addProperty({ name : "focused", type : "boolean", defaultValue : false }); /*! Toggle the possibility to select the element of this widget. */ qx.OO.addProperty({ name : "selectable", type : "boolean", defaultValue : true, getAlias : "isSelectable" }); /*! Contains the tooltip object connected to the widget. */ qx.OO.addProperty({ name : "toolTip", type : "object", instance : "qx.ui.popup.ToolTip" }); /*! Contains the context menu object connected to the widget. (Need real implementation) */ qx.OO.addProperty({ name : "contextMenu", type : "object", instance : "qx.ui.menu.Menu" }); /*! Capture all events and map them to this widget */ qx.OO.addProperty({ name : "capture", type : "boolean", defaultValue : false }); /*! Contains the support drop types for drag and drop support */ qx.OO.addProperty({ name : "dropDataTypes" }); /*! A command called if the widget should be excecuted (a placeholder for buttons, ...) */ qx.OO.addProperty({ name : "command", type : "object", instance : "qx.client.Command" }); /*! Appearance of the widget */ qx.OO.addProperty({ name : "appearance", type : "string" }); /* --------------------------------------------------------------------------- MARGIN/PADDING PROPERTIES --------------------------------------------------------------------------- */ /*! Margin of the widget (top) */ qx.OO.addProperty({ name : "marginTop", type : "number", addToQueue : true, impl : "marginY" }); /*! Margin of the widget (right) */ qx.OO.addProperty({ name : "marginRight", type : "number", addToQueue : true, impl : "marginX" }); /*! Margin of the widget (bottom) */ qx.OO.addProperty({ name : "marginBottom", type : "number", addToQueue : true, impl : "marginY" }); /*! Margin of the widget (left) */ qx.OO.addProperty({ name : "marginLeft", type : "number", addToQueue : true, impl : "marginX" }); /*! Padding of the widget (top) */ qx.OO.addProperty({ name : "paddingTop", type : "number", addToQueue : true, impl : "paddingY" }); /*! Padding of the widget (right) */ qx.OO.addProperty({ name : "paddingRight", type : "number", addToQueue : true, impl : "paddingX" }); /*! Padding of the widget (bottom) */ qx.OO.addProperty({ name : "paddingBottom", type : "number", addToQueue : true, impl : "paddingY" }); /*! Padding of the widget (left) */ qx.OO.addProperty({ name : "paddingLeft", type : "number", addToQueue : true, impl : "paddingX" }); /* --------------------------------------------------------------------------- HORIZONAL DIMENSION PROPERTIES --------------------------------------------------------------------------- */ /*! The distance from the outer left border to the parent left area edge. You could only set two of the three horizonal dimension properties (boxLeft, boxRight, boxWidth) at the same time. This will be omitted during the setup of the new third value. To reset a value you didn't want anymore, set it to null. */ qx.OO.addProperty({ name : "left", addToQueue : true, unitDetection : "pixelPercent" }); /*! The distance from the outer right border to the parent right area edge. You could only set two of the three horizonal dimension properties (boxLeft, boxRight, boxWidth) at the same time. This will be omitted during the setup of the new third value. To reset a value you didn't want anymore, set it to null. */ qx.OO.addProperty({ name : "right", addToQueue : true, unitDetection : "pixelPercent" }); /*! The width of the box (including padding and border). You could only set two of the three horizonal dimension properties (boxLeft, boxRight, boxWidth) at the same time. This will be omitted during the setup of the new third value. To reset a value you didn't want anymore, set it to null. */ qx.OO.addProperty({ name : "width", addToQueue : true, unitDetection : "pixelPercentAutoFlex" }); /*! The minimum width of the box (including padding and border). Set this to omit the shrinking of the box width under this value. */ qx.OO.addProperty({ name : "minWidth", addToQueue : true, unitDetection : "pixelPercentAuto" }); /*! The maximum width of the box (including padding and border). Set this to omit the expanding of the box width above this value. */ qx.OO.addProperty({ name : "maxWidth", addToQueue : true, unitDetection : "pixelPercentAuto" }); /* --------------------------------------------------------------------------- VERTICAL DIMENSION PROPERTIES --------------------------------------------------------------------------- */ /*! The distance from the outer top border to the parent top area edge. You could only set two of the three vertical dimension properties (boxTop, boxBottom, boxHeight) at the same time. This will be omitted during the setup of the new third value. To reset a value you didn't want anymore, set it to null. */ qx.OO.addProperty({ name : "top", addToQueue : true, unitDetection : "pixelPercent" }); /*! The distance from the outer bottom border to the parent bottom area edge. You could only set two of the three vertical dimension properties (boxTop, boxBottom, boxHeight) at the same time. This will be omitted during the setup of the new third value. To reset a value you didn't want anymore, set it to null. */ qx.OO.addProperty({ name : "bottom", addToQueue : true, unitDetection : "pixelPercent" }); /*! The height of the box (including padding and border). You could only set two of the three vertical dimension properties (boxTop, boxBottom, boxHeight) at the same time. This will be omitted during the setup of the new third value. To reset a value you didn't want anymore, set it to null. */ qx.OO.addProperty({ name : "height", addToQueue : true, unitDetection : "pixelPercentAutoFlex" }); /*! The minimum height of the box (including padding and border). Set this to omit the shrinking of the box height under this value. */ qx.OO.addProperty({ name : "minHeight", addToQueue : true, unitDetection : "pixelPercentAuto" }); /*! The maximum height of the box (including padding and border). Set this to omit the expanding of the box height above this value. */ qx.OO.addProperty({ name : "maxHeight", addToQueue : true, unitDetection : "pixelPercentAuto" }); /* --------------------------------------------------------------------------- PROPERTY GROUPS --------------------------------------------------------------------------- */ qx.OO.addPropertyGroup({ name : "location", members : [ "left", "top" ]}); qx.OO.addPropertyGroup({ name : "dimension", members : [ "width", "height" ]}); qx.OO.addPropertyGroup({ name : "space", members : [ "left", "width", "top", "height" ]}); qx.OO.addPropertyGroup({ name : "edge", members : [ "top", "right", "bottom", "left" ], mode : "shorthand" }); qx.OO.addPropertyGroup({ name : "padding", members : [ "paddingTop", "paddingRight", "paddingBottom", "paddingLeft" ], mode: "shorthand" }); qx.OO.addPropertyGroup({ name : "margin", members : [ "marginTop", "marginRight", "marginBottom", "marginLeft" ], mode: "shorthand" }); qx.OO.addPropertyGroup({ name : "heights", members : [ "minHeight", "height", "maxHeight" ]}); qx.OO.addPropertyGroup({ name : "widths", members : [ "minWidth", "width", "maxWidth" ]}); qx.OO.addPropertyGroup({ name : "align", members : [ "horizontalAlign", "verticalAlign" ]}); qx.OO.addPropertyGroup({ name : "stretch", members : [ "stretchX", "stretchY" ]}); qx.OO.addPropertyGroup({ name : "clipLocation", members : [ "clipLeft", "clipTop" ]}); qx.OO.addPropertyGroup({ name : "clipDimension", members : [ "clipWidth", "clipHeight" ]}); qx.OO.addPropertyGroup({ name : "clip", members : [ "clipLeft", "clipTop", "clipWidth", "clipHeight" ]}); /* ************************************************************************ Class data, properties and methods ************************************************************************ */ /* --------------------------------------------------------------------------- ALL QUEUES --------------------------------------------------------------------------- */ if (qx.Settings.getValueOfClass("qx.ui.core.Widget", "enableQueueDebug")) { qx.ui.core.Widget.flushGlobalQueues = function() { if (qx.ui.core.Widget._inFlushGlobalQueues || !qx.core.Init.getInstance().getComponent().isUiReady()) { return; } if (!(qx.ui.core.Widget._globalWidgetQueue.length > 0 || qx.ui.core.Widget._globalElementQueue.length > 0 || qx.ui.core.Widget._globalStateQueue.length > 0 || qx.ui.core.Widget._globalJobQueue.length > 0 || qx.ui.core.Widget._globalLayoutQueue.length > 0 || qx.ui.core.Widget._fastGlobalDisplayQueue.length > 0 || !qx.lang.Object.isEmpty(qx.ui.core.Widget._lazyGlobalDisplayQueue))) { return; } var globalWidgetQueueLength = qx.ui.core.Widget._globalWidgetQueue.length; var globalElementQueueLength = qx.ui.core.Widget._globalElementQueue.length; var globalStateQueueLength = qx.ui.core.Widget._globalStateQueue.length; var globalJobQueueLength = qx.ui.core.Widget._globalJobQueue.length; var globalLayoutQueueLength = qx.ui.core.Widget._globalLayoutQueue.length; var fastGlobalDisplayQueueLength = qx.ui.core.Widget._fastGlobalDisplayQueue.length; var lazyGlobalDisplayQueueLength = qx.ui.core.Widget._lazyGlobalDisplayQueue ? qx.ui.core.Widget._lazyGlobalDisplayQueue.length : 0; // Also used for inline event handling to seperate 'real' events qx.ui.core.Widget._inFlushGlobalQueues = true; var vStart; vStart = (new Date).valueOf(); qx.ui.core.Widget.flushGlobalWidgetQueue(); var vWidgetDuration = (new Date).valueOf() - vStart; vStart = (new Date).valueOf(); qx.ui.core.Widget.flushGlobalStateQueue(); var vStateDuration = (new Date).valueOf() - vStart; vStart = (new Date).valueOf(); qx.ui.core.Widget.flushGlobalElementQueue(); var vElementDuration = (new Date).valueOf() - vStart; vStart = (new Date).valueOf(); qx.ui.core.Widget.flushGlobalJobQueue(); var vJobDuration = (new Date).valueOf() - vStart; vStart = (new Date).valueOf(); qx.ui.core.Widget.flushGlobalLayoutQueue(); var vLayoutDuration = (new Date).valueOf() - vStart; vStart = (new Date).valueOf(); qx.ui.core.Widget.flushGlobalDisplayQueue(); var vDisplayDuration = (new Date).valueOf() - vStart; var vSum = vWidgetDuration + vStateDuration + vElementDuration + vJobDuration + vLayoutDuration + vDisplayDuration; if (vSum > 0) { var logger = qx.dev.log.Logger.getClassLogger(qx.ui.core.Widget); logger.debug("Flush Global Queues"); logger.debug("Widgets: " + vWidgetDuration + "ms (" + globalWidgetQueueLength + ")"); logger.debug("State: " + vStateDuration + "ms (" + globalStateQueueLength + ")"); logger.debug("Element: " + vElementDuration + "ms (" + globalElementQueueLength + ")"); logger.debug("Job: " + vJobDuration + "ms (" + globalJobQueueLength + ")"); logger.debug("Layout: " + vLayoutDuration + "ms (" + globalLayoutQueueLength + ")"); logger.debug("Display: " + vDisplayDuration + "ms (fast:" + fastGlobalDisplayQueueLength + ",lazy:" + lazyGlobalDisplayQueueLength + ")"); window.status = "Flush: Widget:" + vWidgetDuration + " State:" + vStateDuration + " Element:" + vElementDuration + " Job:" + vJobDuration + " Layout:" + vLayoutDuration + " Display:" + vDisplayDuration; } delete qx.ui.core.Widget._inFlushGlobalQueues; } } else { qx.ui.core.Widget.flushGlobalQueues = function() { if (qx.ui.core.Widget._inFlushGlobalQueues || !qx.core.Init.getInstance().getComponent().isUiReady()) { return; } // Also used for inline event handling to seperate 'real' events qx.ui.core.Widget._inFlushGlobalQueues = true; qx.ui.core.Widget.flushGlobalWidgetQueue(); qx.ui.core.Widget.flushGlobalStateQueue(); qx.ui.core.Widget.flushGlobalElementQueue(); qx.ui.core.Widget.flushGlobalJobQueue(); qx.ui.core.Widget.flushGlobalLayoutQueue(); qx.ui.core.Widget.flushGlobalDisplayQueue(); delete qx.ui.core.Widget._inFlushGlobalQueues; } } /* --------------------------------------------------------------------------- WIDGET QUEUE Allows widgets to register to the widget queue to do multiple things before the other queues will be flushed --------------------------------------------------------------------------- */ qx.ui.core.Widget._globalWidgetQueue = []; qx.ui.core.Widget.addToGlobalWidgetQueue = function(vWidget) { if (!vWidget._isInGlobalWidgetQueue && vWidget._isDisplayable) { qx.ui.core.Widget._globalWidgetQueue.push(vWidget); vWidget._isInGlobalWidgetQueue = true; } } qx.ui.core.Widget.removeFromGlobalWidgetQueue = function(vWidget) { if (vWidget._isInGlobalWidgetQueue) { qx.lang.Array.remove(qx.ui.core.Widget._globalWidgetQueue, vWidget); delete vWidget._isInGlobalWidgetQueue; } } qx.ui.core.Widget.flushGlobalWidgetQueue = function() { var vQueue=qx.ui.core.Widget._globalWidgetQueue, vLength, vWidget; while ((vLength=vQueue.length) > 0) { for (var i=0; i 0) { for (var i=0; i 0) { for (var i=0; i 0) { for (var i=0; i 0) { for (var i=0; i= 3) { // creating new document fragment vFragment = document.createDocumentFragment(); // appending all widget elements to fragment for (var i=0, l=vLazyQueue.length; i 0 && el.offsetHeight > 0); } /*! A single setup to the current preferred pixel values of the widget */ qx.Proto.pack = function() { this.setWidth(this.getPreferredBoxWidth()); this.setHeight(this.getPreferredBoxHeight()); } /*! A bounded setup to the preferred width/height of the widget. Keeps in sync if the content or requirements of the widget changes */ qx.Proto.auto = function() { this.setWidth("auto"); this.setHeight("auto"); } /* --------------------------------------------------------------------------- CHILDREN HANDLING: ALL --------------------------------------------------------------------------- */ /*! Get an array of the current children */ qx.Proto.getChildren = qx.util.Return.returnNull; /*! Get the number of children */ qx.Proto.getChildrenLength = qx.util.Return.returnZero; /*! Get if the widget has any children */ qx.Proto.hasChildren = qx.util.Return.returnFalse; /*! Get if the widget has no children */ qx.Proto.isEmpty = qx.util.Return.returnTrue; /*! Return the position of the child inside */ qx.Proto.indexOf = qx.util.Return.returnNegativeIndex; /*! Test if this widget contains the given widget */ qx.Proto.contains = qx.util.Return.returnFalse; /* --------------------------------------------------------------------------- CHILDREN HANDLING: VISIBLE ONES --------------------------------------------------------------------------- */ /*! Get an array of the current visible children */ qx.Proto.getVisibleChildren = qx.util.Return.returnNull; /*! Get the number of children */ qx.Proto.getVisibleChildrenLength = qx.util.Return.returnZero; /*! If this widget has visible children */ qx.Proto.hasVisibleChildren = qx.util.Return.returnFalse; /*! Check if there are any visible children inside */ qx.Proto.isVisibleEmpty = qx.util.Return.returnTrue; /* --------------------------------------------------------------------------- CORE MODIFIER --------------------------------------------------------------------------- */ qx.Proto._hasParent = false; qx.Proto._isDisplayable = false; qx.Proto.isDisplayable = function() { return this._isDisplayable; } qx.Proto._checkParent = function(propValue, propOldValue, propData) { if (this.contains(propValue)) { throw new Error("Could not insert myself into a child " + propValue + "!"); } return propValue; } qx.Proto._modifyParent = function(propValue, propOldValue, propData) { if (propOldValue) { var vOldIndex = propOldValue.getChildren().indexOf(this); // Reset cached dimension and location values this._computedWidthValue = this._computedMinWidthValue = this._computedMaxWidthValue = this._computedLeftValue = this._computedRightValue = null; this._computedHeightValue = this._computedMinHeightValue = this._computedMaxHeightValue = this._computedTopValue = this._computedBottomValue = null; this._cachedBoxWidth = this._cachedInnerWidth = this._cachedOuterWidth = null; this._cachedBoxHeight = this._cachedInnerHeight = this._cachedOuterHeight = null; // Finally remove from children array qx.lang.Array.removeAt(propOldValue.getChildren(), vOldIndex); // Invalidate visible children cache propOldValue._invalidateVisibleChildren(); // Remove child from old parent's children queue propOldValue._removeChildFromChildrenQueue(this); // The layouter adds some layout jobs propOldValue.getLayoutImpl().updateChildrenOnRemoveChild(this, vOldIndex); // Inform job queue propOldValue.addToJobQueue("removeChild"); // Invalidate inner preferred dimensions propOldValue._invalidatePreferredInnerDimensions(); // Store old parent (needed later by _handleDisplayable) this._oldParent = propOldValue; } if (propValue) { this._hasParent = true; if (qx.util.Validation.isValidNumber(this._insertIndex)) { qx.lang.Array.insertAt(propValue.getChildren(), this, this._insertIndex); delete this._insertIndex; } else { propValue.getChildren().push(this); } } else { this._hasParent = false; } return this._handleDisplayable("parent"); } qx.Proto._modifyDisplay = function(propValue, propOldValue, propData) { return this._handleDisplayable("display"); } /* --------------------------------------------------------------------------- DISPLAYBLE HANDLING --------------------------------------------------------------------------- */ qx.Proto._handleDisplayable = function(vHint) { // Detect changes. Return if there is no change. // Also handle the case if the displayable keeps true and the parent // was changed then we must not return here. var vDisplayable = this._computeDisplayable(); if (this._isDisplayable == vDisplayable && !(vDisplayable && vHint == "parent")) { return true; } this._isDisplayable = vDisplayable; var vParent = this.getParent(); // Invalidate visible children if (vParent) { vParent._invalidateVisibleChildren(); vParent._invalidatePreferredInnerDimensions(); } // Remove old parent's elements from DOM and delete old parent if (vHint && this._oldParent && this._oldParent._initialLayoutDone) { var vElement = this.getElement(); if(vElement) { if (this.getVisibility()) { this._beforeDisappear(); } this._beforeRemoveDom(); this._oldParent._getTargetNode().removeChild(vElement); this._afterRemoveDom(); if (this.getVisibility()) { this._afterDisappear(); } } delete this._oldParent; } // Handle 'show' if (vDisplayable) { /* -------------------------------- Update current parent -------------------------------- */ // The layouter added some layout jobs if (vParent._initialLayoutDone) { vParent.getLayoutImpl().updateChildrenOnAddChild(this, vParent.getChildren().indexOf(this)); // Inform parents job queue vParent.addToJobQueue("addChild"); } // Add to parents children queue // (indirectly with a new layout request) this.addToLayoutChanges("initial"); // Add to custom queues this.addToCustomQueues(vHint); // Handle beforeAppear signals if (this.getVisibility()) { this._beforeAppear(); } /* -------------------------------- Add to global Queues -------------------------------- */ // Add element (and create if not ready) if (!this._isCreated) { qx.ui.core.Widget.addToGlobalElementQueue(this); } // Add to global queues qx.ui.core.Widget.addToGlobalStateQueue(this); if (!qx.lang.Object.isEmpty(this._jobQueue)) { qx.ui.core.Widget.addToGlobalJobQueue(this); } if (!qx.lang.Object.isEmpty(this._childrenQueue)) { qx.ui.core.Widget.addToGlobalLayoutQueue(this); } } // Handle 'hide' else { // Removing from global queues qx.ui.core.Widget.removeFromGlobalElementQueue(this); qx.ui.core.Widget.removeFromGlobalStateQueue(this); qx.ui.core.Widget.removeFromGlobalJobQueue(this); qx.ui.core.Widget.removeFromGlobalLayoutQueue(this); // Add to top-level tree queue this.removeFromCustomQueues(vHint); // only remove when itself want to be removed // through a property change - not a parent signal if (vParent && vHint) { if (this.getVisibility()) { this._beforeDisappear(); } // The layouter added some layout jobs if (vParent._initialLayoutDone && this._initialLayoutDone) { vParent.getLayoutImpl().updateChildrenOnRemoveChild(this, vParent.getChildren().indexOf(this)); // Inform parent's job queue vParent.addToJobQueue("removeChild"); // Before Remove DOM Event this._beforeRemoveDom(); // DOM action vParent._getTargetNode().removeChild(this.getElement()); // After Remove DOM Event this._afterRemoveDom(); } // Remove from parents children queue vParent._removeChildFromChildrenQueue(this); if (this.getVisibility()) { this._afterDisappear(); } } } this._handleDisplayableCustom(vDisplayable, vParent, vHint); return true; } qx.Proto.addToCustomQueues = qx.util.Return.returnTrue; qx.Proto.removeFromCustomQueues = qx.util.Return.returnTrue; qx.Proto._handleDisplayableCustom = qx.util.Return.returnTrue; qx.Proto._computeDisplayable = function() { return this.getDisplay() && this._hasParent && this.getParent()._isDisplayable ? true : false; } qx.Proto._beforeAppear = function() { // this.debug("_beforeAppear"); this.createDispatchEvent("beforeAppear"); } qx.Proto._afterAppear = function() { // this.debug("_afterAppear"); this._isSeeable = true; this.createDispatchEvent("appear"); } qx.Proto._beforeDisappear = function() { // this.debug("_beforeDisappear"); // Remove any hover/pressed styles this.removeState("over"); if (qx.OO.isAvailable("qx.ui.form.Button")) { this.removeState("pressed"); this.removeState("abandoned"); } // this.debug("_beforeDisappear"); this.createDispatchEvent("beforeDisappear"); } qx.Proto._afterDisappear = function() { // this.debug("_afterDisappear"); this._isSeeable = false; this.createDispatchEvent("disappear"); } qx.Proto._isSeeable = false; /** * If the widget is currently seeable which means that it: * * * has a also seeable parent * * visibility is true * * display is true */ qx.Proto.isSeeable = function() { return this._isSeeable; } qx.Proto.isAppearRelevant = function() { return this.getVisibility() && this._isDisplayable; } /* --------------------------------------------------------------------------- DOM SIGNAL HANDLING --------------------------------------------------------------------------- */ qx.Proto._beforeInsertDom = function() { // this.debug("_beforeInsertDom"); this.createDispatchEvent("beforeInsertDom"); } qx.Proto._afterInsertDom = function() { // this.debug("_afterInsertDom"); this.createDispatchEvent("insertDom"); } qx.Proto._beforeRemoveDom = function() { // this.debug("_beforeRemoveDom"); this.createDispatchEvent("beforeRemoveDom"); } qx.Proto._afterRemoveDom = function() { // this.debug("_afterRemoveDom"); this.createDispatchEvent("removeDom"); } /* --------------------------------------------------------------------------- VISIBILITY HANDLING --------------------------------------------------------------------------- */ qx.Proto._modifyVisibility = function(propValue, propOldValue, propData) { if (propValue) { if (this._isDisplayable) { this._beforeAppear(); } this.removeStyleProperty("display"); if (this._isDisplayable) { this._afterAppear(); } } else { if (this._isDisplayable) { this._beforeDisappear(); } this.setStyleProperty("display", "none"); if (this._isDisplayable) { this._afterDisappear(); } } return true; } qx.Proto.show = function() { this.setVisibility(true); this.setDisplay(true); } qx.Proto.hide = function() { this.setVisibility(false); } qx.Proto.connect = function() { this.setDisplay(true); } qx.Proto.disconnect = function() { this.setDisplay(false); } /* --------------------------------------------------------------------------- ENHANCED BORDER SUPPORT --------------------------------------------------------------------------- */ if (qx.sys.Client.getInstance().isGecko()) { qx.Proto._createElementForEnhancedBorder = qx.util.Return.returnTrue; } else { qx.Proto._createElementForEnhancedBorder = function() { // Enhanced Border Test (for IE and Opera) if (qx.renderer.border.Border.enhancedCrossBrowserMode && this.getTagName() == "div" && !this._borderElement) { var el = this.getElement(); var cl = this._borderElement = document.createElement("div"); var es = el.style; var cs = this._borderStyle = cl.style; cs.width = cs.height = "100%"; cs.position = "absolute"; for (var i in this._styleProperties) { switch(i) { case "position": case "zIndex": case "filter": case "display": break; default: cs[i] = this._styleProperties[i]; es[i] = ""; } } // Move existing children while(el.firstChild) { cl.appendChild(el.firstChild); } el.appendChild(cl); } } } /* --------------------------------------------------------------------------- DOM ELEMENT HANDLING --------------------------------------------------------------------------- */ qx.Proto._isCreated = false; if (qx.sys.Client.getInstance().isGecko()) { qx.Proto._getTargetNode = function() { return this._element; } } else { qx.Proto._getTargetNode = function() { return this._borderElement || this._element; } } qx.Proto.addToDocument = function() { qx.ui.core.ClientDocument.getInstance().add(this); } /*! Check if the widget is created (or the element is already available). */ qx.Proto.isCreated = function() { return this._isCreated; } /*! Create widget with empty element (of specified tagname). */ qx.Proto._createElementImpl = function() { this.setElement(this.getTopLevelWidget().getDocumentElement().createElement(this.getTagName())); } qx.Proto._modifyElement = function(propValue, propOldValue, propData) { this._isCreated = qx.util.Validation.isValidElement(propValue); if (propOldValue) { // reset reference to widget instance propOldValue.qx_Widget = null; // remove events this._removeInlineEvents(propOldValue); } if (propValue) { // add reference to widget instance propValue.qx_Widget = this; // link element and style reference this._element = propValue; this._style = propValue.style; this._applyStyleProperties(propValue); this._applyHtmlProperties(propValue); this._applyHtmlAttributes(propValue); this._applyElementData(propValue); // attach inline events this._addInlineEvents(propValue); // send out create event this.createDispatchEvent("create"); } else { this._element = this._style = null; } return true; } /* --------------------------------------------------------------------------- JOBS QUEUE --------------------------------------------------------------------------- */ qx.Proto.addToJobQueue = function(p) { if (this._hasParent) { qx.ui.core.Widget.addToGlobalJobQueue(this); } if (!this._jobQueue) { this._jobQueue = {}; } this._jobQueue[p] = true; return true; } qx.Proto._flushJobQueue = function(q) { /* -------------------------------------------------------------------------------- 1. Pre checks -------------------------------------------------------------------------------- */ try { var vQueue = this._jobQueue; var vParent = this.getParent(); if (!vParent || qx.lang.Object.isEmpty(vQueue)) { return; } var vLayoutImpl = this instanceof qx.ui.core.Parent ? this.getLayoutImpl() : null; if (vLayoutImpl) { vLayoutImpl.updateSelfOnJobQueueFlush(vQueue); } } catch(ex) { this.error("Flushing job queue (prechecks#1) failed", ex); } /* -------------------------------------------------------------------------------- 2. Recompute dimensions -------------------------------------------------------------------------------- */ try { var vFlushParentJobQueue = false; var vRecomputeOuterWidth = vQueue.marginLeft || vQueue.marginRight; var vRecomputeOuterHeight = vQueue.marginTop || vQueue.marginBottom; var vRecomputeInnerWidth = vQueue.frameWidth; var vRecomputeInnerHeight = vQueue.frameHeight; var vRecomputeParentPreferredInnerWidth = (vQueue.frameWidth || vQueue.preferredInnerWidth) && this._recomputePreferredBoxWidth(); var vRecomputeParentPreferredInnerHeight = (vQueue.frameHeight || vQueue.preferredInnerHeight) && this._recomputePreferredBoxHeight(); if (vRecomputeParentPreferredInnerWidth) { var vPref = this.getPreferredBoxWidth(); if (this._computedWidthTypeAuto) { this._computedWidthValue = vPref; vQueue.width = true; } if (this._computedMinWidthTypeAuto) { this._computedMinWidthValue = vPref; vQueue.minWidth = true; } if (this._computedMaxWidthTypeAuto) { this._computedMaxWidthValue = vPref; vQueue.maxWidth = true; } } if (vRecomputeParentPreferredInnerHeight) { var vPref = this.getPreferredBoxHeight(); if (this._computedHeightTypeAuto) { this._computedHeightValue = vPref; vQueue.height = true; } if (this._computedMinHeightTypeAuto) { this._computedMinHeightValue = vPref; vQueue.minHeight = true; } if (this._computedMaxHeightTypeAuto) { this._computedMaxHeightValue = vPref; vQueue.maxHeight = true; } } if ((vQueue.width || vQueue.minWidth || vQueue.maxWidth || vQueue.left || vQueue.right) && this._recomputeBoxWidth()) { vRecomputeOuterWidth = vRecomputeInnerWidth = true; } if ((vQueue.height || vQueue.minHeight || vQueue.maxHeight || vQueue.top || vQueue.bottom) && this._recomputeBoxHeight()) { vRecomputeOuterHeight = vRecomputeInnerHeight = true; } } catch(ex) { this.error("Flushing job queue (recompute#2) failed", ex); } /* -------------------------------------------------------------------------------- 3. Signals to parent widgets -------------------------------------------------------------------------------- */ try { if ((vRecomputeOuterWidth && this._recomputeOuterWidth()) || vRecomputeParentPreferredInnerWidth) { vParent._invalidatePreferredInnerWidth(); vParent.getLayoutImpl().updateSelfOnChildOuterWidthChange(this); vFlushParentJobQueue = true; } if ((vRecomputeOuterHeight && this._recomputeOuterHeight()) || vRecomputeParentPreferredInnerHeight) { vParent._invalidatePreferredInnerHeight(); vParent.getLayoutImpl().updateSelfOnChildOuterHeightChange(this); vFlushParentJobQueue = true; } if (vFlushParentJobQueue) { vParent._flushJobQueue(); } } catch(ex) { this.error("Flushing job queue (parentsignals#3) failed", ex); } /* -------------------------------------------------------------------------------- 4. Add layout jobs -------------------------------------------------------------------------------- */ try { // add to layout queue vParent._addChildToChildrenQueue(this); // convert jobs to layout jobs for (var i in vQueue) { this._layoutChanges[i] = true; } } catch(ex) { this.error("Flushing job queue (addjobs#4) failed", ex); } /* -------------------------------------------------------------------------------- 5. Signals to children -------------------------------------------------------------------------------- */ try { // inform children about padding change if (this instanceof qx.ui.core.Parent && (vQueue.paddingLeft || vQueue.paddingRight || vQueue.paddingTop || vQueue.paddingBottom)) { var ch=this.getChildren(), chl=ch.length; if (vQueue.paddingLeft) { for (var i=0; i= 0; } qx.Proto.isFocusRoot = function() { return false; } qx.Proto.getFocusRoot = function() { if(this._hasParent) { return this.getParent().getFocusRoot(); } return null; } qx.Proto.getActiveChild = function() { var vRoot = this.getFocusRoot(); if (vRoot) { return vRoot.getActiveChild(); } return null; } qx.Proto._ontabfocus = qx.util.Return.returnTrue; qx.Proto._modifyFocused = function(propValue, propOldValue, propData) { if (!this.isCreated()) { return true; } var vFocusRoot = this.getFocusRoot(); // this.debug("Focused: " + propValue); if (vFocusRoot) { // may be undefined if this widget has been removed if (propValue) { vFocusRoot.setFocusedChild(this); this._visualizeFocus(); } else { if (vFocusRoot.getFocusedChild() == this) { vFocusRoot.setFocusedChild(null); } this._visualizeBlur(); } } return true; } qx.Proto._visualizeBlur = function() { // Force blur, even if mouseFocus is not active because we // need to be sure that the previous focus rect gets removed. // But this only needs to be done, if there is no new focused element. if (this.getEnableElementFocus() && (!this.getFocusRoot().getFocusedChild() || (this.getFocusRoot().getFocusedChild() && this.getFocusRoot().getFocusedChild().getEnableElementFocus()))) { try { this.getElement().blur(); } catch(ex) {}; } this.removeState("focused"); return true; } qx.Proto._visualizeFocus = function() { //this.info("_visualizeFocus: " + qx.event.handler.FocusHandler.mouseFocus); if (!qx.event.handler.FocusHandler.mouseFocus && this.getEnableElementFocus()) { try { this.getElement().focus(); } catch(ex) {}; } this.addState("focused"); return true; } qx.Proto.focus = function() { delete qx.event.handler.FocusHandler.mouseFocus; this.setFocused(true); } qx.Proto.blur = function() { delete qx.event.handler.FocusHandler.mouseFocus; this.setFocused(false); } /* --------------------------------------------------------------------------- CAPTURE --------------------------------------------------------------------------- */ qx.Proto._modifyCapture = function(propValue, propOldValue, propData) { var vMgr = qx.event.handler.EventHandler.getInstance(); if (propOldValue) { vMgr.setCaptureWidget(null); } else if (propValue) { vMgr.setCaptureWidget(this); } return true; } /* --------------------------------------------------------------------------- ZINDEX --------------------------------------------------------------------------- */ qx.Proto._modifyZIndex = function(propValue, propOldValue, propData) { return this.setStyleProperty(propData.name, propValue); } /* --------------------------------------------------------------------------- TAB INDEX --------------------------------------------------------------------------- */ if (qx.sys.Client.getInstance().isMshtml()) { qx.Proto._modifyTabIndex = function(propValue, propOldValue, propData) { if (propValue < 0 || !this.getEnabled()) { this.setHtmlProperty("unselectable", "on"); } else { this.removeHtmlProperty("unselectable"); } this.setHtmlProperty("tabIndex", propValue < 0 ? -1 : 1); return true; } } else if (qx.sys.Client.getInstance().isGecko()) { qx.Proto._modifyTabIndex = function(propValue, propOldValue, propData) { this.setStyleProperty("MozUserFocus", (propValue < 0 ? "ignore" : "normal")); // be forward compatible (CSS 3 Draft) this.setStyleProperty("userFocus", (propValue < 0 ? "ignore" : "normal")); return true; } } else { qx.Proto._modifyTabIndex = function(propValue, propOldValue, propData) { // CSS 3 Draft this.setStyleProperty("userFocus", (propValue < 0 ? "ignore" : "normal")); // IE Backward Compatible if (propValue < 0 || !this.getEnabled()) { this.setHtmlProperty("unselectable", "on"); } else { this.removeHtmlProperty("unselectable"); } this.setHtmlProperty("tabIndex", propValue < 0 ? -1 : 1); return true; } } /* --------------------------------------------------------------------------- CSS CLASS NAME --------------------------------------------------------------------------- */ qx.Proto.setCssClassName = function(propValue) { this.setHtmlProperty("className", propValue); } qx.Proto.getCssClassName = function() { return this.getHtmlProperty("className"); } /* --------------------------------------------------------------------------- WIDGET FROM POINT --------------------------------------------------------------------------- */ qx.Proto.getWidgetFromPoint = function(x, y) { var ret = this.getWidgetFromPointHelper(x, y); return ret && ret != this ? ret : null; } qx.Proto.getWidgetFromPointHelper = function(x, y) { return this; } /* --------------------------------------------------------------------------- CAN SELECT --------------------------------------------------------------------------- */ if(qx.sys.Client.getInstance().isMshtml()) { qx.Proto._modifySelectable = function(propValue, propOldValue, propData) { if (propValue) { return this.removeHtmlProperty("unselectable"); } else { return this.setHtmlProperty("unselectable", "on"); } } } else if(qx.sys.Client.getInstance().isGecko()) { qx.Proto._modifySelectable = function(propValue, propOldValue, propData) { if (propValue) { this.removeStyleProperty("MozUserSelect"); } else { this.setStyleProperty("MozUserSelect", "none"); } return true; }; } else if (qx.sys.Client.getInstance().isOpera()) { // No known method available for this client qx.Proto._modifySelectable = function(propValue, propOldValue, propData) { return true; } } else if (qx.sys.Client.getInstance().isKhtml() || qx.sys.Client.getInstance().isWebkit()) { qx.Proto._modifySelectable = function(propValue, propOldValue, propData) { // Be forward compatible and use both userSelect and KhtmlUserSelect if (propValue) { this.removeStyleProperty("KhtmlUserSelect"); } else { this.setStyleProperty("KhtmlUserSelect", "none"); } return true; }; } else { qx.Proto._modifySelectable = function(propValue, propOldValue, propData) { if (propValue) { return this.removeStyleProperty("userSelect"); } else { this.setStyleProperty("userSelect", "none"); } } } /* --------------------------------------------------------------------------- OPACITY --------------------------------------------------------------------------- */ /*! Sets the opacity for the widget. Any child widget inside the widget will also become (semi-)transparent. The value should be a number between 0 and 1 inclusive, where 1 means totally opaque and 0 invisible. */ if(qx.sys.Client.getInstance().isMshtml()) { qx.Proto._modifyOpacity = function(propValue, propOldValue, propData) { if(propValue == null || propValue >= 1 || propValue < 0) { this.removeStyleProperty("filter"); } else if (qx.util.Validation.isValidNumber(propValue)) { this.setStyleProperty("filter", ("Alpha(Opacity=" + Math.round(propValue * 100) + ")")); } else { throw new Error("Unsupported opacity value: " + propValue); } return true; } } else { qx.Proto._modifyOpacity = function(propValue, propOldValue, propData) { if(propValue == null || propValue > 1) { if (qx.sys.Client.getInstance().isGecko()) { this.removeStyleProperty("MozOpacity"); } else if (qx.sys.Client.getInstance().isKhtml()) { this.removeStyleProperty("KhtmlOpacity"); } this.removeStyleProperty("opacity"); } else if (qx.util.Validation.isValidNumber(propValue)) { propValue = qx.lang.Number.limit(propValue, 0, 1); // should we omit gecko's flickering here // and limit the max value to 0.99? if (qx.sys.Client.getInstance().isGecko()) { this.setStyleProperty("MozOpacity", propValue); } else if (qx.sys.Client.getInstance().isKhtml()) { this.setStyleProperty("KhtmlOpacity", propValue); } this.setStyleProperty("opacity", propValue); } return true; } } /* --------------------------------------------------------------------------- CURSOR --------------------------------------------------------------------------- */ qx.Proto._modifyCursor = function(propValue, propOldValue, propData) { if (propValue) { if (propValue == "pointer" && qx.sys.Client.getInstance().isMshtml()) { this.setStyleProperty("cursor", "hand"); } else { this.setStyleProperty("cursor", propValue); } } else { this.removeStyleProperty("cursor"); } return true; } /* --------------------------------------------------------------------------- BACKGROUND IMAGE --------------------------------------------------------------------------- */ qx.Proto._modifyBackgroundImage = function(propValue, propOldValue, propData) { return qx.util.Validation.isValidString(propValue) ? this.setStyleProperty("backgroundImage", "url(" + qx.manager.object.AliasManager.getInstance().resolvePath(propValue) + ")") : this.removeStyleProperty("backgroundImage"); } /* --------------------------------------------------------------------------- CLIPPING --------------------------------------------------------------------------- */ qx.Proto._modifyClip = function(propValue, propOldValue, propData) { return this._compileClipString(); } qx.Proto._compileClipString = function() { var vLeft = this.getClipLeft(); var vTop = this.getClipTop(); var vWidth = this.getClipWidth(); var vHeight = this.getClipHeight(); var vRight, vBottom; if(vLeft == null) { vRight = (vWidth == null ? "auto" : vWidth + "px"); vLeft = "auto"; } else { vRight = (vWidth == null ? "auto" : vLeft + vWidth + "px"); vLeft = vLeft + "px"; } if(vTop == null) { vBottom = (vHeight == null ? "auto" : vHeight + "px"); vTop = "auto"; } else { vBottom = (vHeight == null ? "auto" : vTop + vHeight + "px"); vTop = vTop + "px"; } return this.setStyleProperty("clip", ("rect(" + vTop + "," + vRight + "," + vBottom + "," + vLeft + ")")); } /* --------------------------------------------------------------------------- OVERFLOW --------------------------------------------------------------------------- */ /* This will measure the typical native scrollbar size in the environment */ qx.ui.core.Widget.initOverflow = function() { if (qx.ui.core.Widget.initOverflowDone) { return; } var t = document.createElement("div"); var s = t.style; s.height = s.width = "100px"; s.overflow = "scroll"; document.body.appendChild(t); var c = qx.dom.Dimension.getScrollBarSizeRight(t); if (c) { qx.ui.core.Widget.SCROLLBAR_SIZE = c; } document.body.removeChild(t); qx.ui.core.Widget.initOverflowDone = true; } if (qx.sys.Client.getInstance().isGecko()) { qx.Proto._modifyOverflow = function(propValue, propOldValue, propData) { var pv = propValue; var pn = propData.name; switch(pv) { case "hidden": pv = "-moz-scrollbars-none"; break; case "scrollX": pv = "-moz-scrollbars-horizontal"; break; case "scrollY": pv = "-moz-scrollbars-vertical"; break; } return this._applyOverflow(pn, pv, propValue, propOldValue); } } // Mshtml conforms here to CSS3 Spec. Eventually there will be multiple // browsers which support these new overflowX overflowY properties. else if (qx.sys.Client.getInstance().isMshtml()) { qx.Proto._modifyOverflow = function(propValue, propOldValue, propData) { var pv = propValue; var pn = propData.name; switch(pv) { case "scrollX": pn = "overflowX"; pv = "scroll"; break; case "scrollY": pn = "overflowY"; pv = "scroll"; break; } // Clear up concurrenting rules var a = [ "overflow", "overflowX", "overflowY" ]; for (var i=0; i= 0){ this.setOpacity(this._computeFadeOpacity()); this.getFadeTimer().restart(); } else if(this.hasEventListeners(qx.ui.core.Widget.FADE_FINISHED)) { this.createDispatchDataEvent(qx.ui.core.Widget.FADE_FINISHED, qx.ui.core.Widget.FADE_OUT); }; break; }; qx.ui.core.Widget.flushGlobalQueues(); }; qx.Proto._modifyFadeSteps = function(propValue, propOldValue, propData) { if(propValue < 1) return; this.setFadeInterval(parseInt(this.getFadeTime() / propValue)); this.setFadeUnit(Math.round(this.getFadeMax()/propValue)); return true; }; qx.Proto._modifyFadeTime = function(propValue, propOldValue, propData) { if(propValue < 1) return; this.setFadeInterval(parseInt(propValue / this.getFadeSteps())); return true; }; qx.Proto._modifyFadeUnit = function(propValue, propOldValue, propData) { this.setFadeSteps(Math.round(this.getFadeMax()/propValue)); return true; }; qx.Proto._modifyFadeMax = function(propValue, propOldValue, propData) { this.setFadeUnit(Math.round(propValue / this.getFadeSteps())); return true; }; qx.Proto._computeFadeOpacity = function() { var op = this.getFadeUnit() * this.getFadeCounter() / 100; return(op); }; /* --------------------------------------------------------------------------- DISPOSER --------------------------------------------------------------------------- */ qx.Proto.dispose = function() { if(this.getDisposed()) { return; } var vElement = this.getElement(); if (vElement) { this._removeInlineEvents(vElement); delete this._isCreated; vElement.qx_Widget = null; this._element = null; this._style = null; } this._inlineEvents = null; this._element = null; this._style = null; this._borderElement = null; this._borderStyle = null; this._oldParent = null; // should be enough to remove the hashTables delete this._styleProperties; delete this._htmlProperties; delete this._htmlAttributes; delete this._states; // remove queue content for (var i in this._jobQueue) { delete this._jobQueue[i]; } delete this._jobQueue; for (var i in this._layoutChanges) { delete this._layoutChanges[i]; } delete this._layoutChanges; // dispose the fader if(this._fadeTimer){ this._fadeTimer.dispose(); this._fadeTimer = null; } return qx.core.Target.prototype.dispose.call(this); }