diff --git a/Makefile.am b/Makefile.am index c2bb375..f08a0cf 100644 --- a/Makefile.am +++ b/Makefile.am @@ -307,6 +307,7 @@ sgpemv2_SOURCES = \ src/resources_widget.cc \ src/schedulable_state_widget.cc \ src/schedulables_tree_widget.cc \ + src/simulation_controller.cc \ src/simulation_widget.cc \ src/text_simulation.cc @@ -322,6 +323,7 @@ noinst_HEADERS += \ src/resources_widget.hh \ src/schedulable_state_widget.hh \ src/schedulables_tree_widget.hh \ + src/simulation_controller.hh \ src/simulation_widget.hh \ src/text_simulation.hh diff --git a/src/gui_builder.cc b/src/gui_builder.cc index 6b35024..be3952b 100644 --- a/src/gui_builder.cc +++ b/src/gui_builder.cc @@ -1,4 +1,4 @@ -// src/startgui.cc - Copyright 2005, 2006, University +// src/gui_builder.cc - Copyright 2005, 2006, University // of Padova, dept. of Pure and Applied // Mathematics // @@ -21,8 +21,9 @@ #include "config.h" #include "gettext.h" -#include "configure_policy_dialog.hh" #include "gui_builder.hh" + +#include "configure_policy_dialog.hh" #include "graphical_preferences_editor.hh" #include "schedulables_tree_widget.hh" #include "simulation_widget.hh" @@ -31,9 +32,7 @@ #include "sequences.tcc" #include "backend/cpu_policy_exception.hh" -#include "backend/malformed_policy_exception.hh" #include "backend/null_policy_exception.hh" -#include "backend/user_interrupt_exception.hh" #include "backend/cpu_policies_gatekeeper.hh" #include "backend/cpu_policy_manager.hh" #include "backend/resource_policies_gatekeeper.hh" @@ -46,16 +45,15 @@ #include #include -#include #include #include #include #include #include #include +#include #include #include -#include #include #include #include @@ -70,7 +68,8 @@ using Gnome::Glade::Xml; void GuiBuilder::on_edit_preferences_activate() { - new PreferencesEditor(); //FIXME: are we leaking this way? + new PreferencesEditor(); //FIXME: are we leaking this way? (definitely yes. use + // a refptr member data?) } void @@ -380,8 +379,6 @@ GuiBuilder::GuiBuilder(const std::string& gladefile) { using namespace Gtk; - //Window& main_window = get_initial_window(); - // file open dialog MenuItem* file_open = NULL; _refXml->get_widget("MenuItem.File.Open", file_open); @@ -492,191 +489,3 @@ GuiBuilder::open_file(const std::string& filename) std::cout << _("Filename to open: ") << filename << std::endl; } - -// --------------------------------- - -SimulationController::SimulationController(Simulation& simulation, Glib::RefPtr refXml) - : _sim(simulation), _break_requested(false) -{ - using namespace Gtk; - - _sim.attach(*this); - - // Start, pause and stop simulation from the toolbar - // TODO: can we use action groups instead of this? - - refXml->get_widget("ToolBar.Play", _toolbt_start); - refXml->get_widget("ToolBar.Pause", _toolbt_pause); - refXml->get_widget("ToolBar.Stop", _toolbt_stop); - - refXml->get_widget("MenuItem.Simulation.Play", _menuit_start); - refXml->get_widget("MenuItem.Simulation.Pause", _menuit_pause); - refXml->get_widget("MenuItem.Simulation.Stop", _menuit_stop); - - _toolbt_start->signal_clicked().connect(sigc::mem_fun(*this, &SimulationController::on_simulation_run)); - _toolbt_pause->signal_clicked().connect(sigc::mem_fun(*this, &SimulationController::on_simulation_pause)); - _toolbt_stop->signal_clicked().connect(sigc::mem_fun(*this, &SimulationController::on_simulation_stop)); - - _menuit_start->signal_activate().connect(sigc::mem_fun(*this, &SimulationController::on_simulation_run)); - _menuit_pause->signal_activate().connect(sigc::mem_fun(*this, &SimulationController::on_simulation_pause)); - _menuit_stop->signal_activate().connect(sigc::mem_fun(*this, &SimulationController::on_simulation_stop)); -} - - -SimulationController::~SimulationController() -{ - _sim.detach(*this); -} - - -void -SimulationController::on_simulation_run() -{ - // Sensitivities - _toolbt_start->set_sensitive(false); - _toolbt_pause->set_sensitive(true); - _toolbt_stop->set_sensitive(true); - - _menuit_start->set_sensitive(false); - _menuit_pause->set_sensitive(true); - _menuit_stop->set_sensitive(true); - - _break_requested = false; - // Used instead of simply calling "_sim.run()" to - // have exception handling only in one place: - run_simulation_adaptor(); -} - - -void -SimulationController::on_simulation_pause() -{ - // Sensitivities - _toolbt_start->set_sensitive(true); - _toolbt_pause->set_sensitive(false); - _toolbt_stop->set_sensitive(true); - - _menuit_start->set_sensitive(true); - _menuit_pause->set_sensitive(false); - _menuit_stop->set_sensitive(true); - - _break_requested = true; - _sim.pause(); -} - - -void -SimulationController::on_simulation_stop() -{ - // Sensitivities - _toolbt_start->set_sensitive(true); - _toolbt_pause->set_sensitive(false); - _toolbt_stop->set_sensitive(false); - - _menuit_start->set_sensitive(true); - _menuit_pause->set_sensitive(false); - _menuit_stop->set_sensitive(false); - - _break_requested = true; - _sim.stop(); -} - - -void -SimulationController::update(const Simulation& simulation) -{ -#ifndef NDEBUG - std::cerr << "SimulationController::update(), simulation state == " << std::hex << simulation.get_state() << std::endl; -#endif - - if(_break_requested) - return; - - switch(simulation.get_state()) - { - case Simulation::state_stopped: - on_simulation_stop(); - return; - case Simulation::state_paused: - on_simulation_pause(); - return; - case Simulation::state_running: - // Go on with the rest of the method... - break; - } - - // We should never enter here, if the code is correct: - // a step by step simulation should always be in paused - // or stopped state after performing a single step - assert(simulation.get_mode() != Simulation::mode_step_by_step); - - switch(simulation.get_mode()) - { - case Simulation::mode_continuous: - { - int timeout = GlobalPreferences::get_instance().get_speed(); - Glib::signal_timeout().connect(sigc::mem_fun(*this, &SimulationController::run_simulation_adaptor), timeout); - } - break; - default: - // Never gets here. - break; - } -} - - -bool -SimulationController::run_simulation_adaptor() -{ - using Gtk::MessageDialog; - using namespace Glib; - - if(!_break_requested) - try - { - _sim.run(); - } - catch(const UserInterruptException& uie) - { - // Show the user a dialog - MessageDialog diag(_("The selected user CPU policy stopped before returning:\n") + Markup::escape_text(uie.what()), - true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); - diag.run(); - } - catch(const MalformedPolicyException& mpe) - { - // Show user a dialog - MessageDialog diag(_("The selected user CPU policy was malformed and failed to sort the queue:\n") + - Markup::escape_text(mpe.what()), true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); - diag.run(); - - try - { - // Deactivate the policy - _sim.set_policy(NULL); - } - catch(const CPUPolicyException& cpe) - { - // Fatal error. We should never get here. - std::cerr << _(" [EE] Fatal error. Impossible to deactivate the policy in ") << __FILE__ << ":" << __LINE__ - << std::endl << _(" [EE] ") << cpe.what() << std::endl; - ; - abort(); - } - } - catch(const NullPolicyException& npe) - { - MessageDialog diag(_("No active policy selected:\n") + Markup::escape_text(npe.what()), - true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); - diag.run(); - - } - catch(const CPUPolicyException& cpe) - { - MessageDialog diag(_("Unexpected error:\n") + Markup::escape_text(cpe.what()), - true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); - diag.run(); - } - - return false; -} diff --git a/src/gui_builder.hh b/src/gui_builder.hh index 8349522..f7d17fe 100644 --- a/src/gui_builder.hh +++ b/src/gui_builder.hh @@ -26,56 +26,21 @@ #include "backend/cpu_policy.hh" #include "backend/resource_policy.hh" -#include "backend/simulation_observer.hh" + +#include "simulation_controller.hh" #include -#include #include #include #include -/** \brief This class initialize and starts the whole GUI - -*/ namespace sgpem { - class GuiBuilder; - class SimulationController; - - - // Helper class for controlling the simulation via callbacks - // TODO: move me to another file. - class SimulationController : public SimulationObserver - { - public: - SimulationController(Simulation& simulation, Glib::RefPtr main_window); - virtual ~SimulationController(); - - void update(const Simulation& simulation); - - private: - void on_simulation_run(); - void on_simulation_pause(); - void on_simulation_stop(); - - bool run_simulation_adaptor(); - - Simulation& _sim; - bool _break_requested; - - Gtk::ToolButton* _toolbt_start; - Gtk::ToolButton* _toolbt_pause; - Gtk::ToolButton* _toolbt_stop; - - Gtk::MenuItem* _menuit_start; - Gtk::MenuItem* _menuit_pause; - Gtk::MenuItem* _menuit_stop; - }; - - + /** \brief This class initialize and starts the whole GUI + */ class GuiBuilder { public: diff --git a/src/simulation_controller.cc b/src/simulation_controller.cc new file mode 100644 index 0000000..bc17e55 --- /dev/null +++ b/src/simulation_controller.cc @@ -0,0 +1,231 @@ +// src/simulation_controller.cc - Copyright 2005, 2006, University +// of Padova, dept. of Pure and Applied +// Mathematics +// +// This file is part of SGPEMv2. +// +// This is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// SGPEMv2 is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with SGPEMv2; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +#include "gettext.h" + +#include "simulation_controller.hh" + +#include "backend/cpu_policy_exception.hh" +#include "backend/malformed_policy_exception.hh" +#include "backend/null_policy_exception.hh" +#include "backend/user_interrupt_exception.hh" + +#include "backend/global_preferences.hh" +#include "backend/simulation.hh" + +#include +#include +#include +#include +#include +#include + +#include +#include + +using namespace sgpem; +using Gnome::Glade::Xml; + + +SimulationController::SimulationController(Simulation& simulation, Glib::RefPtr refXml) + : _sim(simulation), _break_requested(false) +{ + using namespace Gtk; + + _sim.attach(*this); + + // Start, pause and stop simulation from the toolbar + // TODO: can we use action groups instead of this? + + refXml->get_widget("ToolBar.Play", _toolbt_start); + refXml->get_widget("ToolBar.Pause", _toolbt_pause); + refXml->get_widget("ToolBar.Stop", _toolbt_stop); + + refXml->get_widget("MenuItem.Simulation.Play", _menuit_start); + refXml->get_widget("MenuItem.Simulation.Pause", _menuit_pause); + refXml->get_widget("MenuItem.Simulation.Stop", _menuit_stop); + + _toolbt_start->signal_clicked().connect(sigc::mem_fun(*this, &SimulationController::on_simulation_run)); + _toolbt_pause->signal_clicked().connect(sigc::mem_fun(*this, &SimulationController::on_simulation_pause)); + _toolbt_stop->signal_clicked().connect(sigc::mem_fun(*this, &SimulationController::on_simulation_stop)); + + _menuit_start->signal_activate().connect(sigc::mem_fun(*this, &SimulationController::on_simulation_run)); + _menuit_pause->signal_activate().connect(sigc::mem_fun(*this, &SimulationController::on_simulation_pause)); + _menuit_stop->signal_activate().connect(sigc::mem_fun(*this, &SimulationController::on_simulation_stop)); +} + + +SimulationController::~SimulationController() +{ + _sim.detach(*this); +} + + +void +SimulationController::on_simulation_run() +{ + // Sensitivities + _toolbt_start->set_sensitive(false); + _toolbt_pause->set_sensitive(true); + _toolbt_stop->set_sensitive(true); + + _menuit_start->set_sensitive(false); + _menuit_pause->set_sensitive(true); + _menuit_stop->set_sensitive(true); + + _break_requested = false; + // Used instead of simply calling "_sim.run()" to + // have exception handling only in one place: + run_simulation_adaptor(); +} + + +void +SimulationController::on_simulation_pause() +{ + // Sensitivities + _toolbt_start->set_sensitive(true); + _toolbt_pause->set_sensitive(false); + _toolbt_stop->set_sensitive(true); + + _menuit_start->set_sensitive(true); + _menuit_pause->set_sensitive(false); + _menuit_stop->set_sensitive(true); + + _break_requested = true; + _sim.pause(); +} + + +void +SimulationController::on_simulation_stop() +{ + // Sensitivities + _toolbt_start->set_sensitive(true); + _toolbt_pause->set_sensitive(false); + _toolbt_stop->set_sensitive(false); + + _menuit_start->set_sensitive(true); + _menuit_pause->set_sensitive(false); + _menuit_stop->set_sensitive(false); + + _break_requested = true; + _sim.stop(); +} + + +void +SimulationController::update(const Simulation& simulation) +{ +#ifndef NDEBUG + std::cerr << "SimulationController::update(), simulation state == " << std::hex << simulation.get_state() << std::endl; +#endif + + if(_break_requested) + return; + + switch(simulation.get_state()) + { + case Simulation::state_stopped: + on_simulation_stop(); + return; + case Simulation::state_paused: + on_simulation_pause(); + return; + case Simulation::state_running: + // Go on with the rest of the method... + break; + } + + // We should never enter here, if the code is correct: + // a step by step simulation should always be in paused + // or stopped state after performing a single step + assert(simulation.get_mode() != Simulation::mode_step_by_step); + + switch(simulation.get_mode()) + { + case Simulation::mode_continuous: + { + int timeout = GlobalPreferences::get_instance().get_speed(); + Glib::signal_timeout().connect(sigc::mem_fun(*this, &SimulationController::run_simulation_adaptor), timeout); + } + break; + default: + // Never gets here. + break; + } +} + + +bool +SimulationController::run_simulation_adaptor() +{ + using Gtk::MessageDialog; + using namespace Glib; + + if(!_break_requested) + try + { + _sim.run(); + } + catch(const UserInterruptException& uie) + { + // Show the user a dialog + MessageDialog diag(_("The selected user CPU policy stopped before returning:\n") + Markup::escape_text(uie.what()), + true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); + diag.run(); + } + catch(const MalformedPolicyException& mpe) + { + // Show user a dialog + MessageDialog diag(_("The selected user CPU policy was malformed and failed to sort the queue:\n") + + Markup::escape_text(mpe.what()), true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); + diag.run(); + + try + { + // Deactivate the policy + _sim.set_policy(NULL); + } + catch(const CPUPolicyException& cpe) + { + // Fatal error. We should never get here. + std::cerr << _(" [EE] Fatal error. Impossible to deactivate the policy in ") << __FILE__ << ":" << __LINE__ + << std::endl << _(" [EE] ") << cpe.what() << std::endl; + ; + abort(); + } + } + catch(const NullPolicyException& npe) + { + MessageDialog diag(_("No active policy selected:\n") + Markup::escape_text(npe.what()), + true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); + diag.run(); + + } + catch(const CPUPolicyException& cpe) + { + MessageDialog diag(_("Unexpected error:\n") + Markup::escape_text(cpe.what()), + true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); + diag.run(); + } + + return false; +} diff --git a/src/simulation_controller.hh b/src/simulation_controller.hh new file mode 100644 index 0000000..81c0b6d --- /dev/null +++ b/src/simulation_controller.hh @@ -0,0 +1,70 @@ +// src/simulation_controller.hh - Copyright 2005, 2006, University +// of Padova, dept. of Pure and Applied +// Mathematics +// +// This file is part of SGPEMv2. +// +// This is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// SGPEMv2 is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with SGPEMv2; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +#ifndef SIMULATION_CONTROLLER_HH +#define SIMULATION_CONTROLLER_HH 1 + +#include "config.h" + +#include "backend/simulation_observer.hh" + +#include +#include +#include + +namespace sgpem +{ + + class SimulationController; + + + /** \brief Helper class for controlling the simulation via callback + */ + class SimulationController : public SimulationObserver + { + public: + SimulationController(Simulation& simulation, Glib::RefPtr main_window); + virtual ~SimulationController(); + + void update(const Simulation& simulation); + + private: + void on_simulation_run(); + void on_simulation_pause(); + void on_simulation_stop(); + + bool run_simulation_adaptor(); + + Simulation& _sim; + bool _break_requested; + + Gtk::ToolButton* _toolbt_start; + Gtk::ToolButton* _toolbt_pause; + Gtk::ToolButton* _toolbt_stop; + + Gtk::MenuItem* _menuit_start; + Gtk::MenuItem* _menuit_pause; + Gtk::MenuItem* _menuit_stop; + }; + +} //~ namespace sgpem + +#endif //~ SIMULATION_CONTROLLER_HH +