baja/obj/Icon.js

/**
 * @copyright 2015 Tridium, Inc. All Rights Reserved.
 * @author Gareth Johnson
 */

/**
 * Defines {@link baja.Icon}.
 * @module baja/obj/Icon
 */
define([ "bajaScript/sys",
        "bajaScript/baja/obj/Simple" ], 
        function (baja, Simple) {

  "use strict";
  
  var subclass = baja.subclass,
      callSuper = baja.callSuper,
      strictArg = baja.strictArg,
      
      iconsCache = {},
      iconStdObj;

  
  /**
   * A BajaScript `Icon`.
   * 
   * A BajaScript `Icon` may contain multiple Image references.
   * 
   * For maximum efficiency, all icons in BajaScript are completely interned.
   * 
   * This Constructor shouldn't be invoked directly. Please use the `make()` 
   * methods to create an instance of an Icon.
   *
   * @class
   * @alias baja.Icon
   * @extends baja.Simple
   */    
  var Icon = function Icon(ords) {
    callSuper(Icon, this, arguments); 
    this.$ords = strictArg(ords, Array);     
  };
  
  subclass(Icon, Simple);
  
  /**
   * Default Icon instance.
   * @type {baja.Icon}
   */
  Icon.DEFAULT = new Icon([]);
  
  function encodeIcon(ords) {
    return ords.join("\n");
  }
    
  /**
   * Make an `Icon`.
   *
   * @param {Array.<String|baja.Ord>|baja.Ord|baja.OrdList|String} [ords] an array of Image ORDs or
   * Strings or just a single `baja.Ord`, `baja.OrdList` or String. If a String is provided it can be
   * either be a valid Ord encoding or a valid OrdList encoding.
   * @returns {baja.Icon}
   */
  Icon.make = function (ords) {
    if (arguments.length === 0) {
      return Icon.DEFAULT;
    }
    
    var encodedStr,
        newOrds = [], 
        i,
        icon;
    
    // If a String or OrdList is passed in then convert to an Array
    if (typeof ords === "string" || ords instanceof baja.OrdList) {
      ords = ords.toString().split('\n');
    }
    
    if (!ords || ords.constructor !== Array) {
      throw new Error("Invalid argument for baja.Icon.make");
    }
    
    // If an array is passed in then treat this as an array of ORDs
    encodedStr = encodeIcon(ords);
    // If available from the cache then use it...
    if (iconsCache.hasOwnProperty(encodedStr)) {
      return iconsCache[encodedStr];
    }
  
    if (ords.length === 0) {
      return Icon.DEFAULT;
    }
    if (ords.length === 1 && ords[0].toString() === "") {
      return Icon.DEFAULT;
    }
  
    
    for (i = 0; i < ords.length; ++i) {
      newOrds.push(baja.Ord.make(ords[i].toString()));
    }
    
    icon = new Icon(newOrds);
    // Store icon in cache
    iconsCache[encodedStr] = icon;
    icon.$cEncStr = encodedStr;
    
    return icon;
  };
  
  /**
   * Make an Icon.
   *
   * @param {Array.<String|baja.Ord>|String} [ords] an array of Image ORDs or 
   * Strings or just a single ORD or String
   * @returns {baja.Icon}
   */
  Icon.prototype.make = function (ords) {
    return Icon.make.apply(Icon, arguments);
  };
   
  /**
   * Decode a `String` to an `Icon`.
   *
   * @param {String} str
   * @returns {baja.Icon}
   */
  Icon.prototype.decodeFromString = function (str) {  
    // If available from the cache then use it...
    if (iconsCache.hasOwnProperty(str)) {
      return iconsCache[str];
    }
  
    return Icon.make(str.split("\n"));
  };
  
  /**
   * Encode `Icon` to a `String`.
   *
   * @returns {String}
   */
  Icon.prototype.encodeToString = function () {
    if (!this.$cEncStr) {
      this.$cEncStr = encodeIcon(this.$ords);
    }
    return this.$cEncStr;
  };
        
  /**
   * Return a `String` representation of the `Icon`.
   *
   * @returns {String}
   */
  Icon.prototype.toString = function () {
    return this.encodeToString();
  };
  
  /**
   * Return the inner value of the `Icon`.
   *
   * @returns {String}
   */
  Icon.prototype.valueOf = function () {
    return this.toString();
  };
    
  /**
   * Return a copy of the image ORDs `Array`.
   * 
   * Please note, this is a copy of the Image ORDs and not the URIs to access the images.
   *
   * @see baja.Icon#getImageUris
   *
   * @returns {Array.<baja.Ord>} an array of ORDs to the images.
   */
  Icon.prototype.getImageOrds = function () {
    // Return a copy of the images array
    return Array.prototype.slice.call(this.$ords);
  };  
  
  /**
   * Return an array of URIs to the images.
   *
   * @returns {Array.<String>} an array of URI Strings to the images.
   */
  Icon.prototype.getImageUris = function () {
    var regex = /^module:\/\//,
        i,
        that = this,
        uri;

    if (!that.$uris) {
      that.$uris = [];
      for (i = 0; i < that.$ords.length; ++i) {
        uri = that.$ords[i].toString();
        uri = uri.replace(regex, "/module/");
        if (uri.startsWith("file:")) {
          uri = '/ord/' + uri;
        }
        that.$uris.push(uri);
      }
    }
    return Array.prototype.slice.call(that.$uris);
  }; 
  
  /**
   * Return the standard Object Icon.
   *
   * @returns {baja.Icon}
   */
  Icon.getStdObjectIcon = function () {
    if (!iconStdObj) {
      iconStdObj = Icon.make([ "module://icons/x16/object.png" ]); 
    }
    return iconStdObj;
  };
  
  return Icon;
});