<commit_before>/*
 * Copyright (c) 2014 Adobe Systems Incorporated. All rights reserved.
 *  
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"), 
 * to deal in the Software without restriction, including without limitation 
 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 
 * and/or sell copies of the Software, and to permit persons to whom the 
 * Software is furnished to do so, subject to the following conditions:
 *  
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *  
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
 * DEALINGS IN THE SOFTWARE.
 * 
 */


define(function (require, exports, module) {
    "use strict";

    var React = require("react"),
        Fluxxor = require("fluxxor"),
        FluxMixin = Fluxxor.FluxMixin(React),
        Immutable = require("immutable");

    //HACK - temporarily here to listen to history events
    var descriptor = require("adapter/ps/descriptor"),
        photoshopEvent = require("adapter/lib/photoshopEvent");

    var Label = require("jsx!js/jsx/shared/Label"),
        Gutter = require("jsx!js/jsx/shared/Gutter"),
        NumberInput = require("jsx!js/jsx/shared/NumberInput"),
        SplitButton = require("jsx!js/jsx/shared/SplitButton"),
        SplitButtonList = SplitButton.SplitButtonList,
        SplitButtonItem = SplitButton.SplitButtonItem,
        strings = require("i18n!nls/strings"),
        collection = require("js/util/collection");

    var RotateFlip = React.createClass({
        mixins: [FluxMixin],
        
        propTypes: {
            document: React.PropTypes.object,
            layers: React.PropTypes.arrayOf(React.PropTypes.object)
        },

        /**
         * Last angle on input for relative rotation
         *
         * @type {number}
         */
        _lastAngle: null,

        componentWillReceiveProps: function (nextProps) {
            // Reset this flag every time we receive new props
            this.setState({
                undo: false
            });
        },

        getInitialState: function () {
            return {
                undo: false
            };
        },

        shouldComponentUpdate: function (nextProps, nextState) {
            var curDocument = this.props.document,
                nextDocument = nextProps.document,
                curLayers = curDocument ? curDocument.layers.selected : Immutable.List(),
                nextLayers = nextDocument ? nextDocument.layers.selected : Immutable.List(),
                curLayerIDs = collection.pluck(curLayers, "id"),
                nextLayerIDs = collection.pluck(nextLayers, "id");

            return nextState.undo || !Immutable.is(curLayerIDs, nextLayerIDs);
        },

        componentWillUpdate: function () {
            this._lastAngle = 0;
        },

        componentWillMount: function () {
            // HACK - on Undo, we want to reset this to 0, so we set a flag
            descriptor.addListener("select", function (event) {
                if (photoshopEvent.targetOf(event) === "historyState") {
                    this.setState({
                        undo: true
                    });
                }
            }.bind(this));
        },

        /**
         * Flips the layer horizontally
         * 
         * @private
         */
        _flipX: function () {
            var document = this.props.document,
                layers = document.layers.selected;

            this.getFlux().actions.transform.flipX(document, layers);
        },
        
        /**
         * Flips the layer vertically
         * 
         * @private
         */
        _flipY: function () {
            var document = this.props.document,
                layers = document.layers.selected;

            this.getFlux().actions.transform.flipY(document, layers);
        },

        /**
         * Swaps the two selected layers
         * 
         * @private
         */
        _swapLayers: function () {
            var document = this.props.document,
                layers = document.layers.selected;

            this.getFlux().actions.transform.swapLayers(document, layers);
        },

        /**
         * Rotates the selected layers by the entered angle - last value of the control
         *
         * @private
         * @param {SyntheticEvent} event
         * @param {number} newAngle
         */
        _rotateLayer: function (event, newAngle) {
            var document = this.props.document,
                modAngle = newAngle % 360,
                angleDelta = modAngle - this._lastAngle;

            // We do not debounce this action, because state is kept in React component
            // and the view relies on amount of rotates being sent to Photoshop being accurate
            this.getFlux().actions.transform.rotate(document, angleDelta);
        
            this._lastAngle = newAngle;
        },

        /**
         * Determine if flip operations should be disabled for a given set of layers.
         * TRUE If layers is empty
         * or if either a background or adjustment layer is included
         * (note that adjustment layers are kind of OK, but seem to have subtle issues with bounds afterwards)
         * or if ALL layers are empty groups
         *
         * @private
         * @param {Document} document
         * @param {Immutable.List.<Layer>} layers
         * @return {boolean}
         */
        _flipDisabled: function (document, layers) {
            return layers.isEmpty() ||<commit_msg>Don't send rotate command if angle is 0<commit_after>/*
 * Copyright (c) 2014 Adobe Systems Incorporated. All rights reserved.
 *  
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"), 
 * to deal in the Software without restriction, including without limitation 
 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 
 * and/or sell copies of the Software, and to permit persons to whom the 
 * Software is furnished to do so, subject to the following conditions:
 *  
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *  
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
 * DEALINGS IN THE SOFTWARE.
 * 
 */


define(function (require, exports, module) {
    "use strict";

    var React = require("react"),
        Fluxxor = require("fluxxor"),
        FluxMixin = Fluxxor.FluxMixin(React),
        Immutable = require("immutable");

    //HACK - temporarily here to listen to history events
    var descriptor = require("adapter/ps/descriptor"),
        photoshopEvent = require("adapter/lib/photoshopEvent");

    var Label = require("jsx!js/jsx/shared/Label"),
        Gutter = require("jsx!js/jsx/shared/Gutter"),
        NumberInput = require("jsx!js/jsx/shared/NumberInput"),
        SplitButton = require("jsx!js/jsx/shared/SplitButton"),
        SplitButtonList = SplitButton.SplitButtonList,
        SplitButtonItem = SplitButton.SplitButtonItem,
        strings = require("i18n!nls/strings"),
        collection = require("js/util/collection");

    var RotateFlip = React.createClass({
        mixins: [FluxMixin],
        
        propTypes: {
            document: React.PropTypes.object,
            layers: React.PropTypes.arrayOf(React.PropTypes.object)
        },

        /**
         * Last angle on input for relative rotation
         *
         * @type {number}
         */
        _lastAngle: null,

        componentWillReceiveProps: function () {
            // Reset this flag every time we receive new props
            this.setState({
                undo: false
            });
        },

        getInitialState: function () {
            return {
                undo: false
            };
        },

        shouldComponentUpdate: function (nextProps, nextState) {
            var curDocument = this.props.document,
                nextDocument = nextProps.document,
                curLayers = curDocument ? curDocument.layers.selected : Immutable.List(),
                nextLayers = nextDocument ? nextDocument.layers.selected : Immutable.List(),
                curLayerIDs = collection.pluck(curLayers, "id"),
                nextLayerIDs = collection.pluck(nextLayers, "id");

            return nextState.undo || !Immutable.is(curLayerIDs, nextLayerIDs);
        },

        componentWillUpdate: function () {
            this._lastAngle = 0;
        },

        componentWillMount: function () {
            // HACK - on Undo, we want to reset this to 0, so we set a flag
            descriptor.addListener("select", function (event) {
                if (photoshopEvent.targetOf(event) === "historyState") {
                    this.setState({
                        undo: true
                    });
                }
            }.bind(this));
        },

        /**
         * Flips the layer horizontally
         * 
         * @private
         */
        _flipX: function () {
            var document = this.props.document,
                layers = document.layers.selected;

            this.getFlux().actions.transform.flipX(document, layers);
        },
        
        /**
         * Flips the layer vertically
         * 
         * @private
         */
        _flipY: function () {
            var document = this.props.document,
                layers = document.layers.selected;

            this.getFlux().actions.transform.flipY(document, layers);
        },

        /**
         * Swaps the two selected layers
         * 
         * @private
         */
        _swapLayers: function () {
            var document = this.props.document,
                layers = document.layers.selected;

            this.getFlux().actions.transform.swapLayers(document, layers);
        },

        /**
         * Rotates the selected layers by the entered angle - last value of the control
         *
         * @private
         * @param {SyntheticEvent} event
         * @param {number} newAngle
         */
        _rotateLayer: function (event, newAngle) {
            var document = this.props.document,
                modAngle = newAngle % 360,
                angleDelta = modAngle - this._lastAngle;

            if (angleDelta !== 0) {
                // We do not debounce this action, because state is kept in React component
                // and the view relies on amount of rotates being sent to Photoshop being accurate
                this.getFlux().actions.transform.rotate(document, angleDelta);
            }

            this._lastAngle = newAngle;
        },

        /**
         * Determine if flip operations should be disabled for a given set of layers.
         * TRUE If layers is empty
         * or if either a background or adjustment layer is included
         * (note that adjustment layers are kind of OK, but seem to have subtle issues with bounds afterwards)
         * or if ALL layers are empty groups
         *
         * @private
         * @param {Document} document
         * @param {Immutable.List.<Layer>} layers
         * @return {boolean}
         */
        _flipDisabled: function (document, layers) {
            return layers.isEmpty() ||
{'fraction_non_alphanumeric': 0.0894328845369237, 'fraction_numerical': 0.0019583843329253367, 'mean_word_length': 1.936272160996646, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4900987', 'n_tokens_mistral': 3191, 'n_tokens_neox': 2954, 'n_words': 989}