- Add CairoElements

- Start code for double buffering in custom widgets, using
an off-screen pixmap. Problem: we don't know the height from the 
beginning


git-svn-id: svn://svn.gna.org/svn/sgpemv2/trunk@798 3ecf2c5c-341e-0410-92b4-d18e462d057c
This commit is contained in:
tchernobog 2006-07-28 15:24:56 +00:00
parent 5b22b503a5
commit 25e5a7319b
6 changed files with 296 additions and 34 deletions

View File

@ -271,6 +271,7 @@ sgpemv2_LDADD = \
# Please keep this in sorted order: # Please keep this in sorted order:
sgpemv2_SOURCES = \ sgpemv2_SOURCES = \
src/cairo_elements.cc \
src/graphical_terminal_io.cc \ src/graphical_terminal_io.cc \
src/gui_builder.cc \ src/gui_builder.cc \
src/main.cc \ src/main.cc \
@ -282,6 +283,7 @@ sgpemv2_SOURCES = \
src/text_simulation.cc src/text_simulation.cc
noinst_HEADERS += \ noinst_HEADERS += \
src/cairo_elements.hh \
src/graphical_simulation.hh \ src/graphical_simulation.hh \
src/graphical_terminal_io.hh \ src/graphical_terminal_io.hh \
src/gui_builder.hh \ src/gui_builder.hh \

View File

@ -173,9 +173,7 @@ PythonPolicy::wait_unlock() const throw(UserInterruptException)
{ {
Py_UNBLOCK_THREADS; Py_UNBLOCK_THREADS;
usleep(WAIT_FOR); // hack'a'ton! magggggiccc nummmbeeerrrrrs!! usleep(WAIT_FOR); // hack'a'ton! magggggiccc nummmbeeerrrrrs!!
cout << "got here..." << endl;
Py_BLOCK_THREADS; Py_BLOCK_THREADS;
cout << "wow I also got here!" << endl;
PyObject* retval = PyObject_CallMethod(_adapter, "mutex_test_lock", NULL); PyObject* retval = PyObject_CallMethod(_adapter, "mutex_test_lock", NULL);
assert(retval); assert(retval);

View File

@ -212,7 +212,7 @@ Scheduler::step_forward(History& history, Policy& cpu_policy) throw(UserInterrup
// should be done here as the first thing, instead than // should be done here as the first thing, instead than
// directly after selecting them // directly after selecting them
if(current.get_total_cpu_time() - current.get_elapsed_time() > 0) if(current.get_total_cpu_time() - current.get_elapsed_time() > 0)
running_thread->decrease_remaining_time(); current.decrease_remaining_time();
// 2. mark threads that used all their allotted time as terminated // 2. mark threads that used all their allotted time as terminated
if(current.get_total_cpu_time() - current.get_elapsed_time() == 0) if(current.get_total_cpu_time() - current.get_elapsed_time() == 0)

184
src/cairo_elements.cc Normal file
View File

@ -0,0 +1,184 @@
// src/cairo_elements.cc - Copyright 2005, 2006, University
// of Padova, dept. of Pure and Applied
// Mathematics
//
// This file is part of SGPEMv2.
//
// This is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// SGPEMv2 is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with SGPEMv2; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "cairo_elements.hh"
#include <cmath>
using namespace sgpem;
CairoElements::CairoElements(cairo_t* const ctx)
: _ctx(ctx)
{
}
void
CairoElements::draw_3dsphere(const Point& center, float radius, const Color& cl)
{
cairo_t*& cr = _ctx;
const float& x = center.x;
const float& y = center.y;
const float& r = cl.r;
const float& g = cl.g;
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);
// 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);
// 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);
}
void
CairoElements::draw_3dcube(const Rectangle& area, const Color& cl)
{
cairo_t*& cr = _ctx;
const float& x0 = area.x0;
const float& y0 = area.y0;
const float& w = area.w;
const float& h = area.h;
// FIXME : not implemented
}
void
CairoElements::draw_container(const Rectangle& area)
{
cairo_t*& cr = _ctx;
const float& x0 = area.x0;
const float& y0 = area.y0;
const float& w = area.w;
const float& h = area.h;
const double corner_radius = 0.05;
cairo_save(cr);
cairo_new_path(cr);
cairo_move_to(cr, 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);
// 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);
// 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);
// 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);
cairo_set_source_rgb(cr, 1, 1, 0.9);
cairo_fill_preserve(cr);
cairo_set_line_width(cr, .005);
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_stroke(cr);
cairo_restore(cr);
}
void
CairoElements::draw_expandable(const Rectangle& area, bool expanded)
{
cairo_t*& cr = _ctx;
const float& x0 = area.x0;
const float& y0 = area.y0;
const float& w = area.w;
const float& h = area.h;
cairo_save(cr);
cairo_set_line_width(cr, .005);
cairo_set_source_rgb(cr, 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);
cairo_move_to(cr, x0 + w/10, y0 + h/2);
cairo_line_to(cr, x0 + w*9/10, y0 + h/2);
cairo_stroke(cr);
if(!expanded)
{
cairo_move_to(cr, x0 + w/2, y0 + h/10);
cairo_line_to(cr, x0 + w/2, y0 + h*9/10);
cairo_stroke(cr);
}
cairo_restore(cr);
}
Rectangle draw_thread_status(const Point& top_left_crn,
const Thread& thread_info)
{
}
Rectangle draw_process_status(const Point& top_left_crn,
const Process& process_info)
{
}

78
src/cairo_elements.hh Normal file
View File

@ -0,0 +1,78 @@
// src/cairo_elements.hh - Copyright 2005, 2006, University
// of Padova, dept. of Pure and Applied
// Mathematics
//
// This file is part of SGPEMv2.
//
// This is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// SGPEMv2 is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with SGPEMv2; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#ifndef CAIRO_ELEMENTS_HH
#define CAIRO_ELEMENTS_HH 1
#include "config.h"
#include "backend/thread.hh"
#include "backend/process.hh"
#include <cairo/cairo.h>
namespace sgpem
{
struct Point
{
float x;
float y;
};
struct Rectangle
{
float x0;
float y0;
float w;
float h;
};
struct Color
{
float r;
float g;
float b;
};
class CairoElements
{
public:
CairoElements(cairo_t* const ctx);
void draw_3dsphere(const Point& center, float radius, const Color& cl);
void draw_3dcube(const Rectangle& area, const Color& cl);
void draw_container(const Rectangle& area);
void draw_expandable(const Rectangle& area, bool expanded = false);
Rectangle draw_thread_status(const Point& top_left_crn,
const Thread& thread_info);
Rectangle draw_process_status(const Point& top_left_crn,
const Process& process_info);
private:
cairo_t* _ctx;
};
} //~ namespace sgpem
#endif //~ CAIRO_ELEMENTS_HH

View File

@ -18,6 +18,7 @@
// along with SGPEMv2; if not, write to the Free Software // along with SGPEMv2; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "cairo_elements.hh"
#include "schedulables_widget.hh" #include "schedulables_widget.hh"
#include <cmath> #include <cmath>
@ -26,7 +27,7 @@ using namespace sgpem;
SchedulablesWidget::SchedulablesWidget() SchedulablesWidget::SchedulablesWidget()
: _ctx(NULL) : Gtk::DrawingArea(), _ctx(NULL)
{ {
// Add other events we want to manage (as mouse clicks) // Add other events we want to manage (as mouse clicks)
// when needed // when needed
@ -36,13 +37,29 @@ SchedulablesWidget::SchedulablesWidget()
SchedulablesWidget::~SchedulablesWidget() SchedulablesWidget::~SchedulablesWidget()
{ {
if(_ctx != NULL)
cairo_destroy(_ctx);
} }
void void
SchedulablesWidget::update(const History& history) SchedulablesWidget::update(const History& history)
{ {
// FIXME : write me // FIXME : write me using double buffering
// GdkPixmap* buffer = gdk_pixmap_new(...);
// _ctx = gdk_cairo_create(buffer);
// do the drawing...
// NOTE: just to try
CairoElements ce(_ctx);
Color red = { 1, 0, 0 };
Point center = { 25, 25 };
ce.draw_3dsphere(center, 25, red);
// manually force an expose_event?
} }
@ -60,7 +77,6 @@ bool
SchedulablesWidget::on_expose_event(GdkEventExpose* event) SchedulablesWidget::on_expose_event(GdkEventExpose* event)
{ {
// Use double buffering or we're CPU-dead // Use double buffering or we're CPU-dead
Glib::RefPtr<Gdk::Window> window = get_window(); Glib::RefPtr<Gdk::Window> window = get_window();
GdkWindow* gdkWindow = window->gobj(); GdkWindow* gdkWindow = window->gobj();
GdkDrawable* gdkDrawable; GdkDrawable* gdkDrawable;
@ -71,14 +87,16 @@ SchedulablesWidget::on_expose_event(GdkEventExpose* event)
// we should use something like create_similar to instantiate a // we should use something like create_similar to instantiate a
// compatible surface and then copy the buffer to fg // compatible surface and then copy the buffer to fg
// So the following two lines WILL HAVE TO CHANGE. // So the following two lines WILL HAVE TO CHANGE.
cairo_t*& cr = _ctx; if(_ctx == NULL)
cr = gdk_cairo_create(gdkDrawable); _ctx = gdk_cairo_create(gdkDrawable);
cairo_t* cr = gdk_cairo_create(gdkDrawable);
const Gtk::Allocation& allocation = get_allocation(); const Gtk::Allocation& allocation = get_allocation();
int width = allocation.get_width(); int width = allocation.get_width();
int height = allocation.get_height(); int height = allocation.get_height();
// Already clip, so that paint hasn't to care about it: // Clip to redraw only the smallest possible area
if(event) if(event)
{ {
cairo_rectangle(cr, event->area.x, event->area.y, cairo_rectangle(cr, event->area.x, event->area.y,
@ -86,35 +104,17 @@ SchedulablesWidget::on_expose_event(GdkEventExpose* event)
cairo_clip(cr); cairo_clip(cr);
} }
// NOTE: just to try:
// should be calculated dinamically: // should be calculated dinamically:
set_size_request(200,400); set_size_request(200,400);
// Copy from buffer to video
// if(_ctx != NULL)
// gdk_draw_drawable(buffer, GC??, gdkDrawable, ...clip-region...);
// Height should be calculated dynamically? // Height should be calculated dynamically?
cairo_scale(cr, width, width); cairo_scale(cr, width, width);
cairo_set_line_width(cr, 0.02);
cairo_set_source_rgba(cr, 0, 0, 0, 1);
// Draw initial sphere perimeter
float r = 1.f, g = 0.f, b = 0.f;
double x = .5, y = .5, radius = .5;
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);
cairo_destroy(cr); cairo_destroy(cr);
return true; return true;
} }