- 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:
paolo 2006-09-14 22:31:37 +00:00
parent bb74bcbc48
commit bd6e52f811
2 changed files with 256 additions and 50 deletions

View File

@ -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*/)
{
}

View File

@ -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;
/**