diff --git a/src/gui_builder.cc b/src/gui_builder.cc index 1461414..d6fc9b7 100644 --- a/src/gui_builder.cc +++ b/src/gui_builder.cc @@ -24,6 +24,9 @@ #include "schedulables_widget.hh" #include "gui_builder.hh" +#include "backend/history.hh" +#include "backend/simulation.hh" + #include #include #include @@ -64,6 +67,10 @@ GuiBuilder::GuiBuilder(const std::string& gladefile) scheds_expander->add(*scheds_widget); // we have to remember to manually show custom added widgets: scheds_widget->show(); + + // A test for widget display: + Simulation& sim = Simulation::get_instance(); + sim.get_history().add_process("goofy", 0, 0); } diff --git a/src/schedulables_widget.cc b/src/schedulables_widget.cc index 72438a8..81b58d2 100644 --- a/src/schedulables_widget.cc +++ b/src/schedulables_widget.cc @@ -21,45 +21,72 @@ #include "cairo_elements.hh" #include "schedulables_widget.hh" -#include +#include "backend/history.hh" +#include "backend/simulation.hh" + +#include +#include using namespace sgpem; SchedulablesWidget::SchedulablesWidget() - : Gtk::DrawingArea(), _ctx(NULL) + : Gtk::DrawingArea(), _h(1), _buf(NULL) { // Add other events we want to manage (as mouse clicks) // when needed add_events(Gdk::EXPOSURE_MASK); + + // Register this observer: + Simulation::get_instance().get_history().attach(*this); } SchedulablesWidget::~SchedulablesWidget() { - if(_ctx != NULL) - cairo_destroy(_ctx); + Simulation::get_instance().get_history().detach(*this); } void SchedulablesWidget::update(const History& history) { + // Determine the final height before to start drawing + unsigned int w = get_allocation().get_width(); + _h = calc_height(history); + // FIXME : write me using double buffering - // GdkPixmap* buffer = gdk_pixmap_new(...); - // _ctx = gdk_cairo_create(buffer); + // PROBLEM : get_window() seems to return a null pointer!!! + _buf = Gdk::Pixmap::create(get_window(), w, _h); + cairo_t* ctx = gdk_cairo_create(_buf->gobj()); // do the drawing... + draw_widget(ctx); + + cairo_scale(ctx, w, _h); + + // manually force an expose_event? + cairo_destroy(ctx); +} +void +SchedulablesWidget::draw_widget(cairo_t* ctx) +{ // NOTE: just to try - CairoElements ce(_ctx); + CairoElements ce(ctx); Color red = { 1, 0, 0 }; Point center = { 25, 25 }; - + ce.draw_3dsphere(center, 25, red); +} - // manually force an expose_event? + +unsigned int +SchedulablesWidget::calc_height(const History& history) const +{ + // FIXME: write me + return 400; } @@ -69,52 +96,37 @@ SchedulablesWidget::on_size_request(Gtk::Requisition* requisition) // FIXME: take correct measures, consider also using a viewport(?) *requisition = Gtk::Requisition(); requisition->width = get_allocation().get_width(); - requisition->height = requisition->width; + requisition->height = _h; } bool SchedulablesWidget::on_expose_event(GdkEventExpose* event) { - // Use double buffering or we're CPU-dead - Glib::RefPtr window = get_window(); - GdkWindow* gdkWindow = window->gobj(); - GdkDrawable* gdkDrawable; - gint xOffset, yOffset; - gdk_window_get_internal_paint_info(gdkWindow, &gdkDrawable, &xOffset, &yOffset); - - // Copy new ctx from old one (the buffer); from distant memories, - // we should use something like create_similar to instantiate a - // compatible surface and then copy the buffer to fg - // So the following two lines WILL HAVE TO CHANGE. - if(_ctx == NULL) - _ctx = gdk_cairo_create(gdkDrawable); - - cairo_t* cr = gdk_cairo_create(gdkDrawable); - const Gtk::Allocation& allocation = get_allocation(); int width = allocation.get_width(); int height = allocation.get_height(); // Clip to redraw only the smallest possible area - if(event) - { - cairo_rectangle(cr, event->area.x, event->area.y, - event->area.width, event->area.height); - cairo_clip(cr); - } - - // should be calculated dinamically: - set_size_request(200,400); + std::auto_ptr clip_area; + if(event) + clip_area = std::auto_ptr(new Gdk::Rectangle(event->area.x, event->area.y, + event->area.width, event->area.height)); - // Copy from buffer to video - // if(_ctx != NULL) - // gdk_draw_drawable(buffer, GC??, gdkDrawable, ...clip-region...); + else + clip_area = std::auto_ptr(new Gdk::Rectangle(0, 0, width, height)); - // Height should be calculated dynamically? - cairo_scale(cr, width, width); - - cairo_destroy(cr); + // Use double buffering or we're CPU-dead + // Copy from the buffer to the screen + if(_buf) + get_window()->draw_drawable(Gdk::GC::create(get_window()), _buf, + clip_area->get_x(), clip_area->get_y(), + clip_area->get_x(), clip_area->get_y(), + clip_area->get_width(), clip_area->get_height()); + + // calculated dinamically: + set_size_request(width, _h); + return true; } diff --git a/src/schedulables_widget.hh b/src/schedulables_widget.hh index 71244db..f3de0ec 100644 --- a/src/schedulables_widget.hh +++ b/src/schedulables_widget.hh @@ -25,7 +25,9 @@ #include "backend/history_observer.hh" +#include #include +#include namespace sgpem { @@ -41,6 +43,12 @@ namespace sgpem virtual void on_size_request(Gtk::Requisition* requisition); virtual bool on_expose_event(GdkEventExpose* event); virtual bool on_button_press_event(GdkEventButton* event); + virtual void draw_widget(cairo_t* ctx); + virtual unsigned int calc_height(const History& history) const; + + // The height the widget will assume, must be determined + // before starting drawing by calc_height(). + unsigned int _h; private: typedef Gdk::Rectangle area_t; @@ -48,7 +56,7 @@ namespace sgpem typedef std::pair area_callback_t; typedef std::vector areas_vect_t; - cairo_t* _ctx; + Glib::RefPtr _buf; }; } //~ namespace sgpem