- increased separation between CairoWidget and SimulationWidget
- CairoWidget doesn't extend more History Observer - Modified scaling in CairoWidget - NOTE: this is a partial update; total update will follow soon - added File save/file open in GuiBuilder git-svn-id: svn://svn.gna.org/svn/sgpemv2/trunk@903 3ecf2c5c-341e-0410-92b4-d18e462d057c
This commit is contained in:
parent
5432693169
commit
69c098b266
|
@ -18,11 +18,21 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
the widget's event sequence...
|
||||||
|
|
||||||
|
on_size_request, requisition->width : 0, requisition->height : 0
|
||||||
|
on_realize, alloc.get_width() : 673, alloc.get_height() : 485
|
||||||
|
on_expose_event START... on_expose_event CONTINUE.
|
||||||
|
on_size_request, requisition->width : 120, requisition->height : 120
|
||||||
|
on_expose_event START... on_expose_event CONTINUE.
|
||||||
|
on_expose_event START... on_expose_event CONTINUE.
|
||||||
|
et cetera...
|
||||||
|
*/
|
||||||
#include "cairo_elements.hh"
|
#include "cairo_elements.hh"
|
||||||
#include "cairo_widget.hh"
|
#include "cairo_widget.hh"
|
||||||
|
|
||||||
#include "backend/history.hh"
|
|
||||||
#include "backend/simulation.hh"
|
|
||||||
|
|
||||||
#include <gdkmm/window.h>
|
#include <gdkmm/window.h>
|
||||||
|
|
||||||
|
@ -35,58 +45,66 @@ using namespace sgpem;
|
||||||
|
|
||||||
CairoWidget::CairoWidget()
|
CairoWidget::CairoWidget()
|
||||||
: Glib::ObjectBase("sgpem_CairoWidget"),
|
: Glib::ObjectBase("sgpem_CairoWidget"),
|
||||||
Gtk::Widget(), _w(1), _h(1), _buf(NULL)
|
Gtk::Widget(), _draw_w(1), _draw_h(1), _buf(NULL),
|
||||||
|
_client_w(0), _client_h(0), _pixmap_w(0), _pixmap_h(0),
|
||||||
|
_need_redraw(true), _scaling_mode(scaling_none)
|
||||||
{
|
{
|
||||||
set_flags(Gtk::NO_WINDOW);
|
set_flags(Gtk::NO_WINDOW);
|
||||||
// Register this observer:
|
|
||||||
Simulation::get_instance().get_history().attach(*this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CairoWidget::~CairoWidget()
|
CairoWidget::~CairoWidget()
|
||||||
{
|
{
|
||||||
Simulation::get_instance().get_history().detach(*this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CairoWidget::scaling_mode
|
||||||
void
|
CairoWidget::set_scaling_mode(CairoWidget::scaling_mode scaling)
|
||||||
CairoWidget::update(const History& history)
|
|
||||||
{
|
{
|
||||||
// get_window() returns a null pointer
|
CairoWidget::scaling_mode old_scaling = _scaling_mode;
|
||||||
// if the widget has not been realized
|
_scaling_mode = scaling;
|
||||||
if (!is_realized())
|
/*
|
||||||
return; // Nowhere to draw to.
|
if(_scaling_mode==scaling_none)
|
||||||
|
set_size_request(_draw_w, _draw_h);
|
||||||
|
else
|
||||||
|
set_size_request(_client_w, _client_h);
|
||||||
|
*/
|
||||||
|
|
||||||
// Determine the final height before to start drawing
|
switch(_scaling_mode)
|
||||||
calc_size(history, _w, _h);
|
{
|
||||||
|
case scaling_none:
|
||||||
|
set_size_request(100, 100);
|
||||||
|
break;
|
||||||
|
case scaling_to_w:
|
||||||
|
set_size_request(150, 150);
|
||||||
|
break;
|
||||||
|
case scaling_to_h:
|
||||||
|
set_size_request(200, 200);
|
||||||
|
break;
|
||||||
|
case scaling_min:
|
||||||
|
set_size_request(250, 250);
|
||||||
|
break;
|
||||||
|
case scaling_max:
|
||||||
|
set_size_request(300, 300);
|
||||||
|
break;
|
||||||
|
case scaling_all:
|
||||||
|
set_size_request(350, 350);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
_buf = Gdk::Pixmap::create(get_window(), _w, _h);
|
return old_scaling;
|
||||||
|
}
|
||||||
|
|
||||||
// Draw the widget background as the first thing.
|
CairoWidget::scaling_mode
|
||||||
// I've seen this is how it's done in the very Gtk+ toolkit
|
CairoWidget::get_scaling_mode()
|
||||||
// for the GtkProgressBar widget.
|
{
|
||||||
GtkStyle* gStyle = get_style()->gobj();
|
return _scaling_mode;
|
||||||
gtk_paint_box(gStyle, _buf->gobj(),
|
|
||||||
GTK_STATE_NORMAL, GTK_SHADOW_ETCHED_IN,
|
|
||||||
NULL, this->gobj(), "through",
|
|
||||||
0, 0, _w, _h);
|
|
||||||
|
|
||||||
cairo_t* ctx = gdk_cairo_create(_buf->gobj());
|
|
||||||
|
|
||||||
// do the drawing...
|
|
||||||
std::cout << " Dimensions, w : " << _w << ", h : " << _h << std::endl;
|
|
||||||
cairo_scale(ctx, _w, _h);
|
|
||||||
draw_widget(ctx);
|
|
||||||
cairo_destroy(ctx);
|
|
||||||
|
|
||||||
// Force redraw
|
|
||||||
queue_draw();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
CairoWidget::on_realize()
|
CairoWidget::on_realize()
|
||||||
{
|
{
|
||||||
|
std::cout << " on_realize" << std::endl;
|
||||||
if (is_realized()) return;
|
if (is_realized()) return;
|
||||||
|
|
||||||
Gtk::Widget::on_realize();
|
Gtk::Widget::on_realize();
|
||||||
|
@ -106,7 +124,12 @@ CairoWidget::on_realize()
|
||||||
attributes.window_type = GDK_WINDOW_CHILD;
|
attributes.window_type = GDK_WINDOW_CHILD;
|
||||||
attributes.visual = get_visual()->gobj();
|
attributes.visual = get_visual()->gobj();
|
||||||
attributes.colormap = get_colormap()->gobj();
|
attributes.colormap = get_colormap()->gobj();
|
||||||
|
|
||||||
|
_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
|
static const gint attributes_mask = Gdk::WA_X | Gdk::WA_Y | Gdk::WA_WMCLASS
|
||||||
| Gdk::WA_VISUAL | Gdk::WA_COLORMAP;
|
| Gdk::WA_VISUAL | Gdk::WA_COLORMAP;
|
||||||
|
|
||||||
|
@ -127,32 +150,127 @@ CairoWidget::on_realize()
|
||||||
void
|
void
|
||||||
CairoWidget::on_size_allocate(const Gtk::Allocation& allocation)
|
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);
|
set_allocation(allocation);
|
||||||
|
|
||||||
if (is_realized())
|
if (is_realized())
|
||||||
|
{
|
||||||
get_window()->move_resize(allocation.get_x(), allocation.get_y(),
|
get_window()->move_resize(allocation.get_x(), allocation.get_y(),
|
||||||
allocation.get_width(), allocation.get_height());
|
allocation.get_width(), allocation.get_height());
|
||||||
}
|
_client_w = allocation.get_width();
|
||||||
|
_client_h = allocation.get_height();
|
||||||
|
_need_redraw = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CairoWidget::on_size_request(Gtk::Requisition* requisition)
|
CairoWidget::on_size_request(Gtk::Requisition* requisition)
|
||||||
{
|
{
|
||||||
*requisition = Gtk::Requisition();
|
// Gtk+ asks the desired widget dimension
|
||||||
|
|
||||||
requisition->width = _w;
|
std::cout << " on_size_request, requisition->width : " << requisition->width << ", requisition->height : " << requisition->height << std::endl;
|
||||||
requisition->height = _h;
|
// the response is - what allocated before...
|
||||||
|
/*
|
||||||
|
switch(_scaling_mode)
|
||||||
|
{
|
||||||
|
case scaling_none:
|
||||||
|
*requisition = Gtk::Requisition();
|
||||||
|
requisition->width = _draw_w;
|
||||||
|
requisition->height = _draw_h;
|
||||||
|
break;
|
||||||
|
case scaling_to_w:
|
||||||
|
case scaling_to_h:
|
||||||
|
case scaling_min:
|
||||||
|
case scaling_max:
|
||||||
|
case scaling_all:
|
||||||
|
Glib::RefPtr<Gdk::Window>parent_w = get_parent_window();
|
||||||
|
if(parent_w)
|
||||||
|
{
|
||||||
|
int w, h;
|
||||||
|
parent_w->get_size(w, h);
|
||||||
|
requisition->width = w;
|
||||||
|
requisition->height = h;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
CairoWidget::on_expose_event(GdkEventExpose* event)
|
CairoWidget::on_expose_event(GdkEventExpose* event)
|
||||||
{
|
{
|
||||||
|
std::cout << " on_expose_event START...";
|
||||||
if (event == NULL || event->count > 0)
|
if (event == NULL || event->count > 0)
|
||||||
return false;
|
return false;
|
||||||
|
std::cout << " on_expose_event CONTINUE." << std::endl;
|
||||||
|
|
||||||
|
if(_need_redraw)
|
||||||
|
{
|
||||||
|
_need_redraw = false;
|
||||||
|
if(_client_w>_pixmap_w || _client_h>_pixmap_h)
|
||||||
|
{
|
||||||
|
std::cout << " on_expose_event CREATE Pixmap." << std::endl;
|
||||||
|
_buf = Gdk::Pixmap::create(get_window(), _client_w, _client_h);
|
||||||
|
_pixmap_w = _client_w;
|
||||||
|
_pixmap_h = _client_h;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw the widget background as the first thing.
|
||||||
|
// 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, this->gobj(), "through",
|
||||||
|
0, 0, _client_w, _client_h);
|
||||||
|
|
||||||
|
cairo_t* ctx = gdk_cairo_create(_buf->gobj());
|
||||||
|
|
||||||
|
// Determine the final drawing dimensions before to start drawing
|
||||||
|
calc_size(_draw_w, _draw_h);
|
||||||
|
// do the drawing...
|
||||||
|
if(_scaling_mode!=scaling_none && _draw_w>0 && _draw_h>0)
|
||||||
|
{
|
||||||
|
double sx = (double)_client_w/(double)_draw_w;
|
||||||
|
double sy = (double)_client_h/(double)_draw_h;
|
||||||
|
switch(_scaling_mode)
|
||||||
|
{
|
||||||
|
case scaling_none:
|
||||||
|
sx = sy = 1.0;
|
||||||
|
break;
|
||||||
|
case scaling_to_w:
|
||||||
|
sy = sx;
|
||||||
|
break;
|
||||||
|
case scaling_to_h:
|
||||||
|
sx = sy;
|
||||||
|
break;
|
||||||
|
case scaling_min:
|
||||||
|
if(sx<=sy)
|
||||||
|
sy = sx;
|
||||||
|
else
|
||||||
|
sx = sy;
|
||||||
|
break;
|
||||||
|
case scaling_max:
|
||||||
|
if(sx>=sy)
|
||||||
|
sy = sx;
|
||||||
|
else
|
||||||
|
sx = sy;
|
||||||
|
break;
|
||||||
|
case scaling_all:
|
||||||
|
// nothing to do...
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cairo_scale(ctx, sx, sy);
|
||||||
|
}
|
||||||
|
std::cout << " on_expose_event Dimensions, w : " << _draw_w << ", h : " << _draw_h << std::endl;
|
||||||
|
draw_widget(ctx);
|
||||||
|
cairo_destroy(ctx);
|
||||||
|
}
|
||||||
// calculated dinamically on update():
|
// calculated dinamically on update():
|
||||||
set_size_request(_w, _h);
|
// set_size_request(_draw_w, _draw_h);
|
||||||
|
|
||||||
// Clip to redraw only the smallest possible area
|
// Clip to redraw only the smallest possible area
|
||||||
// Use double buffering or we're CPU-dead
|
// Use double buffering or we're CPU-dead
|
||||||
|
@ -166,11 +284,59 @@ CairoWidget::on_expose_event(GdkEventExpose* event)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
CairoWidget::on_button_press_event(GdkEventButton* event)
|
CairoWidget::on_button_press_event(GdkEventButton* event)
|
||||||
{
|
{
|
||||||
|
std::cout << " on_button_press_event " << std::endl;
|
||||||
|
change_scaling_mode();
|
||||||
// Not here. Yet.
|
// Not here. Yet.
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CairoWidget::redraw()
|
||||||
|
{
|
||||||
|
// Force redraw
|
||||||
|
_need_redraw = true;
|
||||||
|
queue_draw();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CairoWidget::change_scaling_mode()
|
||||||
|
{
|
||||||
|
|
||||||
|
std::cout << " change_scaling_mode " << std::endl;
|
||||||
|
switch(_scaling_mode)
|
||||||
|
{
|
||||||
|
case scaling_none:
|
||||||
|
set_scaling_mode(scaling_to_w);
|
||||||
|
break;
|
||||||
|
case scaling_to_w:
|
||||||
|
case scaling_to_h:
|
||||||
|
case scaling_min:
|
||||||
|
case scaling_max:
|
||||||
|
set_scaling_mode((scaling_mode)(_scaling_mode << 1));
|
||||||
|
break;
|
||||||
|
case scaling_all:
|
||||||
|
set_scaling_mode(scaling_none);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
redraw();
|
||||||
|
/* switch(_scaling_mode)
|
||||||
|
{
|
||||||
|
case scaling_none:
|
||||||
|
_scaling_mode = scaling_to_w;
|
||||||
|
break;
|
||||||
|
case scaling_to_w:
|
||||||
|
case scaling_to_h:
|
||||||
|
case scaling_min:
|
||||||
|
case scaling_max:
|
||||||
|
_scaling_mode = (scaling_mode)(_scaling_mode << 1);
|
||||||
|
break;
|
||||||
|
case scaling_all:
|
||||||
|
_scaling_mode = scaling_none;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
redraw();
|
||||||
|
*/
|
||||||
|
}
|
|
@ -23,21 +23,30 @@
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include "backend/history_observer.hh"
|
|
||||||
|
|
||||||
#include <cairo.h>
|
#include <cairo.h>
|
||||||
#include <gtkmm/widget.h>
|
#include <gtkmm/widget.h>
|
||||||
#include <gdkmm/pixmap.h>
|
#include <gdkmm/pixmap.h>
|
||||||
|
|
||||||
namespace sgpem
|
namespace sgpem
|
||||||
{
|
{
|
||||||
class CairoWidget : public Gtk::Widget, public HistoryObserver
|
class CairoWidget : public Gtk::Widget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
enum scaling_mode
|
||||||
|
{
|
||||||
|
scaling_none = 0, // without any scaling
|
||||||
|
scaling_to_w = 1 << 0, // uses width to calculate scale factor
|
||||||
|
scaling_to_h = 1 << 1, // uses height to calculate scale factor
|
||||||
|
scaling_min = 1 << 2, // uses minimum scale factor from width, height
|
||||||
|
scaling_max = 1 << 3, // uses maximum scale factor from width, height
|
||||||
|
scaling_all = 1 << 4 // scale to stretch into client area
|
||||||
|
};
|
||||||
|
|
||||||
CairoWidget();
|
CairoWidget();
|
||||||
virtual ~CairoWidget();
|
virtual ~CairoWidget();
|
||||||
|
scaling_mode set_scaling_mode(scaling_mode scaling_mode);
|
||||||
void update(const History& history);
|
scaling_mode get_scaling_mode();
|
||||||
|
void change_scaling_mode();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
typedef unsigned int size_t;
|
typedef unsigned int size_t;
|
||||||
|
@ -47,8 +56,14 @@ namespace sgpem
|
||||||
virtual void on_size_request(Gtk::Requisition* request);
|
virtual void on_size_request(Gtk::Requisition* request);
|
||||||
virtual bool on_expose_event(GdkEventExpose* event);
|
virtual bool on_expose_event(GdkEventExpose* event);
|
||||||
virtual bool on_button_press_event(GdkEventButton* event);
|
virtual bool on_button_press_event(GdkEventButton* event);
|
||||||
|
|
||||||
|
// in this method the implemented widget must "do the things"
|
||||||
virtual void draw_widget(cairo_t* ctx) = 0;
|
virtual void draw_widget(cairo_t* ctx) = 0;
|
||||||
virtual void calc_size(const History& history, size_t& width, size_t& height) const = 0;
|
|
||||||
|
// with this method CairoWidget the needed drawing dimensions
|
||||||
|
virtual void calc_size(size_t& width, size_t& height) const = 0;
|
||||||
|
|
||||||
|
void redraw();
|
||||||
|
|
||||||
typedef Gdk::Rectangle area_t;
|
typedef Gdk::Rectangle area_t;
|
||||||
typedef sigc::mem_functor0<void, CairoWidget> method0_t;
|
typedef sigc::mem_functor0<void, CairoWidget> method0_t;
|
||||||
|
@ -58,8 +73,15 @@ namespace sgpem
|
||||||
private:
|
private:
|
||||||
// The width and height the widget will assume, must be determined
|
// The width and height the widget will assume, must be determined
|
||||||
// before starting drawing by calc_size()
|
// before starting drawing by calc_size()
|
||||||
mutable size_t _w;
|
mutable size_t _draw_w;
|
||||||
mutable size_t _h;
|
mutable size_t _draw_h;
|
||||||
|
mutable size_t _client_w;
|
||||||
|
mutable size_t _client_h;
|
||||||
|
mutable size_t _pixmap_w;
|
||||||
|
mutable size_t _pixmap_h;
|
||||||
|
|
||||||
|
mutable bool _need_redraw;
|
||||||
|
scaling_mode _scaling_mode;
|
||||||
|
|
||||||
// The offscreen pixmap we use for double-buffering
|
// The offscreen pixmap we use for double-buffering
|
||||||
Glib::RefPtr<Gdk::Pixmap> _buf;
|
Glib::RefPtr<Gdk::Pixmap> _buf;
|
||||||
|
|
|
@ -30,12 +30,18 @@
|
||||||
#include "backend/history.hh"
|
#include "backend/history.hh"
|
||||||
#include "backend/simulation.hh"
|
#include "backend/simulation.hh"
|
||||||
|
|
||||||
|
#include "backend/serializers_gatekeeper.hh"
|
||||||
|
#include "backend/serializer.hh"
|
||||||
|
|
||||||
#include <glibmm/ustring.h>
|
#include <glibmm/ustring.h>
|
||||||
#include <gtkmm/aboutdialog.h>
|
#include <gtkmm/aboutdialog.h>
|
||||||
|
#include <gtkmm/messagedialog.h>
|
||||||
|
#include <gtkmm/filechooserdialog.h>
|
||||||
#include <gtkmm/expander.h>
|
#include <gtkmm/expander.h>
|
||||||
#include <gtkmm/main.h>
|
#include <gtkmm/main.h>
|
||||||
#include <gtkmm/menuitem.h>
|
#include <gtkmm/menuitem.h>
|
||||||
#include <gtkmm/scrolledwindow.h>
|
#include <gtkmm/scrolledwindow.h>
|
||||||
|
#include <gtkmm/stock.h>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
@ -46,8 +52,10 @@ void
|
||||||
test_me()
|
test_me()
|
||||||
{
|
{
|
||||||
// A test for widget display:
|
// A test for widget display:
|
||||||
|
|
||||||
Simulation& sim = Simulation::get_instance();
|
Simulation& sim = Simulation::get_instance();
|
||||||
sim.get_history().add_process("goofy", 0, 0);
|
sim.get_history().add_process("goofy", 0, 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -56,6 +64,133 @@ GuiBuilder::on_edit_preferences_activate()
|
||||||
new PreferencesEditor(); //FIXME: are we leaking this way?
|
new PreferencesEditor(); //FIXME: are we leaking this way?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GuiBuilder::on_file_open_activate()
|
||||||
|
{
|
||||||
|
Glib::ustring msg;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
std::vector<Serializer*> serializers =
|
||||||
|
SerializersGatekeeper::get_instance().get_registered();
|
||||||
|
|
||||||
|
// FIXME using the first serializer available, this
|
||||||
|
// will need to be changed when multiple serializers will
|
||||||
|
// be made available
|
||||||
|
Serializer& serializer = *serializers.at(0);
|
||||||
|
History& history = Simulation::get_instance().get_history();
|
||||||
|
|
||||||
|
// open file dialog...
|
||||||
|
Gtk::FileChooserDialog dialog("Please choose a file", Gtk::FILE_CHOOSER_ACTION_OPEN);
|
||||||
|
dialog.set_transient_for(get_initial_window());
|
||||||
|
|
||||||
|
//Add response buttons the the dialog:
|
||||||
|
dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
|
||||||
|
dialog.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK);
|
||||||
|
|
||||||
|
//Add filters, so that only certain file types can be selected:
|
||||||
|
for(std::vector<Serializer*>::const_iterator iter=serializers.begin(); iter!=serializers.end(); iter++)
|
||||||
|
{
|
||||||
|
Serializer* ser = *iter;
|
||||||
|
Gtk::FileFilter filter_sgpem;
|
||||||
|
filter_sgpem.set_name(ser->get_filename_description());
|
||||||
|
filter_sgpem.add_pattern(ser->get_filename_extension());
|
||||||
|
dialog.add_filter(filter_sgpem);
|
||||||
|
}
|
||||||
|
|
||||||
|
Gtk::FileFilter filter_any;
|
||||||
|
filter_any.set_name("Any files");
|
||||||
|
filter_any.add_pattern("*");
|
||||||
|
dialog.add_filter(filter_any);
|
||||||
|
|
||||||
|
//Show the dialog and wait for a user response:
|
||||||
|
int result = dialog.run();
|
||||||
|
if(result==Gtk::RESPONSE_OK)
|
||||||
|
{
|
||||||
|
// DISABLED - Actually locks computer
|
||||||
|
// serializer.restore_snapshot("prova1.xgp", history);
|
||||||
|
msg = "File: " + dialog.get_filename() + " loaded.";
|
||||||
|
} // end - if(result==Gtk::RESPONSE_OK)
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (std::out_of_range e)
|
||||||
|
{
|
||||||
|
msg = _("ERROR: No registered serializer available");
|
||||||
|
}
|
||||||
|
catch (SerializerError e)
|
||||||
|
{
|
||||||
|
msg = _("ERROR: ") + Glib::ustring(e.what());
|
||||||
|
}
|
||||||
|
if(!msg.empty())
|
||||||
|
{
|
||||||
|
Gtk::MessageDialog msg_dialog(get_initial_window(), msg);
|
||||||
|
msg_dialog.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GuiBuilder::on_file_save_activate()
|
||||||
|
{
|
||||||
|
_simulation_widget->change_scaling_mode();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GuiBuilder::on_file_saveas_activate()
|
||||||
|
{
|
||||||
|
Glib::ustring msg;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
std::vector<Serializer*> serializers =
|
||||||
|
SerializersGatekeeper::get_instance().get_registered();
|
||||||
|
|
||||||
|
// FIXME using the first serializer available, this
|
||||||
|
// will need to be changed when multiple serializers will
|
||||||
|
// be made available
|
||||||
|
Serializer& serializer = *serializers.at(0);
|
||||||
|
History& history = Simulation::get_instance().get_history();
|
||||||
|
|
||||||
|
// open file dialog...
|
||||||
|
Gtk::FileChooserDialog dialog("Please choose a file", Gtk::FILE_CHOOSER_ACTION_SAVE);
|
||||||
|
dialog.set_transient_for(get_initial_window());
|
||||||
|
|
||||||
|
//Add response buttons the the dialog:
|
||||||
|
dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
|
||||||
|
dialog.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK);
|
||||||
|
|
||||||
|
//Add filters, so that only certain file types can be selected:
|
||||||
|
Gtk::FileFilter filter_sgpem;
|
||||||
|
filter_sgpem.set_name("Sgpem files");
|
||||||
|
filter_sgpem.add_pattern("*.xgp");
|
||||||
|
dialog.add_filter(filter_sgpem);
|
||||||
|
|
||||||
|
Gtk::FileFilter filter_any;
|
||||||
|
filter_any.set_name("Any files");
|
||||||
|
filter_any.add_pattern("*");
|
||||||
|
dialog.add_filter(filter_any);
|
||||||
|
|
||||||
|
//Show the dialog and wait for a user response:
|
||||||
|
int result = dialog.run();
|
||||||
|
if(result==Gtk::RESPONSE_OK)
|
||||||
|
{
|
||||||
|
// DISABLED - Actually locks computer
|
||||||
|
serializer.save_snapshot(dialog.get_filename(), history);
|
||||||
|
msg = "File: " + dialog.get_filename() + " saved.";
|
||||||
|
} // end - if(result==Gtk::RESPONSE_OK)
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (std::out_of_range e)
|
||||||
|
{
|
||||||
|
msg = _("ERROR: No registered serializer available");
|
||||||
|
}
|
||||||
|
catch (SerializerError e)
|
||||||
|
{
|
||||||
|
msg = _("ERROR: ") + Glib::ustring(e.what());
|
||||||
|
}
|
||||||
|
if(!msg.empty())
|
||||||
|
{
|
||||||
|
Gtk::MessageDialog msg_dialog(get_initial_window(), msg);
|
||||||
|
msg_dialog.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
GuiBuilder::GuiBuilder(const std::string& gladefile)
|
GuiBuilder::GuiBuilder(const std::string& gladefile)
|
||||||
: _refXml(Xml::create(gladefile))
|
: _refXml(Xml::create(gladefile))
|
||||||
|
@ -64,6 +199,21 @@ GuiBuilder::GuiBuilder(const std::string& gladefile)
|
||||||
|
|
||||||
//Window& main_window = get_initial_window();
|
//Window& main_window = get_initial_window();
|
||||||
|
|
||||||
|
// file open dialog
|
||||||
|
MenuItem* file_open = NULL;
|
||||||
|
_refXml->get_widget("MenuItem.File.Open", file_open);
|
||||||
|
file_open->signal_activate().connect(sigc::mem_fun(*this, &GuiBuilder::on_file_open_activate));
|
||||||
|
|
||||||
|
// file save dialog
|
||||||
|
MenuItem* file_save = NULL;
|
||||||
|
_refXml->get_widget("MenuItem.File.Save", file_save);
|
||||||
|
file_save->signal_activate().connect(sigc::mem_fun(*this, &GuiBuilder::on_file_save_activate));
|
||||||
|
|
||||||
|
// file save dialog
|
||||||
|
MenuItem* file_saveas = NULL;
|
||||||
|
_refXml->get_widget("MenuItem.File.SaveAs", file_saveas);
|
||||||
|
file_saveas->signal_activate().connect(sigc::mem_fun(*this, &GuiBuilder::on_file_saveas_activate));
|
||||||
|
|
||||||
// Connect extra signals (decide where to do this...
|
// Connect extra signals (decide where to do this...
|
||||||
// here -- ugly -- derive widgets and then use
|
// here -- ugly -- derive widgets and then use
|
||||||
// Glade::Xml::get_widget_derived -- better --)
|
// Glade::Xml::get_widget_derived -- better --)
|
||||||
|
@ -110,7 +260,8 @@ GuiBuilder::GuiBuilder(const std::string& gladefile)
|
||||||
// Main simulation widget
|
// Main simulation widget
|
||||||
ScrolledWindow* simulation_window = NULL;
|
ScrolledWindow* simulation_window = NULL;
|
||||||
_refXml->get_widget("SimulationScrolledWindow", simulation_window);
|
_refXml->get_widget("SimulationScrolledWindow", simulation_window);
|
||||||
SimulationWidget* simulation_widget = manage(new SimulationWidget());
|
_simulation_widget = new SimulationWidget();
|
||||||
|
SimulationWidget* simulation_widget = manage(_simulation_widget);
|
||||||
simulation_window->add(*simulation_widget);
|
simulation_window->add(*simulation_widget);
|
||||||
simulation_widget->show();
|
simulation_widget->show();
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#define GUI_BUILDER_HH 1
|
#define GUI_BUILDER_HH 1
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "simulation_widget.hh"
|
||||||
|
|
||||||
#include <gtkmm/window.h>
|
#include <gtkmm/window.h>
|
||||||
#include <libglademm/xml.h>
|
#include <libglademm/xml.h>
|
||||||
|
@ -43,9 +44,13 @@ namespace sgpem
|
||||||
Gtk::Window& get_initial_window() const;
|
Gtk::Window& get_initial_window() const;
|
||||||
void open_file(const std::string& filename);
|
void open_file(const std::string& filename);
|
||||||
void on_edit_preferences_activate();
|
void on_edit_preferences_activate();
|
||||||
|
void on_file_open_activate();
|
||||||
|
void on_file_save_activate();
|
||||||
|
void on_file_saveas_activate();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Glib::RefPtr<Gnome::Glade::Xml> _refXml;
|
Glib::RefPtr<Gnome::Glade::Xml> _refXml;
|
||||||
|
SimulationWidget* _simulation_widget;
|
||||||
};
|
};
|
||||||
|
|
||||||
} //~ namespace sgpem
|
} //~ namespace sgpem
|
||||||
|
|
|
@ -21,6 +21,9 @@
|
||||||
#include "simulation_widget.hh"
|
#include "simulation_widget.hh"
|
||||||
|
|
||||||
#include "cairo_elements.hh"
|
#include "cairo_elements.hh"
|
||||||
|
#include "backend/history.hh"
|
||||||
|
#include "backend/simulation.hh"
|
||||||
|
#include "backend/string_utils.hh"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
|
@ -32,30 +35,97 @@ using namespace sgpem;
|
||||||
|
|
||||||
|
|
||||||
SimulationWidget::SimulationWidget()
|
SimulationWidget::SimulationWidget()
|
||||||
: Glib::ObjectBase("sgpem_SimulationWidget"), CairoWidget()
|
: Glib::ObjectBase("sgpem_SimulationWidget"), CairoWidget(),
|
||||||
{}
|
_n_update(0)
|
||||||
|
{
|
||||||
|
// Register this observer:
|
||||||
|
Simulation::get_instance().get_history().attach(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
SimulationWidget::~SimulationWidget()
|
SimulationWidget::~SimulationWidget()
|
||||||
{}
|
{
|
||||||
|
Simulation::get_instance().get_history().detach(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SimulationWidget::update(const History& history)
|
||||||
|
{
|
||||||
|
_n_update++;
|
||||||
|
std::cout << " update: " << _n_update << std::endl;
|
||||||
|
|
||||||
|
// Force redraw
|
||||||
|
redraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
SimulationWidget::draw_widget(cairo_t* ctx)
|
SimulationWidget::draw_widget(cairo_t* ctx)
|
||||||
{
|
{
|
||||||
|
cairo_set_source_rgb(ctx, 0, 0, 0);
|
||||||
|
cairo_move_to(ctx, 0, 0);
|
||||||
|
cairo_line_to(ctx, 300, 350);
|
||||||
|
cairo_stroke(ctx);
|
||||||
|
|
||||||
|
cairo_set_source_rgb(ctx, 0, 0, 0);
|
||||||
|
cairo_move_to(ctx, 0, 0);
|
||||||
|
cairo_line_to(ctx, 300, 350);
|
||||||
// NOTE: just to try
|
// NOTE: just to try
|
||||||
CairoElements ce(ctx);
|
CairoElements ce(ctx);
|
||||||
|
|
||||||
Rectangle area = { 0.3, 0.3, 1.0, 1.0 };
|
Rectangle area = { 30, 30, 100, 100 };
|
||||||
ce.draw_container(area);
|
ce.draw_container(area);
|
||||||
|
|
||||||
Color red = { 1, 0, 0 };
|
Color red = { 1, 0, 0 };
|
||||||
Point center = { 0.25, 0.25 };
|
Point center = { 25, 25 };
|
||||||
|
ce.draw_3dsphere(center, 20, red);
|
||||||
|
|
||||||
|
Glib::ustring msg("Number of updates: "), number;
|
||||||
|
int_to_string(_n_update, number);
|
||||||
|
msg = msg + number;
|
||||||
|
cairo_move_to(ctx, 10, 105);
|
||||||
|
cairo_show_text(ctx,msg.c_str());
|
||||||
|
|
||||||
|
switch(get_scaling_mode())
|
||||||
|
{
|
||||||
|
case CairoWidget::scaling_none:
|
||||||
|
msg = "scaling_none = without any scaling";
|
||||||
|
break;
|
||||||
|
case CairoWidget::scaling_to_w:
|
||||||
|
msg = "scaling_to_w = uses width to calculate scale factor";
|
||||||
|
break;
|
||||||
|
case CairoWidget::scaling_to_h:
|
||||||
|
msg = "scaling_to_h = uses height to calculate scale factor";
|
||||||
|
break;
|
||||||
|
case CairoWidget::scaling_min:
|
||||||
|
msg = "scaling_min = uses minimum scale factor from width, height";
|
||||||
|
break;
|
||||||
|
case CairoWidget::scaling_max:
|
||||||
|
msg = "scaling_max = uses maximum scale factor from width, height";
|
||||||
|
break;
|
||||||
|
case CairoWidget::scaling_all:
|
||||||
|
msg = "scaling_all = scale to stretch into client area";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cairo_move_to(ctx, 10, 115);
|
||||||
|
cairo_show_text(ctx,msg.c_str());
|
||||||
|
msg = "clic to change mode...";
|
||||||
|
cairo_move_to(ctx, 10, 125);
|
||||||
|
cairo_show_text(ctx,msg.c_str());
|
||||||
|
|
||||||
ce.draw_3dsphere(center, 0.20, red);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
SimulationWidget::calc_size(size_t& width, size_t& height) const
|
||||||
|
{
|
||||||
|
// FIXME: write me
|
||||||
|
// some magic here!
|
||||||
|
width = 300;
|
||||||
|
height = 350;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
void
|
void
|
||||||
SimulationWidget::calc_size(const History& history, size_t& width, size_t& height) const
|
SimulationWidget::calc_size(const History& history, size_t& width, size_t& height) const
|
||||||
{
|
{
|
||||||
|
@ -63,12 +133,5 @@ SimulationWidget::calc_size(const History& history, size_t& width, size_t& heigh
|
||||||
width = get_allocation().get_width();
|
width = get_allocation().get_width();
|
||||||
height = get_allocation().get_height();
|
height = get_allocation().get_height();
|
||||||
|
|
||||||
/*
|
|
||||||
#ifndef NDEBUG
|
|
||||||
using namespace std;
|
|
||||||
clog << " [DD] New allocation event on " << hex << this << ": "
|
|
||||||
<< dec << width << 'x' << height << endl;
|
|
||||||
#endif
|
|
||||||
*/
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
|
@ -24,18 +24,24 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include "cairo_widget.hh"
|
#include "cairo_widget.hh"
|
||||||
|
#include "backend/history_observer.hh"
|
||||||
|
|
||||||
namespace sgpem
|
namespace sgpem
|
||||||
{
|
{
|
||||||
class SimulationWidget : public CairoWidget
|
class SimulationWidget : public CairoWidget, public HistoryObserver
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SimulationWidget();
|
SimulationWidget();
|
||||||
virtual ~SimulationWidget();
|
virtual ~SimulationWidget();
|
||||||
|
void update(const History& history);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void draw_widget(cairo_t* ctx);
|
void draw_widget(cairo_t* ctx);
|
||||||
void calc_size(const History& history, size_t& width, size_t& height) const;
|
|
||||||
|
virtual void calc_size(size_t& width, size_t& height) const;
|
||||||
|
// void calc_size(const History& history, size_t& width, size_t& height) const;
|
||||||
|
private:
|
||||||
|
int _n_update;
|
||||||
};
|
};
|
||||||
|
|
||||||
} //~ namespace sgpem
|
} //~ namespace sgpem
|
||||||
|
|
Loading…
Reference in New Issue