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