Drawing to drawing name change
[lttv.git] / ltt / branches / poly / lttv / modules / guiControlFlow / Drawing.c
1
2 #include <gtk/gtk.h>
3 #include <gdk/gdk.h>
4
5 #include <lttv/processTrace.h>
6 #include <lttv/gtkTraceSet.h>
7 #include <lttv/hook.h>
8
9 #include "Drawing.h"
10 #include "CFV.h"
11 #include "CFV-private.h"
12 #include "Event_Hooks.h"
13
14 #define g_info(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, format)
15 #define g_debug(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, format)
16
17 /*****************************************************************************
18 * drawing functions *
19 *****************************************************************************/
20
21 //FIXME Colors will need to be dynamic. Graphic context part not done so far.
22 typedef enum
23 {
24 RED,
25 GREEN,
26 BLUE,
27 WHITE,
28 BLACK
29
30 } ControlFlowColors;
31
32 /* Vector of unallocated colors */
33 static GdkColor CF_Colors [] =
34 {
35 { 0, 0xffff, 0x0000, 0x0000 }, // RED
36 { 0, 0x0000, 0xffff, 0x0000 }, // GREEN
37 { 0, 0x0000, 0x0000, 0xffff }, // BLUE
38 { 0, 0xffff, 0xffff, 0xffff }, // WHITE
39 { 0, 0x0000, 0x0000, 0x0000 } // BLACK
40 };
41
42
43 /* Function responsible for updating the exposed area.
44 * It must call processTrace() to ask for this update.
45 * Note : this function cannot clear the background, because it may
46 * erase drawing already present (SAFETY).
47 */
48 void drawing_data_request(Drawing_t *drawing,
49 GdkPixmap **pixmap,
50 gint x, gint y,
51 gint width,
52 gint height)
53 {
54 if(width < 0) return ;
55 if(height < 0) return ;
56 ControlFlowData *control_flow_data =
57 (ControlFlowData*)g_object_get_data(
58 G_OBJECT(
59 drawing->drawing_area),
60 "control_flow_data");
61
62 LttTime start, end;
63 LttTime window_end = ltt_time_add(control_flow_data->time_window.time_width,
64 control_flow_data->time_window.start_time);
65
66 g_critical("req : window_end : %u, %u", window_end.tv_sec,
67 window_end.tv_nsec);
68
69 g_critical("req : time width : %u, %u", control_flow_data->time_window.time_width.tv_sec,
70 control_flow_data->time_window.time_width.tv_nsec);
71
72 g_critical("x is : %i, x+width is : %i", x, x+width);
73
74 convert_pixels_to_time(drawing->drawing_area->allocation.width, x,
75 &control_flow_data->time_window.start_time,
76 &window_end,
77 &start);
78
79 convert_pixels_to_time(drawing->drawing_area->allocation.width, x + width,
80 &control_flow_data->time_window.start_time,
81 &window_end,
82 &end);
83
84 LttvTracesetContext * tsc =
85 get_traceset_context(control_flow_data->mw);
86
87 //send_test_process(
88 //guicontrolflow_get_process_list(drawing->control_flow_data),
89 //drawing);
90 //send_test_drawing(
91 //guicontrolflow_get_process_list(drawing->control_flow_data),
92 //drawing, *pixmap, x, y, width, height);
93
94 // Let's call processTrace() !!
95 EventRequest event_request; // Variable freed at the end of the function.
96 event_request.control_flow_data = control_flow_data;
97 event_request.time_begin = start;
98 event_request.time_end = end;
99 event_request.x_begin = x;
100 event_request.x_end = x+width;
101
102 g_critical("req : start : %u, %u", event_request.time_begin.tv_sec,
103 event_request.time_begin.tv_nsec);
104
105 g_critical("req : end : %u, %u", event_request.time_end.tv_sec,
106 event_request.time_end.tv_nsec);
107
108 LttvHooks *event = lttv_hooks_new();
109 LttvHooks *after_event = lttv_hooks_new();
110 LttvHooks *after_traceset = lttv_hooks_new();
111 lttv_hooks_add(after_traceset, after_data_request, &event_request);
112 lttv_hooks_add(event, draw_event_hook, &event_request);
113 //Modified by xiangxiu: state update hooks are added by the main window
114 //state_add_event_hooks_api(control_flow_data->mw);
115 lttv_hooks_add(after_event, draw_after_hook, &event_request);
116
117 lttv_process_traceset_seek_time(tsc, start);
118 // FIXME : would like to place the after_traceset hook after the traceset,
119 // but the traceset context state is not valid anymore.
120 lttv_traceset_context_add_hooks(tsc,
121 // NULL, after_traceset, NULL, NULL, NULL, NULL,
122 NULL, NULL, NULL, NULL, NULL, NULL,
123 NULL, after_traceset, NULL, event, after_event);
124 lttv_process_traceset(tsc, end, G_MAXULONG);
125 //after_data_request((void*)&event_request,(void*)tsc);
126 lttv_traceset_context_remove_hooks(tsc,
127 //NULL, after_traceset, NULL, NULL, NULL, NULL,
128 NULL, NULL, NULL, NULL, NULL, NULL,
129 NULL, after_traceset, NULL, event, after_event);
130 //Modified by xiangxiu: state update hooks are removed by the main window
131 //state_remove_event_hooks_api(control_flow_data->mw);
132
133 lttv_hooks_destroy(after_traceset);
134 lttv_hooks_destroy(event);
135 lttv_hooks_destroy(after_event);
136
137
138 }
139
140 /* Callbacks */
141
142
143 /* Create a new backing pixmap of the appropriate size */
144 /* As the scaling will always change, it's of no use to copy old
145 * pixmap.
146 */
147 static gboolean
148 configure_event( GtkWidget *widget, GdkEventConfigure *event,
149 gpointer user_data)
150 {
151 Drawing_t *drawing = (Drawing_t*)user_data;
152
153
154 /* First, get the new time interval of the main window */
155 /* we assume (see documentation) that the main window
156 * has updated the time interval before this configure gets
157 * executed.
158 */
159 get_time_window(drawing->control_flow_data->mw,
160 &drawing->control_flow_data->time_window);
161
162 /* New pixmap, size of the configure event */
163 //GdkPixmap *pixmap = gdk_pixmap_new(widget->window,
164 // widget->allocation.width + SAFETY,
165 // widget->allocation.height + SAFETY,
166 // -1);
167
168 g_critical("drawing configure event");
169 g_critical("New draw size : %i by %i",widget->allocation.width, widget->allocation.height);
170
171
172 if (drawing->pixmap)
173 gdk_pixmap_unref(drawing->pixmap);
174
175 /* If no old pixmap present */
176 //if(drawing->pixmap == NULL)
177 {
178 drawing->pixmap = gdk_pixmap_new(
179 widget->window,
180 widget->allocation.width + SAFETY,
181 widget->allocation.height + SAFETY,
182 //ProcessList_get_height
183 // (GuiControlFlow_get_process_list(drawing->control_flow_data)),
184 -1);
185 drawing->width = widget->allocation.width;
186 drawing->height = widget->allocation.height;
187
188
189 // Clear the image
190 gdk_draw_rectangle (drawing->pixmap,
191 widget->style->white_gc,
192 TRUE,
193 0, 0,
194 widget->allocation.width+SAFETY,
195 widget->allocation.height+SAFETY);
196
197 //g_info("init data request");
198
199
200 /* Initial data request */
201 // Do not need to ask for data of 1 pixel : not synchronized with
202 // main window time at this moment.
203 drawing_data_request(drawing, &drawing->pixmap, 0, 0,
204 widget->allocation.width,
205 widget->allocation.height);
206
207 drawing->width = widget->allocation.width;
208 drawing->height = widget->allocation.height;
209
210 return TRUE;
211
212
213
214 }
215 #ifdef NOTUSE
216 // /* Draw empty background */
217 // gdk_draw_rectangle (pixmap,
218 // widget->style->black_gc,
219 // TRUE,
220 // 0, 0,
221 // widget->allocation.width,
222 // widget->allocation.height);
223
224 /* Copy old data to new pixmap */
225 gdk_draw_drawable (pixmap,
226 widget->style->white_gc,
227 drawing->pixmap,
228 0, 0,
229 0, 0,
230 -1, -1);
231
232 if (drawing->pixmap)
233 gdk_pixmap_unref(drawing->pixmap);
234
235 drawing->pixmap = pixmap;
236
237 // Clear the bottom part of the image (SAFETY)
238 gdk_draw_rectangle (pixmap,
239 widget->style->white_gc,
240 TRUE,
241 0, drawing->height+SAFETY,
242 drawing->width+SAFETY, // do not overlap
243 (widget->allocation.height) - drawing->height);
244
245 // Clear the right part of the image (SAFETY)
246 gdk_draw_rectangle (pixmap,
247 widget->style->white_gc,
248 TRUE,
249 drawing->width+SAFETY, 0,
250 (widget->allocation.width) - drawing->width, // do not overlap
251 drawing->height+SAFETY);
252
253 /* Clear the backgound for data request, but not SAFETY */
254 gdk_draw_rectangle (pixmap,
255 drawing->drawing_area->style->white_gc,
256 TRUE,
257 drawing->width + SAFETY, 0,
258 widget->allocation.width - drawing->width, // do not overlap
259 widget->allocation.height+SAFETY);
260
261 /* Request data for missing space */
262 g_info("missing data request");
263 drawing_data_request(drawing, &pixmap, drawing->width, 0,
264 widget->allocation.width - drawing->width,
265 widget->allocation.height);
266
267 drawing->width = widget->allocation.width;
268 drawing->height = widget->allocation.height;
269
270 return TRUE;
271 #endif //NOTUSE
272 }
273
274
275 /* Redraw the screen from the backing pixmap */
276 static gboolean
277 expose_event( GtkWidget *widget, GdkEventExpose *event, gpointer user_data )
278 {
279 Drawing_t *drawing = (Drawing_t*)user_data;
280 ControlFlowData *control_flow_data =
281 (ControlFlowData*)g_object_get_data(
282 G_OBJECT(widget),
283 "control_flow_data");
284
285 g_critical("drawing expose event");
286
287 guint x=0;
288 LttTime* current_time =
289 guicontrolflow_get_current_time(control_flow_data);
290
291 LttTime window_end = ltt_time_add(control_flow_data->time_window.time_width,
292 control_flow_data->time_window.start_time);
293
294 convert_time_to_pixels(
295 control_flow_data->time_window.start_time,
296 window_end,
297 *current_time,
298 widget->allocation.width,
299 &x);
300
301 gdk_draw_pixmap(widget->window,
302 widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
303 drawing->pixmap,
304 event->area.x, event->area.y,
305 event->area.x, event->area.y,
306 event->area.width, event->area.height);
307
308 if(x >= event->area.x && x <= event->area.x+event->area.width)
309 {
310 GdkGC *gc = gdk_gc_new(control_flow_data->drawing->pixmap);
311 gdk_gc_copy(gc, widget->style->black_gc);
312
313 drawing_draw_line(NULL, widget->window,
314 x, event->area.y,
315 x, event->area.y+event->area.height,
316 gc);
317 gdk_gc_unref(gc);
318 }
319 return FALSE;
320 }
321
322 /* mouse click */
323 static gboolean
324 button_press_event( GtkWidget *widget, GdkEventButton *event, gpointer user_data )
325 {
326 ControlFlowData *control_flow_data =
327 (ControlFlowData*)g_object_get_data(
328 G_OBJECT(widget),
329 "control_flow_data");
330 Drawing_t *drawing = control_flow_data->drawing;
331
332
333 g_critical("click");
334 if(event->button == 1)
335 {
336 LttTime time;
337
338 LttTime window_end = ltt_time_add(control_flow_data->time_window.time_width,
339 control_flow_data->time_window.start_time);
340
341
342 /* left mouse button click */
343 g_critical("x click is : %f", event->x);
344
345 convert_pixels_to_time(widget->allocation.width, (guint)event->x,
346 &control_flow_data->time_window.start_time,
347 &window_end,
348 &time);
349
350 set_current_time(control_flow_data->mw, &time);
351
352 }
353
354 return FALSE;
355 }
356
357
358
359
360 Drawing_t *drawing_construct(ControlFlowData *control_flow_data)
361 {
362 Drawing_t *drawing = g_new(Drawing_t, 1);
363
364 drawing->drawing_area = gtk_drawing_area_new ();
365 drawing->control_flow_data = control_flow_data;
366
367 drawing->pango_layout =
368 gtk_widget_create_pango_layout(drawing->drawing_area, NULL);
369
370 //gtk_widget_set_size_request(drawing->drawing_area->window, 50, 50);
371 g_object_set_data_full(
372 G_OBJECT(drawing->drawing_area),
373 "Link_drawing_Data",
374 drawing,
375 (GDestroyNotify)drawing_destroy);
376
377 //gtk_widget_modify_bg( drawing->drawing_area,
378 // GTK_STATE_NORMAL,
379 // &CF_Colors[BLACK]);
380
381 //gdk_window_get_geometry(drawing->drawing_area->window,
382 // NULL, NULL,
383 // &(drawing->width),
384 // &(drawing->height),
385 // -1);
386
387 //drawing->pixmap = gdk_pixmap_new(
388 // drawing->drawing_area->window,
389 // drawing->width,
390 // drawing->height,
391 // drawing->depth);
392
393 drawing->pixmap = NULL;
394
395 // drawing->pixmap = gdk_pixmap_new(drawing->drawing_area->window,
396 // drawing->drawing_area->allocation.width,
397 // drawing->drawing_area->allocation.height,
398 // -1);
399
400 gtk_widget_add_events(drawing->drawing_area, GDK_BUTTON_PRESS_MASK);
401
402 g_signal_connect (G_OBJECT(drawing->drawing_area),
403 "configure_event",
404 G_CALLBACK (configure_event),
405 (gpointer)drawing);
406
407 g_signal_connect (G_OBJECT(drawing->drawing_area),
408 "expose_event",
409 G_CALLBACK (expose_event),
410 (gpointer)drawing);
411
412 g_signal_connect (G_OBJECT(drawing->drawing_area),
413 "button-press-event",
414 G_CALLBACK (button_press_event),
415 (gpointer)drawing);
416
417
418 return drawing;
419 }
420
421 void drawing_destroy(Drawing_t *drawing)
422 {
423
424 // Do not unref here, Drawing_t destroyed by it's widget.
425 //g_object_unref( G_OBJECT(drawing->drawing_area));
426
427 g_free(drawing->pango_layout);
428 g_free(drawing);
429 }
430
431 GtkWidget *drawing_get_widget(Drawing_t *drawing)
432 {
433 return drawing->drawing_area;
434 }
435
436 /* convert_pixels_to_time
437 *
438 * Convert from window pixel and time interval to an absolute time.
439 */
440 void convert_pixels_to_time(
441 gint width,
442 guint x,
443 LttTime *window_time_begin,
444 LttTime *window_time_end,
445 LttTime *time)
446 {
447 LttTime window_time_interval;
448
449 window_time_interval = ltt_time_sub(*window_time_end,
450 *window_time_begin);
451 *time = ltt_time_mul(window_time_interval, (x/(float)width));
452 *time = ltt_time_add(*window_time_begin, *time);
453 }
454
455
456
457 void convert_time_to_pixels(
458 LttTime window_time_begin,
459 LttTime window_time_end,
460 LttTime time,
461 int width,
462 guint *x)
463 {
464 LttTime window_time_interval;
465 float interval_float, time_float;
466
467 window_time_interval = ltt_time_sub(window_time_end,window_time_begin);
468
469 time = ltt_time_sub(time, window_time_begin);
470
471 interval_float = ltt_time_to_double(window_time_interval);
472 time_float = ltt_time_to_double(time);
473
474 *x = (guint)(time_float/interval_float * width);
475
476 }
477
478 void drawing_refresh ( Drawing_t *drawing,
479 guint x, guint y,
480 guint width, guint height)
481 {
482 g_info("Drawing.c : drawing_refresh %u, %u, %u, %u", x, y, width, height);
483 GdkRectangle update_rect;
484
485 gdk_draw_drawable(
486 drawing->drawing_area->window,
487 drawing->drawing_area->
488 style->fg_gc[GTK_WIDGET_STATE (drawing->drawing_area)],
489 GDK_DRAWABLE(drawing->pixmap),
490 x, y,
491 x, y,
492 width, height);
493
494 update_rect.x = 0 ;
495 update_rect.y = 0 ;
496 update_rect.width = drawing->width;
497 update_rect.height = drawing->height ;
498 gtk_widget_draw( drawing->drawing_area, &update_rect);
499
500 }
501
502
503 void drawing_draw_line( Drawing_t *drawing,
504 GdkPixmap *pixmap,
505 guint x1, guint y1,
506 guint x2, guint y2,
507 GdkGC *GC)
508 {
509 gdk_draw_line (pixmap,
510 GC,
511 x1, y1, x2, y2);
512 }
513
514
515
516
517 void drawing_resize(Drawing_t *drawing, guint h, guint w)
518 {
519 drawing->height = h ;
520 drawing->width = w ;
521
522 gtk_widget_set_size_request ( drawing->drawing_area,
523 drawing->width,
524 drawing->height);
525
526
527 }
528
529
530 /* Insert a square corresponding to a new process in the list */
531 /* Applies to whole drawing->width */
532 void drawing_insert_square(Drawing_t *drawing,
533 guint y,
534 guint height)
535 {
536 //GdkRectangle update_rect;
537
538 /* Allocate a new pixmap with new height */
539 GdkPixmap *pixmap = gdk_pixmap_new(drawing->drawing_area->window,
540 drawing->width + SAFETY,
541 drawing->height + height + SAFETY,
542 -1);
543
544 /* Copy the high region */
545 gdk_draw_drawable (pixmap,
546 drawing->drawing_area->style->black_gc,
547 drawing->pixmap,
548 0, 0,
549 0, 0,
550 drawing->width + SAFETY, y);
551
552
553
554
555 /* add an empty square */
556 gdk_draw_rectangle (pixmap,
557 drawing->drawing_area->style->white_gc,
558 TRUE,
559 0, y,
560 drawing->width + SAFETY, // do not overlap
561 height);
562
563
564
565 /* copy the bottom of the region */
566 gdk_draw_drawable (pixmap,
567 drawing->drawing_area->style->black_gc,
568 drawing->pixmap,
569 0, y,
570 0, y + height,
571 drawing->width+SAFETY, drawing->height - y + SAFETY);
572
573
574
575
576 if (drawing->pixmap)
577 gdk_pixmap_unref(drawing->pixmap);
578
579 drawing->pixmap = pixmap;
580
581 drawing->height+=height;
582
583 /* Rectangle to update, from new drawing dimensions */
584 //update_rect.x = 0 ;
585 //update_rect.y = y ;
586 //update_rect.width = drawing->width;
587 //update_rect.height = drawing->height - y ;
588 //gtk_widget_draw( drawing->drawing_area, &update_rect);
589 }
590
591
592 /* Remove a square corresponding to a removed process in the list */
593 void drawing_remove_square(Drawing_t *drawing,
594 guint y,
595 guint height)
596 {
597 //GdkRectangle update_rect;
598
599 /* Allocate a new pixmap with new height */
600 GdkPixmap *pixmap = gdk_pixmap_new(
601 drawing->drawing_area->window,
602 drawing->width + SAFETY,
603 drawing->height - height + SAFETY,
604 -1);
605
606 /* Copy the high region */
607 gdk_draw_drawable (pixmap,
608 drawing->drawing_area->style->black_gc,
609 drawing->pixmap,
610 0, 0,
611 0, 0,
612 drawing->width + SAFETY, y);
613
614
615
616 /* Copy up the bottom of the region */
617 gdk_draw_drawable (pixmap,
618 drawing->drawing_area->style->black_gc,
619 drawing->pixmap,
620 0, y + height,
621 0, y,
622 drawing->width, drawing->height - y - height + SAFETY);
623
624
625 if (drawing->pixmap)
626 gdk_pixmap_unref(drawing->pixmap);
627
628 drawing->pixmap = pixmap;
629
630 drawing->height-=height;
631
632 /* Rectangle to update, from new drawing dimensions */
633 //update_rect.x = 0 ;
634 //update_rect.y = y ;
635 //update_rect.width = drawing->width;
636 //update_rect.height = drawing->height - y ;
637 //gtk_widget_draw( drawing->drawing_area, &update_rect);
638 }
639
640
This page took 0.042799 seconds and 4 git commands to generate.