From c08c30e78fdbbde7e5823b26303b0dded3a4c1cf Mon Sep 17 00:00:00 2001 From: "Ira W. Snyder" Date: Sat, 6 Oct 2007 20:46:42 -0700 Subject: [PATCH] Implement the GUI This implements the GUI in it's entirety. Signed-off-by: Ira W. Snyder --- Makefile | 13 +- callbutton.cpp | 21 ++++ callbutton.hpp | 22 ++++ eclose.png | Bin 0 -> 392 bytes elevatordoor.cpp | 31 +++++ elevatordoor.hpp | 30 +++++ elevatorgui.cpp | 295 ++++++++++++++++++++++++++++++++++++++++++++++ elevatorgui.hpp | 77 ++++++++++++ eopen2.png | Bin 0 -> 702 bytes positionlabel.cpp | 15 +++ positionlabel.hpp | 20 ++++ requestbutton.cpp | 21 ++++ requestbutton.hpp | 22 ++++ test.cpp | 18 +++ 14 files changed, 583 insertions(+), 2 deletions(-) create mode 100644 callbutton.cpp create mode 100644 callbutton.hpp create mode 100644 eclose.png create mode 100644 elevatordoor.cpp create mode 100644 elevatordoor.hpp create mode 100644 elevatorgui.cpp create mode 100644 elevatorgui.hpp create mode 100644 eopen2.png create mode 100644 positionlabel.cpp create mode 100644 positionlabel.hpp create mode 100644 requestbutton.cpp create mode 100644 requestbutton.hpp diff --git a/Makefile b/Makefile index 116c3ce..acc9a11 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,14 @@ -test: position.o stop.o elevator.o elevatorcontroller.o test.o - g++ -o $@ $^ +CC=g++ +CFLAGS=`pkg-config gtkmm-2.4 --cflags` +LIBS=`pkg-config gtkmm-2.4 --libs` + +SRCS=position.cpp stop.cpp elevator.cpp elevatorcontroller.cpp elevatordoor.cpp callbutton.cpp positionlabel.cpp requestbutton.cpp elevatorgui.cpp test.cpp + +test: $(SRCS:.cpp=.o) + $(CC) -o $@ $^ $(LIBS) + +.cpp.o: + $(CC) $(CFLAGS) -c -o $@ $< run: test ./test diff --git a/callbutton.cpp b/callbutton.cpp new file mode 100644 index 0000000..5139130 --- /dev/null +++ b/callbutton.cpp @@ -0,0 +1,21 @@ +#include "callbutton.hpp" + +CallButton::CallButton (int floor, Direction direction) + : Gtk::ToggleButton() + , floor_(floor) + , direction_(direction) +{ + // Intentionally Left Empty +} + +int CallButton::getFloorNumber () const +{ + return floor_; +} + +Direction CallButton::getDirection () const +{ + return direction_; +} + +/* vim: set ts=4 sts=4 sw=4 noet tw=112: */ diff --git a/callbutton.hpp b/callbutton.hpp new file mode 100644 index 0000000..262c5ff --- /dev/null +++ b/callbutton.hpp @@ -0,0 +1,22 @@ +#ifndef CALLBUTTON_HPP +#define CALLBUTTON_HPP + +#include "direction.hpp" +#include + +class CallButton : public Gtk::ToggleButton +{ + public: + CallButton (int floor, Direction direction); + + int getFloorNumber () const; + Direction getDirection () const; + + private: + int floor_; + Direction direction_; +}; + +#endif /* CALLBUTTON_HPP */ + +/* vim: set ts=4 sts=4 sw=4 noet tw=112: */ diff --git a/eclose.png b/eclose.png new file mode 100644 index 0000000000000000000000000000000000000000..95047b79122684e2fc1e907b769af3438ce1823a GIT binary patch literal 392 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1SD@HCBD!6<42E0#E z%>ybt<>}%W65*blAkpIBKT-W+tkSW_IW|)sX=IWFZVKVSCY z`z|@Decc(O;Hl48X1R7+IjbU0`&0yO{5g zEazfH7mdcgwhI{?z0;g4xISK-G%J8jl6T=nfki81na|WN&df03?OmprlbNuk(M==0 z2dvaA(S7!Y#fJ?ufT9U9x)Sc($1XM%Zb>*2ZV+Uo%Ak|D(tfMM$t9cx``Ug@)^E;g b;$m2!b~ +#include + + +const std::string OPENED_IMAGE = "eopen2.png"; +const std::string CLOSED_IMAGE = "eclose.png"; + + +class ElevatorDoor : public Gtk::Image +{ + public: + ElevatorDoor (int elevator, int floor); + + int getElevatorNumber() const; + int getFloorNumber() const; + + void open (); + void close (); + + private: + int elevator_; + int floor_; +}; + +#endif /* ELEVATORDOOR_HPP */ + +/* vim: set ts=4 sts=4 sw=4 noet tw=112: */ diff --git a/elevatorgui.cpp b/elevatorgui.cpp new file mode 100644 index 0000000..f9d03a1 --- /dev/null +++ b/elevatorgui.cpp @@ -0,0 +1,295 @@ +#include "elevatorgui.hpp" + +ElevatorGUI::ElevatorGUI (int floors, int elevators) + : Gtk::Window() + , number_of_floors_(floors) + , number_of_elevators_(elevators) + , simulation_status_(STOPPED) + + /* The ElevatorController */ + , ec_(floors, elevators) + + /* The Timer */ + , timer_() + + /* GUI Elements */ + , table_(floors+1, elevators+3) + , button_playpause_(Gtk::Stock::MEDIA_PLAY) + , button_stop_(Gtk::Stock::STOP) + , button_quit_(Gtk::Stock::QUIT) + + /* Storage for GUI elements for later lookup */ + , call_buttons_() + , position_labels_() + , request_buttons_() + , elevator_doors_() +{ + int i, j, e, f, e_num, f_num, f_attach; + std::ostringstream str; + + /* Fill in all of the ElevatorDoors and CallButtons */ + for (f_attach=0, f=floors-1; f>=0; --f, ++f_attach) + { + std::cout << "at floor: " << f << std::endl; + + /* Create and attach the VBox */ + Gtk::VBox *box = new Gtk::VBox (); + table_.attach (*box, 0, 1, f_attach, f_attach+1); + + /* Only create UP CallButton if we are not on the top floor */ + if (f != floors-1) + { + CallButton *callbutton = new CallButton (f, UP); + callbutton->set_label ("Up"); + + // Connect to the on_call_button_toggled() signal + callbutton->signal_toggled().connect ( + sigc::bind ( + sigc::mem_fun (*this, &ElevatorGUI::on_call_button_toggled), + callbutton + ) + ); + + call_buttons_.push_back (callbutton); + box->pack_start (*callbutton); + } + + /* Only create the DOWN CallButton if we are not on the bottom floor */ + if (f != 0) + { + CallButton *callbutton = new CallButton (f, DOWN); + callbutton->set_label ("Down"); + + // Connect to the on_call_button_toggled() signal + callbutton->signal_toggled().connect ( + sigc::bind ( + sigc::mem_fun (*this, &ElevatorGUI::on_call_button_toggled), + callbutton + ) + ); + + call_buttons_.push_back (callbutton); + box->pack_end (*callbutton); + } + + for (e=0; eset_label (str.str()); + + // Connect the on_request_button_toggled() signal + button->signal_toggled().connect ( + sigc::bind ( + sigc::mem_fun (*this, &ElevatorGUI::on_request_button_toggled), + button + ) + ); + + // save the button + request_buttons_.push_back (button); + + // If floor is odd, attach in the left col + // Otherwise, attach in the right col + if (f % 2 == 0) + panel->attach (*button, 0, 1, f_attach, f_attach+1); + else + panel->attach (*button, 1, 2, f_attach, f_attach+1); + } + + // Attach the Panel + table_.attach (*panel, e+1, e+2, floors, floors+1); + } + + + + /* Fill in all of the PositionLabels */ + for (e=0; epack_start (button_playpause_); + box->pack_start (button_stop_); + box->pack_start (button_quit_); + + /* Attach the box to the bottom of the GUI */ + table_.attach (*box, 0, elevators+1, floors+2, floors+3); + + /* Add the table to the window */ + add (table_); + + /* Show everything, we're up and running! */ + show_all_children (); + show (); +} + +void ElevatorGUI::on_quit_button_clicked () +{ + Gtk::Main::quit (); +} + +void ElevatorGUI::on_playpause_button_clicked () +{ + std::string names[] = { "STOPPED", "RUNNING", "PAUSED" }; + std::cout << "Play/Pause pressed with status=" << names[simulation_status_] << std::endl; + + switch (simulation_status_) + { + case STOPPED: + simulation_status_ = RUNNING; + + // add and start timer + timer_ = Glib::signal_timeout().connect ( + sigc::mem_fun (*this, &ElevatorGUI::on_timer_tick), + timer_tick_ms_); + + break; + case RUNNING: + simulation_status_= PAUSED; + + // stop and remove timer + timer_.disconnect (); + + break; + case PAUSED: + simulation_status_ = RUNNING; + + // add and start timer + timer_ = Glib::signal_timeout().connect ( + sigc::mem_fun (*this, &ElevatorGUI::on_timer_tick), + timer_tick_ms_); + + break; + default: + std::cout << "Bad Simulation Status in Play/Pause" << std::endl; + break; + } +} + +void ElevatorGUI::on_stop_button_clicked () +{ + // FIXME: implement this + std::cout << "STOP Button Clicked" << std::endl; + + simulation_status_ = STOPPED; +} + +void ElevatorGUI::on_request_button_toggled (RequestButton *button) +{ + // Only send an elevator if we are toggled to on + if (button->get_active()) + { + std::cout << "Request elevator=" << button->getElevatorNumber() + << " to floor=" << button->getFloorNumber() << std::endl; + ec_.elevator_request (button->getElevatorNumber(), button->getFloorNumber()); + } +} + +void ElevatorGUI::on_call_button_toggled (CallButton *button) +{ + // Only send an elevator if we are toggled to on + if (button->get_active()) + { + std::cout << "Elevator Called on floor=" << button->getFloorNumber() + << " in direction=" << button->getDirection() << std::endl; + ec_.call_elevator_to (button->getFloorNumber(), button->getDirection()); + } +} + +void ElevatorGUI::gui_update_position_label (int elevator, float new_position) +{ + std::ostringstream str; + + // Generate the text + str << std::setiosflags (std::ios_base::showpoint | std::ios_base::fixed) + << std::setprecision(1) << new_position; + + // Find the correct label and set it + PositionLabelVector::iterator it; + + for (it=position_labels_.begin(); it!=position_labels_.end(); it++) + if ((*it)->getElevatorNumber() == elevator) + (*it)->set_text (str.str()); +} + +void ElevatorGUI::gui_unpress_call_button (int floor, Direction direction) +{ + CallButtonVector::iterator it; + + for (it=call_buttons_.begin(); it!=call_buttons_.end(); it++) + if ((*it)->getFloorNumber() == floor && (*it)->getDirection() == direction) + (*it)->set_active (false); +} + +void ElevatorGUI::gui_unpress_request_button (int elevator, int floor) +{ + RequestButtonVector::iterator it; + + for (it=request_buttons_.begin(); it!=request_buttons_.end(); it++) + if ((*it)->getElevatorNumber() == elevator && (*it)->getFloorNumber() == floor) + (*it)->set_active (false); +} + +void ElevatorGUI::gui_open_door (int elevator, int floor) +{ + ElevatorDoorVector::iterator it; + + for (it=elevator_doors_.begin(); it!=elevator_doors_.end(); it++) + if ((*it)->getElevatorNumber() == elevator && (*it)->getFloorNumber() == floor) + (*it)->open(); +} + +void ElevatorGUI::gui_close_door (int elevator, int floor) +{ + ElevatorDoorVector::iterator it; + + for (it=elevator_doors_.begin(); it!=elevator_doors_.end(); it++) + if ((*it)->getElevatorNumber() == elevator && (*it)->getFloorNumber() == floor) + (*it)->close (); +} + +bool ElevatorGUI::on_timer_tick () +{ + ec_.move_elevators (); + + // Keep going (do NOT disconnect yet) + return true; +} + +/* vim: set ts=4 sts=4 sw=4 noet tw=112: */ diff --git a/elevatorgui.hpp b/elevatorgui.hpp new file mode 100644 index 0000000..77f4d58 --- /dev/null +++ b/elevatorgui.hpp @@ -0,0 +1,77 @@ +#ifndef ELEVATORGUI_HPP +#define ELEVATORGUI_HPP + +#include +#include +#include +#include +#include + +#include "elevatorcontroller.hpp" + +#include "elevatordoor.hpp" +#include "callbutton.hpp" +#include "positionlabel.hpp" +#include "requestbutton.hpp" + + +typedef std::vector CallButtonVector; +typedef std::vector PositionLabelVector; +typedef std::vector RequestButtonVector; +typedef std::vector ElevatorDoorVector; + + +class ElevatorGUI : public Gtk::Window +{ + public: + ElevatorGUI (int floors, int elevators); + + /* Functions to be called from Elevator to change GUI status */ + void gui_update_position_label (int elevator, float new_position); + void gui_unpress_call_button (int floor, Direction direction); + void gui_unpress_request_button (int elevator, int floor); + void gui_open_door (int elevator, int floor); + void gui_close_door (int elevator, int floor); + + private: + /* Callbacks from button presses */ + void on_call_button_toggled (CallButton *button); + void on_request_button_toggled (RequestButton *button); + void on_playpause_button_clicked (); + void on_stop_button_clicked (); + void on_quit_button_clicked (); + + /* Timer Function */ + bool on_timer_tick (); + sigc::connection timer_; + static const int timer_tick_ms_ = 500; + + int number_of_floors_; + int number_of_elevators_; + + enum { STOPPED, RUNNING, PAUSED } simulation_status_; + + ElevatorController ec_; + + // holds custom CallButton which knows it's direction and floor# + CallButtonVector call_buttons_; + + // holds custom position label which knows it's elevator# + PositionLabelVector position_labels_; + + // holds custom RequestButton which knows it's elevator# and floor# + RequestButtonVector request_buttons_; + + // holds custom ElevatorDoor which knows it's elevator# and floor# + ElevatorDoorVector elevator_doors_; + + // Holds the Play / Pause button, Stop button, and Quit button + Gtk::Button button_playpause_, button_stop_, button_quit_; + + // Holds the Table which holds everything + Gtk::Table table_; +}; + +#endif /* ELEVATORGUI_HPP */ + +/* vim: set ts=4 sts=4 sw=4 noet tw=112: */ diff --git a/eopen2.png b/eopen2.png new file mode 100644 index 0000000000000000000000000000000000000000..4521d83ad15e43d28ee7aa418c2d1a17267544b2 GIT binary patch literal 702 zcmV;v0zv(WP)Px#1ZP1_K>z@;j|==^1poj5AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBUy2XskIMF-Xe9tAlY^1poZ0006hNklr(WcJ;2HYG>lh@wA z^;0)HJ#O~w*3GS|3K6D`T47=s)B-o?Ck7{%WC4y|A)ED ze*gIoYCh0G5OlcDFw9!Oz{D2l8Z$F9EiJ7{lP1;I*EdiPKuqiJ@8{&?jE;_;Iddit zzi76b$iZGixHA|=9W)w3c#_;`8X}Y*M?+{dgb0NIA^FiXG#WyLLV%F`Xc`&~AwnTQ zNPaX8jfN1R5FjK!nubP0h)@U+k{?Y&qaj2n1PIBGrlAoRLK7!WtgEX7Mm!Y(`6FoB z+S-#RPX_95q#gj8*3{Gl^d}b=7fC~Uvw&lahK7do=g;r%?(U%;0Gig@+dF5@9Byvz z$jC^d#u)XCtQRj{Y-?-F%F62M>S}FmZ9{F~NFmmw|N<0Nx?xaeJnbUH||907*qoM6N<$f?c^OcmMzZ literal 0 HcmV?d00001 diff --git a/positionlabel.cpp b/positionlabel.cpp new file mode 100644 index 0000000..bdbe24d --- /dev/null +++ b/positionlabel.cpp @@ -0,0 +1,15 @@ +#include "positionlabel.hpp" + +PositionLabel::PositionLabel (int elevator, const std::string text) + : Gtk::Label (text) + , elevator_(elevator) +{ + // Intentionally Left Empty +} + +int PositionLabel::getElevatorNumber () const +{ + return elevator_; +} + +/* vim: set ts=4 sts=4 sw=4 noet tw=112: */ diff --git a/positionlabel.hpp b/positionlabel.hpp new file mode 100644 index 0000000..bd90449 --- /dev/null +++ b/positionlabel.hpp @@ -0,0 +1,20 @@ +#ifndef POSITIONLABEL_HPP +#define POSITIONLABEL_HPP + +#include +#include + +class PositionLabel : public Gtk::Label +{ + public: + PositionLabel (int elevator, const std::string text="0.0"); + + int getElevatorNumber() const; + + private: + int elevator_; +}; + +#endif /* POSITIONLABEL_HPP */ + +/* vim: set ts=4 sts=4 sw=4 noet tw=112: */ diff --git a/requestbutton.cpp b/requestbutton.cpp new file mode 100644 index 0000000..95fae24 --- /dev/null +++ b/requestbutton.cpp @@ -0,0 +1,21 @@ +#include "requestbutton.hpp" + +RequestButton::RequestButton (int elevator, int floor, const std::string text) + : Gtk::ToggleButton (text) + , elevator_(elevator) + , floor_(floor) +{ + // Intentionally Left Empty +} + +int RequestButton::getElevatorNumber () const +{ + return elevator_; +} + +int RequestButton::getFloorNumber () const +{ + return floor_; +} + +/* vim: set ts=4 sts=4 sw=4 noet tw=112: */ diff --git a/requestbutton.hpp b/requestbutton.hpp new file mode 100644 index 0000000..8c14c31 --- /dev/null +++ b/requestbutton.hpp @@ -0,0 +1,22 @@ +#ifndef REQUESTBUTTON_HPP +#define REQUESTBUTTON_HPP + +#include +#include + +class RequestButton : public Gtk::ToggleButton +{ + public: + RequestButton (int elevator, int floor, const std::string text="0"); + + int getElevatorNumber () const; + int getFloorNumber() const; + + private: + int elevator_; + int floor_; +}; + +#endif /* REQUESTBUTTON_HPP */ + +/* vim: set ts=4 sts=4 sw=4 noet tw=112: */ diff --git a/test.cpp b/test.cpp index 6f85ea1..bcfe3b3 100644 --- a/test.cpp +++ b/test.cpp @@ -7,10 +7,27 @@ using namespace std; #include "position.hpp" #include "elevator.hpp" #include "elevatorcontroller.hpp" +#include "elevatorgui.hpp" + +#include int main (int argc, char *argv[]) { + const int floors = 7; + const int elevators = 3; + + // Start GTK + Gtk::Main app(argc, argv); + + ElevatorGUI eg(floors, elevators); + eg.show (); + + Gtk::Main::run (eg); + + + +#if TEST_ELEVATORCONTROLLER const int floors = 10; const int elevators = 2; @@ -30,6 +47,7 @@ int main (int argc, char *argv[]) for (int i=0; i<35; i++) ec.move_elevators (); +#endif #if TEST_ELEVATOR -- 2.34.1