ce0214a6 |
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 | */ |
fa2c4dbe |
18 | |
76a67e8a |
19 | #include <gtk/gtk.h> |
20 | #include <gdk/gdk.h> |
f0d936c0 |
21 | |
2a2fa4f0 |
22 | #include <lttv/lttv.h> |
d8f124de |
23 | #include <lttv/tracecontext.h> |
5ac76b22 |
24 | #include <lttvwindow/viewer.h> |
b21c82b6 |
25 | #include <lttv/state.h> |
f66eba62 |
26 | #include <lttv/hook.h> |
831a876d |
27 | |
d66666fe |
28 | #include "drawing.h" |
a43d67ba |
29 | #include "eventhooks.h" |
d66666fe |
30 | #include "cfv.h" |
31 | #include "cfv-private.h" |
6d5ed1c3 |
32 | |
33 | #define g_info(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, format) |
34 | #define g_debug(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, format) |
35 | |
f0d936c0 |
36 | /***************************************************************************** |
501d5405 |
37 | * drawing functions * |
f0d936c0 |
38 | *****************************************************************************/ |
39 | |
3cb8b205 |
40 | static gboolean |
41 | expose_ruler( GtkWidget *widget, GdkEventExpose *event, gpointer user_data ); |
42 | |
d287af9a |
43 | static gboolean |
44 | motion_notify_ruler(GtkWidget *widget, GdkEventMotion *event, gpointer user_data); |
3cb8b205 |
45 | |
46 | |
831a876d |
47 | //FIXME Colors will need to be dynamic. Graphic context part not done so far. |
f0d936c0 |
48 | typedef enum |
49 | { |
a56a1ba4 |
50 | RED, |
51 | GREEN, |
52 | BLUE, |
53 | WHITE, |
54 | BLACK |
f0d936c0 |
55 | |
56 | } ControlFlowColors; |
57 | |
58 | /* Vector of unallocated colors */ |
59 | static GdkColor CF_Colors [] = |
60 | { |
a56a1ba4 |
61 | { 0, 0xffff, 0x0000, 0x0000 }, // RED |
62 | { 0, 0x0000, 0xffff, 0x0000 }, // GREEN |
63 | { 0, 0x0000, 0x0000, 0xffff }, // BLUE |
64 | { 0, 0xffff, 0xffff, 0xffff }, // WHITE |
65 | { 0, 0x0000, 0x0000, 0x0000 } // BLACK |
f0d936c0 |
66 | }; |
67 | |
68 | |
831a876d |
69 | /* Function responsible for updating the exposed area. |
70 | * It must call processTrace() to ask for this update. |
432a7065 |
71 | * Note : this function cannot clear the background, because it may |
72 | * erase drawing already present (SAFETY). |
831a876d |
73 | */ |
501d5405 |
74 | void drawing_data_request(Drawing_t *drawing, |
b6db18f8 |
75 | GdkPixmap **pixmap, |
a56a1ba4 |
76 | gint x, gint y, |
77 | gint width, |
78 | gint height) |
847b479d |
79 | { |
d9b7ca88 |
80 | if(width < 0) return ; |
81 | if(height < 0) return ; |
224446ce |
82 | |
83 | const TimeWindow *time_window = lttvwindow_get_time_window(drawing->control_flow_data->mw); |
84 | |
a43d67ba |
85 | ControlFlowData *control_flow_data = drawing->control_flow_data; |
86 | // (ControlFlowData*)g_object_get_data( |
87 | // G_OBJECT(drawing->drawing_area), "control_flow_data"); |
a56a1ba4 |
88 | |
a43d67ba |
89 | LttTime start, time_end; |
224446ce |
90 | LttTime window_end = ltt_time_add(time_window->time_width, |
91 | time_window->start_time); |
a56a1ba4 |
92 | |
a43d67ba |
93 | g_debug("req : window start_time : %u, %u", time_window->start_time.tv_sec, |
94 | time_window->start_time.tv_nsec); |
a56a1ba4 |
95 | |
a43d67ba |
96 | g_debug("req : window time width : %u, %u", time_window->time_width.tv_sec, |
224446ce |
97 | time_window->time_width.tv_nsec); |
a56a1ba4 |
98 | |
a43d67ba |
99 | g_debug("req : window_end : %u, %u", window_end.tv_sec, |
100 | window_end.tv_nsec); |
101 | |
2a2fa4f0 |
102 | g_debug("x is : %i, x+width is : %i", x, x+width); |
a56a1ba4 |
103 | |
501d5405 |
104 | convert_pixels_to_time(drawing->drawing_area->allocation.width, x, |
224446ce |
105 | time_window->start_time, |
106 | window_end, |
a56a1ba4 |
107 | &start); |
108 | |
a43d67ba |
109 | convert_pixels_to_time(drawing->drawing_area->allocation.width, x+width, |
224446ce |
110 | time_window->start_time, |
111 | window_end, |
a43d67ba |
112 | &time_end); |
a56a1ba4 |
113 | |
114 | LttvTracesetContext * tsc = |
224446ce |
115 | lttvwindow_get_traceset_context(control_flow_data->mw); |
d52cfc84 |
116 | LttvTracesetState * tss = |
d0cd7f09 |
117 | (LttvTracesetState*)tsc; |
a56a1ba4 |
118 | |
a56a1ba4 |
119 | // Let's call processTrace() !! |
a43d67ba |
120 | |
121 | EventRequest *event_request = control_flow_data->event_request; |
122 | event_request->control_flow_data = control_flow_data; |
123 | event_request->time_begin = start; |
124 | event_request->time_end = time_end; |
125 | |
126 | event_request->x_begin = x; |
127 | event_request->x_end = x+width; |
128 | |
129 | g_debug("req : start : %u, %u", event_request->time_begin.tv_sec, |
130 | event_request->time_begin.tv_nsec); |
131 | |
132 | g_debug("req : end : %u, %u", event_request->time_end.tv_sec, |
133 | event_request->time_end.tv_nsec); |
134 | |
135 | lttv_hooks_add(control_flow_data->after_traceset, after_data_request, event_request); |
136 | lttv_hooks_add(control_flow_data->event, draw_event_hook, event_request); |
137 | lttv_hooks_add(control_flow_data->after_event, draw_after_hook, event_request); |
a56a1ba4 |
138 | |
d52cfc84 |
139 | //lttv_process_traceset_seek_time(tsc, start); |
a43d67ba |
140 | //lttv_state_traceset_seek_time_closest(tss, start); |
a56a1ba4 |
141 | // FIXME : would like to place the after_traceset hook after the traceset, |
142 | // but the traceset context state is not valid anymore. |
143 | lttv_traceset_context_add_hooks(tsc, |
a43d67ba |
144 | NULL, control_flow_data->after_traceset, NULL, NULL, NULL, NULL, |
d0cd7f09 |
145 | //NULL, NULL, NULL, NULL, NULL, NULL, |
a43d67ba |
146 | NULL, NULL, NULL, control_flow_data->event, control_flow_data->after_event); |
147 | TimeWindow time_request; |
148 | time_request.start_time = start; |
149 | time_request.time_width = ltt_time_sub(time_end, start); |
150 | |
151 | lttvwindow_time_interval_request(drawing->control_flow_data->mw, |
152 | time_request, G_MAXUINT, |
153 | after_process_traceset_hook, |
154 | control_flow_data); |
155 | |
156 | //lttv_process_traceset(tsc, end, G_MAXULONG); |
157 | } |
158 | |
a56a1ba4 |
159 | |
a56a1ba4 |
160 | |
a43d67ba |
161 | |
162 | void drawing_data_request_end(Drawing_t *drawing, |
163 | TimeWindow req_time_window) |
164 | { |
165 | gint x, x_end, width; |
166 | |
167 | LttvTracesetContext * tsc = |
168 | lttvwindow_get_traceset_context(drawing->control_flow_data->mw); |
169 | |
170 | const TimeWindow *time_window = lttvwindow_get_time_window(drawing->control_flow_data->mw); |
171 | |
172 | //FIXME ? removing hooks during processtrace can BREAK things! |
173 | lttv_traceset_context_remove_hooks(tsc, |
174 | NULL, drawing->control_flow_data->after_traceset, NULL, NULL, NULL, NULL, |
175 | NULL, NULL, NULL, |
176 | drawing->control_flow_data->event, |
177 | drawing->control_flow_data->after_event); |
178 | |
179 | g_debug("End of data request"); |
a56a1ba4 |
180 | |
a43d67ba |
181 | LttTime window_end = ltt_time_add(time_window->time_width, |
182 | time_window->start_time); |
183 | |
184 | LttTime req_window_end = ltt_time_add(req_time_window.time_width, |
185 | req_time_window.start_time); |
186 | |
187 | convert_time_to_pixels( |
188 | time_window->start_time, |
189 | window_end, |
190 | req_time_window.start_time, |
191 | drawing->width, |
192 | &x); |
193 | |
194 | convert_time_to_pixels( |
195 | time_window->start_time, |
196 | window_end, |
197 | req_window_end, |
198 | drawing->width, |
199 | &x_end); |
200 | |
201 | width = x_end - x; |
202 | |
203 | /* ask for the buffer to be redrawn */ |
204 | gtk_widget_queue_draw_area ( drawing->drawing_area, |
205 | x, 0, |
206 | width, drawing->height); |
207 | |
847b479d |
208 | } |
a43d67ba |
209 | |
210 | |
847b479d |
211 | /* Callbacks */ |
212 | |
213 | |
214 | /* Create a new backing pixmap of the appropriate size */ |
bd24a9af |
215 | /* As the scaling will always change, it's of no use to copy old |
216 | * pixmap. |
217 | */ |
847b479d |
218 | static gboolean |
219 | configure_event( GtkWidget *widget, GdkEventConfigure *event, |
a56a1ba4 |
220 | gpointer user_data) |
f0d936c0 |
221 | { |
501d5405 |
222 | Drawing_t *drawing = (Drawing_t*)user_data; |
f0d936c0 |
223 | |
86c520a7 |
224 | |
a56a1ba4 |
225 | /* First, get the new time interval of the main window */ |
226 | /* we assume (see documentation) that the main window |
227 | * has updated the time interval before this configure gets |
228 | * executed. |
229 | */ |
224446ce |
230 | //lttvwindow_get_time_window(drawing->control_flow_data->mw, |
231 | // &drawing->control_flow_data->time_window); |
a56a1ba4 |
232 | |
b6db18f8 |
233 | /* New pixmap, size of the configure event */ |
234 | //GdkPixmap *pixmap = gdk_pixmap_new(widget->window, |
a56a1ba4 |
235 | // widget->allocation.width + SAFETY, |
236 | // widget->allocation.height + SAFETY, |
237 | // -1); |
238 | |
2a2fa4f0 |
239 | g_debug("drawing configure event"); |
240 | g_debug("New draw size : %i by %i",widget->allocation.width, widget->allocation.height); |
a56a1ba4 |
241 | |
242 | |
501d5405 |
243 | if (drawing->pixmap) |
244 | gdk_pixmap_unref(drawing->pixmap); |
a56a1ba4 |
245 | |
b6db18f8 |
246 | /* If no old pixmap present */ |
501d5405 |
247 | //if(drawing->pixmap == NULL) |
847b479d |
248 | { |
501d5405 |
249 | drawing->pixmap = gdk_pixmap_new( |
a56a1ba4 |
250 | widget->window, |
251 | widget->allocation.width + SAFETY, |
252 | widget->allocation.height + SAFETY, |
253 | //ProcessList_get_height |
501d5405 |
254 | // (GuiControlFlow_get_process_list(drawing->control_flow_data)), |
a56a1ba4 |
255 | -1); |
501d5405 |
256 | drawing->width = widget->allocation.width; |
257 | drawing->height = widget->allocation.height; |
a56a1ba4 |
258 | |
259 | |
260 | // Clear the image |
501d5405 |
261 | gdk_draw_rectangle (drawing->pixmap, |
cfe526b1 |
262 | widget->style->black_gc, |
a56a1ba4 |
263 | TRUE, |
264 | 0, 0, |
265 | widget->allocation.width+SAFETY, |
266 | widget->allocation.height+SAFETY); |
267 | |
268 | //g_info("init data request"); |
269 | |
270 | |
271 | /* Initial data request */ |
a43d67ba |
272 | /* no, do initial data request in the expose event */ |
a56a1ba4 |
273 | // Do not need to ask for data of 1 pixel : not synchronized with |
274 | // main window time at this moment. |
a43d67ba |
275 | //drawing_data_request(drawing, &drawing->pixmap, 0, 0, |
276 | // widget->allocation.width, |
277 | // widget->allocation.height); |
a56a1ba4 |
278 | |
501d5405 |
279 | drawing->width = widget->allocation.width; |
280 | drawing->height = widget->allocation.height; |
a43d67ba |
281 | |
282 | drawing->data_injected = FALSE; |
a56a1ba4 |
283 | |
284 | return TRUE; |
bd24a9af |
285 | |
286 | |
847b479d |
287 | |
288 | } |
847b479d |
289 | } |
290 | |
291 | |
292 | /* Redraw the screen from the backing pixmap */ |
293 | static gboolean |
294 | expose_event( GtkWidget *widget, GdkEventExpose *event, gpointer user_data ) |
295 | { |
501d5405 |
296 | Drawing_t *drawing = (Drawing_t*)user_data; |
a43d67ba |
297 | |
224446ce |
298 | const TimeWindow *time_window = lttvwindow_get_time_window(drawing->control_flow_data->mw); |
299 | const LttTime* current_time = |
300 | lttvwindow_get_current_time(drawing->control_flow_data->mw); |
301 | |
a56a1ba4 |
302 | ControlFlowData *control_flow_data = |
303 | (ControlFlowData*)g_object_get_data( |
304 | G_OBJECT(widget), |
68997a22 |
305 | "control_flow_data"); |
8b90e648 |
306 | |
a43d67ba |
307 | guint cursor_x=0; |
a56a1ba4 |
308 | |
224446ce |
309 | LttTime window_end = ltt_time_add(time_window->time_width, |
310 | time_window->start_time); |
a56a1ba4 |
311 | |
312 | convert_time_to_pixels( |
224446ce |
313 | time_window->start_time, |
a56a1ba4 |
314 | window_end, |
ba90bc77 |
315 | *current_time, |
a56a1ba4 |
316 | widget->allocation.width, |
a43d67ba |
317 | &cursor_x); |
318 | |
319 | |
320 | |
321 | |
322 | if(!drawing->data_injected) |
323 | { |
324 | drawing_data_request(drawing, &drawing->pixmap, 0, 0, |
325 | widget->allocation.width, |
326 | widget->allocation.height); |
327 | drawing->data_injected = TRUE; |
328 | } |
a56a1ba4 |
329 | |
a43d67ba |
330 | /* update the screen from the pixmap buffer */ |
847b479d |
331 | gdk_draw_pixmap(widget->window, |
a56a1ba4 |
332 | widget->style->fg_gc[GTK_WIDGET_STATE (widget)], |
501d5405 |
333 | drawing->pixmap, |
a56a1ba4 |
334 | event->area.x, event->area.y, |
335 | event->area.x, event->area.y, |
336 | event->area.width, event->area.height); |
337 | |
a43d67ba |
338 | |
339 | /* Draw the dotted lines */ |
340 | |
341 | gint8 dash_list[] = { 1, 2 }; |
342 | GdkGC *gc = gdk_gc_new(control_flow_data->drawing->pixmap); |
343 | gdk_gc_copy(gc, widget->style->white_gc); |
344 | gdk_gc_set_line_attributes(gc, |
345 | 1, |
346 | GDK_LINE_ON_OFF_DASH, |
347 | GDK_CAP_BUTT, |
348 | GDK_JOIN_MITER); |
349 | gdk_gc_set_dashes(gc, |
350 | 0, |
351 | dash_list, |
352 | 2); |
353 | drawing_draw_line(NULL, widget->window, |
354 | cursor_x, 0, |
355 | cursor_x, drawing->height, |
356 | gc); |
357 | gdk_gc_unref(gc); |
358 | |
359 | |
360 | |
361 | |
847b479d |
362 | return FALSE; |
363 | } |
364 | |
a43d67ba |
365 | static gboolean |
366 | after_expose_event( GtkWidget *widget, GdkEventExpose *event, gpointer user_data ) |
367 | { |
368 | //g_assert(0); |
369 | g_critical("AFTER EXPOSE"); |
370 | |
371 | return FALSE; |
372 | |
373 | |
374 | } |
375 | |
376 | |
8b90e648 |
377 | /* mouse click */ |
378 | static gboolean |
379 | button_press_event( GtkWidget *widget, GdkEventButton *event, gpointer user_data ) |
380 | { |
a56a1ba4 |
381 | ControlFlowData *control_flow_data = |
382 | (ControlFlowData*)g_object_get_data( |
383 | G_OBJECT(widget), |
68997a22 |
384 | "control_flow_data"); |
501d5405 |
385 | Drawing_t *drawing = control_flow_data->drawing; |
224446ce |
386 | const TimeWindow *time_window = lttvwindow_get_time_window(drawing->control_flow_data->mw); |
8b90e648 |
387 | |
2a2fa4f0 |
388 | g_debug("click"); |
a56a1ba4 |
389 | if(event->button == 1) |
390 | { |
391 | LttTime time; |
8b90e648 |
392 | |
224446ce |
393 | LttTime window_end = ltt_time_add(time_window->time_width, |
394 | time_window->start_time); |
8b90e648 |
395 | |
396 | |
a56a1ba4 |
397 | /* left mouse button click */ |
2a2fa4f0 |
398 | g_debug("x click is : %f", event->x); |
8b90e648 |
399 | |
a56a1ba4 |
400 | convert_pixels_to_time(widget->allocation.width, (guint)event->x, |
224446ce |
401 | time_window->start_time, |
402 | window_end, |
a56a1ba4 |
403 | &time); |
8b90e648 |
404 | |
224446ce |
405 | lttvwindow_report_current_time(control_flow_data->mw, &time); |
8b90e648 |
406 | |
a56a1ba4 |
407 | } |
ebf4f735 |
408 | |
224446ce |
409 | lttvwindow_report_focus(control_flow_data->mw, gtk_widget_get_parent(control_flow_data->scrolled_window)); |
a56a1ba4 |
410 | |
411 | return FALSE; |
8b90e648 |
412 | } |
413 | |
414 | |
415 | |
416 | |
68997a22 |
417 | Drawing_t *drawing_construct(ControlFlowData *control_flow_data) |
847b479d |
418 | { |
501d5405 |
419 | Drawing_t *drawing = g_new(Drawing_t, 1); |
3cb8b205 |
420 | |
501d5405 |
421 | drawing->control_flow_data = control_flow_data; |
a56a1ba4 |
422 | |
3cb8b205 |
423 | drawing->vbox = gtk_vbox_new(FALSE, 1); |
3cb8b205 |
424 | drawing->ruler = gtk_drawing_area_new (); |
425 | gtk_widget_set_size_request(drawing->ruler, -1, 27); |
3cb8b205 |
426 | |
427 | drawing->drawing_area = gtk_drawing_area_new (); |
428 | |
429 | gtk_box_pack_start(GTK_BOX(drawing->vbox), drawing->ruler, |
430 | FALSE, FALSE, 0); |
3cb8b205 |
431 | gtk_box_pack_end(GTK_BOX(drawing->vbox), drawing->drawing_area, |
432 | TRUE, TRUE, 0); |
3cb8b205 |
433 | |
501d5405 |
434 | drawing->pango_layout = |
435 | gtk_widget_create_pango_layout(drawing->drawing_area, NULL); |
a56a1ba4 |
436 | |
a43d67ba |
437 | drawing->height = 0; |
438 | drawing->width = 0; |
439 | drawing->depth = 0; |
440 | |
441 | drawing->data_injected = FALSE; |
442 | |
501d5405 |
443 | //gtk_widget_set_size_request(drawing->drawing_area->window, 50, 50); |
a56a1ba4 |
444 | g_object_set_data_full( |
501d5405 |
445 | G_OBJECT(drawing->drawing_area), |
446 | "Link_drawing_Data", |
447 | drawing, |
a56a1ba4 |
448 | (GDestroyNotify)drawing_destroy); |
449 | |
3cb8b205 |
450 | g_object_set_data( |
451 | G_OBJECT(drawing->ruler), |
452 | "drawing", |
453 | drawing); |
454 | |
455 | |
501d5405 |
456 | //gtk_widget_modify_bg( drawing->drawing_area, |
a56a1ba4 |
457 | // GTK_STATE_NORMAL, |
458 | // &CF_Colors[BLACK]); |
459 | |
501d5405 |
460 | //gdk_window_get_geometry(drawing->drawing_area->window, |
a56a1ba4 |
461 | // NULL, NULL, |
501d5405 |
462 | // &(drawing->width), |
463 | // &(drawing->height), |
a56a1ba4 |
464 | // -1); |
465 | |
501d5405 |
466 | //drawing->pixmap = gdk_pixmap_new( |
467 | // drawing->drawing_area->window, |
468 | // drawing->width, |
469 | // drawing->height, |
470 | // drawing->depth); |
a56a1ba4 |
471 | |
501d5405 |
472 | drawing->pixmap = NULL; |
a56a1ba4 |
473 | |
501d5405 |
474 | // drawing->pixmap = gdk_pixmap_new(drawing->drawing_area->window, |
475 | // drawing->drawing_area->allocation.width, |
476 | // drawing->drawing_area->allocation.height, |
a56a1ba4 |
477 | // -1); |
478 | |
501d5405 |
479 | gtk_widget_add_events(drawing->drawing_area, GDK_BUTTON_PRESS_MASK); |
a56a1ba4 |
480 | |
501d5405 |
481 | g_signal_connect (G_OBJECT(drawing->drawing_area), |
a56a1ba4 |
482 | "configure_event", |
483 | G_CALLBACK (configure_event), |
501d5405 |
484 | (gpointer)drawing); |
3cb8b205 |
485 | |
486 | g_signal_connect (G_OBJECT(drawing->ruler), |
487 | "expose_event", |
488 | G_CALLBACK(expose_ruler), |
489 | (gpointer)drawing); |
490 | |
d287af9a |
491 | gtk_widget_add_events(drawing->ruler, GDK_POINTER_MOTION_MASK); |
492 | |
493 | g_signal_connect (G_OBJECT(drawing->ruler), |
494 | "motion-notify-event", |
495 | G_CALLBACK(motion_notify_ruler), |
496 | (gpointer)drawing); |
497 | |
498 | |
501d5405 |
499 | g_signal_connect (G_OBJECT(drawing->drawing_area), |
a56a1ba4 |
500 | "expose_event", |
501 | G_CALLBACK (expose_event), |
501d5405 |
502 | (gpointer)drawing); |
a56a1ba4 |
503 | |
a43d67ba |
504 | g_signal_connect_after (G_OBJECT(drawing->drawing_area), |
505 | "expose_event", |
506 | G_CALLBACK (after_expose_event), |
507 | (gpointer)drawing); |
508 | |
501d5405 |
509 | g_signal_connect (G_OBJECT(drawing->drawing_area), |
a56a1ba4 |
510 | "button-press-event", |
511 | G_CALLBACK (button_press_event), |
501d5405 |
512 | (gpointer)drawing); |
3cb8b205 |
513 | |
514 | gtk_widget_show(drawing->ruler); |
515 | gtk_widget_show(drawing->drawing_area); |
516 | |
a56a1ba4 |
517 | |
501d5405 |
518 | return drawing; |
f0d936c0 |
519 | } |
520 | |
501d5405 |
521 | void drawing_destroy(Drawing_t *drawing) |
f0d936c0 |
522 | { |
523 | |
a56a1ba4 |
524 | // Do not unref here, Drawing_t destroyed by it's widget. |
501d5405 |
525 | //g_object_unref( G_OBJECT(drawing->drawing_area)); |
a56a1ba4 |
526 | |
501d5405 |
527 | g_free(drawing->pango_layout); |
528 | g_free(drawing); |
f0d936c0 |
529 | } |
530 | |
3cb8b205 |
531 | GtkWidget *drawing_get_drawing_area(Drawing_t *drawing) |
76a67e8a |
532 | { |
501d5405 |
533 | return drawing->drawing_area; |
76a67e8a |
534 | } |
535 | |
3cb8b205 |
536 | GtkWidget *drawing_get_widget(Drawing_t *drawing) |
537 | { |
538 | return drawing->vbox; |
539 | } |
540 | |
f66eba62 |
541 | /* convert_pixels_to_time |
f0d936c0 |
542 | * |
f66eba62 |
543 | * Convert from window pixel and time interval to an absolute time. |
f0d936c0 |
544 | */ |
fa2c4dbe |
545 | void convert_pixels_to_time( |
a56a1ba4 |
546 | gint width, |
547 | guint x, |
224446ce |
548 | LttTime window_time_begin, |
549 | LttTime window_time_end, |
a56a1ba4 |
550 | LttTime *time) |
f0d936c0 |
551 | { |
a56a1ba4 |
552 | LttTime window_time_interval; |
553 | |
224446ce |
554 | window_time_interval = ltt_time_sub(window_time_end, |
555 | window_time_begin); |
a56a1ba4 |
556 | *time = ltt_time_mul(window_time_interval, (x/(float)width)); |
224446ce |
557 | *time = ltt_time_add(window_time_begin, *time); |
fa2c4dbe |
558 | } |
559 | |
560 | |
561 | |
562 | void convert_time_to_pixels( |
a56a1ba4 |
563 | LttTime window_time_begin, |
564 | LttTime window_time_end, |
565 | LttTime time, |
566 | int width, |
567 | guint *x) |
fa2c4dbe |
568 | { |
a56a1ba4 |
569 | LttTime window_time_interval; |
570 | float interval_float, time_float; |
571 | |
572 | window_time_interval = ltt_time_sub(window_time_end,window_time_begin); |
573 | |
574 | time = ltt_time_sub(time, window_time_begin); |
575 | |
576 | interval_float = ltt_time_to_double(window_time_interval); |
577 | time_float = ltt_time_to_double(time); |
578 | |
579 | *x = (guint)(time_float/interval_float * width); |
580 | |
f0d936c0 |
581 | } |
582 | |
501d5405 |
583 | void drawing_draw_line( Drawing_t *drawing, |
b6db18f8 |
584 | GdkPixmap *pixmap, |
a56a1ba4 |
585 | guint x1, guint y1, |
586 | guint x2, guint y2, |
587 | GdkGC *GC) |
847b479d |
588 | { |
b6db18f8 |
589 | gdk_draw_line (pixmap, |
a56a1ba4 |
590 | GC, |
591 | x1, y1, x2, y2); |
847b479d |
592 | } |
593 | |
594 | |
fa2c4dbe |
595 | |
596 | |
501d5405 |
597 | void drawing_resize(Drawing_t *drawing, guint h, guint w) |
f0d936c0 |
598 | { |
501d5405 |
599 | drawing->height = h ; |
600 | drawing->width = w ; |
a56a1ba4 |
601 | |
501d5405 |
602 | gtk_widget_set_size_request ( drawing->drawing_area, |
603 | drawing->width, |
604 | drawing->height); |
a56a1ba4 |
605 | |
606 | |
f0d936c0 |
607 | } |
847b479d |
608 | |
609 | |
5f16133f |
610 | /* Insert a square corresponding to a new process in the list */ |
501d5405 |
611 | /* Applies to whole drawing->width */ |
612 | void drawing_insert_square(Drawing_t *drawing, |
a56a1ba4 |
613 | guint y, |
614 | guint height) |
5f16133f |
615 | { |
a56a1ba4 |
616 | //GdkRectangle update_rect; |
5f16133f |
617 | |
a56a1ba4 |
618 | /* Allocate a new pixmap with new height */ |
501d5405 |
619 | GdkPixmap *pixmap = gdk_pixmap_new(drawing->drawing_area->window, |
620 | drawing->width + SAFETY, |
621 | drawing->height + height + SAFETY, |
a56a1ba4 |
622 | -1); |
623 | |
624 | /* Copy the high region */ |
b6db18f8 |
625 | gdk_draw_drawable (pixmap, |
501d5405 |
626 | drawing->drawing_area->style->black_gc, |
627 | drawing->pixmap, |
a56a1ba4 |
628 | 0, 0, |
629 | 0, 0, |
501d5405 |
630 | drawing->width + SAFETY, y); |
5f16133f |
631 | |
632 | |
633 | |
5f16133f |
634 | |
a56a1ba4 |
635 | /* add an empty square */ |
b6db18f8 |
636 | gdk_draw_rectangle (pixmap, |
cfe526b1 |
637 | drawing->drawing_area->style->black_gc, |
a56a1ba4 |
638 | TRUE, |
639 | 0, y, |
501d5405 |
640 | drawing->width + SAFETY, // do not overlap |
a56a1ba4 |
641 | height); |
5f16133f |
642 | |
643 | |
5f16133f |
644 | |
a56a1ba4 |
645 | /* copy the bottom of the region */ |
b6db18f8 |
646 | gdk_draw_drawable (pixmap, |
501d5405 |
647 | drawing->drawing_area->style->black_gc, |
648 | drawing->pixmap, |
a56a1ba4 |
649 | 0, y, |
650 | 0, y + height, |
501d5405 |
651 | drawing->width+SAFETY, drawing->height - y + SAFETY); |
5f16133f |
652 | |
653 | |
654 | |
5f16133f |
655 | |
501d5405 |
656 | if (drawing->pixmap) |
657 | gdk_pixmap_unref(drawing->pixmap); |
5f16133f |
658 | |
501d5405 |
659 | drawing->pixmap = pixmap; |
a56a1ba4 |
660 | |
501d5405 |
661 | drawing->height+=height; |
a56a1ba4 |
662 | |
501d5405 |
663 | /* Rectangle to update, from new drawing dimensions */ |
a56a1ba4 |
664 | //update_rect.x = 0 ; |
665 | //update_rect.y = y ; |
501d5405 |
666 | //update_rect.width = drawing->width; |
667 | //update_rect.height = drawing->height - y ; |
668 | //gtk_widget_draw( drawing->drawing_area, &update_rect); |
5f16133f |
669 | } |
670 | |
671 | |
672 | /* Remove a square corresponding to a removed process in the list */ |
501d5405 |
673 | void drawing_remove_square(Drawing_t *drawing, |
a56a1ba4 |
674 | guint y, |
675 | guint height) |
5f16133f |
676 | { |
a56a1ba4 |
677 | //GdkRectangle update_rect; |
678 | |
679 | /* Allocate a new pixmap with new height */ |
b6db18f8 |
680 | GdkPixmap *pixmap = gdk_pixmap_new( |
501d5405 |
681 | drawing->drawing_area->window, |
682 | drawing->width + SAFETY, |
683 | drawing->height - height + SAFETY, |
a56a1ba4 |
684 | -1); |
685 | |
686 | /* Copy the high region */ |
b6db18f8 |
687 | gdk_draw_drawable (pixmap, |
501d5405 |
688 | drawing->drawing_area->style->black_gc, |
689 | drawing->pixmap, |
a56a1ba4 |
690 | 0, 0, |
691 | 0, 0, |
501d5405 |
692 | drawing->width + SAFETY, y); |
a56a1ba4 |
693 | |
694 | |
695 | |
696 | /* Copy up the bottom of the region */ |
b6db18f8 |
697 | gdk_draw_drawable (pixmap, |
501d5405 |
698 | drawing->drawing_area->style->black_gc, |
699 | drawing->pixmap, |
a56a1ba4 |
700 | 0, y + height, |
701 | 0, y, |
501d5405 |
702 | drawing->width, drawing->height - y - height + SAFETY); |
a56a1ba4 |
703 | |
704 | |
501d5405 |
705 | if (drawing->pixmap) |
706 | gdk_pixmap_unref(drawing->pixmap); |
a56a1ba4 |
707 | |
501d5405 |
708 | drawing->pixmap = pixmap; |
a56a1ba4 |
709 | |
501d5405 |
710 | drawing->height-=height; |
a56a1ba4 |
711 | |
501d5405 |
712 | /* Rectangle to update, from new drawing dimensions */ |
a56a1ba4 |
713 | //update_rect.x = 0 ; |
714 | //update_rect.y = y ; |
501d5405 |
715 | //update_rect.width = drawing->width; |
716 | //update_rect.height = drawing->height - y ; |
717 | //gtk_widget_draw( drawing->drawing_area, &update_rect); |
5f16133f |
718 | } |
189a5d08 |
719 | |
3cb8b205 |
720 | void drawing_update_ruler(Drawing_t *drawing, TimeWindow *time_window) |
721 | { |
722 | GtkRequisition req; |
723 | GdkRectangle rect; |
724 | |
725 | req.width = drawing->ruler->allocation.width; |
726 | req.height = drawing->ruler->allocation.height; |
727 | |
728 | |
729 | rect.x = 0; |
730 | rect.y = 0; |
731 | rect.width = req.width; |
732 | rect.height = req.height; |
733 | |
734 | gtk_widget_queue_draw(drawing->ruler); |
735 | //gtk_widget_draw( drawing->ruler, &rect); |
736 | } |
737 | |
738 | /* Redraw the ruler */ |
739 | static gboolean |
740 | expose_ruler( GtkWidget *widget, GdkEventExpose *event, gpointer user_data ) |
741 | { |
742 | Drawing_t *drawing = (Drawing_t*)user_data; |
224446ce |
743 | const TimeWindow *time_window = lttvwindow_get_time_window(drawing->control_flow_data->mw); |
3cb8b205 |
744 | gchar text[255]; |
745 | |
746 | PangoContext *context; |
747 | PangoLayout *layout; |
748 | PangoAttribute *attribute; |
749 | PangoFontDescription *FontDesc; |
750 | gint Font_Size; |
751 | PangoRectangle ink_rect; |
752 | guint global_width=0; |
753 | GdkColor foreground = { 0, 0, 0, 0 }; |
754 | GdkColor background = { 0, 0xffff, 0xffff, 0xffff }; |
755 | |
756 | LttTime window_end = |
224446ce |
757 | ltt_time_add(time_window->time_width, |
758 | time_window->start_time); |
3cb8b205 |
759 | LttTime half_width = |
224446ce |
760 | ltt_time_div(time_window->time_width,2.0); |
3cb8b205 |
761 | LttTime window_middle = |
762 | ltt_time_add(half_width, |
224446ce |
763 | time_window->start_time); |
2a2fa4f0 |
764 | g_debug("ruler expose event"); |
3cb8b205 |
765 | |
766 | gdk_draw_rectangle (drawing->ruler->window, |
767 | drawing->ruler->style->white_gc, |
768 | TRUE, |
769 | event->area.x, event->area.y, |
770 | event->area.width, |
771 | event->area.height); |
772 | |
773 | GdkGC *gc = gdk_gc_new(drawing->ruler->window); |
774 | gdk_gc_copy(gc, drawing->ruler->style->black_gc); |
775 | gdk_gc_set_line_attributes(gc, |
776 | 2, |
777 | GDK_LINE_SOLID, |
778 | GDK_CAP_BUTT, |
779 | GDK_JOIN_MITER); |
780 | gdk_draw_line (drawing->ruler->window, |
781 | gc, |
782 | event->area.x, 1, |
783 | event->area.x + event->area.width, 1); |
784 | |
785 | |
786 | snprintf(text, 255, "%lus\n%luns", |
224446ce |
787 | time_window->start_time.tv_sec, |
788 | time_window->start_time.tv_nsec); |
3cb8b205 |
789 | |
790 | layout = gtk_widget_create_pango_layout(drawing->drawing_area, NULL); |
791 | |
792 | context = pango_layout_get_context(layout); |
793 | FontDesc = pango_context_get_font_description(context); |
794 | |
795 | pango_font_description_set_size(FontDesc, 6*PANGO_SCALE); |
796 | pango_layout_context_changed(layout); |
797 | |
798 | pango_layout_set_text(layout, text, -1); |
799 | pango_layout_get_pixel_extents(layout, &ink_rect, NULL); |
800 | global_width += ink_rect.width; |
801 | |
802 | gdk_draw_layout_with_colors(drawing->ruler->window, |
803 | gc, |
804 | 0, |
805 | 6, |
806 | layout, &foreground, &background); |
807 | |
808 | gdk_gc_set_line_attributes(gc, |
809 | 2, |
810 | GDK_LINE_SOLID, |
811 | GDK_CAP_ROUND, |
812 | GDK_JOIN_ROUND); |
813 | |
814 | gdk_draw_line (drawing->ruler->window, |
815 | gc, |
816 | 1, 1, |
817 | 1, 7); |
818 | |
819 | |
820 | snprintf(text, 255, "%lus\n%luns", window_end.tv_sec, |
821 | window_end.tv_nsec); |
822 | |
823 | pango_layout_set_text(layout, text, -1); |
824 | pango_layout_get_pixel_extents(layout, &ink_rect, NULL); |
825 | global_width += ink_rect.width; |
826 | |
827 | if(global_width <= drawing->ruler->allocation.width) |
828 | { |
829 | gdk_draw_layout_with_colors(drawing->ruler->window, |
830 | gc, |
831 | drawing->ruler->allocation.width - ink_rect.width, |
832 | 6, |
833 | layout, &foreground, &background); |
834 | |
835 | gdk_gc_set_line_attributes(gc, |
836 | 2, |
837 | GDK_LINE_SOLID, |
838 | GDK_CAP_ROUND, |
839 | GDK_JOIN_ROUND); |
840 | |
841 | gdk_draw_line (drawing->ruler->window, |
842 | gc, |
843 | drawing->ruler->allocation.width-1, 1, |
844 | drawing->ruler->allocation.width-1, 7); |
845 | } |
846 | |
847 | |
848 | snprintf(text, 255, "%lus\n%luns", window_middle.tv_sec, |
849 | window_middle.tv_nsec); |
850 | |
851 | pango_layout_set_text(layout, text, -1); |
852 | pango_layout_get_pixel_extents(layout, &ink_rect, NULL); |
853 | global_width += ink_rect.width; |
854 | |
855 | if(global_width <= drawing->ruler->allocation.width) |
856 | { |
857 | gdk_draw_layout_with_colors(drawing->ruler->window, |
858 | gc, |
859 | (drawing->ruler->allocation.width - ink_rect.width)/2, |
860 | 6, |
861 | layout, &foreground, &background); |
862 | |
863 | gdk_gc_set_line_attributes(gc, |
864 | 2, |
865 | GDK_LINE_SOLID, |
866 | GDK_CAP_ROUND, |
867 | GDK_JOIN_ROUND); |
868 | |
869 | gdk_draw_line (drawing->ruler->window, |
870 | gc, |
871 | drawing->ruler->allocation.width/2, 1, |
872 | drawing->ruler->allocation.width/2, 7); |
873 | |
874 | |
875 | |
876 | |
877 | } |
878 | |
879 | gdk_gc_unref(gc); |
880 | g_object_unref(layout); |
881 | |
882 | return FALSE; |
883 | } |
884 | |
189a5d08 |
885 | |
d287af9a |
886 | /* notify mouse on ruler */ |
887 | static gboolean |
888 | motion_notify_ruler(GtkWidget *widget, GdkEventMotion *event, gpointer user_data) |
889 | { |
2a2fa4f0 |
890 | //g_debug("motion"); |
d287af9a |
891 | //eventually follow mouse and show time here |
892 | } |