Program Listing for File Widget.h

Return to documentation for file (src/smartpeak/include/SmartPeak/ui/Widget.h)

// --------------------------------------------------------------------------
//   SmartPeak -- Fast and Accurate CE-, GC- and LC-MS(/MS) Data Processing
// --------------------------------------------------------------------------
// Copyright The SmartPeak Team -- Novo Nordisk Foundation
// Center for Biosustainability, Technical University of Denmark 2018-2021.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL ANY OF THE AUTHORS OR THE CONTRIBUTING
// INSTITUTIONS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// --------------------------------------------------------------------------
// $Maintainer: Douglas McCloskey $
// $Authors: Douglas McCloskey $
// --------------------------------------------------------------------------

#pragma once

#include <string>
#include <utility>
#include <vector>
#include <imgui.h>
#include <SmartPeak/core/SessionHandler.h>
#include <unsupported/Eigen/CXX11/Tensor>

namespace SmartPeak
{
  class Widget
  {
  public:
    Widget() = default;
    virtual ~Widget() = default;
    Widget(const Widget &&) = delete;

    virtual void draw() = 0;

    static void FilterPopup(const char* popuop_id, ImGuiTextFilter& filter, const Eigen::Tensor<std::string,1>& column, bool* checked,
      const std::vector<std::pair<std::string, std::vector<size_t>>>& values_indices);

    static void SortButton(const char* button_id, const Eigen::Tensor<std::string,1>& headers,
      Eigen::Tensor<std::string,2>& columns,
      const int n_col,
      bool* checked,
      std::vector<std::vector<std::pair<std::string, std::vector<size_t>>>>& columns_indices,
      bool sort_asc = true);

    static void makeFilters(const Eigen::Tensor<std::string,1>& headers,
      const Eigen::Tensor<std::string,2>& columns,
      std::vector<std::vector<std::pair<std::string, std::vector<size_t>>>>& columns_indices,
      std::vector<ImGuiTextFilter>& filter);
  };

  class GenericTextWidget : public Widget
  {
  public:
    void draw() override;
    std::vector<std::string> text_lines;
  };

  class GenericTableWidget : public Widget
  {
  public:
    GenericTableWidget(const Eigen::Tensor<std::string, 1>&headers, const Eigen::Tensor<std::string, 2>&columns, const Eigen::Tensor<bool, 1>&checked_rows, const std::string&table_id)
      : headers_(headers), columns_(columns), checked_rows_(checked_rows), table_id_(table_id) {};
    /*
    @brief Show the table

    @param[in] headers Column header names
    @param[in,out] columns Table body or matrix
    @param[in,out] checked_rows What rows are checked/filtered
    */
    void draw() override;
    const Eigen::Tensor<std::string,1>& headers_; // keep these `const` and references so that the data is not copied on each call!
    const Eigen::Tensor<std::string,2>& columns_;
    const Eigen::Tensor<bool, 1>& checked_rows_;
    const std::string table_id_; // keep this `const` and non-reference so that the table is not built de-novo on each call!
  };

  class ExplorerWidget : public GenericTableWidget
  {
  public:
    ExplorerWidget(const Eigen::Tensor<std::string, 1>&headers, const Eigen::Tensor<std::string, 2>&columns, const Eigen::Tensor<bool, 1>&checked_rows, const std::string&table_id, const Eigen::Tensor<std::string, 1>&checkbox_headers, Eigen::Tensor<bool, 2>&checkbox_columns)
      :GenericTableWidget(headers, columns, checked_rows, table_id), checkbox_headers_(checkbox_headers), checkbox_columns_(checkbox_columns) {};
    /*
    @brief Show the explorer

    @param[in] headers Column header names
    @param[in,out] columns Table body or matrix
    @param[in,out] checked_rows What rows are checked/filtered
    */
    void draw() override;
    const Eigen::Tensor<std::string, 1>& checkbox_headers_;
    Eigen::Tensor<bool,2>& checkbox_columns_;
  };

  class GenericGraphicWidget : public Widget
  {
  public:
    void draw() override;
  };

  class LinePlot2DWidget : public GenericGraphicWidget
  {
  public:
    LinePlot2DWidget(const Eigen::Tensor<float, 2>&x_data, const Eigen::Tensor<float, 2>&y_data, const Eigen::Tensor<std::string, 1>&series_names,
      const std::string& x_axis_title, const std::string& y_axis_title, const float& x_min, const float& x_max, const float& y_min, const float& y_max,
      const float& plot_width, const float& plot_height, const std::string& plot_title) :
      x_data_(x_data), y_data_(y_data), series_names_(series_names), x_axis_title_(x_axis_title), y_axis_title_(y_axis_title),
      x_min_(x_min), x_max_(x_max), y_min_(y_min), y_max_(y_max), plot_width_(plot_width), plot_height_(plot_height), plot_title_(plot_title) {};
    void draw() override;
    const Eigen::Tensor<float, 2>& x_data_;
    const Eigen::Tensor<float, 2>& y_data_;
    const Eigen::Tensor<std::string, 1>& series_names_;
    const std::string& x_axis_title_;
    const std::string& y_axis_title_;
    const float& x_min_;
    const float& x_max_;
    const float& y_min_;
    const float& y_max_;
    const float& plot_width_;
    const float& plot_height_;
    const std::string plot_title_; // used as the ID of the plot as well so this should be unique across the different Widgets
  };

  class ScatterPlotWidget : public GenericGraphicWidget
  {
  public:
    ScatterPlotWidget(SessionHandler& session_handler,
      SequenceHandler& sequence_handler,
      const std::string& title) :
      session_handler_(session_handler),
      sequence_handler_(sequence_handler),
      plot_title_(title) {};
    void setWindowSize(float width, float height) { plot_width_ = width; plot_height_ = height; };
    void setRefreshNeeded() { refresh_needed_ = true; };
    void draw() override;
  protected:
    virtual void updateScatterPlotData() = 0;
  protected:
    SessionHandler& session_handler_;
    SequenceHandler& sequence_handler_;
    float plot_width_ = 0.0f;
    float plot_height_ = 0.0f;
    const std::string plot_title_; // used as the ID of the plot as well so this should be unique across the different Widgets
    bool show_legend_ = true;
    bool compact_view_ = true;
    SessionHandler::ScatterPlotData chrom_;
    bool refresh_needed_ = false;
    std::pair<float, float> slider_min_max_ = { 0.0f, 0.0f };
    std::pair<float, float> current_range_ = { 0.0f, 0.0f };
  };

  class GenericTreeWidget : public Widget
  {
  public:
    void draw() override;
  };

  class WorkflowWidget : public GenericGraphicWidget
  {
  public:
    void draw() override;
  };
}