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 | |
37 | typedef struct _DrawingAreaInfo { |
38 | |
39 | guint height, width; |
40 | |
41 | } DrawingAreaInfo ; |
42 | |
43 | typedef struct _ControlFlowData { |
44 | |
45 | GtkWidget *Drawing_Area_V; |
46 | GtkWidget *Drawing_Scrolled_Window_VC; |
47 | GtkAdjustment *VAdjust_Draw_C; |
48 | |
49 | GtkWidget *Process_List_VC; |
50 | GtkWidget *Process_Scrolled_Window_VC; |
51 | |
52 | /* Model containing list data */ |
53 | GtkListStore *Store_M; |
54 | |
55 | GtkWidget *HBox_V; |
56 | |
57 | GtkAdjustment *VAdjust_C ; |
58 | |
59 | guint First_Event, Last_Event; |
60 | ltt_time Begin_time, End_Time; |
61 | |
62 | /* Drawing Area Info */ |
63 | DrawingAreaInfo Drawing_Area_Info; |
64 | |
65 | /* TEST DATA, TO BE READ FROM THE TRACE */ |
66 | gint Number_Of_Events ; |
67 | guint Currently_Selected_Event ; |
68 | gboolean Selected_Event ; |
69 | guint Number_Of_Process; |
70 | |
71 | } ControlFlowData ; |
72 | |
73 | |
74 | /** Array containing instanced objects. Used when module is unloaded */ |
75 | static GSList *sControl_Flow_Data_List = NULL ; |
76 | |
77 | |
78 | //! Control Flow Viewer's constructor hook |
79 | GtkWidget *hGuiControlFlow(GtkWidget *pmParentWindow); |
80 | //! Control Flow Viewer's constructor |
81 | ControlFlowData *GuiControlFlow(void); |
82 | //! Control Flow Viewer's destructor |
83 | void GuiControlFlow_Destructor(ControlFlowData *Control_Flow_Data); |
84 | |
85 | |
86 | static int Event_Selected_Hook(void *hook_data, void *call_data); |
87 | |
88 | //void Tree_V_set_cursor(ControlFlowData *Control_Flow_Data); |
89 | //void Tree_V_get_cursor(ControlFlowData *Control_Flow_Data); |
90 | |
91 | /* Prototype for selection handler callback */ |
92 | //static void tree_selection_changed_cb (GtkTreeSelection *selection, gpointer data); |
93 | static void v_scroll_cb (GtkAdjustment *adjustment, gpointer data); |
94 | //static void Tree_V_size_allocate_cb (GtkWidget *widget, GtkAllocation *alloc, gpointer data); |
95 | //static void Tree_V_size_request_cb (GtkWidget *widget, GtkRequisition *requisition, gpointer data); |
96 | //static void Tree_V_cursor_changed_cb (GtkWidget *widget, gpointer data); |
97 | //static void Tree_V_move_cursor_cb (GtkWidget *widget, GtkMovementStep arg1, gint arg2, gpointer data); |
98 | |
99 | static void expose_event_cb (GtkWidget *widget, GdkEventExpose *expose, gpointer data); |
100 | |
101 | void add_test_process(ControlFlowData *Control_Flow_Data); |
102 | |
103 | static void get_test_data(guint Event_Number, guint List_Height, |
104 | ControlFlowData *Control_Flow_Data); |
105 | |
106 | void add_test_data(ControlFlowData *Control_Flow_Data); |
107 | void test_draw(ControlFlowData *Control_Flow_Data); |
108 | |
109 | void Drawing_Area_Init(ControlFlowData *Control_Flow_Data); |
110 | |
111 | |
17abcce3 |
112 | |
17abcce3 |
113 | |
114 | /** |
115 | * plugin's init function |
116 | * |
117 | * This function initializes the Control Flow Viewer functionnality through the |
118 | * gtkTraceSet API. |
119 | */ |
120 | G_MODULE_EXPORT void init() { |
121 | g_critical("GUI ControlFlow Viewer init()"); |
122 | |
123 | /* Register the toolbar insert button */ |
f60d7a47 |
124 | //ToolbarItemReg(guiEventsInsert_xpm, "Insert Control Flow Viewer", guiEvent); |
17abcce3 |
125 | |
126 | /* Register the menu item insert entry */ |
f60d7a47 |
127 | //MenuItemReg("/", "Insert Control Flow Viewer", guiEvent); |
17abcce3 |
128 | |
129 | } |
130 | |
f60d7a47 |
131 | void destroy_walk(gpointer data, gpointer user_data) |
132 | { |
133 | GuiControlFlow_Destructor((ControlFlowData*)data); |
134 | } |
135 | |
136 | |
137 | |
17abcce3 |
138 | /** |
139 | * plugin's destroy function |
140 | * |
141 | * This function releases the memory reserved by the module and unregisters |
142 | * everything that has been registered in the gtkTraceSet API. |
143 | */ |
144 | G_MODULE_EXPORT void destroy() { |
145 | g_critical("GUI Control Flow Viewer destroy()"); |
f60d7a47 |
146 | int i; |
147 | |
148 | ControlFlowData *Control_Flow_Data; |
149 | |
150 | g_critical("GUI Event Viewer destroy()"); |
17abcce3 |
151 | |
f60d7a47 |
152 | g_slist_foreach(sControl_Flow_Data_List, destroy_walk, NULL ); |
153 | |
17abcce3 |
154 | /* Unregister the toolbar insert button */ |
f60d7a47 |
155 | //ToolbarItemUnreg(hGuiEvents); |
17abcce3 |
156 | |
157 | /* Unregister the menu item insert entry */ |
f60d7a47 |
158 | //MenuItemUnreg(hGuiEvents); |
17abcce3 |
159 | } |
160 | |
f60d7a47 |
161 | /** |
162 | * Event Viewer's constructor hook |
163 | * |
164 | * This constructor is given as a parameter to the menuitem and toolbar button |
165 | * registration. It creates the list. |
166 | * @param pmParentWindow A pointer to the parent window. |
167 | * @return The widget created. |
168 | */ |
169 | GtkWidget * |
170 | hGuiControlFlow(GtkWidget *pmParentWindow) |
171 | { |
172 | ControlFlowData* Control_Flow_Data = GuiControlFlow() ; |
173 | |
174 | return Control_Flow_Data->HBox_V ; |
175 | |
176 | } |
177 | |
178 | |
179 | |
180 | /* Enumeration of the columns */ |
181 | enum |
182 | { |
183 | PROCESS_COLUMN, |
184 | N_COLUMNS |
185 | }; |
186 | |
187 | |
188 | |
17abcce3 |
189 | /** |
190 | * Control Flow Viewer's constructor |
191 | * |
192 | * This constructor is given as a parameter to the menuitem and toolbar button |
193 | * registration. It creates the drawing widget. |
194 | * @param ParentWindow A pointer to the parent window. |
195 | * @return The widget created. |
196 | */ |
f60d7a47 |
197 | ControlFlowData * |
198 | GuiControlFlow(void) |
17abcce3 |
199 | { |
17abcce3 |
200 | |
f60d7a47 |
201 | GtkTreeViewColumn *column; |
202 | GtkCellRenderer *renderer; |
203 | |
204 | ControlFlowData* Control_Flow_Data = g_new(ControlFlowData,1) ; |
205 | Control_Flow_Data->Drawing_Area_V = gtk_drawing_area_new (); |
206 | |
207 | /* TEST DATA, TO BE READ FROM THE TRACE */ |
208 | Control_Flow_Data->Number_Of_Events = 1000 ; |
209 | Control_Flow_Data->Currently_Selected_Event = FALSE ; |
210 | Control_Flow_Data->Selected_Event = 0; |
211 | Control_Flow_Data->Number_Of_Process = 10; |
212 | |
213 | /* FIXME register Event_Selected_Hook */ |
214 | |
215 | |
216 | |
217 | /* Create the Process list */ |
218 | Control_Flow_Data->Store_M = gtk_list_store_new ( N_COLUMNS, |
219 | G_TYPE_STRING); |
220 | |
221 | |
222 | Control_Flow_Data->Process_List_VC = gtk_tree_view_new_with_model (GTK_TREE_MODEL (Control_Flow_Data->Store_M)); |
223 | |
224 | g_object_unref (G_OBJECT (Control_Flow_Data->Store_M)); |
225 | |
226 | gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(Control_Flow_Data->Process_List_VC), FALSE); |
227 | |
228 | /* Create a column, associating the "text" attribute of the |
229 | * cell_renderer to the first column of the model */ |
230 | /* Columns alignment : 0.0 : Left 0.5 : Center 1.0 : Right */ |
231 | renderer = gtk_cell_renderer_text_new (); |
232 | column = gtk_tree_view_column_new_with_attributes ("Process", |
233 | renderer, |
234 | "text", PROCESS_COLUMN, |
235 | NULL); |
236 | gtk_tree_view_column_set_alignment (column, 0.0); |
237 | gtk_tree_view_column_set_fixed_width (column, 45); |
238 | gtk_tree_view_append_column (GTK_TREE_VIEW (Control_Flow_Data->Process_List_VC), column); |
239 | |
240 | |
241 | |
242 | /* Create the two scrolled windows with the same adjustment */ |
243 | Control_Flow_Data->Process_Scrolled_Window_VC = gtk_scrolled_window_new(NULL, NULL); |
244 | |
245 | Control_Flow_Data->VAdjust_C = gtk_scrolled_window_get_vadjustment( |
246 | GTK_SCROLLED_WINDOW(Control_Flow_Data->Process_Scrolled_Window_VC)); |
247 | |
248 | gtk_scrolled_window_set_policy( |
249 | GTK_SCROLLED_WINDOW(Control_Flow_Data->Process_Scrolled_Window_VC), |
250 | GTK_POLICY_NEVER, |
251 | // GTK_POLICY_NEVER); |
252 | GTK_POLICY_AUTOMATIC); |
253 | |
254 | |
255 | |
256 | Control_Flow_Data->Drawing_Scrolled_Window_VC = gtk_scrolled_window_new(NULL,Control_Flow_Data->VAdjust_C); |
257 | //Control_Flow_Data->Drawing_Scrolled_Window_VC = gtk_scrolled_window_new(NULL,NULL); |
258 | gtk_scrolled_window_set_policy( |
259 | GTK_SCROLLED_WINDOW(Control_Flow_Data->Drawing_Scrolled_Window_VC), |
260 | GTK_POLICY_NEVER, |
261 | // GTK_POLICY_NEVER); |
262 | GTK_POLICY_AUTOMATIC); |
263 | |
264 | Control_Flow_Data->VAdjust_Draw_C = gtk_scrolled_window_get_vadjustment( |
265 | GTK_SCROLLED_WINDOW(Control_Flow_Data->Drawing_Scrolled_Window_VC)); |
266 | |
267 | gtk_container_add(GTK_CONTAINER(Control_Flow_Data->Process_Scrolled_Window_VC), |
268 | Control_Flow_Data->Process_List_VC); |
269 | |
270 | |
271 | gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(Control_Flow_Data->Drawing_Scrolled_Window_VC), |
272 | Control_Flow_Data->Drawing_Area_V); |
273 | |
274 | |
275 | Control_Flow_Data->HBox_V = gtk_hbox_new(0, 0); |
276 | |
277 | |
278 | |
279 | |
280 | /* Pack the list and the drawing area in the hbox */ |
281 | |
282 | gtk_box_pack_start(GTK_BOX(Control_Flow_Data->HBox_V), Control_Flow_Data->Process_Scrolled_Window_VC, TRUE, TRUE, 0); |
283 | gtk_box_pack_start(GTK_BOX(Control_Flow_Data->HBox_V), Control_Flow_Data->Drawing_Scrolled_Window_VC, TRUE, TRUE, 0); |
284 | |
285 | |
286 | g_signal_connect (G_OBJECT (Control_Flow_Data->Drawing_Area_V), "expose_event", |
287 | G_CALLBACK (expose_event_cb), Control_Flow_Data); |
288 | |
289 | |
290 | |
291 | #ifdef DEBUG |
17abcce3 |
292 | g_signal_connect (G_OBJECT (drawing_area), "expose_event", |
f60d7a47 |
293 | G_CALLBACK (expose_event_callback), Control_Flow_Data); |
294 | |
295 | |
296 | |
297 | Control_Flow_Data->VAdjust_C = gtk_range_get_adjustment(GTK_RANGE(Control_Flow_Data->VScroll_VC)); |
298 | |
299 | g_signal_connect (G_OBJECT (Control_Flow_Data->VAdjust_C), "value-changed", |
300 | G_CALLBACK (v_scroll_cb), |
301 | Control_Flow_Data); |
302 | /* Set the upper bound to the last event number */ |
303 | Control_Flow_Data->VAdjust_C->lower = 0; |
304 | Control_Flow_Data->VAdjust_C->upper = Control_Flow_Data->Number_Of_Events; |
305 | Control_Flow_Data->VAdjust_C->value = 0; |
306 | Control_Flow_Data->VAdjust_C->step_increment = 1; |
307 | Control_Flow_Data->VAdjust_C->page_increment = |
308 | Control_Flow_Data->VTree_Adjust_C->upper; |
309 | Control_Flow_Data->VAdjust_C->page_size = |
310 | Control_Flow_Data->VTree_Adjust_C->upper; |
311 | g_critical("value : %u",Control_Flow_Data->VTree_Adjust_C->upper); |
312 | |
313 | |
314 | |
315 | |
316 | /* Add the object's information to the module's array */ |
317 | g_slist_append(sControl_Flow_Data_List, Control_Flow_Data); |
318 | |
319 | Control_Flow_Data->First_Event = -1 ; |
320 | Control_Flow_Data->Last_Event = 0 ; |
321 | |
322 | Control_Flow_Data->Num_Visible_Events = 1; |
323 | |
324 | /* Test data */ |
325 | get_test_data((int)Control_Flow_Data->VAdjust_C->value, |
326 | Control_Flow_Data->Num_Visible_Events, |
327 | Control_Flow_Data); |
328 | |
329 | /* Set the Selected Event */ |
330 | //Tree_V_set_cursor(Control_Flow_Data); |
331 | #endif //DEBUG |
332 | |
333 | |
334 | g_signal_connect (G_OBJECT (Control_Flow_Data->VAdjust_C), "value-changed", |
335 | G_CALLBACK (v_scroll_cb), |
336 | Control_Flow_Data); |
337 | g_signal_connect (G_OBJECT (Control_Flow_Data->VAdjust_Draw_C), "value-changed", |
338 | G_CALLBACK (v_scroll_cb), |
339 | Control_Flow_Data); |
340 | |
341 | |
342 | |
343 | |
344 | add_test_process(Control_Flow_Data); |
345 | |
346 | |
347 | |
348 | /* Set the size of the drawing area */ |
349 | Drawing_Area_Init(Control_Flow_Data); |
350 | |
351 | |
352 | |
353 | |
354 | gtk_widget_show(Control_Flow_Data->Drawing_Area_V); |
355 | gtk_widget_show(Control_Flow_Data->Process_List_VC); |
356 | gtk_widget_show(Control_Flow_Data->Process_Scrolled_Window_VC); |
357 | gtk_widget_show(Control_Flow_Data->Drawing_Scrolled_Window_VC); |
358 | gtk_widget_show(Control_Flow_Data->HBox_V); |
359 | |
360 | |
361 | test_draw(Control_Flow_Data); |
362 | |
363 | return Control_Flow_Data; |
364 | |
17abcce3 |
365 | } |
366 | |
f60d7a47 |
367 | gint get_cell_height(GtkTreeView *TreeView) |
368 | { |
369 | gint height, width; |
370 | GtkTreeViewColumn *Column = gtk_tree_view_get_column(TreeView, 0); |
371 | GList *Render_List = gtk_tree_view_column_get_cell_renderers(Column); |
372 | GtkCellRenderer *Renderer = g_list_first(Render_List)->data; |
373 | |
374 | gtk_tree_view_column_cell_get_size(Column, NULL, NULL, NULL, NULL, &height); |
375 | g_critical("cell 0 height : %u",height); |
376 | |
377 | return height; |
378 | } |
379 | |
380 | |
381 | void Drawing_Area_Init(ControlFlowData *Control_Flow_Data) |
382 | { |
383 | DrawingAreaInfo *Drawing_Area_Info = &Control_Flow_Data->Drawing_Area_Info; |
384 | guint w; |
385 | //GdkWindow *Tree_View_Window = gtk_tree_view_get_bin_window( |
386 | // GTK_TREE_VIEW(Control_Flow_Data->Process_List_VC)); |
387 | //GdkRectangle visible_rect ; |
388 | w = 500; |
389 | |
390 | |
391 | //gdk_drawable_get_size(Tree_View_Window, NULL, &h); |
392 | //gdk_drawable_get_size(GTK_TREE_VIEW(Control_Flow_Data->Process_List_VC)->priv->bin_window, NULL, &h); |
393 | //gtk_widget_get_size_request(GTK_WIDGET(Control_Flow_Data->Process_Scrolled_Window_VC), NULL, &h); |
394 | //gdk_window_get_geometry(Tree_View_Window, NULL, NULL, &w, &h, NULL); |
395 | //gtk_tree_view_get_visible_rect(GTK_TREE_VIEW(Control_Flow_Data->Process_List_VC), &visible_rect); |
396 | //h = visible_rect.height; |
397 | /* 4 is probably the 2 pixels that the outside cells does not have */ |
398 | Drawing_Area_Info->height = |
399 | get_cell_height(GTK_TREE_VIEW(Control_Flow_Data->Process_List_VC)) |
400 | * Control_Flow_Data->Number_Of_Process - 4 ; |
401 | |
402 | gtk_widget_set_size_request (Control_Flow_Data->Drawing_Area_V, |
403 | w, |
404 | Drawing_Area_Info->height); |
405 | |
406 | |
407 | } |
17abcce3 |
408 | |
409 | |
f60d7a47 |
410 | void expose_event_cb (GtkWidget *widget, GdkEventExpose *expose, gpointer data) |
411 | { |
412 | ControlFlowData *Control_Flow_Data = (ControlFlowData*)data; |
413 | |
414 | g_critical("expose"); |
415 | |
416 | /* When redrawing, use widget->allocation.width to get the width of |
417 | * drawable area. */ |
418 | Control_Flow_Data->Drawing_Area_Info.width = widget->allocation.width; |
419 | |
420 | test_draw(Control_Flow_Data); |
421 | |
422 | //gdk_draw_arc (widget->window, |
423 | // widget->style->fg_gc[GTK_WIDGET_STATE (widget)], |
424 | // TRUE, |
425 | // //0, 0, widget->allocation.width, widget->allocation.height, |
426 | // 0, 0, widget->allocation.width, |
427 | // Control_Flow_Data->Drawing_Area_Info.height, |
428 | // 0, 64 * 360); |
429 | |
430 | |
431 | //Drawing_Area_Init(Control_Flow_Data); |
432 | |
433 | |
434 | } |
435 | |
436 | |
437 | void v_scroll_cb (GtkAdjustment *adjustment, gpointer data) |
438 | { |
439 | ControlFlowData *Control_Flow_Data = (ControlFlowData*)data; |
440 | GtkTreePath *Tree_Path; |
441 | |
442 | g_critical("DEBUG : scroll signal, value : %f", adjustment->value); |
443 | |
444 | //get_test_data((int)adjustment->value, Control_Flow_Data->Num_Visible_Events, |
445 | // Control_Flow_Data); |
446 | |
447 | |
448 | |
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 | /*void Tree_V_set_cursor(ControlFlowData *Control_Flow_Data) |
489 | { |
490 | GtkTreePath *path; |
491 | |
492 | if(Control_Flow_Data->Selected_Event && Control_Flow_Data->First_Event != -1) |
493 | { |
494 | gtk_adjustment_set_value(Control_Flow_Data->VAdjust_C, |
495 | Control_Flow_Data->Currently_Selected_Event); |
496 | |
497 | path = gtk_tree_path_new_from_indices( |
498 | Control_Flow_Data->Currently_Selected_Event- |
499 | Control_Flow_Data->First_Event, |
500 | -1); |
501 | |
502 | gtk_tree_view_set_cursor(GTK_TREE_VIEW(Control_Flow_Data->Tree_V), path, NULL, FALSE); |
503 | gtk_tree_path_free(path); |
504 | } |
505 | } |
506 | |
507 | void Tree_V_get_cursor(ControlFlowData *Control_Flow_Data) |
508 | { |
509 | GtkTreePath *path; |
510 | gint *indices; |
511 | |
512 | gtk_tree_view_get_cursor(GTK_TREE_VIEW(Control_Flow_Data->Tree_V), &path, NULL); |
513 | indices = gtk_tree_path_get_indices(path); |
514 | |
515 | if(indices != NULL) |
516 | { |
517 | Control_Flow_Data->Selected_Event = TRUE; |
518 | Control_Flow_Data->Currently_Selected_Event = |
519 | Control_Flow_Data->First_Event + indices[0]; |
520 | |
521 | } else { |
522 | Control_Flow_Data->Selected_Event = FALSE; |
523 | Control_Flow_Data->Currently_Selected_Event = 0; |
524 | } |
525 | g_critical("DEBUG : Event Selected : %i , num: %u", Control_Flow_Data->Selected_Event, Control_Flow_Data->Currently_Selected_Event) ; |
526 | |
527 | gtk_tree_path_free(path); |
528 | |
529 | } |
530 | */ |
531 | |
532 | #ifdef DEBUG |
533 | void Tree_V_move_cursor_cb (GtkWidget *widget, GtkMovementStep arg1, gint arg2, gpointer data) |
534 | { |
535 | GtkTreePath *path; // = gtk_tree_path_new(); |
536 | gint *indices; |
537 | gdouble value; |
538 | ControlFlowData *Control_Flow_Data = (ControlFlowData*)data; |
539 | |
540 | gtk_tree_view_get_cursor(GTK_TREE_VIEW(Control_Flow_Data->Tree_V), &path, NULL); |
541 | if(path == NULL) |
542 | { |
543 | /* No prior cursor, put it at beginning of page and let the execution do */ |
544 | path = gtk_tree_path_new_from_indices(0, -1); |
545 | gtk_tree_view_set_cursor(GTK_TREE_VIEW(Control_Flow_Data->Tree_V), path, NULL, FALSE); |
546 | } |
547 | |
548 | indices = gtk_tree_path_get_indices(path); |
549 | |
550 | g_critical("DEBUG : move cursor step : %u , int : %i , indice : %i", (guint)arg1, arg2, indices[0]) ; |
551 | |
552 | value = gtk_adjustment_get_value(Control_Flow_Data->VAdjust_C); |
553 | |
554 | if(arg1 == GTK_MOVEMENT_DISPLAY_LINES) |
555 | { |
556 | /* Move one line */ |
557 | if(arg2 == 1) |
558 | { |
559 | /* move one line down */ |
560 | if(indices[0] == Control_Flow_Data->Num_Visible_Events - 1) |
561 | { |
562 | if(value + Control_Flow_Data->Num_Visible_Events <= |
563 | Control_Flow_Data->Number_Of_Events -1) |
564 | { |
565 | g_critical("need 1 event down") ; |
566 | Control_Flow_Data->Currently_Selected_Event += 1; |
567 | gtk_adjustment_set_value(Control_Flow_Data->VAdjust_C, value+1); |
568 | //gtk_tree_path_free(path); |
569 | //path = gtk_tree_path_new_from_indices(Control_Flow_Data->Num_Visible_Events-1, -1); |
570 | //gtk_tree_view_set_cursor(GTK_TREE_VIEW(Control_Flow_Data->Tree_V), path, NULL, FALSE); |
571 | g_signal_stop_emission_by_name(G_OBJECT(widget), "move-cursor"); |
572 | } |
573 | } |
574 | } else { |
575 | /* Move one line up */ |
576 | if(indices[0] == 0) |
577 | { |
578 | if(value - 1 >= 0 ) |
579 | { |
580 | g_critical("need 1 event up") ; |
581 | Control_Flow_Data->Currently_Selected_Event -= 1; |
582 | gtk_adjustment_set_value(Control_Flow_Data->VAdjust_C, value-1); |
583 | //gtk_tree_path_free(path); |
584 | //path = gtk_tree_path_new_from_indices(0, -1); |
585 | //gtk_tree_view_set_cursor(GTK_TREE_VIEW(Control_Flow_Data->Tree_V), path, NULL, FALSE); |
586 | g_signal_stop_emission_by_name(G_OBJECT(widget), "move-cursor"); |
587 | } |
588 | |
589 | } |
590 | } |
591 | |
592 | } |
593 | |
594 | if(arg1 == GTK_MOVEMENT_PAGES) |
595 | { |
596 | /* Move one page */ |
597 | if(arg2 == 1) |
598 | { |
599 | if(Control_Flow_Data->Num_Visible_Events == 1) |
600 | value += 1 ; |
601 | /* move one page down */ |
602 | if(value + Control_Flow_Data->Num_Visible_Events-1 <= |
603 | Control_Flow_Data->Number_Of_Events ) |
604 | { |
605 | g_critical("need 1 page down") ; |
606 | |
607 | Control_Flow_Data->Currently_Selected_Event += Control_Flow_Data->Num_Visible_Events-1; |
608 | gtk_adjustment_set_value(Control_Flow_Data->VAdjust_C, |
609 | value+(Control_Flow_Data->Num_Visible_Events-1)); |
610 | //gtk_tree_path_free(path); |
611 | //path = gtk_tree_path_new_from_indices(0, -1); |
612 | //gtk_tree_view_set_cursor(GTK_TREE_VIEW(Control_Flow_Data->Tree_V), path, NULL, FALSE); |
613 | g_signal_stop_emission_by_name(G_OBJECT(widget), "move-cursor"); |
614 | } |
615 | } else { |
616 | /* Move one page up */ |
617 | if(Control_Flow_Data->Num_Visible_Events == 1) |
618 | value -= 1 ; |
619 | |
620 | if(indices[0] < Control_Flow_Data->Num_Visible_Events - 2 ) |
621 | { |
622 | if(value - (Control_Flow_Data->Num_Visible_Events-1) >= 0) |
623 | { |
624 | g_critical("need 1 page up") ; |
625 | |
626 | Control_Flow_Data->Currently_Selected_Event -= Control_Flow_Data->Num_Visible_Events-1; |
627 | |
628 | gtk_adjustment_set_value(Control_Flow_Data->VAdjust_C, |
629 | value-(Control_Flow_Data->Num_Visible_Events-1)); |
630 | //gtk_tree_path_free(path); |
631 | //path = gtk_tree_path_new_from_indices(0, -1); |
632 | //gtk_tree_view_set_cursor(GTK_TREE_VIEW(Control_Flow_Data->Tree_V), path, NULL, FALSE); |
633 | g_signal_stop_emission_by_name(G_OBJECT(widget), "move-cursor"); |
634 | |
635 | } else { |
636 | /* Go to first Event */ |
637 | g_critical("need 1 page up") ; |
638 | |
639 | Control_Flow_Data->Currently_Selected_Event == 0 ; |
640 | gtk_adjustment_set_value(Control_Flow_Data->VAdjust_C, |
641 | 0); |
642 | //gtk_tree_path_free(path); |
643 | //path = gtk_tree_path_new_from_indices(0, -1); |
644 | //gtk_tree_view_set_cursor(GTK_TREE_VIEW(Control_Flow_Data->Tree_V), path, NULL, FALSE); |
645 | g_signal_stop_emission_by_name(G_OBJECT(widget), "move-cursor"); |
646 | |
647 | } |
648 | } |
649 | |
650 | } |
651 | |
652 | } |
653 | |
654 | if(arg1 == GTK_MOVEMENT_BUFFER_ENDS) |
655 | { |
656 | /* Move to the ends of the buffer */ |
657 | if(arg2 == 1) |
658 | { |
659 | /* move end of buffer */ |
660 | g_critical("End of buffer") ; |
661 | Control_Flow_Data->Currently_Selected_Event = Control_Flow_Data->Number_Of_Events-1 ; |
662 | gtk_adjustment_set_value(Control_Flow_Data->VAdjust_C, |
663 | Control_Flow_Data->Number_Of_Events - |
664 | Control_Flow_Data->Num_Visible_Events); |
665 | //gtk_tree_path_free(path); |
666 | //path = gtk_tree_path_new_from_indices(Control_Flow_Data->Num_Visible_Events-1, -1); |
667 | //gtk_tree_view_set_cursor(GTK_TREE_VIEW(Control_Flow_Data->Tree_V), path, NULL, FALSE); |
668 | g_signal_stop_emission_by_name(G_OBJECT(widget), "move-cursor"); |
669 | } else { |
670 | /* Move beginning of buffer */ |
671 | g_critical("Beginning of buffer") ; |
672 | Control_Flow_Data->Currently_Selected_Event = 0 ; |
673 | gtk_adjustment_set_value(Control_Flow_Data->VAdjust_C, 0); |
674 | //gtk_tree_path_free(path); |
675 | //path = gtk_tree_path_new_from_indices(0, -1); |
676 | //gtk_tree_view_set_cursor(GTK_TREE_VIEW(Control_Flow_Data->Tree_V), path, NULL, FALSE); |
677 | g_signal_stop_emission_by_name(G_OBJECT(widget), "move-cursor"); |
678 | } |
679 | |
680 | } |
681 | |
682 | |
683 | gtk_tree_path_free(path); |
684 | } |
685 | |
686 | void Tree_V_cursor_changed_cb (GtkWidget *widget, gpointer data) |
687 | { |
688 | ControlFlowData *Control_Flow_Data = (ControlFlowData*) data; |
689 | |
690 | g_critical("DEBUG : cursor change"); |
691 | /* On cursor change, modify the currently selected event by calling |
692 | * the right API function */ |
693 | Tree_V_get_cursor(Control_Flow_Data); |
694 | } |
695 | |
696 | |
697 | void v_scroll_cb (GtkAdjustment *adjustment, gpointer data) |
698 | { |
699 | ControlFlowData *Control_Flow_Data = (ControlFlowData*)data; |
700 | GtkTreePath *Tree_Path; |
701 | |
702 | g_critical("DEBUG : scroll signal, value : %f", adjustment->value); |
703 | |
704 | get_test_data((int)adjustment->value, Control_Flow_Data->Num_Visible_Events, |
705 | Control_Flow_Data); |
706 | |
707 | |
708 | if(Control_Flow_Data->Currently_Selected_Event |
709 | >= Control_Flow_Data->First_Event |
710 | && |
711 | Control_Flow_Data->Currently_Selected_Event |
712 | <= Control_Flow_Data->Last_Event |
713 | && |
714 | Control_Flow_Data->Selected_Event) |
715 | { |
716 | |
717 | Tree_Path = gtk_tree_path_new_from_indices( |
718 | Control_Flow_Data->Currently_Selected_Event- |
719 | Control_Flow_Data->First_Event, |
720 | -1); |
721 | |
722 | gtk_tree_view_set_cursor(GTK_TREE_VIEW(Control_Flow_Data->Tree_V), Tree_Path, |
723 | NULL, FALSE); |
724 | gtk_tree_path_free(Tree_Path); |
725 | } |
726 | |
727 | |
728 | } |
729 | |
730 | gint get_cell_height(GtkTreeView *TreeView) |
731 | { |
732 | gint height, width; |
733 | GtkTreeViewColumn *Column = gtk_tree_view_get_column(TreeView, 0); |
734 | GList *Render_List = gtk_tree_view_column_get_cell_renderers(Column); |
735 | GtkCellRenderer *Renderer = g_list_first(Render_List)->data; |
736 | |
737 | gtk_tree_view_column_cell_get_size(Column, NULL, NULL, NULL, NULL, &height); |
738 | g_critical("cell 0 height : %u",height); |
739 | |
740 | return height; |
741 | } |
742 | |
743 | void Tree_V_size_allocate_cb (GtkWidget *widget, GtkAllocation *alloc, gpointer data) |
744 | { |
745 | ControlFlowData *Control_Flow_Data = (ControlFlowData*)data; |
746 | gint Cell_Height = get_cell_height(GTK_TREE_VIEW(Control_Flow_Data->Tree_V)); |
747 | gint Last_Num_Visible_Events = Control_Flow_Data->Num_Visible_Events; |
748 | gdouble Exact_Num_Visible; |
749 | |
750 | g_critical("size-allocate"); |
751 | |
752 | Exact_Num_Visible = ( alloc->height - |
753 | TREE_VIEW_HEADER_HEIGHT (GTK_TREE_VIEW(Control_Flow_Data->Tree_V)) ) |
754 | / (double)Cell_Height ; |
755 | |
756 | Control_Flow_Data->Num_Visible_Events = ceil(Exact_Num_Visible) ; |
757 | |
758 | g_critical("number of events shown : %u",Control_Flow_Data->Num_Visible_Events); |
759 | g_critical("ex number of events shown : %f",Exact_Num_Visible); |
760 | |
761 | Control_Flow_Data->VAdjust_C->page_increment = |
762 | floor(Exact_Num_Visible); |
763 | Control_Flow_Data->VAdjust_C->page_size = |
764 | floor(Exact_Num_Visible); |
765 | |
766 | if(Control_Flow_Data->Num_Visible_Events != Last_Num_Visible_Events) |
767 | { |
768 | get_test_data((int)Control_Flow_Data->VAdjust_C->value, |
769 | Control_Flow_Data->Num_Visible_Events, |
770 | Control_Flow_Data); |
771 | } |
772 | |
773 | |
774 | } |
775 | |
776 | void Tree_V_size_request_cb (GtkWidget *widget, GtkRequisition *requisition, gpointer data) |
777 | { |
778 | gint h; |
779 | ControlFlowData *Control_Flow_Data = (ControlFlowData*)data; |
780 | gint Cell_Height = get_cell_height(GTK_TREE_VIEW(Control_Flow_Data->Tree_V)); |
781 | |
782 | g_critical("size-request"); |
783 | |
784 | h = Cell_Height + TREE_VIEW_HEADER_HEIGHT |
785 | (GTK_TREE_VIEW(Control_Flow_Data->Tree_V)); |
786 | requisition->height = h; |
787 | |
788 | } |
789 | |
790 | #endif //DEBUG |
791 | |
792 | void get_test_data(guint Event_Number, guint List_Height, |
793 | ControlFlowData *Control_Flow_Data) |
794 | { |
795 | //GtkTreeIter iter; |
796 | int i; |
797 | //GtkTreeModel *model = GTK_TREE_MODEL(Control_Flow_Data->Store_M); |
798 | //GtkTreePath *Tree_Path; |
799 | gchar *test_string; |
800 | |
801 | // if(Event_Number > Control_Flow_Data->Last_Event || |
802 | // Event_Number + List_Height-1 < Control_Flow_Data->First_Event || |
803 | // Control_Flow_Data->First_Event == -1) |
804 | { |
805 | /* no event can be reused, clear and start from nothing */ |
806 | //gtk_list_store_clear(Control_Flow_Data->Store_M); |
807 | for(i=Event_Number; i<Event_Number+List_Height; i++) |
808 | { |
809 | if(i>=Control_Flow_Data->Number_Of_Events) break; |
810 | /* Add a new row to the model */ |
811 | // gtk_list_store_append (Control_Flow_Data->Store_M, &iter); |
812 | // gtk_list_store_set (Control_Flow_Data->Store_M, &iter, |
813 | // CPUID_COLUMN, 0, |
814 | // EVENT_COLUMN, "event irq", |
815 | // TIME_COLUMN, i, |
816 | // PID_COLUMN, 100, |
817 | // ENTRY_LEN_COLUMN, 17, |
818 | // EVENT_DESCR_COLUMN, "Detailed information", |
819 | // -1); |
820 | } |
821 | } |
822 | #ifdef DEBUG //do not use this, it's slower and broken |
823 | // } else { |
824 | /* Some events will be reused */ |
825 | if(Event_Number < Control_Flow_Data->First_Event) |
826 | { |
827 | /* scrolling up, prepend events */ |
828 | Tree_Path = gtk_tree_path_new_from_indices |
829 | (Event_Number+List_Height-1 - |
830 | Control_Flow_Data->First_Event + 1, |
831 | -1); |
832 | for(i=0; i<Control_Flow_Data->Last_Event-(Event_Number+List_Height-1); |
833 | i++) |
834 | { |
835 | /* Remove the last events from the list */ |
836 | if(gtk_tree_model_get_iter(model, &iter, Tree_Path)) |
837 | gtk_list_store_remove(Control_Flow_Data->Store_M, &iter); |
838 | } |
839 | |
840 | for(i=Control_Flow_Data->First_Event-1; i>=Event_Number; i--) |
841 | { |
842 | if(i>=Control_Flow_Data->Number_Of_Events) break; |
843 | /* Prepend new events */ |
844 | gtk_list_store_prepend (Control_Flow_Data->Store_M, &iter); |
845 | gtk_list_store_set (Control_Flow_Data->Store_M, &iter, |
846 | CPUID_COLUMN, 0, |
847 | EVENT_COLUMN, "event irq", |
848 | TIME_COLUMN, i, |
849 | PID_COLUMN, 100, |
850 | ENTRY_LEN_COLUMN, 17, |
851 | EVENT_DESCR_COLUMN, "Detailed information", |
852 | -1); |
853 | } |
854 | } else { |
855 | /* Scrolling down, append events */ |
856 | for(i=Control_Flow_Data->First_Event; i<Event_Number; i++) |
857 | { |
858 | /* Remove these events from the list */ |
859 | gtk_tree_model_get_iter_first(model, &iter); |
860 | gtk_list_store_remove(Control_Flow_Data->Store_M, &iter); |
861 | } |
862 | for(i=Control_Flow_Data->Last_Event+1; i<Event_Number+List_Height; i++) |
863 | { |
864 | if(i>=Control_Flow_Data->Number_Of_Events) break; |
865 | /* Append new events */ |
866 | gtk_list_store_append (Control_Flow_Data->Store_M, &iter); |
867 | gtk_list_store_set (Control_Flow_Data->Store_M, &iter, |
868 | CPUID_COLUMN, 0, |
869 | EVENT_COLUMN, "event irq", |
870 | TIME_COLUMN, i, |
871 | PID_COLUMN, 100, |
872 | ENTRY_LEN_COLUMN, 17, |
873 | EVENT_DESCR_COLUMN, "Detailed information", |
874 | -1); |
875 | } |
876 | |
877 | } |
878 | } |
879 | #endif //DEBUG |
880 | Control_Flow_Data->First_Event = Event_Number ; |
881 | Control_Flow_Data->Last_Event = Event_Number+List_Height-1 ; |
882 | |
883 | |
884 | |
885 | } |
886 | |
887 | #ifdef DEBUG |
888 | void add_test_data(ControlFlowData *Control_Flow_Data) |
889 | { |
890 | GtkTreeIter iter; |
891 | int i; |
892 | |
893 | for(i=0; i<10; i++) |
894 | { |
895 | /* Add a new row to the model */ |
896 | gtk_list_store_append (Control_Flow_Data->Store_M, &iter); |
897 | gtk_list_store_set (Control_Flow_Data->Store_M, &iter, |
898 | CPUID_COLUMN, 0, |
899 | EVENT_COLUMN, "event irq", |
900 | TIME_COLUMN, i, |
901 | PID_COLUMN, 100, |
902 | ENTRY_LEN_COLUMN, 17, |
903 | EVENT_DESCR_COLUMN, "Detailed information", |
904 | -1); |
905 | } |
906 | |
907 | } |
908 | |
909 | #endif //DEBUG |
910 | void |
911 | GuiControlFlow_Destructor(ControlFlowData *Control_Flow_Data) |
912 | { |
913 | guint index; |
914 | |
915 | /* May already been done by GTK window closing */ |
916 | if(GTK_IS_WIDGET(Control_Flow_Data->HBox_V)) |
917 | gtk_widget_destroy(Control_Flow_Data->HBox_V); |
918 | |
919 | /* Destroy the Tree View */ |
920 | //gtk_widget_destroy(Control_Flow_Data->Tree_V); |
921 | |
922 | /* Clear raw event list */ |
923 | //gtk_list_store_clear(Control_Flow_Data->Store_M); |
924 | //gtk_widget_destroy(GTK_WIDGET(Control_Flow_Data->Store_M)); |
925 | |
926 | g_slist_remove(sControl_Flow_Data_List,Control_Flow_Data); |
927 | } |
928 | |
929 | //FIXME : call hGuiEvents_Destructor for corresponding data upon widget destroy |
930 | |
931 | #ifdef DEBUG |
932 | static void |
933 | tree_selection_changed_cb (GtkTreeSelection *selection, gpointer data) |
934 | { |
935 | ControlFlowData *Control_Flow_Data = (ControlFlowData*)data; |
936 | GtkTreeIter iter; |
937 | GtkTreeModel *model = GTK_TREE_MODEL(Control_Flow_Data->Store_M); |
938 | gchar *Event; |
939 | |
940 | if (gtk_tree_selection_get_selected (selection, &model, &iter)) |
941 | { |
942 | gtk_tree_model_get (model, &iter, EVENT_COLUMN, &Event, -1); |
943 | |
944 | g_print ("Event selected : %s\n", Event); |
945 | |
946 | g_free (Event); |
947 | } |
948 | } |
949 | #endif //DEBUG |
950 | |
951 | |
952 | int Event_Selected_Hook(void *hook_data, void *call_data) |
953 | { |
954 | ControlFlowData *Control_Flow_Data = (ControlFlowData*) hook_data; |
955 | guint *Event_Number = (guint*) call_data; |
956 | |
957 | g_critical("DEBUG : event selected by main window : %u", *Event_Number); |
958 | |
959 | // Control_Flow_Data->Currently_Selected_Event = *Event_Number; |
960 | // Control_Flow_Data->Selected_Event = TRUE ; |
961 | |
962 | // Tree_V_set_cursor(Control_Flow_Data); |
963 | |
964 | } |
965 | |
966 | |
967 | |
968 | static void destroy_cb( GtkWidget *widget, |
969 | gpointer data ) |
970 | { |
971 | gtk_main_quit (); |
972 | } |
973 | |
974 | |
975 | |
976 | int main(int argc, char **argv) |
977 | { |
978 | GtkWidget *Window; |
979 | GtkWidget *CF_Viewer; |
980 | GtkWidget *VBox_V; |
981 | GtkWidget *HScroll_VC; |
982 | ControlFlowData *Control_Flow_Data; |
983 | guint ev_sel = 444 ; |
984 | /* Horizontal scrollbar and it's adjustment */ |
985 | GtkWidget *VScroll_VC; |
986 | GtkAdjustment *VAdjust_C ; |
987 | |
988 | /* Initialize i18n support */ |
989 | gtk_set_locale (); |
990 | |
991 | /* Initialize the widget set */ |
992 | gtk_init (&argc, &argv); |
993 | |
994 | init(); |
995 | |
996 | Window = gtk_window_new (GTK_WINDOW_TOPLEVEL); |
997 | gtk_window_set_title (GTK_WINDOW (Window), ("Test Window")); |
998 | |
999 | g_signal_connect (G_OBJECT (Window), "destroy", |
1000 | G_CALLBACK (destroy_cb), NULL); |
1001 | |
1002 | |
1003 | VBox_V = gtk_vbox_new(0, 0); |
1004 | gtk_container_add (GTK_CONTAINER (Window), VBox_V); |
1005 | |
1006 | //ListViewer = hGuiEvents(Window); |
1007 | //gtk_box_pack_start(GTK_BOX(VBox_V), ListViewer, TRUE, TRUE, 0); |
1008 | |
1009 | //ListViewer = hGuiEvents(Window); |
1010 | //gtk_box_pack_start(GTK_BOX(VBox_V), ListViewer, FALSE, TRUE, 0); |
1011 | |
1012 | Control_Flow_Data = GuiControlFlow(); |
1013 | CF_Viewer = Control_Flow_Data->HBox_V; |
1014 | gtk_box_pack_start(GTK_BOX(VBox_V), CF_Viewer, TRUE, TRUE, 0); |
1015 | |
1016 | /* Create horizontal scrollbar and pack it */ |
1017 | HScroll_VC = gtk_hscrollbar_new(NULL); |
1018 | gtk_box_pack_start(GTK_BOX(VBox_V), HScroll_VC, FALSE, TRUE, 0); |
1019 | |
1020 | |
1021 | gtk_widget_show (HScroll_VC); |
1022 | gtk_widget_show (VBox_V); |
1023 | gtk_widget_show (Window); |
1024 | |
1025 | //Event_Selected_Hook(Control_Flow_Data, &ev_sel); |
1026 | |
1027 | gtk_main (); |
1028 | |
1029 | g_critical("main loop finished"); |
1030 | |
1031 | //hGuiEvents_Destructor(ListViewer); |
1032 | |
1033 | //g_critical("GuiEvents Destructor finished"); |
1034 | destroy(); |
1035 | |
1036 | return 0; |
1037 | } |
1038 | |
17abcce3 |
1039 | /*\@}*/ |