diff --git a/scalepicker.cpp b/scalepicker.cpp
new file mode 100644
--- /dev/null
+++ b/scalepicker.cpp
@@ -0,0 +1,250 @@
+/*
+ Copyright © 2015 Hasan Yavuz Özderya
+
+ This file is part of serialplot.
+
+ serialplot is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ serialplot 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 serialplot. If not, see .
+*/
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "scalepicker.h"
+
+// minimum size for pick (in pixels)
+#define MIN_PICK_SIZE (2)
+
+class PlotOverlay : public QwtWidgetOverlay
+{
+public:
+ PlotOverlay(QWidget* widget, ScalePicker* picker);
+
+protected:
+ virtual void drawOverlay(QPainter*) const;
+
+private:
+ ScalePicker* _picker;
+};
+
+PlotOverlay::PlotOverlay(QWidget* widget, ScalePicker* picker) :
+ QwtWidgetOverlay(widget)
+{
+ _picker = picker;
+}
+
+void PlotOverlay::drawOverlay(QPainter* painter) const
+{
+ _picker->drawPlotOverlay(painter);
+}
+
+class ScaleOverlay : public QwtWidgetOverlay
+{
+public:
+ ScaleOverlay(QWidget* widget, ScalePicker* picker);
+
+protected:
+ virtual void drawOverlay(QPainter*) const;
+
+private:
+ ScalePicker* _picker;
+};
+
+ScaleOverlay::ScaleOverlay(QWidget* widget, ScalePicker* picker) :
+ QwtWidgetOverlay(widget)
+{
+ _picker = picker;
+}
+
+void ScaleOverlay::drawOverlay(QPainter* painter) const
+{
+ _picker->drawScaleOverlay(painter);
+}
+
+ScalePicker::ScalePicker(QwtScaleWidget* scaleWidget, QWidget* canvas) :
+ QObject(scaleWidget)
+{
+ _scaleWidget = scaleWidget;
+ _canvas = canvas;
+ scaleWidget->installEventFilter(this);
+ scaleWidget->setMouseTracking(true);
+ pickerOverlay = new PlotOverlay(canvas, this);
+ scaleOverlay = new ScaleOverlay(scaleWidget, this);
+ started = false;
+ pressed = false;
+}
+
+bool ScalePicker::eventFilter(QObject* object, QEvent* event)
+{
+ if (event->type() == QEvent::MouseButtonPress ||
+ event->type() == QEvent::MouseButtonRelease ||
+ event->type() == QEvent::MouseMove)
+ {
+ QMouseEvent* mouseEvent = (QMouseEvent*) event;
+ double pos = this->position(mouseEvent);
+ double posPx = this->positionPx(mouseEvent);
+ currentPosPx = posPx;
+
+ if (event->type() == QEvent::MouseButtonPress &&
+ mouseEvent->button() == Qt::LeftButton)
+ {
+ pressed = true; // not yet started
+ firstPos = pos;
+ firstPosPx = posPx;
+ }
+ else if (event->type() == QEvent::MouseMove)
+ {
+ // make sure pick size is big enough, so that just
+ // clicking won't trigger pick
+ if (!started && pressed && (fabs(posPx-firstPosPx) > MIN_PICK_SIZE))
+ {
+ started = true;
+ emit pickStarted(pos);
+ }
+ else if (started)
+ {
+ pickerOverlay->updateOverlay();
+ emit picking(firstPos, pos);
+ }
+ scaleOverlay->updateOverlay();
+ }
+ else // event->type() == QEvent::MouseButtonRelease
+ {
+ if (started)
+ {
+ // finalize
+ started = false;
+ pressed = false;
+ emit picked(firstPos, pos);
+ }
+ }
+ return true;
+ }
+ else if (event->type() == QEvent::Leave)
+ {
+ scaleOverlay->updateOverlay();
+ return true;
+ }
+ else
+ {
+ return QObject::eventFilter(object, event);
+ }
+}
+
+void ScalePicker::drawPlotOverlay(QPainter* painter)
+{
+ if (started)
+ {
+ painter->save();
+ painter->setPen(_pen);
+
+ QRect rect;
+ if (_scaleWidget->alignment() == QwtScaleDraw::BottomScale ||
+ _scaleWidget->alignment() == QwtScaleDraw::TopScale)
+ {
+ int height = painter->device()->height();
+ rect = QRect(posCanvasPx(firstPosPx), 0, currentPosPx-firstPosPx, height);
+ }
+ else // vertical
+ {
+ int width = painter->device()->width();
+ rect = QRect(0, posCanvasPx(firstPosPx), width, currentPosPx-firstPosPx);
+ }
+ painter->drawRect(rect);
+ painter->restore();
+ }
+}
+
+void ScalePicker::drawScaleOverlay(QPainter* painter)
+{
+ painter->save();
+ painter->setPen(_pen);
+ if (1)
+ {
+
+ if (_scaleWidget->alignment() == QwtScaleDraw::BottomScale ||
+ _scaleWidget->alignment() == QwtScaleDraw::TopScale)
+ {
+ int height = painter->device()->height();
+ if (started) painter->drawLine(firstPosPx, 0, firstPosPx, height);
+ if (started || _scaleWidget->underMouse())
+ {
+ painter->drawLine(currentPosPx, 0, currentPosPx, height);
+ }
+ }
+ else // vertical
+ {
+ int width = painter->device()->width();
+ if (started) painter->drawLine(0, firstPosPx, width, firstPosPx);
+ if (started || _scaleWidget->underMouse())
+ {
+ painter->drawLine(0, currentPosPx, width, currentPosPx);
+ }
+ }
+ }
+ painter->restore();
+}
+
+void ScalePicker::setPen(QPen pen)
+{
+ _pen = pen;
+}
+
+double ScalePicker::position(QMouseEvent* mouseEvent)
+{
+ double pos;
+ pos = positionPx(mouseEvent);
+ // convert the position of the click to the plot coordinates
+ pos = _scaleWidget->scaleDraw()->scaleMap().invTransform(pos);
+ return pos;
+}
+
+double ScalePicker::positionPx(QMouseEvent* mouseEvent)
+{
+ double pos;
+ if (_scaleWidget->alignment() == QwtScaleDraw::BottomScale ||
+ _scaleWidget->alignment() == QwtScaleDraw::TopScale)
+ {
+ pos = mouseEvent->pos().x();
+ }
+ else // left or right scale
+ {
+ pos = mouseEvent->pos().y();
+ }
+ return pos;
+}
+
+/*
+ * Scale widget and canvas widget is not always aligned. Especially
+ * when zooming scaleWidget moves around. This causes irregularities
+ * when drawing the tracker lines. This function maps scale widgets
+ * pixel coordinate to canvas' coordinate.
+ */
+double ScalePicker::posCanvasPx(double pos)
+{
+ // assumption: scale.width < canvas.width && scale.x > canvas.x
+ if (_scaleWidget->alignment() == QwtScaleDraw::BottomScale ||
+ _scaleWidget->alignment() == QwtScaleDraw::TopScale)
+ {
+ return pos + (_scaleWidget->x() - _canvas->x());
+ }
+ else // left or right scale
+ {
+ return pos + (_scaleWidget->y() - _canvas->y());
+ }
+ return pos;
+}