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