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