<commit_before>/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2019 Photon Storm Ltd.
 * @license      {@link https://opensource.org/licenses/MIT|MIT License}
 */

var Class = require('../../utils/Class');
var Frame = require('../../textures/Frame');

/**
 * @classdesc
 * A Bob Game Object.
 *
 * A Bob belongs to a Blitter Game Object. The Blitter is responsible for managing and rendering this object.
 *
 * A Bob has a position, alpha value and a frame from a texture that it uses to render with. You can also toggle
 * the flipped and visible state of the Bob. The Frame the Bob uses to render can be changed dynamically, but it
 * must be a Frame within the Texture used by the parent Blitter.
 *
 * Bob positions are relative to the Blitter parent. So if you move the Blitter parent, all Bob children will
 * have their positions impacted by this change as well.
 *
 * You can manipulate Bob objects directly from your game code, but the creation and destruction of them should be
 * handled via the Blitter parent.
 *
 * @class Bob
 * @memberof Phaser.GameObjects
 * @constructor
 * @since 3.0.0
 *
 * @param {Phaser.GameObjects.Blitter} blitter - The parent Blitter object is responsible for updating this Bob.
 * @param {number} x - The horizontal position of this Game Object in the world, relative to the parent Blitter position.
 * @param {number} y - The vertical position of this Game Object in the world, relative to the parent Blitter position.
 * @param {(string|integer)} frame - The Frame this Bob will render with, as defined in the Texture the parent Blitter is using.
 * @param {boolean} visible - Should the Bob render visible or not to start with?
 */
var Bob = new Class({

    initialize:

    function Bob (blitter, x, y, frame, visible)
    {
        /**
         * The Blitter object that this Bob belongs to.
         *
         * @name Phaser.GameObjects.Bob#parent
         * @type {Phaser.GameObjects.Blitter}
         * @since 3.0.0
         */
        this.parent = blitter;

        /**
         * The x position of this Bob, relative to the x position of the Blitter.
         *
         * @name Phaser.GameObjects.Bob#x
         * @type {number}
         * @since 3.0.0
         */
        this.x = x;

        /**
         * The y position of this Bob, relative to the y position of the Blitter.
         *
         * @name Phaser.GameObjects.Bob#y
         * @type {number}
         * @since 3.0.0
         */
        this.y = y;

        /**
         * The frame that the Bob uses to render with.
         * To change the frame use the `Bob.setFrame` method.
         *
         * @name Phaser.GameObjects.Bob#frame
         * @type {Phaser.Textures.Frame}
         * @protected
         * @since 3.0.0
         */
        this.frame = frame;

        /**
         * A blank object which can be used to store data related to this Bob in.
         *
         * @name Phaser.GameObjects.Bob#data
         * @type {object}
         * @default {}
         * @since 3.0.0
         */
        this.data = {};

        /**
         * The visible state of this Bob.
         *
         * @name Phaser.GameObjects.Bob#_visible
         * @type {boolean}
         * @private
         * @since 3.0.0
         */
        this._visible = visible;

        /**
         * The alpha value of this Bob.
         *
         * @name Phaser.GameObjects.Bob#_alpha
         * @type {number}
         * @private
         * @default 1
         * @since 3.0.0
         */
        this._alpha = 1;

        /**
         * The horizontally flipped state of the Bob.
         * A Bob that is flipped horizontally will render inversed on the horizontal axis.
         * Flipping always takes place from the middle of the texture.
         *
         * @name Phaser.GameObjects.Bob#flipX
         * @type {boolean}
         * @since 3.0.0
         */
        this.flipX = false;

        /**
         * The vertically flipped state of the Bob.
         * A Bob that is flipped vertically will render inversed on the vertical axis (i.e. upside down)
         * Flipping always takes place from the middle of the texture.
         *
         * @name Phaser.GameObjects.Bob#flipY
         * @type {boolean}
         * @since 3.0.0
         */
        this.flipY = false;
    },

    /**
     * Changes the Texture Frame being used by this Bob.
     * The frame must be part of the Texture the parent Blitter is using.
     * If no value is given it will use the default frame of the Blitter parent.
     *
     * @method Phaser.GameObjects.Bob#setFrame
     * @since 3.0.0
     *
     * @param {(string|integer|Phaser.Textures.Frame)} [frame] - The frame to be used during rendering.
     *
     * @return {Phaser.GameObjects.Bob} This Bob Game Object.
     */
    setFrame: function (frame)
    {
        if (frame === undefined)
        {
            this.frame = this.parent.frame;
        }
        else if (frame instanceof Frame && frame.texture === this.parent.texture)
        {
            this.frame = frame;
        }
        else
        {
            this.frame = this.parent.texture.get(frame);
        }

        return this;
    },

    /**
     * Resets the horizontal and vertical flipped state of this Bob back to their default un-flipped state.
     *
     * @method Phaser.GameObjects.Bob#resetFlip
     * @since 3.0.0
     *
     * @return {Phaser.GameObjects.Bob} This Bob Game Object.
     */
    resetFlip: function ()
    {
        this.flipX = false;
        this.flipY = false;

        return this;
    },

    /**
     * Resets this Bob.
     *
     * Changes the position to the values given, and optionally changes the frame.
     *
     * Also resets the flipX and flipY values, sets alpha back to 1 and visible to true.
     *
     * @method Phaser.GameObjects.Bob#reset
     * @since 3.0.0
     *
     * @param {number} x - The x position of the Bob. Bob coordinate are relative to the position of the Blitter object.
     * @param {number} y - The y position of the Bob. Bob coordinate are relative to the position of the Blitter object.
     * @param {(string|integer|Phaser.Textures.Frame)} [frame] - The Frame the Bob will use. It _must_ be part of the Texture the parent Blitter object is using.
     *
     * @return {Phaser.GameObjects.Bob} This Bob Game Object.
     */
    reset: function (x, y, frame)
    {
        this.x = x;
        this.y = y;

        this.flipX = false;
        this.flipY = false;

        this._alpha = 1;
        this._visible = true;

        this.parent.dirty = true;

        if (frame)
        {
            this.setFrame(frame);
        }

        return this;
    },

    /**
     * Sets the horizontal flipped state of this Bob.
     *
     * @method Phaser.GameObjects.Bob#setFlipX
     * @since 3.0.0
     *
     * @param {boolean} value - The flipped state. `false` for no flip, or `true` to be flipped.
     *
     * @return {Phaser.GameObjects.Bob} This Bob Game Object.
     */
    setFlipX: function (value)
    {
        this.flipX = value;

        return this;
    },

    /**
     * Sets the vertical flipped state of this Bob.
     *
     * @method Phaser.GameObjects.Bob#setFlipY
     * @since 3.0.0
     *
     * @param {boolean} value - The flipped state. `false` for no flip, or `true` to be flipped.
     *
     * @return {Phaser.GameObjects.Bob} This Bob Game Object.
     */
    setFlipY: function (value)
    {
        this.flipY = value;

        return this;
    },

    /**
     * Sets the horizontal and vertical flipped state of this Bob.
     *
     * @method Phaser.GameObjects.Bob#setFlip
     * @since 3.0.0
     *
     * @param {boolean} x - The horizontal flipped state. `false` for no flip, or `true` to be flipped.
     * @param {boolean} y - The horizontal flipped state. `false` for no flip, or `true` to be flipped.
     *
     * @return {Phaser.GameObjects.Bob} This Bob Game Object.
     */
    setFlip: function (x, y)
    {
        this.flipX = x;
        this.flipY = y;

        return this;
    },

    /**
     * Sets the visibility of this Bob.
     *
     * An invisible Bob will skip rendering.
     *
     * @method Phaser.GameObjects.Bob#setVisible
     * @since 3.0.0
     *
     * @param {boolean} value - The visible state of the Game Object.
     *
     * @return {Phaser.GameObjects.Bob} This Bob Game Object.
     */
    setVisible: function (value)
    {
        this.visible = value;

        return this;
    },

    /**
     * Set the Alpha level of this Bob. The alpha controls the opacity of the Game Object as it renders.
     * Alpha values are provided as a float between 0, fully transparent, and 1, fully opaque.
     *
     * A Bob with alpha 0 will skip rendering.
     *
     * @method Phaser.GameObjects.Bob#setAlpha
     * @since 3.0.0
     *
     * @param {number} value - The alpha value used for this Bob. Between 0 and 1.
     *
     * @return {Phaser.GameObjects.Bob} This Bob Game Object.
     */
    setAlpha: function (value)
    {
        this.alpha = value;

        return this;
    },

    /**
     * Destroys this Bob instance.
     * Removes itself from the Blitter and clears the parent, frame and data properties.
     *
     * @method Phaser.GameObjects.Bob#destroy
     * @since 3.0.0
     */
    destroy: function ()
    {
        this.parent.dirty = true;

        this.parent.children.remove(this);

        this.parent = undefined;
        this.frame = undefined;
        this.data = undefined;
    },

    /**
     * The visible state of the Bob.
     *
     * An invisible Bob will skip rendering.
     *
     * @name Phaser.GameObjects.Bob#visible
     * @type {boolean}
     * @since 3.0.0
     */
    visible: {

        get: function ()
        {
            return this._visible;
        },

        set: function (value)
        {
            this._visible = value;
            this.parent.dirty = true;
        }

    },

    /**
     * The alpha value of the Bob, between 0 and 1.
     *
     * A Bob with alpha 0 will skip rendering.
     *
     * @name Phaser.GameObjects.Bob#alpha
     * @type {number}
     * @since 3.0.0
     */
    alpha: {

        get: function ()
        {
            return this._alpha;
        },

        set: function (value)
        {
            this._alpha = value;
            this.parent.dirty = true;
        }

    }

});

module.exports = Bob;
<commit_msg>Set dirty flag only when render state is changed<commit_after>/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2019 Photon Storm Ltd.
 * @license      {@link https://opensource.org/licenses/MIT|MIT License}
 */

var Class = require('../../utils/Class');
var Frame = require('../../textures/Frame');

/**
 * @classdesc
 * A Bob Game Object.
 *
 * A Bob belongs to a Blitter Game Object. The Blitter is responsible for managing and rendering this object.
 *
 * A Bob has a position, alpha value and a frame from a texture that it uses to render with. You can also toggle
 * the flipped and visible state of the Bob. The Frame the Bob uses to render can be changed dynamically, but it
 * must be a Frame within the Texture used by the parent Blitter.
 *
 * Bob positions are relative to the Blitter parent. So if you move the Blitter parent, all Bob children will
 * have their positions impacted by this change as well.
 *
 * You can manipulate Bob objects directly from your game code, but the creation and destruction of them should be
 * handled via the Blitter parent.
 *
 * @class Bob
 * @memberof Phaser.GameObjects
 * @constructor
 * @since 3.0.0
 *
 * @param {Phaser.GameObjects.Blitter} blitter - The parent Blitter object is responsible for updating this Bob.
 * @param {number} x - The horizontal position of this Game Object in the world, relative to the parent Blitter position.
 * @param {number} y - The vertical position of this Game Object in the world, relative to the parent Blitter position.
 * @param {(string|integer)} frame - The Frame this Bob will render with, as defined in the Texture the parent Blitter is using.
 * @param {boolean} visible - Should the Bob render visible or not to start with?
 */
var Bob = new Class({

    initialize:

    function Bob (blitter, x, y, frame, visible)
    {
        /**
         * The Blitter object that this Bob belongs to.
         *
         * @name Phaser.GameObjects.Bob#parent
         * @type {Phaser.GameObjects.Blitter}
         * @since 3.0.0
         */
        this.parent = blitter;

        /**
         * The x position of this Bob, relative to the x position of the Blitter.
         *
         * @name Phaser.GameObjects.Bob#x
         * @type {number}
         * @since 3.0.0
         */
        this.x = x;

        /**
         * The y position of this Bob, relative to the y position of the Blitter.
         *
         * @name Phaser.GameObjects.Bob#y
         * @type {number}
         * @since 3.0.0
         */
        this.y = y;

        /**
         * The frame that the Bob uses to render with.
         * To change the frame use the `Bob.setFrame` method.
         *
         * @name Phaser.GameObjects.Bob#frame
         * @type {Phaser.Textures.Frame}
         * @protected
         * @since 3.0.0
         */
        this.frame = frame;

        /**
         * A blank object which can be used to store data related to this Bob in.
         *
         * @name Phaser.GameObjects.Bob#data
         * @type {object}
         * @default {}
         * @since 3.0.0
         */
        this.data = {};

        /**
         * The visible state of this Bob.
         *
         * @name Phaser.GameObjects.Bob#_visible
         * @type {boolean}
         * @private
         * @since 3.0.0
         */
        this._visible = visible;

        /**
         * The alpha value of this Bob.
         *
         * @name Phaser.GameObjects.Bob#_alpha
         * @type {number}
         * @private
         * @default 1
         * @since 3.0.0
         */
        this._alpha = 1;

        /**
         * The horizontally flipped state of the Bob.
         * A Bob that is flipped horizontally will render inversed on the horizontal axis.
         * Flipping always takes place from the middle of the texture.
         *
         * @name Phaser.GameObjects.Bob#flipX
         * @type {boolean}
         * @since 3.0.0
         */
        this.flipX = false;

        /**
         * The vertically flipped state of the Bob.
         * A Bob that is flipped vertically will render inversed on the vertical axis (i.e. upside down)
         * Flipping always takes place from the middle of the texture.
         *
         * @name Phaser.GameObjects.Bob#flipY
         * @type {boolean}
         * @since 3.0.0
         */
        this.flipY = false;
    },

    /**
     * Changes the Texture Frame being used by this Bob.
     * The frame must be part of the Texture the parent Blitter is using.
     * If no value is given it will use the default frame of the Blitter parent.
     *
     * @method Phaser.GameObjects.Bob#setFrame
     * @since 3.0.0
     *
     * @param {(string|integer|Phaser.Textures.Frame)} [frame] - The frame to be used during rendering.
     *
     * @return {Phaser.GameObjects.Bob} This Bob Game Object.
     */
    setFrame: function (frame)
    {
        if (frame === undefined)
        {
            this.frame = this.parent.frame;
        }
        else if (frame instanceof Frame && frame.texture === this.parent.texture)
        {
            this.frame = frame;
        }
        else
        {
            this.frame = this.parent.texture.get(frame);
        }

        return this;
    },

    /**
     * Resets the horizontal and vertical flipped state of this Bob back to their default un-flipped state.
     *
     * @method Phaser.GameObjects.Bob#resetFlip
     * @since 3.0.0
     *
     * @return {Phaser.GameObjects.Bob} This Bob Game Object.
     */
    resetFlip: function ()
    {
        this.flipX = false;
        this.flipY = false;

        return this;
    },

    /**
     * Resets this Bob.
     *
     * Changes the position to the values given, and optionally changes the frame.
     *
     * Also resets the flipX and flipY values, sets alpha back to 1 and visible to true.
     *
     * @method Phaser.GameObjects.Bob#reset
     * @since 3.0.0
     *
     * @param {number} x - The x position of the Bob. Bob coordinate are relative to the position of the Blitter object.
     * @param {number} y - The y position of the Bob. Bob coordinate are relative to the position of the Blitter object.
     * @param {(string|integer|Phaser.Textures.Frame)} [frame] - The Frame the Bob will use. It _must_ be part of the Texture the parent Blitter object is using.
     *
     * @return {Phaser.GameObjects.Bob} This Bob Game Object.
     */
    reset: function (x, y, frame)
    {
        this.x = x;
        this.y = y;

        this.flipX = false;
        this.flipY = false;

        this._alpha = 1;
        this._visible = true;

        this.parent.dirty = true;

        if (frame)
        {
            this.setFrame(frame);
        }

        return this;
    },

    /**
     * Sets the horizontal flipped state of this Bob.
     *
     * @method Phaser.GameObjects.Bob#setFlipX
     * @since 3.0.0
     *
     * @param {boolean} value - The flipped state. `false` for no flip, or `true` to be flipped.
     *
     * @return {Phaser.GameObjects.Bob} This Bob Game Object.
     */
    setFlipX: function (value)
    {
        this.flipX = value;

        return this;
    },

    /**
     * Sets the vertical flipped state of this Bob.
     *
     * @method Phaser.GameObjects.Bob#setFlipY
     * @since 3.0.0
     *
     * @param {boolean} value - The flipped state. `false` for no flip, or `true` to be flipped.
     *
     * @return {Phaser.GameObjects.Bob} This Bob Game Object.
     */
    setFlipY: function (value)
    {
        this.flipY = value;

        return this;
    },

    /**
     * Sets the horizontal and vertical flipped state of this Bob.
     *
     * @method Phaser.GameObjects.Bob#setFlip
     * @since 3.0.0
     *
     * @param {boolean} x - The horizontal flipped state. `false` for no flip, or `true` to be flipped.
     * @param {boolean} y - The horizontal flipped state. `false` for no flip, or `true` to be flipped.
     *
     * @return {Phaser.GameObjects.Bob} This Bob Game Object.
     */
    setFlip: function (x, y)
    {
        this.flipX = x;
        this.flipY = y;

        return this;
    },

    /**
     * Sets the visibility of this Bob.
     *
     * An invisible Bob will skip rendering.
     *
     * @method Phaser.GameObjects.Bob#setVisible
     * @since 3.0.0
     *
     * @param {boolean} value - The visible state of the Game Object.
     *
     * @return {Phaser.GameObjects.Bob} This Bob Game Object.
     */
    setVisible: function (value)
    {
        this.visible = value;

        return this;
    },

    /**
     * Set the Alpha level of this Bob. The alpha controls the opacity of the Game Object as it renders.
     * Alpha values are provided as a float between 0, fully transparent, and 1, fully opaque.
     *
     * A Bob with alpha 0 will skip rendering.
     *
     * @method Phaser.GameObjects.Bob#setAlpha
     * @since 3.0.0
     *
     * @param {number} value - The alpha value used for this Bob. Between 0 and 1.
     *
     * @return {Phaser.GameObjects.Bob} This Bob Game Object.
     */
    setAlpha: function (value)
    {
        this.alpha = value;

        return this;
    },

    /**
     * Destroys this Bob instance.
     * Removes itself from the Blitter and clears the parent, frame and data properties.
     *
     * @method Phaser.GameObjects.Bob#destroy
     * @since 3.0.0
     */
    destroy: function ()
    {
        this.parent.dirty = true;

        this.parent.children.remove(this);

        this.parent = undefined;
        this.frame = undefined;
        this.data = undefined;
    },

    /**
     * The visible state of the Bob.
     *
     * An invisible Bob will skip rendering.
     *
     * @name Phaser.GameObjects.Bob#visible
     * @type {boolean}
     * @since 3.0.0
     */
    visible: {

        get: function ()
        {
            return this._visible;
        },

        set: function (value)
        {
            this.parent.dirty |= (this._visible !== value);
            this._visible = value;
        }

    },

    /**
     * The alpha value of the Bob, between 0 and 1.
     *
     * A Bob with alpha 0 will skip rendering.
     *
     * @name Phaser.GameObjects.Bob#alpha
     * @type {number}
     * @since 3.0.0
     */
    alpha: {

        get: function ()
        {
            return this._alpha;
        },

        set: function (value)
        {
            this.parent.dirty |= ((this._alpha > 0) !== (value > 0));
            this._alpha = value;
        }

    }

});

module.exports = Bob;
<|endoftext|>


<commit_before>/**
 * Created by zuozhuo on 2017/5/15.
 */
import {getDataFromEnv} from './utils';
import {getService, SERVICE_NAMES} from './bottle';

function getDefaultWebpackConfig() {
    const dipConfig = getService(SERVICE_NAMES.dipConfig);
    return getDataFromEnv({
        devtool: undefined,
        cache: true,
        node: {
            // 避免某些npm包（例如browserslist）的代码中使用了node的fs模块，
            // 但是在浏览器环境中是没有fs模块的，导致浏览器中抛错
            console: true,
            fs: 'empty',
            net: 'empty',
            tls: 'empty',
        },
        entry: {
            app: [],
            vendors: [],
        },
        devServer: {
            // 传递给webpack-dev-server的配置
            // overlay: true // 增加报错浮层 webpack2.0以上支持
        },
        output: {
            path: null,
            publicPath: null,
            filename: dipConfig.hash ? '[name].[chunkhash].js' : '[name].js',
            // 不能是 [name].[chunkhash].js.map 否则sourcemap会不正确
            // 因为sourcemap不仅仅是js，还有css的。 [file]就相当于前面的filename
            sourceMapFilename: '[file].map',
            chunkFilename: dipConfig.hash ? 'chunk.[name].[id].[chunkhash].js' : 'chunk.[name].[id].js',
        },

        module: {
            // keep empty array here
            rules: [],
        },
        // keep empty array here
        plugins: [],
    });
}

export {
    getDefaultWebpackConfig,
};

<commit_msg>add resolve.extensions<commit_after>/**
 * Created by zuozhuo on 2017/5/15.
 */
import {getDataFromEnv} from './utils';
import {getService, SERVICE_NAMES} from './bottle';

function getDefaultWebpackConfig() {
    const dipConfig = getService(SERVICE_NAMES.dipConfig);
    return getDataFromEnv({
        devtool: undefined,
        cache: true,
        resolve: {
            // default file extension when import or require modules
            extensions: ['.js', '.jsx', '.ts', '.tsx', '.json'],
        },
        node: {
            // 避免某些npm包（例如browserslist）的代码中使用了node的fs模块，
            // 但是在浏览器环境中是没有fs模块的，导致浏览器中抛错
            console: true,
            fs: 'empty',
            net: 'empty',
            tls: 'empty',
        },
        entry: {
            app: [],
            vendors: [],
        },
        devServer: {
            // 传递给webpack-dev-server的配置
            // overlay: true // 增加报错浮层 webpack2.0以上支持
        },
        output: {
            path: null,
            publicPath: null,
            filename: dipConfig.hash ? '[name].[chunkhash].js' : '[name].js',
            // 不能是 [name].[chunkhash].js.map 否则sourcemap会不正确
            // 因为sourcemap不仅仅是js，还有css的。 [file]就相当于前面的filename
            sourceMapFilename: '[file].map',
            chunkFilename: dipConfig.hash ? 'chunk.[name].[id].[chunkhash].js' : 'chunk.[name].[id].js',
        },

        module: {
            // keep empty array here
            rules: [],
        },
        // keep empty array here
        plugins: [],
    });
}

export {
    getDefaultWebpackConfig,
};

<|endoftext|>


<commit_before>// ==========================================================================
// Project:  SproutCore Runtime
// Copyright: ©2011 Strobe Inc. and contributors.
// License:   Licensed under MIT license (see license.js)
// ==========================================================================
/*globals testBoth Global */

require('sproutcore-metal/~tests/props_helper');

var willCount = 0 , didCount = 0,
    willChange = SC.propertyWillChange,
    didChange = SC.propertyDidChange;

module('SC.watch', {
  setup: function() {
    willCount = didCount = 0;
    SC.propertyWillChange = function(cur, keyName) {
      willCount++;
      willChange.call(this, cur, keyName);
    };

    SC.propertyDidChange = function(cur, keyName) {
      didCount++;
      didChange.call(this, cur, keyName);
    };
  },

  teardown: function() {
    SC.propertyWillChange = willChange;
    SC.propertyDidChange  = didChange;
  }
});

testBoth('watching a computed property', function(get, set) {

  var obj = {};
  SC.defineProperty(obj, 'foo', SC.computed(function(keyName, value) {
    if (value !== undefined) this.__foo = value;
    return this.__foo;
  }));

  SC.watch(obj, 'foo');
  set(obj, 'foo', 'bar');
  equals(willCount, 1, 'should have invoked willCount');
  equals(didCount, 1, 'should have invoked didCount');
});

testBoth('watching a regular defined property', function(get, set) {

  var obj = { foo: 'baz' };

  SC.watch(obj, 'foo');
  equals(get(obj, 'foo'), 'baz', 'should have original prop');

  set(obj, 'foo', 'bar');
  equals(willCount, 1, 'should have invoked willCount');
  equals(didCount, 1, 'should have invoked didCount');
});

testBoth('watches should inherit', function(get, set) {

  var obj = { foo: 'baz' };
  var objB = SC.create(obj);

  SC.watch(obj, 'foo');
  equals(get(obj, 'foo'), 'baz', 'should have original prop');

  set(obj, 'foo', 'bar');
  set(objB, 'foo', 'baz');
  equals(willCount, 2, 'should have invoked willCount once only');
  equals(didCount, 2, 'should have invoked didCount once only');
});

test("watching an object THEN defining it should work also", function() {

  var obj = {};
  SC.watch(obj, 'foo');

  SC.defineProperty(obj, 'foo');
  SC.set(obj, 'foo', 'bar');

  equals(SC.get(obj, 'foo'), 'bar', 'should have set');
  equals(willCount, 1, 'should have invoked willChange once');
  equals(didCount, 1, 'should have invoked didChange once');

});

test("accessing a watched unknown property triggers call to unknownProperty", function(){
  var unknownPropertyWasCalled = false;
  var watchedPropertyName = 'foo'

  var obj = {
    unknownProperty: function(propName){
      if (propName === watchedPropertyName) { unknownPropertyWasCalled = true };
    }
  };
  SC.watch(obj, watchedPropertyName);
  SC.get(obj, watchedPropertyName)

  ok(unknownPropertyWasCalled);
});

testBoth('watching an object value then unwatching should restore old value', function(get, set) {

  var obj = { foo: { bar: { baz: { biff: 'BIFF' } } } };
  SC.watch(obj, 'foo.bar.baz.biff');

  var foo = SC.get(obj, 'foo');
  equals(get(get(get(foo, 'bar'), 'baz'), 'biff'), 'BIFF', 'biff should exist');

  SC.unwatch(obj, 'foo.bar.baz.biff');
  equals(get(get(get(foo, 'bar'), 'baz'), 'biff'), 'BIFF', 'biff should exist');
});

testBoth('watching a global object that does not yet exist should queue', function(get, set) {

  Global = null;

  var obj = {};
  SC.watch(obj, 'Global.foo'); // only works on global chained props

  equals(willCount, 0, 'should not have fired yet');
  equals(didCount, 0, 'should not have fired yet');

  Global = { foo: 'bar' };
  SC.watch.flushPending(); // this will also be invoked automatically on ready

  equals(willCount, 0, 'should not have fired yet');
  equals(didCount, 0, 'should not have fired yet');

  set(Global, 'foo', 'baz');

  // should fire twice because this is a chained property (once on key, once
  // on path)
  equals(willCount, 2, 'should be watching');
  equals(didCount, 2, 'should be watching');

  Global = null; // reset
});

<commit_msg>Update unknownProperty unit test to use testBoth<commit_after>// ==========================================================================
// Project:  SproutCore Runtime
// Copyright: ©2011 Strobe Inc. and contributors.
// License:   Licensed under MIT license (see license.js)
// ==========================================================================
/*globals testBoth Global */

require('sproutcore-metal/~tests/props_helper');

var willCount = 0 , didCount = 0,
    willChange = SC.propertyWillChange,
    didChange = SC.propertyDidChange;

module('SC.watch', {
  setup: function() {
    willCount = didCount = 0;
    SC.propertyWillChange = function(cur, keyName) {
      willCount++;
      willChange.call(this, cur, keyName);
    };

    SC.propertyDidChange = function(cur, keyName) {
      didCount++;
      didChange.call(this, cur, keyName);
    };
  },

  teardown: function() {
    SC.propertyWillChange = willChange;
    SC.propertyDidChange  = didChange;
  }
});

testBoth('watching a computed property', function(get, set) {

  var obj = {};
  SC.defineProperty(obj, 'foo', SC.computed(function(keyName, value) {
    if (value !== undefined) this.__foo = value;
    return this.__foo;
  }));

  SC.watch(obj, 'foo');
  set(obj, 'foo', 'bar');
  equals(willCount, 1, 'should have invoked willCount');
  equals(didCount, 1, 'should have invoked didCount');
});

testBoth('watching a regular defined property', function(get, set) {

  var obj = { foo: 'baz' };

  SC.watch(obj, 'foo');
  equals(get(obj, 'foo'), 'baz', 'should have original prop');

  set(obj, 'foo', 'bar');
  equals(willCount, 1, 'should have invoked willCount');
  equals(didCount, 1, 'should have invoked didCount');
});

testBoth('watches should inherit', function(get, set) {

  var obj = { foo: 'baz' };
  var objB = SC.create(obj);

  SC.watch(obj, 'foo');
  equals(get(obj, 'foo'), 'baz', 'should have original prop');

  set(obj, 'foo', 'bar');
  set(objB, 'foo', 'baz');
  equals(willCount, 2, 'should have invoked willCount once only');
  equals(didCount, 2, 'should have invoked didCount once only');
});

test("watching an object THEN defining it should work also", function() {

  var obj = {};
  SC.watch(obj, 'foo');

  SC.defineProperty(obj, 'foo');
  SC.set(obj, 'foo', 'bar');

  equals(SC.get(obj, 'foo'), 'bar', 'should have set');
  equals(willCount, 1, 'should have invoked willChange once');
  equals(didCount, 1, 'should have invoked didChange once');

});

testBoth("accessing a watched unknown property triggers call to unknownProperty", function(get, set){
  var unknownPropertyWasCalled = false;
  var watchedPropertyName = 'foo'

  var obj = {
    unknownProperty: function(propName){
      if (propName === watchedPropertyName) { unknownPropertyWasCalled = true };
    }
  };
  SC.watch(obj, watchedPropertyName);
  get(obj, watchedPropertyName)

  ok(unknownPropertyWasCalled);
});

testBoth('watching an object value then unwatching should restore old value', function(get, set) {

  var obj = { foo: { bar: { baz: { biff: 'BIFF' } } } };
  SC.watch(obj, 'foo.bar.baz.biff');

  var foo = SC.get(obj, 'foo');
  equals(get(get(get(foo, 'bar'), 'baz'), 'biff'), 'BIFF', 'biff should exist');

  SC.unwatch(obj, 'foo.bar.baz.biff');
  equals(get(get(get(foo, 'bar'), 'baz'), 'biff'), 'BIFF', 'biff should exist');
});

testBoth('watching a global object that does not yet exist should queue', function(get, set) {

  Global = null;

  var obj = {};
  SC.watch(obj, 'Global.foo'); // only works on global chained props

  equals(willCount, 0, 'should not have fired yet');
  equals(didCount, 0, 'should not have fired yet');

  Global = { foo: 'bar' };
  SC.watch.flushPending(); // this will also be invoked automatically on ready

  equals(willCount, 0, 'should not have fired yet');
  equals(didCount, 0, 'should not have fired yet');

  set(Global, 'foo', 'baz');

  // should fire twice because this is a chained property (once on key, once
  // on path)
  equals(willCount, 2, 'should be watching');
  equals(didCount, 2, 'should be watching');

  Global = null; // reset
});

<|endoftext|>


<commit_before>var Backbone = require('backbone');
var _ = require('underscore');
var ConfigModel = require('../../../../../../../javascripts/cartodb3/data/config-model');
var UserModel = require('../../../../../../../javascripts/cartodb3/data/user-model');
var LegendsView = require('../../../../../../../javascripts/cartodb3/editor/layers/layer-content-views/legend/legends-view');
var QuerySchemaModel = require('../../../../../../../javascripts/cartodb3/data/query-schema-model');
var QueryGeometryModel = require('../../../../../../../javascripts/cartodb3/data/query-geometry-model');
var LayerContentModel = require('../../../../../../../javascripts/cartodb3/data/layer-content-model');
var LegendDefinitionsCollection = require('../../../../../../../javascripts/cartodb3/data/legends/legend-definitions-collection');
var LegendFactory = require('../../../../../../../javascripts/cartodb3/editor/layers/layer-content-views/legend/legend-factory');
var LayerDefinitionsCollection = require('../../../../../../../javascripts/cartodb3/data/layer-definitions-collection');
var LayerDefinitionModel = require('../../../../../../../javascripts/cartodb3/data/layer-definition-model');
var AnalysisDefinitionNodesCollection = require('../../../../../../../javascripts/cartodb3/data/analysis-definition-nodes-collection');
var QueryRowsCollection = require('../../../../../../../javascripts/cartodb3/data/query-rows-collection');
var FactoryModals = require('../../../../factories/modals');

describe('editor/layers/layer-content-view/legend/legends-view', function () {
  beforeEach(function () {
    this.configModel = new ConfigModel({
      base_url: '/u/pepe'
    });

    this.userModel = new UserModel({}, {
      configModel: this.configModel
    });

    this.querySchemaModel = new QuerySchemaModel({
      query: 'SELECT * FROM table',
      status: 'fetched'
    }, {
      configModel: {}
    });

    spyOn(this.querySchemaModel, 'fetch');

    this.queryGeometryModel = new QueryGeometryModel({
      query: 'SELECT * FROM table',
      status: 'fetched',
      simple_geom: 'point'
    }, {
      configModel: {}
    });
    spyOn(this.queryGeometryModel, 'fetch');

    this.mapDefModel = new Backbone.Model({
      legends: true
    });

    this.editorModel = new Backbone.Model({
      edition: false
    });
    this.editorModel.isEditing = function () { return false; };
    this.editorModel.isDisabled = function () { return false; };

    this.analysisDefinitionNodesCollection = new AnalysisDefinitionNodesCollection(null, {
      configModel: this.configModel,
      userModel: this.userModel
    });

    this.a0 = this.analysisDefinitionNodesCollection.add({
      id: 'a0',
      type: 'source',
      table_name: 'foo'
    });
    spyOn(this.a0, 'isCustomQueryApplied').and.returnValue(false);

    this.layerDefinitionCollection = new LayerDefinitionsCollection(null, {
      configModel: this.configModel,
      userModel: this.userModel,
      analysisDefinitionNodesCollection: this.analysisDefinitionNodesCollection,
      mapId: 'm123',
      stateDefinitionModel: {}
    });
    this.layerDefinitionModel = new LayerDefinitionModel({
      id: 'abc-123',
      kind: 'carto',
      options: {
        type: 'CartoDB',
        color: '#FABADA',
        table_name: 'foo',
        query: 'SELECT * FROM foo',
        tile_style: 'asdasd',
        visible: true
      }
    }, {
      parse: true,
      configModel: this.configModel,
      collection: this.layerDefinitionCollection
    });
    spyOn(this.layerDefinitionModel, 'save');
    spyOn(this.layerDefinitionModel, 'getAnalysisDefinitionNodeModel').and.returnValue(this.a0);

    this.layerDefinitionModel.styleModel = new Backbone.Model({
      fill: {
        color: {
          fixed: '#892b27'
        }
      }
    });

    this.legendDefinitionsCollection = new LegendDefinitionsCollection(null, {
      configModel: {},
      layerDefinitionsCollection: new Backbone.Collection(),
      vizId: 'v-123'
    });

    LegendFactory.init(this.legendDefinitionsCollection);

    spyOn(LegendsView.prototype, '_changeStyle');

    this.queryRowsCollection = new QueryRowsCollection([], {
      configModel: this.configModel,
      querySchemaModel: this.querySchemaModel
    });

    spyOn(this.queryRowsCollection, 'fetch');

    this.layerContentModel = new LayerContentModel({}, {
      querySchemaModel: this.querySchemaModel,
      queryGeometryModel: this.queryGeometryModel,
      queryRowsCollection: this.queryRowsCollection
    });

    this.view = new LegendsView({
      mapDefinitionModel: this.mapDefModel,
      layerDefinitionModel: this.layerDefinitionModel,
      legendDefinitionsCollection: this.legendDefinitionsCollection,
      editorModel: this.editorModel,
      queryGeometryModel: this.queryGeometryModel,
      layerContentModel: this.layerContentModel,
      userActions: {
        saveLayer: jasmine.createSpy('saveLayer')
      },
      userModel: this.userModel,
      configModel: this.configModel,
      modals: FactoryModals.createModalService()
    });

    this.view.render();
  });

  describe('.render', function () {
    it('should render properly', function () {
      expect(_.size(this.view._subviews)).toBe(1); // [TabPaneView]
      expect(this.view.$el.text()).toContain('editor.legend.menu-tab-pane-labels.color');
      expect(this.view.$el.text()).toContain('editor.legend.menu-tab-pane-labels.size');
    });
  });

  it('should show/hide overlay properly', function () {
    this.layerDefinitionModel.set('visible', false);
    expect(this.view._overlayModel.get('visible')).toBe(true);

    this.layerDefinitionModel.set('visible', true);
    expect(this.view._overlayModel.get('visible')).toBe(false);
  });

  describe('._initModels', function () {
    it('should create _infoboxModel', function () {
      this.view._infoboxModel = undefined;
      expect(this.view._infoboxModel).not.toBeDefined();

      this.view._initModels();
      expect(this.view._infoboxModel).toBeDefined();
    });

    it('should create _overlayModel', function () {
      this.view._overlayModel = undefined;
      expect(this.view._overlayModel).not.toBeDefined();

      this.view._initModels();
      expect(this.view._overlayModel).toBeDefined();
    });
  });

  describe('._initBinds', function () {
    it('should call _changeStyle when editorModel:edition changes', function () {
      this.editorModel.set({edition: true});

      expect(LegendsView.prototype._changeStyle).toHaveBeenCalled();
    });
  });

  describe('._isErrored', function () {
    it('should return layerContentModel isErrored', function () {
      var isErroredSpy = spyOn(this.view._layerContentModel, 'isErrored');

      isErroredSpy.and.returnValue(false);
      expect(this.view._isErrored()).toBe(false);

      isErroredSpy.and.returnValue(true);
      expect(this.view._isErrored()).toBe(true);
    });
  });

  describe('._isLayerHidden', function () {
    it('should return true if layerDefinitionModel.visible is false', function () {
      this.layerDefinitionModel.set('visible', false, { silent: true });
      expect(this.view._isLayerHidden()).toBe(true);

      this.layerDefinitionModel.set('visible', true, { silent: true });
      expect(this.view._isLayerHidden()).toBe(false);
    });
  });

  describe('._showHiddenLayer', function () {
    it('should call layerDefinitionModel.toggleVisible', function () {
      spyOn(this.view._layerDefinitionModel, 'toggleVisible');

      this.view._showHiddenLayer();

      expect(this.view._layerDefinitionModel.toggleVisible).toHaveBeenCalled();
    });

    it('should call userActions.saveLayer', function () {
      this.view._showHiddenLayer();
      expect(this.view._userActions.saveLayer).toHaveBeenCalled();
    });
  });

  describe('.isStyleCompatible', function () {
    it('should return true if legend type is not size', function () {
      expect(this.view._isStyleCompatible('color')).toBe(true);
    });
  });

  describe('when layer has errors', function () {
    beforeEach(function () {
      spyOn(this.view, '_isErrored').and.returnValue(true);
      this.view.render();
    });

    describe('.render', function () {
      it('should render properly', function () {
        expect(this.view.$el.text()).toContain('editor.error-query.body');
      });
    });

    describe('._onQueryChanged', function () {
      it('should call render', function () {
        spyOn(this.view, 'render');

        this.view._onQueryChanged();

        expect(this.view.render).toHaveBeenCalled();
      });
    });
  });

  it('should not have any leaks', function () {
    expect(this.view).toHaveNoLeaks();
  });
});
<commit_msg>Add _renderError, and  _isStyleCompatible tests to LegendsView spec<commit_after>var Backbone = require('backbone');
var _ = require('underscore');
var ConfigModel = require('../../../../../../../javascripts/cartodb3/data/config-model');
var UserModel = require('../../../../../../../javascripts/cartodb3/data/user-model');
var LegendsView = require('../../../../../../../javascripts/cartodb3/editor/layers/layer-content-views/legend/legends-view');
var QuerySchemaModel = require('../../../../../../../javascripts/cartodb3/data/query-schema-model');
var QueryGeometryModel = require('../../../../../../../javascripts/cartodb3/data/query-geometry-model');
var LayerContentModel = require('../../../../../../../javascripts/cartodb3/data/layer-content-model');
var LegendDefinitionsCollection = require('../../../../../../../javascripts/cartodb3/data/legends/legend-definitions-collection');
var LegendFactory = require('../../../../../../../javascripts/cartodb3/editor/layers/layer-content-views/legend/legend-factory');
var LayerDefinitionsCollection = require('../../../../../../../javascripts/cartodb3/data/layer-definitions-collection');
var LayerDefinitionModel = require('../../../../../../../javascripts/cartodb3/data/layer-definition-model');
var AnalysisDefinitionNodesCollection = require('../../../../../../../javascripts/cartodb3/data/analysis-definition-nodes-collection');
var QueryRowsCollection = require('../../../../../../../javascripts/cartodb3/data/query-rows-collection');
var FactoryModals = require('../../../../factories/modals');
var sqlErrorTemplate = require('../../../../../../../javascripts/cartodb3/editor/layers/layer-content-views/legend/legend-content-sql-error.tpl');
var actionErrorTemplate = require('../../../../../../../javascripts/cartodb3/editor/layers/sql-error-action.tpl');

describe('editor/layers/layer-content-view/legend/legends-view', function () {
  beforeEach(function () {
    this.configModel = new ConfigModel({
      base_url: '/u/pepe'
    });

    this.userModel = new UserModel({}, {
      configModel: this.configModel
    });

    this.querySchemaModel = new QuerySchemaModel({
      query: 'SELECT * FROM table',
      status: 'fetched'
    }, {
      configModel: {}
    });

    spyOn(this.querySchemaModel, 'fetch');

    this.queryGeometryModel = new QueryGeometryModel({
      query: 'SELECT * FROM table',
      status: 'fetched',
      simple_geom: 'point'
    }, {
      configModel: {}
    });
    spyOn(this.queryGeometryModel, 'fetch');

    this.mapDefModel = new Backbone.Model({
      legends: true
    });

    this.editorModel = new Backbone.Model({
      edition: false
    });
    this.editorModel.isEditing = function () { return false; };
    this.editorModel.isDisabled = function () { return false; };

    this.analysisDefinitionNodesCollection = new AnalysisDefinitionNodesCollection(null, {
      configModel: this.configModel,
      userModel: this.userModel
    });

    this.a0 = this.analysisDefinitionNodesCollection.add({
      id: 'a0',
      type: 'source',
      table_name: 'foo'
    });
    spyOn(this.a0, 'isCustomQueryApplied').and.returnValue(false);

    this.layerDefinitionCollection = new LayerDefinitionsCollection(null, {
      configModel: this.configModel,
      userModel: this.userModel,
      analysisDefinitionNodesCollection: this.analysisDefinitionNodesCollection,
      mapId: 'm123',
      stateDefinitionModel: {}
    });
    this.layerDefinitionModel = new LayerDefinitionModel({
      id: 'abc-123',
      kind: 'carto',
      options: {
        type: 'CartoDB',
        color: '#FABADA',
        table_name: 'foo',
        query: 'SELECT * FROM foo',
        tile_style: 'asdasd',
        visible: true
      }
    }, {
      parse: true,
      configModel: this.configModel,
      collection: this.layerDefinitionCollection
    });
    spyOn(this.layerDefinitionModel, 'save');
    spyOn(this.layerDefinitionModel, 'getAnalysisDefinitionNodeModel').and.returnValue(this.a0);

    this.layerDefinitionModel.styleModel = new Backbone.Model({
      fill: {
        color: {
          fixed: '#892b27'
        },
        size: {
          attribute: 10
        }
      }
    });

    this.legendDefinitionsCollection = new LegendDefinitionsCollection(null, {
      configModel: {},
      layerDefinitionsCollection: new Backbone.Collection(),
      vizId: 'v-123'
    });

    LegendFactory.init(this.legendDefinitionsCollection);

    spyOn(LegendsView.prototype, '_changeStyle');

    this.queryRowsCollection = new QueryRowsCollection([], {
      configModel: this.configModel,
      querySchemaModel: this.querySchemaModel
    });

    spyOn(this.queryRowsCollection, 'fetch');

    this.layerContentModel = new LayerContentModel({}, {
      querySchemaModel: this.querySchemaModel,
      queryGeometryModel: this.queryGeometryModel,
      queryRowsCollection: this.queryRowsCollection
    });

    this.view = new LegendsView({
      mapDefinitionModel: this.mapDefModel,
      layerDefinitionModel: this.layerDefinitionModel,
      legendDefinitionsCollection: this.legendDefinitionsCollection,
      editorModel: this.editorModel,
      queryGeometryModel: this.queryGeometryModel,
      layerContentModel: this.layerContentModel,
      userActions: {
        saveLayer: jasmine.createSpy('saveLayer')
      },
      userModel: this.userModel,
      configModel: this.configModel,
      modals: FactoryModals.createModalService()
    });

    this.view.render();
  });

  describe('.render', function () {
    it('should render properly', function () {
      expect(_.size(this.view._subviews)).toBe(1); // [TabPaneView]
      expect(this.view.$el.text()).toContain('editor.legend.menu-tab-pane-labels.color');
      expect(this.view.$el.text()).toContain('editor.legend.menu-tab-pane-labels.size');
    });

    it('should render error template if layer content model is errored', function () {
      spyOn(this.layerContentModel, 'isErrored').and.returnValue(true);
      var errorTemplate = _t('editor.error-query.body', {
        action: actionErrorTemplate({
          label: _t('editor.error-query.label')
        })
      });

      this.view.render();

      expect(this.view.el.innerHTML).toBe(sqlErrorTemplate({ body: errorTemplate }));
    });
  });

  it('should show/hide overlay properly', function () {
    this.layerDefinitionModel.set('visible', false);
    expect(this.view._overlayModel.get('visible')).toBe(true);

    this.layerDefinitionModel.set('visible', true);
    expect(this.view._overlayModel.get('visible')).toBe(false);
  });

  describe('._initModels', function () {
    it('should create _infoboxModel', function () {
      this.view._infoboxModel = undefined;
      expect(this.view._infoboxModel).not.toBeDefined();

      this.view._initModels();
      expect(this.view._infoboxModel).toBeDefined();
    });

    it('should create _overlayModel', function () {
      this.view._overlayModel = undefined;
      expect(this.view._overlayModel).not.toBeDefined();

      this.view._initModels();
      expect(this.view._overlayModel).toBeDefined();
    });
  });

  describe('._initBinds', function () {
    it('should call _changeStyle when editorModel:edition changes', function () {
      this.editorModel.set({edition: true});

      expect(LegendsView.prototype._changeStyle).toHaveBeenCalled();
    });
  });

  describe('._isErrored', function () {
    it('should return layerContentModel isErrored', function () {
      var isErroredSpy = spyOn(this.view._layerContentModel, 'isErrored');

      isErroredSpy.and.returnValue(false);
      expect(this.view._isErrored()).toBe(false);

      isErroredSpy.and.returnValue(true);
      expect(this.view._isErrored()).toBe(true);
    });
  });

  describe('._isLayerHidden', function () {
    it('should return true if layerDefinitionModel.visible is false', function () {
      this.layerDefinitionModel.set('visible', false, { silent: true });
      expect(this.view._isLayerHidden()).toBe(true);

      this.layerDefinitionModel.set('visible', true, { silent: true });
      expect(this.view._isLayerHidden()).toBe(false);
    });
  });

  describe('._showHiddenLayer', function () {
    it('should call layerDefinitionModel.toggleVisible', function () {
      spyOn(this.view._layerDefinitionModel, 'toggleVisible');

      this.view._showHiddenLayer();

      expect(this.view._layerDefinitionModel.toggleVisible).toHaveBeenCalled();
    });

    it('should call userActions.saveLayer', function () {
      this.view._showHiddenLayer();
      expect(this.view._userActions.saveLayer).toHaveBeenCalled();
    });
  });

  describe('.isStyleCompatible', function () {
    it('should return true if legend type is not size', function () {
      expect(this.view._isStyleCompatible('color')).toBe(true);
    });

    it('should return true if any of the legends size is compatible', function () {
      expect(this.view._isStyleCompatible('size')).toBe(true);
    });

    it('should return false if no legend size is compatible', function () {
      this.view._layerDefinitionModel.styleModel = new Backbone.Model({});
      expect(this.view._isStyleCompatible('size')).toBe(false);
    });
  });

  describe('when layer has errors', function () {
    beforeEach(function () {
      spyOn(this.view, '_isErrored').and.returnValue(true);
      this.view.render();
    });

    describe('.render', function () {
      it('should render properly', function () {
        expect(this.view.$el.text()).toContain('editor.error-query.body');
      });
    });

    describe('._onQueryChanged', function () {
      it('should call render', function () {
        spyOn(this.view, 'render');

        this.view._onQueryChanged();

        expect(this.view.render).toHaveBeenCalled();
      });
    });
  });

  it('should not have any leaks', function () {
    expect(this.view).toHaveNoLeaks();
  });
});
<|endoftext|>


<commit_before>import React, { Component } from "react";
import { connect } from "react-redux";

import {
	addComponent,
	removeComponent,
	watchComponent,
	updateQuery,
	setQueryOptions
} from "@appbaseio/reactivecore/lib/actions";
import types from "@appbaseio/reactivecore/lib/utils/types";

class ReactiveComponent extends Component {
	constructor(props) {
		super(props);

		this.state = {
			hasError: false
		};

		this.internalComponent = null;

		let onQueryChange = null;
		if (props.onQueryChange) {
			onQueryChange = props.onQueryChange;
		}

		this.setQuery = (obj) => {
			this.props.updateQuery({
				...obj,
				componentId: props.componentId,
				label: props.filterLabel,
				showFilter: props.showFilter,
				onQueryChange,
				URLParams: props.URLParams
			});
		};

		if (props.defaultQuery) {
			this.internalComponent = `${props.componentId}__internal`;
		}
	}

	componentWillMount() {
		this.props.addComponent(this.props.componentId);
		if (this.internalComponent) {
			this.props.addComponent(this.internalComponent);
		}

		this.setReact(this.props);

		// set query for internal component
		if (this.internalComponent && this.props.defaultQuery) {
			const { query, ...queryOptions } = this.props.defaultQuery;

			if (queryOptions) {
				this.props.setQueryOptions(this.internalComponent, queryOptions, false);
			}

			this.props.updateQuery({
				componentId: this.internalComponent,
				query: query || null
			});
		}
	}

	componentDidCatch(error, info) {
		this.setState({ hasError: true });
	}

	componentWillUnmount() {
		this.props.removeComponent(this.props.componentId);

		if (this.internalComponent) {
			this.props.removeComponent(this.internalComponent);
		}
	}

	setReact = (props) => {
		const { react } = props;

		if (react) {
			if (this.internalComponent) {
				const newReact = pushToAndClause(react, this.internalComponent);
				props.watchComponent(props.componentId, newReact);
			} else {
				props.watchComponent(props.componentId, react);
			}
		} else if (this.internalComponent) {
			props.watchComponent(props.componentId, { and: this.internalComponent });
		}
	};

	render() {
		const {
			children,
			addComponent,
			watchComponent,
			removeComponent,
			setQueryOptions,
			updateQuery,
			...rest
		} = this.props;

		if (this.state.hasError) {
			return null;
		}

		const childrenWithProps = React.Children.map(children, child =>
			React.cloneElement(child, { ...rest, setQuery: this.setQuery })
		);

		return childrenWithProps;
	}
}

ReactiveComponent.defaultProps = {
	URLParams: false,
	showFilter: true
}

ReactiveComponent.propTypes = {
	componentId: types.stringRequired,
	hits: types.data,
	aggregations: types.selectedValues,
	selectedValue: types.selectedValue,
	addComponent: types.funcRequired,
	removeComponent: types.funcRequired,
	watchComponent: types.funcRequired,
	updateQuery: types.funcRequired,
	setQueryOptions: types.funcRequired,
	onQueryChange: types.func,
	URLParams: types.boolRequired,
	showFilter: types.bool,
	filterLabel: types.string,
	defaultQuery: types.selectedValues,
	react: types.react,
	children: types.children
};

const mapStateToProps = (state, props) => ({
	hits: state.hits[props.componentId] && state.hits[props.componentId].hits || [],
	aggregations: state.aggregations[props.componentId] && state.aggregations[props.componentId] || null,
	selectedValue: state.selectedValues[props.componentId] && state.selectedValues[props.componentId].value || null
});

const mapDispatchtoProps = dispatch => ({
	addComponent: component => dispatch(addComponent(component)),
	removeComponent: component => dispatch(removeComponent(component)),
	watchComponent: (component, react) => dispatch(watchComponent(component, react)),
	updateQuery: updateQueryObject => dispatch(updateQuery(updateQueryObject)),
	setQueryOptions: (component, props, execute) => dispatch(setQueryOptions(component, props, execute))
});

export default connect(mapStateToProps, mapDispatchtoProps)(ReactiveComponent);
<commit_msg>update ReactiveComponent to be react-v15 compatible<commit_after>import React, { Component } from "react";
import { connect } from "react-redux";

import {
	addComponent,
	removeComponent,
	watchComponent,
	updateQuery,
	setQueryOptions
} from "@appbaseio/reactivecore/lib/actions";
import types from "@appbaseio/reactivecore/lib/utils/types";

class ReactiveComponent extends Component {
	constructor(props) {
		super(props);

		this.internalComponent = null;

		let onQueryChange = null;
		if (props.onQueryChange) {
			onQueryChange = props.onQueryChange;
		}

		this.setQuery = (obj) => {
			this.props.updateQuery({
				...obj,
				componentId: props.componentId,
				label: props.filterLabel,
				showFilter: props.showFilter,
				onQueryChange,
				URLParams: props.URLParams
			});
		};

		if (props.defaultQuery) {
			this.internalComponent = `${props.componentId}__internal`;
		}
	}

	componentWillMount() {
		this.props.addComponent(this.props.componentId);
		if (this.internalComponent) {
			this.props.addComponent(this.internalComponent);
		}

		this.setReact(this.props);

		// set query for internal component
		if (this.internalComponent && this.props.defaultQuery) {
			const { query, ...queryOptions } = this.props.defaultQuery;

			if (queryOptions) {
				this.props.setQueryOptions(this.internalComponent, queryOptions, false);
			}

			this.props.updateQuery({
				componentId: this.internalComponent,
				query: query || null
			});
		}
	}

	componentWillUnmount() {
		this.props.removeComponent(this.props.componentId);

		if (this.internalComponent) {
			this.props.removeComponent(this.internalComponent);
		}
	}

	setReact = (props) => {
		const { react } = props;

		if (react) {
			if (this.internalComponent) {
				const newReact = pushToAndClause(react, this.internalComponent);
				props.watchComponent(props.componentId, newReact);
			} else {
				props.watchComponent(props.componentId, react);
			}
		} else if (this.internalComponent) {
			props.watchComponent(props.componentId, { and: this.internalComponent });
		}
	};

	render() {
		const {
			children,
			addComponent,
			watchComponent,
			removeComponent,
			setQueryOptions,
			updateQuery,
			...rest
		} = this.props;

		try {
			const childrenWithProps = React.Children.map(children, child =>
				React.cloneElement(child, { ...rest, setQuery: this.setQuery })
			);
			return <div>{childrenWithProps}</div>;
		} catch(e) {
			return null;
		}
	}
}

ReactiveComponent.defaultProps = {
	URLParams: false,
	showFilter: true
}

ReactiveComponent.propTypes = {
	componentId: types.stringRequired,
	hits: types.data,
	aggregations: types.selectedValues,
	selectedValue: types.selectedValue,
	addComponent: types.funcRequired,
	removeComponent: types.funcRequired,
	watchComponent: types.funcRequired,
	updateQuery: types.funcRequired,
	setQueryOptions: types.funcRequired,
	onQueryChange: types.func,
	URLParams: types.boolRequired,
	showFilter: types.bool,
	filterLabel: types.string,
	defaultQuery: types.selectedValues,
	react: types.react,
	children: types.children
};

const mapStateToProps = (state, props) => ({
	hits: state.hits[props.componentId] && state.hits[props.componentId].hits || [],
	aggregations: state.aggregations[props.componentId] && state.aggregations[props.componentId] || null,
	selectedValue: state.selectedValues[props.componentId] && state.selectedValues[props.componentId].value || null
});

const mapDispatchtoProps = dispatch => ({
	addComponent: component => dispatch(addComponent(component)),
	removeComponent: component => dispatch(removeComponent(component)),
	watchComponent: (component, react) => dispatch(watchComponent(component, react)),
	updateQuery: updateQueryObject => dispatch(updateQuery(updateQueryObject)),
	setQueryOptions: (component, props, execute) => dispatch(setQueryOptions(component, props, execute))
});

export default connect(mapStateToProps, mapDispatchtoProps)(ReactiveComponent);
<|endoftext|>


<commit_before>import L from 'leaflet';
import { RasterLayer } from './RasterLayer';
import { cleanUrl } from '../Util';
import imageService from '../Services/ImageService';

export var ImageMapLayer = RasterLayer.extend({

  options: {
    updateInterval: 150,
    format: 'jpgpng',
    transparent: true,
    f: 'json'
  },

  query: function () {
    return this.service.query();
  },

  identify: function () {
    return this.service.identify();
  },

  initialize: function (options) {
    options.url = cleanUrl(options.url);
    this.service = imageService(options);
    this.service.addEventParent(this);

    L.Util.setOptions(this, options);
  },

  setPixelType: function (pixelType) {
    this.options.pixelType = pixelType;
    this._update();
    return this;
  },

  getPixelType: function () {
    return this.options.pixelType;
  },

  setBandIds: function (bandIds) {
    if (L.Util.isArray(bandIds)) {
      this.options.bandIds = bandIds.join(',');
    } else {
      this.options.bandIds = bandIds.toString();
    }
    this._update();
    return this;
  },

  getBandIds: function () {
    return this.options.bandIds;
  },

  setNoData: function (noData, noDataInterpretation) {
    if (L.Util.isArray(noData)) {
      this.options.noData = noData.join(',');
    } else {
      this.options.noData = noData.toString();
    }
    if (noDataInterpretation) {
      this.options.noDataInterpretation = noDataInterpretation;
    }
    this._update();
    return this;
  },

  getNoData: function () {
    return this.options.noData;
  },

  getNoDataInterpretation: function () {
    return this.options.noDataInterpretation;
  },

  setRenderingRule: function (renderingRule) {
    this.options.renderingRule = renderingRule;
    this._update();
  },

  getRenderingRule: function () {
    return this.options.renderingRule;
  },

  setMosaicRule: function (mosaicRule) {
    this.options.mosaicRule = mosaicRule;
    this._update();
  },

  getMosaicRule: function () {
    return this.options.mosaicRule;
  },

  _getPopupData: function (e) {
    var callback = L.Util.bind(function (error, results, response) {
      if (error) { return; } // we really can't do anything here but authenticate or requesterror will fire
      setTimeout(L.Util.bind(function () {
        this._renderPopup(e.latlng, error, results, response);
      }, this), 300);
    }, this);

    var identifyRequest = this.identify().at(e.latlng);

    // set mosaic rule for identify task if it is set for layer
    if (this.options.mosaicRule) {
      identifyRequest.setMosaicRule(this.options.mosaicRule);
      // @TODO: force return catalog items too?
    }

    // @TODO: set rendering rule? Not sure,
    // sometimes you want raw pixel values
    // if (this.options.renderingRule) {
    //   identifyRequest.setRenderingRule(this.options.renderingRule);
    // }

    identifyRequest.run(callback);

    // set the flags to show the popup
    this._shouldRenderPopup = true;
    this._lastClick = e.latlng;
  },

  _buildExportParams: function () {
    var bounds = this._map.getBounds();
    var size = this._map.getSize();
    var ne = this._map.options.crs.project(bounds._northEast);
    var sw = this._map.options.crs.project(bounds._southWest);

    var params = {
      bbox: [sw.x, sw.y, ne.x, ne.y].join(','),
      size: size.x + ',' + size.y,
      format: this.options.format,
      transparent: this.options.transparent,
      bboxSR: this.options.bboxSR,
      imageSR: this.options.imageSR
    };

    if (this.options.from && this.options.to) {
      params.time = this.options.from.valueOf() + ',' + this.options.to.valueOf();
    }

    if (this.options.pixelType) {
      params.pixelType = this.options.pixelType;
    }

    if (this.options.interpolation) {
      params.interpolation = this.options.interpolation;
    }

    if (this.options.compressionQuality) {
      params.compressionQuality = this.options.compressionQuality;
    }

    if (this.options.bandIds) {
      params.bandIds = this.options.bandIds;
    }

    if (this.options.noData) {
      params.noData = this.options.noData;
    }

    if (this.options.noDataInterpretation) {
      params.noDataInterpretation = this.options.noDataInterpretation;
    }

    if (this.service.options.token) {
      params.token = this.service.options.token;
    }

    if (this.options.renderingRule) {
      params.renderingRule = JSON.stringify(this.options.renderingRule);
    }

    if (this.options.mosaicRule) {
      params.mosaicRule = JSON.stringify(this.options.mosaicRule);
    }

    return params;
  },

  _requestExport: function (params, bounds) {
    if (this.options.f === 'json') {
      this.service.get('exportImage', params, function (error, response) {
        if (error) { return; } // we really can't do anything here but authenticate or requesterror will fire
        this._renderImage(response.href, bounds);
      }, this);
    } else {
      params.f = 'image';
      this._renderImage(this.options.url + 'exportImage' + L.Util.getParamString(params), bounds);
    }
  }
});

export function imageMapLayer (url, options) {
  return new ImageMapLayer(url, options);
}

export default imageMapLayer;
<commit_msg>revert ImageMapLayer to use L.esri.request<commit_after>import L from 'leaflet';
import { RasterLayer } from './RasterLayer';
import { cleanUrl } from '../Util';
import imageService from '../Services/ImageService';

export var ImageMapLayer = RasterLayer.extend({

  options: {
    updateInterval: 150,
    format: 'jpgpng',
    transparent: true,
    f: 'json'
  },

  query: function () {
    return this.service.query();
  },

  identify: function () {
    return this.service.identify();
  },

  initialize: function (options) {
    options.url = cleanUrl(options.url);
    this.service = imageService(options);
    this.service.addEventParent(this);

    L.Util.setOptions(this, options);
  },

  setPixelType: function (pixelType) {
    this.options.pixelType = pixelType;
    this._update();
    return this;
  },

  getPixelType: function () {
    return this.options.pixelType;
  },

  setBandIds: function (bandIds) {
    if (L.Util.isArray(bandIds)) {
      this.options.bandIds = bandIds.join(',');
    } else {
      this.options.bandIds = bandIds.toString();
    }
    this._update();
    return this;
  },

  getBandIds: function () {
    return this.options.bandIds;
  },

  setNoData: function (noData, noDataInterpretation) {
    if (L.Util.isArray(noData)) {
      this.options.noData = noData.join(',');
    } else {
      this.options.noData = noData.toString();
    }
    if (noDataInterpretation) {
      this.options.noDataInterpretation = noDataInterpretation;
    }
    this._update();
    return this;
  },

  getNoData: function () {
    return this.options.noData;
  },

  getNoDataInterpretation: function () {
    return this.options.noDataInterpretation;
  },

  setRenderingRule: function (renderingRule) {
    this.options.renderingRule = renderingRule;
    this._update();
  },

  getRenderingRule: function () {
    return this.options.renderingRule;
  },

  setMosaicRule: function (mosaicRule) {
    this.options.mosaicRule = mosaicRule;
    this._update();
  },

  getMosaicRule: function () {
    return this.options.mosaicRule;
  },

  _getPopupData: function (e) {
    var callback = L.Util.bind(function (error, results, response) {
      if (error) { return; } // we really can't do anything here but authenticate or requesterror will fire
      setTimeout(L.Util.bind(function () {
        this._renderPopup(e.latlng, error, results, response);
      }, this), 300);
    }, this);

    var identifyRequest = this.identify().at(e.latlng);

    // set mosaic rule for identify task if it is set for layer
    if (this.options.mosaicRule) {
      identifyRequest.setMosaicRule(this.options.mosaicRule);
      // @TODO: force return catalog items too?
    }

    // @TODO: set rendering rule? Not sure,
    // sometimes you want raw pixel values
    // if (this.options.renderingRule) {
    //   identifyRequest.setRenderingRule(this.options.renderingRule);
    // }

    identifyRequest.run(callback);

    // set the flags to show the popup
    this._shouldRenderPopup = true;
    this._lastClick = e.latlng;
  },

  _buildExportParams: function () {
    var bounds = this._map.getBounds();
    var size = this._map.getSize();
    var ne = this._map.options.crs.project(bounds._northEast);
    var sw = this._map.options.crs.project(bounds._southWest);

    var params = {
      bbox: [sw.x, sw.y, ne.x, ne.y].join(','),
      size: size.x + ',' + size.y,
      format: this.options.format,
      transparent: this.options.transparent,
      bboxSR: this.options.bboxSR,
      imageSR: this.options.imageSR
    };

    if (this.options.from && this.options.to) {
      params.time = this.options.from.valueOf() + ',' + this.options.to.valueOf();
    }

    if (this.options.pixelType) {
      params.pixelType = this.options.pixelType;
    }

    if (this.options.interpolation) {
      params.interpolation = this.options.interpolation;
    }

    if (this.options.compressionQuality) {
      params.compressionQuality = this.options.compressionQuality;
    }

    if (this.options.bandIds) {
      params.bandIds = this.options.bandIds;
    }

    if (this.options.noData) {
      params.noData = this.options.noData;
    }

    if (this.options.noDataInterpretation) {
      params.noDataInterpretation = this.options.noDataInterpretation;
    }

    if (this.service.options.token) {
      params.token = this.service.options.token;
    }

    if (this.options.renderingRule) {
      params.renderingRule = JSON.stringify(this.options.renderingRule);
    }

    if (this.options.mosaicRule) {
      params.mosaicRule = JSON.stringify(this.options.mosaicRule);
    }

    return params;
  },

  _requestExport: function (params, bounds) {
    if (this.options.f === 'json') {
      this.service.request('exportImage', params, function (error, response) {
        if (error) { return; } // we really can't do anything here but authenticate or requesterror will fire
        this._renderImage(response.href, bounds);
      }, this);
    } else {
      params.f = 'image';
      this._renderImage(this.options.url + 'exportImage' + L.Util.getParamString(params), bounds);
    }
  }
});

export function imageMapLayer (url, options) {
  return new ImageMapLayer(url, options);
}

export default imageMapLayer;
<|endoftext|>


<commit_before>'use strict';

// This code uses ES2015 syntax that requires at least Node.js v4.
// For Node.js ES2015 support details, reference http://node.green/

function validateArgumentType(arg, argName, expectedType) {
    if (typeof arg === 'undefined') {
        throw new Error('Missing argument: ' + argName + '. ' +
            'Expected type: ' + expectedType + '.');
    } else if (typeof arg !== expectedType) {
        throw new Error('Invalid argument: ' + argName + '. ' +
            'Expected type: ' + expectedType + ', got: ' + (typeof arg));
    }
}

// Helper method to convert the device schema to the translator schema.
function providerSchemaToPlatformSchema(providerSchema, expand) {

    var power = {
        href: '/power',
        rt: ['oic.r.switch.binary'],
        if: ['oic.if.a', 'oic.if.baseline']
    };

    if (expand) {
        power.id = 'power';
        power.value = providerSchema['attributes'].switch == 'on';
    }

    return {
        opent2t: {
            schema: 'org.opent2t.sample.binaryswitch.superpopular',
            translator: 'opent2t-translator-com-smartthings-binaryswitch',
            controlId: controlId
        },
        pi: providerSchema['id'],
        mnmn: providerSchema['manufacturer'],
        mnmo: providerSchema['model'],
        n: providerSchema['name'],
        rt: ['org.opent2t.sample.binaryswitch.superpopular'],
        entities: [
            {
                rt: ['oic.d.smartplug'],
                di: providerSchema['id'],
                resources: [ power ]
            }
        ]
    };
}

// Helper method to convert the translator schema to the device schema.
function resourceSchemaToProviderSchema(resourceId, resourceSchema) {

    // build the object with desired state
    var result = {};

    if ('power' === resourceId) {
        result['switch'] = resourceSchema.value ? 'on' : 'off';
    }

    return result;
}

function findResource(schema, di, resourceId) {
    var entity = schema.entities.find((d) => {
        return d.di === di;
    });

    var resource = entity.resources.find((r) => {
        return r.id === resourceId;
    });

    return resource;
}

function getDeviceResource(translator, di, resourceId) {
    return translator.get(true)
        .then(response => {
            return findResource(response, di, resourceId);
        });
}

function postDeviceResource(di, resourceId, payload) {
    var putPayload = resourceSchemaToProviderSchema(resourceId, payload);

    return smartThingsHub.putDeviceDetailsAsync(controlId, putPayload)
        .then((response) => {
            var schema = providerSchemaToPlatformSchema(response, true);

            return findResource(schema, di, resourceId);
        });
}

var controlId;
var smartThingsHub;

// This translator class implements the 'org.opent2t.sample.binaryswitch.superpopular' interface.
class Translator {

    constructor(deviceInfo) {
        console.log('SmartThings Binary Switch initializing...');

        validateArgumentType(deviceInfo, "deviceInfo", "object");

        controlId = deviceInfo.deviceInfo.opent2t.controlId;
        smartThingsHub = deviceInfo.hub;

        console.log('SmartThings Binary Switch initializing...Done');
    }

    // exports for the entire schema object

    // Queries the entire state of the outlet
    // and returns an object that maps to the json schema org.opent2t.sample.binaryswitch.superpopular
    get(expand, payload) {
        if (payload) {
            return providerSchemaToPlatformSchema(payload, expand);
        }
        else {
            return smartThingsHub.getDeviceDetailsAsync(controlId)
                .then((response) => {
                    return providerSchemaToPlatformSchema(response, expand);
                });
        }
    }

    getDevicesPower(di) {
        return getDeviceResource(this, di, 'power');
    }

    postDevicesPower(di, payload) {
        return postDeviceResource(di, 'power', payload);
    }

    /* eslint no-unused-vars: "off" */
    postSubscribe(callbackUrl, verificationRequest) {
        return smartThingsHub._subscribe(controlId);
    }

    deleteSubscribe(callbackUrl) {
        return smartThingsHub._unsubscribe(controlId);
    }
    /* eslint no-unused-vars: "warn" */
}

// Export the translator from the module.
module.exports = Translator;
<commit_msg>Check for device ID when changing device properties<commit_after>'use strict';

// This code uses ES2015 syntax that requires at least Node.js v4.
// For Node.js ES2015 support details, reference http://node.green/

function validateArgumentType(arg, argName, expectedType) {
    if (typeof arg === 'undefined') {
        throw new Error('Missing argument: ' + argName + '. ' +
            'Expected type: ' + expectedType + '.');
    } else if (typeof arg !== expectedType) {
        throw new Error('Invalid argument: ' + argName + '. ' +
            'Expected type: ' + expectedType + ', got: ' + (typeof arg));
    }
}

// Helper method to convert the device schema to the translator schema.
function providerSchemaToPlatformSchema(providerSchema, expand) {

    var power = {
        href: '/power',
        rt: ['oic.r.switch.binary'],
        if: ['oic.if.a', 'oic.if.baseline']
    };

    if (expand) {
        power.id = 'power';
        power.value = providerSchema['attributes'].switch == 'on';
    }

    return {
        opent2t: {
            schema: 'org.opent2t.sample.binaryswitch.superpopular',
            translator: 'opent2t-translator-com-smartthings-binaryswitch',
            controlId: controlId
        },
        pi: providerSchema['id'],
        mnmn: providerSchema['manufacturer'],
        mnmo: providerSchema['model'],
        n: providerSchema['name'],
        rt: ['org.opent2t.sample.binaryswitch.superpopular'],
        entities: [
            {
                rt: ['oic.d.smartplug'],
                di: providerSchema['id'],
                resources: [ power ]
            }
        ]
    };
}

// Helper method to convert the translator schema to the device schema.
function resourceSchemaToProviderSchema(resourceId, resourceSchema) {

    // build the object with desired state
    var result = {};

    if ('power' === resourceId) {
        result['switch'] = resourceSchema.value ? 'on' : 'off';
    }

    return result;
}

function findResource(schema, di, resourceId) {
    var entity = schema.entities.find((d) => {
        return d.di === di;
    });

    var resource = entity.resources.find((r) => {
        return r.id === resourceId;
    });

    return resource;
}

function getDeviceResource(translator, di, resourceId) {
    return translator.get(true)
        .then(response => {
            return findResource(response, di, resourceId);
        });
}

function postDeviceResource(di, resourceId, payload) {
    if (di === controlId){
        var putPayload = resourceSchemaToProviderSchema(resourceId, payload);

        return smartThingsHub.putDeviceDetailsAsync(controlId, putPayload)
            .then((response) => {
                var schema = providerSchemaToPlatformSchema(response, true);

                return findResource(schema, di, resourceId);
            });
    } else {
        throw new Error('NotFound');
    }
}

var controlId;
var smartThingsHub;

// This translator class implements the 'org.opent2t.sample.binaryswitch.superpopular' interface.
class Translator {

    constructor(deviceInfo) {
        console.log('SmartThings Binary Switch initializing...');

        validateArgumentType(deviceInfo, "deviceInfo", "object");

        controlId = deviceInfo.deviceInfo.opent2t.controlId;
        smartThingsHub = deviceInfo.hub;

        console.log('SmartThings Binary Switch initializing...Done');
    }

    // exports for the entire schema object

    // Queries the entire state of the outlet
    // and returns an object that maps to the json schema org.opent2t.sample.binaryswitch.superpopular
    get(expand, payload) {
        if (payload) {
            return providerSchemaToPlatformSchema(payload, expand);
        }
        else {
            return smartThingsHub.getDeviceDetailsAsync(controlId)
                .then((response) => {
                    return providerSchemaToPlatformSchema(response, expand);
                });
        }
    }

    getDevicesPower(di) {
        return getDeviceResource(this, di, 'power');
    }

    postDevicesPower(di, payload) {
        return postDeviceResource(di, 'power', payload);
    }

    /* eslint no-unused-vars: "off" */
    postSubscribe(callbackUrl, verificationRequest) {
        return smartThingsHub._subscribe(controlId);
    }

    deleteSubscribe(callbackUrl) {
        return smartThingsHub._unsubscribe(controlId);
    }
    /* eslint no-unused-vars: "warn" */
}

// Export the translator from the module.
module.exports = Translator;
<|endoftext|>


<commit_before>'use strict';

function Floating2DText(w, text, type, scene, current_color) {
    this.__init__(w, text, type, scene, current_color);
}

const TEMP_SMUDGE_FACTOR = 0.75;

Floating2DText.prototype = {

    material: null,
    dynamic_texture: null,

    background_color: null,

    _update_text: function() {
        if (this.text !== ICON_LEFT && this.text !== ICON_RIGHT && this.text !== ICON_CROSS) {
            if (this.type === TYPE_BUTTON || this.type === TYPE_CHECK_BOX || this.type === TYPE_TITLE || this.type === TYPE_TITLE_CONSTANT || this.type === TYPE_SUPER_TITLE_CONSTANT || this.type === TYPE_SUPER_TITLE) {
                this.dynamic_texture.clear(this.background_color).drawText(this.text, this.texture_width / 2 - this.get_text_length() / 2, this.font_size * TEMP_SMUDGE_FACTOR, this.current_color, this.background_color);
            } else {
                this.dynamic_texture.clear(this.background_color).drawText(this.text, 0, this.font_size * TEMP_SMUDGE_FACTOR, this.current_color, this.background_color);
            }
            this.dynamic_texture.needsUpdate = true;
        }
    },

    // NOTE : Values are different for testing purposes.

    _update_color: function() {
        if (this.text !== ICON_LEFT && this.text !== ICON_RIGHT && this.text !== ICON_CROSS) {
            if (this.type === TYPE_BUTTON || this.type === TYPE_CHECK_BOX || this.type === TYPE_TITLE || this.type === TYPE_TITLE_CONSTANT || this.type === TYPE_SUPER_TITLE_CONSTANT || this.type === TYPE_SUPER_TITLE) {
                this.dynamic_texture.clear(this.background_color).drawText(this.text, this.texture_width / 2 - this.get_text_length() / 2, this.font_size * TEMP_SMUDGE_FACTOR, this.current_color, this.background_color);
            } else {
                this.dynamic_texture.clear(this.background_color).drawText(this.text, 0, this.font_size * TEMP_SMUDGE_FACTOR, this.current_color, this.background_color);
            }
            if (this.background_color === COLOR_TRANSPARENT) {
                this.dynamic_texture.transparent = true;
            }
            this.dynamic_texture.needsUpdate = true;
        }
    },

    _update_width: function(width) {
        this.width = width;
        this.material.dispose();
        this.geometry.dispose();
        this.mesh.dispose();
        this.object3D.remove(this.mesh);
        this.initialize(false);
    },

    initialize: function(add_to_scene) {
        //this.background_color = BACKGROUND_COLOR_DEFAULT;
        this.background_color = COLOR_TRANSPARENT;

        if (this.type === TYPE_TITLE || this.type === TYPE_TITLE_CONSTANT) {
            this.height = 26;
        } else {
            this.height = 16;
        }

        // PlaneGeometry takes in a width, height, optionalWidthSegments (default 1), optionalHeightSegments (default 1)
        this.geometry = new THREE.PlaneGeometry(this.width, this.height);

        if (this.text === ICON_LEFT || this.text === ICON_RIGHT || this.text === ICON_CROSS) {
            this.material = new THREE.MeshBasicMaterial({
                map : MANAGER_WORLD.get_icon_texture(this.text)
            });
            this.material.transparent = true;
        } else {
            this.texture_width = get_nearest_power_of_two_for_number(this.width * 2);
            var texture_height = get_nearest_power_of_two_for_number(this.height * 2);
            //var font_size = Math.round(texture_height * .8);
            this.font_size = texture_height;

            //l('Font size is : ' + font_size);

            this.dynamic_texture = new THREEx.DynamicTexture(this.texture_width, texture_height);
            if (this.type === TYPE_TITLE) {
                this.dynamic_texture.context.font = 'Bold ' + str(this.font_size) + 'px Arial';
            } else {
                this.dynamic_texture.context.font = str(this.font_size) + 'px Arial';
            }

            this.dynamic_texture.texture.anisotropy = MANAGER_RENDERER.renderer.capabilities.getMaxAnisotropy();

            this.material = new THREE.MeshBasicMaterial({
                map : this.dynamic_texture.texture
            });

            this.material.transparent = false;
            // TODO : Temporary for debugging.
            this.material.side = THREE.FrontSide;
            //this.material.side = THREE.DoubleSide;

            this._update_color();
            this._update_text();
        }

        this.mesh = new THREE.Mesh(this.geometry, this.material);

        /*
        // Shader testing
        this.shader_material = new THREE.ShaderMaterial({
            uniforms: {
                'c': {type: 'f', value: 1.0},
                'p': {type: 'f', value: 6},
                glowColor: {type: 'c', value: new THREE.Color(0xffff00)},
                viewVector: {type: 'v3', value: this.object3D.position}
            },
            vertexShader: MANAGER_SHADER.VERTEX_GLOW,
            fragmentShader: MANAGER_SHADER.FRAGMENT_GLOW,
            side: THREE.BackSide,
            blending: THREE.AdditiveBlending,
            transparent: true
        });

        // TODO : Investigate if shader_material needs to be cloned or not.
        this.glow = new THREE.Mesh(this.geometry.clone(), this.shader_material.clone());
        //this.glow.position = this.mesh.position;
        this.glow.scale.multiplyScalar(1.4);
        //

        this.object3D.add(this.glow);
        */

        //
        //

        this.object3D.add(this.mesh);

        if (!is_defined(add_to_scene)) {
            if (is_defined(this.scene)) {
                this.scene.add(this.object3D);
            }
        } else {
            if (add_to_scene) {
                this.scene.add(this.object3D);
            }
        }
    },

    __init__: function(w, text, type, scene, current_color) {
        this.is_2D_text = true;

        // Inherit from FloatingText.
        FloatingText.call(this, w, text, type, scene, current_color);
        // Inherit from Interactive.
        Interactive.call(this);
        // Inherit from Visibility.
        Visibility.call(this);

        this.final_initialize();
    }

};
<commit_msg>general updating 17<commit_after>'use strict';

function Floating2DText(w, text, type, scene, current_color) {
    this.__init__(w, text, type, scene, current_color);
}

const TEMP_SMUDGE_FACTOR = 0.75;

Floating2DText.prototype = {

    material: null,
    dynamic_texture: null,

    background_color: null,

    _update_text: function() {
        if (this.text !== ICON_LEFT && this.text !== ICON_RIGHT && this.text !== ICON_CROSS) {
            if (this.type === TYPE_BUTTON || this.type === TYPE_CHECK_BOX || this.type === TYPE_TITLE || this.type === TYPE_TITLE_CONSTANT || this.type === TYPE_SUPER_TITLE_CONSTANT || this.type === TYPE_SUPER_TITLE) {
                this.dynamic_texture.clear(this.background_color).drawText(this.text, this.texture_width / 2 - this.get_text_length() / 2, this.font_size * TEMP_SMUDGE_FACTOR, this.current_color, this.background_color);
            } else {
                this.dynamic_texture.clear(this.background_color).drawText(this.text, 0, this.font_size * TEMP_SMUDGE_FACTOR, this.current_color, this.background_color);
            }
            this.dynamic_texture.needsUpdate = true;
        }
    },

    // NOTE : Values are different for testing purposes.

    _update_color: function() {
        if (this.text !== ICON_LEFT && this.text !== ICON_RIGHT && this.text !== ICON_CROSS) {
            if (this.type === TYPE_BUTTON || this.type === TYPE_CHECK_BOX || this.type === TYPE_TITLE || this.type === TYPE_TITLE_CONSTANT || this.type === TYPE_SUPER_TITLE_CONSTANT || this.type === TYPE_SUPER_TITLE) {
                this.dynamic_texture.clear(this.background_color).drawText(this.text, this.texture_width / 2 - this.get_text_length() / 2, this.font_size * TEMP_SMUDGE_FACTOR, this.current_color, this.background_color);
            } else {
                this.dynamic_texture.clear(this.background_color).drawText(this.text, 0, this.font_size * TEMP_SMUDGE_FACTOR, this.current_color, this.background_color);
            }
            this.dynamic_texture.needsUpdate = true;
        }
    },

    _update_width: function(width) {
        this.width = width;
        this.material.dispose();
        this.geometry.dispose();
        this.mesh.dispose();
        this.object3D.remove(this.mesh);
        this.initialize(false);
    },

    initialize: function(add_to_scene) {
        //this.background_color = BACKGROUND_COLOR_DEFAULT;
        this.background_color = COLOR_TRANSPARENT;

        if (this.type === TYPE_TITLE || this.type === TYPE_TITLE_CONSTANT) {
            this.height = 26;
        } else {
            this.height = 16;
        }

        // PlaneGeometry takes in a width, height, optionalWidthSegments (default 1), optionalHeightSegments (default 1)
        this.geometry = new THREE.PlaneGeometry(this.width, this.height);

        if (this.text === ICON_LEFT || this.text === ICON_RIGHT || this.text === ICON_CROSS) {
            this.material = new THREE.MeshBasicMaterial({
                map : MANAGER_WORLD.get_icon_texture(this.text)
            });
            this.material.transparent = true;
        } else {
            this.texture_width = get_nearest_power_of_two_for_number(this.width * 2);
            var texture_height = get_nearest_power_of_two_for_number(this.height * 2);
            //var font_size = Math.round(texture_height * .8);
            this.font_size = texture_height;

            //l('Font size is : ' + font_size);

            this.dynamic_texture = new THREEx.DynamicTexture(this.texture_width, texture_height);
            if (this.type === TYPE_TITLE) {
                this.dynamic_texture.context.font = 'Bold ' + str(this.font_size) + 'px Arial';
            } else {
                this.dynamic_texture.context.font = str(this.font_size) + 'px Arial';
            }

            this.dynamic_texture.texture.anisotropy = MANAGER_RENDERER.renderer.capabilities.getMaxAnisotropy();

            this.material = new THREE.MeshBasicMaterial({
                map : this.dynamic_texture.texture
            });

            this.material.transparent = true;
            // TODO : Temporary for debugging.
            this.material.side = THREE.FrontSide;
            //this.material.side = THREE.DoubleSide;

            this._update_color();
            this._update_text();
        }

        this.mesh = new THREE.Mesh(this.geometry, this.material);

        /*
        // Shader testing
        this.shader_material = new THREE.ShaderMaterial({
            uniforms: {
                'c': {type: 'f', value: 1.0},
                'p': {type: 'f', value: 6},
                glowColor: {type: 'c', value: new THREE.Color(0xffff00)},
                viewVector: {type: 'v3', value: this.object3D.position}
            },
            vertexShader: MANAGER_SHADER.VERTEX_GLOW,
            fragmentShader: MANAGER_SHADER.FRAGMENT_GLOW,
            side: THREE.BackSide,
            blending: THREE.AdditiveBlending,
            transparent: true
        });

        // TODO : Investigate if shader_material needs to be cloned or not.
        this.glow = new THREE.Mesh(this.geometry.clone(), this.shader_material.clone());
        //this.glow.position = this.mesh.position;
        this.glow.scale.multiplyScalar(1.4);
        //

        this.object3D.add(this.glow);
        */

        //
        //

        this.object3D.add(this.mesh);

        if (!is_defined(add_to_scene)) {
            if (is_defined(this.scene)) {
                this.scene.add(this.object3D);
            }
        } else {
            if (add_to_scene) {
                this.scene.add(this.object3D);
            }
        }
    },

    __init__: function(w, text, type, scene, current_color) {
        this.is_2D_text = true;

        // Inherit from FloatingText.
        FloatingText.call(this, w, text, type, scene, current_color);
        // Inherit from Interactive.
        Interactive.call(this);
        // Inherit from Visibility.
        Visibility.call(this);

        this.final_initialize();
    }

};
<|endoftext|>