#include <lttvwindow/mainwindow.h>
#include <lttvwindow/mainwindow-private.h>
#include <lttvwindow/menu.h>
+#include <lttvwindow/timebar.h>
#include <lttvwindow/toolbar.h>
#include <lttvwindow/lttvwindow.h>
#include <lttvwindow/lttvwindowtraces.h>
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,
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,
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);
- }
-}
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);
}
-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)
LttvTrace * trace;
Tab *tab = ptab->tab;
- gtk_object_destroy(GTK_OBJECT(tab->tooltips));
-
if(tab->attributes)
g_object_unref(tab->attributes);
// }
/* 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,
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);
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);
--- /dev/null
+/* 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 <gtk/gtkeventbox.h>
+#include <gtk/gtkvseparator.h>
+#include <ltt/time.h>
+
+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);
+}
+
+
--- /dev/null
+/* 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 <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <gtk/gtksignal.h>
+
+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, "<Item>" },
+ { "/Paste time", NULL, on_menu_paste, 0, "<Item>" },
+ };
+
+ gint nmenu_items = sizeof (menu_items) / sizeof (menu_items[0]);
+
+ item_factory = gtk_item_factory_new (GTK_TYPE_MENU, "<main_label>",
+ 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, "<main_label>");
+}
+
+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);
+}