00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "graph_viewport.h"
00024 #include "gvplugin_skillgui_papyrus.h"
00025
00026 #include <gtk/gtk.h>
00027
00028
00029
00030
00031
00032
00033
00034 SkillGuiGraphViewport::SkillGuiGraphViewport()
00035 {
00036 Cairo::RefPtr<Cairo::SolidPattern> bp = Cairo::SolidPattern::create_rgb(1, 1, 1);
00037 Papyrus::Paint::pointer pp = Papyrus::Paint::create(bp);
00038
00039 Papyrus::Canvas::pointer c = canvas();
00040 c->set_scroll_anchor(Papyrus::SCROLL_ANCHOR_TOP_LEFT);
00041 c->set_background(pp);
00042
00043 __affine = Papyrus::AffineController::create();
00044 __affine->insert(c);
00045 __translator = Papyrus::Translator::create();
00046 add_controller(__translator);
00047
00048 __gvc = gvContext();
00049 __gvjob = NULL;
00050
00051 __graph_fsm = "";
00052 __graph = "";
00053
00054 __bbw = __bbh = __pad_x = __pad_y = 0.0;
00055 __translation_x = __translation_y = 0.0;
00056 __scale = 1.0;
00057 __update_graph = true;
00058
00059 Gtk::Window *w = dynamic_cast<Gtk::Window *>(get_toplevel());
00060 if (w) {
00061 __fcd = new Gtk::FileChooserDialog(*w, "Save Graph",
00062 Gtk::FILE_CHOOSER_ACTION_SAVE);
00063 __fcd->set_transient_for(*w);
00064 } else {
00065 __fcd = new Gtk::FileChooserDialog("Save Graph",
00066 Gtk::FILE_CHOOSER_ACTION_SAVE);
00067 }
00068
00069
00070 __fcd->add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
00071 __fcd->add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK);
00072
00073 Gtk::FileFilter *filter_pdf = Gtk::manage(new Gtk::FileFilter());
00074 filter_pdf->set_name("Portable Document Format (PDF)");
00075 filter_pdf->add_pattern("*.pdf");
00076 Gtk::FileFilter *filter_svg = Gtk::manage(new Gtk::FileFilter());;
00077 filter_svg->set_name("Scalable Vector Graphic (SVG)");
00078 filter_svg->add_pattern("*.svg");
00079 Gtk::FileFilter *filter_png = Gtk::manage(new Gtk::FileFilter());;
00080 filter_png->set_name("Portable Network Graphic (PNG)");
00081 filter_png->add_pattern("*.png");
00082 __fcd->add_filter(*filter_pdf);
00083 __fcd->add_filter(*filter_svg);
00084 __fcd->add_filter(*filter_png);
00085 __fcd->set_filter(*filter_pdf);
00086
00087 gvplugin_skillgui_setup(__gvc, this);
00088
00089 signal_size_allocate().connect_notify(sigc::hide(sigc::mem_fun(*this, &SkillGuiGraphViewport::render)));
00090 signal_expose_event().connect_notify(sigc::mem_fun(*this, &SkillGuiGraphViewport::on_expose));
00091 }
00092
00093
00094
00095 SkillGuiGraphViewport::~SkillGuiGraphViewport()
00096 {
00097 gvFreeContext(__gvc);
00098 delete __fcd;
00099 }
00100
00101
00102
00103
00104
00105 void
00106 SkillGuiGraphViewport::set_gvjob(GVJ_t *job)
00107 {
00108 __gvjob = job;
00109 }
00110
00111
00112
00113
00114
00115 void
00116 SkillGuiGraphViewport::set_graph_fsm(std::string fsm_name)
00117 {
00118 if ( __graph_fsm != fsm_name ) {
00119 __translator->set_translate(0, 0);
00120 }
00121 __graph_fsm = fsm_name;
00122 }
00123
00124
00125
00126
00127
00128 void
00129 SkillGuiGraphViewport::set_graph(std::string graph)
00130 {
00131 __graph = graph;
00132 }
00133
00134
00135
00136
00137
00138
00139 void
00140 SkillGuiGraphViewport::add_drawable(Papyrus::Drawable::pointer d)
00141 {
00142 canvas()->add(d);
00143 __translator->insert(d);
00144 }
00145
00146
00147
00148
00149
00150 void
00151 SkillGuiGraphViewport::clear()
00152 {
00153 Papyrus::Gtk::Viewport::clear();
00154 __translator->clear();
00155 }
00156
00157
00158
00159
00160
00161
00162
00163 void
00164 SkillGuiGraphViewport::set_bb(double bbw, double bbh)
00165 {
00166 __bbw = bbw;
00167 __bbh = bbh;
00168 }
00169
00170
00171
00172
00173
00174
00175
00176 void
00177 SkillGuiGraphViewport::set_pad(double pad_x, double pad_y)
00178 {
00179 __pad_x = pad_x;
00180 __pad_y = pad_y;
00181 }
00182
00183
00184
00185
00186
00187
00188
00189 void
00190 SkillGuiGraphViewport::set_translation(double tx, double ty)
00191 {
00192 __translation_x = tx;
00193 __translation_y = ty;
00194 }
00195
00196
00197
00198
00199
00200
00201 void
00202 SkillGuiGraphViewport::set_scale(double scale)
00203 {
00204 __scale = scale;
00205 }
00206
00207
00208
00209
00210 bool
00211 SkillGuiGraphViewport::get_update_graph()
00212 {
00213 return __update_graph;
00214 }
00215
00216
00217
00218
00219
00220 void
00221 SkillGuiGraphViewport::set_update_graph(bool update)
00222 {
00223 __update_graph = update;
00224 }
00225
00226
00227
00228
00229
00230 void
00231 SkillGuiGraphViewport::zoom_in()
00232 {
00233 double sx, sy;
00234 Gtk::Allocation alloc = get_allocation();
00235
00236 __affine->get_scale(sx, sy);
00237 sx += 0.1; sy += 0.1;
00238 __affine->set_scale(sx, sy);
00239 __affine->set_translate((alloc.get_width() - __bbw * sx) / 2.0,
00240 (alloc.get_height() - __bbh * sy) / 2.0);
00241
00242 __scale_override = true;
00243 }
00244
00245
00246
00247
00248
00249 void
00250 SkillGuiGraphViewport::zoom_out()
00251 {
00252 double sx, sy;
00253 __affine->get_scale(sx, sy);
00254 if ( (sx > 0.1) && (sy > 0.1) ) {
00255 Gtk::Allocation alloc = get_allocation();
00256 sx -= 0.1; sy -= 0.1;
00257 __affine->set_scale(sx, sy);
00258 __affine->set_translate((alloc.get_width() - __bbw * sx) / 2.0,
00259 (alloc.get_height() - __bbh * sy) / 2.0);
00260 }
00261 __scale_override = true;
00262 }
00263
00264
00265
00266
00267
00268 void
00269 SkillGuiGraphViewport::zoom_fit()
00270 {
00271 __affine->set_scale(__scale);
00272 __affine->set_translate(__pad_x + __translation_x, __pad_y + __translation_y);
00273 __translator->set_translate(0, 0);
00274 __scale_override = false;
00275 }
00276
00277
00278
00279
00280
00281 void
00282 SkillGuiGraphViewport::zoom_reset()
00283 {
00284 __affine->set_scale(1.0);
00285 if ( __scale == 1.0 ) {
00286 __affine->set_translate(__pad_x + __translation_x, __pad_y + __translation_y);
00287 } else {
00288 __affine->set_translate(__pad_x, __pad_y);
00289 }
00290 __scale_override = true;
00291 }
00292
00293
00294
00295
00296
00297 bool
00298 SkillGuiGraphViewport::scale_override()
00299 {
00300 return __scale_override;
00301 }
00302
00303
00304
00305
00306
00307 Papyrus::AffineController::pointer
00308 SkillGuiGraphViewport::get_affine()
00309 {
00310 return __affine;
00311 }
00312
00313
00314 void
00315 SkillGuiGraphViewport::save()
00316 {
00317 Gtk::Window *w = dynamic_cast<Gtk::Window *>(get_toplevel());
00318
00319 int result = __fcd->run();
00320 if (result == Gtk::RESPONSE_OK) {
00321
00322 double old_scale_x, old_scale_y, old_translate_x, old_translate_y;
00323 __affine->get_scale(old_scale_x, old_scale_y);
00324 __affine->get_translate(old_translate_x, old_translate_y);
00325 __affine->set_scale(1);
00326 __affine->set_translate(__pad_x, __pad_y);
00327
00328 Papyrus::Canvas::pointer c = canvas();
00329
00330 Cairo::RefPtr<Cairo::Surface> surface;
00331
00332 std::string filename = __fcd->get_filename();
00333 bool write_to_png = false;
00334 if (filename != "") {
00335 Gtk::FileFilter *f = __fcd->get_filter();
00336 if (f->get_name().find("PDF") != Glib::ustring::npos) {
00337 surface = Cairo::PdfSurface::create(filename, __bbw, __bbh);
00338 } else if (f->get_name().find("SVG") != Glib::ustring::npos) {
00339 surface = Cairo::SvgSurface::create(filename, __bbw, __bbh);
00340 } else if (f->get_name().find("PNG") != Glib::ustring::npos) {
00341 surface = Cairo::ImageSurface::create(Cairo::FORMAT_ARGB32, __bbw, __bbh);
00342 write_to_png = true;
00343 }
00344
00345 if (surface) {
00346 Cairo::RefPtr<Cairo::Context> context = Cairo::Context::create(surface);
00347 c->render(context);
00348 if (write_to_png) {
00349 surface->write_to_png(filename);
00350 }
00351 }
00352
00353 } else {
00354 Gtk::MessageDialog md(*w, "Invalid filename",
00355 false, Gtk::MESSAGE_ERROR,
00356 Gtk::BUTTONS_OK, true);
00357 md.set_title("Invalid File Name");
00358 md.run();
00359 }
00360
00361 __affine->set_scale(old_scale_x, old_scale_y);
00362 __affine->set_translate(old_translate_x, old_translate_y);
00363 }
00364
00365 __fcd->hide();
00366 }
00367
00368
00369
00370 void
00371 SkillGuiGraphViewport::render()
00372 {
00373 if (! __update_graph) return;
00374
00375 Papyrus::Canvas::pointer c = canvas();
00376 #ifdef HAVE_TIMS_PAPYRUS_PATCHES
00377 c->set_redraw_enabled(false);
00378 #endif
00379 Agraph_t *g = agmemread((char *)__graph.c_str());
00380 if (g) {
00381 gvLayout(__gvc, g, (char *)"dot");
00382 gvRender(__gvc, g, (char *)"skillgui", NULL);
00383 gvFreeLayout(__gvc, g);
00384 agclose(g);
00385 } else {
00386 clear();
00387 }
00388 #ifdef HAVE_TIMS_PAPYRUS_PATCHES
00389 c->set_redraw_enabled(true);
00390 #endif
00391 }
00392
00393
00394
00395
00396
00397 void
00398 SkillGuiGraphViewport::on_expose(GdkEventExpose *event)
00399 {
00400 if (__scale_override) {
00401 Gtk::Allocation alloc = get_allocation();
00402
00403 double sx, sy;
00404 __affine->get_scale(sx, sy);
00405 __affine->set_translate(((alloc.get_width() - __bbw * sx) / 2.0) + __pad_x,
00406 ((alloc.get_height() - __bbh * sy) / 2.0) + __pad_y);
00407
00408 }
00409 }