diff --git a/src/interface/stats_viewer.ui b/src/interface/stats_viewer.ui index f218a5a2a9ae62929b1e5c3eee2ad573e294a465..13753dcb156835fa67e80e2894390d8281112655 100644 --- a/src/interface/stats_viewer.ui +++ b/src/interface/stats_viewer.ui @@ -83,8 +83,13 @@ </property> </widget> </item> - <item row="2" column="1" > + <item row="3" column="1" > <widget class="QComboBox" name="_kind_of_diagram_box" > + <item> + <property name="text" > + <string>Horizontal Histogram</string> + </property> + </item> <item> <property name="text" > <string>Histogram</string> diff --git a/src/render/render_stats_opengl.hpp b/src/render/render_stats_opengl.hpp index 862a6eafca65569ae32847bc5613114acb0cf51f..653c284b8d7f66528971ee706f536331a8732718 100644 --- a/src/render/render_stats_opengl.hpp +++ b/src/render/render_stats_opengl.hpp @@ -90,6 +90,14 @@ public: */ void draw_horizontal_line(const Element_pos x, const Element_pos y, const Element_pos size_x); + /*! + * \brief Draw a line. + * \param x the x position of the text. + * \param y the y position of the text. + * \param value the string value of the text. + */ + void draw_vertical_line(const Element_pos x, const Element_pos y, const Element_pos size_x); + void draw_axis(const Element_pos x, const Element_pos y, const Element_pos size_x, const Element_pos size_y); /*! * \brief Draw a rectangle. @@ -147,6 +155,16 @@ inline void Render_stats_opengl::draw_horizontal_line(const Element_pos x, const glEnd(); } +inline void Render_stats_opengl::draw_vertical_line(const Element_pos x, const Element_pos y, const Element_pos size_y){ + glBegin(GL_LINES); + { + glColor3ub(0, 0, 0); + glVertex2i(x, y); + glVertex2i(x, y+size_y); + } + glEnd(); +} + inline void Render_stats_opengl::draw_axis(const Element_pos x, const Element_pos y, const Element_pos size_x, const Element_pos size_y){ glBegin(GL_LINES); { diff --git a/src/statistics/DrawHDiagram.hpp b/src/statistics/DrawHDiagram.hpp new file mode 100644 index 0000000000000000000000000000000000000000..bf5b45f7c240a2142e6178310b567665145ed5cd --- /dev/null +++ b/src/statistics/DrawHDiagram.hpp @@ -0,0 +1,212 @@ +/*! + *\file DrawStats.hpp + */ + +#ifndef DRAW_HDIAGRAM_HPP +#define DRAW_HDIAGRAM_HPP + +#include <string> +#include <vector> +#include <map> + +#include "../message/Message.hpp" +#include "../trace/Trace.hpp" +#include "../trace/tree/Interval.hpp" +#include "Statistic.hpp" +#include "DrawStats.hpp" + +template<class T> +class DrawHDiagram : public DrawStats<T> { +protected: + double _startx; + double _starty; + double _graph_width; + double _draw_width; + double _draw_height; + double _legend_width; + double _legend_height; + +public: + /* + * \brief The default constructor + */ + DrawHDiagram() { + _startx = _START_HISTOGRAM_X_DEFAULT; + _starty = 200.0f; + + this->_size_for_one_container = _HEIGHT_FOR_ONE_CONTAINER_DEFAULT; + this->_percentage_height_default = (this->_size_for_one_container - _START_HISTOGRAM_Y_DEFAULT) / 100.; + + this->_pos_x_container_name = _POS_X_CONTAINER_NAME; + this->_pos_y_container_name = _POS_Y_CONTAINER_NAME; + + /* Size for rectangles in the legend */ + this->_width_for_rect_legend = 20.; + this->_height_for_rect_legend = 15.; + } + + + /*! + * \brief The destructor + */ + virtual ~DrawHDiagram() { + } + + + /*! + * \fn build(T* draw_object, Trace* trace) + * \brief The trace building function. + * \param draw_object the kind of object which will be drawn (OpenGL, SVG...). + * \param trace the trace data. + */ + void build(T* draw_object, std::vector<Container *> containers_to_print) { + int nbcont; + + draw_object->clear(); + + _draw_height = draw_object->height(); + _draw_width = draw_object->width(); + _legend_height = draw_object->height(); + _legend_width = draw_object->width(); + _graph_width = _draw_width - _startx - 30.; + this->_containers_to_print = containers_to_print; + nbcont = this->_containers_to_print.size(); + + draw_object->start_draw(); + draw_object->set_total_height((nbcont+1)*_WIDTH_HISTOGRAM_DEFAULT + + 10.); + draw_object->set_total_width(draw_object->width()); + + draw_object->draw_axis(_startx, + _starty - (nbcont-1)*_WIDTH_HISTOGRAM_DEFAULT, + _graph_width + 10., + (nbcont+1)*_WIDTH_HISTOGRAM_DEFAULT); + + draw_object->draw_horizontal_line(_startx, + _starty + _WIDTH_HISTOGRAM_DEFAULT, + _graph_width + 10.); + + for (int i=25; i < 101; i+=25) + { + // Draw Up Scale + draw_object->draw_vertical_line(_startx + i*_graph_width/100., + _starty + _WIDTH_HISTOGRAM_DEFAULT - 2.5, + 5.); + draw_object->draw_text(_startx + i*_graph_width/100 - 10., + _starty + _WIDTH_HISTOGRAM_DEFAULT + 15., + QString::number(i, 'd', 1).toStdString()+"%"); + // Dra Down Scale + draw_object->draw_vertical_line(_startx + i*_graph_width/100., + _starty - (nbcont-1)*_WIDTH_HISTOGRAM_DEFAULT - 2.5, + 5.); + draw_object->draw_text(_startx + i*_graph_width/100 - 10., + _starty - (nbcont-1)*_WIDTH_HISTOGRAM_DEFAULT - 15., + QString::number(i, 'd', 1).toStdString()+"%"); + } + + for(int i = 0 ; i < nbcont ; i ++) { + draw_diagram(draw_object, i); + } + draw_legend(draw_object, + _POS_X_LEGEND_DEFAULT + _startx, + _POS_Y_LEGEND_DEFAULT + _starty - (nbcont+3)*_WIDTH_HISTOGRAM_DEFAULT); + end_draw(draw_object); + } + + void draw_diagram(T* draw_object, const int container_id) { + Statistic *stat_temp; + std::map<const EntityValue*, stats*> temp_states; + double duration; + int pos_x, pos_y; + std::string ctname; + + stat_temp = new Statistic(); + this->_containers_to_print[container_id]->fill_stat(stat_temp, Interval(this->_start_time, this->_end_time)); + temp_states = stat_temp->get_states(); + this->_states.push_back(temp_states); + duration = this->_end_time - this->_start_time; + + // Printing of the trace + //std::cout << "nb states " << temp_states.size() << std::endl; + + // Depending on the kind of diagram... + pos_x = _startx; + pos_y = _starty - container_id * _WIDTH_HISTOGRAM_DEFAULT; + + // Draw the container name + ctname = this->_containers_to_print[container_id]->get_name().to_string(); + draw_object->draw_text(_POS_X_CONTAINER_NAME, + pos_y + _WIDTH_HISTOGRAM_DEFAULT / 2. - 5., + ctname); + + // Draw the stats + for (map<const EntityValue *, stats *>::iterator it = temp_states.begin(); + it != temp_states.end(); + it ++) + { + double length = (*it).second->_total_length; + double percent = length / duration ; + double width = percent * _graph_width; + std::string name = (*it).first->get_name().to_string(); + double red = 0.7; + double green = 0.7; + double blue = 0.75; + + // We search for a color + if((*it).first->get_extra_fields()->find(std::string("Color")) != (*it).first->get_extra_fields()->end()) + { + const Color *color = (const Color *)(*it).first->get_extra_fields()->find(std::string("Color"))->second; + red = color->get_red(); + green = color->get_green(); + blue = color->get_blue(); + } + + draw_object->draw_rect(pos_x, pos_y, + width, _WIDTH_HISTOGRAM_DEFAULT, + red, green, blue); + + if ( width > 30. ) + draw_object->draw_text(pos_x + width / 2 - 10., pos_y + _WIDTH_HISTOGRAM_DEFAULT / 2. - 5., + QString::number(percent*100., 'f', 1).toStdString()+"%"); + pos_x += width; + } + + delete stat_temp; + } + + void draw_legend(T* draw_object, int pos_x, int pos_y) { + + const double w = this->_width_for_rect_legend; + const double h = this->_height_for_rect_legend; + + /* used to print legend on 3 rows */ + int decalage = 0; + + for (map<const EntityValue *, stats *>::iterator it = this->_states[0].begin(); + it != this->_states[0].end(); + it ++, decalage ++) { + std::string name = (*it).first->get_name().to_string(); + draw_object->draw_text(pos_x+w+_POS_X_LEGEND_DEFAULT, pos_y, name); + + if((*it).first->get_extra_fields()->find(std::string("Color")) != (*it).first->get_extra_fields()->end()) { + const Color *color = (const Color *)(*it).first->get_extra_fields()->find(std::string("Color"))->second; + draw_object->draw_rect(pos_x, pos_y, w, h, color->get_red(), color->get_green(), color->get_blue()); + } + else { + draw_object->draw_rect(pos_x, pos_y, w, h, 0.7, 0.7, 0.75); + } + + switch(decalage%3) { + case 2: + pos_x += 100; + pos_y += 40; + break; + default: + pos_y -= 20; + break; + } + } + } +}; + +#endif diff --git a/src/statistics/DrawStats.hpp b/src/statistics/DrawStats.hpp index eec4904553591ac34832cdb71394b7d74e3327fa..ff28f2b73ec8552b83c6eda601186a2ba0e3b02f 100644 --- a/src/statistics/DrawStats.hpp +++ b/src/statistics/DrawStats.hpp @@ -124,13 +124,12 @@ public: /*! - * \fn build(T* draw_object, Trace* trace, std::string kind_of_diagram) + * \fn build(T* draw_object, Trace* trace) * \brief The trace building function. * \param draw_object the kind of object which will be drawn (OpenGL, SVG...). * \param trace the trace data. - * \param kind_of_diagram the kind of diagram (histogram, chart...) */ - void build(T* draw_object, std::vector<Container *> containers_to_print, std::string kind_of_diagram) { + virtual void build(T* draw_object, std::vector<Container *> containers_to_print) { draw_object->clear(); @@ -145,14 +144,14 @@ public: for(int i = 0 ; i < number_of_containers ; i ++) { draw_container_name(draw_object, i); - draw_diagram(draw_object, i, kind_of_diagram); + draw_diagram(draw_object, i); draw_legend(draw_object, i); } end_draw(draw_object); } - void draw_container_name(T* draw_object, const int container_id) const { + virtual void draw_container_name(T* draw_object, const int container_id) const { // Get the position for the i-th container name Element_pos pos_x = _pos_x_container_name; @@ -163,7 +162,7 @@ public: draw_object->draw_text(pos_x, pos_y, name); } - void draw_diagram(T* draw_object, const int container_id, std::string kind_of_diagram) { + virtual void draw_diagram(T* draw_object, const int container_id) { Statistic *stat_temp = new Statistic(); _containers_to_print[container_id]->fill_stat(stat_temp, Interval(_start_time, _end_time)); std::map<const EntityValue*, stats*> temp_states = stat_temp->get_states(); @@ -171,53 +170,46 @@ public: // Printing of the trace - // Depending on the kind of diagram... - if(kind_of_diagram == "Histogram") { - - int pos_x = _START_HISTOGRAM_X_DEFAULT; - int pos_y = _START_HISTOGRAM_Y_DEFAULT - container_id*_size_for_one_container; - const double max_percentage = get_max_percentage(temp_states); - // Draw axes - draw_object->draw_axis(pos_x, pos_y, _WIDTH_HISTOGRAM_DEFAULT*(_states[container_id].size()+1), _percentage_height_default*100); - draw_object->draw_text(pos_x-30, pos_y+_percentage_height_default*100-5, QString::number(max_percentage*100., 'g', 3).toStdString()+"%"); - draw_object->draw_horizontal_line(pos_x, pos_y+_percentage_height_default*100, _WIDTH_HISTOGRAM_DEFAULT*(_states[container_id].size()+1)); - - - // Draw the stats - for (map<const EntityValue *, stats *>::iterator it = temp_states.begin(); - it != temp_states.end(); - it ++) { - std::string name = (*it).first->get_name().to_string(); - - // We have to convert the percentage in a rectangle and print it - const double length = (*it).second->_total_length; - const double height = length*100.*_percentage_height_default/(_end_time-_start_time); - - // We search for a color - if((*it).first->get_extra_fields()->find(std::string("Color")) != (*it).first->get_extra_fields()->end()) { - const Color *color = (const Color *)(*it).first->get_extra_fields()->find(std::string("Color"))->second; - draw_object->draw_rect(pos_x, pos_y, _WIDTH_HISTOGRAM_DEFAULT, height/max_percentage, color->get_red(), color->get_green(), color->get_blue()); - } - else { - draw_object->draw_rect(pos_x, pos_y, _WIDTH_HISTOGRAM_DEFAULT, height/max_percentage, 0.7, 0.7, 0.75); - } - - // We print the percentage above - draw_object->draw_text(pos_x, pos_y+height/max_percentage+1, QString::number(length/(_end_time-_start_time)*100., 'f', 1).toStdString()+"%"); - - //std::cout << "State : " << name << " for " << (*it).second->_total_length*100./(_end_time-_start_time)<< "% between " << _start_time << " sec and " << _end_time << " sec" << std::endl; - - pos_x += _WIDTH_HISTOGRAM_DEFAULT; - } - } - else { - *Message::get_instance() << kind_of_diagram << " not yet implemented" << Message::endw; - } + int pos_x = _START_HISTOGRAM_X_DEFAULT; + int pos_y = _START_HISTOGRAM_Y_DEFAULT - container_id*_size_for_one_container; + const double max_percentage = get_max_percentage(temp_states); + // Draw axes + draw_object->draw_axis(pos_x, pos_y, _WIDTH_HISTOGRAM_DEFAULT*(_states[container_id].size()+1), _percentage_height_default*100); + draw_object->draw_text(pos_x-30, pos_y+_percentage_height_default*100-5, QString::number(max_percentage*100., 'g', 3).toStdString()+"%"); + draw_object->draw_horizontal_line(pos_x, pos_y+_percentage_height_default*100, _WIDTH_HISTOGRAM_DEFAULT*(_states[container_id].size()+1)); + + + // Draw the stats + for (map<const EntityValue *, stats *>::iterator it = temp_states.begin(); + it != temp_states.end(); + it ++) { + std::string name = (*it).first->get_name().to_string(); + + // We have to convert the percentage in a rectangle and print it + const double length = (*it).second->_total_length; + const double height = length*100.*_percentage_height_default/(_end_time-_start_time); + + // We search for a color + if((*it).first->get_extra_fields()->find(std::string("Color")) != (*it).first->get_extra_fields()->end()) { + const Color *color = (const Color *)(*it).first->get_extra_fields()->find(std::string("Color"))->second; + draw_object->draw_rect(pos_x, pos_y, _WIDTH_HISTOGRAM_DEFAULT, height/max_percentage, color->get_red(), color->get_green(), color->get_blue()); + } + else { + draw_object->draw_rect(pos_x, pos_y, _WIDTH_HISTOGRAM_DEFAULT, height/max_percentage, 0.7, 0.7, 0.75); + } + + // We print the percentage above + draw_object->draw_text(pos_x, pos_y+height/max_percentage+1, QString::number(length/(_end_time-_start_time)*100., 'f', 1).toStdString()+"%"); + + //std::cout << "State : " << name << " for " << (*it).second->_total_length*100./(_end_time-_start_time)<< "% between " << _start_time << " sec and " << _end_time << " sec" << std::endl; + + pos_x += _WIDTH_HISTOGRAM_DEFAULT; + } delete stat_temp; } - void draw_legend(T* draw_object, const int container_id) { + virtual void draw_legend(T* draw_object, const int container_id) { Element_pos pos_x = _POS_X_CONTAINER_NAME + _POS_X_LEGEND_DEFAULT; Element_pos pos_y = -_size_for_one_container * (container_id) + _POS_Y_LEGEND_DEFAULT; const double w = _width_for_rect_legend; @@ -269,7 +261,7 @@ public: * \return a value between 0. and 1. * */ - double get_max_percentage(std::map<const EntityValue*, stats*> &temp_states) const { + virtual double get_max_percentage(std::map<const EntityValue*, stats*> &temp_states) const { double value; double max_length = 0.; for (map<const EntityValue *, stats *>::iterator it = temp_states.begin(); @@ -285,7 +277,7 @@ public: return value; } - void updateGL(T* draw_object) const { + virtual void updateGL(T* draw_object) const { draw_object->updateGL(); } diff --git a/src/statistics/Stats_window.cpp b/src/statistics/Stats_window.cpp index b8ad6c80e9686571d57fcbe41f966bfaf98eb955..4f1656d52ed614d47d944ace6230e54e04dc80f8 100644 --- a/src/statistics/Stats_window.cpp +++ b/src/statistics/Stats_window.cpp @@ -79,7 +79,7 @@ void Stats_window::init_window() { void Stats_window::on_reload_button_clicked() { - + std::string kind_of_diagram = _kind_of_diagram_box->currentText ().toStdString(); // We delete the previous selected containers if(!_selected_containers.empty()) { _selected_containers.clear(); @@ -105,12 +105,30 @@ void Stats_window::on_reload_button_clicked() { // We get the times _start_time = _start_time_widget->text().toDouble(); - _end_time = _end_time_widget->text().toDouble(); + _end_time = _end_time_widget->text().toDouble(); // We create a drawer - DrawStats<Render_stats_opengl> drawer; - drawer.set_times(_start_time, _end_time); - drawer.build(_ui_stats_area, _selected_containers, _kind_of_diagram_box->currentText ().toStdString()); + DrawStats<Render_stats_opengl> *drawer; + if(kind_of_diagram == "Horizontal Histogram") + { + drawer = new DrawHDiagram<Render_stats_opengl>(); + } + else if (kind_of_diagram == "Histogram") + { + drawer = new DrawStats<Render_stats_opengl>(); + } + else if (kind_of_diagram == "Chart") + { + *Message::get_instance() << kind_of_diagram << " not yet implemented" << Message::endw; + drawer = new DrawStats<Render_stats_opengl>(); + } + else + { + *Message::get_instance() << kind_of_diagram << " not yet implemented" << Message::endw; + drawer = new DrawStats<Render_stats_opengl>(); + } + drawer->set_times(_start_time, _end_time); + drawer->build(_ui_stats_area, _selected_containers); _ui_stats_area->updateGL(); } diff --git a/src/statistics/Stats_window.hpp b/src/statistics/Stats_window.hpp index 761287b676f208a644a1b0337ab7e747d952994b..c9f740b439b4e2246de3cc21eb993e457957ede0 100644 --- a/src/statistics/Stats_window.hpp +++ b/src/statistics/Stats_window.hpp @@ -20,6 +20,7 @@ class Stats_window; #include "../message/Message.hpp" #include "../render/render_stats_opengl.hpp" #include "DrawStats.hpp" +#include "DrawHDiagram.hpp" /*! * \brief Class used to display statistics of containers.