| 1 | /*! \defgroup guiEvents libguiControlFlow: The GUI ControlFlow display plugin */ |
| 2 | /*\@{*/ |
| 3 | |
| 4 | /*! \file guiControlFlow.c |
| 5 | * \brief Graphical plugin for showing control flow of a trace. |
| 6 | * |
| 7 | * This plugin adds a Control Flow Viewer functionnality to Linux TraceToolkit |
| 8 | * GUI when this plugin is loaded. The init and destroy functions add the |
| 9 | * viewer's insertion menu item and toolbar icon by calling gtkTraceSet's |
| 10 | * API functions. Then, when a viewer's object is created, the constructor |
| 11 | * creates ans register through API functions what is needed to interact |
| 12 | * with the TraceSet window. |
| 13 | * |
| 14 | * This plugin uses the gdk library to draw the events and gtk to interact |
| 15 | * with the user. |
| 16 | * |
| 17 | * Author : Mathieu Desnoyers, June 2003 |
| 18 | */ |
| 19 | |
| 20 | #include <glib.h> |
| 21 | #include <gmodule.h> |
| 22 | #include <gtk/gtk.h> |
| 23 | #include <gdk/gdk.h> |
| 24 | |
| 25 | #include <lttv/hook.h> |
| 26 | #include <lttv/module.h> |
| 27 | |
| 28 | //#include "guiControlFlow.h" |
| 29 | #include "icons/hGuiControlFlowInsert.xpm" |
| 30 | |
| 31 | #include "gtktreeprivate.h" |
| 32 | |
| 33 | //FIXME by including ltt.h |
| 34 | #include <time.h> |
| 35 | typedef time_t ltt_time; |
| 36 | |
| 37 | typedef struct _ltt_time_interval |
| 38 | { |
| 39 | ltt_time time_begin, time_end; |
| 40 | } ltt_time_interval; |
| 41 | |
| 42 | |
| 43 | /***************************************************************************** |
| 44 | * Definition of structures * |
| 45 | *****************************************************************************/ |
| 46 | |
| 47 | typedef struct _DrawingAreaInfo { |
| 48 | |
| 49 | guint height, width; |
| 50 | |
| 51 | } DrawingAreaInfo ; |
| 52 | |
| 53 | typedef struct _ControlFlowData { |
| 54 | |
| 55 | GtkWidget *Drawing_Area_V; |
| 56 | GtkWidget *Scrolled_Window_VC; |
| 57 | |
| 58 | GtkWidget *Process_List_VC; |
| 59 | |
| 60 | /* Model containing list data */ |
| 61 | GtkListStore *Store_M; |
| 62 | |
| 63 | GtkWidget *HBox_V; |
| 64 | GtkWidget *Inside_HBox_V; |
| 65 | |
| 66 | GtkAdjustment *VAdjust_C ; |
| 67 | |
| 68 | /* Trace information */ |
| 69 | TraceSet *Trace_Set; |
| 70 | TraceStatistics *Trace_Statistics; |
| 71 | |
| 72 | /* Shown events information */ |
| 73 | guint First_Event, Last_Event; |
| 74 | ltt_time Begin_Time, End_Time; |
| 75 | |
| 76 | |
| 77 | /* Drawing Area Info */ |
| 78 | DrawingAreaInfo Drawing_Area_Info; |
| 79 | |
| 80 | /* TEST DATA, TO BE READ FROM THE TRACE */ |
| 81 | gint Number_Of_Events ; |
| 82 | guint Currently_Selected_Event ; |
| 83 | gboolean Selected_Event ; |
| 84 | guint Number_Of_Process; |
| 85 | |
| 86 | } ControlFlowData ; |
| 87 | |
| 88 | /* Structure used to store and use information relative to one events refresh |
| 89 | * request. Typically filled in by the expose event callback, then passed to the |
| 90 | * library call, then used by the drawing hooks. Then, once all the events are |
| 91 | * sent, it is freed by the hook called after the reading. |
| 92 | */ |
| 93 | typedef struct _EventRequest |
| 94 | { |
| 95 | ControlFlowData *Control_Flow_Data; |
| 96 | ltt_time time_begin, time_end; |
| 97 | /* Fill the Events_Context during the initial expose, before calling for |
| 98 | * events. |
| 99 | */ |
| 100 | GArray Events_Context; //FIXME |
| 101 | } EventRequest ; |
| 102 | |
| 103 | |
| 104 | /** Array containing instanced objects. Used when module is unloaded */ |
| 105 | static GSList *sControl_Flow_Data_List = NULL ; |
| 106 | |
| 107 | |
| 108 | /***************************************************************************** |
| 109 | * Function prototypes * |
| 110 | *****************************************************************************/ |
| 111 | //! Control Flow Viewer's constructor hook |
| 112 | GtkWidget *hGuiControlFlow(GtkWidget *pmParentWindow); |
| 113 | //! Control Flow Viewer's constructor |
| 114 | ControlFlowData *GuiControlFlow(void); |
| 115 | //! Control Flow Viewer's destructor |
| 116 | void GuiControlFlow_Destructor(ControlFlowData *Control_Flow_Data); |
| 117 | |
| 118 | |
| 119 | static int Event_Selected_Hook(void *hook_data, void *call_data); |
| 120 | |
| 121 | static lttv_hooks |
| 122 | *Draw_Before_Hooks, |
| 123 | *Draw_Event_Hooks, |
| 124 | *Draw_After_Hooks; |
| 125 | |
| 126 | Draw_Before_Hook(void *hook_data, void *call_data) |
| 127 | Draw_Event_Hook(void *hook_data, void *call_data) |
| 128 | Draw_After_Hook(void *hook_data, void *call_data) |
| 129 | |
| 130 | |
| 131 | //void Tree_V_set_cursor(ControlFlowData *Control_Flow_Data); |
| 132 | //void Tree_V_get_cursor(ControlFlowData *Control_Flow_Data); |
| 133 | |
| 134 | /* Prototype for selection handler callback */ |
| 135 | //static void tree_selection_changed_cb (GtkTreeSelection *selection, gpointer data); |
| 136 | static void v_scroll_cb (GtkAdjustment *adjustment, gpointer data); |
| 137 | //static void Tree_V_size_allocate_cb (GtkWidget *widget, GtkAllocation *alloc, gpointer data); |
| 138 | //static void Tree_V_size_request_cb (GtkWidget *widget, GtkRequisition *requisition, gpointer data); |
| 139 | //static void Tree_V_cursor_changed_cb (GtkWidget *widget, gpointer data); |
| 140 | //static void Tree_V_move_cursor_cb (GtkWidget *widget, GtkMovementStep arg1, gint arg2, gpointer data); |
| 141 | |
| 142 | static void expose_event_cb (GtkWidget *widget, GdkEventExpose *expose, gpointer data); |
| 143 | |
| 144 | void add_test_process(ControlFlowData *Control_Flow_Data); |
| 145 | |
| 146 | static void get_test_data(guint Event_Number, guint List_Height, |
| 147 | ControlFlowData *Control_Flow_Data); |
| 148 | |
| 149 | void add_test_data(ControlFlowData *Control_Flow_Data); |
| 150 | void test_draw(ControlFlowData *Control_Flow_Data); |
| 151 | |
| 152 | void Drawing_Area_Init(ControlFlowData *Control_Flow_Data); |
| 153 | |
| 154 | |
| 155 | |
| 156 | /***************************************************************************** |
| 157 | * Functions for module loading/unloading * |
| 158 | *****************************************************************************/ |
| 159 | /** |
| 160 | * plugin's init function |
| 161 | * |
| 162 | * This function initializes the Control Flow Viewer functionnality through the |
| 163 | * gtkTraceSet API. |
| 164 | */ |
| 165 | G_MODULE_EXPORT void init() { |
| 166 | g_critical("GUI ControlFlow Viewer init()"); |
| 167 | |
| 168 | /* Register the toolbar insert button */ |
| 169 | //ToolbarItemReg(guiEventsInsert_xpm, "Insert Control Flow Viewer", guiEvent); |
| 170 | |
| 171 | /* Register the menu item insert entry */ |
| 172 | //MenuItemReg("/", "Insert Control Flow Viewer", guiEvent); |
| 173 | |
| 174 | /* Setup the hooks */ |
| 175 | Draw_Before_Hooks = lttv_hooks_new(); |
| 176 | Draw_Event_Hooks = lttv_hooks_new(); |
| 177 | Draw_After_Hooks = lttv_hooks_new(); |
| 178 | |
| 179 | lttv_hooks_add(Draw_Before_Hooks, Draw_Before_Hook, NULL); |
| 180 | lttv_hooks_add(Draw_Event_Hooks, Draw_Event_Hook, NULL); |
| 181 | lttv_hooks_add(Draw_After_Hooks, Draw_After_Hook, NULL); |
| 182 | |
| 183 | } |
| 184 | |
| 185 | void destroy_walk(gpointer data, gpointer user_data) |
| 186 | { |
| 187 | GuiControlFlow_Destructor((ControlFlowData*)data); |
| 188 | } |
| 189 | |
| 190 | |
| 191 | |
| 192 | /** |
| 193 | * plugin's destroy function |
| 194 | * |
| 195 | * This function releases the memory reserved by the module and unregisters |
| 196 | * everything that has been registered in the gtkTraceSet API. |
| 197 | */ |
| 198 | G_MODULE_EXPORT void destroy() { |
| 199 | g_critical("GUI Control Flow Viewer destroy()"); |
| 200 | int i; |
| 201 | |
| 202 | ControlFlowData *Control_Flow_Data; |
| 203 | |
| 204 | g_critical("GUI Event Viewer destroy()"); |
| 205 | |
| 206 | g_slist_foreach(sControl_Flow_Data_List, destroy_walk, NULL ); |
| 207 | |
| 208 | lttv_hooks_destroy(Draw_Before_Hooks); |
| 209 | lttv_hooks_destroy(Draw_Event_Hooks); |
| 210 | lttv_hooks_destroy(Draw_After_Hooks); |
| 211 | |
| 212 | /* Unregister the toolbar insert button */ |
| 213 | //ToolbarItemUnreg(hGuiEvents); |
| 214 | |
| 215 | /* Unregister the menu item insert entry */ |
| 216 | //MenuItemUnreg(hGuiEvents); |
| 217 | } |
| 218 | |
| 219 | |
| 220 | /***************************************************************************** |
| 221 | * Control Flow Viewer class implementation * |
| 222 | *****************************************************************************/ |
| 223 | |
| 224 | |
| 225 | /* Enumeration of the columns */ |
| 226 | enum |
| 227 | { |
| 228 | PROCESS_COLUMN, |
| 229 | N_COLUMNS |
| 230 | }; |
| 231 | |
| 232 | |
| 233 | |
| 234 | /** |
| 235 | * Control Flow Viewer's constructor |
| 236 | * |
| 237 | * This constructor is given as a parameter to the menuitem and toolbar button |
| 238 | * registration. It creates the drawing widget. |
| 239 | * @param ParentWindow A pointer to the parent window. |
| 240 | * @return The widget created. |
| 241 | */ |
| 242 | ControlFlowData * |
| 243 | GuiControlFlow(void) |
| 244 | { |
| 245 | |
| 246 | GtkTreeViewColumn *column; |
| 247 | GtkCellRenderer *renderer; |
| 248 | |
| 249 | ControlFlowData* Control_Flow_Data = g_new(ControlFlowData,1) ; |
| 250 | Control_Flow_Data->Drawing_Area_V = gtk_drawing_area_new (); |
| 251 | |
| 252 | |
| 253 | /* TEST DATA, TO BE READ FROM THE TRACE */ |
| 254 | Control_Flow_Data->Number_Of_Events = 1000 ; |
| 255 | Control_Flow_Data->Currently_Selected_Event = FALSE ; |
| 256 | Control_Flow_Data->Selected_Event = 0; |
| 257 | Control_Flow_Data->Number_Of_Process = 10; |
| 258 | |
| 259 | /* FIXME register Event_Selected_Hook */ |
| 260 | |
| 261 | |
| 262 | |
| 263 | /* Create the Process list */ |
| 264 | Control_Flow_Data->Store_M = gtk_list_store_new ( N_COLUMNS, |
| 265 | G_TYPE_STRING); |
| 266 | |
| 267 | |
| 268 | Control_Flow_Data->Process_List_VC = gtk_tree_view_new_with_model (GTK_TREE_MODEL (Control_Flow_Data->Store_M)); |
| 269 | |
| 270 | g_object_unref (G_OBJECT (Control_Flow_Data->Store_M)); |
| 271 | |
| 272 | gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(Control_Flow_Data->Process_List_VC), FALSE); |
| 273 | |
| 274 | /* Create a column, associating the "text" attribute of the |
| 275 | * cell_renderer to the first column of the model */ |
| 276 | /* Columns alignment : 0.0 : Left 0.5 : Center 1.0 : Right */ |
| 277 | renderer = gtk_cell_renderer_text_new (); |
| 278 | column = gtk_tree_view_column_new_with_attributes ("Process", |
| 279 | renderer, |
| 280 | "text", PROCESS_COLUMN, |
| 281 | NULL); |
| 282 | gtk_tree_view_column_set_alignment (column, 0.0); |
| 283 | gtk_tree_view_column_set_fixed_width (column, 45); |
| 284 | gtk_tree_view_append_column (GTK_TREE_VIEW (Control_Flow_Data->Process_List_VC), column); |
| 285 | |
| 286 | |
| 287 | |
| 288 | Control_Flow_Data->Inside_HBox_V = gtk_hbox_new(0, 0); |
| 289 | |
| 290 | gtk_box_pack_start(GTK_BOX(Control_Flow_Data->Inside_HBox_V), Control_Flow_Data->Process_List_VC, FALSE, TRUE, 0); |
| 291 | gtk_box_pack_start(GTK_BOX(Control_Flow_Data->Inside_HBox_V), Control_Flow_Data->Drawing_Area_V, TRUE, TRUE, 0); |
| 292 | |
| 293 | |
| 294 | Control_Flow_Data->VAdjust_C = GTK_ADJUSTMENT(gtk_adjustment_new(0.0, /* Value */ |
| 295 | 0.0, /* Lower */ |
| 296 | 0.0, /* Upper */ |
| 297 | 0.0, /* Step inc. */ |
| 298 | 0.0, /* Page inc. */ |
| 299 | 0.0 )); /* page size */ |
| 300 | |
| 301 | |
| 302 | Control_Flow_Data->Scrolled_Window_VC = gtk_scrolled_window_new (NULL, |
| 303 | Control_Flow_Data->VAdjust_C); |
| 304 | gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(Control_Flow_Data->Scrolled_Window_VC) , |
| 305 | GTK_POLICY_NEVER, |
| 306 | GTK_POLICY_AUTOMATIC); |
| 307 | |
| 308 | gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(Control_Flow_Data->Scrolled_Window_VC), |
| 309 | Control_Flow_Data->Inside_HBox_V); |
| 310 | |
| 311 | |
| 312 | g_signal_connect (G_OBJECT (Control_Flow_Data->Drawing_Area_V), "expose_event", |
| 313 | G_CALLBACK (expose_event_cb), Control_Flow_Data); |
| 314 | |
| 315 | |
| 316 | |
| 317 | g_signal_connect (G_OBJECT (Control_Flow_Data->VAdjust_C), "value-changed", |
| 318 | G_CALLBACK (v_scroll_cb), |
| 319 | Control_Flow_Data); |
| 320 | |
| 321 | add_test_process(Control_Flow_Data); |
| 322 | |
| 323 | |
| 324 | |
| 325 | /* Set the size of the drawing area */ |
| 326 | Drawing_Area_Init(Control_Flow_Data); |
| 327 | |
| 328 | /* Get trace statistics */ |
| 329 | Control_Flow_Data->Trace_Statistics = get_trace_statistics(Trace); |
| 330 | |
| 331 | |
| 332 | gtk_widget_show(Control_Flow_Data->Drawing_Area_V); |
| 333 | gtk_widget_show(Control_Flow_Data->Process_List_VC); |
| 334 | gtk_widget_show(Control_Flow_Data->Inside_HBox_V); |
| 335 | gtk_widget_show(Control_Flow_Data->Scrolled_Window_VC); |
| 336 | |
| 337 | test_draw(Control_Flow_Data); |
| 338 | |
| 339 | return Control_Flow_Data; |
| 340 | |
| 341 | } |
| 342 | |
| 343 | void |
| 344 | GuiControlFlow_Destructor(ControlFlowData *Control_Flow_Data) |
| 345 | { |
| 346 | guint index; |
| 347 | |
| 348 | /* May already been done by GTK window closing */ |
| 349 | if(GTK_IS_WIDGET(Control_Flow_Data->HBox_V)) |
| 350 | gtk_widget_destroy(Control_Flow_Data->HBox_V); |
| 351 | |
| 352 | /* Destroy the Tree View */ |
| 353 | //gtk_widget_destroy(Control_Flow_Data->Tree_V); |
| 354 | |
| 355 | /* Clear raw event list */ |
| 356 | //gtk_list_store_clear(Control_Flow_Data->Store_M); |
| 357 | //gtk_widget_destroy(GTK_WIDGET(Control_Flow_Data->Store_M)); |
| 358 | |
| 359 | g_slist_remove(sControl_Flow_Data_List,Control_Flow_Data); |
| 360 | } |
| 361 | |
| 362 | //FIXME : call hGuiEvents_Destructor for corresponding data upon widget destroy |
| 363 | |
| 364 | |
| 365 | |
| 366 | /***************************************************************************** |
| 367 | * Drawing functions * |
| 368 | *****************************************************************************/ |
| 369 | |
| 370 | typedef enum |
| 371 | { |
| 372 | RED, |
| 373 | GREEN, |
| 374 | BLUE, |
| 375 | WHITE, |
| 376 | BLACK |
| 377 | |
| 378 | } ControlFlowColors; |
| 379 | |
| 380 | /* Vector of unallocated colors */ |
| 381 | static GdkColor CF_Colors [] = |
| 382 | { |
| 383 | { 0, 0xffff, 0x0000, 0x0000 }, // RED |
| 384 | { 0, 0x0000, 0xffff, 0x0000 }, // GREEN |
| 385 | { 0, 0x0000, 0x0000, 0xffff }, // BLUE |
| 386 | { 0, 0xffff, 0xffff, 0xffff }, // WHITE |
| 387 | { 0, 0x0000, 0x0000, 0x0000 } // BLACK |
| 388 | }; |
| 389 | |
| 390 | |
| 391 | gint get_cell_height(GtkTreeView *TreeView) |
| 392 | { |
| 393 | gint height, width; |
| 394 | GtkTreeViewColumn *Column = gtk_tree_view_get_column(TreeView, 0); |
| 395 | GList *Render_List = gtk_tree_view_column_get_cell_renderers(Column); |
| 396 | GtkCellRenderer *Renderer = g_list_first(Render_List)->data; |
| 397 | |
| 398 | gtk_tree_view_column_cell_get_size(Column, NULL, NULL, NULL, NULL, &height); |
| 399 | g_critical("cell 0 height : %u",height); |
| 400 | |
| 401 | return height; |
| 402 | } |
| 403 | |
| 404 | |
| 405 | /* get_time_from_pixels |
| 406 | * |
| 407 | * Get the time interval from window time and pixels, and pixels requested. This |
| 408 | * function uses TimeMul, which should only be used if the float value is lower |
| 409 | * that 4, and here it's always lower than 1, so it's ok. |
| 410 | */ |
| 411 | void get_time_from_pixels(guint area_x, guint area_width, |
| 412 | guint window_width, |
| 413 | ltt_time &window_time_begin, ltt_time &window_time_end, |
| 414 | ltt_time &time_begin, ltt_time &time_end) |
| 415 | { |
| 416 | ltt_time window_time_interval; |
| 417 | |
| 418 | TimeSub(window_time_interval, window_time_end, window_time_begin); |
| 419 | |
| 420 | |
| 421 | TimeMul(time_begin, window_time_interval, (area_x/(float)window_width)); |
| 422 | TimeAdd(time_begin, window_time_begin, time_begin); |
| 423 | |
| 424 | TimeMul(time_end, window_time_interval, (area_width/(float)window_width)); |
| 425 | TimeAdd(time_end, time_begin, time_end); |
| 426 | |
| 427 | } |
| 428 | |
| 429 | void Drawing_Area_Init(ControlFlowData *Control_Flow_Data) |
| 430 | { |
| 431 | DrawingAreaInfo *Drawing_Area_Info = &Control_Flow_Data->Drawing_Area_Info; |
| 432 | guint w; |
| 433 | |
| 434 | w = 500; |
| 435 | |
| 436 | |
| 437 | Drawing_Area_Info->height = |
| 438 | get_cell_height(GTK_TREE_VIEW(Control_Flow_Data->Process_List_VC)) |
| 439 | * Control_Flow_Data->Number_Of_Process ; |
| 440 | |
| 441 | gtk_widget_modify_bg(Control_Flow_Data->Drawing_Area_V, |
| 442 | GTK_STATE_NORMAL, |
| 443 | &CF_Colors[BLACK]); |
| 444 | |
| 445 | |
| 446 | gtk_widget_set_size_request (Control_Flow_Data->Drawing_Area_V, |
| 447 | w, |
| 448 | Drawing_Area_Info->height); |
| 449 | |
| 450 | |
| 451 | } |
| 452 | |
| 453 | |
| 454 | |
| 455 | void add_test_process(ControlFlowData *Control_Flow_Data) |
| 456 | { |
| 457 | GtkTreeIter iter; |
| 458 | int i; |
| 459 | gchar *process[] = { "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten" }; |
| 460 | |
| 461 | for(i=0; i<Control_Flow_Data->Number_Of_Process; i++) |
| 462 | { |
| 463 | /* Add a new row to the model */ |
| 464 | gtk_list_store_append (Control_Flow_Data->Store_M, &iter); |
| 465 | gtk_list_store_set (Control_Flow_Data->Store_M, &iter, |
| 466 | PROCESS_COLUMN, process[i], |
| 467 | -1); |
| 468 | } |
| 469 | |
| 470 | } |
| 471 | |
| 472 | |
| 473 | |
| 474 | void test_draw(ControlFlowData *Control_Flow_Data) |
| 475 | { |
| 476 | /* Draw event states using available height, Number of process, cell height |
| 477 | * (don't forget to remove two pixels at beginning and end). |
| 478 | * For horizontal : use width, Time_Begin, Time_End. |
| 479 | * This function calls the reading library to get the draw_hook called |
| 480 | * for the desired period of time. */ |
| 481 | |
| 482 | DrawingAreaInfo *Drawing_Area_Info = &Control_Flow_Data->Drawing_Area_Info; |
| 483 | |
| 484 | |
| 485 | } |
| 486 | |
| 487 | |
| 488 | /***************************************************************************** |
| 489 | * Hooks to be called by the main window * |
| 490 | *****************************************************************************/ |
| 491 | /** |
| 492 | * Event Viewer's constructor hook |
| 493 | * |
| 494 | * This constructor is given as a parameter to the menuitem and toolbar button |
| 495 | * registration. It creates the list. |
| 496 | * @param pmParentWindow A pointer to the parent window. |
| 497 | * @return The widget created. |
| 498 | */ |
| 499 | GtkWidget * |
| 500 | hGuiControlFlow(GtkWidget *pmParentWindow) |
| 501 | { |
| 502 | ControlFlowData* Control_Flow_Data = GuiControlFlow() ; |
| 503 | |
| 504 | return Control_Flow_Data->HBox_V ; |
| 505 | |
| 506 | } |
| 507 | |
| 508 | int Event_Selected_Hook(void *hook_data, void *call_data) |
| 509 | { |
| 510 | ControlFlowData *Control_Flow_Data = (ControlFlowData*) hook_data; |
| 511 | guint *Event_Number = (guint*) call_data; |
| 512 | |
| 513 | g_critical("DEBUG : event selected by main window : %u", *Event_Number); |
| 514 | |
| 515 | // Control_Flow_Data->Currently_Selected_Event = *Event_Number; |
| 516 | // Control_Flow_Data->Selected_Event = TRUE ; |
| 517 | |
| 518 | // Tree_V_set_cursor(Control_Flow_Data); |
| 519 | |
| 520 | } |
| 521 | |
| 522 | |
| 523 | /* Hook called before drawing. Gets the initial context at the beginning of the |
| 524 | * drawing interval and copy it to the context in Event_Request. |
| 525 | */ |
| 526 | Draw_Before_Hook(void *hook_data, void *call_data) |
| 527 | { |
| 528 | EventRequest *Event_Request = (EventRequest*)hook_data; |
| 529 | EventsContext Events_Context = (EventsContext*)call_data; |
| 530 | |
| 531 | Event_Request->Events_Context = Events_Context; |
| 532 | } |
| 533 | |
| 534 | /* |
| 535 | * The draw event hook is called by the reading API to have a |
| 536 | * particular event drawn on the screen. |
| 537 | * @param hook_data ControlFlowData structure of the viewer. |
| 538 | * @param call_data Event context. |
| 539 | * |
| 540 | * This function basically draw lines and icons. Two types of lines are drawn : |
| 541 | * one small (3 pixels?) representing the state of the process and the second |
| 542 | * type is thicker (10 pixels?) representing on which CPU a process is running |
| 543 | * (and this only in running state). |
| 544 | * |
| 545 | * Extremums of the lines : |
| 546 | * x_min : time of the last event context for this process kept in memory. |
| 547 | * x_max : time of the current event. |
| 548 | * y : middle of the process in the process list. The process is found in the |
| 549 | * list, therefore is it's position in pixels. |
| 550 | * |
| 551 | * The choice of lines'color is defined by the context of the last event for this |
| 552 | * process. |
| 553 | */ |
| 554 | Draw_Event_Hook(void *hook_data, void *call_data) |
| 555 | { |
| 556 | EventRequest *Event_Request = (EventRequest*)hook_data; |
| 557 | |
| 558 | } |
| 559 | |
| 560 | |
| 561 | Draw_After_Hook(void *hook_data, void *call_data) |
| 562 | { |
| 563 | EventRequest *Event_Request = (EventRequest*)hook_data; |
| 564 | |
| 565 | g_free(Event_Request); |
| 566 | } |
| 567 | |
| 568 | /***************************************************************************** |
| 569 | * Callbacks used for the viewer * |
| 570 | *****************************************************************************/ |
| 571 | void expose_event_cb (GtkWidget *widget, GdkEventExpose *expose, gpointer data) |
| 572 | { |
| 573 | ControlFlowData *Control_Flow_Data = (ControlFlowData*)data; |
| 574 | |
| 575 | EventRequest *Event_Request = g_new(sizeof(EventRequest)); |
| 576 | |
| 577 | Event_Request->Control_Flow_Data = Control_Flow_Data; |
| 578 | |
| 579 | /* Calculate, from pixels in expose, the time interval to get data */ |
| 580 | |
| 581 | get_time_from_pixels(expose->area.x, expose->area.width, |
| 582 | Control_Flow_Data->Drawing_Area_Info.width, |
| 583 | &Control_Flow_Data->Begin_Time, &Control_Flow_Data->End_Time, |
| 584 | &Event_Request->time_begin, &Event_Request->time_end) |
| 585 | |
| 586 | /* Look in statistics of the trace the processes present during the |
| 587 | * whole time interval _shown on the screen_. Modify the list of |
| 588 | * processes to match it. NOTE : modify, not recreate. If recreation is |
| 589 | * needed,keep a pointer to the currently selected event in the list. |
| 590 | */ |
| 591 | |
| 592 | /* Call the reading API to have events sent to drawing hooks */ |
| 593 | lttv_trace_set_process( Control_Flow_Data->Trace_Set, |
| 594 | Draw_Before_Hooks, |
| 595 | Draw_Event_Hooks, |
| 596 | Draw_After_Hooks, |
| 597 | NULL, //FIXME : filter here |
| 598 | Event_Request->time_begin, |
| 599 | Event_Request->time_end); |
| 600 | |
| 601 | } |
| 602 | |
| 603 | #ifdef DEBUG |
| 604 | void test_draw() { |
| 605 | gint cell_height = get_cell_height(GTK_TREE_VIEW(Control_Flow_Data->Process_List_VC)); |
| 606 | GdkGC *GC = gdk_gc_new(widget->window); |
| 607 | GdkColor color = CF_Colors[GREEN]; |
| 608 | |
| 609 | gdk_color_alloc (gdk_colormap_get_system () , &color); |
| 610 | |
| 611 | g_critical("expose"); |
| 612 | |
| 613 | /* When redrawing, use widget->allocation.width to get the width of |
| 614 | * drawable area. */ |
| 615 | Control_Flow_Data->Drawing_Area_Info.width = widget->allocation.width; |
| 616 | |
| 617 | test_draw(Control_Flow_Data); |
| 618 | |
| 619 | gdk_gc_copy(GC,widget->style->white_gc); |
| 620 | gdk_gc_set_foreground(GC,&color); |
| 621 | |
| 622 | //gdk_draw_arc (widget->window, |
| 623 | // widget->style->fg_gc[GTK_WIDGET_STATE (widget)], |
| 624 | // TRUE, |
| 625 | // //0, 0, widget->allocation.width, widget->allocation.height, |
| 626 | // 0, 0, widget->allocation.width, |
| 627 | // Control_Flow_Data->Drawing_Area_Info.height, |
| 628 | // 0, 64 * 360); |
| 629 | |
| 630 | |
| 631 | //Drawing_Area_Init(Control_Flow_Data); |
| 632 | |
| 633 | // 2 pixels for the box around the drawing area, 1 pixel for off-by-one |
| 634 | // (starting from 0) |
| 635 | //gdk_gc_copy (&GC, widget->style->fg_gc[GTK_WIDGET_STATE (widget)]); |
| 636 | |
| 637 | gdk_gc_set_line_attributes(GC,12, GDK_LINE_SOLID, GDK_CAP_NOT_LAST,GDK_JOIN_MITER); |
| 638 | |
| 639 | gdk_draw_line (widget->window, |
| 640 | GC, |
| 641 | 0, (cell_height-1)/2, |
| 642 | widget->allocation.width, (cell_height-1)/2); |
| 643 | |
| 644 | color = CF_Colors[BLUE]; |
| 645 | |
| 646 | gdk_color_alloc (gdk_colormap_get_system () , &color); |
| 647 | |
| 648 | gdk_gc_set_foreground(GC,&color); |
| 649 | |
| 650 | |
| 651 | gdk_gc_set_line_attributes(GC,3, GDK_LINE_SOLID, GDK_CAP_NOT_LAST,GDK_JOIN_MITER); |
| 652 | |
| 653 | gdk_draw_line (widget->window, |
| 654 | GC, |
| 655 | 0, (cell_height-1)/2, |
| 656 | widget->allocation.width,(cell_height-1)/2); |
| 657 | |
| 658 | |
| 659 | |
| 660 | |
| 661 | |
| 662 | |
| 663 | g_object_unref(GC); |
| 664 | |
| 665 | //gdk_colormap_alloc_colors(gdk_colormap_get_system(), TRUE, |
| 666 | |
| 667 | //gdk_gc_set_line_attributes(GC,5, GDK_LINE_SOLID, GDK_CAP_NOT_LAST,GDK_JOIN_MITER); |
| 668 | //gdk_gc_set_foreground(GC, |
| 669 | |
| 670 | //gdk_draw_line (widget->window, |
| 671 | // GC, |
| 672 | // 0, (2*cell_height)-2-1, |
| 673 | // 50, (2*cell_height)-2-1); |
| 674 | |
| 675 | } |
| 676 | #endif //DEBUG |
| 677 | |
| 678 | void v_scroll_cb (GtkAdjustment *adjustment, gpointer data) |
| 679 | { |
| 680 | ControlFlowData *Control_Flow_Data = (ControlFlowData*)data; |
| 681 | GtkTreePath *Tree_Path; |
| 682 | |
| 683 | g_critical("DEBUG : scroll signal, value : %f", adjustment->value); |
| 684 | |
| 685 | //get_test_data((int)adjustment->value, Control_Flow_Data->Num_Visible_Events, |
| 686 | // Control_Flow_Data); |
| 687 | |
| 688 | |
| 689 | |
| 690 | } |
| 691 | |
| 692 | |
| 693 | |
| 694 | |
| 695 | |
| 696 | |
| 697 | static void destroy_cb( GtkWidget *widget, |
| 698 | gpointer data ) |
| 699 | { |
| 700 | gtk_main_quit (); |
| 701 | } |
| 702 | |
| 703 | |
| 704 | |
| 705 | /***************************************************************************** |
| 706 | * test routines * |
| 707 | *****************************************************************************/ |
| 708 | |
| 709 | |
| 710 | int main(int argc, char **argv) |
| 711 | { |
| 712 | GtkWidget *Window; |
| 713 | GtkWidget *CF_Viewer; |
| 714 | GtkWidget *VBox_V; |
| 715 | GtkWidget *HScroll_VC; |
| 716 | ControlFlowData *Control_Flow_Data; |
| 717 | guint ev_sel = 444 ; |
| 718 | /* Horizontal scrollbar and it's adjustment */ |
| 719 | GtkWidget *VScroll_VC; |
| 720 | GtkAdjustment *VAdjust_C ; |
| 721 | |
| 722 | /* Initialize i18n support */ |
| 723 | gtk_set_locale (); |
| 724 | |
| 725 | /* Initialize the widget set */ |
| 726 | gtk_init (&argc, &argv); |
| 727 | |
| 728 | init(); |
| 729 | |
| 730 | Window = gtk_window_new (GTK_WINDOW_TOPLEVEL); |
| 731 | gtk_window_set_title (GTK_WINDOW (Window), ("Test Window")); |
| 732 | |
| 733 | g_signal_connect (G_OBJECT (Window), "destroy", |
| 734 | G_CALLBACK (destroy_cb), NULL); |
| 735 | |
| 736 | |
| 737 | VBox_V = gtk_vbox_new(0, 0); |
| 738 | gtk_container_add (GTK_CONTAINER (Window), VBox_V); |
| 739 | |
| 740 | //ListViewer = hGuiEvents(Window); |
| 741 | //gtk_box_pack_start(GTK_BOX(VBox_V), ListViewer, TRUE, TRUE, 0); |
| 742 | |
| 743 | //ListViewer = hGuiEvents(Window); |
| 744 | //gtk_box_pack_start(GTK_BOX(VBox_V), ListViewer, FALSE, TRUE, 0); |
| 745 | |
| 746 | Control_Flow_Data = GuiControlFlow(); |
| 747 | CF_Viewer = Control_Flow_Data->Scrolled_Window_VC; |
| 748 | gtk_box_pack_start(GTK_BOX(VBox_V), CF_Viewer, TRUE, TRUE, 0); |
| 749 | |
| 750 | /* Create horizontal scrollbar and pack it */ |
| 751 | HScroll_VC = gtk_hscrollbar_new(NULL); |
| 752 | gtk_box_pack_start(GTK_BOX(VBox_V), HScroll_VC, FALSE, TRUE, 0); |
| 753 | |
| 754 | |
| 755 | gtk_widget_show (HScroll_VC); |
| 756 | gtk_widget_show (VBox_V); |
| 757 | gtk_widget_show (Window); |
| 758 | |
| 759 | //Event_Selected_Hook(Control_Flow_Data, &ev_sel); |
| 760 | |
| 761 | gtk_main (); |
| 762 | |
| 763 | g_critical("main loop finished"); |
| 764 | |
| 765 | //hGuiEvents_Destructor(ListViewer); |
| 766 | |
| 767 | //g_critical("GuiEvents Destructor finished"); |
| 768 | destroy(); |
| 769 | |
| 770 | return 0; |
| 771 | } |
| 772 | |
| 773 | /*\@}*/ |