17abcce3 |
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> |
f60d7a47 |
22 | #include <gtk/gtk.h> |
23 | #include <gdk/gdk.h> |
17abcce3 |
24 | |
f60d7a47 |
25 | #include <lttv/hook.h> |
17abcce3 |
26 | #include <lttv/module.h> |
27 | |
f60d7a47 |
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 | |
b213628c |
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 | |
f60d7a47 |
47 | typedef struct _DrawingAreaInfo { |
48 | |
49 | guint height, width; |
50 | |
51 | } DrawingAreaInfo ; |
52 | |
53 | typedef struct _ControlFlowData { |
54 | |
55 | GtkWidget *Drawing_Area_V; |
b213628c |
56 | GtkWidget *Scrolled_Window_VC; |
f60d7a47 |
57 | |
58 | GtkWidget *Process_List_VC; |
f60d7a47 |
59 | |
60 | /* Model containing list data */ |
61 | GtkListStore *Store_M; |
62 | |
63 | GtkWidget *HBox_V; |
b213628c |
64 | GtkWidget *Inside_HBox_V; |
f60d7a47 |
65 | |
66 | GtkAdjustment *VAdjust_C ; |
67 | |
b213628c |
68 | /* Trace information */ |
69 | TraceSet *Trace_Set; |
70 | TraceStatistics *Trace_Statistics; |
71 | |
72 | /* Shown events information */ |
f60d7a47 |
73 | guint First_Event, Last_Event; |
b213628c |
74 | ltt_time Begin_Time, End_Time; |
75 | |
f60d7a47 |
76 | |
77 | /* Drawing Area Info */ |
78 | DrawingAreaInfo Drawing_Area_Info; |
b213628c |
79 | |
f60d7a47 |
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 | |
b213628c |
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 | |
f60d7a47 |
103 | |
104 | /** Array containing instanced objects. Used when module is unloaded */ |
105 | static GSList *sControl_Flow_Data_List = NULL ; |
106 | |
107 | |
b213628c |
108 | /***************************************************************************** |
109 | * Function prototypes * |
110 | *****************************************************************************/ |
f60d7a47 |
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 | |
b213628c |
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 | |
f60d7a47 |
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 | |
17abcce3 |
155 | |
b213628c |
156 | /***************************************************************************** |
157 | * Functions for module loading/unloading * |
158 | *****************************************************************************/ |
17abcce3 |
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 */ |
f60d7a47 |
169 | //ToolbarItemReg(guiEventsInsert_xpm, "Insert Control Flow Viewer", guiEvent); |
17abcce3 |
170 | |
171 | /* Register the menu item insert entry */ |
f60d7a47 |
172 | //MenuItemReg("/", "Insert Control Flow Viewer", guiEvent); |
17abcce3 |
173 | |
b213628c |
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 | |
17abcce3 |
183 | } |
184 | |
f60d7a47 |
185 | void destroy_walk(gpointer data, gpointer user_data) |
186 | { |
187 | GuiControlFlow_Destructor((ControlFlowData*)data); |
188 | } |
189 | |
190 | |
191 | |
17abcce3 |
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()"); |
f60d7a47 |
200 | int i; |
201 | |
202 | ControlFlowData *Control_Flow_Data; |
203 | |
204 | g_critical("GUI Event Viewer destroy()"); |
17abcce3 |
205 | |
f60d7a47 |
206 | g_slist_foreach(sControl_Flow_Data_List, destroy_walk, NULL ); |
207 | |
b213628c |
208 | lttv_hooks_destroy(Draw_Before_Hooks); |
209 | lttv_hooks_destroy(Draw_Event_Hooks); |
210 | lttv_hooks_destroy(Draw_After_Hooks); |
211 | |
17abcce3 |
212 | /* Unregister the toolbar insert button */ |
f60d7a47 |
213 | //ToolbarItemUnreg(hGuiEvents); |
17abcce3 |
214 | |
215 | /* Unregister the menu item insert entry */ |
f60d7a47 |
216 | //MenuItemUnreg(hGuiEvents); |
17abcce3 |
217 | } |
218 | |
f60d7a47 |
219 | |
b213628c |
220 | /***************************************************************************** |
221 | * Control Flow Viewer class implementation * |
222 | *****************************************************************************/ |
f60d7a47 |
223 | |
224 | |
225 | /* Enumeration of the columns */ |
226 | enum |
227 | { |
228 | PROCESS_COLUMN, |
229 | N_COLUMNS |
230 | }; |
231 | |
232 | |
233 | |
17abcce3 |
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 | */ |
f60d7a47 |
242 | ControlFlowData * |
243 | GuiControlFlow(void) |
17abcce3 |
244 | { |
17abcce3 |
245 | |
f60d7a47 |
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 | |
b213628c |
252 | |
f60d7a47 |
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 | |
b213628c |
288 | Control_Flow_Data->Inside_HBox_V = gtk_hbox_new(0, 0); |
f60d7a47 |
289 | |
b213628c |
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); |
f60d7a47 |
292 | |
293 | |
b213628c |
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 */ |
f60d7a47 |
300 | |
f60d7a47 |
301 | |
b213628c |
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); |
f60d7a47 |
307 | |
b213628c |
308 | gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(Control_Flow_Data->Scrolled_Window_VC), |
309 | Control_Flow_Data->Inside_HBox_V); |
f60d7a47 |
310 | |
f60d7a47 |
311 | |
f60d7a47 |
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 | |
f60d7a47 |
317 | g_signal_connect (G_OBJECT (Control_Flow_Data->VAdjust_C), "value-changed", |
318 | G_CALLBACK (v_scroll_cb), |
319 | Control_Flow_Data); |
f60d7a47 |
320 | |
b213628c |
321 | add_test_process(Control_Flow_Data); |
f60d7a47 |
322 | |
f60d7a47 |
323 | |
f60d7a47 |
324 | |
b213628c |
325 | /* Set the size of the drawing area */ |
326 | Drawing_Area_Init(Control_Flow_Data); |
f60d7a47 |
327 | |
b213628c |
328 | /* Get trace statistics */ |
329 | Control_Flow_Data->Trace_Statistics = get_trace_statistics(Trace); |
f60d7a47 |
330 | |
331 | |
b213628c |
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); |
f60d7a47 |
336 | |
b213628c |
337 | test_draw(Control_Flow_Data); |
f60d7a47 |
338 | |
b213628c |
339 | return Control_Flow_Data; |
f60d7a47 |
340 | |
b213628c |
341 | } |
f60d7a47 |
342 | |
b213628c |
343 | void |
344 | GuiControlFlow_Destructor(ControlFlowData *Control_Flow_Data) |
345 | { |
346 | guint index; |
f60d7a47 |
347 | |
b213628c |
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)); |
f60d7a47 |
358 | |
b213628c |
359 | g_slist_remove(sControl_Flow_Data_List,Control_Flow_Data); |
360 | } |
f60d7a47 |
361 | |
b213628c |
362 | //FIXME : call hGuiEvents_Destructor for corresponding data upon widget destroy |
f60d7a47 |
363 | |
f60d7a47 |
364 | |
365 | |
b213628c |
366 | /***************************************************************************** |
367 | * Drawing functions * |
368 | *****************************************************************************/ |
f60d7a47 |
369 | |
b213628c |
370 | typedef enum |
371 | { |
372 | RED, |
373 | GREEN, |
374 | BLUE, |
375 | WHITE, |
376 | BLACK |
f60d7a47 |
377 | |
b213628c |
378 | } ControlFlowColors; |
f60d7a47 |
379 | |
b213628c |
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 | }; |
f60d7a47 |
389 | |
17abcce3 |
390 | |
f60d7a47 |
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 | |
b213628c |
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) |
f60d7a47 |
415 | { |
b213628c |
416 | ltt_time window_time_interval; |
f60d7a47 |
417 | |
b213628c |
418 | TimeSub(window_time_interval, window_time_end, window_time_begin); |
f60d7a47 |
419 | |
f60d7a47 |
420 | |
b213628c |
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); |
f60d7a47 |
426 | |
427 | } |
17abcce3 |
428 | |
b213628c |
429 | void Drawing_Area_Init(ControlFlowData *Control_Flow_Data) |
f60d7a47 |
430 | { |
b213628c |
431 | DrawingAreaInfo *Drawing_Area_Info = &Control_Flow_Data->Drawing_Area_Info; |
432 | guint w; |
f60d7a47 |
433 | |
b213628c |
434 | w = 500; |
f60d7a47 |
435 | |
f60d7a47 |
436 | |
b213628c |
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 ; |
f60d7a47 |
440 | |
b213628c |
441 | gtk_widget_modify_bg(Control_Flow_Data->Drawing_Area_V, |
442 | GTK_STATE_NORMAL, |
443 | &CF_Colors[BLACK]); |
444 | |
f60d7a47 |
445 | |
b213628c |
446 | gtk_widget_set_size_request (Control_Flow_Data->Drawing_Area_V, |
447 | w, |
448 | Drawing_Area_Info->height); |
f60d7a47 |
449 | |
450 | |
f60d7a47 |
451 | } |
452 | |
453 | |
454 | |
f60d7a47 |
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 | |
b213628c |
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) |
f60d7a47 |
501 | { |
b213628c |
502 | ControlFlowData* Control_Flow_Data = GuiControlFlow() ; |
f60d7a47 |
503 | |
b213628c |
504 | return Control_Flow_Data->HBox_V ; |
505 | |
f60d7a47 |
506 | } |
507 | |
b213628c |
508 | int Event_Selected_Hook(void *hook_data, void *call_data) |
f60d7a47 |
509 | { |
b213628c |
510 | ControlFlowData *Control_Flow_Data = (ControlFlowData*) hook_data; |
511 | guint *Event_Number = (guint*) call_data; |
f60d7a47 |
512 | |
b213628c |
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); |
f60d7a47 |
519 | |
b213628c |
520 | } |
f60d7a47 |
521 | |
f60d7a47 |
522 | |
b213628c |
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; |
f60d7a47 |
532 | } |
f60d7a47 |
533 | |
b213628c |
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) |
f60d7a47 |
555 | { |
b213628c |
556 | EventRequest *Event_Request = (EventRequest*)hook_data; |
f60d7a47 |
557 | |
f60d7a47 |
558 | } |
559 | |
f60d7a47 |
560 | |
b213628c |
561 | Draw_After_Hook(void *hook_data, void *call_data) |
562 | { |
563 | EventRequest *Event_Request = (EventRequest*)hook_data; |
564 | |
565 | g_free(Event_Request); |
f60d7a47 |
566 | } |
567 | |
b213628c |
568 | /***************************************************************************** |
569 | * Callbacks used for the viewer * |
570 | *****************************************************************************/ |
571 | void expose_event_cb (GtkWidget *widget, GdkEventExpose *expose, gpointer data) |
f60d7a47 |
572 | { |
573 | ControlFlowData *Control_Flow_Data = (ControlFlowData*)data; |
f60d7a47 |
574 | |
b213628c |
575 | EventRequest *Event_Request = g_new(sizeof(EventRequest)); |
f60d7a47 |
576 | |
b213628c |
577 | Event_Request->Control_Flow_Data = Control_Flow_Data; |
f60d7a47 |
578 | |
b213628c |
579 | /* Calculate, from pixels in expose, the time interval to get data */ |
f60d7a47 |
580 | |
b213628c |
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); |
f60d7a47 |
600 | |
601 | } |
602 | |
b213628c |
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]; |
f60d7a47 |
608 | |
b213628c |
609 | gdk_color_alloc (gdk_colormap_get_system () , &color); |
f60d7a47 |
610 | |
b213628c |
611 | g_critical("expose"); |
f60d7a47 |
612 | |
b213628c |
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; |
f60d7a47 |
616 | |
b213628c |
617 | test_draw(Control_Flow_Data); |
f60d7a47 |
618 | |
b213628c |
619 | gdk_gc_copy(GC,widget->style->white_gc); |
620 | gdk_gc_set_foreground(GC,&color); |
f60d7a47 |
621 | |
b213628c |
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); |
f60d7a47 |
629 | |
f60d7a47 |
630 | |
b213628c |
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)]); |
f60d7a47 |
636 | |
b213628c |
637 | gdk_gc_set_line_attributes(GC,12, GDK_LINE_SOLID, GDK_CAP_NOT_LAST,GDK_JOIN_MITER); |
f60d7a47 |
638 | |
b213628c |
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]; |
f60d7a47 |
645 | |
b213628c |
646 | gdk_color_alloc (gdk_colormap_get_system () , &color); |
f60d7a47 |
647 | |
b213628c |
648 | gdk_gc_set_foreground(GC,&color); |
f60d7a47 |
649 | |
b213628c |
650 | |
651 | gdk_gc_set_line_attributes(GC,3, GDK_LINE_SOLID, GDK_CAP_NOT_LAST,GDK_JOIN_MITER); |
f60d7a47 |
652 | |
b213628c |
653 | gdk_draw_line (widget->window, |
654 | GC, |
655 | 0, (cell_height-1)/2, |
656 | widget->allocation.width,(cell_height-1)/2); |
f60d7a47 |
657 | |
f60d7a47 |
658 | |
f60d7a47 |
659 | |
f60d7a47 |
660 | |
f60d7a47 |
661 | |
f60d7a47 |
662 | |
b213628c |
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); |
f60d7a47 |
674 | |
f60d7a47 |
675 | } |
676 | #endif //DEBUG |
677 | |
b213628c |
678 | void v_scroll_cb (GtkAdjustment *adjustment, gpointer data) |
f60d7a47 |
679 | { |
b213628c |
680 | ControlFlowData *Control_Flow_Data = (ControlFlowData*)data; |
681 | GtkTreePath *Tree_Path; |
f60d7a47 |
682 | |
b213628c |
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); |
f60d7a47 |
687 | |
f60d7a47 |
688 | |
f60d7a47 |
689 | |
690 | } |
691 | |
692 | |
693 | |
b213628c |
694 | |
695 | |
696 | |
f60d7a47 |
697 | static void destroy_cb( GtkWidget *widget, |
698 | gpointer data ) |
699 | { |
700 | gtk_main_quit (); |
701 | } |
702 | |
703 | |
704 | |
b213628c |
705 | /***************************************************************************** |
706 | * test routines * |
707 | *****************************************************************************/ |
708 | |
709 | |
f60d7a47 |
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(); |
b213628c |
747 | CF_Viewer = Control_Flow_Data->Scrolled_Window_VC; |
f60d7a47 |
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 | |
17abcce3 |
773 | /*\@}*/ |