diff --git a/common/utils/T/tracer/gui/Makefile b/common/utils/T/tracer/gui/Makefile
index adec8fdd79a201dcd2fcf400aea1030a6ae36182..b64af3bd18cb741b40c69c94dc61b469161e26eb 100644
--- a/common/utils/T/tracer/gui/Makefile
+++ b/common/utils/T/tracer/gui/Makefile
@@ -2,7 +2,7 @@ CC=gcc
 CFLAGS=-Wall -g -pthread
 
 OBJS=init.o loop.o toplevel_window.o x.o container.o widget.o \
-     gui.o label.o event.o xy_plot.o textlist.o notify.o
+     gui.o label.o event.o xy_plot.o textlist.o notify.o positioner.o
 
 gui.a: $(OBJS)
 	ar cr gui.a $(OBJS)
diff --git a/common/utils/T/tracer/gui/gui.h b/common/utils/T/tracer/gui/gui.h
index 9d7f283ea1a022b7e071d52064d7b5e50ce35c08..92f336ada7e29f4b1e17a0333f2ac96198053e78 100644
--- a/common/utils/T/tracer/gui/gui.h
+++ b/common/utils/T/tracer/gui/gui.h
@@ -21,6 +21,7 @@ void widget_dirty(gui *gui, widget *this);
 
 widget *new_toplevel_window(gui *gui, int width, int height, char *title);
 widget *new_container(gui *gui, int vertical);
+widget *new_positioner(gui *gui);
 widget *new_label(gui *gui, const char *text);
 widget *new_xy_plot(gui *gui, int width, int height, char *label,
     int vruler_width);
diff --git a/common/utils/T/tracer/gui/gui_defs.h b/common/utils/T/tracer/gui/gui_defs.h
index bca856d5ea16ec0f51569525c6f0b712c4128d84..463d9bf8a091ae7e94aec3c52b6eae2f1fb4f8b1 100644
--- a/common/utils/T/tracer/gui/gui_defs.h
+++ b/common/utils/T/tracer/gui/gui_defs.h
@@ -30,7 +30,7 @@ extern int volatile gui_logd;
 /*************************************************************************/
 
 enum widget_type {
-  TOPLEVEL_WINDOW, CONTAINER, TEXT_LIST, XY_PLOT, BUTTON, LABEL
+  TOPLEVEL_WINDOW, CONTAINER, POSITIONER, TEXT_LIST, XY_PLOT, BUTTON, LABEL
 };
 
 struct widget_list;
@@ -77,6 +77,10 @@ struct container_widget {
   int nchildren;
 };
 
+struct positioner_widget {
+  struct widget common;
+};
+
 struct textlist_widget {
   struct widget common;
   char **text;
diff --git a/common/utils/T/tracer/gui/positioner.c b/common/utils/T/tracer/gui/positioner.c
new file mode 100644
index 0000000000000000000000000000000000000000..5bd23e147e900550e27c70dc3a940534aafb611d
--- /dev/null
+++ b/common/utils/T/tracer/gui/positioner.c
@@ -0,0 +1,92 @@
+#include "gui.h"
+#include "gui_defs.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static void add_child(gui *g, widget *_this, widget *child, int position)
+{
+  LOGD("ADD_CHILD positioner\n");
+  struct positioner_widget *this = _this;
+  widget_add_child_internal(g, this, child, position);
+}
+
+static void del_child(gui *g, widget *_this, widget *child)
+{
+  LOGD("DEL_CHILD positioner\n");
+  struct positioner_widget *this = _this;
+  widget_del_child_internal(g, this, child);
+}
+
+static void allocate(
+    gui *_g, widget *_this, int x, int y, int width, int height)
+{
+  LOGD("ALLOCATE positioner %p\n", _this);
+  struct gui *g = _g;
+  struct positioner_widget *this = _this;
+  struct widget_list *l = this->common.children;
+  int cwidth, cheight;
+
+  this->common.x = x;
+  this->common.y = y;
+  this->common.width = width;
+  this->common.height = height;
+
+  if (l != NULL) {
+    l->item->hints(g, l->item, &cwidth, &cheight);
+    l->item->allocate(g, l->item, x+(width-cwidth)/2, y+(height-cheight)/2,
+        cwidth, cheight);
+  }
+}
+
+static void hints(gui *_gui, widget *_w, int *width, int *height)
+{
+  LOGD("HINTS positioner %p\n", _w);
+  struct gui *g = _gui;
+  struct positioner_widget *this = _w;
+  struct widget_list *l = this->common.children;
+  if (l != NULL)
+    l->item->hints(g, l->item, width, height);
+  else { *width = *height = 1; }
+}
+
+static void button(gui *_g, widget *_this, int x, int y, int button, int up)
+{
+  LOGD("BUTTON positioner %p xy %d %d button %d up %d\n", _this, x, y, button, up);
+  struct gui *g = _g;
+  struct positioner_widget *this = _this;
+  struct widget_list *l = this->common.children;
+  if (l != NULL)
+    l->item->button(g, l->item, x, y, button, up);
+}
+
+static void paint(gui *_gui, widget *_this)
+{
+  LOGD("PAINT positioner\n");
+  struct gui *g = _gui;
+  struct widget *this = _this;
+  struct widget_list *l = this->children;
+  if (l != NULL)
+    l->item->paint(g, l->item);
+}
+
+widget *new_positioner(gui *_gui)
+{
+  struct gui *g = _gui;
+  struct positioner_widget *w;
+
+  glock(g);
+
+  w = new_widget(g, POSITIONER, sizeof(struct positioner_widget));
+
+  w->common.paint     = paint;
+  w->common.add_child = add_child;
+  w->common.del_child = del_child;
+  w->common.allocate  = allocate;
+  w->common.hints     = hints;
+  w->common.button    = button;
+
+  gunlock(g);
+
+  return w;
+}
diff --git a/common/utils/T/tracer/gui/widget.c b/common/utils/T/tracer/gui/widget.c
index 6277556333ff30527cd1df4e97287220928cfb4a..db8a754a70f29a48281f3ffdd67876d479b3af80 100644
--- a/common/utils/T/tracer/gui/widget.c
+++ b/common/utils/T/tracer/gui/widget.c
@@ -264,7 +264,8 @@ void widget_dirty(gui *_gui, widget *_this)
 }
 
 static const char *names[] = {
-  "TOPLEVEL_WINDOW", "CONTAINER", "TEXT_LIST", "XY_PLOT", "BUTTON", "LABEL"
+  "TOPLEVEL_WINDOW", "CONTAINER", "POSITIONER", "TEXT_LIST",
+  "XY_PLOT", "BUTTON", "LABEL"
 };
 const char *widget_name(enum widget_type type)
 {
@@ -272,6 +273,7 @@ const char *widget_name(enum widget_type type)
   default: break;
   case TOPLEVEL_WINDOW:
   case CONTAINER:
+  case POSITIONER:
   case TEXT_LIST:
   case XY_PLOT:
   case BUTTON: