/*
** This file is part of the ViTE project.
**
** This software is governed by the CeCILL-A license under French law
** and abiding by the rules of distribution of free software. You can
** use, modify and/or redistribute the software under the terms of the
** CeCILL-A license as circulated by CEA, CNRS and INRIA at the following
** URL: "http://www.cecill.info".
**
** As a counterpart to the access to the source code and rights to copy,
** modify and redistribute granted by the license, users are provided
** only with a limited warranty and the software's author, the holder of
** the economic rights, and the successive licensors have only limited
** liability.
**
** In this respect, the user's attention is drawn to the risks associated
** with loading, using, modifying and/or developing or reproducing the
** software by the user in light of its specific status of free software,
** that may mean that it is complicated to manipulate, and that also
** therefore means that it is reserved for developers and experienced
** professionals having in-depth computer knowledge. Users are therefore
** encouraged to load and test the software's suitability as regards
** their requirements in conditions enabling the security of their
** systems and/or data to be ensured and, more generally, to use and
** operate it in the same conditions as regards security.
**
** The fact that you are presently reading this means that you have had
** knowledge of the CeCILL-A license and that you accept its terms.
**
**
** ViTE developers are (for version 0.* to 1.0):
**
**        - COULOMB Kevin
**        - FAVERGE Mathieu
**        - JAZEIX Johnny
**        - LAGRASSE Olivier
**        - MARCOUEILLE Jule
**        - NOISETTE Pascal
**        - REDONDY Arthur
**        - VUCHENER Clément
**
*/
/*!
 *\file Render_opengl_dl.hpp
 */

#ifndef RENDER_OPENGL_DL_HPP
#define RENDER_OPENGL_DL_HPP

class Render_opengl_dl;

/*!
 * \brief This class defined functions using the OpenGL display list rendering method.
 */
class Render_opengl_dl : public Render_opengl
{
    Q_OBJECT

protected:


    /***********************************
     *
     * The wait screen drawing.
     *
     **********************************/

    /***********************************
     * The wait list Attributes.
     **********************************/

    /*!
     * \brief The wait GLu list.
     */
    GLuint _wait_list;


    /*!
     * \brief Used to draw counter.
     */
    bool _start_new_line;

public:

    /***********************************
     *
     * Constructor and destructor.
     *
     **********************************/

    /*!
     * \brief The default constructor
     */
    Render_opengl_dl(Core* core, QWidget *parent)
        : Render_opengl(this, core, parent){
        _wait_list = 0;
    }

    /*!
     * \brief The destructor
     */
    virtual ~Render_opengl_dl(){
    }


    /***********************************
     *
     * Building functions.
     *
     **********************************/

    /*!
     * \brief This function constructs the trace.
     */
    bool display_build();

    /*!
     * \brief This function releases the trace.
     */
    bool display_unbuild();

    /*!
     * \brief Proceeds with the initialization of the OpenGL draw functions.
     */
    void start_draw();

    /*!
     * \brief Creates and opens the display list for container draws.
     */
    void start_draw_containers();

    /*!
     * \brief Draw a container according to the parameters
     * \param x the x position of the container
     * \param y the y position of the container
     * \param w the width of the container
     * \param h the height of the container
     */
    void draw_container(const Element_pos x, const Element_pos y, const Element_pos w, const Element_pos h);

    /*!
     * \brief Draw the text of a container.
     * \param x the x position of the text.
     * \param y the y position of the text.
     * \param value the string value of the text.
     *
     * This function stores text in a list. This list will be display each time the render area need to be updated.
     */
    void draw_container_text(const Element_pos x, const Element_pos y, const std::string value);

    /*!
     * \brief Closes the container display list.
     */
    void end_draw_containers();

    /*!
     * \brief Creates and opens the display list for stater draws.
     */
    void start_draw_states();

    /*!
     * \brief Draw a state of the trace.
     * \param start the beginning time of the state.
     * \param end the ending time of the state.
     * \param base vertical position of the state.
     * \param height the state height.
     * \param r the red color rate of the state.
     * \param g the green color rate of the state.
     * \param b the blue color rate of the state.
     */
    void draw_state(const Element_pos start , const Element_pos end, const Element_pos base, const Element_pos height, const Element_col r, const Element_col g, const Element_col b);

    /*!
     * \brief Closes the state display list.
     */
    void end_draw_states();

    /*!
     * \brief Open the arrow display list.
     */
    void start_draw_arrows();

    /*!
     * \brief Draw an arrow.
     * \param start_time the beginning time of the arrow.
     * \param end_time the ending time of the arrow.
     * \param start_height vertical position of the begining time of the arrow.
     * \param end_height vertical position of the ending time of the arrow.
     *
     * This function stores all the information of the arrow to display it each time the render area need to be updated.
     */
    void draw_arrow(const Element_pos start_time, const Element_pos end_time, const Element_pos start_height, const Element_pos end_height);

    /*!
     * \brief Closes the arrow display list.
     */
    void end_draw_arrows();

    /*!
     * \brief Draw arrows contained in the Arrow_ vector
     * \param arrows An arrow vector.
     */
    void draw_stored_arrows(std::vector<Arrow_> &arrows);

    /*!
     * \brief Draw an event.
     * \param time time when the event occurs.
     * \param height vertical position of the event.
     * \param container_height information to draw event. It corresponds to the container height when they are drawn horizontally.
     *
     * This function stores all the information of the event to display it each time the render area need to be updated.
     */
    void draw_event(const Element_pos time, const Element_pos height,  const Element_pos container_height);

    /*!
     * \brief Draw events contained in the Event_ vector
     * \param events An event vector.
     */
    void draw_stored_events(std::vector<Event_> &events);

    /*!
     * \brief Creates and opens the display list for counter draws.
     */
    void start_draw_counter();

    /*!
     * \brief Draw a point of the counter.
     * \param x x position of the point.
     * \param y y position of the point.
     *
     * Each time counter is increased, this function is called with the coordinates of the new point.
     */
    void draw_counter(const Element_pos x, const Element_pos y);

    /*!
     * \brief Closes the counter display list.
     */
    void end_draw_counter();

    /*!
     * \brief Do nothing (it is present for compatibility of the Render class).
     */
    void end_draw();



    /***********************************
     *
     * Displaying functions.
     *
     **********************************/

    /*!
     * \brief Display on screen containers between container_begin and container_end.
     * \param container_begin integer value : id of the first container.
     * \param container_end integer value : id of the last container.
     */
    void display_container(Element_count container_begin, Element_count container_end);

    /*!
     * \brief Display on screen states between timer_begin and time_end,
     * container_begin and container_end and with timer width between depth_begin and depth_end.
     * \param time_begin floating point value : time of the first state.
     * \param time_end floating point value : time of the last state.
     * \param container_begin integer value : id of the first container.
     * \param container_end integer value : id of the last container.
     * \param depth_begin floating point value : width of the narrowest state.
     * \param depth_end floating point value : width of the widest state.
     */
    void display_state(Element_pos time_begin, Element_pos time_end,
                       Element_count container_begin, Element_count container_end,
                       Element_pos depth_begin, Element_pos depth_end);

    /*!
     * \brief Display on screen arrows between timer_begin and time_end,
     * container_begin and container_end and with timer width between depth_begin and depth_end.
     * \param time_begin floating point value : time of the smallest arrow time value.
     * \param time_end floating point value : time of the higher arrow time value.
     * \param container_begin integer value : id of the first container.
     * \param container_end integer value : id of the last container.
     * \param depth_begin floating point value : the narrowest difference between
     * the beginning time and the ending time of the arrow.
     * \param depth_end floating point value : width of the widest difference between
     * the beginning time and the ending time of the arrow.
     */
    void display_arrow(Element_pos time_begin, Element_pos time_end,
                       Element_count container_begin, Element_count container_end,
                       Element_pos depth_begin, Element_pos depth_end);

    /*!
     * \brief Display on screen events between timer_begin and time_end,
     * container_begin and container_end.
     * \param time_begin floating point value : time of the first event.
     * \param time_end floating point value : time of the last event.
     * \param container_begin integer value : id of the first container.
     * \param container_end integer value : id of the last container.
     */
    void display_event(Element_pos time_begin, Element_pos time_end,
                       Element_count container_begin, Element_count container_end);

    /*!
     * \brief Display on screen counters between timer_begin and time_end,
     * container_begin and container_end.
     * \param time_begin floating point value : time of the smallest counter time value.
     * \param time_end floating point value : time of the higher counter time value.
     * \param container_begin integer value : id of the first container.
     * \param container_end integer value : id of the last container.
     */
    void display_counter(Element_pos time_begin, Element_pos time_end,
                         Element_count container_begin, Element_count container_end);


    void set_color(float, float, float){}
    void draw_quads(Element_pos, Element_pos, Element_pos, Element_pos, Element_pos){}
    void draw_text(Element_pos, Element_pos, Element_pos, std::string){}
    void draw_triangle(Element_pos, Element_pos, Element_pos,
                       Element_pos, Element_pos, Element_pos,
                       Element_pos, Element_pos, Element_pos){}
    void draw_line(Element_pos, Element_pos, Element_pos,
                   Element_pos, Element_pos, Element_pos){}
    void draw_circle(Element_pos, Element_pos, Element_pos, Element_pos){}
};




/* inline function area */





/***********************************
 *
 *
 *
 * Building functions.
 *
 *
 *
 **********************************/


inline bool Render_opengl_dl::display_build(){

    if (glIsList(_wait_list) == GL_TRUE){/* if the list exists */
        glDeleteLists(_wait_list, 1);
        _wait_list = 0;
    }

    if (glIsList(_wait_list) == GL_TRUE){
        *Message::get_instance() << tr("Cannot unbuild the waiting animation").toStdString() << Message::endw;
    }

    if ((_wait_timer != NULL) && _wait_timer->isActive())/* if timer for the wait animation is running */
        _wait_timer->stop();

    return true;
}



inline bool Render_opengl_dl::display_unbuild(){

    /********************
     *
     * Launch timer again
     *
     ********************/

    if (!_wait_timer->isActive())/* if timer for the wait animation is not running */
        _wait_timer->start(_wait_spf);


    /*****************
     *
     * Draw the rabbit
     *
     *****************/

    if (glIsList(_wait_list) == GL_FALSE)
        _wait_list = draw_wait();/* create the wait draw */
    else {
        *Message::get_instance() << tr("The wait draw was not released.").toStdString() << Message::endw;
        return false;
    }

    /* if there is an error, do not display the wait an return immediatly */
    if (glIsList(_wait_list) == GL_FALSE) {
        *Message::get_instance() << tr("Cannot create the wait draw.").toStdString() << Message::endw;
        return false;
    }


    return true;
}




/***********************************
 *
 *
 *
 * Drawing functions for the trace.
 *
 *
 *
 **********************************/


inline void Render_opengl_dl::start_draw(){
    /* clear lists to store container texts */
    _text_pos.clear();
    _text_value.clear();

    /* clear the event vector */
    _events.clear();

    /* clear the arrow vector */
    _arrows.clear();
}


inline void Render_opengl_dl::start_draw_containers(){

    _list_containers = glGenLists(1);/* create the list */
    if (_list_containers == 0) {

        //        _parent->warning("Error when creating list");
    }

    glNewList(_list_containers, GL_COMPILE);/* open the list */

}


inline void Render_opengl_dl::draw_container(const Element_pos x, const Element_pos y, const Element_pos w, const Element_pos h) {

    float j = 0.6;


    glBegin(GL_QUADS);/* create a quads */
    {
        glColor3d(0, 0, j);glVertex2d(x, y);
        glColor3d(0, 0, j-0.1);glVertex2d(x, y+h);
        glColor3d(0, 0, j-0.1);glVertex2d(x+w, y+h);
        glColor3d(0, 0, j);glVertex2d(x+w, y);
    }
    glEnd();

    if ((x+w)>_container_x_max)
        _container_x_max = x+w;

    if ((y+h)>_container_y_max)
        _container_y_max = y+h;

    if (_container_x_min > x)
        _container_x_min = x;

    if (_container_y_min > y)
        _container_y_min = y;



#ifdef DEBUG_MODE_RENDER_AREA

    std::cerr << __FILE__ << " l." << __LINE__ << ":" << std::endl;
    std::cerr < "Container drawing:" << std::endl;
    std::cerr << "x: " << x << " y: " << y << " w: " << w << " h: " << h << " xmax-xmin: " << _container_x_max << " - " << _container_x_min << " ymax-ymin: " << _container_y_max << " - " << _container_y_min << std::endl;

#endif

}

inline void Render_opengl_dl::draw_container_text(const Element_pos x, const Element_pos y, const std::string value){

    _text_pos.push_back(x);
    _text_pos.push_back(y);
    _text_value.push_back(value);

}



inline void Render_opengl_dl::end_draw_containers(){
    glEndList();/* close the list */
}




inline void Render_opengl_dl::start_draw_states(){

    _list_states = glGenLists(1);/* create the list */
    if (_list_states == 0) {

        //      _parent->warning("Error when creating list");
    }

    glNewList(_list_states, GL_COMPILE);/* open the list */
}


inline void Render_opengl_dl::draw_state(const Element_pos start, const Element_pos end, const Element_pos base, const Element_pos height, const Element_col r, const Element_col g, const Element_col b) {



#ifdef DEBUG_MODE_RENDER_AREA

    std::cerr << __FILE__ << " l." << __LINE__ << ":" << std::endl;
    std::cerr << "States position (for drawing): (x = " <<  start << ", y = " << base << ", w = " << end-start << ", h = " << height << ")" << std::endl << std::endl;

#endif

    /** DEBUG **/
    //  if (start==end)
    /* std::cout << std::setprecision(15) << std::endl;
       std::cerr << "Start "<< start << " end " << end << std::endl;*/

    glBegin(GL_QUADS);/* create a quads */
    {
        glColor3d(r, g, b);glVertex2d(start, base);
        glColor3d(r, g, b);glVertex2d(start, base + height);
        glColor3d(r/1.5, g/1.5, b/1.5);glVertex2d(end, base + height);
        glColor3d(r/1.5, g/1.5, b/1.5);glVertex2d(end, base);
    }
    glEnd();

    if (end > _state_x_max)
        _state_x_max = end;

    if ((base+height) > _state_y_max)
        _state_y_max = base+height;

    if (_state_x_min > start)
        _state_x_min = start;

    if (_state_y_min > base)
        _state_y_min = base;
}


inline void Render_opengl_dl::end_draw_states(){
    glEndList();/* close the list */
}


inline void Render_opengl_dl::start_draw_arrows(){
}

inline void Render_opengl_dl::draw_arrow(const Element_pos start_time, const Element_pos end_time, const Element_pos start_height, const Element_pos end_height){

    Arrow_ buf;

    buf.start_time = start_time;
    buf.end_time = end_time;
    buf.start_height = start_height;
    buf.end_height = end_height;

    _arrows.push_back(buf);
}


inline void Render_opengl_dl::end_draw_arrows(){
}



inline void Render_opengl_dl::draw_stored_arrows(std::vector<Arrow_> &arrows){

    Element_pos start_time, end_time, start_height, end_height;

    /* Manage the event drawing size from state size and render area dimensions */
    Element_pos arrow_scale_x = _x_state_scale*((_render_width-_default_entity_x_translate)/(_state_x_max-_state_x_min));
    Element_pos arrow_scale_y = _y_state_scale*(_render_height-_ruler_height)/_container_y_max;

    Element_pos angle;

    const int arrows_size = arrows.size();
    for (int i = 0 ; i < arrows_size ; i ++){


        start_time = arrows[i].start_time*arrow_scale_x + _default_entity_x_translate -_x_state_translate;
        end_time = arrows[i].end_time*arrow_scale_x + _default_entity_x_translate - _x_state_translate;
        start_height = arrows[i].start_height*arrow_scale_y;// - _y_state_translate;
        end_height = arrows[i].end_height*arrow_scale_y;// - _y_state_translate;

        /* DEBUG */
        // std::cerr << "Arrow draw: (" << start_time << ", " << start_height << ") to (" << end_time << ", " << end_height << ")" << std::endl;


        glPushMatrix();
        {

            glTranslated(end_time, end_height-_y_state_translate, _z_arrow);
            glScalef(2, 2, 0);/* should be set */


            if (start_time != end_time){

                angle = atan2((end_height - start_height), (end_time - start_time))*180.0f/M_PI;/* arc tangent */

                glRotatef(angle, 0, 0, 1);

            }/* end if (start_time != end_time) */
            else
                glRotatef(90, 0, 0, 1);/* vertical alignment */



            glBegin(GL_TRIANGLES);/* create an arrow */
            {
                glColor3d(1.0, 1.0, 1.0);glVertex2d(0.0, 0.0);
                glColor3d(0.9, 0.9, 0.9);glVertex2d(-0.6, -0.2);
                glColor3d(0.9, 0.9, 0.9);glVertex2d(-0.6, 0.2);
            }
            glEnd();

        }
        glPopMatrix();

        glPushMatrix();
        {
            glTranslated(0, 0, _z_arrow);
            // glLineWidth(1.5f);
            glBegin(GL_LINES);
            {
                glColor3d(0.8, 0.8, 0.8);glVertex2d(start_time, start_height-_y_state_translate);
                glColor3d(1.0, 1.0, 1.0);glVertex2d(end_time, end_height-_y_state_translate);
            }
            glEnd();
            // glLineWidth(1.0f);/* 1 is the default value */
        }
        glPopMatrix();
    }
}


inline void Render_opengl_dl::draw_event(const Element_pos time, const Element_pos height, const Element_pos container_height){

    Event_ buf;

    buf.time = time;
    buf.height = height;
    buf.container_height = container_height;

    _events.push_back(buf);
}


inline void Render_opengl_dl::draw_stored_events(std::vector<Event_> &events){

    Element_pos time, height, container_height;

    /* Manage the event drawing size from state size and render area dimensions */
    Element_pos event_scale_x = _x_state_scale*((_render_width-_default_entity_x_translate)/(_state_x_max-_state_x_min));
    Element_pos event_scale_y = _y_state_scale*(_render_height-_ruler_height)/_container_y_max;

    Element_pos radius;/* the circle radius */
    Element_pos angle;
    Element_pos delta_angle;
    int step;


    for (long i = 0 ; i < (long)events.size() ; i ++){

        time = events[i].time*event_scale_x + _default_entity_x_translate -_x_state_translate;
        height = events[i].height*event_scale_y -_y_state_translate;
        container_height = events[i].container_height*event_scale_y;


        /* DEBUG */
        //  std::cerr << "Event draw: (" << time << ", " << height << ") with height of:" << container_height << " - " << _render_width << " : " << _render_height << std::endl;


        /* IMPROVEMENT: put the circle into a display list */



        /* draw a circle */
        radius = 0.3f;
        angle = M_PI/2.0f;
        step = 20;/* 20 polygons for the circle */

        if (step!=0)
            delta_angle = 2*M_PI/step;


        glColor3d(0.5, 0.8, 0.5);
        glBegin(GL_POLYGON);
        {
            for(int i = 0 ; i < step ; i ++){
                glVertex3d(time + cos(angle+delta_angle*i)*radius , height + sin(angle+delta_angle*i)*radius , _z_event);
            }
        }
        glEnd();

        /* draw line */
        glBegin(GL_LINES);
        {
            glColor3d(0.5, 0.8, 0.5);glVertex3d(time, height, _z_event);
            glColor3d(0.4, 0.7, 0.4);glVertex3d(time, height+container_height, _z_event);
        }
        glEnd();

    }/* and loop */
}


/********************
 * Counter
 *******************/

inline void Render_opengl_dl::start_draw_counter(){

    _list_counters = glGenLists(1);/* create the list */
    if (_list_counters == 0) {
        *Message::get_instance() << tr("Error when creating list").toStdString() << Message::ende;
    }

    glNewList(_list_counters, GL_COMPILE);/* open the list */
    _start_new_line = true;
}


inline void Render_opengl_dl::draw_counter(const Element_pos x, const Element_pos y){

    if (_start_new_line){/* Start a new line */

        glBegin(GL_LINE_STRIP);/* set of connected verteces */
        glColor3d(1.0, 1.0, 1.0);glVertex2d(0.0, y);/* draw the init point */

        _counter_last_x = x;
        _counter_last_y = y;
        _start_new_line = false;

    }else{/* line is already started */

        if (x <= 0.0){/* convention: the line is over */

            glColor3d(1.0, 1.0, 1.0);glVertex2d(_state_x_max, _counter_last_y);
            glEnd();
            _start_new_line = true;
        }else{/* add new points to the line */

            glColor3d(1.0, 1.0, 1.0);glVertex2d(x, _counter_last_y);
            glColor3d(1.0, 1.0, 1.0);glVertex2d(x, y);

            _counter_last_x = x;
            _counter_last_y = y;
        }
    }
}


inline void Render_opengl_dl::end_draw_counter(){

    if (!_start_new_line) {/* if a line was previously opened */
      glEnd();/* suppose that line is not ended */
    }
    glEndList();/* close the list */

    /* Find the most suitable scale depending of the state x min and x max */
    _x_state_scale = 1;//(_render_width - _default_entity_x_translate)/(_state_x_max - _state_x_min);
}



inline void Render_opengl_dl::end_draw(){

}




 /***********************************
  *
  *
  *
  * Displaying functions.
  *
  *
  *
  **********************************/

inline void Render_opengl_dl::display_container(Element_count , Element_count ){

    std::list<Element_pos>::iterator it_pos;
    std::list<std::string>::iterator it_txt;
    Element_pos buf_x;
    Element_pos buf_y;
    std::string buf_txt;


    /* Draw container */
    glPushMatrix();
    {
        glTranslatef(0.0f, -_y_state_translate, _z_container);
        glScalef( (_render_width/_container_x_max)*_x_scale_container_state, _y_state_scale*(_render_height-_ruler_height)/_container_y_max, 0.0f);

#ifdef DEBUG_MODE_RENDER_OPENGL
        cerr << __FILE__ << " l." << __LINE__ << ":" << endl;
        cerr << "Default container position (before translation and scaling) : (x_max = " << _container_x_max << ", y_max = " << _container_y_max << ")" << endl << endl;
#endif

        if (glIsList(_list_containers)==GL_FALSE)
            *Message::get_instance() << tr("ERROR LIST not exist for containers.").toStdString() << Message::ende;
        else
            glCallList(_list_containers);
    }
    glPopMatrix();


    /* Draw container texts */
    for (it_txt=_text_value.begin(), it_pos=_text_pos.begin() ; it_txt!=_text_value.end(); it_txt ++, it_pos ++){

        buf_x = *it_pos;
        it_pos ++;

        buf_y =  *it_pos;
        buf_txt = *it_txt;

        glPushMatrix();
        {
            glTranslatef(0.0f, -_y_state_translate, 0.0f);
            glScalef((_render_width/_container_x_max)*_x_scale_container_state, _y_state_scale*(_render_height-_ruler_height)/_container_y_max, 0.0f);

            glColor3d(1, 1, 1);
            glRasterPos2f(buf_x, buf_y);

#ifdef DEBUG_MODE_RENDER_OPENGL
            cerr << __FILE__ << " l." << __LINE__ << ":" << endl;
            cerr << "Container texts position: (x = " << buf_x << ", y = " << buf_y << ") -> '" << buf_txt << "'" << endl << endl;
#endif

            float length = 0;
            const unsigned int buf_text_size = buf_txt.length();
            const int size_of_container = (const int)(20*_x_scale_container_state*_render_width/_container_x_max);
            for(unsigned int i = 0 ; i < buf_text_size ; i ++){
                const char letter = buf_txt.c_str()[i];
                length += glutBitmapWidth(GLUT_BITMAP_HELVETICA_10, letter);
                if(length > size_of_container){
                    break;
                }
                glutBitmapCharacter(GLUT_BITMAP_HELVETICA_10, letter);
            }
        }
        glPopMatrix();
    }/* end for (it_txt=...) */

}


inline void Render_opengl_dl::display_state(Element_pos , Element_pos ,
                          Element_count , Element_count ,
                          Element_pos , Element_pos ){

    glPushMatrix();
    {
        glTranslated( _default_entity_x_translate - _x_state_translate , -_y_state_translate, _z_state);
        glScalef(_x_state_scale*((_render_width-_default_entity_x_translate)/(_state_x_max-_state_x_min)), _y_state_scale*(_render_height-_ruler_height)/_container_y_max, 0.0f);

        if (glIsList(_list_states) == GL_FALSE)
            *Message::get_instance() << tr("ERROR LIST not exist for states.").toStdString() << Message::ende;
        else
            glCallList(_list_states);
    }
    glPopMatrix();
}


inline void Render_opengl_dl::display_arrow(Element_pos , Element_pos ,
                          Element_count , Element_count ,
                          Element_pos , Element_pos ){

    draw_stored_arrows(_arrows);/*draw arrows without display lists */
}


inline void Render_opengl_dl::display_event(Element_pos , Element_pos ,
                          Element_count , Element_count ){

    draw_stored_events(_events);/* draw events without display lists */
}


inline void Render_opengl_dl::display_counter(Element_pos , Element_pos ,
                            Element_count , Element_count ){

    glPushMatrix();
    {
        glTranslated(_default_entity_x_translate - _x_state_translate , -_y_state_translate, _z_counter);
        glScalef(_x_state_scale*((_render_width-_default_entity_x_translate)/(_state_x_max-_state_x_min)), _y_state_scale*(_render_height-_ruler_height)/_container_y_max, 0.0f);

        if (glIsList(_list_counters) == GL_FALSE) {
            *Message::get_instance() << tr("ERROR LIST not exist for counters.").toStdString() << Message::ende;
        }
        else
            glCallList(_list_counters);
    }
    glPopMatrix();
}

#endif
