From 4172f013ca271667f6be4735216e9f69578a88fd Mon Sep 17 00:00:00 2001 From: Yannick Brosseau Date: Fri, 4 Feb 2011 17:15:06 -0500 Subject: [PATCH] Replace the current timebar with a new timebar widget (v2) Create a timeentry GtkWidget to manage the entry of a seconds/nanoseconds value Create a timebar GtkWidget which aggregate 4 timeentry (Start, end, current time +and time interval) Simplify the main window tab widget code by using this new timebar. Changelog: Fix crash in time pasting and spacing adjustment of widgets Fix interval management when pasting to keep a coherent time Rework the signaling management Signed-off-by: Yannick Brosseau Signed-off-by: Mathieu Desnoyers --- .../gui/lttvwindow/lttvwindow/Makefile.am | 4 + .../gui/lttvwindow/lttvwindow/callbacks.c | 1047 ++--------------- .../lttvwindow/mainwindow-private.h | 30 +- .../gui/lttvwindow/lttvwindow/timebar.c | 424 +++++++ .../gui/lttvwindow/lttvwindow/timebar.h | 78 ++ .../gui/lttvwindow/lttvwindow/timeentry.c | 456 +++++++ .../gui/lttvwindow/lttvwindow/timeentry.h | 85 ++ 7 files changed, 1152 insertions(+), 972 deletions(-) create mode 100644 lttv/modules/gui/lttvwindow/lttvwindow/timebar.c create mode 100644 lttv/modules/gui/lttvwindow/lttvwindow/timebar.h create mode 100644 lttv/modules/gui/lttvwindow/lttvwindow/timeentry.c create mode 100644 lttv/modules/gui/lttvwindow/lttvwindow/timeentry.h diff --git a/lttv/modules/gui/lttvwindow/lttvwindow/Makefile.am b/lttv/modules/gui/lttvwindow/lttvwindow/Makefile.am index 00e41774..c953fc9f 100644 --- a/lttv/modules/gui/lttvwindow/lttvwindow/Makefile.am +++ b/lttv/modules/gui/lttvwindow/lttvwindow/Makefile.am @@ -15,6 +15,8 @@ lib_LTLIBRARIES = liblttvwindow.la liblttvwindow_la_SOURCES = \ toolbar.c\ menu.c\ + timebar.c\ + timeentry.c\ lttvwindow.c \ lttvwindowtraces.c \ init_module.c \ @@ -36,6 +38,8 @@ lttvwindowinclude_HEADERS = \ mainwindow.h\ menu.h\ toolbar.h\ + timebar.h\ + timeentry.h\ lttv_plugin_tab.h \ lttv_plugin.h diff --git a/lttv/modules/gui/lttvwindow/lttvwindow/callbacks.c b/lttv/modules/gui/lttvwindow/lttvwindow/callbacks.c index c945e62f..aabd2ace 100644 --- a/lttv/modules/gui/lttvwindow/lttvwindow/callbacks.c +++ b/lttv/modules/gui/lttvwindow/lttvwindow/callbacks.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -80,6 +81,13 @@ LttvPluginTab *create_new_tab(GtkWidget* widget, gpointer user_data); static gboolean lttvwindow_process_pending_requests(Tab *tab); +static void on_timebar_starttime_changed(Timebar *timebar, + gpointer user_data); +static void on_timebar_endtime_changed(Timebar *timebar, + gpointer user_data); +static void on_timebar_currenttime_changed(Timebar *timebar, + gpointer user_data); + enum { CHECKBOX_COLUMN, NAME_COLUMN, @@ -92,262 +100,7 @@ enum N_COLUMNS }; -/* Pasting routines */ - -static void MEventBox1a_receive(GtkClipboard *clipboard, - const gchar *text, - gpointer data) -{ - if(text == NULL) return; - Tab *tab = (Tab *)data; - gchar buffer[CLIP_BUF]; - gchar *ptr = buffer, *ptr_ssec, *ptr_snsec, *ptr_esec, *ptr_ensec; - - strncpy(buffer, text, CLIP_BUF); - - /* start */ - while(!isdigit(*ptr) && ptr < buffer+CLIP_BUF-1) ptr++; - /* remove leading junk */ - ptr_ssec = ptr; - while(isdigit(*ptr) && ptr < buffer+CLIP_BUF-1) ptr++; - /* read all the first number */ - *ptr = '\0'; - ptr++; - - while(!isdigit(*ptr) && ptr < buffer+CLIP_BUF-1) ptr++; - /* remove leading junk */ - ptr_snsec = ptr; - while(isdigit(*ptr) && ptr < buffer+CLIP_BUF-1) ptr++; - /* read all the first number */ - *ptr = '\0'; - - /* end */ - while(!isdigit(*ptr) && ptr < buffer+CLIP_BUF-1) ptr++; - /* remove leading junk */ - ptr_esec = ptr; - while(isdigit(*ptr) && ptr < buffer+CLIP_BUF-1) ptr++; - /* read all the first number */ - *ptr = '\0'; - ptr++; - - while(!isdigit(*ptr) && ptr < buffer+CLIP_BUF-1) ptr++; - /* remove leading junk */ - ptr_ensec = ptr; - while(isdigit(*ptr) && ptr < buffer+CLIP_BUF-1) ptr++; - /* read all the first number */ - *ptr = '\0'; - - gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab->MEntry1), - (double)strtoul(ptr_ssec, NULL, 10)); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab->MEntry2), - (double)strtoul(ptr_snsec, NULL, 10)); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab->MEntry3), - (double)strtoul(ptr_esec, NULL, 10)); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab->MEntry4), - (double)strtoul(ptr_ensec, NULL, 10)); -} - -static gboolean on_MEventBox1a_paste(GtkWidget *widget, GdkEventButton *event, - gpointer data) -{ - Tab *tab = (Tab*)data; - - GtkClipboard *clip = gtk_clipboard_get_for_display(gdk_display_get_default(), - GDK_SELECTION_PRIMARY); - gtk_clipboard_request_text(clip, - (GtkClipboardTextReceivedFunc)MEventBox1a_receive, - (gpointer)tab); - return 0; -} - - -/* Start */ -static void MEventBox1b_receive(GtkClipboard *clipboard, - const gchar *text, - gpointer data) -{ - if(text == NULL) return; - Tab *tab = (Tab *)data; - gchar buffer[CLIP_BUF]; - gchar *ptr = buffer, *ptr_sec, *ptr_nsec; - - strncpy(buffer, text, CLIP_BUF); - - while(!isdigit(*ptr) && ptr < buffer+CLIP_BUF-1) ptr++; - /* remove leading junk */ - ptr_sec = ptr; - while(isdigit(*ptr) && ptr < buffer+CLIP_BUF-1) ptr++; - /* read all the first number */ - *ptr = '\0'; - ptr++; - - while(!isdigit(*ptr) && ptr < buffer+CLIP_BUF-1) ptr++; - /* remove leading junk */ - ptr_nsec = ptr; - while(isdigit(*ptr) && ptr < buffer+CLIP_BUF-1) ptr++; - /* read all the first number */ - *ptr = '\0'; - - gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab->MEntry1), - (double)strtoul(ptr_sec, NULL, 10)); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab->MEntry2), - (double)strtoul(ptr_nsec, NULL, 10)); -} - -/* Start */ -static gboolean on_MEventBox1b_paste(GtkWidget *widget, GdkEventButton *event, - gpointer data) -{ - Tab *tab = (Tab*)data; - - GtkClipboard *clip = gtk_clipboard_get_for_display(gdk_display_get_default(), - GDK_SELECTION_PRIMARY); - gtk_clipboard_request_text(clip, - (GtkClipboardTextReceivedFunc)MEventBox1b_receive, - (gpointer)tab); - return 0; -} - -/* End */ -static void MEventBox3b_receive(GtkClipboard *clipboard, - const gchar *text, - gpointer data) -{ - if(text == NULL) return; - Tab *tab = (Tab *)data; - gchar buffer[CLIP_BUF]; - gchar *ptr = buffer, *ptr_sec, *ptr_nsec; - - strncpy(buffer, text, CLIP_BUF); - - while(!isdigit(*ptr) && ptr < buffer+CLIP_BUF-1) ptr++; - /* remove leading junk */ - ptr_sec = ptr; - while(isdigit(*ptr) && ptr < buffer+CLIP_BUF-1) ptr++; - /* read all the first number */ - *ptr = '\0'; - ptr++; - - while(!isdigit(*ptr) && ptr < buffer+CLIP_BUF-1) ptr++; - /* remove leading junk */ - ptr_nsec = ptr; - while(isdigit(*ptr) && ptr < buffer+CLIP_BUF-1) ptr++; - /* read all the first number */ - *ptr = '\0'; - - gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab->MEntry3), - (double)strtoul(ptr_sec, NULL, 10)); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab->MEntry4), - (double)strtoul(ptr_nsec, NULL, 10)); -} - -/* End */ -static gboolean on_MEventBox3b_paste(GtkWidget *widget, GdkEventButton *event, - gpointer data) -{ - Tab *tab = (Tab*)data; - - GtkClipboard *clip = gtk_clipboard_get_for_display(gdk_display_get_default(), - GDK_SELECTION_PRIMARY); - gtk_clipboard_request_text(clip, - (GtkClipboardTextReceivedFunc)MEventBox3b_receive, - (gpointer)tab); - return 0; -} - -/* Current */ -static void MEventBox5b_receive(GtkClipboard *clipboard, - const gchar *text, - gpointer data) -{ - if(text == NULL) return; - Tab *tab = (Tab *)data; - gchar buffer[CLIP_BUF]; - gchar *ptr = buffer, *ptr_sec, *ptr_nsec; - strncpy(buffer, text, CLIP_BUF); - - while(!isdigit(*ptr) && ptr < buffer+CLIP_BUF-1) ptr++; - /* remove leading junk */ - ptr_sec = ptr; - while(isdigit(*ptr) && ptr < buffer+CLIP_BUF-1) ptr++; - /* read all the first number */ - *ptr = '\0'; - ptr++; - - while(!isdigit(*ptr) && ptr < buffer+CLIP_BUF-1) ptr++; - /* remove leading junk */ - ptr_nsec = ptr; - while(isdigit(*ptr) && ptr < buffer+CLIP_BUF-1) ptr++; - /* read all the first number */ - *ptr = '\0'; - - gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab->MEntry5), - (double)strtoul(ptr_sec, NULL, 10)); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab->MEntry6), - (double)strtoul(ptr_nsec, NULL, 10)); -} - -/* Current */ -static gboolean on_MEventBox5b_paste(GtkWidget *widget, GdkEventButton *event, - gpointer data) -{ - Tab *tab = (Tab*)data; - - GtkClipboard *clip = gtk_clipboard_get_for_display(gdk_display_get_default(), - GDK_SELECTION_PRIMARY); - gtk_clipboard_request_text(clip, - (GtkClipboardTextReceivedFunc)MEventBox5b_receive, - (gpointer)tab); - return 0; -} - -/* Interval */ -static void MEventBox8_receive(GtkClipboard *clipboard, - const gchar *text, - gpointer data) -{ - if(text == NULL) return; - Tab *tab = (Tab *)data; - gchar buffer[CLIP_BUF]; - gchar *ptr = buffer, *ptr_sec, *ptr_nsec; - - strncpy(buffer, text, CLIP_BUF); - - while(!isdigit(*ptr) && ptr < buffer+CLIP_BUF-1) ptr++; - /* remove leading junk */ - ptr_sec = ptr; - while(isdigit(*ptr) && ptr < buffer+CLIP_BUF-1) ptr++; - /* read all the first number */ - *ptr = '\0'; - ptr++; - - while(!isdigit(*ptr) && ptr < buffer+CLIP_BUF-1) ptr++; - /* remove leading junk */ - ptr_nsec = ptr; - while(isdigit(*ptr) && ptr < buffer+CLIP_BUF-1) ptr++; - /* read all the first number */ - *ptr = '\0'; - - gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab->MEntry7), - (double)strtoul(ptr_sec, NULL, 10)); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab->MEntry8), - (double)strtoul(ptr_nsec, NULL, 10)); -} - -/* Interval */ -static gboolean on_MEventBox8_paste(GtkWidget *widget, GdkEventButton *event, - gpointer data) -{ - Tab *tab = (Tab*)data; - - GtkClipboard *clip = gtk_clipboard_get_for_display(gdk_display_get_default(), - GDK_SELECTION_PRIMARY); - gtk_clipboard_request_text(clip, - (GtkClipboardTextReceivedFunc)MEventBox8_receive, - (gpointer)tab); - return 0; -} #if 0 static void on_top_notify(GObject *gobject, @@ -3490,432 +3243,23 @@ void time_change_manager (Tab *tab, ltt_time_sub(start_time, time_span.start_time)) /* value */); /* set the time bar. */ - /* start seconds */ - gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab->MEntry1), - (double)time_span.start_time.tv_sec, - (double)time_span.end_time.tv_sec); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab->MEntry1), - (double)start_time.tv_sec); - - /* start nanoseconds */ - if(start_time.tv_sec == time_span.start_time.tv_sec) { - /* can be both beginning and end at the same time. */ - if(start_time.tv_sec == time_span.end_time.tv_sec) { - /* If we are at the end, max nsec to end.. -1 (not zero length) */ - gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab->MEntry2), - (double)time_span.start_time.tv_nsec, - (double)time_span.end_time.tv_nsec-1); - } else { - gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab->MEntry2), - (double)time_span.start_time.tv_nsec, - (double)NANOSECONDS_PER_SECOND-1); - } - } else if(start_time.tv_sec == time_span.end_time.tv_sec) { - /* If we are at the end, max nsec to end.. -1 (not zero length) */ - gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab->MEntry2), - 0.0, - (double)time_span.end_time.tv_nsec-1); - } else /* anywhere else */ - gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab->MEntry2), - 0.0, - (double)NANOSECONDS_PER_SECOND-1); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab->MEntry2), - (double)start_time.tv_nsec); - - /* end seconds */ - gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab->MEntry3), - (double)time_span.start_time.tv_sec, - (double)time_span.end_time.tv_sec); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab->MEntry3), - (double)end_time.tv_sec); - - /* end nanoseconds */ - if(end_time.tv_sec == time_span.start_time.tv_sec) { - /* can be both beginning and end at the same time. */ - if(end_time.tv_sec == time_span.end_time.tv_sec) { - /* If we are at the end, max nsec to end.. */ - gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab->MEntry4), - (double)time_span.start_time.tv_nsec+1, - (double)time_span.end_time.tv_nsec); - } else { - gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab->MEntry4), - (double)time_span.start_time.tv_nsec+1, - (double)NANOSECONDS_PER_SECOND-1); - } - } - else if(end_time.tv_sec == time_span.end_time.tv_sec) { - /* If we are at the end, max nsec to end.. */ - gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab->MEntry4), - 0.0, - (double)time_span.end_time.tv_nsec); - } - else /* anywhere else */ - gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab->MEntry4), - 0.0, - (double)NANOSECONDS_PER_SECOND-1); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab->MEntry4), - (double)end_time.tv_nsec); - - /* width seconds */ - if(time_width.tv_nsec == 0) { - gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab->MEntry7), - (double)1, - (double)upper.tv_sec); - } else { - gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab->MEntry7), - (double)0, - (double)upper.tv_sec); - } - gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab->MEntry7), - (double)time_width.tv_sec); - - /* width nanoseconds */ - if(time_width.tv_sec == upper.tv_sec) { - if(time_width.tv_sec == 0) { - gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab->MEntry8), - (double)1, - (double)upper.tv_nsec); - } else { - gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab->MEntry8), - (double)0, - (double)upper.tv_nsec); - } - } - else if(time_width.tv_sec == 0) { - gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab->MEntry8), - 1.0, - (double)upper.tv_nsec); - } - else /* anywhere else */ - gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab->MEntry8), - 0.0, - (double)NANOSECONDS_PER_SECOND-1); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab->MEntry8), - (double)time_width.tv_nsec); - - /* call viewer hooks for new time window */ - set_time_window(tab, &new_time_window); - - tab->time_manager_lock = FALSE; -} - - -/* value changed for frame start s - * - * Check time span : if ns is out of range, clip it the nearest good value. - */ -void -on_MEntry1_value_changed (GtkSpinButton *spinbutton, - gpointer user_data) -{ - Tab *tab =(Tab *)user_data; - LttvTracesetContext * tsc = - LTTV_TRACESET_CONTEXT(tab->traceset_info->traceset_context); - TimeInterval time_span = tsc->time_span; - gint value = gtk_spin_button_get_value_as_int(spinbutton); - - TimeWindow new_time_window = tab->time_window; - - LttTime end_time = new_time_window.end_time; - - new_time_window.start_time.tv_sec = value; - - /* start nanoseconds */ - if(new_time_window.start_time.tv_sec == time_span.start_time.tv_sec) { - if(new_time_window.start_time.tv_sec == time_span.end_time.tv_sec) { - if(new_time_window.start_time.tv_nsec > time_span.end_time.tv_nsec) - new_time_window.start_time.tv_nsec = time_span.end_time.tv_nsec-1; - if(new_time_window.start_time.tv_nsec < time_span.start_time.tv_nsec) - new_time_window.start_time.tv_nsec = time_span.start_time.tv_nsec; - } else { - if(new_time_window.start_time.tv_nsec < time_span.start_time.tv_nsec) - new_time_window.start_time.tv_nsec = time_span.start_time.tv_nsec; - } - } - else if(new_time_window.start_time.tv_sec == time_span.end_time.tv_sec) { - if(new_time_window.start_time.tv_nsec > time_span.end_time.tv_nsec) - new_time_window.start_time.tv_nsec = time_span.end_time.tv_nsec-1; - } - - if(ltt_time_compare(new_time_window.start_time, end_time) >= 0) { - /* Then, we must push back end time : keep the same time width - * if possible, else end traceset time */ - end_time = LTT_TIME_MIN(ltt_time_add(new_time_window.start_time, - new_time_window.time_width), - time_span.end_time); - } - - /* Fix the time width to fit start time and end time */ - new_time_window.time_width = ltt_time_sub(end_time, - new_time_window.start_time); - new_time_window.time_width_double = - ltt_time_to_double(new_time_window.time_width); - - new_time_window.end_time = end_time; - - time_change_manager(tab, new_time_window); - -} - -void -on_MEntry2_value_changed (GtkSpinButton *spinbutton, - gpointer user_data) -{ - Tab *tab =(Tab *)user_data; - LttvTracesetContext * tsc = - LTTV_TRACESET_CONTEXT(tab->traceset_info->traceset_context); - TimeInterval time_span = tsc->time_span; - gint value = gtk_spin_button_get_value_as_int(spinbutton); - - TimeWindow new_time_window = tab->time_window; - - LttTime end_time = new_time_window.end_time; - - new_time_window.start_time.tv_nsec = value; - - if(ltt_time_compare(new_time_window.start_time, end_time) >= 0) { - /* Then, we must push back end time : keep the same time width - * if possible, else end traceset time */ - end_time = LTT_TIME_MIN(ltt_time_add(new_time_window.start_time, - new_time_window.time_width), - time_span.end_time); - } - - /* Fix the time width to fit start time and end time */ - new_time_window.time_width = ltt_time_sub(end_time, - new_time_window.start_time); - new_time_window.time_width_double = - ltt_time_to_double(new_time_window.time_width); - - new_time_window.end_time = end_time; - - time_change_manager(tab, new_time_window); - -} - -void -on_MEntry3_value_changed (GtkSpinButton *spinbutton, - gpointer user_data) -{ - Tab *tab =(Tab *)user_data; - LttvTracesetContext * tsc = - LTTV_TRACESET_CONTEXT(tab->traceset_info->traceset_context); - TimeInterval time_span = tsc->time_span; - gint value = gtk_spin_button_get_value_as_int(spinbutton); - - TimeWindow new_time_window = tab->time_window; - - LttTime end_time = new_time_window.end_time; - end_time.tv_sec = value; - /* end nanoseconds */ - if(end_time.tv_sec == time_span.start_time.tv_sec) { - if(end_time.tv_sec == time_span.end_time.tv_sec) { - if(end_time.tv_nsec > time_span.end_time.tv_nsec) - end_time.tv_nsec = time_span.end_time.tv_nsec; - if(end_time.tv_nsec < time_span.start_time.tv_nsec) - end_time.tv_nsec = time_span.start_time.tv_nsec+1; - } else { - if(end_time.tv_nsec < time_span.start_time.tv_nsec) - end_time.tv_nsec = time_span.start_time.tv_nsec+1; - } - } - else if(end_time.tv_sec == time_span.end_time.tv_sec) { - if(end_time.tv_nsec > time_span.end_time.tv_nsec) - end_time.tv_nsec = time_span.end_time.tv_nsec; - } + timebar_set_minmax_time(TIMEBAR(tab->MTimebar), + &time_span.start_time, + &time_span.end_time ); + timebar_set_start_time(TIMEBAR(tab->MTimebar),&start_time); + timebar_set_end_time(TIMEBAR(tab->MTimebar),&end_time); - if(ltt_time_compare(new_time_window.start_time, end_time) >= 0) { - /* Then, we must push front start time : keep the same time width - * if possible, else end traceset time */ - new_time_window.start_time = LTT_TIME_MAX( - ltt_time_sub(end_time, - new_time_window.time_width), - time_span.start_time); - } - - /* Fix the time width to fit start time and end time */ - new_time_window.time_width = ltt_time_sub(end_time, - new_time_window.start_time); - new_time_window.time_width_double = - ltt_time_to_double(new_time_window.time_width); - new_time_window.end_time = end_time; - - time_change_manager(tab, new_time_window); - -} - -void -on_MEntry4_value_changed (GtkSpinButton *spinbutton, - gpointer user_data) -{ - Tab *tab =(Tab *)user_data; - LttvTracesetContext * tsc = - LTTV_TRACESET_CONTEXT(tab->traceset_info->traceset_context); - TimeInterval time_span = tsc->time_span; - gint value = gtk_spin_button_get_value_as_int(spinbutton); - - TimeWindow new_time_window = tab->time_window; - - LttTime end_time = new_time_window.end_time; - - end_time.tv_nsec = value; - - if(ltt_time_compare(new_time_window.start_time, end_time) >= 0) { - /* Then, we must push front start time : keep the same time width - * if possible, else end traceset time */ - new_time_window.start_time = LTT_TIME_MAX( - ltt_time_sub(end_time, - new_time_window.time_width), - time_span.start_time); - } - - /* Fix the time width to fit start time and end time */ - new_time_window.time_width = ltt_time_sub(end_time, - new_time_window.start_time); - new_time_window.time_width_double = - ltt_time_to_double(new_time_window.time_width); - new_time_window.end_time = end_time; - - time_change_manager(tab, new_time_window); - -} - -/* value changed for time frame interval s - * - * Check time span : if ns is out of range, clip it the nearest good value. - */ -void -on_MEntry7_value_changed (GtkSpinButton *spinbutton, - gpointer user_data) -{ - Tab *tab =(Tab *)user_data; - LttvTracesetContext * tsc = - LTTV_TRACESET_CONTEXT(tab->traceset_info->traceset_context); - TimeInterval time_span = tsc->time_span; - gint value = gtk_spin_button_get_value_as_int(spinbutton); - LttTime current_time, time_delta; - TimeWindow new_time_window = tab->time_window; - current_time = tab->current_time; - - time_delta = ltt_time_sub(time_span.end_time,time_span.start_time); - new_time_window.time_width.tv_sec = value; - new_time_window.time_width_double = - ltt_time_to_double(new_time_window.time_width); - if(ltt_time_compare(new_time_window.time_width,time_delta) > 0) - { /* Case where zoom out is bigger than trace length */ - new_time_window.start_time = time_span.start_time; - new_time_window.time_width = time_delta; - new_time_window.time_width_double = ltt_time_to_double(time_delta); - new_time_window.end_time = ltt_time_add(new_time_window.start_time, - new_time_window.time_width) ; - } - else - { - /* Center the image on the current time */ - new_time_window.start_time = - ltt_time_sub(current_time, - ltt_time_from_double(new_time_window.time_width_double/2.0)); - new_time_window.end_time = ltt_time_add(new_time_window.start_time, - new_time_window.time_width) ; - /* If on borders, don't fall off */ - if(ltt_time_compare(new_time_window.start_time, time_span.start_time) <0 - || ltt_time_compare(new_time_window.start_time, time_span.end_time) >0) - { - new_time_window.start_time = time_span.start_time; - new_time_window.end_time = ltt_time_add(new_time_window.start_time, - new_time_window.time_width) ; - } - else - { - if(ltt_time_compare(new_time_window.end_time, - time_span.end_time) > 0 - || ltt_time_compare(new_time_window.end_time, - time_span.start_time) < 0) - { - new_time_window.start_time = - ltt_time_sub(time_span.end_time, new_time_window.time_width); - new_time_window.end_time = ltt_time_add(new_time_window.start_time, - new_time_window.time_width) ; - } - } - - } + /* call viewer hooks for new time window */ + set_time_window(tab, &new_time_window); - if(ltt_time_compare(new_time_window.time_width, ltt_time_zero) == 0) { - g_warning("Zoom more than 1 ns impossible"); - } else { - time_change_manager(tab, new_time_window); - } + tab->time_manager_lock = FALSE; } -void -on_MEntry8_value_changed (GtkSpinButton *spinbutton, - gpointer user_data) -{ - Tab *tab =(Tab *)user_data; - LttvTracesetContext * tsc = - LTTV_TRACESET_CONTEXT(tab->traceset_info->traceset_context); - TimeInterval time_span = tsc->time_span; - gint value = gtk_spin_button_get_value_as_int(spinbutton); - LttTime current_time, time_delta; - TimeWindow new_time_window = tab->time_window; - current_time = tab->current_time; - - time_delta = ltt_time_sub(time_span.end_time,time_span.start_time); - new_time_window.time_width.tv_nsec = value; - new_time_window.time_width_double = - ltt_time_to_double(new_time_window.time_width); - if(ltt_time_compare(new_time_window.time_width,time_delta) > 0) - { /* Case where zoom out is bigger than trace length */ - new_time_window.start_time = time_span.start_time; - new_time_window.time_width = time_delta; - new_time_window.time_width_double = ltt_time_to_double(time_delta); - new_time_window.end_time = ltt_time_add(new_time_window.start_time, - new_time_window.time_width) ; - } - else - { - /* Center the image on the current time */ - new_time_window.start_time = - ltt_time_sub(current_time, - ltt_time_from_double(new_time_window.time_width_double/2.0)); - new_time_window.end_time = ltt_time_add(new_time_window.start_time, - new_time_window.time_width) ; - /* If on borders, don't fall off */ - if(ltt_time_compare(new_time_window.start_time, time_span.start_time) <0 - || ltt_time_compare(new_time_window.start_time, time_span.end_time) >0) - { - new_time_window.start_time = time_span.start_time; - new_time_window.end_time = ltt_time_add(new_time_window.start_time, - new_time_window.time_width) ; - } - else - { - if(ltt_time_compare(new_time_window.end_time, - time_span.end_time) > 0 - || ltt_time_compare(new_time_window.end_time, - time_span.start_time) < 0) - { - new_time_window.start_time = - ltt_time_sub(time_span.end_time, new_time_window.time_width); - new_time_window.end_time = ltt_time_add(new_time_window.start_time, - new_time_window.time_width) ; - } - } - - } - - if(ltt_time_compare(new_time_window.time_width, ltt_time_zero) == 0) { - g_warning("Zoom more than 1 ns impossible"); - } else { - time_change_manager(tab, new_time_window); - } -} @@ -3930,39 +3274,7 @@ void current_time_change_manager (Tab *tab, LttvTracesetContext *tsc = LTTV_TRACESET_CONTEXT(tab->traceset_info->traceset_context); TimeInterval time_span = tsc->time_span; - /* current seconds */ - gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab->MEntry5), - (double)time_span.start_time.tv_sec, - (double)time_span.end_time.tv_sec); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab->MEntry5), - (double)new_current_time.tv_sec); - - - /* start nanoseconds */ - if(new_current_time.tv_sec == time_span.start_time.tv_sec) { - /* can be both beginning and end at the same time. */ - if(new_current_time.tv_sec == time_span.end_time.tv_sec) { - /* If we are at the end, max nsec to end.. */ - gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab->MEntry6), - (double)time_span.start_time.tv_nsec, - (double)time_span.end_time.tv_nsec); - } else { - gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab->MEntry6), - (double)time_span.start_time.tv_nsec, - (double)NANOSECONDS_PER_SECOND-1); - } - } else if(new_current_time.tv_sec == time_span.end_time.tv_sec) { - /* If we are at the end, max nsec to end.. */ - gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab->MEntry6), - 0.0, - (double)time_span.end_time.tv_nsec); - } else /* anywhere else */ - gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab->MEntry6), - 0.0, - (double)NANOSECONDS_PER_SECOND-1); - - gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab->MEntry6), - (double)new_current_time.tv_nsec); + timebar_set_current_time(TIMEBAR(tab->MTimebar), &new_current_time); set_current_time(tab, &new_current_time); @@ -3988,50 +3300,87 @@ void current_position_change_manager(Tab *tab, } -void -on_MEntry5_value_changed (GtkSpinButton *spinbutton, - gpointer user_data) +static void on_timebar_starttime_changed(Timebar *timebar, + gpointer user_data) { - Tab *tab = (Tab*)user_data; - LttvTracesetContext * tsc = - LTTV_TRACESET_CONTEXT(tab->traceset_info->traceset_context); - TimeInterval time_span = tsc->time_span; - gint value = gtk_spin_button_get_value_as_int(spinbutton); - LttTime new_current_time = tab->current_time; - new_current_time.tv_sec = value; - - /* current nanoseconds */ - if(new_current_time.tv_sec == time_span.start_time.tv_sec) { - if(new_current_time.tv_sec == time_span.end_time.tv_sec) { - if(new_current_time.tv_nsec > time_span.end_time.tv_nsec) - new_current_time.tv_nsec = time_span.end_time.tv_nsec; - if(new_current_time.tv_nsec < time_span.start_time.tv_nsec) - new_current_time.tv_nsec = time_span.start_time.tv_nsec; - } else { - if(new_current_time.tv_nsec < time_span.start_time.tv_nsec) - new_current_time.tv_nsec = time_span.start_time.tv_nsec; - } - } - else if(new_current_time.tv_sec == time_span.end_time.tv_sec) { - if(new_current_time.tv_nsec > time_span.end_time.tv_nsec) - new_current_time.tv_nsec = time_span.end_time.tv_nsec; - } + Tab *tab = (Tab *)user_data; + LttvTracesetContext * tsc = + LTTV_TRACESET_CONTEXT(tab->traceset_info->traceset_context); + TimeInterval time_span = tsc->time_span; + + TimeWindow new_time_window = tab->time_window; + new_time_window.start_time = timebar_get_start_time(timebar); + + LttTime end_time = new_time_window.end_time; + + /* TODO ybrosseau 2010-12-02: This if should have been checked + by the timebar already */ + if(ltt_time_compare(new_time_window.start_time, end_time) >= 0) { + /* Then, we must push back end time : keep the same time width + * if possible, else end traceset time */ + end_time = LTT_TIME_MIN(ltt_time_add(new_time_window.start_time, + new_time_window.time_width), + time_span.end_time); + } + + /* Fix the time width to fit start time and end time */ + new_time_window.time_width = ltt_time_sub(end_time, + new_time_window.start_time); + + new_time_window.time_width_double = + ltt_time_to_double(new_time_window.time_width); + + new_time_window.end_time = end_time; + + /* Notify the time_manager */ + time_change_manager(tab, new_time_window); - current_time_change_manager(tab, new_current_time); } -void -on_MEntry6_value_changed (GtkSpinButton *spinbutton, - gpointer user_data) +static void on_timebar_endtime_changed(Timebar *timebar, + gpointer user_data) { - Tab *tab = (Tab*)user_data; - gint value = gtk_spin_button_get_value_as_int(spinbutton); - LttTime new_current_time = tab->current_time; - new_current_time.tv_nsec = value; - - current_time_change_manager(tab, new_current_time); + Tab *tab = (Tab *)user_data; + LttvTracesetContext * tsc = + LTTV_TRACESET_CONTEXT(tab->traceset_info->traceset_context); + TimeInterval time_span = tsc->time_span; + + TimeWindow new_time_window = tab->time_window; + + LttTime end_time = timebar_get_end_time(timebar); + + /* TODO ybrosseau 2010-12-02: This if should have been + checked by the timebar already */ + if(ltt_time_compare(new_time_window.start_time, end_time) >= 0) { + /* Then, we must push front start time : keep the same time + width if possible, else end traceset time */ + new_time_window.start_time = LTT_TIME_MAX( + ltt_time_sub(end_time, + new_time_window.time_width), + time_span.start_time); + } + + /* Fix the time width to fit start time and end time */ + new_time_window.time_width = ltt_time_sub(end_time, + new_time_window.start_time); + + new_time_window.time_width_double = + ltt_time_to_double(new_time_window.time_width); + + new_time_window.end_time = end_time; + + /* Notify the time_manager */ + time_change_manager(tab, new_time_window); +} +static void on_timebar_currenttime_changed(Timebar *timebar, + gpointer user_data) +{ + Tab *tab = (Tab *)user_data; + + LttTime new_current_time = timebar_get_current_time(timebar); + + current_time_change_manager(tab, new_current_time); } - void scroll_value_changed_cb(GtkWidget *scrollbar, gpointer user_data) @@ -4470,8 +3819,6 @@ void tab_destructor(LttvPluginTab * ptab) LttvTrace * trace; Tab *tab = ptab->tab; - gtk_object_destroy(GTK_OBJECT(tab->tooltips)); - if(tab->attributes) g_object_unref(tab->attributes); @@ -4615,180 +3962,8 @@ void init_tab(Tab *tab, MainWindow * mw, Tab *copy_tab, // } /* Create the timebar */ - { - tab->MTimebar = gtk_hbox_new(FALSE, 2); - gtk_widget_show(tab->MTimebar); - tab->tooltips = gtk_tooltips_new(); - - tab->MEventBox1a = gtk_event_box_new(); - gtk_widget_show(tab->MEventBox1a); - gtk_tooltips_set_tip(tab->tooltips, tab->MEventBox1a, - "Paste Start and End Times Here", ""); - tab->MText1a = gtk_label_new("Time Frame "); - gtk_widget_show(tab->MText1a); - gtk_container_add(GTK_CONTAINER(tab->MEventBox1a), tab->MText1a); - tab->MEventBox1b = gtk_event_box_new(); - gtk_widget_show(tab->MEventBox1b); - gtk_tooltips_set_tip(tab->tooltips, tab->MEventBox1b, - "Paste Start Time Here", ""); - tab->MText1b = gtk_label_new("start: "); - gtk_widget_show(tab->MText1b); - gtk_container_add(GTK_CONTAINER(tab->MEventBox1b), tab->MText1b); - tab->MText2 = gtk_label_new("s"); - gtk_widget_show(tab->MText2); - tab->MText3a = gtk_label_new("ns"); - gtk_widget_show(tab->MText3a); - - tab->MEventBox3b = gtk_event_box_new(); - gtk_widget_show(tab->MEventBox3b); - gtk_tooltips_set_tip(tab->tooltips, tab->MEventBox3b, - "Paste End Time Here", ""); - tab->MText3b = gtk_label_new("end:"); - gtk_widget_show(tab->MText3b); - gtk_container_add(GTK_CONTAINER(tab->MEventBox3b), tab->MText3b); - tab->MText4 = gtk_label_new("s"); - gtk_widget_show(tab->MText4); - tab->MText5a = gtk_label_new("ns"); - gtk_widget_show(tab->MText5a); - - tab->MEventBox8 = gtk_event_box_new(); - gtk_widget_show(tab->MEventBox8); - gtk_tooltips_set_tip(tab->tooltips, tab->MEventBox8, - "Paste Time Interval here", ""); - tab->MText8 = gtk_label_new("Time Interval:"); - gtk_widget_show(tab->MText8); - gtk_container_add(GTK_CONTAINER(tab->MEventBox8), tab->MText8); - tab->MText9 = gtk_label_new("s"); - gtk_widget_show(tab->MText9); - tab->MText10 = gtk_label_new("ns"); - gtk_widget_show(tab->MText10); - - tab->MEventBox5b = gtk_event_box_new(); - gtk_widget_show(tab->MEventBox5b); - gtk_tooltips_set_tip(tab->tooltips, tab->MEventBox5b, - "Paste Current Time Here", ""); - tab->MText5b = gtk_label_new("Current Time:"); - gtk_widget_show(tab->MText5b); - gtk_container_add(GTK_CONTAINER(tab->MEventBox5b), tab->MText5b); - tab->MText6 = gtk_label_new("s"); - gtk_widget_show(tab->MText6); - tab->MText7 = gtk_label_new("ns"); - gtk_widget_show(tab->MText7); - - tab->MEntry1 = gtk_spin_button_new_with_range(0.0, 1.0, 1.0); - gtk_spin_button_set_digits(GTK_SPIN_BUTTON(tab->MEntry1),0); - gtk_spin_button_set_snap_to_ticks(GTK_SPIN_BUTTON(tab->MEntry1),TRUE); - gtk_widget_show(tab->MEntry1); - tab->MEntry2 = gtk_spin_button_new_with_range(0.0, 1.0, 1.0); - gtk_spin_button_set_digits(GTK_SPIN_BUTTON(tab->MEntry2),0); - gtk_spin_button_set_snap_to_ticks(GTK_SPIN_BUTTON(tab->MEntry2),TRUE); - gtk_widget_show(tab->MEntry2); - tab->MEntry3 = gtk_spin_button_new_with_range(0.0, 1.0, 1.0); - gtk_spin_button_set_digits(GTK_SPIN_BUTTON(tab->MEntry3),0); - gtk_spin_button_set_snap_to_ticks(GTK_SPIN_BUTTON(tab->MEntry3),TRUE); - gtk_widget_show(tab->MEntry3); - tab->MEntry4 = gtk_spin_button_new_with_range(0.0, 1.0, 1.0); - gtk_spin_button_set_digits(GTK_SPIN_BUTTON(tab->MEntry4),0); - gtk_spin_button_set_snap_to_ticks(GTK_SPIN_BUTTON(tab->MEntry4),TRUE); - gtk_widget_show(tab->MEntry4); - tab->MEntry5 = gtk_spin_button_new_with_range(0.0, 1.0, 1.0); - gtk_spin_button_set_digits(GTK_SPIN_BUTTON(tab->MEntry5),0); - gtk_spin_button_set_snap_to_ticks(GTK_SPIN_BUTTON(tab->MEntry5),TRUE); - gtk_widget_show(tab->MEntry5); - tab->MEntry6 = gtk_spin_button_new_with_range(0.0, 1.0, 1.0); - gtk_spin_button_set_digits(GTK_SPIN_BUTTON(tab->MEntry6),0); - gtk_spin_button_set_snap_to_ticks(GTK_SPIN_BUTTON(tab->MEntry6),TRUE); - gtk_widget_show(tab->MEntry6); - tab->MEntry7 = gtk_spin_button_new_with_range(0.0, 1.0, 1.0); - gtk_spin_button_set_digits(GTK_SPIN_BUTTON(tab->MEntry7),0); - gtk_spin_button_set_snap_to_ticks(GTK_SPIN_BUTTON(tab->MEntry7),TRUE); - gtk_widget_show(tab->MEntry7); - tab->MEntry8 = gtk_spin_button_new_with_range(0.0, 1.0, 1.0); - gtk_spin_button_set_digits(GTK_SPIN_BUTTON(tab->MEntry8),0); - gtk_spin_button_set_snap_to_ticks(GTK_SPIN_BUTTON(tab->MEntry8),TRUE); - gtk_widget_show(tab->MEntry8); - - GtkWidget *temp_widget; - - gtk_box_pack_start (GTK_BOX (tab->MTimebar), tab->MEventBox1a, FALSE, - FALSE, 0); - gtk_box_pack_start (GTK_BOX (tab->MTimebar), tab->MEventBox1b, FALSE, - FALSE, 0); - gtk_box_pack_start (GTK_BOX (tab->MTimebar), tab->MEntry1, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (tab->MTimebar), tab->MText2, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (tab->MTimebar), tab->MEntry2, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (tab->MTimebar), tab->MText3a, FALSE, FALSE, 0); - temp_widget = gtk_vseparator_new(); - gtk_widget_show(temp_widget); - gtk_box_pack_start (GTK_BOX (tab->MTimebar), temp_widget, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (tab->MTimebar), tab->MEventBox3b, FALSE, - FALSE, 0); - gtk_box_pack_start (GTK_BOX (tab->MTimebar), tab->MEntry3, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (tab->MTimebar), tab->MText4, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (tab->MTimebar), tab->MEntry4, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (tab->MTimebar), tab->MText5a, FALSE, FALSE, 0); - temp_widget = gtk_vseparator_new(); - gtk_widget_show(temp_widget); - gtk_box_pack_start (GTK_BOX (tab->MTimebar), temp_widget, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (tab->MTimebar), tab->MEventBox8, FALSE, - FALSE, 0); - gtk_box_pack_start (GTK_BOX (tab->MTimebar), tab->MEntry7, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (tab->MTimebar), tab->MText9, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (tab->MTimebar), tab->MEntry8, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (tab->MTimebar), tab->MText10, FALSE, FALSE, 0); - - temp_widget = gtk_vseparator_new(); - gtk_widget_show(temp_widget); - gtk_box_pack_end (GTK_BOX (tab->MTimebar), tab->MText7, FALSE, FALSE, 0); - gtk_box_pack_end (GTK_BOX (tab->MTimebar), tab->MEntry6, FALSE, FALSE, 0); - gtk_box_pack_end (GTK_BOX (tab->MTimebar), tab->MText6, FALSE, FALSE, 0); - gtk_box_pack_end (GTK_BOX (tab->MTimebar), tab->MEntry5, FALSE, FALSE, 0); - gtk_box_pack_end (GTK_BOX (tab->MTimebar), tab->MEventBox5b, FALSE, - FALSE, 0); - gtk_box_pack_end (GTK_BOX (tab->MTimebar), temp_widget, FALSE, FALSE, 0); - - - //GtkWidget *test = gtk_button_new_with_label("drop"); - //gtk_button_set_relief(GTK_BUTTON(test), GTK_RELIEF_NONE); - //gtk_widget_show(test); - //gtk_box_pack_end(GTK_BOX (tab->MTimebar), test, FALSE, FALSE, 0); - //gtk_widget_add_events(tab->MText1, GDK_ALL_EVENTS_MASK);//GDK_BUTTON_PRESS_MASK); - /*GtkWidget *event_box = gtk_event_box_new(); - gtk_widget_show(event_box); - gtk_tooltips_set_tip(tooltips, event_box, - "Paste Current Time Here", ""); - gtk_box_pack_end(GTK_BOX (tab->MTimebar), event_box, FALSE, FALSE, 0); - GtkWidget *test = gtk_label_new("drop"); - gtk_container_add(GTK_CONTAINER(event_box), test); - gtk_widget_show(test); - g_signal_connect (G_OBJECT(event_box), - "button-press-event", - G_CALLBACK (on_MText1_paste), - (gpointer)tab); -*/ - - g_signal_connect (G_OBJECT(tab->MEventBox1a), - "button-press-event", - G_CALLBACK (on_MEventBox1a_paste), - (gpointer)tab); - - g_signal_connect (G_OBJECT(tab->MEventBox1b), - "button-press-event", - G_CALLBACK (on_MEventBox1b_paste), - (gpointer)tab); - g_signal_connect (G_OBJECT(tab->MEventBox3b), - "button-press-event", - G_CALLBACK (on_MEventBox3b_paste), - (gpointer)tab); - g_signal_connect (G_OBJECT(tab->MEventBox5b), - "button-press-event", - G_CALLBACK (on_MEventBox5b_paste), - (gpointer)tab); - g_signal_connect (G_OBJECT(tab->MEventBox8), - "button-press-event", - G_CALLBACK (on_MEventBox8_paste), - (gpointer)tab); - } + + tab->MTimebar = timebar_new(); gtk_box_pack_end(GTK_BOX(tab->vbox), tab->scrollbar, @@ -4841,8 +4016,10 @@ void init_tab(Tab *tab, MainWindow * mw, Tab *copy_tab, gtk_widget_show(tab->label); gtk_widget_show(tab->scrollbar); + gtk_widget_show(tab->MTimebar); gtk_widget_show(tab->viewer_container); gtk_widget_show(tab->vbox); + //gtk_widget_show(tab->multivpaned); @@ -4856,30 +4033,14 @@ void init_tab(Tab *tab, MainWindow * mw, Tab *copy_tab, g_signal_connect(G_OBJECT(tab->scrollbar), "value-changed", G_CALLBACK(scroll_value_changed_cb), tab); - g_signal_connect ((gpointer) tab->MEntry1, "value-changed", - G_CALLBACK (on_MEntry1_value_changed), - tab); - g_signal_connect ((gpointer) tab->MEntry2, "value-changed", - G_CALLBACK (on_MEntry2_value_changed), - tab); - g_signal_connect ((gpointer) tab->MEntry3, "value-changed", - G_CALLBACK (on_MEntry3_value_changed), - tab); - g_signal_connect ((gpointer) tab->MEntry4, "value-changed", - G_CALLBACK (on_MEntry4_value_changed), - tab); - g_signal_connect ((gpointer) tab->MEntry5, "value-changed", - G_CALLBACK (on_MEntry5_value_changed), - tab); - g_signal_connect ((gpointer) tab->MEntry6, "value-changed", - G_CALLBACK (on_MEntry6_value_changed), - tab); - g_signal_connect ((gpointer) tab->MEntry7, "value-changed", - G_CALLBACK (on_MEntry7_value_changed), - tab); - g_signal_connect ((gpointer) tab->MEntry8, "value-changed", - G_CALLBACK (on_MEntry8_value_changed), - tab); + + /* Timebar signal handler */ + g_signal_connect(G_OBJECT(tab->MTimebar), "start-time-changed", + G_CALLBACK(on_timebar_starttime_changed), tab); + g_signal_connect(G_OBJECT(tab->MTimebar), "end-time-changed", + G_CALLBACK(on_timebar_endtime_changed), tab); + g_signal_connect(G_OBJECT(tab->MTimebar), "current-time-changed", + G_CALLBACK(on_timebar_currenttime_changed), tab); //g_signal_connect(G_OBJECT(tab->scrollbar), "changed", // G_CALLBACK(scroll_value_changed_cb), tab); diff --git a/lttv/modules/gui/lttvwindow/lttvwindow/mainwindow-private.h b/lttv/modules/gui/lttvwindow/lttvwindow/mainwindow-private.h index 5bd9705e..5311fa15 100644 --- a/lttv/modules/gui/lttvwindow/lttvwindow/mainwindow-private.h +++ b/lttv/modules/gui/lttvwindow/lttvwindow/mainwindow-private.h @@ -75,37 +75,9 @@ struct _Tab{ GtkWidget *viewer_container; GtkWidget *scrollbar; - /* Paste zones */ - GtkTooltips *tooltips; - /* time bar */ GtkWidget *MTimebar; - GtkWidget *MEventBox1a; - GtkWidget *MText1a; - GtkWidget *MEventBox1b; - GtkWidget *MText1b; - GtkWidget *MEntry1; - GtkWidget *MText2; - GtkWidget *MEntry2; - GtkWidget *MText3a; - GtkWidget *MEventBox3b; - GtkWidget *MText3b; - GtkWidget *MEntry3; - GtkWidget *MText4; - GtkWidget *MEntry4; - GtkWidget *MText5a; - GtkWidget *MEventBox5b; - GtkWidget *MText5b; - GtkWidget *MEntry5; - GtkWidget *MText6; - GtkWidget *MEntry6; - GtkWidget *MText7; - GtkWidget *MEventBox8; - GtkWidget *MText8; - GtkWidget *MEntry7; - GtkWidget *MText9; - GtkWidget *MEntry8; - GtkWidget *MText10; + // startTime is the left of the visible area. Corresponds to the scrollbar // value. diff --git a/lttv/modules/gui/lttvwindow/lttvwindow/timebar.c b/lttv/modules/gui/lttvwindow/lttvwindow/timebar.c new file mode 100644 index 00000000..9673ec66 --- /dev/null +++ b/lttv/modules/gui/lttvwindow/lttvwindow/timebar.c @@ -0,0 +1,424 @@ +/* This file is part of the Linux Trace Toolkit viewer + * Copyright (C) 2010 Yannick Brosseau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License Version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ +#include "timebar.h" + +#include "timeentry.h" + +#include +#include +#include + +enum { + SIGNAL_START_TIME_CHANGED, + SIGNAL_END_TIME_CHANGED, + SIGNAL_CURRENT_TIME_CHANGED, + LAST_SIGNAL +}; + +static void timebar_class_init(TimebarClass *klass); +static void timebar_init(Timebar *ttt); + +static guint timebar_signals[LAST_SIGNAL] = { 0 }; + +static void on_start_time_value_changed(Timeentry *spinbutton, + gpointer user_data); +static void on_end_time_value_changed(Timeentry *spinbutton, + gpointer user_data); +static void on_interval_time_value_changed(Timeentry *spinbutton, + gpointer user_data); +static void on_current_time_value_changed(Timeentry *spinbutton, + gpointer user_data); + +static void update_interval(Timebar *timebar); + +static inline LttTime timeentry_get_ltt_time(Timeentry *timeentry) +{ + LttTime time; + + timeentry_get_time(timeentry, + &time.tv_sec, + &time.tv_nsec); + return time; +} + +GType timebar_get_type(void) +{ + static GType tb_type = 0; + + if (!tb_type) { + const GTypeInfo tb_info = + { + sizeof (TimebarClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) timebar_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (Timebar), + 0, /* n_preallocs */ + (GInstanceInitFunc) timebar_init, + }; + + tb_type = g_type_register_static(GTK_TYPE_HBOX, + "Timebar", + &tb_info, + 0); + } + + return tb_type; +} + + +static void timebar_class_init(TimebarClass *klass) +{ + timebar_signals[SIGNAL_START_TIME_CHANGED] = g_signal_new("start-time-changed", + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET(TimebarClass, timebar), + NULL, + NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + timebar_signals[SIGNAL_END_TIME_CHANGED] = g_signal_new("end-time-changed", + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET(TimebarClass, timebar), + NULL, + NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + timebar_signals[SIGNAL_CURRENT_TIME_CHANGED] = g_signal_new("current-time-changed", + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET(TimebarClass, timebar), + NULL, + NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} + + +static void timebar_init(Timebar *timebar) +{ + /* Title label */ + timebar->title_eventbox = gtk_event_box_new(); + gtk_widget_show(timebar->title_eventbox); + + timebar->title_label = gtk_label_new("Time Frame "); + gtk_widget_show(timebar->title_label); + gtk_container_add(GTK_CONTAINER(timebar->title_eventbox), timebar->title_label); + + /* Start time entry */ + timebar->start_timeentry = timeentry_new("Start: "); + gtk_widget_show(timebar->start_timeentry); + + /* End time entry */ + timebar->end_timeentry = timeentry_new("End: "); + gtk_widget_show(timebar->end_timeentry); + + /* Interval time entry */ + timebar->interval_timeentry = timeentry_new("Time Interval: "); + gtk_widget_show(timebar->interval_timeentry); + + /* Current time entry */ + timebar->current_timeentry = timeentry_new("Current Time: "); + gtk_widget_show(timebar->current_timeentry); + + /* Pack all the widget in the timebar box */ + GtkWidget *temp_widget; + + gtk_box_pack_start (GTK_BOX(timebar), timebar->title_eventbox, FALSE, FALSE, 2); + + gtk_box_pack_start (GTK_BOX(timebar), timebar->start_timeentry, FALSE, FALSE, 0); + + temp_widget = gtk_vseparator_new(); + gtk_widget_show(temp_widget); + gtk_box_pack_start (GTK_BOX(timebar), temp_widget, FALSE, FALSE, 2); + + gtk_box_pack_start (GTK_BOX(timebar), timebar->end_timeentry, FALSE, FALSE, 0); + + temp_widget = gtk_vseparator_new(); + gtk_widget_show(temp_widget); + gtk_box_pack_start (GTK_BOX(timebar), temp_widget, FALSE, FALSE, 2); + + gtk_box_pack_start (GTK_BOX(timebar), timebar->interval_timeentry, FALSE, FALSE, 0); + + gtk_box_pack_end (GTK_BOX(timebar), timebar->current_timeentry, FALSE, FALSE, 0); + temp_widget = gtk_vseparator_new(); + gtk_widget_show(temp_widget); + gtk_box_pack_end (GTK_BOX(timebar), temp_widget, FALSE, FALSE, 2); + + /* Set an initial time */ + timebar_set_minmax_time(timebar, <t_time_zero, <t_time_one); + + /* Connect signals */ + g_signal_connect ((gpointer) timebar->start_timeentry, "time-changed", + G_CALLBACK(on_start_time_value_changed), + timebar); + g_signal_connect ((gpointer) timebar->end_timeentry, "time-changed", + G_CALLBACK(on_end_time_value_changed), + timebar); + timebar->interval_handler_id = + g_signal_connect ((gpointer) timebar->interval_timeentry, "time-changed", + G_CALLBACK (on_interval_time_value_changed), + timebar); + g_signal_connect ((gpointer) timebar->current_timeentry, "time-changed", + G_CALLBACK(on_current_time_value_changed), + timebar); +} + +GtkWidget *timebar_new(void) +{ + return GTK_WIDGET(g_object_new (TIMEBAR_TYPE, NULL)); +} + +void timebar_set_current_time(Timebar *timebar, const LttTime* time) +{ + if (time == NULL) { + return; + } + + timeentry_set_time(TIMEENTRY(timebar->current_timeentry), + time->tv_sec, + time->tv_nsec); +} + +void timebar_set_start_time(Timebar *timebar, const LttTime* time) +{ + if (time == NULL) { + return; + } + + timeentry_set_time(TIMEENTRY(timebar->start_timeentry), + time->tv_sec, + time->tv_nsec); + + update_interval(timebar); +} + +void timebar_set_end_time(Timebar *timebar, const LttTime* time) +{ + if (time == NULL) { + return; + } + + timeentry_set_time(TIMEENTRY(timebar->end_timeentry), + time->tv_sec, + time->tv_nsec); + update_interval(timebar); +} + +void timebar_set_minmax_time(Timebar *timebar, + const LttTime *min_time, + const LttTime *max_time) +{ + LttTime new_interval_length; + LttTime start_max_time; + LttTime end_min_time; + + /* Need to set both min_time and max_time */ + if (min_time == NULL || max_time == NULL) { + return; + } + /* Do nothing if there is no change */ + if (ltt_time_compare(timebar->min_time, *min_time) == 0 && + ltt_time_compare(timebar->max_time, *max_time) == 0 + ) { + return; + } + + if (min_time != NULL) { + timebar->min_time = *min_time; + } + + if (max_time != NULL) { + timebar->max_time = *max_time; + } + + + if (ltt_time_compare(timebar->min_time, timebar->max_time) == 0) { + + /* If the min and max are equal set the same values, which will + disable all the widgets of the timebar */ + new_interval_length.tv_sec = 0; + new_interval_length.tv_nsec = 1; + + start_max_time.tv_sec = timebar->max_time.tv_sec; + start_max_time.tv_nsec = timebar->max_time.tv_nsec; + + end_min_time.tv_sec = timebar->min_time.tv_sec; + end_min_time.tv_nsec = timebar->min_time.tv_nsec; + + } else { + /* Special minmax (to keep a minimum interval of 1 nsec */ + /* start max time is max minus 1 nsec */ + if (timebar->max_time.tv_nsec == 0) { + start_max_time.tv_sec = timebar->max_time.tv_sec - 1; + start_max_time.tv_nsec = NANOSECONDS_PER_SECOND - 1; + } else { + start_max_time.tv_sec = timebar->max_time.tv_sec; + start_max_time.tv_nsec = timebar->max_time.tv_nsec - 1; + } + + /* end min time is min plus 1 nsec */ + if (timebar->min_time.tv_nsec + 1 == NANOSECONDS_PER_SECOND) { + end_min_time.tv_sec = timebar->min_time.tv_sec + 1; + end_min_time.tv_nsec = 0; + } else { + end_min_time.tv_sec = timebar->min_time.tv_sec; + end_min_time.tv_nsec = timebar->min_time.tv_nsec + 1; + } + + /* Compute max interval */ + new_interval_length = ltt_time_sub(timebar->max_time, + timebar->min_time); + } + + + /* Update widgets */ + timeentry_set_minmax_time(TIMEENTRY(timebar->start_timeentry), + timebar->min_time.tv_sec, + timebar->min_time.tv_nsec, + start_max_time.tv_sec, + start_max_time.tv_nsec); + timeentry_set_minmax_time(TIMEENTRY(timebar->end_timeentry), + end_min_time.tv_sec, + end_min_time.tv_nsec, + timebar->max_time.tv_sec, + timebar->max_time.tv_nsec); + timeentry_set_minmax_time(TIMEENTRY(timebar->current_timeentry), + timebar->min_time.tv_sec, + timebar->min_time.tv_nsec, + timebar->max_time.tv_sec, + timebar->max_time.tv_nsec); + + + timeentry_set_minmax_time(TIMEENTRY(timebar->interval_timeentry), + 0, + 1, + new_interval_length.tv_sec, + new_interval_length.tv_nsec); +} + +LttTime timebar_get_start_time(Timebar *timebar) +{ + return timeentry_get_ltt_time(TIMEENTRY(timebar->start_timeentry)); +} + +LttTime timebar_get_end_time(Timebar *timebar) +{ + return timeentry_get_ltt_time(TIMEENTRY(timebar->end_timeentry)); +} + +LttTime timebar_get_current_time(Timebar *timebar) +{ + return timeentry_get_ltt_time(TIMEENTRY(timebar->current_timeentry)); +} + +static void update_interval(Timebar *timebar) +{ + LttTime start_time = timeentry_get_ltt_time(TIMEENTRY(timebar->start_timeentry)); + LttTime end_time = timeentry_get_ltt_time(TIMEENTRY(timebar->end_timeentry)); + LttTime new_interval; + + /* Compute max interval */ + new_interval = ltt_time_sub(end_time, + start_time); + + /* Don't trigger the signal when we update the interval */ + g_signal_handler_block(timebar->interval_timeentry, + timebar->interval_handler_id); + + timeentry_set_time(TIMEENTRY(timebar->interval_timeentry), + new_interval.tv_sec, + new_interval.tv_nsec); + + g_signal_handler_unblock(timebar->interval_timeentry, + timebar->interval_handler_id); +} + +static void on_start_time_value_changed(Timeentry *timeentry, + gpointer user_data) +{ + Timebar *timebar = (Timebar *)user_data; + + update_interval(timebar); + + g_signal_emit(timebar, + timebar_signals[SIGNAL_START_TIME_CHANGED], 0); +} + +static void on_end_time_value_changed(Timeentry *timeentry, + gpointer user_data) +{ + Timebar *timebar = (Timebar *)user_data; + + update_interval(timebar); + + g_signal_emit(timebar, + timebar_signals[SIGNAL_END_TIME_CHANGED], 0); +} + +static void on_interval_time_value_changed (Timeentry *timeentry, + gpointer user_data) +{ + Timebar *timebar = (Timebar *)user_data; + + LttTime new_interval = timeentry_get_ltt_time(TIMEENTRY(timebar->interval_timeentry)); + + LttTime start_time = timebar_get_start_time(timebar); + + LttTime new_end_time; + + gboolean need_interval_update = FALSE; + + /* Lock the start and change the end */ + new_end_time = ltt_time_add(start_time, new_interval); + + /* We cannot push further the max end */ + if (ltt_time_compare(new_end_time, timebar->max_time) > 0) { + /* Set the end to the max and pull on the start */ + new_end_time = timebar->max_time; + LttTime new_start_time = ltt_time_sub(new_end_time, new_interval); + + /* We cannot pull before the min start */ + if (ltt_time_compare(new_start_time, timebar->min_time) < 0) { + /* Set the interval to the max */ + new_start_time = timebar->min_time; + need_interval_update = TRUE; + } + timebar_set_start_time(timebar, &new_start_time); + } + timebar_set_end_time(timebar, &new_end_time); + + if (need_interval_update) { + update_interval(timebar); + } +} + +static void on_current_time_value_changed(Timeentry *timeentry, + gpointer user_data) +{ + Timebar *timebar = (Timebar *)user_data; + + g_signal_emit(timebar, + timebar_signals[SIGNAL_CURRENT_TIME_CHANGED], 0); +} + + diff --git a/lttv/modules/gui/lttvwindow/lttvwindow/timebar.h b/lttv/modules/gui/lttvwindow/lttvwindow/timebar.h new file mode 100644 index 00000000..a5954168 --- /dev/null +++ b/lttv/modules/gui/lttvwindow/lttvwindow/timebar.h @@ -0,0 +1,78 @@ +/* This file is part of the Linux Trace Toolkit viewer + * Copyright (C) 2010 Yannick Brosseau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License Version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ +#ifndef _TIMEBAR_ +#define _TIMEBAR_ + +#include +#include +#include +#include +#include + +G_BEGIN_DECLS + +#define TIMEBAR_TYPE (timebar_get_type ()) +#define TIMEBAR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TIMEBAR_TYPE, Timebar)) +#define TIMEBAR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TIMEBAR_TYPE, TimebarClass)) +#define IS_TIMEBAR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TIMEBAR_TYPE)) +#define IS_TIMEBAR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TIMEBAR_TYPE)) + +typedef struct _Timebar Timebar; +typedef struct _TimebarClass TimebarClass; + +struct _Timebar { + GtkHBox parent_hbox; + + GtkWidget *title_label; + GtkWidget *title_eventbox; + GtkWidget *start_timeentry; + GtkWidget *end_timeentry; + GtkWidget *interval_timeentry; + GtkWidget *current_timeentry; + + int interval_handler_id; + + /* Time management */ + LttTime min_time; + LttTime max_time; +}; + +struct _TimebarClass { + GtkHBoxClass parent_class; + + void (*timebar) (Timebar *timebar); +}; + + +GType timebar_get_type(void); +GtkWidget *timebar_new(void); + +void timebar_set_current_time(Timebar *timeebar, const LttTime *time); +void timebar_set_start_time(Timebar *timebar, const LttTime *time); +void timebar_set_end_time(Timebar *timebar, const LttTime *time); +void timebar_set_minmax_time(Timebar *timebar, + const LttTime *min_time, + const LttTime *max_time); + +LttTime timebar_get_current_time(Timebar *timeebar); +LttTime timebar_get_start_time(Timebar *timebar); +LttTime timebar_get_end_time(Timebar *timebar); + +G_END_DECLS + +#endif /* _TIMEBAR_ */ diff --git a/lttv/modules/gui/lttvwindow/lttvwindow/timeentry.c b/lttv/modules/gui/lttvwindow/lttvwindow/timeentry.c new file mode 100644 index 00000000..feaf2974 --- /dev/null +++ b/lttv/modules/gui/lttvwindow/lttvwindow/timeentry.c @@ -0,0 +1,456 @@ +/* This file is part of the Linux Trace Toolkit viewer + * Copyright (C) 2010 Yannick Brosseau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License Version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#include "timeentry.h" + +#include +#include +#include +#include + +enum { + SIGNAL_TIME_CHANGED, + LAST_SIGNAL +}; + +static void timeentry_class_init(TimeentryClass *klass); +static void timeentry_init(Timeentry *ttt); + +static guint timeentry_signals[LAST_SIGNAL] = { 0 }; +static unsigned int MAX_NANOSECONDS = 999999999; + +static void on_spinner_value_changed (GtkSpinButton *spinbutton, + gpointer user_data); + +static gboolean on_label_click(GtkWidget *widget, + GdkEventButton *event, + gpointer data); +static void on_menu_copy(gpointer data); +static void on_menu_paste(gpointer callback_data, + guint callback_action, + GtkWidget *widget); + +static void clipboard_receive(GtkClipboard *clipboard, + const gchar *text, + gpointer data); + +GType timeentry_get_type(void) +{ + static GType te_type = 0; + + if (!te_type) { + const GTypeInfo te_info = + { + sizeof (TimeentryClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) timeentry_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (Timeentry), + 0, /* n_preallocs */ + (GInstanceInitFunc) timeentry_init, + }; + + te_type = g_type_register_static (GTK_TYPE_HBOX, + "Timeentry", + &te_info, + 0); + } + + return te_type; +} + +static void timeentry_class_init(TimeentryClass *klass) +{ + timeentry_signals[SIGNAL_TIME_CHANGED] = g_signal_new ("time-changed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (TimeentryClass, timeentry), + NULL, + NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} + +static void timeentry_init(Timeentry *timeentry) +{ + + /* Set default minmax */ + timeentry->min_seconds = 0; + timeentry->min_nanoseconds = 0; + timeentry->max_seconds = 1; + timeentry->max_nanoseconds = 1; + + /* Add main label*/ + timeentry->main_label = gtk_label_new(NULL); + gtk_widget_show(timeentry->main_label); + + timeentry->main_label_box = gtk_event_box_new(); + gtk_widget_show(timeentry->main_label_box); + gtk_container_add(GTK_CONTAINER(timeentry->main_label_box), timeentry->main_label); + + gtk_widget_set_tooltip_text(timeentry->main_label_box, "Paste time here"); + + /* Add seconds spinner */ + timeentry->seconds_spinner = gtk_spin_button_new_with_range(timeentry->min_seconds, + timeentry->max_seconds, + 1.0); + gtk_spin_button_set_digits(GTK_SPIN_BUTTON(timeentry->seconds_spinner), 0); + gtk_spin_button_set_snap_to_ticks(GTK_SPIN_BUTTON(timeentry->seconds_spinner), TRUE); + gtk_widget_show(timeentry->seconds_spinner); + + /* Add nanoseconds spinner */ + /* TODO ybrosseau 2010-11-24: Add wrap management */ + timeentry->nanoseconds_spinner = gtk_spin_button_new_with_range(timeentry->min_nanoseconds, + timeentry->max_nanoseconds, + 1.0); + gtk_spin_button_set_digits(GTK_SPIN_BUTTON(timeentry->nanoseconds_spinner), 0); + gtk_spin_button_set_snap_to_ticks(GTK_SPIN_BUTTON(timeentry->nanoseconds_spinner), TRUE); + gtk_widget_show(timeentry->nanoseconds_spinner); + + /* s and ns labels */ + timeentry->s_label = gtk_label_new("s "); + gtk_widget_show(timeentry->s_label); + timeentry->ns_label = gtk_label_new("ns "); + gtk_widget_show(timeentry->ns_label); + + /* Pack everything */ + gtk_box_pack_start (GTK_BOX (timeentry), timeentry->main_label_box, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (timeentry), timeentry->seconds_spinner, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (timeentry), timeentry->s_label, FALSE, FALSE, 1); + gtk_box_pack_start (GTK_BOX (timeentry), timeentry->nanoseconds_spinner, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (timeentry), timeentry->ns_label, FALSE, FALSE, 1); + + timeentry->seconds_changed_handler_id = + g_signal_connect ((gpointer) timeentry->seconds_spinner, "value-changed", + G_CALLBACK (on_spinner_value_changed), + timeentry); + + timeentry->nanoseconds_changed_handler_id = + g_signal_connect ((gpointer) timeentry->nanoseconds_spinner, "value-changed", + G_CALLBACK (on_spinner_value_changed), + timeentry); + + /* Add pasting callbacks */ + g_signal_connect ((gpointer) timeentry->main_label_box, "button-press-event", + G_CALLBACK (on_label_click), + timeentry); + + /* Create pasting context-menu */ + GtkItemFactory *item_factory; + /* Our menu, an array of GtkItemFactoryEntry structures that defines each menu item */ + GtkItemFactoryEntry menu_items[] = { + { "/Copy time", NULL, on_menu_copy, 0, "" }, + { "/Paste time", NULL, on_menu_paste, 0, "" }, + }; + + gint nmenu_items = sizeof (menu_items) / sizeof (menu_items[0]); + + item_factory = gtk_item_factory_new (GTK_TYPE_MENU, "", + NULL); + gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, timeentry); + timeentry->main_label_context_menu = gtk_item_factory_get_widget (item_factory, ""); +} + +void timeentry_set_main_label (Timeentry *timeentry, + const gchar *str) +{ + g_return_if_fail (IS_TIMEENTRY (timeentry)); + + g_object_freeze_notify (G_OBJECT (timeentry)); + + gtk_label_set_label(GTK_LABEL(timeentry->main_label), str); + + g_object_thaw_notify (G_OBJECT (timeentry)); +} + +static void timeentry_update_nanoseconds_spinner_range(Timeentry *timeentry, + unsigned long current_seconds) +{ + if (current_seconds > timeentry->min_seconds && current_seconds < timeentry->max_seconds) { + /* We are not at a limit, set the spinner to full range */ + gtk_spin_button_set_range(GTK_SPIN_BUTTON(timeentry->nanoseconds_spinner), + 0, + MAX_NANOSECONDS); + } else if (timeentry->min_seconds == timeentry->max_seconds) { + /* special case were the time span is less than a second */ + gtk_spin_button_set_range(GTK_SPIN_BUTTON(timeentry->nanoseconds_spinner), + timeentry->min_nanoseconds, + timeentry->max_nanoseconds); + + } else if (current_seconds <= timeentry->min_seconds) { + /* We are a the start limit */ + gtk_spin_button_set_range(GTK_SPIN_BUTTON(timeentry->nanoseconds_spinner), + timeentry->min_nanoseconds, + MAX_NANOSECONDS); + } else if (current_seconds >= timeentry->max_seconds) { + /* We are a the stop limit */ + gtk_spin_button_set_range(GTK_SPIN_BUTTON(timeentry->nanoseconds_spinner), + 0, + timeentry->max_nanoseconds); + } else { + /* Should never happen */ + g_assert(FALSE); + } +} + +void timeentry_set_minmax_time(Timeentry *timeentry, + unsigned long min_seconds, + unsigned long min_nanoseconds, + unsigned long max_seconds, + unsigned long max_nanoseconds) +{ + unsigned long current_seconds; + unsigned long current_nanoseconds; + + timeentry_get_time(timeentry, ¤t_seconds, ¤t_nanoseconds); + + if (min_seconds > max_seconds || + (min_seconds == max_seconds && min_nanoseconds > max_nanoseconds)) { + return; + } + + timeentry->min_seconds = min_seconds; + timeentry->min_nanoseconds = min_nanoseconds; + timeentry->max_seconds = max_seconds; + timeentry->max_nanoseconds = max_nanoseconds; + + /* Disable the widgets if there is no range possible */ + if (min_seconds == max_seconds && + min_nanoseconds == max_nanoseconds) { + gtk_widget_set_sensitive(timeentry->seconds_spinner, FALSE); + gtk_widget_set_sensitive(timeentry->nanoseconds_spinner, FALSE); + + } else { + gtk_widget_set_sensitive(timeentry->seconds_spinner, TRUE); + gtk_widget_set_sensitive(timeentry->nanoseconds_spinner, TRUE); + } + + /* Set the new time range */ + gtk_spin_button_set_range(GTK_SPIN_BUTTON(timeentry->seconds_spinner), + timeentry->min_seconds, + timeentry->max_seconds); + + timeentry_update_nanoseconds_spinner_range(timeentry, + current_seconds); + + /* Update time if necessary */ + timeentry_set_time(timeentry, current_seconds, current_nanoseconds); +} + +void timeentry_set_time(Timeentry *timeentry, + unsigned long seconds, + unsigned long nanoseconds) +{ + /* Set the passed time in the valid range */ + if (seconds < timeentry->min_seconds) { + seconds = timeentry->min_seconds; + nanoseconds = timeentry->min_nanoseconds; + + } + if (seconds == timeentry->min_seconds && + nanoseconds < timeentry->min_nanoseconds) { + nanoseconds = timeentry->min_nanoseconds; + } + if (seconds > timeentry->max_seconds) { + seconds = timeentry->max_seconds; + nanoseconds = timeentry->max_nanoseconds; + } + if (seconds == timeentry->max_seconds && + nanoseconds > timeentry->max_nanoseconds) { + nanoseconds = timeentry->max_nanoseconds; + } + + if ((gtk_spin_button_get_value (GTK_SPIN_BUTTON(timeentry->seconds_spinner)) == seconds) && + (gtk_spin_button_get_value (GTK_SPIN_BUTTON(timeentry->nanoseconds_spinner)) == nanoseconds)) { + /* No update needed, don't update the spinners */ + return; + } + + /* Block the spinner changed signal when we set the time to them */ + g_signal_handler_block(timeentry->seconds_spinner, + timeentry->seconds_changed_handler_id); + g_signal_handler_block(timeentry->nanoseconds_spinner, + timeentry->nanoseconds_changed_handler_id); + + gtk_spin_button_set_value(GTK_SPIN_BUTTON(timeentry->seconds_spinner), seconds); + timeentry_update_nanoseconds_spinner_range(timeentry, seconds); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(timeentry->nanoseconds_spinner), nanoseconds); + + g_signal_handler_unblock(timeentry->nanoseconds_spinner, + timeentry->nanoseconds_changed_handler_id); + g_signal_handler_unblock(timeentry->seconds_spinner, + timeentry->seconds_changed_handler_id); + + /* Send the time changed signal */ + g_signal_emit(timeentry, + timeentry_signals[SIGNAL_TIME_CHANGED], 0); +} + +void timeentry_get_time (Timeentry *timeentry, + unsigned long *seconds, + unsigned long *nanoseconds) +{ + *seconds = gtk_spin_button_get_value (GTK_SPIN_BUTTON(timeentry->seconds_spinner)); + *nanoseconds = gtk_spin_button_get_value (GTK_SPIN_BUTTON(timeentry->nanoseconds_spinner)); +} + +static void +on_spinner_value_changed (GtkSpinButton *spinbutton, + gpointer user_data) +{ + Timeentry *timeentry = (Timeentry *)user_data; + unsigned long current_seconds; + + /* Manage min/max values of the nanoseconds spinner */ + current_seconds = gtk_spin_button_get_value (GTK_SPIN_BUTTON(timeentry->seconds_spinner)); + timeentry_update_nanoseconds_spinner_range(timeentry, + current_seconds); + + g_signal_emit(timeentry, + timeentry_signals[SIGNAL_TIME_CHANGED], 0); +} + +static gboolean on_label_click(GtkWidget *widget, + GdkEventButton *event, + gpointer data) +{ + Timeentry *timeentry = (Timeentry *)data; + + /* Only take button presses */ + if (event->type != GDK_BUTTON_PRESS) + return FALSE; + + + if (event->button == 3) { + /* Right button click - popup menu */ + + /* Show the menu */ + gtk_menu_popup (GTK_MENU(timeentry->main_label_context_menu), NULL, NULL, + NULL, NULL, event->button, event->time); + + return TRUE; + + } else if (event->button == 2) { + /* Middle button click - paste PRIMARY */ + + GtkClipboard *clip = gtk_clipboard_get_for_display(gdk_display_get_default(), + GDK_SELECTION_PRIMARY); + gtk_clipboard_request_text(clip, + (GtkClipboardTextReceivedFunc)clipboard_receive, + (gpointer)timeentry); + } + + return 0; +} + +static void on_menu_copy(gpointer callback_data) +{ + Timeentry *timeentry = (Timeentry *)callback_data; + const int CLIP_BUFFER_SIZE = 100; + gchar buffer[CLIP_BUFFER_SIZE]; + + unsigned long seconds, nseconds; + timeentry_get_time(timeentry, &seconds, &nseconds); + snprintf(buffer, CLIP_BUFFER_SIZE, "%lu.%lu", seconds, nseconds); + + /* Set the CLIPBOARD */ + GtkClipboard *clip = gtk_clipboard_get_for_display(gdk_display_get_default(), + GDK_SELECTION_CLIPBOARD); + + gtk_clipboard_set_text(clip, buffer, -1); + + /* Set it also in the PRIMARY buffer (for middle click) */ + clip = gtk_clipboard_get_for_display(gdk_display_get_default(), + GDK_SELECTION_PRIMARY); + gtk_clipboard_set_text(clip, buffer, -1); +} + +static void on_menu_paste(gpointer callback_data, + guint callback_action, + GtkWidget *widget) +{ + Timeentry *timeentry = (Timeentry *)callback_data; + + GtkClipboard *clip = gtk_clipboard_get_for_display(gdk_display_get_default(), + GDK_SELECTION_CLIPBOARD); + gtk_clipboard_request_text(clip, + (GtkClipboardTextReceivedFunc)clipboard_receive, + (gpointer)timeentry); +} + +static void clipboard_receive(GtkClipboard *clipboard, + const gchar *text, + gpointer data) +{ + const int CLIP_BUFFER_SIZE = 100; + if (text == NULL) { + return; + } + Timeentry *timeentry = (Timeentry *)data; + gchar buffer[CLIP_BUFFER_SIZE]; + gchar *ptr = buffer, *ptr_sec, *ptr_nsec; + + strncpy(buffer, text, CLIP_BUFFER_SIZE); + g_debug("Timeentry clipboard receive: %s", buffer); + + while (!isdigit(*ptr) && ptr < buffer+CLIP_BUFFER_SIZE-1) { + ptr++; + } + /* remove leading junk */ + ptr_sec = ptr; + while (isdigit(*ptr) && ptr < buffer+CLIP_BUFFER_SIZE-1) { + ptr++; + } + /* read all the first number */ + *ptr = '\0'; + + if (ptr == ptr_sec) { + /* No digit in the input, exit */ + return; + } + ptr++; + + while (!isdigit(*ptr) && ptr < buffer+CLIP_BUFFER_SIZE-1) { + ptr++; + } + /* remove leading junk */ + ptr_nsec = ptr; + while (isdigit(*ptr) && ptr < buffer+CLIP_BUFFER_SIZE-1) { + ptr++; + } + /* read all the first number */ + *ptr = '\0'; + + timeentry_set_time(timeentry, + strtoul(ptr_sec, NULL, 10), + strtoul(ptr_nsec, NULL, 10)); +} + +GtkWidget* +timeentry_new (const gchar *label) +{ + + Timeentry *timeentry = g_object_new (TIMEENTRY_TYPE, NULL); + + if (label && *label) + timeentry_set_main_label (timeentry, label); + + return GTK_WIDGET(timeentry); +} diff --git a/lttv/modules/gui/lttvwindow/lttvwindow/timeentry.h b/lttv/modules/gui/lttvwindow/lttvwindow/timeentry.h new file mode 100644 index 00000000..580b20c1 --- /dev/null +++ b/lttv/modules/gui/lttvwindow/lttvwindow/timeentry.h @@ -0,0 +1,85 @@ + +/* This file is part of the Linux Trace Toolkit viewer + * Copyright (C) 2010 Yannick Brosseau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License Version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ +#ifndef _TIME_ENTRY_ +#define _TIME_ENTRY_ + + +#include +#include +#include +#include + +G_BEGIN_DECLS + +#define TIMEENTRY_TYPE (timeentry_get_type ()) +#define TIMEENTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TIMEENTRY_TYPE, Timeentry)) +#define TIMEENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TIMEENTRY_TYPE, TimeentryClass)) +#define IS_TIMEENTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TIMEENTRY_TYPE)) +#define IS_TIMEENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TIMEENTRY_TYPE)) + +typedef struct _Timeentry Timeentry; +typedef struct _TimeentryClass TimeentryClass; + +struct _Timeentry { + GtkHBox hbox; + + GtkWidget *main_label; + GtkWidget *main_label_box; + GtkWidget *main_label_context_menu; + GtkWidget *seconds_spinner; + GtkWidget *nanoseconds_spinner; + GtkWidget *s_label; + GtkWidget *ns_label; + + int seconds_changed_handler_id; + int nanoseconds_changed_handler_id; + + unsigned long min_seconds; + unsigned long min_nanoseconds; + unsigned long max_seconds; + unsigned long max_nanoseconds; +}; + +struct _TimeentryClass { + GtkHBoxClass parent_class; + + void (*timeentry) (Timeentry *timeentry); +}; + +GType timeentry_get_type(void); +GtkWidget *timeentry_new(const gchar *label); + +void timeentry_set_main_label(Timeentry *timeentry, + const gchar *str); +void timeentry_set_minmax_time(Timeentry *timeentry, + unsigned long min_seconds, + unsigned long min_nanoseconds, + unsigned long max_seconds, + unsigned long max_nanoseconds); + +void timeentry_set_time(Timeentry *timeentry, + unsigned long seconds, + unsigned long nanoseconds); + +void timeentry_get_time(Timeentry *timeentry, + unsigned long *seconds, + unsigned long *nanoseconds); +G_END_DECLS + +#endif /* _TIME_ENTRY_ */ -- 2.34.1