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