- cairo_widget.cc - documentation completed, removed all warnings
- simulation_widget.hh - documentation completed git-svn-id: svn://svn.gna.org/svn/sgpemv2/trunk@1164 3ecf2c5c-341e-0410-92b4-d18e462d057c
This commit is contained in:
parent
bb74bcbc48
commit
bd6e52f811
|
@ -27,7 +27,6 @@
|
|||
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
|
||||
using namespace sgpem;
|
||||
|
@ -36,9 +35,10 @@ using namespace sgpem;
|
|||
CairoWidget::CairoWidget()
|
||||
: Glib::ObjectBase("sgpem_CairoWidget"),
|
||||
Gtk::Widget(),
|
||||
_draw_w(1), _draw_h(1), _buf(NULL),
|
||||
_draw_w(1), _draw_h(1),
|
||||
_client_w(0), _client_h(0), _pixmap_w(0), _pixmap_h(0),
|
||||
_need_redraw(true), _scaling_mode(scaling_none)
|
||||
_need_redraw(true), _scaling_mode(scaling_none),
|
||||
_buf(NULL)
|
||||
{
|
||||
set_flags(Gtk::NO_WINDOW);
|
||||
}
|
||||
|
@ -48,6 +48,9 @@ CairoWidget::~CairoWidget()
|
|||
{
|
||||
}
|
||||
|
||||
/*
|
||||
Scaling mode setter+getter method.
|
||||
*/
|
||||
CairoWidget::scaling_mode
|
||||
CairoWidget::set_scaling_mode(CairoWidget::scaling_mode scaling)
|
||||
{
|
||||
|
@ -56,16 +59,22 @@ CairoWidget::set_scaling_mode(CairoWidget::scaling_mode scaling)
|
|||
return old_scaling;
|
||||
}
|
||||
|
||||
/*
|
||||
Scaling mode getter method.
|
||||
*/
|
||||
CairoWidget::scaling_mode
|
||||
CairoWidget::get_scaling_mode() const
|
||||
{
|
||||
return _scaling_mode;
|
||||
}
|
||||
|
||||
/*
|
||||
Called by Gtk+ before creting the widget.
|
||||
Sets all values and attributes required.
|
||||
*/
|
||||
void
|
||||
CairoWidget::on_realize()
|
||||
{
|
||||
// std::cout << " on_realize" << std::endl;
|
||||
if (is_realized()) return;
|
||||
|
||||
Gtk::Widget::on_realize();
|
||||
|
@ -89,7 +98,6 @@ CairoWidget::on_realize()
|
|||
_client_w = alloc.get_width();
|
||||
_client_h = alloc.get_height();
|
||||
|
||||
// std::cout << " on_realize, alloc.get_width() : " << alloc.get_width() << ", alloc.get_height() : " << alloc.get_height() << std::endl;
|
||||
|
||||
static const gint attributes_mask = Gdk::WA_X | Gdk::WA_Y | Gdk::WA_WMCLASS
|
||||
| Gdk::WA_VISUAL | Gdk::WA_COLORMAP;
|
||||
|
@ -107,66 +115,85 @@ CairoWidget::on_realize()
|
|||
get_style()->set_background(window, Gtk::STATE_ACTIVE);
|
||||
}
|
||||
|
||||
/*
|
||||
This method is called when the widget is moved/resized.
|
||||
*/
|
||||
void
|
||||
CairoWidget::on_size_allocate(const Gtk::Allocation& allocation)
|
||||
{
|
||||
// std::cout << " on_size_allocate, allocation.get_width() : " << allocation.get_width() << ", allocation.get_height() : " << allocation.get_height() << std::endl;
|
||||
set_allocation(allocation);
|
||||
|
||||
if (is_realized())
|
||||
{
|
||||
get_window()->move_resize(allocation.get_x(), allocation.get_y(),
|
||||
allocation.get_width(), allocation.get_height());
|
||||
|
||||
// the widget's dimension are saved for futher use
|
||||
_client_w = allocation.get_width();
|
||||
_client_h = allocation.get_height();
|
||||
|
||||
// the widget must be redrawn
|
||||
_need_redraw = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
This method is called by Gtk to get the widget desired size.
|
||||
*/
|
||||
void
|
||||
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;
|
||||
|
||||
// gets the passed values
|
||||
_client_w = requisition->width;
|
||||
_client_h = requisition->height;
|
||||
|
||||
// ask the desired dimensions
|
||||
calc_widget_size(_client_w, _client_h);
|
||||
|
||||
// pass values back to Gtk
|
||||
requisition->width = _client_w;
|
||||
requisition->height = _client_h;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
This method is called by Gtk when need to redraw widget
|
||||
*/
|
||||
bool
|
||||
CairoWidget::on_expose_event(GdkEventExpose* event)
|
||||
{
|
||||
// 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();
|
||||
// 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;
|
||||
// save actual size
|
||||
size_t actual_w = get_width();
|
||||
size_t actual_h = get_height();
|
||||
|
||||
// the widget must be redrawn if
|
||||
// - there's an explicit request(_need_redraw)
|
||||
// - the size is changed
|
||||
if(_need_redraw || actual_w!=_client_w || actual_h!=_client_h)
|
||||
{
|
||||
// reset flag, set values with actual size
|
||||
_need_redraw = false;
|
||||
_client_w = actual_w;
|
||||
_client_h = actual_h;
|
||||
// lazy technique: allocate only if growing...
|
||||
|
||||
// The pixmap must be crated or no?
|
||||
// If the pixmap buffer size isn't enough
|
||||
// it must be allocated or reallocated.
|
||||
// Here is used a lazy technique:
|
||||
// allocate only if growing, keep if shrinking.
|
||||
// Taking a bigger pixmap saves operations when
|
||||
// many window resizing occours (i.e. mouse resizing).
|
||||
if(_client_w>_pixmap_w || _client_h>_pixmap_h)
|
||||
{
|
||||
// previdence in the code: allocate more than actually needed
|
||||
// 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;
|
||||
|
||||
// allocate the pixmap
|
||||
_buf = Gdk::Pixmap::create(get_window(), _pixmap_w, _pixmap_h);
|
||||
}
|
||||
|
||||
|
@ -175,30 +202,31 @@ CairoWidget::on_expose_event(GdkEventExpose* event)
|
|||
// I've seen this is how it's done in the very Gtk+ toolkit
|
||||
// for the GtkProgressBar widget.
|
||||
GtkStyle* gStyle = get_style()->gobj();
|
||||
// std::cout << " on_expose_event gtk_paint_box." << std::endl;
|
||||
gtk_paint_box(gStyle, _buf->gobj(),
|
||||
GTK_STATE_NORMAL, GTK_SHADOW_ETCHED_IN,
|
||||
NULL, (GtkWidget*)this->gobj(), "through",
|
||||
0, 0, _client_w, _client_h);
|
||||
|
||||
// here the cairo context is creted
|
||||
cairo_t* ctx = gdk_cairo_create(_buf->gobj());
|
||||
|
||||
// Determine the final drawing dimensions before to start drawing
|
||||
// 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);
|
||||
|
||||
// calculate and apply scale factors
|
||||
calc_scale_factors();
|
||||
|
||||
// do the drawing...
|
||||
cairo_scale(ctx, _scale_x, _scale_y);
|
||||
|
||||
// std::cout << " on_expose_event Dimensions, w : " << _draw_w << ", h : " << _draw_h << std::endl;
|
||||
// do the drawing...
|
||||
draw_widget(ctx);
|
||||
cairo_destroy(ctx);
|
||||
}
|
||||
|
||||
// calculated dinamically on update():
|
||||
// set_size_request(_draw_w, _draw_h);
|
||||
// bye bye context
|
||||
cairo_destroy(ctx);
|
||||
} // ~ if(_need_redraw || actual_w!=_client_w || actual_h!=_client_h)
|
||||
|
||||
// Now the in-memory picture is placed on screen
|
||||
|
||||
// Clip to redraw only the smallest possible area
|
||||
// Use double buffering or we're CPU-dead
|
||||
|
@ -212,61 +240,98 @@ CairoWidget::on_expose_event(GdkEventExpose* event)
|
|||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
Here calc the scale factors to apply drawing
|
||||
*/
|
||||
void
|
||||
CairoWidget::calc_scale_factors()
|
||||
{
|
||||
// scale factor is: desired_size/effective_size
|
||||
//
|
||||
// "desired_size" here is how big can fin in window
|
||||
// "effective_size" is how big the application produce
|
||||
if(_scaling_mode!=scaling_none && _draw_w!=0 && _draw_h!=0)
|
||||
{
|
||||
// there are two possible scale factors x and y
|
||||
_scale_x = (double)_client_w/(double)_draw_w;
|
||||
_scale_y = (double)_client_h/(double)_draw_h;
|
||||
|
||||
// will be chosen one, another, both or none
|
||||
// depending on the active mode
|
||||
switch(_scaling_mode)
|
||||
{
|
||||
case scaling_none: // not necessary!
|
||||
// doesn't scale
|
||||
_scale_x = _scale_y = 1.0;
|
||||
break;
|
||||
case scaling_to_w:
|
||||
// scale to fit in width
|
||||
// x and y take the same x value
|
||||
_scale_y = _scale_x;
|
||||
break;
|
||||
|
||||
case scaling_to_h:
|
||||
// scale to fit in height
|
||||
// x and y take the same y value
|
||||
_scale_x = _scale_y;
|
||||
break;
|
||||
|
||||
case scaling_min:
|
||||
// scale to fit always in window
|
||||
// x and y take the same minimum value
|
||||
if(_scale_x<=_scale_y)
|
||||
_scale_y = _scale_x;
|
||||
else
|
||||
_scale_x = _scale_y;
|
||||
break;
|
||||
|
||||
case scaling_max:
|
||||
// scale to fit never in window
|
||||
// x and y take the same mxiimum value
|
||||
if(_scale_x>=_scale_y)
|
||||
_scale_y = _scale_x;
|
||||
else
|
||||
_scale_x = _scale_y;
|
||||
break;
|
||||
|
||||
case scaling_all:
|
||||
// scale to fit stretching in window
|
||||
// x and y mantain the differnt calculated values
|
||||
//
|
||||
// nothing to do...
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// can't determine scaling factors:
|
||||
// take the easy way
|
||||
_scale_x = _scale_y = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Utility method: force to redraw widget
|
||||
*/
|
||||
void
|
||||
CairoWidget::redraw()
|
||||
{
|
||||
// Force redraw
|
||||
_need_redraw = true;
|
||||
|
||||
// invalidate all widget's surface
|
||||
queue_draw();
|
||||
}
|
||||
|
||||
/*
|
||||
Utility method: force to resize and redraw widget
|
||||
*/
|
||||
void
|
||||
CairoWidget::resize_redraw()
|
||||
{
|
||||
// Force redraw
|
||||
_need_redraw = true;
|
||||
|
||||
// std::cout << " resize_redraw BEGIN width: " << get_width() << ", height: " << get_height() << std::endl;
|
||||
if(_buf)
|
||||
{
|
||||
cairo_t* ctx = gdk_cairo_create(_buf->gobj());
|
||||
|
@ -281,23 +346,29 @@ CairoWidget::resize_redraw()
|
|||
|
||||
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;
|
||||
// invalidate all widget's surface
|
||||
queue_draw();
|
||||
}
|
||||
|
||||
/*
|
||||
Dummy method.
|
||||
Derived classes can reimplement it or not as desired.
|
||||
*/
|
||||
void
|
||||
CairoWidget::calc_drawing_size(cairo_t* ctx, size_t& width, size_t& height)
|
||||
CairoWidget::calc_drawing_size(cairo_t* /* ctx */, size_t& /* width */, size_t& /*height*/)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Dummy method.
|
||||
Derived classes can reimplement it or not as desired.
|
||||
*/
|
||||
void
|
||||
CairoWidget::calc_widget_size(size_t& width, size_t& height)
|
||||
CairoWidget::calc_widget_size(size_t& /*width*/, size_t& /*height*/)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -30,60 +30,184 @@
|
|||
|
||||
namespace sgpem
|
||||
{
|
||||
class SimulationWidget : public SimulationObserver, public HistoryObserver, public CairoWidget
|
||||
/**
|
||||
* \brief Implements a cairo widget to draw the simulation
|
||||
* processes ststus graphical rapresentation.
|
||||
*
|
||||
* It shows the simulation processes (and threads if flag is enabled)
|
||||
* names on the left and a bar for each of these on the right.
|
||||
* The bar begins at the time the process bring to life and ends
|
||||
* when it die.
|
||||
*
|
||||
* The bar is composed of small rectangles of different colors
|
||||
* depending on the process' status:
|
||||
* - green = running
|
||||
* - yellow = ready
|
||||
* - red = blocked
|
||||
* This is the Fantasy Kingdom, do you know? ;)
|
||||
*
|
||||
* At the bottom of the graph there is a time line ruler.
|
||||
*
|
||||
* This class implemets a SimulationObserver and HistoryObserver
|
||||
* to have an update signal (and related update) every simulation step.
|
||||
*
|
||||
* \deprecated The class should implement only HistoryObserver
|
||||
*
|
||||
* \see SimulationObserver
|
||||
* \see HistoryObserver
|
||||
*/
|
||||
class SimulationWidget
|
||||
: public SimulationObserver, public HistoryObserver, public CairoWidget
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* \brief default and unique constructor.
|
||||
*
|
||||
* Saves the passed argument in data member _simulation.
|
||||
*/
|
||||
SimulationWidget(Simulation& simulation);
|
||||
|
||||
/**
|
||||
* Destructor!
|
||||
*/
|
||||
virtual ~SimulationWidget();
|
||||
|
||||
/**
|
||||
* \brief SimulationObserver's update method redefinition.
|
||||
*
|
||||
* Actually is a dummy method.
|
||||
*/
|
||||
virtual void update(const Simulation& changed_simulation);
|
||||
|
||||
/**
|
||||
* \brief HistoryObserver's update method redefinition.
|
||||
*
|
||||
* Updates the widget to reflects history current state.
|
||||
*/
|
||||
virtual void update(const History& changed_history);
|
||||
|
||||
/**
|
||||
* \brief Gets the _show_threads flag current status.
|
||||
*/
|
||||
bool get_show_threads();
|
||||
|
||||
/**
|
||||
* \brief Sets gets the _show_threads flag status.
|
||||
*
|
||||
* If _show_threads is enabled both processes and threads
|
||||
* will be drawn on widget.
|
||||
* If _show_threads is disabled only processes
|
||||
* will be shown.
|
||||
*/
|
||||
bool set_show_threads(bool show);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* \brief Catches the mouse click to show a "scaling options"
|
||||
* popup menu.
|
||||
*/
|
||||
virtual bool on_button_press_event(GdkEventButton* event);
|
||||
// void change_scaling_mode();
|
||||
|
||||
/**
|
||||
* \brief Execute the widget painting when needed.
|
||||
*
|
||||
* \see CairoWidget() for more.
|
||||
*/
|
||||
void draw_widget(cairo_t* ctx);
|
||||
|
||||
/**
|
||||
* \brief calculated the needed drawing surface dimensions.
|
||||
*/
|
||||
virtual void calc_drawing_size(cairo_t* ctx, size_t& width, size_t& height);
|
||||
|
||||
void count_elements();
|
||||
void draw_names(cairo_t* ctx);
|
||||
void draw_grid(cairo_t* ctx);
|
||||
void draw_bars(cairo_t* ctx);
|
||||
void draw_instant_rect(cairo_t* ctx, double x, double y,
|
||||
double w, double h, sgpem::Schedulable::state state);
|
||||
void make_gradients();
|
||||
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* \brief Counts the processes number to have the final picture size.
|
||||
*/
|
||||
void count_elements();
|
||||
|
||||
/**
|
||||
* \brief Used internally by draw_widget to show processes/threads name.
|
||||
*/
|
||||
void draw_names(cairo_t* ctx);
|
||||
|
||||
/**
|
||||
* \brief Used internally by draw_widget to show the bars container grid.
|
||||
*/
|
||||
void draw_grid(cairo_t* ctx);
|
||||
|
||||
/**
|
||||
* \brief Used internally by draw_widget to show processes/threads bars.
|
||||
*/
|
||||
void draw_bars(cairo_t* ctx);
|
||||
|
||||
/**
|
||||
* \brief Used internally by draw_widget to build the bars.
|
||||
*/
|
||||
void draw_instant_rect(cairo_t* ctx, double x, double y,
|
||||
double w, double h, sgpem::Schedulable::state state);
|
||||
|
||||
/**
|
||||
* \brief Build the gradients used to picture the bars.
|
||||
*
|
||||
* Gradinets are filling colors soft degrading.
|
||||
* Please refer to cairo documentetion for more.
|
||||
*/
|
||||
void make_gradients();
|
||||
|
||||
/**
|
||||
* \brief "No scaling" menu command responding mathod.
|
||||
*/
|
||||
void _on_no_scaling();
|
||||
|
||||
/**
|
||||
* \brief "Fit scaling" menu command responding mathod.
|
||||
*/
|
||||
void _on_fit_scaling();
|
||||
|
||||
/**
|
||||
* \brief "Stetch scaling" menu command responding mathod.
|
||||
*/
|
||||
void _on_stretch_scaling();
|
||||
|
||||
|
||||
/**
|
||||
* \brief Pointer to the observed simulation.
|
||||
*/
|
||||
Simulation* _simulation;
|
||||
|
||||
/**
|
||||
* \brief Flag to enable/disable threads visualization.
|
||||
*/
|
||||
bool _show_threads;
|
||||
|
||||
/**
|
||||
drawing x unit
|
||||
* \brief Drawing x unit.
|
||||
*
|
||||
* The drawing is constructed upon an arbitrary "squared" surface.
|
||||
* All widgets drawing measure are defined as upon x and y units.
|
||||
* To avoid alignement problems the drawing units are evaluated
|
||||
* on text size. The widtx/height of the text "999" are used as unit.
|
||||
*/
|
||||
double _x_unit;
|
||||
|
||||
/**
|
||||
drawing y unit
|
||||
* \brief Drawing y unit.
|
||||
*
|
||||
* \see _x_unit
|
||||
*/
|
||||
double _y_unit;
|
||||
|
||||
/**
|
||||
actual number of processes
|
||||
* \brief Actual number of processes, needed by drawing rountines.
|
||||
*/
|
||||
int _n_proc;
|
||||
|
||||
/**
|
||||
actual number of threads
|
||||
* \brief Actual number of threads, needed by drawing rountines.
|
||||
*/
|
||||
int _n_thr;
|
||||
|
||||
|
@ -123,8 +247,19 @@ namespace sgpem
|
|||
*/
|
||||
double _yu_thread_bar_height;
|
||||
|
||||
/**
|
||||
* \brief Gradient used to draw ready processes/threads.
|
||||
*/
|
||||
cairo_pattern_t* _ready_process_gradient;
|
||||
|
||||
/**
|
||||
* \brief Gradient used to draw running processes/threads.
|
||||
*/
|
||||
cairo_pattern_t* _running_process_gradient;
|
||||
|
||||
/**
|
||||
* \brief Gradient used to draw blocked processes/threads.
|
||||
*/
|
||||
cairo_pattern_t* _blocked_process_gradient;
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue