Index: Evidence/Edd/Edd.cc
===================================================================
--- Evidence/Edd/Edd.cc	(revision 174)
+++ Evidence/Edd/Edd.cc	(revision 204)
@@ -9,5 +9,5 @@
 a DIM status service
 
-February 2010, Oliver Grimm
+April 2010, Oliver Grimm
 
 ============================================================ */
@@ -195,18 +195,32 @@
   setAttribute(Qt::WA_DeleteOnClose);
   setAutoReplot(false);
-  setCanvasBackground(QColor(Qt::yellow));
-  setAxisScaleDraw(QwtPlot::xBottom, new TimeScale());
+  setCanvasBackground(EddPlotBackgroundColor);
+  setAxisScaleDraw(QwtPlot::xBottom, new EddTimeScale);
+  setMargin(15);
+
+  // Update additional information (e.g. time range) on widget when axis change	
+  connect(axisWidget(QwtPlot::xBottom), SIGNAL(scaleDivChanged()), SLOT(update()));
+
+  Picker = new QwtPicker(QwtPicker::CornerToCorner|QwtPicker::RectSelection, QwtPicker::RectRubberBand, QwtPicker::AlwaysOff, this);
+  connect(Picker, SIGNAL(selected(const QwtPolygon &)), SLOT(MouseSelection(const QwtPolygon &)));
 
   Zoomer = new QwtPlotZoomer(QwtPlot::xBottom,QwtPlot::yLeft,canvas());
   connect(Zoomer, SIGNAL(zoomed(const QwtDoubleRect &)), this, SLOT(HandleZoom(const QwtDoubleRect &)));
+
+  Magnifier = new QwtPlotMagnifier(canvas());
+  Magnifier->setMouseButton(Qt::NoButton,Qt::NoButton);
+  Magnifier->setZoomInKey(Qt::Key_M, Qt::NoModifier);
+  Magnifier->setZoomOutKey(Qt::Key_M, Qt::ShiftModifier);
+
   Panner = new QwtPlotPanner(canvas());
   Panner->setMouseButton(Qt::LeftButton, Qt::ShiftModifier);
+
   Grid = new QwtPlotGrid;
   Grid->setMajPen(QPen(Qt::gray, 0, Qt::DotLine));
   Grid->attach(this);
+
   Legend = new QwtLegend();
   Legend->setItemMode(QwtLegend::ClickableItem);
-  insertLegend(Legend, QwtPlot::TopLegend);
-
+  insertLegend(Legend, QwtPlot::TopLegend, 0.3);
   connect(this, SIGNAL(legendClicked (QwtPlotItem *)), SLOT(LegendClicked(QwtPlotItem *)));
   
@@ -218,4 +232,7 @@
   // Context menu
   Menu = new QMenu(this);
+  StripAction = Menu->addAction("Stripchart", this, SLOT(UpdatePlot()));
+  StripAction->setCheckable(true);
+  Menu->addSeparator();
   YLogAction = Menu->addAction("y scale log", this, SLOT(UpdatePlot()));
   YLogAction->setCheckable(true);
@@ -232,4 +249,5 @@
   Menu->addSeparator();
   Menu->addAction("Paste service", this, SLOT(MenuPasteService()));
+  Menu->addAction("Plot help", this, SLOT(MenuPlotHelp()));
 
   // DIM client
@@ -245,5 +263,6 @@
     Handler->Unsubscribe(Items[i].Name);
     delete Items[i].Signal;
-  }  
+  }
+
   delete Grid;
   delete Mutex;
@@ -363,8 +382,12 @@
 void EddPlot::UpdatePlot() {
 
+  double Lower = axisScaleDiv(QwtPlot::xBottom)->lowerBound();
+  double Upper = axisScaleDiv(QwtPlot::xBottom)->upperBound();
+  double MaxTime = DBL_MIN;
   static QwtSymbol Symbol, Sym1;
   Symbol.setStyle(QwtSymbol::Ellipse);
   Symbol.setSize(4);
 
+  // Select engine for linear or logarithmic scale
   if (!YLogAction->isChecked()) {
     setAxisScaleEngine(QwtPlot::yLeft, new QwtLinearScaleEngine);
@@ -376,8 +399,14 @@
 
   for (int ItemNo=0; ItemNo<Items.size(); ItemNo++) {
-
+	// Determine current maximum value for strip chart plotting
+	if (Items[ItemNo].Signal->boundingRect().right() > MaxTime) {
+	  MaxTime = Items[ItemNo].Signal->boundingRect().right();
+	}
+
+	// Set symbol if requested
     if (StyleAction->isChecked()) Items[ItemNo].Signal->setSymbol(Symbol);
     else Items[ItemNo].Signal->setSymbol(Sym1);
 
+	// Determine number of data points
     int DataPoints = Items[ItemNo].x.size();	
 	if (DataPoints == 0) continue;
@@ -399,10 +428,96 @@
     Items[ItemNo].Signal->setData(Items[ItemNo].x.data(), y, DataPoints);
     Items[ItemNo].Signal->show();
-    Zoomer->setZoomBase(Items[ItemNo].Signal->boundingRect());
-
-    delete[] y;
-  }
+	delete[] y;
+
+	// Generate bounding box of all curves for zoomer
+	BBox = BBox.unite(Items[ItemNo].Signal->boundingRect());
+  }
+
+  // Reset zoom base to include all data
+  Zoomer->setZoomBase(BBox);
+
+  // If plot is strip char, only move axis but keep range
+  if (StripAction->isChecked()) {
+    setCanvasBackground(EddPlotBackgroundColor.lighter(90));
+    setAxisScale(QwtPlot::xBottom, Lower+ BBox.right() - MaxTime, Upper + BBox.right() - MaxTime);
+  }
+  else setCanvasBackground(EddPlotBackgroundColor);
+
   replot();
 }
+
+// Add text indicating time range to plot
+void EddPlot::paintEvent(QPaintEvent *) {
+
+  QString Text;
+  QFont Font;
+  QPainter Painter(this);
+  
+  Text = QDateTime::fromTime_t((int) axisScaleDiv(QwtPlot::xBottom)->lowerBound()).toString("d-MMM-yyyy hh:mm:ss") + " to " + QDateTime::fromTime_t((int) axisScaleDiv(QwtPlot::xBottom)->upperBound()).toString("d-MMM-yyyy hh:mm:ss");
+
+  Font.setPointSize(6);  
+  Painter.setFont(Font);
+  Painter.drawText(0, height(),Text);
+}
+
+// Rescale plot in case selection has been made outside the canvas
+void EddPlot::MouseSelection(const QPolygon &P) {
+ 
+  QwtDoubleInterval xPlot, xMouse, yPlot, yMouse; 
+
+  // Shift selected rectangle so that upper left corner is 0/0 on canvas
+  QRect R = P.boundingRect().translated(-plotLayout()->canvasRect().topLeft());
+
+  // Current axis intervals
+  xPlot = axisScaleDiv(QwtPlot::xBottom)->interval();
+  yPlot = axisScaleDiv(QwtPlot::yLeft)->interval();
+  
+  // Selected axis intervals
+  xMouse = QwtDoubleInterval(invTransform(QwtPlot::xBottom, R.left()),
+  		invTransform(QwtPlot::xBottom, R.right()));
+  yMouse = QwtDoubleInterval(invTransform(QwtPlot::yLeft, R.bottom()),
+		invTransform(QwtPlot::yLeft, R.top()));
+
+  // Selection region outside all axis?
+  if (R.right() < 0 && R.top() > plotLayout()->canvasRect().height()) return;
+  
+  // Rescale both axis if selected rectangle encompasses canvas completely
+  if (P.boundingRect().contains(plotLayout()->canvasRect())) {
+	yMouse.setMaxValue(yMouse.maxValue() + yPlot.width());
+	yMouse.setMinValue(yMouse.minValue() - yPlot.width());
+	xMouse.setMinValue(xMouse.minValue() - xPlot.width());
+	xMouse.setMaxValue(xMouse.maxValue() + xPlot.width());
+
+	setAxisScale(QwtPlot::xBottom, xMouse.minValue(), xMouse.maxValue());
+	setAxisScale(QwtPlot::yLeft, yMouse.minValue(), yMouse.maxValue());
+  }
+
+  // Rescale y axis (increase range if selected rectangle larger than axis area)
+  if (R.right() < 0) {
+	if (R.top() < plotLayout()->canvasRect().top()) {
+	  yMouse.setMaxValue(yMouse.maxValue() + yPlot.width());
+	}
+	if (R.bottom() > plotLayout()->canvasRect().bottom()) {
+	  yMouse.setMinValue(yMouse.minValue() - yPlot.width());
+	}
+	
+	setAxisScale(QwtPlot::yLeft, yMouse.minValue(), yMouse.maxValue());
+  }
+
+  // Rescale x axis (increase range if selected rectangle larger than axis area)
+  if (R.top() > plotLayout()->canvasRect().height()) {
+	if (R.left() < plotLayout()->canvasRect().left()) {
+	  xMouse.setMinValue(xMouse.minValue() - xPlot.width());
+	}
+	if (R.right() > plotLayout()->canvasRect().right()) {
+	  xMouse.setMaxValue(xMouse.maxValue() + xPlot.width());
+	}
+	setAxisScale(QwtPlot::xBottom, xMouse.minValue(), xMouse.maxValue());
+  }
+
+  // Draw new scales
+  replot();
+} 
+
 
 //
@@ -537,4 +652,19 @@
 }
 
+// Help text
+void EddPlot::MenuPlotHelp() {
+
+  QMessageBox::about(this, "Edd - Plot navigation",
+    "Zoom\tMouse wheel\n"
+	"\tKeys m and shift-m\n"
+	"\tSelecting region with left mouse button\n"
+	"\tMiddle button zooms out one level\n"
+	"\tSelecting a range on an axis\n"
+	"\tSelecting whole canvas\n\n"
+    "Pan\tShift and left mouse button\n\n"
+	"ESC cancels selection\n"
+    "Cursor keys move mouse");
+}
+
 
 //////////////////////////////////////
@@ -754,6 +884,9 @@
 
 
-//
-// Main GUI (all widgets have ultimately Central as parent)
+//--------------------------------------------------------------------
+//*************************** Main GUI *******************************
+//--------------------------------------------------------------------
+//
+// All widgets have ultimately Central as parent.
 //
 GUI::GUI() {
@@ -1002,9 +1135,4 @@
 }
 
-
-//---------------------------------------------------------------------
-//************************ All functions ****************************
-//-------------------------------------------------------------------
-
 // Quit application when clicking close button on window
 void GUI::closeEvent(QCloseEvent *) {
Index: Evidence/Edd/Edd.h
===================================================================
--- Evidence/Edd/Edd.h	(revision 174)
+++ Evidence/Edd/Edd.h	(revision 204)
@@ -8,4 +8,5 @@
 #include <qwt_plot_grid.h>
 #include <qwt_plot_zoomer.h>
+#include <qwt_plot_magnifier.h>
 #include <qwt_plot_panner.h>
 #include <qwt_scale_engine.h>
@@ -16,4 +17,5 @@
 #include <qwt_legend_item.h>
 #include <qwt_symbol.h>
+#include <qwt_plot_marker.h>
 
 #include <limits.h>
@@ -25,13 +27,30 @@
 #define SVN_REVISION "$Revision$"
 
+const QColor EddPlotBackgroundColor(Qt::yellow);
+
 QWidget *OpenHistory(char *, int);
 
 // Time scale for axis
-class TimeScale: public QwtScaleDraw {
-  public:
-    TimeScale() { }
+class EddTimeScale: public QwtScaleDraw {
+
+  public:
+    EddTimeScale() {}
+
     virtual QwtText label(double v) const {
-      QDateTime t = QDateTime::fromTime_t((int) v);
-      return t.toString("dMMM'\n'hh:mm:ss");
+
+	  // Adapt text format to time span 
+	  QString Format;
+	  if (scaleDiv().range() < 60*60) Format = "hh' h\n'mm:ss";
+	  else if (scaleDiv().range() < 24*60*60) Format = "hh:mm";
+	  else if (scaleDiv().range() < 30*24*60*60) Format = "h' h\n'd-MMM";
+	  else Format = "d-MMM'\n'yyyy";
+
+	  // Generate text
+	  QwtText Text = QDateTime::fromTime_t((int) v).toString(Format);
+	  QFont Font = Text.font();
+	  Font.setPointSize(7);
+	  Text.setFont(Font);
+
+      return Text;
     }
 };
@@ -89,13 +108,18 @@
     QAction *NormAction;
     QAction *StyleAction;
+    QAction *StripAction;
     
     QwtPlotPanner *Panner;
     QwtPlotGrid *Grid;
     QwtPlotZoomer *Zoomer;
-    QwtLegend *Legend;
-    
+	QwtPlotMagnifier *Magnifier;
+    QwtPicker *Picker;
+	QwtLegend *Legend;
+	QwtDoubleRect BBox;
+
     void dragEnterEvent(QDragEnterEvent *);
     void dropEvent(QDropEvent *);
-
+	void paintEvent(QPaintEvent *);
+	 	
   public:
     EddPlot(QString = QString(), int = 0, QWidget * = NULL);
@@ -108,5 +132,6 @@
 
     void HandleZoom(const QwtDoubleRect &);
-    void contextMenuEvent(QContextMenuEvent *);
+	void MouseSelection(const QwtPolygon &);
+	void contextMenuEvent(QContextMenuEvent *);
 	void LegendClicked(QwtPlotItem *);
     void MenuZoomOut();
@@ -116,4 +141,5 @@
     void MenuPrint();
     void MenuPasteService();
+	void MenuPlotHelp();
 };
 
