/* ************************************************************************
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:
- default
- crosshair
- pointer (hand is the ie name and will mapped to pointer in non-ie).
- move
- n-resize
- ne-resize
- e-resize
- se-resize
- s-resize
- sw-resize
- w-resize
- nw-resize
- text
- wait
- help
- url([file]) = self defined cursor, file should be an ANI- or CUR-type
*/
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);
}