NGL@1.0.0-beta.7 Home Manual Reference Source Gallery

src/utils/counter.js

/**
 * @file Counter
 * @author Alexander Rose <alexander.rose@weirdbyte.de>
 * @private
 */

import { Log } from '../globals.js'

import Signal from '../../lib/signals.es6.js'

/**
 * {@link Signal}, dispatched when the `count` changes
 * @example
 * counter.signals.countChanged.add( function( delta ){ ... } );
 * @event Counter#countChanged
 * @type {Integer}
 */

/**
 * Counter class for keeping track of counts
 */
class Counter {
  constructor () {
        /**
         * The `count`
         * @type {Integer}
         */
    this.count = 0

    this.signals = {
      countChanged: new Signal()
    }
  }

    /**
     * Set the `count` to zero
     * @return {undefined}
     */
  clear () {
    this.change(-this.count)
  }

    /**
     * Change the `count`
     * @fires Counter#countChanged
     * @param {Integer} delta - count change
     * @return {undefined}
     */
  change (delta) {
    this.count += delta
    this.signals.countChanged.dispatch(delta, this.count)

    if (this.count < 0) {
      Log.warn('Counter.count below zero', this.count)
    }
  }

    /**
     * Increments the `count` by one.
     * @return {undefined}
     */
  increment () {
    this.change(1)
  }

    /**
     * Decrements the `count` by one.
     * @return {undefined}
     */
  decrement () {
    this.change(-1)
  }

    /**
     * Listen to another counter object and change this `count` by the
     * same amount
     * @param  {Counter} counter - the counter object to listen to
     * @return {undefined}
     */
  listen (counter) {
    this.change(counter.count)
    counter.signals.countChanged.add(this.change, this)
  }

    /**
     * Stop listening to the other counter object
     * @param  {Counter} counter - the counter object to stop listening to
     * @return {undefined}
     */
  unlisten (counter) {
    var countChanged = counter.signals.countChanged
    if (countChanged.has(this.change, this)) {
      countChanged.remove(this.change, this)
    }
  }

    /**
     * Invole the callback function once, when the `count` becomes zero
     * @param  {Function} callback - the callback function
     * @param  {Object}   context - the context for the callback function
     * @return {undefined}
     */
  onZeroOnce (callback, context) {
    if (this.count === 0) {
      callback.call(context, 0, 0)
    } else {
      var fn = function () {
        if (this.count === 0) {
          this.signals.countChanged.remove(fn, this)
          callback.apply(context, arguments)
        }
      }
      this.signals.countChanged.add(fn, this)
    }
  }

  dispose () {
    this.clear()
    this.signals.countChanged.dispose()
  }
}

export default Counter