diff options
author | Steven Rostedt <srostedt@redhat.com> | 2009-12-16 16:52:57 -0500 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2009-12-17 22:51:03 -0500 |
commit | 5e524c549b3e3b8bbe596dacd71d74e32990a666 (patch) | |
tree | ab1b63f96dad5a7bb19acae00b2a5e64ea9c67e2 | |
parent | 97495e5a901ab993ff84998ad07ad23bd103c89a (diff) |
trace-graph: Add zoom in and zoom out ability
To zoom in, just press the left mouse button and slide right, and release.
To zoom out, press the left mouse button and slide left and release.
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r-- | trace-graph.c | 248 | ||||
-rw-r--r-- | trace-graph.h | 20 |
2 files changed, 181 insertions, 87 deletions
diff --git a/trace-graph.c b/trace-graph.c index 7b7fcda..c9574b6 100644 --- a/trace-graph.c +++ b/trace-graph.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #define TRACE_WIDTH 800 | 35 | #define TRACE_WIDTH 800 |
36 | #define TRACE_HEIGHT 600 | 36 | #define TRACE_HEIGHT 600 |
37 | 37 | ||
38 | #define MAX_WIDTH 10000 | ||
38 | #define input_file "trace.dat" | 39 | #define input_file "trace.dat" |
39 | 40 | ||
40 | #define CPU_MIDDLE(cpu) (80 * (cpu) + 80) | 41 | #define CPU_MIDDLE(cpu) (80 * (cpu) + 80) |
@@ -75,17 +76,11 @@ expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer data) | |||
75 | return FALSE; | 76 | return FALSE; |
76 | } | 77 | } |
77 | 78 | ||
78 | static void start_line(GtkWidget *widget, gint x, gint y, gpointer data) | 79 | static void |
80 | draw_line(GtkWidget *widget, gdouble x, struct graph_info *ginfo) | ||
79 | { | 81 | { |
80 | struct graph_info *ginfo = data; | 82 | gdk_draw_line(widget->window, widget->style->black_gc, |
81 | 83 | x, 0, x, widget->allocation.width); | |
82 | ginfo->last_x = x; | ||
83 | ginfo->last_y = y; | ||
84 | |||
85 | ginfo->mov_w = 0; | ||
86 | ginfo->mov_h = 0; | ||
87 | |||
88 | printf("x=%d y=%d\n", x, y); | ||
89 | } | 84 | } |
90 | 85 | ||
91 | static gboolean | 86 | static gboolean |
@@ -95,64 +90,28 @@ button_press_event(GtkWidget *widget, GdkEventButton *event, gpointer data) | |||
95 | 90 | ||
96 | printf("button = %d\n", event->button); | 91 | printf("button = %d\n", event->button); |
97 | 92 | ||
98 | if ((event->button == 1 || event->button == 3) && | 93 | if (event->button != 1) |
99 | ginfo->curr_pixmap != NULL) { | 94 | return TRUE; |
100 | if (event->button == 3) | ||
101 | ginfo->save = TRUE; | ||
102 | else | ||
103 | ginfo->save = FALSE; | ||
104 | 95 | ||
105 | ginfo->draw_line = TRUE; | 96 | ginfo->start_x = event->x; |
106 | start_line(widget, event->x, event->y, data); | 97 | ginfo->last_x = 0; |
107 | } | ||
108 | 98 | ||
109 | return TRUE; | 99 | draw_line(widget, event->x, ginfo); |
110 | } | ||
111 | 100 | ||
112 | static void normalize_xywh(gint *x, gint *y, gint *w, gint *h) | 101 | ginfo->line_active = TRUE; |
113 | { | ||
114 | if (*w < 0) { | ||
115 | *x = *x + *w; | ||
116 | *w *= -1; | ||
117 | } | ||
118 | 102 | ||
119 | if (*h < 0) { | 103 | return TRUE; |
120 | *y = *y + *h; | ||
121 | *h *= -1; | ||
122 | } | ||
123 | } | 104 | } |
124 | 105 | ||
125 | static void clear_last_line(GtkWidget *widget, struct graph_info *ginfo) | 106 | static void clear_last_line(GtkWidget *widget, struct graph_info *ginfo) |
126 | { | 107 | { |
127 | gint x, y, w, h; | 108 | gint x; |
128 | 109 | ||
129 | x = ginfo->last_x; | 110 | x = ginfo->last_x; |
130 | y = ginfo->last_y; | 111 | if (x) |
131 | 112 | x--; | |
132 | w = ginfo->mov_w; | ||
133 | h = ginfo->mov_h; | ||
134 | |||
135 | normalize_xywh(&x, &y, &w, &h); | ||
136 | |||
137 | w++; | ||
138 | h++; | ||
139 | |||
140 | update_with_backend(ginfo, x, y, w, h); | ||
141 | } | ||
142 | |||
143 | static void | ||
144 | draw_line(GtkWidget *widget, gdouble x, gdouble y, struct graph_info *ginfo) | ||
145 | { | ||
146 | clear_last_line(widget, ginfo); | ||
147 | |||
148 | ginfo->mov_w = x - ginfo->last_x; | ||
149 | ginfo->mov_h = y - ginfo->last_y; | ||
150 | 113 | ||
151 | printf("draw %f %f\n", x, y); | 114 | update_with_backend(ginfo, x, 0, x+2, widget->allocation.height); |
152 | |||
153 | gdk_draw_line(widget->window, widget->style->black_gc, | ||
154 | ginfo->last_x, ginfo->last_y, | ||
155 | x, y); | ||
156 | } | 115 | } |
157 | 116 | ||
158 | static void | 117 | static void |
@@ -409,8 +368,18 @@ motion_notify_event(GtkWidget *widget, GdkEventMotion *event, gpointer data) | |||
409 | if (!ginfo->curr_pixmap) | 368 | if (!ginfo->curr_pixmap) |
410 | return TRUE; | 369 | return TRUE; |
411 | 370 | ||
371 | if (ginfo->line_active) { | ||
372 | if (ginfo->last_x) | ||
373 | clear_last_line(widget, ginfo); | ||
374 | ginfo->last_x = x; | ||
375 | draw_line(widget, ginfo->start_x, ginfo); | ||
376 | draw_line(widget, x, ginfo); | ||
377 | return TRUE; | ||
378 | } | ||
379 | |||
412 | if (ginfo->draw_line) { | 380 | if (ginfo->draw_line) { |
413 | draw_line(widget, x, y, ginfo); | 381 | ginfo->last_x = x; |
382 | // draw_line(widget, x, y, ginfo); | ||
414 | return TRUE; | 383 | return TRUE; |
415 | } | 384 | } |
416 | 385 | ||
@@ -423,13 +392,115 @@ motion_notify_event(GtkWidget *widget, GdkEventMotion *event, gpointer data) | |||
423 | return TRUE; | 392 | return TRUE; |
424 | } | 393 | } |
425 | 394 | ||
395 | static void zoom_in_window(struct graph_info *ginfo, gint start, gint end) | ||
396 | { | ||
397 | gdouble view_width; | ||
398 | gdouble new_width; | ||
399 | gdouble curr_width; | ||
400 | // unsigned long long start_time; | ||
401 | // unsigned long long end_time; | ||
402 | |||
403 | g_assert(start < end); | ||
404 | g_assert(ginfo->vadj); | ||
405 | |||
406 | view_width = gtk_adjustment_get_page_size(ginfo->vadj); | ||
407 | |||
408 | new_width = end - start; | ||
409 | |||
410 | curr_width = ginfo->draw->allocation.width; | ||
411 | |||
412 | ginfo->vadj_value = (gdouble)start * view_width / new_width; | ||
413 | |||
414 | new_width = curr_width * (view_width / new_width); | ||
415 | |||
416 | printf("width=%d\n", ginfo->draw->allocation.width); | ||
417 | if (ginfo->vadj) { | ||
418 | printf("adj:%f-%f\n", gtk_adjustment_get_upper(ginfo->vadj), | ||
419 | gtk_adjustment_get_lower(ginfo->vadj)); | ||
420 | } else | ||
421 | printf("no adjustment\n"); | ||
422 | |||
423 | ginfo->draw_width = new_width; | ||
424 | |||
425 | if (ginfo->draw_width > MAX_WIDTH) | ||
426 | ginfo->draw_width = MAX_WIDTH; | ||
427 | |||
428 | if (ginfo->vadj_value > (ginfo->draw_width - view_width)) | ||
429 | ginfo->vadj_value = ginfo->draw_width - view_width; | ||
430 | |||
431 | printf("new width=%d\n", ginfo->draw_width); | ||
432 | gtk_widget_set_size_request(ginfo->draw, ginfo->draw_width, ginfo->draw_height); | ||
433 | |||
434 | printf("set val %f\n", ginfo->vadj_value); | ||
435 | } | ||
436 | |||
437 | static void zoom_out_window(struct graph_info *ginfo, gint start, gint end) | ||
438 | { | ||
439 | gdouble view_width; | ||
440 | gdouble new_width; | ||
441 | gdouble curr_width; | ||
442 | gdouble value; | ||
443 | // unsigned long long start_time; | ||
444 | // unsigned long long end_time; | ||
445 | |||
446 | g_assert(start > end); | ||
447 | g_assert(ginfo->vadj); | ||
448 | |||
449 | view_width = gtk_adjustment_get_page_size(ginfo->vadj); | ||
450 | |||
451 | new_width = start - end; | ||
452 | |||
453 | curr_width = ginfo->draw->allocation.width; | ||
454 | |||
455 | new_width = curr_width / (view_width / new_width); | ||
456 | |||
457 | printf("width=%d\n", ginfo->draw->allocation.width); | ||
458 | if (ginfo->vadj) { | ||
459 | printf("adj:%f-%f\n", gtk_adjustment_get_upper(ginfo->vadj), | ||
460 | gtk_adjustment_get_lower(ginfo->vadj)); | ||
461 | } else | ||
462 | printf("no adjustment\n"); | ||
463 | |||
464 | ginfo->draw_width = new_width; | ||
465 | |||
466 | if (ginfo->draw_width < view_width) | ||
467 | ginfo->draw_width = 0; | ||
468 | |||
469 | printf("new width=%d\n", ginfo->draw_width); | ||
470 | gtk_widget_set_size_request(ginfo->draw, ginfo->draw_width, ginfo->draw_height); | ||
471 | |||
472 | value = gtk_adjustment_get_value(ginfo->vadj); | ||
473 | if (value > new_width - view_width) | ||
474 | ginfo->vadj_value = new_width - view_width; | ||
475 | } | ||
476 | |||
426 | static gboolean | 477 | static gboolean |
427 | button_release_event(GtkWidget *widget, GdkEventMotion *event, gpointer data) | 478 | button_release_event(GtkWidget *widget, GdkEventMotion *event, gpointer data) |
428 | { | 479 | { |
429 | struct graph_info *ginfo = data; | 480 | struct graph_info *ginfo = data; |
430 | 481 | ||
482 | if (ginfo->line_active) { | ||
483 | ginfo->line_active = FALSE; | ||
484 | clear_last_line(widget, ginfo); | ||
485 | ginfo->last_x = ginfo->start_x; | ||
486 | clear_last_line(widget, ginfo); | ||
487 | |||
488 | if (event->x > ginfo->start_x) { | ||
489 | /* make a decent zoom */ | ||
490 | if (event->x - ginfo->start_x < 10) | ||
491 | return TRUE; | ||
492 | zoom_in_window(ginfo, ginfo->start_x, event->x); | ||
493 | return TRUE; | ||
494 | } else { | ||
495 | /* make a decent zoom */ | ||
496 | if (ginfo->start_x - event->x < 10) | ||
497 | return TRUE; | ||
498 | zoom_out_window(ginfo, ginfo->start_x, event->x); | ||
499 | return TRUE; | ||
500 | } | ||
501 | } | ||
502 | |||
431 | printf("RELEASE %s\n", ginfo->save ? "save" : ""); | 503 | printf("RELEASE %s\n", ginfo->save ? "save" : ""); |
432 | clear_last_line(widget, ginfo); | ||
433 | 504 | ||
434 | ginfo->draw_line = FALSE; | 505 | ginfo->draw_line = FALSE; |
435 | 506 | ||
@@ -532,8 +603,7 @@ static void draw_timeline(struct graph_info *ginfo, gint width) | |||
532 | unsigned long long time; | 603 | unsigned long long time; |
533 | gint mid; | 604 | gint mid; |
534 | gint w, h, height; | 605 | gint w, h, height; |
535 | 606 | gint view_width; | |
536 | mid = width / 2; | ||
537 | 607 | ||
538 | /* --- draw timeline text --- */ | 608 | /* --- draw timeline text --- */ |
539 | 609 | ||
@@ -542,6 +612,7 @@ static void draw_timeline(struct graph_info *ginfo, gint width) | |||
542 | 612 | ||
543 | height = 10 + h; | 613 | height = 10 + h; |
544 | 614 | ||
615 | mid = width / 2; | ||
545 | gdk_draw_layout(ginfo->curr_pixmap, ginfo->draw->style->black_gc, | 616 | gdk_draw_layout(ginfo->curr_pixmap, ginfo->draw->style->black_gc, |
546 | mid - w / 2, 5, layout); | 617 | mid - w / 2, 5, layout); |
547 | g_object_unref(layout); | 618 | g_object_unref(layout); |
@@ -560,11 +631,6 @@ static void draw_timeline(struct graph_info *ginfo, gint width) | |||
560 | gdk_draw_line(ginfo->curr_pixmap, ginfo->draw->style->black_gc, | 631 | gdk_draw_line(ginfo->curr_pixmap, ginfo->draw->style->black_gc, |
561 | width-1, height, width-1, height + 5); | 632 | width-1, height, width-1, height + 5); |
562 | 633 | ||
563 | gdk_draw_line(ginfo->curr_pixmap, ginfo->draw->style->black_gc, | ||
564 | mid, height, mid, height + 5); | ||
565 | |||
566 | height += 10; | ||
567 | |||
568 | /* --- draw starting time --- */ | 634 | /* --- draw starting time --- */ |
569 | convert_nano(ginfo->start_time, &sec, &usec); | 635 | convert_nano(ginfo->start_time, &sec, &usec); |
570 | trace_seq_init(&s); | 636 | trace_seq_init(&s); |
@@ -574,7 +640,7 @@ static void draw_timeline(struct graph_info *ginfo, gint width) | |||
574 | pango_layout_get_pixel_size(layout, &w, &h); | 640 | pango_layout_get_pixel_size(layout, &w, &h); |
575 | 641 | ||
576 | gdk_draw_layout(ginfo->curr_pixmap, ginfo->draw->style->black_gc, | 642 | gdk_draw_layout(ginfo->curr_pixmap, ginfo->draw->style->black_gc, |
577 | 1, height, layout); | 643 | 1, height+10, layout); |
578 | g_object_unref(layout); | 644 | g_object_unref(layout); |
579 | 645 | ||
580 | 646 | ||
@@ -587,22 +653,31 @@ static void draw_timeline(struct graph_info *ginfo, gint width) | |||
587 | pango_layout_get_pixel_size(layout, &w, &h); | 653 | pango_layout_get_pixel_size(layout, &w, &h); |
588 | 654 | ||
589 | gdk_draw_layout(ginfo->curr_pixmap, ginfo->draw->style->black_gc, | 655 | gdk_draw_layout(ginfo->curr_pixmap, ginfo->draw->style->black_gc, |
590 | width - (w + 2), height, layout); | 656 | width - (w + 2), height+10, layout); |
591 | g_object_unref(layout); | 657 | g_object_unref(layout); |
592 | 658 | ||
593 | /* --- draw middle time --- */ | ||
594 | time = mid / ginfo->resolution + ginfo->view_start_time; | ||
595 | 659 | ||
596 | convert_nano(time, &sec, &usec); | 660 | /* --- draw time at intervals --- */ |
597 | trace_seq_init(&s); | 661 | view_width = gtk_adjustment_get_page_size(ginfo->vadj); |
598 | trace_seq_printf(&s, "%lu.%06lu", sec, usec); | ||
599 | 662 | ||
600 | layout = gtk_widget_create_pango_layout(ginfo->draw, s.buffer); | 663 | for (mid = view_width / 2; mid < (width - view_width / 2 + 10); |
601 | pango_layout_get_pixel_size(layout, &w, &h); | 664 | mid += view_width / 2) { |
665 | time = mid / ginfo->resolution + ginfo->view_start_time; | ||
602 | 666 | ||
603 | gdk_draw_layout(ginfo->curr_pixmap, ginfo->draw->style->black_gc, | 667 | convert_nano(time, &sec, &usec); |
604 | mid - (w / 2), height, layout); | 668 | trace_seq_init(&s); |
605 | g_object_unref(layout); | 669 | trace_seq_printf(&s, "%lu.%06lu", sec, usec); |
670 | |||
671 | gdk_draw_line(ginfo->curr_pixmap, ginfo->draw->style->black_gc, | ||
672 | mid, height, mid, height + 5); | ||
673 | |||
674 | layout = gtk_widget_create_pango_layout(ginfo->draw, s.buffer); | ||
675 | pango_layout_get_pixel_size(layout, &w, &h); | ||
676 | |||
677 | gdk_draw_layout(ginfo->curr_pixmap, ginfo->draw->style->black_gc, | ||
678 | mid - (w / 2), height+10, layout); | ||
679 | g_object_unref(layout); | ||
680 | } | ||
606 | } | 681 | } |
607 | 682 | ||
608 | static void draw_info(struct graph_info *ginfo, gint old_width, gint old_height, | 683 | static void draw_info(struct graph_info *ginfo, gint old_width, gint old_height, |
@@ -635,8 +710,7 @@ configure_event(GtkWidget *widget, GdkEventMotion *event, gpointer data) | |||
635 | old_w = ginfo->max_width; | 710 | old_w = ginfo->max_width; |
636 | old_h = ginfo->max_height; | 711 | old_h = ginfo->max_height; |
637 | 712 | ||
638 | 713 | // gtk_widget_set_size_request(widget, 0, ginfo->draw_height); | |
639 | gtk_widget_set_size_request(widget, 0, CPU_SPACE(ginfo->cpus)); | ||
640 | 714 | ||
641 | 715 | ||
642 | if (widget->allocation.width > ginfo->max_width) | 716 | if (widget->allocation.width > ginfo->max_width) |
@@ -675,6 +749,13 @@ configure_event(GtkWidget *widget, GdkEventMotion *event, gpointer data) | |||
675 | g_object_unref(old_pix); | 749 | g_object_unref(old_pix); |
676 | } | 750 | } |
677 | 751 | ||
752 | if (!ginfo->vadj_value) | ||
753 | return TRUE; | ||
754 | |||
755 | gtk_adjustment_set_value(ginfo->vadj, ginfo->vadj_value); | ||
756 | ginfo->vadj_value = gtk_adjustment_get_value(ginfo->vadj); | ||
757 | printf("get val %f\n", ginfo->vadj_value); | ||
758 | ginfo->vadj_value = 0.0; | ||
678 | 759 | ||
679 | return TRUE; | 760 | return TRUE; |
680 | } | 761 | } |
@@ -692,7 +773,7 @@ destroy_event(GtkWidget *widget, gpointer data) | |||
692 | 773 | ||
693 | 774 | ||
694 | static GtkWidget * | 775 | static GtkWidget * |
695 | create_drawing_area(struct tracecmd_input *handle) | 776 | create_drawing_area(struct tracecmd_input *handle, GtkScrolledWindow *scrollwin) |
696 | { | 777 | { |
697 | struct graph_info *ginfo; | 778 | struct graph_info *ginfo; |
698 | unsigned long sec, usec; | 779 | unsigned long sec, usec; |
@@ -709,6 +790,9 @@ create_drawing_area(struct tracecmd_input *handle) | |||
709 | ginfo->start_time = -1ULL; | 790 | ginfo->start_time = -1ULL; |
710 | ginfo->end_time = 0; | 791 | ginfo->end_time = 0; |
711 | 792 | ||
793 | ginfo->draw_height = CPU_SPACE(ginfo->cpus); | ||
794 | ginfo->vadj = gtk_scrolled_window_get_hadjustment(scrollwin); | ||
795 | |||
712 | for (cpu = 0; cpu < ginfo->cpus; cpu++) { | 796 | for (cpu = 0; cpu < ginfo->cpus; cpu++) { |
713 | struct record *record; | 797 | struct record *record; |
714 | 798 | ||
@@ -865,7 +949,7 @@ void trace_graph(int argc, char **argv) | |||
865 | 949 | ||
866 | /* --- Set up Drawing --- */ | 950 | /* --- Set up Drawing --- */ |
867 | 951 | ||
868 | draw = create_drawing_area(handle); | 952 | draw = create_drawing_area(handle, GTK_SCROLLED_WINDOW(scrollwin)); |
869 | 953 | ||
870 | gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrollwin), | 954 | gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrollwin), |
871 | draw); | 955 | draw); |
diff --git a/trace-graph.h b/trace-graph.h index 18426e6..e45b37a 100644 --- a/trace-graph.h +++ b/trace-graph.h | |||
@@ -10,6 +10,7 @@ struct graph_info { | |||
10 | GtkWidget *draw; | 10 | GtkWidget *draw; |
11 | GdkPixmap *main_pixmap; | 11 | GdkPixmap *main_pixmap; |
12 | GdkPixmap *curr_pixmap; | 12 | GdkPixmap *curr_pixmap; |
13 | GtkAdjustment *vadj; | ||
13 | guint64 start_time; | 14 | guint64 start_time; |
14 | guint64 end_time; | 15 | guint64 end_time; |
15 | guint64 view_start_time; | 16 | guint64 view_start_time; |
@@ -17,7 +18,21 @@ struct graph_info { | |||
17 | 18 | ||
18 | gdouble resolution; | 19 | gdouble resolution; |
19 | 20 | ||
21 | gint start_x; | ||
20 | gint last_x; | 22 | gint last_x; |
23 | gboolean line_active; | ||
24 | gdouble vadj_value; | ||
25 | |||
26 | gint draw_width; | ||
27 | gint draw_height; | ||
28 | |||
29 | gint cpu_data_x; | ||
30 | gint cpu_data_y; | ||
31 | gint cpu_data_w; | ||
32 | gint cpu_data_h; | ||
33 | |||
34 | /* not needed in future */ | ||
35 | |||
21 | gint last_y; | 36 | gint last_y; |
22 | gint mov_w; | 37 | gint mov_w; |
23 | gint mov_h; | 38 | gint mov_h; |
@@ -28,11 +43,6 @@ struct graph_info { | |||
28 | gboolean save; | 43 | gboolean save; |
29 | gboolean draw_line; | 44 | gboolean draw_line; |
30 | gchar *test; | 45 | gchar *test; |
31 | |||
32 | gint cpu_data_x; | ||
33 | gint cpu_data_y; | ||
34 | gint cpu_data_w; | ||
35 | gint cpu_data_h; | ||
36 | }; | 46 | }; |
37 | 47 | ||
38 | #endif /* _TRACE_GRAPH_H */ | 48 | #endif /* _TRACE_GRAPH_H */ |