Source: Plotter.js

// Plotter.js

/**
 * @fileOverview a file to define RWTDiagnosticsPlotter class.
 * @author Ryohei Ueda
 */
ROSLIB.RWTDiagnosticsPlotter = function(spec) {
  var self = this;
  self.plotting_infos = [];
  self.previous_directory_names = [];
  var ros = spec.ros;
  self.history = new ROSLIB.DiagnosticsHistory(spec);
  self.name_select_id = spec.name_select_id || 'name-select';
  self.plot_field_select_id = spec.plot_field_select_id || 'plot-field-select';
  self.add_button_id = spec.add_button_id || 'add-button';
  self.plot_windows_id = spec.plot_windows_id || 'plot-windows-area';
  var diagnostics_agg_topic = spec.diagnostics_agg_topic || '/diagnostics_agg';
  
  self.registerNameSelectCallback();
  self.registerPlotFieldSelectCallback();
  self.registerAddCallback();
  self.diagnostics_agg_subscriber = new ROSLIB.Topic({
    ros: ros,
    name: diagnostics_agg_topic,
    messageType: 'diagnostic_msgs/DiagnosticArray'
  });
  
  self.diagnostics_agg_subscriber.subscribe(function(msg) {
    self.diagnosticsCallback(msg);
  });
};


ROSLIB.RWTDiagnosticsPlotter.prototype.registerAddCallback = function() {
  var self = this;
  $('#' + self.add_button_id).click(function(e) {
    var plotting_info = new ROSLIB.DiagnosticsPlotInfo();
    self.plotting_infos.push(plotting_info);
    plotting_info.clearInfo(); // clear it anyway
    var name = $('#' + self.name_select_id).val();
    var directory = self.history.root.findByName(name);
    var directories = [];
    if (directory.hasChildren()) {
      directories = directory.getAllDirectoriesWithoutRoot();
    }
    else {
      directories = [directory];
    }
    
    plotting_info.registerDirectories(directories);
    plotting_info.registerField($('#' + self.plot_field_select_id).val());
    plotting_info.preparePlotWindows(name, self.plot_windows_id);
    e.preventDefault();
    return false;
  });
};


ROSLIB.RWTDiagnosticsPlotter.prototype.registerPlotFieldSelectCallback = function() {
  var self = this;
  $('#' + self.plot_field_select_id).bind('change', function() {
  });
};

ROSLIB.RWTDiagnosticsPlotter.prototype.registerNameSelectCallback = function() {
  var self = this;
  $('#' + self.name_select_id).bind('change', function() {
    var name = $(this).attr('value');
    // get the directory
    var directory = self.history.root.findByName(name);
    var candidate_keys = [];
    $('#' + self.plot_field_select_id + ' option').remove();
    var invoke_error_message = false;
    if (directory.hasChildren()) {
      // get the children
      var children = directory.getAllDirectories();
      _.remove(children, function(dir) {
        return dir === directory;
      });
      var uniq_keys = _(children).map(function(dir) {
        var keys = [];
        for (var key in dir.status.values) {
          if (dir.status.values.hasOwnProperty(key)) {
            var value = dir.status.values[key];
            if (!isNaN(Number(value))) {
              keys.push(key);
            }
          }
        }
        return keys;
      }).flatten().uniq().value();
      uniq_keys.forEach(function(key) {
        var $option = $('<option>' + key + '</option>');
        $option.val(key);
        $('#' + self.plot_field_select_id).append($option);
      });
      if (uniq_keys.length === 0) {
        invoke_error_message = true;
      }
    }
    else {
      var counter = 0;
      for (var key in directory.status.values) {
        var $option = $('<option>' + key + '</option>');
        $option.val(key);
        var value = directory.status.values[key];
        var number_value = Number(value);
        
        if (!isNaN(number_value)) {
          $('#' + self.plot_field_select_id).append($option);
          counter = counter + 1;
        }
      }
      if (counter === 0) {
        invoke_error_message = true;
      }
    }
    if (invoke_error_message) {
      var $modal_html = $('<div class="modal fade" id="rwt-robot-plotter-warn-message">'
                          + '<div class="modal-dialog">'
                          + '<div class="modal-content">'
                          + '<div class="modal-header">'
                          + '<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>'
                          + '<h4 class="modal-title">Error</h4>'
                          + '</div>'
                          + '<div class="modal-body">'
                          + '<p><span class="label label-warning">'
                          + name
                          + '</span> does not have values which can be plotted</p>'
                          + '</div>'
                          + '<div class="modal-footer">'
                          + '<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>'
                          + '</div>'
                          + '</div>'
                          + '</div>'
                          + '</div>');
      $('body').append($modal_html);
      // registering function to remove the html
      $modal_html.on('hidden.bs.modal', function() {
        $('#rwt-robot-plotter-warn-message').remove();
      });
      $('#rwt-robot-plotter-warn-message').modal();
    }
  });
  
};

ROSLIB.RWTDiagnosticsPlotter.prototype.diagnosticsCallback = function(msg) {
  var diagnostics_statuses
    = ROSLIB.DiagnosticsStatus.createFromArray(msg);
  var self = this;
  _.forEach(diagnostics_statuses, function(status) {
    self.history.registerStatus(status);
  });

  // sort the history
  var directories = self.history.root.getAllDirectoriesWithoutRoot();
  // sort self directories
  directories = _.sortBy(directories, function(dir) {
    return dir.fullName();
  });
  //var name_options = [];
  
  var need_to_update_options = false;
  if (self.previous_directory_names.length === 0) {
    need_to_update_options = true;
  }
  else if (self.previous_directory_names.length !== directories.length) {
    need_to_update_options = true;
  }
  else {
    for (var i = 0; i < self.previous_directory_names.length; i++) {
      if (self.previous_directory_names[i].toString() !==
          directories[i].fullName().toString()) {
        need_to_update_options = true;
        break;
      }
    }
  }
  
  if (need_to_update_options) {
    var has_field_before = true;
    if ($('#' + self.plot_field_select_id + ' option').length === 0) {
      has_field_before = false;
    }

    $('#' + self.name_select_id + ' option').remove();
    self.previous_directory_names = [];
    _.forEach(directories, function(dir) {
      var name = dir.fullName();
      //name_options.push('<option>' + dir.fullName() + '</option>');
      var $option = null;
      if (dir.hasChildren()) {
        var children = dir.getAllDirectories();
        $option = $('<option>' + name + '/* (' + (children.length - 1) +')</option>');
        
      }
      else {
        $option = $('<option>' + name + '</option>');
      }
      $option.attr('value', dir.fullName());
      $('#name-select').append($option);
      self.previous_directory_names.push(name);
    });
    
    if (!has_field_before) {
      // force to update field options
      $('#' + self.name_select_id).trigger('change');
    }
  }
  _.forEach(self.plotting_infos, function(plotting_info) {
    if (plotting_info.plottable()) {
      plotting_info.plot();
    }
  });
};