Port the code from Cairo to Cairo--.

See the TODO files for bugs and things that require attention.
The nasty bug that prevents visualization has been around for a while now, since Gtk+ reached 2.12, I think. Must be fixed.


git-svn-id: svn://svn.gna.org/svn/sgpemv2/trunk@1349 3ecf2c5c-341e-0410-92b4-d18e462d057c
This commit is contained in:
tchernobog 2009-12-30 23:36:01 +00:00
parent 1220e1be16
commit bce427d022
12 changed files with 419 additions and 421 deletions

View File

@ -352,7 +352,7 @@ sgpemv2_CPPFLAGS = \
-DLOCALEDIR="\"$(localedir)\"" \
-DSHAREDIR="\"$(sharedir)\"" \
-DUIDIR="\"$(uidir)\"" \
$(CAIRO_CFLAGS) \
$(CAIROMM_CFLAGS) \
$(GTKMM_CFLAGS) \
$(LIBGLADEMM_CFLAGS) \
$(GTHREAD_CFLAGS)
@ -362,7 +362,7 @@ sgpemv2_LDFLAGS = \
-Wl,-rpath -Wl,"$(pkglibdir)"
sgpemv2_LDADD = \
src/backend/libbackend.la \
$(CAIRO_LIBS) \
$(CAIROMM_LIBS) \
$(GTKMM_LIBS) \
$(GTHREAD_LIBS)
@ -530,11 +530,11 @@ src_testsuite_test_key_file_SOURCES = \
src_testsuite_test_cairo_widget_CPPFLAGS = \
-I@top_srcdir@/src \
-I@top_srcdir@/src/backend \
$(CAIRO_CFLAGS) \
$(CAIROMM_CFLAGS) \
$(GTKMM_CFLAGS) \
$(GLIBMM_CFLAGS)
src_testsuite_test_cairo_widget_LDFLAGS = \
$(CAIRO_LIBS) \
$(CAIROMM_LIBS) \
$(GTKMM_LIBS) \
$(GLIBMM_LIBS)
src_testsuite_test_cairo_widget_SOURCES = \
@ -545,14 +545,14 @@ src_testsuite_test_cairo_widget_SOURCES = \
src_testsuite_test_simulation_widget_CPPFLAGS = \
-I@top_srcdir@/src \
-I@top_srcdir@/src/backend \
$(CAIRO_CFLAGS) \
$(CAIROMM_CFLAGS) \
$(GTKMM_CFLAGS) \
$(GLIBMM_CFLAGS) \
$(GTHREAD_CFLAGS)
src_testsuite_test_simulation_widget_LDFLAGS = \
src/backend/libbackend.la \
-Wl,-rpath -Wl,"$(pkglibdir)" \
$(CAIRO_LIBS) \
$(CAIROMM_LIBS) \
$(GTKMM_LIBS) \
$(GLIBMM_LIBS) \
$(GTHREAD_LIBS)
@ -565,14 +565,14 @@ src_testsuite_test_simulation_widget_SOURCES = \
src_testsuite_test_holt_widget_CPPFLAGS = \
-I@top_srcdir@/src \
-I@top_srcdir@/src/backend \
$(CAIRO_CFLAGS) \
$(CAIROMM_CFLAGS) \
$(GTKMM_CFLAGS) \
$(GLIBMM_CFLAGS) \
$(GTHREAD_CFLAGS)
src_testsuite_test_holt_widget_LDFLAGS = \
src/backend/libbackend.la \
-Wl,-rpath -Wl,"$(pkglibdir)" \
$(CAIRO_LIBS) \
$(CAIROMM_LIBS) \
$(GTKMM_LIBS) \
$(GLIBMM_LIBS) \
$(GTHREAD_LIBS)

4
TODO Normal file
View File

@ -0,0 +1,4 @@
- fix nasty bug that prevents all cairowidgets from showing up
- Check for simulationwidget deprecat. meth.
- check headers for #includes with <> instead of ""
- Report bug for presence of PKG, VERSION, etc. macros inside cairomm-config.h

View File

@ -57,9 +57,10 @@ AM_GNU_GETTEXT([external])
AM_GNU_GETTEXT_VERSION([0.17])
dnl various requisites
SIGCPP_VERSION=2.0.10
GTKMM_VERSION=2.12.1
CAIRO_VERSION=1.0.0
SIGCPP_VERSION=2.0.18
GLIBMM_VERSION=2.22.0
GTKMM_VERSION=2.18.0
CAIROMM_VERSION=1.8.0
dnl c++ compiler and flags
AC_PROG_CXX
@ -109,9 +110,9 @@ if test -z "$PKG_CONFIG"; then
AC_MSG_ERROR([You may need to update your pkg-config installation])
fi
PKG_CHECK_MODULES([CAIRO],
[cairo >= $CAIRO_VERSION],
:, AC_MSG_ERROR([$CAIRO_PKG_ERRORS]))
PKG_CHECK_MODULES([CAIROMM],
[cairomm-1.0 >= $CAIROMM_VERSION],
:, AC_MSG_ERROR([$CAIROMM_PKG_ERRORS]))
PKG_CHECK_MODULES([GTHREAD],
[gthread-2.0 >= $GTKMM_VERSION],
:, AC_MSG_ERROR([$GTHREAD_PKG_ERRORS]))
@ -119,7 +120,7 @@ PKG_CHECK_MODULES([SIGCPP],
[sigc++-2.0 >= $SIGCPP_VERSION],
:, AC_MSG_ERROR([$SIGCPP_PKG_ERRORS]))
PKG_CHECK_MODULES([GLIBMM],
[glibmm-2.4 >= $GTKMM_VERSION],
[glibmm-2.4 >= $GLIBMM_VERSION],
:, AC_MSG_ERROR([$GLIBMM_PKG_ERRORS]))
PKG_CHECK_MODULES([GTKMM],
[gtkmm-2.4 >= $GTKMM_VERSION],

View File

@ -29,7 +29,7 @@
using namespace sgpem;
CairoElements::CairoElements(cairo_t* const ctx)
CairoElements::CairoElements(const Cairo::RefPtr<Cairo::Context>& ctx)
: _ctx(ctx)
{
}
@ -38,7 +38,8 @@ CairoElements::CairoElements(cairo_t* const ctx)
void
CairoElements::draw_3dsphere(const Point& center, float radius, const Color& cl)
{
cairo_t*& cr = _ctx;
using namespace Cairo;
const float& x = center.x;
const float& y = center.y;
const float& r = cl.r;
@ -46,52 +47,52 @@ CairoElements::draw_3dsphere(const Point& center, float radius, const Color& cl)
const float& b = cl.b;
// Draw initial sphere perimeter
cairo_save(cr);
cairo_new_path(cr);
cairo_arc(cr, x, y, radius, 0, 2*M_PI);
cairo_pattern_t* grad = cairo_pattern_create_radial(x, y, radius, x, y, radius - .15);
cairo_pattern_add_color_stop_rgba(grad, 0, r - .2, g - .2, b - .2, 1);
cairo_pattern_add_color_stop_rgba(grad, 1, r, g, b, 1);
cairo_set_source(cr, grad);
cairo_fill_preserve(cr);
cairo_pattern_destroy(grad);
cairo_set_source_rgba(cr, 0, 0, 0, 1);
cairo_set_line_width(cr, radius * .01);
cairo_stroke(cr);
cairo_restore(cr);
_ctx->save();
_ctx->begin_new_path();
_ctx->arc(x, y, radius, 0, 2*M_PI);
RefPtr<Gradient> grad = RadialGradient::create(x, y, radius, x, y, radius - .15);
grad->add_color_stop_rgba(0, r - .2, g - .2, b - .2, 1);
grad->add_color_stop_rgba(1, r, g, b, 1);
_ctx->set_source(grad);
_ctx->fill_preserve();
_ctx->set_source_rgba(0, 0, 0, 1);
_ctx->set_line_width(radius * .01);
_ctx->stroke();
_ctx->restore();
// Internal gradient
cairo_save(cr);
grad = cairo_pattern_create_linear(x, y, x, y + radius);
cairo_pattern_add_color_stop_rgba(grad, 1, r - .4, g - .4, b - .4, 1);
cairo_pattern_add_color_stop_rgba(grad, 0, r, g, b, .7);
cairo_set_source(cr, grad);
cairo_translate(cr, x*.2, (y + radius*8 / 9) * 1 / 3);
cairo_scale(cr, .8, 2. / 3);
cairo_arc(cr, x, y, radius, 0, 2*M_PI);
cairo_fill(cr);
cairo_pattern_destroy(grad);
cairo_restore(cr);
_ctx->save();
grad = LinearGradient::create(x, y, x, y + radius);
grad->add_color_stop_rgba(1, r - .4, g - .4, b - .4, 1);
grad->add_color_stop_rgba(0, r, g, b, .7);
_ctx->set_source(grad);
_ctx->translate(x*.2, (y + radius*8 / 9) * 1 / 3);
_ctx->scale(.8, 2. / 3);
_ctx->arc(x, y, radius, 0, 2*M_PI);
_ctx->fill();
_ctx->restore();
// Internal glow
cairo_save(cr);
grad = cairo_pattern_create_linear(x, y - radius, x, y);
cairo_pattern_add_color_stop_rgba(grad, 0, 1, 1, 1, .9);
cairo_pattern_add_color_stop_rgba(grad, 1, 1, 1, 1, .2);
cairo_set_source(cr, grad);
cairo_translate(cr, x * .2, (y - radius*8 / 9) * 1 / 3);
cairo_scale(cr, .8, 2. / 3);
cairo_arc(cr, x, y, radius, 0, 2*M_PI);
cairo_fill(cr);
cairo_pattern_destroy(grad);
cairo_restore(cr);
_ctx->save();
grad = LinearGradient::create(x, y - radius, x, y);
grad->add_color_stop_rgba(0, 1, 1, 1, .9);
grad->add_color_stop_rgba(1, 1, 1, 1, .2);
_ctx->set_source(grad);
_ctx->translate(x * .2, (y - radius*8 / 9) * 1 / 3);
_ctx->scale(.8, 2. / 3);
_ctx->arc(x, y, radius, 0, 2*M_PI);
_ctx->fill();
_ctx->restore();
}
void
CairoElements::draw_3dcube(const Rectangle& area, const Color& cl,
const float x_percent, const float y_percent)
{
cairo_t*& cr = _ctx;
using namespace Cairo;
const float& x0 = area.x0;
const float& y0 = area.y0;
const float& w = area.w;
@ -100,54 +101,53 @@ CairoElements::draw_3dcube(const Rectangle& area, const Color& cl,
const float& g = cl.b;
const float& b = cl.b;
cairo_save(cr);
cairo_set_line_join(cr, CAIRO_LINE_JOIN_ROUND);
_ctx->save();
_ctx->set_line_join(LINE_JOIN_ROUND);
// Front side of the cube:
cairo_rectangle(cr,
x0, y0 + (1 - y_percent) * h,
_ctx->rectangle(x0, y0 + (1 - y_percent) * h,
w * x_percent, h * y_percent);
cairo_set_source_rgb(cr, r, g, b);
cairo_fill_preserve(cr);
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_stroke(cr);
_ctx->set_source_rgb(r, g, b);
_ctx->fill_preserve();
_ctx->set_source_rgb(0, 0, 0);
_ctx->stroke();
// ``Upper'' visible cube side:
cairo_new_path(cr);
cairo_move_to(cr, x0, y0 + (1 - y_percent) * h);
cairo_line_to(cr, x0 + (1 - x_percent) * w, y0);
cairo_line_to(cr, x0 + w, y0);
cairo_line_to(cr, x0 + w * x_percent, y0 + (1 - y_percent) * h);
cairo_close_path(cr);
cairo_set_source_rgb(cr, r - 0.2, g - 0.2, b - 0.2);
cairo_fill_preserve(cr);
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_stroke(cr);
_ctx->begin_new_path();
_ctx->move_to(x0, y0 + (1 - y_percent) * h);
_ctx->line_to(x0 + (1 - x_percent) * w, y0);
_ctx->line_to(x0 + w, y0);
_ctx->line_to(x0 + w * x_percent, y0 + (1 - y_percent) * h);
_ctx->close_path();
_ctx->set_source_rgb(r - 0.2, g - 0.2, b - 0.2);
_ctx->fill_preserve();
_ctx->set_source_rgb(0, 0, 0);
_ctx->stroke();
// ``Right'' visible cube side:
cairo_new_path(cr);
cairo_move_to(cr, x0 + w * x_percent, y0 + (1 - y_percent) * h);
cairo_line_to(cr, x0 + w, y0);
cairo_line_to(cr, x0 + w, y0 + y_percent * h);
cairo_line_to(cr, x0 + w * x_percent, y0 + h);
cairo_close_path(cr);
_ctx->begin_new_path();
_ctx->move_to(x0 + w * x_percent, y0 + (1 - y_percent) * h);
_ctx->line_to(x0 + w, y0);
_ctx->line_to(x0 + w, y0 + y_percent * h);
_ctx->line_to(x0 + w * x_percent, y0 + h);
_ctx->close_path();
cairo_set_source_rgb(cr, r - 0.4, g - 0.4, b - 0.4);
cairo_fill_preserve(cr);
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_stroke(cr);
_ctx->set_source_rgb(r - 0.4, g - 0.4, b - 0.4);
_ctx->fill_preserve();
_ctx->set_source_rgb(0, 0, 0);
_ctx->stroke();
cairo_restore(cr);
_ctx->restore();
}
void
CairoElements::draw_container(const Rectangle& area)
{
cairo_t*& cr = _ctx;
using namespace Cairo;
const float& x0 = area.x0;
const float& y0 = area.y0;
const float& w = area.w;
@ -155,67 +155,68 @@ CairoElements::draw_container(const Rectangle& area)
const double corner_radius = 0.05;
cairo_save(cr);
cairo_new_path(cr);
cairo_move_to(cr, x0 + corner_radius, y0);
_ctx->save();
_ctx->begin_new_path();
_ctx->move_to(x0 + corner_radius, y0);
// NW -> NE
cairo_line_to(cr, x0 + w - corner_radius, y0);
cairo_curve_to(cr, x0 + w, y0, x0 + w, y0, x0 + w, y0 + corner_radius);
_ctx->line_to(x0 + w - corner_radius, y0);
_ctx->curve_to(x0 + w, y0, x0 + w, y0, x0 + w, y0 + corner_radius);
// NE -> SE
cairo_line_to(cr, x0 + w, y0 + h - corner_radius);
cairo_curve_to(cr, x0 + w, y0 + h, x0 + w, y0 + h, x0 + w - corner_radius, y0 + h);
_ctx->line_to(x0 + w, y0 + h - corner_radius);
_ctx->curve_to(x0 + w, y0 + h, x0 + w, y0 + h, x0 + w - corner_radius, y0 + h);
// SE -> SW
cairo_line_to(cr, x0 + corner_radius, y0 + h);
cairo_curve_to(cr, x0, y0 + h, x0, y0 + h, x0, y0 + h - corner_radius);
_ctx->line_to(x0 + corner_radius, y0 + h);
_ctx->curve_to(x0, y0 + h, x0, y0 + h, x0, y0 + h - corner_radius);
// SW -> NW
cairo_line_to(cr, x0, y0 + corner_radius);
cairo_curve_to(cr, x0, y0, x0, y0, x0 + corner_radius, y0);
cairo_close_path(cr);
_ctx->line_to(x0, y0 + corner_radius);
_ctx->curve_to(x0, y0, x0, y0, x0 + corner_radius, y0);
_ctx->close_path();
cairo_set_source_rgb(cr, 1, 1, 0.9);
cairo_fill_preserve(cr);
_ctx->set_source_rgb(1, 1, 0.9);
_ctx->fill_preserve();
cairo_set_line_width(cr, .005);
cairo_set_source_rgb(cr, 0, 0, 0);
_ctx->set_line_width(.005);
_ctx->set_source_rgb(0, 0, 0);
cairo_stroke(cr);
cairo_restore(cr);
_ctx->stroke();
_ctx->restore();
}
void
CairoElements::draw_expandable(const Rectangle& area, bool expanded)
{
cairo_t*& cr = _ctx;
using namespace Cairo;
const float& x0 = area.x0;
const float& y0 = area.y0;
const float& w = area.w;
const float& h = area.h;
cairo_save(cr);
_ctx->save();
cairo_set_line_width(cr, .005);
cairo_set_source_rgb(cr, 1, 1, 1);
_ctx->set_line_width(.005);
_ctx->set_source_rgb(1, 1, 1);
cairo_new_path(cr);
cairo_rectangle(cr, x0, y0, w, h);
cairo_set_source_rgb(cr, 1, 1, 1);
cairo_fill_preserve(cr);
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_stroke(cr);
_ctx->begin_new_path();
_ctx->rectangle(x0, y0, w, h);
_ctx->set_source_rgb(1, 1, 1);
_ctx->fill_preserve();
_ctx->set_source_rgb(0, 0, 0);
_ctx->stroke();
cairo_move_to(cr, x0 + w / 10, y0 + h / 2);
cairo_line_to(cr, x0 + w*9 / 10, y0 + h / 2);
cairo_stroke(cr);
_ctx->move_to(x0 + w / 10, y0 + h / 2);
_ctx->line_to(x0 + w*9 / 10, y0 + h / 2);
_ctx->stroke();
if (!expanded)
if (!expanded) // The "-" becomes a "+"
{
cairo_move_to(cr, x0 + w / 2, y0 + h / 10);
cairo_line_to(cr, x0 + w / 2, y0 + h*9 / 10);
cairo_stroke(cr);
_ctx->move_to(x0 + w / 2, y0 + h / 10);
_ctx->line_to(x0 + w / 2, y0 + h*9 / 10);
_ctx->stroke();
}
cairo_restore(cr);
_ctx->restore();
}

View File

@ -21,11 +21,7 @@
#ifndef CAIRO_ELEMENTS_HH
#define CAIRO_ELEMENTS_HH 1
#include <sgpemv2/thread.hh>
#include <sgpemv2/process.hh>
#include <cairo.h>
#include <cairomm/context.h>
namespace sgpem
{
@ -61,7 +57,7 @@ namespace sgpem
class CairoElements
{
public:
CairoElements(cairo_t* const ctx);
CairoElements(const Cairo::RefPtr<Cairo::Context>& ctx);
void draw_3dsphere(const Point& center, float radius, const Color& cl);
void draw_3dcube(const Rectangle& area, const Color& cl, const float x_percent, const float y_percent);
@ -69,7 +65,7 @@ namespace sgpem
void draw_expandable(const Rectangle& area, bool expanded = false);
private:
cairo_t* _ctx;
Cairo::RefPtr<Cairo::Context> _ctx;
};
} //~ namespace sgpem

View File

@ -75,11 +75,11 @@ CairoWidget::get_scaling_mode() const
void
CairoWidget::on_realize()
{
if (is_realized()) return;
Gtk::Widget::on_realize();
ensure_style();
if (!_ref_gdk_window) return;
GdkWindowAttr attributes;
memset(&attributes, 0, sizeof(attributes));
@ -90,30 +90,29 @@ CairoWidget::on_realize()
attributes.width = alloc.get_width();
attributes.height = alloc.get_height();
attributes.wclass = GDK_INPUT_OUTPUT;
attributes.event_mask = get_events() | GDK_EXPOSURE_MASK | GDK_ALL_EVENTS_MASK;
attributes.event_mask = get_events() | GDK_EXPOSURE_MASK;
attributes.window_type = GDK_WINDOW_CHILD;
attributes.visual = get_visual()->gobj();
attributes.colormap = get_colormap()->gobj();
_client_w = alloc.get_width();
_client_h = alloc.get_height();
static const gint attributes_mask = Gdk::WA_X | Gdk::WA_Y | Gdk::WA_WMCLASS
| Gdk::WA_VISUAL | Gdk::WA_COLORMAP;
static const gint attributes_mask = Gdk::WA_X | Gdk::WA_Y;
Glib::RefPtr<Gdk::Window> window = Gdk::Window::create(get_parent_window(),
&attributes,
attributes_mask);
_ref_gdk_window = Gdk::Window::create(get_window(),
&attributes,
attributes_mask);
unset_flags(Gtk::NO_WINDOW);
set_window(window);
window->set_user_data(gobj());
set_window(_ref_gdk_window);
_ref_gdk_window->set_user_data(gobj());
}
Glib::RefPtr<Gtk::Style> style = get_style ();
style = style->attach (window);
style->set_background(window, Gtk::STATE_ACTIVE);
void
CairoWidget::on_unrealize()
{
_ref_gdk_window.clear();
Gtk::Widget::on_unrealize();
}
/*
@ -124,19 +123,17 @@ CairoWidget::on_size_allocate(const Gtk::Allocation& allocation)
{
set_allocation(allocation);
if (is_realized())
{
get_window()->move_resize(allocation.get_x(), allocation.get_y(),
allocation.get_width(), allocation.get_height());
if (!_ref_gdk_window) return;
// the widget's dimension are saved for futher use
_client_w = allocation.get_width();
_client_h = allocation.get_height();
get_window()->move_resize(allocation.get_x(), allocation.get_y(),
allocation.get_width(), allocation.get_height());
// the widget must be redrawn
_need_redraw = true;
}
// 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;
}
/*
@ -163,6 +160,8 @@ CairoWidget::on_size_request(Gtk::Requisition* requisition)
bool
CairoWidget::on_expose_event(GdkEventExpose* event)
{
if (!_ref_gdk_window) return true;
if (event == NULL || event->count > 0)
return false;
@ -173,14 +172,14 @@ CairoWidget::on_expose_event(GdkEventExpose* event)
// 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)
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;
// The pixmap must be crated or no?
// The pixmap must be crated or not?
// If the pixmap buffer size isn't enough
// it must be allocated or reallocated.
// Here is used a lazy technique:
@ -195,7 +194,7 @@ CairoWidget::on_expose_event(GdkEventExpose* event)
_pixmap_h = (size_t) (_client_h*1.2);
// allocate the pixmap
_buf = Gdk::Pixmap::create(get_window(), _pixmap_w, _pixmap_h);
_buf = Gdk::Pixmap::create(_ref_gdk_window, _pixmap_w, _pixmap_h);
}
@ -208,8 +207,8 @@ CairoWidget::on_expose_event(GdkEventExpose* event)
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());
// here the cairo context is created
Cairo::RefPtr<Cairo::Context> ctx = _buf->create_cairo_context();
// Determine the final drawing dimensions
// before to start drawing
@ -218,13 +217,11 @@ CairoWidget::on_expose_event(GdkEventExpose* event)
// calculate and apply scale factors
calc_scale_factors();
cairo_scale(ctx, _scale_x, _scale_y);
ctx->scale(_scale_x, _scale_y);
// do the drawing...
draw_widget(ctx);
// 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
@ -233,7 +230,7 @@ CairoWidget::on_expose_event(GdkEventExpose* event)
// Use double buffering or we're CPU-dead
// Copy from the buffer to the screen
if (_buf)
get_window()->draw_drawable(get_style()->get_black_gc(), _buf,
_ref_gdk_window->draw_drawable(get_style()->get_black_gc(), _buf,
event->area.x, event->area.y,
event->area.x, event->area.y,
event->area.width, event->area.height);
@ -251,7 +248,7 @@ CairoWidget::calc_scale_factors()
//
// "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)
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;
@ -265,6 +262,7 @@ CairoWidget::calc_scale_factors()
// 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
@ -280,7 +278,7 @@ CairoWidget::calc_scale_factors()
case scaling_min:
// scale to fit always in window
// x and y take the same minimum value
if(_scale_x<=_scale_y)
if(_scale_x <= _scale_y)
_scale_y = _scale_x;
else
_scale_x = _scale_y;
@ -289,7 +287,7 @@ CairoWidget::calc_scale_factors()
case scaling_max:
// scale to fit never in window
// x and y take the same mxiimum value
if(_scale_x>=_scale_y)
if(_scale_x >= _scale_y)
_scale_y = _scale_x;
else
_scale_x = _scale_y;
@ -335,14 +333,14 @@ CairoWidget::resize_redraw()
if(_buf)
{
cairo_t* ctx = gdk_cairo_create(_buf->gobj());
Cairo::RefPtr<Cairo::Context> ctx = _buf->create_cairo_context();
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);
cairo_destroy(ctx);
ctx.clear();
calc_scale_factors();
@ -367,7 +365,7 @@ CairoWidget::resize_redraw()
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::RefPtr<Cairo::Context>& /* ctx */, size_t& /* width */, size_t& /*height*/)
{
}

View File

@ -21,8 +21,7 @@
#ifndef CAIRO_WIDGET_HH
#define CAIRO_WIDGET_HH 1
#include <cairo.h>
#include <gtkmm/drawingarea.h>
#include <cairomm/context.h>
#include <gtkmm/widget.h>
#include <gdkmm/pixmap.h>
@ -141,7 +140,7 @@ namespace sgpem
/**
* \brief Widgets size type.
*/
typedef unsigned int size_t;
typedef guint size_t;
// implementation of fundamental widget's method
/**
@ -152,6 +151,7 @@ namespace sgpem
* See gtkmm documentation for more informations.
*/
virtual void on_realize();
virtual void on_unrealize(); // doesn't need to be documented.
/**
* \brief Implements standard widget's on_size_allocate() mehtod.
@ -193,7 +193,7 @@ namespace sgpem
* draw in the widgets client area.
* See cairo documentation for more informations.
*/
virtual void draw_widget(cairo_t* ctx) = 0;
virtual void draw_widget(Cairo::RefPtr<Cairo::Context>& ctx) = 0;
/**
* \brief Method to calculate widget dimensions.
@ -201,7 +201,7 @@ namespace sgpem
* The user should implement this method to allow scaling factors calculation.
* Is necessary if scaling is needed/used.
*/
virtual void calc_drawing_size(cairo_t* ctx, size_t& width, size_t& height);
virtual void calc_drawing_size(Cairo::RefPtr<Cairo::Context>& ctx, size_t& width, size_t& height);
// with this method CairoWidget tells the needed widget dimensions
/**
@ -232,48 +232,48 @@ namespace sgpem
/**
* \brief Calculated width of drawing.
*/
mutable size_t _draw_w;
size_t _draw_w;
/**
* \brief Calculated height of drawing.
*/
mutable size_t _draw_h;
size_t _draw_h;
private:
/**
* \brief Client area width of widget.
*/
mutable size_t _client_w;
size_t _client_w;
/**
* \brief Client area height of widget.
*/
mutable size_t _client_h;
size_t _client_h;
/**
* \brief Client area width of pixmap.
*/
mutable size_t _pixmap_w;
size_t _pixmap_w;
/**
* \brief Client area width of pixmap.
*/
mutable size_t _pixmap_h;
size_t _pixmap_h;
/**
* \brief Cairo x scale factor.
*/
mutable double _scale_x;
double _scale_x;
/**
* \brief Cairo y scale factor.
*/
mutable double _scale_y;
double _scale_y;
/**
* \brief Flag to signal require redrawing.
*/
mutable bool _need_redraw;
bool _need_redraw;
/**
* \brief Actual scaling mode.
@ -284,6 +284,11 @@ namespace sgpem
* \brief Offscreen pixmap used for double-buffering.
*/
Glib::RefPtr<Gdk::Pixmap> _buf;
/**
*
*/
Glib::RefPtr<Gdk::Window> _ref_gdk_window;
};
} //~ namespace sgpem

View File

@ -21,20 +21,22 @@
#include "cairo_elements.hh"
#include <sgpemv2/history.hh>
#include <sgpemv2/schedulable.hh>
#include <sgpemv2/resource.hh>
#include <sgpemv2/simulation.hh>
#include <sgpemv2/string_utils.hh>
#include <sgpemv2/thread.hh>
#include "sgpemv2/history.hh"
#include "sgpemv2/schedulable.hh"
#include "sgpemv2/process.hh"
#include "sgpemv2/resource.hh"
#include "sgpemv2/simulation.hh"
#include "sgpemv2/string_utils.hh"
#include "sgpemv2/thread.hh"
#include "holt_widget.hh"
#include <sgpemv2/templates/deletor.tcc>
#include <sgpemv2/templates/sequences.tcc>
#include "sgpemv2/templates/deletor.tcc"
#include "sgpemv2/templates/sequences.tcc"
#include <math.h>
#include <cairomm/cairomm.h>
#include <cmath>
#include <cassert>
#ifndef NDEBUG
@ -104,7 +106,7 @@ HoltResource::~HoltResource()
{
}
void HoltResource::draw(cairo_t *cr)
void HoltResource::draw(Cairo::RefPtr<Cairo::Context>& cr)
{
static const Color white(1, 1, 1);
@ -114,43 +116,31 @@ void HoltResource::draw(cairo_t *cr)
CairoElements ce(cr);
// outline
cairo_set_source_rgb (cr, 0, 0, 0);
cr->set_source_rgb (0, 0, 0);
// draw rectangle
Rectangle area(_pos.real() - _radius, _pos.imag() - _radius, 2*_radius, 2*_radius);
ce.draw_3dcube(area, white, x_percent, y_percent);
cr->save();
cairo_save(cr);
// clip text outside region
/*
cairo_rectangle(cr,
_pos.real() - _radius,
_pos.imag() - _radius, // _pos.imag() + _radius (1 - 2.0 * y_percent)
2 * _radius * x_percent,
2 * _radius * y_percent);
*/
cr->rectangle(_pos.real() - _radius,
_pos.imag() + _radius * (1 - 2.0 * y_percent),
2 * _radius * x_percent,
2 * _radius * y_percent);
cr->clip();
cairo_rectangle(cr,
_pos.real() - _radius,
_pos.imag() + _radius * (1 - 2.0 * y_percent),
2 * _radius * x_percent,
2 * _radius * y_percent);
cairo_clip(cr);
// draw text
cairo_text_extents_t extents;
cairo_text_extents(cr, _resource->get_name().c_str(), &extents);
Cairo::TextExtents extents;
cr->get_text_extents(_resource->get_name(), extents);
double xpos = _pos.real() + _radius * (x_percent-1) - extents.width/2.0;
double ypos = _pos.imag() + _radius * (1 - y_percent); // + extents.height/2;
// _pos.imag() + extents.height * ((1 - y_percent) / 2 + 0.5)
// left aligned if too large
if(xpos<_pos.real() - _radius)
xpos = _pos.real() - _radius;
cairo_move_to(cr,
xpos,
ypos );
cairo_show_text(cr, _resource->get_name().c_str());
cr->move_to(xpos, ypos );
cr->show_text(_resource->get_name());
// show used/total places
Glib::ustring used;
@ -159,18 +149,16 @@ void HoltResource::draw(cairo_t *cr)
to_string<int>((int)_resource->get_places(), total);
Glib::ustring msg = used + "/" + total;
cairo_text_extents(cr, msg.c_str(), &extents);
cr->get_text_extents(msg, extents);
xpos = _pos.real() + _radius * (x_percent-1) - extents.width/2.0;
ypos = _pos.imag() + _radius * (1 - y_percent) + extents.height*2;
cairo_move_to(cr,
xpos,
ypos );
cairo_show_text(cr, msg.c_str());
cr->move_to(xpos, ypos);
cr->show_text(msg);
// stroke all
cairo_stroke (cr);
cr->stroke();
cairo_restore(cr);
cr->restore();
}
Vec2 HoltResource::get_intersection_to(Vec2 pt)
@ -224,14 +212,13 @@ HoltSchedulable::~HoltSchedulable()
{
}
void HoltSchedulable::draw(cairo_t *cr)
void HoltSchedulable::draw(Cairo::RefPtr<Cairo::Context>& cr)
{
static const Color red(1, 0, 0);
static const Color yellow(1, 0.8, 0);
static const Color green(0, 1, 0);
cairo_save(cr); // save context state
cr->save(); // save context state
const Point center(_pos.real(), _pos.imag());
const Color* color = &red;
@ -259,22 +246,21 @@ void HoltSchedulable::draw(cairo_t *cr)
cel.draw_3dsphere(center, _radius, *color);
// clip text outside region
cairo_arc(cr, _pos.real(), _pos.imag(), _radius, 0, 2*M_PI);
cairo_clip(cr);
cr->arc(_pos.real(), _pos.imag(), _radius, 0, 2*M_PI);
cr->clip();
// draw text
cairo_text_extents_t extents;
cairo_text_extents(cr, _schedulable->get_name().c_str(), &extents);
Cairo::TextExtents extents;
cr->get_text_extents(_schedulable->get_name(), extents);
double text_width = extents.width;
if(text_width>_radius*2.0)
text_width=_radius*2.0;
cairo_move_to(cr, _pos.real() - text_width/2, _pos.imag() + extents.height/2);
cairo_show_text(cr, _schedulable->get_name().c_str());
if(text_width>_radius*2.0) text_width=_radius*2.0;
cr->move_to(_pos.real() - text_width/2, _pos.imag() + extents.height/2);
cr->show_text(_schedulable->get_name());
// stroke all
cairo_stroke (cr);
cr->stroke();
cairo_restore(cr); // restore context state
cr->restore(); // restore context state
}
Vec2 HoltSchedulable::get_intersection_to(Vec2 pt)
@ -310,24 +296,24 @@ HoltRequest::~HoltRequest()
{
}
void HoltRequest::draw(cairo_t *cr)
void HoltRequest::draw(Cairo::RefPtr<Cairo::Context>& cr)
{
Vec2 resource = _hp->get_intersection_to(_hr->get_position());
Vec2 schedulable = _hr->get_intersection_to(_hp->get_position());
cairo_save(cr);
cr->save();
switch(_state)
{
case Request::state_unallocable:
// red
cairo_set_source_rgb(cr, 1, 0, 0);
cr->set_source_rgb(1, 0, 0);
arrow(cr, schedulable, resource);
break;
case Request::state_allocated:
// green
cairo_set_source_rgb(cr, 0, 1, 0);
cr->set_source_rgb(0, 1, 0);
arrow(cr, resource, schedulable);
break;
@ -339,27 +325,27 @@ void HoltRequest::draw(cairo_t *cr)
case Request::state_allocable:
// yellow
cairo_set_source_rgb(cr, 1, 0.7, 0);
cr->set_source_rgb(1, 0.7, 0);
arrow(cr, schedulable, resource);
break;
}
// stroke all and restore status
cairo_stroke (cr);
cairo_restore(cr);
cr->stroke();
cr->restore();
}
void HoltRequest::arrow(cairo_t *cr, Vec2 first, Vec2 second)
void HoltRequest::arrow(Cairo::RefPtr<Cairo::Context>& cr, Vec2 first, Vec2 second)
{
// option to draw the line a little translated
// this allow to draw two counterflow arrows
// without overlap
bool traslate = true;
double line_width = cairo_get_line_width(cr);
double line_width = cr->get_line_width();
if(traslate)
{
// if needed calc parallel versor of arrow
Vec2 direction = second-first;
Vec2 direction = second - first;
direction /= std::abs(direction); // set unary modulus
// and rotate it 90 degrees
@ -373,12 +359,12 @@ void HoltRequest::arrow(cairo_t *cr, Vec2 first, Vec2 second)
}
// draw main line
cairo_move_to(cr, second.real(), second.imag());
cairo_line_to(cr, first.real(), first.imag());
cr->move_to(second.real(), second.imag());
cr->line_to(first.real(), first.imag());
// some calculation to draw arrowpoint...
// take a short line parallel to main line
Vec2 arrowside = second-first;
Vec2 arrowside = second - first;
arrowside *= 5.0*line_width/std::abs(arrowside);
// make a rotation component
Vec2 deviation(5.0, 1.0); deviation /= std::abs(deviation);
@ -386,11 +372,11 @@ void HoltRequest::arrow(cairo_t *cr, Vec2 first, Vec2 second)
Vec2 side1 = arrowside * deviation;
Vec2 side2 = arrowside * conj(deviation);
// draw one side
cairo_move_to(cr, first.real(), first.imag());
cairo_line_to(cr, first.real()+side1.real(), first.imag()+side1.imag());
cr->move_to(first.real(), first.imag());
cr->line_to(first.real()+side1.real(), first.imag()+side1.imag());
// draw the other side
cairo_move_to(cr, first.real(), first.imag());
cairo_line_to(cr, first.real()+side2.real(), first.imag()+side2.imag());
cr->move_to(first.real(), first.imag());
cr->line_to(first.real()+side2.real(), first.imag()+side2.imag());
}
@ -806,7 +792,7 @@ HoltWidget::acquire()
void
HoltWidget::draw_widget(cairo_t* ctx)
HoltWidget::draw_widget(Cairo::RefPtr<Cairo::Context>& ctx)
{
#ifndef NDEBUG
std::cout << "HoltWidget::draw_widget" << endl;
@ -819,18 +805,16 @@ HoltWidget::draw_widget(cairo_t* ctx)
if(_draw_w>0)
{
const History& hist = _simulation->get_history();
const unsigned int hist_front = hist.get_front() == 0 ? 0 : hist.get_front() - 1;
cairo_text_extents_t extents;
const unsigned int hist_front = hist.get_front() == 0 ? 0 : hist.get_front() - 1;
Cairo::TextExtents extents;
stringstream ss;
ss << "T = " << hist_front;
cairo_text_extents(ctx, ss.str().c_str(), &extents);
cairo_move_to(ctx, _draw_w/2 - extents.width/2.0, extents.height*2.0);
cairo_show_text(ctx, ss.str().c_str());
cairo_stroke(ctx);
ctx->get_text_extents(ss.str(), extents);
ctx->move_to(_draw_w/2 - extents.width/2.0, extents.height*2.0);
ctx->show_text(ss.str());
ctx->stroke();
}
// draw all resources
typedef HoltResources::const_iterator holt_res_iterator;
holt_res_iterator riter = _holt_resources.begin();
@ -865,7 +849,7 @@ HoltWidget::draw_widget(cairo_t* ctx)
void
HoltWidget::calc_drawing_size(cairo_t* ctx, size_t& width, size_t& height)
HoltWidget::calc_drawing_size(Cairo::RefPtr<Cairo::Context>& ctx, size_t& width, size_t& height)
{
#ifndef NDEBUG
cout << "Holt widget BEFORE calc_drawing_size width=" << width << " height=" << height << endl;
@ -881,10 +865,10 @@ HoltWidget::calc_drawing_size(cairo_t* ctx, size_t& width, size_t& height)
int max = _n_proc;
if(_n_res>_n_proc)
max = _n_res;
cairo_text_extents_t extents;
Cairo::TextExtents extents;
static const Glib::ustring val("Process 999 Resource 999");
cairo_text_extents(ctx, val.c_str(), &extents);
ctx->get_text_extents(val, extents);
_radius = extents.width/4.0;
switch(_arrange_mode)

View File

@ -89,7 +89,7 @@ namespace sgpem
*
* \param cr The cairo context to draw to.
*/
virtual void draw(cairo_t *cr) = 0;
virtual void draw(Cairo::RefPtr<Cairo::Context>& cr) = 0;
/**
* \brief Setter and getter method for position parameter.
@ -195,7 +195,7 @@ namespace sgpem
*
* \param cr Cairo context to draw to.
*/
virtual void draw(cairo_t *cr);
virtual void draw(Cairo::RefPtr<Cairo::Context>& cr);
/**
* \brief Computes point of intersection with edge.
@ -278,7 +278,7 @@ namespace sgpem
*
* \param cr Cairo context to draw to.
*/
virtual void draw(cairo_t *cr);
virtual void draw(Cairo::RefPtr<Cairo::Context>& cr);
/**
* \brief Computes point of intersection with edge.
@ -336,7 +336,7 @@ namespace sgpem
*
* \param cr Cairo context to draw to.
*/
virtual void draw(cairo_t *cr);
virtual void draw(Cairo::RefPtr<Cairo::Context>& cr);
private:
/**
@ -346,7 +346,7 @@ namespace sgpem
* \param first Starting point.
* \param first Ending point.
*/
virtual void arrow(cairo_t *cr, Vec2 first, Vec2 second);
virtual void arrow(Cairo::RefPtr<Cairo::Context>& cr, Vec2 first, Vec2 second);
/**
* \brief Pointer to the referring schedulable.
@ -490,7 +490,7 @@ namespace sgpem
* \param ctx the cairo context to draw to
* \see CairoWidget for more.
*/
void draw_widget(cairo_t* ctx);
void draw_widget(Cairo::RefPtr<Cairo::Context>& ctx);
/**
@ -500,7 +500,7 @@ namespace sgpem
* \param width the return parameter for desired width
* \param height the return parameter for desired height
*/
virtual void calc_drawing_size(cairo_t* ctx, size_t& width, size_t& height);
virtual void calc_drawing_size(Cairo::RefPtr<Cairo::Context>& ctx, size_t& width, size_t& height);
// virtual void calc_widget_size(size_t& width, size_t& height);

View File

@ -22,15 +22,19 @@
#include "simulation_widget.hh"
#include "cairo_elements.hh"
#include "sgpemv2/history.hh"
#include "sgpemv2/process.hh"
#include "sgpemv2/thread.hh"
#include "sgpemv2/simulation.hh"
#include "sgpemv2/string_utils.hh"
#include <glibmm/refptr.h>
#include <gtkmm/action.h>
#include <gtkmm/actiongroup.h>
#include <gtkmm/menu.h>
#include <gtkmm/uimanager.h>
#include <sgpemv2/history.hh>
#include <sgpemv2/simulation.hh>
#include <sgpemv2/string_utils.hh>
#include <cairomm/matrix.h>
#include <cassert>
@ -42,7 +46,6 @@ using namespace sgpem;
using namespace Gtk;
using namespace Glib;
SimulationWidget::SimulationWidget(Simulation& simulation)
: Glib::ObjectBase("sgpem_SimulationWidget"),
SimulationObserver(),
@ -60,35 +63,29 @@ SimulationWidget::SimulationWidget(Simulation& simulation)
// count_elements();
// define top margin in y units
_yu_top_margin = 1.0;
// define top margin in y units
_yu_top_margin = 1.0;
// define left margin in x units
_xu_left_margin = 1.0;
// define left margin in x units
_xu_left_margin = 1.0;
// define graph left margin in x units
_xu_left_graph_margin = 11.0;
// define graph left margin in x units
_xu_left_graph_margin = 11.0;
// define process bar spacing in y units
_yu_process_bar_spacing = 1.0;
// define process bar spacing in y units
_yu_process_bar_spacing = 1.0;
// define process bar height in y units
_yu_process_bar_height = 2.0;
// define process bar height in y units
_yu_process_bar_height = 2.0;
// define thread bar spacing in y units
_yu_thread_bar_spacing = 0.5;
// define thread bar spacing in y units
_yu_thread_bar_spacing = 0.5;
// define thread bar height in y units
_yu_thread_bar_height = 1.0;
// define thread bar height in y units
_yu_thread_bar_height = 1.0;
//
_ready_process_gradient = 0;
_running_process_gradient = 0;
_blocked_process_gradient = 0;
_partial_redraw = false;
_last_drawn = 0;
_partial_redraw = false;
_last_drawn = 0;
}
@ -101,9 +98,20 @@ SimulationWidget::~SimulationWidget()
_simulation->detach(*this);
}
void
SimulationWidget::on_realize()
{
CairoWidget::on_realize();
// Register for receiving click events:
RefPtr<Gdk::Window> gdk_win = get_window();
gdk_win->set_events(gdk_win->get_events() | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK);
}
void
SimulationWidget::update(const Simulation& /* changed_simulation */ )
{
// FIXME: DEPRECATED. Does nothing.
}
void
@ -132,12 +140,12 @@ SimulationWidget::set_show_threads(bool show)
void
SimulationWidget::draw_widget(cairo_t* ctx)
SimulationWidget::draw_widget(Cairo::RefPtr<Cairo::Context>& ctx)
{
if(_n_proc<1) // nothing to draw
{
cairo_move_to(ctx, 2.0*_x_unit, 2.0*_y_unit);
cairo_show_text(ctx, _("Nothing to see here... add some processes! Right-click on the Schedulables view in this window."));
ctx->move_to(2.0*_x_unit, 2.0*_y_unit);
ctx->show_text(_("Nothing to see here... add some processes! Right-click on the Schedulables view in this window."));
return;
}
@ -148,12 +156,12 @@ SimulationWidget::draw_widget(cairo_t* ctx)
void
SimulationWidget::draw_names(cairo_t* ctx)
SimulationWidget::draw_names(Cairo::RefPtr<Cairo::Context>& ctx)
{
// show processes (and thread) names...
// useful constants
const History& hist = _simulation->get_history();
const History& hist = _simulation->get_history();
const double top_margin = _yu_top_margin * _y_unit;
const double left_margin = _x_unit;
const double left_graph_margin = _xu_left_graph_margin * _x_unit;
@ -165,11 +173,11 @@ SimulationWidget::draw_names(cairo_t* ctx)
// set a rectangular clip region to cut long names
// - set the rectangle
cairo_rectangle(ctx, 0, top_margin,
ctx->rectangle(0, top_margin,
left_graph_margin - left_margin,
_n_proc*process_height + _n_thr*thread_height);
// - set the clip region
cairo_clip(ctx);
ctx->clip();
// text start position: margin + half of text height
double ypos = top_margin + _y_unit / 2.0;
@ -184,9 +192,9 @@ SimulationWidget::draw_names(cairo_t* ctx)
// move to bar center adding a white row before
ypos += process_bar_spacing + process_bar_height/2.0;
cairo_move_to(ctx, left_margin, ypos);
ctx->move_to(left_margin, ypos);
// show process name
cairo_show_text(ctx,p->get_name().c_str());
ctx->show_text(p->get_name());
// calc position to next row skipping height of process bar
ypos += process_bar_height/2.0;
@ -202,9 +210,9 @@ SimulationWidget::draw_names(cairo_t* ctx)
thr_iter++;
// move to bar center adding white space as needed
ypos += thread_height/2.0;
cairo_move_to(ctx, left_margin+_x_unit, ypos);
ctx->move_to(left_margin+_x_unit, ypos);
// show thread name
cairo_show_text(ctx,t->get_name().c_str());
ctx->show_text(t->get_name());
// calc position to next thread bar begin
ypos += thread_height/2.0; // height of thread bar
@ -216,11 +224,11 @@ SimulationWidget::draw_names(cairo_t* ctx)
} // ~ while(proc_iter!=processes.end())
// remove clip region
cairo_reset_clip(ctx);
ctx->reset_clip();
}
void
SimulationWidget::draw_grid(cairo_t* ctx)
SimulationWidget::draw_grid(Cairo::RefPtr<Cairo::Context>& ctx)
{
const History& hist = _simulation->get_history();
@ -243,8 +251,8 @@ SimulationWidget::draw_grid(cairo_t* ctx)
Process* p = (*proc_iter);
proc_iter++;
// draw one HOR line per process
cairo_move_to(ctx, left_graph_margin, ypos);
cairo_rel_line_to(ctx, graph_width, 0);
ctx->move_to(left_graph_margin, ypos);
ctx->rel_line_to(graph_width, 0);
// calc next line position
ypos += process_height; // skip a process heigh
@ -257,69 +265,69 @@ SimulationWidget::draw_grid(cairo_t* ctx)
} // ~ while(proc_iter!=processes.end())
// draw last HOR line
cairo_move_to(ctx, left_graph_margin, ypos);
cairo_rel_line_to(ctx, graph_width, 0);
ctx->move_to(left_graph_margin, ypos);
ctx->rel_line_to(graph_width, 0);
// - draw left VER line
cairo_move_to(ctx, left_graph_margin, top_margin);
cairo_rel_line_to(ctx, 0, graph_height);
ctx->move_to(left_graph_margin, top_margin);
ctx->rel_line_to(0, graph_height);
// right close the graph only if simulation stopped
if(_simulation->get_state()==Simulation::state_stopped)
{
// - draw right VER line
cairo_move_to(ctx, left_graph_margin + graph_width, top_margin);
cairo_rel_line_to(ctx, 0, graph_height);
ctx->move_to(left_graph_margin + graph_width, top_margin);
ctx->rel_line_to(0, graph_height);
}
// trace lines on output context
cairo_stroke(ctx);
ctx->stroke();
// Draw a grey vertical line every fifth step
cairo_save(ctx);
cairo_set_line_width(ctx, 0.125 * cairo_get_line_width(ctx));
cairo_set_source_rgb(ctx, 0.3, 0.3, 0.3);
ctx->save();
ctx->set_line_width(0.125 * ctx->get_line_width());
ctx->set_source_rgb(0.3, 0.3, 0.3);
for(double step = _x_unit; step < graph_width - _x_unit; step += 5 * _x_unit)
{
cairo_new_path(ctx);
cairo_move_to(ctx, left_graph_margin + step, top_margin);
cairo_rel_line_to(ctx, 0, graph_height);
cairo_stroke(ctx);
ctx->begin_new_path();
ctx->move_to(left_graph_margin + step, top_margin);
ctx->rel_line_to(0, graph_height);
ctx->stroke();
}
cairo_restore(ctx);
ctx->restore();
// draw and write time line
cairo_save(ctx);
cairo_set_source_rgb(ctx, 0, 0, 0);
cairo_set_line_width(ctx, 0.25*cairo_get_line_width(ctx));
ctx->save();
ctx->set_source_rgb(0, 0, 0);
ctx->set_line_width(0.25*ctx->get_line_width());
// "T" label
cairo_move_to(ctx, left_graph_margin,
ctx->move_to(left_graph_margin,
top_margin + graph_height + 2.0 * _y_unit);
cairo_show_text(ctx,"T");
ctx->show_text("T");
// ruler drawing cycle
for(unsigned int t=0; t<=hist_front; t++)
{
// tick
cairo_move_to(ctx, left_graph_margin + (t+1)*_x_unit,
ctx->move_to(left_graph_margin + (t+1)*_x_unit,
top_margin + graph_height);
cairo_rel_line_to(ctx, 0, 0.5 * _y_unit);
ctx->rel_line_to(0, 0.5 * _y_unit);
// value
Glib::ustring val;
to_string<int>(t, val);
cairo_move_to(ctx, left_graph_margin + (t+1)*_x_unit,
ctx->move_to(left_graph_margin + (t+1)*_x_unit,
top_margin + graph_height + 2.0 * _y_unit);
cairo_show_text(ctx,val.c_str());
ctx->show_text(val);
} // ~ for(int t=0; t<=pos; t++)
cairo_stroke(ctx);
cairo_restore(ctx);
ctx->stroke();
ctx->restore();
}
void
SimulationWidget::draw_bars(cairo_t* ctx)
SimulationWidget::draw_bars(Cairo::RefPtr<Cairo::Context>& ctx)
{
// useful constants
const History& hist = _simulation->get_history();
@ -408,53 +416,50 @@ SimulationWidget::draw_bars(cairo_t* ctx)
// draw single rectangle using gradients
void
SimulationWidget::draw_instant_rect(cairo_t* ctx, double x, double y,
SimulationWidget::draw_instant_rect(Cairo::RefPtr<Cairo::Context>& ctx, double x, double y,
double w, double h, Schedulable::state state)
{
cairo_matrix_t matrix;
using namespace Cairo;
switch(state)
{
case Schedulable::state_running:
cairo_save(ctx);
cairo_set_source(ctx, _running_process_gradient);
ctx->save();
ctx->set_source(_running_process_gradient);
// translate the gradient at desired position
cairo_matrix_init_translate(&matrix, 0, -y);
cairo_pattern_set_matrix (_running_process_gradient, &matrix);
_running_process_gradient->set_matrix(translation_matrix(0, -y));
// put the filled rectangle
cairo_rectangle(ctx, x, y, w, h);
cairo_fill(ctx);
cairo_restore(ctx);
ctx->rectangle(x, y, w, h);
ctx->fill();
ctx->restore();
break;
case Schedulable::state_ready:
cairo_save(ctx);
cairo_set_source(ctx, _ready_process_gradient);
ctx->save();
ctx->set_source(_ready_process_gradient);
// translate the gradient at desired position
cairo_matrix_init_translate(&matrix, 0, -y);
cairo_pattern_set_matrix (_ready_process_gradient, &matrix);
_ready_process_gradient->set_matrix(translation_matrix(0, -y));
// put the filled rectangle
cairo_rectangle(ctx, x, y, w, h);
cairo_fill(ctx);
cairo_restore(ctx);
ctx->rectangle(x, y, w, h);
ctx->fill();
ctx->restore();
break;
case Schedulable::state_blocked:
cairo_save(ctx);
cairo_set_source(ctx, _blocked_process_gradient);
ctx->save();
ctx->set_source(_blocked_process_gradient);
// translate the gradient at desired position
cairo_matrix_init_translate(&matrix, 0, -y);
cairo_pattern_set_matrix (_blocked_process_gradient, &matrix);
_blocked_process_gradient->set_matrix(translation_matrix(0, -y));
// put the filled rectangle
cairo_rectangle(ctx, x, y, w, h);
cairo_fill(ctx);
cairo_restore(ctx);
ctx->rectangle(x, y, w, h);
ctx->fill();
ctx->restore();
break;
case Schedulable::state_future:
@ -469,7 +474,7 @@ SimulationWidget::draw_instant_rect(cairo_t* ctx, double x, double y,
void
SimulationWidget::calc_drawing_size(cairo_t* ctx, size_t& width, size_t& height)
SimulationWidget::calc_drawing_size(Cairo::RefPtr<Cairo::Context>& ctx, size_t& width, size_t& height)
{
if(!_simulation)
return;
@ -480,13 +485,13 @@ SimulationWidget::calc_drawing_size(cairo_t* ctx, size_t& width, size_t& height)
int pos = _simulation->get_history().get_front();
// units are defined in terms of text dimensions
cairo_text_extents_t extents;
Cairo::TextExtents extents;
Glib::ustring val("999");
cairo_text_extents(ctx, val.c_str(), &extents);
if(_x_unit<extents.width)
_x_unit=extents.width;
if(_y_unit<extents.height)
_y_unit=extents.height;
ctx->get_text_extents(val, extents);
if(_x_unit < extents.width)
_x_unit = extents.width;
if(_y_unit < extents.height)
_y_unit = extents.height;
// left margin, labels, graph
width = (size_t)((_xu_left_graph_margin + 3.0 + pos) * _x_unit);
@ -509,7 +514,7 @@ SimulationWidget::count_elements()
{
_n_proc = _n_thr = 0;
const History& hist = _simulation->get_history();
const History& hist = _simulation->get_history();
const Environment& env = hist.get_last_environment();
// count processes
@ -533,24 +538,25 @@ SimulationWidget::make_gradients()
{
// linear gradients are referred to 0, 0
// must be translated if used elsewhere
using Cairo::LinearGradient;
_ready_process_gradient = cairo_pattern_create_linear(0, 0, 0, _yu_process_bar_height * _y_unit);
_ready_process_gradient = LinearGradient::create(0, 0, 0, _yu_process_bar_height * _y_unit);
// yellow
cairo_pattern_add_color_stop_rgb(_ready_process_gradient, 0.0, 1.00, 0.7, 0.0);
cairo_pattern_add_color_stop_rgb(_ready_process_gradient, 0.3, 1.00, 0.9, 0.0);
cairo_pattern_add_color_stop_rgb(_ready_process_gradient, 1.0, 1.00, 0.7, 0.0);
_ready_process_gradient->add_color_stop_rgb(0.0, 1.00, 0.7, 0.0);
_ready_process_gradient->add_color_stop_rgb(0.3, 1.00, 0.9, 0.0);
_ready_process_gradient->add_color_stop_rgb(1.0, 1.00, 0.7, 0.0);
_running_process_gradient = cairo_pattern_create_linear(0, 0, 0, _yu_process_bar_height * _y_unit);
_running_process_gradient = LinearGradient::create(0, 0, 0, _yu_process_bar_height * _y_unit);
// green
cairo_pattern_add_color_stop_rgb(_running_process_gradient, 0.0, 0.0, 0.8, 0.0);
cairo_pattern_add_color_stop_rgb(_running_process_gradient, 0.3, 0.0, 1.0, 0.0);
cairo_pattern_add_color_stop_rgb(_running_process_gradient, 1.0, 0.0, 0.65, 0.0);
_running_process_gradient->add_color_stop_rgb(0.0, 0.0, 0.8, 0.0);
_running_process_gradient->add_color_stop_rgb(0.3, 0.0, 1.0, 0.0);
_running_process_gradient->add_color_stop_rgb(1.0, 0.0, 0.65, 0.0);
_blocked_process_gradient = cairo_pattern_create_linear(0, 0, 0, _yu_process_bar_height * _y_unit);
_blocked_process_gradient = LinearGradient::create(0, 0, 0, _yu_process_bar_height * _y_unit);
// red
cairo_pattern_add_color_stop_rgb(_blocked_process_gradient, 0.0, 0.85, 0.0, 0.0);
cairo_pattern_add_color_stop_rgb(_blocked_process_gradient, 0.3, 1.0, 0.5, 0.5);
cairo_pattern_add_color_stop_rgb(_blocked_process_gradient, 1.0, 0.65, 0.0, 0.0);
_blocked_process_gradient->add_color_stop_rgb(0.0, 0.85, 0.0, 0.0);
_blocked_process_gradient->add_color_stop_rgb(0.3, 1.0, 0.5, 0.5);
_blocked_process_gradient->add_color_stop_rgb(1.0, 0.65, 0.0, 0.0);
}
@ -656,3 +662,5 @@ SimulationWidget::_on_stretch_scaling()
resize_redraw();
// set_size_request (20, 20); // force container redimensioning
}

View File

@ -21,12 +21,13 @@
#ifndef SIMULATION_WIDGET_HH
#define SIMULATION_WIDGET_HH 1
#include "cairo_widget.hh"
#include <sgpemv2/history_observer.hh>
#include <sgpemv2/schedulable.hh>
#include <sgpemv2/simulation_observer.hh>
#include "sgpemv2/history_observer.hh"
#include "sgpemv2/schedulable.hh"
#include "sgpemv2/simulation_observer.hh"
#include <cairomm/pattern.h>
namespace sgpem
{
@ -48,7 +49,7 @@ namespace sgpem
*
* At the bottom of the graph there is a time line ruler.
*
* This class implemets a SimulationObserver and HistoryObserver
* This class implements a SimulationObserver and HistoryObserver
* to have an update signal (and related update) every simulation step.
*
* \deprecated The class should implement only HistoryObserver
@ -57,7 +58,7 @@ namespace sgpem
* \see HistoryObserver
*/
class SimulationWidget
: public SimulationObserver, public HistoryObserver, public CairoWidget
: public SimulationObserver, public HistoryObserver, public CairoWidget
{
public:
/**
@ -77,7 +78,7 @@ namespace sgpem
/**
* \brief SimulationObserver's update method redefinition.
*
* Actually is a dummy method.
* \deprecated Actually is a dummy method.
*
* \param changed_simulation the observed Simulation
*/
@ -127,7 +128,7 @@ namespace sgpem
* \param ctx the cairo context to draw to
* \see CairoWidget for more.
*/
void draw_widget(cairo_t* ctx);
void draw_widget(Cairo::RefPtr<Cairo::Context>& ctx);
/**
* \brief calculated the needed drawing surface dimensions.
@ -136,8 +137,12 @@ namespace sgpem
* \param width the return parameter for desired width
* \param height the return parameter for desired height
*/
virtual void calc_drawing_size(cairo_t* ctx, size_t& width, size_t& height);
virtual void calc_drawing_size(Cairo::RefPtr<Cairo::Context>& ctx, size_t& width, size_t& height);
/**
* \brief Adds the click events to the underlying Gdk::Window
*/
virtual void on_realize();
private:
@ -152,21 +157,21 @@ namespace sgpem
*
* \param ctx the cairo context to draw to
*/
void draw_names(cairo_t* ctx);
void draw_names(Cairo::RefPtr<Cairo::Context>& ctx);
/**
* \brief Used internally by draw_widget to show the bars container grid.
*
* \param ctx the cairo context to draw to
*/
void draw_grid(cairo_t* ctx);
void draw_grid(Cairo::RefPtr<Cairo::Context>& ctx);
/**
* \brief Used internally by draw_widget to show processes/threads bars.
*
* \param ctx the cairo context to draw to
*/
void draw_bars(cairo_t* ctx);
void draw_bars(Cairo::RefPtr<Cairo::Context>& ctx);
/**
* \brief Used internally by draw_widget to build the bars.
@ -178,7 +183,7 @@ namespace sgpem
* \param h height of rectangle
* \param state select the color to apply
*/
void draw_instant_rect(cairo_t* ctx, double x, double y,
void draw_instant_rect(Cairo::RefPtr<Cairo::Context>& ctx, double x, double y,
double w, double h, sgpem::Schedulable::state state);
/**
@ -284,17 +289,17 @@ namespace sgpem
/**
* \brief Gradient used to draw ready processes/threads.
*/
cairo_pattern_t* _ready_process_gradient;
Cairo::RefPtr<Cairo::Gradient> _ready_process_gradient;
/**
* \brief Gradient used to draw running processes/threads.
*/
cairo_pattern_t* _running_process_gradient;
Cairo::RefPtr<Cairo::Gradient> _running_process_gradient;
/**
* \brief Gradient used to draw blocked processes/threads.
*/
cairo_pattern_t* _blocked_process_gradient;
Cairo::RefPtr<Cairo::Gradient> _blocked_process_gradient;
/**
* Used to redraw partially the widget.

View File

@ -56,10 +56,10 @@ namespace sgpem
protected:
virtual bool on_button_press_event(GdkEventButton* event);
void draw_widget(cairo_t* ctx);
void draw_widget(Cairo::RefPtr<Cairo::Context>& ctx);
void change_scaling_mode();
virtual void calc_drawing_size(cairo_t* ctx, size_t& width, size_t& height);
virtual void calc_drawing_size(Cairo::RefPtr<Cairo::Context>& ctx, size_t& width, size_t& height);
private:
int _desired_w;
int _desired_h;
@ -70,7 +70,7 @@ namespace sgpem
using namespace sgpem;
TestWidget::TestWidget()
: Glib::ObjectBase("sgpem_TestWidget"), CairoWidget(),
: Glib::ObjectBase("sgpem_TestWidget"), CairoWidget(),
_desired_w(200), _desired_h(300)
{
}
@ -90,13 +90,13 @@ TestWidget::on_button_press_event(GdkEventButton*)
}
void
TestWidget::draw_widget(cairo_t* ctx)
TestWidget::draw_widget(Cairo::RefPtr<Cairo::Context>& ctx)
{
// show line
cairo_set_source_rgb(ctx, 0, 0, 0);
cairo_move_to(ctx, 0, 0);
cairo_line_to(ctx, _desired_w, _desired_w);
cairo_stroke(ctx);
ctx->set_source_rgb(0, 0, 0);
ctx->move_to(0, 0);
ctx->line_to(_desired_w, _desired_w);
ctx->stroke();
// NOTE: just to try
CairoElements ce(ctx);
@ -138,20 +138,16 @@ TestWidget::draw_widget(cairo_t* ctx)
msg = "scaling_all = scale to stretch into client area";
break;
}
cairo_move_to(ctx, 10, 10);
cairo_show_text(ctx,msg.c_str());
ctx->move_to(10, 10);
ctx->show_text(msg);
msg = "clic to change mode...";
cairo_move_to(ctx, 10, 30);
cairo_show_text(ctx,msg.c_str());
ctx->move_to(10, 30);
ctx->show_text(msg);
}
void
TestWidget::calc_drawing_size(cairo_t*, size_t& width, size_t& height)
TestWidget::calc_drawing_size(Cairo::RefPtr<Cairo::Context>&, size_t& width, size_t& height)
{
width = _desired_w;
height = _desired_h;