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