Commit 86c8a54c authored by Olivier Lagrasse's avatar Olivier Lagrasse

- Correction bug lors du recentrage de la trace. (decalee au niveau des x)

- Ajout de PageUp et PageDown pour faire translation d'un ecran vers la droite et la gauche. (idem vers le haut et le bas avec ALT)
- Modification de la regle.
- Liage de la visualisation d'un intervalle pour OpenGL. (à partir de la ligne de commande)
- La trace n'est plus detruite lors de l'ouverture d'un fichier, ce qui permet de ne plus reparser lors d'un export.
- Debut gestion de l'affichage d'information des entites par clic de souris. (l'affichage n'est pas encore actif)
parent 1bdccca5
......@@ -12,7 +12,11 @@ int Info::Entity::x_max = 0;
bool Info::Render::_key_alt = false;
bool Info::Render::_key_ctrl = false;
Element_pos Info::Render::_x_min_visible = 0;;
Element_pos Info::Render::_x_max_visible = 0.;
Element_pos Info::Render::_x_min_visible = 0.0;
Element_pos Info::Render::_x_max_visible = 0.0;
Element_pos Info::Render::_info_x = 0.0;
Element_pos Info::Render::_info_y = 0.0;
Element_pos Info::Render::_info_accurate = 0.0;
bool Info::Render::_no_arrows_and_events = false;
......@@ -100,6 +100,21 @@ public:
*/
static Element_pos _x_max_visible;
/*!
* \brief Contains the x position of selection.
*/
static Element_pos _info_x;
/*!
* \brief Contains the y position of selection.
*/
static Element_pos _info_y;
/*!
* \brief Contains the accurate position of selection.
*/
static Element_pos _info_accurate;
/*!
* \brief To show the x beginning of the trace.
*/
......
......@@ -53,6 +53,7 @@ Interface_console::Interface_console(int argc, char ** argv){
_main_window = NULL;
_render_opengl = NULL;
_trace = NULL;
/* Init of the times */
_time_start = 0;
......@@ -64,6 +65,11 @@ Interface_console::Interface_console(int argc, char ** argv){
* Suppose that no window will be displayed.
*/
_is_window_displayed = false;
/*
* No trace loaded
*/
_is_trace_loaded = false;
launch_action(_state);
}
......@@ -90,7 +96,7 @@ Interface_console::~Interface_console(){
**********************************/
bool Interface_console::draw_trace(const string & filename, const int format){
Trace trace;
// Trace trace;
ParserPaje parser;
......@@ -114,23 +120,35 @@ bool Interface_console::draw_trace(const string & filename, const int format){
// _progress_dialog->show();
// thread.start();
try{
parser.parse(filename, trace);
}
catch (const string &error) {
Error::print_numbers();
Error::flush_in_file("log.txt");
//delete _progress_dialog;
*Message::get_instance() << "Reason : " << error << Message::ende;
QApplication::restoreOverrideCursor();
return false;
if (NULL == _trace){/* no trace is loaded, parse the file */
_trace = new Trace();
try{
parser.parse(filename, *_trace);
}
catch (const string &error) {
Error::print_numbers();
Error::flush_in_file("log.txt");
//delete _progress_dialog;
*Message::get_instance() << "Reason : " << error << Message::ende;
QApplication::restoreOverrideCursor();
return false;
}
}else if ( _file_opened != filename){/* just check if execution is normal */
*Message::get_instance() << "Try to use file: " << filename << " instead of a previous parsed file: " << _file_opened << Message::ende;
}
//delete _progress_dialog;
Interval interval(0, trace.get_max_date());
drawing_ogl.build(_render_opengl, &trace, 0, interval);
Interval interval(_time_start, ((0==_time_end)?_trace->get_max_date():_time_end) );
drawing_ogl.build(_render_opengl, _trace, 0, interval);
_render_opengl->build();
_render_opengl->updateGL();
_render_opengl->refresh_scroll_bars();
_is_trace_loaded = true;
}
_file_opened = filename;/* store filename for a future export */
......@@ -145,17 +163,28 @@ bool Interface_console::draw_trace(const string & filename, const int format){
svg.init(_path_to_export.c_str());
DrawTrace<Svg> drawing_svg;
try{
parser.parse(filename, trace);
}
catch (const string &error){
*Message::get_instance() << "Reason : " << error << Message::ende;
QApplication::restoreOverrideCursor();
return false;
if (NULL == _trace){/* no trace is loaded, parse the file */
_trace = new Trace();
try{
parser.parse(filename, *_trace);
}
catch (const string &error){
*Message::get_instance() << "Reason : " << error << Message::ende;
QApplication::restoreOverrideCursor();
return false;
}
}else if ( _file_opened != filename){/* just check if execution is normal */
*Message::get_instance() << "Try to use file: " << filename << " instead of a previous parsed file: " << _file_opened << Message::ende;
}
Interval interval(0, trace.get_max_date());
drawing_svg.build(&svg, &trace, 0, interval);
Interval interval(_time_start, ((0==_time_end)?_trace->get_max_date():_time_end));
drawing_svg.build(&svg, _trace, 0, interval);
svg.end();
_is_trace_loaded = true;
}
break;
/*******************
......@@ -386,6 +415,8 @@ void Interface_console::extract_times(const char *name) {
void Interface_console::launch_action(int state, void* arg){
DrawTrace<Render_opengl> buf;
switch(state) {
case _STATE_DISPLAY_HELP :
......@@ -468,12 +499,30 @@ void Interface_console::launch_action(int state, void* arg){
cout << "the end of the trace.";
}
launch_action(_STATE_LAUNCH_GRAPHICAL_INTERFACE, NULL);
draw_trace(_file_opened, _DRAW_OPENGL);
break;
case _STATE_RELEASE_RENDER_AREA:
if (_render_opengl->unbuild()==false)
message << "Close file : an error occured with trace releasing." << Message::ende;
_file_opened.clear();
if (false == _is_trace_loaded){
*Message::get_instance() << "Try to release a render area whereas no file was loaded" << Message::ende;
}else{
_is_trace_loaded = false;
}
if (NULL == _trace){
*Message::get_instance() << "Try to release a render area whereas no trace is loaded" << Message::ende;
}else{
delete _trace;
_trace = NULL;
}
_render_opengl->updateGL();
break;
......@@ -522,6 +571,13 @@ void Interface_console::launch_action(int state, void* arg){
_main_window->change_zoom_box_value( *((int*)arg) );
break;
case _STATE_RENDER_DISPLAY_INFORMATION:
buf.display_information(_trace, Info::Render::_info_x, Info::Render::_info_y, Info::Render::_info_accurate);
break;
default:/* like _STATE_UNKNOWN */
display_help();
warning(string("Cannot determine the arguments past. Please check the correct syntax."));
......
......@@ -153,6 +153,11 @@ public:
*/
static const int _STATE_ZOOM_BOX_VALUE = 20;
/*!
*\brief Display information about a selected entity.
*/
static const int _STATE_RENDER_DISPLAY_INFORMATION = 21;
/*!
* \brief Launch an action according to the argument state value.
* \param state An integer corresponding to a kind of action which must be executed.
......@@ -185,6 +190,14 @@ protected:
* are processed. (exportation for example)
*/
bool _is_window_displayed;
/*!
* \brief Use to know if a trace is loaded.
*
* This attributes is used to know for an export if a trace has already be parsed.
*/
bool _is_trace_loaded;
......@@ -209,6 +222,11 @@ protected:
*/
QApplication* app;
/*!
* \brief Contains the trace instance.
*/
Trace* _trace;
/*!
*\brief This attributes contains the launching current directory (_run_env[0]) and the first argument of the running command (_run_env[1]).
*/
......
......@@ -61,8 +61,7 @@ Interface_graphic::~Interface_graphic(){
void Interface_graphic::load_windows(){
QUiLoader loader;
QFile file_main(UI_MAIN_WINDOW_NAME);
QFile file_info(UI_INFO_WINDOW_NAME);
QFile file_info( ":/window/info_window.ui");
QFile file_selection_export(":/window/option_export_window.ui");
......@@ -71,7 +70,7 @@ void Interface_graphic::load_windows(){
/* Load the informative window from a .ui file */
file_info.open(QFile::ReadOnly);
CKFP(_ui_info_window = loader.load(&file_info, this), "Cannot open the .ui file : " << UI_MAIN_WINDOW_NAME);
CKFP(_ui_info_window = loader.load(&file_info, this), "Cannot open the .ui file : " << ":/window/info_window.ui");
file_info.close();
/* Load the _option_export_window from a .ui file */
......
......@@ -43,18 +43,12 @@ class Interface_graphic : public QMainWindow, protected Ui::main_window, public
void load_windows();
/***********************************
*
* Main window widget attributes.
*
**********************************/
/*!
* \brief This variable contains the main window of the application.
*/
//QWidget* _ui_main_window;
/*!
* \brief This variable contains the action to switch in fullscreen mode.
*/
......
......@@ -39,27 +39,6 @@
/* These paths corresponding to the path in the resource file ('vite.qrc' in the 'bin' folder) */
/*!
* \brief The main window ui file.
*/
#define UI_MAIN_WINDOW_NAME ":/window/main_window.ui"
/*!
* \brief The info window ui file.
*/
#define UI_INFO_WINDOW_NAME ":/window/info_window.ui"
/*!
* \brief PI with a precision of 8.
*/
#define PI 3.14159265
/* Now, two checkers are defined (the first for integer return value, the other
for pointer return value). Their body can be empty to enhance program speed.
To pass multi arguments for m, use "<<" between each arguments.
......
This diff is collapsed.
......@@ -995,7 +995,7 @@ inline void Render_opengl::draw_stored_arrows(std::vector<Arrow_> &arrows){
if (start_time != end_time){
angle = atan2((end_height - start_height), (end_time - start_time))*180.0f/PI;/* arc tangent */
angle = atan2((end_height - start_height), (end_time - start_time))*180.0f/M_PI;/* arc tangent */
glRotatef(angle, 0, 0, 1);
......@@ -1075,11 +1075,11 @@ inline void Render_opengl::draw_stored_events(std::vector<Event_> &events){
/* draw a circle */
radius = 0.3f;
angle = PI/2.0f;
angle = M_PI/2.0f;
step = 20;/* 20 polygons for the circle */
if (step!=0)
delta_angle = 2*PI/step;
delta_angle = 2*M_PI/step;
glColor3d(0.5, 0.8, 0.5);
......
......@@ -188,6 +188,15 @@ void Svg::set_wide_factor (Element_pos w) {
_wide_factor = w;
}
Element_pos Svg::get_height_factor() {
return _height_factor;
}
Element_pos Svg::get_wide_factor() {
return _wide_factor;
}
void Svg::set_interval(Times t1, Times t2) {
_start_interval_time = t1;
_end_interval_time = t2;
......
......@@ -204,6 +204,18 @@ public:
*/
static void set_height_factor (Element_pos w);
/*!
* \brief Return the height factor.
* \return The height factor.
*/
static Element_pos get_height_factor();
/*!
* \brief Return the widet factor.
* \return The wide factor.
*/
static Element_pos get_wide_factor();
/*!
* \brief the scale can be more accurate by increasing the _scale_frequency
*/
......
......@@ -117,7 +117,7 @@ void Container::end_link(Date time, Container *destination, String key) {
void Container::set_variable(Date time, VariableType *type, Double value) {
map<VariableType *, Variable *>::iterator i = _variables.find(type);
if (i == _variables.end()) {
_variables[type] = new Variable;
_variables[type] = new Variable(this, type);
_variables[type]->add_value(time, value);
_n_variables++;
}
......@@ -129,7 +129,7 @@ void Container::set_variable(Date time, VariableType *type, Double value) {
void Container::add_variable(Date time, VariableType *type, Double value) {
map<VariableType *, Variable *>::iterator i = _variables.find(type);
if (i == _variables.end()) {
_variables[type] = new Variable;
_variables[type] = new Variable(this, type);
_variables[type]->add_value(time, value);
_n_variables++;
}
......@@ -141,7 +141,7 @@ void Container::add_variable(Date time, VariableType *type, Double value) {
void Container::sub_variable(Date time, VariableType *type, Double value) {
map<VariableType *, Variable *>::iterator i = _variables.find(type);
if (i == _variables.end()) {
_variables[type] = new Variable;
_variables[type] = new Variable(this, type);
_variables[type]->add_value(time, -value);
_n_variables++;
}
......
......@@ -361,6 +361,194 @@ public:
Element_pos y2 = ((double)end+0.5)*(_container_height+_container_v_space);
draw_object->draw_arrow(starttime, endtime, y1, y2);
}
};
/*
* \brief Assuming someone has clicked in (x, y), display the description corresponding to the item clicked
*/
void display_information(const Trace *trace, double x, double y, double d) {
const Container *container = NULL;
const Container *ancestor = NULL;
const Link *link;
const Event *event;
const State *state;
const Variable *variable;
// find container needs to know the position of each container
double yr = y;
const list<Container *> *root_containers = trace->get_root_containers();
if (!root_containers->empty())
for (list<Container *>::const_iterator i = root_containers->begin();
i != root_containers->end();
i++)
if ((container = search_container_by_position(*i, yr)))
break;
// If the clic is out
if (!container)
return;
ancestor = container;
// First we browse to find a communication
while (ancestor) {
if (link = get_link(ancestor, x, y, d)) {
*Message::get_instance() << "Link: " << link->get_value()->get_name().to_string() << Message::endi;
return;
}
else
ancestor = ancestor->get_parent();
}
// Now browsing for the events of the container root
// Verification if it is a clic on an event
if ((!container->get_events()->empty() || !container->get_states()->empty()) && yr < _container_height+_container_v_space) {
if ((event = find_event(container, x, d))) {
*Message::get_instance() << "Event: " << event->get_value()->get_name().to_string() << Message::endi;
return;
}
if ((state = find_state(container, x))) {
*Message::get_instance() << "State: " << state->get_value()->get_name().to_string() << Message::endi;
return;
}
}
else {
if (!container->get_events()->empty() || !container->get_states()->empty())
yr -= _container_height+_container_v_space;
const map<VariableType *, Variable *> *variable_map = container->get_variables();
map<VariableType *, Variable *>::const_iterator i = variable_map->begin();
while (yr > _container_height+_container_v_space) {
yr -= _container_height+_container_v_space;
i++;
}
if (i != variable_map->end()) {
*Message::get_instance() << "Variable: " << (*i).second->get_type()->get_name().to_string() << Message::endi;
return;
}
}
// Nothing has been found
return;// NULL;
}
const Container *search_container_by_position(const Container *container, double &y) {
const Container *result;
// Search if the result is a descendant
const list<Container *> *children = container->get_children();
for (list<Container *>::const_iterator i = children->begin();
i != children->end();
i++) {
if ((result = search_container_by_position(*i, y)) != NULL)
return result;
}
// Calculate the size of the container (without its children)
int size;
if (!container->get_states()->empty() || !container->get_events()->empty()) {
size++;
_entity_containers.push_back(container);
}
if (container->get_variable_number() > 0) {
_variable_containers.push_back(container);
size += container->get_variable_number();
}
// Test if the position is in this container
if (y < size*(_container_height+_container_v_space))
return container;
// The position is outside this container
return NULL;
}
/*!
* \brief Tries to find a link passing by x and y in the container
*/
const Link* get_link(const Container *container, Element_pos x, Element_pos y, Element_pos d) {
const list<Link *> *link_list;
Link *link;
double a, b, c; // Equation: ax + by + c = 0
double x1, x2, y1, y2;
if(!container)
return NULL;
// Browse links
link_list = container->get_links();
for (list<Link *>::const_iterator it = link_list->begin();
it != link_list->end();
it++) {
link = *it;
x1 = link->get_start_time().get_value();
x2 = link->get_end_time().get_value();
y1 = ((double)_container_positions[link->get_source()]+0.5)*(_container_height+_container_v_space);
y2 = ((double)_container_positions[link->get_destination()]+0.5)*(_container_height+_container_v_space);
if (x1-d <= x && x <= x2+d || x2-d <= x && x <= x1+d) { // Test the interval
a = y1 - y2;
b = x2 - x1;
c = -(a*x1 + b*x2);
double e = a*x + b*y + c;
if (e*e/(a*a + b*b) < d*d) // Test the distance
return link;
}
}
return NULL;
}
/*
* \brief Returns the event that occurs at the time x in the container
*/
const Event *find_event(const Container *container, Element_pos x, Element_pos d) {
if(!container)
return NULL;
Node<Event> *node = container->get_events()->get_root();
while(node) {
Element_pos t = node->get_element()->get_time().get_value();
if (x < t) {
if (t - x < d)
return node->get_element();
node = node->get_left_child();
}
else {
if (x - t < d)
return node->get_element();
node = node->get_right_child();
}
}
return NULL;
}
/*
* \brief Returns the state at the time x
*/
const State * find_state(const Container *container, Element_pos x) {
if(!container)
return NULL;
Node<StateChange> *node = container->get_states()->get_root();
while(node) {
Element_pos t = node->get_element()->get_time().get_value();
if (x < t) {
if (node->get_element()->get_left_state()->get_start_time().get_value() < x)
return node->get_element()->get_left_state();
node = node->get_left_child();
}
else {
if (x < node->get_element()->get_right_state()->get_end_time().get_value())
return node->get_element()->get_right_state();
node = node->get_right_child();
}
}
return NULL;
}
};
#endif
#include "Variable.hpp"
Variable::Variable(): _min(0.0), _max(0.0) {
Variable::Variable(Container *container, VariableType *type): Entity(container), _min(0.0), _max(0.0), _type(type) {
}
......@@ -30,3 +30,7 @@ Double Variable::get_max() const {
return _max;
}
const VariableType *Variable::get_type() const {
return _type;
}
......@@ -5,6 +5,10 @@
* \file Variable.hpp
*/
class Variable;
#include "Entity.hpp"
#include "VariableType.hpp"
#include "values/Date.hpp"
#include "values/Double.hpp"
#include <list>
......@@ -15,16 +19,19 @@ using std::pair;
* \class Variable
* \brief Describe a variable
*/
class Variable {
class Variable: public Entity {
private:
list<pair<Date, Double> > _values;
Double _min, _max;
VariableType *_type;
public:
/*!
* \brief Constructor
* \param container Container of this variable
* \parma type Type of this variable
*/
Variable();
Variable(Container *container, VariableType *type);
/*!