All Downloads are FREE. Search and download functionalities are using the official Maven repository.

rwt.widgets.base.Widget.js Maven / Gradle / Ivy

/*******************************************************************************
 * Copyright (c) 2004, 2022 1&1 Internet AG, Germany, http://www.1und1.de,
 *                          EclipseSource, and others.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    1&1 Internet AG and others - original API and implementation
 *    EclipseSource - adaptation for the Eclipse Remote Application Platform
 ******************************************************************************/


/**
 * This is the main widget, all visible objects in the application extend this.
 *
 * @appearance widget
 * @state selected Set by {@link rwt.widgets.util.SelectionManager#renderItemSelectionState}
 * @state anchor Set by {@link rwt.widgets.util.SelectionManager#renderItemAnchorState}
 * @state lead Set by {@link rwt.widgets.util.SelectionManager#renderItemLeadState}
 *
 * @state disabled Set by {@link rwt.qx.Object#enabled}
 * @state focused Set by {@link #focused}
 */

/*jshint boss: true */
rwt.qx.Class.define( "rwt.widgets.base.Widget", {

  extend : rwt.qx.Target,
  include : rwt.widgets.util.HtmlAttributesMixin,

  construct : function() {
    this.base( arguments );
    this._layoutChanges = {};
    this._outerFrame = [ 0, 0 ];
  },

  statics : {

    //////////////////////
    // Global Widget Flush

    _globalWidgetQueue : [],
    _globalElementQueue : [],
    _globalStateQueue : [],
    _globalJobQueue : [],
    _globalLayoutQueue : [],
    _fastGlobalDisplayQueue : [],
    _lazyGlobalDisplayQueues : {},
    _globalDisposeQueue : [],

    _autoFlushTimeout : null,
    _flushGlobalQueuesPhase : 0,
    _renderHtmlIds : false,

    _FLUSH_PHASE_IDLE : 0,
    _FLUSH_PHASE_WIDGET : 1,
    _FLUSH_PHASE_STATE : 2,
    _FLUSH_PHASE_ELEMENT : 3,
    _FLUSH_PHASE_JOB : 4,
    _FLUSH_PHASE_LAYOUT : 5,
    _FLUSH_PHASE_DISPLAY : 6,
    _FLUSH_PHASE_DISPOSE : 7,

    _initAutoFlush : function( phase ) {
      if( rwt.widgets.base.Widget._autoFlushTimeout == null ) {
        // RAP: Fix for bug 303162
        if(    !rwt.widgets.base.Widget._inFlushGlobalQueues
            || phase < rwt.widgets.base.Widget._flushGlobalQueuesPhase ) {
          rwt.widgets.base.Widget._autoFlushTimeout
            = window.setTimeout( rwt.widgets.base.Widget._autoFlushHelper, 0 );
        }
      }
    },

    _removeAutoFlush : function() {
      if( rwt.widgets.base.Widget._autoFlushTimeout != null ) {
        window.clearTimeout( rwt.widgets.base.Widget._autoFlushTimeout );
        rwt.widgets.base.Widget._autoFlushTimeout = null;
      }
    },

    _autoFlushHelper : function() {
      try {
        rwt.widgets.base.Widget._autoFlushTimeout = null;
        if( !rwt.qx.Object.inGlobalDispose() ) {
          rwt.widgets.base.Widget.flushGlobalQueues();
        }
      }catch( ex ) {
        rwt.runtime.ErrorHandler.processJavaScriptError( ex );
      }
    },

    flushGlobalQueues : function() {
      if( rwt.widgets.base.Widget._autoFlushTimeout != null ) {
        rwt.widgets.base.Widget._removeAutoFlush();
      }
      if( rwt.widgets.base.Widget._inFlushGlobalQueues ) {
        return;
      }
      if( !rwt.runtime.System.getInstance().getUiReady() ) {
        return;
      }
      rwt.widgets.base.Widget._inFlushGlobalQueues = true;
      rwt.widgets.base.Widget.flushGlobalWidgetQueue();
      rwt.widgets.base.Widget.flushGlobalStateQueue();
      rwt.widgets.base.Widget.flushGlobalElementQueue();
      rwt.widgets.base.Widget.flushGlobalJobQueue();
      rwt.widgets.base.Widget.flushGlobalLayoutQueue();
      rwt.widgets.base.Widget.flushGlobalDisplayQueue();
      rwt.widgets.base.Widget.flushGlobalDisposeQueue();
      rwt.widgets.base.Widget._flushGlobalQueuesPhase = rwt.widgets.base.Widget._FLUSH_PHASE_IDLE;
      delete rwt.widgets.base.Widget._inFlushGlobalQueues;
    },

    addToGlobalWidgetQueue : function(vWidget) {
      if (!vWidget._isInGlobalWidgetQueue && vWidget._isDisplayable) {
        if (rwt.widgets.base.Widget._autoFlushTimeout == null) {
          rwt.widgets.base.Widget._initAutoFlush( rwt.widgets.base.Widget._FLUSH_PHASE_WIDGET );
        }
        rwt.widgets.base.Widget._globalWidgetQueue.push(vWidget);
        vWidget._isInGlobalWidgetQueue = true;
      }
    },

    removeFromGlobalWidgetQueue : function(vWidget) {
      if (vWidget._isInGlobalWidgetQueue) {
        rwt.util.Arrays.remove(rwt.widgets.base.Widget._globalWidgetQueue, vWidget);
        delete vWidget._isInGlobalWidgetQueue;
      }
    },

    flushGlobalWidgetQueue : function() {
      rwt.widgets.base.Widget._flushGlobalQueuesPhase = rwt.widgets.base.Widget._FLUSH_PHASE_WIDGET;
      var vQueue = rwt.widgets.base.Widget._globalWidgetQueue, vLength, vWidget;
      while ((vLength = vQueue.length) > 0) {
        for (var i=0; i 0) {
        for (var i=0; i 0) {
        var queue = rwt.util.Arrays.copy(Widget._globalStateQueue);
        Widget._globalStateQueue = [];
        for (var i=0, l=queue.length; 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) {
        for (var i=0; ivisibility.
     **/
    visibility : {
      check : "Boolean",
      init : true,
      apply : "_applyVisibility",
      event : "changeVisibility"
    },

    /**
     * Whether the widget should be displayed.
     * Use this property instead of visibility if the change of the visibility
     * should remove the widget from the layout flow and force a relayout of the
     * application. This is similar to the CSS property display.
     */
    display : {
      check : "Boolean",
      init : true,
      apply : "_applyDisplay",
      event : "changeDisplay"
    },

    /**
     * If you switch this to true, the widget doesn't handle
     *  events directly. It will redirect them to the parent
     *  widget.
     */
    anonymous : {
      check : "Boolean",
      init: false,
      event : "changeAnonymous"
    },

    /**
     * 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.
     */
    horizontalAlign : {
      check : [ "left", "center", "right" ],
      themeable : true,
      nullable : true
    },

    /**
     * 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.
     */
    verticalAlign :  {
      check : [ "top", "middle", "bottom" ],
      themeable : true,
      nullable : true
    },

    /**
     * Should this widget be stretched on the x-axis if the layout handler will do this?
     *  Used by some layout handlers (rwt.widgets.base.BoxLayout, ...).
     */
    allowStretchX : {
      check : "Boolean",
      init : true
    },

    /**
     * Should this widget be stretched on the y-axis if the layout handler will do this?
     *  Used by some layout handlers (rwt.widgets.base.BoxLayout, ...).
     */
    allowStretchY : {
      check : "Boolean",
      init : true
    },

    /**
     * Mapping to native style property z-index.
     *
     *  This should be used with caution since in some cases
     *  this might give unrespected results.
     */
    zIndex : {
      check : "Number",
      apply : "_applyZIndex",
      event : "changeZIndex",
      themeable : true,
      nullable : true,
      init : null
    },

    /**
     * The backgroundColor style property of the rendered widget.
     */
    backgroundColor : {
      nullable : true,
      init : null,
      check : "Color",
      apply : "_applyBackgroundColor",
      event : "changeBackgroundColor",
      themeable : true
    },

    backgroundGradient : {
      check : "Array",
      nullable : true,
      init : null,
      apply : "_applyBackgroundGradient",
      event : "changeBackgroundGradient",
      themeable : true
    },

    /**
     * Syntax for shadow:
     * [
     *    inset, //boolean, currently not supported
     *    offsetX, // positive or negative number
     *    offsetY, // positive or negative number
     *    blurRadius, // positive number or zero
     *    spread, // positive or negative number
     *    color, // string
     *    opacity, // number between 0 and 1
     * ]
     */
    shadow : {
      check : "Array",
      nullable : true,
      init : null,
      apply : "_applyShadow",
      event : "changeShadow",
      themeable : true
    },

    textShadow : {
      check : "Array",
      nullable : true,
      init : null,
      apply : "_applyTextShadow",
      event : "changeTextShadow",
      themeable : true
   },

    /**
     * The color (textColor) style property of the rendered widget.
     */
    textColor : {
      nullable : true,
      init : "inherit",
      check : "Color",
      apply : "_applyTextColor",
      event : "changeTextColor",
      themeable : true,
      inheritable : true
    },

    /**
     * The border property describes how to paint the border on the widget.
     */
    border : {
      nullable : true,
      init : null,
      apply : "_applyBorder",
      event : "changeBorder",
      check : "Border",
      themeable : true
    },

    /** The font property describes how to paint the font on the widget. */
    font : {
      nullable : true,
      init : "inherit",
      apply : "_applyFont",
      check : "Font",
      event : "changeFont",
      themeable : true,
      inheritable : 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.
     */
    opacity : {
      check : "Number",
      apply : "_applyOpacity",
      themeable : true,
      nullable : true,
      init : null
    },

    /**
     * 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 crossbrowser:
     * 
  • default
  • *
  • crosshair
  • *
  • pointer
  • *
  • move
  • *
  • n-resize
  • *
  • ne-resize
  • *
  • e-resize
  • *
  • se-resize
  • *
  • s-resize
  • *
  • sw-resize
  • *
  • w-resize
  • *
  • nw-resize
  • *
  • text
  • *
  • wait
  • *
  • help
  • *
*/ cursor : { check : "String", apply : "_applyCursor", event : "changeCursor", themeable : true, nullable : true, init : null }, /** * Mapping to native style property background-image. * * The URI of the image file to use as background image. */ backgroundImage : { check : "String", nullable : true, apply : "_applyBackgroundImage", themeable : true }, /** * Mapping to native style property background-repeat. */ backgroundRepeat : { check : [ "repeat", "repeat-x", "repeat-y", "no-repeat" ], nullable : true, apply : "_applyBackgroundRepeat", themeable : true }, /** * Mapping to native style property background-position. */ backgroundPosition : { check : [ "left top", "left center", "left bottom", "right top", "right center", "right bottom", "center top", "center center", "center bottom" ], nullable : true, apply : "_applyBackgroundPosition", themeable : true }, /** * Describes how to handle content that is too large to fit inside the widget. * * Overflow modes: * * * * * * *
hiddenThe content is clipped
autoScroll bars are shown as needed
scrollScroll bars are always shown. Even if there is enough room for the content inside the widget.
scrollXScroll bars for the X-Axis are always shown. Even if there is enough room for the content inside the widget.
scrollYScroll bars for the Y-Axis are always shown. Even if there is enough room for the content inside the widget.
*/ overflow : { check : ["hidden", "auto", "scroll" ,"scrollX", "scrollY"], nullable : true, apply : "_applyOverflow", event : "changeOverflow", themeable : true, init : null }, /** * Enables/disables overflow on the outer element for enhanced borders. */ containerOverflow : { check : "Boolean", nullable : false, apply : "_applyContainerOverflow", themeable : true, init : true }, /** Clipping of the widget (left) */ clipLeft : { check : "Integer", apply : "_applyClip", themeable : true, nullable : true }, /** Clipping of the widget (top) */ clipTop : { check : "Integer", apply : "_applyClip", themeable : true, nullable : true }, /** Clipping of the widget (width) */ clipWidth : { check : "Integer", apply : "_applyClip", themeable : true, nullable : true }, /** Clipping of the widget (height) */ clipHeight : { check : "Integer", apply : "_applyClip", themeable : true, nullable : true }, /** * 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. * * Setting the tabIndex to -1 deactivate focus handling for the widget. */ tabIndex : { check : "Integer", nullable : true, init : null, apply : "_applyTabIndex", event : "changeTabIndex" }, /** If the focus outline should be hidden. */ hideFocus : { check : "Boolean", init : true, themeable : true }, /** Use DOM focussing (focus() and blur() methods of DOM nodes) */ enableElementFocus : { check : "Boolean", init : 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. */ focused : { check : "Boolean", init : false, apply : "_applyFocused", event : "changeFocused" }, /** Toggle the possibility to select the element of this widget. */ selectable : { check : "Boolean", init : null, nullable : true, apply : "_applySelectable" }, /** Contains the tooltip object connected to the widget. */ toolTipText : { nullable : true, event: "changeToolTipText" }, /** Contains the context menu object connected to the widget. (Need real implementation) */ // RAP : remove check, allow other menu implementation contextMenu : { nullable : true, event: "changeContextMenu" }, /** Capture all events and map them to this widget */ capture : { check : "Boolean", init : false, apply : "_applyCapture", event : "changeCapture" }, /** Contains the support drop types for drag and drop support */ dropDataTypes : { nullable : true, dispose : true }, /** A command called if the widget should be excecuted (a placeholder for buttons, ...) */ command : { check : "qx.client.Command", nullable : true, apply : "_applyCommand" }, /** Appearance of the widget */ appearance : { check : "String", init : "widget", apply : "_applyAppearance", event : "changeAppearance" }, direction : { check : "String", init : "ltr", apply : "_applyDirection", event : "changeDirection" }, /* * The method which this.supportsDrop() calls to determine whether the * widget supports a particular drop operation. * * This is a property so that a mixin can modify it. Otherwise, the mixin * would have to override the supportsDrop() method, requiring the mixin * to be applied with patch() instead of include(). All normal mixins * should be able to be simply include()ed, and not have to be patch()ed. * * If this property is null, then the default supportsDrop() action * defined herein shall be used. */ supportsDropMethod : { check : "Function", nullable : true, init : null }, /** Margin of the widget (top) */ marginTop : { check : "Number", apply : "_applyMarginTop", nullable : true, themeable : true }, /** Margin of the widget (right) */ marginRight : { check : "Number", apply : "_applyMarginRight", nullable : true, themeable : true }, /** Margin of the widget (bottom) */ marginBottom : { check : "Number", apply : "_applyMarginBottom", nullable : true, themeable : true }, /** Margin of the widget (left) */ marginLeft : { check : "Number", apply : "_applyMarginLeft", nullable : true, themeable : true }, /** Padding of the widget (top) */ paddingTop : { check : "Number", apply : "_applyPaddingTop", nullable : true, themeable : true }, /** Padding of the widget (right) */ paddingRight : { check : "Number", apply : "_applyPaddingRight", nullable : true, themeable : true }, /** Padding of the widget (bottom) */ paddingBottom : { check : "Number", apply : "_applyPaddingBottom", nullable : true, themeable : true }, /** Padding of the widget (left) */ paddingLeft : { check : "Number", apply : "_applyPaddingLeft", nullable : true, themeable : true }, /** * 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. */ left : { apply : "_applyLeft", event : "changeLeft", nullable : true, themeable : true, init : null }, /** * 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. */ right : { apply : "_applyRight", event : "changeRight", nullable : true, themeable : true, init : null }, /** * 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. */ width : { apply : "_applyWidth", event : "changeWidth", nullable : true, themeable : true, init : null }, /** * The minimum width of the box (including padding and border). * * Set this to omit the shrinking of the box width under this value. */ minWidth : { apply : "_applyMinWidth", event : "changeMinWidth", nullable : true, themeable : true, init : null }, /** * The maximum width of the box (including padding and border). * * Set this to omit the expanding of the box width above this value. */ maxWidth : { apply : "_applyMaxWidth", event : "changeMaxWidth", nullable : true, themeable : true, init : null }, /** * 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. */ top : { apply : "_applyTop", event : "changeTop", nullable : true, themeable : true, init : null }, /** * 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. */ bottom : { apply : "_applyBottom", event : "changeBottom", nullable : true, themeable : true, init : null }, /** * 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. */ height : { apply : "_applyHeight", event : "changeHeight", nullable : true, themeable : true, init : null }, /** * The minimum height of the box (including padding and border). * * Set this to omit the shrinking of the box height under this value. */ minHeight : { apply : "_applyMinHeight", event : "changeMinHeight", nullable : true, themeable : true, init : null }, /** * The maximum height of the box (including padding and border). * * Set this to omit the expanding of the box height above this value. */ maxHeight : { apply : "_applyMaxHeight", event : "changeMaxHeight", nullable : true, themeable : true, init : null }, location : { group : [ "left", "top" ], themeable : true }, dimension : { group : [ "width", "height" ], themeable : true }, space : { group : [ "left", "width", "top", "height" ], themeable : true }, edge : { group : [ "top", "right", "bottom", "left" ], themeable : true, mode : "shorthand" }, padding : { group : [ "paddingTop", "paddingRight", "paddingBottom", "paddingLeft" ], mode : "shorthand", themeable : true }, /** * The 'margin' property is a shorthand property for setting 'marginTop', * 'marginRight', 'marginBottom' and 'marginLeft' at the same time. * * If four length values are specified they apply to top, right, bottom and * left respectively. If there is only one value, it applies to all sides, * if there are two or three, the missing values are taken from the opposite side. */ margin : { group : [ "marginTop", "marginRight", "marginBottom", "marginLeft" ], mode : "shorthand", themeable : true }, heights : { group : [ "minHeight", "height", "maxHeight" ], themeable : true }, widths : { group : [ "minWidth", "width", "maxWidth" ], themeable : true }, /** * The 'align' property is a shorthand property for setting 'horizontalAlign', * and 'verticalAlign' at the same time. */ align : { group : [ "horizontalAlign", "verticalAlign" ], themeable : true }, clipLocation : { group : [ "clipLeft", "clipTop" ] }, clipDimension : { group : [ "clipWidth", "clipHeight" ] }, clip : { group : [ "clipLeft", "clipTop", "clipWidth", "clipHeight" ] }, innerWidth : { _cached : true, defaultValue : null }, innerHeight : { _cached : true, defaultValue : null }, boxWidth : { _cached : true, defaultValue : null }, boxHeight : { _cached : true, defaultValue : null }, outerWidth : { _cached : true, defaultValue : null }, outerHeight : { _cached : true, defaultValue : null }, frameWidth : { _cached : true, defaultValue : null, addToQueueRuntime : true }, frameHeight : { _cached : true, defaultValue : null, addToQueueRuntime : true }, preferredInnerWidth : { _cached : true, defaultValue : null, addToQueueRuntime : true }, preferredInnerHeight : { _cached : true, defaultValue : null, addToQueueRuntime : true }, preferredBoxWidth : { _cached : true, defaultValue : null }, preferredBoxHeight : { _cached : true, defaultValue : null }, hasPercentX : { _cached : true, defaultValue : false }, hasPercentY : { _cached : true, defaultValue : false }, hasAutoX : { _cached : true, defaultValue : false }, hasAutoY : { _cached : true, defaultValue : false }, hasFlexX : { _cached : true, defaultValue : false }, hasFlexY : { _cached : true, defaultValue : false } }, /* ***************************************************************************** MEMBERS ***************************************************************************** */ members : { _computedLeftValue : null, _computedLeftParsed : null, _computedLeftType : null, _computedLeftTypeNull : true, _computedLeftTypePixel : false, _computedLeftTypePercent : false, _computedLeftTypeAuto : false, _computedLeftTypeFlex : false, _computedRightValue : null, _computedRightParsed : null, _computedRightType : null, _computedRightTypeNull : true, _computedRightTypePixel : false, _computedRightTypePercent : false, _computedRightTypeAuto : false, _computedRightTypeFlex : false, _computedTopValue : null, _computedTopParsed : null, _computedTopType : null, _computedTopTypeNull : true, _computedTopTypePixel : false, _computedTopTypePercent : false, _computedTopTypeAuto : false, _computedTopTypeFlex : false, _computedBottomValue : null, _computedBottomParsed : null, _computedBottomType : null, _computedBottomTypeNull : true, _computedBottomTypePixel : false, _computedBottomTypePercent : false, _computedBottomTypeAuto : false, _computedBottomTypeFlex : false, _computedWidthValue : null, _computedWidthParsed : null, _computedWidthType : null, _computedWidthTypeNull : true, _computedWidthTypePixel : false, _computedWidthTypePercent : false, _computedWidthTypeAuto : false, _computedWidthTypeFlex : false, _computedMinWidthValue : null, _computedMinWidthParsed : null, _computedMinWidthType : null, _computedMinWidthTypeNull : true, _computedMinWidthTypePixel : false, _computedMinWidthTypePercent : false, _computedMinWidthTypeAuto : false, _computedMinWidthTypeFlex : false, _computedMaxWidthValue : null, _computedMaxWidthParsed : null, _computedMaxWidthType : null, _computedMaxWidthTypeNull : true, _computedMaxWidthTypePixel : false, _computedMaxWidthTypePercent : false, _computedMaxWidthTypeAuto : false, _computedMaxWidthTypeFlex : false, _computedHeightValue : null, _computedHeightParsed : null, _computedHeightType : null, _computedHeightTypeNull : true, _computedHeightTypePixel : false, _computedHeightTypePercent : false, _computedHeightTypeAuto : false, _computedHeightTypeFlex : false, _computedMinHeightValue : null, _computedMinHeightParsed : null, _computedMinHeightType : null, _computedMinHeightTypeNull : true, _computedMinHeightTypePixel : false, _computedMinHeightTypePercent : false, _computedMinHeightTypeAuto : false, _computedMinHeightTypeFlex : false, _computedMaxHeightValue : null, _computedMaxHeightParsed : null, _computedMaxHeightType : null, _computedMaxHeightTypeNull : true, _computedMaxHeightTypePixel : false, _computedMaxHeightTypePercent : false, _computedMaxHeightTypeAuto : false, _computedMaxHeightTypeFlex : false, _customVariant : null, /////////////// // apply layout _applyLeft : function(value) { this._unitDetectionPixelPercent("left", value); this.addToQueue("left"); }, _applyRight : function(value) { this._unitDetectionPixelPercent("right", value); this.addToQueue("right"); }, _applyTop : function(value) { this._unitDetectionPixelPercent("top", value); this.addToQueue("top"); }, _applyBottom : function(value) { this._unitDetectionPixelPercent("bottom", value); this.addToQueue("bottom"); }, _applyWidth : function(value) { this._unitDetectionPixelPercentAutoFlex("width", value); this.addToQueue("width"); }, _applyMinWidth : function(value) { this._unitDetectionPixelPercentAuto("minWidth", value); this.addToQueue("minWidth"); }, _applyMaxWidth : function(value) { this._unitDetectionPixelPercentAuto("maxWidth", value); this.addToQueue("maxWidth"); }, _applyHeight : function(value) { this._unitDetectionPixelPercentAutoFlex("height", value); this.addToQueue("height"); }, _applyMinHeight : function(value) { this._unitDetectionPixelPercentAuto("minHeight", value); this.addToQueue("minHeight"); }, _applyMaxHeight : function(value) { this._unitDetectionPixelPercentAuto("maxHeight", value); this.addToQueue("maxHeight"); }, //////////////////// // CHILDREN HANDLING // NOTE: Implemented in Parent.js getChildren : rwt.util.Functions.returnNull, getChildrenLength : rwt.util.Functions.returnZero, hasChildren : rwt.util.Functions.returnFalse, isEmpty : rwt.util.Functions.returnTrue, indexOf : function() { return -1; }, contains : rwt.util.Functions.returnFalse, getVisibleChildren : rwt.util.Functions.returnNull, getVisibleChildrenLength : rwt.util.Functions.returnZero, hasVisibleChildren : rwt.util.Functions.returnFalse, isVisibleEmpty : rwt.util.Functions.returnTrue, ///////////////// // CORE MODIFIER _hasParent : false, _isDisplayable : false, isDisplayable : function() { return this._isDisplayable; }, _checkParent : function(value) { if (this.contains(value)) { throw new Error("Could not insert myself into a child " + value + "!"); } return value; }, _applyParent : function(value, old) { if (old) { var vOldIndex = old.getChildren().indexOf(this); // Reset cached dimension and location values this._computedWidthValue = null; this._computedMinWidthValue = null; this._computedMaxWidthValue = null; this._computedLeftValue = null; this._computedRightValue = null; this._computedHeightValue = null; this._computedMinHeightValue = null; this._computedMaxHeightValue = null; this._computedTopValue = null; this._computedBottomValue = null; this._cachedBoxWidth = null; this._cachedInnerWidth = null; this._cachedOuterWidth = null; this._cachedBoxHeight = null; this._cachedInnerHeight = null; this._cachedOuterHeight = null; // Finally remove from children array rwt.util.Arrays.removeAt(old.getChildren(), vOldIndex); // Invalidate visible children cache old._invalidateVisibleChildren(); // Remove child from old parent's children queue old._removeChildFromChildrenQueue(this); // The layouter adds some layout jobs old.getLayoutImpl().updateChildrenOnRemoveChild(this, vOldIndex); // Inform job queue old.addToJobQueue("removeChild"); // Invalidate inner preferred dimensions old._invalidatePreferredInnerDimensions(); // Store old parent (needed later by _handleDisplayable) this._oldParent = old; } if (value) { this._hasParent = true; if (typeof this._insertIndex == "number") { rwt.util.Arrays.insertAt(value.getChildren(), this, this._insertIndex); delete this._insertIndex; } else { value.getChildren().push(this); } } else { this._hasParent = false; } rwt.qx.Property.refresh(this); return this._handleDisplayable("parent"); }, _applyDisplay : function() { return this._handleDisplayable("display"); }, ////////////////////// // DISPLAYBLE HANDLING _handleDisplayable : function( vHint ) { var vDisplayable = this._computeDisplayable(); if( this._isDisplayable == vDisplayable && !( vDisplayable && vHint == "parent" ) ) { return true; } this._isDisplayable = vDisplayable; var vParent = this.getParent(); 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 elem = this.getElement(); if( elem ) { if( this.getVisibility() ) { this._beforeDisappear(); } try { this._oldParent._getTargetNode().removeChild( elem ); } catch( ex ) { // ignore exception } this._afterRemoveDom(); if ( this.getVisibility() ) { this._afterDisappear(); } } delete this._oldParent; } // old parent end if( vDisplayable ) { // The layouter added some layout jobs if( vParent._initialLayoutDone ) { var index = vParent.getChildren().indexOf( this ); vParent.getLayoutImpl().updateChildrenOnAddChild( this, index ); vParent.addToJobQueue( "addChild" ); } // Add to parents children queue // (indirectly with a new layout request) this.addToLayoutChanges( "initial" ); // Add to custom queues this.addToCustomQueues( vHint ); if( this.getVisibility() ) { this._beforeAppear(); } if( !this._isCreated ) { rwt.widgets.base.Widget.addToGlobalElementQueue(this); } rwt.widgets.base.Widget.addToGlobalStateQueue( this ); if(!rwt.util.Objects.isEmpty(this._jobQueue ) ) { rwt.widgets.base.Widget.addToGlobalJobQueue( this ); } if( !rwt.util.Objects.isEmpty( this._childrenQueue ) ) { rwt.widgets.base.Widget.addToGlobalLayoutQueue( this ); } // displayable end } else { rwt.widgets.base.Widget.removeFromGlobalElementQueue( this ); rwt.widgets.base.Widget.removeFromGlobalStateQueue( this ); rwt.widgets.base.Widget.removeFromGlobalJobQueue( this ); rwt.widgets.base.Widget.removeFromGlobalLayoutQueue( this ); 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(); } if( vParent._initialLayoutDone && this._initialLayoutDone ) { var index = vParent.getChildren().indexOf( this ); vParent.getLayoutImpl().updateChildrenOnRemoveChild( this, index ); vParent.addToJobQueue( "removeChild" ); var parentNode = this.getElement().parentNode; if( parentNode ){ parentNode.removeChild( this.getElement() ); this._afterRemoveDom(); } } vParent._removeChildFromChildrenQueue( this ); if( this.getVisibility() ) { this._afterDisappear(); } } } // not displayable end this._handleDisplayableCustom( vDisplayable, vParent, vHint ); return true; }, addToCustomQueues : rwt.util.Functions.returnTrue, removeFromCustomQueues : rwt.util.Functions.returnTrue, _handleDisplayableCustom : rwt.util.Functions.returnTrue, _computeDisplayable : function() { return this.getDisplay() && this.getParent() && this.getParent()._isDisplayable ? true : false; }, _beforeAppear : function() { this.dispatchSimpleEvent( "beforeAppear" ); }, _afterAppear : function() { this._isSeeable = true; this.dispatchSimpleEvent( "appear" ); }, _beforeDisappear : function() { // Remove any hover/pressed styles this.removeState("over"); this.removeState("pressed"); this.removeState("abandoned"); this.dispatchSimpleEvent( "beforeDisappear" ); }, _afterDisappear : function() { this._isSeeable = false; this.dispatchSimpleEvent("disappear"); }, _isSeeable : false, _isInDom : false, /** * If the widget is currently seeable which means that it: * * * has a also seeable parent * * visibility is true * * display is true * * @type member * @return {boolean} TODOC */ isSeeable : function() { return this._isSeeable; }, isInDom : function() { return this._isInDom; }, isAppearRelevant : function() { return this.getVisibility() && this._isDisplayable; }, _afterInsertDom : function() { this._isInDom = true; this.dispatchSimpleEvent( "insertDom" ); }, _afterRemoveDom : function() { this._isInDom = false; }, ////////////////////// // VISIBILITY HANDLING _applyVisibility : function(value) { if (value) { if ( this._isDisplayable && ( this._isCreated || this._isInGlobalElementQueue ) ) { this._beforeAppear(); } this.removeStyleProperty("display"); if ( this._isDisplayable && this._isCreated ) { this._afterAppear(); } } else { if ( this._isDisplayable && this._isCreated ) { this._beforeDisappear(); } this.setStyleProperty("display", "none"); if ( this._isDisplayable && this._isCreated ) { this._afterDisappear(); } } }, show : function() { this.setVisibility(true); this.setDisplay(true); }, hide : function() { this.setVisibility(false); }, destroy : function () { if( this.getParent() === null || !this.getParent()._isInGlobalDisposeQueue ) { if( this.dispatchSimpleEvent( "destroy" ) ) { this._fireBeforeDispose(); this.setParent( null ); rwt.widgets.base.Widget.addToGlobalDisposeQueue( this ); } } }, _markInDispose : function() { this._isInGlobalDisposeQueue = true; }, _fireBeforeDispose : function() { this.dispatchSimpleEvent( "beforeDispose" ); }, /////////////////////// // DOM ELEMENT HANDLING _isCreated : false, _element : null, _targetNode : null, _style : null, _innerStyle : null, _getTargetNode : function() { return this._targetNode || this._element; }, addToDocument : function() { rwt.widgets.base.ClientDocument.getInstance().add(this); }, enableEnhancedBorder : function() { this._targetNodeEnabled = true; if( this._element ) { this.prepareEnhancedBorder(); } }, /** * Check if the element is already available. */ isCreated : function() { return this._isCreated; }, _createElementImpl : function() { this.setElement( document.createElement( "div" ) ); }, _applyElement : function(value, old) { this._isCreated = value != null; if (old) { // reset reference to widget instance old.rwtWidget = null; } if (value) { // add reference to widget instance value.rwtWidget = this; // make absolute value.style.position = "absolute"; // link element and style reference this._element = value; this._style = value.style; if( this._targetNodeEnabled ) { this.prepareEnhancedBorder( true ); } this.initBackgroundColor(); this._applyStyleProperties(value); this._applyHtmlProperties(value); this._applyHtmlAttributes(value); this._applyElementData(value); // send out create event this.dispatchSimpleEvent( "create" ); // add created instances to state queue this.addToStateQueue(); } else { this._element = this._style = null; } }, //////////// // JOB QUEUE addToJobQueue : function(p){ if (this._hasParent) { rwt.widgets.base.Widget.addToGlobalJobQueue(this); } if (!this._jobQueue) { this._jobQueue = {}; } this._jobQueue[p] = true; return true; }, _flushJobQueue : function() { // 1. Pre checks var vQueue = this._jobQueue; var vParent = this.getParent(); if (!vParent || rwt.util.Objects.isEmpty(vQueue)) { return; } var vLayoutImpl = this instanceof rwt.widgets.base.Parent ? this.getLayoutImpl() : null; if (vLayoutImpl) { vLayoutImpl.updateSelfOnJobQueueFlush(vQueue); } // 2. Recompute dimensions 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; } // 3. Signals to parent widgets 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(); } // 4. Add layout jobs // add to layout queue vParent._addChildToChildrenQueue(this); // convert jobs to layout jobs for (var i in vQueue) { this._layoutChanges[i] = true; } // 5. Signals to children // inform children about padding change if (this instanceof rwt.widgets.base.Parent && (vQueue.paddingLeft || vQueue.paddingRight || vQueue.paddingTop || vQueue.paddingBottom)) { var ch = this.getChildren(), chl = ch.length; if (vQueue.paddingLeft) { for (var i=0; i




© 2015 - 2025 Weber Informatics LLC | Privacy Policy