make batchanalysis and textDump work
[lttv.git] / ltt / branches / poly / lttv / modules / gui / controlflow / drawing.c
1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Mathieu Desnoyers
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
16 * MA 02111-1307, USA.
17 */
18
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
22
23 #include <gtk/gtk.h>
24 #include <gdk/gdk.h>
25 #include <string.h>
26
27 #include <ltt/trace.h>
28
29 #include <lttv/lttv.h>
30 #include <lttv/tracecontext.h>
31 #include <lttvwindow/lttvwindow.h>
32 #include <lttv/state.h>
33 #include <lttv/hook.h>
34
35 #include "drawing.h"
36 #include "eventhooks.h"
37 #include "cfv.h"
38
39 #define g_info(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, format)
40 #define g_debug(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, format)
41
42 //FIXME
43 #define TRACE_NUMBER 0
44 #define EXTRA_ALLOC 1024 // pixels
45
46
47 #if 0 /* colors for two lines representation */
48 GdkColor drawing_colors[NUM_COLORS] =
49 { /* Pixel, R, G, B */
50 { 0, 0, 0, 0 }, /* COL_BLACK */
51 { 0, 0xFFFF, 0xFFFF, 0xFFFF }, /* COL_WHITE */
52 { 0, 0x0FFF, 0xFFFF, 0xFFFF }, /* COL_WAIT_FORK : pale blue */
53 { 0, 0xFFFF, 0xFFFF, 0x0000 }, /* COL_WAIT_CPU : yellow */
54 { 0, 0xFFFF, 0xA000, 0xFCFF }, /* COL_EXIT : pale magenta */
55 { 0, 0xFFFF, 0x0000, 0xFFFF }, /* COL_ZOMBIE : purple */
56 { 0, 0xFFFF, 0x0000, 0x0000 }, /* COL_WAIT : red */
57 { 0, 0x0000, 0xFFFF, 0x0000 }, /* COL_RUN : green */
58 { 0, 0x8800, 0xFFFF, 0x8A00 }, /* COL_USER_MODE : pale green */
59 { 0, 0x09FF, 0x01FF, 0xFFFF }, /* COL_SYSCALL : blue */
60 { 0, 0xF900, 0x4200, 0xFF00 }, /* COL_TRAP : pale purple */
61 { 0, 0xFFFF, 0x5AFF, 0x01FF }, /* COL_IRQ : orange */
62 { 0, 0xFFFF, 0xFFFF, 0xFFFF } /* COL_MODE_UNKNOWN : white */
63
64 };
65 #endif //0
66
67
68 GdkColor drawing_colors[NUM_COLORS] =
69 { /* Pixel, R, G, B */
70 { 0, 0, 0, 0 }, /* COL_BLACK */
71 { 0, 0xFFFF, 0xFFFF, 0xFFFF }, /* COL_WHITE */
72 { 0, 0x0000, 0xFF00, 0x0000 }, /* COL_RUN_USER_MODE : green */
73 { 0, 0x0100, 0x9E00, 0xFFFF }, /* COL_RUN_SYSCALL : pale blue */
74 { 0, 0xFF00, 0xFF00, 0x0100 }, /* COL_RUN_TRAP : yellow */
75 { 0, 0xFFFF, 0x5E00, 0x0000 }, /* COL_RUN_IRQ : red */
76 { 0, 0x6600, 0x0000, 0x0000 }, /* COL_WAIT : dark red */
77 { 0, 0x7700, 0x7700, 0x0000 }, /* COL_WAIT_CPU : dark yellow */
78 { 0, 0x6400, 0x0000, 0x5D00 }, /* COL_ZOMBIE : dark purple */
79 { 0, 0x0700, 0x6400, 0x0000 }, /* COL_WAIT_FORK : dark green */
80 { 0, 0x8900, 0x0000, 0x8400 }, /* COL_EXIT : "less dark" magenta */
81 { 0, 0xFFFF, 0xFFFF, 0xFFFF }, /* COL_MODE_UNKNOWN : white */
82 { 0, 0xFFFF, 0xFFFF, 0xFFFF } /* COL_UNNAMED : white */
83
84 };
85
86 /*
87 RUN+USER MODE green
88 RUN+SYSCALL
89 RUN+TRAP
90 RUN+IRQ
91 WAIT+foncé
92 WAIT CPU + WAIT FORK vert foncé ou jaune
93 IRQ rouge
94 TRAP: orange
95 SYSCALL: bleu pâle
96
97 ZOMBIE + WAIT EXIT
98 */
99
100
101 /*****************************************************************************
102 * drawing functions *
103 *****************************************************************************/
104
105 static gboolean
106 expose_ruler( GtkWidget *widget, GdkEventExpose *event, gpointer user_data );
107
108 static gboolean
109 motion_notify_ruler(GtkWidget *widget, GdkEventMotion *event, gpointer user_data);
110
111
112 /* Function responsible for updating the exposed area.
113 * It must do an events request to the lttvwindow API to ask for this update.
114 * Note : this function cannot clear the background, because it may
115 * erase drawing already present (SAFETY).
116 */
117 void drawing_data_request(Drawing_t *drawing,
118 gint x, gint y,
119 gint width,
120 gint height)
121 {
122 if(width < 0) return ;
123 if(height < 0) return ;
124
125 Tab *tab = drawing->control_flow_data->tab;
126 TimeWindow time_window =
127 lttvwindow_get_time_window(tab);
128
129 ControlFlowData *control_flow_data = drawing->control_flow_data;
130 // (ControlFlowData*)g_object_get_data(
131 // G_OBJECT(drawing->drawing_area), "control_flow_data");
132
133 LttTime start, time_end;
134 LttTime window_end = time_window.end_time;
135
136 g_debug("req : window start_time : %lu, %lu", time_window.start_time.tv_sec,
137 time_window.start_time.tv_nsec);
138
139 g_debug("req : window time width : %lu, %lu", time_window.time_width.tv_sec,
140 time_window.time_width.tv_nsec);
141
142 g_debug("req : window_end : %lu, %lu", window_end.tv_sec,
143 window_end.tv_nsec);
144
145 g_debug("x is : %i, x+width is : %i", x, x+width);
146
147 convert_pixels_to_time(drawing->width, x,
148 time_window,
149 &start);
150
151 convert_pixels_to_time(drawing->width, x+width,
152 time_window,
153 &time_end);
154 time_end = ltt_time_add(time_end, ltt_time_one); // because main window
155 // doesn't deliver end time.
156
157 lttvwindow_events_request_remove_all(tab,
158 control_flow_data);
159
160 {
161 /* find the tracehooks */
162 LttvTracesetContext *tsc = lttvwindow_get_traceset_context(tab);
163
164 LttvTraceset *traceset = tsc->ts;
165
166 guint i, k, nb_trace;
167
168 LttvTraceState *ts;
169
170 LttvTracefileState *tfs;
171
172 GArray *hooks;
173
174 LttvTraceHook hook;
175
176 nb_trace = lttv_traceset_number(traceset);
177 // FIXME : eventually request for more traces
178 // for(i = 0 ; i < nb_trace ; i++) {
179 for(i = 0; i<MIN(TRACE_NUMBER+1, nb_trace);i++)
180 {
181 EventsRequest *events_request = g_new(EventsRequest, 1);
182 // Create the hooks
183 //LttvHooks *event = lttv_hooks_new();
184 LttvHooksById *event_by_id = lttv_hooks_by_id_new();
185 LttvHooks *before_chunk_traceset = lttv_hooks_new();
186 LttvHooks *after_chunk_traceset = lttv_hooks_new();
187 LttvHooks *before_request_hook = lttv_hooks_new();
188 LttvHooks *after_request_hook = lttv_hooks_new();
189
190 lttv_hooks_add(before_chunk_traceset,
191 before_chunk,
192 events_request,
193 LTTV_PRIO_DEFAULT);
194
195 lttv_hooks_add(after_chunk_traceset,
196 after_chunk,
197 events_request,
198 LTTV_PRIO_DEFAULT);
199
200 lttv_hooks_add(before_request_hook,
201 before_request,
202 events_request,
203 LTTV_PRIO_DEFAULT);
204
205 lttv_hooks_add(after_request_hook,
206 after_request,
207 events_request,
208 LTTV_PRIO_DEFAULT);
209
210
211 ts = (LttvTraceState *)tsc->traces[i];
212
213 /* Find the eventtype id for the following events and register the
214 associated by id hooks. */
215
216 hooks = g_array_new(FALSE, FALSE, sizeof(LttvTraceHook));
217 hooks = g_array_set_size(hooks, 10);
218
219 /* before hooks */
220
221 lttv_trace_find_hook(ts->parent.t, "core","syscall_entry","syscall_id",
222 NULL, NULL, before_execmode_hook, &g_array_index(hooks, LttvTraceHook, 0));
223
224 lttv_trace_find_hook(ts->parent.t, "core", "syscall_exit", NULL, NULL,
225 NULL, before_execmode_hook, &g_array_index(hooks, LttvTraceHook, 1));
226
227 lttv_trace_find_hook(ts->parent.t, "core", "trap_entry", "trap_id",
228 NULL, NULL, before_execmode_hook, &g_array_index(hooks, LttvTraceHook, 2));
229
230 lttv_trace_find_hook(ts->parent.t, "core", "trap_exit", NULL, NULL, NULL,
231 before_execmode_hook, &g_array_index(hooks, LttvTraceHook, 3));
232
233 lttv_trace_find_hook(ts->parent.t, "core", "irq_entry", "irq_id", NULL,
234 NULL, before_execmode_hook, &g_array_index(hooks, LttvTraceHook, 4));
235
236 lttv_trace_find_hook(ts->parent.t, "core", "irq_exit", NULL, NULL, NULL,
237 before_execmode_hook, &g_array_index(hooks, LttvTraceHook, 5));
238
239 lttv_trace_find_hook(ts->parent.t, "core", "schedchange", "in", "out",
240 "out_state", before_schedchange_hook,
241 &g_array_index(hooks, LttvTraceHook, 6));
242
243 lttv_trace_find_hook(ts->parent.t, "core", "process", "event_sub_id",
244 "event_data1", "event_data2", before_process_hook,
245 &g_array_index(hooks, LttvTraceHook, 7));
246
247 #if 0
248 lttv_trace_find_hook(ts->parent.t, "core", "process_fork", "child_pid",
249 NULL, NULL, process_fork, &g_array_index(hooks, LttvTraceHook, 7));
250
251 lttv_trace_find_hook(ts->parent.t, "core", "process_exit", NULL, NULL,
252 NULL, process_exit, &g_array_index(hooks, LttvTraceHook, 8));
253 #endif //0
254
255 /* after hooks */
256
257 #if 0
258 /**** DESACTIVATED ****/
259 lttv_trace_find_hook(ts->parent.t, "core","syscall_entry","syscall_id",
260 NULL, NULL, after_execmode_hook, &g_array_index(hooks, LttvTraceHook, 8));
261 /**** DESACTIVATED ****/
262 lttv_trace_find_hook(ts->parent.t, "core", "syscall_exit", NULL, NULL,
263 NULL, after_execmode_hook, &g_array_index(hooks, LttvTraceHook, 9));
264
265 /**** DESACTIVATED ****/
266 lttv_trace_find_hook(ts->parent.t, "core", "trap_entry", "trap_id",
267 NULL, NULL, after_execmode_hook, &g_array_index(hooks, LttvTraceHook, 10));
268
269 /**** DESACTIVATED ****/
270 lttv_trace_find_hook(ts->parent.t, "core", "trap_exit", NULL, NULL, NULL,
271 after_execmode_hook, &g_array_index(hooks, LttvTraceHook, 11));
272
273 /**** DESACTIVATED ****/
274 lttv_trace_find_hook(ts->parent.t, "core", "irq_entry", "irq_id", NULL,
275 NULL, after_execmode_hook, &g_array_index(hooks, LttvTraceHook, 12));
276
277 /**** DESACTIVATED ****/
278 lttv_trace_find_hook(ts->parent.t, "core", "irq_exit", NULL, NULL, NULL,
279 after_execmode_hook, &g_array_index(hooks, LttvTraceHook, 13));
280 #endif //0
281
282 lttv_trace_find_hook(ts->parent.t, "core", "schedchange", "in", "out",
283 "out_state", after_schedchange_hook,
284 &g_array_index(hooks, LttvTraceHook, 8));
285
286 lttv_trace_find_hook(ts->parent.t, "core", "process", "event_sub_id",
287 "event_data1", "event_data2", after_process_hook,
288 &g_array_index(hooks, LttvTraceHook, 9));
289
290 #if 0
291 lttv_trace_find_hook(ts->parent.t, "core", "process_fork", "child_pid",
292 NULL, NULL, process_fork, &g_array_index(hooks, LttvTraceHook, 7));
293
294 lttv_trace_find_hook(ts->parent.t, "core", "process_exit", NULL, NULL,
295 NULL, process_exit, &g_array_index(hooks, LttvTraceHook, 8));
296 #endif //0
297
298
299
300 /* Add these hooks to each event_by_id hooks list */
301 /* add before */
302 for(k = 0 ; k < 8 ; k++) {
303 hook = g_array_index(hooks, LttvTraceHook, k);
304 lttv_hooks_add(lttv_hooks_by_id_find(event_by_id,
305 hook.id), hook.h,
306 events_request,
307 LTTV_PRIO_STATE-5);
308 }
309
310 /* add after */
311 for(k = 8 ; k < 10 ; k++) {
312 hook = g_array_index(hooks, LttvTraceHook, k);
313 lttv_hooks_add(lttv_hooks_by_id_find(event_by_id,
314 hook.id), hook.h,
315 events_request,
316 LTTV_PRIO_STATE+5);
317 }
318
319 events_request->hooks = hooks;
320
321 // Fill the events request
322 events_request->owner = control_flow_data;
323 events_request->viewer_data = control_flow_data;
324 events_request->servicing = FALSE;
325 events_request->start_time = start;
326 events_request->start_position = NULL;
327 events_request->stop_flag = FALSE;
328 events_request->end_time = time_end;
329 events_request->num_events = G_MAXUINT;
330 events_request->end_position = NULL;
331 events_request->trace = i; /* FIXME */
332 events_request->before_chunk_traceset = before_chunk_traceset;
333 events_request->before_chunk_trace = NULL;
334 events_request->before_chunk_tracefile = NULL;
335 events_request->event = NULL;
336 events_request->event_by_id = event_by_id;
337 events_request->after_chunk_tracefile = NULL;
338 events_request->after_chunk_trace = NULL;
339 events_request->after_chunk_traceset = after_chunk_traceset;
340 events_request->before_request = before_request_hook;
341 events_request->after_request = after_request_hook;
342
343 g_debug("req : start : %lu, %lu", start.tv_sec,
344 start.tv_nsec);
345
346 g_debug("req : end : %lu, %lu", time_end.tv_sec,
347 time_end.tv_nsec);
348
349 lttvwindow_events_request(tab, events_request);
350
351 }
352
353 }
354
355 #if 0
356 lttv_hooks_add(event,
357 before_schedchange_hook,
358 events_request,
359 LTTV_PRIO_STATE-5);
360 lttv_hooks_add(event,
361 after_schedchange_hook,
362 events_request,
363 LTTV_PRIO_STATE+5);
364 lttv_hooks_add(event,
365 before_execmode_hook,
366 events_request,
367 LTTV_PRIO_STATE-5);
368 lttv_hooks_add(event,
369 after_execmode_hook,
370 events_request,
371 LTTV_PRIO_STATE+5);
372 lttv_hooks_add(event,
373 before_process_hook,
374 events_request,
375 LTTV_PRIO_STATE-5);
376 lttv_hooks_add(event,
377 after_process_hook,
378 events_request,
379 LTTV_PRIO_STATE+5);
380 #endif //0
381
382 }
383
384
385 static void set_last_start(gpointer key, gpointer value, gpointer user_data)
386 {
387 ProcessInfo *process_info = (ProcessInfo*)key;
388 HashedProcessData *hashed_process_data = (HashedProcessData*)value;
389 guint x = (guint)user_data;
390
391 hashed_process_data->x.over = x;
392 hashed_process_data->x.over_used = FALSE;
393 hashed_process_data->x.over_marked = FALSE;
394 hashed_process_data->x.middle = x;
395 hashed_process_data->x.middle_used = FALSE;
396 hashed_process_data->x.middle_marked = FALSE;
397 hashed_process_data->x.under = x;
398 hashed_process_data->x.under_used = FALSE;
399 hashed_process_data->x.under_marked = FALSE;
400 hashed_process_data->next_good_time = ltt_time_zero;
401
402 return;
403 }
404
405 void drawing_data_request_begin(EventsRequest *events_request, LttvTracesetState *tss)
406 {
407 g_debug("Begin of data request");
408 ControlFlowData *cfd = events_request->viewer_data;
409 LttvTracesetContext *tsc = LTTV_TRACESET_CONTEXT(tss);
410 TimeWindow time_window =
411 lttvwindow_get_time_window(cfd->tab);
412
413 guint width = cfd->drawing->width;
414 guint x=0;
415
416 cfd->drawing->last_start = events_request->start_time;
417
418 convert_time_to_pixels(
419 time_window,
420 events_request->start_time,
421 width,
422 &x);
423
424 g_hash_table_foreach(cfd->process_list->process_hash, set_last_start,
425 (gpointer)x);
426
427 }
428
429 void drawing_chunk_begin(EventsRequest *events_request, LttvTracesetState *tss)
430 {
431 g_debug("Begin of chunk");
432 ControlFlowData *cfd = events_request->viewer_data;
433 LttvTracesetContext *tsc = LTTV_TRACESET_CONTEXT(tss);
434 //LttTime current_time = lttv_traceset_context_get_current_tfc(tsc)->timestamp;
435 guint num_cpu =
436 ltt_trace_per_cpu_tracefile_number(tss->parent.traces[TRACE_NUMBER]->t);
437
438 cfd->process_list->current_hash_data = g_new(HashedProcessData*,num_cpu);
439 memset(cfd->process_list->current_hash_data, 0,
440 sizeof(HashedProcessData*)*num_cpu);
441 //cfd->drawing->last_start = LTT_TIME_MIN(current_time,
442 // events_request->end_time);
443 }
444
445
446 void drawing_request_expose(EventsRequest *events_request,
447 LttvTracesetState *tss,
448 LttTime end_time)
449 {
450 gint x, x_end, width;
451
452 ControlFlowData *cfd = events_request->viewer_data;
453 LttvTracesetContext *tsc = (LttvTracesetContext*)tss;
454 Drawing_t *drawing = cfd->drawing;
455
456 TimeWindow time_window =
457 lttvwindow_get_time_window(cfd->tab);
458
459 g_debug("request expose");
460
461 convert_time_to_pixels(
462 time_window,
463 end_time,
464 drawing->width,
465 &x_end);
466 x = drawing->damage_begin;
467
468 width = x_end - x;
469
470 drawing->damage_begin = x+width;
471
472 // FIXME ?
473 gtk_widget_queue_draw_area ( drawing->drawing_area,
474 x, 0,
475 width, drawing->drawing_area->allocation.height);
476
477 }
478
479
480 /* Callbacks */
481
482
483 /* Create a new backing pixmap of the appropriate size */
484 /* As the scaling will always change, it's of no use to copy old
485 * pixmap.
486 *
487 * Only change the size if width changes. The height is specified and changed
488 * when process ID are added or removed from the process list.
489 */
490 static gboolean
491 configure_event( GtkWidget *widget, GdkEventConfigure *event,
492 gpointer user_data)
493 {
494 Drawing_t *drawing = (Drawing_t*)user_data;
495
496
497 /* First, get the new time interval of the main window */
498 /* we assume (see documentation) that the main window
499 * has updated the time interval before this configure gets
500 * executed.
501 */
502 //lttvwindow_get_time_window(drawing->control_flow_data->mw,
503 // &drawing->control_flow_data->time_window);
504
505 /* New pixmap, size of the configure event */
506 //GdkPixmap *pixmap = gdk_pixmap_new(widget->window,
507 // widget->allocation.width + SAFETY,
508 // widget->allocation.height + SAFETY,
509 // -1);
510
511 if(widget->allocation.width != drawing->width) {
512 g_debug("drawing configure event");
513 g_debug("New alloc draw size : %i by %i",widget->allocation.width,
514 widget->allocation.height);
515
516 drawing->width = widget->allocation.width;
517
518 if(drawing->alloc_width < widget->allocation.width) {
519 //if(drawing->pixmap)
520 // gdk_pixmap_unref(drawing->pixmap);
521
522 //drawing->pixmap = gdk_pixmap_new(widget->window,
523 // drawing->width + SAFETY + EXTRA_ALLOC,
524 // drawing->height + EXTRA_ALLOC,
525 // -1);
526 drawing->alloc_width = drawing->width + SAFETY + EXTRA_ALLOC;
527 drawing->alloc_height = drawing->height + EXTRA_ALLOC;
528 update_pixmap_size(drawing->control_flow_data->process_list,
529 drawing->alloc_width);
530 }
531 //drawing->height = widget->allocation.height;
532
533 //ProcessList_get_height
534 // (GuiControlFlow_get_process_list(drawing->control_flow_data)),
535
536
537 // Clear the image
538 //gdk_draw_rectangle (drawing->pixmap,
539 // widget->style->black_gc,
540 // TRUE,
541 // 0, 0,
542 // drawing->width+SAFETY,
543 // drawing->height);
544
545 //g_info("init data request");
546
547
548 /* Initial data request */
549 /* no, do initial data request in the expose event */
550 // Do not need to ask for data of 1 pixel : not synchronized with
551 // main window time at this moment.
552 //drawing_data_request(drawing, &drawing->pixmap, 0, 0,
553 // widget->allocation.width,
554 // widget->allocation.height);
555
556 //drawing->width = widget->allocation.width;
557 //drawing->height = widget->allocation.height;
558
559 drawing->damage_begin = 0;
560 drawing->damage_end = widget->allocation.width;
561
562 if((widget->allocation.width != 1 &&
563 widget->allocation.height != 1)
564 && drawing->damage_begin < drawing->damage_end)
565 {
566
567 rectangle_pixmap (drawing->control_flow_data->process_list,
568 drawing->drawing_area->style->black_gc,
569 TRUE,
570 0, 0,
571 drawing->alloc_width, // do not overlap
572 -1);
573
574
575 drawing_data_request(drawing,
576 drawing->damage_begin,
577 0,
578 drawing->damage_end - drawing->damage_begin,
579 drawing->height);
580 }
581 }
582 return TRUE;
583 }
584
585
586 /* Redraw the screen from the backing pixmap */
587 static gboolean
588 expose_event( GtkWidget *widget, GdkEventExpose *event, gpointer user_data )
589 {
590 Drawing_t *drawing = (Drawing_t*)user_data;
591
592 ControlFlowData *control_flow_data =
593 (ControlFlowData*)g_object_get_data(
594 G_OBJECT(widget),
595 "control_flow_data");
596 if(unlikely(drawing->gc == NULL)) {
597 drawing->gc = gdk_gc_new(drawing->drawing_area->window);
598 gdk_gc_copy(drawing->gc, drawing->drawing_area->style->black_gc);
599 }
600
601 TimeWindow time_window =
602 lttvwindow_get_time_window(control_flow_data->tab);
603 LttTime current_time =
604 lttvwindow_get_current_time(control_flow_data->tab);
605
606 guint cursor_x=0;
607
608 LttTime window_end = time_window.end_time;
609
610 /* update the screen from the pixmap buffer */
611 #if 0
612 gdk_draw_pixmap(widget->window,
613 widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
614 drawing->pixmap,
615 event->area.x, event->area.y,
616 event->area.x, event->area.y,
617 event->area.width, event->area.height);
618 #endif //0
619 drawing->height = processlist_get_height(control_flow_data->process_list);
620 copy_pixmap_to_screen(control_flow_data->process_list,
621 widget->window,
622 widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
623 event->area.x, event->area.y,
624 event->area.width, event->area.height);
625
626
627 /* Erase the dotted lines left.. */
628 if(widget->allocation.height > drawing->height)
629 {
630 gdk_draw_rectangle (widget->window,
631 drawing->drawing_area->style->black_gc,
632 TRUE,
633 event->area.x, drawing->height,
634 event->area.width, // do not overlap
635 widget->allocation.height - drawing->height);
636 }
637 if(ltt_time_compare(time_window.start_time, current_time) <= 0 &&
638 ltt_time_compare(window_end, current_time) >= 0)
639 {
640 /* Draw the dotted lines */
641 convert_time_to_pixels(
642 time_window,
643 current_time,
644 drawing->width,
645 &cursor_x);
646
647
648 if(drawing->dotted_gc == NULL) {
649
650 drawing->dotted_gc = gdk_gc_new(drawing->drawing_area->window);
651 gdk_gc_copy(drawing->dotted_gc, widget->style->white_gc);
652
653 gint8 dash_list[] = { 1, 2 };
654 gdk_gc_set_line_attributes(drawing->dotted_gc,
655 1,
656 GDK_LINE_ON_OFF_DASH,
657 GDK_CAP_BUTT,
658 GDK_JOIN_MITER);
659 gdk_gc_set_dashes(drawing->dotted_gc,
660 0,
661 dash_list,
662 2);
663 }
664 gint height_tot = MAX(widget->allocation.height, drawing->height);
665 gdk_draw_line(widget->window,
666 drawing->dotted_gc,
667 cursor_x, 0,
668 cursor_x, height_tot);
669 }
670 return FALSE;
671 }
672
673 static gboolean
674 after_expose_event( GtkWidget *widget, GdkEventExpose *event, gpointer user_data )
675 {
676 //g_assert(0);
677 g_debug("AFTER EXPOSE");
678
679 return FALSE;
680
681
682 }
683
684 #if 0
685 void
686 tree_row_activated(GtkTreeModel *treemodel,
687 GtkTreePath *arg1,
688 GtkTreeViewColumn *arg2,
689 gpointer user_data)
690 {
691 ControlFlowData *cfd = (ControlFlowData*)user_data;
692 Drawing_t *drawing = cfd->drawing;
693 GtkTreeView *treeview = cfd->process_list->process_list_widget;
694 gint *path_indices;
695 gint height;
696
697 path_indices = gtk_tree_path_get_indices (arg1);
698
699 height = get_cell_height(cfd->process_list,
700 GTK_TREE_VIEW(treeview));
701 drawing->horizontal_sel = height * path_indices[0];
702 g_critical("new hor sel : %i", drawing->horizontal_sel);
703 }
704 #endif //0
705
706 /* mouse click */
707 static gboolean
708 button_press_event( GtkWidget *widget, GdkEventButton *event, gpointer user_data )
709 {
710 ControlFlowData *control_flow_data =
711 (ControlFlowData*)g_object_get_data(
712 G_OBJECT(widget),
713 "control_flow_data");
714 Drawing_t *drawing = control_flow_data->drawing;
715 TimeWindow time_window =
716 lttvwindow_get_time_window(control_flow_data->tab);
717
718 g_debug("click");
719 if(event->button == 1)
720 {
721 LttTime time;
722
723 /* left mouse button click */
724 g_debug("x click is : %f", event->x);
725
726 convert_pixels_to_time(drawing->width, (guint)event->x,
727 time_window,
728 &time);
729
730 lttvwindow_report_current_time(control_flow_data->tab, time);
731
732 }
733
734 return FALSE;
735 }
736
737 static gboolean
738 scrollbar_size_allocate(GtkWidget *widget,
739 GtkAllocation *allocation,
740 gpointer user_data)
741 {
742 Drawing_t *drawing = (Drawing_t*)user_data;
743
744 gtk_widget_set_size_request(drawing->padding, allocation->width, -1);
745 //gtk_widget_queue_resize(drawing->padding);
746 //gtk_widget_queue_resize(drawing->ruler);
747 gtk_container_check_resize(GTK_CONTAINER(drawing->ruler_hbox));
748 return 0;
749 }
750
751
752
753 Drawing_t *drawing_construct(ControlFlowData *control_flow_data)
754 {
755 Drawing_t *drawing = g_new(Drawing_t, 1);
756
757 drawing->control_flow_data = control_flow_data;
758
759 drawing->vbox = gtk_vbox_new(FALSE, 1);
760
761
762 drawing->ruler_hbox = gtk_hbox_new(FALSE, 1);
763 drawing->ruler = gtk_drawing_area_new ();
764 //gtk_widget_set_size_request(drawing->ruler, -1, 27);
765
766 drawing->padding = gtk_drawing_area_new ();
767 //gtk_widget_set_size_request(drawing->padding, -1, 27);
768 gtk_box_pack_start(GTK_BOX(drawing->ruler_hbox), drawing->ruler,
769 TRUE, TRUE, 0);
770 gtk_box_pack_end(GTK_BOX(drawing->ruler_hbox), drawing->padding,
771 FALSE, FALSE, 0);
772
773
774
775 drawing->drawing_area = gtk_drawing_area_new ();
776
777 drawing->gc = NULL;
778
779 drawing->hbox = gtk_hbox_new(FALSE, 1);
780 drawing->viewport = gtk_viewport_new(NULL, control_flow_data->v_adjust);
781 drawing->scrollbar = gtk_vscrollbar_new(control_flow_data->v_adjust);
782 gtk_box_pack_start(GTK_BOX(drawing->hbox), drawing->viewport,
783 TRUE, TRUE, 0);
784 gtk_box_pack_end(GTK_BOX(drawing->hbox), drawing->scrollbar,
785 FALSE, FALSE, 0);
786
787 //drawing->scrolled_window =
788 // gtk_scrolled_window_new (NULL,
789 // control_flow_data->v_adjust);
790
791 //gtk_scrolled_window_set_policy(
792 // GTK_SCROLLED_WINDOW(drawing->scrolled_window),
793 // GTK_POLICY_NEVER,
794 // GTK_POLICY_AUTOMATIC);
795
796 gtk_container_add(GTK_CONTAINER(drawing->viewport),
797 drawing->drawing_area);
798 //gtk_scrolled_window_add_with_viewport(
799 // GTK_SCROLLED_WINDOW(drawing->scrolled_window),
800 // drawing->drawing_area);
801
802 gtk_box_pack_start(GTK_BOX(drawing->vbox), drawing->ruler_hbox,
803 FALSE, FALSE, 0);
804 gtk_box_pack_end(GTK_BOX(drawing->vbox), drawing->hbox,
805 TRUE, TRUE, 0);
806
807 drawing->pango_layout =
808 gtk_widget_create_pango_layout(drawing->drawing_area, NULL);
809
810 drawing->dotted_gc = NULL;
811
812 drawing->height = 1;
813 drawing->width = 1;
814 drawing->depth = 0;
815 drawing->alloc_height = 1;
816 drawing->alloc_width = 1;
817
818 drawing->damage_begin = 0;
819 drawing->damage_end = 0;
820 drawing->horizontal_sel = -1;
821
822 //gtk_widget_set_size_request(drawing->drawing_area->window, 50, 50);
823 g_object_set_data_full(
824 G_OBJECT(drawing->drawing_area),
825 "Link_drawing_Data",
826 drawing,
827 (GDestroyNotify)drawing_destroy);
828
829 g_object_set_data(
830 G_OBJECT(drawing->ruler),
831 "drawing",
832 drawing);
833
834
835 //gtk_widget_modify_bg( drawing->drawing_area,
836 // GTK_STATE_NORMAL,
837 // &CF_Colors[BLACK]);
838
839 //gdk_window_get_geometry(drawing->drawing_area->window,
840 // NULL, NULL,
841 // &(drawing->width),
842 // &(drawing->height),
843 // -1);
844
845 //drawing->pixmap = gdk_pixmap_new(
846 // drawing->drawing_area->window,
847 // drawing->width,
848 // drawing->height,
849 // drawing->depth);
850
851 //drawing->pixmap = NULL;
852
853 // drawing->pixmap = gdk_pixmap_new(drawing->drawing_area->window,
854 // drawing->drawing_area->allocation.width,
855 // drawing->drawing_area->allocation.height,
856 // -1);
857
858 g_signal_connect (G_OBJECT(drawing->drawing_area),
859 "configure_event",
860 G_CALLBACK (configure_event),
861 (gpointer)drawing);
862
863 g_signal_connect (G_OBJECT(drawing->ruler),
864 "expose_event",
865 G_CALLBACK(expose_ruler),
866 (gpointer)drawing);
867
868 gtk_widget_add_events(drawing->ruler, GDK_POINTER_MOTION_MASK);
869
870 g_signal_connect (G_OBJECT(drawing->ruler),
871 "motion-notify-event",
872 G_CALLBACK(motion_notify_ruler),
873 (gpointer)drawing);
874
875
876 g_signal_connect (G_OBJECT(drawing->scrollbar),
877 "size-allocate",
878 G_CALLBACK(scrollbar_size_allocate),
879 (gpointer)drawing);
880
881
882
883 g_signal_connect (G_OBJECT(drawing->drawing_area),
884 "expose_event",
885 G_CALLBACK (expose_event),
886 (gpointer)drawing);
887
888 g_signal_connect_after (G_OBJECT(drawing->drawing_area),
889 "expose_event",
890 G_CALLBACK (after_expose_event),
891 (gpointer)drawing);
892
893 g_signal_connect (G_OBJECT(drawing->drawing_area),
894 "button-press-event",
895 G_CALLBACK (button_press_event),
896 (gpointer)drawing);
897
898 gtk_widget_show(drawing->ruler);
899 gtk_widget_show(drawing->padding);
900 gtk_widget_show(drawing->ruler_hbox);
901
902 gtk_widget_show(drawing->drawing_area);
903 //gtk_widget_show(drawing->scrolled_window);
904 gtk_widget_show(drawing->viewport);
905 gtk_widget_show(drawing->scrollbar);
906 gtk_widget_show(drawing->hbox);
907
908 /* Allocate the colors */
909 GdkColormap* colormap = gdk_colormap_get_system();
910 gboolean success[NUM_COLORS];
911 gdk_colormap_alloc_colors(colormap, drawing_colors, NUM_COLORS, FALSE,
912 TRUE, success);
913
914 return drawing;
915 }
916
917 void drawing_destroy(Drawing_t *drawing)
918 {
919 g_info("drawing_destroy %p", drawing);
920
921 /* Free the colors */
922 GdkColormap* colormap = gdk_colormap_get_system();
923
924 gdk_colormap_free_colors(colormap, drawing_colors, NUM_COLORS);
925
926
927
928 // Do not unref here, Drawing_t destroyed by it's widget.
929 //g_object_unref( G_OBJECT(drawing->drawing_area));
930 if(drawing->gc != NULL)
931 gdk_gc_unref(drawing->gc);
932
933 g_free(drawing->pango_layout);
934 if(drawing->dotted_gc != NULL) gdk_gc_unref(drawing->dotted_gc);
935 g_free(drawing);
936 g_info("drawing_destroy end");
937 }
938
939 GtkWidget *drawing_get_drawing_area(Drawing_t *drawing)
940 {
941 return drawing->drawing_area;
942 }
943
944 GtkWidget *drawing_get_widget(Drawing_t *drawing)
945 {
946 return drawing->vbox;
947 }
948
949 void drawing_draw_line( Drawing_t *drawing,
950 GdkPixmap *pixmap,
951 guint x1, guint y1,
952 guint x2, guint y2,
953 GdkGC *GC)
954 {
955 gdk_draw_line (pixmap,
956 GC,
957 x1, y1, x2, y2);
958 }
959
960 void drawing_clear(Drawing_t *drawing)
961 {
962 //if (drawing->pixmap)
963 // gdk_pixmap_unref(drawing->pixmap);
964 ControlFlowData *cfd = drawing->control_flow_data;
965
966
967 rectangle_pixmap(cfd->process_list,
968 drawing->drawing_area->style->black_gc,
969 TRUE,
970 0, 0,
971 drawing->alloc_width, // do not overlap
972 -1);
973
974 //drawing->height = 1;
975 /* Allocate a new pixmap with new height */
976 //drawing->pixmap = gdk_pixmap_new(drawing->drawing_area->window,
977 // drawing->width + SAFETY + EXTRA_ALLOC,
978 // drawing->height + EXTRA_ALLOC,
979 // -1);
980 //drawing->alloc_width = drawing->width + SAFETY + EXTRA_ALLOC;
981 //drawing->alloc_height = drawing->height + EXTRA_ALLOC;
982
983 //gtk_widget_set_size_request(drawing->drawing_area,
984 // -1,
985 // drawing->height);
986 //gtk_widget_queue_resize_no_redraw(drawing->drawing_area);
987
988 /* ask for the buffer to be redrawn */
989 gtk_widget_queue_draw ( drawing->drawing_area);
990 }
991
992 #if 0
993 /* Insert a square corresponding to a new process in the list */
994 /* Applies to whole drawing->width */
995 void drawing_insert_square(Drawing_t *drawing,
996 guint y,
997 guint height)
998 {
999 //GdkRectangle update_rect;
1000 gboolean reallocate = FALSE;
1001 GdkPixmap *new_pixmap;
1002
1003 /* Allocate a new pixmap with new height */
1004 if(drawing->alloc_height < drawing->height + height) {
1005
1006 new_pixmap = gdk_pixmap_new(drawing->drawing_area->window,
1007 drawing->width + SAFETY + EXTRA_ALLOC,
1008 drawing->height + height + EXTRA_ALLOC,
1009 -1);
1010 drawing->alloc_width = drawing->width + SAFETY + EXTRA_ALLOC;
1011 drawing->alloc_height = drawing->height + height + EXTRA_ALLOC;
1012 reallocate = TRUE;
1013
1014 /* Copy the high region */
1015 gdk_draw_pixmap (new_pixmap,
1016 drawing->drawing_area->style->black_gc,
1017 drawing->pixmap,
1018 0, 0,
1019 0, 0,
1020 drawing->width + SAFETY, y);
1021
1022 } else {
1023 new_pixmap = drawing->pixmap;
1024 }
1025
1026 //GdkPixmap *pixmap = gdk_pixmap_new(drawing->drawing_area->window,
1027 // drawing->width + SAFETY,
1028 // drawing->height + height,
1029 // -1);
1030
1031 /* add an empty square */
1032 gdk_draw_rectangle (new_pixmap,
1033 drawing->drawing_area->style->black_gc,
1034 TRUE,
1035 0, y,
1036 drawing->width + SAFETY, // do not overlap
1037 height);
1038
1039 /* copy the bottom of the region */
1040 gdk_draw_pixmap (new_pixmap,
1041 drawing->drawing_area->style->black_gc,
1042 drawing->pixmap,
1043 0, y,
1044 0, y + height,
1045 drawing->width+SAFETY, drawing->height - y);
1046
1047
1048 if(reallocate && likely(drawing->pixmap)) {
1049 gdk_pixmap_unref(drawing->pixmap);
1050 drawing->pixmap = new_pixmap;
1051 }
1052
1053 if(unlikely(drawing->height==1)) drawing->height = height;
1054 else drawing->height += height;
1055
1056 gtk_widget_set_size_request(drawing->drawing_area,
1057 -1,
1058 drawing->height);
1059 gtk_widget_queue_resize_no_redraw(drawing->drawing_area);
1060
1061 /* ask for the buffer to be redrawn */
1062 gtk_widget_queue_draw_area ( drawing->drawing_area,
1063 0, y,
1064 drawing->width, drawing->height-y);
1065 }
1066
1067
1068 /* Remove a square corresponding to a removed process in the list */
1069 void drawing_remove_square(Drawing_t *drawing,
1070 guint y,
1071 guint height)
1072 {
1073 GdkPixmap *pixmap;
1074
1075 if(unlikely((guint)drawing->height == height)) {
1076 //pixmap = gdk_pixmap_new(
1077 // drawing->drawing_area->window,
1078 // drawing->width + SAFETY,
1079 // 1,
1080 // -1);
1081 pixmap = drawing->pixmap;
1082 drawing->height=1;
1083 } else {
1084 /* Allocate a new pixmap with new height */
1085 //pixmap = gdk_pixmap_new(
1086 // drawing->drawing_area->window,
1087 // drawing->width + SAFETY,
1088 // drawing->height - height,
1089 // -1);
1090 /* Keep the same preallocated pixmap */
1091 pixmap = drawing->pixmap;
1092
1093 /* Copy the high region */
1094 gdk_draw_pixmap (pixmap,
1095 drawing->drawing_area->style->black_gc,
1096 drawing->pixmap,
1097 0, 0,
1098 0, 0,
1099 drawing->width + SAFETY, y);
1100
1101 /* Copy up the bottom of the region */
1102 gdk_draw_pixmap (pixmap,
1103 drawing->drawing_area->style->black_gc,
1104 drawing->pixmap,
1105 0, y + height,
1106 0, y,
1107 drawing->width, drawing->height - y - height);
1108
1109 drawing->height-=height;
1110 }
1111
1112 //if(likely(drawing->pixmap))
1113 // gdk_pixmap_unref(drawing->pixmap);
1114
1115 //drawing->pixmap = pixmap;
1116
1117 gtk_widget_set_size_request(drawing->drawing_area,
1118 -1,
1119 drawing->height);
1120 gtk_widget_queue_resize_no_redraw(drawing->drawing_area);
1121 /* ask for the buffer to be redrawn */
1122 gtk_widget_queue_draw_area ( drawing->drawing_area,
1123 0, y,
1124 drawing->width, MAX(drawing->height-y, 1));
1125 }
1126 #endif //0
1127
1128 void drawing_update_ruler(Drawing_t *drawing, TimeWindow *time_window)
1129 {
1130 GtkRequisition req;
1131 GdkRectangle rect;
1132
1133 req.width = drawing->ruler->allocation.width;
1134 req.height = drawing->ruler->allocation.height;
1135
1136
1137 rect.x = 0;
1138 rect.y = 0;
1139 rect.width = req.width;
1140 rect.height = req.height;
1141
1142 gtk_widget_queue_draw(drawing->ruler);
1143 //gtk_widget_draw( drawing->ruler, &rect);
1144 }
1145
1146 /* Redraw the ruler */
1147 static gboolean
1148 expose_ruler( GtkWidget *widget, GdkEventExpose *event, gpointer user_data )
1149 {
1150 /* ruler desactivated */
1151 return 0;
1152 Drawing_t *drawing = (Drawing_t*)user_data;
1153 TimeWindow time_window = lttvwindow_get_time_window(drawing->control_flow_data->tab);
1154 gchar text[255];
1155
1156 PangoContext *context;
1157 PangoLayout *layout;
1158 PangoFontDescription *FontDesc;
1159 PangoRectangle ink_rect;
1160 gint global_width=0;
1161 GdkColor foreground = { 0, 0, 0, 0 };
1162 GdkColor background = { 0, 0xffff, 0xffff, 0xffff };
1163
1164 LttTime window_end = time_window.end_time;
1165 LttTime half_width =
1166 ltt_time_div(time_window.time_width,2.0);
1167 LttTime window_middle =
1168 ltt_time_add(half_width,
1169 time_window.start_time);
1170 g_debug("ruler expose event");
1171
1172 gdk_draw_rectangle (drawing->ruler->window,
1173 drawing->ruler->style->white_gc,
1174 TRUE,
1175 event->area.x, event->area.y,
1176 event->area.width,
1177 event->area.height);
1178
1179 GdkGC *gc = gdk_gc_new(drawing->ruler->window);
1180 gdk_gc_copy(gc, drawing->ruler->style->black_gc);
1181 gdk_gc_set_line_attributes(gc,
1182 2,
1183 GDK_LINE_SOLID,
1184 GDK_CAP_BUTT,
1185 GDK_JOIN_MITER);
1186 gdk_draw_line (drawing->ruler->window,
1187 gc,
1188 event->area.x, 1,
1189 event->area.x + event->area.width, 1);
1190
1191
1192 snprintf(text, 255, "%lus\n%luns",
1193 time_window.start_time.tv_sec,
1194 time_window.start_time.tv_nsec);
1195
1196 layout = gtk_widget_create_pango_layout(drawing->drawing_area, NULL);
1197
1198 context = pango_layout_get_context(layout);
1199 FontDesc = pango_context_get_font_description(context);
1200
1201 pango_font_description_set_size(FontDesc, 6*PANGO_SCALE);
1202 pango_layout_context_changed(layout);
1203
1204 pango_layout_set_text(layout, text, -1);
1205 pango_layout_get_pixel_extents(layout, &ink_rect, NULL);
1206 global_width += ink_rect.width;
1207
1208 gdk_draw_layout_with_colors(drawing->ruler->window,
1209 gc,
1210 0,
1211 6,
1212 layout, &foreground, &background);
1213
1214 gdk_gc_set_line_attributes(gc,
1215 2,
1216 GDK_LINE_SOLID,
1217 GDK_CAP_ROUND,
1218 GDK_JOIN_ROUND);
1219
1220 gdk_draw_line (drawing->ruler->window,
1221 gc,
1222 1, 1,
1223 1, 7);
1224
1225
1226 snprintf(text, 255, "%lus\n%luns", window_end.tv_sec,
1227 window_end.tv_nsec);
1228
1229 pango_layout_set_text(layout, text, -1);
1230 pango_layout_get_pixel_extents(layout, &ink_rect, NULL);
1231 global_width += ink_rect.width;
1232
1233 if(global_width <= drawing->ruler->allocation.width)
1234 {
1235 gdk_draw_layout_with_colors(drawing->ruler->window,
1236 gc,
1237 drawing->ruler->allocation.width - ink_rect.width,
1238 6,
1239 layout, &foreground, &background);
1240
1241 gdk_gc_set_line_attributes(gc,
1242 2,
1243 GDK_LINE_SOLID,
1244 GDK_CAP_ROUND,
1245 GDK_JOIN_ROUND);
1246
1247 gdk_draw_line (drawing->ruler->window,
1248 gc,
1249 drawing->ruler->allocation.width-1, 1,
1250 drawing->ruler->allocation.width-1, 7);
1251 }
1252
1253
1254 snprintf(text, 255, "%lus\n%luns", window_middle.tv_sec,
1255 window_middle.tv_nsec);
1256
1257 pango_layout_set_text(layout, text, -1);
1258 pango_layout_get_pixel_extents(layout, &ink_rect, NULL);
1259 global_width += ink_rect.width;
1260
1261 if(global_width <= drawing->ruler->allocation.width)
1262 {
1263 gdk_draw_layout_with_colors(drawing->ruler->window,
1264 gc,
1265 (drawing->ruler->allocation.width - ink_rect.width)/2,
1266 6,
1267 layout, &foreground, &background);
1268
1269 gdk_gc_set_line_attributes(gc,
1270 2,
1271 GDK_LINE_SOLID,
1272 GDK_CAP_ROUND,
1273 GDK_JOIN_ROUND);
1274
1275 gdk_draw_line (drawing->ruler->window,
1276 gc,
1277 drawing->ruler->allocation.width/2, 1,
1278 drawing->ruler->allocation.width/2, 7);
1279
1280
1281
1282
1283 }
1284
1285 gdk_gc_unref(gc);
1286 g_object_unref(layout);
1287
1288 return FALSE;
1289 }
1290
1291
1292 /* notify mouse on ruler */
1293 static gboolean
1294 motion_notify_ruler(GtkWidget *widget, GdkEventMotion *event, gpointer user_data)
1295 {
1296 //g_debug("motion");
1297 //eventually follow mouse and show time here
1298 }
This page took 0.106168 seconds and 4 git commands to generate.