cursor on images with scale true

classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

cursor on images with scale true

kreimer
Hi,

I discover that giving true to the scale property of an qx.ui.basic.Image, then the cursor property seems to be ignored.

Here, the playground link:

http://tinyurl.com/znvwv86

Cheers!
Reply | Threaded
Open this post in threaded view
|

Re: cursor on images with scale true

Peter Schneider
 > Hi,
 >
 > I discover that giving true to the scale property of an qx.ui.basic.Image,
 > then the cursor property seems to be ignored.
 >
 > Here, the playground link:
 >
 > http://tinyurl.com/znvwv86

...can confirm this!

* Setting the 'scale' property, "resets" the cursor[*]...
* Clearing the 'scale' property, "enables" the cursor again ;)

See: http://tinyurl.com/z5s272n



[*]...and other styles as well, I think

> Cheers!
>
>
> --
> View this message in context: http://qooxdoo.678.n2.nabble.com/cursor-on-images-with-scale-true-tp7588002.html
> Sent from the qooxdoo mailing list archive at Nabble.com.

--

** Unsere Veranstaltungen 2016 - Termine vormerken!
Logimat, Stuttgart in Halle 7, Stand A05 8.-10.3.2016
T-Matik, Greven 10.05.2016
InnoMATIK 2016, 4. Innovationsforum Telematik 18.-19.05.2016
 >> Um Anmeldung wird gebeten: http://tis-innomatik.de/
BWVL-Jahrestagung im Oktober 2016

** Kennen Sie schon unseren Blog?
telematics-magazine.com

** Interesse an unseren Unternehmensneuigkeiten? >> Newsletteranmeldung:
http://www.tis-gmbh.de/de/newsletter/anmeldung 


------------------------------------------------------------------------------
Site24x7 APM Insight: Get Deep Visibility into Application Performance
APM + Mobile APM + RUM: Monitor 3 App instances at just $35/Month
Monitor end-to-end web transactions and take corrective actions now
Troubleshoot faster and improve end-user experience. Signup Now!
http://pubads.g.doubleclick.net/gampad/clk?id=272487151&iu=/4140
_______________________________________________
qooxdoo-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/qooxdoo-devel
Reply | Threaded
Open this post in threaded view
|

Re: cursor on images with scale true

kreimer
Yes, indeed... e.g backgroundColor is also affected.

http://tinyurl.com/jstq429

trying to hack the qx.ui.basic.Image to solve this... but I don't fully understand what _styleSource does...
Reply | Threaded
Open this post in threaded view
|

Re: cursor on images with scale true

kreimer
Hi!

First, I want to apologise for having pasted all this code in this post, but tinyurl said "414 Request-URI Too Large"

In order to hack a bit the qx.ui.basic.Image code.. I had to copy the source in the playgground into a new class "kreimer.MyImage2"

inserting  a few lines in the __checkForContentElementReplacement private method:
          // kreimer
          var currentStyles = currentContentElement.getAllStyles();
          this.info("currentStyles" + currentStyles);
          for(var prop in currentStyles) {
              styles[prop] = currentStyles[prop];
          }
          //kreimer

I don't know for sure if its the best solution, it's not fully tested, but it seems to solve the issue. Can somebody try this? Thanks everybody in the community!

Here, the code to paste into the playground:

qx.Class.define("kreimer.MyImage2", {
 extend : qx.ui.core.Widget,



  /*
  *****************************************************************************
     CONSTRUCTOR
  *****************************************************************************
  */

  /**
   * @param source {String?null} The URL of the image to display.
   */
  construct : function(source)
  {
    this.__contentElements = {};

    this.base(arguments);

    if (source) {
      this.setSource(source);
    }
  },




  /*
  *****************************************************************************
     PROPERTIES
  *****************************************************************************
  */

  properties :
  {
    /** The URL of the image. Setting it will possibly abort loading of current image. */
    source :
    {
      check : "String",
      init : null,
      nullable : true,
      event : "changeSource",
      apply : "_applySource",
      themeable : true
    },


    /**
     * Whether the image should be scaled to the given dimensions
     *
     * This is disabled by default because it prevents the usage
     * of image clipping when enabled.
     */
    scale :
    {
      check : "Boolean",
      init : false,
      themeable : true,
      apply : "_applyScale"
    },


    // overridden
    appearance :
    {
      refine : true,
      init : "image"
    },


    // overridden
    allowShrinkX :
    {
      refine : true,
      init : false
    },


    // overridden
    allowShrinkY :
    {
      refine : true,
      init : false
    },


    // overridden
    allowGrowX :
    {
      refine : true,
      init : false
    },


    // overridden
    allowGrowY :
    {
      refine : true,
      init : false
    }
  },


  /*
  *****************************************************************************
     EVENTS
  *****************************************************************************
  */

  events :
  {
    /**
     * Fired if the image source can not be loaded. This event can only be
     * fired for the first loading of an unmanaged resource (external image).
     */
    loadingFailed : "qx.event.type.Event",


    /**
     * Fired if the image has been loaded. This is even true for managed
     * resources (images known by generator).
     */
    loaded : "qx.event.type.Event",


    /** Fired when the pending request has been aborted. */
    aborted : "qx.event.type.Event"
  },


  statics:
  {
    PLACEHOLDER_IMAGE: "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"
  },

  /*
  *****************************************************************************
     MEMBERS
  *****************************************************************************
  */

  members :
  {
    __width : null,
    __height : null,
    __mode : null,
    __contentElements : null,
    __currentContentElement : null,
    __wrapper : null,
    __requestId : 0,


    //overridden
    _onChangeTheme : function() {
      this.base(arguments);
      // restyle source (theme change might have changed the resolved url)
      this._styleSource();
    },

    /*
    ---------------------------------------------------------------------------
      WIDGET API
    ---------------------------------------------------------------------------
    */

    // overridden
    getContentElement : function() {
      return this.__getSuitableContentElement();
    },


    // overridden
    _createContentElement : function() {
      return this.__getSuitableContentElement();
    },


    // overridden
    _getContentHint : function()
    {
      return {
        width : this.__width || 0,
        height : this.__height || 0
      };
    },

    // overridden
    _applyDecorator : function(value, old) {
      this.base(arguments, value, old);

      var source = this.getSource();
      source = qx.util.AliasManager.getInstance().resolve(source);
      var el = this.getContentElement();
      if (this.__wrapper) {
        el = el.getChild(0);
      }
      this.__setSource(el, source);
    },


    // overridden
    _applyPadding : function(value, old, name)
    {
      this.base(arguments, value, old, name);

      var element = this.getContentElement();
      if (this.__wrapper) {
        element.getChild(0).setStyles({
          top: this.getPaddingTop() || 0,
          left: this.getPaddingLeft() || 0
        });
      } else {
        element.setPadding(
          this.getPaddingLeft() || 0, this.getPaddingTop() || 0
        );
      }

    },

    renderLayout : function(left, top, width, height) {
      this.base(arguments, left, top, width, height);

      var element = this.getContentElement();
      if (this.__wrapper) {
        element.getChild(0).setStyles({
          width: width - (this.getPaddingLeft() || 0) - (this.getPaddingRight() || 0),
          height: height - (this.getPaddingTop() || 0) - (this.getPaddingBottom() || 0),
          top: this.getPaddingTop() || 0,
          left: this.getPaddingLeft() || 0
        });
      }
    },




    /*
    ---------------------------------------------------------------------------
      IMAGE API
    ---------------------------------------------------------------------------
    */

    // property apply, overridden
    _applyEnabled : function(value, old)
    {
      this.base(arguments, value, old);

      if (this.getSource()) {
        this._styleSource();
      }
    },


    // property apply
    _applySource : function(value, old)
    {
      // abort loading current image
      if (old) {
        if (qx.io.ImageLoader.isLoading(old)) {
          qx.io.ImageLoader.abort(old);
        }
      }

      this._styleSource();
    },


    // property apply
    _applyScale : function(value) {
      this._styleSource();
    },


    /**
     * Remembers the mode to keep track which contentElement is currently in use.
     * @param mode {String} internal mode (alphaScaled|scaled|nonScaled)
     */
    __setMode : function(mode) {
      this.__mode = mode;
    },


    /**
     * Returns the current mode if set. Otherwise checks the current source and
     * the current scaling to determine the current mode.
     *
     * @return {String} current internal mode
     */
    __getMode : function()
    {
      if (this.__mode == null)
      {
        var source = this.getSource();
        var isPng = false;
        if (source != null) {
          isPng = qx.lang.String.endsWith(source, ".png");
        }

        if (this.getScale() && isPng && qx.core.Environment.get("css.alphaimageloaderneeded")) {
          this.__mode = "alphaScaled";
        } else if (this.getScale()) {
          this.__mode = "scaled";
        } else {
          this.__mode = "nonScaled";
        }
      }

      return this.__mode;
    },


    /**
     * Creates a contentElement suitable for the current mode
     *
     * @param mode {String} internal mode
     * @return {qx.html.Image} suitable image content element
     */
    __createSuitableContentElement : function(mode)
    {
      var scale;
      var tagName;
      if (mode == "alphaScaled")
      {
        scale = true;
        tagName = "div";
      }
      else if (mode == "nonScaled")
      {
        scale = false;
        tagName = "div";
      }
      else
      {
        scale = true;
        tagName = "img";
      }

      var element = new qx.html.Image(tagName);
      element.setAttribute("$$widget", this.toHashCode());
      element.setScale(scale);
      element.setStyles({
        "overflowX": "hidden",
        "overflowY": "hidden",
        "boxSizing": "border-box"
      });

      if (qx.core.Environment.get("css.alphaimageloaderneeded")) {
        var wrapper = this.__wrapper = new qx.html.Element("div");
        wrapper.setAttribute("$$widget", this.toHashCode());
        wrapper.setStyle("position", "absolute");
        wrapper.add(element);
        return wrapper;
      }

      return element;
    },


    /**
     * Returns a contentElement suitable for the current mode
     *
     * @return {qx.html.Image} suitable image contentElement
     */
    __getSuitableContentElement : function()
    {
      if (this.$$disposed) {
        return null;
      }

      var mode = this.__getMode();

      if (this.__contentElements[mode] == null) {
        this.__contentElements[mode] = this.__createSuitableContentElement(mode);
      }

      var element = this.__contentElements[mode];

      if (!this.__currentContentElement) {
        this.__currentContentElement = element;
      }

      return element;
    },


    /**
     * Applies the source to the clipped image instance or preload
     * an image to detect sizes and apply it afterwards.
     *
     */
    _styleSource : function()
    {
      var AliasManager = qx.util.AliasManager.getInstance();
      var ResourceManager = qx.util.ResourceManager.getInstance();

      var source = AliasManager.resolve(this.getSource());

      var element = this.getContentElement();
      if (this.__wrapper) {
        element = element.getChild(0);
      }

      if (!source)
      {
        element.resetSource();
        return;
      }

      this.__checkForContentElementSwitch(source);

      if ((qx.core.Environment.get("engine.name") == "mshtml") &&
        (parseInt(qx.core.Environment.get("engine.version"), 10) < 9 ||
         qx.core.Environment.get("browser.documentmode") < 9))
      {
        var repeat = this.getScale() ? "scale" : "no-repeat";
        element.tagNameHint = qx.bom.element.Decoration.getTagName(repeat, source);
      }

      var contentEl = this.__getContentElement();

      // Detect if the image registry knows this image
      if (qx.util.ResourceManager.getInstance().has(source)) {
        var highResolutionSource = this._findHighResolutionSource(source);
        if (highResolutionSource) {
          var imageWidth = ResourceManager.getImageHeight(source);
          var imageHeight = ResourceManager.getImageWidth(source);
          this.setWidth(imageWidth);
          this.setHeight(imageHeight);
         
          // set backgroud size on current element (div or img)
          var backgroundSize = imageWidth + "px, " + imageHeight + "px";
          this.__currentContentElement.setStyle("background-size", backgroundSize);

          this.setSource(highResolutionSource);
          source = highResolutionSource;
        }
        this.__setManagedImage(contentEl, source);
        this.__fireLoadEvent();
      } else if (qx.io.ImageLoader.isLoaded(source)) {
        this.__setUnmanagedImage(contentEl, source);
        this.__fireLoadEvent();
      } else {
        this.__loadUnmanagedImage(contentEl, source);
      }
    },


    /**
     * Helper function, which fires <code>loaded</code> event asynchronously.
     * It emulates native <code>loaded</code> event of an image object. This
     * helper will be called, if you try to load a managed image or an
     * previously loaded unmanaged image.
     */
    __fireLoadEvent : function()
    {
      this.__requestId++;
      qx.bom.AnimationFrame.request(function(rId){
        // prevent firing of the event if source changed in the meantime
        if (rId === this.__requestId) {
          this.fireEvent("loaded");
        } else {
          this.fireEvent("aborted");
        }
      }.bind(this, this.__requestId));
    },


    /**
     * Returns the content element.
     * @return {qx.html.Image} content element
     */
    __getContentElement : function()
    {
      var contentEl = this.__currentContentElement;
      if (this.__wrapper) {
        contentEl = contentEl.getChild(0);
      }

      return contentEl;
    },


    /**
     * Checks if the current content element is capable to display the image
     * with the current settings (scaling, alpha PNG)
     *
     * @param source {String} source of the image
     */
    __checkForContentElementSwitch : qx.core.Environment.select("engine.name",
    {
      "mshtml" : function(source)
      {
        var alphaImageLoader = qx.core.Environment.get("css.alphaimageloaderneeded");
        var isPng = qx.lang.String.endsWith(source, ".png");

        if (alphaImageLoader && isPng)
        {
          if (this.getScale() && this.__getMode() != "alphaScaled") {
            this.__setMode("alphaScaled");
          } else if (!this.getScale() && this.__getMode() != "nonScaled") {
            this.__setMode("nonScaled");
          }
        }
        else
        {
          if (this.getScale() && this.__getMode() != "scaled") {
            this.__setMode("scaled");
          } else if (!this.getScale() && this.__getMode() != "nonScaled") {
            this.__setMode("nonScaled");
          }
        }

        this.__checkForContentElementReplacement(this.__getSuitableContentElement());
      },

      "default" : function(source)
      {
        if (this.getScale() && this.__getMode() != "scaled") {
          this.__setMode("scaled");
        } else if (!this.getScale() && this.__getMode("nonScaled")) {
          this.__setMode("nonScaled");
        }

        this.__checkForContentElementReplacement(this.__getSuitableContentElement());
      }
    }),


    /**
     * Checks the current child and replaces it if necessary
     *
     * @param elementToAdd {qx.html.Image} content element to add
     */
    __checkForContentElementReplacement : function(elementToAdd)
    {
     
      var currentContentElement = this.__currentContentElement;

      if (currentContentElement != elementToAdd)
      {
        if (currentContentElement != null)
        {
          var pixel = "px";
          var styles = {};
         
          // kreimer
          var currentStyles = currentContentElement.getAllStyles();
          this.info("currentStyles" + currentStyles);
          for(var prop in currentStyles) {
              styles[prop] = currentStyles[prop];
          }
          //kreimer
         
          // Copy dimension and location of the current content element
          var bounds = this.getBounds();
          if (bounds != null)
          {
            styles.width = bounds.width + pixel;
            styles.height = bounds.height + pixel;
          }

          var insets = this.getInsets();
          styles.left = parseInt(currentContentElement.getStyle("left") || insets.left) + pixel;
          styles.top = parseInt(currentContentElement.getStyle("top") || insets.top) + pixel;

          styles.zIndex = 10;

          var newEl = this.__wrapper ? elementToAdd.getChild(0) : elementToAdd;
          newEl.setStyles(styles, true);
          newEl.setSelectable(this.getSelectable());

          if (!currentContentElement.isVisible()) {
            elementToAdd.hide();
          }

          if (!currentContentElement.isIncluded()) {
            elementToAdd.exclude();
          }

          var container = currentContentElement.getParent();

          if (container) {
            var index = container.getChildren().indexOf(currentContentElement);
            container.removeAt(index);
            container.addAt(elementToAdd, index);
          }
          // force re-application of source so __setSource is called again
          var hint = newEl.getNodeName();
          newEl.setSource(null);
          var currentEl = this.__getContentElement();
          newEl.tagNameHint = hint;
          newEl.setAttribute("class", currentEl.getAttribute("class"));

          // Flush elements to make sure the DOM elements are created.
          qx.html.Element.flush();
          var currentDomEl = currentEl.getDomElement();
          var newDomEl = elementToAdd.getDomElement();

          // copy event listeners
          var listeners = currentContentElement.getListeners() || [];
          listeners.forEach(function(listenerData) {
            elementToAdd.addListener(listenerData.type, listenerData.handler, listenerData.self, listenerData.capture);
          });

          if (currentDomEl && newDomEl) {
            // Switch the DOM elements' hash codes. This is required for the event
            // layer to work [BUG #7447]
            var currentHash = currentDomEl.$$hash;
            currentDomEl.$$hash = newDomEl.$$hash;
            newDomEl.$$hash = currentHash;
          }

          this.__currentContentElement = elementToAdd;
        }
      }
    },


    /**
     * Use the ResourceManager to set a managed image
     *
     * @param el {Element} image DOM element
     * @param source {String} source path
     */
    __setManagedImage : function(el, source)
    {
      var ResourceManager = qx.util.ResourceManager.getInstance();

      // Try to find a disabled image in registry
      if (!this.getEnabled())
      {
        var disabled = source.replace(/\.([a-z]+)$/, "-disabled.$1");
        if (ResourceManager.has(disabled))
        {
          source = disabled;
          this.addState("replacement");
        }
        else
        {
          this.removeState("replacement");
        }
      }

      // Optimize case for enabled changes when no disabled image was found
      if (el.getSource() === source) {
        return;
      }

      // Apply source
      this.__setSource(el, source);

      // Compare with old sizes and relayout if necessary
      this.__updateContentHint(
        ResourceManager.getImageWidth(source),
        ResourceManager.getImageHeight(source)
      );
    },


    /**
     * Use the infos of the ImageLoader to set an unmanaged image
     *
     * @param el {Element} image DOM element
     * @param source {String} source path
     */
    __setUnmanagedImage : function(el, source)
    {
      var ImageLoader = qx.io.ImageLoader;

      // Apply source
      this.__setSource(el, source);

      // Compare with old sizes and relayout if necessary
      var width = ImageLoader.getWidth(source);
      var height = ImageLoader.getHeight(source);
      this.__updateContentHint(width, height);
    },


    /**
     * Use the ImageLoader to load an unmanaged image
     *
     * @param el {Element} image DOM element
     * @param source {String} source path
     */
    __loadUnmanagedImage : function(el, source)
    {
      var ImageLoader = qx.io.ImageLoader;

      if (qx.core.Environment.get("qx.debug"))
      {
        // loading external images via HTTP/HTTPS is a common usecase, as is
        // using data URLs.
        var sourceLC = source.toLowerCase();
        var startsWith = qx.lang.String.startsWith;
        if (!startsWith(sourceLC, "http") &&
            !startsWith(sourceLC, "data:image/"))
        {
          var self = this.self(arguments);

          if (!self.__warned) {
            self.__warned = {};
          }

          if (!self.__warned[source])
          {
            this.debug("try to load an unmanaged relative image: " + source);
            self.__warned[source] = true;
          }
        }
      }

      // only try to load the image if it not already failed
      if(!ImageLoader.isFailed(source)) {
        ImageLoader.load(source, this.__loaderCallback, this);
      } else {
        if (el != null) {
          el.resetSource();
        }
      }
    },


    /**
     * Combines the decorator's image styles with our own image to make sure
     * gradient and backgroundImage decorators work on Images.
     *
     * @param el {Element} image DOM element
     * @param source {String} source path
     */
    __setSource: function (el, source) {
      if (el.getNodeName() == "div") {

        // checks if a decorator already set.
        // In this case we have to merge background styles
        var decorator = qx.theme.manager.Decoration.getInstance().resolve(this.getDecorator());
        if (decorator) {
          var hasGradient = (decorator.getStartColor() && decorator.getEndColor());
          var hasBackground = decorator.getBackgroundImage();
          if (hasGradient || hasBackground) {
            var repeat = this.getScale() ? "scale" : "no-repeat";

            // get the style attributes for the given source
            var attr = qx.bom.element.Decoration.getAttributes(source, repeat);
            // get the background image(s) defined by the decorator
            var decoratorStyle = decorator.getStyles(true);

            var combinedStyles = {
              "backgroundImage": attr.style.backgroundImage,
              "backgroundPosition": (attr.style.backgroundPosition || "0 0"),
              "backgroundRepeat": (attr.style.backgroundRepeat || "no-repeat")
            };

            if (hasBackground) {
              combinedStyles["backgroundPosition"] += "," + decoratorStyle["background-position"] || "0 0";
              combinedStyles["backgroundRepeat"] += ", " + decorator.getBackgroundRepeat();
            }

            if (hasGradient) {
              combinedStyles["backgroundPosition"] += ", 0 0";
              combinedStyles["backgroundRepeat"] += ", no-repeat";
            }

            combinedStyles["backgroundImage"] += "," + decoratorStyle["background-image"];

            // apply combined background images
            el.setStyles(combinedStyles);

            return;
          }
        } else {
          // force re-apply to remove old decorator styles
          el.setSource(null);
        }
      }

      el.setSource(source);
    },

    /**
     * Detects whether there is a high-resolution image available.
     * A high-resolution image is assumed to have the same file name as
     * the parameter source, but with a pixelRatio identifier before the file
     * extension, like "@2x".
     * Medium Resolution: "example.png", high-resolution: "example@2x.png"
     *
     * @param lowResImgSrc {String} source of the low resolution image.
     * @return {String|Boolean} If a high-resolution image source.
     */
    _findHighResolutionSource: function(lowResImgSrc) {
      var pixelRatioCandidates = ["3", "2", "1.5"];

      // Calculate the optimal ratio, based on the rem scale factor of the application and the device pixel ratio.
      var factor = parseFloat(qx.bom.client.Device.getDevicePixelRatio().toFixed(2));
      if (factor <= 1) {
        return false;
      }

      var i = pixelRatioCandidates.length;
      while (i > 0 && factor > pixelRatioCandidates[--i]) {}

      var hiResImgSrc;
      var k;

      // Search for best img with a higher resolution.
      for (k = i; k >= 0; k--) {
        hiResImgSrc = this._getHighResolutionSource(lowResImgSrc, pixelRatioCandidates[k]);
        if (hiResImgSrc) {
          return hiResImgSrc;
        }
      }

      // Search for best img with a lower resolution.
      for (k = i + 1; k < pixelRatioCandidates.length; k++) {
        hiResImgSrc = this._getHighResolutionSource(lowResImgSrc, pixelRatioCandidates[k]);
        if (hiResImgSrc) {
          return hiResImgSrc;
        }
      }

      return null;
    },

    /**
     * Returns the source name for the high-resolution image based on the passed
     * parameters.
     * @param source {String} the source of the medium resolution image.
     * @param pixelRatio {Number} the pixel ratio of the high-resolution image.
     * @return {String} the high-resolution source name or null if no source could be found.
     */
    _getHighResolutionSource : function(source, pixelRatio) {
      var fileExtIndex = source.lastIndexOf('.');
      if (fileExtIndex > -1) {
        var pixelRatioIdentifier = "@" + pixelRatio + "x";
        var candidate = source.slice(0, fileExtIndex) + pixelRatioIdentifier + source.slice(fileExtIndex);

        if(qx.util.ResourceManager.getInstance().has(candidate)) {
          return candidate;
        }
      }
      return null;
    },

    /**
     * Event handler fired after the preloader has finished loading the icon
     *
     * @param source {String} Image source which was loaded
     * @param imageInfo {Map} Dimensions of the loaded image
     */
    __loaderCallback : function(source, imageInfo)
    {
      // Ignore the callback on already disposed images
      if (this.$$disposed === true) {
        return;
      }

      // Ignore when the source has already been modified
      if (source !== qx.util.AliasManager.getInstance().resolve(this.getSource())) {
        this.fireEvent("aborted");
        return;
      }

      /// Output a warning if the image could not loaded and quit
      if (imageInfo.failed) {
        this.warn("Image could not be loaded: " + source);
        this.fireEvent("loadingFailed");
      } else if (imageInfo.aborted) {
        this.fireEvent("aborted");
        return;
      } else {
        this.fireEvent("loaded");
      }

      // Update image
      this.__setUnmanagedImage(this.__getContentElement(), source);
    },


    /**
     * Updates the content hint when the image size has been changed
     *
     * @param width {Integer} width of the image
     * @param height {Integer} height of the image
     */
    __updateContentHint : function(width, height)
    {
      // Compare with old sizes and relayout if necessary
      if (width !== this.__width || height !== this.__height)
      {
        this.__width = width;
        this.__height = height;

        qx.ui.core.queue.Layout.add(this);
      }
    }
  },


  /*
  *****************************************************************************
     DESTRUCTOR
  *****************************************************************************
  */

  destruct : function() {
    for (var mode in this.__contentElements) {
      if (this.__contentElements.hasOwnProperty(mode)) {
        this.__contentElements[mode].setAttribute("$$widget", null, true);
      }
    }

    delete this.__currentContentElement;
    if (this.__wrapper) {
      delete this.__wrapper;
    }

    this._disposeMap("__contentElements");
  }
});




var btn = new qx.ui.form.CheckBox("Image#scale").set({ value : true});
var setSrcBtn = new qx.ui.form.Button("setGreen");
setSrcBtn.addListener("execute", function(e) {
    img.setBackgroundColor("green");
}, this);

var img = new  kreimer.MyImage2("http://support.showreelfinder.com/hc/en-us/article_attachments/201500876/reset.png").set({
    cursor : "pointer",
    backgroundColor : "orange",
    height : 64,
    width : 64,
    scale : true
});

var doc = this.getRoot();
doc.add(btn, { left: 10, top: 10 });
doc.add(setSrcBtn, { left: 150, top: 10 });
doc.add(img, { left: 10, top: 50 });
btn.bind("value", img, "scale");
Reply | Threaded
Open this post in threaded view
|

Re: cursor on images with scale true

woprandi
I can confirm this. I don't know why, but in my own app, I have not always this issue I suppose this is a bug.

2016-02-23 14:49 GMT+01:00 kreimer <[hidden email]>:
Hi!

First, I want to apologise for having pasted all this code in this post, but
tinyurl said "414 Request-URI Too Large"

In order to hack a bit the qx.ui.basic.Image code.. I had to copy the source
in the playgground into a new class "kreimer.MyImage2"

inserting  a few lines in the __checkForContentElementReplacement private
method:
          // kreimer
          var currentStyles = currentContentElement.getAllStyles();
          this.info("currentStyles" + currentStyles);
          for(var prop in currentStyles) {
              styles[prop] = currentStyles[prop];
          }
          //kreimer

I don't know for sure if its the best solution, it's not fully tested, but
it seems to solve the issue. Can somebody try this? Thanks everybody in the
community!

Here, the code to paste into the playground:

qx.Class.define("kreimer.MyImage2", {
 extend : qx.ui.core.Widget,



  /*

*****************************************************************************
     CONSTRUCTOR

*****************************************************************************
  */

  /**
   * @param source {String?null} The URL of the image to display.
   */
  construct : function(source)
  {
    this.__contentElements = {};

    this.base(arguments);

    if (source) {
      this.setSource(source);
    }
  },




  /*

*****************************************************************************
     PROPERTIES

*****************************************************************************
  */

  properties :
  {
    /** The URL of the image. Setting it will possibly abort loading of
current image. */
    source :
    {
      check : "String",
      init : null,
      nullable : true,
      event : "changeSource",
      apply : "_applySource",
      themeable : true
    },


    /**
     * Whether the image should be scaled to the given dimensions
     *
     * This is disabled by default because it prevents the usage
     * of image clipping when enabled.
     */
    scale :
    {
      check : "Boolean",
      init : false,
      themeable : true,
      apply : "_applyScale"
    },


    // overridden
    appearance :
    {
      refine : true,
      init : "image"
    },


    // overridden
    allowShrinkX :
    {
      refine : true,
      init : false
    },


    // overridden
    allowShrinkY :
    {
      refine : true,
      init : false
    },


    // overridden
    allowGrowX :
    {
      refine : true,
      init : false
    },


    // overridden
    allowGrowY :
    {
      refine : true,
      init : false
    }
  },


  /*

*****************************************************************************
     EVENTS

*****************************************************************************
  */

  events :
  {
    /**
     * Fired if the image source can not be loaded. This event can only be
     * fired for the first loading of an unmanaged resource (external
image).
     */
    loadingFailed : "qx.event.type.Event",


    /**
     * Fired if the image has been loaded. This is even true for managed
     * resources (images known by generator).
     */
    loaded : "qx.event.type.Event",


    /** Fired when the pending request has been aborted. */
    aborted : "qx.event.type.Event"
  },


  statics:
  {
    PLACEHOLDER_IMAGE:
"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"
  },

  /*

*****************************************************************************
     MEMBERS

*****************************************************************************
  */

  members :
  {
    __width : null,
    __height : null,
    __mode : null,
    __contentElements : null,
    __currentContentElement : null,
    __wrapper : null,
    __requestId : 0,


    //overridden
    _onChangeTheme : function() {
      this.base(arguments);
      // restyle source (theme change might have changed the resolved url)
      this._styleSource();
    },

    /*

---------------------------------------------------------------------------
      WIDGET API

---------------------------------------------------------------------------
    */

    // overridden
    getContentElement : function() {
      return this.__getSuitableContentElement();
    },


    // overridden
    _createContentElement : function() {
      return this.__getSuitableContentElement();
    },


    // overridden
    _getContentHint : function()
    {
      return {
        width : this.__width || 0,
        height : this.__height || 0
      };
    },

    // overridden
    _applyDecorator : function(value, old) {
      this.base(arguments, value, old);

      var source = this.getSource();
      source = qx.util.AliasManager.getInstance().resolve(source);
      var el = this.getContentElement();
      if (this.__wrapper) {
        el = el.getChild(0);
      }
      this.__setSource(el, source);
    },


    // overridden
    _applyPadding : function(value, old, name)
    {
      this.base(arguments, value, old, name);

      var element = this.getContentElement();
      if (this.__wrapper) {
        element.getChild(0).setStyles({
          top: this.getPaddingTop() || 0,
          left: this.getPaddingLeft() || 0
        });
      } else {
        element.setPadding(
          this.getPaddingLeft() || 0, this.getPaddingTop() || 0
        );
      }

    },

    renderLayout : function(left, top, width, height) {
      this.base(arguments, left, top, width, height);

      var element = this.getContentElement();
      if (this.__wrapper) {
        element.getChild(0).setStyles({
          width: width - (this.getPaddingLeft() || 0) -
(this.getPaddingRight() || 0),
          height: height - (this.getPaddingTop() || 0) -
(this.getPaddingBottom() || 0),
          top: this.getPaddingTop() || 0,
          left: this.getPaddingLeft() || 0
        });
      }
    },




    /*

---------------------------------------------------------------------------
      IMAGE API

---------------------------------------------------------------------------
    */

    // property apply, overridden
    _applyEnabled : function(value, old)
    {
      this.base(arguments, value, old);

      if (this.getSource()) {
        this._styleSource();
      }
    },


    // property apply
    _applySource : function(value, old)
    {
      // abort loading current image
      if (old) {
        if (qx.io.ImageLoader.isLoading(old)) {
          qx.io.ImageLoader.abort(old);
        }
      }

      this._styleSource();
    },


    // property apply
    _applyScale : function(value) {
      this._styleSource();
    },


    /**
     * Remembers the mode to keep track which contentElement is currently in
use.
     * @param mode {String} internal mode (alphaScaled|scaled|nonScaled)
     */
    __setMode : function(mode) {
      this.__mode = mode;
    },


    /**
     * Returns the current mode if set. Otherwise checks the current source
and
     * the current scaling to determine the current mode.
     *
     * @return {String} current internal mode
     */
    __getMode : function()
    {
      if (this.__mode == null)
      {
        var source = this.getSource();
        var isPng = false;
        if (source != null) {
          isPng = qx.lang.String.endsWith(source, ".png");
        }

        if (this.getScale() && isPng &&
qx.core.Environment.get("css.alphaimageloaderneeded")) {
          this.__mode = "alphaScaled";
        } else if (this.getScale()) {
          this.__mode = "scaled";
        } else {
          this.__mode = "nonScaled";
        }
      }

      return this.__mode;
    },


    /**
     * Creates a contentElement suitable for the current mode
     *
     * @param mode {String} internal mode
     * @return {qx.html.Image} suitable image content element
     */
    __createSuitableContentElement : function(mode)
    {
      var scale;
      var tagName;
      if (mode == "alphaScaled")
      {
        scale = true;
        tagName = "div";
      }
      else if (mode == "nonScaled")
      {
        scale = false;
        tagName = "div";
      }
      else
      {
        scale = true;
        tagName = "img";
      }

      var element = new qx.html.Image(tagName);
      element.setAttribute("$$widget", this.toHashCode());
      element.setScale(scale);
      element.setStyles({
        "overflowX": "hidden",
        "overflowY": "hidden",
        "boxSizing": "border-box"
      });

      if (qx.core.Environment.get("css.alphaimageloaderneeded")) {
        var wrapper = this.__wrapper = new qx.html.Element("div");
        wrapper.setAttribute("$$widget", this.toHashCode());
        wrapper.setStyle("position", "absolute");
        wrapper.add(element);
        return wrapper;
      }

      return element;
    },


    /**
     * Returns a contentElement suitable for the current mode
     *
     * @return {qx.html.Image} suitable image contentElement
     */
    __getSuitableContentElement : function()
    {
      if (this.$$disposed) {
        return null;
      }

      var mode = this.__getMode();

      if (this.__contentElements[mode] == null) {
        this.__contentElements[mode] =
this.__createSuitableContentElement(mode);
      }

      var element = this.__contentElements[mode];

      if (!this.__currentContentElement) {
        this.__currentContentElement = element;
      }

      return element;
    },


    /**
     * Applies the source to the clipped image instance or preload
     * an image to detect sizes and apply it afterwards.
     *
     */
    _styleSource : function()
    {
      var AliasManager = qx.util.AliasManager.getInstance();
      var ResourceManager = qx.util.ResourceManager.getInstance();

      var source = AliasManager.resolve(this.getSource());

      var element = this.getContentElement();
      if (this.__wrapper) {
        element = element.getChild(0);
      }

      if (!source)
      {
        element.resetSource();
        return;
      }

      this.__checkForContentElementSwitch(source);

      if ((qx.core.Environment.get("engine.name") == "mshtml") &&
        (parseInt(qx.core.Environment.get("engine.version"), 10) < 9 ||
         qx.core.Environment.get("browser.documentmode") < 9))
      {
        var repeat = this.getScale() ? "scale" : "no-repeat";
        element.tagNameHint = qx.bom.element.Decoration.getTagName(repeat,
source);
      }

      var contentEl = this.__getContentElement();

      // Detect if the image registry knows this image
      if (qx.util.ResourceManager.getInstance().has(source)) {
        var highResolutionSource = this._findHighResolutionSource(source);
        if (highResolutionSource) {
          var imageWidth = ResourceManager.getImageHeight(source);
          var imageHeight = ResourceManager.getImageWidth(source);
          this.setWidth(imageWidth);
          this.setHeight(imageHeight);

          // set backgroud size on current element (div or img)
          var backgroundSize = imageWidth + "px, " + imageHeight + "px";
          this.__currentContentElement.setStyle("background-size",
backgroundSize);

          this.setSource(highResolutionSource);
          source = highResolutionSource;
        }
        this.__setManagedImage(contentEl, source);
        this.__fireLoadEvent();
      } else if (qx.io.ImageLoader.isLoaded(source)) {
        this.__setUnmanagedImage(contentEl, source);
        this.__fireLoadEvent();
      } else {
        this.__loadUnmanagedImage(contentEl, source);
      }
    },


    /**
     * Helper function, which fires <code>loaded</code> event
asynchronously.
     * It emulates native <code>loaded</code> event of an image object. This
     * helper will be called, if you try to load a managed image or an
     * previously loaded unmanaged image.
     */
    __fireLoadEvent : function()
    {
      this.__requestId++;
      qx.bom.AnimationFrame.request(function(rId){
        // prevent firing of the event if source changed in the meantime
        if (rId === this.__requestId) {
          this.fireEvent("loaded");
        } else {
          this.fireEvent("aborted");
        }
      }.bind(this, this.__requestId));
    },


    /**
     * Returns the content element.
     * @return {qx.html.Image} content element
     */
    __getContentElement : function()
    {
      var contentEl = this.__currentContentElement;
      if (this.__wrapper) {
        contentEl = contentEl.getChild(0);
      }

      return contentEl;
    },


    /**
     * Checks if the current content element is capable to display the image
     * with the current settings (scaling, alpha PNG)
     *
     * @param source {String} source of the image
     */
    __checkForContentElementSwitch :
qx.core.Environment.select("engine.name",
    {
      "mshtml" : function(source)
      {
        var alphaImageLoader =
qx.core.Environment.get("css.alphaimageloaderneeded");
        var isPng = qx.lang.String.endsWith(source, ".png");

        if (alphaImageLoader && isPng)
        {
          if (this.getScale() && this.__getMode() != "alphaScaled") {
            this.__setMode("alphaScaled");
          } else if (!this.getScale() && this.__getMode() != "nonScaled") {
            this.__setMode("nonScaled");
          }
        }
        else
        {
          if (this.getScale() && this.__getMode() != "scaled") {
            this.__setMode("scaled");
          } else if (!this.getScale() && this.__getMode() != "nonScaled") {
            this.__setMode("nonScaled");
          }
        }


this.__checkForContentElementReplacement(this.__getSuitableContentElement());
      },

      "default" : function(source)
      {
        if (this.getScale() && this.__getMode() != "scaled") {
          this.__setMode("scaled");
        } else if (!this.getScale() && this.__getMode("nonScaled")) {
          this.__setMode("nonScaled");
        }


this.__checkForContentElementReplacement(this.__getSuitableContentElement());
      }
    }),


    /**
     * Checks the current child and replaces it if necessary
     *
     * @param elementToAdd {qx.html.Image} content element to add
     */
    __checkForContentElementReplacement : function(elementToAdd)
    {

      var currentContentElement = this.__currentContentElement;

      if (currentContentElement != elementToAdd)
      {
        if (currentContentElement != null)
        {
          var pixel = "px";
          var styles = {};

          // kreimer
          var currentStyles = currentContentElement.getAllStyles();
          this.info("currentStyles" + currentStyles);
          for(var prop in currentStyles) {
              styles[prop] = currentStyles[prop];
          }
          //kreimer

          // Copy dimension and location of the current content element
          var bounds = this.getBounds();
          if (bounds != null)
          {
            styles.width = bounds.width + pixel;
            styles.height = bounds.height + pixel;
          }

          var insets = this.getInsets();
          styles.left = parseInt(currentContentElement.getStyle("left") ||
insets.left) + pixel;
          styles.top = parseInt(currentContentElement.getStyle("top") ||
insets.top) + pixel;

          styles.zIndex = 10;

          var newEl = this.__wrapper ? elementToAdd.getChild(0) :
elementToAdd;
          newEl.setStyles(styles, true);
          newEl.setSelectable(this.getSelectable());

          if (!currentContentElement.isVisible()) {
            elementToAdd.hide();
          }

          if (!currentContentElement.isIncluded()) {
            elementToAdd.exclude();
          }

          var container = currentContentElement.getParent();

          if (container) {
            var index =
container.getChildren().indexOf(currentContentElement);
            container.removeAt(index);
            container.addAt(elementToAdd, index);
          }
          // force re-application of source so __setSource is called again
          var hint = newEl.getNodeName();
          newEl.setSource(null);
          var currentEl = this.__getContentElement();
          newEl.tagNameHint = hint;
          newEl.setAttribute("class", currentEl.getAttribute("class"));

          // Flush elements to make sure the DOM elements are created.
          qx.html.Element.flush();
          var currentDomEl = currentEl.getDomElement();
          var newDomEl = elementToAdd.getDomElement();

          // copy event listeners
          var listeners = currentContentElement.getListeners() || [];
          listeners.forEach(function(listenerData) {
            elementToAdd.addListener(listenerData.type,
listenerData.handler, listenerData.self, listenerData.capture);
          });

          if (currentDomEl && newDomEl) {
            // Switch the DOM elements' hash codes. This is required for the
event
            // layer to work [BUG #7447]
            var currentHash = currentDomEl.$$hash;
            currentDomEl.$$hash = newDomEl.$$hash;
            newDomEl.$$hash = currentHash;
          }

          this.__currentContentElement = elementToAdd;
        }
      }
    },


    /**
     * Use the ResourceManager to set a managed image
     *
     * @param el {Element} image DOM element
     * @param source {String} source path
     */
    __setManagedImage : function(el, source)
    {
      var ResourceManager = qx.util.ResourceManager.getInstance();

      // Try to find a disabled image in registry
      if (!this.getEnabled())
      {
        var disabled = source.replace(/\.([a-z]+)$/, "-disabled.$1");
        if (ResourceManager.has(disabled))
        {
          source = disabled;
          this.addState("replacement");
        }
        else
        {
          this.removeState("replacement");
        }
      }

      // Optimize case for enabled changes when no disabled image was found
      if (el.getSource() === source) {
        return;
      }

      // Apply source
      this.__setSource(el, source);

      // Compare with old sizes and relayout if necessary
      this.__updateContentHint(
        ResourceManager.getImageWidth(source),
        ResourceManager.getImageHeight(source)
      );
    },


    /**
     * Use the infos of the ImageLoader to set an unmanaged image
     *
     * @param el {Element} image DOM element
     * @param source {String} source path
     */
    __setUnmanagedImage : function(el, source)
    {
      var ImageLoader = qx.io.ImageLoader;

      // Apply source
      this.__setSource(el, source);

      // Compare with old sizes and relayout if necessary
      var width = ImageLoader.getWidth(source);
      var height = ImageLoader.getHeight(source);
      this.__updateContentHint(width, height);
    },


    /**
     * Use the ImageLoader to load an unmanaged image
     *
     * @param el {Element} image DOM element
     * @param source {String} source path
     */
    __loadUnmanagedImage : function(el, source)
    {
      var ImageLoader = qx.io.ImageLoader;

      if (qx.core.Environment.get("qx.debug"))
      {
        // loading external images via HTTP/HTTPS is a common usecase, as is
        // using data URLs.
        var sourceLC = source.toLowerCase();
        var startsWith = qx.lang.String.startsWith;
        if (!startsWith(sourceLC, "http") &&
            !startsWith(sourceLC, "data:image/"))
        {
          var self = this.self(arguments);

          if (!self.__warned) {
            self.__warned = {};
          }

          if (!self.__warned[source])
          {
            this.debug("try to load an unmanaged relative image: " +
source);
            self.__warned[source] = true;
          }
        }
      }

      // only try to load the image if it not already failed
      if(!ImageLoader.isFailed(source)) {
        ImageLoader.load(source, this.__loaderCallback, this);
      } else {
        if (el != null) {
          el.resetSource();
        }
      }
    },


    /**
     * Combines the decorator's image styles with our own image to make sure
     * gradient and backgroundImage decorators work on Images.
     *
     * @param el {Element} image DOM element
     * @param source {String} source path
     */
    __setSource: function (el, source) {
      if (el.getNodeName() == "div") {

        // checks if a decorator already set.
        // In this case we have to merge background styles
        var decorator =
qx.theme.manager.Decoration.getInstance().resolve(this.getDecorator());
        if (decorator) {
          var hasGradient = (decorator.getStartColor() &&
decorator.getEndColor());
          var hasBackground = decorator.getBackgroundImage();
          if (hasGradient || hasBackground) {
            var repeat = this.getScale() ? "scale" : "no-repeat";

            // get the style attributes for the given source
            var attr = qx.bom.element.Decoration.getAttributes(source,
repeat);
            // get the background image(s) defined by the decorator
            var decoratorStyle = decorator.getStyles(true);

            var combinedStyles = {
              "backgroundImage": attr.style.backgroundImage,
              "backgroundPosition": (attr.style.backgroundPosition || "0
0"),
              "backgroundRepeat": (attr.style.backgroundRepeat ||
"no-repeat")
            };

            if (hasBackground) {
              combinedStyles["backgroundPosition"] += "," +
decoratorStyle["background-position"] || "0 0";
              combinedStyles["backgroundRepeat"] += ", " +
decorator.getBackgroundRepeat();
            }

            if (hasGradient) {
              combinedStyles["backgroundPosition"] += ", 0 0";
              combinedStyles["backgroundRepeat"] += ", no-repeat";
            }

            combinedStyles["backgroundImage"] += "," +
decoratorStyle["background-image"];

            // apply combined background images
            el.setStyles(combinedStyles);

            return;
          }
        } else {
          // force re-apply to remove old decorator styles
          el.setSource(null);
        }
      }

      el.setSource(source);
    },

    /**
     * Detects whether there is a high-resolution image available.
     * A high-resolution image is assumed to have the same file name as
     * the parameter source, but with a pixelRatio identifier before the
file
     * extension, like "@2x".
     * Medium Resolution: "example.png", high-resolution: "[hidden email]"
     *
     * @param lowResImgSrc {String} source of the low resolution image.
     * @return {String|Boolean} If a high-resolution image source.
     */
    _findHighResolutionSource: function(lowResImgSrc) {
      var pixelRatioCandidates = ["3", "2", "1.5"];

      // Calculate the optimal ratio, based on the rem scale factor of the
application and the device pixel ratio.
      var factor =
parseFloat(qx.bom.client.Device.getDevicePixelRatio().toFixed(2));
      if (factor <= 1) {
        return false;
      }

      var i = pixelRatioCandidates.length;
      while (i > 0 && factor > pixelRatioCandidates[--i]) {}

      var hiResImgSrc;
      var k;

      // Search for best img with a higher resolution.
      for (k = i; k >= 0; k--) {
        hiResImgSrc = this._getHighResolutionSource(lowResImgSrc,
pixelRatioCandidates[k]);
        if (hiResImgSrc) {
          return hiResImgSrc;
        }
      }

      // Search for best img with a lower resolution.
      for (k = i + 1; k < pixelRatioCandidates.length; k++) {
        hiResImgSrc = this._getHighResolutionSource(lowResImgSrc,
pixelRatioCandidates[k]);
        if (hiResImgSrc) {
          return hiResImgSrc;
        }
      }

      return null;
    },

    /**
     * Returns the source name for the high-resolution image based on the
passed
     * parameters.
     * @param source {String} the source of the medium resolution image.
     * @param pixelRatio {Number} the pixel ratio of the high-resolution
image.
     * @return {String} the high-resolution source name or null if no source
could be found.
     */
    _getHighResolutionSource : function(source, pixelRatio) {
      var fileExtIndex = source.lastIndexOf('.');
      if (fileExtIndex > -1) {
        var pixelRatioIdentifier = "@" + pixelRatio + "x";
        var candidate = source.slice(0, fileExtIndex) + pixelRatioIdentifier
+ source.slice(fileExtIndex);

        if(qx.util.ResourceManager.getInstance().has(candidate)) {
          return candidate;
        }
      }
      return null;
    },

    /**
     * Event handler fired after the preloader has finished loading the icon
     *
     * @param source {String} Image source which was loaded
     * @param imageInfo {Map} Dimensions of the loaded image
     */
    __loaderCallback : function(source, imageInfo)
    {
      // Ignore the callback on already disposed images
      if (this.$$disposed === true) {
        return;
      }

      // Ignore when the source has already been modified
      if (source !==
qx.util.AliasManager.getInstance().resolve(this.getSource())) {
        this.fireEvent("aborted");
        return;
      }

      /// Output a warning if the image could not loaded and quit
      if (imageInfo.failed) {
        this.warn("Image could not be loaded: " + source);
        this.fireEvent("loadingFailed");
      } else if (imageInfo.aborted) {
        this.fireEvent("aborted");
        return;
      } else {
        this.fireEvent("loaded");
      }

      // Update image
      this.__setUnmanagedImage(this.__getContentElement(), source);
    },


    /**
     * Updates the content hint when the image size has been changed
     *
     * @param width {Integer} width of the image
     * @param height {Integer} height of the image
     */
    __updateContentHint : function(width, height)
    {
      // Compare with old sizes and relayout if necessary
      if (width !== this.__width || height !== this.__height)
      {
        this.__width = width;
        this.__height = height;

        qx.ui.core.queue.Layout.add(this);
      }
    }
  },


  /*

*****************************************************************************
     DESTRUCTOR

*****************************************************************************
  */

  destruct : function() {
    for (var mode in this.__contentElements) {
      if (this.__contentElements.hasOwnProperty(mode)) {
        this.__contentElements[mode].setAttribute("$$widget", null, true);
      }
    }

    delete this.__currentContentElement;
    if (this.__wrapper) {
      delete this.__wrapper;
    }

    this._disposeMap("__contentElements");
  }
});




var btn = new qx.ui.form.CheckBox("Image#scale").set({ value : true});
var setSrcBtn = new qx.ui.form.Button("setGreen");
setSrcBtn.addListener("execute", function(e) {
    img.setBackgroundColor("green");
}, this);

var img = new
kreimer.MyImage2("http://support.showreelfinder.com/hc/en-us/article_attachments/201500876/reset.png").set({
    cursor : "pointer",
    backgroundColor : "orange",
    height : 64,
    width : 64,
    scale : true
});

var doc = this.getRoot();
doc.add(btn, { left: 10, top: 10 });
doc.add(setSrcBtn, { left: 150, top: 10 });
doc.add(img, { left: 10, top: 50 });
btn.bind("value", img, "scale");




--
View this message in context: http://qooxdoo.678.n2.nabble.com/cursor-on-images-with-scale-true-tp7588002p7588101.html
Sent from the qooxdoo mailing list archive at Nabble.com.

------------------------------------------------------------------------------
Site24x7 APM Insight: Get Deep Visibility into Application Performance
APM + Mobile APM + RUM: Monitor 3 App instances at just $35/Month
Monitor end-to-end web transactions and take corrective actions now
Troubleshoot faster and improve end-user experience. Signup Now!
http://pubads.g.doubleclick.net/gampad/clk?id=272487151&iu=/4140
_______________________________________________
qooxdoo-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/qooxdoo-devel



--

------------------------------------------------------------------------------
Site24x7 APM Insight: Get Deep Visibility into Application Performance
APM + Mobile APM + RUM: Monitor 3 App instances at just $35/Month
Monitor end-to-end web transactions and take corrective actions now
Troubleshoot faster and improve end-user experience. Signup Now!
http://pubads.g.doubleclick.net/gampad/clk?id=272487151&iu=/4140
_______________________________________________
qooxdoo-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/qooxdoo-devel
Reply | Threaded
Open this post in threaded view
|

Re: cursor on images with scale true

John Spackman
In reply to this post by kreimer
Hi Bernardo

That looks like a sensible fix - please can you submit it as a pull request?

Cheers
John




On 23/02/2016, 13:49, "kreimer" <[hidden email]> wrote:

>Hi!
>
>First, I want to apologise for having pasted all this code in this post, but
>tinyurl said "414 Request-URI Too Large"
>
>In order to hack a bit the qx.ui.basic.Image code.. I had to copy the source
>in the playgground into a new class "kreimer.MyImage2"
>
>inserting  a few lines in the __checkForContentElementReplacement private
>method:
>          // kreimer
>          var currentStyles = currentContentElement.getAllStyles();
>          this.info("currentStyles" + currentStyles);
>          for(var prop in currentStyles) {
>              styles[prop] = currentStyles[prop];
>          }
>          //kreimer
>
>I don't know for sure if its the best solution, it's not fully tested, but
>it seems to solve the issue. Can somebody try this? Thanks everybody in the
>community!
>
>Here, the code to paste into the playground:
>
>qx.Class.define("kreimer.MyImage2", {
> extend : qx.ui.core.Widget,
>
>
>
>  /*
>
>*****************************************************************************
>     CONSTRUCTOR
>
>*****************************************************************************
>  */
>
>  /**
>   * @param source {String?null} The URL of the image to display.
>   */
>  construct : function(source)
>  {
>    this.__contentElements = {};
>
>    this.base(arguments);
>
>    if (source) {
>      this.setSource(source);
>    }
>  },
>
>
>
>
>  /*
>
>*****************************************************************************
>     PROPERTIES
>
>*****************************************************************************
>  */
>
>  properties :
>  {
>    /** The URL of the image. Setting it will possibly abort loading of
>current image. */
>    source :
>    {
>      check : "String",
>      init : null,
>      nullable : true,
>      event : "changeSource",
>      apply : "_applySource",
>      themeable : true
>    },
>
>
>    /**
>     * Whether the image should be scaled to the given dimensions
>     *
>     * This is disabled by default because it prevents the usage
>     * of image clipping when enabled.
>     */
>    scale :
>    {
>      check : "Boolean",
>      init : false,
>      themeable : true,
>      apply : "_applyScale"
>    },
>
>
>    // overridden
>    appearance :
>    {
>      refine : true,
>      init : "image"
>    },
>
>
>    // overridden
>    allowShrinkX :
>    {
>      refine : true,
>      init : false
>    },
>
>
>    // overridden
>    allowShrinkY :
>    {
>      refine : true,
>      init : false
>    },
>
>
>    // overridden
>    allowGrowX :
>    {
>      refine : true,
>      init : false
>    },
>
>
>    // overridden
>    allowGrowY :
>    {
>      refine : true,
>      init : false
>    }
>  },
>
>
>  /*
>
>*****************************************************************************
>     EVENTS
>
>*****************************************************************************
>  */
>
>  events :
>  {
>    /**
>     * Fired if the image source can not be loaded. This event can only be
>     * fired for the first loading of an unmanaged resource (external
>image).
>     */
>    loadingFailed : "qx.event.type.Event",
>
>
>    /**
>     * Fired if the image has been loaded. This is even true for managed
>     * resources (images known by generator).
>     */
>    loaded : "qx.event.type.Event",
>
>
>    /** Fired when the pending request has been aborted. */
>    aborted : "qx.event.type.Event"
>  },
>
>
>  statics:
>  {
>    PLACEHOLDER_IMAGE:
>"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"
>  },
>
>  /*
>
>*****************************************************************************
>     MEMBERS
>
>*****************************************************************************
>  */
>
>  members :
>  {
>    __width : null,
>    __height : null,
>    __mode : null,
>    __contentElements : null,
>    __currentContentElement : null,
>    __wrapper : null,
>    __requestId : 0,
>
>
>    //overridden
>    _onChangeTheme : function() {
>      this.base(arguments);
>      // restyle source (theme change might have changed the resolved url)
>      this._styleSource();
>    },
>
>    /*
>  
>---------------------------------------------------------------------------
>      WIDGET API
>  
>---------------------------------------------------------------------------
>    */
>
>    // overridden
>    getContentElement : function() {
>      return this.__getSuitableContentElement();
>    },
>
>
>    // overridden
>    _createContentElement : function() {
>      return this.__getSuitableContentElement();
>    },
>
>
>    // overridden
>    _getContentHint : function()
>    {
>      return {
>        width : this.__width || 0,
>        height : this.__height || 0
>      };
>    },
>
>    // overridden
>    _applyDecorator : function(value, old) {
>      this.base(arguments, value, old);
>
>      var source = this.getSource();
>      source = qx.util.AliasManager.getInstance().resolve(source);
>      var el = this.getContentElement();
>      if (this.__wrapper) {
>        el = el.getChild(0);
>      }
>      this.__setSource(el, source);
>    },
>
>
>    // overridden
>    _applyPadding : function(value, old, name)
>    {
>      this.base(arguments, value, old, name);
>
>      var element = this.getContentElement();
>      if (this.__wrapper) {
>        element.getChild(0).setStyles({
>          top: this.getPaddingTop() || 0,
>          left: this.getPaddingLeft() || 0
>        });
>      } else {
>        element.setPadding(
>          this.getPaddingLeft() || 0, this.getPaddingTop() || 0
>        );
>      }
>
>    },
>
>    renderLayout : function(left, top, width, height) {
>      this.base(arguments, left, top, width, height);
>
>      var element = this.getContentElement();
>      if (this.__wrapper) {
>        element.getChild(0).setStyles({
>          width: width - (this.getPaddingLeft() || 0) -
>(this.getPaddingRight() || 0),
>          height: height - (this.getPaddingTop() || 0) -
>(this.getPaddingBottom() || 0),
>          top: this.getPaddingTop() || 0,
>          left: this.getPaddingLeft() || 0
>        });
>      }
>    },
>
>
>
>
>    /*
>  
>---------------------------------------------------------------------------
>      IMAGE API
>  
>---------------------------------------------------------------------------
>    */
>
>    // property apply, overridden
>    _applyEnabled : function(value, old)
>    {
>      this.base(arguments, value, old);
>
>      if (this.getSource()) {
>        this._styleSource();
>      }
>    },
>
>
>    // property apply
>    _applySource : function(value, old)
>    {
>      // abort loading current image
>      if (old) {
>        if (qx.io.ImageLoader.isLoading(old)) {
>          qx.io.ImageLoader.abort(old);
>        }
>      }
>
>      this._styleSource();
>    },
>
>
>    // property apply
>    _applyScale : function(value) {
>      this._styleSource();
>    },
>
>
>    /**
>     * Remembers the mode to keep track which contentElement is currently in
>use.
>     * @param mode {String} internal mode (alphaScaled|scaled|nonScaled)
>     */
>    __setMode : function(mode) {
>      this.__mode = mode;
>    },
>
>
>    /**
>     * Returns the current mode if set. Otherwise checks the current source
>and
>     * the current scaling to determine the current mode.
>     *
>     * @return {String} current internal mode
>     */
>    __getMode : function()
>    {
>      if (this.__mode == null)
>      {
>        var source = this.getSource();
>        var isPng = false;
>        if (source != null) {
>          isPng = qx.lang.String.endsWith(source, ".png");
>        }
>
>        if (this.getScale() && isPng &&
>qx.core.Environment.get("css.alphaimageloaderneeded")) {
>          this.__mode = "alphaScaled";
>        } else if (this.getScale()) {
>          this.__mode = "scaled";
>        } else {
>          this.__mode = "nonScaled";
>        }
>      }
>
>      return this.__mode;
>    },
>
>
>    /**
>     * Creates a contentElement suitable for the current mode
>     *
>     * @param mode {String} internal mode
>     * @return {qx.html.Image} suitable image content element
>     */
>    __createSuitableContentElement : function(mode)
>    {
>      var scale;
>      var tagName;
>      if (mode == "alphaScaled")
>      {
>        scale = true;
>        tagName = "div";
>      }
>      else if (mode == "nonScaled")
>      {
>        scale = false;
>        tagName = "div";
>      }
>      else
>      {
>        scale = true;
>        tagName = "img";
>      }
>
>      var element = new qx.html.Image(tagName);
>      element.setAttribute("$$widget", this.toHashCode());
>      element.setScale(scale);
>      element.setStyles({
>        "overflowX": "hidden",
>        "overflowY": "hidden",
>        "boxSizing": "border-box"
>      });
>
>      if (qx.core.Environment.get("css.alphaimageloaderneeded")) {
>        var wrapper = this.__wrapper = new qx.html.Element("div");
>        wrapper.setAttribute("$$widget", this.toHashCode());
>        wrapper.setStyle("position", "absolute");
>        wrapper.add(element);
>        return wrapper;
>      }
>
>      return element;
>    },
>
>
>    /**
>     * Returns a contentElement suitable for the current mode
>     *
>     * @return {qx.html.Image} suitable image contentElement
>     */
>    __getSuitableContentElement : function()
>    {
>      if (this.$$disposed) {
>        return null;
>      }
>
>      var mode = this.__getMode();
>
>      if (this.__contentElements[mode] == null) {
>        this.__contentElements[mode] =
>this.__createSuitableContentElement(mode);
>      }
>
>      var element = this.__contentElements[mode];
>
>      if (!this.__currentContentElement) {
>        this.__currentContentElement = element;
>      }
>
>      return element;
>    },
>
>
>    /**
>     * Applies the source to the clipped image instance or preload
>     * an image to detect sizes and apply it afterwards.
>     *
>     */
>    _styleSource : function()
>    {
>      var AliasManager = qx.util.AliasManager.getInstance();
>      var ResourceManager = qx.util.ResourceManager.getInstance();
>
>      var source = AliasManager.resolve(this.getSource());
>
>      var element = this.getContentElement();
>      if (this.__wrapper) {
>        element = element.getChild(0);
>      }
>
>      if (!source)
>      {
>        element.resetSource();
>        return;
>      }
>
>      this.__checkForContentElementSwitch(source);
>
>      if ((qx.core.Environment.get("engine.name") == "mshtml") &&
>        (parseInt(qx.core.Environment.get("engine.version"), 10) < 9 ||
>         qx.core.Environment.get("browser.documentmode") < 9))
>      {
>        var repeat = this.getScale() ? "scale" : "no-repeat";
>        element.tagNameHint = qx.bom.element.Decoration.getTagName(repeat,
>source);
>      }
>
>      var contentEl = this.__getContentElement();
>
>      // Detect if the image registry knows this image
>      if (qx.util.ResourceManager.getInstance().has(source)) {
>        var highResolutionSource = this._findHighResolutionSource(source);
>        if (highResolutionSource) {
>          var imageWidth = ResourceManager.getImageHeight(source);
>          var imageHeight = ResourceManager.getImageWidth(source);
>          this.setWidth(imageWidth);
>          this.setHeight(imageHeight);
>          
>          // set backgroud size on current element (div or img)
>          var backgroundSize = imageWidth + "px, " + imageHeight + "px";
>          this.__currentContentElement.setStyle("background-size",
>backgroundSize);
>
>          this.setSource(highResolutionSource);
>          source = highResolutionSource;
>        }
>        this.__setManagedImage(contentEl, source);
>        this.__fireLoadEvent();
>      } else if (qx.io.ImageLoader.isLoaded(source)) {
>        this.__setUnmanagedImage(contentEl, source);
>        this.__fireLoadEvent();
>      } else {
>        this.__loadUnmanagedImage(contentEl, source);
>      }
>    },
>
>
>    /**
>     * Helper function, which fires <code>loaded</code> event
>asynchronously.
>     * It emulates native <code>loaded</code> event of an image object. This
>     * helper will be called, if you try to load a managed image or an
>     * previously loaded unmanaged image.
>     */
>    __fireLoadEvent : function()
>    {
>      this.__requestId++;
>      qx.bom.AnimationFrame.request(function(rId){
>        // prevent firing of the event if source changed in the meantime
>        if (rId === this.__requestId) {
>          this.fireEvent("loaded");
>        } else {
>          this.fireEvent("aborted");
>        }
>      }.bind(this, this.__requestId));
>    },
>
>
>    /**
>     * Returns the content element.
>     * @return {qx.html.Image} content element
>     */
>    __getContentElement : function()
>    {
>      var contentEl = this.__currentContentElement;
>      if (this.__wrapper) {
>        contentEl = contentEl.getChild(0);
>      }
>
>      return contentEl;
>    },
>
>
>    /**
>     * Checks if the current content element is capable to display the image
>     * with the current settings (scaling, alpha PNG)
>     *
>     * @param source {String} source of the image
>     */
>    __checkForContentElementSwitch :
>qx.core.Environment.select("engine.name",
>    {
>      "mshtml" : function(source)
>      {
>        var alphaImageLoader =
>qx.core.Environment.get("css.alphaimageloaderneeded");
>        var isPng = qx.lang.String.endsWith(source, ".png");
>
>        if (alphaImageLoader && isPng)
>        {
>          if (this.getScale() && this.__getMode() != "alphaScaled") {
>            this.__setMode("alphaScaled");
>          } else if (!this.getScale() && this.__getMode() != "nonScaled") {
>            this.__setMode("nonScaled");
>          }
>        }
>        else
>        {
>          if (this.getScale() && this.__getMode() != "scaled") {
>            this.__setMode("scaled");
>          } else if (!this.getScale() && this.__getMode() != "nonScaled") {
>            this.__setMode("nonScaled");
>          }
>        }
>
>      
>this.__checkForContentElementReplacement(this.__getSuitableContentElement());
>      },
>
>      "default" : function(source)
>      {
>        if (this.getScale() && this.__getMode() != "scaled") {
>          this.__setMode("scaled");
>        } else if (!this.getScale() && this.__getMode("nonScaled")) {
>          this.__setMode("nonScaled");
>        }
>
>      
>this.__checkForContentElementReplacement(this.__getSuitableContentElement());
>      }
>    }),
>
>
>    /**
>     * Checks the current child and replaces it if necessary
>     *
>     * @param elementToAdd {qx.html.Image} content element to add
>     */
>    __checkForContentElementReplacement : function(elementToAdd)
>    {
>      
>      var currentContentElement = this.__currentContentElement;
>
>      if (currentContentElement != elementToAdd)
>      {
>        if (currentContentElement != null)
>        {
>          var pixel = "px";
>          var styles = {};
>          
>          // kreimer
>          var currentStyles = currentContentElement.getAllStyles();
>          this.info("currentStyles" + currentStyles);
>          for(var prop in currentStyles) {
>              styles[prop] = currentStyles[prop];
>          }
>          //kreimer
>          
>          // Copy dimension and location of the current content element
>          var bounds = this.getBounds();
>          if (bounds != null)
>          {
>            styles.width = bounds.width + pixel;
>            styles.height = bounds.height + pixel;
>          }
>
>          var insets = this.getInsets();
>          styles.left = parseInt(currentContentElement.getStyle("left") ||
>insets.left) + pixel;
>          styles.top = parseInt(currentContentElement.getStyle("top") ||
>insets.top) + pixel;
>
>          styles.zIndex = 10;
>
>          var newEl = this.__wrapper ? elementToAdd.getChild(0) :
>elementToAdd;
>          newEl.setStyles(styles, true);
>          newEl.setSelectable(this.getSelectable());
>
>          if (!currentContentElement.isVisible()) {
>            elementToAdd.hide();
>          }
>
>          if (!currentContentElement.isIncluded()) {
>            elementToAdd.exclude();
>          }
>
>          var container = currentContentElement.getParent();
>
>          if (container) {
>            var index =
>container.getChildren().indexOf(currentContentElement);
>            container.removeAt(index);
>            container.addAt(elementToAdd, index);
>          }
>          // force re-application of source so __setSource is called again
>          var hint = newEl.getNodeName();
>          newEl.setSource(null);
>          var currentEl = this.__getContentElement();
>          newEl.tagNameHint = hint;
>          newEl.setAttribute("class", currentEl.getAttribute("class"));
>
>          // Flush elements to make sure the DOM elements are created.
>          qx.html.Element.flush();
>          var currentDomEl = currentEl.getDomElement();
>          var newDomEl = elementToAdd.getDomElement();
>
>          // copy event listeners
>          var listeners = currentContentElement.getListeners() || [];
>          listeners.forEach(function(listenerData) {
>            elementToAdd.addListener(listenerData.type,
>listenerData.handler, listenerData.self, listenerData.capture);
>          });
>
>          if (currentDomEl && newDomEl) {
>            // Switch the DOM elements' hash codes. This is required for the
>event
>            // layer to work [BUG #7447]
>            var currentHash = currentDomEl.$$hash;
>            currentDomEl.$$hash = newDomEl.$$hash;
>            newDomEl.$$hash = currentHash;
>          }
>
>          this.__currentContentElement = elementToAdd;
>        }
>      }
>    },
>
>
>    /**
>     * Use the ResourceManager to set a managed image
>     *
>     * @param el {Element} image DOM element
>     * @param source {String} source path
>     */
>    __setManagedImage : function(el, source)
>    {
>      var ResourceManager = qx.util.ResourceManager.getInstance();
>
>      // Try to find a disabled image in registry
>      if (!this.getEnabled())
>      {
>        var disabled = source.replace(/\.([a-z]+)$/, "-disabled.$1");
>        if (ResourceManager.has(disabled))
>        {
>          source = disabled;
>          this.addState("replacement");
>        }
>        else
>        {
>          this.removeState("replacement");
>        }
>      }
>
>      // Optimize case for enabled changes when no disabled image was found
>      if (el.getSource() === source) {
>        return;
>      }
>
>      // Apply source
>      this.__setSource(el, source);
>
>      // Compare with old sizes and relayout if necessary
>      this.__updateContentHint(
>        ResourceManager.getImageWidth(source),
>        ResourceManager.getImageHeight(source)
>      );
>    },
>
>
>    /**
>     * Use the infos of the ImageLoader to set an unmanaged image
>     *
>     * @param el {Element} image DOM element
>     * @param source {String} source path
>     */
>    __setUnmanagedImage : function(el, source)
>    {
>      var ImageLoader = qx.io.ImageLoader;
>
>      // Apply source
>      this.__setSource(el, source);
>
>      // Compare with old sizes and relayout if necessary
>      var width = ImageLoader.getWidth(source);
>      var height = ImageLoader.getHeight(source);
>      this.__updateContentHint(width, height);
>    },
>
>
>    /**
>     * Use the ImageLoader to load an unmanaged image
>     *
>     * @param el {Element} image DOM element
>     * @param source {String} source path
>     */
>    __loadUnmanagedImage : function(el, source)
>    {
>      var ImageLoader = qx.io.ImageLoader;
>
>      if (qx.core.Environment.get("qx.debug"))
>      {
>        // loading external images via HTTP/HTTPS is a common usecase, as is
>        // using data URLs.
>        var sourceLC = source.toLowerCase();
>        var startsWith = qx.lang.String.startsWith;
>        if (!startsWith(sourceLC, "http") &&
>            !startsWith(sourceLC, "data:image/"))
>        {
>          var self = this.self(arguments);
>
>          if (!self.__warned) {
>            self.__warned = {};
>          }
>
>          if (!self.__warned[source])
>          {
>            this.debug("try to load an unmanaged relative image: " +
>source);
>            self.__warned[source] = true;
>          }
>        }
>      }
>
>      // only try to load the image if it not already failed
>      if(!ImageLoader.isFailed(source)) {
>        ImageLoader.load(source, this.__loaderCallback, this);
>      } else {
>        if (el != null) {
>          el.resetSource();
>        }
>      }
>    },
>
>
>    /**
>     * Combines the decorator's image styles with our own image to make sure
>     * gradient and backgroundImage decorators work on Images.
>     *
>     * @param el {Element} image DOM element
>     * @param source {String} source path
>     */
>    __setSource: function (el, source) {
>      if (el.getNodeName() == "div") {
>
>        // checks if a decorator already set.
>        // In this case we have to merge background styles
>        var decorator =
>qx.theme.manager.Decoration.getInstance().resolve(this.getDecorator());
>        if (decorator) {
>          var hasGradient = (decorator.getStartColor() &&
>decorator.getEndColor());
>          var hasBackground = decorator.getBackgroundImage();
>          if (hasGradient || hasBackground) {
>            var repeat = this.getScale() ? "scale" : "no-repeat";
>
>            // get the style attributes for the given source
>            var attr = qx.bom.element.Decoration.getAttributes(source,
>repeat);
>            // get the background image(s) defined by the decorator
>            var decoratorStyle = decorator.getStyles(true);
>
>            var combinedStyles = {
>              "backgroundImage": attr.style.backgroundImage,
>              "backgroundPosition": (attr.style.backgroundPosition || "0
>0"),
>              "backgroundRepeat": (attr.style.backgroundRepeat ||
>"no-repeat")
>            };
>
>            if (hasBackground) {
>              combinedStyles["backgroundPosition"] += "," +
>decoratorStyle["background-position"] || "0 0";
>              combinedStyles["backgroundRepeat"] += ", " +
>decorator.getBackgroundRepeat();
>            }
>
>            if (hasGradient) {
>              combinedStyles["backgroundPosition"] += ", 0 0";
>              combinedStyles["backgroundRepeat"] += ", no-repeat";
>            }
>
>            combinedStyles["backgroundImage"] += "," +
>decoratorStyle["background-image"];
>
>            // apply combined background images
>            el.setStyles(combinedStyles);
>
>            return;
>          }
>        } else {
>          // force re-apply to remove old decorator styles
>          el.setSource(null);
>        }
>      }
>
>      el.setSource(source);
>    },
>
>    /**
>     * Detects whether there is a high-resolution image available.
>     * A high-resolution image is assumed to have the same file name as
>     * the parameter source, but with a pixelRatio identifier before the
>file
>     * extension, like "@2x".
>     * Medium Resolution: "example.png", high-resolution: "[hidden email]"
>     *
>     * @param lowResImgSrc {String} source of the low resolution image.
>     * @return {String|Boolean} If a high-resolution image source.
>     */
>    _findHighResolutionSource: function(lowResImgSrc) {
>      var pixelRatioCandidates = ["3", "2", "1.5"];
>
>      // Calculate the optimal ratio, based on the rem scale factor of the
>application and the device pixel ratio.
>      var factor =
>parseFloat(qx.bom.client.Device.getDevicePixelRatio().toFixed(2));
>      if (factor <= 1) {
>        return false;
>      }
>
>      var i = pixelRatioCandidates.length;
>      while (i > 0 && factor > pixelRatioCandidates[--i]) {}
>
>      var hiResImgSrc;
>      var k;
>
>      // Search for best img with a higher resolution.
>      for (k = i; k >= 0; k--) {
>        hiResImgSrc = this._getHighResolutionSource(lowResImgSrc,
>pixelRatioCandidates[k]);
>        if (hiResImgSrc) {
>          return hiResImgSrc;
>        }
>      }
>
>      // Search for best img with a lower resolution.
>      for (k = i + 1; k < pixelRatioCandidates.length; k++) {
>        hiResImgSrc = this._getHighResolutionSource(lowResImgSrc,
>pixelRatioCandidates[k]);
>        if (hiResImgSrc) {
>          return hiResImgSrc;
>        }
>      }
>
>      return null;
>    },
>
>    /**
>     * Returns the source name for the high-resolution image based on the
>passed
>     * parameters.
>     * @param source {String} the source of the medium resolution image.
>     * @param pixelRatio {Number} the pixel ratio of the high-resolution
>image.
>     * @return {String} the high-resolution source name or null if no source
>could be found.
>     */
>    _getHighResolutionSource : function(source, pixelRatio) {
>      var fileExtIndex = source.lastIndexOf('.');
>      if (fileExtIndex > -1) {
>        var pixelRatioIdentifier = "@" + pixelRatio + "x";
>        var candidate = source.slice(0, fileExtIndex) + pixelRatioIdentifier
>+ source.slice(fileExtIndex);
>
>        if(qx.util.ResourceManager.getInstance().has(candidate)) {
>          return candidate;
>        }
>      }
>      return null;
>    },
>
>    /**
>     * Event handler fired after the preloader has finished loading the icon
>     *
>     * @param source {String} Image source which was loaded
>     * @param imageInfo {Map} Dimensions of the loaded image
>     */
>    __loaderCallback : function(source, imageInfo)
>    {
>      // Ignore the callback on already disposed images
>      if (this.$$disposed === true) {
>        return;
>      }
>
>      // Ignore when the source has already been modified
>      if (source !==
>qx.util.AliasManager.getInstance().resolve(this.getSource())) {
>        this.fireEvent("aborted");
>        return;
>      }
>
>      /// Output a warning if the image could not loaded and quit
>      if (imageInfo.failed) {
>        this.warn("Image could not be loaded: " + source);
>        this.fireEvent("loadingFailed");
>      } else if (imageInfo.aborted) {
>        this.fireEvent("aborted");
>        return;
>      } else {
>        this.fireEvent("loaded");
>      }
>
>      // Update image
>      this.__setUnmanagedImage(this.__getContentElement(), source);
>    },
>
>
>    /**
>     * Updates the content hint when the image size has been changed
>     *
>     * @param width {Integer} width of the image
>     * @param height {Integer} height of the image
>     */
>    __updateContentHint : function(width, height)
>    {
>      // Compare with old sizes and relayout if necessary
>      if (width !== this.__width || height !== this.__height)
>      {
>        this.__width = width;
>        this.__height = height;
>
>        qx.ui.core.queue.Layout.add(this);
>      }
>    }
>  },
>
>
>  /*
>
>*****************************************************************************
>     DESTRUCTOR
>
>*****************************************************************************
>  */
>
>  destruct : function() {
>    for (var mode in this.__contentElements) {
>      if (this.__contentElements.hasOwnProperty(mode)) {
>        this.__contentElements[mode].setAttribute("$$widget", null, true);
>      }
>    }
>
>    delete this.__currentContentElement;
>    if (this.__wrapper) {
>      delete this.__wrapper;
>    }
>
>    this._disposeMap("__contentElements");
>  }
>});
>
>
>
>
>var btn = new qx.ui.form.CheckBox("Image#scale").set({ value : true});
>var setSrcBtn = new qx.ui.form.Button("setGreen");
>setSrcBtn.addListener("execute", function(e) {
>    img.setBackgroundColor("green");
>}, this);
>
>var img = new
>kreimer.MyImage2("http://support.showreelfinder.com/hc/en-us/article_attachments/201500876/reset.png").set({
>    cursor : "pointer",
>    backgroundColor : "orange",
>    height : 64,
>    width : 64,
>    scale : true
>});
>
>var doc = this.getRoot();
>doc.add(btn, { left: 10, top: 10 });
>doc.add(setSrcBtn, { left: 150, top: 10 });
>doc.add(img, { left: 10, top: 50 });
>btn.bind("value", img, "scale");
>
>
>
>
>--
>View this message in context: http://qooxdoo.678.n2.nabble.com/cursor-on-images-with-scale-true-tp7588002p7588101.html
>Sent from the qooxdoo mailing list archive at Nabble.com.
>
>------------------------------------------------------------------------------
>Site24x7 APM Insight: Get Deep Visibility into Application Performance
>APM + Mobile APM + RUM: Monitor 3 App instances at just $35/Month
>Monitor end-to-end web transactions and take corrective actions now
>Troubleshoot faster and improve end-user experience. Signup Now!
>http://pubads.g.doubleclick.net/gampad/clk?id=272487151&iu=/4140
>_______________________________________________
>qooxdoo-devel mailing list
>[hidden email]
>https://lists.sourceforge.net/lists/listinfo/qooxdoo-devel



------------------------------------------------------------------------------
Site24x7 APM Insight: Get Deep Visibility into Application Performance
APM + Mobile APM + RUM: Monitor 3 App instances at just $35/Month
Monitor end-to-end web transactions and take corrective actions now
Troubleshoot faster and improve end-user experience. Signup Now!
http://pubads.g.doubleclick.net/gampad/clk?id=272487151&iu=/4140
_______________________________________________
qooxdoo-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/qooxdoo-devel
Reply | Threaded
Open this post in threaded view
|

Re: cursor on images with scale true

kreimer
Hello,

done! here it is: https://github.com/qooxdoo/qooxdoo/pull/176

Thanks!
Reply | Threaded
Open this post in threaded view
|

Re: cursor on images with scale true

kreimer
Added some check on getAllStyles() being not null.
Reply | Threaded
Open this post in threaded view
|

Re: cursor on images with scale true

John Spackman
Brill, thanks Bernardo




On 24/02/2016, 12:53, "kreimer" <[hidden email]> wrote:

>Added some check on getAllStyles() being not null.
>
>
>
>--
>View this message in context: http://qooxdoo.678.n2.nabble.com/cursor-on-images-with-scale-true-tp7588002p7588105.html
>Sent from the qooxdoo mailing list archive at Nabble.com.
>
>------------------------------------------------------------------------------
>Site24x7 APM Insight: Get Deep Visibility into Application Performance
>APM + Mobile APM + RUM: Monitor 3 App instances at just $35/Month
>Monitor end-to-end web transactions and take corrective actions now
>Troubleshoot faster and improve end-user experience. Signup Now!
>http://pubads.g.doubleclick.net/gampad/clk?id=272487151&iu=/4140
>_______________________________________________
>qooxdoo-devel mailing list
>[hidden email]
>https://lists.sourceforge.net/lists/listinfo/qooxdoo-devel



------------------------------------------------------------------------------
Site24x7 APM Insight: Get Deep Visibility into Application Performance
APM + Mobile APM + RUM: Monitor 3 App instances at just $35/Month
Monitor end-to-end web transactions and take corrective actions now
Troubleshoot faster and improve end-user experience. Signup Now!
http://pubads.g.doubleclick.net/gampad/clk?id=272487151&iu=/4140
_______________________________________________
qooxdoo-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/qooxdoo-devel