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