// TODO: Complete implementation / Document
// QML Image
QObjects.Image = {
  init: function() {
    // TODO: Should this be group or layer? infer based on anim etc?
    this._.kNode = new Kinetic.Group();
    this._.kImage = new Kinetic.Image();
    this._.kNode.add(this._.kImage);
    try {
      this.parent._.kNode.add(this._.kNode);
    }
    catch(e) {
      // Throw 'Image cannot be child of parent.type'
    }

    this._.domImage = new Image();

    // When the user assigns the source attribute nextSource is set
    // to the provided value, which triggers the download of the image
    // file by setting domImage.src. Upon completion, activeSource is
    // set to nextSource which then triggers the render update.
    // nextSource is required because:
    // a) If src is specified in the QML Document is needs to be assigned
    //    somewhere but domImage won't exist yet
    // b) Reading the value of domImage.src will most of the time not yeild
    //    what was written to it, so there is no way to prevent updates
    //    when src is re-assigned its current value
    var self = this;

    if(nullOrUndefined(this._.nextSource)) {
      this._.nextSource = ko.observable(null);
    }
    this._.activeSource = ko.observable(null);

    this._.domImage.onload = function() {
      self._.activeSource(self._.nextSource());
    };

    this._.nextSource.subscribe(function(v) {
      self._.domImage.src = v;
    });
    this._.nextSource.valueHasMutated();

    this.update();
  },
  update: function() {
    if(nullOrUndefined(this._.activeSource()) || !this._.activeSource().length) {
      // TODO: Detach image from group and redraw
      console.log('no image');
      return;
    }

    this.layout(this._.kNode);
    var nodeWidth = this._.kNode.getWidth(),
        nodeHeight = this._.kNode.getHeight(),
        imageWidth = this._.domImage.naturalWidth,
        imageHeight = this._.domImage.naturalHeight;

    if(this.fillMode === Image.Stretch) {
      this._.kImage.setFillPatternImage(null);
      this._.kImage.setImage(this._.domImage);
    }
    else {
      this._.kImage.setImage(null);
      this._.kImage.setFillPatternImage(this._.domImage);
      if(this.fillMode === Image.Tile) {
        // Pattern needs to be offset to fill about the centre
        this._.kImage.setFillPatternOffset([-0.5 * (nodeWidth - imageWidth), -0.5 * (nodeHeight - imageHeight)]);
      }
    }

    this._.kImage.setWidth(this._.kNode.getWidth());
    this._.kImage.setHeight(this._.kNode.getHeight());

    this.draw();
  },
  draw: function() {
    this.parent.draw();
  }
};

Object.defineProperties(QObjects.Image, {
  inherits: {
    value: 'Item'
  },
  defaultProperties: {
    value: {
      //asynchronous: bool,
      //cache: bool,
      fillMode: Image.Stretch,
      //horizontalAlignment: enumeration,
      //mirror: false,
      //paintedHeight: real,
      //paintedWidth: real,
      //progress: real,
      //smooth: bool,
      source: {
        read: function() {
          return this._.activeSource();
        },
        write: function(v) {
          // TODO: Architecture for handling writes to private this.vars before init is called?
          if(nullOrUndefined(this._.nextSource)) {
            this._.nextSource = ko.observable(v);
          }
          else {
            this._.nextSource(v);
          }
        }
      }
      //sourceSize: QSize,
      //status: enumeration,
      //verticalAlignment: enumeration
    }
  }
});

@@ -1736,24 +1736,25 @@
 s._.kNode);%0A
+%0A
     var node
@@ -1946,139 +1946,944 @@
     
-if(this.fillMode === Image.Stretch) %7B%0A      this._.kImage.setFillPatternImage(null);%0A      this._.kImage.setImage(this._.domImage);
+// TODO: Store the to-be-set values in a var and set them once at the end%0A    this._.kImage.setX(0);%0A    this._.kImage.setY(0);%0A    this._.kImage.setWidth(nodeWidth);%0A    this._.kImage.setHeight(nodeHeight);%0A%0A    if(this.fillMode === Image.Stretch %7C%7C this.fillMode == Image.PreserveAspectFit) %7B%0A      this._.kImage.setFillPatternImage(null);%0A      this._.kImage.setImage(this._.domImage);%0A      if(this.fillMode === Image.PreserveAspectFit) %7B%0A        // Set the size of kImage to fit inside kNode%0A        var scale = 1, rX = nodeWidth / imageWidth, rY = nodeHeight / imageHeight;%0A        if(rX %3C rY) %7B%0A          scale = rX;%0A          this._.kImage.setY((nodeHeight - imageHeight * scale) * 0.5);%0A        %7D%0A        else %7B%0A          scale = rY;%0A          this._.kImage.setX((nodeWidth - imageWidth * scale) * 0.5);%0A        %7D%0A        this._.kImage.setWidth(imageWidth * scale);%0A        this._.kImage.setHeight(imageHeight * scale);%0A      %7D
 %0A   
@@ -3227,117 +3227,8 @@
  %7D%0A%0A
-    this._.kImage.setWidth(this._.kNode.getWidth());%0A    this._.kImage.setHeight(this._.kNode.getHeight());%0A%0A
     

Add layout for PreserveAspectFit in images