diff --git a/src/cairo_widget.cc b/src/cairo_widget.cc index fb4a387..26dff27 100644 --- a/src/cairo_widget.cc +++ b/src/cairo_widget.cc @@ -130,24 +130,27 @@ CairoWidget::on_size_request(Gtk::Requisition* requisition) // Gtk+ asks the desired widget dimension // std::cout << " on_size_request, requisition->width : " << requisition->width << ", requisition->height : " << requisition->height << std::endl; + + _client_w = requisition->width; + _client_h = requisition->height; + calc_widget_size(_client_w, _client_h); + requisition->width = _client_w; requisition->height = _client_h; - } bool CairoWidget::on_expose_event(GdkEventExpose* event) { - // std::cout << " on_expose_event START..."; + // std::cout << " on_expose_event START..."; if (event == NULL || event->count > 0) return false; // std::cout << " on_expose_event CONTINUE." << std::endl; - - int actual_w = get_width(); - int actual_h = get_height(); - + + int actual_w = get_width(); + int actual_h = get_height(); // std::cout << " get_width() : " << actual_w << ", get_height() : " << actual_h << std::endl; // std::cout << " _client_w : " << _client_w << ", _client_h : " << _client_h << std::endl; // std::cout << " _pixmap_w : " << _pixmap_w << ", _pixmap_h : " << _pixmap_h << std::endl; @@ -163,9 +166,10 @@ CairoWidget::on_expose_event(GdkEventExpose* event) // previdence in the code: allocate more than actually needed _pixmap_w = (size_t) (_client_w*1.2); _pixmap_h = (size_t) (_client_h*1.2); - std::cout << " on_expose_event CREATE Pixmap. w : " << _pixmap_w << ", h : " << _pixmap_h<< std::endl; + // std::cout << " on_expose_event CREATE Pixmap. w : " << _pixmap_w << ", h : " << _pixmap_h<< std::endl; _buf = Gdk::Pixmap::create(get_window(), _pixmap_w, _pixmap_h); } + // Draw the widget background as the first thing. // I've seen this is how it's done in the very Gtk+ toolkit @@ -176,50 +180,23 @@ CairoWidget::on_expose_event(GdkEventExpose* event) GTK_STATE_NORMAL, GTK_SHADOW_ETCHED_IN, NULL, (GtkWidget*)this->gobj(), "through", 0, 0, _client_w, _client_h); - + cairo_t* ctx = gdk_cairo_create(_buf->gobj()); - + // Determine the final drawing dimensions before to start drawing _draw_w = _draw_h = 0; // default no scaling - calc_drawing_size(_draw_w, _draw_h); + calc_drawing_size(ctx, _draw_w, _draw_h); + + calc_scale_factors(); + // do the drawing... - if(_scaling_mode!=scaling_none && _draw_w>0 && _draw_h>0) - { - double sx = (double)_client_w/(double)_draw_w; - double sy = (double)_client_h/(double)_draw_h; - switch(_scaling_mode) - { - case scaling_none: - sx = sy = 1.0; - break; - case scaling_to_w: - sy = sx; - break; - case scaling_to_h: - sx = sy; - break; - case scaling_min: - if(sx<=sy) - sy = sx; - else - sx = sy; - break; - case scaling_max: - if(sx>=sy) - sy = sx; - else - sx = sy; - break; - case scaling_all: - // nothing to do... - break; - } - cairo_scale(ctx, sx, sy); - } + cairo_scale(ctx, _scale_x, _scale_y); + // std::cout << " on_expose_event Dimensions, w : " << _draw_w << ", h : " << _draw_h << std::endl; draw_widget(ctx); cairo_destroy(ctx); } + // calculated dinamically on update(): // set_size_request(_draw_w, _draw_h); @@ -235,6 +212,47 @@ CairoWidget::on_expose_event(GdkEventExpose* event) return true; } +void +CairoWidget::calc_scale_factors() +{ + if(_scaling_mode!=scaling_none && _draw_w!=0 && _draw_h!=0) + { + _scale_x = (double)_client_w/(double)_draw_w; + _scale_y = (double)_client_h/(double)_draw_h; + switch(_scaling_mode) + { + case scaling_none: // not necessary! + _scale_x = _scale_y = 1.0; + break; + case scaling_to_w: + _scale_y = _scale_x; + break; + case scaling_to_h: + _scale_x = _scale_y; + break; + case scaling_min: + if(_scale_x<=_scale_y) + _scale_y = _scale_x; + else + _scale_x = _scale_y; + break; + case scaling_max: + if(_scale_x>=_scale_y) + _scale_y = _scale_x; + else + _scale_x = _scale_y; + break; + case scaling_all: + // nothing to do... + break; + } + } + else + { + _scale_x = _scale_y = 1.0; + } +} + bool CairoWidget::on_button_press_event(GdkEventButton* event) { @@ -249,13 +267,42 @@ CairoWidget::redraw() queue_draw(); } - void -CairoWidget::calc_drawing_size(size_t& width, size_t& height) const +CairoWidget::resize_redraw() { + + // std::cout << " resize_redraw BEGIN width: " << get_width() << ", height: " << get_height() << std::endl; + if(_buf) + { + cairo_t* ctx = gdk_cairo_create(_buf->gobj()); + + if(ctx) + { + // Determine the final drawing dimensions before to start drawing + _draw_w = _draw_h = 0; // default no scaling + calc_drawing_size(ctx, _draw_w, _draw_h); + + calc_scale_factors(); + + set_size_request((int)_scale_x*_draw_w, (int)_scale_y*_draw_h); + cairo_destroy(ctx); + //std::cout << " resize_redraw DO width: " << _scale_x*_draw_w << ", height: " << _scale_y*_draw_h << std::endl; + } + } + + // Force redraw + _need_redraw = true; + queue_draw(); } void -CairoWidget::calc_widget_size(size_t& width, size_t& height) const +CairoWidget::calc_drawing_size(cairo_t* ctx, size_t& width, size_t& height) { } + + +void +CairoWidget::calc_widget_size(size_t& width, size_t& height) +{ +} + diff --git a/src/cairo_widget.hh b/src/cairo_widget.hh index 63591c4..f74f34a 100644 --- a/src/cairo_widget.hh +++ b/src/cairo_widget.hh @@ -24,6 +24,7 @@ #include "config.h" #include +#include #include #include @@ -44,14 +45,24 @@ namespace sgpem CairoWidget(); virtual ~CairoWidget(); + + // scaling related functions scaling_mode set_scaling_mode(scaling_mode scaling_mode); scaling_mode get_scaling_mode(); - void change_scaling_mode(); + + // need for redrawing the widget (double buffering related) void redraw(); + // need for auto resizing and redrawing the widget (double buffering related) + void resize_redraw(); + + // TODO - temporary: will be removed soon + // void change_scaling_mode(); + protected: typedef unsigned int size_t; + // implements fundamental widget's method virtual void on_realize(); virtual void on_size_allocate(const Gtk::Allocation& allocation); virtual void on_size_request(Gtk::Requisition* request); @@ -62,10 +73,12 @@ namespace sgpem virtual void draw_widget(cairo_t* ctx) = 0; // with this method CairoWidget tells the needed drawing dimensions - virtual void calc_drawing_size(size_t& width, size_t& height) const; + virtual void calc_drawing_size(cairo_t* ctx, size_t& width, size_t& height); // with this method CairoWidget tells the needed widgwt dimensions - virtual void calc_widget_size(size_t& width, size_t& height) const; + virtual void calc_widget_size(size_t& width, size_t& height); + + void calc_scale_factors(); typedef Gdk::Rectangle area_t; typedef sigc::mem_functor0 method0_t; @@ -75,12 +88,18 @@ namespace sgpem private: // The width and height the widget will assume, must be determined // before starting drawing by calc_size() + // drawing dimensions required mutable size_t _draw_w; mutable size_t _draw_h; + // window client area mutable size_t _client_w; mutable size_t _client_h; + // pixmap client area mutable size_t _pixmap_w; mutable size_t _pixmap_h; + // cairo scale factors + mutable double _scale_x; + mutable double _scale_y; mutable bool _need_redraw; scaling_mode _scaling_mode; diff --git a/src/simulation_widget.cc b/src/simulation_widget.cc index 37447fd..a5affd9 100644 --- a/src/simulation_widget.cc +++ b/src/simulation_widget.cc @@ -57,7 +57,8 @@ SimulationWidget::update(const Simulation& changed_simulation) _simulation = &changed_simulation; // Force redraw - redraw(); + //redraw(); + resize_redraw(); } @@ -71,24 +72,63 @@ SimulationWidget::draw_widget(cairo_t* ctx) std::cout << " draw_widget continue " << std::endl; */ - const History& hist = Simulation::get_instance().get_history(); + + const Simulation& simu = Simulation::get_instance(); + double top_margin = _y_unit; + double left_margin = _x_unit; + double top_graph_margin = 1.0 * _y_unit; //3.0 * _y_unit; + double left_graph_margin = 11.0 * _x_unit; + double process_label_delta = 1.0 * _y_unit; + double process_bar_delta = 1.0 * _y_unit; + double process_bar_height = 1.0 * _y_unit; + double process_height = process_bar_height + 2*process_bar_delta; + Simulation::state sim_state = simu.get_state(); + const History& hist = simu.get_history(); const Environment::Processes& processes = hist.get_last_environment().get_processes(); int nproc = processes.size(); double text_maxw = 0; bool* terminated = 0; + cairo_text_extents_t extents; + + // evaluate minimum x and y extensions + /* + // show simulation title + Glib::ustring title; + switch(sim_state) + { + case Simulation::state_running: + title = "Simulation Running"; + break; + case Simulation::state_paused: + title = "Simulation Paused"; + break; + case Simulation::state_stopped: + title = "Simulation Stopped"; + break; + } + cairo_text_extents(ctx, title.c_str(), &extents); + cairo_move_to(ctx, left_margin, extents.height + top_margin); + cairo_show_text(ctx,title.c_str()); + */ + if(nproc>0) terminated = new bool[nproc]; - + + // show processes names... + // set clip region to cut long names + cairo_rectangle(ctx, 0, top_graph_margin, left_graph_margin - _x_unit, nproc*process_height); + cairo_clip(ctx); // set the rectangular clip region for(int i=0; iget_name().c_str(), &extents); if(text_maxwget_name().c_str()); terminated[i] = false; } + cairo_reset_clip(ctx); // remove clip region if(_simulation && hist.get_size()>0 /* && _simulation->get_state()!=Simulation::state_stopped */ ) @@ -96,13 +136,38 @@ SimulationWidget::draw_widget(cairo_t* ctx) // std::cout << " draw_widget not_stop " << std::endl; unsigned int pos = _simulation->get_front(); + // show grid + cairo_save(ctx); + cairo_set_line_width(ctx, 0.5*cairo_get_line_width(ctx)); + // nproc+1 horizontal lines + for(int i=0; i<=nproc; i++) + { + cairo_move_to(ctx, left_graph_margin, top_graph_margin + process_height*i); + cairo_line_to(ctx, left_graph_margin + (pos+2)*_x_unit, top_graph_margin + process_height*i); + } + // opening vertical line + cairo_move_to(ctx, left_graph_margin, top_graph_margin); + cairo_line_to(ctx, left_graph_margin, top_graph_margin + process_height*nproc); + cairo_stroke(ctx); + + // closing vertical line + if(sim_state!=Simulation::state_stopped) + { + double dashes = 1.5; + cairo_set_dash(ctx, &dashes, 1, 0.0); + } + cairo_move_to(ctx, left_graph_margin + (pos+2)*_x_unit, top_graph_margin); + cairo_line_to(ctx, left_graph_margin + (pos+2)*_x_unit, top_graph_margin + process_height*nproc); + cairo_stroke(ctx); + cairo_restore(ctx); + for(int t=1; t<=pos; t++) { const Environment::Processes& processes = hist.get_environment_at(t).get_processes(); - double xpos = text_maxw + (1 + t)*_x_unit; + double xpos = left_graph_margin + t*_x_unit; for(int i=0; iget_state(); switch(st) { @@ -135,20 +200,57 @@ SimulationWidget::draw_widget(cairo_t* ctx) } } } + + + cairo_save(ctx); + cairo_set_source_rgb(ctx, 0, 0, 0); + cairo_set_line_width(ctx, 0.25*cairo_get_line_width(ctx)); + for(int t=0; t<=pos; t++) + { + cairo_move_to(ctx, left_graph_margin + (t+1)*_x_unit, top_graph_margin + process_height*nproc); + cairo_rel_line_to(ctx, 0, 0.5 * _y_unit); + Glib::ustring val; + int_to_string(t, val); + cairo_move_to(ctx, left_graph_margin + (t+1)*_x_unit, + top_graph_margin + process_height*nproc + _y_unit + extents.height); + cairo_show_text(ctx,val.c_str()); + } + cairo_stroke(ctx); + cairo_restore(ctx); + + /* + int w = left_graph_margin + (pos+4)*_x_unit; + int h = top_graph_margin + process_height*nproc + 4*_y_unit; + if(get_height()get_history(); const Environment::Processes& processes = hist.get_last_environment().get_processes(); - width = (10 + 1 + hist.get_size()) * _x_unit; - height = 3 * processes.size() * _y_unit; + int pos = _simulation->get_front(); + cairo_text_extents_t extents; + + // std::cout << " x_unit: " << std::endl; + Glib::ustring val("999"); + cairo_text_extents(ctx, val.c_str(), &extents); + if(_x_unit #include #include #include #include #include +#include #include +#include #include #include #include -/* -#include "backend/concrete_environment.hh" -#include "backend/concrete_history.hh" -*/ #include "backend/cpu_policies_gatekeeper.hh" #include "backend/cpu_policy.hh" #include "backend/cpu_policy_manager.hh" @@ -52,20 +51,18 @@ #include "cairo_elements.hh" #include "cairo_widget.hh" #include "simulation_widget.hh" -// #include "backend/concrete_history.hh" using namespace sgpem; using namespace std; using Glib::ustring; + // ------------------------------------------------------ // // PRRPolicy class // // ------------------------------------------------------ - - /** An hard-coded Priority Round Robin policy * it adds a new constructor taking the quantum size (time slice)*/ @@ -102,16 +99,6 @@ public: ReadyQueue* sl = Scheduler::get_instance().get_ready_queue(); if(sl && sl->size()>=2) { - /* - cout << " sort_queue time: " << Simulation::get_instance().get_front() << endl; - for (int i = 0; i < sl->size(); i++) - { - cout << " i: " << i << " name: " << sl->get_item_at(i).get_name() - << " pr: " << sl->get_item_at(i).get_current_priority() - << " last: " << sl->get_item_at(i).get_last_acquisition() - << endl; - } - */ for (int i = 0; i < sl->size(); i++) { for (int j = 0; j < sl->size() - 1; j++) @@ -125,25 +112,15 @@ public: } } - /* - cout << "after" << endl; - for (int i = 0; i < sl->size(); i++) - { - cout << " i: " << i << " name: " << sl->get_item_at(i).get_name() - << " pr: " << sl->get_item_at(i).get_current_priority() - << " last: " << sl->get_item_at(i).get_last_acquisition() - << endl; - } - cout << endl; - */ } - } + /* int get_id() const { return 42; } + */ virtual Glib::ustring get_description() const { @@ -178,18 +155,17 @@ public: protected: PolicyParameters _parameters; - int _id; + // int _id; int _quantum; private: static PRRPolicy* _instance; - - }; PRRPolicy* PRRPolicy::_instance=0; + // ------------------------------------------------------ // // DummyPolicyManager class @@ -246,25 +222,13 @@ protected: -// insert some resources, processes, threads, requests, subrequests -void fillHistory(History &hist); - -// print entire environment into the passed ostream -void dumpEnvironment(const Environment& env, ostream &os); - -Glib::ustring get_schedulable_state_name(Schedulable::state st); - -Glib::ustring get_request_state_name(Request::state st); - -Glib::ustring get_simulation_state_name(Simulation::state st); - +/* // ------------------------------------------------------ // // TestWidget class // // ------------------------------------------------------ - namespace sgpem { class TestWidget : public SimulationObserver, public CairoWidget @@ -429,12 +393,14 @@ TestWidget::change_scaling_mode() } redraw(); } - +*/ // ------------------------------------------------------ // // MainWindow class // +// contains and controls the tested widget +// // ------------------------------------------------------ class MainWindow : public Gtk::Window { @@ -445,18 +411,27 @@ public: protected: virtual void on_button_start_clicked(); virtual void on_button_stop_clicked(); + virtual void on_button_pause_clicked(); + virtual void on_button_runmode_clicked(); + virtual bool on_timer_timeout(); - TestWidget _test_widget; + // TestWidget _test_widget; SimulationWidget _simulation_widget; Gtk::Button _start_button; Gtk::Button _stop_button; + Gtk::Button _pause_button; + Gtk::CheckButton _runmode_button; Gtk::HBox _buttons_box; Gtk::VBox _main_box; + Gtk::ScrolledWindow _scroller; + Simulation::state _sim_state; }; -MainWindow::MainWindow() : _start_button("Start"), _stop_button("Stop") +MainWindow::MainWindow() : _start_button("Start"), _stop_button("Stop"), + _pause_button("Pause"), _runmode_button("Continue") { + _sim_state = Simulation::state_stopped; // This just sets the title of our new window. set_title("Simulation Widget Test"); add(_main_box); @@ -464,18 +439,43 @@ MainWindow::MainWindow() : _start_button("Start"), _stop_button("Stop") _start_button.show(); _buttons_box.pack_start(_stop_button); _stop_button.show(); + _buttons_box.pack_start(_pause_button); + _pause_button.show(); + _buttons_box.pack_start(_runmode_button); + _runmode_button.set_active(false); + _runmode_button.show(); _main_box.pack_start(_buttons_box, Gtk::PACK_SHRINK); _buttons_box.show(); // _main_box.pack_start(_test_widget); // _test_widget.show(); - _main_box.pack_start(_simulation_widget); + _scroller.add(_simulation_widget); + _scroller.show(); + + _main_box.pack_start(_scroller); _simulation_widget.show(); _main_box.show(); // Simulation::get_instance().attach(_simulation_widget); - +/* _start_button.signal_clicked().connect( sigc::mem_fun(*this, &MainWindow::on_button_start_clicked) ); _stop_button.signal_clicked().connect( sigc::mem_fun(*this, &MainWindow::on_button_stop_clicked) ); + _pause_button.signal_clicked().connect( sigc::mem_fun(*this, &MainWindow::on_button_pause_clicked) ); + _runmode_button.signal_clicked().connect( sigc::mem_fun(*this, &MainWindow::on_button_runmode_clicked) ); +*/ + // connect after standard signal handler + _start_button.signal_clicked().connect( sigc::mem_fun(*this, &MainWindow::on_button_start_clicked), true ); + _stop_button.signal_clicked().connect( sigc::mem_fun(*this, &MainWindow::on_button_stop_clicked), true ); + _pause_button.signal_clicked().connect( sigc::mem_fun(*this, &MainWindow::on_button_pause_clicked), true ); + _runmode_button.signal_clicked().connect( sigc::mem_fun(*this, &MainWindow::on_button_runmode_clicked), true ); + + Glib::signal_timeout().connect(sigc::mem_fun(*this, &MainWindow::on_timer_timeout), 1000); + + //is equivalent to: + /* + const Glib::RefPtr timeout_source = Glib::TimeoutSource::create(1000); + timeout_source->connect(sigc::ptr_fun(&timeout_handler)); + timeout_source->attach(Glib::MainContext::get_default()); + */ } MainWindow::~MainWindow() @@ -484,17 +484,89 @@ MainWindow::~MainWindow() void MainWindow::on_button_start_clicked() { - Simulation::get_instance().run(); + if(_sim_state == Simulation::state_stopped + || _sim_state == Simulation::state_paused) + { + if(!_runmode_button.get_active()) + { + // one step - drive directly simulation + Simulation& simu = Simulation::get_instance(); + simu.run(); + _sim_state = simu.get_state(); + // _simulation_widget.redraw(); + } + else + { + _sim_state = Simulation::state_running; + } + } } void MainWindow::on_button_stop_clicked() { - Simulation::get_instance().stop(); - _simulation_widget.redraw(); + if(_sim_state == Simulation::state_running + || _sim_state == Simulation::state_paused) + { + _sim_state = Simulation::state_stopped; + Simulation::get_instance().stop(); + // _simulation_widget.redraw(); + } +} +void MainWindow::on_button_pause_clicked() +{ + if(_sim_state == Simulation::state_running) + { + _sim_state = Simulation::state_paused; + } + else if(_sim_state == Simulation::state_paused) + { + _sim_state = Simulation::state_running; + } +} +void MainWindow::on_button_runmode_clicked() +{ +} + +bool MainWindow::on_timer_timeout() +{ + // std::cout << "Timer sim stat= " << _sim_state << endl; + if(_sim_state == Simulation::state_running) + { + Simulation& simu = Simulation::get_instance(); + simu.run(); + // _simulation_widget.redraw(); + if(simu.get_state()==Simulation::state_stopped) + _sim_state = Simulation::state_stopped; + } + return true; } +// utility functions... +// insert some resources, processes, threads, requests, subrequests +void fillHistory(History &hist); + +// print entire environment into the passed ostream +void dumpEnvironment(const Environment& env, ostream &os); + +// return the Schedulable::state readable string +Glib::ustring get_schedulable_state_name(Schedulable::state st); + +// return the Request::state readable string +Glib::ustring get_request_state_name(Request::state st); + +// return the Simulation::state readable string +Glib::ustring get_simulation_state_name(Simulation::state st); + + + + +// ------------------------------------------------------ +// +// MainWindow class +// +// ------------------------------------------------------ int main(int argc, char** argv) @@ -516,24 +588,19 @@ main(int argc, char** argv) info << "gets history \n"; DummyPolicyManager dummy_manager; - /* - DummyPolicy dummy_policy; - PRRPolicy PRR_Policy; - */ const std::vector& policies = dummy_manager.get_avail_policies(); CPUPolicy* pol = policies[0]; info << "policy " << pol->get_name() << endl; - // CPUPoliciesGatekeeper::get_instance().register_manager(&dummy_manager); + fillHistory(hist); info << "history filled \n"; - // CPUPoliciesGatekeeper::get_instance().activate_policy(&hist, pol); simu.set_policy(pol); info << "policy activated \n"; simu.set_mode(false); - simu.set_timer(100); + simu.set_timer(0); info << "simulation set_mode single step\n"; info << "START environment dump \n"; @@ -541,11 +608,10 @@ main(int argc, char** argv) info << "END environment dump \n"; info << "simulation state: " << get_simulation_state_name(simu.get_state()) << endl; - // Gtk::Window win; MainWindow win; win.set_border_width(10); - win.resize (700, 200); + win.resize (400, 200); Gtk::Main::run(win); return 0;