00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00032 #include <gtk/gtk.h>
00033
00034 #include <graphviz/gvplugin_device.h>
00035 #include <graphviz/gvplugin_render.h>
00036 #include <graphviz/gvplugin.h>
00037 #include <graphviz/gvc.h>
00038 #include <graphviz/gvplugin_layout.h>
00039 #include <graphviz/gvcjob.h>
00040 #include <graphviz/gvcommon.h>
00041 #include <graphviz/gvcext.h>
00042 #include <graphviz/types.h>
00043 #include <graphviz/graph.h>
00044 #include <graphviz/geom.h>
00045
00046 #include "callbacks.h"
00047
00048 #include <iostream>
00049
00050 #include <boost/format.hpp>
00051
00052 #include <mtt/hypothesisTree.h>
00053
00054 #include <mtt/graph_wrapper.h>
00055
00056 using namespace std;
00057 using namespace boost;
00058
00060 extern GVGraph*graph_context;
00061
00063 extern hypothesisTreePtr htreePtr;
00064
00065 extern "C" {
00066 extern int agrelabel_node(Agnode_t * n, char *newname);
00067 }
00068
00069 ostream& operator<< (ostream &o, const pointf &i)
00070 {
00071 return o<<i.x<<" "<<i.y;
00072 }
00073
00074 ostream& operator<< (ostream &o, const boxf &i)
00075 {
00076 return o<<"LL: "<<i.LL<<" UR: "<<i.UR;
00077 }
00078
00079
00080 gboolean drawGraph(void)
00081 {
00082 if(pthread_mutex_trylock(&(htreePtr->_draw_mutex))!=0)
00083 return false;
00084
00085 if(htreePtr->need_layout==false)
00086 {
00087 pthread_mutex_unlock(&(htreePtr->_draw_mutex));
00088 return false;
00089 }
00090
00091 graph_context->freeLayout();
00092
00093 HypothesisTree::iterator parent;
00094 HypothesisTree::iterator it;
00095
00096 graph_context->clearNodes();
00097
00098 for(it = htreePtr->begin(); it != htreePtr->end(); ++it)
00099 {
00100 assert(*it!=0);
00101
00102 graph_context->addNode((*it)->nameUI());
00103
00104 for(uint a=0;a<(*it)->_attribute_names.size();++a)
00105 graph_context->setNodeAttribute((*it)->nameUI(),(*it)->_attribute_names[a],(*it)->_attribute_values[a]);
00106
00107 parent=htreePtr->parent(it);
00108
00109 if(parent!=NULL)
00110 graph_context->addEdge((*parent)->nameUI(),(*it)->nameUI());
00111 }
00112
00113 graph_context->applyLayout();
00114
00115 htreePtr->need_layout=false;
00116
00117 pthread_mutex_unlock(&(htreePtr->_draw_mutex));
00118
00119 return true;
00120 }
00121
00122 gboolean DrawingareaExposeEvent(GtkWidget*widget,GdkEventExpose*event,gpointer user_data)
00123 {
00124
00125 pthread_mutex_lock(&(htreePtr->_draw_mutex));
00126
00127 GVJ_t *job = (GVJ_t *)g_object_get_data(G_OBJECT(widget),"job");
00128 cairo_t *cr = gdk_cairo_create(widget->window);
00129
00130 (job->callbacks->motion)(job, job->pointer);
00131
00132 job->context = (void *)cr;
00133 job->external_context = true;
00134 job->width = widget->allocation.width;
00135 job->height = widget->allocation.height;
00136
00137
00138 (job->callbacks->refresh)(job);
00139
00140
00141 cairo_destroy(cr);
00142
00143 pthread_mutex_unlock(&(htreePtr->_draw_mutex));
00144
00145 return true;
00146 }
00147
00148 gboolean DrawingareaButtonPressEvent(GtkWidget*widget,GdkEventButton *event,gpointer user_data)
00149 {
00150 static bool init=true;
00151 static bool dragging=false;
00152
00153 if(init)
00154 {
00155 g_object_set_data(G_OBJECT(widget),"dragging",&dragging);
00156 init=false;
00157 }
00158
00159 if(event->type==GDK_BUTTON_PRESS)
00160 dragging=true;
00161 else if(event->type==GDK_BUTTON_RELEASE)
00162 dragging=false;
00163
00164 return true;
00165 }
00166
00167 gboolean DrawingareaMotionNotifyEvent(GtkWidget*widget,GdkEventMotion*event,gpointer user_data)
00168 {
00169 static bool first_drag=true;
00170
00171 GVJ_t *job = (GVJ_t *)g_object_get_data(G_OBJECT(widget),"job");
00172
00173 bool *dragging_p = (bool*)g_object_get_data(G_OBJECT(widget),"dragging");
00174 if(!dragging_p)
00175 return FALSE;
00176
00177 bool dragging=*dragging_p;
00178
00179 static pointf diff;
00180
00181 double dpix=-1/job->devscale.x;
00182 double dpiy=-1/job->devscale.y;
00183
00184 diff.x=event->x-job->pointer.x;
00185 diff.y=event->y-job->pointer.y;
00186
00187 job->pointer.x = event->x;
00188 job->pointer.y = event->y;
00189
00190 gtk_widget_queue_draw(widget);
00191
00192 if(dragging)
00193 {
00194 if(first_drag)
00195 {
00196 diff.x=0;
00197 diff.y=0;
00198 first_drag=false;
00199 }
00200
00201 job->focus.x+= diff.x*dpix/job->zoom;
00202 job->focus.y+= diff.y*dpiy/job->zoom;
00203
00204 double x_lim = (0.37*job->width-1)/job->zoom;
00205 double y_lim = (0.37*job->height-1)/job->zoom;
00206
00207
00208
00209
00210
00211
00212
00213
00214 if(job->focus.x>= x_lim)
00215 job->focus.x= x_lim;
00216
00217 if(job->focus.y>= y_lim)
00218 job->focus.y= y_lim;
00219 }
00220
00221 return true;
00222 }
00223
00224 gboolean DrawingareaScrollEvent(GtkWidget*widget,GdkEventScroll *event,gpointer user_data)
00225 {
00226 if(event->type==GDK_SCROLL)
00227 {
00228 GVJ_t *job = (GVJ_t *)g_object_get_data(G_OBJECT(widget),"job");
00229
00230 pointf pointer;
00231 pointer.x=event->x;
00232 pointer.y=event->y;
00233
00234 if(event->direction==GDK_SCROLL_UP)
00235 (job->callbacks->button_press)(job,4, pointer);
00236 else if(event->direction==GDK_SCROLL_DOWN)
00237 (job->callbacks->button_press)(job,5, pointer);
00238
00239 double x_lim = (0.37*job->width-1)/job->zoom;
00240 double y_lim = (0.37*job->height-1)/job->zoom;
00241
00242 if(job->focus.x>= x_lim)
00243 job->focus.x= x_lim;
00244
00245 if(job->focus.y>= y_lim)
00246 job->focus.y= y_lim;
00247 }
00248
00249 return true;
00250 }
00251
00252 gboolean WindowDeleteEvent(GtkWidget*widget,GdkEvent*event,gpointer user_data)
00253 {
00254 gtk_main_quit();
00255 return true;
00256 }
00257
00258 gboolean DrawingareaConfigureEvent(GtkWidget*widget,GdkEventConfigure*event,gpointer user_data)
00259 {
00260 GVJ_t *job;
00261 double zoom_to_fit;
00262
00263
00264
00265
00266
00267
00268
00269 job = (GVJ_t *)g_object_get_data(G_OBJECT(widget),"job");
00270
00271 if (! job->has_been_rendered)
00272 {
00273 zoom_to_fit = MIN((double) event->width / (double) job->width,(double) event->height / (double) job->height);
00274 if (zoom_to_fit < 1.0)
00275 job->zoom *= zoom_to_fit;
00276 }else if(job->fit_mode)
00277 {
00278 zoom_to_fit = MIN((double) event->width / (double) job->width, (double) event->height / (double) job->height);
00279 job->zoom *= zoom_to_fit;
00280 }
00281
00282 if ((unsigned int)event->width > job->width || (unsigned int)event->height > job->height)
00283 job->has_grown = TRUE;
00284
00285 job->width = event->width;
00286 job->height = event->height;
00287 job->needs_refresh = TRUE;
00288
00289 return FALSE;
00290 }