23 #include "graph_drawing_area.h" 24 #include "gvplugin_skillgui_cairo.h" 39 add_events(Gdk::SCROLL_MASK | Gdk::BUTTON_MOTION_MASK);
46 __bbw = __bbh = __pad_x = __pad_y = 0.0;
47 __translation_x = __translation_y = 0.0;
49 __scale_override =
false;
50 __update_graph =
true;
53 gvplugin_skillgui_cairo_setup(__gvc,
this);
55 __fcd_save =
new Gtk::FileChooserDialog(
"Save Graph",
56 Gtk::FILE_CHOOSER_ACTION_SAVE);
57 __fcd_open =
new Gtk::FileChooserDialog(
"Load Graph",
58 Gtk::FILE_CHOOSER_ACTION_OPEN);
59 __fcd_recording =
new Gtk::FileChooserDialog(
"Recording Directory",
60 Gtk::FILE_CHOOSER_ACTION_CREATE_FOLDER);
63 __fcd_save->add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
64 __fcd_save->add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK);
65 __fcd_open->add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
66 __fcd_open->add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK);
67 __fcd_recording->add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
68 __fcd_recording->add_button(Gtk::Stock::OK, Gtk::RESPONSE_OK);
70 #if GTK_VERSION_GE(3,0) 71 __filter_pdf = Gtk::FileFilter::create();
72 __filter_svg = Gtk::FileFilter::create();
73 __filter_png = Gtk::FileFilter::create();
74 __filter_dot = Gtk::FileFilter::create();
76 __filter_pdf =
new Gtk::FileFilter();
77 __filter_svg =
new Gtk::FileFilter();
78 __filter_png =
new Gtk::FileFilter();
79 __filter_dot =
new Gtk::FileFilter();
81 __filter_pdf->set_name(
"Portable Document Format (PDF)");
82 __filter_pdf->add_pattern(
"*.pdf");
83 __filter_svg->set_name(
"Scalable Vector Graphic (SVG)");
84 __filter_svg->add_pattern(
"*.svg");
85 __filter_png->set_name(
"Portable Network Graphic (PNG)");
86 __filter_png->add_pattern(
"*.png");
87 __filter_dot->set_name(
"DOT Graph");
88 __filter_dot->add_pattern(
"*.dot");
89 #if GTK_VERSION_GE(3,0) 90 __fcd_save->add_filter(__filter_pdf);
91 __fcd_save->add_filter(__filter_svg);
92 __fcd_save->add_filter(__filter_png);
93 __fcd_save->add_filter(__filter_dot);
94 __fcd_save->set_filter(__filter_pdf);
96 __fcd_open->add_filter(__filter_dot);
97 __fcd_open->set_filter(__filter_dot);
99 __fcd_save->add_filter(*__filter_pdf);
100 __fcd_save->add_filter(*__filter_svg);
101 __fcd_save->add_filter(*__filter_png);
102 __fcd_save->add_filter(*__filter_dot);
103 __fcd_save->set_filter(*__filter_pdf);
105 __fcd_open->add_filter(*__filter_dot);
106 __fcd_open->set_filter(*__filter_dot);
109 add_events(Gdk::SCROLL_MASK | Gdk::BUTTON_MOTION_MASK |
110 Gdk::BUTTON_PRESS_MASK );
112 #if GTK_VERSION_LT(3,0) 119 SkillGuiGraphDrawingArea::~SkillGuiGraphDrawingArea()
121 gvFreeContext(__gvc);
125 delete __fcd_recording;
126 #if GTK_VERSION_GE(3,0) 127 __filter_pdf.reset();
128 __filter_svg.reset();
129 __filter_png.reset();
130 __filter_dot.reset();
146 return __signal_update_disabled;
156 if ( __update_graph ) {
157 if ( __graph_fsm != fsm_name ) {
158 __scale_override =
false;
160 __graph_fsm = fsm_name;
162 __nonupd_graph_fsm = fsm_name;
173 if ( __update_graph ) {
177 __nonupd_graph = graph;
182 #if defined(__MACH__) && defined(__APPLE__) 184 if (gettimeofday(&t, NULL) == 0) {
185 long int nsec = t.tv_usec * 1000;
188 if (clock_gettime(CLOCK_REALTIME, &t) == 0) {
189 long int nsec = t.tv_nsec;
192 localtime_r(&t.tv_sec, &tms);
194 if ( asprintf(&tmp,
"%s/%s_%04i%02i%02i-%02i%02i%02i.%09li.dot",
195 __record_directory.c_str(), __graph_fsm.c_str(),
196 tms.tm_year + 1900, tms.tm_mon + 1, tms.tm_mday,
197 tms.tm_hour, tms.tm_min, tms.tm_sec, nsec) != -1)
204 printf(
"Warning: Could not create file name for recording, skipping graph\n");
207 printf(
"Warning: Could not time recording, skipping graph\n");
246 if (__scale_override) {
263 __translation_x = tx;
264 __translation_y = ty;
295 tx = __translation_x;
296 ty = __translation_y;
307 Gtk::Allocation alloc = get_allocation();
308 width = alloc.get_width();
309 height = alloc.get_height();
319 Gtk::Allocation alloc = get_allocation();
321 __scale_override =
true;
322 __translation_x = (alloc.get_width() - __bbw * __scale) / 2.0;
323 __translation_y = (alloc.get_height() - __bbh * __scale) / 2.0 + __bbh * __scale;
333 __scale_override =
true;
334 if ( __scale > 0.1 ) {
335 Gtk::Allocation alloc = get_allocation();
337 __translation_x = (alloc.get_width() - __bbw * __scale) / 2.0;
338 __translation_y = (alloc.get_height() - __bbh * __scale) / 2.0 + __bbh * __scale;
350 __scale_override =
false;
361 Gtk::Allocation alloc = get_allocation();
363 __scale_override =
true;
364 __translation_x = (alloc.get_width() - __bbw) / 2.0 + __pad_x;
365 __translation_y = (alloc.get_height() - __bbh) / 2.0 + __bbh - __pad_y;
376 return __scale_override;
385 Cairo::RefPtr<Cairo::Context>
399 return __update_graph;
409 if (update && ! __update_graph) {
410 if ( __graph_fsm != __nonupd_graph_fsm ) {
411 __scale_override =
false;
413 __graph = __nonupd_graph;
414 __graph_fsm = __nonupd_graph_fsm;
417 __update_graph = update;
422 SkillGuiGraphDrawingArea::save_dotfile(
const char *filename)
424 FILE *f = fopen(filename,
"w");
426 if (fwrite(__graph.c_str(), __graph.length(), 1, f) != 1) {
428 printf(
"Failed to write dot file '%s'\n", filename);
445 Gtk::Window *w =
dynamic_cast<Gtk::Window *
>(get_toplevel());
446 __fcd_recording->set_transient_for(*w);
447 int result = __fcd_recording->run();
448 if (result == Gtk::RESPONSE_OK) {
449 __record_directory = __fcd_recording->get_filename();
452 __fcd_recording->hide();
464 Gtk::Window *w =
dynamic_cast<Gtk::Window *
>(get_toplevel());
465 __fcd_save->set_transient_for(*w);
467 int result = __fcd_save->run();
468 if (result == Gtk::RESPONSE_OK) {
470 #if GTK_VERSION_GE(3,0) 471 Glib::RefPtr<Gtk::FileFilter> f = __fcd_save->get_filter();
473 Gtk::FileFilter *f = __fcd_save->get_filter();
475 std::string filename = __fcd_save->get_filename();
476 if (filename !=
"") {
477 if (f == __filter_dot) {
478 save_dotfile(filename.c_str());
480 Cairo::RefPtr<Cairo::Surface> surface;
482 bool write_to_png =
false;
483 if (f == __filter_pdf) {
484 surface = Cairo::PdfSurface::create(filename, __bbw, __bbh);
485 }
else if (f == __filter_svg) {
486 surface = Cairo::SvgSurface::create(filename, __bbw, __bbh);
487 }
else if (f == __filter_png) {
488 surface = Cairo::ImageSurface::create(Cairo::FORMAT_ARGB32,
495 __cairo = Cairo::Context::create(surface);
497 bool old_scale_override = __scale_override;
498 double old_tx = __translation_x;
499 double old_ty = __translation_y;
500 double old_scale = __scale;
501 __translation_x = __pad_x;
502 __translation_y = __bbh - __pad_y;
504 __scale_override =
true;
506 Agraph_t *g = agmemread((
char *)__graph.c_str());
508 gvLayout(__gvc, g, (
char *)
"dot");
509 gvRender(__gvc, g, (
char *)
"skillguicairo", NULL);
510 gvFreeLayout(__gvc, g);
515 surface->write_to_png(filename);
520 __translation_x = old_tx;
521 __translation_y = old_ty;
523 __scale_override = old_scale_override;
528 Gtk::MessageDialog md(*w,
"Invalid filename",
529 false, Gtk::MESSAGE_ERROR,
530 Gtk::BUTTONS_OK,
true);
531 md.set_title(
"Invalid File Name");
544 Gtk::Window *w =
dynamic_cast<Gtk::Window *
>(get_toplevel());
545 __fcd_open->set_transient_for(*w);
547 int result = __fcd_open->run();
548 if (result == Gtk::RESPONSE_OK) {
549 __update_graph =
false;
551 char *basec = strdup(__fcd_open->get_filename().c_str());
552 char *basen = basename(basec);
556 FILE *f = fopen(__fcd_open->get_filename().c_str(),
"r");
560 if ((s = fread(tmp, 1, 4096, f)) > 0) {
561 __graph.append(tmp, s);
565 __signal_update_disabled.emit();
573 #if GTK_VERSION_GE(3,0) 579 SkillGuiGraphDrawingArea::on_draw(
const Cairo::RefPtr<Cairo::Context> &cr)
590 Glib::RefPtr<Gdk::Window> window = get_window();
600 #if GTK_VERSION_LT(3,0) 601 __cairo = window->create_cairo_context();
605 __cairo->set_source_rgb(1, 1, 1);
608 Agraph_t *g = agmemread((
char *)__graph.c_str());
610 gvLayout(__gvc, g, (
char *)
"dot");
611 gvRender(__gvc, g, (
char *)
"skillguicairo", NULL);
612 gvFreeLayout(__gvc, g);
629 if (event->direction == GDK_SCROLL_UP) {
631 }
else if (event->direction == GDK_SCROLL_DOWN) {
645 __last_mouse_x =
event->x;
646 __last_mouse_y =
event->y;
658 __scale_override =
true;
659 __translation_x -= __last_mouse_x -
event->x;
660 __translation_y -= __last_mouse_y -
event->y;
661 __last_mouse_x =
event->x;
662 __last_mouse_y =
event->y;
void set_graph(std::string graph)
Set graph.
virtual bool on_scroll_event(GdkEventScroll *event)
Scroll event handler.
bool set_recording(bool recording)
Enable/disable recording.
sigc::signal< void > signal_update_disabled()
Get "update disabled" signal.
SkillGuiGraphDrawingArea()
Constructor.
double get_scale()
Get scale.
bool get_update_graph()
Check if graph is being updated.
void set_graph_fsm(std::string fsm_name)
Set graph's FSM name.
virtual bool on_expose_event(GdkEventExpose *event)
Expose event handler.
Cairo::RefPtr< Cairo::Context > get_cairo()
Get Cairo context.
virtual bool on_motion_notify_event(GdkEventMotion *event)
Mouse motion notify event handler.
void zoom_fit()
Zoom to fit.
void zoom_reset()
Zoom reset.
bool scale_override()
Check if scale override is enabled.
void save()
save current graph.
void get_translation(double &tx, double &ty)
Get translation.
void set_update_graph(bool update)
Set if the graph should be updated on new data.
void get_dimensions(double &width, double &height)
Get dimensions.
void set_pad(double pad_x, double pad_y)
Set padding.
void get_pad(double &pad_x, double &pad_y)
Get padding.
void set_translation(double tx, double ty)
Set translation.
void set_bb(double bbw, double bbh)
Set bounding box.
void open()
Open a dot graph and display it.
virtual bool on_button_press_event(GdkEventButton *event)
Button press event handler.
void set_scale(double scale)
Set scale.