text: "use strict";
  /*-----------------------------------------------------------------------------
  | Copyright (c) 2014-2017, PhosphorJS Contributors
  |
  | Distributed under the terms of the BSD 3-Clause License.
  |
  | The full license is in the file LICENSE, distributed with this software.
  |----------------------------------------------------------------------------*/
  Object.defineProperty(exports, "__esModule", { value: true });
  /**
   * A sizer object for use with the box engine layout functions.
   *
   * #### Notes
   * A box sizer holds the geometry information for an object along an
   * arbitrary layout orientation.
   *
   * For best performance, this class should be treated as a raw data
   * struct. It should not typically be subclassed.
   */
  var BoxSizer = (function () {
      function BoxSizer() {
          /**
           * The preferred size for the sizer.
           *
           * #### Notes
           * The sizer will be given this initial size subject to its size
           * bounds. The sizer will not deviate from this size unless such
           * deviation is required to fit into the available layout space.
           *
           * There is no limit to this value, but it will be clamped to the
           * bounds defined by [[minSize]] and [[maxSize]].
           *
           * The default value is `0`.
           */
          this.sizeHint = 0;
          /**
           * The minimum size of the sizer.
           *
           * #### Notes
           * The sizer will never be sized less than this value, even if
           * it means the sizer will overflow the available layout space.
           *
           * It is assumed that this value lies in the range `[0, Infinity)`
           * and that it is `<=` to [[maxSize]]. Failure to adhere to this
           * constraint will yield undefined results.
           *
           * The default value is `0`.
           */
          this.minSize = 0;
          /**
           * The maximum size of the sizer.
           *
           * #### Notes
           * The sizer will never be sized greater than this value, even if
           * it means the sizer will underflow the available layout space.
           *
           * It is assumed that this value lies in the range `[0, Infinity]`
           * and that it is `>=` to [[minSize]]. Failure to adhere to this
           * constraint will yield undefined results.
           *
           * The default value is `Infinity`.
           */
          this.maxSize = Infinity;
          /**
           * The stretch factor for the sizer.
           *
           * #### Notes
           * This controls how much the sizer stretches relative to its sibling
           * sizers when layout space is distributed. A stretch factor of zero
           * is special and will cause the sizer to only be resized after all
           * other sizers with a stretch factor greater than zero have been
           * resized to their limits.
           *
           * It is assumed that this value is an integer that lies in the range
           * `[0, Infinity)`. Failure to adhere to this constraint will yield
           * undefined results.
           *
           * The default value is `1`.
           */
          this.stretch = 1;
          /**
           * The computed size of the sizer.
           *
           * #### Notes
           * This value is the output of a call to [[boxCalc]]. It represents
           * the computed size for the object along the layout orientation,
           * and will always lie in the range `[minSize, maxSize]`.
           *
           * This value is output only.
           *
           * Changing this value will have no effect.
           */
          this.size = 0;
          /**
           * An internal storage property for the layout algorithm.
           *
           * #### Notes
           * This value is used as temporary storage by the layout algorithm.
           *
           * Changing this value will have no effect.
           */
          this.done = false;
      }
      return BoxSizer;
  }());
  exports.BoxSizer = BoxSizer;
  /**
   * The namespace for the box engine layout functions.
   */
  var BoxEngine;
  (function (BoxEngine) {
      /**
       * Calculate the optimal layout sizes for a sequence of box sizers.
       *
       * This distributes the available layout space among the box sizers
       * according to the following algorithm:
       *
       * 1. Initialize the sizers's size to its size hint and compute the
       *    sums for each of size hint, min size, and max size.
       *
       * 2. If the total size hint equals the available space, return.
       *
       * 3. If the available space is less than the total min size, set all
       *    sizers to their min size and return.
       *
       * 4. If the available space is greater than the total max size, set
       *    all sizers to their max size and return.
       *
       * 5. If the layout space is less than the total size hint, distribute
       *    the negative delta as follows:
       *
       *    a. Shrink each sizer with a stretch factor greater than zero by
       *       an amount proportional to the negative space and the sum of
       *       stretch factors. If the sizer reaches its min size, remove
       *       it and its stretch factor from the computation.
       *
       *    b. If after adjusting all stretch sizers there remains negative
       *       space, distribute the space equally among the sizers with a
       *       stretch factor of zero. If a sizer reaches its min size,
       *       remove it from the computation.
       *
       * 6. If the layout space is greater than the total size hint,
       *    distribute the positive delta as follows:
       *
       *    a. Expand each sizer with a stretch factor greater than zero by
       *       an amount proportional to the postive space and the sum of
       *       stretch factors. If the sizer reaches its max size, remove
       *       it and its stretch factor from the computation.
       *
       *    b. If after adjusting all stretch sizers there remains positive
       *       space, distribute the space equally among the sizers with a
       *       stretch factor of zero. If a sizer reaches its max size,
       *       remove it from the computation.
       *
       * 7. return
       *
       * @param sizers - The sizers for a particular layout line.
       *
       * @param space - The available layout space for the sizers.
       *
       * @returns The delta between the provided available space and the
       *   actual consumed space. This value will be zero if the sizers
       *   can be adjusted to fit, negative if the available space is too
       *   small, and positive if the available space is too large.
       *
       * #### Notes
       * The [[size]] of each sizer is updated with the computed size.
       *
       * This function can be called at any time to recompute the layout for
       * an existing sequence of sizers. The previously computed results will
       * have no effect on the new output. It is therefore not necessary to
       * create new sizer objects on each resize event.
       */
      function calc(sizers, space) {
          // Bail early if there is nothing to do.
          var count = sizers.length;
          if (count === 0) {
              return space;
          }
          // Setup the size and stretch counters.
          var totalMin = 0;
          var totalMax = 0;
          var totalSize = 0;
          var totalStretch = 0;
          var stretchCount = 0;
          // Setup the sizers and compute the totals.
          for (var i = 0; i < count; ++i) {
              var sizer = sizers[i];
              var min = sizer.minSize;
              var max = sizer.maxSize;
              var hint = sizer.sizeHint;
              sizer.done = false;
              sizer.size = Math.max(min, Math.min(hint, max));
              totalSize += sizer.size;
              totalMin += min;
              totalMax += max;
              if (sizer.stretch > 0) {
                  totalStretch += sizer.stretch;
                  stretchCount++;
              }
          }
          // If the space is equal to the total size, return early.
          if (space === totalSize) {
              return 0;
          }
          // If the space is less than the total min, minimize each sizer.
          if (space <= totalMin) {
              for (var i = 0; i < count; ++i) {
                  var sizer = sizers[i];
                  sizer.size = sizer.minSize;
              }
              return space - totalMin;
          }
          // If the space is greater than the total max, maximize each sizer.
          if (space >= totalMax) {
              for (var i = 0; i < count; ++i) {
                  var sizer = sizers[i];
                  sizer.size = sizer.maxSize;
              }
              return space - totalMax;
          }
          // The loops below perform sub-pixel precision sizing. A near zero
          // value is used for compares instead of zero to ensure that the
          // loop terminates when the subdivided space is reasonably small.
          var nearZero = 0.01;
          // A counter which is decremented each time a sizer is resized to
          // its limit. This ensures the loops terminate even if there is
          // space remaining to distribute.
          var notDoneCount = count;
          // Distribute negative delta space.
          if (space < totalSize) {
              // Shrink each stretchable sizer by an amount proportional to its
              // stretch factor. If a sizer reaches its min size it's marked as
              // done. The loop progresses in phases where each sizer is given
              // a chance to consume its fair share for the pass, regardless of
              // whether a sizer before it reached its limit. This continues
              // until the stretchable sizers or the free space is exhausted.
              var freeSpace = totalSize - space;
              while (stretchCount > 0 && freeSpace > nearZero) {
                  var distSpace = freeSpace;
                  var distStretch = totalStretch;
                  for (var i = 0; i < count; ++i) {
                      var sizer = sizers[i];
                      if (sizer.done || sizer.stretch === 0) {
                          continue;
                      }
                      var amt = sizer.stretch * distSpace / distStretch;
                      if (sizer.size - amt <= sizer.minSize) {
                          freeSpace -= sizer.size - sizer.minSize;
                          totalStretch -= sizer.stretch;
                          sizer.size = sizer.minSize;
                          sizer.done = true;
                          notDoneCount--;
                          stretchCount--;
                      }
                      else {
                          freeSpace -= amt;
                          sizer.size -= amt;
                      }
                  }
              }
              // Distribute any remaining space evenly among the non-stretchable
              // sizers. This progresses in phases in the same manner as above.
              while (notDoneCount > 0 && freeSpace > nearZero) {
                  var amt = freeSpace / notDoneCount;
                  for (var i = 0; i < count; ++i) {
                      var sizer = sizers[i];
                      if (sizer.done) {
                          continue;
                      }
                      if (sizer.size - amt <= sizer.minSize) {
                          freeSpace -= sizer.size - sizer.minSize;
                          sizer.size = sizer.minSize;
                          sizer.done = true;
                          notDoneCount--;
                      }
                      else {
                          freeSpace -= amt;
                          sizer.size -= amt;
                      }
                  }
              }
          }
          else {
              // Expand each stretchable sizer by an amount proportional to its
              // stretch factor. If a sizer reaches its max size it's marked as
              // done. The loop progresses in phases where each sizer is given
              // a chance to consume its fair share for the pass, regardless of
              // whether a sizer before it reached its limit. This continues
              // until the stretchable sizers or the free space is exhausted.
              var freeSpace = space - totalSize;
              while (stretchCount > 0 && freeSpace > nearZero) {
                  var distSpace = freeSpace;
                  var distStretch = totalStretch;
                  for (var i = 0; i < count; ++i) {
                      var sizer = sizers[i];
                      if (sizer.done || sizer.stretch === 0) {
                          continue;
                      }
                      var amt = sizer.stretch * distSpace / distStretch;
                      if (sizer.size + amt >= sizer.maxSize) {
                          freeSpace -= sizer.maxSize - sizer.size;
                          totalStretch -= sizer.stretch;
                          sizer.size = sizer.maxSize;
                          sizer.done = true;
                          notDoneCount--;
                          stretchCount--;
                      }
                      else {
                          freeSpace -= amt;
                          sizer.size += amt;
                      }
                  }
              }
              // Distribute any remaining space evenly among the non-stretchable
              // sizers. This progresses in phases in the same manner as above.
              while (notDoneCount > 0 && freeSpace > nearZero) {
                  var amt = freeSpace / notDoneCount;
                  for (var i = 0; i < count; ++i) {
                      var sizer = sizers[i];
                      if (sizer.done) {
                          continue;
                      }
                      if (sizer.size + amt >= sizer.maxSize) {
                          freeSpace -= sizer.maxSize - sizer.size;
                          sizer.size = sizer.maxSize;
                          sizer.done = true;
                          notDoneCount--;
                      }
                      else {
                          freeSpace -= amt;
                          sizer.size += amt;
                      }
                  }
              }
          }
          // Indicate that the consumed space equals the available space.
          return 0;
      }
      BoxEngine.calc = calc;
      /**
       * Adjust a sizer by a delta and update its neighbors accordingly.
       *
       * @param sizers - The sizers which should be adjusted.
       *
       * @param index - The index of the sizer to grow.
       *
       * @param delta - The amount to adjust the sizer, positive or negative.
       *
       * #### Notes
       * This will adjust the indicated sizer by the specified amount, along
       * with the sizes of the appropriate neighbors, subject to the limits
       * specified by each of the sizers.
       *
       * This is useful when implementing box layouts where the boundaries
       * between the sizers are interactively adjustable by the user.
       */
      function adjust(sizers, index, delta) {
          // Bail early when there is nothing to do.
          if (sizers.length === 0 || delta === 0) {
              return;
          }
          // Dispatch to the proper implementation.
          if (delta > 0) {
              growSizer(sizers, index, delta);
          }
          else {
              shrinkSizer(sizers, index, -delta);
          }
      }
      BoxEngine.adjust = adjust;
      /**
       * Grow a sizer by a positive delta and adjust neighbors.
       */
      function growSizer(sizers, index, delta) {
          // Compute how much the items to the left can expand.
          var growLimit = 0;
          for (var i = 0; i <= index; ++i) {
              var sizer = sizers[i];
              growLimit += sizer.maxSize - sizer.size;
          }
          // Compute how much the items to the right can shrink.
          var shrinkLimit = 0;
          for (var i = index + 1, n = sizers.length; i < n; ++i) {
              var sizer = sizers[i];
              shrinkLimit += sizer.size - sizer.minSize;
          }
          // Clamp the delta adjustment to the limits.
          delta = Math.min(delta, growLimit, shrinkLimit);
          // Grow the sizers to the left by the delta.
          var grow = delta;
          for (var i = index; i >= 0 && grow > 0; --i) {
              var sizer = sizers[i];
              var limit = sizer.maxSize - sizer.size;
              if (limit >= grow) {
                  sizer.sizeHint = sizer.size + grow;
                  grow = 0;
              }
              else {
                  sizer.sizeHint = sizer.size + limit;
                  grow -= limit;
              }
          }
          // Shrink the sizers to the right by the delta.
          var shrink = delta;
          for (var i = index + 1, n = sizers.length; i < n && shrink > 0; ++i) {
              var sizer = sizers[i];
              var limit = sizer.size - sizer.minSize;
              if (limit >= shrink) {
                  sizer.sizeHint = sizer.size - shrink;
                  shrink = 0;
              }
              else {
                  sizer.sizeHint = sizer.size - limit;
                  shrink -= limit;
              }
          }
      }
      /**
       * Shrink a sizer by a positive delta and adjust neighbors.
       */
      function shrinkSizer(sizers, index, delta) {
          // Compute how much the items to the right can expand.
          var growLimit = 0;
          for (var i = index + 1, n = sizers.length; i < n; ++i) {
              var sizer = sizers[i];
              growLimit += sizer.maxSize - sizer.size;
          }
          // Compute how much the items to the left can shrink.
          var shrinkLimit = 0;
          for (var i = 0; i <= index; ++i) {
              var sizer = sizers[i];
              shrinkLimit += sizer.size - sizer.minSize;
          }
          // Clamp the delta adjustment to the limits.
          delta = Math.min(delta, growLimit, shrinkLimit);
          // Grow the sizers to the right by the delta.
          var grow = delta;
          for (var i = index + 1, n = sizers.length; i < n && grow > 0; ++i) {
              var sizer = sizers[i];
              var limit = sizer.maxSize - sizer.size;
              if (limit >= grow) {
                  sizer.sizeHint = sizer.size + grow;
                  grow = 0;
              }
              else {
                  sizer.sizeHint = sizer.size + limit;
                  grow -= limit;
              }
          }
          // Shrink the sizers to the left by the delta.
          var shrink = delta;
          for (var i = index; i >= 0 && shrink > 0; --i) {
              var sizer = sizers[i];
              var limit = sizer.size - sizer.minSize;
              if (limit >= shrink) {
                  sizer.sizeHint = sizer.size - shrink;
                  shrink = 0;
              }
              else {
                  sizer.sizeHint = sizer.size - limit;
                  shrink -= limit;
              }
          }
      }
  })(BoxEngine = exports.BoxEngine || (exports.BoxEngine = {}));
  