[ltt-dev] [PATCH] Delegate the timebar management to a new timebar widget which uses a new timeentry widget

Yannick Brosseau yannick.brosseau at gmail.com
Fri Dec 3 18:58:09 EST 2010


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.

Signed-off-by: Yannick Brosseau <yannick.brosseau at gmail.com>
---
 lttv/modules/gui/lttvwindow/lttvwindow/Makefile.am |    4 +
 lttv/modules/gui/lttvwindow/lttvwindow/callbacks.c | 1045 ++------------------
 .../gui/lttvwindow/lttvwindow/mainwindow-private.h |   30 +-
 lttv/modules/gui/lttvwindow/lttvwindow/timebar.c   |  389 ++++++++
 lttv/modules/gui/lttvwindow/lttvwindow/timebar.h   |   80 ++
 lttv/modules/gui/lttvwindow/lttvwindow/timeentry.c |  427 ++++++++
 lttv/modules/gui/lttvwindow/lttvwindow/timeentry.h |   82 ++
 7 files changed, 1086 insertions(+), 971 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 00e4177..c953fc9 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 4b1a974..f1ab4a2 100644
--- a/lttv/modules/gui/lttvwindow/lttvwindow/callbacks.c
+++ b/lttv/modules/gui/lttvwindow/lttvwindow/callbacks.c
@@ -43,6 +43,7 @@
 #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>
@@ -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,
@@ -3512,432 +3265,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;
-  }
-
-  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;
+  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);
+  /* call viewer hooks for new time window */
+  set_time_window(tab, &new_time_window);
 
+  tab->time_manager_lock = FALSE;
 }
 
-/* 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) ;
-      }
-    }
-    
-  }
-
-  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);
-  }
-}
-
-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);
-  }
-}
 
 
 
@@ -3952,39 +3296,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);
 
@@ -4011,50 +3323,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;
+	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;
 
-  current_time_change_manager(tab, new_current_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)
@@ -4493,8 +3842,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);
 
@@ -4638,180 +3985,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,
@@ -4864,8 +4039,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);
 
 
@@ -4879,30 +4056,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 5bd9705..5311fa1 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 0000000..8e5b0a6
--- /dev/null
+++ b/lttv/modules/gui/lttvwindow/lttvwindow/timebar.c
@@ -0,0 +1,389 @@
+/* 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, 0);
+
+    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, 0);
+   
+    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, 0);
+
+    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, 0);
+    
+    /* Set an initial time */
+    timebar_set_minmax_time(timebar,&ltt_time_zero,&ltt_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);
+    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;
+
+	/* 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;
+	}
+
+	/* Update widgets */
+	timeentry_set_minmax_time(TIMEENTRY(timebar->start_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->end_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->current_timeentry),
+				timebar->min_time.tv_sec,
+				timebar->min_time.tv_nsec,
+				timebar->max_time.tv_sec,
+				timebar->max_time.tv_nsec);
+
+	/* Compute max interval */
+	new_interval_length = ltt_time_sub(timebar->max_time,
+					timebar->min_time);
+	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);
+	timeentry_set_time(TIMEENTRY(timebar->interval_timeentry),
+				new_interval.tv_sec,
+				new_interval.tv_nsec);	
+}
+
+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 0000000..ded4d80
--- /dev/null
+++ b/lttv/modules/gui/lttvwindow/lttvwindow/timebar.h
@@ -0,0 +1,80 @@
+/* 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 <glib.h>
+#include <gtk/gtkhbox.h>
+#include <gtk/gtktooltips.h>
+#include <gtk/gtkwidget.h>
+#include <ltt/time.h>
+
+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;
+
+	/* Paste zones */
+	/* TODO ybrosseau 2010-11-25: Add a context menu to explicit pasting */
+
+	/* 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 0000000..e669851
--- /dev/null
+++ b/lttv/modules/gui/lttvwindow/lttvwindow/timeentry.c
@@ -0,0 +1,427 @@
+/* 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, 0);
+	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, 0);
+
+	g_signal_connect ((gpointer) timeentry->seconds_spinner, "value-changed",
+			G_CALLBACK (on_spinner_value_changed),
+			timeentry);
+	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, &current_seconds, &current_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;
+	
+
+	
+
+	/* 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)
+{
+	
+	if (seconds < timeentry->min_seconds) {
+		seconds = timeentry->min_seconds;
+	}
+	if(seconds == timeentry->min_seconds && 
+		nanoseconds < timeentry->min_nanoseconds) {
+		nanoseconds = timeentry->min_nanoseconds;
+	} 
+	if (seconds > timeentry->max_seconds) {
+		seconds = timeentry->max_seconds;
+	}
+	if(seconds == timeentry->max_seconds && 
+		nanoseconds > timeentry->max_nanoseconds) {
+		nanoseconds = timeentry->max_nanoseconds;
+	} 
+
+	gtk_spin_button_set_value(GTK_SPIN_BUTTON(timeentry->seconds_spinner),seconds);
+	gtk_spin_button_set_value(GTK_SPIN_BUTTON(timeentry->nanoseconds_spinner),nanoseconds);
+
+	timeentry_update_nanoseconds_spinner_range(timeentry, seconds);
+
+}
+
+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);
+	
+	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';
+	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 0000000..c217597
--- /dev/null
+++ b/lttv/modules/gui/lttvwindow/lttvwindow/timeentry.h
@@ -0,0 +1,82 @@
+/* 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 <glib.h>
+#include <gtk/gtkhbox.h>
+#include <gtk/gtkspinbutton.h>
+#include <gtk/gtklabel.h>
+
+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;
+
+	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_ */
-- 
1.7.2.3





More information about the lttng-dev mailing list