src_image_maskSegmentHelper.js

// namespaces
var dwv = dwv || {};
dwv.image = dwv.image || {};

/**
 * Mask segment helper.
 *
 * @class
 * @param {object} mask The associated mask image.
 */
dwv.image.MaskSegmentHelper = function (mask) {

  /**
   * The segments: array of segment description.
   *
   * @private
   * @type {Array}
   */
  var segments = mask.getMeta().custom.segments;

  /**
   * List of ids of hidden segments.
   *
   * @private
   * @type {Array}
   */
  var hiddenSegments = [];

  /**
   * Check if a segment is part of the inner segment list.
   *
   * @param {number} segmentNumber The segment number.
   * @returns {boolean} True if the segment is included.
   */
  this.hasSegment = function (segmentNumber) {
    return typeof this.getSegment(segmentNumber) !== 'undefined';
  };

  /**
   * Check if a segment is present in a mask image.
   *
   * @param {Array} numbers Array of segment numbers.
   * @returns {Array} Array of boolean set to true
   *   if the segment is present in the mask.
   */
  this.maskHasSegments = function (numbers) {
    // create values using displayValue
    var values = [];
    var unknowns = [];
    for (var i = 0; i < numbers.length; ++i) {
      var segment = this.getSegment(numbers[i]);
      if (typeof segment !== 'undefined') {
        values.push(segment.displayValue);
      } else {
        dwv.logger.warn('Unknown segment in maskHasSegments: ' + numbers[i]);
        unknowns.push(i);
      }
    }
    var res = mask.hasValues(values);
    // insert unknowns as false in result
    for (var j = 0; j < unknowns.length; ++j) {
      res.splice(unknowns[j], 0, false);
    }
    return res;
  };

  /**
   * Get a segment from the inner segment list.
   *
   * @param {number} segmentNumber The segment number.
   * @returns {object} The segment.
   */
  this.getSegment = function (segmentNumber) {
    return segments.find(function (item) {
      return item.number === segmentNumber;
    });
  };

  /**
   * Get the inner segment list.
   *
   * @returns {Array} The list of segments.
   */
  this.getSegments = function () {
    return segments;
  };

  /**
   * Set the inner segment list.
   *
   * @param {Array} list The segment list.
   */
  this.setSegments = function (list) {
    segments = list;
  };

  /**
   * Set the hidden segment list.
   * TODO: not sure if needed...
   *
   * @param {Array} list The list of hidden segment numbers.
   */
  this.setHiddenSegments = function (list) {
    hiddenSegments = list;
  };

  /**
   * Get the index of a segment in the hidden list.
   *
   * @param {number} segmentNumber The segment number.
   * @returns {number|undefined} The index in the array.
   */
  function getHiddenIndex(segmentNumber) {
    return hiddenSegments.findIndex(function (item) {
      return item === segmentNumber;
    });
  }

  /**
   * Check if a segment is in the hidden list.
   *
   * @param {number} segmentNumber The segment number.
   * @returns {boolean} True if the segment is in the list.
   */
  this.isHidden = function (segmentNumber) {
    return getHiddenIndex(segmentNumber) !== -1;
  };

  /**
   * Add a segment to the hidden list.
   *
   * @param {number} segmentNumber The segment number.
   */
  this.addToHidden = function (segmentNumber) {
    if (!this.isHidden(segmentNumber)) {
      hiddenSegments.push(segmentNumber);
    } else {
      dwv.logger.warn(
        'Segment is allready in the hidden list: ' + segmentNumber);
    }
  };

  /**
   * Remove a segment from the hidden list.
   *
   * @param {number} segmentNumber The segment number.
   */
  this.removeFromHidden = function (segmentNumber) {
    var index = getHiddenIndex(segmentNumber);
    if (index !== -1) {
      hiddenSegments.splice(index, 1);
    } else {
      dwv.logger.warn('Segment is not in the hidden list: ' + segmentNumber);
    }
  };

  /**
   * Get the alpha function to apply hidden colors.
   *
   * @returns {Function} The corresponding alpha function.
   */
  this.getAlphaFunc = function () {
    // get colours
    var hiddenColours = [{r: 0, g: 0, b: 0}];
    for (var i = 0; i < hiddenSegments.length; ++i) {
      var segment = this.getSegment(hiddenSegments[i]);
      if (typeof segment !== 'undefined') {
        hiddenColours.push(segment.displayValue);
      }
    }

    // create alpha function
    return function (value/*, index*/) {
      for (var i = 0; i < hiddenColours.length; ++i) {
        if (value[0] === hiddenColours[i].r &&
          value[1] === hiddenColours[i].g &&
          value[2] === hiddenColours[i].b) {
          return 0;
        }
      }
      // default
      return 255;
    };
  };

  /**
   * Delete a segment.
   *
   * @param {number} segmentNumber The segment number.
   * @param {Function} cmdCallback The command event callback.
   * @param {Function} exeCallback The post execution callback.
   */
  this.deleteSegment = function (segmentNumber, cmdCallback, exeCallback) {
    var delcmd = new dwv.image.DeleteSegmentCommand(
      mask, this.getSegment(segmentNumber));
    delcmd.onExecute = cmdCallback;
    delcmd.onUndo = cmdCallback;
    if (delcmd.isValid()) {
      delcmd.execute();
      // callback
      exeCallback(delcmd);
      // possibly hidden
      if (this.isHidden(segmentNumber)) {
        this.removeFromHidden(segmentNumber);
      }
    }
  };
};

/**
 * Delete segment command.
 *
 * @param {object} mask The mask image.
 * @param {object} segment The segment to remove.
 * @param {boolean} silent Whether to send a creation event or not.
 * @class
 */
dwv.image.DeleteSegmentCommand = function (mask, segment, silent) {
  var isSilent = (typeof silent === 'undefined') ? false : silent;

  // list of offsets with the colour to delete
  var offsets = mask.getOffsets(segment.displayValue);

  /**
   * Get the command name.
   *
   * @returns {string} The command name.
   */
  this.getName = function () {
    return 'Delete-segment';
  };

  /**
   * Check if a command is valid and can be executed.
   *
   * @returns {boolean} True if the command is valid.
   */
  this.isValid = function () {
    return offsets.length !== 0;
  };

  /**
   * Execute the command.
   *
   * @fires dwv.image.DeleteSegmentCommand#masksegmentdelete
   */
  this.execute = function () {
    // remove
    mask.setAtOffsets(offsets, {r: 0, g: 0, b: 0});

    // callback
    if (!isSilent) {
      /**
       * Segment delete event.
       *
       * @event dwv.image.DeleteSegmentCommand#masksegmentdelete
       * @type {object}
       * @property {number} segmentnumber The segment number.
       */
      this.onExecute({
        type: 'masksegmentdelete',
        segmentnumber: segment.number
      });
    }
  };

  /**
   * Undo the command.
   *
   * @fires dwv.image.DeleteSegmentCommand#masksegmentredraw
   */
  this.undo = function () {
    // re-draw
    mask.setAtOffsets(offsets, segment.displayValue);

    // callback
    /**
     * Segment redraw event.
     *
     * @event dwv.image.DeleteSegmentCommand#masksegmentredraw
     * @type {object}
     * @property {number} segmentnumber The segment number.
     */
    this.onUndo({
      type: 'masksegmentredraw',
      segmentnumber: segment.number
    });
  };
}; // DeleteSegmentCommand class

/**
 * Handle an execute event.
 *
 * @param {object} _event The execute event with type and id.
 */
dwv.image.DeleteSegmentCommand.prototype.onExecute = function (_event) {
  // default does nothing.
};
/**
 * Handle an undo event.
 *
 * @param {object} _event The undo event with type and id.
 */
dwv.image.DeleteSegmentCommand.prototype.onUndo = function (_event) {
  // default does nothing.
};